diff --git a/ChangeLog b/ChangeLog index 143a189c4..f2acda5e6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,3065 @@ +2012-02-18 Vladimir Serbinenko + + * conf/Makefile.common (platform_SCRIPTS): New variable. + (platform_PROGRAMS): Likewise. + * gentpl.py: Mark *,module and *.image for install. + * grub-core/gdb_grub.in: Add a notice of expected environment. + * grub-core/Makefile.core.def (gdb_grub): Mark for install. + (gmodule.pl): Likewise. + +2012-02-18 Vladimir Serbinenko + + Replace grub_checkkey with grub_getkey_noblock. + + * grub-core/kern/term.c (grub_checkkey): Replaced with ... + (grub_getkey_noblock): ... this. All users updated. + +2012-02-18 Vladimir Serbinenko + + * grub-core/kern/emu/console.c: Move to ... + * grub-core/term/emu/console.c: ...here. + (grub_ncurses_getkey): Fix return value if no key is detected. + +2012-02-12 Vladimir Serbinenko + + * include/grub/test.h (grub_unit_test_init): Add missing prototype. + (grub_unit_test_fini): Likewise. + * tests/lib/unit_test.c (main): Remove extra nested external prototype. + +2012-02-12 Vladimir Serbinenko + + * include/grub/test.h (GRUB_UNIT_TEST) + +2012-02-12 Vladimir Serbinenko + + * grub-core/script/execute.c (grub_script_break): Clarify logic. + Better error handling. + (grub_script_return): Likewise. + * grub-core/script/lexer.c (grub_script_lexer_yywrap): Likewise. + +2012-02-12 Vladimir Serbinenko + + * grub-core/lib/libgcrypt_wrap/cipher_wrap.h (__GNU_LIBRARY__): Avoid + rimplicit redifinition. + +2012-02-12 Vladimir Serbinenko + + * docs/grub.texi (Internationalisation): Detail (lack of) collation in + GRUB. + +2012-02-12 Vladimir Serbinenko + + * grub-core/normal/cmdline.c (grub_cmdline_get): Don't gettext prompt. + * grub-core/normal/main.c (grub_normal_read_line_real): Gettext + prompt here. + +2012-02-12 Vladimir Serbinenko + + * grub-core/fs/zfs/zfs.c (zfs_fetch_nvlist): Mark unknown member here + as GRUB_ERR_BUG. Don't malloc if no device is available. + +2012-02-12 Vladimir Serbinenko + + * grub-core/term/terminfo.c (grub_terminfo_output_unregister): + Mark calling with invalid term as GRUB_ERR_BUG. + +2012-02-12 Vladimir Serbinenko + + * grub-core/net/tftp.c (tftp_receive): Silently discard too short + packets rather than raising an error. + +2012-02-12 Vladimir Serbinenko + + * grub-core/loader/xnu.c (grub_xnu_writetree_toheap_real): Avoid set + in if. + +2012-02-12 Vladimir Serbinenko + + * grub-core/loader/efi/appleloader.c (grub_cmd_appleloader): Move + diagnostic to dprintf. + * grub-core/loader/i386/pc/linux.c (grub_cmd_linux): Likewise. + +2012-02-12 Vladimir Serbinenko + + * grub-core/kern/corecmd.c (grub_core_cmd_ls): Handle error in parsing + device name. + +2012-02-12 Vladimir Serbinenko + + * grub-core/fs/ntfs.c (locate_attr): Avoid set in if. + (grub_ntfs_iterate_dir): Likewise. + +2012-02-12 Vladimir Serbinenko + + Efiemu stylistic fixes and gettext. + + * grub-core/efiemu/i386/loadcore32.c + (grub_arch_efiemu_relocate_symbols32): Avoid set in if. + * grub-core/efiemu/i386/loadcore64.c + (grub_arch_efiemu_relocate_symbols64): Likewise. + * grub-core/efiemu/i386/pc/cfgtables.c + (grub_machine_efiemu_init_tables): Likewise. + * grub-core/efiemu/loadcore.c (grub_efiemu_resolve_symbols): Likewise. + (grub_efiemu_loadcore_initXX): Add a filename argument. + All users updated. + Improved error message. + * grub-core/efiemu/loadcore_common.c (grub_efiemu_loadcore_init): + Add a filename argument. + All users updated. + * grub-core/efiemu/symbols.c (grub_efiemu_set_virtual_address_map): + Reclassify double relocation as GRUB_ERR_BUG. + +2012-02-12 Vladimir Serbinenko + + * grub-core/commands/i386/pc/play.c (grub_cmd_play): Improve error + handling. + +2012-02-12 Vladimir Serbinenko + + * grub-core/commands/hdparm.c (grub_cmd_hdparm): Allow running + on partition. + +2012-02-12 Vladimir Serbinenko + + * include/grub/misc.h (grub_error_save): Fix cleaning grub_errno. + +2012-02-12 Vladimir Serbinenko + + Improve string. Gettextize. + +2012-02-11 Vladimir Serbinenko + + * configure.ac: Remove -Winline altogether and -Wmissing-prototypes on + utils. + * util/import_gcry.py: Add -Wno-strict-aliasing on checked modules. + +2012-02-11 Vladimir Serbinenko + + * grub-core/disk/diskfilter.c (grub_diskfilter_print_partmap) + [GRUB_UTIL]: New function. + (insert_array) [GRUB_UTIL]: Store partmaps. + * include/grub/diskfilter.h (grub_diskfilter_pv) [GRUB_UTIL]: New member + partmaps. + (grub_diskfilter_print_partmap) [GRUB_UTIL]: New proto. + * util/grub-probe.c (probe_partmap): Call grub_diskfilter_print_partmap. + (probe_abstraction): Print diskfilter and not raid. + Reported by: Lennart Sorensen + +2012-02-11 Vladimir Serbinenko + + * util/grub-mkimage.c (generate_image): Explicitly init decompress_size. + * util/grub-mkimagexx.c (MASK3): New define. + (add_value_to_slot_20b): Use MASK3. + (add_value_to_slot_21): Likewise. + (relocate_addresses): Fix format specification. + (load_image): Explicitly init symtab_section. + +2012-02-11 Vladimir Serbinenko + + * util/getroot.c (grub_find_root_devices_from_mountinfo): Fix types. + (grub_util_biosdisk_get_grub_dev): Fix format specification. + +2012-02-11 Vladimir Serbinenko + + * grub-core/kern/emu/full.c (grub_arch_dl_get_tramp_got_size): Enable + on powerpc. + Reported by: Lennart Sorensen + +2012-02-11 Vladimir Serbinenko + + * gentpl.py: Add missing license header. + * docs/grub.texi: Update copyright year. + +2012-02-10 Grégoire Sutre + + Source grub-mkconfig_lib from the build directory at build time. + Suggested by: Vladimir Serbinenko. + + * gentpl.py (manpage): Set pkgdatadir to $(builddir) on help2man call. + * util/grub-install.in: Define pkgdatadir if not already set, and source + grub-mkconfig_lib from there. + * util/grub-kbdcomp.in: Likewise. + * util/grub-mkconfig.in: Likewise. + * util/grub-mknetdir.in: Likewise. + * util/grub-mkrescue.in: Likewise. + * util/grub-mkstandalone.in: Likewise. + * util/grub-reboot.in: Likewise. + * util/grub-set-default.in: Likewise. + * util/powerpc/ieee1275/grub-mkrescue.in: Likewise. + +2012-02-10 Vladimir Serbinenko + + Increase warning level. + + * conf/Makefile.common (CFLAGS_GNULIB): Add -Wno-redundant-decls + -Wno-unreachable-code -Wno-conversion -Wno-old-style-definition. + * configure.ac (HOST_CFLAGS): Add bunch of -W arguments. + (TARGET_CFLAGS): Likewise. + (HOST_CFLAGS): Add -Werror unless --disable-werror is activated. + * grub-core/Makefile.core.def (decompressor_xz): Add + -Wno-unreachable-code. + (normal): Add -Wno-redundant-decls. + (xzio): Add -Wno-unreachable-code. + (lzopio): Add -Wno-redundant-decls -Wno-error. + * grub-core/commands/acpi.c: Add exception to -Wcast-align. + * grub-core/commands/lsacpi.c: Add exception to -Wcast-align. + * grub-core/gensymlist.sh: Add exception to -Wmissing-format-attribute. + * grub-core/kern/dl.c: Add exception to -Wcast-align. + * grub-core/kern/efi/efi.c (grub_efi_modules_addr): Likewise. + * grub-core/kern/i386/coreboot/init.c: Add exception to + -Wsuggest-attribute=noreturn. + * grub-core/kern/ia64/dl.c: Add exception to -Wcast-align. + * grub-core/kern/ia64/dl_helper.c: Likewise. + * grub-core/kern/mips/dl.c: Likewise. + * grub-core/kern/sparc64/dl.c: Likewise. + * grub-core/lib/LzmaEnc.c: Add exception to -Wshadow. + * grub-core/lib/libgcrypt_wrap/cipher_wrap.h (memcpy): Likewise. + (memcmp): Likewise. + * grub-core/lib/pbkdf2.c: Add exception to -Wunreachable-code. + * grub-core/loader/ia64/efi/linux.c: Add exception to -Wcast-align. + * grub-core/loader/mips/linux.c: Likewise. + * grub-core/loader/multiboot_elfxx.c: Likewise. + * grub-core/script/parser.y: Add exception to -Wunreachable-code. + * grub-core/video/sm712.c: Add exception to -Wcast-align. + * util/import_gcry.py: Add -Wno-cast-align to modules checked by hand. + * grub-core/font/font.c (grub_font_loader_init): Add explicit cast and + fixme. + * grub-core/fs/iso9660.c (grub_iso9660_iterate_dir): Likewise. + * grub-core/kern/i386/multiboot_mmap.c (grub_machine_mmap_init): + Fix prototype. + +2012-02-10 Vladimir Serbinenko + + * grub-core/lib/i386/relocator16.S: Fix incorrect use of absolute + address. + +2012-02-10 Vladimir Serbinenko + + * grub-core/commands/legacycfg.c (grub_cmd_legacy_kernel): + Avoid improper use of strings. + (grub_cmd_legacy_initrdnounzip): Likewise. + +2012-02-10 Vladimir Serbinenko + + * include/grub/emu/misc.h (grub_util_warn): Add missing format + attribute. + (grub_util_info): Likewise. + (grub_util_error): Likewise. + +2012-02-10 Vladimir Serbinenko + + * util/grub-mount.c (fuse_init): Avoid improper use of strings. + * util/grub-fstest.c (fstest): Likewise. + +2012-02-10 Vladimir Serbinenko + + * grub-core/disk/geli.c (grub_md_sha256_real): Respect format security. + (grub_md_sha512_real): Likewise. + (grub_util_get_geli_uuid): Likewise. + * grub-core/kern/emu/hostdisk.c (grub_util_get_fd_sectors): Likewise. + (grub_util_biosdisk_open): Fix format specification. + Respect format security. + * grub-core/kern/emu/misc.c (xmalloc): Respect format security. + (xrealloc): Likewise. + (xasprintf): Likewise. + +2012-02-10 Vladimir Serbinenko + + * util/import_gcry.py: Include grub/crypto.h in init.c. + +2012-02-10 Vladimir Serbinenko + + * util/grub-mkimage.c (compress_kernel_lzma): Respect format security. + (generate_image): Make prefix a const char *. + Fix format specifications. Respect format security. + Avoid void * arithmetics. + Avoid shadowing. + (argp_parser): Remove unused variable. Respect format security. + * util/grub-mkimagexx.c (relocate_symbols): Avoid shadowing. + (count_funcs) [!MKIMAGE_ELF64]: #if-out. + (count_funcs): Remove unused variable. + (relocate_addresses): Fix format specification. + Disable x86-64 with elf32. Remove unused variables. + (add_fixup_entry): Avoid shadowing. + (make_reloc_section): Fix format specification. + Use assert. + (locate_sections): Fix format specifications. + (load_image): Avoid shadowing. + +2012-02-10 Vladimir Serbinenko + + * util/grub-setup.c (setup): Remove unused variable. Avoid shadowing. + Fix format specifications. Respect format security. + Don't translate already translated grub_errmsg. + (argp_parser): Remove unused variable + +2012-02-10 Vladimir Serbinenko + + * util/grub-mkrelpath.c (argp_parser): Remove unused variable. + +2012-02-10 Vladimir Serbinenko + + * util/grub-mkpasswd-pbkdf2.c (argp_parser): Remove unused variable. + (main): Likewise. Use xmalloc. Respect format security. + +2012-02-10 Vladimir Serbinenko + + * util/grub-mklayout.c (console_grub_equivalence): Make "layout" + a const char *. + (argp_parser): Remove unused variable. + +2012-02-10 Vladimir Serbinenko + + * util/grub-mkfont.c (grub_font_info): Make name a const char *. + (add_pixel): Make static. + (add_font): Likewise. + (write_string_section): Make name and str a const char *. + (write_be16_section): Make name a const char *. + (print_glyphs): Make static. + (write_font_ascii_bitmap): Likewise. + (write_font_width_spec): Likewise. + (write_font_pf2): Likewise. + (argp_parser): Remove unused variable. + Respect format security. + (main): Avoid shadowing. Respect format security. + +2012-02-10 Vladimir Serbinenko + + * util/grub-editenv.c (argp_parser): Make static. + (create_envblk_file): Use xmalloc. + (open_envblk_file): Likewise. + Resepect format security. + (set_variables): Respect format security. + +2012-02-10 Vladimir Serbinenko + + * util/getroot.c (grub_find_device): Respect format security. + (get_mdadm_uuid): Remove unused variable. + (grub_util_pull_device): Dont call gettext on already translated + grub_errmsg. + (find_system_device): Remove unused variable. + (grub_util_get_grub_dev): Likewise. + (grub_make_system_path_relative_to_its_root): Respect format security. + +2012-02-10 Vladimir Serbinenko + + * util/grub-fstest.c (execute_command): Make first argument + a const char *. + (read_file): Avoid shadowing. + Reuse underlying error message if device open fails. + (cmd_cmp): Respect format security. + (root): Make const char *. + (fstest): Remove args argument and use global copy. + Respect format security. + (argp_parser): Make static. + (main): Make default_root const char *. + +2012-02-10 Vladimir Serbinenko + + * util/grub-mount.c (root): Make const char *. + (execute_command): Make first argument a const char *. + (fuse_init): Respect format security. + (argp_parser): Make static. Remove unused variable. + (main): Make default_root a const char *. + Respect format security. + +2012-02-10 Vladimir Serbinenko + + * util/grub-probe.c (probe): Don't call gettext on already translated + grub_errmsg. + Remove unused variables. + (argp_parser): Remove unused variable. + +2012-02-10 Vladimir Serbinenko + + * util/grub-script-check.c (argp_parser): Remove unused variable. + (main): Rename read to curread to avoid shadowing. + +2012-02-10 Vladimir Serbinenko + + * util/misc.c (grub_util_write_image_at): Fix format specification. + (grub_util_write_image): Likewise. + (grub_script_execute_argument_to_string): Removed (unused). + (grub_script_execute_menuentry): Likewise. + (grub_putchar): Likewise. + +2012-02-10 Vladimir Serbinenko + + * include/grub/symbol.h (EXT_C) [GRUB_UTIL]: Removed. + (FUNCTION) [GRUB_UTIL]: Likewise. + (VARIABLE) [GRUB_UTIL]: Likewise. + +2012-02-10 Vladimir Serbinenko + + * include/grub/misc.h: Avoid evaluationg NEED_ENABLE_EXECUTE_STACK and + NEED_REGISTER_FRAME_INFO in GRUB_UTIL. + +2012-02-10 Vladimir Serbinenko + + * grub-core/partmap/bsdlabel.c (iterate_real): Fix freeing of static + buffer. + +2012-02-10 Vladimir Serbinenko + + * grub-core/lib/LzmaEnc.c (LzmaEnc_FastPosInit): Made static. + (LzmaEnc_SaveState): Removed (unused). + (LzmaEnc_RestoreState): Likewise. + (LzmaEnc_InitPriceTables): Made static. + (LzmaEnc_Construct): Likewise. + (LzmaEnc_FreeLits): Likewise. + (LzmaEnc_Destruct): Likewise. + (LzmaEnc_Init): Likewise. + (LzmaEnc_InitPrices): Likewise. + (LzmaEnc_Finish): Likewise. + (LzmaEnc_PrepareForLzma2): Removed (unused). + (LzmaEnc_MemPrepare): Likewise. + (LzmaEnc_GetNumAvailableBytes): Likewise. + (LzmaEnc_GetCurBuf): Likewise. + (LzmaEnc_CodeOneMemBlock): Likewise. + +2012-02-10 Vladimir Serbinenko + + * grub-core/disk/ldm.c (grub_util_get_ldm): Remove unused variables. + (grub_util_ldm_embed): Likewise. + +2012-02-10 Vladimir Serbinenko + + * util/grub-editenv.c (print_var): Rename name to varname to + avoid shadowing. + (main): Rename index to curindex to avoid shadowing. + Make filename a const char *. + +2012-02-10 Vladimir Serbinenko + + * grub-core/script/lexer.c (grub_script_lexer_init): Rename getline + to arg_getline to avoid shadowing. + +2012-02-10 Vladimir Serbinenko + + * grub-core/partmap/gpt.c (gpt_partition_map_embed): Rename disk to + disk_ to avoid shadowing. + +2012-02-10 Vladimir Serbinenko + + * grub-core/lib/LzFind.c (MatchFinder_GetIndexByte): Rename index to + curindex to avoid shadowing. + Make static. + (MatchFinder_GetNumAvailableBytes): Make static. + +2012-02-10 Vladimir Serbinenko + + * grub-core/fs/squash4.c (direct_read): Rename read to curread to + avoid shadowing. + +2012-02-10 Vladimir Serbinenko + + * grub-core/disk/cryptodisk.c (grub_cryptodisk_endecrypt): Rename + argument from encrypt to do_encrypt to avoid shadowing. + +2012-02-09 Vladimir Serbinenko + + * grub-core/loader/multiboot_elfxx.c (grub_multiboot_load_elf): Fix + incorrect nesting of #if's. + +2012-02-09 Vladimir Serbinenko + + * grub-core/commands/lsacpi.c (disp_acpi_xsdt_table): #if'-out the + checks which are always false on some platforms. + (grub_cmd_lsacpi): Likewise. + * grub-core/kern/misc.c (grub_strtoul): Likewise. + * grub-core/loader/multiboot.c (grub_multiboot_set_video_mode): + Likewise. + +2012-02-09 Vladimir Serbinenko + + * grub-core/disk/diskfilter.c (read_segment): Renome unreachable code. + * grub-core/net/ip.c (grub_net_recv_ip4_packets): Likewise. + +2012-02-09 Vladimir Serbinenko + + * grub-core/gnulib/regex.h (re_pattern_buffer): Declare buffer as + re_dfa_t to avoid breaking alignment invariants. + * grub-core/gnulib/regex_internal.h (re_dfa_t): Moved to ... + * grub-core/gnulib/regex.h (re_dfa_t): ... here. + +2012-02-09 Vladimir Serbinenko + + * grub-core/loader/i386/xnu.c (grub_xnu_boot): Fix printf. + * grub-core/loader/ia64/efi/linux.c (grub_cmd_fpswa): Likewise. + +2012-02-09 Vladimir Serbinenko + + * grub-core/kern/i386/qemu/mmap.c (grub_machine_mmap_init): + Fix declaration. + +2012-02-09 Vladimir Serbinenko + + * grub-core/bus/usb/ehci.c (grub_ehci_ehcc_read32): Restructure to + conserve alignment invariants. + (grub_ehci_ehcc_read16): Likewise. + (grub_ehci_oper_read32): Likewise. + (grub_ehci_oper_write32): Likewise. + (grub_ehci_pci_iter) [!GRUB_HAVE_UNALIGNED_ACCESS]: Check alignment. + Conserve alignment invariants. + +2012-02-09 Vladimir Serbinenko + + * grub-core/kern/emu/full.c (grub_emu_post_init): Remove raid reinit. + * include/grub/disk.h [GRUB_MACHINE_EMU]: Remove now useless LVM/RAID + declarations. + +2012-02-09 Vladimir Serbinenko + + * grub-core/kern/emu/hostfs.c (grub_hostfs_close): + Remove unused variable. + +2012-02-09 Vladimir Serbinenko + + * grub-core/efiemu/loadcore_common.c (grub_efiemu_loadcore_load): + Remove set in if. + +2012-02-09 Vladimir Serbinenko + + * include/grub/net.h: Remove double declarations. + +2012-02-09 Vladimir Serbinenko + + Remove "payload" command in ia64 Linux loader since I couldn't + find any evidence of it being used for anything. + Replace "relocate" command with an environment variable + + * grub-core/loader/ia64/efi/linux.c (ia64_boot_param): Remove extra + fields. + (ia64_boot_payload): Removed. + (last_payload): Likewise. + (RELOCATE_OFF): Likewise. + (RELOCATE_ON): Likewise. + (RELOCATE_FORCE): Likewise. + (relocate): Likewise. + (free_pages): Don't free payloads. + (grub_load_elf64): Use common error messages. + Use "linux_relocate" variable. + Increase the space after boot_params. + (grub_cmd_payload): Removed. + (grub_cmd_relocate): Likewise. + (grub_cmd_fpswa): Improve messages. + (cmd_payload): Removed. + (cmd_relocate): Likewise. + (GRUB_MOD_INIT): Don't register "payload" and "relocate". + (GRUB_MOD_FINI): Don't unregister "payload" and "relocate". + +2012-02-09 Vladimir Serbinenko + + Convert UHCI to DMA framework. + + * grub-core/bus/usb/uhci.c (grub_uhci): Add chunk and phys members. + (grub_uhci_pci_iter): Fill new members + (grub_alloc_td): Use P2V and V2P functions. + (grub_free_queue): Likewise. + (grub_alloc_qh): Likewise. + (grub_uhci_setup_transfer): Likewise. + (grub_uhci_check_transfer): Likewise. + +2012-02-09 Vladimir Serbinenko + + * grub-core/video/colors.c (grub_video_parse_color): Fix error message. + Remove assignment in if while on it. + +2012-02-09 Vladimir Serbinenko + + * util/grub-mkstandalone.in: Fix modules directory. + +2012-02-09 Vladimir Serbinenko + + * util/grub-mkimage.c (image_targets): Set default_compression to lzma + on i386-pc target. + (argp_parser): Accept "auto" as compression specification. + +2012-02-09 Vladimir Serbinenko + + Fix `help' with unloaded modules. + + * include/grub/normal.h (grub_dyncmd_get_cmd): New proto. + * grub-core/normal/dyncmd.c (grub_dyncmd_get_cmd): New function. + (grub_dyncmd_dispatcher): Small stylistic fix. + * grub-core/commands/help.c (grub_cmd_help): Load missing modules when + explicit help is requested. + +2012-02-09 Vladimir Serbinenko + + * grub-core/fs/cpio.c (grub_cpio_dir): Fix a bug with multiple listing. + Explicitly init restart while on it. + +2012-02-09 Vladimir Serbinenko + + * grub-core/lib/posix_wrap/wchar.h (mbrtowc): Set pwc to zero to avoid + uninited variable. + +2012-02-08 Vladimir Serbinenko + + * util/grub-mknetdir.in: Use . rather than source for POSIX + compatibility. + +2012-02-08 Vladimir Serbinenko + + * util/grub-probe.c (main): Fix trailing space in compatibility hint. + +2012-02-08 Vladimir Serbinenko + + * grub-core/kern/partition.c (grub_partition_get_name): Fix uninited + variable. + +2012-02-08 Vladimir Serbinenko + + * grub-core/commands/hdparm.c (grub_cmd_hdparm): Accept device name + without quotes. + +2012-02-08 Vladimir Serbinenko + + * grub-core/net/net.c (GRUB_MOD_INIT): Don't register netfs. + +2012-02-08 Vladimir Serbinenko + + * grub-core/kern/partition.c (grub_partition_get_name): Fix reverse + iteration of partitions. + +2012-02-08 Vladimir Serbinenko + + Improve gettext support. Stylistic fixes and error handling fixes while + on it. + +2012-02-07 Vladimir Serbinenko + + * grub-core/lib/i386/relocator16.S: Revert moving A20 code into PM + part. Instead setup the correct stack in RM. + * grub-core/lib/i386/relocator.c (grub_relocator16_boot): Reserve place + for stack. + * include/grub/i386/relocator_private.h: New file. + +2012-02-05 Vladimir Serbinenko + + * grub-core/commands/minicmd.c (GRUB_MOD_INIT): Add missing SIZE + argument. + * util/grub-fstest.c (options): Add missing DEVICE part. + +2012-02-05 Vladimir Serbinenko + + Clarify and unify messages. + + * grub-core/commands/hashsum.c (options): Unify messages. + * grub-core/commands/keystatus.c (GRUB_MOD_INIT): Don't mark a + literal-only message as translatable. + * grub-core/commands/lsacpi.c (GRUB_MOD_INIT): Likewise. + * grub-core/loader/ia64/efi/linux.c (GRUB_MOD_INIT): Likewise. + * grub-core/commands/legacycfg.c (GRUB_MOD_INIT): Add quoting around + commands. + * grub-core/commands/menuentry.c (options): Clarify that it's a keyboard + key, not the key used to unlock. Clarify what it's used for. + * grub-core/kern/emu/hostdisk.c (read_device_map): Unify error message. + * grub-core/loader/xnu.c (grub_xnu_load_driver): Remove erroneous colon. + * grub-core/script/main.c (GRUB_MOD_INIT): Clarify [n] to be [NUM]. + * util/grub-editenv.c (options): Unify "verbose" message. + * util/grub-fstest.c (read_file): Unify error message. + (fstest): Add quotes around commands. + (options): Unify "verbose" message. + * util/grub-install.in: Add quotes around variable name. + * util/grub-kbdcomp.in: Unify error message. + * util/grub-mkfont.c (main): Likewise. + * util/grub-mkrescue.in: Likewise. + * util/grub-mklayout.c (options): Unify "verbose" message. + * util/grub-mkstandalone.in: Unify help and verbose messages. + * util/grub-mount.c (options): Unify "verbose" message. + * util/grub-probe.c (options): Likewise. + * util/grub-script-check.c (options): Likewise. + * util/grub-setup.c (setup): Unify no-terminator message. + (options): Use DEVICE and not DEV. + Unify "verbose" message. + * util/ieee1275/ofpath.c (xrealpath): Unify error message. + +2012-02-05 Vladimir Serbinenko + + Improve and unify messages. + + * grub-core/kern/emu/hostdisk.c (grub_util_get_fd_sectors): Add argument + name. All users updated. + Print filename in error. + (read_device_map): Print filename in error. + * util/getroot.c (grub_guess_root_devices): Print filename in error. + (grub_util_get_os_disk): Likewise. + (grub_util_biosdisk_get_grub_dev): Likewise. + (grub_util_check_block_device): Likewise. + (grub_util_check_char_device): Likewise. + (grub_make_system_path_relative_to_its_root): Likewise. + * util/grub-editenv.c (create_envblk_file): Likewise. + (open_envblk_file): Likewise. + (write_envblk): Likewise. + * util/grub-fstest.c (cmd_cp): Likewise. + (cmd_cat): Likewise. + (cmd_cmp): Likewise. + * util/grub-menulst2cfg.c (main): Likewise. + * util/grub-mkfont.c (write_font_ascii_bitmap): Likewise. + (write_font_width_spec): Likewise. + (write_font_pf2): Likewise. + * util/grub-mkimage.c (generate_image): New argument outname. + All users updated. + Remove unreacheable message. + (options): Unify messages. + (help_filter): Likewise. + * util/grub-mklayout.c (usage): Removed (unused). + (main): Print filename in error. + * util/grub-mkrescue.in: Fix wrong quoting. + * util/grub-setup.c (setup): Print filename in error. + * util/ieee1275/ofpath.c (vendor_is_ATA): Likewise. + (check_sas): Likewise. + * util/misc.c (grub_util_get_fp_size): Removed. + (grub_util_get_image_size): Print filename in error. + (grub_util_read_at): Removed. + (grub_util_read_image): Print filename in error. + (grub_util_load_image): Likewise. + (grub_util_write_image_at): New argument filename. All users updated. + Print filename in error. + (grub_util_write_image): New argument filename. All users updated. + Print filename in error. + * util/raid.c (grub_util_raid_getmembers): Print filename in error. + * util/resolve.c (grub_util_resolve_dependencies): Likewise. + +2012-02-05 Vladimir Serbinenko + + * grub-core/Makefile.core.def (pxechain): New module. + * grub-core/loader/i386/pc/pxechainloader.c: New file. + * grub-core/net/drivers/i386/pc/pxe.c (grub_pxe_get_cached): New + function. + (grub_pc_net_config_real): Use grub_pxe_get_cached. + * include/grub/i386/pc/pxe.h (grub_pxe_get_cached): New proto. + +2012-02-05 Vladimir Serbinenko + + * grub-core/kern/err.c (GRUB_MAX_ERRMSG): Move to ... + * include/grub/err.h (GRUB_MAX_ERRMSG): ... here. + * include/grub/err.h (grub_error_saved): New struct. + (grub_errmsg): Make array size explicit. + * include/grub/misc.h (grub_error_save): New function. + (grub_error_load): Likewise. + * grub-core/kern/err.c (grub_error_stack_items): Use grub_error_saved. + (grub_error_push): Update `errno' member name. + (grub_error_pop): Likewise + * grub-core/net/tftp.c (tftp_data): New member save_err. + (tftp_receive): Save error. + (tftp_open): Restore error. + +2012-02-05 Vladimir Serbinenko + + * grub-core/lib/i386/relocator16.S (grub_relocator16_start): Move switch + to real mode down to execute A20-related code in protected mode as + intended. + +2012-02-05 Grégoire Sutre + + * grub-core/disk/diskfilter.c (grub_diskfilter_make_raid): Return + NULL when the argument `level' has an unexpected value. + +2012-02-04 Vladimir Serbinenko + + Move platform-dependent files from $prefix to $prefix/$platform. + + * config.h.in (GRUB_TARGET_CPU): New definition. + (GRUB_PLATFORM): Likewise. + * configure.ac: Define GRUB_TARGET_CPU and GRUB_PLATFORM. + * grub-core/commands/parttool.c (grub_cmd_parttool): Update dir. + * grub-core/efiemu/main.c (grub_efiemu_autocore): Likewise. + * grub-core/kern/dl.c (grub_dl_load): Likewise. + * grub-core/normal/autofs.c (read_fs_list): Likewise. + * grub-core/normal/crypto.c (read_crypto_list): Likewise. + * grub-core/normal/dyncmd.c (read_command_list): Likewise. + * grub-core/normal/term.c (read_terminal_list): Likewise. + * grub-core/gettext/gettext.c (grub_mofile_open_lang): Use + $prefix/locale. + (grub_gettext_init_ext): Likewise. + * grub-core/normal/main.c (GRUB_MOD_INIT): Define grub_cpu and + grub_platform. + * util/grub-install.in: Update directories. + * util/grub-mknetdir.in: Likewise. + * util/grub-mkrescue.in: Likewise. + +2012-02-04 Vladimir Serbinenko + + * grub-core/kern/ieee1275/openfw.c (grub_claimmap): Change to + grub_error framework. All users updated. + +2012-02-04 Vladimir Serbinenko + + * grub-core/gettext/gettext.c: Mostly rewritten to avoid using + lists (by always binsearching), improve caching (cache strings + used for binsearch, not only results), improve + maintainability (by using more structured binary search) and correct + error handling. + +2012-02-04 Vladimir Serbinenko + + * grub-core/script/execute.c (grub_script_return): Fix warning. + +2012-02-04 Vladimir Serbinenko + + * grub-core/script/execute.c (grub_script_return): Fix potential + NULL-dereference. + Reported by: Jim Meyering. + +2012-02-03 Vladimir Serbinenko + + * po/POTFILES.in: Regenerate. + * util/grub-install.in: Gettextize the strings missed in first pass. + +2012-02-03 Vladimir Serbinenko + + * Makefile.util.def (grub-mkdevicemap): Removed. + * include/grub/emu/hostdisk.h (grub_util_get_os_disk): New proto. + * include/grub/util/deviceiter.h: Removed. + * util/deviceiter.c: Likewise. + * util/getroot.c (grub_util_get_os_disk): New function. + * util/grub-install.in: Remove grub-mkdevicemap. Use -t disk as + replacement for EFI. + * util/grub-mkdevicemap.c: Removed. + * util/grub-probe.c (probe): Handle PRINT_DISK. + (argp_parser): Handle -t disk. + +2012-02-03 Vladimir Serbinenko + + * util/grub-mkfont.c: Migrate to argp. + * util/grub-mklayout.c: Likewise. + * util/grub-mkpasswd-pbkdf2.c: Likewise. + * util/grub-mkrelpath.c: Likewise. + * util/grub-probe.c: Likewise. + * util/grub-script-check.c: Likewise. + +2012-02-03 Vladimir Serbinenko + + * util/grub-reboot.in: Add missing datarootdir. + Add missing newline. + * util/grub-set-default.in: Add missing datarootdir. + * util/powerpc/ieee1275/grub-mkrescue.in: Add missing newline. + * util/grub-mkrescue.in: Likewise. + +2012-02-03 Vladimir Serbinenko + + * util/grub.d/30_os-prober.in: Fix TRANSLATORS comment. + +2012-02-03 Vladimir Serbinenko + + * util/grub-kbdcomp.in: Add decent help and gettextize. + * docs/man/grub-kbdcomp.h2m: New file. + +2012-02-03 Vladimir Serbinenko + + Migrate grub-mkimage.c to argp. + + * Makefile.util.def (grub-mkimage): Add util/argp_common.c. + (grub-setup): Likewise. + * util/grub-setup.c (print_version): Move to ... + * util/argp_common.c (print_version): ... here. + * util/grub-setup.c (argp_program_version_hook): Move to ... + * util/argp_common.c (argp_program_version_hook): ... here. + * util/grub-setup.c (argp_parser): Add exit (1) on fatal error for + safety. + * util/grub-mkimage.c (main): Migrate to argp. + +2012-02-03 Vladimir Serbinenko + + * util/grub-mkrescue.in: Use same message as + util/powerpc/ieee1275/grub-mkrescue.in with %s in place of command + for better translations. + +2012-02-03 Vladimir Serbinenko + + * util/powerpc/ieee1275/grub-mkrescue.in: Gettextize. Unify the command + options with generic grub-mkrescue.in with the goal of future + merge. + +2012-02-03 Vladimir Serbinenko + + * grub-core/kern/mm.c: Add missing include of i18n.h + * grub-core/lib/relocator.c: Likewise. + +2012-02-03 Vladimir Serbinenko + + * grub-core/loader/ia64/efi/linux.c (find_mmap_size): Replace fatal with + error. + (allocate_pages): Check return value. + Replace fatal with error. + (grub_linux_boot): Replace printf with dprintf. + Check find_mmap_size return value. + Replace fatal with error. + Don't call grub_machine_fini. + (grub_load_elf64): Replace printf with dprintf. + (grub_cmd_linux): Likewise. + (grub_cmd_initrd): Likewise. + (grub_cmd_payload): Likewise. + +2012-02-03 Vladimir Serbinenko + + * grub-core/loader/i386/xnu.c (grub_cmd_devprop_load): Fix error + message. + * grub-core/video/radeon_fuloong2e.c + (grub_video_radeon_fuloong2e_setup): Likewise. + * grub-core/video/sis315pro.c (grub_video_sis315pro_setup): Likewise. + * grub-core/video/video.c (grub_video_set_mode): Don't override + standard out of memory message. + +2012-02-03 Grégoire Sutre + + NetBSD disk wedge support. + + * grub-core/kern/emu/hostdisk.c (grub_hostdisk_find_partition_start) + [__NetBSD__]: Handle NetBSD disk wedges. + * util/getroot.c (convert_system_partition_to_system_disk) + [__NetBSD__]: Likewise. + +2012-02-03 Mark Wooding + + * util/grub-mkconfig.in: Use umask rather than chmod to create + grub.cfg.new to avoid insecure grub.cfg. + +2012-02-03 Vladimir Serbinenko + + * grub-core/commands/ls.c: Gettextize. + * grub-core/commands/setpci.c: Likewise. + * grub-core/commands/videotest.c: Likewise. + * grub-core/disk/geli.c: Likewise. + * grub-core/kern/mm.c: Likewise. + * grub-core/lib/relocator.c: Likewise. + * grub-core/loader/efi/appleloader.c: Likewise. + * grub-core/loader/i386/xnu.c: Likewise. + * grub-core/loader/ia64/efi/linux.c: Likewise. + * grub-core/loader/xnu.c: Likewise. + * grub-core/net/dns.c: Likewise. + * grub-core/net/net.c: Likewise. + * grub-core/script/lexer.c: Likewise. + * grub-core/script/parser.y: Likewise. + * grub-core/script/yylex.l: Likewise. + * util/getroot.c: Likewise. + * util/grub-setup.c: Likewise. + +2012-02-03 Vladimir Serbinenko + + * grub-core/fs/reiserfs.c (grub_reiserfs_get_item): Use proper error + number. + +2012-02-03 Vladimir Serbinenko + + * grub-core/disk/ldm.c (grub_util_ldm_embed): Correct error message. + +2012-02-03 Vladimir Serbinenko + + * grub-core/commands/search_file.c (SEARCH_TARGET): Remove obsolete + macro. + * grub-core/commands/search_label.c (SEARCH_TARGET): Likewise. + * grub-core/commands/search_uuid.c (SEARCH_TARGET): Likewise. + +2012-02-03 Vladimir Serbinenko + + * util/grub-mkstandalone.in: Fix help messages. Gettextize. + * util/grub-install.in: Gettextize. + * util/grub-mkconfig.in: Likewise. + * util/grub-mkconfig_lib.in: Replace gettext with echo -n and not echo + if not available. + (grub_warn): Gettextize. + * util/grub-mknetdir.in: Gettextize. + * util/grub-mkrescue.in: Likewise. + * util/grub-mkstandalone.in: Likewise. + * util/grub-reboot.in: Likewise. + * util/grub-set-default.in: Likewise. + * util/grub.d/00_header.in: Likewise. + * util/grub.d/10_hurd.in: Likewise. + * util/grub.d/10_kfreebsd.in: Likewise. + * util/grub.d/10_linux.in: Likewise. + * util/grub.d/10_netbsd.in: Likewise. + * util/grub.d/10_windows.in: Likewise. + * util/grub.d/20_linux_xen.in: Likewise. + * util/grub.d/30_os-prober.in: Likewise. + * po/POTFILES-shell.in: Regenerate. + +2012-02-03 Richard Laager + + * util/grub-mkimage.c (main): Fix format-security warning. + * util/grub-mkrelpath.c (main): Likewise. + * util/grub-probe.c (main): Likewise. + +2012-02-03 Richard Laager + + * util/grub-probe.c (probe): Don't crash on canonicalize_file_name + failure. + Put back lost PRINT_DRIVE. + +2012-02-03 Richard Laager + + * util/getroot.c (find_root_devices_from_libzfs): Fix compilation error. + (grub_guess_root_devices): Replace strlen with sizeof. + Avoid crash. + (find_root_devices_from_poolname): Remove unused variable. + Handle raidzN. + +2012-02-03 Vladimir Serbinenko + + Support install on multi-device filesystems. + + * include/grub/emu/getroot.h (grub_guess_root_device): Renamed to ... + (grub_guess_root_devices): ...this. Return char **. All users updated. + * include/grub/emu/misc.h (grub_find_root_device_from_mountinfo): + Removed. + * util/getroot.c (find_root_device_from_libzfs): Moved pool logic to ... + (find_root_devices_from_poolname): ... here. + (grub_find_root_devices_from_mountinfo): Return char **. Make static. + Support zfs-fuse. + (grub_guess_root_device): Rename to ... + (grub_guess_root_devices): ... this. Return char **. All users updated. + * util/grub-install.in: Handle multi-device filesystems. + * util/grub-probe.c (probe). Make device_names a char **. Add delim + argument. All users updated. + Handle multi-device filesystems. + Use 'delim' as separator. + Remove device check to allow filesystems on file. + (main): Support -0 argument. Handle multi-device. + * util/grub-setup.c (setup): Remove root argument. Handle multi-device. + Fix a cross-device check while on it. + (arguments): Remove root_dev. + (argp_parser): Remove -r. + (main): Remove root_dev. + +2012-02-01 Vladimir Serbinenko + + * grub-core/fs/zfs/zfscrypt.c: Add link to documentation. + +2012-02-01 Vladimir Serbinenko + + * grub-core/commands/videotest.c (grub_cmd_videotest): Fix subset + symbol. + Reported by: NODA, Kai . + +2012-02-01 Vladimir Serbinenko + + Fix ehci on amd64. + + * grub-core/bus/usb/usbhub.c (grub_usb_hub_add_dev): Use %p to print + pointers. + * grub-core/bus/usb/ehci.c (grub_ehci_pci_iter): Likewise. + (grub_ehci_setup_qh): Likewise. + (grub_ehci_find_qh): Likewise. + (grub_ehci_transaction): Likewise. + (grub_ehci_setup_transfer): Likewise. + (grub_ehci_check_transfer): Likewise. + (grub_ehci_portstatus): Likewise. + (grub_ehci_detect_dev): Likewise. + (grub_ehci_transfer_controller_data): New field td_last_phys. + (grub_ehci_setup_transfer): Fill td_last_phys. + (grub_ehci_check_transfer): Use td_last_phys. + +2012-02-01 Seth Goldberg + + * grub-core/normal/context.c (grub_env_extractor_close): Don't crash + if no submenu is present. + +2012-02-01 Aleš Nesrsta + + CBI support. + + * include/grub/usb.h (grub_usbms_protocol_t): New values + GRUB_USBMS_PROTOCOL_CB and GRUB_USBMS_PROTOCOL_CBI. + * grub-core/disk/usbms.c (GRUB_USBMS_CBI_CMD_SIZE): New define. + (GRUB_USBMS_CBI_ADSC_REQ): Likewise. + (grub_usbms_dev): Add subclass, protocol and intrpt. + Remove in_maxsz and out_maxsz. + (grub_usbms_reset): Rename to ... + (grub_usbms_bo_reset): .. this. + (grub_usbms_cbi_cmd): New function. + (grub_usbms_cbi_reset): Likewise. + (grub_usbms_reset): Likewise. + (grub_usbms_attach): Recognize cbi. Same subclass and protocol. + (grub_usbms_transfer): Rename to ... + (grub_usbms_transfer_bo): ... this. + (grub_usbms_transfer_cbi): Likewise. + (grub_usbms_transfer): Likewise. + +2012-02-01 Aleš Nesrsta +2012-02-01 Vladimir Serbinenko + + EHCI support. All of the credit goes to Aleš Nesrsta. I've just added + the support for the CS5536 modification thereos and few bugfixes. + + * grub-core/Makefile.core.def (ehci): New module. + * grub-core/bus/usb/ehci.c: New file. + * grub-core/bus/usb/usbhub.c (grub_usb_hub_add_dev): New arguments + port and hubaddr. All users updated. + Save port and hubaddr into dev structure. + * include/grub/cs5536.h (GRUB_CS5536_MSR_USB_BASE_SMI_ENABLE): New + define. + * include/grub/pci.h (grub_dma_phys2virt): New function. + (grub_dma_virt2phys): Likewise. + * include/grub/usb.h (grub_usb_device): New members port and hubaddr. + +2012-01-31 Vladimir Serbinenko + + * grub-core/fs/fat.c (grub_fat_mount) [!MODE_EXFAT]: Remove fstype + check as some mkfs implementations omit it. + +2012-01-31 Vladimir Serbinenko + + * docs/grub.texi (Unicode): Mention identifier and space limitations. + +2012-01-31 Vladimir Serbinenko + + * grub-core/fs/jfs.c (grub_jfs_sblock): Make volname a char array. + Add new member volname2. + (grub_jfs_label): Use volname2 if available. + +2012-01-31 Vladimir Serbinenko + + * grub-core/fs/nilfs2.c (grub_nilfs2_super_block): Expand volume_name + over last_mounted as seen in image generated by mkfs.nilfs2. + (grub_nilfs2_label): Use sizeof for the size of s_volume_name. + +2012-01-31 Vladimir Serbinenko + + * grub-core/fs/fat.c (grub_fat_dir_entry) [MODE_EXFAT]: Expand label + to 15 UTF-16 characters as seen in FS generated by mkexfatfs. + (grub_fat_label) [MODE_EXFAT]: Use macros for size. + +2012-01-31 Vladimir Serbinenko + + * grub-core/fs/romfs.c (grub_romfs_mount): Fix a bug with labels going + over the sector. + +2012-01-31 Vladimir Serbinenko + + * grub-core/fs/zfs/zfs.c (get_filesystem_dnode): Support space in + subvolume name (by removing a bogus and useless check). + +2012-01-31 Vladimir Serbinenko + + * grub-core/fs/ext2.c (grub_ext2_label): Fix field size. Change to + sizeof while on it. + +2012-01-30 Vladimir Serbinenko + + * grub-core/disk/scsi.c (grub_scsi_read_capacity): Renamed to ... + (grub_scsi_read_capacity10): ... this. + (grub_scsi_read_capacity16): New function. + (grub_scsi_open): Use read_capacity16 if read_capacity10 returned + 0xffffffff. + Fix off-by-one error. + * include/grub/scsi.h (grub_scsi): Rename size to last_block and make it + 64-bit unsigned. + * include/grub/scsicmd.h (grub_scsi_read_capacity): Rename to ... + (grub_scsi_read_capacity10): ... this. + (grub_scsi_read_capacity_data): Rename to ... + (grub_scsi_read_capacity10_data): ... this. Rename size to last_block. + (grub_scsi_read_capacity16): New struct. + (grub_scsi_read_capacity16_data): Likewise. + (grub_scsi_cmd_t): Rename grub_scsi_cmd_read_capacity to + grub_scsi_cmd_read_capacity10. + New command grub_scsi_cmd_read_capacity16. + +2012-01-30 Vladimir Serbinenko + + SCSI >2TiB support. + + * grub-core/disk/scsi.c (grub_scsi_read16): New function. + (grub_scsi_write16): Likewise. + (grub_scsi_read): Use read16 when necessary. + (grub_scsi_write): Likewise. + * include/grub/scsicmd.h (grub_scsi_read16): New struct. + (grub_scsi_write16): Likewise. + (grub_scsi_cmd_t): Add READ16 and WRITE16. + +2012-01-30 Vladimir Serbinenko + + SCSI write support (for usbms mainly). + + * grub-core/disk/scsi.c (grub_scsi_write10): Uncomment. Make buffer + a const pointer. + (grub_scsi_write): Implement. + * include/grub/scsi.h (grub_scsi_dev): Make write buffer a const pointer + +2012-01-30 Vladimir Serbinenko + + * grub-core/io/lzopio.c (uncompress_block): Fix use of incorrect + variable. + +2012-01-29 Vladimir Serbinenko + + * grub-core/lib/posix_wrap/string.h (memchr): New function. + +2012-01-29 Vladimir Serbinenko + + * po/POTFILES.in: Regenerate. + +2012-01-29 Vladimir Serbinenko + + * grub-core/lib/posix_wrap/assert.h (assert_real): Replace grub_fatal + with grub_printf to avoid unnecessary fatal failure. + +2012-01-29 Vladimir Serbinenko + + * grub-core/lib/posix_wrap/limits.h (SHRT_MAX): New define. + (INT_MAX): Likewise. + * grub-core/lib/posix_wrap/stdio.h (snprintf): New function. + * grub-core/lib/posix_wrap/stdlib.h (abs): Likewise. + * grub-core/lib/posix_wrap/string.h (memcmp): Likewise. + (strcpy): Likewise. + (strstr): Likewise. + (strchr): Likewise. + (strncpy): Likewise. + (strcat): Likewise. + (strncat): Likewise. + (strcoll): Likewise. + * include/grub/types.h (GRUB_SHRT_MAX): New define. + (GRUB_INT_MAX): Likewise. + +2012-01-29 Vladimir Serbinenko + + * grub-core/gnulib/regcomp.c (regerror): Don't use abort on + unexpected error. + (optimize_utf8): Likewise. + * grub-core/lib/posix_wrap/stdlib.h (abort): Removed. + +2012-01-29 Vladimir Serbinenko + + * grub-core/boot/i386/pc/lnxboot.S: Use + GRUB_DECOMPRESSOR_MAX_DECOMPRESSOR_SIZE. + * grub-core/boot/i386/pc/startup_raw.S: Ensure about boot_dev + location. + * include/grub/offsets.h (GRUB_DECOMPRESSOR_I386_PC_BOOT_DEVICE): New + definition. + (GRUB_DECOMPRESSOR_I386_PC_MAX_DECOMPRESSOR_SIZE): Likewise. + +2012-01-29 Vladimir Serbinenko + + * util/getroot.c (grub_util_get_dm_node_linear_info): Fix memory leak. + * grub-core/disk/cryptodisk.c (cryptodisk_cleanup): Disable for + now to avoid double free. + * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_dev): Rename to + hostdisk. + * include/grub/disk.h (grub_disk_dev_id): New id HOSTDISK. + * util/grub-probe.c (escape_of_path): Always return a new copy. + (print_full_name): Escape path. + (probe): Don't call grub_util_devname_to_ofpath on NULL. + Fix hints on abstractions. + +2012-01-29 Vladimir Serbinenko + + * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): + Don't add "root" line if no compatibility hont is available. + Suggested by: Seth Goldberg. + +2012-01-29 Vladimir Serbinenko + + * include/grub/ata.h (grub_ata): Add a new element maxbuffer. + * grub-core/disk/ata.c (grub_ata_readwrite): Limit to ata->maxbuffer. + * grub-core/disk/pata.c (grub_pata_open): Set ata->maxbuffer. + * grub-core/disk/ahci.c (grub_ahci_open): Likewise. + +2012-01-29 Vladimir Serbinenko + + * include/grub/zfs/dnode.h (DN_MIN_INDBLKSHIFT): Removed. + +2012-01-29 Vladimir Serbinenko + + * util/grub-pe2elf.c (ehdr): Make static. + (shdr): Likewise. + (num_sections): Likewise. + (offset): Likewise. + +2012-01-29 Vladimir Serbinenko + + Eliminate ofpath limits and possible overflows. + + * util/ieee1275/ofpath.c (grub_util_info) [STANDALONE]: New function. + (OF_PATH_MAX): Removed. + (MAX_DISK_CAT): New const. + (find_obppath): Use allocated rather than preallocated buffer. + Return result. Argument of_path removed. All users updated. + Add missing fdstat. + (xrealpath): New function. + (block_device_get_sysfs_path_and_link): Remove sysfs argument. + Allocate rather than use preallocated buffer. All users updated. + (__of_path_common): Use allocated rather than preallocatecd buffer. + Return result. Argument of_path removed. All users updated. + (vendor_is_ATA): Read only needed part form the file. + (check_sas): Allocate depending on contents rather than fixed. + (main) [STANDALONE]: Handle NULL result. + +2012-01-29 Vladimir Serbinenko + + * grub-core/normal/completion.c (iterate_dev): Close the disk. + +2012-01-29 Vladimir Serbinenko + + Cryptodisk write support. + + * grub-core/disk/cryptodisk.c (grub_crypto_pcbc_encrypt): New function. + (grub_cryptodisk_decrypt): Moved logic to ... + (grub_cryptodisk_endecrypt): ...this. New argument "encrypt". + (grub_cryptodisk_write): Implement. + * grub-core/kern/emu/hostdisk.c (nwrite): Rename to ... + (grub_util_fd_write): ... this. Make global. + * include/grub/emu/hostdisk.h (grub_util_fd_write): New proto. + +2012-01-29 Vladimir Serbinenko + + * include/grub/list.h (grub_list_remove): Don't crash if element is + removed twice. + +2012-01-29 Vladimir Serbinenko + + Rename ofconsole to console. + + * grub-core/commands/terminal.c (handle_command): Handle ofconsole + as sysnonym to console. + * grub-core/term/ieee1275/ofconsole.c: Renamed to .. + * grub-core/term/ieee1275/console.c: ... this. All users updated. + Rename grub_ofconsole_ to grub_console_. All users updated + (grub_console_term_output): Rename "ofconsole" to "console". + * grub-core/term/terminfo.c (grub_cmd_terminfo): Handle "ofconsole" + as "console". + +2012-01-29 Vladimir Serbinenko + + * grub-core/loader/i386/pc/plan9.c (grub_cmd_plan9): Remove PXE + handling. + * include/grub/disk.h (grub_disk_dev_id): Remove obsolete + GRUB_DISK_DEVICE_UUID_ID, GRUB_DISK_DEVICE_PXE_ID and + GRUB_DISK_DEVICE_FILE_ID. + +2012-01-29 Vladimir Serbinenko + + * grub-core/kern/partition.c (grub_partition_get_name): Simplify logic + and improve performance. + +2012-01-29 Vladimir Serbinenko + + * grub-core/kern/ieee1275/openfw.c (grub_ieee1275_encode_devname): Fix + missing ieee1275/ prefix on whole disk. + +2012-01-29 Vladimir Serbinenko + + * include/grub/powerpc/ieee1275/util/biosdisk.h: Remove. + * include/grub/powerpc/ieee1275/biosdisk.h: Likewise. + +2012-01-29 Vladimir Serbinenko + + * grub-core/fs/cpio.c (handle_symlink): Fix a bug. + +2012-01-29 Vladimir Serbinenko + + Merge common RAID and LVM logic to an abstract diskfilter. + Add LDM support using the same framework. + + * Makefile.util.def (libgrubkern): Add grub-core/disk/ldm.c, + grub-core/disk/diskfilter.c and grub-core/partmap/gpt.c. + (libgrubmods): Remove grub-core/disk/raid.c and + grub-core/partmap/gpt.c. + * grub-core/Makefile.core.def (ldm): New module. + (raid): Renamed to diskfilter. All users updated. + * grub-core/disk/raid.c: Moved to ... + * grub-core/disk/diskfilter.c: ... here. + * grub-core/disk/diskfilter.c: Rename grub_raid_ to grub_diskfilter_. + (lv_num): New var. + (find_array): Renamed to ... + (find_lv): ... this. Support multi-LV. Skip nameless LVs + (grub_is_array_readable): Renamed to ... + (grub_is_lv_readable): ... this. Support multinode hierarchy. + (insert_array): New argument id. + (is_node_readable): New function. + (scan_device): Rename to ... + (scan_disk): .. this. Restrict to one disk. + (scan_devices): New function. + (grub_diskfilter_iterate): Support multi-LV. + Skip invisible and nameless LVs. + (grub_diskfilter_memberlist): Support multi-LV. + (grub_diskfilter_read_node): New function. + (grub_raid_read): Most of logic moved to ... + (read_segment): ... here + (read_lv): New function. + (grub_diskfilter_get_vg_by_uuid): New function. + (grub_diskfilter_make_raid): Likewise. + * grub-core/disk/ldm.c: New file. + * grub-core/disk/lvm.c (vg_list): Removed. + (lv_count): Likewise. + (scan_depth): Likewise. + (is_lv_readable): Likewise. + (grub_lvm_getvalue): Advance pointer past the number. + (find_lv): Removed. + (do_lvm_scan): Refactored into ... + (grub_lvm_detect): ... this. Support raid. + (grub_lvm_iterate): Removed. + (grub_lvm_memberlist): Likewise. + (grub_lvm_open): Likewise. + (grub_lvm_close): Likewise. + (read_lv): Likewise. + (read_node): Likewise. + (is_node_readable): Likewise. + (is_lv_readable): Likewise. + (grub_lvm_read): Likewise. + (grub_lvm_write): Likewise. + (grub_lvm_dev): Use diskfilter + (GRUB_MOD_INIT): Likewise. + (GRUB_MOD_FINI): Likewise. + * grub-core/disk/dmraid_nvidia.c (grub_dmraid_nv_detect): Use + new interface. + * grub-core/disk/mdraid1x_linux.c (grub_mdraid_detect): Likewise. + * grub-core/disk/mdraid_linux.c (grub_mdraid_detect): Likewise. + * grub-core/disk/raid5_recover.c (grub_raid5_recover): Use + grub_diskfilter_read_node. + Fix a bug with xor. + * grub-core/disk/raid6_recover.c (grub_raid6_recover): Use + grub_diskfilter_read_node. + Support GRUB_RAID_LAYOUT_MUL_FROM_POS. + * grub-core/kern/disk.c (grub_disk_dev_list): Make global. + (grub_disk_dev_iterate): Move from here... + * include/grub/disk.h (grub_disk_dev_iterate): ... to here. Inlined. + * grub-core/kern/emu/hostdisk.c (grub_hostdisk_find_partition_start): + Make global. + (grub_hostdisk_find_partition_start): Likewise. + (grub_hostdisk_os_dev_to_grub_drive): New function. + (grub_util_biosdisk_get_osdev): Check that disk is biosdisk. + * grub-core/kern/emu/hostdisk.c (make_device_name): Move to ... + * util/getroot.c (make_device_name): ... here. + * grub-core/kern/emu/hostdisk.c (grub_util_get_dm_node_linear_info): + Move to ... + * util/getroot.c (grub_util_get_dm_node_linear_info): ...here. + * grub-core/kern/emu/hostdisk.c + (convert_system_partition_to_system_disk): Move to ... + * util/getroot.c (convert_system_partition_to_system_disk): ...here. + * grub-core/kern/emu/hostdisk.c (device_is_wholedisk): Move to ... + * util/getroot.c (device_is_wholedisk): ... here. + * grub-core/kern/emu/hostdisk.c (find_system_device): Move to ... + * util/getroot.c (find_system_device): ... here. + * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_is_present): + Move to ... + * util/getroot.c (grub_util_biosdisk_is_present): ...here. + * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_get_grub_dev): + Move to ... + * util/getroot.c (grub_util_biosdisk_get_grub_dev): ... here. + Handle LDM. + * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_is_floppy): + Move to ... + * util/getroot.c (grub_util_biosdisk_is_floppy): ... here. + * grub-core/partmap/gpt.c (grub_gpt_partition_map_iterate): Made global. + * include/grub/disk.h (grub_disk_dev_id): Replaced RAID and LVM with + DISKFILTER. + * include/grub/raid.h: Renamed to ... + * include/grub/diskfilter.h: ... this. + * include/grub/diskfilter.h: Rename grub_raid_* to grub_diskfilter_* + (GRUB_RAID_LAYOUT_*): Make into array. + (GRUB_RAID_LAYOUT_MUL_FROM_POS): New value. + (grub_diskfilter_vg): New struct. + (grub_diskfilter_pv_id): Likewise. + (grub_raid_member): Removed. + (grub_raid_array): Likewise. + (grub_diskfilter_pv): New struct. + (grub_diskfilter_lv): Likewise. + (grub_diskfilter_segment): Likewise. + (grub_diskfilter_node): Likewise. + (grub_diskfilter_get_vg_by_uuid): New proto. + (grub_raid_register): Inline. + (grub_diskfilter_unregister): Likewise. + (grub_diskfilter_make_raid): New proto. + (grub_diskfilter_vg_register): Likewise. + (grub_diskfilter_read_node): Likewise. + (grub_diskfilter_get_pv_from_disk) [GRUB_UTIL]: Likewise. + * include/grub/emu/hostdisk.h (grub_util_get_ldm): New proto. + (grub_util_is_ldm): Likewise. + (grub_util_ldm_embed) [GRUB_UTIL]: Likewise. + (grub_hostdisk_find_partition_start): Likewise. + (grub_hostdisk_os_dev_to_grub_drive): Likewise. + * include/grub/gpt_partition.h (GRUB_GPT_PARTITION_TYPE_LDM): + New definition. + (grub_gpt_partition_map_iterate): New proto. + * include/grub/lvm.h (grub_lvm_vg): Removed. + (grub_lvm_pv): Likewise. + (grub_lvm_lv): Likewise. + (grub_lvm_segment): Likewise. + (grub_lvm_node): Likewise. + * util/getroot.c [...] + * util/grub-probe.c (probe_raid_level): Handle diskfilter. + (probe_abstraction): Likewise. + * util/grub-setup.c (setup): Remove must_embed. Support LDM. + (main): Remove dead logic. + +2012-01-28 Vladimir Serbinenko + + Simplify root device discover and don't fail when trying to open + incorrect devices. + + * grub-core/disk/efi/efidisk.c (get_diskname_from_path_real): New + function. + (get_diskname_from_path): Likewise. + (grub_efidisk_get_device_name): Use get_diskname_from_path instead + of iterating. + +2012-01-27 Vladimir Serbinenko + + * grub-core/Makefile.core.def (setpci): Enable on all PCI platforms. + +2012-01-27 Vladimir Serbinenko + + * grub-core/fs/zfs/zfs.c (nvlist_find_value): Check that we don't go + pastthe end. + +2012-01-27 Vladimir Serbinenko + + * util/grub-install.in: Add missing \. + Reported by: gentoofan + +2012-01-26 Vladimir Serbinenko + + * grub-core/fs/squash4.c (xz_decompress): Fix return value. + (direct_read): Use correct compressed size. + (grub_squash_read_data): Likewise. + +2012-01-26 Vladimir Serbinenko + + * docs/grub.texi (Platform limitations): New section. + (Platform-specific operations): Likewise. + * docs/grub-dev.texi (Porting): Likewise. + +2012-01-25 Vladimir Serbinenko + + IEEE1275 disk write support. + + * grub-core/kern/ieee1275/ieee1275.c (grub_ieee1275_write): Make buffer + const void *. + * include/grub/ieee1275/ieee1275.h (grub_ieee1275_write): Likewise. + * grub-core/disk/ieee1275/ofdisk.c (grub_ofdisk_read): Move open + and seek loginc to ... + (grub_ofdisk_prepare): ... here. + (grub_ofdisk_write): Implement. + +2012-01-25 Vladimir Serbinenko + + ARC disk write support. + + * grub-core/disk/arc/arcdisk.c (handle_writable): New var. + (reopen): New argument writable. All users updated. + Handle required access mode. + (grub_arcdisk_write): Implement. + * include/grub/arc/arc.h (grub_arc_file_access): New enum. + (grub_arc_firmware_vector): Make buffer to write a const buffer. + +2012-01-25 Vladimir Serbinenko + + * grub-core/fs/btrfs.c (grub_btrfs_device): New field size. + (read_sblock): Don't attempt to read superblocks outside the disk size. + +2012-01-25 Vladimir Serbinenko + + * grub-core/fs/nilfs2.c (grub_nilfs2_load_sb): Use device size from + first superblock to find the second one when possible. + +2012-01-25 Vladimir Serbinenko + + * util/grub-install.in: Fix an ARC bug. + Print a warning if no platform-specific setup is available. + +2012-01-24 Vladimir Serbinenko + + Use static allocation rather than scratch pointer in reed_solomon. + It decreases its size significantly and avoids a variable in .text. + + * grub-core/lib/reed_solomon.c (scratch): Removed. + (chosenstat): New const or static array. + (sigma): Likewise. + (errpot): Likewise. + (errpos): Likewise. + (sy): Likewise. + (mstat): Likewise. + (errvals): Likewise. + (eqstat): Likewise. + (pol_evaluate): Replace x with log_x argument. All users updated. + (syndroms): Removed. + (gauss_solve): Use statically allocated arrays. + (rs_recover): Likewise. + Calculate syndroms directly. + (decode_block): Use statically allocated arrays. + (grub_reed_solomon_add_redundancy) [TEST]: Fix -DTEST compilation. + (main) [TEST]: Allow -DTEST -DSTANDALONE. + +2012-01-24 Vladimir Serbinenko + + Eliminate fixed limit on reed solomon decoder length. + + * grub-core/boot/i386/pc/lnxboot.S: Scan for multiboot signature + rather than hardcoding the address. + * grub-core/boot/i386/pc/startup_raw.S: Add new data field + no_reed_solomon_length. + Move gate_a20 to no-reed-solomon part. + Don't force a particular size of no reed-solomon part. + * include/grub/offsets.h (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART): + Removed. + (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_LENGTH): New define. + * util/grub-setup.c (setup): Read no_rs_length from the image itself. + +2012-01-24 Vladimir Serbinenko + + * grub-core/commands/wildcard.c (match_files): Handle filenames + without explicit device. + (wildcard_expand): Don't add explicit device if not already present. + * tests/grub_script_echo1.in: Add a new expansion test. + +2012-01-24 Vladimir Serbinenko + + Replace single-linked with double-linked lists. It results in more + compact and more efficient code. + + * grub-core/kern/list.c (grub_list_push): Moved from here ... + * include/grub/list.h (grub_list_push): ... to here. Set prev. + (grub_list_remove): Moved from here ... + * include/grub/list.h (grub_list_remove): ... here. Use and set prev. + (grub_prio_list_insert): Set prev. + * include/grub/list.h (grub_list): Add prev. All users updated. + +2012-01-24 Vladimir Serbinenko + + Handle newer autotools. Add some missing quotes while on it. + + * Makefile.am (pkglib_DATA): Remove update-grub_lib. + (pkglib_DATA): Move grub-mkconfig_lib from here ... + (pkgdata_DATA): ... here. + * Makefile.util.def (update-grub_lib): Removed. + * conf/Makefile.common (pkglib_DATA): Removed. + (pkglib_SCRIPTS): Likewise. + (pkgdata_DATA): New variable. + * tests/util/grub-shell-tester.in: Replace pkglib with pkgdata where + needed. + Add missing quotes. + Remove unused variable while on it. + * tests/util/grub-shell.in: Likewise. + * util/grub-install.in: Likewise. + * util/grub-mkconfig.in: Likewise. + * util/grub-mknetdir.in: Likewise. + * util/grub-mkrescue.in: Likewise. + * util/grub-mkstandalone.in: Likewise. + * util/grub.d/00_header.in: Likewise. + * util/grub.d/10_hurd.in: Likewise. + * util/grub.d/10_illumos.in: Likewise. + * util/grub.d/10_kfreebsd.in: Likewise. + * util/grub.d/10_linux.in: Likewise. + * util/grub.d/10_netbsd.in: Likewise. + * util/grub.d/10_windows.in: Likewise. + * util/grub.d/20_linux_xen.in: Likewise. + * util/grub.d/30_os-prober.in: Likewise. + * util/update-grub_lib.in: Removed. + +2012-01-24 Seth Goldberg + + * grub-core/net/drivers/i386/pc/pxe.c (grub_pxe_recv): Relax checks as + a workaround for intel problem. + +2012-01-23 Paulo de Rezende Pinatti +2012-01-23 Vladimir Serbinenko +2012-01-23 pfsmorigo + + * util/grub-install.in: Support dd'in into PreP partition. + * util/grub-probe.c (probe): Support discovering partition type. + (main): Support -t msdos_parttype. + +2012-01-23 Vladimir Serbinenko + + * grub-core/normal/crypto.c (grub_crypto_autoload): Prevent + infinite recursion using counter. + * grub-core/lib/xzembed/xz_dec_stream.c (xz_dec_init): Defer s->crc32 + init to skip it if the magic check fails. + (dec_stream_header): Init s->crc32. + +2012-01-22 Vladimir Serbinenko +2012-01-22 Zachary Bedell +2012-01-22 Richard Laager + + * grub-core/fs/zfs/zfs.c (uberblock_verify): New parameter size. + All users updated. + (find_bestub): Determine correct size. + (fill_vdev_info_real): Fill ashift. New argument. All users updated. + (scan_disk): Align the size down. + Call check pool before find_bestub to have ashift. + +2012-01-22 Vladimir Serbinenko + + * grub-core/lib/relocator.c (malloc_in_range): Remove couple of + dprintf in no-malloc zone. + +2012-01-22 Mario Limonciello + + * configure.ac: Add back in test for limits.h. + +2012-01-20 Vladimir Serbinenko + + Support 4K-sector NTFS. + + * include/grub/ntfs.h (GRUB_NTFS_MAX_MFT): Increase to 8. + (grub_ntfs_data): Remove blocksize. + * grub-core/fs/ntfs.c (fixup): Fix size comparison. + Remove data argument. All users updated. + +2012-01-20 Vladimir Serbinenko + + * grub-core/kern/mips/arc/init.c (grub_total_modules_size): Mark as + being in .text to avoid dprel references. + * include/grub/mips/loongson/kernel.h (grub_arch_machine): Likewise. + * include/grub/mips/loongson/memory.h (grub_arch_memsize): Likewise. + (grub_arch_highmemsize): Likewise. + * include/grub/mips/loongson/time.h (grub_arch_busclock): Likewise. + * include/grub/mips/qemu_mips/memory.h (grub_arch_memsize): Likewise. + * include/grub/mips/time.h (grub_arch_cpuclock): Likewise. + +2012-01-18 Vladimir Serbinenko + + Support powerpc with GCC that defines __PPC__ but not __powerpc__. + + * config.h.in (__powerpc__) [__PPC__ && !__powerpc__]: New definition. + * grub-core/lib/setjmp.S: Treat __PPC__ as equivalent to __powerpc__. + +2012-01-18 Vladimir Serbinenko + + * include/grub/datetime.h (grub_get_datetime_cmos): Don't define in + GRUB_UTIL. + (grub_set_datetime_cmos): Likewise. + +2012-01-18 Vladimir Serbinenko + + Make XZ compression parameters dependent on target and not host CPU. + + * configure.ac: Define GRUB_TARGET_CPU_XYZ series. + * grub-core/lib/xzembed/xz_config.h: Use GRUB_TARGET_CPU_XYZ. + +2012-01-18 Vladimir Serbinenko + + * grub-core/kern/powerpc/dl.c (grub_arch_dl_get_tramp_got_size): Remove + set but not used variable. + +2012-01-14 Vladimir Serbinenko + + * grub-core/fs/reiserfs.c (grub_reiserfs_uuid): Reject 0-uuid as + created when no uuid support is compiled into mkfs.reiser. + +2012-01-14 Vladimir Serbinenko + + * grub-core/fs/hfs.c (macroman_to_utf8): Convert / to :. + (utf8_to_macroman): Do the opposite. + * grub-core/fs/hfsplus.c (grub_hfsplus_iterate_dir): Convert / to :. + +2012-01-14 Vladimir Serbinenko + + * configure.ac: Refise build qemu_mips w/o unifont. + +2012-01-14 Vladimir Serbinenko + + Eliminate grub_min/grub_max prone to overflow usage. + + * grub-core/bus/usb/usbhub.c (grub_usb_add_hub): Eliminate grub_min. + (poll_nonroot_hub): Likewise. + * grub-core/fs/affs.c (grub_affs_iterate_dir): Likewise. + (grub_affs_label): Likewise. + * grub-core/fs/btrfs.c (grub_btrfs_lzo_decompress): Likewise. + * grub-core/fs/hfs.c (grub_hfs_dir): Likewise. + (grub_hfs_label): Likewise. + * grub-core/fs/hfsplus.c (grub_hfsplus_cmp_catkey): Likewise. + * grub-core/fs/zfs/zfs.c (MIN): Remove. + (zap_leaf_array_equal): Use grub_size. Remove MIN. + (zap_leaf_array_get): Likewise. + (dnode_get_path): Likewise. + * grub-core/io/lzopio.c (grub_lzopio_read): Eliminate grub_min. + * grub-core/io/xzio.c (grub_xzio_read): Likewise. + * grub-core/script/execute.c (grub_script_break): Likewise. + * grub-core/script/lexer.c (grub_script_lexer_record): Eliminate + grub_max. + * grub-core/script/yylex.l (grub_lexer_yyrealloc): Likewise. + * include/grub/misc.h (grub_min): Removed. + (grub_max): Likewise. + +2012-01-14 Samuel Thibault + + * grub-core/fs/ext2.c (grub_ext2_iterate_dir): Ignore entries with + direct.inode = 0. + +2012-01-14 Vladimir Serbinenko + + * grub-core/lib/posix_wrap/wctype.h (CHARCLASS_NAME_MAX): New define. + +2012-01-14 Vladimir Serbinenko + + * include/grub/datetime.h (grub_datetime2unixtime): Fix offset. + +2012-01-14 Vladimir Serbinenko + + * grub-core/lib/posix_wrap/stdlib.h (MB_CUR_MAX): Moved from here ... + * grub-core/lib/posix_wrap/wchar.h (MB_CUR_MAX): ... here. Value fixed. + +2012-01-14 Vladimir Serbinenko + + * grub-core/fs/fshelp.c (grub_fshelp_find_file): Use grub_strcasecmp + rather than a hack for grub_strncasemap. + +2012-01-14 Vladimir Serbinenko + + Support multiple initrds + Note: part of this was accidently committed in r3739. + + * grub-core/loader/i386/linux.c (grub_cmd_initrd): Support multiple + initrd. + * grub-core/loader/i386/pc/linux.c (grub_cmd_initrd): Likewise. + * grub-core/loader/ia64/efi/linux.c (grub_cmd_initrd): Likewise. + * grub-core/loader/mips/linux.c (grub_cmd_initrd): Likewise. + * grub-core/loader/powerpc/ieee1275/linux.c (grub_cmd_initrd): Likewise. + * grub-core/loader/sparc64/ieee1275/linux.c (grub_cmd_initrd): Likewise. + +2012-01-14 Vladimir Serbinenko + + * grub-core/disk/dmraid_nvidia.c (grub_dmraid_nv_detect): Skip + disks with unknown size. + * grub-core/disk/raid.c (scan_devices): Allow disks with unknown sizes. + +2012-01-14 Vladimir Serbinenko + + Remove defines pertaining to arbitrary limits not affecting GRUB + anymore. + + * grub-core/fs/ext2.c (EXT2_PATH_MAX): Removed. + (EXT2_MAX_SYMLINKCNT): Likewise. + * grub-core/fs/nilfs2.c (NILFS_BTREE_LEVEL_MAX): Likewise. + * grub-core/net/tftp.c (TFTP_MAX_PACKET): Likewise. + * include/grub/i386/pc/pxe.h (GRUB_PXE_MIN_BLKSIZE): Likewise. + (GRUB_PXE_MAX_BLKSIZE): Likewise. + * include/grub/normal.h (GRUB_MAX_CMDLINE): Likewise. + * include/grub/zfs/dnode.h (DN_MAX_INDBLKSHIFT): Likewise. + (DN_MAX_OBJECT_SHIFT): Likewise. + (DN_MAX_OFFSET_SHIFT): Likewise. + (DN_MAX_OBJECT): Likewise. + (DNODES_PER_LEVEL_SHIFT): Likewise. + * include/grub/zfs/spa.h (SPA_MAXBLOCKSHIFT): Likewise. + (SPA_MAXBLOCKSIZE): Likewise. + (SPA_BLOCKSIZES): Likewise. + * include/grub/zfs/zap_impl.h (MZAP_MAX_BLKSHIFT): Likewise. + (MZAP_MAX_BLKSZ): Likewise. + +2012-01-14 Vladimir Serbinenko + + * grub-core/fs/zfs/zfs.c (grub_zfs_read): Remove useless alloc and + handle NULL appropriately. + Remove MIN. + +2012-01-13 Vladimir Serbinenko + + Fix efiemu. + + * grub-core/efiemu/runtime/efiemu.c: explicitly include right + cpu/types.h. + (efiemu_set_virtual_address_map): Remove UINT_TO_PTR. + * configure.ac: Fix efiemu check. + +2012-01-13 Vladimir Serbinenko + + * util/grub.d/30_os-prober.in: Fix occurence of grub-probe instead of + grub_probe. + Reported by: adamwill + +2012-01-12 Seth Goldberg + + * grub-core/lib/arg.c (grub_arg_parse): Fix NULL pointer dereference. + +2012-01-12 Vladimir Serbinenko + + Fix handling of wide characters in gfxterm. + + * grub-core/term/gfxterm.c (grub_colored_char): Remove width and index. + (clear_char): Likewise. + (paint_char): Skip code == NULL chars. + (grub_gfxterm_putchar): Set code = NULL on "shadowed" positions. + +2012-01-12 Vladimir Serbinenko + + * grub-core/normal/charset.c: Move comment to right place. + +2012-01-11 Vladimir Serbinenko + + * grub-core/fs/affs.c (grub_affs_bblock): Revert flags. + (GRUB_AFFS_FLAG_FFS): Put back where it was. + (grub_affs_mount): Revert the correct version checking. + +2012-01-11 Vladimir Serbinenko + + * docs/grub.texi (Unicode): Mention several other unsupported features. + +2011-12-26 Vladimir Serbinenko + + * grub-core/fs/squash4.c (squash_mount): Mark endian conversion in + case statements as compile-time one. + (direct_read): Prevent spurious warnings. + (grub_squash_read_data): Likewise. + +2011-12-26 Vladimir Serbinenko + + Various squash4 fixes and LZO and XZ support. + + * Makefile.util.def (libgrubmods.a): Add xzembed directory to cppflags. + Add xzembed source files. + * grub-core/Makefile.core.def (squash4): Add xzembed and minilzo flags. + * grub-core/fs/squash4.c (grub_squash_super): New field compression. + (grub_squash_inode): New subtype long_dir. + (SQUASH_TYPE_LONG_DIR): New inode type. + (COMPRESSION): New enum. + (XZBUFSIZ): New const. + (grub_squash_data): New fields blksz, decompress, xzdec, xzbuf. + (read_chunk): Use data->decompress. + (zlib_decompress): New function. + (lzo_decompress): Likewise. + (xz_decompress): Likewise. + (squash_mount): Set new data fields. + (grub_squash_iterate_dir): Handle long dir. + (squash_unmount): Free xzdec and xzbuf. + (grub_squash_open): Check ino type. + (direct_read): Stylistic fixes. Use data->decompress. + (grub_squash_read_data): Likewise. + * grub-core/io/gzio.c (grub_gzio): Remove disk_input. + (get_byte): Likewise. + (grub_zlib_disk_read): Removed. + * grub-core/lib/posix_wrap/sys/types.h (ssize_t): New type. + (GRUB_POSIX_BOOL_DEFINED): New define. + * grub-core/lib/posix_wrap/unistd.h: Include sys/types.h. + * grub-core/lib/xzembed/xz.h: Addmissing includes. + [!GRUB_POSIX_BOOL_DEFINED]: Define bool. + * include/grub/deflate.h (grub_zlib_disk_read): Removed. + +2011-12-26 Vladimir Serbinenko + + Don't override more informative errors. + + * grub-core/commands/acpi.c (grub_cmd_acpi): Don't override errors. + * grub-core/font/font.c (open_section): Likewise. + * grub-core/loader/i386/bsd.c (grub_bsd_load_aout): New argument + filename. Don't override errors. + (grub_cmd_openbsd_ramdisk): Don't override errors. + * grub-core/loader/i386/linux.c (grub_cmd_linux): Likewise. + (grub_cmd_initrd): Likewise. + * grub-core/loader/i386/pc/linux.c (grub_cmd_linux): Likewise. + (grub_cmd_initrd): Likewise. + * grub-core/loader/ia64/efi/linux.c (grub_load_elf64): Likewise. + (grub_cmd_linux): Likewise. + (grub_cmd_initrd): Likewise. + (grub_cmd_payload): Likewise. + * grub-core/loader/mips/linux.c (grub_cmd_initrd): Likewise. + * grub-core/loader/multiboot.c (grub_cmd_multiboot): Likewise. + (grub_cmd_module): Likewise. + * grub-core/loader/powerpc/ieee1275/linux.c (grub_cmd_initrd): Likewise. + * grub-core/loader/sparc64/ieee1275/linux.c (grub_cmd_initrd): Likewise. + * grub-core/loader/xnu.c (grub_xnu_load_driver): Likewise. + (grub_cmd_xnu_mkext): Likewise. + (grub_cmd_xnu_ramdisk): Likewise. + (grub_xnu_check_os_bundle_required): Likewise. + (grub_xnu_load_kext_from_dir): Likewise. + (grub_cmd_xnu_kextdir): Likewise. + * grub-core/loader/xnu_resume.c (grub_xnu_resume): Likewise. + +2011-12-25 Vladimir Serbinenko + + * grub-core/fs/minix.c (grub_minix_mount) [MODE_MINIX3]: Treat 0xffff + as 1024 in block size field. Found on one of my test images. + Small optimisation while on it. + +2011-12-25 Vladimir Serbinenko + + * docs/grub.texi (Filesystems): Mention SFS as Latin1 filesystem. + * grub-core/fs/sfs.c (grub_sfs_mount): Fix a memory leak while on it. + (grub_sfs_iterate_dir): Convert Latin1 to UTF8. Stylistic and + performance fixes while on it. + (grub_sfs_close): Fix memory leak while on it. + (grub_sfs_label): Convert Latin1 to UTF-8. + +2011-12-25 Vladimir Serbinenko + + * grub-core/fs/hfs.c (grub_hfs_dir): Cap keylen to actually available + space to avoid overflows. + (grub_hfs_label): Convert from macroman to UTF-8. + +2011-12-25 Vladimir Serbinenko + + * grub-core/fs/affs.c (grub_affs_label): Interpret label as latin1. + +2011-12-25 Vladimir Serbinenko + + * grub-core/normal/menu.c (menu_init): Don't stop menu init at gfxterm. + +2011-12-25 Vladimir Serbinenko + + * unicode: Import Unicode 6.0 data. + +2011-12-25 Vladimir Serbinenko + + * grub-core/term/gfxterm.c (grub_gfxterm_putchar): Don't set values + outside of range. + +2011-12-25 Vladimir Serbinenko + + Avoid cutting in the middle of UTF-8 character. + + * include/grub/charset.h (grub_getend): New function. + * grub-core/script/function.c (grub_script_function_find): Use + grub_getend. + * grub-core/normal/completion.c (add_completion): Likewise. + +2011-12-25 Vladimir Serbinenko + + * grub-core/normal/charset.c (grub_ucs4_to_utf8): Small stylistic fix. + (grub_bidi_line_logical_to_visual): Skip tags. They are deprecated. + * include/grub/unicode.h (GRUB_UNICODE_TAG_START): New enum value. + (GRUB_UNICODE_TAG_END): Likewise. + (GRUB_UNICODE_LAST_VALID): Likewise. + +2011-12-25 Vladimir Serbinenko + + * include/grub/unicode.h (grub_unicode_compact_range): Replace end with + len and make it smaller. All users updated. + * util/import_unicode.py: Put length and not end character. + Check length. + +2011-12-25 Vladimir Serbinenko + + Make better Unicode-compliant and unify some UTF-8 code pathes. + + * grub-core/normal/charset.c (grub_utf8_to_utf16): Don't eat possibly + valid character. + (grub_is_valid_utf8): Use grub_utf8_process. + Check resulting code range. + (grub_utf8_to_ucs4): Use grub_utf8_process. + * include/grub/charset.h (grub_utf16_to_utf8): Don't eat up a possibly + valid character. + +2011-12-25 Vladimir Serbinenko + + * grub-core/io/bufio.c (grub_bufio_read): Fix handling of corner cases. + +2011-12-25 Vladimir Serbinenko + + * docs/grub.texi (Filesystems): Mention AFS. + +2011-12-25 Vladimir Serbinenko + + * docs/grub.texi (Filesystems): Clarify restrictions. + (Regexp): Mention non-Unicode regexp behaviour. + (Other): Mention non-Unicode matching behaviour. + +2011-12-24 Vladimir Serbinenko + + Make HFS implementation use MacRoman. + + * grub-core/fs/hfs.c (MAX_UTF8_PER_MAC_ROMAN): New define. + (macroman): New const array. + (macroman_to_utf8): New function. + (utf8_to_macroman): Likewise. + (grub_hfs_find_dir): Use utf8_to_macroman. + (grub_hfs_dir): Use macroman_to_utf8. + Set case_insensitive. + +2011-12-24 Vladimir Serbinenko + + * docs/grub.texi (Filesystems): Add IEEE1275 full-path example. + +2011-12-24 Vladimir Serbinenko + + Integrate hints into autogeneration scripts. + + * docs/grub.texi (Filesystems): Add a hostdisk example. + * Makefile.util.def (grub-mkdevicemap): Remove ofpath. + (grub-probe): Add ofpath. + * gentpl.py: Remove group nosparc64. + * grub-core/commands/search.c (cache_entry): New struct. + (cache): New var. + (FUNC_NAME): Use and save cache. Fix handling of trailing comma. + * grub-core/commands/search_wrap.c (options): Add platform-specific + hint options. + (grub_cmd_search): Handle platform-specific hints. + (GRUB_MOD_INIT): Declare grub_cmd_search as accept_dash. + * grub-core/kern/emu/hostdisk.c (map): New field device_map. + (grub_util_biosdisk_data): Likewise. + (grub_util_biosdisk_open): Set device_map. + (read_device_map): Handle "" as indication of no map. + Set device_map. + (find_system_device): Add hostdisk/ prefix for autogenerated entries. + (grub_util_biosdisk_get_compatibility_hint): New function. + * grub-core/normal/main.c (features): Add feature_platform_search_hint. + * include/grub/emu/hostdisk.h + (grub_util_biosdisk_get_compatibility_hint): New proto. + * util/grub-install.in: Don't call grub-mkdevicemap. + Add platform-specific hint to load.cfg. + * util/grub-mkconfig.in: Don't call grub-mkdevicemap. + * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Add + hints. Set root preliminary to compatibility hint, not to OS name. + * util/grub-probe.c (PRINT_*): Add hints. + (print): Make static. + (escape_of_path): New function. + (guess_bios_drive): Likewise. + (guess_efi_drive): Likewise. + (guess_baremetal_drive): Likewise. + (print_full_name): Likewise. + (probe): Handle hints. + (main): Likewise. + * util/ieee1275/devicemap.c: Removed. + * util/ieee1275/ofpath.c (find_obppath): Allow to fail. All users + updated. + (grub_util_devname_to_ofpath): Return NULL on failure. + + * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_get_grub_dev): Fix + resource leak. + * util/getroot.c (grub_util_pull_device): Fix memory leak. + + * po/POTFILES.in: Regenerated. + + Allow purely long options + + * grub-core/lib/arg.c (SHORT_ARG_HELP): Removed. + (SHORT_ARG_USAGE): Likewise. + (grub_arg_show_help): Compare opt with help_options. + (parse_option): Receive opt as argument. If makes big simplificatons. + All users updated + +2011-12-24 Vladimir Serbinenko + + * grub-core/lib/libgcrypt_wrap/cipher_wrap.h (WORDS_BIGENDIAN): + Restructure to avoid warning. + +2011-12-24 Vladimir Serbinenko + + * util/grub-install.in: Account for possible escaped comma in device + name. + +2011-12-24 Vladimir Serbinenko + + * util/ieee1275/ofpath.c (of_path_of_ide): Fix address for secondary + channel. + +2011-12-24 Vladimir Serbinenko + + * grub-core/kern/ieee1275/openfw.c (grub_devalias_iterate): Fix + allocation and zero-setting. + (grub_ieee1275_get_devname): Check that alias is complete. + +2011-12-24 Vladimir Serbinenko + + * grub-core/kern/disk.c (grub_disk_read): Fix hook calling for + unaligned segments. + +2011-12-24 Vladimir Serbinenko + + * grub-core/disk/ieee1275/ofdisk.c (grub_ofdisk_iterate): Add ieee1275/ + prefix. + (grub_ofdisk_open): Check and discard ieee1275 prefix. + * grub-core/kern/ieee1275/openfw.c (grub_ieee1275_encode_devname): + Add ieee1275 prefix. + +2011-12-23 Vladimir Serbinenko + + * docs/grub.texi (Filesystems): Update. + +2011-12-23 Vladimir Serbinenko + + Support odc, newc and bigendian cpio formats. + + * Makefile.util.def (libgrubmods): Add odc.c, newc.c and cpio_be.c. + * grub-core/Makefile.core.def (newc): New module. + (odc): Likewise. + (cpio_be): Likewise. + * grub-core/fs/cpio.c (ALIGN_CPIO): New macro. + (MAGIC): Likewise. + (MAGIC2): Likewise. + (head) [MODE_ODC]: Adapt for the format. + (head) [MODE_NEWC]: Likewise. + (head) [!MODE_*]: Write fields of interest as arrays. + (MAGIC_USTAR): Removed. + (read_number) [MODE_NEWC]: Change to hex. + (read_number) [!MODE_*]: Parse binary arrays. + (grub_cpio_find_file): Factor out the code for better structure and + always use read_number. + (grub_cpio_mount): Use MAGIC and MAGIC2. + (grub_cpio_dir): Exit on first hook non-0 return. + (grub_cpio_fs) [MODE_ODC]: Set name to odc. + (grub_cpio_fs) [MODE_NEWC]: Set name to newc. + (GRUB_MOD_INIT) [MODE_ODC]: Set name to odc. + (GRUB_MOD_INIT) [MODE_NEWC]: Set name to newc. + (GRUB_MOD_FINI) [MODE_ODC]: Set name to odc. + (GRUB_MOD_FINI) [MODE_NEWC]: Set name to newc. + * grub-core/fs/newc.c: New file. + * grub-core/fs/odc.c: Likewise. + * grub-core/fs/cpio_be.c: Likewise. + +2011-12-23 Vladimir Serbinenko + + Fix handling of tar numbers occupying the whole field. + + * grub-core/fs/cpio.c (read_number): New function. + (grub_cpio_find_file): Use read_number instead of strtoull. + +2011-12-23 Vladimir Serbinenko + + * grub-core/fs/cpio.c (grub_cpio_find_file): Fix handling of names + occupying the whole field size. + +2011-12-23 Lukas Anzinger + + * util/grub-mkconfig_lib.in (version_test_gt): Fix variable names. + +2011-12-23 Vladimir Serbinenko + + * grub-core/net/net.c (grub_cmd_delroute): Add missing out condition. + +2011-12-23 Seth Goldberg + + * grub-core/Makefile.core.def (lzma_decompress): Add missing + TARGET_IMG_LDFLAGS. + +2011-12-23 Vladimir Serbinenko + + * util/getroot.c (ESCAPED_PATH_MAX): New define. + (mountinfo_entry): Increase the field size to take escaping into + account. + (find_root_device_from_libzfs): Add one byte to size of strings for + security. + +2011-12-23 Vladimir Serbinenko + + * grub-core/lib/reed_solomon.c (grub_reed_solomon_add_redundancy): Add + an assert. + * util/grub-setup.c (setup): Likewise. + +2011-12-23 Vladimir Serbinenko + + * grub-core/boot/i386/pc/startup_raw.S: Add missing argument for + _LzmaDecodeA. + +2011-12-22 Vladimir Serbinenko + + * docs/grub.texi (Internationalisation): New section. + +2011-12-22 Vladimir Serbinenko + + * docs/grub.texi (Loopback booting): New section. + +2011-12-22 Keshav P R + + * util/grub-mkstandalone.in: Fix minor typo errors. + +2011-12-20 Vladimir Serbinenko + + IPv6, TCP, HTTP, ICMP and DNS support. Several cleanups and bugfixes. + + * grub-core/Makefile.core.def (net): Add net/dns.c, net/tcp.c, + net/icmp.c and net/icmp6.c. + (http): New module. + (priority_queue): Likewise. + * grub-core/io/bufio.c: Rewritten. + * grub-core/lib/legacy_parse.c (legacy_command): New argument type + TYPE_WITH_CONFIGFILE_OPTION. + (legacy_commands): Add bootp and dhcp. + (is_option): Handle TYPE_WITH_CONFIGFILE_OPTION. + (grub_legacy_parse): Likewise. + * grub-core/lib/priority_queue.c: New file. + * grub-core/net/arp.c: Add missing license header. + (arp_find_entry): Removed. + (arp_find_entry): Likewise. + (grub_net_arp_resolve): Rename to ... + (grub_net_arp_send_request): ...this. + (grub_net_arp_receive): New card argument. + * grub-core/net/bootp.c (parse_dhcp_vendor): Clean up. + Set router and DNS server. + (grub_net_configure_by_dhcp_ack): Handle routing information. + (grub_cmd_bootp): Set checksum. + (grub_bootp_init): Remove net_dhcp. + * grub-core/net/dns.c: New file. + * grub-core/net/drivers/efi/efinet.c (send_card_buffer): Wait for + completion. + (get_card_packet): Handle allocation. + (grub_efinet_findcards): Set mtu. + * grub-core/net/drivers/emu/emunet.c: Add missing license header. + (get_card_packet): Handle allocation. + (emucard): Set mtu. + * grub-core/net/drivers/i386/pc/pxe.c (grub_pxe_recv): Handle allocation + (GRUB_MOD_INIT): Set mtu. + * grub-core/net/drivers/ieee1275/ofnet.c (grub_ofnetcard_data): Remove + mtu. + (get_card_packet): Handle allocation. + (grub_ofnet_findcards): Set mtu. + * grub-core/net/ethernet.c (send_ethernet_packet): Add compile time + assert. + (grub_net_recv_ethernet_packet): Handle IPv6. + * grub-core/net/http.c: New file. + * grub-core/net/icmp.c: Likewise. + * grub-core/net/icmp6.c: Likewise. + * grub-core/net/ip.c (ip6addr): New type. + (ip6hdr): Likewise. + (reassemble): Likewise. + (cmp): New function. + (reassembles): New variable. + (grub_net_ip_chksum): Handle 0xffff sum and unaligned buffers. + (id): New variable. + (send_fragmented): New function. + (grub_net_send_ip_packet): Rename to ... + (grub_net_send_ip4_packet): ... this. Send fragmented if needed. + Handle non-UDP. + (grub_net_recv_ip_packets): Rename to ... + (handle_dgram): ... this. Check checksum. Handle non-UDP. + (free_rsm): New function. + (free_old_fragments): Likewise. + (grub_net_recv_ip4_packets): New function. + (grub_net_send_ip6_packet): Likewise. + (grub_net_send_ip_packet): Likewise. + (grub_net_recv_ip6_packets): Likewise. + (grub_net_recv_ip_packets): Likewise. + * grub-core/net/net.c (grub_net_link_layer_entry): New struct. + (LINK_LAYER_CACHE_SIZE): New const. + (link_layer_find_entry): New function. + (grub_net_link_layer_add_address): Likewise. + (grub_net_link_layer_resolve_check): Likewise. + (grub_net_link_layer_resolve): Likewise. + (grub_net_ipv6_get_slaac): Likewise. + (grub_net_ipv6_get_link_local): Likewise. + (grub_cmd_ipv6_autoconf): Likewise. + (parse_ip): Handle one number representation. + (parse_ip6): New functoion. + (match_net): Handle IPv6. + (grub_net_resolve_address): Handle IPv6 and DNS. + (grub_net_resolve_net_address): Handle IPv6. + (route_cmp): New function. + (grub_net_route_address): Find best route. + (grub_net_addr_to_str): Handle IPv6. + (grub_net_addr_cmp): New function. + (grub_net_add_addr): Register local route. + (print_net_address): Handle net address. + (grub_net_poll_cards): Retransmit TCP. + (grub_net_poll_cards_idle_real): Likewise. + (have_ahead): New function. + (grub_net_seek_real): Use underlying seek. + (GRUB_MOD_INIT): Register net_ipv6_autoconf and init dns. + * grub-core/net/tcp.c: New file. + * grub-core/net/tftp.c (tftp_data): Add priority_queue. + (cmp): New function. + (ack): Likewise. + (tftp_receive): Handle unordered input. + (destroy_pq): New function. + (tftp_close): Close pq. + * grub-core/net/udp.c: Put missing license header. + (grub_net_udp_socket): New function. + (udp_socket_register): Likewise. + (grub_net_udp_close): Likewise. + (grub_net_recv_udp_packet): Check checksum. + * include/grub/efi/api.h (grub_efi_simple_network): Add status. + * include/grub/misc.h (grub_memchr): New function. + * include/grub/net.h (GRUB_NET_*_SIZE): New enum. + (grub_net_card_driver): Return buf in recv. + (grub_net_slaac_mac_list): New struct. + (grub_network_level_protocol_id): Add ipv6. + (grub_net_network_level_addr): Likewise. + (grub_net_network_level_net_addr): Likewise. + (grub_net_app_protocol): Add seek. + (grub_net_socket): Removed. + (grub_net_sockets): Likewise. + (grub_net_socket_register): Likewise. + (grub_net_socket_unregister): Likewise. + (FOR_NET_SOCKETS): Likewise. + (grub_net_add_addr): Add const. + (GRUB_NET_BOOTP_*): New enum. + (grub_net_addr_cmp): New proto. + (GRUB_NET_MAX_STR_ADDR_LEN): Take IPV6 into account. + (GRUB_NET_MAX_STR_HWADDR_LEN): New define. + (grub_net_hwaddr_to_str): NEw proto. + (FOR_NET_NETWORK_LEVEL_INTERFACES): New macro. + (FOR_NET_NETWORK_LEVEL_INTERFACES_SAFE): Handle NULL. + (grub_dns_init): New proto. + (grub_dns_fini): Likewise. + (grub_net_tcp_retransmit): Likewise. + (grub_net_link_layer_add_address): Likewise. + (grub_net_link_layer_resolve_check): Likewise. + (grub_net_link_layer_resolve): Likewise. + (grub_net_dns_lookup): Likewise. + (grub_net_add_dns_server): Likewise. + (grub_net_remove_dns_server): Likewise. + (GRUB_NET_TRIES): New const. + (GRUB_NET_INTERVAL): Likewise. + * include/grub/net/arp.h: Mostly rewritten. + * include/grub/net/ethernet.h (grub_net_ethertype_t): New enum. + * include/grub/net/ip.h: Mostly rewritten. + * include/grub/net/netbuff.h: Indent. + * include/grub/net/tcp.h: New file. + * include/grub/net/udp.h: Mostly rewritten. + * include/grub/priority_queue.h: New file. + * include/grub/types.h (PRIdGRUB_SSIZE): New define. + (grub_swap_bytes64_compile_time): Likewise. + (grub_cpu_to_be16_compile_time): Likewise. + (grub_cpu_to_be32_compile_time): Likewise. + (grub_cpu_to_be64_compile_time): Likewise. + (grub_be_to_cpu64_compile_time): Likewise. + +2011-12-16 Vladimir Serbinenko + + * grub-core/commands/i386/pc/drivemap.c (int13slot): Replace + UINT_TO_PTR with cast. + +2011-12-15 Vladimir Serbinenko + + * util/import_gcry.py: Skip _gcry_rmd160_mixblock and serpent_test. We + don't use them. + +2011-12-15 Vladimir Serbinenko + + * util/import_gcry.py: Don't add include camellia.h to camellia.c. It's + already there. + +2011-12-15 Vladimir Serbinenko + + * util/grub-mkimage.c (generate_image): Clean multiboot header to avoid + confusing ipxe. + +2011-12-15 Vladimir Serbinenko + + * grub-core/lib/libgcrypt/cipher/md4.c (transform) [WORDS_BIGENDIAN]: + Add missing const attribute. + * grub-core/lib/libgcrypt/cipher/md5.c (transform) [WORDS_BIGENDIAN]: + Likewise. + * grub-core/lib/libgcrypt/cipher/rmd160.c (transform) [WORDS_BIGENDIAN]: + Likewise. + +2011-12-15 Vladimir Serbinenko + + * grub-core/lib/libgcrypt/cipher/serpent.c (serpent_key_prepare): Fix + misaligned access. + (serpent_setkey): Likewise. + (serpent_encrypt_internal): Likewise. + (serpent_decrypt_internal): Likewise. + (serpent_encrypt): Don't put an alignment-increasing cast. + (serpent_decrypt): Likewise. + (serpent_test): Likewise. + +2011-12-15 Vladimir Serbinenko + + * grub-core/loader/multiboot.c (grub_cmd_module): Fix target address. + +2011-12-15 Vladimir Serbinenko + + Replace UINT_TO_PTR and PTR_TO_UINT with explicit grub_addr_t casts. + + * include/grub/types.h (UINT_TO_PTR): Removed. All users switched to + grub_addr_t casts. + (PTR_TO_UINT64): Likewise. + (PTR_TO_UINT32): Likewise. + +2011-12-15 Vladimir Serbinenko + + * util/grub-mkimage.c (generate_image): Decrease the higher limit + because of stack. + * util/grub-setup.c (setup): Don't add redundancy past the higher load + limit. + +2011-12-15 Vladimir Serbinenko + + * grub-core/gfxmenu/gui_label.c (label_paint): Handle the case + text_width > available width a bit more gracefully. + +2011-12-15 Vladimir Serbinenko + + * grub-core/loader/i386/bsdXX.c (grub_freebsd_load_elfmodule): Fix + current address calculation. + +2011-12-15 Vladimir Serbinenko + + * grub-core/lib/reed_solomon.c (decode_block): Allocate on heap and not + stack. + (encode_block): Likewise. + +2011-12-15 Vladimir Serbinenko + + * grub-core/boot/i386/pc/startup_raw.S: Clear direction flag for + certainety. + +2011-12-15 Vladimir Serbinenko + + * grub-core/boot/i386/pc/startup_raw.S: Move realmode routines to + non-RS part to avoid RS messing with GDT. + * include/grub/offsets.h (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART): + Increase to suit in realmode routines. + +2011-12-15 Vladimir Serbinenko + + * grub-core/kern/i386/realmode.S: Increase alignment. + * grub-core/boot/i386/pc/startup_raw.S: Likewise. + +2011-12-14 Vladimir Serbinenko + + * grub-core/lib/reed_solomon.c (init_powx): Set gf_powx_inv[0] just to + be deterministic. + (syndroms): Compute 0 syndrom. + (rs_recover): Use 0 syndrom. + +2011-12-14 Vladimir Serbinenko + + * include/grub/kernel.h (FOR_MODULES): Make it a bit faster. + +2011-12-14 Vladimir Serbinenko + + * include/grub/types.h (GRUB_PROPERLY_ALIGNED_ARRAY): Add missing + brackets. + +2011-12-14 Vladimir Serbinenko + + * grub-core/gfxmenu/widget-box.c (get_left_pad): Take corners into + account. + (get_top_pad): Likewise. + (get_right_pad): Likewise. + (get_bottom_pad): Likewise. + +2011-12-14 Vladimir Serbinenko + + * grub-core/gfxmenu/gui_list.c (draw_menu): Don't use assignment in if. + +2011-12-14 Vladimir Serbinenko + + * include/grub/efi/api.h (grub_efi_memory_descriptor): Add packed + attribute as the structure isn't guaranteed to be properly aligned. + (grub_efi_pci_device_path): Likewise. + (grub_efi_pccard_device_path): Likewise. + (grub_efi_memory_mapped_device_path): Likewise. Additionaly explicitly + specify the size of `memory_type'. + (grub_efi_vendor_device_path): Likewise. + (grub_efi_controller_device_path): Likewise. + (grub_efi_acpi_device_path): Likewise. + (grub_efi_expanded_acpi_device_path): Likewise. + (grub_efi_atapi_device_path): Likewise. + (grub_efi_scsi_device_path): Likewise. + (grub_efi_fibre_channel_device_path): Likewise. + (grub_efi_1394_device_path): Likewise. + (grub_efi_usb_device_path): Likewise. + (grub_efi_usb_class_device_path): Likewise. + (grub_efi_i2o_device_path): Likewise. + (grub_efi_mac_address_device_path): Likewise. + (grub_efi_ipv4_device_path): Likewise. + (grub_efi_ipv6_device_path): Likewise. + (grub_efi_infiniband_device_path): Likewise. + (grub_efi_uart_device_path): Likewise. + (grub_efi_vendor_messaging_device_path): Likewise. + (grub_efi_hard_drive_device_path): Likewise. + (grub_efi_cdrom_device_path): Likewise. + (grub_efi_vendor_media_device_path): Likewise. + (grub_efi_file_path_device_path): Likewise. + (grub_efi_protocol_device_path): Likewise. + (grub_efi_piwg_device_path): Likewise. + (grub_efi_bios_device_path): Likewise. + +2011-12-14 Vladimir Serbinenko + + * include/grub/charset.h (grub_utf16_to_utf8): Make src a const pointer. + (grub_ucs4_to_utf8_alloc): Likewise. + (grub_ucs4_to_utf8): Likewise. + * grub-core/normal/charset.c (grub_ucs4_to_utf8): Likewise. + (grub_ucs4_to_utf8_alloc): Likewise. + +2011-12-14 Vladimir Serbinenko + + AFFS never uses unicode. + + * include/grub/charset.h (GRUB_MAX_UTF8_PER_LATIN1): New const. + (grub_latin1_to_utf8): New inline function. + * grub-core/fs/affs.c (grub_affs_iterate_dir): Convert latin1 to UTF8. + +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/romfs.c (grub_romfs_mount): Fix pointer comparison + overflow. + +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/squash4.c (grub_squash_inode): Fix field sizes. + (grub_squash_dirent_header): Likewise. + (read_chunk): Don't double swap. + (grub_squash_iterate_dir): Fix swap sizes. + +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/jfs.c (grub_jfs_getent): Handle UTF16 endianness. + +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/hfs.c (grub_hfs_find_node): Handle unaligned keys. + (grub_hfs_iterate_dir): Likewise. + +2011-12-13 Vladimir Serbinenko + + Fix video on platforms where unaligned access is forbidden. + Make several optimisations while on it. + + * grub-core/video/fb/fbblit.c (grub_video_fbblit_replace_directN): + Optimise and use GRUB_VIDEO_FB_ADVANCE_POINTER. + (grub_video_fbblit_replace_32bit_1bit): Likewise. + (grub_video_fbblit_replace_24bit_1bit) [!GRUB_HAVE_UNALIGNED_ACCESS]: + Disable. + (grub_video_fbblit_replace_16bit_1bit): + Optimise and use GRUB_VIDEO_FB_ADVANCE_POINTER. + (grub_video_fbblit_replace_8bit_1bit): Likewise. + (grub_video_fbblit_replace_BGRX8888_RGBX8888): Likewise. + (grub_video_fbblit_replace_BGRX8888_RGB888): Likewise. + (grub_video_fbblit_replace_BGR888_RGBX8888): Likewise. + (grub_video_fbblit_replace_BGR888_RGBX8888): Likewise. + (grub_video_fbblit_replace_BGR888_RGB888): Likewise. + (grub_video_fbblit_replace_RGBX8888_RGB88): Likewise. + (grub_video_fbblit_replace_RGB888_RGBX888): Likewise. + (grub_video_fbblit_replace_RGB888_RGBX8888): Likewise. + (grub_video_fbblit_replace_index_RGBX8888): Likewise. + (grub_video_fbblit_replace_index_RGB888): Likewise. + (grub_video_fbblit_blend_BGRA8888_RGBA8888): Likewise. + (grub_video_fbblit_blend_BGR888_RGBA8888): Likewise. + (grub_video_fbblit_blend_RGBA8888_RGBA8888): Likewise. + (grub_video_fbblit_blend_RGB888_RGBA8888): Likewise. + (grub_video_fbblit_blend_index_RGBA8888): Likewise. + (grub_video_fbblit_blend_XXXA8888_1bit): Likewise. + (grub_video_fbblit_blend_XXX888_1bit) [!GRUB_HAVE_UNALIGNED_ACCESS]: + Disable. + (grub_video_fbblit_blend_XXX565_1bit): + Optimise and use GRUB_VIDEO_FB_ADVANCE_POINTER. + * grub-core/video/fb/fbfill.c (grub_video_fbfill_direct32): Likewise. + * grub-core/video/fb/fbutil.c (grub_video_fb_get_video_ptr): Return + void *. + * grub-core/video/fb/video_fb.c (common_blitter) + [!GRUB_HAVE_UNALIGNED_ACCESS]: Skip disabled blitters. + (grub_video_fb_create_render_target_from_pointer) + [!GRUB_HAVE_UNALIGNED_ACCESS]: Check alignment. + * include/grub/fbutil.h (grub_video_fb_get_video_ptr): Return void *. + * include/grub/i386/types.h (GRUB_HAVE_UNALIGNED_ACCESS): New + definition. + * include/grub/x86_64/types.h (GRUB_HAVE_UNALIGNED_ACCESS): Likewise. + +2011-12-13 Vladimir Serbinenko + + * grub-core/kern/sparc64/dl.c (grub_arch_dl_relocate_symbols): Support + HH22 and HM10 relocations. + +2011-12-13 Vladimir Serbinenko + + * grub-core/kern/misc.c (grub_vsnprintf_real): Fix fmt2 parsing. + +2011-12-13 Vladimir Serbinenko + + * grub-core/commands/videotest.c (grub_cmd_videotest): Check that + allocation succeeded. + +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/iso9660.c (grub_iso9660_convert_string): Make first + argument a u8 pointer. All users updated. + Handle unaligned buffers. + +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/iso9660.c (grub_iso9660_iterate_dir): Force inlining of + add_part to workaround compiler bug. + +2011-12-13 Vladimir Serbinenko + + * include/grub/kernel.h (FOR_MODULES): Preserve alignment invariants. + +2011-12-13 Vladimir Serbinenko + + * grub-core/loader/multiboot_mbi2.c (grub_multiboot_add_elfsyms): + Reserve alignment invariants. + (grub_multiboot_load): Likewise. + (retrieve_video_parameters): Likewise. + (grub_multiboot_make_mbi): Likewise. + +2011-12-13 Vladimir Serbinenko + + * grub-core/loader/i386/xnu.c (grub_xnu_devprop_remove_property): Fix + incorrect pointer. + +2011-12-13 Vladimir Serbinenko + + * grub-core/disk/pata.c (grub_pata_pio_read): Handle unaligned buffer. + (grub_pata_pio_write): Likewise. + +2011-12-13 Vladimir Serbinenko + + Add noreturn attributes and remove unreachable code. + + * grub-core/bus/cs5536.c (grub_cs5536_smbus_wait): Remove unreachable + code. + * grub-core/commands/halt.c (grub_cmd_halt): Remove unreachable + code. Mark as noreturn. + * grub-core/commands/minicmd.c (grub_mini_cmd_exit): Likewise. + * grub-core/commands/reboot.c (grub_cmd_reboot): Likewise. + * grub-core/disk/efi/efidisk.c (grub_efidisk_get_device_name): Remove + unreachable code. + * grub-core/kern/main.c (grub_main): Mark as noreturn. + * grub-core/kern/rescue_reader.c (grub_rescue_run): Likewise. + * grub-core/lib/posix_wrap/stdlib.h (abort): Likewise. + * grub-core/normal/menu.c (run_menu): Remove unreachable code. + * include/grub/kernel.h (grub_main): Mark as noreturn. + * include/grub/reader.h (grub_rescue_run): Likewise. + +2011-12-13 Vladimir Serbinenko + + * include/grub/i386/qemu/memory.h (grub_machine_mmap_init): Remove + redundant declaration. + +2011-12-13 Vladimir Serbinenko + + * include/grub/net.h (grub_net_network_level_interfaces): Remove + redundant declaration. + (FOR_NET_NETWORK_LEVEL_INTERFACES): Move to appropriate place. + +2011-12-13 Vladimir Serbinenko + + * grub-core/commands/hdparm.c (le16_to_char): Make src and dest uint16 * + to ensure alignment. + (grub_hdparm_print_identify): Make argument uint16 * to ensure + alignment. Ensure tmp alignment. + (grub_cmd_hdparm): Ensure buf alignment. + * grub-core/disk/ata.c (grub_ata_strncpy): Make src and dest uint16 * + to ensure alignment. + (grub_ata_dumpinfo): Ensure text alignment. + (grub_atapi_identify): Preserve alignment invariant. + (grub_ata_identify): Likewise. Use grub_get_unaligned32 when necessary. + +2011-12-13 Vladimir Serbinenko + + * include/grub/emu/misc.h (xasprintf): Add missing format attribute. + * include/grub/mips/kernel.h (grub_halt): Remove redundant declaration. + * include/grub/mips/qemu_mips/kernel.h (grub_halt): Likewise. + * include/grub/misc.h (grub_reboot) + [GRUB_MACHINE_EMU || GRUB_MACHINE_QEMU_MIPS]: Export. + (grub_halt) [__mips__]: Likewise. + +2011-12-13 Vladimir Serbinenko + + * include/grub/efi/memory.h (grub_machine_mmap_iterate): + Remove redundant declaration. + (grub_mmap_get_post64): Likewise. + (grub_mmap_get_upper): Likewise. + (grub_mmap_get_lower): Likewise. + +2011-12-13 Vladimir Serbinenko + + * grub-core/partmap/dvh.c (grub_dvh_is_valid): Make argument + uint32_t * to ensure alignment. + (dvh_partition_map_iterate): Make `block' a union to ensure alignment. + +2011-12-13 Vladimir Serbinenko + + * grub-core/partmap/sunpc.c (grub_sun_is_valid): Make argument + uint16_t * to ensure alignment. + (sun_pc_partition_map_iterate): Make `block' a union to ensure + alignment. + +2011-12-13 Vladimir Serbinenko + + * grub-core/partmap/sun.c (grub_sun_is_valid): Make argument uint16_t * + to ensure alignment. + (sun_partition_map_iterate): Make `block' a union to ensure alignment. + +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/ntfs.c (u16at): Make into inline function. + Handle unaligned pointers. + (u32at): Likewise. + (u64at): Likewise. + (fixup): Use byte access instead of v16at. + (find_attr): Fix imporper usage of v32at. + (read_data): Likewise. + (list_file): Handle byte-swapping and unaligned strings. + (grub_ntfs_label): Likewise. + +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/udf.c (grub_udf_partmap): Add packed attribute + as it's not necessarily aligned. + +2011-12-13 Vladimir Serbinenko + + * grub-core/kern/mips/qemu_mips/init.c (grub_at_keyboard_init): Remove + redundant declaration. + (grub_serial_init): Likewise. + (grub_terminfo_init): Likewise. + +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/zfs/zfs.c (DVA_OFFSET_TO_PHYS_SECTOR): Make into inline + function. + (ZAP_HASH_IDX): Likewise. + (ZAP_LEAF_HASH_SHIFT): Likewise. + (ZAP_LEAF_HASH_NUMENTRIES): Likewise. + (LEAF_HASH): Likewise. + (ZAP_LEAF_NUMCHUNKS): Likewise. + (ZAP_LEAF_CHUNK): Likewise. Changed pointer arithmetic to preserve + alignment invariants. Return pointer. All users updated. + (ZAP_LEAF_ENTRY): Make into inline function. + (NBBY): Removed. + (xor): LIkewise. + (xor_out): Use grub_crypto_xor. + (dnode_get_path): Use grub_get_unaligned. + (nvlist_find_value): Likewise. + (grub_zfs_nvlist_lookup_uint64): Likewise. + (grub_zfs_nvlist_lookup_string): Likewise. + (get_nvlist_size): Likewise. + (grub_zfs_open): Likewise. + (fill_fs_info): Likewise. + (grub_zfs_dir): Likewise. + * include/grub/zfs/zap_leaf.h (zap_leaf_phys): Adapt to preserve + alignment invariants. + * include/grub/zfs/zio.h (zio_eck_t): Mark as packed as it's not + necessarily aligned. + +2011-12-13 Vladimir Serbinenko + + * grub-core/net/netbuff.c (grub_netbuff_alloc): Ensure proper alignment. + +2011-12-13 Vladimir Serbinenko + + * grub-core/disk/mdraid_linux.c (grub_mdraid_detect): Change pointer + arithmetic to conserve alignment invariants. + +2011-12-13 Vladimir Serbinenko + + * include/grub/efiemu/efiemu.h (grub_efiemu_get_memory_map): Remove + redundant declaration. + (grub_efiemu_mm_obtain_request): Likewise. + (grub_efiemu_prepare): Likewise. + +2011-12-13 Vladimir Serbinenko + + * include/grub/list.h: Explicitly cast return of grub_bad_type_cast + to match types. + +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/hfsplus.c (grub_hfsplus_btree_recoffset): Handle the + case of aunaligned recptr. + (grub_hfsplus_read_block): Declare extoverflow as key to ensure + alignment. + (grub_hfsplus_btree_search): Handle unaligned index. + +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/xfs.c (grub_xfs_iterate_dir): Use grub_get_unaligned16 + to get freetag and skip. + +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/nilfs2.c (grub_nilfs2_btree_node): Add zero-size keys + array. + (grub_nilfs2_btree_node_dkeys): Ensure return pointer alignment. + (grub_nilfs2_btree_lookup): Ensure buffer alignment. + +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/romfs.c (grub_romfs_iterate_dir): Properly align + name for checksum and fix allocation algorithm. + +2011-12-13 Vladimir Serbinenko + + * include/grub/types.h (grub_properly_aligned_t): New type. + (GRUB_PROPERLY_ALIGNED_ARRAY): New macro. + (grub_get_unaligned16): Add explicit casts. + (grub_get_unaligned32): Likewise. + (grub_get_unaligned64): Likewise. + (grub_set_unaligned16): New function. + (grub_set_unaligned32): Likewise. + +2011-12-13 Vladimir Serbinenko + + * grub-core/normal/datetime.c (grub_weekday_names): Make const. + +2011-12-13 Vladimir Serbinenko + + * grub-core/fs/udf.c (read_string): Macroify GRUB_MAX_UTF8_PER_UTF16. + * grub-core/fs/jfs.c (grub_jfs_diropen): Likewise. + * grub-core/fs/fat.c (grub_fat_iterate_dir): Likewise. + +2011-12-13 Vladimir Serbinenko + + * grub-core/term/at_keyboard.c (set_scancodes): Fix preprocessor + conditionals. + +2011-12-13 Vladimir Serbinenko + + * grub-core/kern/emu/main.c (main): Add missing const qualifier. + * grub-core/loader/efi/appleloader.c (devdata): Likewise. + +2011-12-13 Vladimir Serbinenko + + Unify and improve RAID and crypto xor. + + * grub-core/disk/raid.c (grub_raid_block_xor): Removed. All users + changed to grub_crypto_xor + * grub-core/lib/crypto.c (grub_crypto_xor): Moved from here ... + * include/grub/crypto.h (grub_crypto_xor): ... here. Inlined. + Use bigger types when possible. + +2011-12-13 Vladimir Serbinenko + + * grub-core/disk/raid.c (scan_devices): Fix condition. + +2011-12-13 Vladimir Serbinenko + + * grub-core/net/drivers/ieee1275/ofnet.c (bootp_response_properties): + Make name a const ptr. + +2011-12-13 Vladimir Serbinenko + + * grub-core/kern/ieee1275/ieee1275.c (grub_ieee1275_finddevice): Make + first argument a const pointer. + * grub-core/kern/ieee1275/openfw.c (grub_children_iterate): Likewise. + * include/grub/ieee1275/ieee1275.h (grub_ieee1275_finddevice): Update + proto. + (grub_children_iterate): Likewise. + (grub_machine_mmap_iterate): Remove redundant declaration. + +2011-12-13 Vladimir Serbinenko + + * grub-core/commands/acpi.c (grub_acpi_create_ebda) [!x86]: Disable. + (grub_cmd_acpi) [!x86]: Disable EBDA. + +2011-12-13 Vladimir Serbinenko + + Enable UTF8 in gnulib regexp. + + * config.h.in (RE_ENABLE_I18N) [!GRUB_UTIL]: New define. + * grub-core/lib/posix_wrap/ctype.h (islower): Use grub_islower. + (isupper): Use grub_isupper. + (isascii): New inline function. + * grub-core/lib/posix_wrap/wchar.h: Replace dummy with real contents. + * grub-core/lib/posix_wrap/wctype.h: Likewise. + * grub-core/normal/charset.c (grub_utf8_process): New function. + (grub_utf8_to_utf16): Use grub_utf8_process. + (grub_encode_utf8_character): New function. + (grub_ucs4_to_utf8): Use grub_encode_utf8_character. + * include/grub/charset.h (grub_utf8_process): New declaration. + (grub_encode_utf8_character): Likewise. + * include/grub/misc.h (grub_islower): New inline function. + (grub_isupper): Likewise. + (grub_strchrsub): Moved down to fix the definitions. + +2011-12-13 Vladimir Serbinenko + + * grub-core/bus/usb/ohci.c (grub_ohci_check_transfer): Add an unsigned + specification. + +2011-12-13 Vladimir Serbinenko + + * include/grub/loader.h (grub_loader_register_preboot_hook): + Use struct preboot * and not void * for handle. All users updated. + (grub_loader_unregister_preboot_hook): Likewise. + +2011-12-12 Vladimir Serbinenko + + * include/grub/charset.h (GRUB_MAX_UTF8_PER_UTF16): New const. + * grub-core/fs/hfsplus.c (grub_hfsplus_catkey_internal): Change to + UTF-16-BE. All users updated. + (grub_hfsplus_cmp_catkey): Fix unicode handling. + (grub_hfsplus_iterate_dir): Likewise. + (grub_hfsplus_label): Likewise. + +2011-12-12 Vladimir Serbinenko + + * grub-core/disk/ahci.c (grub_ahci_pciinit): Fix compat condition. + +2011-11-30 Vladimir Serbinenko + + Add missing const qualifiers. + + * grub-core/commands/i386/pc/sendkey.c (keysym): Add missing const. + * grub-core/commands/lspci.c (grub_pci_classname): Likewise. + * grub-core/commands/menuentry.c (hotkey_aliases): Likewise. + * grub-core/disk/lvm.c (grub_lvm_getvalue): Likewise. + (grub_lvm_check_flag): Likewise. + * grub-core/efiemu/i386/coredetect.c + (grub_efiemu_get_default_core_name): Likewise + * grub-core/efiemu/main.c (grub_efiemu_autocore): Likewise. + * grub-core/fs/hfsplus.c (grub_hfsplus_catkey_internal): Likewise. + * grub-core/fs/ntfs.c (fixup): Likewise. + * grub-core/fs/xfs.c (grub_xfs_iterate_dir): Likewise. + * grub-core/fs/zfs/zfs.c (decomp_entry): Likewise. + (fzap_lookup): Likewise. + (zap_lookup): Likewise. + * grub-core/gnulib/regcomp.c (init_dfa): Likewise. + * grub-core/lib/legacy_parse.c (check_option): Likewise. + * grub-core/lib/posix_wrap/langinfo.h (nl_langinfo): Likewise. + * grub-core/loader/i386/bsd.c (grub_bsd_add_meta): Likewise. + (grub_freebsd_add_meta_module): Likewise. + (grub_cmd_freebsd_module): Likewise. + * grub-core/loader/i386/xnu.c (tbl_alias): Likewise. + * grub-core/loader/xnu.c (grub_xnu_register_memory): Likewise. + (grub_xnu_writetree_get_size): Likewise. + (grub_xnu_writetree_toheap_real): Likewise. + (grub_xnu_find_key): Likewise. + (grub_xnu_create_key): Likewise. + (grub_xnu_create_value): Likewise. + (grub_xnu_register_memory): Likewise. + (grub_xnu_check_os_bundle_required): Likewise. + (grub_xnu_scan_dir_for_kexts): Likewise. + (grub_xnu_load_kext_from_dir): Likewise. + * grub-core/normal/color.c (color_list): Likewise. + * grub-core/normal/completion.c (current_word): Likewise. + * grub-core/normal/menu_entry.c (insert_string): Likewise. + * grub-core/term/serial.c (grub_serial_find): Likewise. + * grub-core/term/tparm.c (grub_terminfo_tparm): Likewise. + * include/grub/efiemu/efiemu.h (grub_efiemu_get_default_core_name): + Likewise. + * include/grub/i386/bsd.h (grub_bsd_add_meta): Likewise. + (grub_freebsd_add_meta_module): Likewise. + * include/grub/lib/arg.h (grub_arg_option): Likewise. + * include/grub/net.h (grub_net_card_driver): Likewise. + (grub_net_card): Likewise. + (grub_net_app_protocol): Likewise. + * include/grub/parttool.h (grub_parttool_argdesc): Likewise. + * include/grub/serial.h (grub_serial_find): Likewise. + * include/grub/tparm.h (grub_terminfo_tparm): Likewise. + * include/grub/xnu.h (grub_xnu_create_key): Likewise. + (grub_xnu_create_value): Likewise. + (grub_xnu_find_key): Likewise. + (grub_xnu_scan_dir_for_kexts): Likewise. + (grub_xnu_load_kext_from_dir): Likewise. + + * include/grub/zfs/zio_checksum.h (zio_checksum_t): Moved from here ... + * grub-core/fs/zfs/zfs.c (zio_checksum_t): ...here. + * include/grub/zfs/zio_checksum.h (zio_checksum_info): + Moved from here ... + * grub-core/fs/zfs/zfs.c (zio_checksum_info): ... here. Added missing const. + +2011-11-28 Colin Watson + + * util/getroot.c (find_root_device_from_libzfs): Use xasprintf. + +2011-11-27 Vladimir Serbinenko + + * grub-core/fs/zfs/zfs.c (recovery): Fix spelling. + (read_device): Fix size calculation. + +2011-11-25 Robert Millan + + * util/getroot.c [HAVE_LIMITS_H]: Include `'. + (find_root_device_from_libzfs): Add zpool output parser to be used + as fallback when libzfs isn't available. + +2011-11-25 Seth Goldberg + + * po/Makefile.in.in: Add missing escape-continuation. + +2011-11-25 Vladimir Serbinenko + + * grub-core/fs/cpio.c (grub_cpio_dir): Handle subdirs correctly. + +2011-11-16 Vladimir Serbinenko + + * grub-core/kern/dl.c (grub_dl_load_segments): Fix alignment handling. + +2011-11-16 Vladimir Serbinenko + + * grub-core/kern/dl.c (grub_dl_unload): Fix freeing segments. + +2011-11-16 Vladimir Serbinenko + + * grub-core/kern/x86_64/efi/callwrap.S: Fix the comment. + 2011-11-14 Vladimir Serbinenko * grub-core/lib/adler32.c: Add missing license specification. diff --git a/Makefile.am b/Makefile.am index c5f486e0d..24bf9f86a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -101,8 +101,7 @@ CLEANFILES += widthspec.h # Install config.h into platformdir platform_HEADERS = config.h -pkglib_DATA += grub-mkconfig_lib -pkglib_DATA += update-grub_lib +pkgdata_DATA += grub-mkconfig_lib if COND_i386_coreboot @@ -305,7 +304,7 @@ endif BOOTCHECKS += bootcheck-kfreebsd-aout -BOOTCHECKS += bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 +#BOOTCHECKS += bootcheck-kopenbsd-i386 bootcheck-kopenbsd-x86_64 BOOTCHECKS += bootcheck-multiboot bootcheck-multiboot2 diff --git a/Makefile.util.def b/Makefile.util.def index b52b5db9c..98a7e1ecb 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -29,12 +29,15 @@ library = { common = grub-core/lib/pbkdf2.c; common = grub-core/commands/extcmd.c; common = grub-core/lib/arg.c; + common = grub-core/disk/ldm.c; + common = grub-core/disk/diskfilter.c; + common = grub-core/partmap/gpt.c; }; library = { name = libgrubmods.a; cflags = '$(CFLAGS_POSIX) -Wno-undef'; - cppflags = '-I$(srcdir)/lib/posix_wrap -I$(top_srcdir)/grub-core/lib/minilzo -DMINILZO_HAVE_CONFIG_H'; + cppflags = '-I$(top_srcdir)/grub-core/lib/minilzo -I$(srcdir)/grub-core/lib/xzembed -DMINILZO_HAVE_CONFIG_H'; common_nodist = grub_script.tab.c; common_nodist = grub_script.yy.c; @@ -53,12 +56,14 @@ 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/disk/raid.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/cpio.c; + common = grub-core/fs/cpio_be.c; + common = grub-core/fs/odc.c; + common = grub-core/fs/newc.c; common = grub-core/fs/ext2.c; common = grub-core/fs/fat.c; common = grub-core/fs/exfat.c; @@ -100,7 +105,6 @@ library = { common = grub-core/partmap/acorn.c; common = grub-core/partmap/amiga.c; common = grub-core/partmap/apple.c; - common = grub-core/partmap/gpt.c; common = grub-core/partmap/msdos.c; common = grub-core/partmap/sun.c; common = grub-core/partmap/plan.c; @@ -116,6 +120,9 @@ library = { common = grub-core/io/lzopio.c; common = grub-core/kern/ia64/dl_helper.c; common = grub-core/lib/minilzo/minilzo.c; + common = grub-core/lib/xzembed/xz_dec_bcj.c; + common = grub-core/lib/xzembed/xz_dec_lzma2.c; + common = grub-core/lib/xzembed/xz_dec_stream.c; }; program = { @@ -135,6 +142,8 @@ program = { common = util/grub-mkimage.c; common = util/resolve.c; + common = util/argp_common.c; + extra_dist = util/grub-mkimagexx.c; ldadd = libgrubmods.a; @@ -151,6 +160,7 @@ program = { mansection = 1; common = util/grub-mkrelpath.c; + common = util/argp_common.c; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; @@ -164,6 +174,7 @@ program = { mansection = 1; common = util/grub-script-check.c; + common = util/argp_common.c; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; @@ -190,6 +201,7 @@ program = { mansection = 1; common = util/grub-mkpasswd-pbkdf2.c; + common = util/argp_common.c; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; @@ -259,6 +271,7 @@ program = { mansection = 1; common = util/grub-mkfont.c; common = grub-core/unidata.c; + common = util/argp_common.c; cflags = '$(freetype_cflags)'; @@ -271,30 +284,13 @@ program = { condition = COND_GRUB_MKFONT; }; -program = { - name = grub-mkdevicemap; - installdir = sbin; - mansection = 8; - - common = util/grub-mkdevicemap.c; - common = util/deviceiter.c; - nosparc64 = util/devicemap.c; - - sparc64_ieee1275 = util/ieee1275/ofpath.c; - sparc64_ieee1275 = util/ieee1275/devicemap.c; - - ldadd = libgrubmods.a; - ldadd = libgrubgcry.a; - ldadd = libgrubkern.a; - ldadd = grub-core/gnulib/libgnu.a; - ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)'; -}; - program = { name = grub-probe; installdir = sbin; mansection = 8; common = util/grub-probe.c; + common = util/ieee1275/ofpath.c; + common = util/argp_common.c; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; @@ -309,6 +305,7 @@ program = { mansection = 8; common = util/grub-setup.c; common = util/lvm.c; + common = util/argp_common.c; common = grub-core/lib/reed_solomon.c; sparc64_ieee1275 = util/ieee1275/ofpath.c; @@ -344,6 +341,7 @@ program = { mansection = 1; common = util/grub-mklayout.c; + common = util/argp_common.c; ldadd = libgrubmods.a; ldadd = libgrubgcry.a; @@ -494,15 +492,10 @@ script = { installdir = noinst; }; -script = { - name = update-grub_lib; - common = util/update-grub_lib.in; - installdir = noinst; -}; - script = { name = grub-kbdcomp; common = util/grub-kbdcomp.in; + mansection = 1; }; script = { diff --git a/conf/Makefile.common b/conf/Makefile.common index 751188b26..b960bdf81 100644 --- a/conf/Makefile.common +++ b/conf/Makefile.common @@ -105,7 +105,7 @@ platformdir = $(pkglibrootdir)/$(target_cpu)-$(platform) CFLAGS_GCRY = -Wno-error -Wno-missing-field-initializers CPPFLAGS_GCRY = -I$(top_srcdir)/grub-core/lib/libgcrypt_wrap -CFLAGS_GNULIB = -Wno-undef -Wno-sign-compare -Wno-unused -Wno-unused-parameter +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 @@ -137,7 +137,7 @@ KERNEL_HEADER_FILES = man_MANS = noinst_DATA = -pkglib_DATA = +pkgdata_DATA = bin_SCRIPTS = sbin_SCRIPTS = bin_PROGRAMS = @@ -147,11 +147,12 @@ check_SCRIPTS = grubconf_DATA = check_PROGRAMS = noinst_SCRIPTS = -pkglib_SCRIPTS = noinst_PROGRAMS = grubconf_SCRIPTS = noinst_LIBRARIES = dist_noinst_DATA = +platform_SCRIPTS = +platform_PROGRAMS = TESTS = EXTRA_DIST = diff --git a/config.h.in b/config.h.in index 92d7a07f2..a7eaf1925 100644 --- a/config.h.in +++ b/config.h.in @@ -2,6 +2,9 @@ #undef _FILE_OFFSET_BITS #define _LARGEFILE_SOURCE #define _FILE_OFFSET_BITS 64 +#if defined(__PPC__) && !defined(__powerpc__) +#define __powerpc__ 1 +#endif #if defined (GRUB_UTIL) || !defined (GRUB_MACHINE) #include #define NESTED_FUNC_ATTR @@ -39,6 +42,11 @@ /* Define to 1 to enable disk cache statistics. */ #define DISK_CACHE_STATS @DISK_CACHE_STATS@ +#define GRUB_TARGET_CPU "@GRUB_TARGET_CPU@" +#define GRUB_PLATFORM "@GRUB_PLATFORM@" + +#define RE_ENABLE_I18N 1 + #if defined(__i386__) #define NESTED_FUNC_ATTR __attribute__ ((__regparm__ (1))) #else diff --git a/configure.ac b/configure.ac index 7699e8330..e70064f75 100644 --- a/configure.ac +++ b/configure.ac @@ -177,7 +177,7 @@ esac if test x${target_cpu} = xmipsel ; then machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE=`echo mips_$platform | sed y,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ,`" else - machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE=`echo ${target_cpu}_$platform | sed y,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ,`" + machine_CPPFLAGS="$machine_CPPFLAGS -DGRUB_MACHINE=`echo ${target_cpu}_$platform | sed y,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ,` -DGRUB_TARGET_CPU_`echo ${target_cpu} | sed y,abcdefghijklmnopqrstuvwxyz,ABCDEFGHIJKLMNOPQRSTUVWXYZ,`=1" fi HOST_CPPFLAGS="$HOST_CPPFLAGS $machine_CPPFLAGS" @@ -234,7 +234,7 @@ for ext in pcf pcf.gz bdf bdf.gz ttf ttf.gz; do done done -if test "x$FONT_SOURCE" = x && ( test "x$platform" = xqemu || test "x$platform" = xloongson ); then +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 @@ -298,7 +298,7 @@ fi # Check for functions and headers. AC_CHECK_FUNCS(posix_memalign memalign asprintf vasprintf getextmntent) -AC_CHECK_HEADERS(libzfs.h libnvpair.h sys/param.h sys/mount.h sys/mnttab.h sys/mkdev.h) +AC_CHECK_HEADERS(libzfs.h libnvpair.h sys/param.h sys/mount.h sys/mnttab.h sys/mkdev.h limits.h) AC_CHECK_MEMBERS([struct statfs.f_fstypename],,,[$ac_includes_default #include @@ -373,7 +373,9 @@ LDFLAGS="$TARGET_LDFLAGS" LIBS="" # debug flags. -TARGET_CFLAGS="$TARGET_CFLAGS -Wall -W -Wshadow -Wpointer-arith -Wmissing-prototypes -Wundef -Wstrict-prototypes -g" +WARN_FLAGS="-Wall -W -Wshadow -Wold-style-declaration -Wold-style-definition -Wpointer-arith -Wundef -Wextra -Waddress -Warray-bounds -Wattributes -Wbuiltin-macro-redefined -Wcast-align -Wchar-subscripts -Wclobbered -Wcomment -Wcoverage-mismatch -Wdeprecated -Wdeprecated-declarations -Wdisabled-optimization -Wdiv-by-zero -Wempty-body -Wendif-labels -Wfloat-equal -Wformat-contains-nul -Wformat-extra-args -Wformat-security -Wformat-y2k -Wignored-qualifiers -Wimplicit -Wimplicit-function-declaration -Wimplicit-int -Winit-self -Wint-to-pointer-cast -Winvalid-pch -Wunsafe-loop-optimizations -Wlogical-op -Wmain -Wmissing-braces -Wmissing-field-initializers -Wmissing-format-attribute -Wmissing-noreturn -Wmudflap -Wmultichar -Wnonnull -Woverflow -Wpacked-bitfield-compat -Wparentheses -Wpointer-arith -Wpointer-to-int-cast -Wreturn-type -Wsequence-point -Wshadow -Wsign-compare -Wstack-protector -Wstrict-aliasing -Wswitch -Wsync-nand -Wtrigraphs -Wtype-limits -Wundef -Wuninitialized -Wunknown-pragmas -Wunreachable-code -Wunused -Wunused-function -Wunused-label -Wunused-parameter -Wunused-result -Wunused-value -Wunused-variable -Wvariadic-macros -Wvolatile-register-var -Wwrite-strings -Wmissing-declarations -Wmissing-parameter-type -Wmissing-prototypes -Wnested-externs -Wstrict-prototypes -Wpointer-sign" +HOST_CFLAGS="$HOST_CFLAGS $WARN_FLAGS" +TARGET_CFLAGS="$TARGET_CFLAGS $WARN_FLAGS -g -Wredundant-decls -Wmissing-prototypes" TARGET_CCASFLAGS="$TARGET_CCASFLAGS -g" # Force no alignment to save space on i386. @@ -477,6 +479,40 @@ case "${host_os}" in 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, [ + 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]) + ]) + 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" @@ -558,11 +594,18 @@ AC_ARG_ENABLE([werror], [do not use -Werror when building GRUB])]) if test x"$enable_werror" != xno ; then TARGET_CFLAGS="$TARGET_CFLAGS -Werror" + HOST_CFLAGS="$HOST_CFLAGS -Werror" fi TARGET_CPP="$TARGET_CC -E" TARGET_CCAS=$TARGET_CC +GRUB_TARGET_CPU="${target_cpu}" +GRUB_PLATFORM="${platform}" + +AC_SUBST(GRUB_TARGET_CPU) +AC_SUBST(GRUB_PLATFORM) + AC_SUBST(OBJCONV) AC_SUBST(TARGET_CPP) AC_SUBST(TARGET_CCAS) @@ -636,39 +679,6 @@ if test "x$target_cpu" = xi386; then grub_I386_ASM_ADDR32 fi -AC_ARG_ENABLE([efiemu], - [AS_HELP_STRING([--enable-efiemu], - [build and install the efiemu runtimes (default=guessed)])]) -if test x"$enable_efiemu" = xno ; then - efiemu_excuse="explicitly disabled" -fi -if test x"$target_cpu" != xi386 ; then - efiemu_excuse="only available on i386" -fi -if test x"$platform" = xefi ; then - efiemu_excuse="not available on efi" -fi -if test x"$efiemu_excuse" = x ; then - AC_CACHE_CHECK([whether options required for efiemu work], grub_cv_cc_efiemu, [ - CFLAGS="$CFLAGS -m64 -mcmodel=large -mno-red-zone -nostdlib" - 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]) - if test "$platform" != emu; then AC_CACHE_CHECK([whether -nostdinc -isystem works], [grub_cv_cc_isystem], [ SAVED_CPPFLAGS="$CPPFLAGS" diff --git a/docs/grub-dev.texi b/docs/grub-dev.texi index 93d2bdb4d..51b47872d 100644 --- a/docs/grub-dev.texi +++ b/docs/grub-dev.texi @@ -77,6 +77,7 @@ This edition documents version @value{VERSION}. * Finding your way around:: * Coding style:: * Contributing Changes:: +* Porting:: * Error Handling:: * CIA:: * BIOS port memory map:: @@ -447,6 +448,315 @@ If your intention is to just get started, please do not submit a inclusion request. Instead, please subscribe to the mailing list, and communicate first (e.g. sending a patch, asking a question, commenting on another message...). +@node Porting +@chapter Porting + +GRUB2 is designed to be easily portable accross platforms. But because of the +nature of bootloader every new port must be done separately. Here is how I did +MIPS (loongson and ARC) and Xen ports. Note than this is more of suggestions, +not absolute truth. + +First of all grab any architecture specifications you can find in public +(please avoid NDA). + +First stage is ``Hello world''. I've done it outside of GRUB for simplicity. +Your task is to have a small program which is loadable as bootloader and +clearly shows its presence to you. If you have easily accessible console +you can just print a message. If you have a mapped framebuffer you know address +of, you can draw a square. If you have a debug facility, just hanging without +crashing might be enough. For the first stage you can choose to load the +bootloader across the network since format for network image is often easier +than for local boot and it skips the need of small intermediary stages and +nvram handling. Additionally you can often have a good idea of the needed +format by running ``file'' on any netbootable executable for given platform. + +This program should probably have 2 parts: an assembler and C one. Assembler one +handles BSS cleaning and other needed setup (on some platforms you may need +to switch modes or copy the executable to its definitive position). So your code +may look like (x86 assembly for illustration purposes) + +@example + .globl _start +_start: + movl $_bss_start, %edi + movl $_end, %ecx + subl %edi, %ecx + xorl %eax, %eax + cld + rep + stosb + call main +@end example + +@example + +static const char msg[] = "Hello, world"; + +void +putchar (int c) +@{ + ... +@} + +void +main (void) +@{ + const char *ptr = msg; + while (*ptr) + putchar (*ptr++); + while (1); +@} +@end example + +Sometimes you need a third file: assembly stubs for ABI-compatibility. + +Once this file is functional it's time to move it into GRUB2. The startup +assembly file goes to grub-core/kern/$cpu/$platform/startup.S. You should also +include grub/symbol.h and replace call to entry point with call to +EXT_C(grub_main). The C file goes to grub-core/kern/$cpu/$platform/init.c +and its entry point is renamed to void grub_machine_init (void). Keep final +infinite loop for now. Stubs file if any goes to +grub-core/kern/$cpu/$platform/callwrap.S. Sometimes either $cpu or $platform +is dropped if file is used on several cpus respectivelyplatforms. +Check those locations if they already have what you're looking for. + +Then modify in configure.ac the following parts: + +CPU names: + +@example +case "$target_cpu" in + i[[3456]]86) target_cpu=i386 ;; + amd64) target_cpu=x86_64 ;; + sparc) target_cpu=sparc64 ;; + s390x) target_cpu=s390 ;; + ... +esac +@end example + +Sometimes CPU have additional architecture names which don't influence booting. +You might want to have some canonical name to avoid having bunch of identical +platforms with different names. + +NOTE: it doesn't influence compile optimisations which depend solely on +chosen compiler and compile options. + +@example +if test "x$with_platform" = x; then + case "$target_cpu"-"$target_vendor" in + i386-apple) platform=efi ;; + i386-*) platform=pc ;; + x86_64-apple) platform=efi ;; + x86_64-*) platform=pc ;; + powerpc-*) platform=ieee1275 ;; + ... + esac +else + ... +fi +@end example + +This part deals with guessing the platform from CPU and vendor. Sometimes you +need to use 32-bit mode for booting even if OS runs in 64-bit one. If so add +your platform to: + +@example +case "$target_cpu"-"$platform" in + x86_64-efi) ;; + x86_64-emu) ;; + x86_64-*) target_cpu=i386 ;; + powerpc64-ieee1275) target_cpu=powerpc ;; +esac +@end example + +Add your platform to the list of supported ones: + +@example +case "$target_cpu"-"$platform" in + i386-efi) ;; + x86_64-efi) ;; + i386-pc) ;; + i386-multiboot) ;; + i386-coreboot) ;; + ... +esac +@end example + +If explicit -m32 or -m64 is needed add it to: + +@example +case "$target_cpu" in + i386 | powerpc) target_m32=1 ;; + x86_64 | sparc64) target_m64=1 ;; +esac +@end example + +Finally you need to add a conditional to the following block: + +@example +AM_CONDITIONAL([COND_mips_arc], [test x$target_cpu = xmips -a x$platform = xarc]) +AM_CONDITIONAL([COND_sparc64_ieee1275], [test x$target_cpu = xsparc64 -a x$platform = xieee1275]) +AM_CONDITIONAL([COND_powerpc_ieee1275], [test x$target_cpu = xpowerpc -a x$platform = xieee1275]) +@end example + +Next stop is gentpl.py. You need to add your platform to the list of supported +ones (sorry that this list is duplicated): + +@example +GRUB_PLATFORMS = [ "emu", "i386_pc", "i386_efi", "i386_qemu", "i386_coreboot", + "i386_multiboot", "i386_ieee1275", "x86_64_efi", + "mips_loongson", "sparc64_ieee1275", + "powerpc_ieee1275", "mips_arc", "ia64_efi", + "mips_qemu_mips", "s390_mainframe" ] +@end example + +You may also want already to add new platform to one or several of available +groups. In particular we always have a group for each CPU even when only +one platform for given CPU is available. + +Then comes grub-core/Makefile.core.def. In the block ``kernel'' you'll need +to define ldflags for your platform ($cpu_$platform_ldflags). You also need to +declare startup asm file ($cpu_$platform_startup) as well as any other files +(e.g. init.c and callwrap.S) (e.g. $cpu_$platform = kern/$cpu/$platform/init.c). +At this stage you will also need to add dummy dl.c and cache.S with functions +grub_err_t grub_arch_dl_check_header (void *ehdr), grub_err_t +grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) (dl.c) and +void grub_arch_sync_caches (void *address, grub_size_t len) (cache.S). They +won't be used for now. + +You will need to create directory include/$cpu/$platform and a file +include/$cpu/types.h. The later folowing this template: + +@example +#ifndef GRUB_TYPES_CPU_HEADER +#define GRUB_TYPES_CPU_HEADER 1 + +/* The size of void *. */ +#define GRUB_TARGET_SIZEOF_VOID_P 4 + +/* The size of long. */ +#define GRUB_TARGET_SIZEOF_LONG 4 + +/* mycpu is big-endian. */ +#define GRUB_TARGET_WORDS_BIGENDIAN 1 +/* Alternatively: mycpu is little-endian. */ +#undef GRUB_TARGET_WORDS_BIGENDIAN + +#endif /* ! GRUB_TYPES_CPU_HEADER */ +@end example + +You will also need to add a dummy file to datetime and setjmp modules to +avoid any of it having no files. It can be just completely empty at this stage. + +You'll need to make grub-mkimage.c (util/grub_mkimage.c) aware of the needed +format. For most commonly used formats like ELF, PE, aout or raw the support +is already present and you'll need to make it follow the existant code paths +for your platform adding adjustments if necessary. When done compile: + +@example +./autogen.sh +./configure --target=$cpu --with-platform=$platform TARGET_CC=.. OBJCOPY=... STRIP=... +make > /dev/null +@end example + +And create image + +@example +./grub-mkimage -d grub-core -O $format_id -o test.img +@end example + +And it's time to test your test.img. + +If it works next stage is to have heap, console and timer. + +To have the heap working you need to determine which regions are suitable for +heap usage, allocate them from firmware and map (if applicable). Then call +grub_mm_init_region (vois *start, grub_size_t s) for every of this region. +As a shortcut for early port you can allocate right after _end or have +a big static array for heap. If you do you'll probably need to come back to +this later. As for output console you should distinguish between an array of +text, terminfo or graphics-based console. Many of real-world examples don't +fit perfectly into any of these categories but one of the models is easier +to be used as base. In second and third case you should add your platform to +terminfokernel respectively videoinkernel group. A good example of array of +text is i386-pc (kern/i386/pc/init.c and term/i386/pc/console.c). +Of terminfo is ieee1275 (kern/ieee1275/init.c and term/ieee1275/console.c). +Of video is loongson (kern/mips/loongson/init.c). Note that terminfo has +to be inited in 2 stages: one before (to get at least rudimentary console +as early as possible) and another after the heap (to get full-featured console). +For the input there are string of keys, terminfo and direct hardware. For string +of keys look at i386-pc (same files), for termino ieee1275 (same files) and for +hardware loongson (kern/mips/loongson/init.c and term/at_keyboard.c). + +For the timer you'll need to call grub_install_get_time_ms (...) with as sole +argument a function returning a grub_uint64_t of a number of milliseconds +elapsed since arbitrary point in the past. + +Once these steps accomplished you can remove the inifinite loop and you should +be able to get to the minimal console. Next step is to have module loading +working. For this you'll need to fill kern/$cpu/dl.c and kern/$cpu/cache.S +with real handling of relocations and respectively the real sync of I and D +caches. Also you'll need to decide where in the image to store the modules. +Usual way is to have it concatenated at the end. In this case you'll need to +modify startup.S to copy modules out of bss to let's say ALIGN_UP (_end, 8) +before cleaning out bss. You'll probably find useful to add total_module_size +field to startup.S. In init.c you need to set grub_modbase to the address +where modules can be found. You may need grub_modules_get_end () to avoid +declaring the space occupied by modules as usable for heap. You can test modules +with: + +@example +./grub-mkimage -d grub-core -O $format_id -o test.img hello +@end example + +and then running ``hello'' in the shell. + +Once this works, you should think of implementing disk access. Look around +disk/ for examples. + +Then, very importantly, you probably need to implement the actual loader +(examples available in loader/) + +Last step to have minimally usable port is to add support to grub-install to +put GRUB in a place where firmware or platform will pick it up. + +Next steps are: filling datetime.c, setjmp.S, network (net/drivers), +video (video/), halt (lib/), reboot (lib/). + +Please add your platform to Platform limitations and Supported kernels chapter +in user documentation and mention any steps you skipped which result in reduced +features or performance. Here is the quick checklist of features. Some of them +are less important than others and skipping them is completely ok, just needs +to be mentioned in user documentation. + +Checklist: +@itemize +@item Is heap big enough? +@item Which charset is supported by console? +@item Does platform have disk driver? +@item Do you have network card support? +@item Are you able to retrieve datetime (with date)? +@item Are you able to set datetime (with date)? +@item Is serial supported? +@item Do you have direct disk support? +@item Do you have direct keyboard support? +@item Do you have USB support? +@item Do you support loading through network? +@item Do you support loading from disk? +@item Do you support chainloading? +@item Do you support network chainloading? +@item Does cpuid command supports checking all +CPU features that the user might want conditionalise on +(64-bit mode, hypervisor,...) +@item Do you support hints? How reliable are they? +@item Does platform have ACPI? If so do ``acpi'' and ``lsacpi'' modules work? +@item Do any of platform-specific operations mentioned in the relevant section of +user manual makes sense on your platform? +@item Does your platform support PCI? If so is there an appropriate driver for +GRUB? +@item Do you support badram? +@end itemize + @node Error Handling @chapter Error Handling diff --git a/docs/grub.texi b/docs/grub.texi index f2e19cc74..2c737593d 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 Free Software Foundation, Inc. +Copyright @copyright{} 1999,2000,2001,2002,2004,2006,2008,2009,2010,2011,2012 Free Software Foundation, Inc. @quotation Permission is granted to copy, distribute and/or modify this document @@ -89,7 +89,10 @@ This edition documents version @value{VERSION}. * 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 +* Platform limitations:: The list of platform-specific limitations +* Platform-specific operations:: Platform-specific operations * Supported kernels:: The list of supported kernels * Troubleshooting:: Error messages produced by GRUB * Invoking grub-install:: How to use the GRUB installer @@ -340,11 +343,17 @@ devices, partitions, and files in a directory depending on context. @item Support multiple filesystem types Support multiple filesystem types transparently, plus a useful explicit blocklist notation. The currently supported filesystem types are @dfn{Amiga -Fast FileSystem (AFFS)}, @dfn{AtheOS fs}, @dfn{BeFS}, @dfn{cpio}, @dfn{Linux -ext2/ext3/ext4}, @dfn{DOS FAT12/FAT16/FAT32}, @dfn{HFS}, @dfn{HFS+}, -@dfn{ISO9660}, @dfn{JFS}, @dfn{Minix fs}, @dfn{nilfs2}, @dfn{NTFS}, -@dfn{ReiserFS}, @dfn{Amiga Smart FileSystem (SFS)}, @dfn{tar}, @dfn{UDF}, -@dfn{BSD UFS/UFS2}, and @dfn{XFS}. @xref{Filesystem}, for more information. +Fast FileSystem (AFFS)}, @dfn{AtheOS fs}, @dfn{BeFS}, +@dfn{BtrFS} (including raid0, raid1, raid10, gzip and lzo), +@dfn{cpio} (little- and big-endian bin, odc and newc variants), +@dfn{Linux ext2/ext3/ext4}, @dfn{DOS FAT12/FAT16/FAT32}, @dfn{exFAT}, @dfn{HFS}, +@dfn{HFS+}, @dfn{ISO9660} (including Joliet, Rock-ridge and multi-chunk files), +@dfn{JFS}, @dfn{Minix fs} (versions 1, 2 and 3), @dfn{nilfs2}, +@dfn{NTFS} (including compression), @dfn{ReiserFS}, @dfn{ROMFS}, +@dfn{Amiga Smart FileSystem (SFS)}, @dfn{Squash4}, @dfn{tar}, @dfn{UDF}, +@dfn{BSD UFS/UFS2}, @dfn{XFS}, and @dfn{ZFS} (including lzjb, gzip, +zle, mirror, stripe, raidz1/2/3 and encryption in AES-CCM and AES-GCM). +@xref{Filesystem}, for more information. @item Support automatic decompression Can decompress files which were compressed by @command{gzip} or @@ -784,6 +793,7 @@ magic. @menu * General boot methods:: How to boot OSes with GRUB generally +* Loopback booting:: Notes on booting from loopbacks * OS-specific notes:: Notes on some operating systems @end menu @@ -855,6 +865,31 @@ required. @xref{DOS/Windows}. Chain-loading is only supported on PC BIOS and EFI platforms. +@node Loopback booting +@section Loopback booting +GRUB is able to read from an image (be it one of CD or HDD) stored on +any of its accessible storages (refer to @pxref{loopback} command). +However the OS itself should be able to find its root. This usually +involves running a userspace program running before the real root +is discovered. This is achieved by GRUB loading a specially made +small image and passing it as ramdisk to the kernel. This is achieved +by commands @command{kfreebsd_module}, @command{knetbsd_module_elf}, +@command{kopenbsd_ramdisk}, @command{initrd} (@pxref{initrd}), +@command{initrd16} (@pxref{initrd}), @command{multiboot_module}, +@command{multiboot2_module} or @command{xnu_ramdisk} +depending on the loader. Note that for knetbsd the image must be put +inside miniroot.kmod and the whole miniroot.kmod has to be loaded. In +kopenbsd payload this is disabled by default. Aditionally behaviour of +initial ramdisk depends on command line options. Several distributors provide +the image for this purpose or it's integrated in their standard ramdisk and +activated by special option. Consult your kernel and distribution manual for +more details. Other loaders like appleloader, chainloader (BIOS, EFI, coreboot), +freedos, ntldr and plan9 provide no possibility of loading initial ramdisk and +as far as author is aware the payloads in question don't support either initial +ramdisk or discovering loopback boot in other way and as such not bootable this +way. Please consider alternative boot methods like copying all files +from the image to actual partition. Consult your OS documentation for +more details @node OS-specific notes @section Some caveats on OS-specific issues @@ -2203,42 +2238,67 @@ you see the files in a device or use the command @command{search} The device syntax is like this: @example -@code{(@var{device}[,@var{part-num}][,@var{bsd-subpart-letter}])} +@code{(@var{device}[,@var{partmap-name1}@var{part-num1}[,@var{partmap-name2}@var{part-num2}[,...]]])} @end example -@samp{[]} means the parameter is optional. @var{device} should be -either @samp{fd} or @samp{hd} followed by a digit, like @samp{fd0}. -But you can also set @var{device} to a hexadecimal or a decimal number -which is a BIOS drive number, so the following are equivalent: +@samp{[]} means the parameter is optional. @var{device} depends on the disk +driver in use. BIOS and EFI disks use either @samp{fd} or @samp{hd} followed +by a digit, like @samp{fd0}, or @samp{cd}. +AHCI, PATA (ata), crypto, USB use the name of driver followed by a number. +Memdisk and host are limited to one disk and so it's refered just by driver +name. +RAID (md), ofdisk (ieee1275), LVM (lv) and arcdisk (arc) use intrinsic name +of disk prefixed by driver name. 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 or hostdisk/. +For crypto and RAID (md) additionally you can use the syntax +uuid/. @example +(fd0) (hd0) -(0x80) -(128) +(cd) +(ahci0) +(ata0) +(crypto0) +(usb0) +(cryptouuid/123456789abcdef0123456789abcdef0) +(mduuid/123456789abcdef0123456789abcdef0) +(lv/system-root) +(md/myraid) +(md/0) +(ieee1275/disk2) +(ieee1275//pci@@1f\,0/ide@@d/disk@@2) +(memdisk) +(host) +(myloop) +(hostdisk//dev/sda) @end example @var{part-num} represents the partition number of @var{device}, starting -from one for primary partitions and from five for extended partitions, -and @var{bsd-subpart-letter} represents the BSD disklabel subpartition, -such as @samp{a} or @samp{e}. - -A shortcut for specifying BSD subpartitions is -@code{(@var{device},@var{bsd-subpart-letter})}, in this case, GRUB -searches for the first PC partition containing a BSD disklabel, then -finds the subpartition @var{bsd-subpart-letter}. Here is an example: - -@example -(hd0,a) -@end example +from one. @var{partname} is optional but is recommended since disk may have +several top-level partmaps. Specifying third and later component you can access +to subpartitions. The syntax @samp{(hd0)} represents using the entire disk (or the MBR when installing GRUB), while the syntax @samp{(hd0,1)} represents using the first partition of the disk (or the boot sector of the partition when installing GRUB). -If you enabled the network support, the special drive @samp{(pxe)} is -also available. Before using the network drive, you must initialize the -network. @xref{Network}, for more information. +@example +(hd0,msdos1) +(hd0,msdos1,msdos5) +(hd0,msdos1,bsd3) +(hd0,netbsd1) +(hd0,gpt1) +(hd0,1,3) +@end example + +If you enabled the network support, the special drives @samp{(tftp)}, +@samp{(http)} and so on ars also available. +Before using the network drive, you must initialize the network. +@xref{Network}, for more information. If you boot GRUB from a CD-ROM, @samp{(cd)} is available. @xref{Making a GRUB bootable CD-ROM}, for details. @@ -3867,6 +3927,102 @@ Unset the environment variable @var{envvar}. This command is not yet implemented for GRUB 2, although it is planned. +@node Internationalisation +@chapter Charset +GRUB uses UTF-8 internally other than in rendering where some GRUB-specific +appropriate representation is used. All text files (including config) are +assumed to be encoded in UTF-8. + +@chapter Filesystems +NTFS, JFS, UDF, HFS+, exFAT, long filenames in FAT, Joliet part of +ISO9660 are treated as UTF-16 as per specification. AFS and BFS are read +as UTF-8, again according to specification. BtrFS, cpio, tar, squash4, minix, +minix2, minix3, ROMFS, ReiserFS, XFS, ext2, ext3, ext4, FAT (short names), +ISO9660 (plain and RockRidge), nilfs2, UFS1, UFS2 and ZFS are assumed +to be UTF-8. This might be false on systems configured with legacy charset +but as long as the charset used is superset of ASCII you should be able to +access ASCII-named files. And it's recommended to configure your system to use +UTF-8 to access the filesystem, convmv may help with migration. AFFS, SFS +and HFS never use unicode and GRUB assumes them to be in Latin1, Latin1 +and MacRoman respectively. GRUB handles filesystem case-insensitivity however +no attempt is performed at case conversion of international characters +so e.g. a file named lowercase greek alpha is treated as different from +the one named as uppercase alpha. The filesystems in questions are +NTFS (except POSIX namespace), HFS+ (by default), FAT, exFAT and +ZFS (configurable on per-subvolume basis by property ``casesensitivity'', +default sensitive). On ZFS subvolumes marked as case insensitive files +containing lowercase international characters are inaccessible. +Also like all supported filesystems except HFS+ and ZFS (configurable on +per-subvolume basis by property ``normalization'', default none) GRUB makes +no attempt at check of canonical equivalence so a file name u-diaresis is +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 +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. + +@chapter Input terminal +Firmware console on BIOS, IEEE1275 and ARC doesn't allow you to enter non-ASCII +characters. EFI specification allows for such but author is unaware of any +actual implementations. Serial input is currently limited for latin1 (unlikely +to change). Own keyboard implementations (at_keyboard and usb_keyboard) +supports any key but work on one-char-per-keystroke. +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 +GRUB supports being translated. For this you need to have language *.mo files in $prefix/locale, load gettext module and set ``lang'' variable. + +@chapter Regexp +Regexps work on unicode characters, however no attempt at checking cannonical +equivalence has been made. Moreover the classes like [:alpha:] match only +ASCII subset. + +@chapter Other +Currently GRUB always uses YEAR-MONTH-DAY HOUR:MINUTE:SECOND [WEEKDAY] 24-hour +datetime format but weekdays are translated. +GRUB always uses the decimal number format with [0-9] as digits and . as +descimal separator and no group separator. +IEEE1275 aliases are matched case-insensitively except non-ASCII which is +matched as binary. Similar behaviour is for matching OSBundleRequired. +Since IEEE1275 aliases and OSBundleRequired don't contain any non-ASCII it +should never be a problem in practice. +Case-sensitive identifiers are matched as raw strings, no canonical +equivalence check is performed. Case-insenstive identifiers are matched +as RAW but additionally [a-z] is equivalent to [A-Z]. GRUB-defined +identifiers use only ASCII and so should user-defined ones. +Identifiers containing non-ASCII may work but aren't supported. +Only the ASCII space characters (space U+0020, tab U+000b, CR U+000d and +LF U+000a) are recognised. Other unicode space characters aren't a valid +field separator. +@command{test} tests <, >, <=, >=, -pgt and -plt compare the strings in the +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 @@ -3935,6 +4091,167 @@ adding @kbd{set superusers=} and @kbd{password} or @kbd{password_pbkdf2} commands. +@node Platform limitations +@chapter Platform limitations + +GRUB2 is designed to be portable and is actually ported across platforms. We +try to keep all platforms at the level. Unfortunately some platforms are better +supported than others. This is detailed in current and 2 following sections. + +ARC platform is unable to change datetime (firmware doesn't seem to provide a +function for it). +EMU has similar limitation. + +Console charset refers only to firmware-assisted console. gfxterm is always +Unicode (see Internationalisation section for its limitations). Serial is +configurable to UTF-8 or ASCII (see Internationalisation). In case of qemu +and coreboot ports the refered console is vga_text. Loongson always uses +gfxterm. + +Most limited one is ASCII. CP437 provides additionally pseudographics. +GRUB2 doesn't use any language characters from CP437 as often CP437 is replaced +by national encoding compatible only in pseudographics. +Unicode is the most versatile charset which supports many languages. However +the actual console may be much more limited depending on firmware + +On BIOS network is supported only if the image is loaded through network. +On sparc64 GRUB is unable to determine which server it was booted from. + +On platforms not having direct serial support (as indicated in the line serial) +you can still redirect firmware console to serial if it allows so. + +Direct ATA/AHCI support allows to circumvent various firmware limitations but +isn't needed for normal operation except on baremetal ports. + +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. + +USB support provides benefits similar to ATA (for USB disks) or AT (for USB +keyboards). In addition it allows USBserial. + +Chainloading refers to the ability to load another bootloader through the same protocol + +Hints allow faster disk discovery by already knowing in advance which is the disk in +question. On some platforms hints are correct unless you move the disk between boots. +On other platforms it's just an educated guess. +Note that hint failure results in just reduced performance, not a failure + +BadRAM is the ability to mark some of the RAM as ``bad''. Note: due to protocol +limitations mips-loongson (with Linux protocol) +and mips-qemu_mips can use only memory up to first hole. + +@multitable @columnfractions .20 .20 .20 .20 .20 +@item @tab BIOS @tab Coreboot @tab Multiboot @tab Qemu +@item video @tab yes @tab yes @tab yes @tab yes +@item console charset @tab CP437 @tab CP437 @tab CP437 @tab CP437 +@item network @tab yes (*) @tab no @tab no @tab no +@item serial @tab yes @tab yes @tab yes @tab yes +@item ATA/AHCI @tab yes @tab yes @tab yes @tab yes +@item AT keyboard @tab yes @tab yes @tab yes @tab yes +@item USB @tab yes @tab yes @tab yes @tab yes +@item chainloader @tab local @tab yes @tab yes @tab no +@item cpuid @tab partial @tab partial @tab partial @tab partial +@item hints @tab guess @tab guess @tab guess @tab guess +@item PCI @tab yes @tab yes @tab yes @tab yes +@item badram @tab yes @tab yes @tab yes @tab yes +@item compression @tab always @tab pointless @tab no @tab no +@item exit @tab yes @tab no @tab no @tab no +@end multitable + +@multitable @columnfractions .20 .20 .20 .20 .20 +@item @tab ia32 EFI @tab amd64 EFI @tab ia32 IEEE1275 @tab Itanium +@item video @tab yes @tab yes @tab no @tab no +@item console charset @tab Unicode @tab Unicode @tab ASCII @tab Unicode +@item network @tab yes @tab yes @tab yes @tab yes +@item serial @tab yes @tab yes @tab yes @tab no +@item ATA/AHCI @tab yes @tab yes @tab yes @tab no +@item AT keyboard @tab yes @tab yes @tab yes @tab no +@item USB @tab yes @tab yes @tab yes @tab no +@item chainloader @tab local @tab local @tab no @tab local +@item cpuid @tab partial @tab partial @tab partial @tab no +@item hints @tab guess @tab guess @tab good @tab guess +@item PCI @tab yes @tab yes @tab yes @tab no +@item badram @tab yes @tab yes @tab no @tab yes +@item compression @tab no @tab no @tab no @tab no +@item exit @tab yes @tab yes @tab yes @tab yes +@end multitable + +@multitable @columnfractions .20 .20 .20 .20 .20 +@item @tab Loongson @tab sparc64 @tab Powerpc @tab ARC +@item video @tab yes @tab no @tab yes @tab no +@item console charset @tab N/A @tab ASCII @tab ASCII @tab ASCII +@item network @tab no @tab yes (*) @tab yes @tab no +@item serial @tab yes @tab no @tab no @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 USB @tab yes @tab no @tab no @tab no +@item chainloader @tab yes @tab no @tab no @tab no +@item cpuid @tab no @tab no @tab no @tab no +@item hints @tab good @tab good @tab good @tab no +@item PCI @tab yes @tab no @tab no @tab no +@item badram @tab yes (*) @tab no @tab no @tab no +@item compression @tab configurable @tab no @tab no @tab configurable +@item exit @tab no @tab yes @tab yes @tab yes +@end multitable + +@multitable @columnfractions .20 .20 .20 .20 .20 +@item @tab MIPS qemu @tab emu +@item video @tab no @tab no +@item console charset @tab CP437 @tab ASCII +@item network @tab no @tab yes +@item serial @tab yes @tab no +@item ATA/AHCI @tab yes @tab no +@item AT keyboard @tab yes @tab no +@item USB @tab N/A @tab yes +@item chainloader @tab yes @tab no +@item cpuid @tab no @tab no +@item hints @tab guess @tab no +@item PCI @tab no @tab no +@item badram @tab yes (*) @tab no +@item compression @tab configurable @tab no +@item exit @tab no @tab yes +@end multitable + +@node Platform-specific operations +@chapter Outline + +Some platforms have features which allows to implement +some commands useless or not implementable on others. + +Quick summary: + +Information retrieval: + +@itemize +@item mipsel-loongson: lsspd +@item mips-arc: lsdev +@item efi: lsefisystab, lssal, lsefimmap +@item i386-pc: lsapm +@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 acpi-enabled (i386-pc, i386-coreboot, i386-multiboot, *-efi): + acpi (override ACPI tables) +@item i386-pc: drivemap +@item i386-pc: sendkey +@end itemize + +Advanced operations for power users: +@itemize +@item x86: iorw (direct access to I/O ports) +@end itemize + +Miscelaneous: +@itemize +@item cmos (x86-*, ieee1275, mips-qemu_mips, mips-loongson): cmostest + (used on some laptops to check for special power-on key) +@item i386-pc: play +@end itemize + @node Supported kernels @chapter Supported boot targets @@ -3992,7 +4309,7 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel @end multitable @multitable @columnfractions .50 .22 .22 -@item @tab 32-bit EFI @tab 64-bit EFI +@item @tab ia32 EFI @tab amd64 EFI @item BIOS chainloading @tab no (1) @tab no (1) @item NTLDR @tab no (1) @tab no (1) @item Plan9 @tab no (1) @tab no (1) @@ -4018,7 +4335,7 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel @end multitable @multitable @columnfractions .50 .22 .22 -@item @tab IEEE1275 +@item @tab ia32 IEEE1275 @item BIOS chainloading @tab no (1) @item NTLDR @tab no (1) @item Plan9 @tab no (1) @@ -4052,7 +4369,8 @@ X86 support is summarised in the following table. ``Yes'' means that the kernel @item Requires ACPI @end enumerate -PowerPC and Sparc ports support only Linux. MIPS port supports Linux and multiboot2. +PowerPC, IA64 and Sparc64 ports support only Linux. MIPS port supports Linux +and multiboot2. @chapter Boot tests diff --git a/docs/man/grub-kbdcomp.h2m b/docs/man/grub-kbdcomp.h2m new file mode 100644 index 000000000..d81f9157e --- /dev/null +++ b/docs/man/grub-kbdcomp.h2m @@ -0,0 +1,10 @@ +[NAME] +grub-kbdcomp \- generate a GRUB keyboard layout file +[DESCRIPTION] +grub-kbdcomp processes a X keyboard layout description in +.BR keymaps (5) +format into a format that can be used by GRUB's +.B keymap +command. +[SEE ALSO] +.BR grub-mklayout (8) diff --git a/gentpl.py b/gentpl.py index af210a040..adbf6d492 100644 --- a/gentpl.py +++ b/gentpl.py @@ -1,4 +1,19 @@ #! /usr/bin/python +# GRUB -- GRand Unified Bootloader +# Copyright (C) 2010,2011 Free Software Foundation, Inc. +# +# GRUB is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# GRUB is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GRUB. If not, see . # # This is the python script used to generate Makefile.tpl @@ -47,7 +62,6 @@ GROUPS["terminfomodule"] = GRUB_PLATFORMS[:]; for i in GROUPS["terminfoinkernel"]: GROUPS["terminfomodule"].remove(i) # Miscelaneous groups schedulded to disappear in future -GROUPS["nosparc64"] = GRUB_PLATFORMS[:]; GROUPS["nosparc64"].remove("sparc64_ieee1275") GROUPS["i386_coreboot_multiboot_qemu"] = ["i386_coreboot", "i386_multiboot", "i386_qemu"] GROUPS["nopc"] = GRUB_PLATFORMS[:]; GROUPS["nopc"].remove("i386_pc") @@ -356,7 +370,7 @@ def first_time(snippet): def module(platform): r = set_canonical_name_suffix(".module") - r += gvar_add("noinst_PROGRAMS", "[+ name +].module") + r += gvar_add("platform_PROGRAMS", "[+ name +].module") r += gvar_add("MODULE_FILES", "[+ name +].module$(EXEEXT)") r += var_set(cname() + "_SOURCES", platform_sources(platform) + " ## platform sources") @@ -384,7 +398,7 @@ def module(platform): def kernel(platform): r = set_canonical_name_suffix(".exec") - r += gvar_add("noinst_PROGRAMS", "[+ name +].exec") + r += gvar_add("platform_PROGRAMS", "[+ name +].exec") r += var_set(cname() + "_SOURCES", platform_startup(platform)) r += var_add(cname() + "_SOURCES", platform_sources(platform)) r += var_set("nodist_" + cname() + "_SOURCES", platform_nodist_sources(platform) + " ## platform nodist sources") @@ -409,7 +423,7 @@ def kernel(platform): def image(platform): r = set_canonical_name_suffix(".image") - r += gvar_add("noinst_PROGRAMS", "[+ name +].image") + r += gvar_add("platform_PROGRAMS", "[+ name +].image") r += var_set(cname() + "_SOURCES", platform_sources(platform)) r += var_set("nodist_" + cname() + "_SOURCES", platform_nodist_sources(platform) + "## platform nodist sources") r += var_set(cname() + "_LDADD", platform_ldadd(platform)) @@ -466,7 +480,7 @@ def manpage(): r += gvar_add("man_MANS", "[+ name +].[+ mansection +]\n") r += rule("[+ name +].[+ mansection +]", "[+ name +]", """ chmod a+x [+ name +] -PATH=$(builddir):$$PATH $(HELP2MAN) --section=[+ mansection +] -i $(top_srcdir)/docs/man/[+ name +].h2m -o $@ [+ name +] +PATH=$(builddir):$$PATH pkgdatadir=$(builddir) $(HELP2MAN) --section=[+ mansection +] -i $(top_srcdir)/docs/man/[+ name +].h2m -o $@ [+ name +] """) r += gvar_add("CLEANFILES", "[+ name +].[+ mansection +]") r += "endif\n" diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 49651345a..585567d56 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -19,13 +19,13 @@ script = { }; script = { - installdir = noinst; + installdir = platform; name = gmodule.pl; common = gmodule.pl.in; }; script = { - installdir = noinst; + installdir = platform; name = gdb_grub; common = gdb_grub.in; }; @@ -113,7 +113,7 @@ kernel = { ieee1275 = kern/ieee1275/ieee1275.c; ieee1275 = kern/ieee1275/mmap.c; ieee1275 = kern/ieee1275/openfw.c; - ieee1275 = term/ieee1275/ofconsole.c; + ieee1275 = term/ieee1275/console.c; ieee1275 = kern/ieee1275/init.c; terminfoinkernel = term/terminfo.c; @@ -207,7 +207,6 @@ kernel = { emu = gnulib/progname.c; emu = gnulib/error.c; emu = kern/emu/cache_s.S; - emu = kern/emu/console.c; emu = kern/emu/hostdisk.c; emu = kern/emu/hostfs.c; emu = kern/emu/main.c; @@ -215,6 +214,7 @@ kernel = { emu = kern/emu/mm.c; emu = kern/emu/time.c; emu = kern/emu/cache.c; + emu = term/emu/console.c; videoinkernel = term/gfxterm.c; videoinkernel = font/font.c; @@ -348,7 +348,7 @@ image = { mips_qemu_mips_ldflags = '-static-libgcc -Wl,-Ttext,0x80100000'; mips_arc_ldflags = '-static-libgcc -Wl,-Ttext,0x8bc00000'; ldadd = '-lgcc'; - cflags = '-static-libgcc'; + cflags = '-Wno-unreachable-code -static-libgcc'; enable = mips; }; @@ -373,7 +373,7 @@ image = { i386_pc = boot/i386/pc/startup_raw.S; objcopyflags = '-O binary'; - ldflags = '-Wl,-Ttext,0x8200'; + ldflags = '$(TARGET_IMG_LDFLAGS) -Wl,-Ttext,0x8200'; enable = i386_pc; }; @@ -462,6 +462,12 @@ module = { enable = pci; }; +module = { + name = ehci; + common = bus/usb/ehci.c; + enable = pci; +}; + module = { name = pci; common = bus/pci.c; @@ -792,7 +798,7 @@ module = { module = { name = setpci; common = commands/setpci.c; - enable = x86; + enable = pci; }; module = { @@ -874,6 +880,11 @@ module = { common = disk/lvm.c; }; +module = { + name = ldm; + common = disk/ldm.c; +}; + module = { name = mdraid09; common = disk/mdraid_linux.c; @@ -885,8 +896,8 @@ module = { }; module = { - name = raid; - common = disk/raid.c; + name = diskfilter; + common = disk/diskfilter.c; }; module = { @@ -1014,6 +1025,21 @@ module = { common = fs/cpio.c; }; +module = { + name = cpio_be; + common = fs/cpio_be.c; +}; + +module = { + name = newc; + common = fs/newc.c; +}; + +module = { + name = odc; + common = fs/odc.c; +}; + module = { name = ext2; common = fs/ext2.c; @@ -1102,6 +1128,8 @@ module = { module = { name = squash4; common = fs/squash4.c; + cflags = '$(CFLAGS_POSIX) -Wno-undef'; + cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed -I$(srcdir)/lib/minilzo -DMINILZO_HAVE_CONFIG_H'; }; module = { @@ -1303,6 +1331,12 @@ module = { enable = i386_pc; }; +module = { + name = pxechain; + i386_pc = loader/i386/pc/pxechainloader.c; + enable = i386_pc; +}; + module = { name = multiboot2; cppflags = "-DGRUB_USE_MULTIBOOT2"; @@ -1418,7 +1452,7 @@ module = { extra_dist = script/yylex.l; extra_dist = script/parser.y; - cflags = '$(CFLAGS_POSIX)'; + cflags = '$(CFLAGS_POSIX) -Wno-redundant-decls'; cppflags = '$(CPPFLAGS_POSIX)'; }; @@ -1642,9 +1676,13 @@ module = { module = { name = net; common = net/net.c; + common = net/dns.c; common = net/bootp.c; common = net/ip.c; common = net/udp.c; + common = net/tcp.c; + common = net/icmp.c; + common = net/icmp6.c; common = net/ethernet.c; common = net/arp.c; common = net/netbuff.c; @@ -1655,6 +1693,11 @@ module = { common = net/tftp.c; }; +module = { + name = http; + common = net/http.c; +}; + module = { name = ofnet; common = net/drivers/ieee1275/ofnet.c; @@ -1694,13 +1737,14 @@ module = { common = lib/xzembed/xz_dec_lzma2.c; common = lib/xzembed/xz_dec_stream.c; cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/xzembed'; + cflags='-Wno-unreachable-code'; }; module = { name = lzopio; common = io/lzopio.c; common = lib/minilzo/minilzo.c; - cflags = '$(CFLAGS_POSIX) -Wno-undef'; + cflags = '$(CFLAGS_POSIX) -Wno-undef -Wno-redundant-decls -Wno-error'; cppflags = '-I$(srcdir)/lib/posix_wrap -I$(srcdir)/lib/minilzo -DMINILZO_HAVE_CONFIG_H'; }; @@ -1727,6 +1771,11 @@ module = { enable = videomodules; }; +module = { + name = priority_queue; + common = lib/priority_queue.c; +}; + module = { name = time; common = commands/time.c; diff --git a/grub-core/boot/i386/pc/lnxboot.S b/grub-core/boot/i386/pc/lnxboot.S index 4fe0df139..e4bc8b425 100644 --- a/grub-core/boot/i386/pc/lnxboot.S +++ b/grub-core/boot/i386/pc/lnxboot.S @@ -177,20 +177,21 @@ real_code_2: pushw %es popw %ds -#if GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4 < 0x200 - movl $0x200, %ecx - addl %ecx, %esi -#else - movl $(GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4), %ecx + movl $0x1000, %ecx addl $0x200, %esi -#endif movl $DATA_ADDR, %edi call LOCAL(move_memory) /* Check for multiboot signature. */ - cmpl $MULTIBOOT_HEADER_MAGIC, %ss:(DATA_ADDR + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART) + movl $DATA_ADDR, %edi +3: + movl %ss:(%edi), %eax + cmpl $MULTIBOOT_HEADER_MAGIC, %eax jz 1f + addl $4, %edi + cmpl $(DATA_ADDR + 0x1000), %edi + jne 3b movl (ramdisk_image - start), %esi movl (ramdisk_size - start), %ecx @@ -199,8 +200,9 @@ real_code_2: 1: + movl $(DATA_ADDR + 0x1000), %edi movl %ss:(DATA_ADDR + GRUB_DECOMPRESSOR_MACHINE_COMPRESSED_SIZE), %ecx - addl $((0x9000 - 0x8200) - (GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + 4)), %ecx + addl $GRUB_DECOMPRESSOR_I386_PC_MAX_DECOMPRESSOR_SIZE, %ecx 2: call LOCAL(move_memory) diff --git a/grub-core/boot/i386/pc/startup_raw.S b/grub-core/boot/i386/pc/startup_raw.S index 9e0f23d71..fdd408702 100644 --- a/grub-core/boot/i386/pc/startup_raw.S +++ b/grub-core/boot/i386/pc/startup_raw.S @@ -60,11 +60,13 @@ LOCAL(uncompressed_size): . = _start + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY reed_solomon_redundancy: .long 0 + . = _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_LENGTH + .short (LOCAL(reed_solomon_part) - _start) /* * This is the area for all of the special variables. */ - + . = _start + GRUB_DECOMPRESSOR_I386_PC_BOOT_DEVICE LOCAL(boot_dev): .byte 0xFF, 0xFF, 0xFF LOCAL(boot_drive): @@ -99,94 +101,23 @@ LOCAL (codestart): .code32 incl %eax + cld call grub_gate_a20 movl LOCAL(compressed_size), %edx - addl $(LOCAL(decompressor_end) - GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART - _start), %edx + addl $(LOCAL(decompressor_end) - LOCAL(reed_solomon_part)), %edx movl reed_solomon_redundancy, %ecx - leal _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART, %eax + leal LOCAL(reed_solomon_part), %eax + cld call EXT_C (grub_reed_solomon_recover) jmp post_reed_solomon +#include "../../../kern/i386/realmode.S" + #include .text - . = _start + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART -/* - * Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself). - * This uses the a.out kludge to load raw binary to the area starting at 1MB, - * and relocates itself after loaded. - */ - .p2align 2 /* force 4-byte alignment */ -multiboot_header: - /* magic */ - .long 0x1BADB002 - /* flags */ - .long (1 << 16) - /* checksum */ - .long -0x1BADB002 - (1 << 16) - /* header addr */ - .long multiboot_header - _start + 0x100000 + 0x200 - /* load addr */ - .long 0x100000 - /* load end addr */ - .long 0 - /* bss end addr */ - .long 0 - /* entry addr */ - .long multiboot_entry - _start + 0x100000 + 0x200 - -multiboot_entry: - .code32 - /* obtain the boot device */ - movl 12(%ebx), %edx - - movl $GRUB_MEMORY_MACHINE_PROT_STACK, %ebp - movl %ebp, %esp - - /* relocate the code */ - movl $(LOCAL(decompressor_end) + 0x200), %ecx - addl LOCAL(compressed_size) - _start + 0x100000 + 0x200, %ecx - movl $0x100000, %esi - movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %edi - cld - rep - movsb - /* jump to the real address */ - movl $multiboot_trampoline, %eax - jmp *%eax - -multiboot_trampoline: - /* fill the boot information */ - movl %edx, LOCAL(boot_dev) - shrl $24, %edx - /* enter the usual booting */ - call prot_to_real - .code16 - jmp LOCAL (codestart) - .code32 - -post_reed_solomon: - -#ifdef ENABLE_LZMA - movl $GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR, %edi - movl $LOCAL(decompressor_end), %esi - pushl %edi - movl LOCAL (uncompressed_size), %ecx - leal (%edi, %ecx), %ebx - call _LzmaDecodeA - /* _LzmaDecodeA clears DF, so no need to run cld */ - popl %esi -#endif - - movl LOCAL(boot_dev), %edx - movl $prot_to_real, %edi - movl $real_to_prot, %ecx - jmp *%esi - -#include "../../../kern/i386/realmode.S" - /* * grub_gate_a20(int on) * @@ -337,10 +268,87 @@ gate_a20_check_state: popl %ebx ret +LOCAL(reed_solomon_part): + +/* + * Support for booting GRUB from a Multiboot boot loader (e.g. GRUB itself). + * This uses the a.out kludge to load raw binary to the area starting at 1MB, + * and relocates itself after loaded. + */ + .p2align 2 /* force 4-byte alignment */ +multiboot_header: + /* magic */ + .long 0x1BADB002 + /* flags */ + .long (1 << 16) + /* checksum */ + .long -0x1BADB002 - (1 << 16) + /* header addr */ + .long multiboot_header - _start + 0x100000 + 0x200 + /* load addr */ + .long 0x100000 + /* load end addr */ + .long 0 + /* bss end addr */ + .long 0 + /* entry addr */ + .long multiboot_entry - _start + 0x100000 + 0x200 + +multiboot_entry: + .code32 + /* obtain the boot device */ + movl 12(%ebx), %edx + + movl $GRUB_MEMORY_MACHINE_PROT_STACK, %ebp + movl %ebp, %esp + + /* relocate the code */ + movl $(LOCAL(decompressor_end) + 0x200), %ecx + addl LOCAL(compressed_size) - _start + 0x100000 + 0x200, %ecx + movl $0x100000, %esi + movl $GRUB_BOOT_MACHINE_KERNEL_ADDR, %edi + cld + rep + movsb + /* jump to the real address */ + movl $multiboot_trampoline, %eax + jmp *%eax + +multiboot_trampoline: + /* fill the boot information */ + movl %edx, LOCAL(boot_dev) + shrl $24, %edx + /* enter the usual booting */ + call prot_to_real + .code16 + jmp LOCAL (codestart) + .code32 + +post_reed_solomon: + +#ifdef ENABLE_LZMA + movl $GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR, %edi + movl $LOCAL(decompressor_end), %esi + pushl %edi + movl LOCAL (uncompressed_size), %ecx + leal (%edi, %ecx), %ebx + /* Don't remove this push: it's an argument. */ + push %ecx + call _LzmaDecodeA + pop %ecx + /* _LzmaDecodeA clears DF, so no need to run cld */ + popl %esi +#endif + + movl LOCAL(boot_dev), %edx + movl $prot_to_real, %edi + movl $real_to_prot, %ecx + jmp *%esi + #ifdef ENABLE_LZMA #include "lzma_decode.S" #endif - .p2align 2 + .p2align 4 LOCAL(decompressor_end): diff --git a/grub-core/bus/cs5536.c b/grub-core/bus/cs5536.c index 1aae7852e..9e7796ea1 100644 --- a/grub-core/bus/cs5536.c +++ b/grub-core/bus/cs5536.c @@ -97,8 +97,6 @@ grub_cs5536_smbus_wait (grub_port_t smbbase) if (grub_get_time_ms () > start + 40) return grub_error (GRUB_ERR_IO, "SM stalled"); } - - return GRUB_ERR_NONE; } grub_err_t diff --git a/grub-core/bus/pci.c b/grub-core/bus/pci.c index f007ec33a..ad85738df 100644 --- a/grub-core/bus/pci.c +++ b/grub-core/bus/pci.c @@ -36,6 +36,16 @@ grub_memalign_dma32 (grub_size_t align, grub_size_t size) align = 64; size = ALIGN_UP (size, align); ret = grub_memalign (align, size); +#if GRUB_CPU_SIZEOF_VOID_P == 8 + if ((grub_addr_t) ret >> 32) + { + /* Shouldn't happend since the only platform in this case is + x86_64-efi and it skips any regions > 4GiB because + of EFI bugs anyway. */ + grub_error (GRUB_ERR_BUG, "allocation outside 32-bit range"); + return 0; + } +#endif if (!ret) return 0; grub_arch_sync_dma_caches (ret, size); diff --git a/grub-core/bus/usb/ehci.c b/grub-core/bus/usb/ehci.c new file mode 100644 index 000000000..5e3a72356 --- /dev/null +++ b/grub-core/bus/usb/ehci.c @@ -0,0 +1,1856 @@ +/* ehci.c - EHCI Support. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +/* This simple GRUB implementation of EHCI driver: + * - assumes no IRQ + * - is not supporting isochronous transfers (iTD, siTD) + * - is not supporting interrupt transfers + */ + +#define GRUB_EHCI_PCI_SBRN_REG 0x60 + +/* Capability registers offsets */ +enum +{ + GRUB_EHCI_EHCC_CAPLEN = 0x00, /* byte */ + GRUB_EHCI_EHCC_VERSION = 0x02, /* word */ + GRUB_EHCI_EHCC_SPARAMS = 0x04, /* dword */ + GRUB_EHCI_EHCC_CPARAMS = 0x08, /* dword */ + GRUB_EHCI_EHCC_PROUTE = 0x0c, /* 60 bits */ +}; + +#define GRUB_EHCI_EECP_MASK (0xff << 8) +#define GRUB_EHCI_EECP_SHIFT 8 + +#define GRUB_EHCI_ADDR_MEM_MASK (~0xff) +#define GRUB_EHCI_POINTER_MASK (~0x1f) + +/* Capability register SPARAMS bits */ +enum +{ + GRUB_EHCI_SPARAMS_N_PORTS = (0xf << 0), + GRUB_EHCI_SPARAMS_PPC = (1 << 4), /* Power port control */ + GRUB_EHCI_SPARAMS_PRR = (1 << 7), /* Port routing rules */ + GRUB_EHCI_SPARAMS_N_PCC = (0xf << 8), /* No of ports per comp. */ + GRUB_EHCI_SPARAMS_NCC = (0xf << 12), /* No of com. controllers */ + GRUB_EHCI_SPARAMS_P_IND = (1 << 16), /* Port indicators present */ + GRUB_EHCI_SPARAMS_DEBUG_P = (0xf << 20) /* Debug port */ +}; + +#define GRUB_EHCI_MAX_N_PORTS 15 /* Max. number of ports */ + +/* Capability register CPARAMS bits */ +enum +{ + GRUB_EHCI_CPARAMS_64BIT = (1 << 0), + GRUB_EHCI_CPARAMS_PROG_FRAMELIST = (1 << 1), + GRUB_EHCI_CPARAMS_PARK_CAP = (1 << 2) +}; + +#define GRUB_EHCI_N_FRAMELIST 1024 +#define GRUB_EHCI_N_QH 256 +#define GRUB_EHCI_N_TD 640 + +#define GRUB_EHCI_QH_EMPTY 1 + +/* USBLEGSUP bits and related OS OWNED byte offset */ +enum +{ + GRUB_EHCI_BIOS_OWNED = (1 << 16), + GRUB_EHCI_OS_OWNED = (1 << 24) +}; + +/* Operational registers offsets */ +enum +{ + GRUB_EHCI_COMMAND = 0x00, + GRUB_EHCI_STATUS = 0x04, + GRUB_EHCI_INTERRUPT = 0x08, + GRUB_EHCI_FRAME_INDEX = 0x0c, + GRUB_EHCI_64BIT_SEL = 0x10, + GRUB_EHCI_FL_BASE = 0x14, + GRUB_EHCI_CUR_AL_ADDR = 0x18, + GRUB_EHCI_CONFIG_FLAG = 0x40, + GRUB_EHCI_PORT_STAT_CMD = 0x44 +}; + +/* Operational register COMMAND bits */ +enum +{ + GRUB_EHCI_CMD_RUNSTOP = (1 << 0), + GRUB_EHCI_CMD_HC_RESET = (1 << 1), + GRUB_EHCI_CMD_FL_SIZE = (3 << 2), + GRUB_EHCI_CMD_PS_ENABL = (1 << 4), + GRUB_EHCI_CMD_AS_ENABL = (1 << 5), + GRUB_EHCI_CMD_AS_ADV_D = (1 << 6), + GRUB_EHCI_CMD_L_HC_RES = (1 << 7), + GRUB_EHCI_CMD_AS_PARKM = (3 << 8), + GRUB_EHCI_CMD_AS_PARKE = (1 << 11), + GRUB_EHCI_CMD_INT_THRS = (0xff << 16) +}; + +/* Operational register STATUS bits */ +enum +{ + GRUB_EHCI_ST_INTERRUPT = (1 << 0), + GRUB_EHCI_ST_ERROR_INT = (1 << 1), + GRUB_EHCI_ST_PORT_CHG = (1 << 2), + GRUB_EHCI_ST_FL_ROLLOVR = (1 << 3), + GRUB_EHCI_ST_HS_ERROR = (1 << 4), + GRUB_EHCI_ST_AS_ADVANCE = (1 << 5), + GRUB_EHCI_ST_HC_HALTED = (1 << 12), + GRUB_EHCI_ST_RECLAM = (1 << 13), + GRUB_EHCI_ST_PS_STATUS = (1 << 14), + GRUB_EHCI_ST_AS_STATUS = (1 << 15) +}; + +/* Operational register PORT_STAT_CMD bits */ +enum +{ + GRUB_EHCI_PORT_CONNECT = (1 << 0), + GRUB_EHCI_PORT_CONNECT_CH = (1 << 1), + GRUB_EHCI_PORT_ENABLED = (1 << 2), + GRUB_EHCI_PORT_ENABLED_CH = (1 << 3), + GRUB_EHCI_PORT_OVERCUR = (1 << 4), + GRUB_EHCI_PORT_OVERCUR_CH = (1 << 5), + GRUB_EHCI_PORT_RESUME = (1 << 6), + GRUB_EHCI_PORT_SUSPEND = (1 << 7), + GRUB_EHCI_PORT_RESET = (1 << 8), + GRUB_EHCI_PORT_LINE_STAT = (3 << 10), + GRUB_EHCI_PORT_POWER = (1 << 12), + GRUB_EHCI_PORT_OWNER = (1 << 13), + GRUB_EHCI_PORT_INDICATOR = (3 << 14), + GRUB_EHCI_PORT_TEST = (0xf << 16), + GRUB_EHCI_PORT_WON_CONN_E = (1 << 20), + GRUB_EHCI_PORT_WON_DISC_E = (1 << 21), + GRUB_EHCI_PORT_WON_OVER_E = (1 << 22), + + GRUB_EHCI_PORT_LINE_SE0 = (0 << 10), + GRUB_EHCI_PORT_LINE_K = (1 << 10), + GRUB_EHCI_PORT_LINE_J = (2 << 10), + GRUB_EHCI_PORT_LINE_UNDEF = (3 << 10), + GRUB_EHCI_PORT_LINE_LOWSP = GRUB_EHCI_PORT_LINE_K, /* K state means low speed */ + GRUB_EHCI_PORT_WMASK = ~(GRUB_EHCI_PORT_CONNECT_CH + | GRUB_EHCI_PORT_ENABLED_CH + | GRUB_EHCI_PORT_OVERCUR_CH) +}; + +/* Operational register CONFIGFLAGS bits */ +enum +{ + GRUB_EHCI_CF_EHCI_OWNER = (1 << 0) +}; + +/* Queue Head & Transfer Descriptor constants */ +#define GRUB_EHCI_HPTR_OFF 5 /* Horiz. pointer bit offset */ +enum +{ + GRUB_EHCI_HPTR_TYPE_MASK = (3 << 1), + GRUB_EHCI_HPTR_TYPE_ITD = (0 << 1), + GRUB_EHCI_HPTR_TYPE_QH = (1 << 1), + GRUB_EHCI_HPTR_TYPE_SITD = (2 << 1), + GRUB_EHCI_HPTR_TYPE_FSTN = (3 << 1) +}; + +enum +{ + GRUB_EHCI_C = (1 << 27), + GRUB_EHCI_MAXPLEN_MASK = (0x7ff << 16), + GRUB_EHCI_H = (1 << 15), + GRUB_EHCI_DTC = (1 << 14), + GRUB_EHCI_SPEED_MASK = (3 << 12), + GRUB_EHCI_SPEED_FULL = (0 << 12), + GRUB_EHCI_SPEED_LOW = (1 << 12), + GRUB_EHCI_SPEED_HIGH = (2 << 12), + GRUB_EHCI_SPEED_RESERVED = (3 << 12), + GRUB_EHCI_EP_NUM_MASK = (0xf << 8), + GRUB_EHCI_DEVADDR_MASK = 0x7f, + GRUB_EHCI_TARGET_MASK = (GRUB_EHCI_EP_NUM_MASK | GRUB_EHCI_DEVADDR_MASK) +}; + +enum +{ + GRUB_EHCI_MAXPLEN_OFF = 16, + GRUB_EHCI_SPEED_OFF = 12, + GRUB_EHCI_EP_NUM_OFF = 8 +}; + +enum +{ + GRUB_EHCI_MULT_MASK = (3 << 30), + GRUB_EHCI_MULT_RESERVED = (0 << 30), + GRUB_EHCI_MULT_ONE = (0 << 30), + GRUB_EHCI_MULT_TWO = (0 << 30), + GRUB_EHCI_MULT_THREE = (0 << 30), + GRUB_EHCI_DEVPORT_MASK = (0x7f << 23), + GRUB_EHCI_HUBADDR_MASK = (0x7f << 16) +}; + +enum +{ + GRUB_EHCI_MULT_OFF = 30, + GRUB_EHCI_DEVPORT_OFF = 23, + GRUB_EHCI_HUBADDR_OFF = 16 +}; + +#define GRUB_EHCI_TERMINATE (1<<0) + +#define GRUB_EHCI_TOGGLE (1<<31) + +enum +{ + GRUB_EHCI_TOTAL_MASK = (0x7fff << 16), + GRUB_EHCI_CERR_MASK = (3 << 10), + GRUB_EHCI_CERR_0 = (0 << 10), + GRUB_EHCI_CERR_1 = (1 << 10), + GRUB_EHCI_CERR_2 = (2 << 10), + GRUB_EHCI_CERR_3 = (3 << 10), + GRUB_EHCI_PIDCODE_OUT = (0 << 8), + GRUB_EHCI_PIDCODE_IN = (1 << 8), + GRUB_EHCI_PIDCODE_SETUP = (2 << 8), + GRUB_EHCI_STATUS_MASK = 0xff, + GRUB_EHCI_STATUS_ACTIVE = (1 << 7), + GRUB_EHCI_STATUS_HALTED = (1 << 6), + GRUB_EHCI_STATUS_BUFERR = (1 << 5), + GRUB_EHCI_STATUS_BABBLE = (1 << 4), + GRUB_EHCI_STATUS_TRANERR = (1 << 3), + GRUB_EHCI_STATUS_MISSDMF = (1 << 2), + GRUB_EHCI_STATUS_SPLITST = (1 << 1), + GRUB_EHCI_STATUS_PINGERR = (1 << 0) +}; + +enum +{ + GRUB_EHCI_TOTAL_OFF = 16, + GRUB_EHCI_CERR_OFF = 10 +}; + +#define GRUB_EHCI_BUFPTR_MASK (0xfffff<<12) +#define GRUB_EHCI_QHTDPTR_MASK 0xffffffe0 + +#define GRUB_EHCI_TD_BUF_PAGES 5 + +#define GRUB_EHCI_BUFPAGELEN 0x1000 +#define GRUB_EHCI_MAXBUFLEN 0x5000 + +struct grub_ehci_td; +struct grub_ehci_qh; +typedef volatile struct grub_ehci_td *grub_ehci_td_t; +typedef volatile struct grub_ehci_qh *grub_ehci_qh_t; + +/* EHCI Isochronous Transfer Descriptor */ +/* Currently not supported */ + +/* EHCI Split Transaction Isochronous Transfer Descriptor */ +/* Currently not supported */ + +/* EHCI Queue Element Transfer Descriptor (qTD) */ +/* Align to 32-byte boundaries */ +struct grub_ehci_td +{ + /* EHCI HW part */ + grub_uint32_t next_td; /* Pointer to next qTD */ + grub_uint32_t alt_next_td; /* Pointer to alternate next qTD */ + grub_uint32_t token; /* Toggle, Len, Interrupt, Page, Error, PID, Status */ + grub_uint32_t buffer_page[GRUB_EHCI_TD_BUF_PAGES]; /* Buffer pointer (+ cur. offset in page 0 */ + /* 64-bits part */ + grub_uint32_t buffer_page_high[GRUB_EHCI_TD_BUF_PAGES]; + /* EHCI driver part */ + grub_uint32_t link_td; /* pointer to next free/chained TD */ + grub_uint32_t size; + grub_uint32_t pad[1]; /* padding to some multiple of 32 bytes */ +}; + +/* EHCI Queue Head */ +/* Align to 32-byte boundaries */ +/* QH allocation is made in the similar/same way as in OHCI driver, + * because unlninking QH from the Asynchronous list is not so + * trivial as on UHCI (at least it is time consuming) */ +struct grub_ehci_qh +{ + /* EHCI HW part */ + grub_uint32_t qh_hptr; /* Horiz. pointer & Terminate */ + grub_uint32_t ep_char; /* EP characteristics */ + grub_uint32_t ep_cap; /* EP capabilities */ + grub_uint32_t td_current; /* current TD link pointer */ + struct grub_ehci_td td_overlay; /* TD overlay area = 64 bytes */ + /* EHCI driver part */ + grub_uint32_t pad[4]; /* padding to some multiple of 32 bytes */ +}; + +/* EHCI Periodic Frame Span Traversal Node */ +/* Currently not supported */ + +struct grub_ehci +{ + volatile grub_uint32_t *iobase_ehcc; /* Capability registers */ + volatile grub_uint32_t *iobase; /* Operational registers */ + struct grub_pci_dma_chunk *framelist_chunk; /* Currently not used */ + volatile grub_uint32_t *framelist_virt; + grub_uint32_t framelist_phys; + struct grub_pci_dma_chunk *qh_chunk; /* GRUB_EHCI_N_QH Queue Heads */ + grub_ehci_qh_t qh_virt; + grub_uint32_t qh_phys; + struct grub_pci_dma_chunk *td_chunk; /* GRUB_EHCI_N_TD Transfer Descriptors */ + grub_ehci_td_t td_virt; + grub_uint32_t td_phys; + grub_ehci_td_t tdfree_virt; /* Free Transfer Descriptors */ + int flag64; + grub_uint32_t reset; /* bits 1-15 are flags if port was reset from connected time or not */ + struct grub_ehci *next; +}; + +static struct grub_ehci *ehci; + +/* EHCC registers access functions */ +static inline grub_uint32_t +grub_ehci_ehcc_read32 (struct grub_ehci *e, grub_uint32_t addr) +{ + return + grub_le_to_cpu32 (*((volatile grub_uint32_t *) e->iobase_ehcc + + (addr / sizeof (grub_uint32_t)))); +} + +static inline grub_uint16_t +grub_ehci_ehcc_read16 (struct grub_ehci *e, grub_uint32_t addr) +{ + return + grub_le_to_cpu16 (*((volatile grub_uint16_t *) e->iobase_ehcc + + (addr / sizeof (grub_uint16_t)))); +} + +static inline grub_uint8_t +grub_ehci_ehcc_read8 (struct grub_ehci *e, grub_uint32_t addr) +{ + return *((volatile grub_uint8_t *) e->iobase_ehcc + addr); +} + +/* Operational registers access functions */ +static inline grub_uint32_t +grub_ehci_oper_read32 (struct grub_ehci *e, grub_uint32_t addr) +{ + return + grub_le_to_cpu32 (* + ((volatile grub_uint32_t *) e->iobase + + (addr / sizeof (grub_uint32_t)))); +} + +static inline void +grub_ehci_oper_write32 (struct grub_ehci *e, grub_uint32_t addr, + grub_uint32_t value) +{ + *((volatile grub_uint32_t *) e->iobase + (addr / sizeof (grub_uint32_t))) = + grub_cpu_to_le32 (value); +} + +static inline grub_uint32_t +grub_ehci_port_read (struct grub_ehci *e, grub_uint32_t port) +{ + return grub_ehci_oper_read32 (e, GRUB_EHCI_PORT_STAT_CMD + port * 4); +} + +static inline void +grub_ehci_port_resbits (struct grub_ehci *e, grub_uint32_t port, + grub_uint32_t bits) +{ + grub_ehci_oper_write32 (e, GRUB_EHCI_PORT_STAT_CMD + port * 4, + grub_ehci_port_read (e, + port) & GRUB_EHCI_PORT_WMASK & + ~(bits)); + grub_ehci_port_read (e, port); +} + +static inline void +grub_ehci_port_setbits (struct grub_ehci *e, grub_uint32_t port, + grub_uint32_t bits) +{ + grub_ehci_oper_write32 (e, GRUB_EHCI_PORT_STAT_CMD + port * 4, + (grub_ehci_port_read (e, port) & + GRUB_EHCI_PORT_WMASK) | bits); + grub_ehci_port_read (e, port); +} + +/* Halt if EHCI HC not halted */ +static grub_usb_err_t +grub_ehci_halt (struct grub_ehci *e) +{ + grub_uint64_t maxtime; + + if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) & GRUB_EHCI_ST_HC_HALTED) == 0) /* EHCI is not halted */ + { + /* Halt EHCI */ + grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND, + ~GRUB_EHCI_CMD_RUNSTOP + & grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND)); + /* Ensure command is written */ + grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND); + maxtime = grub_get_time_ms () + 1000; /* Fix: Should be 2ms ! */ + while (((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) + & GRUB_EHCI_ST_HC_HALTED) == 0) + && (grub_get_time_ms () < maxtime)); + if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) + & GRUB_EHCI_ST_HC_HALTED) == 0) + return GRUB_USB_ERR_TIMEOUT; + } + + return GRUB_USB_ERR_NONE; +} + +/* EHCI HC reset */ +static grub_usb_err_t +grub_ehci_reset (struct grub_ehci *e) +{ + grub_uint64_t maxtime; + + grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND, + GRUB_EHCI_CMD_HC_RESET + | grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND)); + /* Ensure command is written */ + grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND); + /* XXX: How long time could take reset of HC ? */ + maxtime = grub_get_time_ms () + 1000; + while (((grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND) + & GRUB_EHCI_CMD_HC_RESET) != 0) + && (grub_get_time_ms () < maxtime)); + if ((grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND) + & GRUB_EHCI_CMD_HC_RESET) != 0) + return GRUB_USB_ERR_TIMEOUT; + + return GRUB_USB_ERR_NONE; +} + +/* PCI iteration function... */ +static int NESTED_FUNC_ATTR +grub_ehci_pci_iter (grub_pci_device_t dev, + grub_pci_id_t pciid __attribute__ ((unused))) +{ + grub_uint8_t release; + grub_uint32_t class_code; + grub_uint32_t interf; + grub_uint32_t subclass; + grub_uint32_t class; + grub_uint32_t base, base_h; + struct grub_ehci *e; + grub_uint32_t eecp_offset; + grub_uint32_t fp; + int i; + grub_uint32_t usblegsup = 0; + grub_uint64_t maxtime; + grub_uint32_t n_ports; + grub_uint8_t caplen; + + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: begin\n"); + + if (pciid == GRUB_CS5536_PCIID) + { + grub_uint64_t basereg; + + basereg = grub_cs5536_read_msr (dev, GRUB_CS5536_MSR_USB_EHCI_BASE); + if (!(basereg & GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE)) + { + /* Shouldn't happen. */ + grub_dprintf ("ehci", "No EHCI address is assigned\n"); + return 0; + } + base = (basereg & GRUB_CS5536_MSR_USB_BASE_ADDR_MASK); + basereg |= GRUB_CS5536_MSR_USB_BASE_BUS_MASTER; + basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_ENABLED; + basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_STATUS; + basereg &= ~GRUB_CS5536_MSR_USB_BASE_SMI_ENABLE; + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_USB_EHCI_BASE, basereg); + } + else + { + grub_pci_address_t addr; + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); + class_code = grub_pci_read (addr) >> 8; + interf = class_code & 0xFF; + subclass = (class_code >> 8) & 0xFF; + class = class_code >> 16; + + /* If this is not an EHCI controller, just return. */ + if (class != 0x0c || subclass != 0x03 || interf != 0x20) + return 0; + + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: class OK\n"); + + /* Check Serial Bus Release Number */ + addr = grub_pci_make_address (dev, GRUB_EHCI_PCI_SBRN_REG); + release = grub_pci_read_byte (addr); + if (release != 0x20) + { + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: Wrong SBRN: %0x\n", + release); + return 0; + } + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: bus rev. num. OK\n"); + + /* Determine EHCI EHCC registers base address. */ + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); + base = grub_pci_read (addr); + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG1); + base_h = grub_pci_read (addr); + /* Stop if registers are mapped above 4G - GRUB does not currently + * work with registers mapped above 4G */ + if (((base & GRUB_PCI_ADDR_MEM_TYPE_MASK) != GRUB_PCI_ADDR_MEM_TYPE_32) + && (base_h != 0)) + { + grub_dprintf ("ehci", + "EHCI grub_ehci_pci_iter: registers above 4G are not supported\n"); + return 0; + } + + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: 32-bit EHCI OK\n"); + } + + /* Allocate memory for the controller and fill basic values. */ + e = grub_zalloc (sizeof (*e)); + if (!e) + return 1; + e->framelist_chunk = NULL; + e->td_chunk = NULL; + e->qh_chunk = NULL; + e->iobase_ehcc = grub_pci_device_map_range (dev, + (base & GRUB_EHCI_ADDR_MEM_MASK), + 0x100); + + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: iobase of EHCC: %08x\n", + (base & GRUB_EHCI_ADDR_MEM_MASK)); + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CAPLEN: %02x\n", + grub_ehci_ehcc_read8 (e, GRUB_EHCI_EHCC_CAPLEN)); + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: VERSION: %04x\n", + grub_ehci_ehcc_read16 (e, GRUB_EHCI_EHCC_VERSION)); + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: SPARAMS: %08x\n", + grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_SPARAMS)); + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CPARAMS: %08x\n", + grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_CPARAMS)); + + /* Determine base address of EHCI operational registers */ + caplen = grub_ehci_ehcc_read8 (e, GRUB_EHCI_EHCC_CAPLEN); +#ifndef GRUB_HAVE_UNALIGNED_ACCESS + if (caplen & (sizeof (grub_uint32_t) - 1)) + { + grub_dprintf ("ehci", "Unaligned caplen\n"); + return 0; + } + e->iobase = ((volatile grub_uint32_t *) e->iobase_ehcc + + (caplen / sizeof (grub_uint32_t))); +#else + e->iobase = (volatile grub_uint32_t *) + ((grub_uint8_t *) e->iobase_ehcc + caplen); +#endif + + grub_dprintf ("ehci", + "EHCI grub_ehci_pci_iter: iobase of oper. regs: %08x\n", + (base & GRUB_EHCI_ADDR_MEM_MASK) + caplen); + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: COMMAND: %08x\n", + grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND)); + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: STATUS: %08x\n", + grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)); + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: INTERRUPT: %08x\n", + grub_ehci_oper_read32 (e, GRUB_EHCI_INTERRUPT)); + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: FRAME_INDEX: %08x\n", + grub_ehci_oper_read32 (e, GRUB_EHCI_FRAME_INDEX)); + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: FL_BASE: %08x\n", + grub_ehci_oper_read32 (e, GRUB_EHCI_FL_BASE)); + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CUR_AL_ADDR: %08x\n", + grub_ehci_oper_read32 (e, GRUB_EHCI_CUR_AL_ADDR)); + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CONFIG_FLAG: %08x\n", + grub_ehci_oper_read32 (e, GRUB_EHCI_CONFIG_FLAG)); + + /* Is there EECP ? */ + eecp_offset = (grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_CPARAMS) + & GRUB_EHCI_EECP_MASK) >> GRUB_EHCI_EECP_SHIFT; + + /* Check format of data structures requested by EHCI */ + /* XXX: In fact it is not used at any place, it is prepared for future + * This implementation uses 32-bits pointers only */ + e->flag64 = ((grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_CPARAMS) + & GRUB_EHCI_CPARAMS_64BIT) != 0); + + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: flag64=%d\n", e->flag64); + + /* Reserve a page for the frame list - it is accurate for max. + * possible size of framelist. But currently it is not used. */ + e->framelist_chunk = grub_memalign_dma32 (4096, 4096); + if (!e->framelist_chunk) + goto fail; + e->framelist_virt = grub_dma_get_virt (e->framelist_chunk); + e->framelist_phys = grub_dma_get_phys (e->framelist_chunk); + grub_memset ((void *) e->framelist_virt, 0, 4096); + + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: framelist mem=%p. OK\n", + e->framelist_virt); + + /* Allocate memory for the QHs and register it in "e". */ + e->qh_chunk = grub_memalign_dma32 (4096, + sizeof (struct grub_ehci_qh) * + GRUB_EHCI_N_QH); + if (!e->qh_chunk) + goto fail; + e->qh_virt = (grub_ehci_qh_t) grub_dma_get_virt (e->qh_chunk); + e->qh_phys = grub_dma_get_phys (e->qh_chunk); + grub_memset ((void *) e->qh_virt, 0, + sizeof (struct grub_ehci_qh) * GRUB_EHCI_N_QH); + + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: QH mem=%p. OK\n", + e->qh_virt); + + /* Allocate memory for the TDs and register it in "e". */ + e->td_chunk = grub_memalign_dma32 (4096, + sizeof (struct grub_ehci_td) * + GRUB_EHCI_N_TD); + if (!e->td_chunk) + goto fail; + e->td_virt = (grub_ehci_td_t) grub_dma_get_virt (e->td_chunk); + e->td_phys = grub_dma_get_phys (e->td_chunk); + grub_memset ((void *) e->td_virt, 0, + sizeof (struct grub_ehci_td) * GRUB_EHCI_N_TD); + + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: TD mem=%p. OK\n", + e->td_virt); + + /* Setup all frame list pointers. Since no isochronous transfers + are supported, they all point to the (same!) queue + head with index 0. */ + fp = grub_cpu_to_le32 ((e->qh_phys & GRUB_EHCI_POINTER_MASK) + | GRUB_EHCI_HPTR_TYPE_QH); + for (i = 0; i < GRUB_EHCI_N_FRAMELIST; i++) + e->framelist_virt[i] = fp; + /* Prepare chain of all TDs and set Terminate in all TDs */ + for (i = 0; i < (GRUB_EHCI_N_TD - 1); i++) + { + e->td_virt[i].link_td = e->td_phys + (i + 1) * sizeof (struct grub_ehci_td); + e->td_virt[i].next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); + e->td_virt[i].alt_next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); + } + e->td_virt[GRUB_EHCI_N_TD - 1].next_td = + grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); + e->td_virt[GRUB_EHCI_N_TD - 1].alt_next_td = + 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].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); + /* Also set Halted bit in token */ + e->qh_virt[0].td_overlay.token = grub_cpu_to_le32 (GRUB_EHCI_STATUS_HALTED); + /* Set the H bit in first QH used for AL */ + e->qh_virt[1].ep_char = grub_cpu_to_le32 (GRUB_EHCI_H); + /* Set Terminate into TD in rest of QHs and set horizontal link + * pointer to itself - these QHs will be used for asynchronous + * schedule and they should have valid value in horiz. link */ + for (i = 1; i < GRUB_EHCI_N_QH; i++) + { + e->qh_virt[i].qh_hptr = + grub_cpu_to_le32 ((grub_dma_virt2phys (&e->qh_virt[i], + e->qh_chunk) & + GRUB_EHCI_POINTER_MASK) | GRUB_EHCI_HPTR_TYPE_QH); + e->qh_virt[i].td_overlay.next_td = + grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); + e->qh_virt[i].td_overlay.alt_next_td = + grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); + /* Also set Halted bit in token */ + e->qh_virt[i].td_overlay.token = + grub_cpu_to_le32 (GRUB_EHCI_STATUS_HALTED); + } + + /* Note: QH 0 and QH 1 are reserved and must not be used anywhere. + * QH 0 is used as empty QH for framelist + * QH 1 is used as starting empty QH for asynchronous schedule + * QH 1 must exist at any time because at least one QH linked to + * itself must exist in asynchronous schedule + * QH 1 has the H flag set to one */ + + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: QH/TD init. OK\n"); + + /* Determine and change ownership. */ + /* EECP offset valid in HCCPARAMS */ + /* Ownership can be changed via EECP only */ + if (pciid != GRUB_CS5536_PCIID && eecp_offset >= 0x40) + { + grub_pci_address_t pciaddr_eecp; + pciaddr_eecp = grub_pci_make_address (dev, eecp_offset); + + usblegsup = grub_pci_read (pciaddr_eecp); + if (usblegsup & GRUB_EHCI_BIOS_OWNED) + { + grub_dprintf ("ehci", + "EHCI grub_ehci_pci_iter: EHCI owned by: BIOS\n"); + /* Ownership change - set OS_OWNED bit */ + grub_pci_write (pciaddr_eecp, usblegsup | GRUB_EHCI_OS_OWNED); + /* Ensure PCI register is written */ + grub_pci_read (pciaddr_eecp); + + /* Wait for finish of ownership change, EHCI specification + * doesn't say how long it can take... */ + maxtime = grub_get_time_ms () + 1000; + while ((grub_pci_read (pciaddr_eecp) & GRUB_EHCI_BIOS_OWNED) + && (grub_get_time_ms () < maxtime)); + if (grub_pci_read (pciaddr_eecp) & GRUB_EHCI_BIOS_OWNED) + { + grub_dprintf ("ehci", + "EHCI grub_ehci_pci_iter: EHCI change ownership timeout"); + /* Change ownership in "hard way" - reset BIOS ownership */ + grub_pci_write (pciaddr_eecp, GRUB_EHCI_OS_OWNED); + /* Ensure PCI register is written */ + grub_pci_read (pciaddr_eecp); + /* Disable SMI. */ + pciaddr_eecp = grub_pci_make_address (dev, eecp_offset + 4); + grub_pci_write (pciaddr_eecp, 0); + /* Ensure PCI register is written */ + grub_pci_read (pciaddr_eecp); + } + } + else if (usblegsup & GRUB_EHCI_OS_OWNED) + /* XXX: What to do in this case - nothing ? Can it happen ? */ + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: EHCI owned by: OS\n"); + else + { + grub_dprintf ("ehci", + "EHCI grub_ehci_pci_iter: EHCI owned by: NONE\n"); + /* XXX: What to do in this case ? Can it happen ? + * Is code below correct ? */ + /* Ownership change - set OS_OWNED bit */ + grub_pci_write (pciaddr_eecp, GRUB_EHCI_OS_OWNED); + /* Ensure PCI register is written */ + grub_pci_read (pciaddr_eecp); + /* Disable SMI, just to be sure. */ + pciaddr_eecp = grub_pci_make_address (dev, eecp_offset + 4); + grub_pci_write (pciaddr_eecp, 0); + /* Ensure PCI register is written */ + grub_pci_read (pciaddr_eecp); + } + } + + grub_dprintf ("ehci", "inithw: EHCI grub_ehci_pci_iter: ownership OK\n"); + + /* Now we can setup EHCI (maybe...) */ + + /* Check if EHCI is halted and halt it if not */ + if (grub_ehci_halt (e) != GRUB_USB_ERR_NONE) + { + grub_error (GRUB_ERR_TIMEOUT, + "EHCI grub_ehci_pci_iter: EHCI halt timeout"); + goto fail; + } + + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: halted OK\n"); + + /* Reset EHCI */ + if (grub_ehci_reset (e) != GRUB_USB_ERR_NONE) + { + grub_error (GRUB_ERR_TIMEOUT, + "EHCI grub_ehci_pci_iter: EHCI reset timeout"); + goto fail; + } + + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: reset OK\n"); + + /* Setup list address registers */ + grub_ehci_oper_write32 (e, GRUB_EHCI_FL_BASE, e->framelist_phys); + grub_ehci_oper_write32 (e, GRUB_EHCI_CUR_AL_ADDR, + grub_dma_virt2phys (&e->qh_virt[1], + e->qh_chunk)); + + /* 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 */ + grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND, + GRUB_EHCI_CMD_AS_ENABL + | grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND)); + + /* Now should be possible to power-up and enumerate ports etc. */ + if ((grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_SPARAMS) + & GRUB_EHCI_SPARAMS_PPC) != 0) + { /* EHCI has port powering control */ + /* Power on all ports */ + n_ports = grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_SPARAMS) + & GRUB_EHCI_SPARAMS_N_PORTS; + for (i = 0; i < (int) n_ports; i++) + grub_ehci_oper_write32 (e, GRUB_EHCI_PORT_STAT_CMD + i * 4, + GRUB_EHCI_PORT_POWER + | grub_ehci_oper_read32 (e, + GRUB_EHCI_PORT_STAT_CMD + + i * 4)); + } + + /* Ensure all commands are written */ + grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND); + + /* Enable EHCI */ + grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND, + GRUB_EHCI_CMD_RUNSTOP + | grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND)); + + /* Ensure command is written */ + grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND); + + /* Link to ehci now that initialisation is successful. */ + e->next = ehci; + ehci = e; + + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: OK at all\n"); + + grub_dprintf ("ehci", + "EHCI grub_ehci_pci_iter: iobase of oper. regs: %08x\n", + (base & GRUB_EHCI_ADDR_MEM_MASK)); + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: COMMAND: %08x\n", + grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND)); + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: STATUS: %08x\n", + grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)); + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: INTERRUPT: %08x\n", + grub_ehci_oper_read32 (e, GRUB_EHCI_INTERRUPT)); + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: FRAME_INDEX: %08x\n", + grub_ehci_oper_read32 (e, GRUB_EHCI_FRAME_INDEX)); + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: FL_BASE: %08x\n", + grub_ehci_oper_read32 (e, GRUB_EHCI_FL_BASE)); + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CUR_AL_ADDR: %08x\n", + grub_ehci_oper_read32 (e, GRUB_EHCI_CUR_AL_ADDR)); + grub_dprintf ("ehci", "EHCI grub_ehci_pci_iter: CONFIG_FLAG: %08x\n", + grub_ehci_oper_read32 (e, GRUB_EHCI_CONFIG_FLAG)); + + return 0; + +fail: + if (e) + { + if (e->td_chunk) + grub_dma_free ((void *) e->td_chunk); + if (e->qh_chunk) + grub_dma_free ((void *) e->qh_chunk); + if (e->framelist_chunk) + grub_dma_free (e->framelist_chunk); + } + grub_free (e); + + return 0; +} + +static int +grub_ehci_iterate (int (*hook) (grub_usb_controller_t dev)) +{ + struct grub_ehci *e; + struct grub_usb_controller dev; + + for (e = ehci; e; e = e->next) + { + dev.data = e; + if (hook (&dev)) + return 1; + } + + return 0; +} + +static void +grub_ehci_setup_qh (grub_ehci_qh_t qh, grub_usb_transfer_t transfer) +{ + grub_uint32_t ep_char = 0; + grub_uint32_t ep_cap = 0; + + /* Note: Another part of code is responsible to this QH is + * Halted ! But it can be linked in AL, so we cannot erase or + * change qh_hptr ! */ + /* We will not change any TD field because they should/must be + * in safe state from previous use. */ + + /* EP characteristic setup */ + /* Currently not used NAK counter (RL=0), + * C bit set if EP is not HIGH speed and is control, + * Max Packet Length is taken from transfer structure, + * H bit = 0 (because QH[1] has this bit set), + * DTC bit set to 1 because we are using our own toggle bit control, + * SPEED is selected according to value from transfer structure, + * EP number is taken from transfer structure + * "I" bit must not be set, + * Device Address is taken from transfer structure + * */ + if ((transfer->dev->speed != GRUB_USB_SPEED_HIGH) + && (transfer->type == GRUB_USB_TRANSACTION_TYPE_CONTROL)) + ep_char |= GRUB_EHCI_C; + ep_char |= (transfer->max << GRUB_EHCI_MAXPLEN_OFF) + & GRUB_EHCI_MAXPLEN_MASK; + ep_char |= GRUB_EHCI_DTC; + switch (transfer->dev->speed) + { + case GRUB_USB_SPEED_LOW: + ep_char |= GRUB_EHCI_SPEED_LOW; + break; + case GRUB_USB_SPEED_FULL: + ep_char |= GRUB_EHCI_SPEED_FULL; + break; + case GRUB_USB_SPEED_HIGH: + default: + ep_char |= GRUB_EHCI_SPEED_HIGH; + /* XXX: How we will handle unknown value of speed? */ + } + ep_char |= (transfer->endpoint << GRUB_EHCI_EP_NUM_OFF) + & GRUB_EHCI_EP_NUM_MASK; + ep_char |= transfer->devaddr & GRUB_EHCI_DEVADDR_MASK; + qh->ep_char = grub_cpu_to_le32 (ep_char); + /* EP capabilities setup */ + /* MULT field - we try to use max. number + * PortNumber - included now in device structure referenced + * inside transfer structure + * HubAddress - included now in device structure referenced + * inside transfer structure + * 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) + & GRUB_EHCI_DEVPORT_MASK; + ep_cap |= (transfer->dev->hubaddr << GRUB_EHCI_HUBADDR_OFF) + & GRUB_EHCI_HUBADDR_MASK; + qh->ep_cap = grub_cpu_to_le32 (ep_cap); + + grub_dprintf ("ehci", "setup_qh: qh=%p, not changed: qh_hptr=%08x\n", + qh, grub_le_to_cpu32 (qh->qh_hptr)); + grub_dprintf ("ehci", "setup_qh: ep_char=%08x, ep_cap=%08x\n", + ep_char, ep_cap); + grub_dprintf ("ehci", "setup_qh: end\n"); + grub_dprintf ("ehci", "setup_qh: not changed: td_current=%08x\n", + grub_le_to_cpu32 (qh->td_current)); + grub_dprintf ("ehci", "setup_qh: not changed: next_td=%08x\n", + grub_le_to_cpu32 (qh->td_overlay.next_td)); + grub_dprintf ("ehci", "setup_qh: not changed: alt_next_td=%08x\n", + grub_le_to_cpu32 (qh->td_overlay.alt_next_td)); + grub_dprintf ("ehci", "setup_qh: not changed: token=%08x\n", + grub_le_to_cpu32 (qh->td_overlay.token)); +} + +static grub_ehci_qh_t +grub_ehci_find_qh (struct grub_ehci *e, grub_usb_transfer_t transfer) +{ + grub_uint32_t target, mask; + int i; + grub_ehci_qh_t qh = e->qh_virt; + + /* Prepare part of EP Characteristic to find existing QH */ + target = ((transfer->endpoint << GRUB_EHCI_EP_NUM_OFF) | + transfer->devaddr) & GRUB_EHCI_TARGET_MASK; + target = grub_cpu_to_le32 (target); + mask = grub_cpu_to_le32 (GRUB_EHCI_TARGET_MASK); + + /* First try to find existing QH with proper target */ + for (i = 2; i < GRUB_EHCI_N_QH; i++) /* We ignore zero and first QH */ + { + if (!qh[i].ep_char) + break; /* Found first not-allocated QH, finish */ + if (target == (qh[i].ep_char & mask)) + { + /* Found proper existing (and linked) QH, do setup of QH */ + grub_dprintf ("ehci", "find_qh: found, i=%d, QH=%p\n", + i, &qh[i]); + grub_ehci_setup_qh (&qh[i], transfer); + return &qh[i]; + } + } + /* QH with target_addr does not exist, we have to add it */ + /* Have we any free QH in array ? */ + if (i >= GRUB_EHCI_N_QH) /* No. */ + { + grub_dprintf ("ehci", "find_qh: end - no free QH\n"); + return NULL; + } + grub_dprintf ("ehci", "find_qh: new, i=%d, QH=%p\n", + i, &qh[i]); + /* Currently we simply take next (current) QH in array, no allocation + * function is used. It should be no problem until we will need to + * de-allocate QHs of unplugged devices. */ + /* We should preset new QH and link it into AL */ + grub_ehci_setup_qh (&qh[i], transfer); + /* Linking - this new (last) QH will point to first QH */ + qh[i].qh_hptr = grub_cpu_to_le32 (GRUB_EHCI_HPTR_TYPE_QH + | grub_dma_virt2phys (&qh[1], + e->qh_chunk)); + /* Linking - previous last QH will point to this new QH */ + qh[i - 1].qh_hptr = grub_cpu_to_le32 (GRUB_EHCI_HPTR_TYPE_QH + | grub_dma_virt2phys (&qh[i], + e->qh_chunk)); + + return &qh[i]; +} + +static grub_ehci_td_t +grub_ehci_alloc_td (struct grub_ehci *e) +{ + grub_ehci_td_t ret; + + /* Check if there is a Transfer Descriptor available. */ + if (!e->tdfree_virt) + { + grub_dprintf ("ehci", "alloc_td: end - no free TD\n"); + return NULL; + } + + ret = e->tdfree_virt; /* Take current free TD */ + /* Advance to next free TD in chain */ + if (ret->link_td) + e->tdfree_virt = grub_dma_phys2virt (ret->link_td, e->td_chunk); + else + e->tdfree_virt = NULL; + ret->link_td = 0; /* Reset link_td in allocated TD */ + return ret; +} + +static void +grub_ehci_free_td (struct grub_ehci *e, grub_ehci_td_t td) +{ + /* Chain new free TD & rest */ + if (e->tdfree_virt) + td->link_td = grub_dma_virt2phys (e->tdfree_virt, e->td_chunk); + else + td->link_td = 0; + e->tdfree_virt = td; /* Change address of first free TD */ +} + +static void +grub_ehci_free_tds (struct grub_ehci *e, grub_ehci_td_t td, + grub_usb_transfer_t transfer, grub_size_t * actual) +{ + int i; /* Index of TD in transfer */ + grub_uint32_t token, to_transfer; + + /* Note: Another part of code is responsible to this QH is + * INACTIVE ! */ + *actual = 0; + + /* Free the TDs in this queue and set last_trans. */ + for (i = 0; td; i++) + { + grub_ehci_td_t tdprev; + + token = grub_le_to_cpu32 (td->token); + to_transfer = (token & GRUB_EHCI_TOTAL_MASK) >> GRUB_EHCI_TOTAL_OFF; + + /* Check state of TD - if it did not transfered + * whole data then set last_trans - it should be last executed TD + * in case when something went wrong. */ + if (transfer && (td->size != to_transfer)) + transfer->last_trans = i; + + *actual += td->size - to_transfer; + + /* Unlink the TD */ + tdprev = td; + if (td->link_td) + td = grub_dma_phys2virt (td->link_td, e->td_chunk); + else + td = NULL; + + /* Free the TD. */ + grub_ehci_free_td (e, tdprev); + } + + /* Check if last_trans was set. If not and something was + * transferred (it should be all data in this case), set it + * to index of last TD, i.e. i-1 */ + if (transfer && (transfer->last_trans < 0) && (*actual != 0)) + transfer->last_trans = i - 1; + + /* XXX: Fix it: last_trans may be set to bad index. + * Probably we should test more error flags to distinguish + * if TD was at least partialy executed or not at all. + * Generaly, we still could have problem with toggling because + * EHCI can probably split transactions into smaller parts then + * we defined in transaction even if we did not exceed MaxFrame + * length - it probably could happen at the end of microframe (?) + * and if the buffer is crossing page boundary (?). */ +} + +static grub_ehci_td_t +grub_ehci_transaction (struct grub_ehci *e, + grub_transfer_type_t type, + unsigned int toggle, grub_size_t size, + grub_uint32_t data, grub_ehci_td_t td_alt) +{ + grub_ehci_td_t td; + grub_uint32_t token; + grub_uint32_t bufadr; + int i; + + /* Test of transfer size, it can be: + * <= GRUB_EHCI_MAXBUFLEN if data aligned to page boundary + * <= GRUB_EHCI_MAXBUFLEN - GRUB_EHCI_BUFPAGELEN if not aligned + * (worst case) + */ + if ((((data % GRUB_EHCI_BUFPAGELEN) == 0) + && (size > GRUB_EHCI_MAXBUFLEN)) + || + (((data % GRUB_EHCI_BUFPAGELEN) != 0) + && (size > (GRUB_EHCI_MAXBUFLEN - GRUB_EHCI_BUFPAGELEN)))) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, + "too long data buffer for EHCI transaction"); + return 0; + } + + /* Grab a free Transfer Descriptor and initialize it. */ + td = grub_ehci_alloc_td (e); + if (!td) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, + "no transfer descriptors available for EHCI transfer"); + return 0; + } + + grub_dprintf ("ehci", + "transaction: type=%d, toggle=%d, size=%lu data=0x%x td=%p\n", + type, toggle, (unsigned long) size, data, td); + + /* Fill whole TD by zeros */ + grub_memset ((void *) td, 0, sizeof (struct grub_ehci_td)); + + /* Don't point to any TD yet, just terminate. */ + td->next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); + /* Set alternate pointer. When short packet occurs, alternate TD + * will not be really fetched because it is not active. But don't + * forget, EHCI will try to fetch alternate TD every scan of AL + * until QH is halted. */ + td->alt_next_td = grub_cpu_to_le32 (grub_dma_virt2phys (td_alt, + e->td_chunk)); + /* token: + * TOGGLE - according to toggle + * TOTAL SIZE = size + * Interrupt On Complete = FALSE, we don't need IRQ + * Current Page = 0 + * Error Counter = max. value = 3 + * PID Code - according to type + * STATUS: + * ACTIVE bit should be set to one + * SPLIT TRANS. STATE bit should be zero. It is ignored + * in HIGH speed transaction, and should be zero for LOW/FULL + * speed to indicate state Do Split Transaction */ + token = toggle ? GRUB_EHCI_TOGGLE : 0; + token |= (size << GRUB_EHCI_TOTAL_OFF) & GRUB_EHCI_TOTAL_MASK; + token |= GRUB_EHCI_CERR_3; + switch (type) + { + case GRUB_USB_TRANSFER_TYPE_IN: + token |= GRUB_EHCI_PIDCODE_IN; + break; + case GRUB_USB_TRANSFER_TYPE_OUT: + token |= GRUB_EHCI_PIDCODE_OUT; + break; + case GRUB_USB_TRANSFER_TYPE_SETUP: + token |= GRUB_EHCI_PIDCODE_SETUP; + break; + default: /* XXX: Should not happen, but what to do if it does ? */ + break; + } + token |= GRUB_EHCI_STATUS_ACTIVE; + td->token = grub_cpu_to_le32 (token); + + /* Fill buffer pointers according to size */ + bufadr = data; + td->buffer_page[0] = grub_cpu_to_le32 (bufadr); + bufadr = ((bufadr / GRUB_EHCI_BUFPAGELEN) + 1) * GRUB_EHCI_BUFPAGELEN; + for (i = 1; ((bufadr - data) < size) && (i < GRUB_EHCI_TD_BUF_PAGES); i++) + { + td->buffer_page[i] = grub_cpu_to_le32 (bufadr & GRUB_EHCI_BUFPTR_MASK); + bufadr = ((bufadr / GRUB_EHCI_BUFPAGELEN) + 1) * GRUB_EHCI_BUFPAGELEN; + } + + /* Remember data size for future use... */ + td->size = (grub_uint32_t) size; + + grub_dprintf ("ehci", "td=%p\n", td); + grub_dprintf ("ehci", "HW: next_td=%08x, alt_next_td=%08x\n", + grub_le_to_cpu32 (td->next_td), + grub_le_to_cpu32 (td->alt_next_td)); + grub_dprintf ("ehci", "HW: token=%08x, buffer[0]=%08x\n", + grub_le_to_cpu32 (td->token), + grub_le_to_cpu32 (td->buffer_page[0])); + grub_dprintf ("ehci", "HW: buffer[1]=%08x, buffer[2]=%08x\n", + grub_le_to_cpu32 (td->buffer_page[1]), + grub_le_to_cpu32 (td->buffer_page[2])); + grub_dprintf ("ehci", "HW: buffer[3]=%08x, buffer[4]=%08x\n", + grub_le_to_cpu32 (td->buffer_page[3]), + grub_le_to_cpu32 (td->buffer_page[4])); + grub_dprintf ("ehci", "link_td=%08x, size=%08x\n", + td->link_td, td->size); + + return td; +} + +struct grub_ehci_transfer_controller_data +{ + grub_ehci_qh_t qh_virt; + grub_ehci_td_t td_first_virt; + grub_ehci_td_t td_alt_virt; + grub_ehci_td_t td_last_virt; + grub_uint32_t td_last_phys; +}; + +static grub_usb_err_t +grub_ehci_setup_transfer (grub_usb_controller_t dev, + grub_usb_transfer_t transfer) +{ + struct grub_ehci *e = (struct grub_ehci *) dev->data; + grub_ehci_td_t td = NULL; + grub_ehci_td_t td_prev = NULL; + int i; + struct grub_ehci_transfer_controller_data *cdata; + + /* Check if EHCI is running and AL is enabled */ + if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) + & GRUB_EHCI_ST_HC_HALTED) != 0) + /* XXX: Fix it: Currently we don't do anything to restart EHCI */ + return GRUB_USB_ERR_INTERNAL; + if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) + & GRUB_EHCI_ST_AS_STATUS) == 0) + /* XXX: Fix it: Currently we don't do anything to restart EHCI */ + return GRUB_USB_ERR_INTERNAL; + + /* Check if transfer is not high speed and connected to root hub. + * It should not happened but... */ + if ((transfer->dev->speed != GRUB_USB_SPEED_HIGH) + && !transfer->dev->hubaddr) + { + grub_error (GRUB_USB_ERR_BADDEVICE, + "FULL/LOW speed device on EHCI port!?!"); + return GRUB_USB_ERR_BADDEVICE; + } + + /* Allocate memory for controller transfer data. */ + cdata = grub_malloc (sizeof (*cdata)); + if (!cdata) + return GRUB_USB_ERR_INTERNAL; + cdata->td_first_virt = NULL; + + /* Allocate a queue head for the transfer queue. */ + cdata->qh_virt = grub_ehci_find_qh (e, transfer); + if (!cdata->qh_virt) + { + grub_free (cdata); + return GRUB_USB_ERR_INTERNAL; + } + + /* To detect short packet we need some additional "alternate" TD, + * allocate it first. */ + cdata->td_alt_virt = grub_ehci_alloc_td (e); + if (!cdata->td_alt_virt) + { + grub_free (cdata); + return GRUB_USB_ERR_INTERNAL; + } + /* Fill whole alternate TD by zeros (= inactive) and set + * Terminate bits and Halt bit */ + grub_memset ((void *) cdata->td_alt_virt, 0, sizeof (struct grub_ehci_td)); + cdata->td_alt_virt->next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); + cdata->td_alt_virt->alt_next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); + cdata->td_alt_virt->token = grub_cpu_to_le32 (GRUB_EHCI_STATUS_HALTED); + + /* Allocate appropriate number of TDs and set */ + for (i = 0; i < transfer->transcnt; i++) + { + grub_usb_transaction_t tr = &transfer->transactions[i]; + + td = grub_ehci_transaction (e, tr->pid, tr->toggle, tr->size, + tr->data, cdata->td_alt_virt); + + if (!td) /* de-allocate and free all */ + { + grub_size_t actual = 0; + + if (cdata->td_first_virt) + grub_ehci_free_tds (e, cdata->td_first_virt, NULL, &actual); + + grub_free (cdata); + return GRUB_USB_ERR_INTERNAL; + } + + /* Register new TD in cdata or previous TD */ + if (!cdata->td_first_virt) + cdata->td_first_virt = td; + else + { + td_prev->link_td = grub_dma_virt2phys (td, e->td_chunk); + td_prev->next_td = + grub_cpu_to_le32 (grub_dma_virt2phys (td, e->td_chunk)); + } + td_prev = td; + } + + /* Remember last TD */ + cdata->td_last_virt = td; + cdata->td_last_phys = grub_dma_virt2phys (td, e->td_chunk); + /* Last TD should not have set alternate TD */ + cdata->td_last_virt->alt_next_td = grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); + + grub_dprintf ("ehci", "setup_transfer: cdata=%p, qh=%p\n", + cdata,cdata->qh_virt); + grub_dprintf ("ehci", "setup_transfer: td_first=%p, td_alt=%p\n", + cdata->td_first_virt, + cdata->td_alt_virt); + grub_dprintf ("ehci", "setup_transfer: td_last=%p\n", + cdata->td_last_virt); + + /* Start transfer: */ + /* Unlink possible alternate pointer in QH */ + cdata->qh_virt->td_overlay.alt_next_td = + grub_cpu_to_le32 (GRUB_EHCI_TERMINATE); + /* Link new TDs with QH via next_td */ + cdata->qh_virt->td_overlay.next_td = + grub_cpu_to_le32 (grub_dma_virt2phys + (cdata->td_first_virt, e->td_chunk)); + /* Reset Active and Halted bits in QH to activate Advance Queue, + * i.e. reset token */ + cdata->qh_virt->td_overlay.token = grub_cpu_to_le32 (0); + + /* Finito */ + transfer->controller_data = cdata; + + return GRUB_USB_ERR_NONE; +} + +/* This function expects QH is not active. + * Function set Halt bit in QH TD overlay and possibly prints + * necessary debug information. */ +static void +grub_ehci_pre_finish_transfer (grub_usb_transfer_t transfer) +{ + struct grub_ehci_transfer_controller_data *cdata = + transfer->controller_data; + + /* Collect debug data here if necessary */ + + /* Set Halt bit in not active QH. AL will not attempt to do + * Advance Queue on QH with Halt bit set, i.e., we can then + * safely manipulate with QH TD part. */ + cdata->qh_virt->td_overlay.token = (cdata->qh_virt->td_overlay.token + | + grub_cpu_to_le32 + (GRUB_EHCI_STATUS_HALTED)) & + grub_cpu_to_le32 (~GRUB_EHCI_STATUS_ACTIVE); + + /* Print debug data here if necessary */ + +} + +static grub_usb_err_t +grub_ehci_parse_notrun (grub_usb_controller_t dev, + grub_usb_transfer_t transfer, grub_size_t * actual) +{ + struct grub_ehci *e = dev->data; + struct grub_ehci_transfer_controller_data *cdata = + transfer->controller_data; + + grub_dprintf ("ehci", "parse_notrun: info\n"); + + /* QH can be in any state in this case. */ + /* But EHCI or AL is not running, so QH is surely not active + * even if it has Active bit set... */ + grub_ehci_pre_finish_transfer (transfer); + grub_ehci_free_tds (e, cdata->td_first_virt, transfer, actual); + grub_ehci_free_td (e, cdata->td_alt_virt); + grub_free (cdata); + + /* Additionally, do something with EHCI to make it running (what?) */ + /* Try enable EHCI and AL */ + grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND, + GRUB_EHCI_CMD_RUNSTOP | GRUB_EHCI_CMD_AS_ENABL + | grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND)); + /* Ensure command is written */ + grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND); + + return GRUB_USB_ERR_UNRECOVERABLE; +} + +static grub_usb_err_t +grub_ehci_parse_halt (grub_usb_controller_t dev, + grub_usb_transfer_t transfer, grub_size_t * actual) +{ + struct grub_ehci *e = dev->data; + struct grub_ehci_transfer_controller_data *cdata = + transfer->controller_data; + grub_uint32_t token; + grub_usb_err_t err = GRUB_USB_ERR_NAK; + + /* QH should be halted and not active in this case. */ + + grub_dprintf ("ehci", "parse_halt: info\n"); + + /* Remember token before call pre-finish function */ + token = grub_le_to_cpu32 (cdata->qh_virt->td_overlay.token); + + /* Do things like in normal finish */ + grub_ehci_pre_finish_transfer (transfer); + grub_ehci_free_tds (e, cdata->td_first_virt, transfer, actual); + grub_ehci_free_td (e, cdata->td_alt_virt); + grub_free (cdata); + + /* Evaluation of error code - currently we don't have GRUB USB error + * codes for some EHCI states, GRUB_USB_ERR_DATA is used for them. + * Order of evaluation is critical, specially bubble/stall. */ + if ((token & GRUB_EHCI_STATUS_BABBLE) != 0) + err = GRUB_USB_ERR_BABBLE; + else if ((token & GRUB_EHCI_CERR_MASK) != 0) + err = GRUB_USB_ERR_STALL; + else if ((token & GRUB_EHCI_STATUS_TRANERR) != 0) + err = GRUB_USB_ERR_DATA; + else if ((token & GRUB_EHCI_STATUS_BUFERR) != 0) + err = GRUB_USB_ERR_DATA; + else if ((token & GRUB_EHCI_STATUS_MISSDMF) != 0) + err = GRUB_USB_ERR_DATA; + + return err; +} + +static grub_usb_err_t +grub_ehci_parse_success (grub_usb_controller_t dev, + grub_usb_transfer_t transfer, grub_size_t * actual) +{ + struct grub_ehci *e = dev->data; + struct grub_ehci_transfer_controller_data *cdata = + transfer->controller_data; + + grub_dprintf ("ehci", "parse_success: info\n"); + + /* QH should be not active in this case, but it is not halted. */ + grub_ehci_pre_finish_transfer (transfer); + grub_ehci_free_tds (e, cdata->td_first_virt, transfer, actual); + grub_ehci_free_td (e, cdata->td_alt_virt); + grub_free (cdata); + + return GRUB_USB_ERR_NONE; +} + + +static grub_usb_err_t +grub_ehci_check_transfer (grub_usb_controller_t dev, + grub_usb_transfer_t transfer, grub_size_t * actual) +{ + struct grub_ehci *e = dev->data; + struct grub_ehci_transfer_controller_data *cdata = + transfer->controller_data; + grub_uint32_t token; + + grub_dprintf ("ehci", + "check_transfer: EHCI STATUS=%08x, cdata=%p, qh=%p\n", + grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS), + cdata, cdata->qh_virt); + grub_dprintf ("ehci", "check_transfer: qh_hptr=%08x, ep_char=%08x\n", + grub_le_to_cpu32 (cdata->qh_virt->qh_hptr), + grub_le_to_cpu32 (cdata->qh_virt->ep_char)); + grub_dprintf ("ehci", "check_transfer: ep_cap=%08x, td_current=%08x\n", + grub_le_to_cpu32 (cdata->qh_virt->ep_cap), + grub_le_to_cpu32 (cdata->qh_virt->td_current)); + grub_dprintf ("ehci", "check_transfer: next_td=%08x, alt_next_td=%08x\n", + grub_le_to_cpu32 (cdata->qh_virt->td_overlay.next_td), + grub_le_to_cpu32 (cdata->qh_virt->td_overlay.alt_next_td)); + grub_dprintf ("ehci", "check_transfer: token=%08x, buffer[0]=%08x\n", + grub_le_to_cpu32 (cdata->qh_virt->td_overlay.token), + grub_le_to_cpu32 (cdata->qh_virt->td_overlay.buffer_page[0])); + + /* Check if EHCI is running and AL is enabled */ + if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) + & GRUB_EHCI_ST_HC_HALTED) != 0) + return grub_ehci_parse_notrun (dev, transfer, actual); + if ((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) + & GRUB_EHCI_ST_AS_STATUS) == 0) + return grub_ehci_parse_notrun (dev, transfer, actual); + + token = grub_le_to_cpu32 (cdata->qh_virt->td_overlay.token); + + /* Detect QH halted */ + if ((token & GRUB_EHCI_STATUS_HALTED) != 0) + return grub_ehci_parse_halt (dev, transfer, actual); + + /* Detect QH not active - QH is not active and no next TD */ + if ((token & GRUB_EHCI_STATUS_ACTIVE) == 0) + { + /* It could be finish at all or short packet condition */ + if ((grub_le_to_cpu32 (cdata->qh_virt->td_overlay.next_td) + & GRUB_EHCI_TERMINATE) && + ((grub_le_to_cpu32 (cdata->qh_virt->td_current) + & GRUB_EHCI_QHTDPTR_MASK) == cdata->td_last_phys)) + /* Normal finish */ + return grub_ehci_parse_success (dev, transfer, actual); + else if ((token & GRUB_EHCI_TOTAL_MASK) != 0) + /* Short packet condition */ + /* But currently we don't handle it - higher level will do it */ + return grub_ehci_parse_success (dev, transfer, actual); + } + + return GRUB_USB_ERR_WAIT; +} + +static grub_usb_err_t +grub_ehci_cancel_transfer (grub_usb_controller_t dev, + grub_usb_transfer_t transfer) +{ + struct grub_ehci *e = dev->data; + struct grub_ehci_transfer_controller_data *cdata = + transfer->controller_data; + grub_size_t actual; + int i; + grub_uint64_t maxtime; + + /* 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) == 0)) + { + grub_ehci_pre_finish_transfer (transfer); + grub_ehci_free_tds (e, cdata->td_first_virt, transfer, &actual); + grub_ehci_free_td (e, cdata->td_alt_virt); + grub_free (cdata); + grub_dprintf ("ehci", "cancel_transfer: end - EHCI not running\n"); + return GRUB_USB_ERR_NONE; + } + + /* EHCI and AL are running. What to do? + * Try to Halt QH via de-scheduling QH. */ + /* Find index of current QH - we need previous QH, i.e. i-1 */ + i = ((int) (e->qh_virt - cdata->qh_virt)) / sizeof (struct grub_ehci_qh); + /* Unlink QH from AL */ + e->qh_virt[i - 1].qh_hptr = cdata->qh_virt->qh_hptr; + /* Ring the doorbell */ + grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND, + GRUB_EHCI_CMD_AS_ADV_D + | grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND)); + /* Ensure command is written */ + grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND); + /* Wait answer with timeout */ + maxtime = grub_get_time_ms () + 2; + while (((grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS) + & GRUB_EHCI_ST_AS_ADVANCE) == 0) + && (grub_get_time_ms () < maxtime)); + + /* We do not detect the timeout because if timeout occurs, it most + * probably means something wrong with EHCI - maybe stopped etc. */ + + /* Shut up the doorbell */ + grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND, + ~GRUB_EHCI_CMD_AS_ADV_D + & grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND)); + grub_ehci_oper_write32 (e, GRUB_EHCI_STATUS, + GRUB_EHCI_ST_AS_ADVANCE + | grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)); + /* Ensure command is written */ + grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS); + + /* Now is QH out of AL and we can do anything with it... */ + grub_ehci_pre_finish_transfer (transfer); + grub_ehci_free_tds (e, cdata->td_first_virt, transfer, &actual); + grub_ehci_free_td (e, cdata->td_alt_virt); + + /* Finaly we should return QH back to the AL... */ + e->qh_virt[i - 1].qh_hptr = + grub_cpu_to_le32 (grub_dma_virt2phys + (cdata->qh_virt, e->qh_chunk)); + grub_free (cdata); + + grub_dprintf ("ehci", "cancel_transfer: end\n"); + + return GRUB_USB_ERR_NONE; +} + +static int +grub_ehci_hubports (grub_usb_controller_t dev) +{ + struct grub_ehci *e = (struct grub_ehci *) dev->data; + grub_uint32_t portinfo; + + portinfo = grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_SPARAMS) + & GRUB_EHCI_SPARAMS_N_PORTS; + grub_dprintf ("ehci", "root hub ports=%d\n", portinfo); + return portinfo; +} + +static grub_err_t +grub_ehci_portstatus (grub_usb_controller_t dev, + unsigned int port, unsigned int enable) +{ + struct grub_ehci *e = (struct grub_ehci *) dev->data; + grub_uint64_t endtime; + + grub_dprintf ("ehci", "portstatus: EHCI STATUS: %08x\n", + grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)); + grub_dprintf ("ehci", + "portstatus: begin, iobase=%p, port=%d, status=0x%02x\n", + e->iobase, port, grub_ehci_port_read (e, port)); + + /* In any case we need to disable port: + * - if enable==false - we should disable port + * - if enable==true we will do the reset and the specification says + * PortEnable should be FALSE in such case */ + /* Disable the port and wait for it. */ + grub_ehci_port_resbits (e, port, GRUB_EHCI_PORT_ENABLED); + 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"); + + 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; + } + + grub_dprintf ("ehci", "portstatus: enable\n"); + + /* 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 */ + grub_ehci_port_setbits (e, port, GRUB_EHCI_PORT_RESET); + grub_millisleep (50); + + /* Reset RESET bit and wait for the end of reset */ + grub_ehci_port_resbits (e, port, GRUB_EHCI_PORT_RESET); + 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"); + /* Remember "we did the reset" - needed by detect_dev */ + e->reset |= (1 << port); + /* Test if port enabled, i.e. HIGH speed device connected */ + if ((grub_ehci_port_read (e, port) & GRUB_EHCI_PORT_ENABLED) != 0) /* yes! */ + { + grub_dprintf ("ehci", "portstatus: Enabled!\n"); + /* "Reset recovery time" (USB spec.) */ + grub_millisleep (10); + } + else /* no... */ + { + /* FULL speed device connected - change port ownership. + * It results in disconnected state of this EHCI port. */ + grub_ehci_port_setbits (e, port, GRUB_EHCI_PORT_OWNER); + return GRUB_USB_ERR_BADDEVICE; + } + + /* XXX: Fix it! There is possible problem - we can say to calling + * function that we lost device if it is FULL speed onlu via + * return value <> GRUB_ERR_NONE. It (maybe) displays also error + * message on screen - but this situation is not error, it is normal + * state! */ + + grub_dprintf ("ehci", "portstatus: end, status=0x%02x\n", + grub_ehci_port_read (e, port)); + + return GRUB_ERR_NONE; +} + +static grub_usb_speed_t +grub_ehci_detect_dev (grub_usb_controller_t dev, int port, int *changed) +{ + struct grub_ehci *e = (struct grub_ehci *) dev->data; + grub_uint32_t status, line_state; + + status = grub_ehci_port_read (e, port); + + grub_dprintf ("ehci", "detect_dev: EHCI STATUS: %08x\n", + grub_ehci_oper_read32 (e, GRUB_EHCI_STATUS)); + grub_dprintf ("ehci", "detect_dev: iobase=%p, port=%d, status=0x%02x\n", + e->iobase, port, status); + + /* Connect Status Change bit - it detects change of connection */ + if (status & GRUB_EHCI_PORT_CONNECT_CH) + { + *changed = 1; + /* Reset bit Connect Status Change */ + grub_ehci_port_setbits (e, port, GRUB_EHCI_PORT_CONNECT_CH); + } + else + *changed = 0; + + if (!(status & GRUB_EHCI_PORT_CONNECT)) + { /* We should reset related "reset" flag in not connected state */ + e->reset &= ~(1 << port); + return GRUB_USB_SPEED_NONE; + } + /* Detected connected state, so we should return speed. + * But we can detect only LOW speed device and only at connection + * time when PortEnabled=FALSE. FULL / HIGH speed detection is made + * later by EHCI-specific reset procedure. + * Another thing - if detected speed is LOW at connection time, + * we should change port ownership to companion controller. + * So: + * 1. If we detect connected and enabled and EHCI-owned port, + * we can say it is HIGH speed. + * 2. If we detect connected and not EHCI-owned port, we can say + * NONE speed, because such devices are not handled by EHCI. + * 3. If we detect connected, not enabled but reset port, we can say + * NONE speed, because it means FULL device connected to port and + * such devices are not handled by EHCI. + * 4. If we detect connected, not enabled and not reset port, which + * has line state != "K", we will say HIGH - it could be FULL or HIGH + * device, we will see it later after end of EHCI-specific reset + * procedure. + * 5. If we detect connected, not enabled and not reset port, which + * has line state == "K", we can say NONE speed, because LOW speed + * device is connected and we should change port ownership. */ + if ((status & GRUB_EHCI_PORT_ENABLED) != 0) /* Port already enabled, return high speed. */ + return GRUB_USB_SPEED_HIGH; + if ((status & GRUB_EHCI_PORT_OWNER) != 0) /* EHCI is not port owner */ + return GRUB_USB_SPEED_NONE; /* EHCI driver is ignoring this port. */ + if ((e->reset & (1 << port)) != 0) /* Port reset was done = FULL speed */ + return GRUB_USB_SPEED_NONE; /* EHCI driver is ignoring this port. */ + else /* Port connected but not enabled - test port speed. */ + { + line_state = status & GRUB_EHCI_PORT_LINE_STAT; + if (line_state != GRUB_EHCI_PORT_LINE_LOWSP) + return GRUB_USB_SPEED_HIGH; + /* Detected LOW speed device, we should change + * port ownership. + * XXX: Fix it!: There should be test if related companion + * controler is available ! And what to do if it does not exist ? */ + grub_ehci_port_setbits (e, port, GRUB_EHCI_PORT_OWNER); + return GRUB_USB_SPEED_NONE; /* Ignore this port */ + /* Note: Reset of PORT_OWNER bit is done by EHCI HW when + * device is really disconnected from port. + * Don't do PORT_OWNER bit reset by SW when not connected signal + * is detected in port register ! */ + } +} + +static void +grub_ehci_inithw (void) +{ + grub_pci_iterate (grub_ehci_pci_iter); +} + +static grub_err_t +grub_ehci_restore_hw (void) +{ + struct grub_ehci *e; + grub_uint32_t n_ports; + int i; + + /* We should re-enable all EHCI HW similarly as on inithw */ + for (e = ehci; e; e = e->next) + { + /* 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"); + + /* Reset EHCI */ + if (grub_ehci_reset (e) != GRUB_USB_ERR_NONE) + grub_error (GRUB_ERR_TIMEOUT, "restore_hw: EHCI reset timeout"); + + /* Setup some EHCI registers and enable EHCI */ + grub_ehci_oper_write32 (e, GRUB_EHCI_FL_BASE, e->framelist_phys); + grub_ehci_oper_write32 (e, GRUB_EHCI_CUR_AL_ADDR, + grub_dma_virt2phys (&e->qh_virt[1], + e->qh_chunk)); + grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND, + GRUB_EHCI_CMD_RUNSTOP | + grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND)); + + /* 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 */ + grub_ehci_oper_write32 (e, GRUB_EHCI_COMMAND, + GRUB_EHCI_CMD_AS_ENABL + | grub_ehci_oper_read32 (e, GRUB_EHCI_COMMAND)); + + /* Now should be possible to power-up and enumerate ports etc. */ + if ((grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_SPARAMS) + & GRUB_EHCI_SPARAMS_PPC) != 0) + { /* EHCI has port powering control */ + /* Power on all ports */ + n_ports = grub_ehci_ehcc_read32 (e, GRUB_EHCI_EHCC_SPARAMS) + & GRUB_EHCI_SPARAMS_N_PORTS; + for (i = 0; i < (int) n_ports; i++) + grub_ehci_oper_write32 (e, GRUB_EHCI_PORT_STAT_CMD + i * 4, + GRUB_EHCI_PORT_POWER + | grub_ehci_oper_read32 (e, + GRUB_EHCI_PORT_STAT_CMD + + i * 4)); + } + } + + return GRUB_USB_ERR_NONE; +} + +static grub_err_t +grub_ehci_fini_hw (int noreturn __attribute__ ((unused))) +{ + struct grub_ehci *e; + + /* We should disable all EHCI HW to prevent any DMA access etc. */ + for (e = ehci; e; e = e->next) + { + /* 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"); + + /* Reset EHCI */ + if (grub_ehci_reset (e) != GRUB_USB_ERR_NONE) + grub_error (GRUB_ERR_TIMEOUT, "restore_hw: EHCI reset timeout"); + } + + return GRUB_USB_ERR_NONE; +} + +static struct grub_usb_controller_dev usb_controller = { + .name = "ehci", + .iterate = grub_ehci_iterate, + .setup_transfer = grub_ehci_setup_transfer, + .check_transfer = grub_ehci_check_transfer, + .cancel_transfer = grub_ehci_cancel_transfer, + .hubports = grub_ehci_hubports, + .portstatus = grub_ehci_portstatus, + .detect_dev = grub_ehci_detect_dev +}; + +GRUB_MOD_INIT (ehci) +{ + COMPILE_TIME_ASSERT (sizeof (struct grub_ehci_td) == 64); + COMPILE_TIME_ASSERT (sizeof (struct grub_ehci_qh) == 96); + grub_ehci_inithw (); + grub_usb_controller_dev_register (&usb_controller); + grub_loader_register_preboot_hook (grub_ehci_fini_hw, grub_ehci_restore_hw, + GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK); +} + +GRUB_MOD_FINI (ehci) +{ + grub_ehci_fini_hw (0); + grub_usb_controller_dev_unregister (&usb_controller); +} diff --git a/grub-core/bus/usb/ohci.c b/grub-core/bus/usb/ohci.c index b659c3f62..23cf63187 100644 --- a/grub-core/bus/usb/ohci.c +++ b/grub-core/bus/usb/ohci.c @@ -294,13 +294,15 @@ grub_ohci_pci_iter (grub_pci_device_t dev, o->hcca_chunk, o->hcca, o->hcca_addr); /* Reserve memory for ctrl EDs. */ - o->ed_ctrl_chunk = grub_memalign_dma32 (16, sizeof(struct grub_ohci_ed)*GRUB_OHCI_CTRL_EDS); + o->ed_ctrl_chunk = grub_memalign_dma32 (16, sizeof(struct grub_ohci_ed) + * GRUB_OHCI_CTRL_EDS); if (! o->ed_ctrl_chunk) goto fail; o->ed_ctrl = grub_dma_get_virt (o->ed_ctrl_chunk); o->ed_ctrl_addr = grub_dma_get_phys (o->ed_ctrl_chunk); /* Preset EDs */ - grub_memset ((void*)o->ed_ctrl, 0, sizeof(struct grub_ohci_ed) * GRUB_OHCI_CTRL_EDS); + grub_memset ((void *) o->ed_ctrl, 0, sizeof (struct grub_ohci_ed) + * GRUB_OHCI_CTRL_EDS); for (j=0; j < GRUB_OHCI_CTRL_EDS; j++) o->ed_ctrl[j].target = grub_cpu_to_le32 (1 << 14); /* skip */ @@ -308,7 +310,8 @@ grub_ohci_pci_iter (grub_pci_device_t dev, o->ed_ctrl_chunk, o->ed_ctrl, o->ed_ctrl_addr); /* Reserve memory for bulk EDs. */ - o->ed_bulk_chunk = grub_memalign_dma32 (16, sizeof(struct grub_ohci_ed)*GRUB_OHCI_BULK_EDS); + o->ed_bulk_chunk = grub_memalign_dma32 (16, sizeof (struct grub_ohci_ed) + * GRUB_OHCI_BULK_EDS); if (! o->ed_bulk_chunk) goto fail; o->ed_bulk = grub_dma_get_virt (o->ed_bulk_chunk); @@ -1152,8 +1155,8 @@ grub_ohci_check_transfer (grub_usb_controller_t dev, return parse_halt (dev, transfer, actual); /* Finished ED detection */ - if ( (grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xf) == - (grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xf) ) /* Empty ED */ + if ( (grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xfU) == + (grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xfU) ) /* Empty ED */ { /* Check the HALT bit */ /* It looks like nonsense - it was tested previously... @@ -1426,7 +1429,7 @@ static struct grub_usb_controller_dev usb_controller = .detect_dev = grub_ohci_detect_dev }; -static void *fini_hnd; +static struct grub_preboot *fini_hnd; GRUB_MOD_INIT(ohci) { diff --git a/grub-core/bus/usb/serial/ftdi.c b/grub-core/bus/usb/serial/ftdi.c index 07ac7ac52..cce26d9eb 100644 --- a/grub-core/bus/usb/serial/ftdi.c +++ b/grub-core/bus/usb/serial/ftdi.c @@ -23,6 +23,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -137,19 +138,23 @@ ftdi_hw_configure (struct grub_serial_port *port, divisor = get_divisor (config->speed); if (divisor == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad speed"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("unsupported serial port speed")); if (config->parity != GRUB_SERIAL_PARITY_NONE && config->parity != GRUB_SERIAL_PARITY_ODD && config->parity != GRUB_SERIAL_PARITY_EVEN) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "unsupported parity"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("unsupported serial port parity")); if (config->stop_bits != GRUB_SERIAL_STOP_BITS_1 && config->stop_bits != GRUB_SERIAL_STOP_BITS_2) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "unsupported stop bits"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("unsupported serial port stop bits number")); if (config->word_len < 5 || config->word_len > 8) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "unsupported word length"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("unsupported serial port word length")); port->config = *config; port->configured = 0; diff --git a/grub-core/bus/usb/serial/pl2303.c b/grub-core/bus/usb/serial/pl2303.c index b9954116b..f92172c1d 100644 --- a/grub-core/bus/usb/serial/pl2303.c +++ b/grub-core/bus/usb/serial/pl2303.c @@ -23,6 +23,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -150,19 +151,23 @@ pl2303_hw_configure (struct grub_serial_port *port, struct grub_serial_config *config) { if (!is_speed_supported (config->speed)) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad speed"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("unsupported serial port speed")); if (config->parity != GRUB_SERIAL_PARITY_NONE && config->parity != GRUB_SERIAL_PARITY_ODD && config->parity != GRUB_SERIAL_PARITY_EVEN) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "unsupported parity"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("unsupported serial port parity")); if (config->stop_bits != GRUB_SERIAL_STOP_BITS_1 && config->stop_bits != GRUB_SERIAL_STOP_BITS_2) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "unsupported stop bits"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("unsupported serial port stop bits number")); if (config->word_len < 5 || config->word_len > 8) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "unsupported word length"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("unsupported serial port word length")); port->config = *config; port->configured = 0; diff --git a/grub-core/bus/usb/uhci.c b/grub-core/bus/usb/uhci.c index a9a4c45a2..8f60850de 100644 --- a/grub-core/bus/usb/uhci.c +++ b/grub-core/bus/usb/uhci.c @@ -23,8 +23,9 @@ #include #include #include -#include +#include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -125,13 +126,19 @@ typedef volatile struct grub_uhci_qh *grub_uhci_qh_t; struct grub_uhci { int iobase; - grub_uint32_t *framelist; + volatile grub_uint32_t *framelist_virt; + grub_uint32_t framelist_phys; + struct grub_pci_dma_chunk *framelist_chunk; /* N_QH Queue Heads. */ - grub_uhci_qh_t qh; + struct grub_pci_dma_chunk *qh_chunk; + volatile grub_uhci_qh_t qh_virt; + grub_uint32_t qh_phys; /* N_TD Transfer Descriptors. */ - grub_uhci_td_t td; + struct grub_pci_dma_chunk *td_chunk; + volatile grub_uhci_td_t td_virt; + grub_uint32_t td_phys; /* Free Transfer Descriptors. */ grub_uhci_td_t tdfree; @@ -236,90 +243,71 @@ grub_uhci_pci_iter (grub_pci_device_t dev, grub_uhci_readreg16(u, GRUB_UHCI_REG_USBCMD); /* Reserve a page for the frame list. */ - u->framelist = grub_memalign (4096, 4096); - if (! u->framelist) + u->framelist_chunk = grub_memalign_dma32 (4096, 4096); + if (! u->framelist_chunk) goto fail; + u->framelist_virt = grub_dma_get_virt (u->framelist_chunk); + u->framelist_phys = grub_dma_get_phys (u->framelist_chunk); - grub_dprintf ("uhci", "class=0x%02x 0x%02x interface 0x%02x base=0x%x framelist=%p\n", - class, subclass, interf, u->iobase, u->framelist); - - /* The framelist pointer of UHCI is only 32 bits, make sure this - code works on on 64 bits architectures. */ -#if GRUB_CPU_SIZEOF_VOID_P == 8 - if ((grub_uint64_t) u->framelist >> 32) - { - grub_error (GRUB_ERR_OUT_OF_MEMORY, - "allocated frame list memory not <4GB"); - goto fail; - } -#endif + grub_dprintf ("uhci", + "class=0x%02x 0x%02x interface 0x%02x base=0x%x framelist=%p\n", + class, subclass, interf, u->iobase, u->framelist_virt); /* The QH pointer of UHCI is only 32 bits, make sure this code works on on 64 bits architectures. */ - u->qh = (grub_uhci_qh_t) grub_memalign (4096, sizeof(struct grub_uhci_qh)*N_QH); - if (! u->qh) + u->qh_chunk = grub_memalign_dma32 (4096, sizeof(struct grub_uhci_qh) * N_QH); + if (! u->qh_chunk) goto fail; - -#if GRUB_CPU_SIZEOF_VOID_P == 8 - if ((grub_uint64_t) u->qh >> 32) - { - grub_error (GRUB_ERR_OUT_OF_MEMORY, "allocated QH memory not <4GB"); - goto fail; - } -#endif + u->qh_virt = grub_dma_get_virt (u->qh_chunk); + u->qh_phys = grub_dma_get_phys (u->qh_chunk); /* The TD pointer of UHCI is only 32 bits, make sure this code works on on 64 bits architectures. */ - u->td = (grub_uhci_td_t) grub_memalign (4096, sizeof(struct grub_uhci_td)*N_TD); - if (! u->td) + u->td_chunk = grub_memalign_dma32 (4096, sizeof(struct grub_uhci_td) * N_TD); + if (! u->td_chunk) goto fail; - -#if GRUB_CPU_SIZEOF_VOID_P == 8 - if ((grub_uint64_t) u->td >> 32) - { - grub_error (GRUB_ERR_OUT_OF_MEMORY, "allocated TD memory not <4GB"); - goto fail; - } -#endif + u->td_virt = grub_dma_get_virt (u->td_chunk); + u->td_phys = grub_dma_get_phys (u->td_chunk); grub_dprintf ("uhci", "QH=%p, TD=%p\n", - u->qh, u->td); + u->qh_virt, u->td_virt); /* Link all Transfer Descriptors in a list of available Transfer Descriptors. */ for (i = 0; i < N_TD; i++) - u->td[i].linkptr = (grub_uint32_t) (grub_addr_t) &u->td[i + 1]; - u->td[N_TD - 2].linkptr = 0; - u->tdfree = u->td; + u->td_virt[i].linkptr = u->td_phys + (i + 1) * sizeof(struct grub_uhci_td); + u->td_virt[N_TD - 2].linkptr = 0; + u->tdfree = u->td_virt; /* Setup the frame list pointers. Since no isochronous transfers are and will be supported, they all point to the (same!) queue head. */ - fp = (grub_uint32_t) (grub_addr_t) u->qh & (~15); + fp = u->qh_phys & (~15); /* Mark this as a queue head. */ fp |= 2; for (i = 0; i < 1024; i++) - u->framelist[i] = fp; + u->framelist_virt[i] = fp; /* Program the framelist address into the UHCI controller. */ - grub_uhci_writereg32 (u, GRUB_UHCI_REG_FLBASEADD, - (grub_uint32_t) (grub_addr_t) u->framelist); + grub_uhci_writereg32 (u, GRUB_UHCI_REG_FLBASEADD, u->framelist_phys); /* Make the Queue Heads point to each other. */ for (i = 0; i < N_QH; i++) { /* Point to the next QH. */ - u->qh[i].linkptr = (grub_uint32_t) (grub_addr_t) (&u->qh[i + 1]) & (~15); + u->qh_virt[i].linkptr = ((u->qh_phys + + (i + 1) * sizeof(struct grub_uhci_qh)) + & (~15)); /* This is a QH. */ - u->qh[i].linkptr |= GRUB_UHCI_LINK_QUEUE_HEAD; + u->qh_virt[i].linkptr |= GRUB_UHCI_LINK_QUEUE_HEAD; /* For the moment, do not point to a Transfer Descriptor. These are set at transfer time, so just terminate it. */ - u->qh[i].elinkptr = 1; + u->qh_virt[i].elinkptr = 1; } /* The last Queue Head should terminate. */ - u->qh[N_QH - 1].linkptr = 1; + u->qh_virt[N_QH - 1].linkptr = 1; /* Enable UHCI again. */ grub_uhci_writereg16 (u, GRUB_UHCI_REG_USBCMD, @@ -352,8 +340,8 @@ grub_uhci_pci_iter (grub_pci_device_t dev, fail: if (u) { - grub_free ((void *) u->qh); - grub_free (u->framelist); + grub_dma_free (u->qh_chunk); + grub_dma_free (u->framelist_chunk); } grub_free (u); @@ -376,7 +364,7 @@ grub_alloc_td (struct grub_uhci *u) return NULL; ret = u->tdfree; - u->tdfree = (grub_uhci_td_t) (grub_addr_t) u->tdfree->linkptr; + u->tdfree = grub_dma_phys2virt (u->tdfree->linkptr, u->td_chunk); return ret; } @@ -384,7 +372,7 @@ grub_alloc_td (struct grub_uhci *u) static void grub_free_td (struct grub_uhci *u, grub_uhci_td_t td) { - td->linkptr = (grub_uint32_t) (grub_addr_t) u->tdfree; + td->linkptr = grub_dma_virt2phys (u->tdfree, u->td_chunk); u->tdfree = td; } @@ -394,7 +382,7 @@ grub_free_queue (struct grub_uhci *u, grub_uhci_qh_t qh, grub_uhci_td_t td, { int i; /* Index of TD in transfer */ - u->qh_busy[qh - u->qh] = 0; + u->qh_busy[qh - u->qh_virt] = 0; *actual = 0; @@ -411,7 +399,7 @@ grub_free_queue (struct grub_uhci *u, grub_uhci_qh_t qh, grub_uhci_td_t td, /* Unlink the queue. */ tdprev = td; - td = (grub_uhci_td_t) (grub_addr_t) td->linkptr2; + td = grub_dma_phys2virt (td->linkptr2, u->td_chunk); /* Free the TD. */ grub_free_td (u, tdprev); @@ -439,7 +427,7 @@ grub_alloc_qh (struct grub_uhci *u, if (!u->qh_busy[i]) break; } - qh = &u->qh[i]; + qh = &u->qh_virt[i]; if (i == N_QH) { grub_error (GRUB_ERR_OUT_OF_MEMORY, @@ -447,7 +435,7 @@ grub_alloc_qh (struct grub_uhci *u, return NULL; } - u->qh_busy[qh - u->qh] = 1; + u->qh_busy[qh - u->qh_virt] = 1; return qh; } @@ -561,8 +549,8 @@ grub_uhci_setup_transfer (grub_usb_controller_t dev, cdata->td_first = td; else { - td_prev->linkptr2 = (grub_uint32_t) (grub_addr_t) td; - td_prev->linkptr = (grub_uint32_t) (grub_addr_t) td; + td_prev->linkptr2 = grub_dma_virt2phys (td, u->td_chunk); + td_prev->linkptr = grub_dma_virt2phys (td, u->td_chunk); td_prev->linkptr |= 4; } td_prev = td; @@ -574,7 +562,7 @@ grub_uhci_setup_transfer (grub_usb_controller_t dev, /* Link it into the queue and terminate. Now the transaction can take place. */ - cdata->qh->elinkptr = (grub_uint32_t) (grub_addr_t) cdata->td_first; + cdata->qh->elinkptr = grub_dma_virt2phys (cdata->td_first, u->td_chunk); grub_dprintf ("uhci", "initiate transaction\n"); @@ -594,7 +582,7 @@ grub_uhci_check_transfer (grub_usb_controller_t dev, *actual = 0; - errtd = (grub_uhci_td_t) (grub_addr_t) (cdata->qh->elinkptr & ~0x0f); + errtd = grub_dma_phys2virt (cdata->qh->elinkptr & ~0x0f, u->qh_chunk); grub_dprintf ("uhci", ">t status=0x%02x data=0x%02x td=%p\n", errtd->ctrl_status, errtd->buffer & (~15), errtd); diff --git a/grub-core/bus/usb/usb.c b/grub-core/bus/usb/usb.c index cde57ced8..fb04e6572 100644 --- a/grub-core/bus/usb/usb.c +++ b/grub-core/bus/usb/usb.c @@ -340,7 +340,7 @@ grub_usb_register_attach_hook_class (struct grub_usb_attach_desc *desc) void grub_usb_unregister_attach_hook_class (struct grub_usb_attach_desc *desc) { - grub_list_remove (GRUB_AS_LIST_P (&attach_hooks), GRUB_AS_LIST (desc)); + grub_list_remove (GRUB_AS_LIST (desc)); } diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c index b59f2f51d..5fc5eba39 100644 --- a/grub-core/bus/usb/usbhub.c +++ b/grub-core/bus/usb/usbhub.c @@ -44,7 +44,9 @@ static struct grub_usb_hub *hubs; /* Add a device that currently has device number 0 and resides on CONTROLLER, the Hub reported that the device speed is SPEED. */ static grub_usb_device_t -grub_usb_hub_add_dev (grub_usb_controller_t controller, grub_usb_speed_t speed) +grub_usb_hub_add_dev (grub_usb_controller_t controller, + grub_usb_speed_t speed, + int port, int hubaddr) { grub_usb_device_t dev; int i; @@ -56,6 +58,8 @@ grub_usb_hub_add_dev (grub_usb_controller_t controller, grub_usb_speed_t speed) dev->controller = *controller; dev->speed = speed; + dev->port = port; + dev->hubaddr = hubaddr; err = grub_usb_device_initialize (dev); if (err) @@ -97,6 +101,11 @@ grub_usb_hub_add_dev (grub_usb_controller_t controller, grub_usb_speed_t speed) dev->initialized = 1; grub_usb_devs[i] = dev; + 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); + /* Wait "recovery interval", spec. says 2ms */ grub_millisleep (2); @@ -158,11 +167,13 @@ grub_usb_add_hub (grub_usb_device_t dev) if ((endp->endp_addr & 128) && grub_usb_get_ep_type(endp) == GRUB_USB_EP_INTERRUPT) { + grub_size_t len; dev->hub_endpoint = endp; + len = endp->maxpacket; + if (len > sizeof (dev->statuschange)) + len = sizeof (dev->statuschange); dev->hub_transfer - = grub_usb_bulk_read_background (dev, endp->endp_addr, - grub_min (endp->maxpacket, - sizeof (dev->statuschange)), + = grub_usb_bulk_read_background (dev, endp->endp_addr, len, (char *) &dev->statuschange); break; } @@ -218,7 +229,7 @@ attach_root_port (struct grub_usb_hub *hub, int portno, grub_millisleep (10); /* Enable the port and create a device. */ - dev = grub_usb_hub_add_dev (hub->controller, speed); + dev = grub_usb_hub_add_dev (hub->controller, speed, portno, 0); hub->controller->dev->pending_reset = 0; if (! dev) return; @@ -314,7 +325,7 @@ poll_nonroot_hub (grub_usb_device_t dev) grub_usb_err_t err; unsigned i; grub_uint8_t changed; - grub_size_t actual; + grub_size_t actual, len; int j, total; if (!dev->hub_transfer) @@ -327,10 +338,11 @@ poll_nonroot_hub (grub_usb_device_t dev) changed = dev->statuschange; + len = dev->hub_endpoint->maxpacket; + if (len > sizeof (dev->statuschange)) + len = sizeof (dev->statuschange); dev->hub_transfer - = grub_usb_bulk_read_background (dev, dev->hub_endpoint->endp_addr, - grub_min (dev->hub_endpoint->maxpacket, - sizeof (dev->statuschange)), + = grub_usb_bulk_read_background (dev, dev->hub_endpoint->endp_addr, len, (char *) &dev->statuschange); if (err || actual == 0 || changed == 0) @@ -353,7 +365,7 @@ poll_nonroot_hub (grub_usb_device_t dev) 0, i, sizeof (status), (char *) &status); grub_dprintf ("usb", "dev = %p, i = %d, status = %08x\n", - dev, i, status); + dev, i, status); if (err) continue; @@ -472,7 +484,7 @@ poll_nonroot_hub (grub_usb_device_t dev) grub_millisleep (10); /* Add the device and assign a device address to it. */ - next_dev = grub_usb_hub_add_dev (&dev->controller, speed); + next_dev = grub_usb_hub_add_dev (&dev->controller, speed, i, dev->addr); dev->controller.dev->pending_reset = 0; if (! next_dev) continue; diff --git a/grub-core/commands/acpi.c b/grub-core/commands/acpi.c index 8f4429627..57e7003f4 100644 --- a/grub-core/commands/acpi.c +++ b/grub-core/commands/acpi.c @@ -33,6 +33,8 @@ #include #endif +#pragma GCC diagnostic ignored "-Wcast-align" + GRUB_MOD_LICENSE ("GPLv3+"); static const struct grub_arg_option options[] = { @@ -41,8 +43,8 @@ static const struct grub_arg_option options[] = { 0, ARG_TYPE_STRING}, {"load-only", 'n', 0, N_("Load only tables specified by comma-separated list."), 0, ARG_TYPE_STRING}, - {"v1", '1', 0, N_("Expose v1 tables."), 0, ARG_TYPE_NONE}, - {"v2", '2', 0, N_("Expose v2 and v3 tables."), 0, ARG_TYPE_NONE}, + {"v1", '1', 0, N_("Export version 1 tables to the OS."), 0, ARG_TYPE_NONE}, + {"v2", '2', 0, N_("Export version 2 and version 3 tables to the OS."), 0, ARG_TYPE_NONE}, {"oemid", 'o', 0, N_("Set OEMID of RSDP, XSDT and RSDT."), 0, ARG_TYPE_STRING}, {"oemtable", 't', 0, N_("Set OEMTABLE ID of RSDP, XSDT and RSDT."), 0, ARG_TYPE_STRING}, @@ -138,6 +140,7 @@ iszero (grub_uint8_t *reg, int size) return 1; } +#if defined (__i386__) || defined (__x86_64__) grub_err_t grub_acpi_create_ebda (void) { @@ -165,7 +168,7 @@ grub_acpi_create_ebda (void) return 0; } - ebda = (grub_uint8_t *) UINT_TO_PTR ((*((grub_uint16_t *)0x40e)) << 4); + ebda = (grub_uint8_t *) (grub_addr_t) ((*((grub_uint16_t *)0x40e)) << 4); ebda_kb_len = *(grub_uint16_t *) ebda; if (! ebda || ebda_kb_len > 16) ebda_kb_len = 0; @@ -173,14 +176,14 @@ grub_acpi_create_ebda (void) /* FIXME: use low-memory mm allocation once it's available. */ grub_mmap_iterate (find_hook); - targetebda = (grub_uint8_t *) UINT_TO_PTR (highestlow); + targetebda = (grub_uint8_t *) (grub_addr_t) highestlow; grub_dprintf ("acpi", "creating ebda @%llx\n", (unsigned long long) highestlow); if (! highestlow) return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't find space for the new EBDA"); - mmapregion = grub_mmap_register (PTR_TO_UINT64 (targetebda), ebda_len, + mmapregion = grub_mmap_register ((grub_addr_t) targetebda, ebda_len, GRUB_MEMORY_RESERVED); if (! mmapregion) return grub_errno; @@ -297,6 +300,7 @@ grub_acpi_create_ebda (void) return GRUB_ERR_NONE; } +#endif /* Create tables common to ACPIv1 and ACPIv2+ */ static void @@ -328,13 +332,13 @@ setup_common_tables (void) if (grub_memcmp (fadt->hdr.signature, GRUB_ACPI_FADT_SIGNATURE, sizeof (fadt->hdr.signature)) == 0) { - fadt->dsdt_addr = PTR_TO_UINT32 (table_dsdt); + fadt->dsdt_addr = (grub_addr_t) table_dsdt; fadt->facs_addr = facs_addr; /* Does a revision 2 exist at all? */ if (fadt->hdr.revision >= 3) { - fadt->dsdt_xaddr = PTR_TO_UINT64 (table_dsdt); + fadt->dsdt_xaddr = (grub_addr_t) table_dsdt; fadt->facs_xaddr = facs_addr; } @@ -365,7 +369,7 @@ setup_common_tables (void) rsdt->creator_rev = root_creator_rev; for (cur = acpi_tables; cur; cur = cur->next) - *(rsdt_entry++) = PTR_TO_UINT32 (cur->addr); + *(rsdt_entry++) = (grub_addr_t) cur->addr; /* Recompute checksum. */ rsdt->checksum = 0; @@ -383,7 +387,7 @@ setv1table (void) sizeof (rsdpv1_new->signature)); grub_memcpy (&(rsdpv1_new->oemid), root_oemid, sizeof (rsdpv1_new->oemid)); rsdpv1_new->revision = 0; - rsdpv1_new->rsdt_addr = PTR_TO_UINT32 (rsdt_addr); + rsdpv1_new->rsdt_addr = (grub_addr_t) rsdt_addr; rsdpv1_new->checksum = 0; rsdpv1_new->checksum = 1 + ~grub_byte_checksum (rsdpv1_new, sizeof (*rsdpv1_new)); @@ -408,7 +412,7 @@ setv2table (void) xsdt_entry = (grub_uint64_t *)(xsdt + 1); for (cur = acpi_tables; cur; cur = cur->next) - *(xsdt_entry++) = PTR_TO_UINT64 (cur->addr); + *(xsdt_entry++) = (grub_addr_t) cur->addr; grub_memcpy (&(xsdt->signature), "XSDT", 4); xsdt->length = sizeof (struct grub_acpi_table_header) + 8 * numoftables; xsdt->revision = 1; @@ -428,12 +432,12 @@ setv2table (void) grub_memcpy (&(rsdpv2_new->rsdpv1.oemid), root_oemid, sizeof (rsdpv2_new->rsdpv1.oemid)); rsdpv2_new->rsdpv1.revision = rev2; - rsdpv2_new->rsdpv1.rsdt_addr = PTR_TO_UINT32 (rsdt_addr); + rsdpv2_new->rsdpv1.rsdt_addr = (grub_addr_t) rsdt_addr; rsdpv2_new->rsdpv1.checksum = 0; rsdpv2_new->rsdpv1.checksum = 1 + ~grub_byte_checksum (&(rsdpv2_new->rsdpv1), sizeof (rsdpv2_new->rsdpv1)); rsdpv2_new->length = sizeof (*rsdpv2_new); - rsdpv2_new->xsdt_addr = PTR_TO_UINT64 (xsdt); + rsdpv2_new->xsdt_addr = (grub_addr_t) xsdt; rsdpv2_new->checksum = 0; rsdpv2_new->checksum = 1 + ~grub_byte_checksum (rsdpv2_new, rsdpv2_new->length); @@ -463,7 +467,6 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) struct grub_arg_list *state = ctxt->state; struct grub_acpi_rsdp_v10 *rsdp; struct efiemu_acpi_table *cur, *t; - grub_err_t err; int i, mmapregion; int numoftables; @@ -506,7 +509,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) /* Set revision variables to replicate the same version as host. */ rev1 = ! rsdp->revision; rev2 = rsdp->revision; - rsdt = (struct grub_acpi_table_header *) UINT_TO_PTR (rsdp->rsdt_addr); + rsdt = (struct grub_acpi_table_header *) (grub_addr_t) rsdp->rsdt_addr; /* Load host tables. */ for (entry_ptr = (grub_uint32_t *) (rsdt + 1); entry_ptr < (grub_uint32_t *) (((grub_uint8_t *) rsdt) @@ -516,7 +519,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) char signature[5]; struct efiemu_acpi_table *table; struct grub_acpi_table_header *curtable - = (struct grub_acpi_table_header *) UINT_TO_PTR (*entry_ptr); + = (struct grub_acpi_table_header *) (grub_addr_t) *entry_ptr; signature[4] = 0; for (i = 0; i < 4;i++) signature[i] = grub_tolower (curtable->signature[i]); @@ -540,7 +543,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) /* Load DSDT if not excluded. */ dsdt = (struct grub_acpi_table_header *) - UINT_TO_PTR (fadt->dsdt_addr); + (grub_addr_t) fadt->dsdt_addr; if (dsdt && (! exclude || ! grub_strword (exclude, "dsdt")) && (! load_only || grub_strword (load_only, "dsdt")) && dsdt->length >= sizeof (*dsdt)) @@ -552,8 +555,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) free_tables (); grub_free (exclude); grub_free (load_only); - return grub_error (GRUB_ERR_OUT_OF_MEMORY, - "couldn't allocate table"); + return grub_errno; } grub_memcpy (table_dsdt, dsdt, dsdt->length); } @@ -579,8 +581,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) free_tables (); grub_free (exclude); grub_free (load_only); - return grub_error (GRUB_ERR_OUT_OF_MEMORY, - "couldn't allocate table structure"); + return grub_errno; } table->size = curtable->length; table->addr = grub_malloc (table->size); @@ -588,8 +589,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) if (! table->addr) { free_tables (); - return grub_error (GRUB_ERR_OUT_OF_MEMORY, - "couldn't allocate table"); + return grub_errno; } table->next = acpi_tables; acpi_tables = table; @@ -632,7 +632,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) if (! file) { free_tables (); - return grub_error (GRUB_ERR_BAD_OS, "couldn't open file %s", args[i]); + return grub_errno; } size = grub_file_size (file); @@ -640,7 +640,8 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) { grub_file_close (file); free_tables (); - return grub_error (GRUB_ERR_BAD_OS, "file %s is too small", args[i]); + return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + args[i]); } buf = (char *) grub_malloc (size); @@ -648,15 +649,17 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) { grub_file_close (file); free_tables (); - return grub_error (GRUB_ERR_OUT_OF_MEMORY, - "couldn't read file %s", args[i]); + return grub_errno; } if (grub_file_read (file, buf, size) != (int) size) { grub_file_close (file); free_tables (); - return grub_error (GRUB_ERR_BAD_OS, "couldn't read file %s", args[i]); + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + args[i]); + return grub_errno; } grub_file_close (file); @@ -675,8 +678,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) if (! table) { free_tables (); - return grub_error (GRUB_ERR_OUT_OF_MEMORY, - "couldn't allocate table structure"); + return grub_errno; } table->size = size; @@ -732,13 +734,20 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) } acpi_tables = 0; - if (! state[9].set && (err = grub_acpi_create_ebda ())) +#if defined (__i386__) || defined (__x86_64__) + if (! state[9].set) { - rsdpv1_new = 0; - rsdpv2_new = 0; - grub_mmap_free_and_unregister (mmapregion); - return err; + grub_err_t err; + err = grub_acpi_create_ebda (); + if (err) + { + rsdpv1_new = 0; + rsdpv2_new = 0; + grub_mmap_free_and_unregister (mmapregion); + return err; + } } +#endif #ifdef GRUB_MACHINE_EFI { @@ -761,7 +770,7 @@ GRUB_MOD_INIT(acpi) { cmd = grub_register_extcmd ("acpi", grub_cmd_acpi, 0, N_("[-1|-2] [--exclude=TABLE1,TABLE2|" - "--load-only=table1,table2] FILE1" + "--load-only=TABLE1,TABLE2] FILE1" " [FILE2] [...]"), N_("Load host ACPI tables and tables " "specified by arguments."), diff --git a/grub-core/commands/blocklist.c b/grub-core/commands/blocklist.c index 5eb12e434..164a6fea3 100644 --- a/grub-core/commands/blocklist.c +++ b/grub-core/commands/blocklist.c @@ -82,7 +82,7 @@ grub_cmd_blocklist (grub_command_t cmd __attribute__ ((unused)), } if (argc < 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); grub_file_filter_disable_compression (); file = grub_file_open (args[0]); diff --git a/grub-core/commands/boot.c b/grub-core/commands/boot.c index 7714011bf..f27cb4266 100644 --- a/grub-core/commands/boot.c +++ b/grub-core/commands/boot.c @@ -31,17 +31,17 @@ static grub_err_t (*grub_loader_boot_func) (void); static grub_err_t (*grub_loader_unload_func) (void); static int grub_loader_noreturn; -struct grub_preboot_t +struct grub_preboot { grub_err_t (*preboot_func) (int); grub_err_t (*preboot_rest_func) (void); grub_loader_preboot_hook_prio_t prio; - struct grub_preboot_t *next; - struct grub_preboot_t *prev; + struct grub_preboot *next; + struct grub_preboot *prev; }; static int grub_loader_loaded; -static struct grub_preboot_t *preboots_head = 0, +static struct grub_preboot *preboots_head = 0, *preboots_tail = 0; int @@ -51,23 +51,20 @@ grub_loader_is_loaded (void) } /* Register a preboot hook. */ -void * +struct grub_preboot * grub_loader_register_preboot_hook (grub_err_t (*preboot_func) (int noreturn), grub_err_t (*preboot_rest_func) (void), grub_loader_preboot_hook_prio_t prio) { - struct grub_preboot_t *cur, *new_preboot; + struct grub_preboot *cur, *new_preboot; if (! preboot_func && ! preboot_rest_func) return 0; - new_preboot = (struct grub_preboot_t *) - grub_malloc (sizeof (struct grub_preboot_t)); + new_preboot = (struct grub_preboot *) + grub_malloc (sizeof (struct grub_preboot)); if (! new_preboot) - { - grub_error (GRUB_ERR_OUT_OF_MEMORY, "hook not added"); - return 0; - } + return 0; new_preboot->preboot_func = preboot_func; new_preboot->preboot_rest_func = preboot_rest_func; @@ -96,9 +93,9 @@ grub_loader_register_preboot_hook (grub_err_t (*preboot_func) (int noreturn), } void -grub_loader_unregister_preboot_hook (void *hnd) +grub_loader_unregister_preboot_hook (struct grub_preboot *hnd) { - struct grub_preboot_t *preb = hnd; + struct grub_preboot *preb = hnd; if (preb->next) preb->next->prev = preb->prev; @@ -143,10 +140,11 @@ grub_err_t grub_loader_boot (void) { grub_err_t err = GRUB_ERR_NONE; - struct grub_preboot_t *cur; + struct grub_preboot *cur; if (! grub_loader_loaded) - return grub_error (GRUB_ERR_NO_KERNEL, "no loaded kernel"); + return grub_error (GRUB_ERR_NO_KERNEL, + N_("you need to load the kernel first")); if (grub_loader_noreturn) grub_machine_fini (); diff --git a/grub-core/commands/cacheinfo.c b/grub-core/commands/cacheinfo.c index 92aaa218d..ead6ff82c 100644 --- a/grub-core/commands/cacheinfo.c +++ b/grub-core/commands/cacheinfo.c @@ -31,14 +31,16 @@ grub_rescue_cmd_info (struct grub_command *cmd __attribute__ ((unused)), unsigned long hits, misses; grub_disk_cache_get_performance (&hits, &misses); - grub_printf_ (N_("Disk cache: hits = %lu, misses = %lu "), hits, misses); if (hits + misses) { unsigned long ratio = hits * 10000 / (hits + misses); grub_printf ("(%lu.%lu%%)\n", ratio / 100, ratio % 100); + grub_printf_ (N_("Disk cache statistics: hits = %lu (%lu.%02lu%%)," + " misses = %lu\n"), ratio / 100, ratio % 100, + hits, misses); } else - grub_puts_ (N_("(N/A)")); + grub_printf ("%s\n", _("No disk cache statistics available\n")); return 0; } diff --git a/grub-core/commands/cat.c b/grub-core/commands/cat.c index 9be6cbc8f..7dccce823 100644 --- a/grub-core/commands/cat.c +++ b/grub-core/commands/cat.c @@ -41,13 +41,13 @@ grub_cmd_cat (grub_extcmd_context_t ctxt, int argc, char **args) grub_file_t file; char buf[GRUB_DISK_SECTOR_SIZE]; grub_ssize_t size; - int key = 0; + int key = GRUB_TERM_NO_KEY; if (state[0].set) dos = 1; if (argc != 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); file = grub_file_open (args[0]); if (! file) @@ -77,8 +77,7 @@ grub_cmd_cat (grub_extcmd_context_t ctxt, int argc, char **args) } } - while (grub_checkkey () >= 0 && - (key = grub_getkey ()) != GRUB_TERM_ESC) + while ((key = grub_getkey_noblock ()) != GRUB_TERM_ESC) ; } diff --git a/grub-core/commands/cmp.c b/grub-core/commands/cmp.c index 5d5925dd5..cc23ee67e 100644 --- a/grub-core/commands/cmp.c +++ b/grub-core/commands/cmp.c @@ -40,7 +40,7 @@ grub_cmd_cmp (grub_command_t cmd __attribute__ ((unused)), char *buf2 = 0; if (argc != 2) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "two arguments required"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected")); grub_printf_ (N_("Compare file `%s' with `%s':\n"), args[0], args[1]); diff --git a/grub-core/commands/configfile.c b/grub-core/commands/configfile.c index 124a09a9e..17ab397bf 100644 --- a/grub-core/commands/configfile.c +++ b/grub-core/commands/configfile.c @@ -32,7 +32,7 @@ grub_cmd_source (grub_command_t cmd, int argc, char **args) int new_env, extractor; if (argc != 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); extractor = (cmd->name[0] == 'e'); new_env = (cmd->name[extractor ? sizeof ("extract_entries_") - 1 : 0] == 'c'); diff --git a/grub-core/commands/efi/loadbios.c b/grub-core/commands/efi/loadbios.c index 5eb490fd4..214adc3d2 100644 --- a/grub-core/commands/efi/loadbios.c +++ b/grub-core/commands/efi/loadbios.c @@ -165,7 +165,7 @@ grub_cmd_loadbios (grub_command_t cmd __attribute__ ((unused)), int size; if (argc == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "no ROM image specified"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); if (argc > 1) { @@ -206,7 +206,9 @@ static grub_command_t cmd_fakebios, cmd_loadbios; GRUB_MOD_INIT(loadbios) { cmd_fakebios = grub_register_command ("fakebios", grub_cmd_fakebios, - 0, N_("Fake BIOS.")); + 0, N_("Create BIOS-like structures for" + " backward compatibility with" + " existing OS.")); cmd_loadbios = grub_register_command ("loadbios", grub_cmd_loadbios, N_("BIOS_DUMP [INT10_DUMP]"), diff --git a/grub-core/commands/gptsync.c b/grub-core/commands/gptsync.c index 88d4b6296..0b527e30d 100644 --- a/grub-core/commands/gptsync.c +++ b/grub-core/commands/gptsync.c @@ -133,7 +133,8 @@ grub_cmd_gptsync (grub_command_t cmd __attribute__ ((unused)), if (! partition) { grub_device_close (dev); - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such partition"); + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, + N_("no such partition")); } if (partition->start + partition->len > 0xffffffff) diff --git a/grub-core/commands/halt.c b/grub-core/commands/halt.c index 317f7753f..f8596ecdc 100644 --- a/grub-core/commands/halt.c +++ b/grub-core/commands/halt.c @@ -24,13 +24,12 @@ GRUB_MOD_LICENSE ("GPLv3+"); -static grub_err_t +static grub_err_t __attribute__ ((noreturn)) grub_cmd_halt (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { grub_halt (); - return 0; } static grub_command_t cmd; diff --git a/grub-core/commands/hashsum.c b/grub-core/commands/hashsum.c index fb737c2f8..9593becc9 100644 --- a/grub-core/commands/hashsum.c +++ b/grub-core/commands/hashsum.c @@ -30,8 +30,9 @@ GRUB_MOD_LICENSE ("GPLv3+"); static const struct grub_arg_option options[] = { {"hash", 'h', 0, N_("Specify hash to use."), N_("HASH"), ARG_TYPE_STRING}, - {"check", 'c', 0, N_("Check hash list file."), N_("FILE"), ARG_TYPE_STRING}, - {"prefix", 'p', 0, N_("Base directory for hash list."), N_("DIRECTORY"), + {"check", 'c', 0, N_("Check hashes of files with hash list FILE."), + N_("FILE"), ARG_TYPE_STRING}, + {"prefix", 'p', 0, N_("Base directory for hash list."), N_("DIR"), ARG_TYPE_STRING}, {"keep-going", 'k', 0, N_("Don't stop after first error."), 0, 0}, {"uncompress", 'u', 0, N_("Uncompress file before checksumming."), 0, 0}, diff --git a/grub-core/commands/hdparm.c b/grub-core/commands/hdparm.c index 240170734..d1e2178c4 100644 --- a/grub-core/commands/hdparm.c +++ b/grub-core/commands/hdparm.c @@ -47,7 +47,7 @@ static const struct grub_arg_option options[] = { {"sleep", 'Y', 0, N_("Set drive to sleep mode."), 0, ARG_TYPE_NONE}, {"identify", 'i', 0, N_("Print drive identity and settings."), 0, ARG_TYPE_NONE}, - {"dumpid", 'I', 0, N_("Dump contents of ATA IDENTIFY sector."), + {"dumpid", 'I', 0, N_("Show raw contents of ATA IDENTIFY sector."), 0, ARG_TYPE_NONE}, {"smart", -1, 0, N_("Disable/enable SMART (0/1)."), 0, ARG_TYPE_INT}, {"quiet", 'q', 0, N_("Do not print messages."), 0, ARG_TYPE_NONE}, @@ -165,22 +165,20 @@ grub_hdparm_set_val_cmd (const char * msg, int val, } static const char * -le16_to_char (char *dest, const grub_uint16_t * src16, unsigned bytes) +le16_to_char (grub_uint16_t *dest, const grub_uint16_t * src16, unsigned bytes) { - grub_uint16_t * dest16 = (grub_uint16_t *) dest; unsigned i; for (i = 0; i < bytes / 2; i++) - dest16[i] = grub_be_to_cpu16 (src16[i]); - return dest; + dest[i] = grub_be_to_cpu16 (src16[i]); + dest[i] = 0; + return (char *) dest; } static void -grub_hdparm_print_identify (const char * idbuf) +grub_hdparm_print_identify (const grub_uint16_t * idw) { - const grub_uint16_t * idw = (const grub_uint16_t *) idbuf; - /* Print identity strings. */ - char tmp[40]; + grub_uint16_t tmp[21]; grub_printf ("Model: \"%.40s\"\n", le16_to_char (tmp, &idw[27], 40)); grub_printf ("Firmware: \"%.8s\"\n", le16_to_char (tmp, &idw[23], 8)); grub_printf ("Serial: \"%.20s\"\n", le16_to_char (tmp, &idw[10], 20)); @@ -277,19 +275,25 @@ static int get_int_arg (const struct grub_arg_list *state) } static grub_err_t -grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state???? +grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) { struct grub_arg_list *state = ctxt->state; struct grub_ata *ata; + const char *diskname; /* Check command line. */ if (argc != 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing device name argument"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); - grub_size_t len = grub_strlen (args[0]); - if (! (args[0][0] == '(' && args[0][len - 1] == ')')) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "argument is not a device name"); - args[0][len - 1] = 0; + if (args[0][0] == '(') + { + grub_size_t len = grub_strlen (args[0]); + if (args[0][len - 1] == ')') + args[0][len - 1] = 0; + diskname = &args[0][1]; + } + else + diskname = &args[0][0]; int i = 0; int apm = get_int_arg (&state[i++]); @@ -306,16 +310,10 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state???? quiet = state[i++].set; /* Open disk. */ - grub_disk_t disk = grub_disk_open (&args[0][1]); + grub_disk_t disk = grub_disk_open (diskname); if (! disk) return grub_errno; - if (disk->partition) - { - grub_disk_close (disk); - return grub_error (GRUB_ERR_BAD_ARGUMENT, "partition not allowed"); - } - switch (disk->dev->id) { case GRUB_DISK_DEVICE_ATA_ID: @@ -377,7 +375,7 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state???? /* Print/dump IDENTIFY. */ if (ident || dumpid) { - char buf[GRUB_DISK_SECTOR_SIZE]; + grub_uint16_t buf[GRUB_DISK_SECTOR_SIZE / 2]; if (grub_hdparm_do_ata_cmd (ata, GRUB_ATA_CMD_IDENTIFY_DEVICE, 0, 0, buf, sizeof (buf))) grub_printf ("Cannot read ATA IDENTIFY data\n"); @@ -386,7 +384,7 @@ grub_cmd_hdparm (grub_extcmd_context_t ctxt, int argc, char **args) // state???? if (ident) grub_hdparm_print_identify (buf); if (dumpid) - hexdump (0, buf, sizeof (buf)); + hexdump (0, (char *) buf, sizeof (buf)); } } diff --git a/grub-core/commands/help.c b/grub-core/commands/help.c index 82f3200c7..f33e55635 100644 --- a/grub-core/commands/help.c +++ b/grub-core/commands/help.c @@ -47,7 +47,7 @@ grub_cmd_help (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc, char *command_help; grub_uint32_t *unicode_command_help; grub_uint32_t *unicode_last_position; - + command_help = grub_xasprintf ("%s %s", cmd->name, summary_translated); if (!command_help) break; @@ -99,28 +99,37 @@ grub_cmd_help (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc, else { int i; - grub_command_t cmd; + grub_command_t cmd_iter, cmd; for (i = 0; i < argc; i++) { currarg = args[i]; - FOR_COMMANDS(cmd) + FOR_COMMANDS(cmd_iter) { - if (cmd->prio & GRUB_PRIO_LIST_FLAG_ACTIVE) - { - if (! grub_strncmp (cmd->name, currarg, grub_strlen (currarg))) - { - if (cnt++ > 0) - grub_printf ("\n\n"); + if (!(cmd_iter->prio & GRUB_PRIO_LIST_FLAG_ACTIVE)) + continue; - if ((cmd->flags & GRUB_COMMAND_FLAG_EXTCMD) && - ! (cmd->flags & GRUB_COMMAND_FLAG_DYNCMD)) - grub_arg_show_help ((grub_extcmd_t) cmd->data); - else - grub_printf ("%s %s %s\n%s\n", _("Usage:"), cmd->name, _(cmd->summary), - _(cmd->description)); - } + if (grub_strncmp (cmd_iter->name, currarg, + grub_strlen (currarg)) != 0) + continue; + if (cmd_iter->flags & GRUB_COMMAND_FLAG_DYNCMD) + cmd = grub_dyncmd_get_cmd (cmd_iter); + else + cmd = cmd_iter; + if (!cmd) + { + grub_print_error (); + continue; } + if (cnt++ > 0) + grub_printf ("\n\n"); + + if ((cmd->flags & GRUB_COMMAND_FLAG_EXTCMD) && + ! (cmd->flags & GRUB_COMMAND_FLAG_DYNCMD)) + grub_arg_show_help ((grub_extcmd_t) cmd->data); + else + grub_printf ("%s %s %s\n%s\n", _("Usage:"), cmd->name, + _(cmd->summary), _(cmd->description)); } } } diff --git a/grub-core/commands/hexdump.c b/grub-core/commands/hexdump.c index 9ba83598a..4c884b3a1 100644 --- a/grub-core/commands/hexdump.c +++ b/grub-core/commands/hexdump.c @@ -44,7 +44,7 @@ grub_cmd_hexdump (grub_extcmd_context_t ctxt, int argc, char **args) int namelen; if (argc != 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); namelen = grub_strlen (args[0]); skip = (state[0].set) ? grub_strtoull (state[0].arg, 0, 0) : 0; @@ -123,7 +123,7 @@ GRUB_MOD_INIT (hexdump) { cmd = grub_register_extcmd ("hexdump", grub_cmd_hexdump, 0, N_("[OPTIONS] FILE_OR_DEVICE"), - N_("Dump the contents of a file or memory."), + N_("Show raw contents of a file or memory."), options); } diff --git a/grub-core/commands/i386/cmostest.c b/grub-core/commands/i386/cmostest.c index 6a4290155..d2a184026 100644 --- a/grub-core/commands/i386/cmostest.c +++ b/grub-core/commands/i386/cmostest.c @@ -30,11 +30,11 @@ parse_args (int argc, char *argv[], int *byte, int *bit) char *rest; if (argc != 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "Address required."); + return grub_error (GRUB_ERR_BAD_ARGUMENT, "address required"); *byte = grub_strtoul (argv[0], &rest, 0); if (*rest != ':') - return grub_error (GRUB_ERR_BAD_ARGUMENT, "Address required."); + return grub_error (GRUB_ERR_BAD_ARGUMENT, "address required"); *bit = grub_strtoul (rest + 1, 0, 0); @@ -60,7 +60,7 @@ grub_cmd_cmostest (struct grub_command *cmd __attribute__ ((unused)), if (value & (1 << bit)) return GRUB_ERR_NONE; - return grub_error (GRUB_ERR_TEST_FAILURE, "false"); + return grub_error (GRUB_ERR_TEST_FAILURE, N_("false")); } static grub_err_t diff --git a/grub-core/commands/i386/cpuid.c b/grub-core/commands/i386/cpuid.c index 6a771ba74..f2f250bb6 100644 --- a/grub-core/commands/i386/cpuid.c +++ b/grub-core/commands/i386/cpuid.c @@ -50,7 +50,9 @@ grub_cmd_cpuid (grub_extcmd_context_t ctxt __attribute__ ((unused)), char **args __attribute__ ((unused))) { return grub_cpuid_has_longmode ? GRUB_ERR_NONE - : grub_error (GRUB_ERR_TEST_FAILURE, "false"); + /* TRANSLATORS: it's a standalone boolean value, + opposite of "true". */ + : grub_error (GRUB_ERR_TEST_FAILURE, N_("false")); } static grub_extcmd_t cmd; diff --git a/grub-core/commands/i386/pc/drivemap.c b/grub-core/commands/i386/pc/drivemap.c index 4f752bed5..c19c9ef62 100644 --- a/grub-core/commands/i386/pc/drivemap.c +++ b/grub-core/commands/i386/pc/drivemap.c @@ -32,7 +32,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); /* Real mode IVT slot (seg:off far pointer) for interrupt 0x13. */ -static grub_uint32_t *const int13slot = UINT_TO_PTR (4 * 0x13); +static grub_uint32_t *const int13slot = (grub_uint32_t *) (4 * 0x13); /* Remember to update enum opt_idxs accordingly. */ static const struct grub_arg_option options[] = { @@ -107,8 +107,7 @@ drivemap_set (grub_uint8_t newdrive, grub_uint8_t redirto) { mapping = grub_malloc (sizeof (drivemap_node_t)); if (! mapping) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, - "cannot allocate map entry, not enough memory"); + return grub_errno; mapping->newdrive = newdrive; mapping->redirto = redirto; mapping->next = map_head; @@ -230,7 +229,7 @@ grub_cmd_drivemap (struct grub_extcmd_context *ctxt, int argc, char **args) grub_err_t err; if (argc != 2) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "two arguments required"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected")); err = tryparse_diskstring (args[0], &mapfrom); if (err != GRUB_ERR_NONE) diff --git a/grub-core/commands/i386/pc/lsapm.c b/grub-core/commands/i386/pc/lsapm.c index 45b43b242..c82476df1 100644 --- a/grub-core/commands/i386/pc/lsapm.c +++ b/grub-core/commands/i386/pc/lsapm.c @@ -72,9 +72,9 @@ grub_cmd_lsapm (grub_command_t cmd __attribute__ ((unused)), { struct grub_apm_info info; if (!grub_apm_get_info (&info)) - return grub_error (GRUB_ERR_IO, "no APM found"); + return grub_error (GRUB_ERR_IO, N_("no APM found")); - grub_printf_ (N_("Vesion %u.%u\n" + grub_printf_ (N_("Version %u.%u\n" "32-bit CS = 0x%x, len = 0x%x, offset = 0x%x\n" "16-bit CS = 0x%x, len = 0x%x\n" "DS = 0x%x, len = 0x%x\n"), diff --git a/grub-core/commands/i386/pc/play.c b/grub-core/commands/i386/pc/play.c index 1adf296ec..6ca17a181 100644 --- a/grub-core/commands/i386/pc/play.c +++ b/grub-core/commands/i386/pc/play.c @@ -151,7 +151,7 @@ play (unsigned tempo, struct note *note) { unsigned int to; - if (note->pitch == T_FINE || grub_checkkey () >= 0) + if (note->pitch == T_FINE || grub_getkey_noblock () != GRUB_TERM_NO_KEY) return 1; grub_dprintf ("play", "pitch = %d, duration = %d\n", note->pitch, @@ -169,7 +169,8 @@ play (unsigned tempo, struct note *note) } to = grub_get_rtc () + BASE_TEMPO * note->duration / tempo; - while (((unsigned int) grub_get_rtc () <= to) && (grub_checkkey () < 0)) + while (((unsigned int) grub_get_rtc () <= to) + && (grub_getkey_noblock () == GRUB_TERM_NO_KEY)) ; return 0; @@ -181,7 +182,8 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)), { if (argc < 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name or tempo and notes required"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("filename or tempo and notes expected")); if (argc == 1) { @@ -192,13 +194,15 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)), file = grub_file_open (args[0]); if (! file) - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", args[0]); + return grub_errno; if (grub_file_read (file, &tempo, sizeof (tempo)) != sizeof (tempo)) { grub_file_close (file); - return grub_error (GRUB_ERR_FILE_READ_ERROR, - "file doesn't even contains a full tempo record"); + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), + args[0]); + return grub_errno; } tempo = grub_le_to_cpu32 (tempo); @@ -227,23 +231,27 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)), if (*end) /* Was not a number either, assume it was supposed to be a file name. */ - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", args[0]); + return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), args[0]); grub_dprintf ("play","tempo = %d\n", tempo); for (i = 1; i + 1 < argc; i += 2) { note.pitch = grub_strtoul (args[i], &end, 0); + if (grub_errno) + break; if (*end) { - grub_error (GRUB_ERR_BAD_NUMBER, "bogus pitch number"); + grub_error (GRUB_ERR_BAD_NUMBER, N_("unrecognized number")); break; } note.duration = grub_strtoul (args[i + 1], &end, 0); + if (grub_errno) + break; if (*end) { - grub_error (GRUB_ERR_BAD_NUMBER, "bogus duration number"); + grub_error (GRUB_ERR_BAD_NUMBER, N_("unrecognized number")); break; } @@ -254,9 +262,6 @@ grub_cmd_play (grub_command_t cmd __attribute__ ((unused)), beep_off (); - while (grub_checkkey () > 0) - grub_getkey (); - return 0; } diff --git a/grub-core/commands/i386/pc/sendkey.c b/grub-core/commands/i386/pc/sendkey.c index 83400c347..ab1090672 100644 --- a/grub-core/commands/i386/pc/sendkey.c +++ b/grub-core/commands/i386/pc/sendkey.c @@ -63,8 +63,8 @@ static grub_uint32_t andmask = 0xffffffff, ormask = 0; struct keysym { - char *unshifted_name; /* the name in unshifted state */ - char *shifted_name; /* the name in shifted state */ + const char *unshifted_name; /* the name in unshifted state */ + const char *shifted_name; /* the name in shifted state */ unsigned char unshifted_ascii; /* the ascii code in unshifted state */ unsigned char shifted_ascii; /* the ascii code in shifted state */ unsigned char keycode; /* keyboard scancode */ @@ -365,7 +365,7 @@ grub_cmd_sendkey (grub_extcmd_context_t ctxt, int argc, char **args) } static grub_extcmd_t cmd; -static void *preboot_hook; +static struct grub_preboot *preboot_hook; GRUB_MOD_INIT (sendkey) { diff --git a/grub-core/commands/ieee1275/suspend.c b/grub-core/commands/ieee1275/suspend.c index 844485077..49daaba08 100644 --- a/grub-core/commands/ieee1275/suspend.c +++ b/grub-core/commands/ieee1275/suspend.c @@ -42,7 +42,7 @@ static grub_command_t cmd; GRUB_MOD_INIT(ieee1275_suspend) { cmd = grub_register_command ("suspend", grub_cmd_suspend, - 0, N_("Return to Open Firmware prompt.")); + 0, N_("Return to IEEE1275 prompt.")); } GRUB_MOD_FINI(ieee1275_suspend) diff --git a/grub-core/commands/iorw.c b/grub-core/commands/iorw.c index e7035b528..2a06e976d 100644 --- a/grub-core/commands/iorw.c +++ b/grub-core/commands/iorw.c @@ -44,7 +44,7 @@ grub_cmd_read (grub_extcmd_context_t ctxt, int argc, char **argv) grub_uint32_t value = 0; if (argc != 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid number of arguments"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); addr = grub_strtoul (argv[0], 0, 0); switch (ctxt->extcmd->cmd->name[sizeof ("in") - 1]) @@ -82,7 +82,7 @@ grub_cmd_write (grub_command_t cmd, int argc, char **argv) grub_uint32_t mask = 0xffffffff; if (argc != 2 && argc != 3) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid number of arguments"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected")); addr = grub_strtoul (argv[0], 0, 0); value = grub_strtoul (argv[1], 0, 0); @@ -120,25 +120,28 @@ GRUB_MOD_INIT(memrw) { cmd_read_byte = grub_register_extcmd ("inb", grub_cmd_read, 0, - N_("PORT"), N_("Read byte from PORT."), options); + N_("PORT"), N_("Read 8-bit value from PORT."), + options); cmd_read_word = grub_register_extcmd ("inw", grub_cmd_read, 0, - N_("PORT"), N_("Read word from PORT."), options); + N_("PORT"), N_("Read 16-bit value from PORT."), + options); cmd_read_dword = grub_register_extcmd ("inl", grub_cmd_read, 0, - N_("PORT"), N_("Read dword from PORT."), options); + N_("PORT"), N_("Read 32-bit value from PORT."), + options); cmd_write_byte = grub_register_command ("outb", grub_cmd_write, N_("PORT VALUE [MASK]"), - N_("Write byte VALUE to PORT.")); + N_("Write 8-bit VALUE to PORT.")); cmd_write_word = grub_register_command ("outw", grub_cmd_write, N_("PORT VALUE [MASK]"), - N_("Write word VALUE to PORT.")); + N_("Write 16-bit VALUE to PORT.")); cmd_write_dword = grub_register_command ("outl", grub_cmd_write, N_("ADDR VALUE [MASK]"), - N_("Write dword VALUE to PORT.")); + N_("Write 32-bit VALUE to PORT.")); } GRUB_MOD_FINI(memrw) diff --git a/grub-core/commands/keylayouts.c b/grub-core/commands/keylayouts.c index 6c5913a54..10eeae375 100644 --- a/grub-core/commands/keylayouts.c +++ b/grub-core/commands/keylayouts.c @@ -207,7 +207,7 @@ grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)), { const char *prefix = grub_env_get ("prefix"); if (!prefix) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "No prefix set"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("variable `%s' isn't set"), "prefix"); filename = grub_xasprintf ("%s/layouts/%s.gkb", prefix, argv[0]); if (!filename) return grub_errno; @@ -222,7 +222,8 @@ grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)), if (grub_file_read (file, magic, sizeof (magic)) != sizeof (magic)) { if (!grub_errno) - grub_error (GRUB_ERR_BAD_ARGUMENT, "file is too short"); + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("premature end of file %s"), + filename); goto fail; } @@ -236,7 +237,8 @@ grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)), if (grub_file_read (file, &version, sizeof (version)) != sizeof (version)) { if (!grub_errno) - grub_error (GRUB_ERR_BAD_ARGUMENT, "file is too short"); + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("premature end of file %s"), + filename); goto fail; } @@ -253,7 +255,8 @@ grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)), if (grub_file_read (file, newmap, sizeof (*newmap)) != sizeof (*newmap)) { if (!grub_errno) - grub_error (GRUB_ERR_BAD_ARGUMENT, "file is too short"); + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("premature end of file %s"), + filename); goto fail; } diff --git a/grub-core/commands/keystatus.c b/grub-core/commands/keystatus.c index f3a669942..f4aceae89 100644 --- a/grub-core/commands/keystatus.c +++ b/grub-core/commands/keystatus.c @@ -78,11 +78,11 @@ grub_cmd_keystatus (grub_extcmd_context_t ctxt, FOR_ACTIVE_TERM_INPUTS (term) if (!term->getkeystatus) - return grub_error (GRUB_ERR_TEST_FAILURE, "false"); + return grub_error (GRUB_ERR_TEST_FAILURE, N_("false")); else nterms++; if (!nterms) - return grub_error (GRUB_ERR_TEST_FAILURE, "false"); + return grub_error (GRUB_ERR_TEST_FAILURE, N_("false")); return 0; } @@ -91,7 +91,7 @@ grub_cmd_keystatus (grub_extcmd_context_t ctxt, if (mods >= 0 && (mods & expect_mods) != 0) return 0; else - return grub_error (GRUB_ERR_TEST_FAILURE, "false"); + return grub_error (GRUB_ERR_TEST_FAILURE, N_("false")); } static grub_extcmd_t cmd; @@ -99,7 +99,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(keystatus) { cmd = grub_register_extcmd ("keystatus", grub_cmd_keystatus, 0, - N_("[--shift] [--ctrl] [--alt]"), + "[--shift] [--ctrl] [--alt]", N_("Check key modifier status."), options); } diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c index 4de2d84d5..fb06401e9 100644 --- a/grub-core/commands/legacycfg.c +++ b/grub-core/commands/legacycfg.c @@ -194,7 +194,7 @@ grub_cmd_legacy_source (struct grub_command *cmd, grub_err_t ret; if (argc != 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); extractor = (cmd->name[0] == 'e'); new_env = (cmd->name[extractor ? (sizeof ("extract_legacy_entries_") - 1) @@ -299,7 +299,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), } if (argc < 2) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "filename required"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); cutargs = grub_malloc (sizeof (cutargs[0]) * (argc - 1)); cutargc = argc - 1; @@ -411,10 +411,11 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), } else { + char rbuf[3] = "-r"; bsdargc = cutargc + 2; bsdargs = grub_malloc (sizeof (bsdargs[0]) * bsdargc); grub_memcpy (bsdargs, args, argc * sizeof (bsdargs[0])); - bsdargs[argc] = "-r"; + bsdargs[argc] = rbuf; bsdargs[argc + 1] = bsddevname; grub_snprintf (bsddevname, sizeof (bsddevname), "wd%d%c", bsd_device, @@ -453,7 +454,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), } while (0); - return grub_error (GRUB_ERR_BAD_OS, "couldn't load file %s\n", + return grub_error (GRUB_ERR_BAD_OS, "couldn't load file %s", args[0]); } @@ -467,7 +468,8 @@ grub_cmd_legacy_initrd (struct grub_command *mycmd __attribute__ ((unused)), { cmd = grub_command_find ("initrd16"); if (!cmd) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "command initrd16 not found"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"), + "initrd16"); return cmd->func (cmd, argc, args); } @@ -475,13 +477,14 @@ grub_cmd_legacy_initrd (struct grub_command *mycmd __attribute__ ((unused)), { cmd = grub_command_find ("module"); if (!cmd) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "command module not found"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"), + "module"); return cmd->func (cmd, argc, args); } return grub_error (GRUB_ERR_BAD_ARGUMENT, - "no kernel with module support is loaded in legacy way"); + N_("you need to load the kernel first")); } static grub_err_t @@ -494,7 +497,8 @@ grub_cmd_legacy_initrdnounzip (struct grub_command *mycmd __attribute__ ((unused { cmd = grub_command_find ("initrd16"); if (!cmd) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "command initrd16 not found"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"), + "initrd16"); return cmd->func (cmd, argc, args); } @@ -502,14 +506,16 @@ grub_cmd_legacy_initrdnounzip (struct grub_command *mycmd __attribute__ ((unused { char **newargs; grub_err_t err; + char nounzipbuf[10] = "--nounzip"; newargs = grub_malloc ((argc + 1) * sizeof (newargs[0])); if (!newargs) return grub_errno; grub_memcpy (newargs + 1, args, argc * sizeof (newargs[0])); - newargs[0] = "--nounzip"; + newargs[0] = nounzipbuf; cmd = grub_command_find ("module"); if (!cmd) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "command module not found"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't find command `%s'"), + "module"); err = cmd->func (cmd, argc + 1, newargs); grub_free (newargs); @@ -517,7 +523,7 @@ grub_cmd_legacy_initrdnounzip (struct grub_command *mycmd __attribute__ ((unused } return grub_error (GRUB_ERR_BAD_ARGUMENT, - "no kernel with module support is loaded in legacy way"); + N_("you need to load the kernel first")); } static grub_err_t @@ -696,7 +702,7 @@ grub_cmd_legacy_password (struct grub_command *mycmd __attribute__ ((unused)), struct legacy_md5_password *pw = NULL; if (argc == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments expected"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); if (args[0][0] != '-' || args[0][1] != '-') return grub_normal_set_password ("legacy", args[0]); @@ -722,7 +728,7 @@ grub_cmd_legacy_check_password (struct grub_command *mycmd __attribute__ ((unuse char entered[GRUB_AUTH_MAX_PASSLEN]; if (argc == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments expected"); + 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; @@ -781,26 +787,26 @@ GRUB_MOD_INIT(legacycfg) cmd_kernel = grub_register_command ("legacy_kernel", grub_cmd_legacy_kernel, N_("[--no-mem-option] [--type=TYPE] FILE [ARG ...]"), - N_("Simulate grub-legacy kernel command")); + N_("Simulate grub-legacy `kernel' command")); cmd_initrd = grub_register_command ("legacy_initrd", grub_cmd_legacy_initrd, N_("FILE [ARG ...]"), - N_("Simulate grub-legacy initrd command")); + N_("Simulate grub-legacy `initrd' command")); cmd_initrdnounzip = grub_register_command ("legacy_initrd_nounzip", grub_cmd_legacy_initrdnounzip, N_("FILE [ARG ...]"), - N_("Simulate grub-legacy modulenounzip command")); + N_("Simulate grub-legacy `modulenounzip' command")); cmd_password = grub_register_command ("legacy_password", grub_cmd_legacy_password, N_("[--md5] PASSWD [FILE]"), - N_("Simulate grub-legacy password command")); + N_("Simulate grub-legacy `password' command")); cmd_check_password = grub_register_command ("legacy_check_password", grub_cmd_legacy_check_password, N_("[--md5] PASSWD [FILE]"), - N_("Simulate grub-legacy password command in menuentry mode")); + N_("Simulate grub-legacy `password' command in menuentry mode")); } diff --git a/grub-core/commands/loadenv.c b/grub-core/commands/loadenv.c index 1073712d5..4dcb5d49a 100644 --- a/grub-core/commands/loadenv.c +++ b/grub-core/commands/loadenv.c @@ -65,7 +65,7 @@ open_envblk_file (char *filename) } else { - grub_error (GRUB_ERR_FILE_NOT_FOUND, "prefix is not found"); + grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "prefix"); return 0; } } @@ -93,8 +93,6 @@ read_envblk_file (grub_file_t file) ret = grub_file_read (file, buf + offset, size); if (ret <= 0) { - if (grub_errno == GRUB_ERR_NONE) - grub_error (GRUB_ERR_FILE_READ_ERROR, "cannot read"); grub_free (buf); return 0; } diff --git a/grub-core/commands/ls.c b/grub-core/commands/ls.c index db9307780..f36202b71 100644 --- a/grub-core/commands/ls.c +++ b/grub-core/commands/ls.c @@ -168,7 +168,7 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human) grub_free (pathname); } else - grub_printf ("%-12s", "DIR"); + grub_printf ("%-12s", _("DIR")); if (info->mtimeset) { diff --git a/grub-core/commands/lsacpi.c b/grub-core/commands/lsacpi.c index fd19e380a..4f1742b8d 100644 --- a/grub-core/commands/lsacpi.c +++ b/grub-core/commands/lsacpi.c @@ -25,6 +25,8 @@ #include #include +#pragma GCC diagnostic ignored "-Wcast-align" + GRUB_MOD_LICENSE ("GPLv3+"); static void @@ -132,11 +134,13 @@ disp_acpi_xsdt_table (struct grub_acpi_table_header *t) desc = (grub_uint64_t *) (t + 1); for (; len > 0; desc++, len -= sizeof (*desc)) { - if (sizeof (grub_addr_t) == 4 && *desc >= (1ULL << 32)) +#if GRUB_CPU_SIZEOF_VOID_P == 4 + if (*desc >= (1ULL << 32)) { grub_printf ("Unreachable table\n"); continue; } +#endif t = (struct grub_acpi_table_header *) (grub_addr_t) *desc; if (t == NULL) @@ -222,9 +226,11 @@ grub_cmd_lsacpi (struct grub_extcmd_context *ctxt, grub_printf ("No RSDPv2\n"); else { - if (sizeof (grub_addr_t) == 4 && rsdp2->xsdt_addr >= (1ULL << 32)) - grub_printf ("Unreachable RSDPv2\n"); +#if GRUB_CPU_SIZEOF_VOID_P == 4 + if (rsdp2->xsdt_addr >= (1ULL << 32)) + grub_printf ("Unreachable RSDPv2\n"); else +#endif { grub_printf ("RSDPv2 signature:"); disp_acpi_rsdpv2 (rsdp2); @@ -240,7 +246,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(lsapi) { - cmd = grub_register_extcmd ("lsacpi", grub_cmd_lsacpi, 0, N_("[-1|-2]"), + cmd = grub_register_extcmd ("lsacpi", grub_cmd_lsacpi, 0, "[-1|-2]", N_("Show ACPI information."), options); } diff --git a/grub-core/commands/lsmmap.c b/grub-core/commands/lsmmap.c index 4815fd174..260b4536d 100644 --- a/grub-core/commands/lsmmap.c +++ b/grub-core/commands/lsmmap.c @@ -26,13 +26,13 @@ GRUB_MOD_LICENSE ("GPLv3+"); static const char *names[] = { - [GRUB_MEMORY_AVAILABLE] = N_("available"), - [GRUB_MEMORY_RESERVED] = N_("reserved"), - [GRUB_MEMORY_ACPI] = N_("ACPI reclamaible"), - [GRUB_MEMORY_NVS] = N_("ACPI non-volatile storage"), - [GRUB_MEMORY_BADRAM] = N_("BadRAM"), - [GRUB_MEMORY_CODE] = N_("firmware code"), - [GRUB_MEMORY_HOLE] = N_("hole") + [GRUB_MEMORY_AVAILABLE] = N_("available RAM"), + [GRUB_MEMORY_RESERVED] = N_("reserved RAM"), + [GRUB_MEMORY_ACPI] = N_("ACPI reclaimable RAM"), + [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") }; static grub_err_t diff --git a/grub-core/commands/lspci.c b/grub-core/commands/lspci.c index 03541df6c..9f836298f 100644 --- a/grub-core/commands/lspci.c +++ b/grub-core/commands/lspci.c @@ -29,7 +29,7 @@ struct grub_pci_classname { int class; int subclass; - char *desc; + const char *desc; }; static const struct grub_pci_classname grub_pci_classes[] = diff --git a/grub-core/commands/memrw.c b/grub-core/commands/memrw.c index 5984288ce..db2e435f2 100644 --- a/grub-core/commands/memrw.c +++ b/grub-core/commands/memrw.c @@ -44,7 +44,7 @@ grub_cmd_read (grub_extcmd_context_t ctxt, int argc, char **argv) char buf[sizeof ("XXXXXXXX")]; if (argc != 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid number of arguments"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); addr = grub_strtoul (argv[0], 0, 0); switch (ctxt->extcmd->cmd->name[sizeof ("read_") - 1]) @@ -81,7 +81,7 @@ grub_cmd_write (grub_command_t cmd, int argc, char **argv) grub_uint32_t mask = 0xffffffff; if (argc != 2 && argc != 3) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid number of arguments"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected")); addr = grub_strtoul (argv[0], 0, 0); value = grub_strtoul (argv[1], 0, 0); @@ -122,22 +122,28 @@ GRUB_MOD_INIT(memrw) { cmd_read_byte = grub_register_extcmd ("read_byte", grub_cmd_read, 0, - N_("ADDR"), N_("Read byte from ADDR."), options); + N_("ADDR"), N_("Read 8-bit value from ADDR."), + options); cmd_read_word = grub_register_extcmd ("read_word", grub_cmd_read, 0, - N_("ADDR"), N_("Read word from ADDR."), options); + N_("ADDR"), N_("Read 16-bit value from ADDR."), + options); cmd_read_dword = grub_register_extcmd ("read_dword", grub_cmd_read, 0, - N_("ADDR"), N_("Read dword from ADDR."), options); + N_("ADDR"), N_("Read 32-bit value from ADDR."), + options); cmd_write_byte = grub_register_command ("write_byte", grub_cmd_write, - N_("ADDR VALUE [MASK]"), N_("Write byte VALUE to ADDR.")); + N_("ADDR VALUE [MASK]"), + N_("Write 8-bit VALUE to ADDR.")); cmd_write_word = grub_register_command ("write_word", grub_cmd_write, - N_("ADDR VALUE [MASK]"), N_("Write word VALUE to ADDR.")); + N_("ADDR VALUE [MASK]"), + N_("Write 16-bit VALUE to ADDR.")); cmd_write_dword = grub_register_command ("write_dword", grub_cmd_write, - N_("ADDR VALUE [MASK]"), N_("Write dword VALUE to ADDR.")); + N_("ADDR VALUE [MASK]"), + N_("Write 32-bit VALUE to ADDR.")); } GRUB_MOD_FINI(memrw) diff --git a/grub-core/commands/menuentry.c b/grub-core/commands/menuentry.c index f5ec60bff..108062e6a 100644 --- a/grub-core/commands/menuentry.c +++ b/grub-core/commands/menuentry.c @@ -30,17 +30,18 @@ static const struct grub_arg_option options[] = {"class", 1, GRUB_ARG_OPTION_REPEATABLE, N_("Menu entry type."), N_("STRING"), ARG_TYPE_STRING}, {"users", 2, 0, - N_("Users allowed to boot this entry."), N_("USERNAME"), ARG_TYPE_STRING}, + N_("List of users allowed to boot this entry."), N_("USERNAME[,USERNAME]"), + ARG_TYPE_STRING}, {"hotkey", 3, 0, - N_("Keyboard key for this entry."), N_("KEY"), ARG_TYPE_STRING}, + N_("Keyboard key to quickly boot this entry."), N_("KEYBOARD_KEY"), ARG_TYPE_STRING}, {"source", 4, 0, - N_("Menu entry definition as a string."), N_("STRING"), ARG_TYPE_STRING}, + N_("Use STRING as menu entry body."), N_("STRING"), ARG_TYPE_STRING}, {0, 0, 0, 0, 0, 0} }; static struct { - char *name; + const char *name; int key; } hotkey_aliases[] = { diff --git a/grub-core/commands/minicmd.c b/grub-core/commands/minicmd.c index 1bb0147df..ce9a6cc27 100644 --- a/grub-core/commands/minicmd.c +++ b/grub-core/commands/minicmd.c @@ -41,7 +41,7 @@ grub_mini_cmd_cat (struct grub_command *cmd __attribute__ ((unused)), grub_ssize_t size; if (argc < 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); file = grub_file_open (argv[0]); if (! file) @@ -165,13 +165,13 @@ grub_mini_cmd_lsmod (struct grub_command *cmd __attribute__ ((unused)), } /* exit */ -static grub_err_t +static grub_err_t __attribute__ ((noreturn)) grub_mini_cmd_exit (struct grub_command *cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), char *argv[] __attribute__ ((unused))) { grub_exit (); - return 0; + /* Not reached. */ } static grub_command_t cmd_cat, cmd_help; @@ -187,7 +187,7 @@ GRUB_MOD_INIT(minicmd) 0, N_("Show this message.")); cmd_dump = grub_register_command ("dump", grub_mini_cmd_dump, - N_("ADDR"), N_("Dump memory.")); + N_("ADDR [SIZE]"), N_("Show memory contents.")); cmd_rmmod = grub_register_command ("rmmod", grub_mini_cmd_rmmod, N_("MODULE"), N_("Remove a module.")); diff --git a/grub-core/commands/mips/loongson/lsspd.c b/grub-core/commands/mips/loongson/lsspd.c index 76999368f..002df4a2a 100644 --- a/grub-core/commands/mips/loongson/lsspd.c +++ b/grub-core/commands/mips/loongson/lsspd.c @@ -49,14 +49,15 @@ grub_cmd_lsspd (grub_command_t cmd __attribute__ ((unused)), if (err) return err; - grub_printf_ (N_("SMB base = 0x%x\n"), smbbase); + grub_printf_ (N_("System management bus controller I/O space is at 0x%x\n"), + smbbase); for (i = GRUB_SMB_RAM_START_ADDR; i < GRUB_SMB_RAM_START_ADDR + GRUB_SMB_RAM_NUM_MAX; i++) { struct grub_smbus_spd spd; grub_memset (&spd, 0, sizeof (spd)); - grub_printf_ (N_("Device %d\n"), i); + grub_printf_ (N_("RAM slot number %d\n"), i); err = grub_cs5536_read_spd (smbbase, i, &spd); if (err) { diff --git a/grub-core/commands/parttool.c b/grub-core/commands/parttool.c index ab5ab5ea4..983c07e88 100644 --- a/grub-core/commands/parttool.c +++ b/grub-core/commands/parttool.c @@ -185,7 +185,8 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)), { char *filename; - filename = grub_xasprintf ("%s/parttool.lst", prefix); + filename = grub_xasprintf ("%s/" GRUB_TARGET_CPU "-" GRUB_PLATFORM + "/parttool.lst", prefix); if (filename) { grub_file_t file; @@ -268,7 +269,7 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)), break; } if (! cur) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "unrecognised argument %s", + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unknown argument `%s'"), args[i]); ptool = cur; pargs = (struct grub_parttool_args *) diff --git a/grub-core/commands/password.c b/grub-core/commands/password.c index 8821607b8..6d42c9b02 100644 --- a/grub-core/commands/password.c +++ b/grub-core/commands/password.c @@ -72,7 +72,7 @@ grub_cmd_password (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) { if (argc != 2) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "two arguments expected"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected")); return grub_normal_set_password (args[0], args[1]); } diff --git a/grub-core/commands/password_pbkdf2.c b/grub-core/commands/password_pbkdf2.c index 05a627219..0c627da2f 100644 --- a/grub-core/commands/password_pbkdf2.c +++ b/grub-core/commands/password_pbkdf2.c @@ -90,11 +90,11 @@ grub_cmd_password (grub_command_t cmd __attribute__ ((unused)), struct pbkdf2_password *pass; if (argc != 2) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "Two arguments expected."); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected")); if (grub_memcmp (args[1], "grub.pbkdf2.sha512.", sizeof ("grub.pbkdf2.sha512.") - 1) != 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "Incorrect PBKDF2 password."); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid PBKDF2 password")); ptr = args[1] + sizeof ("grub.pbkdf2.sha512.") - 1; @@ -103,10 +103,12 @@ grub_cmd_password (grub_command_t cmd __attribute__ ((unused)), return grub_errno; pass->c = grub_strtoul (ptr, &ptr, 0); + if (grub_errno) + return grub_errno; if (*ptr != '.') { grub_free (pass); - return grub_error (GRUB_ERR_BAD_ARGUMENT, "Incorrect PBKDF2 password."); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid PBKDF2 password")); } ptr++; @@ -114,7 +116,7 @@ grub_cmd_password (grub_command_t cmd __attribute__ ((unused)), if (!ptr2 || ((ptr2 - ptr) & 1) || grub_strlen (ptr2 + 1) & 1) { grub_free (pass); - return grub_error (GRUB_ERR_BAD_ARGUMENT, "Incorrect PBKDF2 password."); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid PBKDF2 password")); } pass->saltlen = (ptr2 - ptr) >> 1; @@ -137,7 +139,7 @@ grub_cmd_password (grub_command_t cmd __attribute__ ((unused)), grub_free (pass->salt); grub_free (pass); return grub_error (GRUB_ERR_BAD_ARGUMENT, - "Incorrect PBKDF2 password."); + N_("invalid PBKDF2 password")); } *ptro = (hex1 << 4) | hex2; @@ -166,7 +168,7 @@ grub_cmd_password (grub_command_t cmd __attribute__ ((unused)), grub_free (pass->salt); grub_free (pass); return grub_error (GRUB_ERR_BAD_ARGUMENT, - "Incorrect PBKDF2 password."); + N_("invalid PBKDF2 password")); } *ptro = (hex1 << 4) | hex2; diff --git a/grub-core/commands/probe.c b/grub-core/commands/probe.c index a1d68cdeb..8527dd531 100644 --- a/grub-core/commands/probe.c +++ b/grub-core/commands/probe.c @@ -68,7 +68,7 @@ grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args) else dev = grub_device_open (args[0]); if (! dev) - return grub_error (GRUB_ERR_BAD_DEVICE, "couldn't open device"); + return grub_errno; if (state[1].set) { @@ -96,7 +96,7 @@ grub_cmd_probe (grub_extcmd_context_t ctxt, int argc, char **args) } fs = grub_fs_probe (dev); if (! fs) - return grub_error (GRUB_ERR_UNKNOWN_FS, "unrecognised fs"); + return grub_errno; if (state[3].set) { if (state[0].set) diff --git a/grub-core/commands/reboot.c b/grub-core/commands/reboot.c index 8e18083c0..46d364c99 100644 --- a/grub-core/commands/reboot.c +++ b/grub-core/commands/reboot.c @@ -24,13 +24,12 @@ GRUB_MOD_LICENSE ("GPLv3+"); -static grub_err_t +static grub_err_t __attribute__ ((noreturn)) grub_cmd_reboot (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { grub_reboot (); - return 0; } static grub_command_t cmd; diff --git a/grub-core/commands/regexp.c b/grub-core/commands/regexp.c index 1e8a6f309..b911ffd60 100644 --- a/grub-core/commands/regexp.c +++ b/grub-core/commands/regexp.c @@ -32,7 +32,7 @@ GRUB_MOD_LICENSE ("GPLv3+"); static const struct grub_arg_option options[] = { { "set", 's', GRUB_ARG_OPTION_REPEATABLE, - N_("Variable names to update with matches."), + N_("Store matched component NUMBER in VARNAME."), N_("[NUMBER:]VARNAME"), ARG_TYPE_STRING }, { 0, 0, 0, 0, 0, 0 } }; @@ -42,7 +42,6 @@ set_matches (char **varnames, char *str, grub_size_t nmatches, regmatch_t *matches) { int i; - char ch; char *p; char *q; grub_err_t err; @@ -51,6 +50,7 @@ set_matches (char **varnames, char *str, grub_size_t nmatches, 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); @@ -59,7 +59,8 @@ set_matches (char **varnames, char *str, grub_size_t nmatches, for (i = 0; varnames && varnames[i]; i++) { - if (! (p = grub_strchr (varnames[i], ':'))) + p = grub_strchr (varnames[i], ':'); + if (! p) { /* varname w/o index defaults to 1 */ if (nmatches < 2 || matches[1].rm_so == -1) @@ -97,7 +98,7 @@ grub_cmd_regexp (grub_extcmd_context_t ctxt, int argc, char **args) regmatch_t *matches = 0; if (argc != 2) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "2 arguments expected"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected")); ret = regcomp (®ex, args[0], REG_EXTENDED); if (ret) diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c index ba80d80ef..5e9b7e381 100644 --- a/grub-core/commands/search.c +++ b/grub-core/commands/search.c @@ -33,11 +33,21 @@ GRUB_MOD_LICENSE ("GPLv3+"); +struct cache_entry +{ + struct cache_entry *next; + char *key; + char *value; +}; + +static struct cache_entry *cache; + void FUNC_NAME (const char *key, const char *var, int no_floppy, char **hints, unsigned nhints) { int count = 0; + int is_cache = 0; grub_fs_autoload_hook_t saved_autoload; auto int iterate_device (const char *name); @@ -50,6 +60,12 @@ FUNC_NAME (const char *key, const char *var, int 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 +#else +#define compare_fn grub_strcmp +#endif + #ifdef DO_SEARCH_FILE { char *buf; @@ -81,10 +97,8 @@ FUNC_NAME (const char *key, const char *var, int no_floppy, fs = grub_fs_probe (dev); #ifdef DO_SEARCH_FS_UUID -#define compare_fn grub_strcasecmp #define read_fn uuid #else -#define compare_fn grub_strcmp #define read_fn label #endif @@ -106,6 +120,31 @@ FUNC_NAME (const char *key, const char *var, int no_floppy, } #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 (found) { count++; @@ -143,6 +182,32 @@ FUNC_NAME (const char *key, const char *var, int no_floppy, void try (void) { unsigned i; + struct cache_entry **prev; + struct cache_entry *cache_ent; + + for (prev = &cache, cache_ent = *prev; cache_ent; + prev = &cache_ent->next, cache_ent = *prev) + if (compare_fn (cache_ent->key, key) == 0) + break; + if (cache_ent) + { + is_cache = 1; + if (iterate_device (cache_ent->value)) + { + is_cache = 0; + 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; + } + } + for (i = 0; i < nhints; i++) { char *end; @@ -164,17 +229,20 @@ FUNC_NAME (const char *key, const char *var, int no_floppy, dev = grub_device_open (hints[i]); if (!dev) { - *end = ','; + if (!*end) + *end = ','; continue; } if (!dev->disk) { grub_device_close (dev); - *end = ','; + if (!*end) + *end = ','; continue; } ret = grub_partition_iterate (dev->disk, part_hook); - *end = ','; + if (!*end) + *end = ','; grub_device_close (dev); if (ret) return; @@ -209,7 +277,7 @@ grub_cmd_do_search (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) { if (argc == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "no argument specified"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); FUNC_NAME (args[0], argc == 1 ? 0 : args[1], 0, (args + 2), argc > 2 ? argc - 2 : 0); diff --git a/grub-core/commands/search_file.c b/grub-core/commands/search_file.c index 73ce89ccc..cc2a5f939 100644 --- a/grub-core/commands/search_file.c +++ b/grub-core/commands/search_file.c @@ -1,6 +1,5 @@ #define DO_SEARCH_FILE 1 #define FUNC_NAME grub_search_fs_file #define COMMAND_NAME "search.file" -#define SEARCH_TARGET "file" #define HELP_MESSAGE N_("Search devices by file. If VARIABLE is specified, the first device found is set to a variable.") #include "search.c" diff --git a/grub-core/commands/search_label.c b/grub-core/commands/search_label.c index ee9c792be..12e7c1831 100644 --- a/grub-core/commands/search_label.c +++ b/grub-core/commands/search_label.c @@ -1,6 +1,5 @@ #define DO_SEARCH_FS_LABEL 1 #define FUNC_NAME grub_search_label #define COMMAND_NAME "search.fs_label" -#define SEARCH_TARGET "filesystem label" #define HELP_MESSAGE N_("Search devices by label. If VARIABLE is specified, the first device found is set to a variable.") #include "search.c" diff --git a/grub-core/commands/search_uuid.c b/grub-core/commands/search_uuid.c index 52f83812c..541bcf54b 100644 --- a/grub-core/commands/search_uuid.c +++ b/grub-core/commands/search_uuid.c @@ -1,6 +1,5 @@ #define DO_SEARCH_FS_UUID 1 #define FUNC_NAME grub_search_fs_uuid #define COMMAND_NAME "search.fs_uuid" -#define SEARCH_TARGET "filesystem UUID" #define HELP_MESSAGE N_("Search devices by UUID. If VARIABLE is specified, the first device found is set to a variable.") #include "search.c" diff --git a/grub-core/commands/search_wrap.c b/grub-core/commands/search_wrap.c index 7b0a99565..e055cd5c7 100644 --- a/grub-core/commands/search_wrap.c +++ b/grub-core/commands/search_wrap.c @@ -42,6 +42,21 @@ static const struct grub_arg_option options[] = {"hint", 'h', GRUB_ARG_OPTION_REPEATABLE, N_("First try the device HINT. If HINT ends in comma, " "also try subpartitions"), N_("HINT"), ARG_TYPE_STRING}, + {"hint-ieee1275", 0, GRUB_ARG_OPTION_REPEATABLE, + N_("First try the device HINT if on IEEE1275. If HINT ends in comma, " + "also try subpartitions"), N_("HINT"), ARG_TYPE_STRING}, + {"hint-bios", 0, GRUB_ARG_OPTION_REPEATABLE, + N_("First try the device HINT if on BIOS. If HINT ends in comma, " + "also try subpartitions"), N_("HINT"), ARG_TYPE_STRING}, + {"hint-baremetal", 0, GRUB_ARG_OPTION_REPEATABLE, + N_("First try the device HINT. If HINT ends in comma, " + "also try subpartitions"), N_("HINT"), ARG_TYPE_STRING}, + {"hint-efi", 0, GRUB_ARG_OPTION_REPEATABLE, + N_("First try the device HINT if on EFI. If HINT ends in comma, " + "also try subpartitions"), N_("HINT"), ARG_TYPE_STRING}, + {"hint-arc", 0, GRUB_ARG_OPTION_REPEATABLE, + N_("First try the device HINT if on ARC. If HINT ends in comma, " + "also try subpartitions"), N_("HINT"), ARG_TYPE_STRING}, {0, 0, 0, 0, 0, 0} }; @@ -52,7 +67,12 @@ enum options SEARCH_FS_UUID, SEARCH_SET, SEARCH_NO_FLOPPY, - SEARCH_HINT + SEARCH_HINT, + SEARCH_HINT_IEEE1275, + SEARCH_HINT_BIOS, + SEARCH_HINT_BAREMETAL, + SEARCH_HINT_EFI, + SEARCH_HINT_ARC, }; static grub_err_t @@ -60,27 +80,98 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args) { struct grub_arg_list *state = ctxt->state; const char *var = 0; - int nhints = 0; + int i = 0, j = 0, nhints = 0; + char **hints = NULL; if (state[SEARCH_HINT].set) - while (state[SEARCH_HINT].args[nhints]) + for (i = 0; state[SEARCH_HINT].args[i]; i++) nhints++; - if (argc == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "no argument specified"); +#ifdef GRUB_MACHINE_IEEE1275 + if (state[SEARCH_HINT_IEEE1275].set) + for (i = 0; state[SEARCH_HINT_IEEE1275].args[i]; i++) + nhints++; +#endif + +#ifdef GRUB_MACHINE_EFI + if (state[SEARCH_HINT_EFI].set) + for (i = 0; state[SEARCH_HINT_EFI].args[i]; i++) + nhints++; +#endif + +#ifdef GRUB_MACHINE_PCBIOS + if (state[SEARCH_HINT_BIOS].set) + for (i = 0; state[SEARCH_HINT_BIOS].args[i]; i++) + nhints++; +#endif + +#ifdef GRUB_MACHINE_ARC + if (state[SEARCH_HINT_ARC].set) + for (i = 0; state[SEARCH_HINT_ARC].args[i]; i++) + nhints++; +#endif + + if (state[SEARCH_HINT_BAREMETAL].set) + for (i = 0; state[SEARCH_HINT_BAREMETAL].args[i]; i++) + nhints++; + + hints = grub_malloc (sizeof (hints[0]) * nhints); + if (!hints) + return grub_errno; + j = 0; + + if (state[SEARCH_HINT].set) + for (i = 0; state[SEARCH_HINT].args[i]; i++) + hints[j++] = state[SEARCH_HINT].args[i]; + +#ifdef GRUB_MACHINE_IEEE1275 + if (state[SEARCH_HINT_IEEE1275].set) + for (i = 0; state[SEARCH_HINT_IEEE1275].args[i]; i++) + hints[j++] = state[SEARCH_HINT_IEEE1275].args[i]; +#endif + +#ifdef GRUB_MACHINE_EFI + if (state[SEARCH_HINT_EFI].set) + for (i = 0; state[SEARCH_HINT_EFI].args[i]; i++) + hints[j++] = state[SEARCH_HINT_EFI].args[i]; +#endif + +#ifdef GRUB_MACHINE_ARC + if (state[SEARCH_HINT_ARC].set) + for (i = 0; state[SEARCH_HINT_ARC].args[i]; i++) + hints[j++] = state[SEARCH_HINT_ARC].args[i]; +#endif + +#ifdef GRUB_MACHINE_PCBIOS + if (state[SEARCH_HINT_BIOS].set) + for (i = 0; state[SEARCH_HINT_BIOS].args[i]; i++) + hints[j++] = state[SEARCH_HINT_BIOS].args[i]; +#endif + + if (state[SEARCH_HINT_BAREMETAL].set) + for (i = 0; state[SEARCH_HINT_BAREMETAL].args[i]; i++) + hints[j++] = state[SEARCH_HINT_BAREMETAL].args[i]; + + /* Skip hints for future platforms. */ + for (j = 0; j < argc; j++) + if (grub_memcmp (args[j], "--hint-", sizeof ("--hint-") - 1) != 0) + break; + + if (argc == j) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); if (state[SEARCH_SET].set) var = state[SEARCH_SET].arg ? state[SEARCH_SET].arg : "root"; if (state[SEARCH_LABEL].set) - grub_search_label (args[0], var, state[SEARCH_NO_FLOPPY].set, - state[SEARCH_HINT].args, nhints); + grub_search_label (args[j], var, state[SEARCH_NO_FLOPPY].set, + hints, nhints); else if (state[SEARCH_FS_UUID].set) - grub_search_fs_uuid (args[0], var, state[SEARCH_NO_FLOPPY].set, - state[SEARCH_HINT].args, nhints); + grub_search_fs_uuid (args[j], var, state[SEARCH_NO_FLOPPY].set, + hints, nhints); else if (state[SEARCH_FILE].set) - grub_search_fs_file (args[0], var, state[SEARCH_NO_FLOPPY].set, - state[SEARCH_HINT].args, nhints); + grub_search_fs_file (args[j], var, state[SEARCH_NO_FLOPPY].set, + hints, nhints); else return grub_error (GRUB_ERR_INVALID_COMMAND, "unspecified search type"); @@ -92,7 +183,8 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(search) { cmd = - grub_register_extcmd ("search", grub_cmd_search, GRUB_COMMAND_FLAG_EXTRACTOR, + grub_register_extcmd ("search", grub_cmd_search, + GRUB_COMMAND_FLAG_EXTRACTOR | GRUB_COMMAND_ACCEPT_DASH, N_("[-f|-l|-u|-s|-n] [--hint HINT [--hint HINT] ...]" " NAME"), N_("Search devices by file, filesystem label" diff --git a/grub-core/commands/setpci.c b/grub-core/commands/setpci.c index 81e7f726d..fcfec4058 100644 --- a/grub-core/commands/setpci.c +++ b/grub-core/commands/setpci.c @@ -128,7 +128,7 @@ grub_setpci_iter (grub_pci_device_t dev, grub_pci_id_t pciid) if (!write_mask) { - grub_printf (N_("Register %x of %d:%d.%d is %x\n"), regaddr, + grub_printf (_("Register %x of %d:%d.%d is %x\n"), regaddr, grub_pci_get_bus (dev), grub_pci_get_device (dev), grub_pci_get_function (dev), @@ -179,7 +179,7 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv) if (grub_errno) return grub_errno; if (*ptr != ':') - return grub_error (GRUB_ERR_BAD_ARGUMENT, "Colon expected."); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("missing `%c' symbol"), ':'); ptr++; pciid_check_value |= (grub_strtoul (ptr, (char **) &ptr, 16) & 0xffff) << 16; @@ -210,7 +210,7 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv) if (grub_errno) return grub_errno; if (*ptr != ':') - return grub_error (GRUB_ERR_BAD_ARGUMENT, "Colon expected."); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("missing `%c' symbol"), ':'); ptr++; optr = ptr; device = grub_strtoul (ptr, (char **) &ptr, 16); @@ -238,11 +238,8 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv) write_mask = 0; - if (argc == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "Command expected."); - - if (argc > 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "Only one command is supported."); + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); ptr = argv[0]; @@ -257,7 +254,7 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv) regsize = 0; regaddr = grub_strtoul (ptr, (char **) &ptr, 16); if (grub_errno) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown register"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown register"); } else { @@ -298,7 +295,7 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv) if (!regsize) return grub_error (GRUB_ERR_BAD_ARGUMENT, - "Unknown register size."); + "unknown register size"); write_mask = 0; if (*ptr == '=') @@ -321,7 +318,7 @@ grub_cmd_setpci (grub_extcmd_context_t ctxt, int argc, char **argv) if (write_mask && varname) return grub_error (GRUB_ERR_BAD_ARGUMENT, - "Option -v isn't valid for writes."); + "option -v isn't valid for writes"); grub_pci_iterate (grub_setpci_iter); return GRUB_ERR_NONE; diff --git a/grub-core/commands/sleep.c b/grub-core/commands/sleep.c index 97e7a40a6..5b51d3b21 100644 --- a/grub-core/commands/sleep.c +++ b/grub-core/commands/sleep.c @@ -54,7 +54,7 @@ grub_interruptible_millisleep (grub_uint32_t ms) start = grub_get_time_ms (); while (grub_get_time_ms () - start < ms) - if (grub_checkkey () >= 0 && grub_getkey () == GRUB_TERM_ESC) + if (grub_getkey_noblock () == GRUB_TERM_ESC) return 1; return 0; @@ -67,7 +67,7 @@ grub_cmd_sleep (grub_extcmd_context_t ctxt, int argc, char **args) int n; if (argc != 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing operand"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); n = grub_strtoul (args[0], 0, 10); diff --git a/grub-core/commands/terminal.c b/grub-core/commands/terminal.c index 0adfd3d2e..425a41126 100644 --- a/grub-core/commands/terminal.c +++ b/grub-core/commands/terminal.c @@ -31,6 +31,7 @@ struct grub_term_autoload *grub_term_output_autoload = NULL; struct abstract_terminal { struct abstract_terminal *next; + struct abstract_terminal *prev; const char *name; grub_err_t (*init) (struct abstract_terminal *term); grub_err_t (*fini) (struct abstract_terminal *term); @@ -94,19 +95,26 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled, while (1) { for (term = *disabled; term; term = term->next) - if (grub_strcmp (args[i], term->name) == 0) + if (grub_strcmp (args[i], term->name) == 0 + || (grub_strcmp (args[i], "ofconsole") == 0 + && grub_strcmp ("console", term->name) == 0)) break; if (term == 0) for (term = *enabled; term; term = term->next) - if (grub_strcmp (args[i], term->name) == 0) + if (grub_strcmp (args[i], term->name) == 0 + || (grub_strcmp (args[i], "ofconsole") == 0 + && grub_strcmp ("console", term->name) == 0)) break; if (term) break; if (again) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminal '%s'\n", + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("terminal `%s' isn't found"), args[i]); for (aut = autoloads; aut; aut = aut->next) if (grub_strcmp (args[i], aut->name) == 0 + || (grub_strcmp (args[i], "ofconsole") == 0 + && grub_strcmp ("console", aut->name) == 0) || (aut->name[0] && aut->name[grub_strlen (aut->name) - 1] == '*' && grub_memcmp (args[i], aut->name, grub_strlen (aut->name) - 1) == 0)) @@ -119,7 +127,8 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled, break; } if (!aut) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminal '%s'\n", + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("terminal `%s' isn't found"), args[i]); again = 1; } @@ -130,14 +139,16 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled, for (i = 1; i < argc; i++) { for (term = *disabled; term; term = term->next) - if (grub_strcmp (args[i], term->name) == 0) + if (grub_strcmp (args[i], term->name) == 0 + || (grub_strcmp (args[i], "ofconsole") == 0 + && grub_strcmp ("console", term->name) == 0)) break; if (term) { if (term->init && term->init (term) != GRUB_ERR_NONE) return grub_errno; - grub_list_remove (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term)); + grub_list_remove (GRUB_AS_LIST (term)); grub_list_push (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term)); } } @@ -149,14 +160,16 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled, for (i = 1; i < argc; i++) { for (term = *enabled; term; term = term->next) - if (grub_strcmp (args[i], term->name) == 0) + if (grub_strcmp (args[i], term->name) == 0 + || (grub_strcmp (args[i], "ofconsole") == 0 + && grub_strcmp ("console", term->name) == 0)) break; if (term) { if (!term->next && term == *enabled) return grub_error (GRUB_ERR_BAD_ARGUMENT, "can't remove the last terminal"); - grub_list_remove (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term)); + grub_list_remove (GRUB_AS_LIST (term)); if (term->fini) term->fini (term); grub_list_push (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term)); @@ -167,14 +180,16 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled, for (i = 0; i < argc; i++) { for (term = *disabled; term; term = term->next) - if (grub_strcmp (args[i], term->name) == 0) + if (grub_strcmp (args[i], term->name) == 0 + || (grub_strcmp (args[i], "ofconsole") == 0 + && grub_strcmp ("console", term->name) == 0)) break; if (term) { if (term->init && term->init (term) != GRUB_ERR_NONE) return grub_errno; - grub_list_remove (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term)); + grub_list_remove (GRUB_AS_LIST (term)); grub_list_push (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term)); } } @@ -185,14 +200,16 @@ handle_command (int argc, char **args, struct abstract_terminal **enabled, { next = term->next; for (i = 0; i < argc; i++) - if (grub_strcmp (args[i], term->name) == 0) + if (grub_strcmp (args[i], term->name) == 0 + || (grub_strcmp (args[i], "ofconsole") == 0 + && grub_strcmp ("console", term->name) == 0)) break; if (i == argc) { if (!term->next && term == *enabled) return grub_error (GRUB_ERR_BAD_ARGUMENT, "can't remove the last terminal"); - grub_list_remove (GRUB_AS_LIST_P (enabled), GRUB_AS_LIST (term)); + grub_list_remove (GRUB_AS_LIST (term)); if (term->fini) term->fini (term); grub_list_push (GRUB_AS_LIST_P (disabled), GRUB_AS_LIST (term)); @@ -208,6 +225,7 @@ grub_cmd_terminal_input (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) { (void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, next); + (void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, prev); (void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, name); (void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, init); (void) GRUB_FIELD_MATCH (grub_term_inputs, struct abstract_terminal *, fini); @@ -224,6 +242,7 @@ grub_cmd_terminal_output (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) { (void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, next); + (void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, prev); (void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, name); (void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, init); (void) GRUB_FIELD_MATCH (grub_term_outputs, struct abstract_terminal *, fini); diff --git a/grub-core/commands/test.c b/grub-core/commands/test.c index 50d5aba5e..3a0e0e069 100644 --- a/grub-core/commands/test.c +++ b/grub-core/commands/test.c @@ -416,7 +416,7 @@ grub_cmd_test (grub_command_t cmd __attribute__ ((unused)), argc--; return test_parse (args, &argn, argc) ? GRUB_ERR_NONE - : grub_error (GRUB_ERR_TEST_FAILURE, "false"); + : grub_error (GRUB_ERR_TEST_FAILURE, N_("false")); } static grub_command_t cmd_1, cmd_2; diff --git a/grub-core/commands/testload.c b/grub-core/commands/testload.c index fe06f3d1e..ef68ad141 100644 --- a/grub-core/commands/testload.c +++ b/grub-core/commands/testload.c @@ -50,7 +50,7 @@ grub_cmd_testload (struct grub_command *cmd __attribute__ ((unused)), } if (argc < 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); file = grub_file_open (argv[0]); if (! file) diff --git a/grub-core/commands/time.c b/grub-core/commands/time.c index 224f92b3f..40d496e7b 100644 --- a/grub-core/commands/time.c +++ b/grub-core/commands/time.c @@ -35,12 +35,12 @@ grub_cmd_time (grub_command_t ctxt __attribute__ ((unused)), grub_uint32_t end; if (argc == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "command expected"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("no command is specified")); cmd = grub_command_find (args[0]); if (!cmd) - return grub_error (GRUB_ERR_UNKNOWN_COMMAND, "Unknown command `%s'\n", + return grub_error (GRUB_ERR_UNKNOWN_COMMAND, N_("can't find command `%s'"), args[0]); start = grub_get_time_ms (); diff --git a/grub-core/commands/true.c b/grub-core/commands/true.c index 82775e7ef..b76682d06 100644 --- a/grub-core/commands/true.c +++ b/grub-core/commands/true.c @@ -36,7 +36,7 @@ grub_cmd_false (struct grub_command *cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), char *argv[] __attribute__ ((unused))) { - return grub_error (GRUB_ERR_TEST_FAILURE, "false"); + return grub_error (GRUB_ERR_TEST_FAILURE, N_("false")); } static grub_command_t cmd_true, cmd_false; @@ -46,9 +46,13 @@ GRUB_MOD_INIT(true) { cmd_true = grub_register_command ("true", grub_cmd_true, + /* TRANSLATORS: it's imperative, not + infinitive. */ 0, N_("Do nothing, successfully.")); cmd_false = grub_register_command ("false", grub_cmd_false, + /* TRANSLATORS: it's imperative, not + infinitive. */ 0, N_("Do nothing, unsuccessfully.")); } diff --git a/grub-core/commands/videoinfo.c b/grub-core/commands/videoinfo.c index 9e12ff55e..7d2b0dac7 100644 --- a/grub-core/commands/videoinfo.c +++ b/grub-core/commands/videoinfo.c @@ -126,7 +126,9 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), if (grub_errno) return grub_errno; if (*ptr != 'x') - return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid mode specification"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("invalid video mode specification `%s'"), + args[0]); ptr++; height = grub_strtoul (ptr, &ptr, 0); if (grub_errno) @@ -178,7 +180,7 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), { if (adapter->init ()) { - grub_puts_ (N_(" Failed")); + grub_puts_ (N_(" Failed to initialize video adapter")); grub_errno = GRUB_ERR_NONE; continue; } diff --git a/grub-core/commands/videotest.c b/grub-core/commands/videotest.c index dc7a6485f..9a6ba6256 100644 --- a/grub-core/commands/videotest.c +++ b/grub-core/commands/videotest.c @@ -74,6 +74,8 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), grub_video_create_render_target (&text_layer, width, height, GRUB_VIDEO_MODE_TYPE_RGB | GRUB_VIDEO_MODE_TYPE_ALPHA); + if (!text_layer) + goto fail; grub_video_set_active_render_target (text_layer); @@ -114,13 +116,13 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), U+03C4 Greek tau CF 84 U+00E4 lowercase letter a with umlaut C3 A4 U+2124 set 'Z' symbol (integers) E2 84 A4 - U+2287 subset symbol E2 8A 87 + U+2286 subset symbol E2 8A 86 U+211D set 'R' symbol (real numbers) E2 84 9D */ str = "Unicode test: happy\xE2\x98\xBA \xC2\xA3 5.00" " \xC2\xA1\xCF\x84\xC3\xA4u! " - " \xE2\x84\xA4\xE2\x8A\x87\xE2\x84\x9D"; + " \xE2\x84\xA4\xE2\x8A\x86\xE2\x84\x9D"; color = grub_video_map_rgb (128, 128, 255); /* All characters in the string exist in the 'Fixed 20' (10x20) font. */ @@ -191,6 +193,11 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), grub_errno = GRUB_ERR_NONE; return grub_errno; + + fail: + grub_video_delete_render_target (text_layer); + grub_video_restore (); + return grub_errno; } static grub_command_t cmd; @@ -201,7 +208,7 @@ static grub_command_t cmd_vbe; GRUB_MOD_INIT(videotest) { cmd = grub_register_command ("videotest", grub_cmd_videotest, - "[WxH]", + N_("[WxH]"), N_("Test video subsystem in mode WxH.")); #ifdef GRUB_MACHINE_PCBIOS cmd_vbe = grub_register_command ("vbetest", grub_cmd_videotest, diff --git a/grub-core/commands/wildcard.c b/grub-core/commands/wildcard.c index d991b2010..8afda3c99 100644 --- a/grub-core/commands/wildcard.c +++ b/grub-core/commands/wildcard.c @@ -326,10 +326,15 @@ match_files (const char *prefix, const char *suffix, const char *end, if (! fs) goto fail; - path = grub_strchr (dir, ')'); - if (! path) - goto fail; - path++; + if (dir[0] == '(') + { + path = grub_strchr (dir, ')'); + if (!path) + goto fail; + path++; + } + else + path = dir; if (fs->dir (dev, path, match)) goto fail; @@ -431,25 +436,8 @@ wildcard_expand (const char *s, char ***strs) if (start == noregexop) /* device part has regexop */ paths = match_devices (®exp, *start != '('); - else if (*start == '(') /* device part explicit wo regexop */ + else /* device part explicit wo regexop */ paths = match_files ("", start, noregexop, ®exp); - - else if (*start == '/') /* no device part */ - { - const char *root; - char *prefix; - - root = grub_env_get ("root"); - if (! root) - goto fail; - - prefix = grub_xasprintf ("(%s)", root); - if (! prefix) - goto fail; - - paths = match_files (prefix, start, noregexop, ®exp); - grub_free (prefix); - } } else { diff --git a/grub-core/disk/ahci.c b/grub-core/disk/ahci.c index 38c4d5e2d..4ab2d18db 100644 --- a/grub-core/disk/ahci.c +++ b/grub-core/disk/ahci.c @@ -121,6 +121,7 @@ enum struct grub_ahci_device { struct grub_ahci_device *next; + struct grub_ahci_device **prev; volatile struct grub_ahci_hba *hba; int port; int num; @@ -305,7 +306,7 @@ grub_ahci_pciinit (grub_pci_device_t dev, else grub_dprintf ("ahci", "AHCI is already in OS mode\n"); - if (~(hba->global_control & GRUB_AHCI_HBA_GLOBAL_CONTROL_AHCI_EN)) + 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"); @@ -542,10 +543,10 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev, (unsigned long long) parms->cmdsize); if (parms->cmdsize != 0 && parms->cmdsize != 12 && parms->cmdsize != 16) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "incorrect ATAPI command size"); + return grub_error (GRUB_ERR_BUG, "incorrect ATAPI command size"); if (parms->size > GRUB_AHCI_PRDT_MAX_CHUNK_LENGTH) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "too big data buffer"); + return grub_error (GRUB_ERR_BUG, "too big data buffer"); bufc = grub_memalign_dma32 (1024, parms->size + (parms->size & 1)); @@ -625,7 +626,7 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev, dev->hba->ports[dev->port].command_issue, dev->hba->ports[dev->port].intstatus, dev->hba->ports[dev->port].task_file_data); - err = grub_error (GRUB_ERR_IO, "AHCI transfer timeouted"); + err = grub_error (GRUB_ERR_IO, "AHCI transfer timed out"); break; } @@ -692,6 +693,7 @@ grub_ahci_open (int id, int devnum, struct grub_ata *ata) ata->data = dev; ata->dma = 1; + ata->maxbuffer = GRUB_AHCI_PRDT_MAX_CHUNK_LENGTH; ata->present = &dev->present; return GRUB_ERR_NONE; @@ -706,7 +708,7 @@ static struct grub_ata_dev grub_ahci_dev = -static void *fini_hnd; +static struct grub_preboot *fini_hnd; GRUB_MOD_INIT(ahci) { diff --git a/grub-core/disk/arc/arcdisk.c b/grub-core/disk/arc/arcdisk.c index 170bf521d..10cbc8759 100644 --- a/grub-core/disk/arc/arcdisk.c +++ b/grub-core/disk/arc/arcdisk.c @@ -21,9 +21,11 @@ #include #include #include +#include static grub_arc_fileno_t last_handle = 0; static char *last_path = NULL; +static int handle_writable = 0; static int lnum = 0; @@ -100,11 +102,12 @@ grub_arcdisk_iterate (int (*hook_in) (const char *name), #define RAW_SUFFIX "partition(10)" static grub_err_t -reopen (const char *name) +reopen (const char *name, int writable) { grub_arc_fileno_t handle; - if (last_path && grub_strcmp (last_path, name) == 0) + if (last_path && grub_strcmp (last_path, name) == 0 + && (!writable || handle_writable)) { grub_dprintf ("arcdisk", "using already opened %s\n", name); return GRUB_ERR_NONE; @@ -115,12 +118,16 @@ reopen (const char *name) grub_free (last_path); last_path = NULL; last_handle = 0; + handle_writable = 0; } - if (GRUB_ARC_FIRMWARE_VECTOR->open (name, 0, &handle)) + if (GRUB_ARC_FIRMWARE_VECTOR->open (name, + writable ? GRUB_ARC_FILE_ACCESS_OPEN_RW + : GRUB_ARC_FILE_ACCESS_OPEN_RO, &handle)) { grub_dprintf ("arcdisk", "couldn't open %s\n", name); return grub_error (GRUB_ERR_IO, "couldn't open %s", name); } + handle_writable = writable; last_path = grub_strdup (name); if (!last_path) return grub_errno; @@ -180,7 +187,7 @@ grub_arcdisk_open (const char *name, grub_disk_t disk) if (!hash) return grub_errno; - err = reopen (fullname); + err = reopen (fullname, 0); if (err) return err; @@ -234,7 +241,7 @@ grub_arcdisk_read (grub_disk_t disk, grub_disk_addr_t sector, grub_uint64_t totl = size << 9; grub_arc_err_t r; - err = reopen (disk->data); + err = reopen (disk->data, 0); if (err) return err; r = GRUB_ARC_FIRMWARE_VECTOR->seek (last_handle, &pos, 0); @@ -249,7 +256,11 @@ grub_arcdisk_read (grub_disk_t disk, grub_disk_addr_t sector, { if (GRUB_ARC_FIRMWARE_VECTOR->read (last_handle, buf, totl, &count)) - return grub_error (GRUB_ERR_READ_ERROR, "read failed"); + return grub_error (GRUB_ERR_READ_ERROR, + N_("failure reading sector 0x%llx " + "from `%s'"), + (unsigned long long) sector, + disk->name); totl -= count; buf += count; } @@ -258,12 +269,39 @@ grub_arcdisk_read (grub_disk_t disk, grub_disk_addr_t sector, } static grub_err_t -grub_arcdisk_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_arcdisk_write (grub_disk_t disk, grub_disk_addr_t sector, + grub_size_t size, const char *buf) { - return GRUB_ERR_NOT_IMPLEMENTED_YET; + grub_err_t err; + grub_uint64_t pos = sector << 9; + unsigned long count; + grub_uint64_t totl = size << 9; + grub_arc_err_t r; + + err = reopen (disk->data, 1); + if (err) + return err; + r = GRUB_ARC_FIRMWARE_VECTOR->seek (last_handle, &pos, 0); + if (r) + { + grub_dprintf ("arcdisk", "seek to 0x%" PRIxGRUB_UINT64_T " failed: %ld\n", + pos, r); + return grub_error (GRUB_ERR_IO, "couldn't seek"); + } + + while (totl) + { + if (GRUB_ARC_FIRMWARE_VECTOR->write (last_handle, buf, + totl, &count)) + return grub_error (GRUB_ERR_WRITE_ERROR, N_("failure writing sector 0x%llx " + "to `%s'"), + (unsigned long long) sector, + disk->name); + totl -= count; + buf += count; + } + + return GRUB_ERR_NONE; } static struct grub_disk_dev grub_arcdisk_dev = diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index 330635f57..c90e86832 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -29,29 +29,27 @@ static grub_ata_dev_t grub_ata_dev_list; /* Byteorder has to be changed before strings can be read. */ static void -grub_ata_strncpy (char *dst, char *src, grub_size_t len) +grub_ata_strncpy (grub_uint16_t *dst16, grub_uint16_t *src16, grub_size_t len) { - grub_uint16_t *src16 = (grub_uint16_t *) src; - grub_uint16_t *dst16 = (grub_uint16_t *) dst; unsigned int i; for (i = 0; i < len / 2; i++) *(dst16++) = grub_be_to_cpu16 (*(src16++)); - dst[len] = '\0'; + dst16[i] = 0; } static void -grub_ata_dumpinfo (struct grub_ata *dev, char *info) +grub_ata_dumpinfo (struct grub_ata *dev, grub_uint16_t *info) { - char text[41]; + grub_uint16_t text[21]; /* The device information was read, dump it for debugging. */ - grub_ata_strncpy (text, info + 20, 20); - grub_dprintf ("ata", "Serial: %s\n", text); - grub_ata_strncpy (text, info + 46, 8); - grub_dprintf ("ata", "Firmware: %s\n", text); - grub_ata_strncpy (text, info + 54, 40); - grub_dprintf ("ata", "Model: %s\n", text); + grub_ata_strncpy (text, info + 10, 20); + grub_dprintf ("ata", "Serial: %s\n", (char *) text); + grub_ata_strncpy (text, info + 23, 8); + grub_dprintf ("ata", "Firmware: %s\n", (char *) text); + grub_ata_strncpy (text, info + 27, 40); + grub_dprintf ("ata", "Model: %s\n", (char *) text); if (! dev->atapi) { @@ -65,7 +63,7 @@ static grub_err_t grub_atapi_identify (struct grub_ata *dev) { struct grub_disk_ata_pass_through_parms parms; - char *info; + grub_uint16_t *info; grub_err_t err; info = grub_malloc (GRUB_DISK_SECTOR_SIZE); @@ -105,17 +103,19 @@ static grub_err_t grub_ata_identify (struct grub_ata *dev) { struct grub_disk_ata_pass_through_parms parms; - char *info; + grub_uint64_t *info64; + grub_uint32_t *info32; grub_uint16_t *info16; grub_err_t err; - info = grub_malloc (GRUB_DISK_SECTOR_SIZE); - if (! info) + info64 = grub_malloc (GRUB_DISK_SECTOR_SIZE); + info32 = (grub_uint32_t *) info64; + info16 = (grub_uint16_t *) info64; + if (! info16) return grub_errno; - info16 = (grub_uint16_t *) info; grub_memset (&parms, 0, sizeof (parms)); - parms.buffer = info; + parms.buffer = info16; parms.size = GRUB_DISK_SECTOR_SIZE; parms.taskfile.disk = 0xE0; @@ -126,7 +126,7 @@ grub_ata_identify (struct grub_ata *dev) if (err || parms.size != GRUB_DISK_SECTOR_SIZE) { grub_uint8_t sts = parms.taskfile.status; - grub_free (info); + 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 @@ -167,14 +167,14 @@ grub_ata_identify (struct grub_ata *dev) /* Determine the amount of sectors. */ if (dev->addr != GRUB_ATA_LBA48) - dev->size = grub_le_to_cpu32(*((grub_uint32_t *) &info16[60])); + dev->size = grub_le_to_cpu32 (info32[30]); else - dev->size = grub_le_to_cpu64(*((grub_uint64_t *) &info16[100])); + dev->size = grub_le_to_cpu64 (info64[25]); if (info16[106] & (1 << 12)) { grub_uint32_t secsize; - secsize = grub_le_to_cpu32 (*((grub_uint32_t *) &info16[117])); + secsize = grub_le_to_cpu32 (grub_get_unaligned32 (&info16[117])); if (secsize & (secsize - 1) || !secsize || secsize > 1048576) secsize = 256; @@ -191,9 +191,9 @@ grub_ata_identify (struct grub_ata *dev) dev->heads = info16[3]; dev->sectors_per_track = info16[6]; - grub_ata_dumpinfo (dev, info); + grub_ata_dumpinfo (dev, info16); - grub_free(info); + grub_free (info16); return 0; } @@ -278,6 +278,7 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, grub_ata_addressing_t addressing = ata->addr; grub_size_t batch; int cmd, cmd_write; + grub_size_t nsectors = 0; grub_dprintf("ata", "grub_ata_readwrite (size=%llu, rw=%d)\n", (unsigned long long) size, rw); @@ -314,9 +315,11 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector, cmd = GRUB_ATA_CMD_READ_SECTORS; cmd_write = GRUB_ATA_CMD_WRITE_SECTORS; } - } + } + + if (batch > (ata->maxbuffer >> ata->log_sector_size)) + batch = (ata->maxbuffer >> ata->log_sector_size); - grub_size_t nsectors = 0; while (nsectors < size) { struct grub_disk_ata_pass_through_parms parms; @@ -534,7 +537,7 @@ grub_atapi_write (struct grub_scsi *scsi __attribute__((unused)), grub_size_t cmdsize __attribute__((unused)), char *cmd __attribute__((unused)), grub_size_t size __attribute__((unused)), - char *buf __attribute__((unused))) + const char *buf __attribute__((unused))) { // XXX: scsi.mod does not use write yet. return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "ATAPI write not implemented"); diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c index 2852b65c4..7b0873948 100644 --- a/grub-core/disk/cryptodisk.c +++ b/grub-core/disk/cryptodisk.c @@ -41,7 +41,7 @@ static const struct grub_arg_option options[] = { {"uuid", 'u', 0, N_("Mount by UUID."), 0, 0}, {"all", 'a', 0, N_("Mount all."), 0, 0}, - {"boot", 'b', 0, N_("Mount all volumes marked as boot."), 0, 0}, + {"boot", 'b', 0, N_("Mount all volumes with `boot' flag set."), 0, 0}, {0, 0, 0, 0, 0, 0} }; @@ -128,6 +128,29 @@ grub_crypto_pcbc_decrypt (grub_crypto_cipher_handle_t cipher, return GPG_ERR_NO_ERROR; } +static gcry_err_code_t +grub_crypto_pcbc_encrypt (grub_crypto_cipher_handle_t cipher, + void *out, void *in, grub_size_t size, + void *iv) +{ + grub_uint8_t *inptr, *outptr, *end; + grub_uint8_t ivt[cipher->cipher->blocksize]; + if (!cipher->cipher->decrypt) + return GPG_ERR_NOT_SUPPORTED; + if (size % cipher->cipher->blocksize != 0) + return GPG_ERR_INV_ARG; + end = (grub_uint8_t *) in + size; + for (inptr = in, outptr = out; inptr < end; + inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize) + { + grub_memcpy (ivt, inptr, cipher->cipher->blocksize); + grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize); + cipher->cipher->encrypt (cipher->ctx, outptr, inptr); + grub_crypto_xor (iv, ivt, outptr, cipher->cipher->blocksize); + } + return GPG_ERR_NO_ERROR; +} + struct lrw_sector { grub_uint8_t low[GRUB_CRYPTODISK_GF_BYTES]; @@ -189,17 +212,18 @@ lrw_xor (const struct lrw_sector *sec, dev->lrw_precalc, sec->low_byte * GRUB_CRYPTODISK_GF_BYTES); } -gcry_err_code_t -grub_cryptodisk_decrypt (struct grub_cryptodisk *dev, - grub_uint8_t * data, grub_size_t len, - grub_disk_addr_t sector) +static gcry_err_code_t +grub_cryptodisk_endecrypt (struct grub_cryptodisk *dev, + grub_uint8_t * data, grub_size_t len, + grub_disk_addr_t sector, int do_encrypt) { grub_size_t i; gcry_err_code_t err; /* The only mode without IV. */ if (dev->mode == GRUB_CRYPTODISK_MODE_ECB && !dev->rekey) - return grub_crypto_ecb_decrypt (dev->cipher, data, data, len); + return (do_encrypt ? grub_crypto_ecb_encrypt (dev->cipher, data, data, len) + : grub_crypto_ecb_decrypt (dev->cipher, data, data, len)); for (i = 0; i < len; i += (1U << dev->log_sector_size)) { @@ -269,15 +293,23 @@ grub_cryptodisk_decrypt (struct grub_cryptodisk *dev, switch (dev->mode) { case GRUB_CRYPTODISK_MODE_CBC: - err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i, - (1U << dev->log_sector_size), iv); + if (do_encrypt) + err = grub_crypto_cbc_encrypt (dev->cipher, data + i, data + i, + (1U << dev->log_sector_size), iv); + else + err = grub_crypto_cbc_decrypt (dev->cipher, data + i, data + i, + (1U << dev->log_sector_size), iv); if (err) return err; break; case GRUB_CRYPTODISK_MODE_PCBC: - err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i, - (1U << dev->log_sector_size), iv); + if (do_encrypt) + err = grub_crypto_pcbc_encrypt (dev->cipher, data + i, data + i, + (1U << dev->log_sector_size), iv); + else + err = grub_crypto_pcbc_decrypt (dev->cipher, data + i, data + i, + (1U << dev->log_sector_size), iv); if (err) return err; break; @@ -294,9 +326,14 @@ grub_cryptodisk_decrypt (struct grub_cryptodisk *dev, { grub_crypto_xor (data + i + j, data + i + j, iv, dev->cipher->cipher->blocksize); - err = grub_crypto_ecb_decrypt (dev->cipher, data + i + j, - data + i + j, - dev->cipher->cipher->blocksize); + if (do_encrypt) + err = grub_crypto_ecb_encrypt (dev->cipher, data + i + j, + data + i + j, + dev->cipher->cipher->blocksize); + else + err = grub_crypto_ecb_decrypt (dev->cipher, data + i + j, + data + i + j, + dev->cipher->cipher->blocksize); if (err) return err; grub_crypto_xor (data + i + j, data + i + j, iv, @@ -312,17 +349,26 @@ grub_cryptodisk_decrypt (struct grub_cryptodisk *dev, generate_lrw_sector (&sec, dev, (grub_uint8_t *) iv); lrw_xor (&sec, dev, data + i); - err = grub_crypto_ecb_decrypt (dev->cipher, data + i, - data + i, - (1U << dev->log_sector_size)); + if (do_encrypt) + err = grub_crypto_ecb_encrypt (dev->cipher, data + i, + data + i, + (1U << dev->log_sector_size)); + else + err = grub_crypto_ecb_decrypt (dev->cipher, data + i, + data + i, + (1U << dev->log_sector_size)); if (err) return err; lrw_xor (&sec, dev, data + i); } break; case GRUB_CRYPTODISK_MODE_ECB: - grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i, - (1U << dev->log_sector_size)); + if (do_encrypt) + grub_crypto_ecb_encrypt (dev->cipher, data + i, data + i, + (1U << dev->log_sector_size)); + else + grub_crypto_ecb_decrypt (dev->cipher, data + i, data + i, + (1U << dev->log_sector_size)); break; default: return GPG_ERR_NOT_IMPLEMENTED; @@ -332,6 +378,14 @@ grub_cryptodisk_decrypt (struct grub_cryptodisk *dev, return GPG_ERR_NO_ERROR; } +gcry_err_code_t +grub_cryptodisk_decrypt (struct grub_cryptodisk *dev, + grub_uint8_t * data, grub_size_t len, + grub_disk_addr_t sector) +{ + return grub_cryptodisk_endecrypt (dev, data, len, sector, 0); +} + gcry_err_code_t grub_cryptodisk_setkey (grub_cryptodisk_t dev, grub_uint8_t *key, grub_size_t keysize) { @@ -447,7 +501,7 @@ grub_cryptodisk_open (const char *name, grub_disk_t disk) if (dev->cheat_fd == -1) dev->cheat_fd = open (dev->cheat, O_RDONLY); if (dev->cheat_fd == -1) - return grub_error (GRUB_ERR_IO, "couldn't open %s: %s", + return grub_error (GRUB_ERR_IO, N_("cannot open `%s': %s"), dev->cheat, strerror (errno)); } #endif @@ -506,8 +560,8 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector, return err; if (grub_util_fd_read (dev->cheat_fd, buf, size << disk->log_sector_size) != (ssize_t) (size << disk->log_sector_size)) - return grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", - dev->cheat); + return grub_error (GRUB_ERR_READ_ERROR, N_("cannot read `%s': %s"), + dev->cheat, strerror (errno)); return GRUB_ERR_NONE; } #endif @@ -526,19 +580,61 @@ grub_cryptodisk_read (grub_disk_t disk, grub_disk_addr_t sector, grub_dprintf ("cryptodisk", "grub_disk_read failed with error %d\n", err); return err; } - gcry_err = grub_cryptodisk_decrypt (dev, (grub_uint8_t *) buf, - size << disk->log_sector_size, - sector); + gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) buf, + size << disk->log_sector_size, + sector, 0); return grub_crypto_gcry_error (gcry_err); } static grub_err_t -grub_cryptodisk_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_cryptodisk_write (grub_disk_t disk, grub_disk_addr_t sector, + grub_size_t size, const char *buf) { - return GRUB_ERR_NOT_IMPLEMENTED_YET; + grub_cryptodisk_t dev = (grub_cryptodisk_t) disk->data; + gcry_err_code_t gcry_err; + char *tmp; + grub_err_t err; + +#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; + 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)); + return GRUB_ERR_NONE; + } +#endif + + tmp = grub_malloc (size << disk->log_sector_size); + if (!tmp) + return grub_errno; + grub_memcpy (tmp, buf, size << disk->log_sector_size); + + grub_dprintf ("cryptodisk", + "Writing %" PRIuGRUB_SIZE " sectors to sector 0x%" + PRIxGRUB_UINT64_T " with offset of %" PRIuGRUB_UINT64_T "\n", + size, sector, dev->offset); + + gcry_err = grub_cryptodisk_endecrypt (dev, (grub_uint8_t *) tmp, + size << disk->log_sector_size, + sector, 1); + if (gcry_err) + { + grub_free (tmp); + return grub_crypto_gcry_error (gcry_err); + } + + err = grub_disk_write (dev->source_disk, + (sector << (disk->log_sector_size + - GRUB_DISK_SECTOR_BITS)) + dev->offset, + 0, size << disk->log_sector_size, tmp); + grub_free (tmp); + return err; } #ifdef GRUB_UTIL @@ -562,6 +658,7 @@ grub_cryptodisk_memberlist (grub_disk_t disk) static void cryptodisk_cleanup (void) { +#if 0 grub_cryptodisk_t dev = cryptodisk_list; grub_cryptodisk_t tmp; @@ -575,6 +672,7 @@ cryptodisk_cleanup (void) grub_free (dev); dev = tmp; } +#endif } grub_err_t diff --git a/grub-core/disk/diskfilter.c b/grub-core/disk/diskfilter.c new file mode 100644 index 000000000..875c7eae6 --- /dev/null +++ b/grub-core/disk/diskfilter.c @@ -0,0 +1,1116 @@ +/* diskfilter.c - module to read RAID arrays. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef GRUB_UTIL +#include +#include +#endif + +GRUB_MOD_LICENSE ("GPLv3+"); + +/* Linked list of DISKFILTER arrays. */ +static struct grub_diskfilter_vg *array_list; +grub_raid5_recover_func_t grub_raid5_recover_func; +grub_raid6_recover_func_t grub_raid6_recover_func; +grub_diskfilter_t grub_diskfilter_list; +static int inscnt = 0; +static int lv_num = 0; + +static struct grub_diskfilter_lv * +find_lv (const char *name); +static int is_lv_readable (struct grub_diskfilter_lv *lv); + + + +static grub_err_t +is_node_readable (const struct grub_diskfilter_node *node) +{ + /* Check whether we actually know the physical volume we want to + read from. */ + if (node->pv) + return !!(node->pv->disk); + if (node->lv) + return is_lv_readable (node->lv); + return 0; +} + +static int +is_lv_readable (struct grub_diskfilter_lv *lv) +{ + unsigned i, j; + if (!lv) + return 0; + for (i = 0; i < lv->segment_count; i++) + { + int need = lv->segments[i].node_count, have = 0; + switch (lv->segments[i].type) + { + case GRUB_DISKFILTER_RAID6: + need--; + case GRUB_DISKFILTER_RAID4: + case GRUB_DISKFILTER_RAID5: + need--; + case GRUB_DISKFILTER_STRIPED: + break; + + case GRUB_DISKFILTER_MIRROR: + need = 1; + break; + + case GRUB_DISKFILTER_RAID10: + { + unsigned int n; + n = lv->segments[i].layout & 0xFF; + if (n == 1) + n = (lv->segments[i].layout >> 8) & 0xFF; + need = lv->segments[i].node_count - n + 1; + } + break; + } + for (j = 0; j < lv->segments[i].node_count; j++) + { + if (is_node_readable (lv->segments[i].nodes + j)) + have++; + if (have >= need) + break; + } + if (have < need) + return 0; + } + + return 1; +} + +static grub_err_t +insert_array (grub_disk_t disk, const struct grub_diskfilter_pv_id *id, + struct grub_diskfilter_vg *array, + grub_disk_addr_t start_sector, const char *scanner_name, + grub_diskfilter_t diskfilter __attribute__ ((unused))); + +static int +scan_disk (const char *name) +{ + 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) + { + id.uuid = 0; + id.uuidlen = 0; + arr = diskfilter->detect (disk, &id, &start_sector); + if (arr && + (! insert_array (disk, &id, arr, start_sector, diskfilter->name, + 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; + + if (scan_depth > 100) + return 0; + + disk = grub_disk_open (name); + if (!disk) + { + grub_errno = GRUB_ERR_NONE; + return 0; + } + scan_depth++; + if (hook (disk, 0)) + return 1; + if (grub_partition_iterate (disk, hook)) + return 1; + scan_depth--; + grub_disk_close (disk); + return 0; +} + +static void +scan_devices (const char *arname) +{ + grub_disk_dev_t p; + grub_disk_pull_t pull; + + 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, pull)) + return; + if (arname && is_lv_readable (find_lv (arname))) + return; + } +} + +static int +grub_diskfilter_iterate (int (*hook) (const char *name), + grub_disk_pull_t pull) +{ + struct grub_diskfilter_vg *array; + int islcnt = 0; + + if (pull == GRUB_DISK_PULL_RESCAN) + { + islcnt = inscnt; + scan_devices (NULL); + } + + if (pull != GRUB_DISK_PULL_NONE && pull != GRUB_DISK_PULL_RESCAN) + return 0; + + for (array = array_list; array; array = array->next) + { + struct grub_diskfilter_lv *lv; + if (array->lvs) + for (lv = array->lvs; lv; lv = lv->next) + if (lv->visible && lv->fullname && lv->became_readable_at >= islcnt) + { + if (hook (lv->fullname)) + return 1; + } + } + + return 0; +} + +#ifdef GRUB_UTIL +static grub_disk_memberlist_t +grub_diskfilter_memberlist (grub_disk_t disk) +{ + struct grub_diskfilter_lv *lv = disk->data; + grub_disk_memberlist_t list = NULL, tmp; + struct grub_diskfilter_pv *pv; + + if (lv->vg->pvs) + for (pv = lv->vg->pvs; pv; pv = pv->next) + { + if (!pv->disk) + grub_util_error (_("Couldn't find physical volume `%s'." + " Check your device.map"), pv->name); + tmp = grub_malloc (sizeof (*tmp)); + tmp->disk = pv->disk; + tmp->next = list; + list = tmp; + } + + return list; +} + +void +grub_diskfilter_print_partmap (grub_disk_t disk) +{ + struct grub_diskfilter_lv *lv = disk->data; + struct grub_diskfilter_pv *pv; + + if (lv->vg->pvs) + for (pv = lv->vg->pvs; pv; pv = pv->next) + { + grub_size_t s; + if (!pv->disk) + grub_util_error (_("Couldn't find physical volume `%s'." + " Check your device.map"), pv->name); + for (s = 0; pv->partmaps[s]; s++) + grub_printf ("%s ", pv->partmaps[s]); + } +} + +static const char * +grub_diskfilter_getname (struct grub_disk *disk) +{ + struct grub_diskfilter_lv *array = disk->data; + + return array->vg->driver->name; +} +#endif + +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 struct grub_diskfilter_lv * +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)) + 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 + && is_lv_readable (lv)) + return lv; + } + return NULL; +} + +static grub_err_t +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) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown DISKFILTER device %s", + name); + + lv = find_lv (name); + + if (! lv) + { + scan_devices (name); + if (grub_errno) + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + } + lv = find_lv (name); + } + + if (!lv) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown DISKFILTER device %s", + name); + + disk->id = lv->number; + disk->data = lv; + + grub_dprintf ("diskfilter", "%s: total_devs=%d, total_size=%lld\n", name, + lv->segments ? lv->segments->node_count : 0, + (unsigned long long) lv->size); + disk->total_sectors = lv->size; + grub_dprintf ("diskfilter", "%s: level=%d, total_sectors=%lld\n", name, + lv->segments ? lv->segments->type : 0, + (unsigned long long) disk->total_sectors); + + return 0; +} + +static void +grub_diskfilter_close (grub_disk_t disk __attribute ((unused))) +{ + return; +} + +static grub_err_t +read_lv (struct grub_diskfilter_lv *lv, grub_disk_addr_t sector, + grub_size_t size, char *buf); + +grub_err_t +grub_diskfilter_read_node (const struct grub_diskfilter_node *node, + grub_disk_addr_t sector, + grub_size_t size, char *buf) +{ + /* Check whether we actually know the physical volume we want to + read from. */ + if (node->pv) + { + if (node->pv->disk) + return grub_disk_read (node->pv->disk, sector + node->start + + node->pv->start_sector, + 0, size << GRUB_DISK_SECTOR_BITS, buf); + else + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, + N_("physical volume %s not found"), node->pv->name); + + } + if (node->lv) + return read_lv (node->lv, sector + node->start, size, buf); + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown node '%s'", node->name); +} + +static grub_err_t +read_segment (struct grub_diskfilter_segment *seg, grub_disk_addr_t sector, + grub_size_t size, char *buf) +{ + grub_err_t err; + switch (seg->type) + { + case GRUB_DISKFILTER_STRIPED: + if (seg->node_count == 1) + return grub_diskfilter_read_node (&seg->nodes[0], + sector, size, buf); + case GRUB_DISKFILTER_MIRROR: + case GRUB_DISKFILTER_RAID10: + { + grub_disk_addr_t read_sector, far_ofs; + grub_uint64_t disknr, b, near, far, ofs; + unsigned int i, j; + + read_sector = grub_divmod64 (sector, seg->stripe_size, &b); + far = ofs = near = 1; + far_ofs = 0; + + if (seg->type == 1) + near = seg->node_count; + else if (seg->type == 10) + { + near = seg->layout & 0xFF; + far = (seg->layout >> 8) & 0xFF; + if (seg->layout >> 16) + { + ofs = far; + far_ofs = 1; + } + else + far_ofs = grub_divmod64 (seg->raid_member_size, + far * seg->stripe_size, 0); + + far_ofs *= seg->stripe_size; + } + + read_sector = grub_divmod64 (read_sector * near, + seg->node_count, + &disknr); + + ofs *= seg->stripe_size; + read_sector *= ofs; + + while (1) + { + grub_size_t read_size; + + read_size = seg->stripe_size - b; + if (read_size > size) + read_size = size; + + for (i = 0; i < near; i++) + { + unsigned int k; + + k = disknr; + for (j = 0; j < far; j++) + { + if (grub_errno == GRUB_ERR_READ_ERROR + || grub_errno == GRUB_ERR_UNKNOWN_DEVICE) + grub_errno = GRUB_ERR_NONE; + + err = grub_diskfilter_read_node (&seg->nodes[k], + read_sector + + j * far_ofs + b, + read_size, + buf); + if (! err) + break; + else if (err != GRUB_ERR_READ_ERROR + && err != GRUB_ERR_UNKNOWN_DEVICE) + return err; + k++; + if (k == seg->node_count) + k = 0; + } + + if (! err) + break; + + disknr++; + if (disknr == seg->node_count) + { + disknr = 0; + read_sector += ofs; + } + } + + if (err) + return err; + + buf += read_size << GRUB_DISK_SECTOR_BITS; + size -= read_size; + if (! size) + return GRUB_ERR_NONE; + + b = 0; + disknr += (near - i); + while (disknr >= seg->node_count) + { + disknr -= seg->node_count; + read_sector += ofs; + } + } + } + + case GRUB_DISKFILTER_RAID4: + case GRUB_DISKFILTER_RAID5: + case GRUB_DISKFILTER_RAID6: + { + grub_disk_addr_t read_sector; + grub_uint64_t b, p, n, disknr, e; + + /* n = 1 for level 4 and 5, 2 for level 6. */ + n = seg->type / 3; + + /* Find the first sector to read. */ + read_sector = grub_divmod64 (sector, seg->stripe_size, &b); + read_sector = grub_divmod64 (read_sector, seg->node_count - n, + &disknr); + if (seg->type >= 5) + { + grub_divmod64 (read_sector, seg->node_count, &p); + + if (! (seg->layout & GRUB_RAID_LAYOUT_RIGHT_MASK)) + p = seg->node_count - 1 - p; + + if (seg->layout & GRUB_RAID_LAYOUT_SYMMETRIC_MASK) + { + disknr += p + n; + } + else + { + grub_uint32_t q; + + q = p + (n - 1); + if (q >= seg->node_count) + q -= seg->node_count; + + if (disknr >= p) + disknr += n; + else if (disknr >= q) + disknr += q + 1; + } + + if (disknr >= seg->node_count) + disknr -= seg->node_count; + } + else + p = seg->node_count - n; + read_sector *= seg->stripe_size; + + while (1) + { + grub_size_t read_size; + int next_level; + + read_size = seg->stripe_size - b; + if (read_size > size) + read_size = size; + + e = 0; + /* Reset read error. */ + if (grub_errno == GRUB_ERR_READ_ERROR + || grub_errno == GRUB_ERR_UNKNOWN_DEVICE) + grub_errno = GRUB_ERR_NONE; + + err = grub_diskfilter_read_node (&seg->nodes[disknr], + read_sector + b, + read_size, + buf); + + if ((err) && (err != GRUB_ERR_READ_ERROR + && err != GRUB_ERR_UNKNOWN_DEVICE)) + return err; + e++; + + if (err) + { + grub_errno = GRUB_ERR_NONE; + if (seg->type == GRUB_DISKFILTER_RAID6) + { + err = ((grub_raid6_recover_func) ? + (*grub_raid6_recover_func) (seg, disknr, p, + buf, read_sector + b, + read_size) : + grub_error (GRUB_ERR_BAD_DEVICE, + N_("module `%s' isn't loaded"), + "raid6rec")); + } + else + { + err = ((grub_raid5_recover_func) ? + (*grub_raid5_recover_func) (seg, disknr, + buf, read_sector + b, + read_size) : + grub_error (GRUB_ERR_BAD_DEVICE, + N_("module `%s' isn't loaded"), + "raid5rec")); + } + + if (err) + return err; + } + + buf += read_size << GRUB_DISK_SECTOR_BITS; + size -= read_size; + sector += read_size; + if (! size) + break; + + b = 0; + disknr++; + + if (seg->layout & GRUB_RAID_LAYOUT_SYMMETRIC_MASK) + { + if (disknr == seg->node_count) + disknr = 0; + + next_level = (disknr == p); + } + else + { + if (disknr == p) + disknr += n; + + next_level = (disknr >= seg->node_count); + } + + if (next_level) + { + read_sector += seg->stripe_size; + + if (seg->type >= 5) + { + if (seg->layout & GRUB_RAID_LAYOUT_RIGHT_MASK) + p = (p == seg->node_count - 1) ? 0 : p + 1; + else + p = (p == 0) ? seg->node_count - 1 : p - 1; + + if (seg->layout & GRUB_RAID_LAYOUT_SYMMETRIC_MASK) + { + disknr = p + n; + if (disknr >= seg->node_count) + disknr -= seg->node_count; + } + else + { + disknr -= seg->node_count; + if (disknr == p) + disknr += n; + } + } + else + disknr = 0; + } + } + } + return GRUB_ERR_NONE; + default: + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "unsupported RAID level %d", seg->type); + } +} + +static grub_err_t +read_lv (struct grub_diskfilter_lv *lv, grub_disk_addr_t sector, + grub_size_t size, char *buf) +{ + if (!lv) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown volume"); + + while (size) + { + grub_err_t err = 0; + struct grub_diskfilter_vg *vg = lv->vg; + struct grub_diskfilter_segment *seg = lv->segments; + grub_uint64_t extent; + grub_size_t to_read; + + extent = grub_divmod64 (sector, vg->extent_size, NULL); + + /* Find the right segment. */ + { + unsigned int i; + for (i = 0; i < lv->segment_count; i++) + { + if ((seg->start_extent <= extent) + && ((seg->start_extent + seg->extent_count) > extent)) + break; + seg++; + } + if (i == lv->segment_count) + return grub_error (GRUB_ERR_READ_ERROR, "incorrect segment"); + } + to_read = ((seg->start_extent + seg->extent_count) + * vg->extent_size) - sector; + if (to_read > size) + to_read = size; + + err = read_segment (seg, sector - seg->start_extent * vg->extent_size, + to_read, buf); + if (err) + return err; + + size -= to_read; + sector += to_read; + buf += to_read << GRUB_DISK_SECTOR_BITS; + } + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_diskfilter_read (grub_disk_t disk, grub_disk_addr_t sector, + grub_size_t size, char *buf) +{ + return read_lv (disk->data, sector, size, buf); +} + +static grub_err_t +grub_diskfilter_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_NOT_IMPLEMENTED_YET; +} + +struct grub_diskfilter_vg * +grub_diskfilter_get_vg_by_uuid (grub_size_t uuidlen, char *uuid) +{ + struct grub_diskfilter_vg *p; + + for (p = array_list; p != NULL; p = p->next) + if ((p->uuid_len == uuidlen) && + (! grub_memcmp (p->uuid, uuid, p->uuid_len))) + return p; + return NULL; +} + +grub_err_t +grub_diskfilter_vg_register (struct grub_diskfilter_vg *vg) +{ + struct grub_diskfilter_lv *lv, *p; + struct grub_diskfilter_vg *vgp; + unsigned i; + + grub_dprintf ("diskfilter", "Found array %s\n", vg->name); +#ifdef GRUB_UTIL + grub_util_info ("Found array %s", vg->name); +#endif + + for (lv = vg->lvs; lv; lv = lv->next) + { + lv->number = lv_num++; + + if (lv->fullname) + { + grub_size_t len; + int max_used_number = 0, need_new_name = 0; + len = grub_strlen (lv->fullname); + for (vgp = array_list; vgp; vgp = vgp->next) + for (p = vgp->lvs; p; p = p->next) + { + int cur_num; + char *num, *end; + if (!p->fullname) + continue; + if (grub_strncmp (p->fullname, lv->fullname, len) != 0) + continue; + if (p->fullname[len] == 0) + { + need_new_name = 1; + continue; + } + num = p->fullname + len + 1; + if (!grub_isdigit (num[0])) + continue; + cur_num = grub_strtoul (num, &end, 10); + if (end[0]) + continue; + if (cur_num > max_used_number) + max_used_number = cur_num; + } + if (need_new_name) + { + char *tmp; + tmp = grub_xasprintf ("%s_%d", lv->fullname, max_used_number + 1); + if (!tmp) + return grub_errno; + grub_free (lv->fullname); + lv->fullname = tmp; + } + } + /* RAID 1 doesn't use a chunksize but code assumes one so set + one. */ + for (i = 0; i < lv->segment_count; i++) + if (lv->segments[i].type == 1) + lv->segments[i].stripe_size = 64; + lv->vg = vg; + } + /* Add our new array to the list. */ + vg->next = array_list; + array_list = vg; + return GRUB_ERR_NONE; +} + +struct grub_diskfilter_vg * +grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb, + char *name, grub_uint64_t disk_size, + grub_uint64_t stripe_size, + int layout, int level) +{ + struct grub_diskfilter_vg *array; + int i; + grub_uint64_t totsize; + struct grub_diskfilter_pv *pv; + grub_err_t err; + + switch (level) + { + case 1: + totsize = disk_size; + break; + + case 10: + { + int n; + n = layout & 0xFF; + if (n == 1) + n = (layout >> 8) & 0xFF; + + totsize = grub_divmod64 (nmemb * disk_size, n, 0); + } + break; + + case 0: + case 4: + case 5: + case 6: + totsize = (nmemb - level / 3) * disk_size; + break; + + default: + return NULL; + } + + array = grub_diskfilter_get_vg_by_uuid (uuidlen, uuid); + if (array) + { + if (array->lvs && array->lvs->size < totsize) + { + array->lvs->size = totsize; + if (array->lvs->segments) + array->lvs->segments->extent_count = totsize; + } + + if (array->lvs->segments + && array->lvs->segments->raid_member_size > disk_size) + array->lvs->segments->raid_member_size = disk_size; + + grub_free (uuid); + return array; + } + array = grub_zalloc (sizeof (*array)); + if (!array) + return NULL; + array->uuid = uuid; + array->uuid_len = uuidlen; + if (name) + { + /* Strip off the homehost if present. */ + char *colon = grub_strchr (name, ':'); + char *new_name = grub_xasprintf ("md/%s", + colon ? colon + 1 : name); + + if (! new_name) + goto fail; + + array->name = new_name; + } + array->extent_size = 1; + array->lvs = grub_zalloc (sizeof (*array->lvs)); + if (!array->lvs) + goto fail; + array->lvs->segment_count = 1; + array->lvs->visible = 1; + array->lvs->name = array->name; + array->lvs->fullname = array->name; + + array->lvs->size = totsize; + + array->lvs->segments = grub_zalloc (sizeof (*array->lvs->segments)); + if (!array->lvs->segments) + goto fail; + array->lvs->segments->stripe_size = stripe_size; + array->lvs->segments->layout = layout; + array->lvs->segments->start_extent = 0; + array->lvs->segments->extent_count = totsize; + array->lvs->segments->type = level; + array->lvs->segments->node_count = nmemb; + array->lvs->segments->raid_member_size = disk_size; + array->lvs->segments->nodes + = grub_zalloc (nmemb * sizeof (array->lvs->segments->nodes[0])); + array->lvs->segments->stripe_size = stripe_size; + for (i = 0; i < nmemb; i++) + { + pv = grub_zalloc (sizeof (*pv)); + if (!pv) + goto fail; + pv->id.uuidlen = 0; + pv->id.id = i; + pv->next = array->pvs; + array->pvs = pv; + array->lvs->segments->nodes[i].pv = pv; + } + + err = grub_diskfilter_vg_register (array); + if (err) + goto fail; + + return array; + + fail: + grub_free (array->lvs); + while (array->pvs) + { + pv = array->pvs->next; + grub_free (array->pvs); + array->pvs = pv; + } + grub_free (array); + return NULL; +} + +static grub_err_t +insert_array (grub_disk_t disk, const struct grub_diskfilter_pv_id *id, + struct grub_diskfilter_vg *array, + grub_disk_addr_t start_sector, const char *scanner_name, + grub_diskfilter_t diskfilter __attribute__ ((unused))) +{ + struct grub_diskfilter_pv *pv; + + grub_dprintf ("diskfilter", "Inserting %s into %s (%s)\n", disk->name, + array->name, scanner_name); +#ifdef GRUB_UTIL + grub_util_info ("Inserting %s into %s (%s)\n", disk->name, + array->name, scanner_name); + array->driver = diskfilter; +#endif + + for (pv = array->pvs; pv; pv = pv->next) + if (id->uuidlen == pv->id.uuidlen + && id->uuidlen + ? (grub_memcmp (pv->id.uuid, id->uuid, id->uuidlen) == 0) + : (pv->id.id == id->id)) + { + struct grub_diskfilter_lv *lv; + /* FIXME: Check whether the update time of the superblocks are + the same. */ + /* This could happen to LVM on RAID, pv->disk points to the + raid device, we shouldn't change it. */ + if (! pv->disk) + { + pv->disk = grub_disk_open (disk->name); + if (! pv->disk) + return grub_errno; + pv->part_start = grub_partition_get_start (disk->partition); + pv->part_size = grub_disk_get_size (disk); + +#ifdef GRUB_UTIL + { + grub_size_t s = 1; + grub_partition_t p; + for (p = disk->partition; p; p = p->parent) + s++; + pv->partmaps = xmalloc (s * sizeof (pv->partmaps[0])); + s = 0; + for (p = disk->partition; p; p = p->parent) + pv->partmaps[s++] = xstrdup (p->partmap->name); + pv->partmaps[s++] = 0; + } +#endif + if (start_sector != (grub_uint64_t)-1) + pv->start_sector = start_sector; + pv->start_sector += pv->part_start; + } + /* 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)) + { + lv->became_readable_at = ++inscnt; + scan_disk (lv->fullname); + } + break; + } + + return 0; +} + +static void +free_array (void) +{ + while (array_list) + { + struct grub_diskfilter_vg *vg; + struct grub_diskfilter_pv *pv; + struct grub_diskfilter_lv *lv; + + vg = array_list; + array_list = array_list->next; + + while ((pv = vg->pvs)) + { + vg->pvs = pv->next; + grub_free (pv->name); + if (pv->disk) + grub_disk_close (pv->disk); + if (pv->id.uuidlen) + grub_free (pv->id.uuid); + grub_free (pv->internal_id); + grub_free (pv); + } + + while ((lv = vg->lvs)) + { + unsigned i; + vg->lvs = lv->next; + if (lv->name != lv->fullname) + grub_free (lv->fullname); + if (lv->name != vg->name) + grub_free (lv->name); + for (i = 0; i < lv->segment_count; i++) + grub_free (lv->segments[i].nodes); + grub_free (lv->segments); + grub_free (lv->internal_id); + grub_free (lv); + } + + grub_free (vg->uuid); + grub_free (vg->name); + grub_free (vg); + } + + array_list = 0; +} + +#ifdef GRUB_UTIL +struct grub_diskfilter_pv * +grub_diskfilter_get_pv_from_disk (grub_disk_t disk, + struct grub_diskfilter_vg **vg_out) +{ + struct grub_diskfilter_pv *pv; + struct grub_diskfilter_vg *vg; + + scan_disk (disk->name); + for (vg = array_list; vg; vg = vg->next) + for (pv = vg->pvs; pv; pv = pv->next) + { + if (pv->disk && pv->disk->id == disk->id + && pv->disk->dev->id == disk->dev->id + && pv->part_start == grub_partition_get_start (disk->partition) + && pv->part_size == grub_disk_get_size (disk)) + { + if (vg_out) + *vg_out = vg; + return pv; + } + } + return NULL; +} +#endif + +static struct grub_disk_dev grub_diskfilter_dev = + { + .name = "diskfilter", + .id = GRUB_DISK_DEVICE_DISKFILTER_ID, + .iterate = grub_diskfilter_iterate, + .open = grub_diskfilter_open, + .close = grub_diskfilter_close, + .read = grub_diskfilter_read, + .write = grub_diskfilter_write, +#ifdef GRUB_UTIL + .memberlist = grub_diskfilter_memberlist, + .raidname = grub_diskfilter_getname, +#endif + .next = 0 + }; + + +GRUB_MOD_INIT(diskfilter) +{ + grub_disk_dev_register (&grub_diskfilter_dev); +} + +GRUB_MOD_FINI(diskfilter) +{ + grub_disk_dev_unregister (&grub_diskfilter_dev); + free_array (); +} diff --git a/grub-core/disk/dmraid_nvidia.c b/grub-core/disk/dmraid_nvidia.c index 154193eb0..aa3a6ef6c 100644 --- a/grub-core/disk/dmraid_nvidia.c +++ b/grub-core/disk/dmraid_nvidia.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -90,70 +90,91 @@ struct grub_nv_super struct grub_nv_array array; /* Array information */ } __attribute__ ((packed)); -static grub_err_t -grub_dmraid_nv_detect (grub_disk_t disk, struct grub_raid_array *array, - grub_disk_addr_t *start_sector) +static struct grub_diskfilter_vg * +grub_dmraid_nv_detect (grub_disk_t disk, + struct grub_diskfilter_pv_id *id, + grub_disk_addr_t *start_sector) { grub_disk_addr_t sector; struct grub_nv_super sb; + int level; + int layout; + grub_uint64_t disk_size; + char *uuid; if (disk->partition) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "skip partition"); - - sector = grub_disk_get_size (disk) - 2; + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "skip partition"); + return NULL; + } + sector = grub_disk_get_size (disk); + if (sector == GRUB_DISK_SIZE_UNKNOWN) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "not raid"); + return NULL; + } + sector -= 2; if (grub_disk_read (disk, sector, 0, sizeof (sb), &sb)) - return grub_errno; + return NULL; if (grub_memcmp (sb.vendor, NV_ID_STRING, 6)) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "not raid"); + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "not raid"); + return NULL; + } if (sb.version != NV_VERSION) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "unknown version: %d.%d", sb.version); + { + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "unknown version: %d.%d", sb.version); + return NULL; + } switch (sb.array.raid_level) { case NV_LEVEL_0: - array->level = 0; - array->disk_size = sb.capacity / sb.array.total_volumes; + level = 0; + disk_size = sb.capacity / sb.array.total_volumes; break; case NV_LEVEL_1: - array->level = 1; - array->disk_size = sb.capacity; + level = 1; + disk_size = sb.capacity; break; case NV_LEVEL_5: - array->level = 5; - array->layout = GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC; - array->disk_size = sb.capacity / (sb.array.total_volumes - 1); + level = 5; + layout = GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC; + disk_size = sb.capacity / (sb.array.total_volumes - 1); break; default: - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "unsupported RAID level: %d", sb.array.raid_level); + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "unsupported RAID level: %d", sb.array.raid_level); + return NULL; } - array->name = NULL; - array->number = 0; - array->total_devs = sb.array.total_volumes; - array->chunk_size = sb.array.stripe_block_size; - array->index = sb.unit_number; - array->uuid_len = sizeof (sb.array.signature); - array->uuid = grub_malloc (sizeof (sb.array.signature)); - if (! array->uuid) - return grub_errno; + uuid = grub_malloc (sizeof (sb.array.signature)); + if (! uuid) + return NULL; - grub_memcpy (array->uuid, (char *) &sb.array.signature, + grub_memcpy (uuid, (char *) &sb.array.signature, sizeof (sb.array.signature)); + id->uuidlen = 0; + id->id = sb.unit_number; + *start_sector = 0; - return 0; + return grub_diskfilter_make_raid (sizeof (sb.array.signature), + uuid, sb.array.total_volumes, + NULL, disk_size, + sb.array.stripe_block_size, layout, + level); } -static struct grub_raid grub_dmraid_nv_dev = +static struct grub_diskfilter grub_dmraid_nv_dev = { .name = "dmraid_nv", .detect = grub_dmraid_nv_detect, @@ -162,10 +183,10 @@ static struct grub_raid grub_dmraid_nv_dev = GRUB_MOD_INIT(dm_nv) { - grub_raid_register (&grub_dmraid_nv_dev); + grub_diskfilter_register (&grub_dmraid_nv_dev); } GRUB_MOD_FINI(dm_nv) { - grub_raid_unregister (&grub_dmraid_nv_dev); + grub_diskfilter_unregister (&grub_dmraid_nv_dev); } diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c index 0baeb8e4b..779f2a624 100644 --- a/grub-core/disk/efi/efidisk.c +++ b/grub-core/disk/efi/efidisk.c @@ -533,7 +533,10 @@ grub_efidisk_read (struct grub_disk *disk, grub_disk_addr_t sector, (grub_efi_uintn_t) size << disk->log_sector_size, buf); if (status != GRUB_EFI_SUCCESS) - return grub_error (GRUB_ERR_READ_ERROR, "efidisk read error"); + return grub_error (GRUB_ERR_READ_ERROR, + N_("failure reading sector 0x%llx from `%s'"), + (unsigned long long) sector, + disk->name); return GRUB_ERR_NONE; } @@ -559,7 +562,9 @@ grub_efidisk_write (struct grub_disk *disk, grub_disk_addr_t sector, (grub_efi_uintn_t) size << disk->log_sector_size, (void *) buf); if (status != GRUB_EFI_SUCCESS) - return grub_error (GRUB_ERR_WRITE_ERROR, "efidisk write error"); + return grub_error (GRUB_ERR_WRITE_ERROR, + N_("failure writing sector 0x%llx to `%s'"), + (unsigned long long) sector, disk->name); return GRUB_ERR_NONE; } @@ -664,38 +669,52 @@ grub_efidisk_get_device_handle (grub_disk_t disk) return 0; } +#define NEEDED_BUFLEN sizeof ("XdXXXXXXXXXX") +static inline int +get_diskname_from_path_real (const grub_efi_device_path_t *path, + struct grub_efidisk_data *head, + char *buf) +{ + int count = 0; + struct grub_efidisk_data *d; + for (d = head, count = 0; d; d = d->next, count++) + if (grub_efi_compare_device_paths (d->device_path, path) == 0) + { + grub_snprintf (buf, NEEDED_BUFLEN - 1, "d%d", count); + return 1; + } + return 0; +} + +static inline int +get_diskname_from_path (const grub_efi_device_path_t *path, + char *buf) +{ + if (get_diskname_from_path_real (path, hd_devices, buf + 1)) + { + buf[0] = 'h'; + return 1; + } + + if (get_diskname_from_path_real (path, fd_devices, buf + 1)) + { + buf[0] = 'f'; + return 1; + } + + if (get_diskname_from_path_real (path, cd_devices, buf + 1)) + { + buf[0] = 'c'; + return 1; + } + return 0; +} + char * grub_efidisk_get_device_name (grub_efi_handle_t *handle) { - grub_efi_device_path_t *dp, *ldp, *sdp; - /* This is a hard disk partition. */ - grub_disk_t parent = 0; - auto int find_parent_disk (const char *name); - - /* Find the disk which is the parent of a given hard disk partition. */ - int find_parent_disk (const char *name) - { - grub_disk_t disk; - - disk = grub_disk_open (name); - if (! disk) - return 1; - - if (disk->dev->id == GRUB_DISK_DEVICE_EFIDISK_ID) - { - struct grub_efidisk_data *d; - - d = disk->data; - if (grub_efi_compare_device_paths (d->device_path, sdp) == 0) - { - parent = disk; - return 1; - } - } - - grub_disk_close (disk); - return 0; - } + grub_efi_device_path_t *dp, *ldp; + char device_name[NEEDED_BUFLEN]; dp = grub_efi_get_device_path (handle); if (! dp) @@ -710,9 +729,11 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) == GRUB_EFI_HARD_DRIVE_DEVICE_PATH_SUBTYPE)) { char *partition_name = NULL; - char *device_name; + char *dev_name; grub_efi_device_path_t *dup_dp, *dup_ldp; grub_efi_hard_drive_device_path_t hd; + grub_disk_t parent = 0; + auto int find_partition (grub_disk_t disk, const grub_partition_t part); /* Find the identical partition. */ @@ -741,11 +762,9 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) dup_ldp->length[0] = sizeof (*dup_ldp); dup_ldp->length[1] = 0; - sdp = dup_dp; - - grub_efidisk_iterate (find_parent_disk, GRUB_DISK_PULL_NONE); - if (!parent) - grub_efidisk_iterate (find_parent_disk, GRUB_DISK_PULL_REMOVABLE); + if (!get_diskname_from_path (dup_dp, device_name)) + return 0; + parent = grub_disk_open (device_name); grub_free (dup_dp); if (! parent) @@ -756,7 +775,7 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) if (hd.partition_start == 0 && hd.partition_size == grub_disk_get_size (parent)) { - device_name = grub_strdup (parent->name); + dev_name = grub_strdup (parent->name); } else { @@ -768,29 +787,18 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) return 0; } - device_name = grub_xasprintf ("%s,%s", parent->name, partition_name); + dev_name = grub_xasprintf ("%s,%s", parent->name, partition_name); grub_free (partition_name); } grub_disk_close (parent); - return device_name; + return dev_name; } else { /* This should be an entire disk. */ - char *device_name = 0; - - sdp = dp; - - grub_efidisk_iterate (find_parent_disk, GRUB_DISK_PULL_NONE); - if (!parent) - grub_efidisk_iterate (find_parent_disk, GRUB_DISK_PULL_REMOVABLE); - if (!parent) - return NULL; - device_name = grub_strdup (parent->name); - grub_disk_close (parent); - return device_name; + if (!get_diskname_from_path (dp, device_name)) + return 0; + return grub_strdup (device_name); } - - return 0; } diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c index d3137bc16..855c12e4c 100644 --- a/grub-core/disk/geli.c +++ b/grub-core/disk/geli.c @@ -72,7 +72,7 @@ grub_md_sha256_real (void) const gcry_md_spec_t *ret; ret = grub_crypto_lookup_md_by_name ("sha256"); if (!ret) - grub_util_error ("Coulnd't load sha256"); + grub_util_error ("%s", _("Coulnd't load sha256")); return ret; } @@ -82,7 +82,7 @@ grub_md_sha512_real (void) const gcry_md_spec_t *ret; ret = grub_crypto_lookup_md_by_name ("sha512"); if (!ret) - grub_util_error ("Coulnd't load sha512"); + grub_util_error ("%s", _("Coulnd't load sha512")); return ret; } @@ -221,12 +221,12 @@ grub_util_get_geli_uuid (const char *dev) if (fd < 0) return NULL; - s = grub_util_get_fd_sectors (fd, &log_secsize); + s = grub_util_get_fd_sectors (fd, dev, &log_secsize); grub_util_fd_seek (fd, dev, (s << log_secsize) - 512); uuid = xmalloc (GRUB_MD_SHA256->mdlen * 2 + 1); if (grub_util_fd_read (fd, (void *) &hdr, 512) < 0) - grub_util_error (_("couldn't read ELI metadata")); + grub_util_error ("%s", _("couldn't read ELI metadata")); COMPILE_TIME_ASSERT (sizeof (header) <= 512); header = (void *) &hdr; @@ -235,7 +235,7 @@ grub_util_get_geli_uuid (const char *dev) if (grub_memcmp (header->magic, GELI_MAGIC, sizeof (GELI_MAGIC)) || grub_le_to_cpu32 (header->version) > 5 || grub_le_to_cpu32 (header->version) < 1) - grub_util_error (_("wrong ELI magic or version")); + grub_util_error ("%s", _("wrong ELI magic or version")); err = make_uuid ((void *) &hdr, uuid); if (err) @@ -408,7 +408,7 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev) sector = grub_disk_get_size (source); if (sector == GRUB_DISK_SIZE_UNKNOWN || sector == 0) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "not a geli"); + return grub_error (GRUB_ERR_BUG, "not a geli"); /* Read the GELI header. */ err = grub_disk_read (source, sector - 1, 0, sizeof (header), &header); diff --git a/grub-core/disk/i386/pc/biosdisk.c b/grub-core/disk/i386/pc/biosdisk.c index 173e734d8..8f40f8d17 100644 --- a/grub-core/disk/i386/pc/biosdisk.c +++ b/grub-core/disk/i386/pc/biosdisk.c @@ -465,14 +465,17 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk, int i; if (cmd) - return grub_error (GRUB_ERR_WRITE_ERROR, "can\'t write to cdrom"); + return grub_error (GRUB_ERR_WRITE_ERROR, N_("cannot write to cdrom")); for (i = 0; i < GRUB_BIOSDISK_CDROM_RETRY_COUNT; i++) if (! grub_biosdisk_rw_int13_extensions (0x42, data->drive, dap)) break; if (i == GRUB_BIOSDISK_CDROM_RETRY_COUNT) - return grub_error (GRUB_ERR_READ_ERROR, "cdrom read error"); + return grub_error (GRUB_ERR_READ_ERROR, N_("failure reading sector 0x%llx " + "from `%s'"), + (unsigned long long) sector, + disk->name); } else if (grub_biosdisk_rw_int13_extensions (cmd + 0x42, data->drive, dap)) @@ -494,7 +497,9 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk, 1024 /* cylinders */ * 256 /* heads */ * 63 /* spt */) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "%s out of disk", disk->name); + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("attempt to read or write outside of disk `%s'"), + disk->name); soff = ((grub_uint32_t) sector) % data->sectors + 1; head = ((grub_uint32_t) sector) / data->sectors; @@ -502,7 +507,9 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk, coff = head / data->heads; if (coff >= data->cylinders) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "%s out of disk", disk->name); + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("attempt to read or write outside of disk `%s'"), + disk->name); if (grub_biosdisk_rw_standard (cmd + 0x02, data->drive, coff, hoff, soff, size, segment)) @@ -510,9 +517,15 @@ grub_biosdisk_rw (int cmd, grub_disk_t disk, switch (cmd) { case GRUB_BIOSDISK_READ: - return grub_error (GRUB_ERR_READ_ERROR, "%s read error", disk->name); + return grub_error (GRUB_ERR_READ_ERROR, N_("failure reading sector 0x%llx " + "from `%s'"), + (unsigned long long) sector, + disk->name); case GRUB_BIOSDISK_WRITE: - return grub_error (GRUB_ERR_WRITE_ERROR, "%s write error", disk->name); + return grub_error (GRUB_ERR_WRITE_ERROR, N_("failure writing sector 0x%llx " + "to `%s'"), + (unsigned long long) sector, + disk->name); } } } @@ -576,7 +589,7 @@ grub_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector, struct grub_biosdisk_data *data = disk->data; if (data->flags & GRUB_BIOSDISK_FLAG_CDROM) - return grub_error (GRUB_ERR_IO, "can't write to CDROM"); + return grub_error (GRUB_ERR_IO, N_("cannot write to cdrom")); while (size) { @@ -627,7 +640,8 @@ GRUB_MOD_INIT(biosdisk) if (grub_disk_firmware_is_tainted) { - grub_puts_ (N_("Firmware is marked as tainted, refusing to initialize.")); + grub_puts_ (N_("Native disk drivers are in use. " + "Refusing to use firmware disk interface.")); return; } grub_disk_firmware_fini = grub_disk_biosdisk_fini; diff --git a/grub-core/disk/ieee1275/nand.c b/grub-core/disk/ieee1275/nand.c index 94d62bc4f..7e24cfbd9 100644 --- a/grub-core/disk/ieee1275/nand.c +++ b/grub-core/disk/ieee1275/nand.c @@ -22,6 +22,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -177,7 +178,10 @@ grub_nand_read (grub_disk_t disk, grub_disk_addr_t sector, args.result = 1; if ((IEEE1275_CALL_ENTRY_FN (&args) == -1) || (args.result)) - return grub_error (GRUB_ERR_READ_ERROR, "read error"); + return grub_error (GRUB_ERR_READ_ERROR, N_("failure reading sector 0x%llx " + "from `%s'"), + (unsigned long long) sector, + disk->name); ofs = 0; size -= len; diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c index 2cd43d80a..80bc06a45 100644 --- a/grub-core/disk/ieee1275/ofdisk.c +++ b/grub-core/disk/ieee1275/ofdisk.c @@ -22,6 +22,7 @@ #include #include #include +#include static char *last_devpath; static grub_ieee1275_ihandle_t last_ihandle; @@ -198,8 +199,14 @@ grub_ofdisk_iterate (int (*hook) (const char *name), if (grub_strncmp (ent->shortest, "cdrom", 5) == 0) continue; - if (hook (ent->shortest)) - return 1; + { + char buffer[sizeof ("ieee1275/") + grub_strlen (ent->shortest)]; + char *ptr; + ptr = grub_stpcpy (buffer, "ieee1275/"); + grub_strcpy (ptr, ent->shortest); + if (hook (buffer)) + return 1; + } } } return 0; @@ -241,7 +248,10 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) char prop[64]; grub_ssize_t actual; - devpath = compute_dev_path (name); + if (grub_strncmp (name, "ieee1275/", sizeof ("ieee1275/") - 1) != 0) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, + "not IEEE1275 device"); + devpath = compute_dev_path (name + sizeof ("ieee1275/") - 1); if (! devpath) return grub_errno; @@ -264,7 +274,7 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) if (grub_strcmp (prop, "block")) { grub_free (devpath); - return grub_error (GRUB_ERR_BAD_DEVICE, "not a block device"); + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a block device"); } /* XXX: There is no property to read the number of blocks. There @@ -302,10 +312,9 @@ grub_ofdisk_close (grub_disk_t disk) } static grub_err_t -grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector, - grub_size_t size, char *buf) +grub_ofdisk_prepare (grub_disk_t disk, grub_disk_addr_t sector) { - grub_ssize_t status, actual; + grub_ssize_t status; unsigned long long pos; if (disk->data != last_devpath) @@ -334,28 +343,54 @@ grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector, last_devpath = disk->data; } - pos = sector * 512UL; + pos = sector << GRUB_DISK_SECTOR_BITS; grub_ieee1275_seek (last_ihandle, pos, &status); if (status < 0) return grub_error (GRUB_ERR_READ_ERROR, "seek error, can't seek block %llu", (long long) sector); - grub_ieee1275_read (last_ihandle, buf, size * 512UL, &actual); - if (actual != (grub_ssize_t) (size * 512UL)) - return grub_error (GRUB_ERR_READ_ERROR, "read error on block: %llu", - (long long) sector); + return 0; +} + +static grub_err_t +grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector, + grub_size_t size, char *buf) +{ + grub_err_t err; + grub_ssize_t actual; + err = grub_ofdisk_prepare (disk, sector); + if (err) + return err; + grub_ieee1275_read (last_ihandle, buf, size << GRUB_DISK_SECTOR_BITS, + &actual); + if (actual != (grub_ssize_t) (size << GRUB_DISK_SECTOR_BITS)) + return grub_error (GRUB_ERR_READ_ERROR, N_("failure reading sector 0x%llx " + "from `%s'"), + (unsigned long long) sector, + disk->name); return 0; } static grub_err_t -grub_ofdisk_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_ofdisk_write (grub_disk_t disk, grub_disk_addr_t sector, + grub_size_t size, const char *buf) { - return GRUB_ERR_NOT_IMPLEMENTED_YET; + grub_err_t err; + grub_ssize_t actual; + err = grub_ofdisk_prepare (disk, sector); + if (err) + return err; + grub_ieee1275_write (last_ihandle, buf, size << GRUB_DISK_SECTOR_BITS, + &actual); + if (actual != (grub_ssize_t) (size << GRUB_DISK_SECTOR_BITS)) + return grub_error (GRUB_ERR_WRITE_ERROR, N_("failure writing sector 0x%llx " + "to `%s'"), + (unsigned long long) sector, + disk->name); + + return 0; } static struct grub_disk_dev grub_ofdisk_dev = diff --git a/grub-core/disk/ldm.c b/grub-core/disk/ldm.c new file mode 100644 index 000000000..154c8c98a --- /dev/null +++ b/grub-core/disk/ldm.c @@ -0,0 +1,996 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006,2007,2008,2009,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 + +#ifdef GRUB_UTIL +#include +#include +#endif + +GRUB_MOD_LICENSE ("GPLv3+"); + +#define LDM_GUID_STRLEN 64 +#define LDM_NAME_STRLEN 32 + +typedef grub_uint8_t *grub_ldm_id_t; + +enum { STRIPE = 1, SPANNED = 2, RAID5 = 3 }; + +#define LDM_LABEL_SECTOR 6 +struct grub_ldm_vblk { + char magic[4]; + grub_uint8_t unused1[12]; + grub_uint16_t update_status; + grub_uint8_t flags; + grub_uint8_t type; + grub_uint32_t unused2; + grub_uint8_t dynamic[104]; +} __attribute__ ((packed)); +#define LDM_VBLK_MAGIC "VBLK" + +enum + { + STATUS_CONSISTENT = 0, + STATUS_STILL_ACTIVE = 1, + STATUS_NOT_ACTIVE_YET = 2 + }; + +enum + { + ENTRY_COMPONENT = 0x32, + ENTRY_PARTITION = 0x33, + ENTRY_DISK = 0x34, + ENTRY_VOLUME = 0x51, + }; + +struct grub_ldm_label +{ + char magic[8]; + grub_uint32_t unused1; + grub_uint16_t ver_major; + grub_uint16_t ver_minor; + grub_uint8_t unused2[32]; + char disk_guid[LDM_GUID_STRLEN]; + char host_guid[LDM_GUID_STRLEN]; + char group_guid[LDM_GUID_STRLEN]; + char group_name[LDM_NAME_STRLEN]; + grub_uint8_t unused3[11]; + grub_uint64_t pv_start; + grub_uint64_t pv_size; + grub_uint64_t config_start; + grub_uint64_t config_size; +} __attribute__ ((packed)); + + +#define LDM_MAGIC "PRIVHEAD" + + + +static inline grub_uint64_t +read_int (grub_uint8_t *in, grub_size_t s) +{ + grub_uint8_t *ptr2; + grub_uint64_t ret; + ret = 0; + for (ptr2 = in; ptr2 < in + s; ptr2++) + { + ret <<= 8; + ret |= *ptr2; + } + return ret; +} + +static const grub_gpt_part_type_t ldm_type = GRUB_GPT_PARTITION_TYPE_LDM; + +static grub_disk_addr_t +gpt_ldm_sector (grub_disk_t dsk) +{ + grub_disk_addr_t sector = 0; + grub_err_t err; + auto int hook (grub_disk_t disk, const grub_partition_t p); + int hook (grub_disk_t disk, const grub_partition_t p) + { + struct grub_gpt_partentry gptdata; + grub_partition_t p2; + + p2 = disk->partition; + disk->partition = p->parent; + if (grub_disk_read (disk, p->offset, p->index, + sizeof (gptdata), &gptdata)) + { + disk->partition = p2; + return 0; + } + disk->partition = p2; + + if (! grub_memcmp (&gptdata.type, &ldm_type, 16)) + { + sector = p->start + p->len - 1; + return 1; + } + return 0; + } + err = grub_gpt_partition_map_iterate (dsk, hook); + if (err) + { + grub_errno = GRUB_ERR_NONE; + return 0; + } + return sector; +} + +static struct grub_diskfilter_vg * +make_vg (grub_disk_t disk, + const struct grub_ldm_label *label) +{ + grub_disk_addr_t startsec, endsec, cursec; + struct grub_diskfilter_vg *vg; + grub_err_t err; + + /* First time we see this volume group. We've to create the + whole volume group structure. */ + vg = grub_malloc (sizeof (*vg)); + if (! vg) + return NULL; + vg->extent_size = 1; + vg->name = grub_malloc (LDM_NAME_STRLEN + 1); + vg->uuid = grub_malloc (LDM_GUID_STRLEN + 1); + if (! vg->uuid || !vg->name) + { + grub_free (vg->uuid); + grub_free (vg->name); + return NULL; + } + grub_memcpy (vg->uuid, label->group_guid, LDM_GUID_STRLEN); + grub_memcpy (vg->name, label->group_name, LDM_NAME_STRLEN); + vg->name[LDM_NAME_STRLEN] = 0; + vg->uuid[LDM_GUID_STRLEN] = 0; + vg->uuid_len = grub_strlen (vg->uuid); + + vg->lvs = NULL; + vg->pvs = NULL; + + startsec = grub_be_to_cpu64 (label->config_start); + endsec = startsec + grub_be_to_cpu64 (label->config_size); + + /* First find disks. */ + for (cursec = startsec + 0x12; cursec < endsec; cursec++) + { + struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE + / sizeof (struct grub_ldm_vblk)]; + unsigned i; + err = grub_disk_read (disk, cursec, 0, + sizeof(vblk), &vblk); + if (err) + goto fail2; + + for (i = 0; i < ARRAY_SIZE (vblk); i++) + { + struct grub_diskfilter_pv *pv; + grub_uint8_t *ptr; + if (grub_memcmp (vblk[i].magic, LDM_VBLK_MAGIC, + sizeof (vblk[i].magic)) != 0) + continue; + if (grub_be_to_cpu16 (vblk[i].update_status) + != STATUS_CONSISTENT + && grub_be_to_cpu16 (vblk[i].update_status) + != STATUS_STILL_ACTIVE) + continue; + if (vblk[i].type != ENTRY_DISK) + continue; + pv = grub_zalloc (sizeof (*pv)); + if (!pv) + goto fail2; + + pv->disk = 0; + ptr = vblk[i].dynamic; + if (ptr + *ptr + 1 >= vblk[i].dynamic + + sizeof (vblk[i].dynamic)) + { + grub_free (pv); + goto fail2; + } + pv->internal_id = grub_malloc (ptr[0] + 2); + if (!pv->internal_id) + { + grub_free (pv); + goto fail2; + } + grub_memcpy (pv->internal_id, ptr, (grub_size_t) ptr[0] + 1); + pv->internal_id[(grub_size_t) ptr[0] + 1] = 0; + + ptr += *ptr + 1; + if (ptr + *ptr + 1 >= vblk[i].dynamic + + sizeof (vblk[i].dynamic)) + { + grub_free (pv); + goto fail2; + } + /* ptr = name. */ + ptr += *ptr + 1; + if (ptr + *ptr + 1 + >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) + { + grub_free (pv); + goto fail2; + } + pv->id.uuidlen = *ptr; + pv->id.uuid = grub_malloc (pv->id.uuidlen + 1); + grub_memcpy (pv->id.uuid, ptr + 1, pv->id.uuidlen); + pv->id.uuid[pv->id.uuidlen] = 0; + + pv->next = vg->pvs; + vg->pvs = pv; + } + } + + /* Then find LVs. */ + for (cursec = startsec + 0x12; cursec < endsec; cursec++) + { + struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE + / sizeof (struct grub_ldm_vblk)]; + unsigned i; + err = grub_disk_read (disk, cursec, 0, + sizeof(vblk), &vblk); + if (err) + goto fail2; + + for (i = 0; i < ARRAY_SIZE (vblk); i++) + { + struct grub_diskfilter_lv *lv; + grub_uint8_t *ptr; + if (grub_memcmp (vblk[i].magic, LDM_VBLK_MAGIC, + sizeof (vblk[i].magic)) != 0) + continue; + if (grub_be_to_cpu16 (vblk[i].update_status) + != STATUS_CONSISTENT + && grub_be_to_cpu16 (vblk[i].update_status) + != STATUS_STILL_ACTIVE) + continue; + if (vblk[i].type != ENTRY_VOLUME) + continue; + lv = grub_zalloc (sizeof (*lv)); + if (!lv) + goto fail2; + + lv->vg = vg; + lv->segment_count = 1; + lv->segment_alloc = 1; + lv->visible = 1; + lv->segments = grub_zalloc (sizeof (*lv->segments)); + if (!lv->segments) + goto fail2; + lv->segments->start_extent = 0; + lv->segments->type = GRUB_DISKFILTER_MIRROR; + lv->segments->node_count = 0; + lv->segments->node_alloc = 8; + lv->segments->nodes = grub_zalloc (sizeof (*lv->segments->nodes) + * lv->segments->node_alloc); + if (!lv->segments->nodes) + goto fail2; + ptr = vblk[i].dynamic; + if (ptr + *ptr + 1 >= vblk[i].dynamic + + sizeof (vblk[i].dynamic)) + { + grub_free (lv); + goto fail2; + } + lv->internal_id = grub_malloc ((grub_size_t) ptr[0] + 2); + if (!lv->internal_id) + { + grub_free (lv); + goto fail2; + } + grub_memcpy (lv->internal_id, ptr, ptr[0] + 1); + lv->internal_id[ptr[0] + 1] = 0; + + ptr += *ptr + 1; + if (ptr + *ptr + 1 >= vblk[i].dynamic + + sizeof (vblk[i].dynamic)) + { + grub_free (lv); + goto fail2; + } + lv->name = grub_malloc (*ptr + 1); + if (!lv->name) + { + grub_free (lv->internal_id); + grub_free (lv); + goto fail2; + } + grub_memcpy (lv->name, ptr + 1, *ptr); + lv->name[*ptr] = 0; + lv->fullname = grub_xasprintf ("ldm/%s/%s", + vg->uuid, lv->name); + if (!lv->fullname) + { + grub_free (lv->internal_id); + grub_free (lv->name); + grub_free (lv); + goto fail2; + } + ptr += *ptr + 1; + if (ptr + *ptr + 1 + >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) + { + grub_free (lv->internal_id); + grub_free (lv->name); + grub_free (lv); + goto fail2; + } + /* ptr = volume type. */ + ptr += *ptr + 1; + if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) + { + grub_free (lv->internal_id); + grub_free (lv->name); + grub_free (lv); + goto fail2; + } + /* ptr = flags. */ + ptr += *ptr + 1; + if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) + { + grub_free (lv->internal_id); + grub_free (lv->name); + grub_free (lv); + goto fail2; + } + + /* Skip state, type, unknown, volume number, zeros, flags. */ + ptr += 14 + 1 + 1 + 1 + 3 + 1; + /* ptr = number of children. */ + if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) + { + grub_free (lv->internal_id); + grub_free (lv->name); + grub_free (lv); + goto fail2; + } + ptr += *ptr + 1; + if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) + { + grub_free (lv->internal_id); + grub_free (lv->name); + grub_free (lv); + goto fail2; + } + + /* Skip 2 more fields. */ + ptr += 8 + 8; + if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic) + || ptr + *ptr + 1>= vblk[i].dynamic + + sizeof (vblk[i].dynamic)) + { + grub_free (lv->internal_id); + grub_free (lv->name); + grub_free (lv); + goto fail2; + } + lv->size = read_int (ptr + 1, *ptr); + lv->segments->extent_count = lv->size; + + lv->next = vg->lvs; + vg->lvs = lv; + } + } + + /* Now the components. */ + for (cursec = startsec + 0x12; cursec < endsec; cursec++) + { + struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE + / sizeof (struct grub_ldm_vblk)]; + unsigned i; + err = grub_disk_read (disk, cursec, 0, + sizeof(vblk), &vblk); + if (err) + goto fail2; + + for (i = 0; i < ARRAY_SIZE (vblk); i++) + { + struct grub_diskfilter_lv *comp; + struct grub_diskfilter_lv *lv; + grub_uint8_t type; + + grub_uint8_t *ptr; + if (grub_memcmp (vblk[i].magic, LDM_VBLK_MAGIC, + sizeof (vblk[i].magic)) != 0) + continue; + if (grub_be_to_cpu16 (vblk[i].update_status) + != STATUS_CONSISTENT + && grub_be_to_cpu16 (vblk[i].update_status) + != STATUS_STILL_ACTIVE) + continue; + if (vblk[i].type != ENTRY_COMPONENT) + continue; + comp = grub_zalloc (sizeof (*comp)); + if (!comp) + goto fail2; + comp->visible = 0; + comp->name = 0; + comp->fullname = 0; + + ptr = vblk[i].dynamic; + if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) + { + goto fail2; + } + comp->internal_id = grub_malloc ((grub_size_t) ptr[0] + 2); + if (!comp->internal_id) + { + grub_free (comp); + goto fail2; + } + grub_memcpy (comp->internal_id, ptr, ptr[0] + 1); + comp->internal_id[ptr[0] + 1] = 0; + + ptr += *ptr + 1; + if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) + { + grub_free (comp->internal_id); + grub_free (comp); + goto fail2; + } + /* ptr = name. */ + ptr += *ptr + 1; + if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) + { + grub_free (comp->internal_id); + grub_free (comp); + goto fail2; + } + /* ptr = state. */ + ptr += *ptr + 1; + type = *ptr++; + /* skip zeros. */ + ptr += 4; + if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) + { + grub_free (comp->internal_id); + grub_free (comp); + goto fail2; + } + + /* ptr = number of children. */ + ptr += *ptr + 1; + if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) + { + grub_free (comp->internal_id); + grub_free (comp); + goto fail2; + } + ptr += 8 + 8; + if (ptr + *ptr + 1 >= vblk[i].dynamic + + sizeof (vblk[i].dynamic)) + { + grub_free (comp->internal_id); + grub_free (comp); + goto fail2; + } + for (lv = vg->lvs; lv; lv = lv->next) + { + if (lv->internal_id[0] == ptr[0] + && grub_memcmp (lv->internal_id + 1, ptr + 1, ptr[0]) == 0) + break; + } + if (!lv) + { + grub_free (comp->internal_id); + grub_free (comp); + continue; + } + comp->size = lv->size; + if (type == SPANNED) + { + comp->segment_alloc = 8; + comp->segment_count = 0; + comp->segments = grub_malloc (sizeof (*comp->segments) + * comp->segment_alloc); + if (!comp->segments) + goto fail2; + } + else + { + comp->segment_alloc = 1; + comp->segment_count = 1; + comp->segments = grub_malloc (sizeof (*comp->segments)); + if (!comp->segments) + goto fail2; + comp->segments->start_extent = 0; + comp->segments->extent_count = lv->size; + comp->segments->layout = 0; + if (type == STRIPE) + comp->segments->type = GRUB_DISKFILTER_STRIPED; + else if (type == RAID5) + { + comp->segments->type = GRUB_DISKFILTER_RAID5; + comp->segments->layout = GRUB_RAID_LAYOUT_SYMMETRIC_MASK; + } + else + goto fail2; + ptr += *ptr + 1; + ptr++; + if (!(vblk[i].flags & 0x10)) + goto fail2; + if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic) + || ptr + *ptr + 1 >= vblk[i].dynamic + + sizeof (vblk[i].dynamic)) + { + grub_free (comp->internal_id); + grub_free (comp); + goto fail2; + } + comp->segments->stripe_size = read_int (ptr + 1, *ptr); + ptr += *ptr + 1; + if (ptr + *ptr + 1 >= vblk[i].dynamic + + sizeof (vblk[i].dynamic)) + { + grub_free (comp->internal_id); + grub_free (comp); + goto fail2; + } + comp->segments->node_count = read_int (ptr + 1, *ptr); + comp->segments->node_alloc = comp->segments->node_count; + comp->segments->nodes = grub_zalloc (sizeof (*comp->segments->nodes) + * comp->segments->node_alloc); + if (!lv->segments->nodes) + goto fail2; + } + + if (lv->segments->node_alloc == lv->segments->node_count) + { + void *t; + lv->segments->node_alloc *= 2; + t = grub_realloc (lv->segments->nodes, + sizeof (*lv->segments->nodes) + * lv->segments->node_alloc); + if (!t) + goto fail2; + lv->segments->nodes = t; + } + lv->segments->nodes[lv->segments->node_count].pv = 0; + lv->segments->nodes[lv->segments->node_count].start = 0; + lv->segments->nodes[lv->segments->node_count++].lv = comp; + comp->next = vg->lvs; + vg->lvs = comp; + } + } + /* Partitions. */ + for (cursec = startsec + 0x12; cursec < endsec; cursec++) + { + struct grub_ldm_vblk vblk[GRUB_DISK_SECTOR_SIZE + / sizeof (struct grub_ldm_vblk)]; + unsigned i; + err = grub_disk_read (disk, cursec, 0, + sizeof(vblk), &vblk); + if (err) + goto fail2; + + for (i = 0; i < ARRAY_SIZE (vblk); i++) + { + struct grub_diskfilter_lv *comp; + struct grub_diskfilter_node part; + grub_disk_addr_t start, size; + + grub_uint8_t *ptr; + if (grub_memcmp (vblk[i].magic, LDM_VBLK_MAGIC, + sizeof (vblk[i].magic)) != 0) + continue; + if (grub_be_to_cpu16 (vblk[i].update_status) + != STATUS_CONSISTENT + && grub_be_to_cpu16 (vblk[i].update_status) + != STATUS_STILL_ACTIVE) + continue; + if (vblk[i].type != ENTRY_PARTITION) + continue; + part.lv = 0; + part.pv = 0; + + ptr = vblk[i].dynamic; + if (ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) + { + goto fail2; + } + /* ID */ + ptr += *ptr + 1; + if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) + { + goto fail2; + } + /* ptr = name. */ + ptr += *ptr + 1; + if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) + { + goto fail2; + } + + /* skip zeros and logcommit id. */ + ptr += 4 + 8; + if (ptr + 16 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) + { + goto fail2; + } + part.start = read_int (ptr, 8); + start = read_int (ptr + 8, 8); + ptr += 16; + if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic) + || ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) + { + goto fail2; + } + size = read_int (ptr + 1, *ptr); + ptr += *ptr + 1; + if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic) + || ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) + { + goto fail2; + } + + for (comp = vg->lvs; comp; comp = comp->next) + if (comp->internal_id[0] == ptr[0] + && grub_memcmp (ptr + 1, comp->internal_id + 1, + comp->internal_id[0]) == 0) + goto out; + continue; + out: + if (ptr >= vblk[i].dynamic + sizeof (vblk[i].dynamic) + || ptr + *ptr + 1 >= vblk[i].dynamic + sizeof (vblk[i].dynamic)) + { + goto fail2; + } + ptr += *ptr + 1; + struct grub_diskfilter_pv *pv; + for (pv = vg->pvs; pv; pv = pv->next) + if (pv->internal_id[0] == ptr[0] + && grub_memcmp (pv->internal_id + 1, ptr + 1, ptr[0]) == 0) + part.pv = pv; + + if (comp->segment_alloc == 1) + { + unsigned 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; + } + else + { + if (comp->segment_alloc == comp->segment_count) + { + void *t; + comp->segment_alloc *= 2; + t = grub_realloc (comp->segments, + comp->segment_alloc + * sizeof (*comp->segments)); + if (!t) + goto fail2; + comp->segments = t; + } + comp->segments[comp->segment_count].start_extent = start; + comp->segments[comp->segment_count].extent_count = size; + comp->segments[comp->segment_count].type = GRUB_DISKFILTER_STRIPED; + comp->segments[comp->segment_count].node_count = 1; + comp->segments[comp->segment_count].node_alloc = 1; + comp->segments[comp->segment_count].nodes + = grub_malloc (sizeof (*comp->segments[comp->segment_count].nodes)); + if (!comp->segments[comp->segment_count].nodes) + goto fail2; + comp->segments[comp->segment_count].nodes[0] = part; + comp->segment_count++; + } + } + } + if (grub_diskfilter_vg_register (vg)) + goto fail2; + return vg; + fail2: + { + struct grub_diskfilter_lv *lv, *next_lv; + struct grub_diskfilter_pv *pv, *next_pv; + for (lv = vg->lvs; lv; lv = next_lv) + { + unsigned i; + for (i = 0; i < lv->segment_count; i++) + grub_free (lv->segments[i].nodes); + + next_lv = lv->next; + grub_free (lv->segments); + grub_free (lv->internal_id); + grub_free (lv->name); + grub_free (lv->fullname); + grub_free (lv); + } + for (pv = vg->pvs; pv; pv = next_pv) + { + next_pv = pv->next; + grub_free (pv->id.uuid); + grub_free (pv); + } + } + grub_free (vg->uuid); + grub_free (vg); + return NULL; +} + +static struct grub_diskfilter_vg * +grub_ldm_detect (grub_disk_t disk, + struct grub_diskfilter_pv_id *id, + grub_disk_addr_t *start_sector) +{ + grub_err_t err; + struct grub_ldm_label label; + struct grub_diskfilter_vg *vg; + +#ifdef GRUB_UTIL + grub_util_info ("scanning %s for LDM", disk->name); +#endif + + { + int i; + for (i = 0; i < 3; i++) + { + grub_disk_addr_t sector; + switch (i) + { + case 0: + sector = LDM_LABEL_SECTOR; + break; + case 1: + /* LDM is never inside a partition. */ + if (disk->partition) + continue; + sector = grub_disk_get_size (disk); + if (sector == GRUB_DISK_SIZE_UNKNOWN) + continue; + sector--; + break; + /* FIXME: try the third copy. */ + case 2: + sector = gpt_ldm_sector (disk); + if (!sector) + continue; + break; + } + err = grub_disk_read (disk, sector, 0, + sizeof(label), &label); + if (err) + return NULL; + if (grub_memcmp (label.magic, LDM_MAGIC, sizeof (label.magic)) == 0 + && grub_be_to_cpu16 (label.ver_major) == 0x02 + && grub_be_to_cpu16 (label.ver_minor) >= 0x0b + && grub_be_to_cpu16 (label.ver_minor) <= 0x0c) + break; + } + + /* Return if we didn't find a label. */ + if (i == 3) + { +#ifdef GRUB_UTIL + grub_util_info ("no LDM signature found"); +#endif + return NULL; + } + } + + id->uuid = grub_malloc (LDM_GUID_STRLEN + 1); + if (!id->uuid) + return NULL; + grub_memcpy (id->uuid, label.disk_guid, LDM_GUID_STRLEN); + id->uuid[LDM_GUID_STRLEN] = 0; + id->uuidlen = grub_strlen ((char *) id->uuid); + *start_sector = grub_be_to_cpu64 (label.pv_start); + + { + grub_size_t s; + for (s = 0; s < LDM_GUID_STRLEN && label.group_guid[s]; s++); + vg = grub_diskfilter_get_vg_by_uuid (s, label.group_guid); + if (! vg) + vg = make_vg (disk, &label); + } + + if (!vg) + { + grub_free (id->uuid); + return NULL; + } + return vg; +} + +#ifdef GRUB_UTIL + +char * +grub_util_get_ldm (grub_disk_t disk, grub_disk_addr_t start) +{ + struct grub_diskfilter_pv *pv = NULL; + struct grub_diskfilter_vg *vg = NULL; + struct grub_diskfilter_lv *res, *lv; + + pv = grub_diskfilter_get_pv_from_disk (disk, &vg); + + if (!pv) + return NULL; + + for (lv = vg->lvs; lv; lv = lv->next) + if (lv->segment_count == 1 && lv->segments->node_count == 1 + && lv->segments->type == GRUB_DISKFILTER_STRIPED + && lv->segments->nodes->pv == pv + && lv->segments->nodes->start + pv->start_sector == start) + { + res = lv; + break; + } + for (lv = vg->lvs; lv; lv = lv->next) + if (lv->segment_count == 1 && lv->segments->node_count == 1 + && lv->segments->type == GRUB_DISKFILTER_MIRROR + && lv->segments->nodes->lv == lv) + { + res = lv; + break; + } + if (res->fullname) + return grub_strdup (lv->fullname); + return NULL; +} + +int +grub_util_is_ldm (grub_disk_t disk) +{ + int i; + for (i = 0; i < 3; i++) + { + grub_disk_addr_t sector; + grub_err_t err; + struct grub_ldm_label label; + + switch (i) + { + case 0: + sector = LDM_LABEL_SECTOR; + break; + case 1: + /* LDM is never inside a partition. */ + if (disk->partition) + continue; + sector = grub_disk_get_size (disk); + if (sector == GRUB_DISK_SIZE_UNKNOWN) + continue; + sector--; + break; + /* FIXME: try the third copy. */ + case 2: + sector = gpt_ldm_sector (disk); + if (!sector) + continue; + break; + } + err = grub_disk_read (disk, sector, 0, sizeof(label), &label); + if (err) + { + grub_errno = GRUB_ERR_NONE; + return 0; + } + /* This check is more relaxed on purpose. */ + if (grub_memcmp (label.magic, LDM_MAGIC, sizeof (label.magic)) == 0) + return 1; + } + + return 0; +} + +grub_err_t +grub_util_ldm_embed (struct grub_disk *disk, unsigned int *nsectors, + grub_embed_type_t embed_type, + grub_disk_addr_t **sectors) +{ + struct grub_diskfilter_pv *pv = NULL; + struct grub_diskfilter_vg *vg; + struct grub_diskfilter_lv *lv; + unsigned i; + + if (embed_type != GRUB_EMBED_PCBIOS) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "LDM curently supports only PC-BIOS embedding"); + if (disk->partition) + return grub_error (GRUB_ERR_BUG, "disk isn't LDM"); + pv = grub_diskfilter_get_pv_from_disk (disk, &vg); + if (!pv) + return grub_error (GRUB_ERR_BUG, "disk isn't LDM"); + for (lv = vg->lvs; lv; lv = lv->next) + { + struct grub_diskfilter_lv *comp; + + if (!lv->visible || !lv->fullname) + continue; + + if (lv->segment_count != 1) + continue; + if (lv->segments->type != GRUB_DISKFILTER_MIRROR + || lv->segments->node_count != 1 + || lv->segments->start_extent != 0 + || lv->segments->extent_count != lv->size) + continue; + + comp = lv->segments->nodes->lv; + if (!comp) + continue; + + if (comp->segment_count != 1 || comp->size != lv->size) + continue; + if (comp->segments->type != GRUB_DISKFILTER_STRIPED + || comp->segments->node_count != 1 + || comp->segments->start_extent != 0 + || comp->segments->extent_count != lv->size) + continue; + + /* How to implement proper check is to be discussed. */ +#if 1 + if (1) + continue; +#else + if (grub_strcmp (lv->name, "Volume5") != 0) + continue; +#endif + if (lv->size < *nsectors) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("your LDM embed Partition is too small;" + " embedding won't be possible")); + *nsectors = lv->size; + *sectors = grub_malloc (*nsectors * sizeof (**sectors)); + if (!*sectors) + return grub_errno; + for (i = 0; i < *nsectors; i++) + (*sectors)[i] = (lv->segments->nodes->start + + comp->segments->nodes->start + + comp->segments->nodes->pv->start_sector + i); + return GRUB_ERR_NONE; + } + + return grub_error (GRUB_ERR_FILE_NOT_FOUND, + N_("this LDM has no Embedding Partition;" + " embedding won't be possible")); +} +#endif + +static struct grub_diskfilter grub_ldm_dev = { + .name = "ldm", + .detect = grub_ldm_detect, + .next = 0 +}; + +GRUB_MOD_INIT (ldm) +{ + grub_diskfilter_register (&grub_ldm_dev); +} + +GRUB_MOD_FINI (ldm) +{ + grub_diskfilter_unregister (&grub_ldm_dev); +} diff --git a/grub-core/disk/loopback.c b/grub-core/disk/loopback.c index dca83b7c6..afdcf481d 100644 --- a/grub-core/disk/loopback.c +++ b/grub-core/disk/loopback.c @@ -38,7 +38,7 @@ static struct grub_loopback *loopback_list; static const struct grub_arg_option options[] = { - {"delete", 'd', 0, N_("Delete the loopback device entry."), 0, 0}, + {"delete", 'd', 0, N_("Delete the specified loopback drive."), 0, 0}, {0, 0, 0, 0, 0, 0} }; @@ -86,7 +86,7 @@ grub_cmd_loopback (grub_extcmd_context_t ctxt, int argc, char **args) return delete_loopback (args[0]); if (argc < 2) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); file = grub_file_open (args[1]); if (! file) @@ -224,7 +224,7 @@ GRUB_MOD_INIT(loopback) { cmd = grub_register_extcmd ("loopback", grub_cmd_loopback, 0, N_("[-d] DEVICENAME FILE."), - N_("Make a device of a file."), options); + N_("Make a virtual drive from a file."), options); grub_disk_dev_register (&grub_loopback_dev); } diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c index 2fd736439..d7be3e8a5 100644 --- a/grub-core/disk/lvm.c +++ b/grub-core/disk/lvm.c @@ -33,24 +33,18 @@ GRUB_MOD_LICENSE ("GPLv3+"); -static struct grub_lvm_vg *vg_list; -static int lv_count; -static int scan_depth = 0; - -static int is_lv_readable (struct grub_lvm_lv *lv); - /* Go the string STR and return the number after STR. *P will point at the number. In case STR is not found, *P will be NULL and the return value will be 0. */ static int -grub_lvm_getvalue (char **p, char *str) +grub_lvm_getvalue (char **p, const char *str) { *p = grub_strstr (*p, str); if (! *p) return 0; *p += grub_strlen (str); - return grub_strtoul (*p, NULL, 10); + return grub_strtoul (*p, p, 10); } #if 0 @@ -69,7 +63,7 @@ grub_lvm_checkvalue (char **p, char *str, char *tmpl) #endif static int -grub_lvm_check_flag (char *p, char *str, char *flag) +grub_lvm_check_flag (char *p, const char *str, const char *flag) { int len_str = grub_strlen (str), len_flag = grub_strlen (flag); while (1) @@ -101,932 +95,671 @@ grub_lvm_check_flag (char *p, char *str, char *flag) } } -static struct grub_lvm_lv * -find_lv (const char *name) +static struct grub_diskfilter_vg * +grub_lvm_detect (grub_disk_t disk, + struct grub_diskfilter_pv_id *id, + grub_disk_addr_t *start_sector) { - struct grub_lvm_vg *vg; - struct grub_lvm_lv *lv = NULL; - for (vg = vg_list; vg; vg = vg->next) + grub_err_t err; + grub_uint64_t mda_offset, mda_size; + char buf[GRUB_LVM_LABEL_SIZE]; + char vg_id[GRUB_LVM_ID_STRLEN+1]; + char pv_id[GRUB_LVM_ID_STRLEN+1]; + char *metadatabuf, *p, *q, *vgname; + struct grub_lvm_label_header *lh = (struct grub_lvm_label_header *) buf; + struct grub_lvm_pv_header *pvh; + struct grub_lvm_disk_locn *dlocn; + struct grub_lvm_mda_header *mdah; + struct grub_lvm_raw_locn *rlocn; + unsigned int i, j, vgname_len; + struct grub_diskfilter_vg *vg; + struct grub_diskfilter_pv *pv; + + /* Search for label. */ + for (i = 0; i < GRUB_LVM_LABEL_SCAN_SECTORS; i++) { - if (vg->lvs) - for (lv = vg->lvs; lv; lv = lv->next) - if ((grub_strcmp (lv->fullname, name) == 0 - || grub_strcmp (lv->compatname, name) == 0) - && is_lv_readable (lv)) - return lv; + err = grub_disk_read (disk, i, 0, sizeof(buf), buf); + if (err) + goto fail; + + if ((! grub_strncmp ((char *)lh->id, GRUB_LVM_LABEL_ID, + sizeof (lh->id))) + && (! grub_strncmp ((char *)lh->type, GRUB_LVM_LVM2_LABEL, + sizeof (lh->type)))) + break; } + + /* Return if we didn't find a label. */ + if (i == GRUB_LVM_LABEL_SCAN_SECTORS) + { +#ifdef GRUB_UTIL + grub_util_info ("no LVM signature found"); +#endif + goto fail; + } + + pvh = (struct grub_lvm_pv_header *) (buf + grub_le_to_cpu32(lh->offset_xl)); + + for (i = 0, j = 0; i < GRUB_LVM_ID_LEN; i++) + { + pv_id[j++] = pvh->pv_uuid[i]; + if ((i != 1) && (i != 29) && (i % 4 == 1)) + pv_id[j++] = '-'; + } + pv_id[j] = '\0'; + + dlocn = pvh->disk_areas_xl; + + dlocn++; + /* Is it possible to have multiple data/metadata areas? I haven't + seen devices that have it. */ + if (dlocn->offset) + { + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "we don't support multiple LVM data areas"); + +#ifdef GRUB_UTIL + grub_util_info ("we don't support multiple LVM data areas\n"); +#endif + goto fail; + } + + dlocn++; + mda_offset = grub_le_to_cpu64 (dlocn->offset); + mda_size = grub_le_to_cpu64 (dlocn->size); + + /* It's possible to have multiple copies of metadata areas, we just use the + first one. */ + + /* Allocate buffer space for the circular worst-case scenario. */ + metadatabuf = grub_malloc (2 * mda_size); + if (! metadatabuf) + goto fail; + + err = grub_disk_read (disk, 0, mda_offset, mda_size, metadatabuf); + if (err) + goto fail2; + + mdah = (struct grub_lvm_mda_header *) metadatabuf; + if ((grub_strncmp ((char *)mdah->magic, GRUB_LVM_FMTT_MAGIC, + sizeof (mdah->magic))) + || (grub_le_to_cpu32 (mdah->version) != GRUB_LVM_FMTT_VERSION)) + { + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "unknown LVM metadata header"); +#ifdef GRUB_UTIL + grub_util_info ("unknown LVM metadata header\n"); +#endif + goto fail2; + } + + rlocn = mdah->raw_locns; + if (grub_le_to_cpu64 (rlocn->offset) + grub_le_to_cpu64 (rlocn->size) > + grub_le_to_cpu64 (mdah->size)) + { + /* Metadata is circular. Copy the wrap in place. */ + grub_memcpy (metadatabuf + mda_size, + metadatabuf + GRUB_LVM_MDA_HEADER_SIZE, + grub_le_to_cpu64 (rlocn->offset) + + grub_le_to_cpu64 (rlocn->size) - + grub_le_to_cpu64 (mdah->size)); + } + p = q = metadatabuf + grub_le_to_cpu64 (rlocn->offset); + + while (*q != ' ' && q < metadatabuf + mda_size) + q++; + + if (q == metadatabuf + mda_size) + { +#ifdef GRUB_UTIL + grub_util_info ("error parsing metadata\n"); +#endif + goto fail2; + } + + vgname_len = q - p; + vgname = grub_malloc (vgname_len + 1); + if (!vgname) + goto fail2; + + grub_memcpy (vgname, p, vgname_len); + vgname[vgname_len] = '\0'; + + p = grub_strstr (q, "id = \""); + if (p == NULL) + { +#ifdef GRUB_UTIL + grub_util_info ("couldn't find ID\n"); +#endif + goto fail3; + } + p += sizeof ("id = \"") - 1; + grub_memcpy (vg_id, p, GRUB_LVM_ID_STRLEN); + vg_id[GRUB_LVM_ID_STRLEN] = '\0'; + + vg = grub_diskfilter_get_vg_by_uuid (GRUB_LVM_ID_STRLEN, vg_id); + + if (! vg) + { + /* First time we see this volume group. We've to create the + whole volume group structure. */ + vg = grub_malloc (sizeof (*vg)); + if (! vg) + goto fail3; + vg->name = vgname; + vg->uuid = grub_malloc (GRUB_LVM_ID_STRLEN); + if (! vg->uuid) + goto fail3; + grub_memcpy (vg->uuid, vg_id, GRUB_LVM_ID_STRLEN); + vg->uuid_len = GRUB_LVM_ID_STRLEN; + + vg->extent_size = grub_lvm_getvalue (&p, "extent_size = "); + if (p == NULL) + { +#ifdef GRUB_UTIL + grub_util_info ("unknown extent size\n"); +#endif + goto fail4; + } + + vg->lvs = NULL; + vg->pvs = NULL; + + p = grub_strstr (p, "physical_volumes {"); + if (p) + { + p += sizeof ("physical_volumes {") - 1; + + /* Add all the pvs to the volume group. */ + while (1) + { + int s; + while (grub_isspace (*p)) + p++; + + if (*p == '}') + break; + + pv = grub_zalloc (sizeof (*pv)); + q = p; + while (*q != ' ') + q++; + + s = q - p; + pv->name = grub_malloc (s + 1); + grub_memcpy (pv->name, p, s); + pv->name[s] = '\0'; + + p = grub_strstr (p, "id = \""); + if (p == NULL) + goto pvs_fail; + p += sizeof("id = \"") - 1; + + pv->id.uuid = grub_malloc (GRUB_LVM_ID_STRLEN); + if (!pv->id.uuid) + goto pvs_fail; + grub_memcpy (pv->id.uuid, p, GRUB_LVM_ID_STRLEN); + pv->id.uuidlen = GRUB_LVM_ID_STRLEN; + + pv->start_sector = grub_lvm_getvalue (&p, "pe_start = "); + if (p == NULL) + { +#ifdef GRUB_UTIL + grub_util_info ("unknown pe_start\n"); +#endif + goto pvs_fail; + } + + p = grub_strchr (p, '}'); + if (p == NULL) + { +#ifdef GRUB_UTIL + grub_util_info ("error parsing pe_start\n"); +#endif + goto pvs_fail; + } + p++; + + pv->disk = NULL; + pv->next = vg->pvs; + vg->pvs = pv; + + continue; + pvs_fail: + grub_free (pv->name); + grub_free (pv); + goto fail4; + } + } + + p = grub_strstr (p, "logical_volumes"); + if (p) + { + p += sizeof ("logical_volumes = ") - 1; + + /* And add all the lvs to the volume group. */ + while (1) + { + int s; + int skip_lv = 0; + struct grub_diskfilter_lv *lv; + struct grub_diskfilter_segment *seg; + int is_pvmove; + + while (grub_isspace (*p)) + p++; + + if (*p == '}') + break; + + lv = grub_zalloc (sizeof (*lv)); + + q = p; + while (*q != ' ') + q++; + + s = q - p; + lv->name = grub_strndup (p, s); + if (!lv->name) + goto lvs_fail; + + { + const char *iptr; + char *optr; + lv->fullname = grub_malloc (sizeof ("lvm/") - 1 + 2 * vgname_len + + 1 + 2 * s + 1); + if (!lv->fullname) + goto lvs_fail; + + grub_memcpy (lv->fullname, "lvm/", sizeof ("lvm/") - 1); + optr = lv->fullname + sizeof ("lvm/") - 1; + for (iptr = vgname; iptr < vgname + vgname_len; iptr++) + { + *optr++ = *iptr; + if (*iptr == '-') + *optr++ = '-'; + } + *optr++ = '-'; + for (iptr = p; iptr < p + s; iptr++) + { + *optr++ = *iptr; + if (*iptr == '-') + *optr++ = '-'; + } + *optr++ = 0; + } + + lv->size = 0; + + lv->visible = grub_lvm_check_flag (p, "status", "VISIBLE"); + is_pvmove = grub_lvm_check_flag (p, "status", "PVMOVE"); + + lv->segment_count = grub_lvm_getvalue (&p, "segment_count = "); + if (p == NULL) + { +#ifdef GRUB_UTIL + grub_util_info ("unknown segment_count\n"); +#endif + goto lvs_fail; + } + lv->segments = grub_malloc (sizeof (*seg) * lv->segment_count); + seg = lv->segments; + + for (i = 0; i < lv->segment_count; i++) + { + + p = grub_strstr (p, "segment"); + if (p == NULL) + { +#ifdef GRUB_UTIL + grub_util_info ("unknown segment\n"); +#endif + goto lvs_segment_fail; + } + + seg->start_extent = grub_lvm_getvalue (&p, "start_extent = "); + if (p == NULL) + { +#ifdef GRUB_UTIL + grub_util_info ("unknown start_extent\n"); +#endif + goto lvs_segment_fail; + } + seg->extent_count = grub_lvm_getvalue (&p, "extent_count = "); + if (p == NULL) + { +#ifdef GRUB_UTIL + grub_util_info ("unknown extent_count\n"); +#endif + goto lvs_segment_fail; + } + + p = grub_strstr (p, "type = \""); + if (p == NULL) + goto lvs_segment_fail; + p += sizeof("type = \"") - 1; + + lv->size += seg->extent_count * vg->extent_size; + + if (grub_memcmp (p, "striped\"", + sizeof ("striped\"") - 1) == 0) + { + struct grub_diskfilter_node *stripe; + + seg->type = GRUB_DISKFILTER_STRIPED; + seg->node_count = grub_lvm_getvalue (&p, "stripe_count = "); + if (p == NULL) + { +#ifdef GRUB_UTIL + grub_util_info ("unknown stripe_count\n"); +#endif + goto lvs_segment_fail; + } + + if (seg->node_count != 1) + seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = "); + + seg->nodes = grub_zalloc (sizeof (*stripe) + * seg->node_count); + stripe = seg->nodes; + + p = grub_strstr (p, "stripes = ["); + if (p == NULL) + { +#ifdef GRUB_UTIL + grub_util_info ("unknown stripes\n"); +#endif + goto lvs_segment_fail2; + } + p += sizeof("stripes = [") - 1; + + for (j = 0; j < seg->node_count; j++) + { + p = grub_strchr (p, '"'); + if (p == NULL) + continue; + q = ++p; + while (*q != '"') + q++; + + s = q - p; + + stripe->name = grub_malloc (s + 1); + if (stripe->name == NULL) + goto lvs_segment_fail2; + + grub_memcpy (stripe->name, p, s); + stripe->name[s] = '\0'; + + p = q + 1; + + stripe->start = grub_lvm_getvalue (&p, ",") + * vg->extent_size; + if (p == NULL) + continue; + + stripe++; + } + } + else if (grub_memcmp (p, "mirror\"", sizeof ("mirror\"") - 1) + == 0) + { + seg->type = GRUB_DISKFILTER_MIRROR; + seg->node_count = grub_lvm_getvalue (&p, "mirror_count = "); + if (p == NULL) + { +#ifdef GRUB_UTIL + grub_util_info ("unknown mirror_count\n"); +#endif + goto lvs_segment_fail; + } + + seg->nodes = grub_zalloc (sizeof (seg->nodes[0]) + * seg->node_count); + + p = grub_strstr (p, "mirrors = ["); + if (p == NULL) + { +#ifdef GRUB_UTIL + grub_util_info ("unknown mirrors\n"); +#endif + goto lvs_segment_fail2; + } + p += sizeof("mirrors = [") - 1; + + for (j = 0; j < seg->node_count; j++) + { + char *lvname; + + p = grub_strchr (p, '"'); + if (p == NULL) + continue; + q = ++p; + while (*q != '"') + q++; + + s = q - p; + + lvname = grub_malloc (s + 1); + if (lvname == NULL) + goto lvs_segment_fail2; + + grub_memcpy (lvname, p, s); + lvname[s] = '\0'; + seg->nodes[j].name = lvname; + p = q + 1; + } + /* Only first (original) is ok with in progress pvmove. */ + if (is_pvmove) + seg->node_count = 1; + } + else if (grub_memcmp (p, "raid", sizeof ("raid") - 1) + == 0 && (p[sizeof ("raid") - 1] >= '4' + && p[sizeof ("raid") - 1] <= '6') + && p[sizeof ("raidX") - 1] == '"') + { + switch (p[sizeof ("raid") - 1]) + { + case '4': + seg->type = GRUB_DISKFILTER_RAID4; + seg->layout = GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC; + break; + case '5': + seg->type = GRUB_DISKFILTER_RAID5; + seg->layout = GRUB_RAID_LAYOUT_LEFT_SYMMETRIC; + break; + case '6': + seg->type = GRUB_DISKFILTER_RAID6; + seg->layout = (GRUB_RAID_LAYOUT_RIGHT_ASYMMETRIC + | GRUB_RAID_LAYOUT_MUL_FROM_POS); + break; + } + seg->node_count = grub_lvm_getvalue (&p, "device_count = "); + + if (p == NULL) + { +#ifdef GRUB_UTIL + grub_util_info ("unknown device_count\n"); +#endif + goto lvs_segment_fail; + } + + seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = "); + if (p == NULL) + { +#ifdef GRUB_UTIL + grub_util_info ("unknown stripe_size\n"); +#endif + goto lvs_segment_fail; + } + + + seg->nodes = grub_zalloc (sizeof (seg->nodes[0]) + * seg->node_count); + + p = grub_strstr (p, "raids = ["); + if (p == NULL) + { +#ifdef GRUB_UTIL + grub_util_info ("unknown mirrors\n"); +#endif + goto lvs_segment_fail2; + } + p += sizeof("raids = [") - 1; + + for (j = 0; j < seg->node_count; j++) + { + char *lvname; + + p = grub_strchr (p, '"'); + p = p ? grub_strchr (p + 1, '"') : 0; + p = p ? grub_strchr (p + 1, '"') : 0; + if (p == NULL) + continue; + q = ++p; + while (*q != '"') + q++; + + s = q - p; + + lvname = grub_malloc (s + 1); + if (lvname == NULL) + goto lvs_segment_fail2; + + grub_memcpy (lvname, p, s); + lvname[s] = '\0'; + seg->nodes[j].name = lvname; + p = q + 1; + } + if (seg->type == GRUB_DISKFILTER_RAID4) + { + char *tmp; + tmp = seg->nodes[0].name; + grub_memmove (seg->nodes, seg->nodes + 1, + sizeof (seg->nodes[0]) + * (seg->node_count - 1)); + seg->nodes[seg->node_count - 1].name = tmp; + } + } + else + { +#ifdef GRUB_UTIL + char *p2; + p2 = grub_strchr (p, '"'); + if (p2) + *p2 = 0; + grub_util_info ("unknown LVM type %s\n", p); + if (p2) + *p2 ='"'; +#endif + /* Found a non-supported type, give up and move on. */ + skip_lv = 1; + break; + } + + seg++; + + continue; + lvs_segment_fail2: + grub_free (seg->nodes); + lvs_segment_fail: + goto fail4; + } + + if (p != NULL) + p = grub_strchr (p, '}'); + if (p == NULL) + goto lvs_fail; + p += 3; + + if (skip_lv) + { + grub_free (lv->name); + grub_free (lv); + continue; + } + + lv->vg = vg; + lv->next = vg->lvs; + vg->lvs = lv; + + continue; + lvs_fail: + grub_free (lv->name); + grub_free (lv); + goto fail4; + } + } + + /* Match lvs. */ + { + struct grub_diskfilter_lv *lv1; + struct grub_diskfilter_lv *lv2; + for (lv1 = vg->lvs; lv1; lv1 = lv1->next) + for (i = 0; i < lv1->segment_count; i++) + for (j = 0; j < lv1->segments[i].node_count; j++) + { + if (vg->pvs) + for (pv = vg->pvs; pv; pv = pv->next) + { + if (! grub_strcmp (pv->name, + lv1->segments[i].nodes[j].name)) + { + lv1->segments[i].nodes[j].pv = pv; + break; + } + } + if (lv1->segments[i].nodes[j].pv == NULL) + for (lv2 = vg->lvs; lv2; lv2 = lv2->next) + if (grub_strcmp (lv2->name, + lv1->segments[i].nodes[j].name) == 0) + lv1->segments[i].nodes[j].lv = lv2; + } + + } + if (grub_diskfilter_vg_register (vg)) + goto fail4; + } + else + { + grub_free (vgname); + } + + id->uuid = grub_malloc (GRUB_LVM_ID_STRLEN); + if (!id->uuid) + goto fail4; + grub_memcpy (id->uuid, pv_id, GRUB_LVM_ID_STRLEN); + id->uuidlen = GRUB_LVM_ID_STRLEN; + grub_free (metadatabuf); + *start_sector = -1; + return vg; + + /* Failure path. */ + fail4: + grub_free (vg); + fail3: + grub_free (vgname); + + fail2: + grub_free (metadatabuf); + fail: return NULL; } -static void -do_lvm_scan (const char *scan_for) -{ - auto int grub_lvm_scan_device (const char *name); - int grub_lvm_scan_device (const char *name) - { - grub_err_t err; - grub_disk_t disk; - grub_uint64_t mda_offset, mda_size; - char buf[GRUB_LVM_LABEL_SIZE]; - char vg_id[GRUB_LVM_ID_STRLEN+1]; - char pv_id[GRUB_LVM_ID_STRLEN+1]; - char *metadatabuf, *p, *q, *vgname; - struct grub_lvm_label_header *lh = (struct grub_lvm_label_header *) buf; - struct grub_lvm_pv_header *pvh; - struct grub_lvm_disk_locn *dlocn; - struct grub_lvm_mda_header *mdah; - struct grub_lvm_raw_locn *rlocn; - unsigned int i, j, vgname_len; - struct grub_lvm_vg *vg; - struct grub_lvm_pv *pv; - -#ifdef GRUB_UTIL - grub_util_info ("scanning %s for LVM", name); -#endif - - disk = grub_disk_open (name); - if (!disk) - { - if (grub_errno == GRUB_ERR_OUT_OF_RANGE) - grub_errno = GRUB_ERR_NONE; - return 0; - } - - for (vg = vg_list; vg; vg = vg->next) - for (pv = vg->pvs; pv; pv = pv->next) - if (pv->disk && pv->disk->id == disk->id - && pv->disk->dev->id == disk->dev->id - && grub_partition_get_start (pv->disk->partition) - == grub_partition_get_start (disk->partition) - && grub_disk_get_size (pv->disk) - == grub_disk_get_size (disk)) - { - grub_disk_close (disk); - return 0; - } - - /* Search for label. */ - for (i = 0; i < GRUB_LVM_LABEL_SCAN_SECTORS; i++) - { - err = grub_disk_read (disk, i, 0, sizeof(buf), buf); - if (err) - goto fail; - - if ((! grub_strncmp ((char *)lh->id, GRUB_LVM_LABEL_ID, - sizeof (lh->id))) - && (! grub_strncmp ((char *)lh->type, GRUB_LVM_LVM2_LABEL, - sizeof (lh->type)))) - break; - } - - /* Return if we didn't find a label. */ - if (i == GRUB_LVM_LABEL_SCAN_SECTORS) - { -#ifdef GRUB_UTIL - grub_util_info ("no LVM signature found"); -#endif - goto fail; - } - - pvh = (struct grub_lvm_pv_header *) (buf + grub_le_to_cpu32(lh->offset_xl)); - - for (i = 0, j = 0; i < GRUB_LVM_ID_LEN; i++) - { - pv_id[j++] = pvh->pv_uuid[i]; - if ((i != 1) && (i != 29) && (i % 4 == 1)) - pv_id[j++] = '-'; - } - pv_id[j] = '\0'; - - dlocn = pvh->disk_areas_xl; - - dlocn++; - /* Is it possible to have multiple data/metadata areas? I haven't - seen devices that have it. */ - if (dlocn->offset) - { - grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "we don't support multiple LVM data areas"); - -#ifdef GRUB_UTIL - grub_util_info ("we don't support multiple LVM data areas\n"); -#endif - goto fail; - } - - dlocn++; - mda_offset = grub_le_to_cpu64 (dlocn->offset); - mda_size = grub_le_to_cpu64 (dlocn->size); - - /* It's possible to have multiple copies of metadata areas, we just use the - first one. */ - - /* Allocate buffer space for the circular worst-case scenario. */ - metadatabuf = grub_malloc (2 * mda_size); - if (! metadatabuf) - goto fail; - - err = grub_disk_read (disk, 0, mda_offset, mda_size, metadatabuf); - if (err) - goto fail2; - - mdah = (struct grub_lvm_mda_header *) metadatabuf; - if ((grub_strncmp ((char *)mdah->magic, GRUB_LVM_FMTT_MAGIC, - sizeof (mdah->magic))) - || (grub_le_to_cpu32 (mdah->version) != GRUB_LVM_FMTT_VERSION)) - { - grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "unknown LVM metadata header"); -#ifdef GRUB_UTIL - grub_util_info ("unknown LVM metadata header\n"); -#endif - goto fail2; - } - - rlocn = mdah->raw_locns; - if (grub_le_to_cpu64 (rlocn->offset) + grub_le_to_cpu64 (rlocn->size) > - grub_le_to_cpu64 (mdah->size)) - { - /* Metadata is circular. Copy the wrap in place. */ - grub_memcpy (metadatabuf + mda_size, - metadatabuf + GRUB_LVM_MDA_HEADER_SIZE, - grub_le_to_cpu64 (rlocn->offset) + - grub_le_to_cpu64 (rlocn->size) - - grub_le_to_cpu64 (mdah->size)); - } - p = q = metadatabuf + grub_le_to_cpu64 (rlocn->offset); - - while (*q != ' ' && q < metadatabuf + mda_size) - q++; - - if (q == metadatabuf + mda_size) - { -#ifdef GRUB_UTIL - grub_util_info ("error parsing metadata\n"); -#endif - goto fail2; - } - - vgname_len = q - p; - vgname = grub_malloc (vgname_len + 1); - if (!vgname) - goto fail2; - - grub_memcpy (vgname, p, vgname_len); - vgname[vgname_len] = '\0'; - - p = grub_strstr (q, "id = \""); - if (p == NULL) - { -#ifdef GRUB_UTIL - grub_util_info ("couldn't find ID\n"); -#endif - goto fail3; - } - p += sizeof ("id = \"") - 1; - grub_memcpy (vg_id, p, GRUB_LVM_ID_STRLEN); - vg_id[GRUB_LVM_ID_STRLEN] = '\0'; - - for (vg = vg_list; vg; vg = vg->next) - { - if (! grub_memcmp(vg_id, vg->id, GRUB_LVM_ID_STRLEN)) - break; - } - - if (! vg) - { - /* First time we see this volume group. We've to create the - whole volume group structure. */ - vg = grub_malloc (sizeof (*vg)); - if (! vg) - goto fail3; - vg->name = vgname; - grub_memcpy (vg->id, vg_id, GRUB_LVM_ID_STRLEN+1); - - vg->extent_size = grub_lvm_getvalue (&p, "extent_size = "); - if (p == NULL) - { -#ifdef GRUB_UTIL - grub_util_info ("unknown extent size\n"); -#endif - goto fail4; - } - - vg->lvs = NULL; - vg->pvs = NULL; - - p = grub_strstr (p, "physical_volumes {"); - if (p) - { - p += sizeof ("physical_volumes {") - 1; - - /* Add all the pvs to the volume group. */ - while (1) - { - int s; - while (grub_isspace (*p)) - p++; - - if (*p == '}') - break; - - pv = grub_malloc (sizeof (*pv)); - q = p; - while (*q != ' ') - q++; - - s = q - p; - pv->name = grub_malloc (s + 1); - grub_memcpy (pv->name, p, s); - pv->name[s] = '\0'; - - p = grub_strstr (p, "id = \""); - if (p == NULL) - goto pvs_fail; - p += sizeof("id = \"") - 1; - - grub_memcpy (pv->id, p, GRUB_LVM_ID_STRLEN); - pv->id[GRUB_LVM_ID_STRLEN] = '\0'; - - pv->start = grub_lvm_getvalue (&p, "pe_start = "); - if (p == NULL) - { -#ifdef GRUB_UTIL - grub_util_info ("unknown pe_start\n"); -#endif - goto pvs_fail; - } - - p = grub_strchr (p, '}'); - if (p == NULL) - { -#ifdef GRUB_UTIL - grub_util_info ("error parsing pe_start\n"); -#endif - goto pvs_fail; - } - p++; - - pv->disk = NULL; - pv->next = vg->pvs; - vg->pvs = pv; - - continue; - pvs_fail: - grub_free (pv->name); - grub_free (pv); - goto fail4; - } - } - - p = grub_strstr (p, "logical_volumes"); - if (p) - { - p += 18; - - /* And add all the lvs to the volume group. */ - while (1) - { - int s; - int skip_lv = 0; - struct grub_lvm_lv *lv; - struct grub_lvm_segment *seg; - int is_pvmove; - - while (grub_isspace (*p)) - p++; - - if (*p == '}') - break; - - lv = grub_malloc (sizeof (*lv)); - - q = p; - while (*q != ' ') - q++; - - s = q - p; - lv->name = grub_strndup (p, s); - if (!lv->name) - goto lvs_fail; - lv->compatname = grub_malloc (vgname_len + 1 + s + 1); - if (!lv->compatname) - goto lvs_fail; - grub_memcpy (lv->compatname, vgname, vgname_len); - lv->compatname[vgname_len] = '-'; - grub_memcpy (lv->compatname + vgname_len + 1, p, s); - lv->compatname[vgname_len + 1 + s] = '\0'; - - { - const char *iptr; - char *optr; - lv->fullname = grub_malloc (sizeof("lvm/") + 2 * vgname_len - + 1 + 2 * s + 1); - if (!lv->fullname) - goto lvs_fail; - - optr = lv->fullname; - grub_memcpy (optr, "lvm/", sizeof ("lvm/") - 1); - optr += sizeof ("lvm/") - 1; - for (iptr = vgname; iptr < vgname + vgname_len; iptr++) - { - *optr++ = *iptr; - if (*iptr == '-') - *optr++ = '-'; - } - *optr++ = '-'; - for (iptr = p; iptr < p + s; iptr++) - { - *optr++ = *iptr; - if (*iptr == '-') - *optr++ = '-'; - } - *optr++ = 0; - } - - lv->size = 0; - - lv->visible = grub_lvm_check_flag (p, "status", "VISIBLE"); - is_pvmove = grub_lvm_check_flag (p, "status", "PVMOVE"); - - lv->segment_count = grub_lvm_getvalue (&p, "segment_count = "); - if (p == NULL) - { -#ifdef GRUB_UTIL - grub_util_info ("unknown segment_count\n"); -#endif - goto lvs_fail; - } - lv->segments = grub_malloc (sizeof (*seg) * lv->segment_count); - seg = lv->segments; - - for (i = 0; i < lv->segment_count; i++) - { - - p = grub_strstr (p, "segment"); - if (p == NULL) - { -#ifdef GRUB_UTIL - grub_util_info ("unknown segment\n"); -#endif - goto lvs_segment_fail; - } - - seg->start_extent = grub_lvm_getvalue (&p, "start_extent = "); - if (p == NULL) - { -#ifdef GRUB_UTIL - grub_util_info ("unknown start_extent\n"); -#endif - goto lvs_segment_fail; - } - seg->extent_count = grub_lvm_getvalue (&p, "extent_count = "); - if (p == NULL) - { -#ifdef GRUB_UTIL - grub_util_info ("unknown extent_count\n"); -#endif - goto lvs_segment_fail; - } - - p = grub_strstr (p, "type = \""); - if (p == NULL) - goto lvs_segment_fail; - p += sizeof("type = \"") - 1; - - lv->size += seg->extent_count * vg->extent_size; - - if (grub_memcmp (p, "striped\"", - sizeof ("striped\"") - 1) == 0) - { - struct grub_lvm_node *stripe; - - seg->type = GRUB_LVM_STRIPED; - seg->node_count = grub_lvm_getvalue (&p, "stripe_count = "); - if (p == NULL) - { -#ifdef GRUB_UTIL - grub_util_info ("unknown stripe_count\n"); -#endif - goto lvs_segment_fail; - } - - if (seg->node_count != 1) - seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = "); - - seg->nodes = grub_zalloc (sizeof (*stripe) - * seg->node_count); - stripe = seg->nodes; - - p = grub_strstr (p, "stripes = ["); - if (p == NULL) - { -#ifdef GRUB_UTIL - grub_util_info ("unknown stripes\n"); -#endif - goto lvs_segment_fail2; - } - p += sizeof("stripes = [") - 1; - - for (j = 0; j < seg->node_count; j++) - { - p = grub_strchr (p, '"'); - if (p == NULL) - continue; - q = ++p; - while (*q != '"') - q++; - - s = q - p; - - stripe->name = grub_malloc (s + 1); - if (stripe->name == NULL) - goto lvs_segment_fail2; - - grub_memcpy (stripe->name, p, s); - stripe->name[s] = '\0'; - - stripe->start = grub_lvm_getvalue (&p, ","); - if (p == NULL) - continue; - - stripe++; - } - } - else if (grub_memcmp (p, "mirror\"", sizeof ("mirror\"") - 1) - == 0) - { - seg->type = GRUB_LVM_MIRROR; - seg->node_count = grub_lvm_getvalue (&p, "mirror_count = "); - if (p == NULL) - { -#ifdef GRUB_UTIL - grub_util_info ("unknown mirror_count\n"); -#endif - goto lvs_segment_fail; - } - - seg->nodes = grub_zalloc (sizeof (seg->nodes[0]) - * seg->node_count); - - p = grub_strstr (p, "mirrors = ["); - if (p == NULL) - { -#ifdef GRUB_UTIL - grub_util_info ("unknown mirrors\n"); -#endif - goto lvs_segment_fail2; - } - p += sizeof("mirrors = [") - 1; - - for (j = 0; j < seg->node_count; j++) - { - char *lvname; - - p = grub_strchr (p, '"'); - if (p == NULL) - continue; - q = ++p; - while (*q != '"') - q++; - - s = q - p; - - lvname = grub_malloc (s + 1); - if (lvname == NULL) - goto lvs_segment_fail2; - - grub_memcpy (lvname, p, s); - lvname[s] = '\0'; - seg->nodes[j].name = lvname; - p = q + 1; - } - /* Only first (original) is ok with in progress pvmove. */ - if (is_pvmove) - seg->node_count = 1; - } - else - { -#ifdef GRUB_UTIL - char *p2; - p2 = grub_strchr (p, '"'); - if (p2) - *p2 = 0; - grub_util_info ("unknown LVM type %s\n", p); - if (p2) - *p2 ='"'; -#endif - /* Found a non-supported type, give up and move on. */ - skip_lv = 1; - break; - } - - seg++; - - continue; - lvs_segment_fail2: - grub_free (seg->nodes); - lvs_segment_fail: - goto fail4; - } - - if (p != NULL) - p = grub_strchr (p, '}'); - if (p == NULL) - goto lvs_fail; - p += 3; - - if (skip_lv) - { - grub_free (lv->name); - grub_free (lv); - continue; - } - - lv->number = lv_count++; - lv->vg = vg; - lv->next = vg->lvs; - vg->lvs = lv; - - continue; - lvs_fail: - grub_free (lv->name); - grub_free (lv); - goto fail4; - } - } - - /* Match lvs. */ - { - struct grub_lvm_lv *lv1; - struct grub_lvm_lv *lv2; - for (lv1 = vg->lvs; lv1; lv1 = lv1->next) - for (i = 0; i < lv1->segment_count; i++) - for (j = 0; j < lv1->segments[i].node_count; j++) - { - if (vg->pvs) - for (pv = vg->pvs; pv; pv = pv->next) - { - if (! grub_strcmp (pv->name, - lv1->segments[i].nodes[j].name)) - { - lv1->segments[i].nodes[j].pv = pv; - break; - } - } - if (lv1->segments[i].nodes[j].pv == NULL) - for (lv2 = vg->lvs; lv2; lv2 = lv2->next) - if (grub_strcmp (lv2->name + grub_strlen (vg->name) + 1, - lv1->segments[i].nodes[j].name) == 0) - lv1->segments[i].nodes[j].lv = lv2; - } - - } - - vg->next = vg_list; - vg_list = vg; - } - else - { - grub_free (vgname); - } - - /* Match the device we are currently reading from with the right - PV. */ - if (vg->pvs) - for (pv = vg->pvs; pv; pv = pv->next) - { - if (! grub_memcmp (pv->id, pv_id, GRUB_LVM_ID_STRLEN)) - { - /* This could happen to LVM on RAID, pv->disk points to the - raid device, we shouldn't change it. */ - if (! pv->disk) - pv->disk = grub_disk_open (name); - break; - } - } - - goto fail2; - - /* Failure path. */ - fail4: - grub_free (vg); - fail3: - grub_free (vgname); - - /* Normal exit path. */ - fail2: - grub_free (metadatabuf); - fail: - grub_disk_close (disk); - if (grub_errno == GRUB_ERR_OUT_OF_RANGE) - grub_errno = GRUB_ERR_NONE; - grub_print_error (); - if (scan_for && find_lv (scan_for)) - return 1; - return 0; - } - - scan_depth++; - grub_device_iterate (&grub_lvm_scan_device); - scan_depth--; -} - -static int -grub_lvm_iterate (int (*hook) (const char *name), - grub_disk_pull_t pull) -{ - struct grub_lvm_vg *vg; - unsigned old_count = 0; - if (pull == GRUB_DISK_PULL_RESCAN && scan_depth) - return 0; - - if (pull == GRUB_DISK_PULL_RESCAN) - { - old_count = lv_count; - if (!scan_depth) - do_lvm_scan (NULL); - } - if (pull != GRUB_DISK_PULL_RESCAN && pull != GRUB_DISK_PULL_NONE) - return GRUB_ERR_NONE; - for (vg = vg_list; vg; vg = vg->next) - { - struct grub_lvm_lv *lv; - if (vg->lvs) - for (lv = vg->lvs; lv; lv = lv->next) - if (lv->visible && lv->number >= old_count) - { - if (hook (lv->fullname)) - return 1; - } - } - - return 0; -} - -#ifdef GRUB_UTIL -static grub_disk_memberlist_t -grub_lvm_memberlist (grub_disk_t disk) -{ - struct grub_lvm_lv *lv = disk->data; - grub_disk_memberlist_t list = NULL, tmp; - struct grub_lvm_pv *pv; - - if (lv->vg->pvs) - for (pv = lv->vg->pvs; pv; pv = pv->next) - { - if (!pv->disk) - grub_util_error (_("Couldn't find PV %s. Check your device.map"), - pv->name); - tmp = grub_malloc (sizeof (*tmp)); - tmp->disk = pv->disk; - tmp->next = list; - list = tmp; - } - - return list; -} -#endif - -static grub_err_t -grub_lvm_open (const char *name, grub_disk_t disk) -{ - struct grub_lvm_lv *lv = NULL; - int explicit = 0; - - if (grub_memcmp (name, "lvm/", sizeof ("lvm/") - 1) == 0) - explicit = 1; - - lv = find_lv (name); - - if (! lv && !scan_depth && explicit) - { - do_lvm_scan (name); - if (grub_errno) - { - grub_print_error (); - grub_errno = GRUB_ERR_NONE; - } - lv = find_lv (name); - } - - if (! lv) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown LVM device %s", name); - - disk->id = lv->number; - disk->data = lv; - disk->total_sectors = lv->size; - - return 0; -} - -static void -grub_lvm_close (grub_disk_t disk __attribute ((unused))) -{ - return; -} - -static grub_err_t -read_lv (struct grub_lvm_lv *lv, grub_disk_addr_t sector, - grub_size_t size, char *buf); - -static grub_err_t -read_node (const struct grub_lvm_node *node, grub_disk_addr_t sector, - grub_size_t size, char *buf) -{ - /* Check whether we actually know the physical volume we want to - read from. */ - if (node->pv) - { - if (node->pv->disk) - return grub_disk_read (node->pv->disk, sector + node->pv->start, 0, - size << GRUB_DISK_SECTOR_BITS, buf); - else - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, - "physical volume %s not found", node->pv->name); - - } - if (node->lv) - return read_lv (node->lv, sector, size, buf); - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown node '%s'", node->name); -} - -static grub_err_t -read_lv (struct grub_lvm_lv *lv, grub_disk_addr_t sector, - grub_size_t size, char *buf) -{ - grub_err_t err = 0; - struct grub_lvm_vg *vg = lv->vg; - struct grub_lvm_segment *seg = lv->segments; - struct grub_lvm_node *node; - grub_uint64_t offset; - grub_uint64_t extent; - unsigned int i; - - if (!lv) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown volume"); - - extent = grub_divmod64 (sector, vg->extent_size, NULL); - - /* Find the right segment. */ - for (i = 0; i < lv->segment_count; i++) - { - if ((seg->start_extent <= extent) - && ((seg->start_extent + seg->extent_count) > extent)) - { - break; - } - - seg++; - } - - if (i == lv->segment_count) - return grub_error (GRUB_ERR_READ_ERROR, "incorrect segment"); - - switch (seg->type) - { - case GRUB_LVM_STRIPED: - if (seg->node_count == 1) - { - /* This segment is linear, so that's easy. We just need to find - out the offset in the physical volume and read SIZE bytes - from that. */ - struct grub_lvm_node *stripe = seg->nodes; - grub_uint64_t seg_offset; /* Offset of the segment in PV device. */ - - node = stripe; - seg_offset = ((grub_uint64_t) stripe->start - * (grub_uint64_t) vg->extent_size); - - offset = sector - ((grub_uint64_t) seg->start_extent - * (grub_uint64_t) vg->extent_size) + seg_offset; - } - else - { - /* This is a striped segment. We have to find the right PV - similar to RAID0. */ - struct grub_lvm_node *stripe = seg->nodes; - grub_uint64_t a, b; - grub_uint64_t seg_offset; /* Offset of the segment in PV device. */ - grub_uint64_t stripenr; - - offset = sector - ((grub_uint64_t) seg->start_extent - * (grub_uint64_t) vg->extent_size); - - a = grub_divmod64 (offset, seg->stripe_size, NULL); - grub_divmod64 (a, seg->node_count, &stripenr); - - a = grub_divmod64 (offset, seg->stripe_size * seg->node_count, NULL); - grub_divmod64 (offset, seg->stripe_size, &b); - offset = a * seg->stripe_size + b; - - stripe += stripenr; - node = stripe; - - seg_offset = ((grub_uint64_t) stripe->start - * (grub_uint64_t) vg->extent_size); - - offset += seg_offset; - } - return read_node (node, offset, size, buf); - case GRUB_LVM_MIRROR: - i = 0; - while (1) - { - err = read_node (&seg->nodes[i], sector, size, buf); - if (!err) - return err; - if (++i >= seg->node_count) - return err; - grub_errno = GRUB_ERR_NONE; - } - } - return grub_error (GRUB_ERR_IO, "unknown LVM segment"); -} - -static grub_err_t -is_node_readable (const struct grub_lvm_node *node) -{ - /* Check whether we actually know the physical volume we want to - read from. */ - if (node->pv) - return !!(node->pv->disk); - if (node->lv) - return is_lv_readable (node->lv); - return 0; -} - -static int -is_lv_readable (struct grub_lvm_lv *lv) -{ - unsigned int i, j; - - if (!lv) - return 0; - - /* Find the right segment. */ - for (i = 0; i < lv->segment_count; i++) - switch (lv->segments[i].type) - { - case GRUB_LVM_STRIPED: - for (j = 0; j < lv->segments[i].node_count; j++) - if (!is_node_readable (lv->segments[i].nodes + j)) - return 0; - break; - case GRUB_LVM_MIRROR: - for (j = 0; j < lv->segments[i].node_count; j++) - if (is_node_readable (lv->segments[i].nodes + j)) - break; - if (j == lv->segments[i].node_count) - return 0; - default: - return 0; - } - - return 1; -} - - -static grub_err_t -grub_lvm_read (grub_disk_t disk, grub_disk_addr_t sector, - grub_size_t size, char *buf) -{ - return read_lv (disk->data, sector, size, buf); -} - -static grub_err_t -grub_lvm_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_NOT_IMPLEMENTED_YET; -} - -static struct grub_disk_dev grub_lvm_dev = - { - .name = "lvm", - .id = GRUB_DISK_DEVICE_LVM_ID, - .iterate = grub_lvm_iterate, - .open = grub_lvm_open, - .close = grub_lvm_close, - .read = grub_lvm_read, - .write = grub_lvm_write, -#ifdef GRUB_UTIL - .memberlist = grub_lvm_memberlist, -#endif - .next = 0 - }; - -GRUB_MOD_INIT(lvm) + +static struct grub_diskfilter grub_lvm_dev = { + .name = "lvm", + .detect = grub_lvm_detect, + .next = 0 +}; + +GRUB_MOD_INIT (lvm) { - grub_disk_dev_register (&grub_lvm_dev); + grub_diskfilter_register (&grub_lvm_dev); } -GRUB_MOD_FINI(lvm) +GRUB_MOD_FINI (lvm) { - grub_disk_dev_unregister (&grub_lvm_dev); - vg_list = NULL; - /* FIXME: free the lvm list. */ + grub_diskfilter_unregister (&grub_lvm_dev); } diff --git a/grub-core/disk/mdraid1x_linux.c b/grub-core/disk/mdraid1x_linux.c index 19c43f455..fa4b97b77 100644 --- a/grub-core/disk/mdraid1x_linux.c +++ b/grub-core/disk/mdraid1x_linux.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -103,8 +103,9 @@ struct grub_raid_super_1x #define WriteMostly1 1 /* Mask for writemostly flag in above devflags. */ -static grub_err_t -grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array, +static struct grub_diskfilter_vg * +grub_mdraid_detect (grub_disk_t disk, + struct grub_diskfilter_pv_id *id, grub_disk_addr_t *start_sector) { grub_disk_addr_t sector = 0; @@ -142,7 +143,7 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array, if (grub_disk_read (disk, sector, 0, sizeof (struct grub_raid_super_1x), &sb)) - return grub_errno; + return NULL; if (grub_le_to_cpu32 (sb.magic) != SB_MAGIC || grub_le_to_cpu64 (sb.super_offset) != sector) @@ -154,9 +155,12 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array, grub_uint32_t level; if (grub_le_to_cpu32 (sb.major_version) != 1) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "Unsupported RAID version: %d", - grub_le_to_cpu32 (sb.major_version)); + { + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "Unsupported RAID version: %d", + grub_le_to_cpu32 (sb.major_version)); + return NULL; + } level = grub_le_to_cpu32 (sb.level); @@ -166,8 +170,11 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array, if (level != 0 && level != 1 && level != 4 && level != 5 && level != 6 && level != 10) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "Unsupported RAID level: %d", sb.level); + { + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "Unsupported RAID level: %d", sb.level); + return NULL; + } /* 1.x superblocks don't have a fixed size on disk. So we have to read it again now that we now the max device count. */ @@ -175,62 +182,68 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array, + 2 * grub_le_to_cpu32 (sb.max_dev); real_sb = grub_malloc (sb_size); if (! real_sb) - return grub_errno; + return NULL; if (grub_disk_read (disk, sector, 0, sb_size, real_sb)) { grub_free (real_sb); - return grub_errno; + return NULL; } - array->name = grub_strdup (real_sb->set_name); - if (! array->name) - { - grub_free (real_sb); - return grub_errno; - } - - array->number = 0; - array->level = grub_le_to_cpu32 (real_sb->level); - array->layout = grub_le_to_cpu32 (real_sb->layout); - array->total_devs = grub_le_to_cpu32 (real_sb->raid_disks); - if (real_sb->size) - array->disk_size = grub_le_to_cpu64 (real_sb->size); - else - array->disk_size = grub_le_to_cpu64 (real_sb->data_size); - array->chunk_size = grub_le_to_cpu32 (real_sb->chunksize); + struct grub_diskfilter_vg *array; + char *uuid; if (grub_le_to_cpu32 (real_sb->dev_number) >= grub_le_to_cpu32 (real_sb->max_dev)) - return grub_error (GRUB_ERR_OUT_OF_RANGE, - "spares aren't implemented"); - - array->index = grub_le_to_cpu16 - (real_sb->dev_roles[grub_le_to_cpu32 (real_sb->dev_number)]); - if (array->index >= array->total_devs) - return grub_error (GRUB_ERR_OUT_OF_RANGE, - "spares aren't implemented"); - array->uuid_len = 16; - array->uuid = grub_malloc (16); - if (!array->uuid) { - grub_free (real_sb); - return grub_errno; + grub_error (GRUB_ERR_OUT_OF_RANGE, + "spares aren't implemented"); + return NULL; } - grub_memcpy (array->uuid, real_sb->set_uuid, 16); - + id->uuidlen = 0; + id->id = grub_le_to_cpu16 + (real_sb->dev_roles[grub_le_to_cpu32 (real_sb->dev_number)]); + + uuid = grub_malloc (16); + if (!uuid) + { + grub_free (real_sb); + return NULL; + } + + grub_memcpy (uuid, real_sb->set_uuid, 16); + *start_sector = grub_le_to_cpu64 (real_sb->data_offset); + if (grub_le_to_cpu32 (real_sb->dev_number) + >= grub_le_to_cpu32 (real_sb->raid_disks)) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, + "spares aren't implemented"); + return NULL; + } + + array = grub_diskfilter_make_raid (16, uuid, + grub_le_to_cpu32 (real_sb->raid_disks), + real_sb->set_name, + (real_sb->size) + ? grub_le_to_cpu64 (real_sb->size) + : grub_le_to_cpu64 (real_sb->data_size), + grub_le_to_cpu32 (real_sb->chunksize), + grub_le_to_cpu32 (real_sb->layout), + grub_le_to_cpu32 (real_sb->level)); + grub_free (real_sb); - return 0; + return array; } } - return grub_error (GRUB_ERR_OUT_OF_RANGE, "not 1.x raid"); + grub_error (GRUB_ERR_OUT_OF_RANGE, "not 1.x raid"); + return NULL; } -static struct grub_raid grub_mdraid_dev = { +static struct grub_diskfilter grub_mdraid_dev = { .name = "mdraid1x", .detect = grub_mdraid_detect, .next = 0 @@ -238,10 +251,10 @@ static struct grub_raid grub_mdraid_dev = { GRUB_MOD_INIT (mdraid1x) { - grub_raid_register (&grub_mdraid_dev); + grub_diskfilter_register (&grub_mdraid_dev); } GRUB_MOD_FINI (mdraid1x) { - grub_raid_unregister (&grub_mdraid_dev); + grub_diskfilter_unregister (&grub_mdraid_dev); } diff --git a/grub-core/disk/mdraid_linux.c b/grub-core/disk/mdraid_linux.c index 0e2d85009..1ca76fdfa 100644 --- a/grub-core/disk/mdraid_linux.c +++ b/grub-core/disk/mdraid_linux.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include /* Linux RAID on disk structures and constants, copied from include/linux/raid/md_p.h. */ @@ -161,8 +161,9 @@ struct grub_raid_super_09 struct grub_raid_disk_09 this_disk; } __attribute__ ((packed)); -static grub_err_t -grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array, +static struct grub_diskfilter_vg * +grub_mdraid_detect (grub_disk_t disk, + struct grub_diskfilter_pv_id *id, grub_disk_addr_t *start_sector) { grub_disk_addr_t sector; @@ -174,22 +175,31 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array, /* The sector where the mdraid 0.90 superblock is stored, if available. */ size = grub_disk_get_size (disk); if (size == GRUB_DISK_SIZE_UNKNOWN) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "not 0.9x raid"); + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "not 0.9x raid"); + return NULL; + } sector = NEW_SIZE_SECTORS (size); if (grub_disk_read (disk, sector, 0, SB_BYTES, &sb)) - return grub_errno; + return NULL; /* Look whether there is a mdraid 0.90 superblock. */ if (grub_le_to_cpu32 (sb.md_magic) != SB_MAGIC) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "not 0.9x raid"); + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "not 0.9x raid"); + return NULL; + } if (grub_le_to_cpu32 (sb.major_version) != 0 || grub_le_to_cpu32 (sb.minor_version) != 90) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "unsupported RAID version: %d.%d", - grub_le_to_cpu32 (sb.major_version), - grub_le_to_cpu32 (sb.minor_version)); + { + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "unsupported RAID version: %d.%d", + grub_le_to_cpu32 (sb.major_version), + grub_le_to_cpu32 (sb.minor_version)); + return NULL; + } /* FIXME: Check the checksum. */ @@ -200,27 +210,23 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array, if (level != 0 && level != 1 && level != 4 && level != 5 && level != 6 && level != 10) - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "unsupported RAID level: %d", level); + { + grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "unsupported RAID level: %d", level); + return NULL; + } if (grub_le_to_cpu32 (sb.this_disk.number) == 0xffff || grub_le_to_cpu32 (sb.this_disk.number) == 0xfffe) - return grub_error (GRUB_ERR_OUT_OF_RANGE, - "spares aren't implemented"); + { + grub_error (GRUB_ERR_OUT_OF_RANGE, + "spares aren't implemented"); + return NULL; + } - array->name = NULL; - array->number = grub_le_to_cpu32 (sb.md_minor); - array->level = level; - array->layout = grub_le_to_cpu32 (sb.layout); - array->total_devs = grub_le_to_cpu32 (sb.raid_disks); - array->disk_size = (sb.size) ? grub_le_to_cpu32 (sb.size) * 2 : sector; - array->chunk_size = grub_le_to_cpu32 (sb.chunk_size) >> 9; - array->index = grub_le_to_cpu32 (sb.this_disk.number); - array->uuid_len = 16; - array->uuid = grub_malloc (16); - if (!array->uuid) - return grub_errno; + uuid = grub_malloc (16); + if (!uuid) + return NULL; - uuid = (grub_uint32_t *) array->uuid; uuid[0] = grub_swap_bytes32 (sb.set_uuid0); uuid[1] = grub_swap_bytes32 (sb.set_uuid1); uuid[2] = grub_swap_bytes32 (sb.set_uuid2); @@ -228,10 +234,21 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array, *start_sector = 0; - return 0; + id->uuidlen = 0; + id->id = grub_le_to_cpu32 (sb.this_disk.number); + + char buf[32]; + grub_snprintf (buf, sizeof (buf), "md%d", grub_le_to_cpu32 (sb.md_minor)); + return grub_diskfilter_make_raid (16, (char *) uuid, + grub_le_to_cpu32 (sb.raid_disks), buf, + (sb.size) ? grub_le_to_cpu32 (sb.size) * 2 + : sector, + grub_le_to_cpu32 (sb.chunk_size) >> 9, + grub_le_to_cpu32 (sb.layout), + level); } -static struct grub_raid grub_mdraid_dev = { +static struct grub_diskfilter grub_mdraid_dev = { .name = "mdraid09", .detect = grub_mdraid_detect, .next = 0 @@ -239,10 +256,10 @@ static struct grub_raid grub_mdraid_dev = { GRUB_MOD_INIT (mdraid09) { - grub_raid_register (&grub_mdraid_dev); + grub_diskfilter_register (&grub_mdraid_dev); } GRUB_MOD_FINI (mdraid09) { - grub_raid_unregister (&grub_mdraid_dev); + grub_diskfilter_unregister (&grub_mdraid_dev); } diff --git a/grub-core/disk/pata.c b/grub-core/disk/pata.c index c54fe91ab..089059d10 100644 --- a/grub-core/disk/pata.c +++ b/grub-core/disk/pata.c @@ -116,12 +116,13 @@ grub_pata_wait (void) static void grub_pata_pio_read (struct grub_pata_device *dev, char *buf, grub_size_t size) { - grub_uint16_t *buf16 = (grub_uint16_t *) buf; unsigned int i; /* Read in the data, word by word. */ for (i = 0; i < size / 2; i++) - buf16[i] = grub_le_to_cpu16 (grub_inw(dev->ioaddress + GRUB_ATA_REG_DATA)); + grub_set_unaligned16 (buf + 2 * i, + grub_le_to_cpu16 (grub_inw(dev->ioaddress + + GRUB_ATA_REG_DATA))); if (size & 1) buf[size - 1] = (char) grub_le_to_cpu16 (grub_inw (dev->ioaddress + GRUB_ATA_REG_DATA)); @@ -130,12 +131,11 @@ grub_pata_pio_read (struct grub_pata_device *dev, char *buf, grub_size_t size) static void grub_pata_pio_write (struct grub_pata_device *dev, char *buf, grub_size_t size) { - grub_uint16_t *buf16 = (grub_uint16_t *) buf; unsigned int i; /* Write the data, word by word. */ for (i = 0; i < size / 2; i++) - grub_outw(grub_cpu_to_le16 (buf16[i]), dev->ioaddress + GRUB_ATA_REG_DATA); + grub_outw(grub_cpu_to_le16 (grub_get_unaligned16 (buf + 2 * i)), dev->ioaddress + GRUB_ATA_REG_DATA); } /* ATA pass through support, used by hdparm.mod. */ @@ -484,6 +484,7 @@ grub_pata_open (int id, int devnum, struct grub_ata *ata) ata->data = devfnd; ata->dma = 0; + ata->maxbuffer = 256 * 512; ata->present = &devfnd->present; return GRUB_ERR_NONE; diff --git a/grub-core/disk/raid.c b/grub-core/disk/raid.c deleted file mode 100644 index e4c53e73b..000000000 --- a/grub-core/disk/raid.c +++ /dev/null @@ -1,939 +0,0 @@ -/* raid.c - module to read RAID arrays. */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GRUB. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#ifdef GRUB_UTIL -#include -#endif - -GRUB_MOD_LICENSE ("GPLv3+"); - -/* Linked list of RAID arrays. */ -static struct grub_raid_array *array_list; -grub_raid5_recover_func_t grub_raid5_recover_func; -grub_raid6_recover_func_t grub_raid6_recover_func; -static grub_raid_t grub_raid_list; -static int inscnt = 0; - -static struct grub_raid_array * -find_array (const char *name); - - -static char -grub_is_array_readable (struct grub_raid_array *array) -{ - switch (array->level) - { - case 0: - if (array->nr_devs == array->total_devs) - return 1; - break; - - case 1: - if (array->nr_devs >= 1) - return 1; - break; - - case 4: - case 5: - case 6: - case 10: - { - unsigned int n; - - if (array->level == 10) - { - n = array->layout & 0xFF; - if (n == 1) - n = (array->layout >> 8) & 0xFF; - - n--; - } - else - n = array->level / 3; - - if (array->nr_devs >= array->total_devs - n) - return 1; - - break; - } - } - - return 0; -} - -static grub_err_t -insert_array (grub_disk_t disk, struct grub_raid_array *new_array, - grub_disk_addr_t start_sector, const char *scanner_name, - grub_raid_t raid __attribute__ ((unused))); - -static int scan_depth = 0; - -static void -scan_devices (const char *arname) -{ - grub_raid_t raid; - - auto int hook (const char *name); - int hook (const char *name) - { - grub_disk_t disk; - struct grub_raid_array array; - struct grub_raid_array *arr; - grub_disk_addr_t start_sector; - - grub_dprintf ("raid", "Scanning for %s RAID devices on disk %s\n", - raid->name, name); -#ifdef GRUB_UTIL - grub_util_info ("Scanning for %s RAID devices on disk %s", - raid->name, name); -#endif - - disk = grub_disk_open (name); - if (!disk) - return 0; - - for (arr = array_list; arr != NULL; arr = arr->next) - { - struct grub_raid_member *m; - for (m = arr->members; m < arr->members + arr->nr_devs; m++) - if (m->device && m->device->id == disk->id - && m->device->dev->id == m->device->dev->id - && grub_partition_get_start (m->device->partition) - == grub_partition_get_start (disk->partition) - && grub_disk_get_size (m->device) - == grub_disk_get_size (disk)) - { - grub_disk_close (disk); - return 0; - } - } - - if ((disk->total_sectors != GRUB_ULONG_MAX) && - (! raid->detect (disk, &array, &start_sector)) && - (! insert_array (disk, &array, start_sector, raid->name, - raid))) - return 0; - - /* This error usually means it's not raid, no need to display - it. */ - if (grub_errno != GRUB_ERR_OUT_OF_RANGE) - grub_print_error (); - - grub_errno = GRUB_ERR_NONE; - - grub_disk_close (disk); - - if (arname && find_array (arname)) - return 1; - - return 0; - } - - if (scan_depth) - return; - - scan_depth++; - for (raid = grub_raid_list; raid; raid = raid->next) - grub_device_iterate (&hook); - scan_depth--; -} - -static int -grub_raid_iterate (int (*hook) (const char *name), - grub_disk_pull_t pull) -{ - struct grub_raid_array *array; - int islcnt = 0; - - if (pull == GRUB_DISK_PULL_RESCAN) - { - islcnt = inscnt; - scan_devices (NULL); - } - - if (pull != GRUB_DISK_PULL_NONE && pull != GRUB_DISK_PULL_RESCAN) - return 0; - - for (array = array_list; array != NULL; array = array->next) - { - if (grub_is_array_readable (array) && array->became_readable_at >= islcnt) - if (hook (array->name)) - return 1; - } - - return 0; -} - -#ifdef GRUB_UTIL -static grub_disk_memberlist_t -grub_raid_memberlist (grub_disk_t disk) -{ - struct grub_raid_array *array = disk->data; - grub_disk_memberlist_t list = NULL, tmp; - unsigned int i; - - for (i = 0; i < array->total_devs; i++) - if (array->members[i].device) - { - tmp = grub_malloc (sizeof (*tmp)); - tmp->disk = array->members[i].device; - tmp->next = list; - list = tmp; - } - - return list; -} - -static const char * -grub_raid_getname (struct grub_disk *disk) -{ - struct grub_raid_array *array = disk->data; - - return array->driver->name; -} -#endif - -static 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 struct grub_raid_array * -find_array (const char *name) -{ - struct grub_raid_array *array; - - 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 (array = array_list; array != NULL; array = array->next) - { - if (uuid_len == (unsigned) array->uuid_len - && grub_memcmp (uuidbin, array->uuid, uuid_len) == 0) - if (grub_is_array_readable (array)) - return array; - } - } - else - for (array = array_list; array != NULL; array = array->next) - { - if (!grub_strcmp (array->name, name)) - if (grub_is_array_readable (array)) - return array; - } - return NULL; -} - -static grub_err_t -grub_raid_open (const char *name, grub_disk_t disk) -{ - struct grub_raid_array *array; - unsigned n; - - if (grub_memcmp (name, "md", sizeof ("md") - 1) != 0) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown RAID device %s", - name); - - array = find_array (name); - - if (! array) - { - scan_devices (name); - if (grub_errno) - { - grub_print_error (); - grub_errno = GRUB_ERR_NONE; - } - array = find_array (name); - } - - if (!array) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown RAID device %s", - name); - - disk->id = array->number; - disk->data = array; - - grub_dprintf ("raid", "%s: total_devs=%d, disk_size=%lld\n", name, - array->total_devs, (unsigned long long) array->disk_size); - - switch (array->level) - { - case 1: - disk->total_sectors = array->disk_size; - break; - - case 10: - n = array->layout & 0xFF; - if (n == 1) - n = (array->layout >> 8) & 0xFF; - - disk->total_sectors = grub_divmod64 (array->total_devs * - array->disk_size, - n, 0); - break; - - case 0: - case 4: - case 5: - case 6: - n = array->level / 3; - - disk->total_sectors = (array->total_devs - n) * array->disk_size; - break; - } - - grub_dprintf ("raid", "%s: level=%d, total_sectors=%lld\n", name, - array->level, (unsigned long long) disk->total_sectors); - - return 0; -} - -static void -grub_raid_close (grub_disk_t disk __attribute ((unused))) -{ - return; -} - -void -grub_raid_block_xor (char *buf1, const char *buf2, int size) -{ - grub_size_t *p1; - const grub_size_t *p2; - - p1 = (grub_size_t *) buf1; - p2 = (const grub_size_t *) buf2; - size /= GRUB_CPU_SIZEOF_VOID_P; - - while (size) - { - *(p1++) ^= *(p2++); - size--; - } -} - -static grub_err_t -grub_raid_read (grub_disk_t disk, grub_disk_addr_t sector, - grub_size_t size, char *buf) -{ - struct grub_raid_array *array = disk->data; - grub_err_t err = 0; - - switch (array->level) - { - case 0: - case 1: - case 10: - { - grub_disk_addr_t read_sector, far_ofs; - grub_uint64_t disknr, b, near, far, ofs; - - read_sector = grub_divmod64 (sector, array->chunk_size, &b); - far = ofs = near = 1; - far_ofs = 0; - - if (array->level == 1) - near = array->total_devs; - else if (array->level == 10) - { - near = array->layout & 0xFF; - far = (array->layout >> 8) & 0xFF; - if (array->layout >> 16) - { - ofs = far; - far_ofs = 1; - } - else - far_ofs = grub_divmod64 (array->disk_size, - far * array->chunk_size, 0); - - far_ofs *= array->chunk_size; - } - - read_sector = grub_divmod64 (read_sector * near, array->total_devs, - &disknr); - - ofs *= array->chunk_size; - read_sector *= ofs; - - while (1) - { - grub_size_t read_size; - unsigned int i, j; - - read_size = array->chunk_size - b; - if (read_size > size) - read_size = size; - - for (i = 0; i < near; i++) - { - unsigned int k; - - k = disknr; - for (j = 0; j < far; j++) - { - if (array->members[k].device) - { - if (grub_errno == GRUB_ERR_READ_ERROR) - grub_errno = GRUB_ERR_NONE; - - err = grub_disk_read (array->members[k].device, - array->members[k].start_sector + - read_sector + j * far_ofs + b, - 0, - read_size << GRUB_DISK_SECTOR_BITS, - buf); - if (! err) - break; - else if (err != GRUB_ERR_READ_ERROR) - return err; - } - else - err = grub_error (GRUB_ERR_READ_ERROR, - "disk missing"); - - k++; - if (k == array->total_devs) - k = 0; - } - - if (! err) - break; - - disknr++; - if (disknr == array->total_devs) - { - disknr = 0; - read_sector += ofs; - } - } - - if (err) - return err; - - buf += read_size << GRUB_DISK_SECTOR_BITS; - size -= read_size; - if (! size) - break; - - b = 0; - disknr += (near - i); - while (disknr >= array->total_devs) - { - disknr -= array->total_devs; - read_sector += ofs; - } - } - break; - } - - case 4: - case 5: - case 6: - { - grub_disk_addr_t read_sector; - grub_uint64_t b, p, n, disknr, e; - - /* n = 1 for level 4 and 5, 2 for level 6. */ - n = array->level / 3; - - /* Find the first sector to read. */ - read_sector = grub_divmod64 (sector, array->chunk_size, &b); - read_sector = grub_divmod64 (read_sector, array->total_devs - n, - &disknr); - if (array->level >= 5) - { - grub_divmod64 (read_sector, array->total_devs, &p); - - if (! (array->layout & GRUB_RAID_LAYOUT_RIGHT_MASK)) - p = array->total_devs - 1 - p; - - if (array->layout & GRUB_RAID_LAYOUT_SYMMETRIC_MASK) - { - disknr += p + n; - } - else - { - grub_uint32_t q; - - q = p + (n - 1); - if (q >= array->total_devs) - q -= array->total_devs; - - if (disknr >= p) - disknr += n; - else if (disknr >= q) - disknr += q + 1; - } - - if (disknr >= array->total_devs) - disknr -= array->total_devs; - } - else - p = array->total_devs - n; - - read_sector *= array->chunk_size; - - while (1) - { - grub_size_t read_size; - int next_level; - - read_size = array->chunk_size - b; - if (read_size > size) - read_size = size; - - e = 0; - if (array->members[disknr].device) - { - /* Reset read error. */ - if (grub_errno == GRUB_ERR_READ_ERROR) - grub_errno = GRUB_ERR_NONE; - - err = grub_disk_read (array->members[disknr].device, - array->members[disknr].start_sector + - read_sector + b, 0, - read_size << GRUB_DISK_SECTOR_BITS, - buf); - - if ((err) && (err != GRUB_ERR_READ_ERROR)) - break; - e++; - } - else - err = GRUB_ERR_READ_ERROR; - - if (err) - { - if (array->nr_devs < array->total_devs - n + e) - break; - - grub_errno = GRUB_ERR_NONE; - if (array->level == 6) - { - err = ((grub_raid6_recover_func) ? - (*grub_raid6_recover_func) (array, disknr, p, - buf, read_sector + b, - read_size) : - grub_error (GRUB_ERR_BAD_DEVICE, - "raid6rec is not loaded")); - } - else - { - err = ((grub_raid5_recover_func) ? - (*grub_raid5_recover_func) (array, disknr, - buf, read_sector + b, - read_size) : - grub_error (GRUB_ERR_BAD_DEVICE, - "raid5rec is not loaded")); - } - - if (err) - break; - } - - buf += read_size << GRUB_DISK_SECTOR_BITS; - size -= read_size; - if (! size) - break; - - b = 0; - disknr++; - - if (array->layout & GRUB_RAID_LAYOUT_SYMMETRIC_MASK) - { - if (disknr == array->total_devs) - disknr = 0; - - next_level = (disknr == p); - } - else - { - if (disknr == p) - disknr += n; - - next_level = (disknr >= array->total_devs); - } - - if (next_level) - { - read_sector += array->chunk_size; - - if (array->level >= 5) - { - if (array->layout & GRUB_RAID_LAYOUT_RIGHT_MASK) - p = (p == array->total_devs - 1) ? 0 : p + 1; - else - p = (p == 0) ? array->total_devs - 1 : p - 1; - - if (array->layout & GRUB_RAID_LAYOUT_SYMMETRIC_MASK) - { - disknr = p + n; - if (disknr >= array->total_devs) - disknr -= array->total_devs; - } - else - { - disknr -= array->total_devs; - if (disknr == p) - disknr += n; - } - } - else - disknr = 0; - } - } - } - break; - } - - return err; -} - -static grub_err_t -grub_raid_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_NOT_IMPLEMENTED_YET; -} - -static grub_err_t -insert_array (grub_disk_t disk, struct grub_raid_array *new_array, - grub_disk_addr_t start_sector, const char *scanner_name, - grub_raid_t raid __attribute__ ((unused))) -{ - struct grub_raid_array *array = 0, *p; - int was_readable = 0; - - /* See whether the device is part of an array we have already seen a - device from. */ - for (p = array_list; p != NULL; p = p->next) - if ((p->uuid_len == new_array->uuid_len) && - (! grub_memcmp (p->uuid, new_array->uuid, p->uuid_len))) - { - grub_free (new_array->uuid); - array = p; - - was_readable = grub_is_array_readable (array); - - /* Do some checks before adding the device to the array. */ - - if (new_array->index >= array->allocated_devs) - { - void *tmp; - unsigned int newnum = 2 * (new_array->index + 1); - tmp = grub_realloc (array->members, newnum - * sizeof (array->members[0])); - if (!tmp) - return grub_errno; - array->members = tmp; - grub_memset (array->members + array->allocated_devs, - 0, (newnum - array->allocated_devs) - * sizeof (array->members[0])); - array->allocated_devs = newnum; - } - - /* FIXME: Check whether the update time of the superblocks are - the same. */ - - if (array->total_devs == array->nr_devs) - /* We found more members of the array than the array - actually has according to its superblock. This shouldn't - happen normally. */ - return grub_error (GRUB_ERR_BAD_DEVICE, - "superfluous RAID member (%d found)", - array->total_devs); - - if (array->members[new_array->index].device != NULL) - /* We found multiple devices with the same number. Again, - this shouldn't happen. */ - return grub_error (GRUB_ERR_BAD_DEVICE, - "found two disks with the index %d for RAID %s", - new_array->index, array->name); - - if (new_array->disk_size < array->disk_size) - array->disk_size = new_array->disk_size; - break; - } - - /* Add an array to the list if we didn't find any. */ - if (!array) - { - array = grub_malloc (sizeof (*array)); - if (!array) - { - grub_free (new_array->uuid); - return grub_errno; - } - - *array = *new_array; - array->nr_devs = 0; -#ifdef GRUB_UTIL - array->driver = raid; -#endif - array->allocated_devs = 32; - if (new_array->index >= array->allocated_devs) - array->allocated_devs = 2 * (new_array->index + 1); - - array->members = grub_zalloc (array->allocated_devs - * sizeof (array->members[0])); - - if (!array->members) - { - grub_free (new_array->uuid); - return grub_errno; - } - - if (! array->name) - { - for (p = array_list; p != NULL; p = p->next) - { - if (p->number == array->number) - break; - } - } - - if (array->name || p) - { - /* The number is already in use, so we need to find a new one. - (Or, in the case of named arrays, the array doesn't have its - own number, but we need one that doesn't clash for use as a key - in the disk cache. */ - int i = array->name ? 0x40000000 : 0; - - while (1) - { - for (p = array_list; p != NULL; p = p->next) - { - if (p->number == i) - break; - } - - if (! p) - { - /* We found an unused number. */ - array->number = i; - break; - } - - i++; - } - } - - /* mdraid 1.x superblocks have only a name stored not a number. - Use it directly as GRUB device. */ - if (! array->name) - { - array->name = grub_xasprintf ("md%d", array->number); - if (! array->name) - { - grub_free (array->members); - grub_free (array->uuid); - grub_free (array); - - return grub_errno; - } - } - else - { - /* Strip off the homehost if present. */ - char *colon = grub_strchr (array->name, ':'); - char *new_name = grub_xasprintf ("md/%s", - colon ? colon + 1 : array->name); - - if (! new_name) - { - grub_free (array->members); - grub_free (array->uuid); - grub_free (array); - - return grub_errno; - } - - grub_free (array->name); - array->name = new_name; - } - - grub_dprintf ("raid", "Found array %s (%s)\n", array->name, - scanner_name); -#ifdef GRUB_UTIL - grub_util_info ("Found array %s (%s)", array->name, - scanner_name); -#endif - - { - int max_used_number = 0, len, need_new_name = 0; - int add_us = 0; - len = grub_strlen (array->name); - if (len && grub_isdigit (array->name[len-1])) - add_us = 1; - for (p = array_list; p != NULL; p = p->next) - { - int cur_num; - char *num, *end; - if (grub_strncmp (p->name, array->name, len) != 0) - continue; - if (p->name[len] == 0) - { - need_new_name = 1; - continue; - } - if (add_us && p->name[len] != '_') - continue; - if (add_us) - num = p->name + len + 1; - else - num = p->name + len; - if (!grub_isdigit (num[0])) - continue; - cur_num = grub_strtoull (num, &end, 10); - if (end[0]) - continue; - if (cur_num > max_used_number) - max_used_number = cur_num; - } - if (need_new_name) - { - char *tmp; - tmp = grub_xasprintf ("%s%s%d", array->name, add_us ? "_" : "", - max_used_number + 1); - if (!tmp) - return grub_errno; - grub_free (array->name); - array->name = tmp; - } - } - - /* Add our new array to the list. */ - array->next = array_list; - array_list = array; - - /* RAID 1 doesn't use a chunksize but code assumes one so set - one. */ - if (array->level == 1) - array->chunk_size = 64; - } - - /* Add the device to the array. */ - array->members[new_array->index].device = disk; - array->members[new_array->index].start_sector = start_sector; - array->nr_devs++; - if (!was_readable && grub_is_array_readable (array)) - array->became_readable_at = inscnt++; - - return 0; -} - -static void -free_array (void) -{ - struct grub_raid_array *array; - - array = array_list; - while (array) - { - struct grub_raid_array *p; - unsigned int i; - - p = array; - array = array->next; - - for (i = 0; i < p->allocated_devs; i++) - if (p->members[i].device) - grub_disk_close (p->members[i].device); - grub_free (p->members); - - grub_free (p->uuid); - grub_free (p->name); - grub_free (p); - } - - array_list = 0; -} - -void -grub_raid_register (grub_raid_t raid) -{ - raid->next = grub_raid_list; - grub_raid_list = raid; -} - -void -grub_raid_unregister (grub_raid_t raid) -{ - grub_raid_t *p, q; - - for (p = &grub_raid_list, q = *p; q; p = &(q->next), q = q->next) - if (q == raid) - { - *p = q->next; - break; - } -} - -static struct grub_disk_dev grub_raid_dev = - { - .name = "raid", - .id = GRUB_DISK_DEVICE_RAID_ID, - .iterate = grub_raid_iterate, - .open = grub_raid_open, - .close = grub_raid_close, - .read = grub_raid_read, - .write = grub_raid_write, -#ifdef GRUB_UTIL - .memberlist = grub_raid_memberlist, - .raidname = grub_raid_getname, -#endif - .next = 0 - }; - - -GRUB_MOD_INIT(raid) -{ - grub_disk_dev_register (&grub_raid_dev); -} - -GRUB_MOD_FINI(raid) -{ - grub_disk_dev_unregister (&grub_raid_dev); - free_array (); -} diff --git a/grub-core/disk/raid5_recover.c b/grub-core/disk/raid5_recover.c index c26d05e94..62d76d1df 100644 --- a/grub-core/disk/raid5_recover.c +++ b/grub-core/disk/raid5_recover.c @@ -22,12 +22,13 @@ #include #include #include -#include +#include +#include GRUB_MOD_LICENSE ("GPLv3+"); static grub_err_t -grub_raid5_recover (struct grub_raid_array *array, int disknr, +grub_raid5_recover (struct grub_diskfilter_segment *array, int disknr, char *buf, grub_disk_addr_t sector, int size) { char *buf2; @@ -40,16 +41,15 @@ grub_raid5_recover (struct grub_raid_array *array, int disknr, grub_memset (buf, 0, size); - for (i = 0; i < (int) array->total_devs; i++) + for (i = 0; i < (int) array->node_count; i++) { grub_err_t err; if (i == disknr) continue; - err = grub_disk_read (array->members[i].device, - array->members[i].start_sector + sector, - 0, size, buf2); + err = grub_diskfilter_read_node (&array->nodes[i], sector, + size >> GRUB_DISK_SECTOR_BITS, buf2); if (err) { @@ -57,7 +57,7 @@ grub_raid5_recover (struct grub_raid_array *array, int disknr, return err; } - grub_raid_block_xor (buf, buf2, size); + grub_crypto_xor (buf, buf, buf2, size); } grub_free (buf2); diff --git a/grub-core/disk/raid6_recover.c b/grub-core/disk/raid6_recover.c index e91992547..779a39eaa 100644 --- a/grub-core/disk/raid6_recover.c +++ b/grub-core/disk/raid6_recover.c @@ -22,7 +22,8 @@ #include #include #include -#include +#include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -63,7 +64,7 @@ grub_raid6_init_table (void) } static grub_err_t -grub_raid6_recover (struct grub_raid_array *array, int disknr, int p, +grub_raid6_recover (struct grub_diskfilter_segment *array, int disknr, int p, char *buf, grub_disk_addr_t sector, int size) { int i, q, pos; @@ -80,27 +81,30 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p, goto quit; q = p + 1; - if (q == (int) array->total_devs) + if (q == (int) array->node_count) q = 0; pos = q + 1; - if (pos == (int) array->total_devs) + if (pos == (int) array->node_count) pos = 0; - for (i = 0; i < (int) array->total_devs - 2; i++) + for (i = 0; i < (int) array->node_count - 2; i++) { + int c; + if (array->layout & GRUB_RAID_LAYOUT_MUL_FROM_POS) + c = pos; + else + c = i; if (pos == disknr) - bad1 = i; + bad1 = c; else { - if ((array->members[pos].device) && - (! grub_disk_read (array->members[pos].device, - array->members[pos].start_sector + sector, - 0, size, buf))) + if (! grub_diskfilter_read_node (&array->nodes[pos], sector, + size >> GRUB_DISK_SECTOR_BITS, buf)) { - grub_raid_block_xor (pbuf, buf, size); - grub_raid_block_mulx (i, buf, size); - grub_raid_block_xor (qbuf, buf, size); + grub_crypto_xor (pbuf, pbuf, buf, size); + grub_raid_block_mulx (c, buf, size); + grub_crypto_xor (qbuf, qbuf, buf, size); } else { @@ -108,13 +112,13 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p, if (bad2 >= 0) goto quit; - bad2 = i; + bad2 = c; grub_errno = GRUB_ERR_NONE; } } pos++; - if (pos == (int) array->total_devs) + if (pos == (int) array->node_count) pos = 0; } @@ -125,27 +129,19 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p, if (bad2 < 0) { /* One bad device */ - if ((array->members[p].device) && - (! grub_disk_read (array->members[p].device, - array->members[p].start_sector + sector, - 0, size, buf))) + if ((! grub_diskfilter_read_node (&array->nodes[p], sector, + size >> GRUB_DISK_SECTOR_BITS, buf))) { - grub_raid_block_xor (buf, pbuf, size); - goto quit; - } - - if (! array->members[q].device) - { - grub_error (GRUB_ERR_READ_ERROR, "not enough disk to restore"); + grub_crypto_xor (buf, buf, pbuf, size); goto quit; } grub_errno = GRUB_ERR_NONE; - if (grub_disk_read (array->members[q].device, - array->members[q].start_sector + sector, 0, size, buf)) + if (grub_diskfilter_read_node (&array->nodes[q], sector, + size >> GRUB_DISK_SECTOR_BITS, buf)) goto quit; - grub_raid_block_xor (buf, qbuf, size); + grub_crypto_xor (buf, buf, qbuf, size); grub_raid_block_mulx (255 - bad1, buf, size); } @@ -154,25 +150,17 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p, /* Two bad devices */ int c; - if ((! array->members[p].device) || (! array->members[q].device)) - { - grub_error (GRUB_ERR_READ_ERROR, "not enough disk to restore"); - goto quit; - } - - if (grub_disk_read (array->members[p].device, - array->members[p].start_sector + sector, - 0, size, buf)) + if (grub_diskfilter_read_node (&array->nodes[p], sector, + size >> GRUB_DISK_SECTOR_BITS, buf)) goto quit; - grub_raid_block_xor (pbuf, buf, size); + grub_crypto_xor (pbuf, pbuf, buf, size); - if (grub_disk_read (array->members[q].device, - array->members[q].start_sector + sector, - 0, size, buf)) + if (grub_diskfilter_read_node (&array->nodes[q], sector, + size >> GRUB_DISK_SECTOR_BITS, buf)) goto quit; - grub_raid_block_xor (qbuf, buf, size); + grub_crypto_xor (qbuf, qbuf, buf, size); c = (255 - bad1 + (255 - powx_inv[(powx[bad2 - bad1 + 255] ^ 1)])) % 255; grub_raid_block_mulx (c, qbuf, size); @@ -180,7 +168,7 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p, c = (bad2 + c) % 255; grub_raid_block_mulx (c, pbuf, size); - grub_raid_block_xor (pbuf, qbuf, size); + grub_crypto_xor (pbuf, pbuf, qbuf, size); grub_memcpy (buf, pbuf, size); } diff --git a/grub-core/disk/scsi.c b/grub-core/disk/scsi.c index 610cc4dc5..37c5ad3b3 100644 --- a/grub-core/disk/scsi.c +++ b/grub-core/disk/scsi.c @@ -26,6 +26,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -153,14 +154,14 @@ grub_scsi_inquiry (grub_scsi_t scsi) /* Read the capacity and block size of SCSI. */ static grub_err_t -grub_scsi_read_capacity (grub_scsi_t scsi) +grub_scsi_read_capacity10 (grub_scsi_t scsi) { - struct grub_scsi_read_capacity rc; - struct grub_scsi_read_capacity_data rcd; + struct grub_scsi_read_capacity10 rc; + struct grub_scsi_read_capacity10_data rcd; grub_err_t err; grub_err_t err_sense; - rc.opcode = grub_scsi_cmd_read_capacity; + rc.opcode = grub_scsi_cmd_read_capacity10; rc.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT; rc.logical_block_addr = 0; rc.reserved1 = 0; @@ -182,7 +183,42 @@ grub_scsi_read_capacity (grub_scsi_t scsi) if (err) return err; - scsi->size = grub_be_to_cpu32 (rcd.size); + scsi->last_block = grub_be_to_cpu32 (rcd.last_block); + scsi->blocksize = grub_be_to_cpu32 (rcd.blocksize); + + return GRUB_ERR_NONE; +} + +/* Read the capacity and block size of SCSI. */ +static grub_err_t +grub_scsi_read_capacity16 (grub_scsi_t scsi) +{ + struct grub_scsi_read_capacity16 rc; + struct grub_scsi_read_capacity16_data rcd; + grub_err_t err; + grub_err_t err_sense; + + rc.opcode = grub_scsi_cmd_read_capacity16; + rc.lun = (scsi->lun << GRUB_SCSI_LUN_SHIFT) | 0x10; + rc.logical_block_addr = 0; + rc.alloc_len = grub_cpu_to_be32 (sizeof (rcd)); + rc.PMI = 0; + rc.control = 0; + + err = scsi->dev->read (scsi, sizeof (rc), (char *) &rc, + sizeof (rcd), (char *) &rcd); + + /* Each SCSI command should be followed by Request Sense. + If not so, many devices STALLs or definitely freezes. */ + err_sense = grub_scsi_request_sense (scsi); + if (err_sense != GRUB_ERR_NONE) + grub_errno = err; +/* err_sense is ignored for now and Request Sense Data also... */ + + if (err) + return err; + + scsi->last_block = grub_be_to_cpu64 (rcd.last_block); scsi->blocksize = grub_be_to_cpu32 (rcd.blocksize); return GRUB_ERR_NONE; @@ -253,12 +289,43 @@ grub_scsi_read12 (grub_disk_t disk, grub_disk_addr_t sector, return err; } -#if 0 +/* Send a SCSI request for DISK: read SIZE sectors starting with + sector SECTOR to BUF. */ +static grub_err_t +grub_scsi_read16 (grub_disk_t disk, grub_disk_addr_t sector, + grub_size_t size, char *buf) +{ + grub_scsi_t scsi; + struct grub_scsi_read16 rd; + grub_err_t err; + grub_err_t err_sense; + + scsi = disk->data; + + rd.opcode = grub_scsi_cmd_read16; + rd.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT; + rd.lba = grub_cpu_to_be64 (sector); + rd.size = grub_cpu_to_be32 (size); + rd.reserved = 0; + rd.control = 0; + + err = scsi->dev->read (scsi, sizeof (rd), (char *) &rd, size * scsi->blocksize, buf); + + /* Each SCSI command should be followed by Request Sense. + If not so, many devices STALLs or definitely freezes. */ + err_sense = grub_scsi_request_sense (scsi); + if (err_sense != GRUB_ERR_NONE) + grub_errno = err; + /* err_sense is ignored for now and Request Sense Data also... */ + + return err; +} + /* Send a SCSI request for DISK: write the data stored in BUF to SIZE sectors starting with SECTOR. */ static grub_err_t grub_scsi_write10 (grub_disk_t disk, grub_disk_addr_t sector, - grub_size_t size, char *buf) + grub_size_t size, const char *buf) { grub_scsi_t scsi; struct grub_scsi_write10 wr; @@ -287,6 +354,8 @@ grub_scsi_write10 (grub_disk_t disk, grub_disk_addr_t sector, return err; } +#if 0 + /* Send a SCSI request for DISK: write the data stored in BUF to SIZE sectors starting with SECTOR. */ static grub_err_t @@ -320,6 +389,39 @@ grub_scsi_write12 (grub_disk_t disk, grub_disk_addr_t sector, } #endif +/* Send a SCSI request for DISK: write the data stored in BUF to SIZE + sectors starting with SECTOR. */ +static grub_err_t +grub_scsi_write16 (grub_disk_t disk, grub_disk_addr_t sector, + grub_size_t size, const char *buf) +{ + grub_scsi_t scsi; + struct grub_scsi_write16 wr; + grub_err_t err; + grub_err_t err_sense; + + scsi = disk->data; + + wr.opcode = grub_scsi_cmd_write16; + wr.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT; + wr.lba = grub_cpu_to_be64 (sector); + wr.size = grub_cpu_to_be32 (size); + wr.reserved = 0; + wr.control = 0; + + err = scsi->dev->write (scsi, sizeof (wr), (char *) &wr, size * scsi->blocksize, buf); + + /* Each SCSI command should be followed by Request Sense. + If not so, many devices STALLs or definitely freezes. */ + err_sense = grub_scsi_request_sense (scsi); + if (err_sense != GRUB_ERR_NONE) + grub_errno = err; + /* err_sense is ignored for now and Request Sense Data also... */ + + return err; +} + + static int grub_scsi_iterate (int (*hook) (const char *name), @@ -475,15 +577,26 @@ grub_scsi_open (const char *name, grub_disk_t disk) grub_errno = GRUB_ERR_NONE; /* Read capacity of media */ - err = grub_scsi_read_capacity (scsi); + err = grub_scsi_read_capacity10 (scsi); if (err) { grub_free (scsi); - grub_dprintf ("scsi", "READ CAPACITY failed\n"); + grub_dprintf ("scsi", "READ CAPACITY10 failed\n"); return err; } - disk->total_sectors = scsi->size; + if (scsi->last_block == 0xffffffff) + { + err = grub_scsi_read_capacity16 (scsi); + if (err) + { + grub_free (scsi); + grub_dprintf ("scsi", "READ CAPACITY16 failed\n"); + return err; + } + } + + disk->total_sectors = scsi->last_block + 1; if (scsi->blocksize & (scsi->blocksize - 1) || !scsi->blocksize) { grub_free (scsi); @@ -491,11 +604,11 @@ grub_scsi_open (const char *name, grub_disk_t disk) scsi->blocksize); } for (disk->log_sector_size = 0; - (1 << disk->log_sector_size) < scsi->blocksize; + (1U << disk->log_sector_size) < scsi->blocksize; disk->log_sector_size++); - grub_dprintf ("scsi", "blocks=%u, blocksize=%u\n", - scsi->size, scsi->blocksize); + grub_dprintf ("scsi", "last_block=%" PRIuGRUB_UINT64_T ", blocksize=%u\n", + scsi->last_block, scsi->blocksize); grub_dprintf ("scsi", "Disk total sectors = %llu\n", (unsigned long long) disk->total_sectors); @@ -539,13 +652,19 @@ grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector, switch (scsi->devtype) { case grub_scsi_devtype_direct: - err = grub_scsi_read10 (disk, sector, len, buf); + if (sector >> 32) + err = grub_scsi_read16 (disk, sector, len, buf); + else + err = grub_scsi_read10 (disk, sector, len, buf); if (err) return err; break; case grub_scsi_devtype_cdrom: - err = grub_scsi_read12 (disk, sector, len, buf); + 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; @@ -595,13 +714,41 @@ grub_scsi_write (grub_disk_t disk __attribute((unused)), grub_size_t size __attribute((unused)), const char *buf __attribute((unused))) { -#if 0 - /* XXX: Not tested yet! */ + grub_scsi_t scsi; - /* XXX: This should depend on the device type? */ - return grub_scsi_write10 (disk, sector, size, buf); -#endif - return GRUB_ERR_NOT_IMPLEMENTED_YET; + scsi = disk->data; + + if (scsi->devtype == grub_scsi_devtype_cdrom) + return grub_error (GRUB_ERR_IO, N_("cannot write to cdrom")); + + while (size) + { + /* PATA doesn't support more than 32K reads. + Not sure about AHCI and USB. If it's confirmed that either of + them can do bigger reads reliably this value can be moved to 'scsi' + structure. */ + grub_size_t len = 32768 >> disk->log_sector_size; + grub_err_t err; + if (len > size) + len = size; + /* Depending on the type, select a read function. */ + switch (scsi->devtype) + { + case grub_scsi_devtype_direct: + if (sector >> 32) + err = grub_scsi_write16 (disk, sector, len, buf); + else + err = grub_scsi_write10 (disk, sector, len, buf); + if (err) + return err; + break; + } + size -= len; + sector += len; + buf += len << disk->log_sector_size; + } + + return GRUB_ERR_NONE; } diff --git a/grub-core/disk/usbms.c b/grub-core/disk/usbms.c index a4c2addf1..52cc33e93 100644 --- a/grub-core/disk/usbms.c +++ b/grub-core/disk/usbms.c @@ -28,6 +28,12 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define GRUB_USBMS_DIRECTION_BIT 7 +/* Length of CBI command should be always 12 bytes */ +#define GRUB_USBMS_CBI_CMD_SIZE 12 +/* CBI class-specific USB request ADSC - it sends CBI (scsi) command to + * device in DATA stage */ +#define GRUB_USBMS_CBI_ADSC_REQ 0x00 + /* The USB Mass Storage Command Block Wrapper. */ struct grub_usbms_cbw { @@ -59,8 +65,9 @@ struct grub_usbms_dev struct grub_usb_desc_endp *in; struct grub_usb_desc_endp *out; - int in_maxsz; - int out_maxsz; + int subclass; + int protocol; + struct grub_usb_desc_endp *intrpt; }; typedef struct grub_usbms_dev *grub_usbms_dev_t; @@ -70,7 +77,39 @@ static grub_usbms_dev_t grub_usbms_devices[MAX_USBMS_DEVICES]; static int first_available_slot = 0; static grub_err_t -grub_usbms_reset (grub_usb_device_t dev, int interface) +grub_usbms_cbi_cmd (grub_usb_device_t dev, int interface, + grub_uint8_t *cbicb) +{ + return grub_usb_control_msg (dev, + GRUB_USB_REQTYPE_CLASS_INTERFACE_OUT, + GRUB_USBMS_CBI_ADSC_REQ, 0, interface, + GRUB_USBMS_CBI_CMD_SIZE, (char*)cbicb); +} + +static grub_err_t +grub_usbms_cbi_reset (grub_usb_device_t dev, int interface) +{ + /* Prepare array with Command Block Reset (=CBR) */ + /* CBI specific communication reset command should be send to device + * via CBI USB class specific request ADCS */ + struct grub_cbi_reset + { + grub_uint8_t opcode; /* 0x1d = SEND DIAGNOSTIC */ + grub_uint8_t lun; /* 7-5 LUN, 4-0 flags - for CBR always = 0x04 */ + grub_uint8_t pad[10]; + /* XXX: There is collision between CBI and UFI specifications: + * CBI says 0xff, UFI says 0x00 ... probably it does + * not matter ... (?) */ + } cbicb = { 0x1d, 0x04, + { 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff } + }; + + return grub_usbms_cbi_cmd (dev, interface, (grub_uint8_t *)&cbicb); +} + +static grub_err_t +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); @@ -79,6 +118,15 @@ grub_usbms_reset (grub_usb_device_t dev, int interface) return GRUB_ERR_NONE; } +static grub_err_t +grub_usbms_reset (grub_usbms_dev_t dev) +{ + if (dev->protocol == GRUB_USBMS_PROTOCOL_BULK) + return grub_usbms_bo_reset (dev->dev, dev->interface); + else + return grub_usbms_cbi_reset (dev->dev, dev->interface); +} + static void grub_usbms_detach (grub_usb_device_t usbdev, int config, int interface) { @@ -101,7 +149,7 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno) int j; grub_uint8_t luns = 0; unsigned curnum; - grub_usb_err_t err; + grub_usb_err_t err = GRUB_ERR_NONE; if (first_available_slot == ARRAY_SIZE (grub_usbms_devices)) return 0; @@ -117,7 +165,9 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno) && interf->subclass != GRUB_USBMS_SUBCLASS_MMC2 && interf->subclass != GRUB_USBMS_SUBCLASS_UFI && interf->subclass != GRUB_USBMS_SUBCLASS_SFF8070 ) - || interf->protocol != GRUB_USBMS_PROTOCOL_BULK) + || (interf->protocol != GRUB_USBMS_PROTOCOL_BULK + && interf->protocol != GRUB_USBMS_PROTOCOL_CBI + && interf->protocol != GRUB_USBMS_PROTOCOL_CB)) return 0; grub_usbms_devices[curnum] = grub_zalloc (sizeof (struct grub_usbms_dev)); @@ -126,6 +176,8 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno) grub_usbms_devices[curnum]->dev = usbdev; grub_usbms_devices[curnum]->interface = interfno; + grub_usbms_devices[curnum]->subclass = interf->subclass; + grub_usbms_devices[curnum]->protocol = interf->protocol; grub_dprintf ("usbms", "alive\n"); @@ -137,24 +189,19 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno) endp = &usbdev->config[0].interf[interfno].descendp[j]; if ((endp->endp_addr & 128) && (endp->attrib & 3) == 2) - { - /* Bulk IN endpoint. */ - grub_usbms_devices[curnum]->in = endp; - /* Clear Halt is not possible yet! */ - /* grub_usb_clear_halt (usbdev, endp->endp_addr); */ - grub_usbms_devices[curnum]->in_maxsz = endp->maxpacket; - } + /* Bulk IN endpoint. */ + grub_usbms_devices[curnum]->in = endp; else if (!(endp->endp_addr & 128) && (endp->attrib & 3) == 2) - { - /* Bulk OUT endpoint. */ - grub_usbms_devices[curnum]->out = endp; - /* Clear Halt is not possible yet! */ - /* grub_usb_clear_halt (usbdev, endp->endp_addr); */ - grub_usbms_devices[curnum]->out_maxsz = endp->maxpacket; - } + /* Bulk OUT endpoint. */ + grub_usbms_devices[curnum]->out = endp; + else if ((endp->endp_addr & 128) && (endp->attrib & 3) == 3) + /* Interrupt (IN) endpoint. */ + grub_usbms_devices[curnum]->intrpt = endp; } - if (!grub_usbms_devices[curnum]->in || !grub_usbms_devices[curnum]->out) + if (!grub_usbms_devices[curnum]->in || !grub_usbms_devices[curnum]->out + || ((grub_usbms_devices[curnum]->protocol == GRUB_USBMS_PROTOCOL_CBI) + && !grub_usbms_devices[curnum]->intrpt)) { grub_free (grub_usbms_devices[curnum]); grub_usbms_devices[curnum] = 0; @@ -167,27 +214,34 @@ grub_usbms_attach (grub_usb_device_t usbdev, int configno, int interfno) grub_usb_set_configuration (usbdev, 1); /* Query the amount of LUNs. */ - err = grub_usb_control_msg (usbdev, 0xA1, 254, 0, interfno, 1, (char *) &luns); - - if (err) - { - /* In case of a stall, clear the stall. */ - if (err == GRUB_USB_ERR_STALL) - { - grub_usb_clear_halt (usbdev, grub_usbms_devices[curnum]->in->endp_addr); - grub_usb_clear_halt (usbdev, grub_usbms_devices[curnum]->out->endp_addr); - } - /* Just set the amount of LUNs to one. */ - grub_errno = GRUB_ERR_NONE; - grub_usbms_devices[curnum]->luns = 1; + if (grub_usbms_devices[curnum]->protocol == GRUB_USBMS_PROTOCOL_BULK) + { /* Only Bulk only devices support Get Max LUN command */ + err = grub_usb_control_msg (usbdev, 0xA1, 254, 0, interfno, 1, (char *) &luns); + + if (err) + { + /* In case of a stall, clear the stall. */ + if (err == GRUB_USB_ERR_STALL) + { + grub_usb_clear_halt (usbdev, grub_usbms_devices[curnum]->in->endp_addr); + grub_usb_clear_halt (usbdev, grub_usbms_devices[curnum]->out->endp_addr); + } + /* Just set the amount of LUNs to one. */ + grub_errno = GRUB_ERR_NONE; + grub_usbms_devices[curnum]->luns = 1; + } + else + /* luns = 0 means one LUN with ID 0 present ! */ + /* We get from device not number of LUNs but highest + * LUN number. LUNs are numbered from 0, + * i.e. number of LUNs is luns+1 ! */ + grub_usbms_devices[curnum]->luns = luns + 1; } else - /* luns = 0 means one LUN with ID 0 present ! */ - /* We get from device not number of LUNs but highest - * LUN number. LUNs are numbered from 0, - * i.e. number of LUNs is luns+1 ! */ - grub_usbms_devices[curnum]->luns = luns + 1; - + /* XXX: Does CBI devices support multiple LUNs ? + * I.e., should we detect number of device's LUNs ? (How?) */ + grub_usbms_devices[curnum]->luns = 1; + grub_dprintf ("usbms", "alive\n"); usbdev->config[configno].interf[interfno].detach_hook = grub_usbms_detach; @@ -232,8 +286,8 @@ grub_usbms_iterate (int NESTED_FUNC_ATTR (*hook) (int id, int bus, int luns), } static grub_err_t -grub_usbms_transfer (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, - grub_size_t size, char *buf, int read_write) +grub_usbms_transfer_bo (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, + grub_size_t size, char *buf, int read_write) { struct grub_usbms_cbw cbw; grub_usbms_dev_t dev = (grub_usbms_dev_t) scsi->data; @@ -242,7 +296,7 @@ grub_usbms_transfer (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, grub_usb_err_t err = GRUB_USB_ERR_NONE; grub_usb_err_t errCSW = GRUB_USB_ERR_NONE; int retrycnt = 3 + 1; - + retry: retrycnt--; if (retrycnt == 0) @@ -343,7 +397,7 @@ CheckCSW: if (errCSW) { /* Bulk-only reset device. */ grub_dprintf ("usb", "Bulk-only reset device - errCSW\n"); - grub_usbms_reset (dev->dev, dev->interface); + grub_usbms_reset (dev); grub_usb_clear_halt (dev->dev, dev->in->endp_addr); grub_usb_clear_halt (dev->dev, dev->out->endp_addr); goto retry; @@ -360,7 +414,7 @@ CheckCSW: (status.signature != grub_cpu_to_le32(0x53425355))) { /* Bulk-only reset device. */ grub_dprintf ("usb", "Bulk-only reset device - bad status\n"); - grub_usbms_reset (dev->dev, dev->interface); + grub_usbms_reset (dev); grub_usb_clear_halt (dev->dev, dev->in->endp_addr); grub_usb_clear_halt (dev->dev, dev->out->endp_addr); @@ -378,6 +432,158 @@ CheckCSW: return GRUB_ERR_NONE; } +static grub_err_t +grub_usbms_transfer_cbi (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, + grub_size_t size, char *buf, int read_write) +{ + grub_usbms_dev_t dev = (grub_usbms_dev_t) scsi->data; + int retrycnt = 3 + 1; + grub_usb_err_t err = GRUB_USB_ERR_NONE; + grub_uint8_t cbicb[GRUB_USBMS_CBI_CMD_SIZE]; + grub_uint16_t status; + + retry: + retrycnt--; + if (retrycnt == 0) + return grub_error (GRUB_ERR_IO, "USB Mass Storage CBI failed"); + + /* Setup the request. */ + grub_memset (cbicb, 0, sizeof (cbicb)); + grub_memcpy (cbicb, cmd, + cmdsize >= GRUB_USBMS_CBI_CMD_SIZE + ? GRUB_USBMS_CBI_CMD_SIZE + : cmdsize); + + /* Debug print of CBIcb content. */ + grub_dprintf ("usb", "cbicb:\n %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + cbicb[ 0], cbicb[ 1], cbicb[ 2], cbicb[ 3], + cbicb[ 4], cbicb[ 5], cbicb[ 6], cbicb[ 7], + cbicb[ 8], cbicb[ 9], cbicb[10], cbicb[11]); + + /* Write the request. + * XXX: Error recovery is maybe not correct. */ + err = grub_usbms_cbi_cmd (dev->dev, dev->interface, cbicb); + if (err) + { + grub_dprintf ("usb", "CBI cmdcb setup err=%d\n", err); + if (err == GRUB_USB_ERR_STALL) + { + /* Stall in this place probably means bad or unsupported + * command, so we will not try it again. */ + return grub_error (GRUB_ERR_IO, "USB Mass Storage CBI request failed"); + } + 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, + 2, (char*)&status); + grub_dprintf ("usb", "CBI cmdcb setup status: err=%d, status=0x%x\n", err, status); + } + /* Any other error could be transport problem, try it again */ + goto retry; + } + + /* Read/write the data, (maybe) according to specification. */ + if (size && (read_write == 0)) + { + err = grub_usb_bulk_read (dev->dev, dev->in->endp_addr, size, buf); + grub_dprintf ("usb", "read: %d\n", err); + if (err) + { + if (err == GRUB_USB_ERR_STALL) + grub_usb_clear_halt (dev->dev, dev->in->endp_addr); + goto retry; + } + } + else if (size) + { + err = grub_usb_bulk_write (dev->dev, dev->out->endp_addr, size, buf); + grub_dprintf ("usb", "write: %d\n", err); + if (err) + { + if (err == GRUB_USB_ERR_STALL) + grub_usb_clear_halt (dev->dev, dev->out->endp_addr); + goto retry; + } + } + + /* XXX: It is not clear to me yet, how to check status of CBI + * data transfer on devices without interrupt pipe. + * AFAIK there is probably no status phase to indicate possibly + * bad transported data. + * Maybe we should do check on higher level, i.e. issue RequestSense + * command (we do it already in scsi.c) and check returned values + * (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, + 2, (char*)&status); + grub_dprintf ("usb", "read status: %d\n", err); + if (err) + { + /* Try to reset device, because it is probably not standard + * situation */ + grub_usbms_reset (dev); + grub_usb_clear_halt (dev->dev, dev->in->endp_addr); + grub_usb_clear_halt (dev->dev, dev->out->endp_addr); + grub_usb_clear_halt (dev->dev, dev->intrpt->endp_addr); + goto retry; + } + if (dev->subclass == GRUB_USBMS_SUBCLASS_UFI) + { + /* These devices should return bASC and bASCQ */ + if (status != 0) + /* Some error, currently we don't care what it is... */ + goto retry; + } + else if (dev->subclass == GRUB_USBMS_SUBCLASS_RBC) + { + /* XXX: I don't understand what returns RBC subclass devices, + * so I don't check it - maybe somebody helps ? */ + } + else + { + /* Any other device should return bType = 0 and some bValue */ + if (status & 0xff) + return grub_error (GRUB_ERR_IO, "USB Mass Storage CBI status type != 0"); + status = (status & 0x0300) >> 8; + switch (status) + { + case 0 : /* OK */ + break; + case 1 : /* Fail */ + goto retry; + break; + case 2 : /* Phase error */ + case 3 : /* Persistent Failure */ + grub_dprintf ("usb", "CBI reset device - phase error or persistent failure\n"); + grub_usbms_reset (dev); + grub_usb_clear_halt (dev->dev, dev->in->endp_addr); + grub_usb_clear_halt (dev->dev, dev->out->endp_addr); + grub_usb_clear_halt (dev->dev, dev->intrpt->endp_addr); + goto retry; + break; + } + } + } + + return err; +} + + +static grub_err_t +grub_usbms_transfer (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, + grub_size_t size, char *buf, int read_write) +{ + grub_usbms_dev_t dev = (grub_usbms_dev_t) scsi->data; + + if (dev->protocol == GRUB_USBMS_PROTOCOL_BULK) + return grub_usbms_transfer_bo (scsi, cmdsize, cmd, size, buf, + read_write); + else + return grub_usbms_transfer_cbi (scsi, cmdsize, cmd, size, buf, + read_write); +} static grub_err_t grub_usbms_read (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, @@ -388,9 +594,9 @@ grub_usbms_read (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, static grub_err_t grub_usbms_write (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, - grub_size_t size, char *buf) + grub_size_t size, const char *buf) { - return grub_usbms_transfer (scsi, cmdsize, cmd, size, buf, 1); + return grub_usbms_transfer (scsi, cmdsize, cmd, size, (char *) buf, 1); } static grub_err_t diff --git a/grub-core/efiemu/i386/coredetect.c b/grub-core/efiemu/i386/coredetect.c index 975c4aa5d..c3782fda9 100644 --- a/grub-core/efiemu/i386/coredetect.c +++ b/grub-core/efiemu/i386/coredetect.c @@ -26,7 +26,7 @@ #define bit_LM (1 << 29) -char * +const char * grub_efiemu_get_default_core_name (void) { diff --git a/grub-core/efiemu/i386/loadcore32.c b/grub-core/efiemu/i386/loadcore32.c index 24b63ec98..e746df8df 100644 --- a/grub-core/efiemu/i386/loadcore32.c +++ b/grub-core/efiemu/i386/loadcore32.c @@ -23,6 +23,7 @@ #include #include #include +#include /* Check if EHDR is a valid ELF header. */ int @@ -86,23 +87,29 @@ grub_arch_efiemu_relocate_symbols32 (grub_efiemu_segment_t segs, switch (ELF32_R_TYPE (rel->r_info)) { case R_386_32: - if ((err = grub_efiemu_write_value - (addr, sym.off + *addr, sym.handle, 0, - seg->ptv_rel_needed, sizeof (grub_uint32_t)))) + err = grub_efiemu_write_value (addr, sym.off + *addr, + sym.handle, 0, + seg->ptv_rel_needed, + sizeof (grub_uint32_t)); + if (err) return err; break; case R_386_PC32: - if ((err = grub_efiemu_write_value - (addr, sym.off + *addr - rel->r_offset - - seg->off, sym.handle, seg->handle, - seg->ptv_rel_needed, sizeof (grub_uint32_t)))) + err = grub_efiemu_write_value (addr, sym.off + *addr + - rel->r_offset + - seg->off, sym.handle, + seg->handle, + seg->ptv_rel_needed, + sizeof (grub_uint32_t)); + if (err) return err; break; default: - return grub_error (GRUB_ERR_BAD_OS, - "unrecognised relocation"); + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("relocation 0x%x is not implemented yet"), + ELF_R_TYPE (rel->r_info)); } } } diff --git a/grub-core/efiemu/i386/loadcore64.c b/grub-core/efiemu/i386/loadcore64.c index a69279077..e49d0b6ff 100644 --- a/grub-core/efiemu/i386/loadcore64.c +++ b/grub-core/efiemu/i386/loadcore64.c @@ -23,6 +23,7 @@ #include #include #include +#include /* Check if EHDR is a valid ELF header. */ int @@ -87,30 +88,41 @@ grub_arch_efiemu_relocate_symbols64 (grub_efiemu_segment_t segs, switch (ELF64_R_TYPE (rel->r_info)) { case R_X86_64_64: - if ((err = grub_efiemu_write_value - (addr, *addr64 + rel->r_addend + sym.off, sym.handle, - 0, seg->ptv_rel_needed, sizeof (grub_uint64_t)))) + err = grub_efiemu_write_value (addr, + *addr64 + rel->r_addend + + sym.off, sym.handle, + 0, seg->ptv_rel_needed, + sizeof (grub_uint64_t)); + if (err) return err; break; case R_X86_64_PC32: - if ((err = grub_efiemu_write_value - (addr, *addr32 + rel->r_addend + sym.off - - rel->r_offset - seg->off, sym.handle, seg->handle, - seg->ptv_rel_needed, sizeof (grub_uint32_t)))) + err = grub_efiemu_write_value (addr, + *addr32 + rel->r_addend + + sym.off + - rel->r_offset - seg->off, + sym.handle, seg->handle, + seg->ptv_rel_needed, + sizeof (grub_uint32_t)); + if (err) return err; break; case R_X86_64_32: case R_X86_64_32S: - if ((err = grub_efiemu_write_value - (addr, *addr32 + rel->r_addend + sym.off, sym.handle, - 0, seg->ptv_rel_needed, sizeof (grub_uint32_t)))) + err = grub_efiemu_write_value (addr, + *addr32 + rel->r_addend + + sym.off, sym.handle, + 0, seg->ptv_rel_needed, + sizeof (grub_uint32_t)); + if (err) return err; break; default: - return grub_error (GRUB_ERR_BAD_OS, - "unrecognised relocation"); + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("relocation 0x%x is not implemented yet"), + ELF_R_TYPE (rel->r_info)); } } } diff --git a/grub-core/efiemu/i386/pc/cfgtables.c b/grub-core/efiemu/i386/pc/cfgtables.c index 7b6a40c87..492c07c46 100644 --- a/grub-core/efiemu/i386/pc/cfgtables.c +++ b/grub-core/efiemu/i386/pc/cfgtables.c @@ -67,7 +67,8 @@ grub_machine_efiemu_init_tables (void) if (ptr < (grub_uint8_t *) 0x100000) { grub_dprintf ("efiemu", "Registering SMBIOS\n"); - if ((err = grub_efiemu_register_configuration_table (smbios, 0, 0, ptr))) + err = grub_efiemu_register_configuration_table (smbios, 0, 0, ptr); + if (err) return err; } diff --git a/grub-core/efiemu/loadcore.c b/grub-core/efiemu/loadcore.c index edadd4580..6968b3719 100644 --- a/grub-core/efiemu/loadcore.c +++ b/grub-core/efiemu/loadcore.c @@ -23,6 +23,7 @@ #include #include #include +#include /* ELF symbols and their values */ static struct grub_efiemu_elf_sym *grub_efiemu_elfsyms = 0; @@ -119,9 +120,9 @@ grub_efiemu_get_string (unsigned offset, const Elf_Ehdr *e) unsigned i; Elf_Shdr *s; - for (i = 0, s = (Elf_Shdr *)((char *) e + e->e_shoff); + for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); i < e->e_shnum; - i++, s = (Elf_Shdr *)((char *) s + e->e_shentsize)) + i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) if (s->sh_type == SHT_STRTAB && offset < s->sh_size) return (char *) e + s->sh_offset + offset; return 0; @@ -134,9 +135,9 @@ grub_efiemu_init_segments (grub_efiemu_segment_t *segs, const Elf_Ehdr *e) unsigned i; Elf_Shdr *s; - for (i = 0, s = (Elf_Shdr *)((char *) e + e->e_shoff); + for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); i < e->e_shnum; - i++, s = (Elf_Shdr *)((char *) s + e->e_shentsize)) + i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) { if (s->sh_flags & SHF_ALLOC) { @@ -193,7 +194,7 @@ grub_efiemu_count_symbols (const Elf_Ehdr *e) break; if (i == e->e_shnum) - return grub_error (GRUB_ERR_BAD_OS, "no symbol table"); + return grub_error (GRUB_ERR_BAD_OS, N_("no symbol table")); grub_efiemu_nelfsyms = (unsigned) s->sh_size / (unsigned) s->sh_entsize; grub_efiemu_elfsyms = (struct grub_efiemu_elf_sym *) @@ -230,7 +231,7 @@ grub_efiemu_resolve_symbols (grub_efiemu_segment_t segs, Elf_Ehdr *e) break; if (i == e->e_shnum) - return grub_error (GRUB_ERR_BAD_OS, "no symbol table"); + return grub_error (GRUB_ERR_BAD_OS, N_("no symbol table")); sym = (Elf_Sym *) ((char *) e + s->sh_offset); size = s->sh_size; @@ -256,7 +257,8 @@ grub_efiemu_resolve_symbols (grub_efiemu_segment_t segs, Elf_Ehdr *e) /* Resolve a global symbol. */ if (sym->st_name != 0 && sym->st_shndx == 0) { - if ((err = grub_efiemu_resolve_symbol (name, &handle, &off))) + err = grub_efiemu_resolve_symbol (name, &handle, &off); + if (err) return err; grub_efiemu_elfsyms[i].handle = handle; grub_efiemu_elfsyms[i].off = off; @@ -266,34 +268,43 @@ grub_efiemu_resolve_symbols (grub_efiemu_segment_t segs, Elf_Ehdr *e) break; case STT_OBJECT: - if ((err = grub_efiemu_get_section_addr - (segs, sym->st_shndx, &handle, &off))) + err = grub_efiemu_get_section_addr (segs, sym->st_shndx, + &handle, &off); + if (err) return err; off += sym->st_value; if (bind != STB_LOCAL) - if ((err = grub_efiemu_register_symbol (name, handle, off))) - return err; + { + err = grub_efiemu_register_symbol (name, handle, off); + if (err) + return err; + } grub_efiemu_elfsyms[i].handle = handle; grub_efiemu_elfsyms[i].off = off; break; case STT_FUNC: - if ((err = grub_efiemu_get_section_addr - (segs, sym->st_shndx, &handle, &off))) + err = grub_efiemu_get_section_addr (segs, sym->st_shndx, + &handle, &off); + if (err) return err; off += sym->st_value; if (bind != STB_LOCAL) - if ((err = grub_efiemu_register_symbol (name, handle, off))) - return err; + { + err = grub_efiemu_register_symbol (name, handle, off); + if (err) + return err; + } grub_efiemu_elfsyms[i].handle = handle; grub_efiemu_elfsyms[i].off = off; break; case STT_SECTION: - if ((err = grub_efiemu_get_section_addr - (segs, sym->st_shndx, &handle, &off))) + err = grub_efiemu_get_section_addr (segs, sym->st_shndx, + &handle, &off); + if (err) { grub_efiemu_elfsyms[i].handle = 0; grub_efiemu_elfsyms[i].off = 0; @@ -321,22 +332,26 @@ grub_efiemu_resolve_symbols (grub_efiemu_segment_t segs, Elf_Ehdr *e) /* Load runtime to the memory and request memory for definitive location*/ grub_err_t -SUFFIX (grub_efiemu_loadcore_init) (void *core, grub_size_t core_size, +SUFFIX (grub_efiemu_loadcore_init) (void *core, const char *filename, + grub_size_t core_size, grub_efiemu_segment_t *segments) { Elf_Ehdr *e = (Elf_Ehdr *) core; grub_err_t err; if (e->e_type != ET_REL) - return grub_error (GRUB_ERR_BAD_MODULE, "invalid ELF file type"); + return grub_error (GRUB_ERR_BAD_MODULE, N_("this ELF file is not of the right type")); /* Make sure that every section is within the core. */ if ((grub_size_t) core_size < e->e_shoff + e->e_shentsize * e->e_shnum) - return grub_error (GRUB_ERR_BAD_OS, "ELF sections outside core"); + return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); - if ((err = grub_efiemu_init_segments (segments, core))) + err = grub_efiemu_init_segments (segments, core); + if (err) return err; - if ((err = grub_efiemu_count_symbols (core))) + err = grub_efiemu_count_symbols (core); + if (err) return err; grub_efiemu_request_symbols (1); diff --git a/grub-core/efiemu/loadcore_common.c b/grub-core/efiemu/loadcore_common.c index a4db0ee9b..64d79608f 100644 --- a/grub-core/efiemu/loadcore_common.c +++ b/grub-core/efiemu/loadcore_common.c @@ -111,7 +111,8 @@ grub_efiemu_loadcore_unload(void) /* Load runtime file and do some initial preparations */ grub_err_t -grub_efiemu_loadcore_init (grub_file_t file) +grub_efiemu_loadcore_init (grub_file_t file, + const char *filename) { grub_err_t err; @@ -140,8 +141,10 @@ grub_efiemu_loadcore_init (grub_file_t file) switch (grub_efiemu_mode) { case GRUB_EFIEMU32: - if ((err = grub_efiemu_loadcore_init32 (efiemu_core, efiemu_core_size, - &efiemu_segments))) + err = grub_efiemu_loadcore_init32 (efiemu_core, filename, + efiemu_core_size, + &efiemu_segments); + if (err) { grub_free (efiemu_core); efiemu_core = 0; @@ -151,8 +154,10 @@ grub_efiemu_loadcore_init (grub_file_t file) break; case GRUB_EFIEMU64: - if ((err = grub_efiemu_loadcore_init64 (efiemu_core, efiemu_core_size, - &efiemu_segments))) + err = grub_efiemu_loadcore_init64 (efiemu_core, filename, + efiemu_core_size, + &efiemu_segments); + if (err) { grub_free (efiemu_core); efiemu_core = 0; @@ -162,7 +167,7 @@ grub_efiemu_loadcore_init (grub_file_t file) break; default: - return grub_error (GRUB_ERR_BAD_OS, "unknown EFI runtime"); + return grub_error (GRUB_ERR_BUG, "unknown EFI runtime"); } return GRUB_ERR_NONE; } @@ -174,16 +179,18 @@ grub_efiemu_loadcore_load (void) switch (grub_efiemu_mode) { case GRUB_EFIEMU32: - if ((err = grub_efiemu_loadcore_load32 (efiemu_core, efiemu_core_size, - efiemu_segments))) - grub_efiemu_loadcore_unload (); + err = grub_efiemu_loadcore_load32 (efiemu_core, efiemu_core_size, + efiemu_segments); + if (err) + grub_efiemu_loadcore_unload (); return err; case GRUB_EFIEMU64: - if ((err = grub_efiemu_loadcore_load64 (efiemu_core, efiemu_core_size, - efiemu_segments))) - grub_efiemu_loadcore_unload (); + err = grub_efiemu_loadcore_load64 (efiemu_core, efiemu_core_size, + efiemu_segments); + if (err) + grub_efiemu_loadcore_unload (); return err; default: - return grub_error (GRUB_ERR_BAD_OS, "unknown EFI runtime"); + return grub_error (GRUB_ERR_BUG, "unknown EFI runtime"); } } diff --git a/grub-core/efiemu/main.c b/grub-core/efiemu/main.c index 126ecf9e7..f2140ad29 100644 --- a/grub-core/efiemu/main.c +++ b/grub-core/efiemu/main.c @@ -121,11 +121,9 @@ grub_efiemu_register_prepare_hook (grub_err_t (*hook) (void *data), void *data) { struct grub_efiemu_prepare_hook *nhook; - if (! hook) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "you must supply the hook"); nhook = (struct grub_efiemu_prepare_hook *) grub_malloc (sizeof (*nhook)); if (! nhook) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't prepare hook"); + return grub_errno; nhook->hook = hook; nhook->unload = unload; nhook->data = data; @@ -146,16 +144,13 @@ grub_efiemu_register_configuration_table (grub_efi_guid_t guid, struct grub_efiemu_configuration_table *tbl; grub_err_t err; - if (! get_table && ! data) - return grub_error (GRUB_ERR_BAD_ARGUMENT, - "you must set at least get_table or data"); err = grub_efiemu_unregister_configuration_table (guid); if (err) return err; tbl = (struct grub_efiemu_configuration_table *) grub_malloc (sizeof (*tbl)); if (! tbl) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't register table"); + return grub_errno; tbl->guid = guid; tbl->get_table = get_table; @@ -201,12 +196,12 @@ grub_efiemu_load_file (const char *filename) { grub_file_close (file); grub_efiemu_unload (); - return grub_error (grub_errno, "couldn't init memory management"); + return grub_errno; } grub_dprintf ("efiemu", "mm initialized\n"); - err = grub_efiemu_loadcore_init (file); + err = grub_efiemu_loadcore_init (file, filename); if (err) { grub_file_close (file); @@ -227,7 +222,7 @@ grub_efiemu_autocore (void) { const char *prefix; char *filename; - char *suffix; + const char *suffix; grub_err_t err; if (grub_efiemu_sizeof_uintn_t () != 0) @@ -237,16 +232,14 @@ grub_efiemu_autocore (void) if (! prefix) return grub_error (GRUB_ERR_FILE_NOT_FOUND, - "couldn't find efiemu core because prefix " - "isn't set"); + N_("variable `%s' isn't set"), "prefix"); suffix = grub_efiemu_get_default_core_name (); - filename = grub_xasprintf ("%s/%s", prefix, suffix); + filename = grub_xasprintf ("%s/" GRUB_TARGET_CPU "-" GRUB_PLATFORM "/%s", + prefix, suffix); if (! filename) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, - "couldn't allocate temporary space"); - + return grub_errno; err = grub_efiemu_load_file (filename); grub_free (filename); @@ -297,7 +290,7 @@ grub_cmd_efiemu_load (grub_command_t cmd __attribute__ ((unused)), grub_efiemu_unload (); if (argc != 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "filename required"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); err = grub_efiemu_load_file (args[0]); if (err) diff --git a/grub-core/efiemu/mm.c b/grub-core/efiemu/mm.c index 7bb7cc080..10cbc68cc 100644 --- a/grub-core/efiemu/mm.c +++ b/grub-core/efiemu/mm.c @@ -62,12 +62,17 @@ grub_efiemu_add_to_mmap (grub_uint64_t start, grub_uint64_t size, /* Extend map if necessary*/ if (mmap_num >= mmap_reserved_size) { + void *old; + mmap_reserved_size = 2 * (mmap_reserved_size + 1); + old = efiemu_mmap; efiemu_mmap = (grub_efi_memory_descriptor_t *) - grub_realloc (efiemu_mmap, (++mmap_reserved_size) + grub_realloc (efiemu_mmap, mmap_reserved_size * sizeof (grub_efi_memory_descriptor_t)); if (!efiemu_mmap) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, - "not enough space for memory map"); + { + grub_free (old); + return grub_errno; + } } /* Fill slot*/ @@ -176,8 +181,7 @@ efiemu_alloc_requests (void) /* Allocate the whole memory in one block */ resident_memory = grub_memalign (GRUB_EFIEMU_PAGESIZE, total_alloc); if (!resident_memory) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, - "couldn't allocate resident memory"); + return grub_errno; /* Split the memory into blocks by type */ curptr = resident_memory; @@ -201,10 +205,10 @@ efiemu_alloc_requests (void) - (requested_memory[reqorder[i]] % GRUB_EFIEMU_PAGESIZE); if (align_overhead == GRUB_EFIEMU_PAGESIZE) align_overhead = 0; - curptr = ((grub_uint8_t *)curptr) + align_overhead; + curptr = ((grub_uint8_t *) curptr) + align_overhead; /* Add the region to memory map */ - grub_efiemu_add_to_mmap (PTR_TO_UINT64 (typestart), + grub_efiemu_add_to_mmap ((grub_addr_t) typestart, curptr - typestart, reqorder[i]); } @@ -540,8 +544,7 @@ grub_efiemu_mmap_sort_and_uniq (void) { grub_free (result); grub_free (scanline_events); - return grub_error (GRUB_ERR_OUT_OF_MEMORY, - "couldn't allocate space for new memory map"); + return grub_errno; } /* Register scanline events */ @@ -642,12 +645,14 @@ grub_efiemu_mm_do_alloc (void) if (!efiemu_mmap) { grub_efiemu_unload (); - return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't initialize mmap"); + return grub_errno; } - if ((err = efiemu_alloc_requests ())) + err = efiemu_alloc_requests (); + if (err) return err; - if ((err = grub_efiemu_mmap_fill ())) + err = grub_efiemu_mmap_fill (); + if (err) return err; return grub_efiemu_mmap_sort_and_uniq (); } diff --git a/grub-core/efiemu/pnvram.c b/grub-core/efiemu/pnvram.c index e58fce84e..28d005044 100644 --- a/grub-core/efiemu/pnvram.c +++ b/grub-core/efiemu/pnvram.c @@ -171,12 +171,6 @@ nvram_set (void * data __attribute__ ((unused))) (nvramsize - (nvramptr - nvram)) / 2, (grub_uint8_t *) varname, len, NULL); - if (len < 0) - { - grub_error (GRUB_ERR_BAD_ARGUMENT, "broken UTF-8 in variable name"); - return 1; - } - nvramptr += 2 * len; *((grub_uint16_t *) nvramptr) = 0; nvramptr += 2; diff --git a/grub-core/efiemu/prepare.c b/grub-core/efiemu/prepare.c index 171e092c9..5c3146490 100644 --- a/grub-core/efiemu/prepare.c +++ b/grub-core/efiemu/prepare.c @@ -97,10 +97,9 @@ SUFFIX (grub_efiemu_prepare) (struct grub_efiemu_prepare_hook *prepare_hooks, grub_memcpy (&(conftables[i].vendor_guid), &(cur->guid), sizeof (cur->guid)); if (cur->get_table) - conftables[i].vendor_table - = PTR_TO_UINT64 (cur->get_table (cur->data)); + conftables[i].vendor_table = (grub_addr_t) cur->get_table (cur->data); else - conftables[i].vendor_table = PTR_TO_UINT64 (cur->data); + conftables[i].vendor_table = (grub_addr_t) cur->data; } err = SUFFIX (grub_efiemu_crc) (); diff --git a/grub-core/efiemu/runtime/efiemu.c b/grub-core/efiemu/runtime/efiemu.c index 73893414a..2c71fbed0 100644 --- a/grub-core/efiemu/runtime/efiemu.c +++ b/grub-core/efiemu/runtime/efiemu.c @@ -21,6 +21,12 @@ As it emulates only runtime serviceit isn't able to chainload EFI bootloader on non-EFI system (TODO) */ +#ifdef __i386__ +#include +#else +#include +#endif + #include #include #include @@ -369,16 +375,16 @@ grub_efi_status_t EFI_FUNC switch (cur_relloc->size) { case 8: - *((grub_uint64_t *) UINT_TO_PTR (cur_relloc->addr)) += corr; + *((grub_uint64_t *) (grub_addr_t) cur_relloc->addr) += corr; break; case 4: - *((grub_uint32_t *) UINT_TO_PTR (cur_relloc->addr)) += corr; + *((grub_uint32_t *) (grub_addr_t) cur_relloc->addr) += corr; break; case 2: - *((grub_uint16_t *) UINT_TO_PTR (cur_relloc->addr)) += corr; + *((grub_uint16_t *) (grub_addr_t) cur_relloc->addr) += corr; break; case 1: - *((grub_uint8_t *) UINT_TO_PTR (cur_relloc->addr)) += corr; + *((grub_uint8_t *) (grub_addr_t) cur_relloc->addr) += corr; break; } } diff --git a/grub-core/efiemu/symbols.c b/grub-core/efiemu/symbols.c index 4fc546b59..cc148552d 100644 --- a/grub-core/efiemu/symbols.c +++ b/grub-core/efiemu/symbols.c @@ -22,6 +22,7 @@ #include #include #include +#include static int ptv_written = 0; static int ptv_alloc = 0; @@ -69,7 +70,7 @@ grub_efiemu_request_symbols (int num) return grub_error (GRUB_ERR_BAD_ARGUMENT, "symbols have already been allocated"); if (num < 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, + return grub_error (GRUB_ERR_BUG, "can't request negative symbols"); ptv_requested += num; return GRUB_ERR_NONE; @@ -88,7 +89,7 @@ grub_efiemu_resolve_symbol (const char *name, int *handle, grub_off_t *off) return GRUB_ERR_NONE; } grub_dprintf ("efiemu", "%s not found\n", name); - return grub_error (GRUB_ERR_BAD_OS, "symbol %s isn't found", name); + return grub_error (GRUB_ERR_BAD_OS, N_("symbol `%s' not found"), name); } /* Register symbol named NAME in memory handle HANDLE at offset OFF */ @@ -99,7 +100,7 @@ grub_efiemu_register_symbol (const char *name, int handle, grub_off_t off) cur = (struct grub_efiemu_sym *) grub_malloc (sizeof (*cur)); grub_dprintf ("efiemu", "registering symbol '%s'\n", name); if (!cur) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't register symbol"); + return grub_errno; cur->name = grub_strdup (name); cur->next = efiemu_syms; cur->handle = handle; @@ -153,7 +154,7 @@ grub_efiemu_write_value (void *addr, grub_uint32_t value, int plus_handle, = grub_efiemu_mm_obtain_request (ptv_handle); if (ptv_needed && ptv_written >= ptv_alloc) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, + return grub_error (GRUB_ERR_BUG, "your module didn't declare efiemu " " relocators correctly"); @@ -169,7 +170,7 @@ grub_efiemu_write_value (void *addr, grub_uint32_t value, int plus_handle, else ptv_rels[ptv_written].plustype = 0; - ptv_rels[ptv_written].addr = PTR_TO_UINT64 (addr); + ptv_rels[ptv_written].addr = (grub_addr_t) addr; ptv_rels[ptv_written].size = size; ptv_written++; @@ -179,10 +180,10 @@ grub_efiemu_write_value (void *addr, grub_uint32_t value, int plus_handle, /* Compute the value */ if (minus_handle) - value -= PTR_TO_UINT32 (grub_efiemu_mm_obtain_request (minus_handle)); + value -= (grub_addr_t) grub_efiemu_mm_obtain_request (minus_handle); if (plus_handle) - value += PTR_TO_UINT32 (grub_efiemu_mm_obtain_request (plus_handle)); + value += (grub_addr_t) grub_efiemu_mm_obtain_request (plus_handle); /* Write the value */ switch (size) @@ -200,7 +201,7 @@ grub_efiemu_write_value (void *addr, grub_uint32_t value, int plus_handle, *((grub_uint8_t *) addr) = value; break; default: - return grub_error (GRUB_ERR_BAD_ARGUMENT, "wrong symbol size"); + return grub_error (GRUB_ERR_BUG, "wrong symbol size"); } return GRUB_ERR_NONE; @@ -222,7 +223,7 @@ grub_efiemu_set_virtual_address_map (grub_efi_uintn_t memory_map_size, /* Ensure that we are called only once */ if (*ptv_relocated) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "EfiEmu is already relocated"); + return grub_error (GRUB_ERR_BUG, "EfiEmu is already relocated"); *ptv_relocated = 1; /* Correct addresses using information supplied by grub */ @@ -248,16 +249,16 @@ grub_efiemu_set_virtual_address_map (grub_efi_uintn_t memory_map_size, switch (cur_relloc->size) { case 8: - *((grub_uint64_t *) UINT_TO_PTR (cur_relloc->addr)) += corr; + *((grub_uint64_t *) (grub_addr_t) cur_relloc->addr) += corr; break; case 4: - *((grub_uint32_t *) UINT_TO_PTR (cur_relloc->addr)) += corr; + *((grub_uint32_t *) (grub_addr_t) cur_relloc->addr) += corr; break; case 2: - *((grub_uint16_t *) UINT_TO_PTR (cur_relloc->addr)) += corr; + *((grub_uint16_t *) (grub_addr_t) cur_relloc->addr) += corr; break; case 1: - *((grub_uint8_t *) UINT_TO_PTR (cur_relloc->addr)) += corr; + *((grub_uint8_t *) (grub_addr_t) cur_relloc->addr) += corr; break; } } diff --git a/grub-core/font/font.c b/grub-core/font/font.c index 3737480cf..e0597ea45 100644 --- a/grub-core/font/font.c +++ b/grub-core/font/font.c @@ -192,7 +192,8 @@ grub_font_loader_init (void) /* Initialize the null font. */ font_init (&null_font); - null_font.name = ""; + /* FIXME: Fix this slightly improper cast. */ + null_font.name = (char *) ""; null_font.ascent = unknown_glyph->height - 3; null_font.descent = 3; null_font.max_char_width = unknown_glyph->width; @@ -250,8 +251,7 @@ open_section (grub_file_t file, struct font_file_section *section) } else if (retval < 0) { - grub_error (GRUB_ERR_BAD_FONT, - "font format error: can't read section name"); + /* Read error. */ return 1; } @@ -265,8 +265,7 @@ open_section (grub_file_t file, struct font_file_section *section) } else if (retval < 0) { - grub_error (GRUB_ERR_BAD_FONT, - "font format error: can't read section length"); + /* Read error. */ return 1; } diff --git a/grub-core/font/font_cmd.c b/grub-core/font/font_cmd.c index b38eccd6d..b010a0c15 100644 --- a/grub-core/font/font_cmd.c +++ b/grub-core/font/font_cmd.c @@ -29,7 +29,7 @@ loadfont_command (grub_command_t cmd __attribute__ ((unused)), char **args) { if (argc == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "no font specified"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); while (argc--) if (grub_font_load (*args++) != 0) diff --git a/grub-core/fs/affs.c b/grub-core/fs/affs.c index 06f41c4c3..7c7813729 100644 --- a/grub-core/fs/affs.c +++ b/grub-core/fs/affs.c @@ -25,6 +25,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -32,11 +33,15 @@ GRUB_MOD_LICENSE ("GPLv3+"); struct grub_affs_bblock { grub_uint8_t type[3]; - grub_uint8_t version; + grub_uint8_t flags; grub_uint32_t checksum; grub_uint32_t rootblock; } __attribute__ ((packed)); +/* Set if the filesystem is a AFFS filesystem. Otherwise this is an + OFS filesystem. */ +#define GRUB_AFFS_FLAG_FFS 1 + /* The affs rootblock. */ struct grub_affs_rblock { @@ -191,7 +196,7 @@ grub_affs_mount (grub_disk_t disk) } /* Test if the filesystem is a OFS filesystem. */ - if (data->bblock.version < 1) + if (! (data->bblock.flags & GRUB_AFFS_FLAG_FFS)) { grub_error (GRUB_ERR_BAD_FS, "OFS not yet supported"); goto fail; @@ -292,15 +297,16 @@ 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 (const char *name, - grub_uint32_t block, + 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 (const char *name, - grub_uint32_t block, + 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; + node = grub_zalloc (sizeof (*node)); if (!node) { @@ -322,7 +328,12 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, node->di = *fil; node->parent = dir; - if (hook (name, type, node)) + len = fil->namelen; + if (len > sizeof (fil->name)) + len = sizeof (fil->name); + *grub_latin1_to_utf8 (name_u8, fil->name, len) = '\0'; + + if (hook ((char *) name_u8, type, node)) { grub_free (hashtable); return 1; @@ -377,9 +388,7 @@ grub_affs_iterate_dir (grub_fshelp_node_t dir, if (grub_errno) goto fail; - file.name[file.namelen] = '\0'; - - if (grub_affs_create_node ((char *) (file.name), next, &file)) + if (grub_affs_create_node (next, &file)) return 1; next = grub_be_to_cpu32 (file.next); @@ -524,6 +533,7 @@ grub_affs_label (grub_device_t device, char **label) data = grub_affs_mount (disk); if (data) { + grub_size_t len; /* The rootblock maps quite well on a file header block, it's something we can use here. */ grub_disk_read (data->disk, grub_be_to_cpu32 (data->bblock.rootblock), @@ -533,7 +543,12 @@ grub_affs_label (grub_device_t device, char **label) if (grub_errno) return 0; - *label = grub_strndup ((char *) (file.name), file.namelen); + len = file.namelen; + if (len > sizeof (file.name)) + len = sizeof (file.name); + *label = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1); + if (*label) + *grub_latin1_to_utf8 ((grub_uint8_t *) *label, file.name, len) = '\0'; } else *label = 0; diff --git a/grub-core/fs/bfs.c b/grub-core/fs/bfs.c index fe8f991c4..095764ffe 100644 --- a/grub-core/fs/bfs.c +++ b/grub-core/fs/bfs.c @@ -28,6 +28,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -215,7 +216,7 @@ read_bfs_file (grub_disk_t disk, if (off + len > grub_bfs_to_cpu64 (ino->size)) return grub_error (GRUB_ERR_OUT_OF_RANGE, - "attempt to read past the end of file"); + N_("attempt to read past the end of file")); if (off < (grub_bfs_to_cpu64 (ino->max_direct_range) << RANGE_SHIFT)) { @@ -529,7 +530,7 @@ find_in_b_tree (grub_disk_t disk, if (err) return err; if (node.count_keys == 0) - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", + 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]; @@ -600,7 +601,7 @@ find_in_b_tree (grub_disk_t disk, level--; continue; } - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", + return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), name); } } @@ -615,7 +616,7 @@ hop_level (grub_disk_t disk, grub_uint64_t res; if (((grub_bfs_to_cpu32 (ino->mode) & ATTR_TYPE) != ATTR_DIR)) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); err = find_in_b_tree (disk, sb, ino, name, &res); if (err) @@ -677,7 +678,7 @@ find_file (const char *path, grub_disk_t disk, { grub_free (alloc); return grub_error (GRUB_ERR_SYMLINK_LOOP, - "too deep nesting of symlinks"); + N_("too deep nesting of symlinks")); } #ifndef MODE_AFS @@ -829,7 +830,7 @@ grub_bfs_dir (grub_device_t device, const char *path, if (err) return err; if (((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) != ATTR_DIR)) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); iterate_in_b_tree (device->disk, &sb, &ino.ino, hook); } @@ -857,7 +858,7 @@ grub_bfs_open (struct grub_file *file, const char *name) if (err) return err; if (((grub_bfs_to_cpu32 (ino.ino.mode) & ATTR_TYPE) != ATTR_REG)) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a regular file"); + 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)); diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c index db251ffd7..654abc75b 100644 --- a/grub-core/fs/btrfs.c +++ b/grub-core/fs/btrfs.c @@ -27,6 +27,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -49,7 +50,8 @@ typedef grub_uint16_t grub_btrfs_uuid_t[8]; struct grub_btrfs_device { grub_uint64_t device_id; - grub_uint8_t dummy[0x62 - 8]; + grub_uint64_t size; + grub_uint8_t dummy[0x62 - 0x10]; } __attribute__ ((packed)); struct grub_btrfs_superblock @@ -248,6 +250,10 @@ read_sblock (grub_disk_t disk, struct grub_btrfs_superblock *sb) for (i = 0; i < ARRAY_SIZE (superblock_sectors); i++) { struct grub_btrfs_superblock sblock; + /* Don't try additional superblocks beyond device size. */ + if (i && (grub_le_to_cpu64 (sblock.this_device.size) + >> GRUB_DISK_SECTOR_BITS) <= superblock_sectors[i]) + break; err = grub_disk_read (disk, superblock_sectors[i], 0, sizeof (sblock), &sblock); if (err == GRUB_ERR_OUT_OF_RANGE) @@ -568,7 +574,9 @@ find_device (struct grub_btrfs_data *data, grub_uint64_t id, int do_rescan) grub_device_iterate (hook); if (!dev_found) { - grub_error (GRUB_ERR_BAD_FS, "couldn't find a member device"); + grub_error (GRUB_ERR_BAD_FS, + N_("couldn't find a necesssary member device " + "of multi-device filesystem")); return NULL; } data->n_devices_attached++; @@ -928,13 +936,17 @@ grub_btrfs_lzo_decompress(char *ibuf, grub_size_t isize, grub_off_t off, /* Block partially filled with requested data. */ if (off > 0 || osize < GRUB_BTRFS_LZO_BLOCK_SIZE) { - grub_size_t to_copy = grub_min(osize, GRUB_BTRFS_LZO_BLOCK_SIZE - off); + grub_size_t to_copy = GRUB_BTRFS_LZO_BLOCK_SIZE - off; + + if (to_copy > osize) + to_copy = osize; if (lzo1x_decompress_safe ((lzo_bytep)ibuf, cblock_size, buf, &usize, NULL) != LZO_E_OK) return -1; - to_copy = grub_min(to_copy, usize); + if (to_copy > usize) + to_copy = usize; grub_memcpy(obuf, buf + off, to_copy); osize -= to_copy; @@ -1195,7 +1207,7 @@ find_path (struct grub_btrfs_data *data, { grub_free (path_alloc); grub_free (origpath); - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); } key->type = GRUB_BTRFS_ITEM_TYPE_DIR_ITEM; @@ -1214,7 +1226,7 @@ find_path (struct grub_btrfs_data *data, { grub_free (direl); grub_free (path_alloc); - err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", origpath); + err = grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), origpath); grub_free (origpath); return err; } @@ -1258,7 +1270,7 @@ find_path (struct grub_btrfs_data *data, { grub_free (direl); grub_free (path_alloc); - err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", origpath); + err = grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), origpath); grub_free (origpath); return err; } @@ -1276,7 +1288,7 @@ find_path (struct grub_btrfs_data *data, grub_free (path_alloc); grub_free (origpath); return grub_error (GRUB_ERR_SYMLINK_LOOP, - "too deep nesting of symlinks"); + N_("too deep nesting of symlinks")); } err = grub_btrfs_read_inode (data, &inode, @@ -1346,7 +1358,7 @@ find_path (struct grub_btrfs_data *data, { grub_free (direl); grub_free (path_alloc); - err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", origpath); + err = grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), origpath); grub_free (origpath); return err; } @@ -1369,7 +1381,7 @@ find_path (struct grub_btrfs_data *data, { grub_free (direl); grub_free (path_alloc); - err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", origpath); + err = grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), origpath); grub_free (origpath); return err; } @@ -1421,7 +1433,7 @@ grub_btrfs_dir (grub_device_t device, const char *path, if (type != GRUB_BTRFS_DIR_ITEM_TYPE_DIRECTORY) { grub_btrfs_unmount (data); - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); } err = lower_bound (data, &key_in, &key_out, tree, &elemaddr, &elemsize, &desc); @@ -1526,7 +1538,7 @@ grub_btrfs_open (struct grub_file *file, const char *name) if (type != GRUB_BTRFS_DIR_ITEM_TYPE_REGULAR) { grub_btrfs_unmount (data); - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a regular file"); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file")); } data->inode = key_in.object_id; @@ -1619,8 +1631,8 @@ grub_btrfs_embed (grub_device_t device __attribute__ ((unused)), if (64 * 2 - 1 < *nsectors) return grub_error (GRUB_ERR_OUT_OF_RANGE, - "Your core.img is unusually large. " - "It won't fit in the embedding area."); + N_("your core.img is unusually large. " + "It won't fit in the embedding area")); *nsectors = 64 * 2 - 1; *sectors = grub_malloc (*nsectors * sizeof (**sectors)); diff --git a/grub-core/fs/cpio.c b/grub-core/fs/cpio.c index 39b35b335..1065df94a 100644 --- a/grub-core/fs/cpio.c +++ b/grub-core/fs/cpio.c @@ -22,6 +22,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -30,28 +31,69 @@ GRUB_MOD_LICENSE ("GPLv3+"); #define ATTR_DIR 0040000 #define ATTR_LNK 0120000 -#ifndef MODE_USTAR -/* cpio support */ -#define MAGIC_BCPIO 070707 +#ifdef MODE_ODC +#define ALIGN_CPIO(x) x +#define MAGIC "070707" struct head { - grub_uint16_t magic; + 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]; grub_uint16_t dev; grub_uint16_t ino; - grub_uint16_t mode; + 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_1; - grub_uint16_t mtime_2; - grub_uint16_t namesize; - grub_uint16_t filesize_1; - grub_uint16_t filesize_2; + grub_uint16_t mtime[2]; + grub_uint16_t namesize[1]; + grub_uint16_t filesize[2]; } __attribute__ ((packed)); #else /* tar support */ -#define MAGIC_USTAR "ustar" +#define MAGIC "ustar" struct head { char name[100]; @@ -108,6 +150,49 @@ canonicalize (char *name) *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, @@ -115,35 +200,40 @@ grub_cpio_find_file (struct grub_cpio_data *data, char **name, { #ifndef MODE_USTAR struct head hd; + grub_size_t namesize; + grub_uint32_t modeval; if (grub_disk_read (data->disk, 0, data->hofs, sizeof (hd), &hd)) return grub_errno; - if (hd.magic != MAGIC_BCPIO) + 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 = (((grub_uint32_t) hd.filesize_1) << 16) + hd.filesize_2; + data->size = read_number (hd.filesize, ARRAY_SIZE (hd.filesize)); if (mtime) - *mtime = (((grub_uint32_t) hd.mtime_1) << 16) + hd.mtime_2; + *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 = hd.mode; + *mode = modeval; - if (hd.namesize & 1) - hd.namesize++; - - *name = grub_malloc (hd.namesize + 1); + *name = grub_malloc (namesize + 1); if (*name == NULL) return grub_errno; if (grub_disk_read (data->disk, 0, data->hofs + sizeof (hd), - hd.namesize, *name)) + namesize, *name)) { grub_free (*name); return grub_errno; } - (*name)[hd.namesize] = 0; + (*name)[namesize] = 0; - if (data->size == 0 && hd.mode == 0 && hd.namesize == 11 + 1 + if (data->size == 0 && modeval == 0 && namesize == 11 && grub_memcmp(*name, "TRAILER!!!", 11) == 0) { *ofs = 0; @@ -153,10 +243,8 @@ grub_cpio_find_file (struct grub_cpio_data *data, char **name, canonicalize (*name); - data->dofs = data->hofs + sizeof (hd) + hd.namesize; - *ofs = data->dofs + data->size; - if (data->size & 1) - (*ofs)++; + 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; @@ -172,13 +260,13 @@ grub_cpio_find_file (struct grub_cpio_data *data, char **name, return GRUB_ERR_NONE; } - if (grub_memcmp (hd.magic, MAGIC_USTAR, sizeof (MAGIC_USTAR) - 1)) + 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 = grub_strtoull (hd.size, NULL, 8); + grub_size_t namesize = read_number (hd.size, sizeof (hd.size)); *name = grub_malloc (namesize + 1); if (*name == NULL) return grub_errno; @@ -198,7 +286,7 @@ grub_cpio_find_file (struct grub_cpio_data *data, char **name, if (hd.typeflag == 'K') { grub_err_t err; - grub_size_t linksize = grub_strtoull (hd.size, NULL, 8); + grub_size_t linksize = read_number (hd.size, sizeof (hd.size)); if (data->linkname_alloc < linksize + 1) { char *n; @@ -225,20 +313,20 @@ grub_cpio_find_file (struct grub_cpio_data *data, char **name, if (!have_longname) { - *name = grub_strdup (hd.name); + *name = grub_strndup (hd.name, sizeof (hd.name)); if (*name == NULL) return grub_errno; } - data->size = grub_strtoull (hd.size, NULL, 8); + 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 = grub_strtoul (hd.mtime, NULL, 8); + *mtime = read_number (hd.mtime, sizeof (hd.mtime)); if (mode) { - *mode = grub_strtoul (hd.mode, NULL, 8); + *mode = read_number (hd.mode, sizeof (hd.mode)); switch (hd.typeflag) { case '2': @@ -284,12 +372,11 @@ grub_cpio_mount (grub_disk_t disk) if (grub_disk_read (disk, 0, 0, sizeof (hd), &hd)) goto fail; -#ifndef MODE_USTAR - if (hd.magic != MAGIC_BCPIO) -#else - if (grub_memcmp (hd.magic, MAGIC_USTAR, - sizeof (MAGIC_USTAR) - 1)) + 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)); @@ -384,7 +471,7 @@ handle_symlink (struct grub_cpio_data *data, if (prefixlen) { grub_memcpy (target, *name, prefixlen); - target[prefixlen] = '/'; + target[prefixlen-1] = '/'; } ptr = target + prefixlen + size; ptr = grub_stpcpy (ptr, rest); @@ -404,13 +491,15 @@ grub_cpio_dir (grub_device_t device, const char *path_in, { struct grub_cpio_data *data; grub_disk_addr_t ofs; - char *prev, *name, *path; + char *prev, *name, *path, *ptr; grub_size_t len; int symlinknest = 0; path = grub_strdup (path_in + 1); if (!path) return grub_errno; + for (ptr = path + grub_strlen (path) - 1; ptr >= path && *ptr == '/'; ptr--) + *ptr = 0; grub_dl_ref (my_mod); @@ -443,14 +532,14 @@ grub_cpio_dir (grub_device_t device, const char *path_in, char *p, *n; n = name + len; - if (*n == '/') + while (*n == '/') n++; - p = grub_strchr (name + len, '/'); + p = grub_strchr (n, '/'); if (p) *p = 0; - if (((!prev) || (grub_strcmp (prev, name) != 0)) && name[len] != 0) + if (((!prev) || (grub_strcmp (prev, name) != 0)) && *n != 0) { struct grub_dirhook_info info; grub_memset (&info, 0, sizeof (info)); @@ -458,13 +547,14 @@ grub_cpio_dir (grub_device_t device, const char *path_in, info.mtime = mtime; info.mtimeset = 1; - hook (name + len, &info); + if (hook (n, &info)) + goto fail; grub_free (prev); prev = name; } else { - int restart; + int restart = 0; err = handle_symlink (data, name, &path, mode, &restart); grub_free (name); if (err) @@ -475,7 +565,7 @@ grub_cpio_dir (grub_device_t device, const char *path_in, if (++symlinknest == 8) { grub_error (GRUB_ERR_SYMLINK_LOOP, - "too deep nesting of symlinks"); + N_("too deep nesting of symlinks")); goto fail; } ofs = 0; @@ -533,7 +623,7 @@ grub_cpio_open (grub_file_t file, const char *name_in) if (!ofs) { - grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), name_in); break; } @@ -549,7 +639,7 @@ grub_cpio_open (grub_file_t file, const char *name_in) if (++symlinknest == 8) { grub_error (GRUB_ERR_SYMLINK_LOOP, - "too deep nesting of symlinks"); + N_("too deep nesting of symlinks")); goto fail; } goto no_match; @@ -612,6 +702,10 @@ grub_cpio_close (grub_file_t file) 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 @@ -626,6 +720,12 @@ static struct grub_fs grub_cpio_fs = { #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 @@ -636,6 +736,12 @@ GRUB_MOD_INIT (cpio) #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 diff --git a/grub-core/fs/cpio_be.c b/grub-core/fs/cpio_be.c new file mode 100644 index 000000000..8bad314cd --- /dev/null +++ b/grub-core/fs/cpio_be.c @@ -0,0 +1,2 @@ +#define MODE_BIGENDIAN 1 +#include "cpio.c" diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c index 0fdf151a2..875f7b928 100644 --- a/grub-core/fs/ext2.c +++ b/grub-core/fs/ext2.c @@ -21,10 +21,6 @@ #define EXT2_MAGIC 0xEF53 /* Amount of indirect blocks in an inode. */ #define INDIRECT_BLOCKS 12 -/* Maximum length of a pathname. */ -#define EXT2_PATH_MAX 4096 -/* Maximum nesting of symlinks, used to prevent a loop. */ -#define EXT2_MAX_SYMLINKCNT 8 /* The good old revision and the default inode size. */ #define EXT2_GOOD_OLD_REVISION 0 @@ -337,7 +333,7 @@ grub_ext2_blockgroup (struct grub_ext2_data *data, int group, } static struct grub_ext4_extent_header * -grub_ext4_find_leaf (struct grub_ext2_data *data, char *buf, +grub_ext4_find_leaf (struct grub_ext2_data *data, grub_properly_aligned_t *buf, struct grub_ext4_extent_header *ext_block, grub_uint32_t fileblock) { @@ -387,7 +383,7 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) if (grub_le_to_cpu32(inode->flags) & EXT4_EXTENTS_FLAG) { - char buf[EXT2_BLOCK_SIZE(data)]; + GRUB_PROPERLY_ALIGNED_ARRAY (buf, EXT2_BLOCK_SIZE(data)); struct grub_ext4_extent_header *leaf; struct grub_ext4_extent *ext; int i; @@ -689,7 +685,7 @@ grub_ext2_iterate_dir (grub_fshelp_node_t dir, if (dirent.direntlen == 0) return 0; - if (dirent.namelen != 0) + if (dirent.inode != 0 && dirent.namelen != 0) { char filename[dirent.namelen + 1]; struct grub_fshelp_node *fdiro; @@ -896,7 +892,8 @@ grub_ext2_label (grub_device_t device, char **label) data = grub_ext2_mount (disk); if (data) - *label = grub_strndup (data->sblock.volume_name, 14); + *label = grub_strndup (data->sblock.volume_name, + sizeof (data->sblock.volume_name)); else *label = NULL; diff --git a/grub-core/fs/fat.c b/grub-core/fs/fat.c index 0d32e229d..a6c9760c6 100644 --- a/grub-core/fs/fat.c +++ b/grub-core/fs/fat.c @@ -27,6 +27,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -122,8 +123,7 @@ struct grub_fat_dir_entry } __attribute__ ((packed)) file_name; struct { grub_uint8_t character_count; - grub_uint16_t str[11]; - grub_uint8_t reserved[8]; + grub_uint16_t str[15]; } __attribute__ ((packed)) volume_label; } __attribute__ ((packed)) type_specific; } __attribute__ ((packed)); @@ -245,11 +245,6 @@ grub_fat_mount (grub_disk_t disk) if (grub_memcmp ((const char *) bpb.oem_name, "EXFAT ", sizeof (bpb.oem_name)) != 0) goto fail; -#else - if (grub_strncmp((const char *) bpb.version_specific.fat12_or_fat16.fstype, "FAT12", 5) - && grub_strncmp((const char *) bpb.version_specific.fat12_or_fat16.fstype, "FAT16", 5) - && grub_strncmp((const char *) bpb.version_specific.fat32.fstype, "FAT32", 5)) - goto fail; #endif /* Get the sizes of logical sectors and clusters. */ @@ -589,7 +584,7 @@ grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data, char *filename; unibuf = grub_malloc (15 * 256 * 2); - filename = grub_malloc (15 * 256 * 4 + 1); + filename = grub_malloc (15 * 256 * GRUB_MAX_UTF8_PER_UTF16 + 1); while (1) { @@ -693,10 +688,10 @@ grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data, grub_ssize_t offset = -sizeof(dir); if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY)) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); /* Allocate space enough to hold a long name. */ - filename = grub_malloc (0x40 * 13 * 4 + 1); + filename = grub_malloc (0x40 * 13 * GRUB_MAX_UTF8_PER_UTF16 + 1); unibuf = (grub_uint16_t *) grub_malloc (0x40 * 13 * 2); if (! filename || ! unibuf) { @@ -870,7 +865,7 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data, if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY)) { - grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); return 0; } @@ -902,7 +897,7 @@ grub_fat_find_dir (grub_disk_t disk, struct grub_fat_data *data, grub_fat_iterate_dir (disk, data, iter_hook); if (grub_errno == GRUB_ERR_NONE && ! found && !call_hook) - grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", origpath); + grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), origpath); fail: grub_free (dirname); @@ -978,7 +973,7 @@ grub_fat_open (grub_file_t file, const char *name) if (data->attr & GRUB_FAT_ATTR_DIRECTORY) { - grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a file"); + grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file")); goto fail; } @@ -1046,7 +1041,8 @@ grub_fat_label (grub_device_t device, char **label) if (dir.entry_type == 0x83) { grub_size_t chc; - *label = grub_malloc (11 * 4 + 1); + *label = grub_malloc (ARRAY_SIZE (dir.type_specific.volume_label.str) + * GRUB_MAX_UTF8_PER_UTF16 + 1); if (!*label) { grub_free (data); @@ -1091,7 +1087,7 @@ grub_fat_label (grub_device_t device, char **label) if (! (data->attr & GRUB_FAT_ATTR_DIRECTORY)) { - grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); return 0; } diff --git a/grub-core/fs/fshelp.c b/grub-core/fs/fshelp.c index 275cb9e1b..fa2c8bef5 100644 --- a/grub-core/fs/fshelp.c +++ b/grub-core/fs/fshelp.c @@ -23,6 +23,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -84,7 +85,7 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode, if (filetype == GRUB_FSHELP_UNKNOWN || (grub_strcmp (name, filename) && (! (filetype & GRUB_FSHELP_CASE_INSENSITIVE) || - grub_strncasecmp (name, filename, GRUB_LONG_MAX)))) + grub_strcasecmp (name, filename)))) { grub_free (node); return 0; @@ -128,7 +129,7 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode, if (type != GRUB_FSHELP_DIR) { free_node (currnode); - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); } /* Iterate over the directory. */ @@ -152,7 +153,7 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode, free_node (currnode); free_node (oldnode); return grub_error (GRUB_ERR_SYMLINK_LOOP, - "too deep nesting of symlinks"); + N_("too deep nesting of symlinks")); } symlink = read_symlink (currnode); @@ -196,12 +197,12 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode, name = next; } - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", path); + return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path); } if (!path || path[0] != '/') { - grub_error (GRUB_ERR_BAD_FILENAME, "bad filename"); + grub_error (GRUB_ERR_BAD_FILENAME, N_("invalid file name `%s'"), path); return grub_errno; } @@ -211,9 +212,9 @@ grub_fshelp_find_file (const char *path, grub_fshelp_node_t rootnode, /* Check if the node that was found was of the expected type. */ if (expecttype == GRUB_FSHELP_REG && foundtype != expecttype) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a regular file"); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file")); else if (expecttype == GRUB_FSHELP_DIR && foundtype != expecttype) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); return 0; } diff --git a/grub-core/fs/hfs.c b/grub-core/fs/hfs.c index 973a2d2ef..7a5947b23 100644 --- a/grub-core/fs/hfs.c +++ b/grub-core/fs/hfs.c @@ -28,6 +28,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -750,10 +751,7 @@ grub_hfs_find_node (struct grub_hfs_data *data, char *key, entry. In case of a non-leaf mode it will be used to lookup the rest of the tree. */ if (cmp <= 0) - { - grub_uint32_t *node = (grub_uint32_t *) rec->data; - found = grub_be_to_cpu32 (*node); - } + found = grub_be_to_cpu32 (grub_get_unaligned32 (rec->data)); else /* The key can not be found in the tree. */ return 1; @@ -817,7 +815,7 @@ grub_hfs_iterate_dir (struct grub_hfs_data *data, grub_uint32_t root_idx, struct grub_hfs_catalog_key *ckey = rec->key; if (grub_hfs_cmp_catkeys (rec->key, (void *) &key) <= 0) - found = grub_be_to_cpu32 (*(grub_uint32_t *) rec->data); + found = grub_be_to_cpu32 (grub_get_unaligned32 (rec->data)); if (hnd->type == 0xFF && ckey->strlen > 0) { @@ -865,6 +863,203 @@ grub_hfs_iterate_dir (struct grub_hfs_data *data, grub_uint32_t root_idx, return grub_errno; } +#define MAX_UTF8_PER_MAC_ROMAN 3 + +static const char macroman[0x80][MAX_UTF8_PER_MAC_ROMAN + 1] = + { + /* 80 */ "\xc3\x84", + /* 81 */ "\xc3\x85", + /* 82 */ "\xc3\x87", + /* 83 */ "\xc3\x89", + /* 84 */ "\xc3\x91", + /* 85 */ "\xc3\x96", + /* 86 */ "\xc3\x9c", + /* 87 */ "\xc3\xa1", + /* 88 */ "\xc3\xa0", + /* 89 */ "\xc3\xa2", + /* 8A */ "\xc3\xa4", + /* 8B */ "\xc3\xa3", + /* 8C */ "\xc3\xa5", + /* 8D */ "\xc3\xa7", + /* 8E */ "\xc3\xa9", + /* 8F */ "\xc3\xa8", + /* 90 */ "\xc3\xaa", + /* 91 */ "\xc3\xab", + /* 92 */ "\xc3\xad", + /* 93 */ "\xc3\xac", + /* 94 */ "\xc3\xae", + /* 95 */ "\xc3\xaf", + /* 96 */ "\xc3\xb1", + /* 97 */ "\xc3\xb3", + /* 98 */ "\xc3\xb2", + /* 99 */ "\xc3\xb4", + /* 9A */ "\xc3\xb6", + /* 9B */ "\xc3\xb5", + /* 9C */ "\xc3\xba", + /* 9D */ "\xc3\xb9", + /* 9E */ "\xc3\xbb", + /* 9F */ "\xc3\xbc", + /* A0 */ "\xe2\x80\xa0", + /* A1 */ "\xc2\xb0", + /* A2 */ "\xc2\xa2", + /* A3 */ "\xc2\xa3", + /* A4 */ "\xc2\xa7", + /* A5 */ "\xe2\x80\xa2", + /* A6 */ "\xc2\xb6", + /* A7 */ "\xc3\x9f", + /* A8 */ "\xc2\xae", + /* A9 */ "\xc2\xa9", + /* AA */ "\xe2\x84\xa2", + /* AB */ "\xc2\xb4", + /* AC */ "\xc2\xa8", + /* AD */ "\xe2\x89\xa0", + /* AE */ "\xc3\x86", + /* AF */ "\xc3\x98", + /* B0 */ "\xe2\x88\x9e", + /* B1 */ "\xc2\xb1", + /* B2 */ "\xe2\x89\xa4", + /* B3 */ "\xe2\x89\xa5", + /* B4 */ "\xc2\xa5", + /* B5 */ "\xc2\xb5", + /* B6 */ "\xe2\x88\x82", + /* B7 */ "\xe2\x88\x91", + /* B8 */ "\xe2\x88\x8f", + /* B9 */ "\xcf\x80", + /* BA */ "\xe2\x88\xab", + /* BB */ "\xc2\xaa", + /* BC */ "\xc2\xba", + /* BD */ "\xce\xa9", + /* BE */ "\xc3\xa6", + /* BF */ "\xc3\xb8", + /* C0 */ "\xc2\xbf", + /* C1 */ "\xc2\xa1", + /* C2 */ "\xc2\xac", + /* C3 */ "\xe2\x88\x9a", + /* C4 */ "\xc6\x92", + /* C5 */ "\xe2\x89\x88", + /* C6 */ "\xe2\x88\x86", + /* C7 */ "\xc2\xab", + /* C8 */ "\xc2\xbb", + /* C9 */ "\xe2\x80\xa6", + /* CA */ "\xc2\xa0", + /* CB */ "\xc3\x80", + /* CC */ "\xc3\x83", + /* CD */ "\xc3\x95", + /* CE */ "\xc5\x92", + /* CF */ "\xc5\x93", + /* D0 */ "\xe2\x80\x93", + /* D1 */ "\xe2\x80\x94", + /* D2 */ "\xe2\x80\x9c", + /* D3 */ "\xe2\x80\x9d", + /* D4 */ "\xe2\x80\x98", + /* D5 */ "\xe2\x80\x99", + /* D6 */ "\xc3\xb7", + /* D7 */ "\xe2\x97\x8a", + /* D8 */ "\xc3\xbf", + /* D9 */ "\xc5\xb8", + /* DA */ "\xe2\x81\x84", + /* DB */ "\xe2\x82\xac", + /* DC */ "\xe2\x80\xb9", + /* DD */ "\xe2\x80\xba", + /* DE */ "\xef\xac\x81", + /* DF */ "\xef\xac\x82", + /* E0 */ "\xe2\x80\xa1", + /* E1 */ "\xc2\xb7", + /* E2 */ "\xe2\x80\x9a", + /* E3 */ "\xe2\x80\x9e", + /* E4 */ "\xe2\x80\xb0", + /* E5 */ "\xc3\x82", + /* E6 */ "\xc3\x8a", + /* E7 */ "\xc3\x81", + /* E8 */ "\xc3\x8b", + /* E9 */ "\xc3\x88", + /* EA */ "\xc3\x8d", + /* EB */ "\xc3\x8e", + /* EC */ "\xc3\x8f", + /* ED */ "\xc3\x8c", + /* EE */ "\xc3\x93", + /* EF */ "\xc3\x94", + /* F0 */ "\xef\xa3\xbf", + /* F1 */ "\xc3\x92", + /* F2 */ "\xc3\x9a", + /* F3 */ "\xc3\x9b", + /* F4 */ "\xc3\x99", + /* F5 */ "\xc4\xb1", + /* F6 */ "\xcb\x86", + /* F7 */ "\xcb\x9c", + /* F8 */ "\xc2\xaf", + /* F9 */ "\xcb\x98", + /* FA */ "\xcb\x99", + /* FB */ "\xcb\x9a", + /* FC */ "\xc2\xb8", + /* FD */ "\xcb\x9d", + /* FE */ "\xcb\x9b", + /* FF */ "\xcb\x87", + }; + +static void +macroman_to_utf8 (char *to, const grub_uint8_t *from, grub_size_t len) +{ + char *optr = to; + const grub_uint8_t *iptr; + + for (iptr = from; iptr < from + len && *iptr; iptr++) + { + /* Translate '/' to ':' as per HFS spec. */ + if (*iptr == '/') + { + *optr++ = ':'; + continue; + } + if (!(*iptr & 0x80)) + { + *optr++ = *iptr; + continue; + } + optr = grub_stpcpy (optr, macroman[*iptr & 0x7f]); + } + *optr = 0; +} + +static grub_ssize_t +utf8_to_macroman (grub_uint8_t *to, const char *from) +{ + grub_uint8_t *end = to + 31; + grub_uint8_t *optr = to; + const char *iptr = from; + + while (*iptr && optr < end) + { + int i, clen; + /* Translate ':' to '/' as per HFS spec. */ + if (*iptr == ':') + { + *optr++ = '/'; + iptr++; + continue; + } + if (!(*iptr & 0x80)) + { + *optr++ = *iptr++; + continue; + } + clen = 2; + if ((*iptr & 0xf0) == 0xe0) + clen++; + for (i = 0; i < 0x80; i++) + if (grub_memcmp (macroman[i], iptr, clen) == 0) + break; + if (i == 0x80) + break; + *optr++ = i | 0x80; + iptr += clen; + } + /* Too long or not encodable. */ + if (*iptr) + return -1; + return optr - to; +} + /* Find a file or directory with the pathname PATH in the filesystem DATA. Return the file record in RETDATA when it is non-zero. @@ -885,7 +1080,7 @@ grub_hfs_find_dir (struct grub_hfs_data *data, const char *path, if (path[0] != '/') { - grub_error (GRUB_ERR_BAD_FILENAME, "bad filename"); + grub_error (GRUB_ERR_BAD_FILENAME, N_("invalid file name `%s'"), path); return 0; } @@ -899,9 +1094,10 @@ grub_hfs_find_dir (struct grub_hfs_data *data, const char *path, while (path && grub_strlen (path)) { + grub_ssize_t slen; if (fdrec.frec.type != GRUB_HFS_FILETYPE_DIR) { - grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); goto fail; } @@ -916,14 +1112,19 @@ grub_hfs_find_dir (struct grub_hfs_data *data, const char *path, struct grub_hfs_catalog_key key; key.parent_dir = grub_cpu_to_be32 (inode); - key.strlen = grub_strlen (path); - grub_strcpy ((char *) (key.str), path); + slen = utf8_to_macroman (key.str, path); + if (slen < 0) + { + grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path); + goto fail; + } + key.strlen = slen; /* Lookup this node. */ if (! grub_hfs_find_node (data, (char *) &key, data->cat_root, 0, (char *) &fdrec.frec, sizeof (fdrec.frec))) { - grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", origpath); + grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), origpath); goto fail; } @@ -958,14 +1159,21 @@ grub_hfs_dir (grub_device_t device, const char *path, int dir_hook (struct grub_hfs_record *rec) { - char fname[32] = { 0 }; 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] = { 0 }; struct grub_dirhook_info info; + grub_size_t len; + grub_memset (&info, 0, sizeof (info)); - grub_strncpy (fname, (char *) (ckey->str), ckey->strlen); + len = ckey->strlen; + if (len > sizeof (ckey->str)) + len = sizeof (ckey->str); + macroman_to_utf8 (fname, ckey->str, len); + + info.case_insensitive = 1; if (drec->type == GRUB_HFS_FILETYPE_DIR) { @@ -1000,7 +1208,7 @@ grub_hfs_dir (grub_device_t device, const char *path, if (frec.type != GRUB_HFS_FILETYPE_DIR) { - grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); goto fail; } @@ -1036,7 +1244,7 @@ grub_hfs_open (struct grub_file *file, const char *name) if (frec.type != GRUB_HFS_FILETYPE_FILE) { grub_free (data); - grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a file"); + grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file")); grub_dl_unref (my_mod); return grub_errno; } @@ -1081,8 +1289,15 @@ grub_hfs_label (grub_device_t device, char **label) data = grub_hfs_mount (device->disk); if (data) - *label = grub_strndup ((char *) (data->sblock.volname + 1), - *data->sblock.volname); + { + grub_size_t len = data->sblock.volname[0]; + if (len > sizeof (data->sblock.volname) - 1) + len = sizeof (data->sblock.volname) - 1; + *label = grub_malloc (len * MAX_UTF8_PER_MAC_ROMAN + 1); + if (*label) + macroman_to_utf8 (*label, data->sblock.volname + 1, + len + 1); + } else *label = 0; diff --git a/grub-core/fs/hfsplus.c b/grub-core/fs/hfsplus.c index 3d9bc42fa..b20f9f3bb 100644 --- a/grub-core/fs/hfsplus.c +++ b/grub-core/fs/hfsplus.c @@ -181,7 +181,8 @@ enum grub_hfsplus_filetype struct grub_hfsplus_catkey_internal { grub_uint32_t parent; - char *name; + const grub_uint16_t *name; + grub_size_t namelen; }; /* Internal representation of an extent overflow key. */ @@ -250,10 +251,9 @@ grub_hfsplus_btree_recoffset (struct grub_hfsplus_btree *btree, struct grub_hfsplus_btnode *node, int index) { char *cnode = (char *) node; - grub_uint16_t *recptr; - recptr = (grub_uint16_t *) (&cnode[btree->nodesize - - index * sizeof (grub_uint16_t) - 2]); - return grub_be_to_cpu16 (*recptr); + 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 @@ -314,7 +314,7 @@ grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) while (1) { struct grub_hfsplus_extkey *key; - struct grub_hfsplus_extkey_internal extoverflow; + struct grub_hfsplus_key_internal extoverflow; grub_disk_addr_t blk; grub_off_t ptr; @@ -342,11 +342,11 @@ grub_hfsplus_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) } /* Set up the key to look for in the extent overflow file. */ - extoverflow.fileid = node->fileid; - extoverflow.start = fileblock - blksleft; + extoverflow.extkey.fileid = node->fileid; + extoverflow.extkey.start = fileblock - blksleft; if (grub_hfsplus_btree_search (&node->data->extoverflow_tree, - (struct grub_hfsplus_key_internal *) &extoverflow, + &extoverflow, grub_hfsplus_cmp_extkey, &nnode, &ptr)) { grub_error (GRUB_ERR_READ_ERROR, @@ -519,9 +519,8 @@ grub_hfsplus_cmp_catkey (struct grub_hfsplus_key *keya, { struct grub_hfsplus_catkey *catkey_a = &keya->catkey; struct grub_hfsplus_catkey_internal *catkey_b = &keyb->catkey; - char *filename; - int i; int diff; + grub_size_t len; /* Safe unsigned comparison */ grub_uint32_t aparent = grub_be_to_cpu32 (catkey_a->parent); @@ -530,26 +529,14 @@ grub_hfsplus_cmp_catkey (struct grub_hfsplus_key *keya, if (aparent < catkey_b->parent) return -1; - /* Change the filename in keya so the endianness is correct. */ - for (i = 0; i < grub_be_to_cpu16 (catkey_a->namelen); i++) - catkey_a->name[i] = grub_be_to_cpu16 (catkey_a->name[i]); + len = grub_be_to_cpu16 (catkey_a->namelen); + if (len > catkey_b->namelen) + len = catkey_b->namelen; + diff = grub_memcmp (catkey_a->name, catkey_b->name, + len * sizeof (catkey_a->name[0])); + if (diff == 0) + diff = grub_be_to_cpu16 (catkey_a->namelen) - catkey_b->namelen; - filename = grub_malloc (grub_be_to_cpu16 (catkey_a->namelen) + 1); - - if (! grub_utf16_to_utf8 ((grub_uint8_t *) filename, catkey_a->name, - grub_be_to_cpu16 (catkey_a->namelen))) - return -1; /* XXX: This error never occurs, but in case it happens - just skip this entry. */ - - diff = grub_strncmp (filename, catkey_b->name, - grub_be_to_cpu16 (catkey_a->namelen)); - - grub_free (filename); - - /* The endianness was changed to host format, change it back to - whatever it was. */ - for (i = 0; i < grub_be_to_cpu16 (catkey_a->namelen); i++) - catkey_a->name[i] = grub_cpu_to_be16 (catkey_a->name[i]); return diff; } @@ -711,7 +698,7 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree, } else if (nodedesc->type == GRUB_HFSPLUS_BTNODE_TYPE_INDEX) { - grub_uint32_t *pointer; + void *pointer; /* The place where the key could have been found didn't contain the key. This means that the previous match @@ -723,10 +710,10 @@ grub_hfsplus_btree_search (struct grub_hfsplus_btree *btree, that we are looking for. The last match that is found will be used to locate the child which can contain the record. */ - pointer = (grub_uint32_t *) ((char *) currkey - + grub_be_to_cpu16 (currkey->keylen) - + 2); - currnode = grub_be_to_cpu32 (*pointer); + pointer = ((char *) currkey + + grub_be_to_cpu16 (currkey->keylen) + + 2); + currnode = grub_be_to_cpu32 (grub_get_unaligned32 (pointer)); match = 1; } } @@ -792,53 +779,51 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir, 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; } - filename = grub_malloc (grub_be_to_cpu16 (catkey->namelen) + 1); - if (! filename) - return 0; - - if (! grub_utf16_to_utf8 ((grub_uint8_t *) filename, catkey->name, - grub_be_to_cpu16 (catkey->namelen))) - { - grub_free (filename); - return 0; - } - - filename[grub_be_to_cpu16 (catkey->namelen)] = '\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++) - catkey->name[i] = grub_be_to_cpu16 (catkey->name[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; - /* Only accept valid nodes. */ - if (grub_strlen (filename) == grub_be_to_cpu16 (catkey->namelen)) - { - /* A valid node is found; setup the node and call the - callback function. */ - node = grub_malloc (sizeof (*node)); - node->data = dir->data; + /* A valid node is found; setup the node and call the + callback function. */ + node = grub_malloc (sizeof (*node)); + node->data = dir->data; - grub_memcpy (node->extents, fileinfo->data.extents, - sizeof (node->extents)); - node->mtime = grub_be_to_cpu32 (fileinfo->mtime) - 2082844800; - node->size = grub_be_to_cpu64 (fileinfo->data.size); - node->fileid = grub_be_to_cpu32 (fileinfo->fileid); + 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); - } + ret = hook (filename, type, node); grub_free (filename); @@ -851,7 +836,8 @@ grub_hfsplus_iterate_dir (grub_fshelp_node_t dir, /* Create a key that points to the first entry in the directory. */ intern.catkey.parent = dir->fileid; - intern.catkey.name = ""; + intern.catkey.name = 0; + intern.catkey.namelen = 0; /* First lookup the first entry. */ if (grub_hfsplus_btree_search (&dir->data->catalog_tree, &intern, @@ -999,7 +985,8 @@ grub_hfsplus_label (grub_device_t device, char **label) /* Create a key that points to the label. */ intern.catkey.parent = 1; - intern.catkey.name = ""; + intern.catkey.name = 0; + intern.catkey.namelen = 0; /* First lookup the first entry. */ if (grub_hfsplus_btree_search (&data->catalog_tree, &intern, @@ -1022,20 +1009,12 @@ grub_hfsplus_label (grub_device_t device, char **label) return 0; } - *label = grub_malloc (label_len + 1); + *label = grub_malloc (label_len * GRUB_MAX_UTF8_PER_UTF16 + 1); if (! *label) return grub_errno; - if (! grub_utf16_to_utf8 ((grub_uint8_t *) (*label), catkey->name, - label_len)) - { - grub_free (node); - grub_free (*label); - grub_free (data); - *label = 0; - return grub_errno; - } - (*label)[label_len] = '\0'; + *grub_utf16_to_utf8 ((grub_uint8_t *) (*label), catkey->name, + label_len) = '\0'; grub_free (node); grub_free (data); diff --git a/grub-core/fs/iso9660.c b/grub-core/fs/iso9660.c index 7b1e32f7c..5e767dc27 100644 --- a/grub-core/fs/iso9660.c +++ b/grub-core/fs/iso9660.c @@ -331,19 +331,20 @@ grub_iso9660_susp_iterate (grub_fshelp_node_t node, grub_off_t off, } static char * -grub_iso9660_convert_string (grub_uint16_t *us, int len) +grub_iso9660_convert_string (grub_uint8_t *us, int len) { char *p; int i; + grub_uint16_t t[len]; - p = grub_malloc (len * 4 + 1); + p = grub_malloc (len * GRUB_MAX_UTF8_PER_UTF16 + 1); if (! p) return p; for (i=0; idata[0] & GRUB_ISO9660_RR_DOT) - filename = "."; + filename = (char *) "."; else if (entry->data[0] & GRUB_ISO9660_RR_DOTDOT) - filename = ".."; + filename = (char *) ".."; else if (entry->len >= 5) { grub_size_t size = 1, csize = 1; @@ -744,7 +748,7 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, oldname = filename; filename = grub_iso9660_convert_string - ((grub_uint16_t *) oldname, dirent.namelen >> 1); + ((grub_uint8_t *) oldname, dirent.namelen >> 1); semicolon = grub_strrchr (filename, ';'); if (semicolon) @@ -976,8 +980,7 @@ grub_iso9660_label (grub_device_t device, char **label) if (data) { if (data->joliet) - *label = grub_iso9660_convert_string - ((grub_uint16_t *) &data->voldesc.volname, 16); + *label = grub_iso9660_convert_string (data->voldesc.volname, 16); else *label = grub_strndup ((char *) data->voldesc.volname, 32); if (*label) diff --git a/grub-core/fs/jfs.c b/grub-core/fs/jfs.c index 91497f143..3676ed719 100644 --- a/grub-core/fs/jfs.c +++ b/grub-core/fs/jfs.c @@ -25,6 +25,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -53,9 +54,10 @@ struct grub_jfs_sblock grub_uint16_t log2_blksz; grub_uint8_t unused[79]; - grub_uint8_t volname[11]; + char volname[11]; grub_uint8_t unused2[24]; grub_uint8_t uuid[16]; + char volname2[16]; }; struct grub_jfs_extent @@ -241,7 +243,7 @@ struct grub_jfs_diropen /* On-disk name is at most 255 UTF-16 codepoints. Every UTF-16 codepoint is at most 4 UTF-8 bytes. */ - char name[256 * 4 + 1]; + char name[256 * GRUB_MAX_UTF8_PER_UTF16 + 1]; grub_uint32_t ino; } __attribute__ ((packed)); @@ -402,7 +404,7 @@ grub_jfs_opendir (struct grub_jfs_data *data, struct grub_jfs_inode *inode) if (!((grub_le_to_cpu32 (inode->mode) & GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_DIR)) { - grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); return 0; } @@ -490,7 +492,7 @@ grub_jfs_getent (struct grub_jfs_diropen *diro) void addstr (grub_uint16_t *name, int ulen) { while (ulen--) - filename[strpos++] = *(name++); + filename[strpos++] = grub_le_to_cpu16 (*(name++)); } /* The last node, read in more. */ @@ -703,7 +705,7 @@ grub_jfs_find_file (struct grub_jfs_data *data, const char *path, } grub_jfs_closedir (diro); - grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", path); + grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path); return grub_errno; } @@ -715,7 +717,7 @@ grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint32_t ino) char symlink[size + 1]; if (++data->linknest > GRUB_JFS_MAX_SYMLNK_CNT) - return grub_error (GRUB_ERR_SYMLINK_LOOP, "too deep nesting of symlinks"); + 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); @@ -729,8 +731,6 @@ grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint32_t ino) ino = 2; grub_jfs_find_file (data, symlink, ino); - if (grub_errno) - grub_error (grub_errno, "cannot follow symlink `%s'", symlink); return grub_errno; } @@ -809,7 +809,7 @@ grub_jfs_open (struct grub_file *file, const char *name) if (! ((grub_le_to_cpu32 (data->currinode.mode) & GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_REG)) { - grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a regular file"); + grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file")); goto fail; } @@ -887,7 +887,14 @@ grub_jfs_label (grub_device_t device, char **label) data = grub_jfs_mount (device->disk); if (data) - *label = grub_strndup ((char *) (data->sblock.volname), 11); + { + if (data->sblock.volname2[0]) + *label = grub_strndup (data->sblock.volname2, + sizeof (data->sblock.volname2)); + else + *label = grub_strndup (data->sblock.volname, + sizeof (data->sblock.volname)); + } else *label = 0; diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c index 401883e36..ce5c4c738 100644 --- a/grub-core/fs/minix.c +++ b/grub-core/fs/minix.c @@ -24,6 +24,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -332,7 +333,7 @@ grub_minix_lookup_symlink (struct grub_minix_data *data, int ino) char symlink[GRUB_MINIX_INODE_SIZE (data) + 1]; if (++data->linknest > GRUB_MINIX_MAX_SYMLNK_CNT) - return grub_error (GRUB_ERR_SYMLINK_LOOP, "too deep nesting of symlinks"); + 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) @@ -349,8 +350,6 @@ grub_minix_lookup_symlink (struct grub_minix_data *data, int ino) return grub_errno; grub_minix_find_file (data, symlink); - if (grub_errno) - grub_error (grub_errno, "cannot follow symlink `%s'", symlink); return grub_errno; } @@ -433,7 +432,7 @@ grub_minix_find_file (struct grub_minix_data *data, const char *path) if ((GRUB_MINIX_INODE_MODE (data) & GRUB_MINIX_IFDIR) != GRUB_MINIX_IFDIR) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); continue; } @@ -441,7 +440,7 @@ grub_minix_find_file (struct grub_minix_data *data, const char *path) pos += sizeof (ino) + data->filename_size; } while (pos < GRUB_MINIX_INODE_SIZE (data)); - grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", path); + grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path); return grub_errno; } @@ -480,12 +479,18 @@ grub_minix_mount (grub_disk_t disk) data->disk = disk; data->linknest = 0; #ifdef MODE_MINIX3 - if ((grub_le_to_cpu16 (data->sblock.block_size) - & (grub_le_to_cpu16 (data->sblock.block_size) - 1)) - || grub_le_to_cpu16 (data->sblock.block_size) == 0) - goto fail; - for (data->log_block_size = 0; (1 << data->log_block_size) - < grub_le_to_cpu16 (data->sblock.block_size); data->log_block_size++); + /* These tests are endian-independent. No need to byteswap. */ + if (data->sblock.block_size == 0xffff) + data->log_block_size = 10; + else + { + if ((data->sblock.block_size & (data->sblock.block_size - 1)) + || data->sblock.block_size == 0) + goto fail; + for (data->log_block_size = 0; (1 << data->log_block_size) + < grub_le_to_cpu16 (data->sblock.block_size); + data->log_block_size++); + } #else data->log_block_size = 10; #endif @@ -526,7 +531,7 @@ grub_minix_dir (grub_device_t device, const char *path, if ((GRUB_MINIX_INODE_MODE (data) & GRUB_MINIX_IFDIR) != GRUB_MINIX_IFDIR) { - grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); goto fail; } @@ -594,7 +599,7 @@ grub_minix_open (struct grub_file *file, const char *name) if (!name || name[0] != '/') { - grub_error (GRUB_ERR_BAD_FILENAME, "bad filename"); + grub_error (GRUB_ERR_BAD_FILENAME, N_("invalid file name `%s'"), name); return grub_errno; } diff --git a/grub-core/fs/newc.c b/grub-core/fs/newc.c new file mode 100644 index 000000000..fdcc160e8 --- /dev/null +++ b/grub-core/fs/newc.c @@ -0,0 +1,2 @@ +#define MODE_NEWC 1 +#include "cpio.c" diff --git a/grub-core/fs/nilfs2.c b/grub-core/fs/nilfs2.c index 35a040b97..31d91dbd9 100644 --- a/grub-core/fs/nilfs2.c +++ b/grub-core/fs/nilfs2.c @@ -49,7 +49,6 @@ GRUB_MOD_LICENSE ("GPLv3+"); /* nilfs btree node level. */ #define NILFS_BTREE_LEVEL_DATA 0 #define NILFS_BTREE_LEVEL_NODE_MIN (NILFS_BTREE_LEVEL_DATA + 1) -#define NILFS_BTREE_LEVEL_MAX 14 /* nilfs 1st super block posission from beginning of the partition in 512 block size */ @@ -127,8 +126,7 @@ struct grub_nilfs2_super_block grub_uint16_t s_checkpoint_size; grub_uint16_t s_segment_usage_size; grub_uint8_t s_uuid[16]; - char s_volume_name[16]; - char s_last_mounted[64]; + char s_volume_name[80]; grub_uint32_t s_c_interval; grub_uint32_t s_c_block_max; grub_uint32_t s_reserved[192]; @@ -208,6 +206,7 @@ struct grub_nilfs2_btree_node grub_uint8_t bn_level; grub_uint16_t bn_nchildren; grub_uint32_t bn_pad; + grub_uint64_t keys[0]; }; struct grub_nilfs2_palloc_group_desc @@ -399,9 +398,9 @@ grub_nilfs2_btree_get_level (struct grub_nilfs2_btree_node *node) static inline grub_uint64_t * grub_nilfs2_btree_node_dkeys (struct grub_nilfs2_btree_node *node) { - return (grub_uint64_t *) ((char *) (node + 1) + - ((node->bn_flags & NILFS_BTREE_NODE_ROOT) ? - 0 : NILFS_BTREE_NODE_EXTRA_PAD_SIZE)); + return (node->keys + + ((node->bn_flags & NILFS_BTREE_NODE_ROOT) ? + 0 : (NILFS_BTREE_NODE_EXTRA_PAD_SIZE / sizeof (grub_uint64_t)))); } static inline grub_uint64_t @@ -502,7 +501,7 @@ grub_nilfs2_btree_lookup (struct grub_nilfs2_data *data, grub_uint64_t key, int need_translate) { struct grub_nilfs2_btree_node *node; - unsigned char block[NILFS2_BLOCK_SIZE (data)]; + GRUB_PROPERLY_ALIGNED_ARRAY (block, NILFS2_BLOCK_SIZE (data)); grub_uint64_t ptr; int level, found, index; @@ -734,7 +733,11 @@ grub_nilfs2_load_sb (struct grub_nilfs2_data *data) /* Make sure if 1st super block is valid. */ valid[0] = grub_nilfs2_valid_sb (&data->sblock); - partition_size = grub_disk_get_size (disk); + if (valid[0]) + partition_size = (grub_le_to_cpu64 (data->sblock.s_dev_size) + >> GRUB_DISK_SECTOR_BITS); + else + partition_size = grub_disk_get_size (disk); if (partition_size != GRUB_DISK_SIZE_UNKNOWN) { /* Read second super block. */ @@ -1095,7 +1098,8 @@ grub_nilfs2_label (grub_device_t device, char **label) data = grub_nilfs2_mount (disk); if (data) - *label = grub_strndup (data->sblock.s_volume_name, 14); + *label = grub_strndup (data->sblock.s_volume_name, + sizeof (data->sblock.s_volume_name)); else *label = NULL; diff --git a/grub-core/fs/ntfs.c b/grub-core/fs/ntfs.c index ac695a29f..a2e014945 100644 --- a/grub-core/fs/ntfs.c +++ b/grub-core/fs/ntfs.c @@ -34,43 +34,52 @@ static grub_dl_t my_mod; #define grub_fshelp_node grub_ntfs_file -#define valueat(buf,ofs,type) *((type*)(((char*)buf)+ofs)) +static inline grub_uint16_t +u16at (void *ptr, grub_size_t ofs) +{ + return grub_le_to_cpu16 (grub_get_unaligned16 ((char *) ptr + ofs)); +} -#define u16at(buf,ofs) grub_le_to_cpu16(valueat(buf,ofs,grub_uint16_t)) -#define u32at(buf,ofs) grub_le_to_cpu32(valueat(buf,ofs,grub_uint32_t)) -#define u64at(buf,ofs) grub_le_to_cpu64(valueat(buf,ofs,grub_uint64_t)) +static inline grub_uint32_t +u32at (void *ptr, grub_size_t ofs) +{ + return grub_le_to_cpu32 (grub_get_unaligned32 ((char *) ptr + ofs)); +} -#define v16at(buf,ofs) valueat(buf,ofs,grub_uint16_t) -#define v32at(buf,ofs) valueat(buf,ofs,grub_uint32_t) -#define v64at(buf,ofs) valueat(buf,ofs,grub_uint64_t) +static inline grub_uint64_t +u64at (void *ptr, grub_size_t ofs) +{ + return grub_le_to_cpu64 (grub_get_unaligned64 ((char *) ptr + ofs)); +} grub_ntfscomp_func_t grub_ntfscomp_func; static grub_err_t -fixup (struct grub_ntfs_data *data, char *buf, int len, char *magic) +fixup (char *buf, int len, const char *magic) { int ss; char *pu; grub_uint16_t us; + COMPILE_TIME_ASSERT ((1 << GRUB_NTFS_BLK_SHR) == GRUB_DISK_SECTOR_SIZE); + if (grub_memcmp (buf, magic, 4)) return grub_error (GRUB_ERR_BAD_FS, "%s label not found", magic); ss = u16at (buf, 6) - 1; - if (ss * (int) data->blocksize != len * GRUB_DISK_SECTOR_SIZE) - return grub_error (GRUB_ERR_BAD_FS, "size not match", - ss * (int) data->blocksize, - len * GRUB_DISK_SECTOR_SIZE); + if (ss != len) + return grub_error (GRUB_ERR_BAD_FS, "size not match"); pu = buf + u16at (buf, 4); us = u16at (pu, 0); buf -= 2; while (ss > 0) { - buf += data->blocksize; + buf += GRUB_DISK_SECTOR_SIZE; pu += 2; if (u16at (buf, 0) != us) return grub_error (GRUB_ERR_BAD_FS, "fixup signature not match"); - v16at (buf, 0) = v16at (pu, 0); + buf[0] = pu[0]; + buf[1] = pu[1]; ss--; } @@ -131,17 +140,15 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr) if (at->flags & GRUB_NTFS_AF_MMFT) { if ((grub_disk_read - (at->mft->data->disk, v32at (at->attr_cur, 0x10), 0, + (at->mft->data->disk, u32at (at->attr_cur, 0x10), 0, 512, at->emft_buf)) || (grub_disk_read - (at->mft->data->disk, v32at (at->attr_cur, 0x14), 0, + (at->mft->data->disk, u32at (at->attr_cur, 0x14), 0, 512, at->emft_buf + 512))) return NULL; - if (fixup - (at->mft->data, at->emft_buf, at->mft->data->mft_size, - "FILE")) + if (fixup (at->emft_buf, at->mft->data->mft_size, "FILE")) return NULL; } else @@ -228,8 +235,11 @@ find_attr (struct grub_ntfs_attr *at, unsigned char attr) at->flags |= GRUB_NTFS_AF_GPOS; at->attr_cur = at->attr_nxt; pa = at->attr_cur; - v32at (pa, 0x10) = at->mft->data->mft_start; - v32at (pa, 0x14) = at->mft->data->mft_start + 1; + grub_set_unaligned32 ((char *) pa + 0x10, + grub_cpu_to_le32 (at->mft->data->mft_start)); + grub_set_unaligned32 ((char *) pa + 0x14, + grub_cpu_to_le32 (at->mft->data->mft_start + + 1)); pa = at->attr_nxt + u16at (pa, 4); while (pa < at->attr_end) { @@ -257,13 +267,15 @@ locate_attr (struct grub_ntfs_attr *at, struct grub_ntfs_file *mft, char *pa; init_attr (at, mft); - if ((pa = find_attr (at, attr)) == NULL) + pa = find_attr (at, attr); + if (pa == NULL) return NULL; if ((at->flags & GRUB_NTFS_AF_ALST) == 0) { while (1) { - if ((pa = find_attr (at, attr)) == NULL) + pa = find_attr (at, attr); + if (pa == NULL) break; if (at->flags & GRUB_NTFS_AF_ALST) return pa; @@ -459,8 +471,8 @@ read_data (struct grub_ntfs_attr *at, char *pa, char *dest, return grub_errno; st1 = ctx->curr_lcn * ctx->comp.spc; } - v32at (dest, 0) = st0; - v32at (dest, 4) = st1; + grub_set_unaligned32 (dest, grub_cpu_to_le32 (st0)); + grub_set_unaligned32 (dest + 4, grub_cpu_to_le32 (st1)); return 0; } @@ -477,7 +489,8 @@ read_data (struct grub_ntfs_attr *at, char *pa, char *dest, return (grub_ntfscomp_func) ? grub_ntfscomp_func (at, dest, ofs, len, ctx, vcn) : - grub_error (GRUB_ERR_BAD_FS, "ntfscomp module not loaded"); + grub_error (GRUB_ERR_BAD_FS, N_("module `%s' isn't loaded"), + "ntfscomp"); } static grub_err_t @@ -530,7 +543,7 @@ read_mft (struct grub_ntfs_data *data, char *buf, grub_uint32_t mftno) (&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 (data, buf, data->mft_size, "FILE"); + return fixup (buf, data->mft_size, "FILE"); } static grub_err_t @@ -636,12 +649,18 @@ list_file (struct grub_ntfs_file *diro, char *pos, else fdiro->mtime = u64at (pos, 0x28); - ustr = grub_malloc (ns * 4 + 1); + ustr = grub_malloc (ns * GRUB_MAX_UTF8_PER_UTF16 + 1); if (ustr == NULL) return 0; - *grub_utf16_to_utf8 ((grub_uint8_t *) ustr, (grub_uint16_t *) np, - ns) = '\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; @@ -783,7 +802,8 @@ grub_ntfs_iterate_dir (grub_fshelp_node_t dir, init_attr (at, mft); while (1) { - if ((cur_pos = find_attr (at, GRUB_NTFS_AT_INDEX_ROOT)) == NULL) + cur_pos = find_attr (at, GRUB_NTFS_AT_INDEX_ROOT); + if (cur_pos == NULL) { grub_error (GRUB_ERR_BAD_FS, "no $INDEX_ROOT"); goto done; @@ -883,7 +903,7 @@ 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 (mft->data, indx, mft->data->idx_size, "INDX"))) + || (fixup (indx, mft->data->idx_size, "INDX"))) goto done; ret = list_file (mft, &indx[0x18 + u16at (indx, 0x18)], hook); if (ret) @@ -928,8 +948,9 @@ grub_ntfs_mount (grub_disk_t disk) if (grub_memcmp ((char *) &bpb.oem_name, "NTFS", 4)) goto fail; - data->blocksize = grub_le_to_cpu16 (bpb.bytes_per_sector); - data->spc = bpb.sectors_per_cluster * (data->blocksize >> GRUB_NTFS_BLK_SHR); + data->spc = (bpb.sectors_per_cluster + * (grub_le_to_cpu16 (bpb.bytes_per_sector) + >> GRUB_NTFS_BLK_SHR)); if (bpb.clusters_per_mft > 0) data->mft_size = data->spc * bpb.clusters_per_mft; @@ -959,7 +980,7 @@ grub_ntfs_mount (grub_disk_t disk) data->uuid = grub_le_to_cpu64 (bpb.num_serial); - if (fixup (data, data->mmft.buf, data->mft_size, "FILE")) + if (fixup (data->mmft.buf, data->mft_size, "FILE")) goto fail; if (!locate_attr (&data->mmft.attr, &data->mmft, GRUB_NTFS_AT_DATA)) @@ -1163,8 +1184,14 @@ grub_ntfs_label (grub_device_t device, char **label) len = u32at (pa, 0x10) / 2; buf = grub_malloc (len * 4 + 1); pa += u16at (pa, 0x14); - *grub_utf16_to_utf8 ((grub_uint8_t *) buf, (grub_uint16_t *) pa, len) = - '\0'; + { + 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; } diff --git a/grub-core/fs/odc.c b/grub-core/fs/odc.c new file mode 100644 index 000000000..5fa88e3f9 --- /dev/null +++ b/grub-core/fs/odc.c @@ -0,0 +1,2 @@ +#define MODE_ODC 1 +#include "cpio.c" diff --git a/grub-core/fs/reiserfs.c b/grub-core/fs/reiserfs.c index 639de8d74..5bb529285 100644 --- a/grub-core/fs/reiserfs.c +++ b/grub-core/fs/reiserfs.c @@ -38,6 +38,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -477,23 +478,25 @@ grub_reiserfs_get_item (struct grub_reiserfs_data *data, grub_uint16_t previous_level = ~0; struct grub_reiserfs_item_header *item_headers = 0; +#if 0 if (! data) { - grub_error (GRUB_ERR_TEST_FAILURE, "data is NULL"); + grub_error (GRUB_ERR_BAD_FS, "data is NULL"); goto fail; } if (! key) { - grub_error (GRUB_ERR_TEST_FAILURE, "key is NULL"); + grub_error (GRUB_ERR_BAD_FS, "key is NULL"); goto fail; } if (! item) { - grub_error (GRUB_ERR_TEST_FAILURE, "item is NULL"); + grub_error (GRUB_ERR_BAD_FS, "item is NULL"); goto fail; } +#endif block_size = grub_le_to_cpu16 (data->superblock.block_size); block_number = grub_le_to_cpu32 (data->superblock.root_block); @@ -520,7 +523,7 @@ grub_reiserfs_get_item (struct grub_reiserfs_data *data, if (current_level >= previous_level) { grub_dprintf ("reiserfs_tree", "level loop detected, aborting\n"); - grub_error (GRUB_ERR_FILE_READ_ERROR, "level loop"); + grub_error (GRUB_ERR_BAD_FS, "level loop"); goto fail; } previous_level = current_level; @@ -725,8 +728,7 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item, if (item->type != GRUB_REISERFS_DIRECTORY) { - grub_error (GRUB_ERR_BAD_FILE_TYPE, - "grub_reiserfs_iterate_dir called on a non-directory item"); + grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); goto fail; } block_size = grub_le_to_cpu16 (data->superblock.block_size); @@ -754,7 +756,7 @@ grub_reiserfs_iterate_dir (grub_fshelp_node_t item, #if 0 if (grub_le_to_cpu16 (block_header->level) != 1) { - grub_error (GRUB_ERR_TEST_FAILURE, + grub_error (GRUB_ERR_BAD_FS, "reiserfs: block %d is not a leaf block", block_number); goto fail; @@ -1351,21 +1353,25 @@ grub_reiserfs_uuid (grub_device_t device, char **uuid) grub_dl_ref (my_mod); + *uuid = NULL; data = grub_reiserfs_mount (disk); if (data) { - *uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x", - grub_be_to_cpu16 (data->superblock.uuid[0]), - grub_be_to_cpu16 (data->superblock.uuid[1]), - grub_be_to_cpu16 (data->superblock.uuid[2]), - grub_be_to_cpu16 (data->superblock.uuid[3]), - grub_be_to_cpu16 (data->superblock.uuid[4]), - grub_be_to_cpu16 (data->superblock.uuid[5]), - grub_be_to_cpu16 (data->superblock.uuid[6]), - grub_be_to_cpu16 (data->superblock.uuid[7])); + unsigned i; + for (i = 0; i < ARRAY_SIZE (data->superblock.uuid); i++) + if (data->superblock.uuid[i]) + break; + if (i < ARRAY_SIZE (data->superblock.uuid)) + *uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x", + grub_be_to_cpu16 (data->superblock.uuid[0]), + grub_be_to_cpu16 (data->superblock.uuid[1]), + grub_be_to_cpu16 (data->superblock.uuid[2]), + grub_be_to_cpu16 (data->superblock.uuid[3]), + grub_be_to_cpu16 (data->superblock.uuid[4]), + grub_be_to_cpu16 (data->superblock.uuid[5]), + grub_be_to_cpu16 (data->superblock.uuid[6]), + grub_be_to_cpu16 (data->superblock.uuid[7])); } - else - *uuid = NULL; grub_dl_unref (my_mod); diff --git a/grub-core/fs/romfs.c b/grub-core/fs/romfs.c index 202ca102e..3ea90a214 100644 --- a/grub-core/fs/romfs.c +++ b/grub-core/fs/romfs.c @@ -112,26 +112,29 @@ grub_romfs_mount (grub_device_t dev) if (err) return NULL; for (ptr = sb.sb.label; (void *) ptr < (void *) (&sb + 1) - && ptr < sb.d + grub_be_to_cpu32 (sb.sb.total_size); ptr++) + && ptr - sb.d < (grub_ssize_t) grub_be_to_cpu32 (sb.sb.total_size); ptr++) if (!*ptr) break; - if ((void *) ptr == &sb + 1) - for (sec++; ; sec++) - { - err = grub_disk_read (dev->disk, sec, 0, sizeof (sb), &sb); - if (err == GRUB_ERR_OUT_OF_RANGE) - err = grub_errno = GRUB_ERR_BAD_FS; - if (err) - return NULL; - for (ptr = sb.d; (void *) ptr < (void *) (&sb + 1) - && ptr < sb.d + grub_be_to_cpu32 (sb.sb.total_size); ptr++) - if (!*ptr) - break; - } + while ((void *) ptr == &sb + 1) + { + sec++; + err = grub_disk_read (dev->disk, sec, 0, sizeof (sb), &sb); + if (err == GRUB_ERR_OUT_OF_RANGE) + err = grub_errno = GRUB_ERR_BAD_FS; + if (err) + return NULL; + for (ptr = sb.d; (void *) ptr < (void *) (&sb + 1) + && (ptr - sb.d + (sec << GRUB_DISK_SECTOR_BITS) + < grub_be_to_cpu32 (sb.sb.total_size)); + ptr++) + if (!*ptr) + break; + } data = grub_malloc (sizeof (*data)); if (!data) return NULL; - data->first_file = ALIGN_UP (ptr - sb.d, GRUB_ROMFS_ALIGN) + sec * 512; + data->first_file = ALIGN_UP (ptr + 1 - sb.d, GRUB_ROMFS_ALIGN) + + (sec << GRUB_DISK_SECTOR_BITS); data->disk = dev->disk; return data; } @@ -166,17 +169,18 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir, { grub_disk_addr_t caddr; struct grub_romfs_file_header hdr; - grub_size_t a = 0; - char *name = NULL; unsigned nptr; unsigned i, j; + grub_size_t a = 0; + grub_properly_aligned_t *name = NULL; + for (caddr = dir->data_addr; caddr; caddr = grub_be_to_cpu32 (hdr.next_file) & ~(GRUB_ROMFS_ALIGN - 1)) { grub_disk_addr_t naddr = caddr + sizeof (hdr); grub_uint32_t csum = 0; enum grub_fshelp_filetype filetype = GRUB_FSHELP_UNKNOWN; - struct grub_fshelp_node *node; + struct grub_fshelp_node *node = NULL; grub_err_t err; err = grub_disk_read (dir->data->disk, caddr >> GRUB_DISK_SECTOR_BITS, @@ -189,9 +193,9 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir, } for (nptr = 0; ; nptr++, naddr += 16) { - if (a >= nptr) + if (a <= nptr) { - char *on; + grub_properly_aligned_t *on; a = 2 * (nptr + 1); on = name; name = grub_realloc (name, a * 16); @@ -201,13 +205,14 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir, return 1; } } + COMPILE_TIME_ASSERT (16 % sizeof (name[0]) == 0); err = grub_disk_read (dir->data->disk, naddr >> GRUB_DISK_SECTOR_BITS, naddr & (GRUB_DISK_SECTOR_SIZE - 1), - 16, name + 16 * nptr); + 16, name + (16 / sizeof (name[0])) * nptr); if (err) return 1; for (j = 0; j < 16; j++) - if (!name[16 * nptr + j]) + if (!((char *) name)[16 * nptr + j]) break; if (j != 16) break; @@ -292,7 +297,7 @@ grub_romfs_iterate_dir (grub_fshelp_node_t dir, } } - if (hook (name, filetype, node)) + if (hook ((char *) name, filetype, node)) { grub_free (name); return 1; diff --git a/grub-core/fs/sfs.c b/grub-core/fs/sfs.c index f1e09ccbd..bc7258963 100644 --- a/grub-core/fs/sfs.c +++ b/grub-core/fs/sfs.c @@ -25,6 +25,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -303,6 +304,7 @@ grub_sfs_mount (grub_disk_t disk) data->disk = disk; data->label = grub_strdup ((char *) (rootobjc->objects[0].filename)); + grub_free (rootobjc_data); return data; fail: @@ -357,24 +359,39 @@ grub_sfs_iterate_dir (grub_fshelp_node_t dir, unsigned int next = dir->block; int pos; - auto int NESTED_FUNC_ATTR grub_sfs_create_node (const char *name, int block, + auto int NESTED_FUNC_ATTR grub_sfs_create_node (const char *name, + int block, int size, int type, grub_uint32_t mtime); - int NESTED_FUNC_ATTR grub_sfs_create_node (const char *name, int block, + int NESTED_FUNC_ATTR grub_sfs_create_node (const char *name, + int block, int 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; - return hook (name, type, node); + *grub_latin1_to_utf8 (name_u8, (const grub_uint8_t *) name, len) = '\0'; + + ret = hook ((char *) name_u8, type, node); + grub_free (name_u8); + return ret; } objc_data = grub_malloc (data->blocksize); @@ -398,7 +415,7 @@ grub_sfs_iterate_dir (grub_fshelp_node_t dir, { struct grub_sfs_obj *obj; obj = (struct grub_sfs_obj *) ((char *) objc + pos); - char *filename = (char *) (obj->filename); + const char *filename = (const char *) obj->filename; int len; enum grub_fshelp_filetype type; unsigned int block; @@ -412,7 +429,7 @@ grub_sfs_iterate_dir (grub_fshelp_node_t dir, /* Round up to a multiple of two bytes. */ pos = ((pos + 1) >> 1) << 1; - if (grub_strlen (filename) == 0) + if (filename[0] == 0) continue; /* First check if the file was not deleted. */ @@ -491,7 +508,10 @@ grub_sfs_open (struct grub_file *file, const char *name) static grub_err_t grub_sfs_close (grub_file_t file) { - grub_free (file->data); + struct grub_sfs_data *data = (struct grub_sfs_data *) file->data; + + grub_free (data->label); + grub_free (data); grub_dl_unref (my_mod); @@ -571,8 +591,15 @@ grub_sfs_label (grub_device_t device, char **label) data = grub_sfs_mount (disk); if (data) - *label = data->label; - + { + grub_size_t len = grub_strlen (data->label); + *label = grub_malloc (len * GRUB_MAX_UTF8_PER_LATIN1 + 1); + if (*label) + *grub_latin1_to_utf8 ((grub_uint8_t *) *label, + (const grub_uint8_t *) data->label, + len) = '\0'; + grub_free (data->label); + } grub_free (data); return grub_errno; diff --git a/grub-core/fs/squash4.c b/grub-core/fs/squash4.c index 0728287b7..2d66abf07 100644 --- a/grub-core/fs/squash4.c +++ b/grub-core/fs/squash4.c @@ -26,6 +26,10 @@ #include #include #include +#include + +#include "xz.h" +#include "xz_stream.h" GRUB_MOD_LICENSE ("GPLv3+"); @@ -53,7 +57,9 @@ struct grub_squash_super grub_uint32_t dummy1; grub_uint32_t creation_time; grub_uint32_t block_size; - grub_uint64_t dummy3; + grub_uint32_t dummy2; + grub_uint16_t compression; + grub_uint16_t dummy3; grub_uint64_t dummy4; grub_uint16_t root_ino_offset; grub_uint32_t root_ino_chunk; @@ -74,36 +80,43 @@ struct grub_squash_inode grub_uint16_t type; grub_uint16_t dummy[3]; grub_uint32_t mtime; + grub_uint32_t dummy2; union { struct { - grub_uint32_t dummy; grub_uint32_t chunk; grub_uint32_t fragment; - grub_uint32_t offset; + grub_uint16_t offset; + grub_uint16_t dummy; grub_uint32_t size; grub_uint32_t block_size[0]; } __attribute__ ((packed)) file; struct { - grub_uint32_t dummy; grub_uint64_t chunk; grub_uint64_t size; - grub_uint32_t dummy2[3]; + grub_uint32_t dummy1[3]; grub_uint32_t fragment; - grub_uint32_t offset; + grub_uint16_t offset; + grub_uint16_t dummy2; grub_uint32_t dummy3; grub_uint32_t block_size[0]; } __attribute__ ((packed)) long_file; struct { - grub_uint32_t dummy1; grub_uint32_t chunk; - grub_uint32_t dummy2; + grub_uint32_t dummy; grub_uint16_t size; - grub_uint32_t offset; - grub_uint16_t dummy3; + grub_uint16_t offset; } __attribute__ ((packed)) dir; struct { - grub_uint64_t dummy; + grub_uint32_t dummy1; + grub_uint32_t size; + grub_uint32_t chunk; + grub_uint32_t dummy2; + grub_uint16_t dummy3; + grub_uint16_t offset; + } __attribute__ ((packed)) long_dir; + struct { + grub_uint32_t dummy; grub_uint32_t namelen; char name[0]; } __attribute__ ((packed)) symlink; @@ -124,7 +137,8 @@ struct grub_squash_dirent_header { /* Actually the value is the number of elements - 1. */ grub_uint32_t nelems; - grub_uint64_t ino_chunk; + grub_uint32_t ino_chunk; + grub_uint32_t dummy; } __attribute__ ((packed)); struct grub_squash_dirent @@ -142,6 +156,7 @@ enum SQUASH_TYPE_DIR = 1, SQUASH_TYPE_REGULAR = 2, SQUASH_TYPE_SYMLINK = 3, + SQUASH_TYPE_LONG_DIR = 8, SQUASH_TYPE_LONG_REGULAR = 9, }; @@ -165,7 +180,16 @@ enum SQUASH_BLOCK_UNCOMPRESSED = 0x1000000 }; +enum + { + COMPRESSION_ZLIB = 1, + COMPRESSION_LZO = 3, + COMPRESSION_XZ = 4, + }; + + #define SQUASH_CHUNK_SIZE 0x2000 +#define XZBUFSIZ 0x2000 struct grub_squash_data { @@ -174,6 +198,12 @@ struct grub_squash_data struct grub_squash_cache_inode ino; grub_uint64_t fragments; int log2_blksz; + grub_size_t blksz; + grub_ssize_t (*decompress) (char *inbuf, grub_size_t insize, grub_off_t off, + char *outbuf, grub_size_t outsize, + struct grub_squash_data *data); + struct xz_dec *xzdec; + char *xzbuf; }; struct grub_fshelp_node @@ -186,10 +216,8 @@ struct grub_fshelp_node static grub_err_t read_chunk (struct grub_squash_data *data, void *buf, grub_size_t len, - grub_uint64_t chunk, grub_off_t offset) + grub_uint64_t chunk_start, grub_off_t offset) { - grub_uint64_t chunk_start; - chunk_start = grub_le_to_cpu64 (chunk); while (len > 0) { grub_uint64_t csize; @@ -240,8 +268,8 @@ read_chunk (struct grub_squash_data *data, void *buf, grub_size_t len, return err; } - if (grub_zlib_decompress (tmp, bsize, offset, - buf, csize) < 0) + if (data->decompress (tmp, bsize, offset, + buf, csize, data) < 0) { grub_free (tmp); return grub_errno; @@ -255,6 +283,94 @@ read_chunk (struct grub_squash_data *data, void *buf, grub_size_t len, return GRUB_ERR_NONE; } +static grub_ssize_t +zlib_decompress (char *inbuf, grub_size_t insize, grub_off_t off, + char *outbuf, grub_size_t outsize, + struct grub_squash_data *data __attribute__ ((unused))) +{ + return grub_zlib_decompress (inbuf, insize, off, outbuf, outsize); +} + +static grub_ssize_t +lzo_decompress (char *inbuf, grub_size_t insize, grub_off_t off, + char *outbuf, grub_size_t len, struct grub_squash_data *data) +{ + lzo_uint usize = data->blksz; + grub_uint8_t *udata; + + udata = grub_malloc (data->blksz); + if (!udata) + return -1; + + if (lzo1x_decompress_safe ((grub_uint8_t *) inbuf, + insize, udata, &usize, NULL) != LZO_E_OK) + { + grub_free (udata); + return -1; + } + grub_memcpy (outbuf, udata + off, len); + grub_free (udata); + return len; +} + +static grub_ssize_t +xz_decompress (char *inbuf, grub_size_t insize, grub_off_t off, + char *outbuf, grub_size_t len, struct grub_squash_data *data) +{ + grub_size_t ret = 0; + grub_off_t pos = 0; + struct xz_buf buf; + + xz_dec_reset (data->xzdec); + buf.in = (grub_uint8_t *) inbuf; + buf.in_pos = 0; + buf.in_size = insize; + buf.out = (grub_uint8_t *) data->xzbuf; + buf.out_pos = 0; + buf.out_size = XZBUFSIZ; + + while (len) + { + enum xz_ret xzret; + + buf.out_pos = 0; + + xzret = xz_dec_run (data->xzdec, &buf); + + if (xzret != XZ_OK && xzret != XZ_STREAM_END) + { + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "invalid xz chunk"); + return -1; + } + if (pos + buf.out_pos >= off) + { + grub_ssize_t outoff = pos - off; + grub_size_t l; + if (outoff >= 0) + { + l = buf.out_pos; + if (l > len) + l = len; + grub_memcpy (outbuf + outoff, buf.out, l); + } + else + { + outoff = -outoff; + l = buf.out_pos - outoff; + if (l > len) + l = len; + grub_memcpy (outbuf, buf.out + outoff, l); + } + ret += l; + len -= l; + } + pos += buf.out_pos; + if (xzret == XZ_STREAM_END) + break; + } + return ret; +} + static struct grub_squash_data * squash_mount (grub_disk_t disk) { @@ -268,10 +384,9 @@ squash_mount (grub_disk_t disk) grub_error (GRUB_ERR_BAD_FS, "not a squash4"); if (err) return NULL; - if (grub_le_to_cpu32 (sb.magic) != SQUASH_MAGIC - || grub_le_to_cpu32 (sb.block_size) == 0 - || ((grub_le_to_cpu32 (sb.block_size) - 1) - & grub_le_to_cpu32 (sb.block_size))) + if (sb.magic != grub_cpu_to_le32_compile_time (SQUASH_MAGIC) + || sb.block_size == 0 + || ((sb.block_size - 1) & sb.block_size)) { grub_error (GRUB_ERR_BAD_FS, "not squash4"); return NULL; @@ -294,8 +409,40 @@ squash_mount (grub_disk_t disk) data->disk = disk; data->fragments = grub_le_to_cpu64 (frag); + switch (sb.compression) + { + case grub_cpu_to_le16_compile_time (COMPRESSION_ZLIB): + data->decompress = zlib_decompress; + break; + case grub_cpu_to_le16_compile_time (COMPRESSION_LZO): + data->decompress = lzo_decompress; + break; + case grub_cpu_to_le16_compile_time (COMPRESSION_XZ): + data->decompress = xz_decompress; + data->xzbuf = grub_malloc (XZBUFSIZ); + if (!data->xzbuf) + { + grub_free (data); + return NULL; + } + data->xzdec = xz_dec_init (1 << 16); + if (!data->xzdec) + { + grub_free (data->xzbuf); + grub_free (data); + return NULL; + } + break; + default: + grub_free (data); + grub_error (GRUB_ERR_BAD_FS, "unsupported compression %d", + grub_le_to_cpu16 (sb.compression)); + return NULL; + } + + data->blksz = grub_le_to_cpu32 (data->sb.block_size); for (data->log2_blksz = 0; - (1U << data->log2_blksz) < grub_le_to_cpu32 (data->sb.block_size); + (1U << data->log2_blksz) < data->blksz; data->log2_blksz++); return data; @@ -330,12 +477,29 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, enum grub_fshelp_filetype filetype, grub_fshelp_node_t node)) { - grub_uint32_t off = grub_le_to_cpu16 (dir->ino.dir.offset); + grub_uint32_t off; grub_uint32_t endoff; + grub_uint64_t chunk; unsigned i; /* FIXME: why - 3 ? */ - endoff = grub_le_to_cpu32 (dir->ino.dir.size) + off - 3; + switch (dir->ino.type) + { + case grub_cpu_to_le16_compile_time (SQUASH_TYPE_DIR): + off = grub_le_to_cpu16 (dir->ino.dir.offset); + endoff = grub_le_to_cpu16 (dir->ino.dir.size) + off - 3; + chunk = grub_le_to_cpu32 (dir->ino.dir.chunk); + break; + case grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_DIR): + off = grub_le_to_cpu16 (dir->ino.long_dir.offset); + endoff = grub_le_to_cpu16 (dir->ino.long_dir.size) + off - 3; + chunk = grub_le_to_cpu32 (dir->ino.long_dir.chunk); + break; + default: + grub_error (GRUB_ERR_BAD_FS, "unexpected ino type 0x%x", + grub_le_to_cpu16 (dir->ino.type)); + return 0; + } while (off < endoff) { @@ -344,11 +508,11 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, err = read_chunk (dir->data, &dh, sizeof (dh), grub_le_to_cpu64 (dir->data->sb.diroffset) - + grub_le_to_cpu32 (dir->ino.dir.chunk), off); + + chunk, off); if (err) return 0; off += sizeof (dh); - for (i = 0; i < (unsigned) grub_le_to_cpu16 (dh.nelems) + 1; i++) + for (i = 0; i < (unsigned) grub_le_to_cpu32 (dh.nelems) + 1; i++) { char *buf; int r; @@ -359,7 +523,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, err = read_chunk (dir->data, &di, sizeof (di), grub_le_to_cpu64 (dir->data->sb.diroffset) - + grub_le_to_cpu32 (dir->ino.dir.chunk), off); + + chunk, off); if (err) return 0; off += sizeof (di); @@ -377,7 +541,7 @@ grub_squash_iterate_dir (grub_fshelp_node_t dir, err = read_chunk (dir->data, buf, grub_le_to_cpu16 (di.namelen) + 1, grub_le_to_cpu64 (dir->data->sb.diroffset) - + grub_le_to_cpu32 (dir->ino.dir.chunk), off); + + chunk, off); if (err) return 0; @@ -414,13 +578,16 @@ make_root_node (struct grub_squash_data *data, struct grub_fshelp_node *root) return read_chunk (data, &root->ino, sizeof (root->ino), grub_le_to_cpu64 (data->sb.inodeoffset) - + grub_le_to_cpu16 (data->sb.root_ino_chunk), + + grub_le_to_cpu32 (data->sb.root_ino_chunk), grub_cpu_to_le16 (data->sb.root_ino_offset)); } static void squash_unmount (struct grub_squash_data *data) { + if (data->xzdec) + xz_dec_end (data->xzdec); + grub_free (data->xzbuf); grub_free (data->ino.cumulated_block_sizes); grub_free (data->ino.block_sizes); grub_free (data); @@ -503,11 +670,22 @@ grub_squash_open (struct grub_file *file, const char *name) data->ino.ino_chunk = fdiro->ino_chunk; data->ino.ino_offset = fdiro->ino_offset; - if (fdiro->ino.type - == grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR)) - file->size = grub_le_to_cpu64 (fdiro->ino.long_file.size); - else - file->size = grub_le_to_cpu32 (fdiro->ino.file.size); + switch (fdiro->ino.type) + { + case grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR): + file->size = grub_le_to_cpu64 (fdiro->ino.long_file.size); + break; + case grub_cpu_to_le16_compile_time (SQUASH_TYPE_REGULAR): + file->size = grub_le_to_cpu32 (fdiro->ino.file.size); + break; + default: + { + grub_uint16_t type = grub_le_to_cpu16 (fdiro->ino.type); + grub_free (fdiro); + squash_unmount (data); + return grub_error (GRUB_ERR_BAD_FS, "unexpected ino type 0x%x", type); + } + } grub_free (fdiro); @@ -521,36 +699,39 @@ direct_read (struct grub_squash_data *data, { grub_err_t err; grub_off_t cumulated_uncompressed_size = 0; - grub_uint64_t a; + grub_uint64_t a = 0; grub_size_t i; grub_size_t origlen = len; - if (ino->ino.type == grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR)) - a = grub_le_to_cpu64 (ino->ino.long_file.chunk); - else - a = grub_le_to_cpu32 (ino->ino.file.chunk); + switch (ino->ino.type) + { + case grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR): + a = grub_le_to_cpu64 (ino->ino.long_file.chunk); + break; + case grub_cpu_to_le16_compile_time (SQUASH_TYPE_REGULAR): + a = grub_le_to_cpu32 (ino->ino.file.chunk); + break; + } if (!ino->block_sizes) { - grub_off_t total_size; + grub_off_t total_size = 0; grub_size_t total_blocks; - grub_size_t block_offset; - if (ino->ino.type - == grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR)) + grub_size_t block_offset = 0; + switch (ino->ino.type) { + case grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR): total_size = grub_le_to_cpu64 (ino->ino.long_file.size); block_offset = ((char *) &ino->ino.long_file.block_size - (char *) &ino->ino); - } - else - { + break; + case grub_cpu_to_le16_compile_time (SQUASH_TYPE_REGULAR): total_size = grub_le_to_cpu32 (ino->ino.file.size); block_offset = ((char *) &ino->ino.file.block_size - (char *) &ino->ino); + break; } - total_blocks = ((total_size - + grub_le_to_cpu32 (data->sb.block_size) - 1) - >> data->log2_blksz); + total_blocks = ((total_size + data->blksz - 1) >> data->log2_blksz); ino->block_sizes = grub_malloc (total_blocks * sizeof (ino->block_sizes[0])); ino->cumulated_block_sizes = grub_malloc (total_blocks @@ -585,31 +766,56 @@ direct_read (struct grub_squash_data *data, if (a == 0) a = sizeof (struct grub_squash_super); i = off >> data->log2_blksz; - cumulated_uncompressed_size = grub_le_to_cpu32 (data->sb.block_size) - * (grub_disk_addr_t) i; + cumulated_uncompressed_size = data->blksz * (grub_disk_addr_t) i; while (cumulated_uncompressed_size < off + len) { - grub_size_t boff, read; + grub_size_t boff, curread; boff = off - cumulated_uncompressed_size; - read = grub_le_to_cpu32 (data->sb.block_size) - boff; - if (read > len) - read = len; - if (!(ino->block_sizes[i] & SQUASH_BLOCK_UNCOMPRESSED)) - err = grub_zlib_disk_read (data->disk, - ino->cumulated_block_sizes[i] + a, - boff, buf, read); + curread = data->blksz - boff; + if (curread > len) + curread = len; + if (!(ino->block_sizes[i] + & grub_cpu_to_le32_compile_time (SQUASH_BLOCK_UNCOMPRESSED))) + { + char *block; + grub_size_t csize; + csize = grub_le_to_cpu32 (ino->block_sizes[i]) & ~SQUASH_BLOCK_FLAGS; + block = grub_malloc (csize); + if (!block) + return -1; + err = grub_disk_read (data->disk, + (ino->cumulated_block_sizes[i] + a) + >> GRUB_DISK_SECTOR_BITS, + (ino->cumulated_block_sizes[i] + a) + & (GRUB_DISK_SECTOR_SIZE - 1), + csize, block); + if (err) + { + grub_free (block); + return -1; + } + if (data->decompress (block, csize, boff, buf, curread, data) + != (grub_ssize_t) curread) + { + grub_free (block); + if (!grub_errno) + grub_error (GRUB_ERR_BAD_FS, "incorrect compressed chunk"); + return -1; + } + grub_free (block); + } else err = grub_disk_read (data->disk, (ino->cumulated_block_sizes[i] + a + boff) >> GRUB_DISK_SECTOR_BITS, (ino->cumulated_block_sizes[i] + a + boff) & (GRUB_DISK_SECTOR_SIZE - 1), - read, buf); + curread, buf); if (err) return -1; - off += read; - len -= read; - buf += read; + off += curread; + len -= curread; + buf += curread; cumulated_uncompressed_size += grub_le_to_cpu32 (data->sb.block_size); i++; } @@ -623,20 +829,21 @@ grub_squash_read_data (struct grub_squash_data *data, grub_off_t off, char *buf, grub_size_t len) { grub_err_t err; - grub_uint64_t a, b; - grub_uint32_t fragment; + grub_uint64_t a = 0, b; + grub_uint32_t fragment = 0; int compressed = 0; struct grub_squash_frag_desc frag; - if (ino->ino.type == grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR)) + switch (ino->ino.type) { + case grub_cpu_to_le16_compile_time (SQUASH_TYPE_LONG_REGULAR): a = grub_le_to_cpu64 (ino->ino.long_file.chunk); fragment = grub_le_to_cpu32 (ino->ino.long_file.fragment); - } - else - { + break; + case grub_cpu_to_le16_compile_time (SQUASH_TYPE_REGULAR): a = grub_le_to_cpu32 (ino->ino.file.chunk); fragment = grub_le_to_cpu32 (ino->ino.file.fragment); + break; } if (fragment == 0xffffffff) @@ -655,12 +862,37 @@ grub_squash_read_data (struct grub_squash_data *data, /* FIXME: cache uncompressed chunks. */ if (compressed) - err = grub_zlib_disk_read (data->disk, a, b, buf, len); + { + char *block; + block = grub_malloc (frag.size); + if (!block) + return -1; + err = grub_disk_read (data->disk, + a >> GRUB_DISK_SECTOR_BITS, + a & (GRUB_DISK_SECTOR_SIZE - 1), + frag.size, block); + if (err) + { + grub_free (block); + return -1; + } + if (data->decompress (block, frag.size, b, buf, len, data) + != (grub_ssize_t) len) + { + grub_free (block); + if (!grub_errno) + grub_error (GRUB_ERR_BAD_FS, "incorrect compressed chunk"); + return -1; + } + grub_free (block); + } else - err = grub_disk_read (data->disk, (a + b) >> GRUB_DISK_SECTOR_BITS, + { + err = grub_disk_read (data->disk, (a + b) >> GRUB_DISK_SECTOR_BITS, (a + b) & (GRUB_DISK_SECTOR_SIZE - 1), len, buf); - if (err) - return -1; + if (err) + return -1; + } return len; } diff --git a/grub-core/fs/udf.c b/grub-core/fs/udf.c index e1f115015..537bb37f0 100644 --- a/grub-core/fs/udf.c +++ b/grub-core/fs/udf.c @@ -317,7 +317,7 @@ struct grub_udf_partmap grub_uint8_t ident[62]; } type2; }; -}; +} __attribute__ ((packed)); struct grub_udf_lvd { @@ -820,7 +820,7 @@ read_string (grub_uint8_t *raw, grub_size_t sz) for (i = 0; i < utf16len; i++) utf16[i] = (raw[2 * i + 1] << 8) | raw[2*i + 2]; } - ret = grub_malloc (utf16len * 3 + 1); + ret = grub_malloc (utf16len * GRUB_MAX_UTF8_PER_UTF16 + 1); if (ret) *grub_utf16_to_utf8 ((grub_uint8_t *) ret, utf16, utf16len) = '\0'; grub_free (utf16); diff --git a/grub-core/fs/ufs.c b/grub-core/fs/ufs.c index cd2994895..12c0e8715 100644 --- a/grub-core/fs/ufs.c +++ b/grub-core/fs/ufs.c @@ -24,6 +24,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -398,7 +399,7 @@ grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino) char symlink[INODE_SIZE (data) + 1]; if (++data->linknest > GRUB_UFS_MAX_SYMLNK_CNT) - return grub_error (GRUB_ERR_SYMLINK_LOOP, "too deep nesting of symlinks"); + return grub_error (GRUB_ERR_SYMLINK_LOOP, N_("too deep nesting of symlinks")); if (INODE_SIZE (data) <= sizeof (data->inode.symlink)) grub_strcpy (symlink, (char *) INODE (data, symlink)); @@ -415,8 +416,6 @@ grub_ufs_lookup_symlink (struct grub_ufs_data *data, int ino) return grub_errno; grub_ufs_find_file (data, symlink); - if (grub_errno) - grub_error (grub_errno, "cannot follow symlink `%s'", symlink); return grub_errno; } @@ -504,7 +503,7 @@ grub_ufs_find_file (struct grub_ufs_data *data, const char *path) } if ((INODE_MODE(data) & GRUB_UFS_ATTR_TYPE) != GRUB_UFS_ATTR_DIR) - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); continue; } @@ -513,7 +512,7 @@ grub_ufs_find_file (struct grub_ufs_data *data, const char *path) pos += grub_le_to_cpu16 (dirent.direntlen); } while (pos < INODE_SIZE (data)); - grub_error (GRUB_ERR_FILE_NOT_FOUND, "file `%s' not found", path); + grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path); return grub_errno; } @@ -589,7 +588,7 @@ grub_ufs_dir (grub_device_t device, const char *path, if (!path || path[0] != '/') { - grub_error (GRUB_ERR_BAD_FILENAME, "bad filename"); + grub_error (GRUB_ERR_BAD_FILENAME, N_("invalid file name `%s'"), path); return grub_errno; } @@ -599,7 +598,7 @@ grub_ufs_dir (grub_device_t device, const char *path, if ((INODE_MODE (data) & GRUB_UFS_ATTR_TYPE) != GRUB_UFS_ATTR_DIR) { - grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); goto fail; } @@ -669,7 +668,7 @@ grub_ufs_open (struct grub_file *file, const char *name) if (!name || name[0] != '/') { - grub_error (GRUB_ERR_BAD_FILENAME, "bad filename"); + grub_error (GRUB_ERR_BAD_FILENAME, N_("invalid file name `%s'"), name); return grub_errno; } diff --git a/grub-core/fs/xfs.c b/grub-core/fs/xfs.c index c4d47a099..fbadc8fa5 100644 --- a/grub-core/fs/xfs.c +++ b/grub-core/fs/xfs.c @@ -451,9 +451,9 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, grub_fshelp_node_t node)) { struct grub_fshelp_node *diro = (struct grub_fshelp_node *) dir; - auto int NESTED_FUNC_ATTR call_hook (grub_uint64_t ino, char *filename); + auto int NESTED_FUNC_ATTR call_hook (grub_uint64_t ino, const char *filename); - int NESTED_FUNC_ATTR call_hook (grub_uint64_t ino, char *filename) + int NESTED_FUNC_ATTR call_hook (grub_uint64_t ino, const char *filename) { struct grub_fshelp_node *fdiro; @@ -589,18 +589,18 @@ grub_xfs_iterate_dir (grub_fshelp_node_t dir, - (int) sizeof (struct grub_xfs_dir2_entry))) { struct grub_xfs_dir2_entry *direntry; - grub_uint16_t *freetag; + grub_uint8_t *freetag; char *filename; direntry = (struct grub_xfs_dir2_entry *) &dirblock[pos]; - freetag = (grub_uint16_t *) direntry; + freetag = (grub_uint8_t *) direntry; - if (*freetag == 0XFFFF) + if (grub_get_unaligned16 (freetag) == 0XFFFF) { - grub_uint16_t *skip = (grub_uint16_t *) (freetag + 1); + grub_uint8_t *skip = (freetag + sizeof (grub_uint16_t)); /* This entry is not used, go to the next one. */ - pos += grub_be_to_cpu16 (*skip); + pos += grub_be_to_cpu16 (grub_get_unaligned16 (skip)); continue; } diff --git a/grub-core/fs/zfs/zfs.c b/grub-core/fs/zfs/zfs.c index 83a067237..20f425d63 100644 --- a/grub-core/fs/zfs/zfs.c +++ b/grub-core/fs/zfs/zfs.c @@ -53,13 +53,12 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); #define ZPOOL_PROP_BOOTFS "bootfs" -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) - /* * For nvlist manipulation. (from nvpair.h) */ @@ -77,14 +76,23 @@ static grub_dl_t my_mod; #endif #define P2PHASE(x, align) ((x) & ((align) - 1)) -#define DVA_OFFSET_TO_PHYS_SECTOR(offset) \ - ((offset + VDEV_LABEL_START_SIZE) >> SPA_MINBLOCKSHIFT) + +static inline grub_disk_addr_t +DVA_OFFSET_TO_PHYS_SECTOR (grub_disk_addr_t offset) +{ + return ((offset + VDEV_LABEL_START_SIZE) >> SPA_MINBLOCKSHIFT); +} /* * FAT ZAP data structures */ #define ZFS_CRC64_POLY 0xC96C5795D7870F42ULL /* ECMA-182, reflected form */ -#define ZAP_HASH_IDX(hash, n) (((n) == 0) ? 0 : ((hash) >> (64 - (n)))) +static inline grub_uint64_t +ZAP_HASH_IDX (grub_uint64_t hash, grub_uint64_t n) +{ + return (((n) == 0) ? 0 : ((hash) >> (64 - (n)))); +} + #define CHAIN_END 0xffff /* end of the chunk chain */ /* @@ -93,37 +101,60 @@ static grub_dl_t my_mod; */ #define ZAP_LEAF_ARRAY_BYTES (ZAP_LEAF_CHUNKSIZE - 3) -#define ZAP_LEAF_HASH_SHIFT(bs) (bs - 5) -#define ZAP_LEAF_HASH_NUMENTRIES(bs) (1 << ZAP_LEAF_HASH_SHIFT(bs)) -#define LEAF_HASH(bs, h) \ - ((ZAP_LEAF_HASH_NUMENTRIES(bs)-1) & \ - ((h) >> (64 - ZAP_LEAF_HASH_SHIFT(bs)-l->l_hdr.lh_prefix_len))) +static inline int +ZAP_LEAF_HASH_SHIFT (int bs) +{ + return bs - 5; +} + +static inline int +ZAP_LEAF_HASH_NUMENTRIES (int bs) +{ + return 1 << ZAP_LEAF_HASH_SHIFT(bs); +} + +static inline grub_size_t +LEAF_HASH (int bs, grub_uint64_t h, zap_leaf_phys_t *l) +{ + return ((ZAP_LEAF_HASH_NUMENTRIES (bs)-1) + & ((h) >> (64 - ZAP_LEAF_HASH_SHIFT (bs) - l->l_hdr.lh_prefix_len))); +} /* * The amount of space available for chunks is: * block size shift - hash entry size (2) * number of hash * entries - header space (2*chunksize) */ -#define ZAP_LEAF_NUMCHUNKS(bs) \ - (((1<l_hash + ZAP_LEAF_HASH_NUMENTRIES(bs)))[idx] -#define ZAP_LEAF_ENTRY(l, bs, idx) (&ZAP_LEAF_CHUNK(l, bs, idx).l_entry) +static inline zap_leaf_chunk_t * +ZAP_LEAF_CHUNK (zap_leaf_phys_t *l, int bs, int idx) +{ + return &((zap_leaf_chunk_t *) (l->l_entries + + (ZAP_LEAF_HASH_NUMENTRIES(bs) * 2) + / sizeof (grub_properly_aligned_t)))[idx]; +} + +static inline struct zap_leaf_entry * +ZAP_LEAF_ENTRY(zap_leaf_phys_t *l, int bs, int idx) +{ + return &ZAP_LEAF_CHUNK(l, bs, idx)->l_entry; +} /* * Decompression Entry - lzjb */ -#ifndef NBBY -#define NBBY 8 -#endif extern grub_err_t lzjb_decompress (void *, void *, grub_size_t, grub_size_t); @@ -131,10 +162,26 @@ 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 { - char *name; + const char *name; zfs_decomp_func_t *decomp_func; } decomp_entry_t; +/* + * Signature for checksum functions. + */ +typedef void zio_checksum_t(const void *data, grub_uint64_t size, + grub_zfs_endian_t endian, zio_cksum_t *zcp); + +/* + * Information about each checksum function. + */ +typedef struct zio_checksum_info { + zio_checksum_t *ci_func; /* checksum function for each byteorder */ + int ci_correctable; /* number of correctable bits */ + int ci_eck; /* uses zio embedded checksum? */ + const char *ci_name; /* descriptive name */ +} zio_checksum_info_t; + typedef struct dnode_end { dnode_phys_t dn; @@ -146,6 +193,7 @@ struct grub_zfs_device_desc enum { DEVICE_LEAF, DEVICE_MIRROR, DEVICE_RAIDZ } type; grub_uint64_t id; grub_uint64_t guid; + unsigned ashift; /* Valid only for non-leafs. */ unsigned n_children; @@ -153,7 +201,6 @@ struct grub_zfs_device_desc /* Valid only for RAIDZ. */ unsigned nparity; - unsigned ashift; /* Valid only for leaf devices. */ grub_device_t dev; @@ -368,7 +415,7 @@ zio_checksum_verify (zio_cksum_t zc, grub_uint32_t checksum, (unsigned long long) zc.zc_word[1], (unsigned long long) zc.zc_word[2], (unsigned long long) zc.zc_word[3]); - return grub_error (GRUB_ERR_BAD_FS, "checksum verification failed"); + return grub_error (GRUB_ERR_BAD_FS, N_("checksum verification failed")); } return GRUB_ERR_NONE; @@ -420,12 +467,12 @@ vdev_uberblock_compare (uberblock_t * ub1, uberblock_t * ub2) * Three pieces of information are needed to verify an uberblock: the magic * number, the version number, and the checksum. * - * Currently Implemented: version number, magic number - * Need to Implement: checksum + * Currently Implemented: version number, magic number, checksum * */ static grub_err_t -uberblock_verify (uberblock_phys_t * ub, grub_uint64_t offset) +uberblock_verify (uberblock_phys_t * ub, grub_uint64_t offset, + grub_size_t s) { uberblock_t *uber = &ub->ubp_uberblock; grub_err_t err; @@ -452,7 +499,7 @@ uberblock_verify (uberblock_phys_t * ub, grub_uint64_t offset) zc.zc_word[0] = grub_cpu_to_zfs64 (offset, endian); err = zio_checksum_verify (zc, ZIO_CHECKSUM_LABEL, endian, - (char *) ub, UBERBLOCK_SIZE); + (char *) ub, s); return err; } @@ -464,28 +511,37 @@ uberblock_verify (uberblock_phys_t * ub, grub_uint64_t offset) * Failure - NULL */ static uberblock_phys_t * -find_bestub (uberblock_phys_t * ub_array, grub_disk_addr_t sector) +find_bestub (uberblock_phys_t * ub_array, + const struct grub_zfs_device_desc *desc) { - uberblock_phys_t *ubbest = NULL; + uberblock_phys_t *ubbest = NULL, *ubptr; int i; grub_disk_addr_t offset; grub_err_t err = GRUB_ERR_NONE; + int ub_shift; - for (i = 0; i < (VDEV_UBERBLOCK_RING >> VDEV_UBERBLOCK_SHIFT); i++) + ub_shift = desc->ashift; + if (ub_shift < VDEV_UBERBLOCK_SHIFT) + ub_shift = VDEV_UBERBLOCK_SHIFT; + + for (i = 0; i < (VDEV_UBERBLOCK_RING >> ub_shift); i++) { - offset = (sector << SPA_MINBLOCKSHIFT) + VDEV_PHYS_SIZE - + (i << VDEV_UBERBLOCK_SHIFT); + offset = (desc->vdev_phys_sector << SPA_MINBLOCKSHIFT) + VDEV_PHYS_SIZE + + (i << ub_shift); - err = uberblock_verify (&ub_array[i], offset); + ubptr = (uberblock_phys_t *) ((grub_properly_aligned_t *) ub_array + + ((i << ub_shift) + / sizeof (grub_properly_aligned_t))); + err = uberblock_verify (ubptr, offset, 1 << ub_shift); if (err) { grub_errno = GRUB_ERR_NONE; continue; } if (ubbest == NULL - || vdev_uberblock_compare (&(ub_array[i].ubp_uberblock), + || vdev_uberblock_compare (&(ubptr->ubp_uberblock), &(ubbest->ubp_uberblock)) > 0) - ubbest = &ub_array[i]; + ubbest = ubptr; } if (!ubbest) grub_errno = err; @@ -515,9 +571,12 @@ zfs_fetch_nvlist (struct grub_zfs_device_desc *diskdesc, char **nvlist) { grub_err_t err; - *nvlist = grub_malloc (VDEV_PHYS_SIZE); + *nvlist = 0; + if (!diskdesc->dev) - return grub_error (GRUB_ERR_BAD_FS, "member drive unknown"); + return grub_error (GRUB_ERR_BUG, "member drive unknown"); + + *nvlist = grub_malloc (VDEV_PHYS_SIZE); /* Read in the vdev name-value pair list (112K). */ err = grub_disk_read (diskdesc->dev->disk, diskdesc->vdev_phys_sector, 0, @@ -536,7 +595,8 @@ fill_vdev_info_real (struct grub_zfs_data *data, const char *nvlist, struct grub_zfs_device_desc *fill, struct grub_zfs_device_desc *insert, - int *inserted) + int *inserted, + unsigned ashift) { char *type; @@ -557,6 +617,19 @@ fill_vdev_info_real (struct grub_zfs_data *data, return grub_error (GRUB_ERR_BAD_FS, "couldn't find vdev id"); } + { + grub_uint64_t par; + if (grub_zfs_nvlist_lookup_uint64 (nvlist, "ashift", &par)) + fill->ashift = par; + else if (ashift != 0xffffffff) + fill->ashift = ashift; + else + { + grub_free (type); + return grub_error (GRUB_ERR_BAD_FS, "couldn't find ashift"); + } + } + if (grub_strcmp (type, VDEV_TYPE_DISK) == 0 || grub_strcmp (type, VDEV_TYPE_FILE) == 0) { @@ -570,6 +643,7 @@ fill_vdev_info_real (struct grub_zfs_data *data, fill->original = insert->original; if (!data->device_original) data->device_original = fill; + insert->ashift = fill->ashift; *inserted = 1; } @@ -595,12 +669,6 @@ fill_vdev_info_real (struct grub_zfs_data *data, return grub_error (GRUB_ERR_BAD_FS, "couldn't find raidz parity"); } fill->nparity = par; - if (!grub_zfs_nvlist_lookup_uint64 (nvlist, "ashift", &par)) - { - grub_free (type); - return grub_error (GRUB_ERR_BAD_FS, "couldn't find raidz ashift"); - } - fill->ashift = par; } nelm = grub_zfs_nvlist_lookup_nvlist_array_get_nelm (nvlist, @@ -629,7 +697,7 @@ fill_vdev_info_real (struct grub_zfs_data *data, (nvlist, ZPOOL_CONFIG_CHILDREN, i); err = fill_vdev_info_real (data, child, &fill->children[i], insert, - inserted); + inserted, fill->ashift); grub_free (child); @@ -664,7 +732,7 @@ fill_vdev_info (struct grub_zfs_data *data, for (i = 0; i < data->n_devices_attached; i++) if (data->devices_attached[i].id == id) return fill_vdev_info_real (data, nvlist, &data->devices_attached[i], - diskdesc, inserted); + diskdesc, inserted, 0xffffffff); data->n_devices_attached++; if (data->n_devices_attached > data->n_devices_allocated) @@ -687,7 +755,7 @@ fill_vdev_info (struct grub_zfs_data *data, return fill_vdev_info_real (data, nvlist, &data->devices_attached[data->n_devices_attached - 1], - diskdesc, inserted); + diskdesc, inserted, 0xffffffff); } /* @@ -862,7 +930,8 @@ scan_disk (grub_device_t dev, struct grub_zfs_data *data, desc.vdev_phys_sector = label * (sizeof (vdev_label_t) >> SPA_MINBLOCKSHIFT) + ((VDEV_SKIP_SIZE + VDEV_BOOT_HEADER_SIZE) >> SPA_MINBLOCKSHIFT) - + (label < VDEV_LABELS / 2 ? 0 : grub_disk_get_size (dev->disk) + + (label < VDEV_LABELS / 2 ? 0 : + ALIGN_DOWN (grub_disk_get_size (dev->disk), sizeof (vdev_label_t)) - VDEV_LABELS * (sizeof (vdev_label_t) >> SPA_MINBLOCKSHIFT)); /* Read in the uberblock ring (128K). */ @@ -876,7 +945,14 @@ scan_disk (grub_device_t dev, struct grub_zfs_data *data, } grub_dprintf ("zfs", "label ok %d\n", label); - ubbest = find_bestub (ub_array, desc.vdev_phys_sector); + err = check_pool_label (data, &desc, inserted); + if (err || !*inserted) + { + grub_errno = GRUB_ERR_NONE; + continue; + } + + ubbest = find_bestub (ub_array, &desc); if (!ubbest) { grub_dprintf ("zfs", "No uberblock found\n"); @@ -890,12 +966,6 @@ scan_disk (grub_device_t dev, struct grub_zfs_data *data, grub_memmove (&(data->current_uberblock), &ubbest->ubp_uberblock, sizeof (uberblock_t)); - err = check_pool_label (data, &desc, inserted); - if (err) - { - grub_errno = GRUB_ERR_NONE; - continue; - } #if 0 if (find_best_root && vdev_uberblock_compare (&ubbest->ubp_uberblock, @@ -953,14 +1023,6 @@ scan_devices (struct grub_zfs_data *data) return GRUB_ERR_NONE; } -static inline void -xor (grub_uint64_t *a, const grub_uint64_t *b, grub_size_t s) -{ - s /= sizeof (grub_uint64_t); - while (s--) - *a++ ^= *b++; -} - /* x**y. */ static grub_uint8_t powx[255 * 2]; /* Such an s that x**s = y */ @@ -969,17 +1031,15 @@ static const grub_uint8_t poly = 0x1d; /* perform the operation a ^= b * (x ** (known_idx * recovery_pow) ) */ static inline void -xor_out (void *a_in, const void *b_in, grub_size_t s, +xor_out (grub_uint8_t *a, const grub_uint8_t *b, grub_size_t s, int known_idx, int recovery_pow) { int add; - grub_uint8_t *a = a_in; - const grub_uint8_t *b = b_in; /* Simple xor. */ if (known_idx == 0 || recovery_pow == 0) { - xor (a_in, b_in, s); + grub_crypto_xor (a, a, b, s); return; } add = (known_idx * recovery_pow) % 255; @@ -1001,7 +1061,7 @@ recovery (grub_uint8_t *bufs[4], grub_size_t s, const int nbufs, const unsigned *powers, const int *idx) { - grub_dprintf ("zfs", "recovering %u bufers\n", nbufs); + grub_dprintf ("zfs", "recovering %u buffers\n", nbufs); /* Now we have */ /* b_i = sum (r_j* (x ** (powers[i] * idx[j])))*/ /* Let's invert the matrix in question. */ @@ -1147,7 +1207,9 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, sector = DVA_OFFSET_TO_PHYS_SECTOR (offset); if (!desc->dev) { - return grub_error (GRUB_ERR_BAD_FS, "member drive unknown"); + return grub_error (GRUB_ERR_BAD_FS, + N_("couldn't find a necesssary member device " + "of multi-device filesystem")); } /* read in a data block */ return grub_disk_read (desc->dev->disk, sector, 0, len, buf); @@ -1338,8 +1400,8 @@ read_device (grub_uint64_t offset, struct grub_zfs_device_desc *desc, { grub_uint8_t *tmp_recovery_buf[4]; for (j = 0; j < i; j++) - tmp_recovery_buf[j] = recovery_buf[j] + recovery_len[j] - 1; - err = recovery (tmp_recovery_buf, 1, i, redundancy_pow, + tmp_recovery_buf[j] = recovery_buf[j] + recovery_len[failed_devices - 1]; + err = recovery (tmp_recovery_buf, recovery_len[0] - recovery_len[failed_devices - 1], i, redundancy_pow, recovery_idx); if (err) return err; @@ -1551,7 +1613,9 @@ zio_read (blkptr_t *bp, grub_zfs_endian_t endian, void **buf, if (encrypted) { if (!grub_zfs_decrypt) - err = grub_error (GRUB_ERR_BAD_FS, "zfscrypt module not loaded"); + err = grub_error (GRUB_ERR_BAD_FS, + N_("module `%s' isn't loaded"), + "zfscrypt"); else { unsigned i, besti = 0; @@ -1710,7 +1774,7 @@ mzap_lookup (mzap_phys_t * zapobj, grub_zfs_endian_t endian, } } - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "couldn't find %s", name); + return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), name); } static int @@ -1804,18 +1868,21 @@ name_cmp (const char *s1, const char *s2, grub_size_t n, /* XXX */ static int zap_leaf_array_equal (zap_leaf_phys_t * l, grub_zfs_endian_t endian, - int blksft, int chunk, int array_len, const char *buf, - int case_insensitive) + int blksft, int chunk, grub_size_t array_len, + const char *buf, int case_insensitive) { - int bseen = 0; + grub_size_t bseen = 0; while (bseen < array_len) { - struct zap_leaf_array *la = &ZAP_LEAF_CHUNK (l, blksft, chunk).l_array; - int toread = MIN (array_len - bseen, ZAP_LEAF_ARRAY_BYTES); + struct zap_leaf_array *la = &ZAP_LEAF_CHUNK (l, blksft, chunk)->l_array; + grub_size_t toread = array_len - bseen; + + if (toread > ZAP_LEAF_ARRAY_BYTES) + toread = ZAP_LEAF_ARRAY_BYTES; if (chunk >= ZAP_LEAF_NUMCHUNKS (blksft)) - return (0); + return 0; if (name_cmp ((char *) la->la_array, buf + bseen, toread, case_insensitive) != 0) @@ -1829,14 +1896,17 @@ zap_leaf_array_equal (zap_leaf_phys_t * l, grub_zfs_endian_t endian, /* XXX */ static grub_err_t zap_leaf_array_get (zap_leaf_phys_t * l, grub_zfs_endian_t endian, int blksft, - int chunk, int array_len, char *buf) + int chunk, grub_size_t array_len, char *buf) { - int bseen = 0; + grub_size_t bseen = 0; while (bseen < array_len) { - struct zap_leaf_array *la = &ZAP_LEAF_CHUNK (l, blksft, chunk).l_array; - int toread = MIN (array_len - bseen, ZAP_LEAF_ARRAY_BYTES); + struct zap_leaf_array *la = &ZAP_LEAF_CHUNK (l, blksft, chunk)->l_array; + grub_size_t toread = array_len - bseen; + + if (toread > ZAP_LEAF_ARRAY_BYTES) + toread = ZAP_LEAF_ARRAY_BYTES; if (chunk >= ZAP_LEAF_NUMCHUNKS (blksft)) /* Don't use grub_error because this error is to be ignored. */ @@ -1871,7 +1941,7 @@ zap_leaf_lookup (zap_leaf_phys_t * l, grub_zfs_endian_t endian, if (grub_zfs_to_cpu32 (l->l_hdr.lh_magic, endian) != ZAP_LEAF_MAGIC) return grub_error (GRUB_ERR_BAD_FS, "invalid leaf magic"); - for (chunk = grub_zfs_to_cpu16 (l->l_hash[LEAF_HASH (blksft, h)], endian); + for (chunk = grub_zfs_to_cpu16 (l->l_hash[LEAF_HASH (blksft, h, l)], endian); chunk != CHAIN_END; chunk = grub_zfs_to_cpu16 (le->le_next, endian)) { @@ -1901,7 +1971,7 @@ zap_leaf_lookup (zap_leaf_phys_t * l, grub_zfs_endian_t endian, return grub_error (GRUB_ERR_BAD_FS, "invalid leaf chunk entry"); /* get the uint64_t property value */ - la = &ZAP_LEAF_CHUNK (l, blksft, le->le_value_chunk).l_array; + la = &ZAP_LEAF_CHUNK (l, blksft, le->le_value_chunk)->l_array; *value = grub_be_to_cpu64 (la->la_array64); @@ -1909,7 +1979,7 @@ zap_leaf_lookup (zap_leaf_phys_t * l, grub_zfs_endian_t endian, } } - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "couldn't find %s", name); + return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), name); } @@ -1933,8 +2003,8 @@ zap_verify (zap_phys_t *zap, grub_zfs_endian_t endian) /* XXX */ static grub_err_t fzap_lookup (dnode_end_t * zap_dnode, zap_phys_t * zap, - char *name, grub_uint64_t * value, struct grub_zfs_data *data, - int case_insensitive) + const char *name, grub_uint64_t * value, + struct grub_zfs_data *data, int case_insensitive) { void *l; grub_uint64_t hash, idx, blkid; @@ -2096,7 +2166,7 @@ fzap_iterate (dnode_end_t * zap_dnode, zap_phys_t * zap, * */ static grub_err_t -zap_lookup (dnode_end_t * zap_dnode, char *name, grub_uint64_t * val, +zap_lookup (dnode_end_t * zap_dnode, const char *name, grub_uint64_t *val, struct grub_zfs_data *data, int case_insensitive) { grub_uint64_t block_type; @@ -2425,7 +2495,7 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, if (dnode_path->dn.dn.dn_type != DMU_OT_DIRECTORY_CONTENTS) { grub_free (path_buf); - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); } err = zap_lookup (&(dnode_path->dn), cname, &objnum, data, subvol->case_insensitive); @@ -2478,7 +2548,9 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, if (err) return err; - movesize = MIN (sym_sz - block * blksz, blksz); + movesize = sym_sz - block * blksz; + if (movesize > blksz) + movesize = blksz; grub_memcpy (sym_value + block * blksz, t, movesize); grub_free (t); @@ -2536,11 +2608,17 @@ dnode_get_path (struct subvolume *subvol, const char *path_in, dnode_end_t *dn, hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); - if (((grub_zfs_to_cpu64 (*(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_TYPE_OFFSET), dnode_path->dn.endian) >> 12) & 0xf) == 0xa) + if (((grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + + hdrsize + + SA_TYPE_OFFSET), + dnode_path->dn.endian) >> 12) & 0xf) == 0xa) { char *sym_value = (char *) sahdrp + hdrsize + SA_SYMLINK_OFFSET; grub_size_t sym_sz = - grub_zfs_to_cpu64 (*(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_SIZE_OFFSET), dnode_path->dn.endian); + grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + + hdrsize + + SA_SIZE_OFFSET), + dnode_path->dn.endian); char *oldpath = path, *oldpathbuf = path_buf; path = path_buf = grub_malloc (sym_sz + grub_strlen (oldpath) + 1); if (!path_buf) @@ -2684,7 +2762,7 @@ get_filesystem_dnode (dnode_end_t * mosmdn, char *fsname, break; cname = fsname; - while (*fsname && !grub_isspace (*fsname) && *fsname != '/') + while (*fsname && *fsname != '/') fsname++; ch = *fsname; *fsname = 0; @@ -2969,12 +3047,12 @@ dnode_get_fullpath (const char *fullpath, struct subvolume *subvol, */ static int -nvlist_find_value (const char *nvlist, const char *name, +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; + const char *nvpair, *nvp_name, *nvlist = nvlist_in; /* Verify if the 1st and 2nd byte in the nvlist are valid. */ /* NOTE: independently of what endianness header announces all @@ -2993,22 +3071,38 @@ nvlist_find_value (const char *nvlist, const char *name, * 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_uint32_t *) nvlist))) + while ((encode_size = grub_be_to_cpu32 (grub_get_unaligned32 (nvlist)))) { int nelm; + if (nvlist + 4 * 4 >= nvlist_in + VDEV_PHYS_SIZE) + { + grub_dprintf ("zfs", "nvlist overflow\n"); + grub_error (GRUB_ERR_BAD_FS, "incorrect nvlist"); + return 0; + } + nvpair = nvlist + 4 * 2; /* skip the encode/decode size */ - name_len = grub_be_to_cpu32 (*(grub_uint32_t *) nvpair); + name_len = grub_be_to_cpu32 (grub_get_unaligned32 (nvpair)); nvpair += 4; nvp_name = nvpair; nvpair = nvpair + ((name_len + 3) & ~3); /* align */ - type = grub_be_to_cpu32 (*(grub_uint32_t *) nvpair); + 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_uint32_t *) nvpair); + nelm = grub_be_to_cpu32 (grub_get_unaligned32 (nvpair)); if (nelm < 1) return grub_error (GRUB_ERR_BAD_FS, "empty nvpair"); @@ -3045,7 +3139,7 @@ grub_zfs_nvlist_lookup_uint64 (const char *nvlist, const char *name, return 0; } - *out = grub_be_to_cpu64 (*(grub_uint64_t *) nvpair); + *out = grub_be_to_cpu64 (grub_get_unaligned64 (nvpair)); return 1; } @@ -3066,7 +3160,7 @@ grub_zfs_nvlist_lookup_string (const char *nvlist, const char *name) grub_error (GRUB_ERR_BAD_FS, "invalid string"); return 0; } - slen = grub_be_to_cpu32 (*(grub_uint32_t *) nvpair); + slen = grub_be_to_cpu32 (grub_get_unaligned32 (nvpair)); if (slen > size - 4) slen = size - 4; ret = grub_malloc (slen + 1); @@ -3122,7 +3216,7 @@ get_nvlist_size (const char *beg, const char *limit) ptr = beg + 8; while (ptr < limit - && (encode_size = grub_be_to_cpu32 (*(grub_uint32_t *) ptr))) + && (encode_size = grub_be_to_cpu32 (grub_get_unaligned32 (ptr)))) ptr += encode_size; /* goto the next nvpair */ ptr += 8; return (ptr > limit) ? -1 : (ptr - beg); @@ -3397,14 +3491,14 @@ grub_zfs_open (struct grub_file *file, const char *fsfilename) if (isfs) { zfs_unmount (data); - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "Missing @ or / separator"); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("missing `%c' symbol"), '@'); } /* We found the dnode for this file. Verify if it is a plain file. */ if (data->dnode.dn.dn_type != DMU_OT_PLAIN_FILE_CONTENTS) { zfs_unmount (data); - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a file"); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file")); } /* get the file size and set the file position to 0 */ @@ -3437,7 +3531,7 @@ grub_zfs_open (struct grub_file *file, const char *fsfilename) } hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); - file->size = grub_zfs_to_cpu64 (*(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_SIZE_OFFSET), data->dnode.endian); + file->size = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_SIZE_OFFSET), data->dnode.endian); } else if (data->dnode.dn.dn_bonustype == DMU_OT_ZNODE) { @@ -3465,14 +3559,6 @@ grub_zfs_read (grub_file_t file, char *buf, grub_size_t len) grub_size_t read; grub_err_t err; - if (data->file_buf == NULL) - { - data->file_buf = grub_malloc (SPA_MAXBLOCKSIZE); - if (!data->file_buf) - return -1; - data->file_start = data->file_end = 0; - } - /* * If offset is in memory, move it into the buffer provided and return. */ @@ -3509,12 +3595,18 @@ grub_zfs_read (grub_file_t file, char *buf, grub_size_t len) 0, data); data->file_buf = t; if (err) - return -1; + { + data->file_buf = NULL; + data->file_start = data->file_end = 0; + return -1; + } data->file_start = blkid * blksz; data->file_end = data->file_start + blksz; - movesize = MIN (length, data->file_end - file->offset - read); + movesize = data->file_end - file->offset - read; + if (movesize > length) + movesize = length; grub_memmove (buf, data->file_buf + file->offset + read - data->file_start, movesize); @@ -3629,7 +3721,7 @@ fill_fs_info (struct grub_dirhook_info *info, hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); info->mtimeset = 1; - info->mtime = grub_zfs_to_cpu64 (*(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian); + info->mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian); } if (dn.dn.dn_bonustype == DMU_OT_ZNODE) @@ -3690,7 +3782,7 @@ grub_zfs_dir (grub_device_t device, const char *path, hdrsize = SA_HDR_SIZE (((sa_hdr_phys_t *) sahdrp)); info.mtimeset = 1; - info.mtime = grub_zfs_to_cpu64 (*(grub_uint64_t *) ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian); + info.mtime = grub_zfs_to_cpu64 (grub_get_unaligned64 ((char *) sahdrp + hdrsize + SA_MTIME_OFFSET), dn.endian); info.case_insensitive = data->subvol.case_insensitive; } @@ -3798,7 +3890,7 @@ grub_zfs_dir (grub_device_t device, const char *path, if (data->dnode.dn.dn_type != DMU_OT_DIRECTORY_CONTENTS) { zfs_unmount (data); - return grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory"); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory")); } zap_iterate_u64 (&(data->dnode), iterate_zap, data); } @@ -3821,8 +3913,8 @@ grub_zfs_embed (grub_device_t device __attribute__ ((unused)), if ((VDEV_BOOT_SIZE >> GRUB_DISK_SECTOR_BITS) < *nsectors) return grub_error (GRUB_ERR_OUT_OF_RANGE, - "Your core.img is unusually large. " - "It won't fit in the embedding area."); + N_("your core.img is unusually large. " + "It won't fit in the embedding area")); *nsectors = (VDEV_BOOT_SIZE >> GRUB_DISK_SECTOR_BITS); *sectors = grub_malloc (*nsectors * sizeof (**sectors)); diff --git a/grub-core/fs/zfs/zfscrypt.c b/grub-core/fs/zfs/zfscrypt.c index 63380f66a..4ea53b863 100644 --- a/grub-core/fs/zfs/zfscrypt.c +++ b/grub-core/fs/zfs/zfscrypt.c @@ -44,6 +44,11 @@ GRUB_MOD_LICENSE ("GPLv3+"); +/* + Mostly based on following article: + https://blogs.oracle.com/darren/entry/zfs_encryption_what_is_on + */ + enum grub_zfs_algo { GRUB_ZFS_ALGO_CCM, @@ -283,7 +288,7 @@ grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher, if (!cipher) return grub_error (GRUB_ERR_ACCESS_DENIED, - "no decryption key available");; + N_("no decryption key available")); err = algo_decrypt (cipher, algo, (grub_uint8_t *) buf, (grub_uint8_t *) buf, @@ -295,7 +300,7 @@ grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher, for (i = 0; i < 3; i++) if (grub_zfs_to_cpu32 (expected_mac[i], endian) != grub_be_to_cpu32 (mac[i])) - return grub_error (GRUB_ERR_BAD_FS, "MAC verification failed"); + return grub_error (GRUB_ERR_BAD_FS, N_("MAC verification failed")); return GRUB_ERR_NONE; } diff --git a/grub-core/fs/zfs/zfsinfo.c b/grub-core/fs/zfs/zfsinfo.c index 94f2a1ac8..ef7a22195 100644 --- a/grub-core/fs/zfs/zfsinfo.c +++ b/grub-core/fs/zfs/zfsinfo.c @@ -45,31 +45,32 @@ print_state (char *nvlist, int tab) int isok = 1; print_tabs (tab); - grub_xputs (_("State: ")); if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_REMOVED, &ival)) { - grub_xputs (_("removed ")); + grub_puts_ (N_("Virtual device is removed")); isok = 0; } if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_FAULTED, &ival)) { - grub_xputs (_("faulted ")); + grub_puts_ (N_("Virtual device is faulted")); isok = 0; } if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_OFFLINE, &ival)) { - grub_xputs (_("offline ")); + grub_puts_ (N_("Virtual device is offline")); isok = 0; } if (grub_zfs_nvlist_lookup_uint64 (nvlist, ZPOOL_CONFIG_FAULTED, &ival)) - grub_xputs (_("degraded ")); + /* TRANSLATORS: degraded doesn't mean broken but that some of + component are missing but virtual device as whole is still usable. */ + grub_puts_ (N_("Virtual device is degraded")); if (isok) - grub_xputs (_("online")); + grub_puts_ (N_("Virtual device is online")); grub_xputs ("\n"); return GRUB_ERR_NONE; @@ -85,7 +86,7 @@ print_vdev_info (char *nvlist, int tab) if (!type) { print_tabs (tab); - grub_puts_ (N_("Incorrect VDEV: no type available")); + grub_puts_ (N_("Incorrect virtual device: no type available")); return grub_errno; } @@ -96,7 +97,7 @@ print_vdev_info (char *nvlist, int tab) char *devid = 0; print_tabs (tab); - grub_puts_ (N_("Leaf VDEV")); + grub_puts_ (N_("Leaf virtual device (file or disk)")); print_state (nvlist, tab); @@ -137,10 +138,10 @@ print_vdev_info (char *nvlist, int tab) print_tabs (tab); if (nelm <= 0) { - grub_puts_ (N_("Incorrect mirror VDEV")); + grub_puts_ (N_("Incorrect mirror")); return GRUB_ERR_NONE; } - grub_printf_ (N_("Mirror VDEV with %d children\n"), nelm); + grub_printf_ (N_("Mirror with %d children\n"), nelm); print_state (nvlist, tab); for (i = 0; i < nelm; i++) { @@ -152,11 +153,11 @@ print_vdev_info (char *nvlist, int tab) print_tabs (tab); if (!child) { - grub_printf_ (N_("Mirror VDEV element %d isn't correct\n"), i); + grub_printf_ (N_("Mirror element %d isn't correct\n"), i); continue; } - grub_printf_ (N_("Mirror VDEV element %d:\n"), i); + grub_printf_ (N_("Mirror element %d:\n"), i); print_vdev_info (child, tab + 1); grub_free (child); @@ -165,7 +166,7 @@ print_vdev_info (char *nvlist, int tab) } print_tabs (tab); - grub_printf_ (N_("Unknown VDEV type: %s\n"), type); + grub_printf_ (N_("Unknown virtual device type: %s\n"), type); return GRUB_ERR_NONE; } @@ -248,7 +249,7 @@ grub_cmd_zfsinfo (grub_command_t cmd __attribute__ ((unused)), int argc, int found; if (argc < 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); if (args[0][0] == '(' && args[0][grub_strlen (args[0]) - 1] == ')') { @@ -298,7 +299,7 @@ grub_cmd_zfsinfo (grub_command_t cmd __attribute__ ((unused)), int argc, nv = grub_zfs_nvlist_lookup_nvlist (nvlist, ZPOOL_CONFIG_VDEV_TREE); if (!nv) - grub_puts_ (N_("No vdev tree available")); + grub_puts_ (N_("No virtual device tree available")); else print_vdev_info (nv, 1); @@ -324,7 +325,7 @@ grub_cmd_zfs_bootfs (grub_command_t cmd __attribute__ ((unused)), int argc, grub_uint64_t mdnobj; if (argc < 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "filesystem name required"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); devname = grub_file_get_device_name (args[0]); if (grub_errno) diff --git a/grub-core/gdb_grub.in b/grub-core/gdb_grub.in index 4a55233da..01ef3e15b 100644 --- a/grub-core/gdb_grub.in +++ b/grub-core/gdb_grub.in @@ -2,6 +2,9 @@ ### Load debuging information about GNU GRUB 2 modules into GDB ### automatically. Needs readelf, Perl and gmodule.pl script ### +### Has to be launched from the writable and trusted +### directory containing *.image and *.module +### ### $Id: .gdbinit,v 1.1 2006/05/14 11:38:08 lkundrak Exp $ ### Lubomir Kundrak ### diff --git a/grub-core/gensymlist.sh b/grub-core/gensymlist.sh index 5f402ea87..a13d7cc38 100644 --- a/grub-core/gensymlist.sh +++ b/grub-core/gensymlist.sh @@ -41,6 +41,8 @@ cat <. */ -#include #include #include #include @@ -38,322 +37,333 @@ GRUB_MOD_LICENSE ("GPLv3+"); static grub_file_t fd_mo; -static int grub_gettext_offsetoriginal; -static int grub_gettext_max; +static grub_off_t grub_gettext_offset_original; +static grub_off_t grub_gettext_offset_translation; +static grub_size_t grub_gettext_max; +static int grub_gettext_max_log; static const char *(*grub_gettext_original) (const char *s); struct grub_gettext_msg { - struct grub_gettext_msg *next; - const char *name; - - const char *translated; + char *name; + char *translated; }; static struct grub_gettext_msg *grub_gettext_msg_list = NULL; -#define GETTEXT_MAGIC_NUMBER 0 -#define GETTEXT_FILE_FORMAT 4 -#define GETTEXT_NUMBER_OF_STRINGS 8 -#define GETTEXT_OFFSET_ORIGINAL 12 -#define GETTEXT_OFFSET_TRANSLATION 16 +struct header +{ + grub_uint32_t magic; + grub_uint32_t version; + grub_uint32_t number_of_strings; + grub_uint32_t offset_original; + grub_uint32_t offset_translation; +}; + +struct string_descriptor +{ + grub_uint32_t length; + grub_uint32_t offset; +}; #define MO_MAGIC_NUMBER 0x950412de -static grub_ssize_t +static grub_err_t grub_gettext_pread (grub_file_t file, void *buf, grub_size_t len, grub_off_t offset) { if (grub_file_seek (file, offset) == (grub_off_t) - 1) + return grub_errno; + if (grub_file_read (file, buf, len) != (grub_ssize_t) len) { - return -1; + if (!grub_errno) + grub_error (GRUB_ERR_READ_ERROR, N_("premature end of file")); + return grub_errno; } - return grub_file_read (file, buf, len); + return GRUB_ERR_NONE; } -static grub_uint32_t -grub_gettext_get_info (int offset) +static char * +grub_gettext_getstr_from_position (grub_off_t off, + grub_size_t position) { - grub_uint32_t value; - - grub_gettext_pread (fd_mo, (char *) &value, 4, offset); - - value = grub_cpu_to_le32 (value); - return value; -} - -static void -grub_gettext_getstring_from_offset (grub_uint32_t offset, - grub_uint32_t length, char *translation) -{ - grub_gettext_pread (fd_mo, translation, length, offset); - translation[length] = '\0'; -} - -static const char * -grub_gettext_gettranslation_from_position (int position) -{ - int offsettranslation; - int internal_position; - grub_uint32_t length, offset; + grub_off_t internal_position; + grub_size_t length; + grub_off_t offset; char *translation; + struct string_descriptor desc; + grub_err_t err; - offsettranslation = grub_gettext_get_info (GETTEXT_OFFSET_TRANSLATION); + internal_position = (off + position * sizeof (desc)); - internal_position = offsettranslation + position * 8; - - grub_gettext_pread (fd_mo, (char *) &length, 4, internal_position); - length = grub_cpu_to_le32 (length); - - grub_gettext_pread (fd_mo, (char *) &offset, 4, internal_position + 4); - offset = grub_cpu_to_le32 (offset); + err = grub_gettext_pread (fd_mo, (char *) &desc, + sizeof (desc), internal_position); + if (err) + return NULL; + length = grub_cpu_to_le32 (desc.length); + offset = grub_cpu_to_le32 (desc.offset); translation = grub_malloc (length + 1); - grub_gettext_getstring_from_offset (offset, length, translation); + if (!translation) + return NULL; + + err = grub_gettext_pread (fd_mo, translation, length, offset); + if (err) + { + grub_free (translation); + return NULL; + } + translation[length] = '\0'; return translation; } -static char * -grub_gettext_getstring_from_position (int position) +static const char * +grub_gettext_gettranslation_from_position (grub_size_t position) { - int internal_position; - int length, offset; - char *original; + if (!grub_gettext_msg_list[position].translated) + grub_gettext_msg_list[position].translated + = grub_gettext_getstr_from_position (grub_gettext_offset_translation, + position); + return grub_gettext_msg_list[position].translated; +} - /* Get position for string i. */ - internal_position = grub_gettext_offsetoriginal + (position * 8); - - /* Get the length of the string i. */ - grub_gettext_pread (fd_mo, (char *) &length, 4, internal_position); - - /* Get the offset of the string i. */ - grub_gettext_pread (fd_mo, (char *) &offset, 4, internal_position + 4); - - /* Get the string i. */ - original = grub_malloc (length + 1); - grub_gettext_getstring_from_offset (offset, length, original); - - return original; +static const char * +grub_gettext_getstring_from_position (grub_size_t position) +{ + if (!grub_gettext_msg_list[position].name) + grub_gettext_msg_list[position].name + = grub_gettext_getstr_from_position (grub_gettext_offset_original, + position); + return grub_gettext_msg_list[position].name; } static const char * grub_gettext_translate (const char *orig) { - char *current_string; - const char *ret; + grub_size_t current = 0; + int i; + const char *current_string; + static int depth = 0; - int min, max, current; - int found = 0; + if (!grub_gettext_msg_list || !fd_mo) + return orig; - struct grub_gettext_msg *cur; + /* Shouldn't happen. Just a precaution if our own code + calls gettext somehow. */ + if (depth > 2) + return orig; + depth++; /* Make sure we can use grub_gettext_translate for error messages. Push active error message to error stack and reset error message. */ grub_error_push (); - cur = grub_named_list_find (GRUB_AS_NAMED_LIST (grub_gettext_msg_list), - orig); - - if (cur) + for (i = grub_gettext_max_log; i >= 0; i--) { - grub_error_pop (); - return cur->translated; - } + grub_size_t test; + int cmp; - if (fd_mo == 0) - { - grub_error_pop (); - return orig; - } + test = current | (1 << i); + if (test >= grub_gettext_max) + continue; - min = 0; - max = grub_gettext_max; + current_string = grub_gettext_getstring_from_position (test); - current = (max + min) / 2; - - while (current != min && current != max && found == 0) - { - current_string = grub_gettext_getstring_from_position (current); + if (!current_string) + { + grub_errno = GRUB_ERR_NONE; + grub_error_pop (); + depth--; + return orig; + } /* Search by bisection. */ - if (grub_strcmp (current_string, orig) < 0) + cmp = grub_strcmp (current_string, orig); + if (cmp <= 0) + current = test; + if (cmp == 0) { - grub_free (current_string); - min = current; - } - else if (grub_strcmp (current_string, orig) > 0) - { - grub_free (current_string); - max = current; - } - else if (grub_strcmp (current_string, orig) == 0) - { - grub_free (current_string); - found = 1; - } - current = (max + min) / 2; - } - - ret = found ? grub_gettext_gettranslation_from_position (current) : orig; - - if (found) - { - cur = grub_zalloc (sizeof (*cur)); - - if (cur) - { - cur->name = grub_strdup (orig); - if (cur->name) + const char *ret = 0; + ret = grub_gettext_gettranslation_from_position (current); + if (!ret) { - cur->translated = ret; - grub_list_push (GRUB_AS_LIST_P (&grub_gettext_msg_list), - GRUB_AS_LIST (cur)); + grub_errno = GRUB_ERR_NONE; + grub_error_pop (); + depth--; + return orig; } + grub_error_pop (); + depth--; + return ret; } - else - grub_errno = GRUB_ERR_NONE; } grub_error_pop (); - return ret; -} - -/* This is similar to grub_file_open. */ -static grub_file_t -grub_mofile_open (const char *filename) -{ - int unsigned magic; - int version; - - /* Using fd_mo and not another variable because - it's needed for grub_gettext_get_info. */ - - fd_mo = grub_file_open (filename); - grub_errno = GRUB_ERR_NONE; - - if (!fd_mo) - { - grub_dprintf ("gettext", "Cannot read %s\n", filename); - return 0; - } - - magic = grub_gettext_get_info (GETTEXT_MAGIC_NUMBER); - - if (magic != MO_MAGIC_NUMBER) - { - grub_error (GRUB_ERR_BAD_FILE_TYPE, "mo: invalid mo file: %s", - filename); - grub_file_close (fd_mo); - fd_mo = 0; - return 0; - } - - version = grub_gettext_get_info (GETTEXT_FILE_FORMAT); - - if (version != 0) - { - grub_error (GRUB_ERR_BAD_FILE_TYPE, - "mo: invalid mo version in file: %s", filename); - fd_mo = 0; - return 0; - } - - return fd_mo; -} - -/* Returning grub_file_t would be more natural, but grub_mofile_open assigns - to fd_mo anyway ... */ -static void -grub_mofile_open_lang (const char *locale_dir, const char *locale) -{ - char *mo_file; - - /* mo_file e.g.: /boot/grub/locale/ca.mo */ - - mo_file = grub_xasprintf ("%s/%s.mo", locale_dir, locale); - if (!mo_file) - return; - - fd_mo = grub_mofile_open (mo_file); - - /* Will try adding .gz as well. */ - if (fd_mo == NULL) - { - char *mo_file_old; - mo_file_old = mo_file; - mo_file = grub_xasprintf ("%s.gz", mo_file); - grub_free (mo_file_old); - if (!mo_file) - return; - fd_mo = grub_mofile_open (mo_file); - } -} - -static void -grub_gettext_init_ext (const char *locale) -{ - const char *locale_dir; - - if (!locale) - return; - - locale_dir = grub_env_get ("locale_dir"); - if (locale_dir == NULL) - { - grub_dprintf ("gettext", "locale_dir variable is not set up.\n"); - return; - } - - fd_mo = NULL; - - grub_mofile_open_lang (locale_dir, locale); - - /* ll_CC didn't work, so try ll. */ - if (fd_mo == NULL) - { - char *lang = grub_strdup (locale); - char *underscore = grub_strchr (lang, '_'); - - if (underscore) - { - *underscore = '\0'; - grub_mofile_open_lang (locale_dir, lang); - } - - grub_free (lang); - } - - if (fd_mo) - { - grub_gettext_offsetoriginal = - grub_gettext_get_info (GETTEXT_OFFSET_ORIGINAL); - grub_gettext_max = grub_gettext_get_info (GETTEXT_NUMBER_OF_STRINGS); - - grub_gettext_original = grub_gettext; - grub_gettext = grub_gettext_translate; - } + depth--; + return orig; } static void grub_gettext_delete_list (void) { - while (grub_gettext_msg_list) + struct grub_gettext_msg *l = grub_gettext_msg_list; + grub_size_t i; + + if (!l) + return; + grub_gettext_msg_list = 0; + for (i = 0; i < grub_gettext_max; i++) + grub_free (l[i].name); + /* Don't delete the translated message because could be in use. */ + grub_free (l); +} + +/* This is similar to grub_file_open. */ +static grub_err_t +grub_mofile_open (const char *filename) +{ + struct header head; + grub_err_t err; + grub_file_t fd; + + /* Using fd_mo and not another variable because + it's needed for grub_gettext_get_info. */ + + fd = grub_file_open (filename); + + if (!fd) + return grub_errno; + + err = grub_gettext_pread (fd, &head, sizeof (head), 0); + if (err) { - grub_free ((char *) grub_gettext_msg_list->name); - grub_gettext_msg_list = grub_gettext_msg_list->next; - /* Don't delete the translated message because could be in use. */ + grub_file_close (fd); + return err; } + + if (head.magic != grub_cpu_to_le32_compile_time (MO_MAGIC_NUMBER)) + { + grub_file_close (fd); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "mo: invalid mo magic in file: %s", filename); + } + + if (head.version != 0) + { + grub_file_close (fd); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + "mo: invalid mo version in file: %s", filename); + } + + grub_gettext_offset_original = grub_le_to_cpu32 (head.offset_original); + grub_gettext_offset_translation = grub_le_to_cpu32 (head.offset_translation); + grub_gettext_max = grub_le_to_cpu32 (head.number_of_strings); + for (grub_gettext_max_log = 0; grub_gettext_max >> grub_gettext_max_log; + grub_gettext_max_log++); + if (fd_mo) + grub_file_close (fd_mo); + fd_mo = 0; + + grub_gettext_delete_list (); + grub_gettext_msg_list = grub_zalloc (grub_gettext_max + * sizeof (grub_gettext_msg_list[0])); + if (!grub_gettext_msg_list) + { + grub_file_close (fd); + return grub_errno; + } + fd_mo = fd; + if (grub_gettext != grub_gettext_translate) + { + grub_gettext_original = grub_gettext; + grub_gettext = grub_gettext_translate; + } + return 0; +} + +/* Returning grub_file_t would be more natural, but grub_mofile_open assigns + to fd_mo anyway ... */ +static grub_err_t +grub_mofile_open_lang (const char *part1, const char *part2, const char *locale) +{ + char *mo_file; + grub_err_t err; + + /* mo_file e.g.: /boot/grub/locale/ca.mo */ + + mo_file = grub_xasprintf ("%s%s/%s.mo", part1, part2, locale); + if (!mo_file) + return grub_errno; + + err = grub_mofile_open (mo_file); + + /* Will try adding .gz as well. */ + if (err) + { + char *mo_file_old; + grub_errno = GRUB_ERR_NONE; + mo_file_old = mo_file; + mo_file = grub_xasprintf ("%s.gz", mo_file); + grub_free (mo_file_old); + if (!mo_file) + return grub_errno; + err = grub_mofile_open (mo_file); + } + return err; +} + +static grub_err_t +grub_gettext_init_ext (const char *locale) +{ + const char *part1, *part2; + grub_err_t err; + + if (!locale) + return 0; + + part1 = grub_env_get ("locale_dir"); + part2 = ""; + if (!part1) + { + part1 = grub_env_get ("prefix"); + if (!part1) + return 0; + part2 = "/locale"; + } + + err = grub_mofile_open_lang (part1, part2, locale); + + /* ll_CC didn't work, so try ll. */ + if (err) + { + char *lang = grub_strdup (locale); + char *underscore = lang ? grub_strchr (lang, '_') : 0; + + if (underscore) + { + *underscore = '\0'; + grub_errno = GRUB_ERR_NONE; + err = grub_mofile_open_lang (part1, part2, lang); + } + + grub_free (lang); + } + return err; } static char * grub_gettext_env_write_lang (struct grub_env_var *var __attribute__ ((unused)), const char *val) { - grub_gettext_init_ext (val); - - grub_gettext_delete_list (); + grub_err_t err; + err = grub_gettext_init_ext (val); + if (err) + { + grub_print_error (); + return NULL; + } return grub_strdup (val); } @@ -363,7 +373,7 @@ grub_cmd_translate (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) { if (argc != 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "text to translate required"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); const char *translation; translation = grub_gettext_translate (args[0]); diff --git a/grub-core/gfxmenu/gfxmenu.c b/grub-core/gfxmenu/gfxmenu.c index 2f210e02b..3bd795138 100644 --- a/grub-core/gfxmenu/gfxmenu.c +++ b/grub-core/gfxmenu/gfxmenu.c @@ -36,6 +36,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -58,7 +59,8 @@ grub_gfxmenu_try (int entry, grub_menu_t menu, int nested) theme_path = grub_env_get ("theme"); if (! theme_path) - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "no theme specified"); + return grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), + "theme"); instance = grub_zalloc (sizeof (*instance)); if (!instance) diff --git a/grub-core/gfxmenu/gui_image.c b/grub-core/gfxmenu/gui_image.c index 60e4a46de..29784ed2d 100644 --- a/grub-core/gfxmenu/gui_image.c +++ b/grub-core/gfxmenu/gui_image.c @@ -151,11 +151,6 @@ rescale_image (grub_gui_image_t self) height, self->raw_bitmap, GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST); - if (grub_errno != GRUB_ERR_NONE) - { - grub_error_push (); - grub_error (grub_errno, "failed to scale bitmap for image component"); - } return grub_errno; } @@ -224,7 +219,7 @@ image_set_property (void *vself, const char *name, const char *value) /* Resolve to an absolute path. */ if (! self->theme_dir) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "unspecified theme_dir"); + return grub_error (GRUB_ERR_BUG, "unspecified theme_dir"); absvalue = grub_resolve_relative_path (self->theme_dir, value); if (! absvalue) return grub_errno; diff --git a/grub-core/gfxmenu/gui_label.c b/grub-core/gfxmenu/gui_label.c index a7dc95afc..688bea077 100644 --- a/grub-core/gfxmenu/gui_label.c +++ b/grub-core/gfxmenu/gui_label.c @@ -94,15 +94,17 @@ label_paint (void *vself, const grub_video_rect_t *region) if (self->align == align_left) left_x = 0; else if (self->align == align_center) - left_x = ((self->bounds.width - - grub_font_get_string_width (self->font, self->text)) - ) / 2; + left_x = (self->bounds.width + - grub_font_get_string_width (self->font, self->text)) / 2; else if (self->align == align_right) left_x = (self->bounds.width - grub_font_get_string_width (self->font, self->text)); else return; /* Invalid alignment. */ + if (left_x < 0 || left_x > (int) self->bounds.width) + left_x = 0; + grub_video_rect_t vpsave; grub_gui_set_viewport (&self->bounds, &vpsave); grub_font_draw_string (self->text, diff --git a/grub-core/gfxmenu/gui_list.c b/grub-core/gfxmenu/gui_list.c index 2ff6e0f97..1982d9a40 100644 --- a/grub-core/gfxmenu/gui_list.c +++ b/grub-core/gfxmenu/gui_list.c @@ -245,6 +245,7 @@ draw_menu (list_impl_t self, int num_shown_items) visible_index++, menu_index++) { int is_selected = (menu_index == self->view->selected); + struct grub_video_bitmap *icon; if (is_selected) { @@ -256,8 +257,8 @@ draw_menu (list_impl_t self, int num_shown_items) item_top - sel_toppad); } - struct grub_video_bitmap *icon; - if ((icon = get_item_icon (self, menu_index)) != 0) + 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, diff --git a/grub-core/gfxmenu/icon_manager.c b/grub-core/gfxmenu/icon_manager.c index 6990d05d4..45e8f7dea 100644 --- a/grub-core/gfxmenu/icon_manager.c +++ b/grub-core/gfxmenu/icon_manager.c @@ -169,11 +169,7 @@ try_loading_icon (grub_gfxmenu_icon_manager_t mgr, GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST); grub_video_bitmap_destroy (raw_bitmap); if (! scaled_bitmap) - { - grub_error_push (); - grub_error (grub_errno, "failed to scale icon"); - return 0; - } + return 0; return scaled_bitmap; } diff --git a/grub-core/gfxmenu/widget-box.c b/grub-core/gfxmenu/widget-box.c index 41ca7f536..18e2ef469 100644 --- a/grub-core/gfxmenu/widget-box.c +++ b/grub-core/gfxmenu/widget-box.c @@ -130,12 +130,6 @@ scale_pixmap (grub_gfxmenu_box_t self, int i, int w, int h) if (w != 0 && h != 0) grub_video_bitmap_create_scaled (scaled, w, h, raw, GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST); - if (grub_errno != GRUB_ERR_NONE) - { - grub_error_push (); - grub_error (grub_errno, - "failed to scale bitmap for styled box pixmap #%d", i); - } } return grub_errno; @@ -188,25 +182,65 @@ get_border_width (grub_gfxmenu_box_t self) static int get_left_pad (grub_gfxmenu_box_t self) { - return get_width (self->raw_pixmaps[BOX_PIXMAP_W]); + int v, c; + + v = get_width (self->raw_pixmaps[BOX_PIXMAP_W]); + c = get_width (self->raw_pixmaps[BOX_PIXMAP_NW]); + if (c > v) + v = c; + c = get_width (self->raw_pixmaps[BOX_PIXMAP_SW]); + if (c > v) + v = c; + + return v; } static int get_top_pad (grub_gfxmenu_box_t self) { - return get_height (self->raw_pixmaps[BOX_PIXMAP_N]); + int v, c; + + v = get_height (self->raw_pixmaps[BOX_PIXMAP_N]); + c = get_height (self->raw_pixmaps[BOX_PIXMAP_NW]); + if (c > v) + v = c; + c = get_height (self->raw_pixmaps[BOX_PIXMAP_NE]); + if (c > v) + v = c; + + return v; } static int get_right_pad (grub_gfxmenu_box_t self) { - return get_width (self->raw_pixmaps[BOX_PIXMAP_E]); + int v, c; + + v = get_width (self->raw_pixmaps[BOX_PIXMAP_E]); + c = get_width (self->raw_pixmaps[BOX_PIXMAP_NE]); + if (c > v) + v = c; + c = get_width (self->raw_pixmaps[BOX_PIXMAP_SE]); + if (c > v) + v = c; + + return v; } static int get_bottom_pad (grub_gfxmenu_box_t self) { - return get_height (self->raw_pixmaps[BOX_PIXMAP_S]); + int v, c; + + v = get_height (self->raw_pixmaps[BOX_PIXMAP_S]); + c = get_height (self->raw_pixmaps[BOX_PIXMAP_SW]); + if (c > v) + v = c; + c = get_height (self->raw_pixmaps[BOX_PIXMAP_SE]); + if (c > v) + v = c; + + return v; } static void diff --git a/grub-core/gnulib/regcomp.c b/grub-core/gnulib/regcomp.c index 86ca02b0c..083469ef3 100644 --- a/grub-core/gnulib/regcomp.c +++ b/grub-core/gnulib/regcomp.c @@ -555,7 +555,7 @@ regerror (int errcode, const regex_t *_Restrict_ preg, 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 = "unknown regexp error"; msg = gettext (__re_error_msgid + __re_error_msgid_idx[errcode]); @@ -776,7 +776,7 @@ re_compile_internal (regex_t *preg, const char * pattern, size_t length, if (dfa == NULL) return REG_ESPACE; preg->allocated = sizeof (re_dfa_t); - preg->buffer = (unsigned char *) dfa; + preg->buffer = dfa; } preg->used = sizeof (re_dfa_t); @@ -851,7 +851,7 @@ init_dfa (re_dfa_t *dfa, size_t pat_len) { __re_size_t table_size; #ifndef _LIBC - char *codeset_name; + const char *codeset_name; #endif #ifdef RE_ENABLE_I18N size_t max_i18n_object_size = MAX (sizeof (wchar_t), sizeof (wctype_t)); @@ -1119,7 +1119,7 @@ optimize_utf8 (re_dfa_t *dfa) } break; default: - abort (); + break; } if (mb_chars || has_period) diff --git a/grub-core/gnulib/regex.h b/grub-core/gnulib/regex.h index e8bd5496c..1c139d680 100644 --- a/grub-core/gnulib/regex.h +++ b/grub-core/gnulib/regex.h @@ -448,12 +448,15 @@ typedef enum compiled, the `re_nsub' field is available. All other fields are private to the regex routines. */ +struct re_dfa_t; +typedef struct re_dfa_t re_dfa_t; + struct re_pattern_buffer { /* Space that holds the compiled pattern. It is declared as `unsigned char *' because its elements are sometimes used as array indexes. */ - unsigned char *_REG_RE_NAME (buffer); + re_dfa_t *_REG_RE_NAME (buffer); /* Number of bytes to which `buffer' points. */ __re_long_size_t _REG_RE_NAME (allocated); diff --git a/grub-core/gnulib/regex_internal.h b/grub-core/gnulib/regex_internal.h index 5aa5aa287..e5b6679d1 100644 --- a/grub-core/gnulib/regex_internal.h +++ b/grub-core/gnulib/regex_internal.h @@ -413,10 +413,6 @@ 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)) diff --git a/grub-core/hello/hello.c b/grub-core/hello/hello.c index 2c9e90f72..0c595e2ef 100644 --- a/grub-core/hello/hello.c +++ b/grub-core/hello/hello.c @@ -33,7 +33,7 @@ grub_cmd_hello (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - grub_printf ("Hello World\n"); + grub_printf ("%s\n", _("Hello World")); return 0; } diff --git a/grub-core/io/bufio.c b/grub-core/io/bufio.c index adb38af56..2a315e2d8 100644 --- a/grub-core/io/bufio.c +++ b/grub-core/io/bufio.c @@ -35,6 +35,7 @@ struct grub_bufio grub_file_t file; grub_size_t block_size; grub_size_t buffer_len; + grub_off_t buffer_at; char buffer[0]; }; typedef struct grub_bufio *grub_bufio_t; @@ -70,6 +71,7 @@ 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; @@ -104,82 +106,82 @@ grub_buffile_open (const char *name, int size) static grub_ssize_t grub_bufio_read (grub_file_t file, char *buf, grub_size_t len) { - grub_size_t res = len; + grub_size_t res = 0; + grub_off_t next_buf; grub_bufio_t bufio = file->data; - grub_uint64_t pos; + grub_ssize_t really_read; - if ((file->offset >= bufio->file->offset) && - (file->offset < bufio->file->offset + bufio->buffer_len)) + if (file->size == GRUB_FILE_SIZE_UNKNOWN) + file->size = bufio->file->size; + + /* First part: use whatever we already have in the buffer. */ + if ((file->offset >= bufio->buffer_at) && + (file->offset < bufio->buffer_at + bufio->buffer_len)) { grub_size_t n; + grub_uint64_t pos; - pos = file->offset - bufio->file->offset; + pos = file->offset - bufio->buffer_at; n = bufio->buffer_len - pos; if (n > len) n = len; grub_memcpy (buf, &bufio->buffer[pos], n); len -= n; - if (! len) - return res; + res += n; buf += n; - bufio->file->offset += bufio->buffer_len; - pos = 0; } - else + if (len == 0) + return res; + + /* Need to read some more. */ + next_buf = (file->offset + res + len - 1) & ~((grub_off_t) bufio->block_size - 1); + /* Now read between file->offset + res and bufio->buffer_at. */ + if (file->offset + res < next_buf) { - bufio->file->offset = grub_divmod64 (file->offset, bufio->block_size, - &pos); - bufio->file->offset *= bufio->block_size; + grub_size_t read_now; + read_now = next_buf - (file->offset + res); + grub_file_seek (bufio->file, file->offset + res); + really_read = grub_file_read (bufio->file, buf, read_now); + if (really_read < 0) + return -1; + if (file->size == GRUB_FILE_SIZE_UNKNOWN) + file->size = bufio->file->size; + len -= really_read; + buf += really_read; + res += really_read; + + /* Partial read. File ended unexpectedly. Save the last chunk in buffer. + */ + if (really_read != (grub_ssize_t) read_now) + { + bufio->buffer_len = really_read; + if (bufio->buffer_len > bufio->block_size) + bufio->buffer_len = bufio->block_size; + bufio->buffer_at = file->offset + res - bufio->buffer_len; + grub_memcpy (&bufio->buffer[0], buf - bufio->buffer_len, + bufio->buffer_len); + return res; + } } - if (pos + len >= bufio->block_size) - { - if (pos) - { - grub_size_t n; - - bufio->file->fs->read (bufio->file, bufio->buffer, - bufio->block_size); - if (grub_errno) - return -1; - - n = bufio->block_size - pos; - grub_memcpy (buf, &bufio->buffer[pos], n); - len -= n; - buf += n; - bufio->file->offset += bufio->block_size; - pos = 0; - } - - while (len >= bufio->block_size) - { - bufio->file->fs->read (bufio->file, buf, bufio->block_size); - if (grub_errno) - return -1; - - len -= bufio->block_size; - buf += bufio->block_size; - bufio->file->offset += bufio->block_size; - } - - if (! len) - { - bufio->buffer_len = 0; - return res; - } - } - - bufio->buffer_len = bufio->file->size - bufio->file->offset; - if (bufio->buffer_len > bufio->block_size) - bufio->buffer_len = bufio->block_size; - - bufio->file->fs->read (bufio->file, bufio->buffer, bufio->buffer_len); - if (grub_errno) + /* Read into buffer. */ + grub_file_seek (bufio->file, next_buf); + really_read = grub_file_read (bufio->file, bufio->buffer, + bufio->block_size); + if (really_read < 0) return -1; + bufio->buffer_at = next_buf; + bufio->buffer_len = really_read; - grub_memcpy (buf, &bufio->buffer[pos], len); + if (file->size == GRUB_FILE_SIZE_UNKNOWN) + file->size = bufio->file->size; + + if (len > bufio->buffer_len) + len = bufio->buffer_len; + grub_memcpy (buf, &bufio->buffer[file->offset + res - next_buf], len); + res += len; return res; } diff --git a/grub-core/io/gzio.c b/grub-core/io/gzio.c index 7380221aa..cc81aaaa1 100644 --- a/grub-core/io/gzio.c +++ b/grub-core/io/gzio.c @@ -41,8 +41,8 @@ #include #include #include -#include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -65,9 +65,6 @@ struct grub_gzio /* If input is in memory following fields are used instead of file. */ grub_size_t mem_input_size, mem_input_off; grub_uint8_t *mem_input; - grub_disk_addr_t disk_input_off; - grub_disk_addr_t disk_input_start; - grub_disk_t disk_input; /* The offset at which the data starts in the underlying file. */ grub_off_t data_offset; /* The type of current block. */ @@ -197,10 +194,7 @@ test_gzip_header (grub_file_t file) if (grub_file_read (gzio->file, &hdr, 10) != 10 || ((hdr.magic != GZIP_MAGIC) && (hdr.magic != OLD_GZIP_MAGIC))) - { - grub_error (GRUB_ERR_BAD_FILE_TYPE, "no gzip magic found"); - return 0; - } + return 0; /* * This does consistency checking on the header data. If a @@ -215,10 +209,7 @@ test_gzip_header (grub_file_t file) grub_le_to_cpu16 (extra_len)))) || ((hdr.flags & ORIG_NAME) && eat_field (gzio->file, -1)) || ((hdr.flags & COMMENT) && eat_field (gzio->file, -1))) - { - grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "unsupported gzip format"); - return 0; - } + return 0; gzio->data_offset = grub_file_tell (gzio->file); @@ -226,10 +217,7 @@ test_gzip_header (grub_file_t file) { grub_file_seek (gzio->file, grub_file_size (gzio->file) - 4); if (grub_file_read (gzio->file, &orig_len, 4) != 4) - { - grub_error (GRUB_ERR_BAD_FILE_TYPE, "unsupported gzip format"); - return 0; - } + return 0; /* FIXME: this does not handle files whose original size is over 4GB. But how can we know the real original size? */ file->size = grub_le_to_cpu32 (orig_len); @@ -388,18 +376,6 @@ get_byte (grub_gzio_t gzio) return 0; } - if (gzio->disk_input && (gzio->disk_input_off == gzio->data_offset - || gzio->inbuf_d == INBUFSIZ)) - { - grub_disk_addr_t d = gzio->disk_input_start + gzio->disk_input_off; - gzio->inbuf_d = 0; - grub_disk_read (gzio->disk_input, - d >> GRUB_DISK_SECTOR_BITS, - d & (GRUB_DISK_SECTOR_SIZE - 1), - INBUFSIZ, gzio->inbuf); - gzio->disk_input_off += INBUFSIZ; - } - if (gzio->file && (grub_file_tell (gzio->file) == (grub_off_t) gzio->data_offset || gzio->inbuf_d == INBUFSIZ)) @@ -418,12 +394,10 @@ gzio_seek (grub_gzio_t gzio, grub_off_t off) { if (off > gzio->mem_input_size) grub_error (GRUB_ERR_OUT_OF_RANGE, - "attempt to seek outside of the file"); + N_("attempt to seek outside of the file")); else gzio->mem_input_off = off; } - else if (gzio->disk_input) - gzio->disk_input_off = off; else grub_file_seek (gzio->file, off); } @@ -1176,10 +1150,10 @@ grub_gzio_open (grub_file_t io) if (! test_gzip_header (file)) { + grub_errno = GRUB_ERR_NONE; grub_free (gzio); grub_free (file); grub_file_seek (io, 0); - grub_errno = GRUB_ERR_NONE; return io; } @@ -1198,20 +1172,20 @@ test_zlib_header (grub_gzio_t gzio) /* Check that compression method is DEFLATE. */ if ((cmf & 0xf) != DEFLATED) { - grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "unsupported gzip format"); + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, N_("unsupported gzip format")); return 0; } if ((cmf * 256 + flg) % 31) { - grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "unsupported gzip format"); + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, N_("unsupported gzip format")); return 0; } /* Dictionary isn't supported. */ if (flg & 0x20) { - grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "unsupported gzip format"); + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, N_("unsupported gzip format")); return 0; } @@ -1314,34 +1288,6 @@ grub_zlib_decompress (char *inbuf, grub_size_t insize, grub_off_t off, return ret; } -grub_err_t -grub_zlib_disk_read (grub_disk_t disk, grub_disk_addr_t zlibstart, - grub_off_t off, char *outbuf, grub_size_t outsize) -{ - grub_gzio_t gzio = 0; - grub_ssize_t ret; - - gzio = grub_zalloc (sizeof (*gzio)); - if (! gzio) - return -1; - - gzio->disk_input_off = 0; - gzio->disk_input_start = zlibstart; - gzio->disk_input = disk; - - if (!test_zlib_header (gzio)) - { - grub_free (gzio); - return -1; - } - - ret = grub_gzio_read_real (gzio, off, outbuf, outsize); - grub_free (gzio); - - /* FIXME: Check Adler. */ - return ret < 0 ? grub_errno : GRUB_ERR_NONE; -} - static struct grub_fs grub_gzio_fs = diff --git a/grub-core/io/lzopio.c b/grub-core/io/lzopio.c index bd6f8e738..9f0dba5dc 100644 --- a/grub-core/io/lzopio.c +++ b/grub-core/io/lzopio.c @@ -212,7 +212,7 @@ uncompress_block (struct grub_lzopio *lzopio) if (lzopio->ucheck_fun) { - grub_uint64_t context[(lzopio->ccheck_fun->contextsize + 7) / 8]; + grub_uint64_t context[(lzopio->ucheck_fun->contextsize + 7) / 8]; lzopio->ucheck_fun->init (context); lzopio->ucheck_fun->write (context, lzopio->block.udata, @@ -299,31 +299,17 @@ test_header (grub_file_t file) grub_uint8_t *name = NULL; if (grub_file_read (lzopio->file, &header, sizeof (header)) != sizeof (header)) - { - grub_error (GRUB_ERR_BAD_FILE_TYPE, "no lzop magic found"); - return 0; - } + return 0; if (grub_memcmp (header.magic, LZOP_MAGIC, LZOP_MAGIC_SIZE) != 0) - { - grub_error (GRUB_ERR_BAD_FILE_TYPE, "no lzop magic found"); - return 0; - } + return 0; if (grub_be_to_cpu16(header.lib_version) < LZOP_NEW_LIB) - { - grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, - "unsupported (too old) LZOP version"); - return 0; - } + return 0; /* Too new version, should upgrade minilzo? */ if (grub_be_to_cpu16 (header.lib_version_ext) > MINILZO_VERSION) - { - grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, - "unsupported (too new) LZO version"); - return 0; - } + return 0; flags = grub_be_to_cpu32 (header.flags); @@ -417,8 +403,6 @@ test_header (grub_file_t file) return 1; CORRUPTED: - grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "lzop file corrupted"); - grub_free(name); return 0; @@ -500,14 +484,16 @@ grub_lzopio_read (grub_file_t file, char *buf, grub_size_t len) while (len != 0 && lzopio->block.usize != 0) { - long to_copy; + grub_size_t to_copy; /* Block not decompressed yet. */ if (!lzopio->block.udata && uncompress_block (lzopio) < 0) goto CORRUPTED; /* Copy requested data into buffer. */ - to_copy = grub_min (lzopio->block.usize - off, len); + to_copy = lzopio->block.usize - off; + if (to_copy > len) + to_copy = len; grub_memcpy (buf, lzopio->block.udata + off, to_copy); len -= to_copy; @@ -523,7 +509,7 @@ grub_lzopio_read (grub_file_t file, char *buf, grub_size_t len) return ret; CORRUPTED: - grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "lzop file corrupted"); + grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, N_("lzop file corrupted")); return -1; } diff --git a/grub-core/io/xzio.c b/grub-core/io/xzio.c index 1575ca236..ae30e6f80 100644 --- a/grub-core/io/xzio.c +++ b/grub-core/io/xzio.c @@ -98,24 +98,15 @@ test_header (grub_file_t file) STREAM_HEADER_SIZE); if (xzio->buf.in_size != STREAM_HEADER_SIZE) - { - grub_error (GRUB_ERR_BAD_FILE_TYPE, "no xz magic found"); - return 0; - } + return 0; ret = xz_dec_run (xzio->dec, &xzio->buf); if (ret == XZ_FORMAT_ERROR) - { - grub_error (GRUB_ERR_BAD_FILE_TYPE, "no xz magic found"); - return 0; - } + return 0; if (ret != XZ_OK) - { - grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "not supported xz options"); - return 0; - } + return 0; return 1; } @@ -174,7 +165,6 @@ test_footer (grub_file_t file) return 1; ERROR: - grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "bad footer magic"); return 0; } @@ -266,9 +256,9 @@ grub_xzio_read (grub_file_t file, char *buf, grub_size_t len) while (len > 0) { - xzio->buf.out_size = grub_min (file->offset + ret + len - current_offset, - XZBUFSIZ); - + xzio->buf.out_size = file->offset + ret + len - current_offset; + if (xzio->buf.out_size > XZBUFSIZ) + xzio->buf.out_size = XZBUFSIZ; /* Feed input. */ if (xzio->buf.in_pos == xzio->buf.in_size) { @@ -288,7 +278,7 @@ grub_xzio_read (grub_file_t file, char *buf, grub_size_t len) case XZ_DATA_ERROR: case XZ_BUF_ERROR: grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, - "file corrupted or unsupported block options"); + N_("xz file corrupted or unsupported block options")); return -1; default: break; diff --git a/grub-core/kern/command.c b/grub-core/kern/command.c index 7f353b653..91e469181 100644 --- a/grub-core/kern/command.c +++ b/grub-core/kern/command.c @@ -52,7 +52,6 @@ grub_register_command_prio (const char *name, void grub_unregister_command (grub_command_t cmd) { - grub_prio_list_remove (GRUB_AS_PRIO_LIST_P (&grub_command_list), - GRUB_AS_PRIO_LIST (cmd)); + grub_prio_list_remove (GRUB_AS_PRIO_LIST (cmd)); grub_free (cmd); } diff --git a/grub-core/kern/corecmd.c b/grub-core/kern/corecmd.c index 687692f3c..0ec6bdd28 100644 --- a/grub-core/kern/corecmd.c +++ b/grub-core/kern/corecmd.c @@ -68,7 +68,7 @@ grub_core_cmd_unset (struct grub_command *cmd __attribute__ ((unused)), { if (argc < 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, - "no environment variable specified"); + N_("one argument expected")); grub_env_unset (argv[0]); return 0; @@ -83,7 +83,7 @@ grub_core_cmd_insmod (struct grub_command *cmd __attribute__ ((unused)), grub_dl_t mod; if (argc == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); p = grub_strchr (argv[0], '/'); if (! p) @@ -133,6 +133,8 @@ grub_core_cmd_ls (struct grub_command *cmd __attribute__ ((unused)), char *path; device_name = grub_file_get_device_name (argv[0]); + if (grub_errno) + goto fail; dev = grub_device_open (device_name); if (! dev) goto fail; diff --git a/grub-core/kern/device.c b/grub-core/kern/device.c index c998d4d4b..7ba09b03f 100644 --- a/grub-core/kern/device.c +++ b/grub-core/kern/device.c @@ -25,6 +25,7 @@ #include #include #include +#include grub_net_t (*grub_net_open) (const char *name) = NULL; @@ -39,7 +40,7 @@ grub_device_open (const char *name) name = grub_env_get ("root"); if (name == NULL || *name == '\0') { - grub_error (GRUB_ERR_BAD_DEVICE, "no device is set"); + grub_error (GRUB_ERR_BAD_DEVICE, N_("variable `%s' isn't set"), "root"); goto fail; } } diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c index 460d8778f..7207cb9d9 100644 --- a/grub-core/kern/disk.c +++ b/grub-core/kern/disk.c @@ -24,6 +24,7 @@ #include #include #include +#include #define GRUB_CACHE_TIMEOUT 2 @@ -177,7 +178,7 @@ grub_disk_cache_store (unsigned long dev_id, unsigned long disk_id, -static grub_disk_dev_t grub_disk_dev_list; +grub_disk_dev_t grub_disk_dev_list; void grub_disk_dev_register (grub_disk_dev_t dev) @@ -199,20 +200,6 @@ grub_disk_dev_unregister (grub_disk_dev_t dev) } } -int -grub_disk_dev_iterate (int (*hook) (const char *name)) -{ - grub_disk_dev_t p; - grub_disk_pull_t pull; - - for (pull = 0; pull < GRUB_DISK_PULL_MAX; pull++) - for (p = grub_disk_dev_list; p; p = p->next) - if (p->iterate && (p->iterate) (hook, pull)) - return 1; - - return 0; -} - /* Return the location of the first ',', if any, which is not escaped by a '\'. */ static const char * @@ -277,7 +264,8 @@ grub_disk_open (const char *name) if (! dev) { - grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such disk"); + grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("disk `%s' not found"), + name); goto fail; } if (disk->log_sector_size > GRUB_DISK_CACHE_BITS + GRUB_DISK_SECTOR_BITS @@ -296,7 +284,7 @@ grub_disk_open (const char *name) disk->partition = grub_partition_probe (disk, p + 1); if (! disk->partition) { - grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such partition"); + grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("no such partition")); goto fail; } } @@ -374,7 +362,8 @@ grub_disk_adjust_range (grub_disk_t disk, grub_disk_addr_t *sector, if (*sector >= len || len - *sector < ((*offset + size + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS)) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of partition"); + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("attempt to read or write outside of partition")); *sector += start; } @@ -385,7 +374,8 @@ grub_disk_adjust_range (grub_disk_t disk, grub_disk_addr_t *sector, >> GRUB_DISK_SECTOR_BITS) > (disk->total_sectors << (disk->log_sector_size - GRUB_DISK_SECTOR_BITS)) - *sector)) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "out of disk"); + return grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("attempt to read or write outside of disk `%s'"), disk->name); return GRUB_ERR_NONE; } @@ -607,12 +597,13 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, while (l) { - (disk->read_hook) (s, o, - ((l > GRUB_DISK_SECTOR_SIZE) - ? GRUB_DISK_SECTOR_SIZE - : l)); + grub_size_t cl; + cl = GRUB_DISK_SECTOR_SIZE - o; + if (cl > l) + cl = l; + (disk->read_hook) (s, o, cl); s++; - l -= GRUB_DISK_SECTOR_SIZE - o; + l -= cl; o = 0; } } diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c index 26cf0d21d..aff4c095b 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -31,6 +31,7 @@ #include #include #include +#include /* Platforms where modules are in a readonly area of memory. */ #if defined(GRUB_MACHINE_QEMU) @@ -43,6 +44,8 @@ +#pragma GCC diagnostic ignored "-Wcast-align" + grub_dl_t grub_dl_head = 0; static grub_err_t @@ -208,20 +211,24 @@ static grub_err_t grub_dl_check_header (void *ehdr, grub_size_t size) { Elf_Ehdr *e = ehdr; + grub_err_t err; /* Check the header size. */ if (size < sizeof (Elf_Ehdr)) return grub_error (GRUB_ERR_BAD_OS, "ELF header smaller than expected"); /* Check the magic numbers. */ - if (grub_arch_dl_check_header (ehdr) - || e->e_ident[EI_MAG0] != ELFMAG0 + if (e->e_ident[EI_MAG0] != ELFMAG0 || e->e_ident[EI_MAG1] != ELFMAG1 || e->e_ident[EI_MAG2] != ELFMAG2 || e->e_ident[EI_MAG3] != ELFMAG3 || e->e_ident[EI_VERSION] != EV_CURRENT || e->e_version != EV_CURRENT) - return grub_error (GRUB_ERR_BAD_OS, "invalid arch independent ELF magic"); + return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch independent ELF magic")); + + err = grub_arch_dl_check_header (ehdr); + if (err) + return err; return GRUB_ERR_NONE; } @@ -243,7 +250,7 @@ grub_dl_load_segments (grub_dl_t mod, const Elf_Ehdr *e) i < e->e_shnum; i++, s = (Elf_Shdr *)((char *) s + e->e_shentsize)) { - tsize += ALIGN_UP (s->sh_size, s->sh_addralign); + tsize = ALIGN_UP (tsize, s->sh_addralign) + s->sh_size; if (talign < s->sh_addralign) talign = s->sh_addralign; } @@ -345,7 +352,7 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e) break; if (i == e->e_shnum) - return grub_error (GRUB_ERR_BAD_MODULE, "no symbol table"); + return grub_error (GRUB_ERR_BAD_MODULE, N_("no symbol table")); #ifdef GRUB_MODULES_MACHINE_READONLY mod->symtab = grub_malloc (s->sh_size); @@ -378,7 +385,7 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e) grub_symbol_t nsym = grub_dl_resolve_symbol (name); if (! nsym) return grub_error (GRUB_ERR_BAD_MODULE, - "symbol not found: `%s'", name); + N_("symbol `%s' not found"), name); sym->st_value = (Elf_Addr) nsym->addr; if (nsym->isfunc) sym->st_info = ELF_ST_INFO (bind, STT_FUNC); @@ -596,7 +603,7 @@ grub_dl_load_core (void *addr, grub_size_t size) if (e->e_type != ET_REL) { - grub_error (GRUB_ERR_BAD_MODULE, "invalid ELF file type"); + grub_error (GRUB_ERR_BAD_MODULE, N_("this ELF file is not of the right type")); return 0; } @@ -704,11 +711,12 @@ grub_dl_load (const char *name) return mod; if (! grub_dl_dir) { - grub_error (GRUB_ERR_FILE_NOT_FOUND, "\"prefix\" is not set"); + grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("variable `%s' isn't set"), "prefix"); return 0; } - filename = grub_xasprintf ("%s/%s.mod", grub_dl_dir, name); + filename = grub_xasprintf ("%s/" GRUB_TARGET_CPU "-" GRUB_PLATFORM "/%s.mod", + grub_dl_dir, name); if (! filename) return 0; @@ -729,7 +737,6 @@ int grub_dl_unload (grub_dl_t mod) { grub_dl_dep_t dep, depn; - grub_dl_segment_t seg, segn; if (mod->ref_count > 0) return 0; @@ -749,13 +756,7 @@ grub_dl_unload (grub_dl_t mod) grub_free (dep); } - for (seg = mod->segment; seg; seg = segn) - { - segn = seg->next; - grub_free (seg->addr); - grub_free (seg); - } - + grub_free (mod->base); grub_free (mod->name); #ifdef GRUB_MODULES_MACHINE_READONLY grub_free (mod->symtab); diff --git a/grub-core/kern/efi/efi.c b/grub-core/kern/efi/efi.c index 9a2c5e64d..6600f8b97 100644 --- a/grub-core/kern/efi/efi.c +++ b/grub-core/kern/efi/efi.c @@ -203,6 +203,8 @@ grub_get_rtc (void) return grub_rtc_get_time_ms (); } +#pragma GCC diagnostic ignored "-Wcast-align" + /* Search the mods section from the PE32/PE32+ image. This code uses a PE32 header, but should work with PE32+ as well. */ grub_addr_t @@ -246,6 +248,8 @@ grub_efi_modules_addr (void) return (grub_addr_t) info; } +#pragma GCC diagnostic error "-Wcast-align" + char * grub_efi_get_filename (grub_efi_device_path_t *dp) { diff --git a/grub-core/kern/elf.c b/grub-core/kern/elf.c index 9c7b8cec2..dcf10c64e 100644 --- a/grub-core/kern/elf.c +++ b/grub-core/kern/elf.c @@ -24,6 +24,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -39,7 +40,7 @@ grub_elf_check_header (grub_elf_t elf) || e->e_ident[EI_MAG3] != ELFMAG3 || e->e_ident[EI_VERSION] != EV_CURRENT || e->e_version != EV_CURRENT) - return grub_error (GRUB_ERR_BAD_OS, "invalid arch independent ELF magic"); + return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch independent ELF magic")); return GRUB_ERR_NONE; } @@ -59,7 +60,7 @@ grub_elf_close (grub_elf_t elf) } grub_elf_t -grub_elf_file (grub_file_t file) +grub_elf_file (grub_file_t file, const char *filename) { grub_elf_t elf; @@ -75,8 +76,9 @@ grub_elf_file (grub_file_t file) if (grub_file_read (elf->file, &elf->ehdr, sizeof (elf->ehdr)) != sizeof (elf->ehdr)) { - grub_error_push (); - grub_error (GRUB_ERR_READ_ERROR, "cannot read ELF header"); + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), + filename); goto fail; } @@ -101,7 +103,7 @@ grub_elf_open (const char *name) if (! file) return 0; - elf = grub_elf_file (file); + elf = grub_elf_file (file, name); if (! elf) grub_file_close (file); @@ -118,7 +120,7 @@ grub_elf_is_elf32 (grub_elf_t elf) } static grub_err_t -grub_elf32_load_phdrs (grub_elf_t elf) +grub_elf32_load_phdrs (grub_elf_t elf, const char *filename) { grub_ssize_t phdrs_size; @@ -135,8 +137,10 @@ grub_elf32_load_phdrs (grub_elf_t elf) 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)) { - grub_error_push (); - return grub_error (GRUB_ERR_READ_ERROR, "cannot read program headers"); + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), + filename); + return grub_errno; } return GRUB_ERR_NONE; @@ -144,6 +148,7 @@ grub_elf32_load_phdrs (grub_elf_t elf) 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) { @@ -151,7 +156,7 @@ grub_elf32_phdr_iterate (grub_elf_t elf, unsigned int i; if (! elf->phdrs) - if (grub_elf32_load_phdrs (elf)) + if (grub_elf32_load_phdrs (elf, filename)) return grub_errno; phdrs = elf->phdrs; @@ -174,7 +179,8 @@ grub_elf32_phdr_iterate (grub_elf_t elf, /* Calculate the amount of memory spanned by the segments. */ grub_size_t -grub_elf32_size (grub_elf_t elf, Elf32_Addr *base, grub_uint32_t *max_align) +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; @@ -201,7 +207,7 @@ grub_elf32_size (grub_elf_t elf, Elf32_Addr *base, grub_uint32_t *max_align) return 0; } - grub_elf32_phdr_iterate (elf, calcsize, 0); + grub_elf32_phdr_iterate (elf, filename, calcsize, 0); if (base) *base = 0; @@ -228,7 +234,8 @@ grub_elf32_size (grub_elf_t elf, Elf32_Addr *base, grub_uint32_t *max_align) /* Load every loadable segment into memory specified by `_load_hook'. */ grub_err_t -grub_elf32_load (grub_elf_t _elf, grub_elf32_load_hook_t _load_hook, +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; @@ -257,11 +264,7 @@ grub_elf32_load (grub_elf_t _elf, grub_elf32_load_hook_t _load_hook, (unsigned long long) phdr->p_memsz); if (grub_file_seek (elf->file, phdr->p_offset) == (grub_off_t) -1) - { - grub_error_push (); - return grub_error (GRUB_ERR_BAD_OS, - "invalid offset in program header"); - } + return grub_errno; if (phdr->p_filesz) { @@ -270,11 +273,10 @@ grub_elf32_load (grub_elf_t _elf, grub_elf32_load_hook_t _load_hook, if (read != (grub_ssize_t) phdr->p_filesz) { /* XXX How can we free memory from `load_hook'? */ - grub_error_push (); - return grub_error (GRUB_ERR_BAD_OS, - "couldn't read segment from file: " - "wanted 0x%lx bytes; read 0x%lx bytes", - phdr->p_filesz, read); + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), + filename); + return grub_errno; } } @@ -287,7 +289,8 @@ grub_elf32_load (grub_elf_t _elf, grub_elf32_load_hook_t _load_hook, return 0; } - err = grub_elf32_phdr_iterate (_elf, grub_elf32_load_segment, _load_hook); + err = grub_elf32_phdr_iterate (_elf, filename, + grub_elf32_load_segment, _load_hook); if (base) *base = load_base; @@ -307,7 +310,7 @@ grub_elf_is_elf64 (grub_elf_t elf) } static grub_err_t -grub_elf64_load_phdrs (grub_elf_t elf) +grub_elf64_load_phdrs (grub_elf_t elf, const char *filename) { grub_ssize_t phdrs_size; @@ -324,8 +327,10 @@ grub_elf64_load_phdrs (grub_elf_t elf) 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)) { - grub_error_push (); - return grub_error (GRUB_ERR_READ_ERROR, "cannot read program headers"); + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), + filename); + return grub_errno; } return GRUB_ERR_NONE; @@ -333,6 +338,7 @@ grub_elf64_load_phdrs (grub_elf_t elf) 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) { @@ -340,7 +346,7 @@ grub_elf64_phdr_iterate (grub_elf_t elf, unsigned int i; if (! elf->phdrs) - if (grub_elf64_load_phdrs (elf)) + if (grub_elf64_load_phdrs (elf, filename)) return grub_errno; phdrs = elf->phdrs; @@ -363,7 +369,8 @@ grub_elf64_phdr_iterate (grub_elf_t elf, /* Calculate the amount of memory spanned by the segments. */ grub_size_t -grub_elf64_size (grub_elf_t elf, Elf64_Addr *base, grub_uint64_t *max_align) +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; @@ -390,7 +397,7 @@ grub_elf64_size (grub_elf_t elf, Elf64_Addr *base, grub_uint64_t *max_align) return 0; } - grub_elf64_phdr_iterate (elf, calcsize, 0); + grub_elf64_phdr_iterate (elf, filename, calcsize, 0); if (base) *base = 0; @@ -417,7 +424,8 @@ grub_elf64_size (grub_elf_t elf, Elf64_Addr *base, grub_uint64_t *max_align) /* Load every loadable segment into memory specified by `_load_hook'. */ grub_err_t -grub_elf64_load (grub_elf_t _elf, grub_elf64_load_hook_t _load_hook, +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; @@ -447,11 +455,7 @@ grub_elf64_load (grub_elf_t _elf, grub_elf64_load_hook_t _load_hook, (unsigned long long) phdr->p_memsz); if (grub_file_seek (elf->file, phdr->p_offset) == (grub_off_t) -1) - { - grub_error_push (); - return grub_error (GRUB_ERR_BAD_OS, - "invalid offset in program header"); - } + return grub_errno; if (phdr->p_filesz) { @@ -460,11 +464,10 @@ grub_elf64_load (grub_elf_t _elf, grub_elf64_load_hook_t _load_hook, if (read != (grub_ssize_t) phdr->p_filesz) { /* XXX How can we free memory from `load_hook'? */ - grub_error_push (); - return grub_error (GRUB_ERR_BAD_OS, - "couldn't read segment from file: " - "wanted 0x%lx bytes; read 0x%lx bytes", - phdr->p_filesz, read); + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), + filename); + return grub_errno; } } @@ -477,7 +480,8 @@ grub_elf64_load (grub_elf_t _elf, grub_elf64_load_hook_t _load_hook, return 0; } - err = grub_elf64_phdr_iterate (_elf, grub_elf64_load_segment, _load_hook); + err = grub_elf64_phdr_iterate (_elf, filename, + grub_elf64_load_segment, _load_hook); if (base) *base = load_base; diff --git a/grub-core/kern/emu/full.c b/grub-core/kern/emu/full.c index 87317c916..b167a141b 100644 --- a/grub-core/kern/emu/full.c +++ b/grub-core/kern/emu/full.c @@ -50,7 +50,7 @@ grub_emu_init (void) grub_no_autoload = 1; } -#ifdef __ia64__ +#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) { @@ -69,12 +69,4 @@ grub_arch_dl_init_linker (void) void grub_emu_post_init (void) { - grub_lvm_fini (); - grub_mdraid09_fini (); - grub_mdraid1x_fini (); - grub_raid_fini (); - grub_raid_init (); - grub_mdraid09_init (); - grub_mdraid1x_init (); - grub_lvm_init (); } diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index da2cc6aa2..46e751e33 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -68,26 +68,12 @@ struct hd_geometry # ifndef BLKGETSIZE64 # define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size */ # endif /* ! BLKGETSIZE64 */ -# ifndef MAJOR -# ifndef MINORBITS -# define MINORBITS 8 -# endif /* ! MINORBITS */ -# define MAJOR(dev) ((unsigned) ((dev) >> MINORBITS)) -# endif /* ! MAJOR */ -# ifndef FLOPPY_MAJOR -# define FLOPPY_MAJOR 2 -# endif /* ! FLOPPY_MAJOR */ -# ifndef LOOP_MAJOR -# define LOOP_MAJOR 7 -# endif /* ! LOOP_MAJOR */ #endif /* __linux__ */ #ifdef __CYGWIN__ # include # include /* BLKGETSIZE64 */ # include /* HDIO_GETGEO */ -# define MAJOR(dev) ((unsigned) ((dev) >> 16)) -# define FLOPPY_MAJOR 2 #endif #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) @@ -96,8 +82,6 @@ struct hd_geometry # include # include #include -# define MAJOR(dev) major(dev) -# define FLOPPY_MAJOR 2 #endif #if defined (__sun__) @@ -116,6 +100,7 @@ struct hd_geometry # 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__) */ @@ -125,9 +110,6 @@ struct hd_geometry # include /* getrawpartition */ # endif /* HAVE_GETRAWPARTITION */ # include -# ifndef FLOPPY_MAJOR -# define FLOPPY_MAJOR 2 -# endif /* ! FLOPPY_MAJOR */ # ifndef RAW_FLOPPY_MAJOR # define RAW_FLOPPY_MAJOR 9 # endif /* ! RAW_FLOPPY_MAJOR */ @@ -137,6 +119,7 @@ struct { char *drive; char *device; + int device_map; } map[256]; struct grub_util_biosdisk_data @@ -145,6 +128,7 @@ struct grub_util_biosdisk_data int access_mode; int fd; int is_disk; + int device_map; }; #ifdef __linux__ @@ -256,7 +240,7 @@ grub_util_biosdisk_iterate (int (*hook) (const char *name), #if !defined(__MINGW32__) grub_uint64_t -grub_util_get_fd_sectors (int fd, unsigned *log_secsize) +grub_util_get_fd_sectors (int fd, const char *name, unsigned *log_secsize) { # if defined(__NetBSD__) struct disklabel label; @@ -269,7 +253,7 @@ grub_util_get_fd_sectors (int fd, unsigned *log_secsize) struct stat st; if (fstat (fd, &st) < 0) - grub_util_error (_("fstat failed")); + grub_util_error (_("cannot stat `%s': %s"), name, strerror (errno)); #if defined(__linux__) || defined(__CYGWIN__) || defined(__FreeBSD__) || \ defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) \ @@ -324,7 +308,7 @@ grub_util_get_fd_sectors (int fd, unsigned *log_secsize) return minfo.dki_capacity; # else if (nr & ((1 << log_sector_size) - 1)) - grub_util_error (_("unaligned device size")); + grub_util_error ("%s", _("unaligned device size")); return (nr >> log_sector_size); # endif @@ -364,6 +348,7 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk) data->access_mode = 0; data->fd = -1; data->is_disk = 0; + data->device_map = map[drive].device_map; /* Get the size. */ #if defined(__MINGW32__) @@ -387,9 +372,11 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk) fd = open (map[drive].device, O_RDONLY); if (fd == -1) - return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "cannot open `%s' while attempting to get disk size", map[drive].device); + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("cannot open `%s': %s"), + map[drive].device, strerror (errno)); - disk->total_sectors = grub_util_get_fd_sectors (fd, &disk->log_sector_size); + disk->total_sectors = grub_util_get_fd_sectors (fd, map[drive].device, + &disk->log_sector_size); # if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) if (fstat (fd, &st) < 0 || ! S_ISCHR (st.st_mode)) @@ -400,7 +387,8 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk) close (fd); - grub_util_info ("the size of %s is %llu", name, disk->total_sectors); + grub_util_info ("the size of %s is %" PRIuGRUB_UINT64_T, + name, disk->total_sectors); return GRUB_ERR_NONE; } @@ -442,13 +430,19 @@ grub_util_follow_gpart_up (const char *name, grub_disk_addr_t *off_out, char **n error = geom_gettree (&mesh); if (error != 0) + /* TRANSLATORS: geom is the name of (k)FreeBSD device framework. + Usually left untranslated. + */ grub_util_error (_("couldn't open geom")); LIST_FOREACH (class, &mesh.lg_class, lg_class) if (strcasecmp (class->lg_name, "part") == 0) break; if (!class) - grub_util_error (_("couldn't open geom part")); + /* TRANSLATORS: geom is the name of (k)FreeBSD device framework. + Usually left untranslated. + */ + grub_util_error (_("couldn't find geom `part' class")); LIST_FOREACH (geom, &class->lg_geom, lg_geom) { @@ -478,8 +472,8 @@ grub_util_follow_gpart_up (const char *name, grub_disk_addr_t *off_out, char **n *off_out = 0; } -static grub_disk_addr_t -find_partition_start (const char *dev) +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) @@ -490,8 +484,8 @@ find_partition_start (const char *dev) } #elif defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO) || defined (__sun__) -static grub_disk_addr_t -find_partition_start (const char *dev) +grub_disk_addr_t +grub_hostdisk_find_partition_start (const char *dev) { int fd; #ifdef __sun__ @@ -499,6 +493,9 @@ find_partition_start (const char *dev) # 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) */ @@ -574,12 +571,8 @@ devmapper_fail: fd = open (dev, O_RDONLY); if (fd == -1) { - grub_error (GRUB_ERR_BAD_DEVICE, -# if !defined(HAVE_DIOCGDINFO) - "cannot open `%s' while attempting to get disk geometry", dev); -# else /* defined(HAVE_DIOCGDINFO) */ - "cannot open `%s' while attempting to get disk label", dev); -# endif /* !defined(HAVE_DIOCGDINFO) */ + grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot open `%s': %s"), + dev, strerror (errno)); return 0; } @@ -590,6 +583,12 @@ devmapper_fail: # 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) */ @@ -632,6 +631,7 @@ devmapper_fail: struct linux_partition_cache { struct linux_partition_cache *next; + struct linux_partition_cache **prev; char *dev; unsigned long start; int partno; @@ -702,7 +702,7 @@ linux_find_partition (char *dev, grub_disk_addr_t sector) missing = 0; close (fd); - start = find_partition_start (real_dev); + start = grub_hostdisk_find_partition_start (real_dev); /* We don't care about errors here. */ grub_errno = GRUB_ERR_NONE; @@ -740,9 +740,8 @@ grub_util_fd_seek (int fd, const char *name, grub_uint64_t off) offset = (loff_t) off; if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET)) - { - return grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", name); - } + return grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot seek `%s': %s"), + name, strerror (errno)); return GRUB_ERR_NONE; } #else @@ -752,11 +751,38 @@ 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, "cannot seek `%s'", name); + return grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot seek `%s': %s"), + name, strerror (errno)); return 0; } #endif +const char * +grub_hostdisk_os_dev_to_grub_drive (const char *os_disk, int add) +{ + unsigned int i; + + 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; + + if (!add) + return NULL; + + if (i == ARRAY_SIZE (map)) + grub_util_error ("%s", _("device count exceeds limit")); + + map[i].device = xstrdup (os_disk); + map[i].drive = xmalloc (sizeof ("hostdisk/") + strlen (os_disk)); + strcpy (map[i].drive, "hostdisk/"); + strcpy (map[i].drive + sizeof ("hostdisk/") - 1, os_disk); + map[i].device_map = 0; + + return map[i].drive; +} + static int open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags) { @@ -820,7 +846,8 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags) fd = open (dev, flags); if (fd < 0) { - grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s'", dev); + grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot open `%s': %s"), + dev, strerror (errno)); return -1; } @@ -900,7 +927,8 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags) if (fd < 0) { - grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s' in open_device()", map[disk->id].device); + grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot open `%s': %s"), + map[disk->id].device, strerror (errno)); return -1; } #endif /* ! __linux__ */ @@ -947,8 +975,8 @@ grub_util_fd_read (int fd, char *buf, size_t len) /* Write LEN bytes from BUF to FD. Return less than or equal to zero if an error occurs, otherwise return LEN. */ -static ssize_t -nwrite (int fd, const char *buf, size_t len) +ssize_t +grub_util_fd_write (int fd, const char *buf, size_t len) { ssize_t size = len; @@ -1008,7 +1036,8 @@ grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector, if (grub_util_fd_read (fd, buf, (1 << disk->log_sector_size)) != (1 << disk->log_sector_size)) { - grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id].device); + grub_error (GRUB_ERR_READ_ERROR, N_("cannot read `%s': %s"), + map[disk->id].device, strerror (errno)); return grub_errno; } @@ -1019,7 +1048,8 @@ grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector, if (grub_util_fd_read (fd, buf, size << disk->log_sector_size) != (ssize_t) (size << disk->log_sector_size)) - grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id].device); + grub_error (GRUB_ERR_READ_ERROR, N_("cannot read `%s': %s"), + map[disk->id].device, strerror (errno)); return grub_errno; } @@ -1051,9 +1081,10 @@ grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector, if (fd < 0) return grub_errno; - if (nwrite (fd, buf, size << disk->log_sector_size) + if (grub_util_fd_write (fd, buf, size << disk->log_sector_size) != (ssize_t) (size << disk->log_sector_size)) - grub_error (GRUB_ERR_WRITE_ERROR, "cannot write to `%s'", map[disk->id].device); + grub_error (GRUB_ERR_WRITE_ERROR, N_("cannot write to `%s': %s"), + map[disk->id].device, strerror (errno)); return grub_errno; } @@ -1096,8 +1127,8 @@ grub_util_biosdisk_close (struct grub_disk *disk) static struct grub_disk_dev grub_util_biosdisk_dev = { - .name = "biosdisk", - .id = GRUB_DISK_DEVICE_BIOSDISK_ID, + .name = "hostdisk", + .id = GRUB_DISK_DEVICE_HOSTDISK_ID, .iterate = grub_util_biosdisk_iterate, .open = grub_util_biosdisk_open, .close = grub_util_biosdisk_close, @@ -1120,10 +1151,16 @@ read_device_map (const char *dev_map) grub_util_error ("%s:%d: %s", dev_map, lineno, msg); } + if (dev_map[0] == '\0') + { + grub_util_info ("no device.map"); + return; + } + fp = fopen (dev_map, "r"); if (! fp) { - grub_util_info (_("cannot open `%s'"), dev_map); + grub_util_info (_("cannot open `%s': %s"), dev_map, strerror (errno)); return; } @@ -1144,7 +1181,11 @@ read_device_map (const char *dev_map) continue; if (*p != '(') - show_error (_("No open parenthesis found")); + { + char *tmp; + tmp = xasprintf (_("missing `%c' symbol"), '('); + show_error (tmp); + } p++; /* Find a free slot. */ @@ -1155,11 +1196,16 @@ read_device_map (const char *dev_map) e = p; p = strchr (p, ')'); if (! p) - show_error (_("No close parenthesis found")); + { + char *tmp; + tmp = xasprintf (_("missing `%c' symbol"), ')'); + show_error (tmp); + } map[drive].drive = xmalloc (p - e + sizeof ('\0')); strncpy (map[drive].drive, e, p - e + sizeof ('\0')); map[drive].drive[p - e] = '\0'; + map[drive].device_map = 1; p++; /* Skip leading spaces. */ @@ -1167,7 +1213,7 @@ read_device_map (const char *dev_map) p++; if (*p == '\0') - show_error (_("No filename found")); + show_error (_("filename expected")); /* NUL-terminate the filename. */ e = p; @@ -1196,7 +1242,7 @@ read_device_map (const char *dev_map) { map[drive].device = xmalloc (PATH_MAX); if (! realpath (p, map[drive].device)) - grub_util_error (_("cannot get the real path of `%s'"), p); + grub_util_error (_("failed to get canonical path of %s"), p); } else #endif @@ -1230,784 +1276,19 @@ grub_util_biosdisk_fini (void) grub_disk_dev_unregister (&grub_util_biosdisk_dev); } -/* - * Note: we do not use the new partition naming scheme as dos_part does not - * necessarily correspond to an msdos partition. - */ -static char * -make_device_name (int drive, int dos_part, int bsd_part) +const char * +grub_util_biosdisk_get_compatibility_hint (grub_disk_t disk) { - char *ret, *ptr, *end; - const char *iptr; - - ret = xmalloc (strlen (map[drive].drive) * 2 - + sizeof (",XXXXXXXXXXXXXXXXXXXXXXXXXX" - ",XXXXXXXXXXXXXXXXXXXXXXXXXX")); - end = (ret + strlen (map[drive].drive) * 2 - + sizeof (",XXXXXXXXXXXXXXXXXXXXXXXXXX" - ",XXXXXXXXXXXXXXXXXXXXXXXXXX")); - ptr = ret; - for (iptr = map[drive].drive; *iptr; iptr++) - { - if (*iptr == ',') - *ptr++ = '\\'; - *ptr++ = *iptr; - } - *ptr = 0; - if (dos_part >= 0) - snprintf (ptr, end - ptr, ",%d", dos_part + 1); - ptr += strlen (ptr); - if (bsd_part >= 0) - snprintf (ptr, end - ptr, ",%d", bsd_part + 1); - - return ret; -} - -#ifdef HAVE_DEVICE_MAPPER -static int -grub_util_get_dm_node_linear_info (const char *dev, - int *maj, int *min) -{ - struct dm_task *dmt; - void *next = NULL; - uint64_t length, start; - char *target, *params; - char *ptr; - int major, minor; - - dmt = dm_task_create(DM_DEVICE_TABLE); - if (!dmt) - return 0; - - if (!dm_task_set_name(dmt, dev)) - return 0; - dm_task_no_open_count(dmt); - if (!dm_task_run(dmt)) - return 0; - next = dm_get_next_target(dmt, next, &start, &length, - &target, ¶ms); - if (grub_strcmp (target, "linear") != 0) - return 0; - major = grub_strtoul (params, &ptr, 10); - if (grub_errno) - { - grub_errno = GRUB_ERR_NONE; - return 0; - } - if (*ptr != ':') - return 0; - ptr++; - minor = grub_strtoul (ptr, 0, 10); - if (grub_errno) - { - grub_errno = GRUB_ERR_NONE; - return 0; - } - if (maj) - *maj = major; - if (min) - *min = minor; - return 1; -} -#endif - -static char * -convert_system_partition_to_system_disk (const char *os_dev, struct stat *st) -{ -#if defined(__linux__) - char *path = xmalloc (PATH_MAX); - if (! realpath (os_dev, path)) - return NULL; - - if (strncmp ("/dev/", path, 5) == 0) - { - char *p = path + 5; - - /* If this is an IDE disk. */ - if (strncmp ("ide/", p, 4) == 0) - { - p = strstr (p, "part"); - if (p) - strcpy (p, "disc"); - - return path; - } - - /* If this is a SCSI disk. */ - if (strncmp ("scsi/", p, 5) == 0) - { - p = strstr (p, "part"); - if (p) - strcpy (p, "disc"); - - return path; - } - - /* If this is a DAC960 disk. */ - if (strncmp ("rd/c", p, 4) == 0) - { - /* /dev/rd/c[0-9]+d[0-9]+(p[0-9]+)? */ - p = strchr (p, 'p'); - if (p) - *p = '\0'; - - return path; - } - - /* If this is a Mylex AcceleRAID Array. */ - if (strncmp ("rs/c", p, 4) == 0) - { - /* /dev/rd/c[0-9]+d[0-9]+(p[0-9]+)? */ - p = strchr (p, 'p'); - if (p) - *p = '\0'; - - return path; - } - /* If this is a CCISS disk. */ - if (strncmp ("cciss/c", p, sizeof ("cciss/c") - 1) == 0) - { - /* /dev/cciss/c[0-9]+d[0-9]+(p[0-9]+)? */ - p = strchr (p, 'p'); - if (p) - *p = '\0'; - - return path; - } - - /* If this is a Compaq Intelligent Drive Array. */ - if (strncmp ("ida/c", p, sizeof ("ida/c") - 1) == 0) - { - /* /dev/ida/c[0-9]+d[0-9]+(p[0-9]+)? */ - p = strchr (p, 'p'); - if (p) - *p = '\0'; - - return path; - } - - /* If this is an I2O disk. */ - if (strncmp ("i2o/hd", p, sizeof ("i2o/hd") - 1) == 0) - { - /* /dev/i2o/hd[a-z]([0-9]+)? */ - p[sizeof ("i2o/hda") - 1] = '\0'; - return path; - } - - /* If this is a MultiMediaCard (MMC). */ - if (strncmp ("mmcblk", p, sizeof ("mmcblk") - 1) == 0) - { - /* /dev/mmcblk[0-9]+(p[0-9]+)? */ - p = strchr (p, 'p'); - if (p) - *p = '\0'; - - return path; - } - - if (strncmp ("md", p, 2) == 0 - && p[2] >= '0' && p[2] <= '9') - { - char *ptr = p + 2; - while (*ptr >= '0' && *ptr <= '9') - ptr++; - *ptr = 0; - return path; - } - - /* If this is an IDE, SCSI or Virtio disk. */ - if (strncmp ("vdisk", p, 5) == 0 - && p[5] >= 'a' && p[5] <= 'z') - { - /* /dev/vdisk[a-z][0-9]* */ - p[6] = '\0'; - return path; - } - if ((strncmp ("hd", p, 2) == 0 - || strncmp ("vd", p, 2) == 0 - || strncmp ("sd", p, 2) == 0) - && p[2] >= 'a' && p[2] <= 'z') - { - char *pp = p + 2; - while (*pp >= 'a' && *pp <= 'z') - pp++; - /* /dev/[hsv]d[a-z]+[0-9]* */ - *pp = '\0'; - return path; - } - - /* If this is a Xen virtual block device. */ - if ((strncmp ("xvd", p, 3) == 0) && p[3] >= 'a' && p[3] <= 'z') - { - char *pp = p + 3; - while (*pp >= 'a' && *pp <= 'z') - pp++; - /* /dev/xvd[a-z]+[0-9]* */ - *pp = '\0'; - return path; - } - -#ifdef HAVE_DEVICE_MAPPER - /* If this is a DM-RAID device. - Compare os_dev rather than path here, since nodes under - /dev/mapper/ are often symlinks. */ - if ((strncmp ("/dev/mapper/", os_dev, 12) == 0)) - { - struct dm_tree *tree; - uint32_t maj, min; - struct dm_tree_node *node = NULL, *child; - void *handle; - const char *node_uuid, *mapper_name = NULL, *child_uuid, *child_name; - - tree = dm_tree_create (); - if (! tree) - { - grub_dprintf ("hostdisk", "dm_tree_create failed\n"); - goto devmapper_out; - } - - maj = major (st->st_rdev); - min = minor (st->st_rdev); - if (! dm_tree_add_dev (tree, maj, min)) - { - grub_dprintf ("hostdisk", "dm_tree_add_dev failed\n"); - goto devmapper_out; - } - - node = dm_tree_find_node (tree, maj, min); - if (! node) - { - grub_dprintf ("hostdisk", "dm_tree_find_node failed\n"); - goto devmapper_out; - } - node_uuid = dm_tree_node_get_uuid (node); - if (! node_uuid) - { - grub_dprintf ("hostdisk", "%s has no DM uuid\n", path); - node = NULL; - goto devmapper_out; - } - if (strncmp (node_uuid, "LVM-", 4) == 0) - { - grub_dprintf ("hostdisk", "%s is an LVM\n", path); - node = NULL; - goto devmapper_out; - } - if (strncmp (node_uuid, "mpath-", 6) == 0) - { - /* Multipath partitions have partN-mpath-* UUIDs, and are - linear mappings so are handled by - grub_util_get_dm_node_linear_info. Multipath disks are not - linear mappings and must be handled specially. */ - grub_dprintf ("hostdisk", "%s is a multipath disk\n", path); - mapper_name = dm_tree_node_get_name (node); - goto devmapper_out; - } - if (strncmp (node_uuid, "DMRAID-", 7) != 0) - { - int major, minor; - const char *node_name; - grub_dprintf ("hostdisk", "%s is not DM-RAID\n", path); - - if ((node_name = dm_tree_node_get_name (node)) - && grub_util_get_dm_node_linear_info (node_name, - &major, &minor)) - { - if (tree) - dm_tree_free (tree); - free (path); - char *ret = grub_find_device ("/dev", - (major << 8) | minor); - return ret; - } - - node = NULL; - goto devmapper_out; - } - - handle = NULL; - /* Counter-intuitively, device-mapper refers to the disk-like - device containing a DM-RAID partition device as a "child" of - the partition device. */ - child = dm_tree_next_child (&handle, node, 0); - if (! child) - { - grub_dprintf ("hostdisk", "%s has no DM children\n", path); - goto devmapper_out; - } - child_uuid = dm_tree_node_get_uuid (child); - if (! child_uuid) - { - grub_dprintf ("hostdisk", "%s child has no DM uuid\n", path); - goto devmapper_out; - } - else if (strncmp (child_uuid, "DMRAID-", 7) != 0) - { - grub_dprintf ("hostdisk", "%s child is not DM-RAID\n", path); - goto devmapper_out; - } - child_name = dm_tree_node_get_name (child); - if (! child_name) - { - grub_dprintf ("hostdisk", "%s child has no DM name\n", path); - goto devmapper_out; - } - mapper_name = child_name; - -devmapper_out: - if (! mapper_name && node) - { - /* This is a DM-RAID disk, not a partition. */ - mapper_name = dm_tree_node_get_name (node); - if (! mapper_name) - grub_dprintf ("hostdisk", "%s has no DM name\n", path); - } - if (tree) - dm_tree_free (tree); - free (path); - if (mapper_name) - return xasprintf ("/dev/mapper/%s", mapper_name); - else - return NULL; - } -#endif /* HAVE_DEVICE_MAPPER */ - } - - return path; - -#elif defined(__GNU__) - char *path = xstrdup (os_dev); - if (strncmp ("/dev/sd", path, 7) == 0 || strncmp ("/dev/hd", path, 7) == 0) - { - char *p = strchr (path + 7, 's'); - if (p) - *p = '\0'; - } - return path; - -#elif defined(__CYGWIN__) - char *path = xstrdup (os_dev); - if (strncmp ("/dev/sd", path, 7) == 0 && 'a' <= path[7] && path[7] <= 'z') - path[8] = 0; - return path; - -#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) - char *out, *out2; - if (strncmp (os_dev, "/dev/", sizeof ("/dev/") - 1) != 0) - return xstrdup (os_dev); - grub_util_follow_gpart_up (os_dev + sizeof ("/dev/") - 1, NULL, &out); - - out2 = xasprintf ("/dev/%s", out); - free (out); - - return out2; -#elif defined(__APPLE__) - char *path = xstrdup (os_dev); - if (strncmp ("/dev/", path, 5) == 0) - { - char *p; - for (p = path + 5; *p; ++p) - if (grub_isdigit(*p)) - { - p = strpbrk (p, "sp"); - if (p) - *p = '\0'; - break; - } - } - return path; - -#elif defined(__NetBSD__) - /* NetBSD uses "/dev/r[a-z]+[0-9][a-z]". */ - char *path = xstrdup (os_dev); - if (strncmp ("/dev/r", path, sizeof("/dev/r") - 1) == 0 && - (path[sizeof("/dev/r") - 1] >= 'a' && path[sizeof("/dev/r") - 1] <= 'z') && - strncmp ("fd", path + sizeof("/dev/r") - 1, sizeof("fd") - 1) != 0) /* not a floppy device name */ - { - char *p; - for (p = path + sizeof("/dev/r"); *p >= 'a' && *p <= 'z'; p++); - if (grub_isdigit(*p)) - { - p++; - if ((*p >= 'a' && *p <= 'z') && (*(p+1) == '\0')) - { - /* path matches the required regular expression and - p points to its last character. */ - int rawpart = -1; -# ifdef HAVE_GETRAWPARTITION - rawpart = getrawpartition(); -# endif /* HAVE_GETRAWPARTITION */ - if (rawpart >= 0) - *p = 'a' + rawpart; - } - } - } - return path; - -#elif defined (__sun__) - char *colon = grub_strrchr (os_dev, ':'); - if (grub_memcmp (os_dev, "/devices", sizeof ("/devices") - 1) == 0 - && colon) - { - char *ret = xmalloc (colon - os_dev + sizeof (":q,raw")); - grub_memcpy (ret, os_dev, colon - os_dev); - grub_memcpy (ret + (colon - os_dev), ":q,raw", sizeof (":q,raw")); - return ret; - } - else - return xstrdup (os_dev); -#else -# warning "The function `convert_system_partition_to_system_disk' might not work on your OS correctly." - return xstrdup (os_dev); -#endif -} - -#if defined(__sun__) -static int -device_is_wholedisk (const char *os_dev) -{ - if (grub_memcmp (os_dev, "/devices/", sizeof ("/devices/") - 1) != 0) - return 1; - if (grub_memcmp (os_dev + strlen (os_dev) - (sizeof (":q,raw") - 1), - ":q,raw", (sizeof (":q,raw") - 1)) == 0) - return 1; + if (disk->dev != &grub_util_biosdisk_dev || map[disk->id].device_map) + return disk->name; return 0; } -#endif - -#if defined(__linux__) || defined(__CYGWIN__) -static int -device_is_wholedisk (const char *os_dev) -{ - int len = strlen (os_dev); - - if (os_dev[len - 1] < '0' || os_dev[len - 1] > '9') - return 1; - return 0; -} -#endif - -#if defined(__NetBSD__) -/* Try to determine whether a given device name corresponds to a whole disk. - This function should give in most cases a definite answer, but it may - actually give an approximate one in the following sense: if the return - value is 0 then the device name does not correspond to a whole disk. */ -static int -device_is_wholedisk (const char *os_dev) -{ - int len = strlen (os_dev); - int rawpart = -1; - -# ifdef HAVE_GETRAWPARTITION - rawpart = getrawpartition(); -# endif /* HAVE_GETRAWPARTITION */ - if (rawpart < 0) - return 1; - return (os_dev[len - 1] == ('a' + rawpart)); -} -#endif /* defined(__NetBSD__) */ - -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) -static int -device_is_wholedisk (const char *os_dev) -{ - const char *p; - - if (strncmp (os_dev, "/dev/", sizeof ("/dev/") - 1) != 0) - return 0; - - for (p = os_dev + sizeof ("/dev/") - 1; *p; ++p) - if (grub_isdigit (*p)) - { - if (strchr (p, 's')) - return 0; - break; - } - - return 1; -} -#endif /* defined(__FreeBSD__) || defined(__FreeBSD_kernel__) */ - -static int -find_system_device (const char *os_dev, struct stat *st, int convert, int add) -{ - unsigned int i; - char *os_disk; - - if (convert) - os_disk = convert_system_partition_to_system_disk (os_dev, st); - else - os_disk = xstrdup (os_dev); - if (! os_disk) - return -1; - - for (i = 0; i < ARRAY_SIZE (map); i++) - if (! map[i].device) - break; - else if (strcmp (map[i].device, os_disk) == 0) - { - free (os_disk); - return i; - } - - if (!add) - { - free (os_disk); - return -1; - } - - if (i == ARRAY_SIZE (map)) - grub_util_error (_("device count exceeds limit")); - - map[i].device = os_disk; - map[i].drive = xstrdup (os_disk); - - return i; -} - -int -grub_util_biosdisk_is_present (const char *os_dev) -{ - struct stat st; - - if (stat (os_dev, &st) < 0) - return 0; - - return find_system_device (os_dev, &st, 1, 0) != -1; -} - -char * -grub_util_biosdisk_get_grub_dev (const char *os_dev) -{ - struct stat st; - int drive; - char *sys_disk; - - grub_util_info ("Looking for %s", os_dev); - - if (stat (os_dev, &st) < 0) - { - grub_error (GRUB_ERR_BAD_DEVICE, "cannot stat `%s'", os_dev); - grub_util_info ("cannot stat `%s'", os_dev); - return 0; - } - - drive = find_system_device (os_dev, &st, 1, 1); - if (drive < 0) - { - grub_error (GRUB_ERR_UNKNOWN_DEVICE, - "no mapping exists for `%s'", os_dev); - grub_util_info ("no mapping exists for `%s'", os_dev); - return 0; - } - - sys_disk = convert_system_partition_to_system_disk (os_dev, &st); - if (grub_strcmp (os_dev, sys_disk) == 0) - { - free (sys_disk); - return make_device_name (drive, -1, -1); - } - free (sys_disk); - -#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 - return make_device_name (drive, -1, -1); - -#if defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined (__sun__) - - /* Linux counts partitions uniformly, whether a BSD partition or a DOS - partition, so mapping them to GRUB devices is not trivial. - Here, get the start sector of a partition by HDIO_GETGEO, and - compare it with each partition GRUB recognizes. - - Cygwin /dev/sdXN emulation uses Windows partition mapping. It - does not count the extended partition and missing primary - partitions. Use same method as on Linux here. - - For NetBSD and FreeBSD, proceed as for Linux, except that the start - sector is obtained from the disk label. */ - { - char *name, *partname; - grub_disk_t disk; - grub_disk_addr_t start; - auto int find_partition (grub_disk_t dsk, - const grub_partition_t partition); - - int find_partition (grub_disk_t dsk __attribute__ ((unused)), - const grub_partition_t partition) - { - grub_disk_addr_t part_start = 0; - grub_util_info ("Partition %d starts from %lu", - partition->number, partition->start); - - part_start = grub_partition_get_start (partition); - - if (start == part_start) - { - partname = grub_partition_get_name (partition); - return 1; - } - - return 0; - } - - name = make_device_name (drive, -1, -1); - -# if !defined(HAVE_DIOCGDINFO) && !defined(__sun__) - if (MAJOR (st.st_rdev) == FLOPPY_MAJOR) - return name; -# else /* defined(HAVE_DIOCGDINFO) */ - /* Since os_dev and convert_system_partition_to_system_disk (os_dev) are - * different, we know that os_dev cannot be a floppy device. */ -# endif /* !defined(HAVE_DIOCGDINFO) */ - - start = find_partition_start (os_dev); - if (grub_errno != GRUB_ERR_NONE) - { - free (name); - return 0; - } - - grub_util_info ("%s starts from %lu", os_dev, start); - - if (start == 0 && device_is_wholedisk (os_dev)) - return name; - - grub_util_info ("opening the device %s", name); - disk = grub_disk_open (name); - free (name); - - if (! disk) - { - /* We already know that the partition exists. Given that we already - checked the device map above, we can only get - GRUB_ERR_UNKNOWN_DEVICE at this point if the disk does not exist. - This can happen on Xen, where disk images in the host can be - assigned to devices that have partition-like names in the guest - but are really more like disks. */ - if (grub_errno == GRUB_ERR_UNKNOWN_DEVICE) - { - grub_util_warn - ("disk does not exist, so falling back to partition device %s", - os_dev); - - drive = find_system_device (os_dev, &st, 0, 1); - if (drive < 0) - { - grub_error (GRUB_ERR_UNKNOWN_DEVICE, - "no mapping exists for `%s'", os_dev); - return 0; - } - - return make_device_name (drive, -1, -1); - } - else - return 0; - } - - partname = NULL; - grub_partition_iterate (disk, find_partition); - if (grub_errno != GRUB_ERR_NONE) - { - grub_disk_close (disk); - return 0; - } - - if (partname == NULL) - { - grub_disk_close (disk); - grub_util_info ("cannot find the partition of `%s'", os_dev); - grub_error (GRUB_ERR_BAD_DEVICE, - "cannot find the partition of `%s'", os_dev); - return 0; - } - - name = grub_xasprintf ("%s,%s", disk->name, partname); - free (partname); - return name; - } - -#elif defined(__GNU__) - /* GNU uses "/dev/[hs]d[0-9]+(s[0-9]+[a-z]?)?". */ - { - char *p; - int dos_part = -1; - int bsd_part = -1; - - p = strrchr (os_dev, 's'); - if (p) - { - long int n; - char *q; - - p++; - n = strtol (p, &q, 10); - if (p != q && n != GRUB_LONG_MIN && n != GRUB_LONG_MAX) - { - dos_part = (int) n - 1; - - if (*q >= 'a' && *q <= 'g') - bsd_part = *q - 'a'; - } - } - - return make_device_name (drive, dos_part, bsd_part); - } - -#else -# warning "The function `grub_util_biosdisk_get_grub_dev' might not work on your OS correctly." - return make_device_name (drive, -1, -1); -#endif -} const char * grub_util_biosdisk_get_osdev (grub_disk_t disk) { - return map[disk->id].device; -} - -int -grub_util_biosdisk_is_floppy (grub_disk_t disk) -{ - struct stat st; - int fd; - if (disk->dev != &grub_util_biosdisk_dev) return 0; - fd = open (map[disk->id].device, O_RDONLY); - /* Shouldn't happen. */ - if (fd == -1) - return 0; - - /* Shouldn't happen either. */ - if (fstat (fd, &st) < 0) - { - close (fd); - return 0; - } - - close (fd); - -#if defined(__NetBSD__) - if (major(st.st_rdev) == RAW_FLOPPY_MAJOR) - return 1; -#endif - -#if defined(FLOPPY_MAJOR) - if (major(st.st_rdev) == FLOPPY_MAJOR) -#else - /* Some kernels (e.g. kFreeBSD) don't have a static major number - for floppies, but they still use a "fd[0-9]" pathname. */ - if (map[disk->id].device[5] == 'f' - && map[disk->id].device[6] == 'd' - && map[disk->id].device[7] >= '0' - && map[disk->id].device[7] <= '9') -#endif - return 1; - - return 0; + return map[disk->id].device; } diff --git a/grub-core/kern/emu/hostfs.c b/grub-core/kern/emu/hostfs.c index 501ad4664..6c819da81 100644 --- a/grub-core/kern/emu/hostfs.c +++ b/grub-core/kern/emu/hostfs.c @@ -21,8 +21,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -54,6 +56,12 @@ is_dir (const char *path, const char *name) return S_ISDIR (st.st_mode); } +struct grub_hostfs_data +{ + char *filename; + FILE *f; +}; + static grub_err_t grub_hostfs_dir (grub_device_t device, const char *path, int (*hook) (const char *filename, @@ -68,7 +76,8 @@ grub_hostfs_dir (grub_device_t device, const char *path, dir = opendir (path); if (! dir) return grub_error (GRUB_ERR_BAD_FILENAME, - "can't open the hostfs directory `%s'", path); + N_("can't open `%s': %s"), path, + strerror (errno)); while (1) { @@ -95,12 +104,30 @@ static grub_err_t grub_hostfs_open (struct grub_file *file, const char *name) { FILE *f; + struct grub_hostfs_data *data; f = fopen (name, "rb"); if (! f) return grub_error (GRUB_ERR_BAD_FILENAME, - "can't open `%s'", name); - file->data = f; + N_("can't open `%s': %s"), name, + strerror (errno)); + data = grub_malloc (sizeof (*data)); + if (!data) + { + fclose (f); + return grub_errno; + } + data->filename = grub_strdup (name); + if (!data->filename) + { + grub_free (data); + fclose (f); + return grub_errno; + } + + data->f = f; + + file->data = data; #ifdef __MINGW32__ file->size = grub_util_get_disk_size (name); @@ -116,18 +143,20 @@ grub_hostfs_open (struct grub_file *file, const char *name) static grub_ssize_t grub_hostfs_read (grub_file_t file, char *buf, grub_size_t len) { - FILE *f; + struct grub_hostfs_data *data; - f = (FILE *) file->data; - if (fseeko (f, file->offset, SEEK_SET) != 0) + data = file->data; + if (fseeko (data->f, file->offset, SEEK_SET) != 0) { - grub_error (GRUB_ERR_OUT_OF_RANGE, "fseeko: %s", strerror (errno)); + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("cannot seek `%s': %s"), + data->filename, strerror (errno)); return -1; } - unsigned int s = fread (buf, 1, len, f); + unsigned int s = fread (buf, 1, len, data->f); if (s != len) - grub_error (GRUB_ERR_FILE_READ_ERROR, "fread: %s", strerror (errno)); + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("cannot read `%s': %s"), + data->filename, strerror (errno)); return (signed) s; } @@ -135,10 +164,12 @@ grub_hostfs_read (grub_file_t file, char *buf, grub_size_t len) static grub_err_t grub_hostfs_close (grub_file_t file) { - FILE *f; + struct grub_hostfs_data *data; - f = (FILE *) file->data; - fclose (f); + data = file->data; + fclose (data->f); + grub_free (data->filename); + grub_free (data); return GRUB_ERR_NONE; } diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c index 725d1ac7f..64e72dff6 100644 --- a/grub-core/kern/emu/main.c +++ b/grub-core/kern/emu/main.c @@ -127,7 +127,7 @@ void grub_emu_init (void); int main (int argc, char *argv[]) { - char *dev_map = DEFAULT_DEVICE_MAP; + const char *dev_map = DEFAULT_DEVICE_MAP; volatile int hold = 0; int opt; diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c index 21f314d55..53753a818 100644 --- a/grub-core/kern/emu/misc.c +++ b/grub-core/kern/emu/misc.c @@ -117,7 +117,7 @@ xmalloc (grub_size_t size) p = malloc (size); if (! p) - grub_util_error (_("out of memory")); + grub_util_error ("%s", _("out of memory")); return p; } @@ -127,7 +127,7 @@ xrealloc (void *ptr, grub_size_t size) { ptr = realloc (ptr, size); if (! ptr) - grub_util_error (_("out of memory")); + grub_util_error ("%s", _("out of memory")); return ptr; } @@ -185,7 +185,7 @@ xasprintf (const char *fmt, ...) if (vasprintf (&result, fmt, ap) < 0) { if (errno == ENOMEM) - grub_util_error (_("out of memory")); + grub_util_error ("%s", _("out of memory")); return NULL; } diff --git a/grub-core/kern/emu/mm.c b/grub-core/kern/emu/mm.c index b58ccc794..0461ea51c 100644 --- a/grub-core/kern/emu/mm.c +++ b/grub-core/kern/emu/mm.c @@ -23,6 +23,7 @@ #include #include #include +#include void * grub_malloc (grub_size_t size) @@ -30,7 +31,7 @@ grub_malloc (grub_size_t size) void *ret; ret = malloc (size); if (!ret) - grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); return ret; } @@ -58,7 +59,7 @@ grub_realloc (void *ptr, grub_size_t size) void *ret; ret = realloc (ptr, size); if (!ret) - grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); return ret; } @@ -77,11 +78,11 @@ grub_memalign (grub_size_t align, grub_size_t size) #else (void) align; (void) size; - grub_util_error (_("grub_memalign is not supported")); + grub_util_error (_("grub_memalign is not supported on your system")); #endif if (!p) - grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); return p; } diff --git a/grub-core/kern/err.c b/grub-core/kern/err.c index 74f3915aa..52ba6de62 100644 --- a/grub-core/kern/err.c +++ b/grub-core/kern/err.c @@ -22,18 +22,13 @@ #include #include -#define GRUB_MAX_ERRMSG 256 #define GRUB_ERROR_STACK_SIZE 10 grub_err_t grub_errno; char grub_errmsg[GRUB_MAX_ERRMSG]; int grub_err_printed_errors; -static struct -{ - grub_err_t errno; - char errmsg[GRUB_MAX_ERRMSG]; -} grub_error_stack_items[GRUB_ERROR_STACK_SIZE]; +static struct grub_error_saved grub_error_stack_items[GRUB_ERROR_STACK_SIZE]; static int grub_error_stack_pos; static int grub_error_stack_assert; @@ -71,7 +66,7 @@ grub_error_push (void) if (grub_error_stack_pos < GRUB_ERROR_STACK_SIZE) { /* Copy active error message to stack. */ - grub_error_stack_items[grub_error_stack_pos].errno = grub_errno; + grub_error_stack_items[grub_error_stack_pos].grub_errno = grub_errno; grub_memcpy (grub_error_stack_items[grub_error_stack_pos].errmsg, grub_errmsg, sizeof (grub_errmsg)); @@ -99,7 +94,7 @@ grub_error_pop (void) /* Pop error message from error stack to current active error. */ grub_error_stack_pos--; - grub_errno = grub_error_stack_items[grub_error_stack_pos].errno; + grub_errno = grub_error_stack_items[grub_error_stack_pos].grub_errno; grub_memcpy (grub_errmsg, grub_error_stack_items[grub_error_stack_pos].errmsg, sizeof (grub_errmsg)); diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c index f69ef6fd4..4f1f59ff7 100644 --- a/grub-core/kern/file.c +++ b/grub-core/kern/file.c @@ -24,6 +24,7 @@ #include #include #include +#include void (*EXPORT_VAR (grub_grubnet_fini)) (void); @@ -41,7 +42,7 @@ grub_file_get_device_name (const char *name) if (! p) { - grub_error (GRUB_ERR_BAD_FILENAME, "missing `)'"); + grub_error (GRUB_ERR_BAD_FILENAME, N_("missing `%c' symbol"), ')'); return 0; } @@ -138,7 +139,7 @@ grub_file_read (grub_file_t file, void *buf, grub_size_t len) if (file->offset > file->size) { grub_error (GRUB_ERR_OUT_OF_RANGE, - "attempt to read past the end of file"); + N_("attempt to read past the end of file")); return -1; } @@ -178,7 +179,7 @@ grub_file_seek (grub_file_t file, grub_off_t offset) if (offset > file->size) { grub_error (GRUB_ERR_OUT_OF_RANGE, - "attempt to seek outside of the file"); + N_("attempt to seek outside of the file")); return -1; } diff --git a/grub-core/kern/fs.c b/grub-core/kern/fs.c index 14d389e07..8fe28cc5d 100644 --- a/grub-core/kern/fs.c +++ b/grub-core/kern/fs.c @@ -26,6 +26,7 @@ #include #include #include +#include grub_fs_t grub_fs_list = 0; @@ -97,7 +98,7 @@ grub_fs_probe (grub_device_t device) else if (device->net && device->net->fs) return device->net->fs; - grub_error (GRUB_ERR_UNKNOWN_FS, "unknown filesystem"); + grub_error (GRUB_ERR_UNKNOWN_FS, N_("unknown filesystem")); return 0; } @@ -145,7 +146,7 @@ grub_fs_blocklist_open (grub_file_t file, const char *name) if (grub_errno != GRUB_ERR_NONE || *p != '+') { grub_error (GRUB_ERR_BAD_FILENAME, - "invalid file name `%s'", name); + N_("invalid file name `%s'"), name); goto fail; } } @@ -157,7 +158,7 @@ grub_fs_blocklist_open (grub_file_t file, const char *name) || (*p && *p != ',' && ! grub_isspace (*p))) { grub_error (GRUB_ERR_BAD_FILENAME, - "invalid file name `%s'", name); + N_("invalid file name `%s'"), name); goto fail; } diff --git a/grub-core/kern/i386/coreboot/init.c b/grub-core/kern/i386/coreboot/init.c index 95209bb70..b96b9c6f2 100644 --- a/grub-core/kern/i386/coreboot/init.c +++ b/grub-core/kern/i386/coreboot/init.c @@ -42,6 +42,8 @@ extern grub_uint8_t _start[]; extern grub_uint8_t _end[]; extern grub_uint8_t _edata[]; +#pragma GCC diagnostic warning "-Wsuggest-attribute=noreturn" + grub_uint32_t grub_get_rtc (void) { diff --git a/grub-core/kern/i386/dl.c b/grub-core/kern/i386/dl.c index 57854964b..73035c9ea 100644 --- a/grub-core/kern/i386/dl.c +++ b/grub-core/kern/i386/dl.c @@ -21,6 +21,7 @@ #include #include #include +#include /* Check if EHDR is a valid ELF header. */ grub_err_t @@ -32,7 +33,7 @@ grub_arch_dl_check_header (void *ehdr) if (e->e_ident[EI_CLASS] != ELFCLASS32 || e->e_ident[EI_DATA] != ELFDATA2LSB || e->e_machine != EM_386) - return grub_error (GRUB_ERR_BAD_OS, "invalid arch specific ELF magic"); + return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch dependent ELF magic")); return GRUB_ERR_NONE; } @@ -54,7 +55,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) break; if (i == e->e_shnum) - return grub_error (GRUB_ERR_BAD_MODULE, "no symtab found"); + return grub_error (GRUB_ERR_BAD_MODULE, N_("no symbol table")); entsize = s->sh_entsize; @@ -100,6 +101,10 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) *addr += (sym->st_value - (Elf_Word) seg->addr - rel->r_offset); break; + default: + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + N_("relocation 0x%x is not implemented yet"), + ELF_R_TYPE (rel->r_info)); } } } diff --git a/grub-core/kern/i386/multiboot_mmap.c b/grub-core/kern/i386/multiboot_mmap.c index 7f4bc3b5c..1cb422fef 100644 --- a/grub-core/kern/i386/multiboot_mmap.c +++ b/grub-core/kern/i386/multiboot_mmap.c @@ -34,7 +34,7 @@ static struct multiboot_info kern_multiboot_info; static grub_uint8_t mmap_entries[sizeof (struct multiboot_mmap_entry) * 32]; void -grub_machine_mmap_init () +grub_machine_mmap_init (void) { if (! startup_multiboot_info) grub_fatal ("Unable to find Multiboot Information (is CONFIG_MULTIBOOT disabled in coreboot?)"); diff --git a/grub-core/kern/i386/qemu/mmap.c b/grub-core/kern/i386/qemu/mmap.c index 2b0c7f6a7..ffb61a47a 100644 --- a/grub-core/kern/i386/qemu/mmap.c +++ b/grub-core/kern/i386/qemu/mmap.c @@ -39,7 +39,7 @@ extern char _end[]; static grub_uint64_t mem_size, above_4g; void -grub_machine_mmap_init () +grub_machine_mmap_init (void) { grub_uint8_t high, low, b, c, d; grub_cmos_read (QEMU_CMOS_MEMSIZE_HIGH, &high); diff --git a/grub-core/kern/i386/realmode.S b/grub-core/kern/i386/realmode.S index ecfdf4f19..a91adc3cd 100644 --- a/grub-core/kern/i386/realmode.S +++ b/grub-core/kern/i386/realmode.S @@ -46,7 +46,7 @@ * This is the area for all of the special variables. */ - .p2align 2 /* force 4-byte alignment */ + .p2align 5 /* force 4-byte alignment */ protstack: .long GRUB_MEMORY_MACHINE_PROT_STACK @@ -79,7 +79,7 @@ protstack: * description. */ - .p2align 2 /* force 4-byte alignment */ + .p2align 5 /* force 4-byte alignment */ gdt: .word 0, 0 .byte 0, 0, 0, 0 @@ -113,6 +113,7 @@ gdt: .byte 0, 0x92, 0, 0 + .p2align 5 /* this is the GDT descriptor */ gdtdesc: .word 0x27 /* limit */ diff --git a/grub-core/kern/ia64/dl.c b/grub-core/kern/ia64/dl.c index 31b5f94cf..39b77ceda 100644 --- a/grub-core/kern/ia64/dl.c +++ b/grub-core/kern/ia64/dl.c @@ -22,6 +22,7 @@ #include #include #include +#include /* Check if EHDR is a valid ELF header. */ grub_err_t @@ -33,11 +34,13 @@ grub_arch_dl_check_header (void *ehdr) if (e->e_ident[EI_CLASS] != ELFCLASS64 || e->e_ident[EI_DATA] != ELFDATA2LSB || e->e_machine != EM_IA_64) - return grub_error (GRUB_ERR_BAD_OS, "invalid arch specific ELF magic"); + return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch dependent ELF magic")); return GRUB_ERR_NONE; } +#pragma GCC diagnostic ignored "-Wcast-align" + #define MASK20 ((1 << 20) - 1) #define MASK19 ((1 << 19) - 1) @@ -181,7 +184,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) break; if (i == e->e_shnum) - return grub_error (GRUB_ERR_BAD_MODULE, "no symtab found"); + return grub_error (GRUB_ERR_BAD_MODULE, N_("no symbol table")); entsize = s->sh_entsize; @@ -265,7 +268,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) break; default: return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "this relocation (0x%x) is not implemented yet", + N_("relocation 0x%x is not implemented yet"), ELF_R_TYPE (rel->r_info)); } } diff --git a/grub-core/kern/ia64/dl_helper.c b/grub-core/kern/ia64/dl_helper.c index 958cdb25e..9394e32e2 100644 --- a/grub-core/kern/ia64/dl_helper.c +++ b/grub-core/kern/ia64/dl_helper.c @@ -23,6 +23,8 @@ #include #include +#pragma GCC diagnostic ignored "-Wcast-align" + void grub_ia64_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, grub_size_t *got) diff --git a/grub-core/kern/ieee1275/ieee1275.c b/grub-core/kern/ieee1275/ieee1275.c index b32fd2d8b..98217029f 100644 --- a/grub-core/kern/ieee1275/ieee1275.c +++ b/grub-core/kern/ieee1275/ieee1275.c @@ -27,7 +27,7 @@ int -grub_ieee1275_finddevice (char *name, grub_ieee1275_phandle_t *phandlep) +grub_ieee1275_finddevice (const char *name, grub_ieee1275_phandle_t *phandlep) { struct find_device_args { @@ -232,7 +232,7 @@ grub_ieee1275_instance_to_path (grub_ieee1275_ihandle_t ihandle, } int -grub_ieee1275_write (grub_ieee1275_ihandle_t ihandle, void *buffer, +grub_ieee1275_write (grub_ieee1275_ihandle_t ihandle, const void *buffer, grub_size_t len, grub_ssize_t *actualp) { struct write_args diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c index 76f932d09..bf59dc822 100644 --- a/grub-core/kern/ieee1275/init.c +++ b/grub-core/kern/ieee1275/init.c @@ -192,11 +192,11 @@ grub_claim_heap (void) if (len) { + grub_err_t err; /* Claim and use it. */ - if (grub_claimmap (addr, len) < 0) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, - "failed to claim heap at 0x%llx, len 0x%llx", - addr, len); + err = grub_claimmap (addr, len); + if (err) + return err; grub_mm_init_region ((void *) (grub_addr_t) addr, len); } diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c index 3568ffe64..caf820df5 100644 --- a/grub-core/kern/ieee1275/openfw.c +++ b/grub-core/kern/ieee1275/openfw.c @@ -34,7 +34,7 @@ enum grub_ieee1275_parse_type /* Walk children of 'devpath', calling hook for each. */ int -grub_children_iterate (char *devpath, +grub_children_iterate (const char *devpath, int (*hook) (struct grub_ieee1275_devalias *alias)) { grub_ieee1275_phandle_t dev; @@ -164,7 +164,7 @@ grub_devalias_iterate (int (*hook) (struct grub_ieee1275_devalias *alias)) strings, so we will add a NULL byte at the end explicitly. */ pathlen += 1; - devpath = grub_malloc (pathlen); + devpath = grub_malloc (pathlen + 1); if (! devpath) { grub_free (devtype); @@ -173,12 +173,15 @@ grub_devalias_iterate (int (*hook) (struct grub_ieee1275_devalias *alias)) } if (grub_ieee1275_get_property (aliases, aliasname, devpath, pathlen, - &actual)) + &actual) || actual < 0) { grub_dprintf ("devalias", "get_property (%s) failed\n", aliasname); goto nextprop; } - devpath [actual] = '\0'; + if (actual > pathlen) + actual = pathlen; + devpath[actual] = '\0'; + devpath[pathlen] = '\0'; if (grub_ieee1275_finddevice (devpath, &dev)) { @@ -252,7 +255,7 @@ grub_ieee1275_map (grub_addr_t phys, grub_addr_t virt, grub_size_t size, return args.catch_result; } -int +grub_err_t grub_claimmap (grub_addr_t addr, grub_size_t size) { if (grub_ieee1275_claim (addr, size, 0, 0)) @@ -261,13 +264,13 @@ grub_claimmap (grub_addr_t addr, grub_size_t size) if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_REAL_MODE) && grub_ieee1275_map (addr, addr, size, 0x00)) { - grub_printf ("map failed: address 0x%llx, size 0x%llx\n", - (long long) addr, (long long) size); + grub_error (GRUB_ERR_OUT_OF_MEMORY, "map failed: address 0x%llx, size 0x%llx\n", + (long long) addr, (long long) size); grub_ieee1275_release (addr, size); - return -1; + return grub_errno; } - return 0; + return GRUB_ERR_NONE; } /* Get the device arguments of the Open Firmware node name `path'. */ @@ -294,7 +297,8 @@ grub_ieee1275_get_devname (const char *path) int match_alias (struct grub_ieee1275_devalias *curalias) { /* briQ firmware can change capitalization in /chosen/bootpath. */ - if (! grub_strncasecmp (curalias->path, path, pathlen)) + if (grub_strncasecmp (curalias->path, path, pathlen) == 0 + && curalias->path[pathlen] == 0) { newpath = grub_strdup (curalias->name); return 1; @@ -446,10 +450,10 @@ grub_ieee1275_encode_devname (const char *path) /* GRUB partition 1 is OF partition 0. */ partno++; - encoding = grub_xasprintf ("%s,%d", device, partno); + encoding = grub_xasprintf ("ieee1275/%s,%d", device, partno); } else - encoding = grub_strdup (device); + encoding = grub_xasprintf ("ieee1275/%s", device); grub_free (partition); grub_free (device); diff --git a/grub-core/kern/list.c b/grub-core/kern/list.c index 33c334166..f7c4e6bbe 100644 --- a/grub-core/kern/list.c +++ b/grub-core/kern/list.c @@ -21,26 +21,6 @@ #include #include -void -grub_list_push (grub_list_t *head, grub_list_t item) -{ - item->next = *head; - *head = item; -} - -void -grub_list_remove (grub_list_t *head, grub_list_t item) -{ - grub_list_t *p, q; - - for (p = head, q = *p; q; p = &(q->next), q = q->next) - if (q == item) - { - *p = q->next; - break; - } -} - void * grub_named_list_find (grub_named_list_t head, const char *name) { @@ -81,6 +61,9 @@ grub_prio_list_insert (grub_prio_list_t *head, grub_prio_list_t nitem) *p = nitem; nitem->next = q; + if (q) + q->prev = &nitem->next; + nitem->prev = p; if (! inactive) nitem->prio |= GRUB_PRIO_LIST_FLAG_ACTIVE; diff --git a/grub-core/kern/main.c b/grub-core/kern/main.c index bf2789860..185230c5c 100644 --- a/grub-core/kern/main.c +++ b/grub-core/kern/main.c @@ -190,7 +190,7 @@ grub_load_normal_mode (void) } /* The main routine. */ -void +void __attribute__ ((noreturn)) grub_main (void) { /* First of all, initialize the machine. */ diff --git a/grub-core/kern/mips/arc/init.c b/grub-core/kern/mips/arc/init.c index 41545b11f..657a68ecd 100644 --- a/grub-core/kern/mips/arc/init.c +++ b/grub-core/kern/mips/arc/init.c @@ -125,7 +125,7 @@ grub_machine_mmap_iterate (grub_memory_hook_t hook) } } -extern grub_uint32_t grub_total_modules_size; +extern grub_uint32_t grub_total_modules_size __attribute__ ((section(".text"))); grub_addr_t grub_modbase; void diff --git a/grub-core/kern/mips/dl.c b/grub-core/kern/mips/dl.c index ad9340683..22b23d654 100644 --- a/grub-core/kern/mips/dl.c +++ b/grub-core/kern/mips/dl.c @@ -23,6 +23,7 @@ #include #include #include +#include /* Dummy __gnu_local_gp. Resolved by linker. */ static char __gnu_local_gp_dummy; @@ -43,11 +44,13 @@ grub_arch_dl_check_header (void *ehdr) || e->e_ident[EI_DATA] != ELFDATA2LSB || e->e_machine != EM_MIPS) #endif - return grub_error (GRUB_ERR_BAD_OS, "invalid arch specific ELF magic"); + return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch dependent ELF magic")); return GRUB_ERR_NONE; } +#pragma GCC diagnostic ignored "-Wcast-align" + /* Relocate symbols. */ grub_err_t grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) @@ -69,7 +72,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) break; if (i == e->e_shnum) - return grub_error (GRUB_ERR_BAD_MODULE, "no symtab found"); + return grub_error (GRUB_ERR_BAD_MODULE, N_("no symbol table")); entsize = s->sh_entsize; @@ -233,7 +236,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) { grub_free (gp); return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "Unknown relocation type %d\n", + N_("relocation 0x%x is not implemented yet"), ELF_R_TYPE (rel->r_info)); } break; diff --git a/grub-core/kern/mips/qemu_mips/init.c b/grub-core/kern/mips/qemu_mips/init.c index d331e1b24..120b450f5 100644 --- a/grub-core/kern/mips/qemu_mips/init.c +++ b/grub-core/kern/mips/qemu_mips/init.c @@ -18,9 +18,6 @@ extern void grub_video_init (void); extern void grub_bitmap_init (void); extern void grub_font_init (void); extern void grub_gfxterm_init (void); -extern void grub_at_keyboard_init (void); -extern void grub_serial_init (void); -extern void grub_terminfo_init (void); extern void grub_keylayouts_init (void); extern void grub_boot_init (void); extern void grub_vga_text_init (void); diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c index 128139dc8..cb49243d2 100644 --- a/grub-core/kern/misc.c +++ b/grub-core/kern/misc.c @@ -370,11 +370,13 @@ grub_strtoul (const char *str, char **end, int base) unsigned long long num; num = grub_strtoull (str, end, base); +#if GRUB_CPU_SIZEOF_LONG != 8 if (num > ~0UL) { - grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow is detected"); + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); return ~0UL; } +#endif return (unsigned long) num; } @@ -425,7 +427,8 @@ grub_strtoull (const char *str, char **end, int base) /* NUM * BASE + DIGIT > ~0ULL */ if (num > grub_divmod64 (~0ULL - digit, base, 0)) { - grub_error (GRUB_ERR_OUT_OF_RANGE, "overflow is detected"); + grub_error (GRUB_ERR_OUT_OF_RANGE, + N_("overflow is detected")); return ~0ULL; } @@ -435,7 +438,8 @@ grub_strtoull (const char *str, char **end, int base) if (! found) { - grub_error (GRUB_ERR_BAD_NUMBER, "unrecognized number"); + grub_error (GRUB_ERR_BAD_NUMBER, + N_("unrecognized number")); return 0; } @@ -749,6 +753,12 @@ grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt0, va_list a while (*fmt && grub_isdigit (*fmt)) fmt++; + if (*fmt && *fmt =='.') + fmt++; + + while (*fmt && grub_isdigit (*fmt)) + fmt++; + p = fmt; if (*fmt && *fmt == '$') diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c index ee4d58d81..95dd5ddf1 100644 --- a/grub-core/kern/mm.c +++ b/grub-core/kern/mm.c @@ -65,6 +65,7 @@ #include #include #include +#include #include #ifdef MM_DEBUG @@ -324,7 +325,7 @@ grub_memalign (grub_size_t align, grub_size_t size) } fail: - grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); return 0; } diff --git a/grub-core/kern/partition.c b/grub-core/kern/partition.c index cd9e8ae0f..82ae9c8c2 100644 --- a/grub-core/kern/partition.c +++ b/grub-core/kern/partition.c @@ -223,32 +223,34 @@ grub_partition_iterate (struct grub_disk *disk, char * grub_partition_get_name (const grub_partition_t partition) { - char *out = 0; - int curlen = 0; + char *out = 0, *ptr; + grub_size_t needlen = 0; grub_partition_t part; + if (!partition) + return grub_strdup (""); + for (part = partition; part; part = part->parent) + /* Even on 64-bit machines this buffer is enough to hold + longest number. */ + needlen += grub_strlen (part->partmap->name) + 1 + 27; + out = grub_malloc (needlen + 1); + if (!out) + return NULL; + + ptr = out + needlen; + *ptr = 0; for (part = partition; part; part = part->parent) { - /* Even on 64-bit machines this buffer is enough to hold - longest number. */ - char buf[grub_strlen (part->partmap->name) + 25]; - int strl; - grub_snprintf (buf, sizeof (buf), "%s%d", part->partmap->name, - part->number + 1); - strl = grub_strlen (buf); - if (curlen) - { - out = grub_realloc (out, curlen + strl + 2); - grub_memcpy (out + strl + 1, out, curlen); - out[curlen + 1 + strl] = 0; - grub_memcpy (out, buf, strl); - out[strl] = ','; - curlen = curlen + 1 + strl; - } - else - { - curlen = strl; - out = grub_strdup (buf); - } + char buf[27]; + grub_size_t len; + grub_snprintf (buf, sizeof (buf), "%d", part->number + 1); + len = grub_strlen (buf); + ptr -= len; + grub_memcpy (ptr, buf, len); + len = grub_strlen (part->partmap->name); + ptr -= len; + grub_memcpy (ptr, part->partmap->name, len); + *--ptr = ','; } + grub_memmove (out, ptr + 1, out + needlen - ptr); return out; } diff --git a/grub-core/kern/powerpc/dl.c b/grub-core/kern/powerpc/dl.c index 34e780a45..5b1db338c 100644 --- a/grub-core/kern/powerpc/dl.c +++ b/grub-core/kern/powerpc/dl.c @@ -21,6 +21,7 @@ #include #include #include +#include /* Check if EHDR is a valid ELF header. */ grub_err_t @@ -32,7 +33,7 @@ grub_arch_dl_check_header (void *ehdr) if (e->e_ident[EI_CLASS] != ELFCLASS32 || e->e_ident[EI_DATA] != ELFDATA2MSB || e->e_machine != EM_PPC) - return grub_error (GRUB_ERR_BAD_OS, "invalid arch specific ELF magic"); + return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch dependent ELF magic")); return GRUB_ERR_NONE; } @@ -43,7 +44,6 @@ grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, { const Elf_Ehdr *e = ehdr; const Elf_Shdr *s; - Elf_Word entsize; unsigned i; *tramp = 0; @@ -59,8 +59,6 @@ grub_arch_dl_get_tramp_got_size (const void *ehdr, grub_size_t *tramp, if (i == e->e_shnum) return; - entsize = s->sh_entsize; - for (i = 0, s = (const Elf_Shdr *) ((const char *) e + e->e_shoff); i < e->e_shnum; i++, s = (const Elf_Shdr *) ((const char *) s + e->e_shentsize)) @@ -115,7 +113,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) break; if (i == e->e_shnum) - return grub_error (GRUB_ERR_BAD_MODULE, "no symtab found"); + return grub_error (GRUB_ERR_BAD_MODULE, N_("no symbol table")); entsize = s->sh_entsize; @@ -198,7 +196,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) default: return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "this relocation (%d) is not implemented yet", + N_("relocation 0x%x is not implemented yet"), ELF_R_TYPE (rel->r_info)); } } diff --git a/grub-core/kern/rescue_parser.c b/grub-core/kern/rescue_parser.c index 9c85ba6bd..656342d27 100644 --- a/grub-core/kern/rescue_parser.c +++ b/grub-core/kern/rescue_parser.c @@ -23,6 +23,7 @@ #include #include #include +#include grub_err_t grub_rescue_parse_line (char *line, grub_reader_getline_t getline) @@ -63,7 +64,7 @@ grub_rescue_parse_line (char *line, grub_reader_getline_t getline) } else { - grub_printf ("Unknown command `%s'\n", name); + grub_printf_ (N_("Unknown command `%s'.\n"), name); if (grub_command_find ("help")) grub_printf ("Try `help' for usage\n"); } diff --git a/grub-core/kern/rescue_reader.c b/grub-core/kern/rescue_reader.c index a81008579..4587b944f 100644 --- a/grub-core/kern/rescue_reader.c +++ b/grub-core/kern/rescue_reader.c @@ -74,7 +74,7 @@ grub_rescue_read_line (char **line, int cont) return 0; } -void +void __attribute__ ((noreturn)) grub_rescue_run (void) { grub_printf ("Entering rescue mode...\n"); diff --git a/grub-core/kern/sparc64/dl.c b/grub-core/kern/sparc64/dl.c index 7b6266cac..a0c1837d0 100644 --- a/grub-core/kern/sparc64/dl.c +++ b/grub-core/kern/sparc64/dl.c @@ -21,6 +21,7 @@ #include #include #include +#include /* Check if EHDR is a valid ELF header. */ grub_err_t @@ -32,11 +33,12 @@ grub_arch_dl_check_header (void *ehdr) if (e->e_ident[EI_CLASS] != ELFCLASS64 || e->e_ident[EI_DATA] != ELFDATA2MSB || e->e_machine != EM_SPARCV9) - return grub_error (GRUB_ERR_BAD_OS, "invalid arch specific ELF magic"); + return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch dependent ELF magic")); return GRUB_ERR_NONE; } +#pragma GCC diagnostic ignored "-Wcast-align" /* Relocate symbols. */ grub_err_t @@ -55,7 +57,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) break; if (i == e->e_shnum) - return grub_error (GRUB_ERR_BAD_MODULE, "no symtab found"); + return grub_error (GRUB_ERR_BAD_MODULE, N_("no symbol table")); entsize = s->sh_entsize; @@ -111,10 +113,13 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) (((grub_int32_t) ((value - (Elf_Addr) addr) >> 2)) & 0x3FFFFFFF); break; + case R_SPARC_HH22: /* 9 V-imm22 */ + *addr = (*addr & 0xFFC00000) | ((value >> 42) & 0x3FFFFF); + break; + case R_SPARC_HM10: /* 12 T-simm13 */ + *addr = (*addr & 0xFFFFFC00) | ((value >> 32) & 0x3FF); + break; case R_SPARC_HI22: /* 9 V-imm22 */ - if (((grub_int32_t) value) & 0xFF00000000) - return grub_error (GRUB_ERR_BAD_MODULE, - "high address out of 22 bits range"); *addr = (*addr & 0xFFC00000) | ((value >> 10) & 0x3FFFFF); break; case R_SPARC_LO10: /* 12 T-simm13 */ @@ -131,7 +136,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) break; default: return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "this relocation (%d) is not implemented yet", + N_("relocation 0x%x is not implemented yet"), ELF_R_TYPE (rel->r_info)); } } diff --git a/grub-core/kern/term.c b/grub-core/kern/term.c index d7c65dd82..767f5c107 100644 --- a/grub-core/kern/term.c +++ b/grub-core/kern/term.c @@ -79,16 +79,11 @@ grub_xputs_dumb (const char *str) void (*grub_xputs) (const char *str) = grub_xputs_dumb; -static int pending_key = GRUB_TERM_NO_KEY; - int -grub_checkkey (void) +grub_getkey_noblock (void) { grub_term_input_t term; - if (pending_key != GRUB_TERM_NO_KEY) - return pending_key; - if (grub_term_poll_usb) grub_term_poll_usb (); @@ -97,12 +92,12 @@ grub_checkkey (void) FOR_ACTIVE_TERM_INPUTS(term) { - pending_key = term->getkey (term); - if (pending_key != GRUB_TERM_NO_KEY) - return pending_key; + int key = term->getkey (term); + if (key != GRUB_TERM_NO_KEY) + return key; } - return -1; + return GRUB_TERM_NO_KEY; } int @@ -112,18 +107,15 @@ grub_getkey (void) grub_refresh (); - grub_checkkey (); - while (pending_key == GRUB_TERM_NO_KEY) + while (1) { + ret = grub_getkey_noblock (); + if (ret != GRUB_TERM_NO_KEY) + return ret; grub_cpu_idle (); - grub_checkkey (); } - ret = pending_key; - pending_key = GRUB_TERM_NO_KEY; - return ret; } - void grub_refresh (void) { diff --git a/grub-core/kern/x86_64/dl.c b/grub-core/kern/x86_64/dl.c index 9b63b30f8..cf3adf9d0 100644 --- a/grub-core/kern/x86_64/dl.c +++ b/grub-core/kern/x86_64/dl.c @@ -21,6 +21,7 @@ #include #include #include +#include /* Check if EHDR is a valid ELF header. */ grub_err_t @@ -32,7 +33,7 @@ grub_arch_dl_check_header (void *ehdr) if (e->e_ident[EI_CLASS] != ELFCLASS64 || e->e_ident[EI_DATA] != ELFDATA2LSB || e->e_machine != EM_X86_64) - return grub_error (GRUB_ERR_BAD_OS, "invalid arch specific ELF magic"); + return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch dependent ELF magic")); return GRUB_ERR_NONE; } @@ -54,7 +55,7 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) break; if (i == e->e_shnum) - return grub_error (GRUB_ERR_BAD_MODULE, "no symtab found"); + return grub_error (GRUB_ERR_BAD_MODULE, N_("no symbol table")); entsize = s->sh_entsize; @@ -108,9 +109,9 @@ grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) *addr32 += rel->r_addend + sym->st_value; break; - default: + default: return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "this relocation (%d) is not implemented yet", + N_("relocation 0x%x is not implemented yet"), ELF_R_TYPE (rel->r_info)); } } diff --git a/grub-core/kern/x86_64/efi/callwrap.S b/grub-core/kern/x86_64/efi/callwrap.S index dced859ac..2df95dda1 100644 --- a/grub-core/kern/x86_64/efi/callwrap.S +++ b/grub-core/kern/x86_64/efi/callwrap.S @@ -25,7 +25,7 @@ * different call conversion, so we need to do some conversion. * * gcc: - * %rdi, %esi, %rdx, %rcx, %r8, %r9, 8(%rsp), 16(%rsp), ... + * %rdi, %rsi, %rdx, %rcx, %r8, %r9, 8(%rsp), 16(%rsp), ... * * efi: * %rcx, %rdx, %r8, %r9, 32(%rsp), 40(%rsp), 48(%rsp), ... diff --git a/grub-core/lib/LzFind.c b/grub-core/lib/LzFind.c index d2bb15c65..dcb20d921 100644 --- a/grub-core/lib/LzFind.c +++ b/grub-core/lib/LzFind.c @@ -69,9 +69,9 @@ static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *a } Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } -Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; } +static Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 curindex) { return p->buffer[curindex]; } -UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } +static UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) { diff --git a/grub-core/lib/LzmaEnc.c b/grub-core/lib/LzmaEnc.c index 258ed9c91..ae0c3b9f6 100644 --- a/grub-core/lib/LzmaEnc.c +++ b/grub-core/lib/LzmaEnc.c @@ -120,7 +120,7 @@ UInt32 GetPosSlot1(UInt32 pos) #define kNumLogBits (9 + (int)sizeof(size_t) / 2) #define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) -void LzmaEnc_FastPosInit(Byte *g_FastPos) +static void LzmaEnc_FastPosInit(Byte *g_FastPos) { int c = 2, slotFast; g_FastPos[0] = 0; @@ -374,58 +374,6 @@ typedef struct _CLzmaEnc CSaveState saveState; } CLzmaEnc; -void LzmaEnc_SaveState(CLzmaEncHandle pp) -{ - CLzmaEnc *p = (CLzmaEnc *)pp; - CSaveState *dest = &p->saveState; - int i; - dest->lenEnc = p->lenEnc; - dest->repLenEnc = p->repLenEnc; - dest->state = p->state; - - for (i = 0; i < kNumStates; i++) - { - memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); - memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); - } - for (i = 0; i < kNumLenToPosStates; i++) - memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); - memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); - memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); - memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); - memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); - memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); - memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); - memcpy(dest->reps, p->reps, sizeof(p->reps)); - memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb)); -} - -void LzmaEnc_RestoreState(CLzmaEncHandle pp) -{ - CLzmaEnc *dest = (CLzmaEnc *)pp; - const CSaveState *p = &dest->saveState; - int i; - dest->lenEnc = p->lenEnc; - dest->repLenEnc = p->repLenEnc; - dest->state = p->state; - - for (i = 0; i < kNumStates; i++) - { - memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i])); - memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i])); - } - for (i = 0; i < kNumLenToPosStates; i++) - memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i])); - memcpy(dest->isRep, p->isRep, sizeof(p->isRep)); - memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0)); - memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1)); - memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2)); - memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders)); - memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder)); - memcpy(dest->reps, p->reps, sizeof(p->reps)); - memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb)); -} - SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) { CLzmaEnc *p = (CLzmaEnc *)pp; @@ -643,7 +591,7 @@ static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, while (symbol < 0x10000); } -void LzmaEnc_InitPriceTables(UInt32 *ProbPrices) +static void LzmaEnc_InitPriceTables(UInt32 *ProbPrices) { UInt32 i; for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits)) @@ -975,6 +923,8 @@ static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur) #define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300) +#pragma GCC diagnostic ignored "-Wshadow" + static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes) { UInt32 numAvailableBytes, lenMain, numDistancePairs; @@ -1769,7 +1719,7 @@ static void FillDistancesPrices(CLzmaEnc *p) p->matchPriceCount = 0; } -void LzmaEnc_Construct(CLzmaEnc *p) +static void LzmaEnc_Construct(CLzmaEnc *p) { RangeEnc_Construct(&p->rc); MatchFinder_Construct(&p->matchFinderBase); @@ -1802,7 +1752,7 @@ CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc) return p; } -void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) +static void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) { alloc->Free(alloc, p->litProbs); alloc->Free(alloc, p->saveState.litProbs); @@ -1810,7 +1760,7 @@ void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc) p->saveState.litProbs = 0; } -void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) +static void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig) { #ifdef COMPRESS_MF_MT MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); @@ -2043,7 +1993,7 @@ static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, I return SZ_OK; } -void LzmaEnc_Init(CLzmaEnc *p) +static void LzmaEnc_Init(CLzmaEnc *p) { UInt32 i; p->state = 0; @@ -2102,7 +2052,7 @@ void LzmaEnc_Init(CLzmaEnc *p) p->lpMask = (1 << p->lp) - 1; } -void LzmaEnc_InitPrices(CLzmaEnc *p) +static void LzmaEnc_InitPrices(CLzmaEnc *p) { if (!p->fastMode) { @@ -2143,15 +2093,6 @@ static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqInStream *inStream, ISeqOutSt return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); } -SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, - ISeqInStream *inStream, UInt32 keepWindowSize, - ISzAlloc *alloc, ISzAlloc *allocBig) -{ - CLzmaEnc *p = (CLzmaEnc *)pp; - p->inStream = inStream; - return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); -} - static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) { p->seqBufInStream.funcTable.Read = MyRead; @@ -2159,16 +2100,7 @@ static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) p->seqBufInStream.rem = srcLen; } -SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, - UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig) -{ - CLzmaEnc *p = (CLzmaEnc *)pp; - LzmaEnc_SetInputBuf(p, src, srcLen); - p->inStream = &p->seqBufInStream.funcTable; - return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); -} - -void LzmaEnc_Finish(CLzmaEncHandle pp) +static void LzmaEnc_Finish(CLzmaEncHandle pp) { #ifdef COMPRESS_MF_MT CLzmaEnc *p = (CLzmaEnc *)pp; @@ -2201,53 +2133,6 @@ static size_t MyWrite(void *pp, const void *data, size_t size) return size; } - -UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp) -{ - const CLzmaEnc *p = (CLzmaEnc *)pp; - return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); -} - -const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) -{ - const CLzmaEnc *p = (CLzmaEnc *)pp; - return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; -} - -SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit, - Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) -{ - CLzmaEnc *p = (CLzmaEnc *)pp; - UInt64 nowPos64; - SRes res; - CSeqOutStreamBuf outStream; - - outStream.funcTable.Write = MyWrite; - outStream.data = dest; - outStream.rem = *destLen; - outStream.overflow = False; - - p->writeEndMark = False; - p->finished = False; - p->result = SZ_OK; - - if (reInit) - LzmaEnc_Init(p); - LzmaEnc_InitPrices(p); - nowPos64 = p->nowPos64; - RangeEnc_Init(&p->rc); - p->rc.outStream = &outStream.funcTable; - - res = LzmaEnc_CodeOneBlock(pp, True, desiredPackSize, *unpackSize); - - *unpackSize = (UInt32)(p->nowPos64 - nowPos64); - *destLen -= outStream.rem; - if (outStream.overflow) - return SZ_ERROR_OUTPUT_EOF; - - return res; -} - SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig) { diff --git a/grub-core/lib/arg.c b/grub-core/lib/arg.c index 75b1dd53c..b34188528 100644 --- a/grub-core/lib/arg.c +++ b/grub-core/lib/arg.c @@ -25,14 +25,11 @@ #include /* Built-in parser for default options. */ -#define SHORT_ARG_HELP -100 -#define SHORT_ARG_USAGE -101 - static const struct grub_arg_option help_options[] = { - {"help", SHORT_ARG_HELP, 0, + {"help", 0, 0, N_("Display this help and exit."), 0, ARG_TYPE_NONE}, - {"usage", SHORT_ARG_USAGE, 0, + {"usage", 0, 0, N_("Display the usage of this command and exit."), 0, ARG_TYPE_NONE}, {0, 0, 0, 0, 0, 0} }; @@ -125,9 +122,9 @@ grub_arg_show_help (grub_extcmd_t cmd) if (opt->shortarg && grub_isgraph (opt->shortarg)) grub_printf ("-%c%c ", opt->shortarg, opt->longarg ? ',':' '); - else if (opt->shortarg == SHORT_ARG_HELP && ! h_is_used) + else if (opt == help_options && ! h_is_used) grub_printf ("-h, "); - else if (opt->shortarg == SHORT_ARG_USAGE && ! u_is_used) + else if (opt == help_options + 1 && ! u_is_used) grub_printf ("-u, "); else grub_printf (" "); @@ -180,50 +177,34 @@ grub_arg_show_help (grub_extcmd_t cmd) static int -parse_option (grub_extcmd_t cmd, int key, char *arg, struct grub_arg_list *usr) +parse_option (grub_extcmd_t cmd, const struct grub_arg_option *opt, + char *arg, struct grub_arg_list *usr) { - switch (key) + if (opt == help_options) { - case SHORT_ARG_HELP: grub_arg_show_help (cmd); return -1; + } - case SHORT_ARG_USAGE: + if (opt == help_options + 1) + { show_usage (cmd); return -1; - - default: - { - int found = -1; - int i = 0; - const struct grub_arg_option *opt = cmd->options; - - while (opt->doc) - { - if (opt->shortarg && key == opt->shortarg) - { - found = i; - break; - } - opt++; - i++; - } - - if (found == -1) - return -1; - - if (opt->flags & GRUB_ARG_OPTION_REPEATABLE) - { - usr[found].args[usr[found].set++] = arg; - usr[found].args[usr[found].set] = NULL; - } - else - { - usr[found].set = 1; - usr[found].arg = arg; - } - } } + { + int found = opt - cmd->options; + + if (opt->flags & GRUB_ARG_OPTION_REPEATABLE) + { + usr[found].args[usr[found].set++] = arg; + usr[found].args[usr[found].set] = NULL; + } + else + { + usr[found].set = 1; + usr[found].arg = arg; + } + } return 0; } @@ -296,8 +277,9 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, if (! opt) { + char tmp[3] = { '-', *curshort, 0 }; grub_error (GRUB_ERR_BAD_ARGUMENT, - "unknown argument `-%c'", *curshort); + N_("unknown argument `%s'"), tmp); goto fail; } @@ -307,7 +289,7 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, it can have an argument value. */ if (*curshort) { - if (parse_option (cmd, opt->shortarg, 0, usr) || grub_errno) + if (parse_option (cmd, opt, 0, usr) || grub_errno) goto fail; } else @@ -351,7 +333,7 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, opt = find_long (cmd->options, arg + 2, arglen); if (!option && argv[curarg + 1] && argv[curarg + 1][0] != '-' - && opt->type != ARG_TYPE_NONE) + && opt && opt->type != ARG_TYPE_NONE) option = argv[++curarg]; if (!opt && (cmd->cmd->flags & GRUB_COMMAND_ACCEPT_DASH)) @@ -363,7 +345,7 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, if (! opt) { - grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown argument `%s'", arg); + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unknown argument `%s'"), arg); goto fail; } } @@ -374,7 +356,7 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, if (! option) { grub_error (GRUB_ERR_BAD_ARGUMENT, - "missing mandatory option for `%s'", opt->longarg); + N_("missing mandatory option for `%s'"), opt->longarg); goto fail; } @@ -396,7 +378,7 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, if (tail == 0 || tail == option || *tail != '\0' || grub_errno) { grub_error (GRUB_ERR_BAD_ARGUMENT, - "the argument `%s' requires an integer", + N_("the argument `%s' requires an integer"), arg); goto fail; @@ -411,7 +393,7 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, /* XXX: Not implemented. */ break; } - if (parse_option (cmd, opt->shortarg, option, usr) || grub_errno) + if (parse_option (cmd, opt, option, usr) || grub_errno) goto fail; } else @@ -419,12 +401,12 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, if (option) { grub_error (GRUB_ERR_BAD_ARGUMENT, - "a value was assigned to the argument `%s' while it " - "doesn't require an argument", arg); + N_("a value was assigned to the argument `%s' while it " + "doesn't require an argument"), arg); goto fail; } - if (parse_option (cmd, opt->shortarg, 0, usr) || grub_errno) + if (parse_option (cmd, opt, 0, usr) || grub_errno) goto fail; } } diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c index 4dec5c694..f4b13ed3d 100644 --- a/grub-core/lib/crypto.c +++ b/grub-core/lib/crypto.c @@ -22,6 +22,7 @@ #include #include #include +#include #ifdef GRUB_UTIL #include @@ -169,20 +170,6 @@ grub_crypto_cipher_set_key (grub_crypto_cipher_handle_t cipher, return cipher->cipher->setkey (cipher->ctx, key, keylen); } -void -grub_crypto_xor (void *out, const void *in1, const void *in2, grub_size_t size) -{ - const grub_uint8_t *in1ptr = in1, *in2ptr = in2; - grub_uint8_t *outptr = out; - while (size--) - { - *outptr = *in1ptr ^ *in2ptr; - in1ptr++; - in2ptr++; - outptr++; - } -} - gcry_err_code_t grub_crypto_ecb_decrypt (grub_crypto_cipher_handle_t cipher, void *out, const void *in, grub_size_t size) diff --git a/grub-core/lib/i386/relocator.c b/grub-core/lib/i386/relocator.c index 1f0aa0dd1..74379f6f0 100644 --- a/grub-core/lib/i386/relocator.c +++ b/grub-core/lib/i386/relocator.c @@ -25,6 +25,7 @@ #include #include +#include extern grub_uint8_t grub_relocator_forward_start; extern grub_uint8_t grub_relocator_forward_end; @@ -200,8 +201,10 @@ grub_relocator16_boot (struct grub_relocator *rel, /* Put it higher than the byte it checks for A20 check. */ err = grub_relocator_alloc_chunk_align (rel, &ch, 0x8010, - 0xa0000 - RELOCATOR_SIZEOF (16), - RELOCATOR_SIZEOF (16), 16, + 0xa0000 - RELOCATOR_SIZEOF (16) + - GRUB_RELOCATOR16_STACK_SIZE, + RELOCATOR_SIZEOF (16) + + GRUB_RELOCATOR16_STACK_SIZE, 16, GRUB_RELOCATOR_PREFERENCE_NONE); if (err) return err; diff --git a/grub-core/lib/i386/relocator16.S b/grub-core/lib/i386/relocator16.S index babe69e1d..30629dbe1 100644 --- a/grub-core/lib/i386/relocator16.S +++ b/grub-core/lib/i386/relocator16.S @@ -26,6 +26,8 @@ #define PSEUDO_REAL_DSEG 0x20 +#include + #include "relocator_common.S" .p2align 4 /* force 16-byte alignment */ @@ -101,10 +103,9 @@ VARIABLE(grub_relocator16_keep_a20_enabled) test %ax, %ax jnz LOCAL(gate_a20_done) - /* first of all, test if already in a good state */ - call LOCAL(gate_a20_check_state) - testb %al, %al - jz LOCAL(gate_a20_done) + movw %cs, %ax + movw %ax, %ss + leaw EXT_C(grub_relocator16_end) - LOCAL(base) + GRUB_RELOCATOR16_STACK_SIZE, %sp /* second, try a BIOS call */ movw $0x2400, %ax @@ -132,14 +133,6 @@ LOCAL(gate_a20_check_state): /* iterate the checking for a while */ movw $100, %cx 1: - call 3f - testb %al, %al - jz 2f - loop 1b -2: - ret - -3: xorw %ax, %ax movw %ax, %ds decw %ax @@ -168,7 +161,12 @@ LOCAL(gate_a20_check_state): subb %dh, %al xorb $1, %al /* restore the original */ - movb %dl, %es:(%di) + movb %dl, %ds:(%si) + + testb %al, %al + jz LOCAL(gate_a20_done) + loop 1b +2: ret LOCAL(gate_a20_done): diff --git a/grub-core/lib/ieee1275/relocator.c b/grub-core/lib/ieee1275/relocator.c index c09f1e9c5..021f0ce71 100644 --- a/grub-core/lib/ieee1275/relocator.c +++ b/grub-core/lib/ieee1275/relocator.c @@ -85,7 +85,10 @@ grub_relocator_firmware_fill_events (struct grub_relocator_mmap_event *events) int grub_relocator_firmware_alloc_region (grub_addr_t start, grub_size_t size) { - return (grub_claimmap (start, size) >= 0); + grub_err_t err; + err = grub_claimmap (start, size); + grub_errno = 0; + return (err == 0); } void diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 43fca51dc..775eaad1f 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -22,6 +22,7 @@ #include #include #include +#include struct legacy_command { @@ -42,7 +43,8 @@ struct legacy_command TYPE_BOOL, TYPE_INT, TYPE_REST_VERBATIM, - TYPE_VBE_MODE + TYPE_VBE_MODE, + TYPE_WITH_CONFIGFILE_OPTION } argt[4]; enum { FLAG_IGNORE_REST = 0x001, @@ -67,7 +69,13 @@ static struct legacy_command legacy_commands[] = "Print the blocklist notation of the file FILE."}, {"boot", "boot\n", NULL, 0, 0, {}, 0, 0, "Boot the OS/chain-loader which has been loaded."}, - /* FIXME: bootp unsupported. */ + {"bootp", "net_bootp; net_ls_addr; if [ x%s = x--with-configfile ]; then " + "if net_get_dhcp_option configfile_name pxe 150 string; then " + "configfile $configfile_name; fi; fi\n", NULL, 0, 1, + {TYPE_WITH_CONFIGFILE_OPTION}, FLAG_IGNORE_REST, "[--with-configfile]", + "Initialize a network device via BOOTP. If the option `--with-configfile'" + " is given, try to load a configuration file specified by the 150 vendor" + " tag."}, {"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, @@ -105,7 +113,13 @@ static struct legacy_command legacy_commands[] = "[NUM | `saved']", "Set the default entry to entry number NUM (if not specified, it is" " 0, the first entry) or the entry number saved by savedefault."}, - /* FIXME: dhcp unsupported. */ + {"dhcp", "net_bootp; net_ls_addr; if [ x%s = x--with-configfile ]; then " + "if net_get_dhcp_option configfile_name pxe 150 string; then " + "configfile $configfile_name; fi; fi\n", NULL, 0, 1, + {TYPE_WITH_CONFIGFILE_OPTION}, FLAG_IGNORE_REST, "[--with-configfile]", + "Initialize a network device via BOOTP. If the option `--with-configfile'" + " is given, try to load a configuration file specified by the 150 vendor" + " tag."}, {"displayapm", "lsapm\n", NULL, 0, 0, {}, 0, 0, "Display APM BIOS information."}, {"displaymem", "lsmmap\n", NULL, 0, 0, {}, 0, 0, @@ -402,7 +416,7 @@ adjust_file (const char *in, grub_size_t len) } static int -check_option (const char *a, char *b, grub_size_t len) +check_option (const char *a, const char *b, grub_size_t len) { if (grub_strlen (b) != len) return 0; @@ -414,6 +428,8 @@ is_option (enum arg_type opt, const char *curarg, grub_size_t len) { switch (opt) { + case TYPE_WITH_CONFIGFILE_OPTION: + return check_option (curarg, "--with-configfile", len); case TYPE_NOAPM_OPTION: return check_option (curarg, "--no-apm", len); case TYPE_FORCE_OPTION: @@ -665,6 +681,7 @@ grub_legacy_parse (const char *buf, char **entryname, char **suffix) case TYPE_VERBATIM: args[i] = grub_legacy_escape (curarg, curarglen); break; + case TYPE_WITH_CONFIGFILE_OPTION: case TYPE_FORCE_OPTION: case TYPE_NOAPM_OPTION: case TYPE_TYPE_OR_NOMEM_OPTION: @@ -759,6 +776,7 @@ grub_legacy_parse (const char *buf, char **entryname, char **suffix) case TYPE_FILE: case TYPE_REST_VERBATIM: case TYPE_VERBATIM: + case TYPE_WITH_CONFIGFILE_OPTION: case TYPE_FORCE_OPTION: case TYPE_NOAPM_OPTION: case TYPE_TYPE_OR_NOMEM_OPTION: @@ -784,7 +802,7 @@ grub_legacy_parse (const char *buf, char **entryname, char **suffix) len = grub_strlen (corig); if (!slash) { - grub_error (GRUB_ERR_BAD_ARGUMENT, "bad color specification %s", + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid color specification `%s'"), args[0]); return NULL; } diff --git a/grub-core/lib/libgcrypt/cipher/md4.c b/grub-core/lib/libgcrypt/cipher/md4.c index 680cf87f5..aa180f0d4 100644 --- a/grub-core/lib/libgcrypt/cipher/md4.c +++ b/grub-core/lib/libgcrypt/cipher/md4.c @@ -101,7 +101,8 @@ transform ( MD4_CONTEXT *ctx, const unsigned char *data ) #ifdef WORDS_BIGENDIAN { int i; - byte *p2, *p1; + byte *p2; + const byte *p1; for(i=0, p1=data, p2=(byte*)in; i < 16; i++, p2 += 4 ) { p2[3] = *p1++; diff --git a/grub-core/lib/libgcrypt/cipher/md5.c b/grub-core/lib/libgcrypt/cipher/md5.c index 899dce89a..3d3046df2 100644 --- a/grub-core/lib/libgcrypt/cipher/md5.c +++ b/grub-core/lib/libgcrypt/cipher/md5.c @@ -92,7 +92,8 @@ transform ( MD5_CONTEXT *ctx, const unsigned char *data ) #ifdef WORDS_BIGENDIAN { int i; - byte *p2, *p1; + byte *p2; + const byte *p1; for(i=0, p1=data, p2=(byte*)correct_words; i < 16; i++, p2 += 4 ) { p2[3] = *p1++; diff --git a/grub-core/lib/libgcrypt/cipher/rmd160.c b/grub-core/lib/libgcrypt/cipher/rmd160.c index 7805bf53b..73d533739 100644 --- a/grub-core/lib/libgcrypt/cipher/rmd160.c +++ b/grub-core/lib/libgcrypt/cipher/rmd160.c @@ -169,7 +169,8 @@ transform ( RMD160_CONTEXT *hd, const unsigned char *data ) u32 x[16]; { int i; - byte *p2, *p1; + byte *p2; + const byte *p1; for (i=0, p1=data, p2=(byte*)x; i < 16; i++, p2 += 4 ) { p2[3] = *p1++; diff --git a/grub-core/lib/libgcrypt/cipher/serpent.c b/grub-core/lib/libgcrypt/cipher/serpent.c index 6b7e655a9..b1026eafc 100644 --- a/grub-core/lib/libgcrypt/cipher/serpent.c +++ b/grub-core/lib/libgcrypt/cipher/serpent.c @@ -585,22 +585,19 @@ serpent_key_prepare (const byte *key, unsigned int key_length, int i; /* Copy key. */ - for (i = 0; i < key_length / 4; i++) - { + memcpy (key_prepared, key, key_length); #ifdef WORDS_BIGENDIAN - key_prepared[i] = byte_swap_32 (((u32 *) key)[i]); -#else - key_prepared[i] = ((u32 *) key)[i]; + for (i = 0; i < key_length / 4; i++) + key_prepared[i] = byte_swap_32 (key_prepared[i]); #endif - } - if (i < 8) + if (key_length < 32) { /* Key must be padded according to the Serpent specification. */ - key_prepared[i] = 0x00000001; + key_prepared[key_length / 4] = 0x00000001; - for (i++; i < 8; i++) + for (i = key_length / 4 + 1; i < 8; i++) key_prepared[i] = 0; } } @@ -707,21 +704,17 @@ serpent_setkey (void *ctx, static void serpent_encrypt_internal (serpent_context_t *context, - const serpent_block_t input, serpent_block_t output) + const byte *input, byte *output) { serpent_block_t b, b_next; int round = 0; + memcpy (b, input, sizeof (b)); #ifdef WORDS_BIGENDIAN - b[0] = byte_swap_32 (input[0]); - b[1] = byte_swap_32 (input[1]); - b[2] = byte_swap_32 (input[2]); - b[3] = byte_swap_32 (input[3]); -#else - b[0] = input[0]; - b[1] = input[1]; - b[2] = input[2]; - b[3] = input[3]; + b[0] = byte_swap_32 (b[0]); + b[1] = byte_swap_32 (b[1]); + b[2] = byte_swap_32 (b[2]); + b[3] = byte_swap_32 (b[3]); #endif ROUND (0, context->keys, b, b_next); @@ -759,35 +752,27 @@ serpent_encrypt_internal (serpent_context_t *context, ROUND_LAST (7, context->keys, b, b_next); #ifdef WORDS_BIGENDIAN - output[0] = byte_swap_32 (b_next[0]); - output[1] = byte_swap_32 (b_next[1]); - output[2] = byte_swap_32 (b_next[2]); - output[3] = byte_swap_32 (b_next[3]); -#else - output[0] = b_next[0]; - output[1] = b_next[1]; - output[2] = b_next[2]; - output[3] = b_next[3]; + b_next[0] = byte_swap_32 (b_next[0]); + b_next[1] = byte_swap_32 (b_next[1]); + b_next[2] = byte_swap_32 (b_next[2]); + b_next[3] = byte_swap_32 (b_next[3]); #endif + memcpy (output, b_next, sizeof (b_next)); } static void serpent_decrypt_internal (serpent_context_t *context, - const serpent_block_t input, serpent_block_t output) + const byte *input, byte *output) { serpent_block_t b, b_next; int round = ROUNDS; + memcpy (b, input, sizeof (b)); #ifdef WORDS_BIGENDIAN - b_next[0] = byte_swap_32 (input[0]); - b_next[1] = byte_swap_32 (input[1]); - b_next[2] = byte_swap_32 (input[2]); - b_next[3] = byte_swap_32 (input[3]); -#else - b_next[0] = input[0]; - b_next[1] = input[1]; - b_next[2] = input[2]; - b_next[3] = input[3]; + b[0] = byte_swap_32 (b[0]); + b[1] = byte_swap_32 (b[1]); + b[2] = byte_swap_32 (b[2]); + b[3] = byte_swap_32 (b[3]); #endif ROUND_FIRST_INVERSE (7, context->keys, b_next, b); @@ -824,18 +809,13 @@ serpent_decrypt_internal (serpent_context_t *context, ROUND_INVERSE (1, context->keys, b, b_next); ROUND_INVERSE (0, context->keys, b, b_next); - #ifdef WORDS_BIGENDIAN - output[0] = byte_swap_32 (b_next[0]); - output[1] = byte_swap_32 (b_next[1]); - output[2] = byte_swap_32 (b_next[2]); - output[3] = byte_swap_32 (b_next[3]); -#else - output[0] = b_next[0]; - output[1] = b_next[1]; - output[2] = b_next[2]; - output[3] = b_next[3]; + b_next[0] = byte_swap_32 (b_next[0]); + b_next[1] = byte_swap_32 (b_next[1]); + b_next[2] = byte_swap_32 (b_next[2]); + b_next[3] = byte_swap_32 (b_next[3]); #endif + memcpy (output, b_next, sizeof (b_next)); } static void @@ -843,8 +823,7 @@ serpent_encrypt (void *ctx, byte *buffer_out, const byte *buffer_in) { serpent_context_t *context = ctx; - serpent_encrypt_internal (context, - (const u32 *) buffer_in, (u32 *) buffer_out); + serpent_encrypt_internal (context, buffer_in, buffer_out); _gcry_burn_stack (2 * sizeof (serpent_block_t)); } @@ -853,9 +832,7 @@ serpent_decrypt (void *ctx, byte *buffer_out, const byte *buffer_in) { serpent_context_t *context = ctx; - serpent_decrypt_internal (context, - (const u32 *) buffer_in, - (u32 *) buffer_out); + serpent_decrypt_internal (context, buffer_in, buffer_out); _gcry_burn_stack (2 * sizeof (serpent_block_t)); } @@ -915,8 +892,8 @@ serpent_test (void) serpent_setkey_internal (&context, test_data[i].key, test_data[i].key_length); serpent_encrypt_internal (&context, - (const u32 *) test_data[i].text_plain, - (u32 *) scratch); + test_data[i].text_plain, + scratch); if (memcmp (scratch, test_data[i].text_cipher, sizeof (serpent_block_t))) switch (test_data[i].key_length) @@ -930,8 +907,8 @@ serpent_test (void) } serpent_decrypt_internal (&context, - (const u32 *) test_data[i].text_cipher, - (u32 *) scratch); + test_data[i].text_cipher, + scratch); if (memcmp (scratch, test_data[i].text_plain, sizeof (serpent_block_t))) switch (test_data[i].key_length) { diff --git a/grub-core/lib/libgcrypt_wrap/cipher_wrap.h b/grub-core/lib/libgcrypt_wrap/cipher_wrap.h index 0141400fc..70c0fb430 100644 --- a/grub-core/lib/libgcrypt_wrap/cipher_wrap.h +++ b/grub-core/lib/libgcrypt_wrap/cipher_wrap.h @@ -25,13 +25,14 @@ #include #include -#ifdef GRUB_CPU_WORDS_BIGENDIAN -#define WORDS_BIGENDIAN -#else #undef WORDS_BIGENDIAN + +#ifdef GRUB_CPU_WORDS_BIGENDIAN +#define WORDS_BIGENDIAN 1 #endif -#define __GNU_LIBRARY__ +#undef __GNU_LIBRARY__ +#define __GNU_LIBRARY__ 1 #define DIM ARRAY_SIZE @@ -88,6 +89,7 @@ fips_mode (void) } #ifdef GRUB_UTIL +#pragma GCC diagnostic ignored "-Wshadow" static inline void * memcpy (void *dest, const void *src, grub_size_t n) { @@ -105,6 +107,7 @@ memcmp (const void *s1, const void *s2, grub_size_t n) { return grub_memcmp (s1, s2, n); } +#pragma GCC diagnostic error "-Wshadow" #endif diff --git a/grub-core/lib/pbkdf2.c b/grub-core/lib/pbkdf2.c index 09b8c7360..beac3c3d6 100644 --- a/grub-core/lib/pbkdf2.c +++ b/grub-core/lib/pbkdf2.c @@ -31,6 +31,8 @@ GRUB_MOD_LICENSE ("GPLv2+"); desired derived output length DKLEN. Output buffer is DK which must have room for at least DKLEN octets. The output buffer will be filled with the derived data. */ +#pragma GCC diagnostic ignored "-Wunreachable-code" + gcry_err_code_t grub_crypto_pbkdf2 (const struct gcry_md_spec *md, const grub_uint8_t *P, grub_size_t Plen, diff --git a/grub-core/lib/posix_wrap/assert.h b/grub-core/lib/posix_wrap/assert.h index 94cfdd543..6b00a0ba3 100644 --- a/grub-core/lib/posix_wrap/assert.h +++ b/grub-core/lib/posix_wrap/assert.h @@ -27,7 +27,7 @@ static inline void assert_real (const char *file, int line, int cond) { if (!cond) - grub_fatal ("Assertion failed at %s:%d\n", file, line); + grub_printf ("Assertion failed at %s:%d\n", file, line); } #endif diff --git a/grub-core/lib/posix_wrap/ctype.h b/grub-core/lib/posix_wrap/ctype.h index 9589778b6..38b572703 100644 --- a/grub-core/lib/posix_wrap/ctype.h +++ b/grub-core/lib/posix_wrap/ctype.h @@ -42,13 +42,19 @@ isdigit (int c) static inline int islower (int c) { - return (c >= 'a' && c <= 'z'); + return grub_islower (c); +} + +static inline int +isascii (int c) +{ + return !(c & ~0x7f); } static inline int isupper (int c) { - return (c >= 'A' && c <= 'Z'); + return grub_isupper (c); } static inline int diff --git a/grub-core/lib/posix_wrap/langinfo.h b/grub-core/lib/posix_wrap/langinfo.h index 72b5b9612..ab75af15d 100644 --- a/grub-core/lib/posix_wrap/langinfo.h +++ b/grub-core/lib/posix_wrap/langinfo.h @@ -23,7 +23,7 @@ typedef enum { CODESET } nl_item; -static inline char * +static inline const char * nl_langinfo (nl_item item) { switch (item) diff --git a/grub-core/lib/posix_wrap/limits.h b/grub-core/lib/posix_wrap/limits.h index fe8523e68..588e5899a 100644 --- a/grub-core/lib/posix_wrap/limits.h +++ b/grub-core/lib/posix_wrap/limits.h @@ -26,6 +26,9 @@ #define UINT_MAX GRUB_UINT_MAX #define ULONG_MAX GRUB_ULONG_MAX +#define SHRT_MAX GRUB_SHRT_MAX +#define INT_MAX GRUB_INT_MAX + #define CHAR_BIT 8 #endif diff --git a/grub-core/lib/posix_wrap/stdio.h b/grub-core/lib/posix_wrap/stdio.h index 701fceaa4..e6b1178c5 100644 --- a/grub-core/lib/posix_wrap/stdio.h +++ b/grub-core/lib/posix_wrap/stdio.h @@ -26,4 +26,17 @@ typedef struct grub_file FILE; #define EOF -1 +static inline int +snprintf (char *str, size_t n, const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start (ap, fmt); + ret = grub_vsnprintf (str, n, fmt, ap); + va_end (ap); + + return ret; +} + #endif diff --git a/grub-core/lib/posix_wrap/stdlib.h b/grub-core/lib/posix_wrap/stdlib.h index 4c725f6e2..3b46f47ff 100644 --- a/grub-core/lib/posix_wrap/stdlib.h +++ b/grub-core/lib/posix_wrap/stdlib.h @@ -46,12 +46,10 @@ realloc (void *ptr, grub_size_t size) return grub_realloc (ptr, size); } -static inline void -abort (void) +static inline int +abs (int c) { - grub_abort (); + return (c >= 0) ? c : -c; } -#define MB_CUR_MAX 6 - #endif diff --git a/grub-core/lib/posix_wrap/string.h b/grub-core/lib/posix_wrap/string.h index f38c97ba4..77fbe383b 100644 --- a/grub-core/lib/posix_wrap/string.h +++ b/grub-core/lib/posix_wrap/string.h @@ -45,6 +45,61 @@ memcpy (void *dest, const void *src, grub_size_t n) { return grub_memcpy (dest, src, n); } -#endif + +static inline int +memcmp (const void *s1, const void *s2, size_t n) +{ + return grub_memcmp (s1, s2, n); +} + +#endif + +static inline char * +strcpy (char *dest, const char *src) +{ + return grub_strcpy (dest, src); +} + +static inline char * +strstr (const char *haystack, const char *needle) +{ + return grub_strstr (haystack, needle); +} + +static inline char * +strchr (const char *s, int c) +{ + return grub_strchr (s, c); +} + +static inline char * +strncpy (char *dest, const char *src, size_t n) +{ + return grub_strncpy (dest, src, n); +} + +static inline char * +strcat (char *dest, const char *src) +{ + return grub_strcat (dest, src); +} + +static inline char * +strncat (char *dest, const char *src, size_t n) +{ + return grub_strncat (dest, src, n); +} + +static inline int +strcoll (const char *s1, const char *s2) +{ + return grub_strcmp (s1, s2); +} + +static inline void * +memchr (const void *s, int c, size_t n) +{ + return grub_memchr (s, c, n); +} #endif diff --git a/grub-core/lib/posix_wrap/sys/types.h b/grub-core/lib/posix_wrap/sys/types.h index 0c58d6c44..b21811606 100644 --- a/grub-core/lib/posix_wrap/sys/types.h +++ b/grub-core/lib/posix_wrap/sys/types.h @@ -22,7 +22,11 @@ #include typedef grub_size_t size_t; +typedef grub_ssize_t ssize_t; +#ifndef GRUB_POSIX_BOOL_DEFINED typedef enum { false = 0, true = 1 } bool; +#define GRUB_POSIX_BOOL_DEFINED 1 +#endif typedef grub_uint8_t uint8_t; typedef grub_uint16_t uint16_t; diff --git a/grub-core/lib/posix_wrap/unistd.h b/grub-core/lib/posix_wrap/unistd.h index e69de29bb..a12c43b15 100644 --- a/grub-core/lib/posix_wrap/unistd.h +++ b/grub-core/lib/posix_wrap/unistd.h @@ -0,0 +1 @@ +#include diff --git a/grub-core/lib/posix_wrap/wchar.h b/grub-core/lib/posix_wrap/wchar.h index fd56fd332..fb90cc044 100644 --- a/grub-core/lib/posix_wrap/wchar.h +++ b/grub-core/lib/posix_wrap/wchar.h @@ -19,7 +19,97 @@ #ifndef GRUB_POSIX_WCHAR_H #define GRUB_POSIX_WCHAR_H 1 +#include + /* UCS-4. */ -typedef grub_uint32_t wchar_t; +typedef grub_int32_t wint_t; +enum + { + WEOF = -1 + }; + +/* UCS-4. */ +typedef grub_int32_t wchar_t; + +typedef struct mbstate { + grub_uint32_t code; + int count; +} mbstate_t; + +/* UTF-8. */ +#define MB_CUR_MAX 4 +#define MB_LEN_MAX 4 + +static inline size_t +mbrtowc (wchar_t *pwc, const char *s, size_t n, mbstate_t *ps) +{ + const char *ptr; + if (!s) + { + pwc = 0; + s = ""; + n = 1; + } + + if (pwc) + *pwc = 0; + + for (ptr = s; ptr < s + n; ptr++) + { + if (!grub_utf8_process (*ptr, &ps->code, &ps->count)) + return -1; + if (ps->count) + continue; + if (pwc) + *pwc = ps->code; + if (ps->code == 0) + return 0; + return ptr - s + 1; + } + return -2; +} + +static inline int +mbsinit(const mbstate_t *ps) +{ + return ps->count == 0; +} + +static inline size_t +wcrtomb (char *s, wchar_t wc, mbstate_t *ps __attribute__ ((unused))) +{ + if (s == 0) + return 1; + return grub_encode_utf8_character ((grub_uint8_t *) s, + (grub_uint8_t *) s + MB_LEN_MAX, + wc); +} + +static inline wint_t btowc (int c) +{ + if (c & ~0x7f) + return WEOF; + return c; +} + + +static inline int +wcscoll (const wchar_t *s1, const wchar_t *s2) +{ + while (*s1 && *s2) + { + if (*s1 != *s2) + break; + + s1++; + s2++; + } + + if (*s1 < *s2) + return -1; + if (*s1 > *s2) + return +1; + return 0; +} #endif diff --git a/grub-core/lib/posix_wrap/wctype.h b/grub-core/lib/posix_wrap/wctype.h index e69de29bb..0dab48b97 100644 --- a/grub-core/lib/posix_wrap/wctype.h +++ b/grub-core/lib/posix_wrap/wctype.h @@ -0,0 +1,108 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_POSIX_WCTYPE_H +#define GRUB_POSIX_WCTYPE_H 1 + +#include +#include + +typedef enum { GRUB_CTYPE_INVALID, + GRUB_CTYPE_ALNUM, GRUB_CTYPE_CNTRL, GRUB_CTYPE_LOWER, + GRUB_CTYPE_SPACE, GRUB_CTYPE_ALPHA, GRUB_CTYPE_DIGIT, + GRUB_CTYPE_PRINT, GRUB_CTYPE_UPPER, GRUB_CTYPE_BLANK, + GRUB_CTYPE_GRAPH, GRUB_CTYPE_PUNCT, GRUB_CTYPE_XDIGIT, + GRUB_CTYPE_MAX} wctype_t; + +#define CHARCLASS_NAME_MAX (sizeof ("xdigit") - 1) + +static inline wctype_t +wctype (const char *name) +{ + wctype_t i; + static const char names[][10] = { "", + "alnum", "cntrl", "lower", + "space", "alpha", "digit", + "print", "upper", "blank", + "graph", "punct", "xdigit" }; + for (i = GRUB_CTYPE_INVALID; i < GRUB_CTYPE_MAX; i++) + if (grub_strcmp (names[i], name) == 0) + return i; + return GRUB_CTYPE_INVALID; +} + +/* FIXME: take into account international lowercase characters. */ +static inline int +iswlower (wint_t wc) +{ + return grub_islower (wc); +} + +static inline wint_t +towlower (wint_t c) +{ + return grub_tolower (c); +} + +static inline wint_t +towupper (wint_t c) +{ + return grub_toupper (c); +} + +static inline int +iswalnum (wint_t c) +{ + return grub_isalpha (c) || grub_isdigit (c); +} + +static inline int +iswctype (wint_t wc, wctype_t desc) +{ + switch (desc) + { + case GRUB_CTYPE_ALNUM: + return iswalnum (wc); + case GRUB_CTYPE_CNTRL: + return grub_iscntrl (wc); + case GRUB_CTYPE_LOWER: + return iswlower (wc); + case GRUB_CTYPE_SPACE: + return grub_isspace (wc); + case GRUB_CTYPE_ALPHA: + return grub_isalpha (wc); + case GRUB_CTYPE_DIGIT: + return grub_isdigit (wc); + case GRUB_CTYPE_PRINT: + return grub_isprint (wc); + case GRUB_CTYPE_UPPER: + return grub_isupper (wc); + case GRUB_CTYPE_BLANK: + return wc == ' ' || wc == '\t'; + case GRUB_CTYPE_GRAPH: + return grub_isgraph (wc); + case GRUB_CTYPE_PUNCT: + return grub_isprint (wc) && !grub_isspace (wc) && !iswalnum (wc); + case GRUB_CTYPE_XDIGIT: + return grub_isxdigit (wc); + default: + return 0; + } +} + +#endif diff --git a/grub-core/lib/priority_queue.c b/grub-core/lib/priority_queue.c new file mode 100644 index 000000000..a790910a8 --- /dev/null +++ b/grub-core/lib/priority_queue.c @@ -0,0 +1,257 @@ +/* + * 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 . + */ + +#ifndef TEST +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +#else +#include +#include +#include + +#include + +using namespace std; + +typedef size_t grub_size_t; +typedef int (*grub_comparator_t) (const void *a, const void *b); +typedef unsigned char grub_uint8_t; +#define grub_malloc malloc +#define grub_memcpy memcpy +#define grub_realloc realloc +#define grub_free free + +typedef enum + { + GRUB_ERR_NONE, + grub_errno + } grub_err_t; +#endif + +struct grub_priority_queue +{ + grub_size_t elsize; + grub_size_t allocated; + grub_size_t used; + grub_comparator_t cmp; + void *els; +}; + +#ifdef TEST +typedef struct grub_priority_queue *grub_priority_queue_t; +#endif + +static inline void * +element (struct grub_priority_queue *pq, grub_size_t k) +{ + return ((grub_uint8_t *) pq->els) + k * pq->elsize; +} + +static inline void +swap (struct grub_priority_queue *pq, grub_size_t m, grub_size_t n) +{ + grub_uint8_t *p1, *p2; + grub_size_t l; + p1 = (grub_uint8_t *) element (pq, m); + p2 = (grub_uint8_t *) element (pq, n); + for (l = pq->elsize; l; l--, p1++, p2++) + { + grub_uint8_t t; + t = *p1; + *p1 = *p2; + *p2 = t; + } +} + +static inline grub_size_t +parent (grub_size_t v) +{ + return (v - 1) / 2; +} + +static inline grub_size_t +left_child (grub_size_t v) +{ + return 2 * v + 1; +} + +static inline grub_size_t +right_child (grub_size_t v) +{ + return 2 * v + 2; +} + +void * +grub_priority_queue_top (grub_priority_queue_t pq) +{ + if (!pq->used) + return 0; + return element (pq, 0); +} + +void +grub_priority_queue_destroy (grub_priority_queue_t pq) +{ + grub_free (pq->els); + grub_free (pq); +} + +grub_priority_queue_t +grub_priority_queue_new (grub_size_t elsize, + grub_comparator_t cmp) +{ + struct grub_priority_queue *ret; + void *els; + els = grub_malloc (elsize * 8); + if (!els) + return 0; + ret = (struct grub_priority_queue *) grub_malloc (sizeof (*ret)); + if (!ret) + { + grub_free (els); + return 0; + } + ret->elsize = elsize; + ret->allocated = 8; + ret->used = 0; + ret->cmp = cmp; + ret->els = els; + return ret; +} + +/* Heap property: pq->cmp (element (pq, p), element (pq, parent (p))) <= 0. */ +grub_err_t +grub_priority_queue_push (grub_priority_queue_t pq, const void *el) +{ + grub_size_t p; + if (pq->used == pq->allocated) + { + void *els; + els = grub_realloc (pq->els, pq->elsize * 2 * pq->allocated); + if (!els) + return grub_errno; + pq->allocated *= 2; + pq->els = els; + } + pq->used++; + grub_memcpy (element (pq, pq->used - 1), el, pq->elsize); + for (p = pq->used - 1; p; p = parent (p)) + { + if (pq->cmp (element (pq, p), element (pq, parent (p))) <= 0) + break; + swap (pq, p, parent (p)); + } + + return GRUB_ERR_NONE; +} + +void +grub_priority_queue_pop (grub_priority_queue_t pq) +{ + grub_size_t p; + + swap (pq, 0, pq->used - 1); + pq->used--; + for (p = 0; left_child (p) < pq->used; ) + { + grub_size_t c; + if (pq->cmp (element (pq, left_child (p)), element (pq, p)) <= 0 + && (right_child (p) >= pq->used + || pq->cmp (element (pq, right_child (p)), element (pq, p)) <= 0)) + break; + if (right_child (p) >= pq->used + || pq->cmp (element (pq, left_child (p)), + element (pq, right_child (p))) > 0) + c = left_child (p); + else + c = right_child (p); + swap (pq, p, c); + p = c; + } +} + +#ifdef TEST + +static int +compar (const void *a_, const void *b_) +{ + int a = *(int *) a_; + int b = *(int *) b_; + if (a < b) + return -1; + if (a > b) + return +1; + return 0; +} + +int +main (void) +{ + priority_queue pq; + grub_priority_queue_t pq2; + int counter; + int s = 0; + pq2 = grub_priority_queue_new (sizeof (int), compar); + if (!pq2) + return 1; + srand (1); + + for (counter = 0; counter < 1000000; counter++) + { + int op = rand () % 10; + if (s && *(int *) grub_priority_queue_top (pq2) != pq.top ()) + { + printf ("Error at %d\n", counter); + return 2; + } + if (op < 3 && s) + { + grub_priority_queue_pop (pq2); + pq.pop (); + s--; + } + else + { + int v = rand (); + int e; + pq.push (v); + e = grub_priority_queue_push (pq2, &v); + if (e) + return 3; + s++; + } + } + while (s) + { + if (*(int *) grub_priority_queue_top (pq2) != pq.top ()) + { + printf ("Error at the end. %d elements remaining.\n", s); + return 4; + } + grub_priority_queue_pop (pq2); + pq.pop (); + s--; + } + printf ("All tests passed successfully\n"); + return 0; +} +#endif diff --git a/grub-core/lib/reed_solomon.c b/grub-core/lib/reed_solomon.c index 7da5f204c..704ebd3f2 100644 --- a/grub-core/lib/reed_solomon.c +++ b/grub-core/lib/reed_solomon.c @@ -25,6 +25,10 @@ #define grub_memcpy memcpy #endif +#ifndef STANDALONE +#include +#endif + #ifndef STANDALONE #ifdef TEST typedef unsigned int grub_size_t; @@ -37,6 +41,9 @@ typedef unsigned char grub_uint8_t; #endif #endif +#define SECTOR_SIZE 512 +#define MAX_BLOCK_SIZE (200 * SECTOR_SIZE) + #ifdef STANDALONE #ifdef TEST typedef unsigned int grub_size_t; @@ -56,19 +63,29 @@ typedef grub_uint8_t gf_single_t; #if defined (STANDALONE) && !defined (TEST) static gf_single_t * const gf_powx __attribute__ ((section(".text"))) = (void *) 0x100000; static gf_single_t * const gf_powx_inv __attribute__ ((section(".text"))) = (void *) 0x100200; - -static char *scratch __attribute__ ((section(".text"))) = (void *) 0x100300; +static int *const chosenstat __attribute__ ((section(".text"))) = (void *) 0x100300; +static gf_single_t *const sigma __attribute__ ((section(".text"))) = (void *) 0x100700; +static gf_single_t *const errpot __attribute__ ((section(".text"))) = (void *) 0x100800; +static int *const errpos __attribute__ ((section(".text"))) = (void *) 0x100900; +static gf_single_t *const sy __attribute__ ((section(".text"))) = (void *) 0x100d00; +static gf_single_t *const mstat __attribute__ ((section(".text"))) = (void *) 0x100e00; +static gf_single_t *const errvals __attribute__ ((section(".text"))) = (void *) 0x100f00; +static gf_single_t *const eqstat __attribute__ ((section(".text"))) = (void *) 0x101000; +/* Next available address: (void *) 0x112000. */ #else -#if defined (STANDALONE) -static char *scratch; -#endif + static gf_single_t gf_powx[255 * 2]; static gf_single_t gf_powx_inv[256]; +static int chosenstat[256]; +static gf_single_t sigma[256]; +static gf_single_t errpot[256]; +static int errpos[256]; +static gf_single_t sy[256]; +static gf_single_t mstat[256]; +static gf_single_t errvals[256]; +static gf_single_t eqstat[65536 + 256]; #endif -#define SECTOR_SIZE 512 -#define MAX_BLOCK_SIZE (200 * SECTOR_SIZE) - static gf_single_t gf_mul (gf_single_t a, gf_single_t b) { @@ -89,6 +106,7 @@ init_powx (void) int i; grub_uint8_t cur = 1; + gf_powx_inv[0] = 0; for (i = 0; i < 255; i++) { gf_powx[i] = cur; @@ -102,14 +120,11 @@ init_powx (void) } static gf_single_t -pol_evaluate (gf_single_t *pol, grub_size_t degree, gf_single_t x) +pol_evaluate (gf_single_t *pol, grub_size_t degree, int log_x) { int i; gf_single_t s = 0; - int log_xn = 0, log_x; - if (x == 0) - return pol[0]; - log_x = gf_powx_inv[x]; + int log_xn = 0; for (i = degree; i >= 0; i--) { if (pol[i]) @@ -159,25 +174,6 @@ rs_encode (gf_single_t *data, grub_size_t s, grub_size_t rs) } #endif -static void -syndroms (gf_single_t *m, grub_size_t s, grub_size_t rs, - gf_single_t *sy) -{ - gf_single_t xn = 1; - unsigned i; - for (i = 0; i < rs; i++) - { - if (xn & (1 << (GF_SIZE - 1))) - { - xn <<= 1; - xn ^= GF_POLYNOMIAL; - } - else - xn <<= 1; - sy[i] = pol_evaluate (m, s + rs - 1, xn); - } -} - static void gauss_eliminate (gf_single_t *eq, int n, int m, int *chosen) { @@ -208,65 +204,34 @@ gauss_eliminate (gf_single_t *eq, int n, int m, int *chosen) static void gauss_solve (gf_single_t *eq, int n, int m, gf_single_t *sol) { - int *chosen; int i, j; -#ifndef STANDALONE - chosen = xmalloc (n * sizeof (int)); -#else - chosen = (void *) scratch; - scratch += n * sizeof (int); -#endif for (i = 0; i < n; i++) - chosen[i] = -1; + chosenstat[i] = -1; for (i = 0; i < m; i++) sol[i] = 0; - gauss_eliminate (eq, n, m, chosen); + gauss_eliminate (eq, n, m, chosenstat); for (i = n - 1; i >= 0; i--) { gf_single_t s = 0; - if (chosen[i] == -1) + if (chosenstat[i] == -1) continue; for (j = 0; j < m; j++) s ^= gf_mul (eq[i * (m + 1) + j], sol[j]); s ^= eq[i * (m + 1) + m]; - sol[chosen[i]] = s; + sol[chosenstat[i]] = s; } -#ifndef STANDALONE - free (chosen); -#else - scratch -= n * sizeof (int); -#endif } static void -rs_recover (gf_single_t *m, grub_size_t s, grub_size_t rs) +rs_recover (gf_single_t *mm, grub_size_t s, grub_size_t rs) { grub_size_t rs2 = rs / 2; - gf_single_t *sigma; - gf_single_t *errpot; - int *errpos; - gf_single_t *sy; int errnum = 0; int i, j; -#ifndef STANDALONE - sigma = xmalloc (rs2 * sizeof (gf_single_t)); - errpot = xmalloc (rs2 * sizeof (gf_single_t)); - errpos = xmalloc (rs2 * sizeof (int)); - sy = xmalloc (rs * sizeof (gf_single_t)); -#else - sigma = (void *) scratch; - scratch += rs2 * sizeof (gf_single_t); - errpot = (void *) scratch; - scratch += rs2 * sizeof (gf_single_t); - errpos = (void *) scratch; - scratch += rs2 * sizeof (int); - sy = (void *) scratch; - scratch += rs * sizeof (gf_single_t); -#endif - - syndroms (m, s, rs, sy); + for (i = 0; i < (int) rs; i++) + sy[i] = pol_evaluate (mm, s + rs - 1, i); for (i = 0; i < (int) rs; i++) if (sy[i] != 0) @@ -274,109 +239,44 @@ rs_recover (gf_single_t *m, grub_size_t s, grub_size_t rs) /* No error detected. */ if (i == (int) rs) - { -#ifndef STANDALONE - free (sigma); - free (errpot); - free (errpos); - free (sy); -#else - scratch -= rs2 * sizeof (gf_single_t); - scratch -= rs2 * sizeof (gf_single_t); - scratch -= rs2 * sizeof (int); - scratch -= rs * sizeof (gf_single_t); -#endif - return; - } + return; { - gf_single_t *eq; - -#ifndef STANDALONE - eq = xmalloc (rs2 * (rs2 + 1) * sizeof (gf_single_t)); -#else - eq = (void *) scratch; - scratch += rs2 * (rs2 + 1) * sizeof (gf_single_t); -#endif for (i = 0; i < (int) rs2; i++) for (j = 0; j < (int) rs2 + 1; j++) - eq[i * (rs2 + 1) + j] = sy[i+j]; + eqstat[i * (rs2 + 1) + j] = sy[i+j]; for (i = 0; i < (int) rs2; i++) sigma[i] = 0; - gauss_solve (eq, rs2, rs2, sigma); - -#ifndef STANDALONE - free (eq); -#else - scratch -= rs2 * (rs2 + 1) * sizeof (gf_single_t); -#endif + gauss_solve (eqstat, rs2, rs2, sigma); } - { - gf_single_t xn = 1, yn = 1; - for (i = 0; i < (int) (rs + s); i++) + for (i = 0; i < (int) (rs + s); i++) + if (pol_evaluate (sigma, rs2 - 1, 255 - i) == gf_powx[i]) { - gf_single_t ev = (gf_mul (pol_evaluate (sigma, rs2 - 1, xn), xn) ^ 1); - if (ev == 0) - { - errpot[errnum] = yn; - errpos[errnum++] = s + rs - i - 1; - } - yn = gf_mul (yn, 2); - xn = gf_mul (xn, GF_INVERT2); + errpot[errnum] = gf_powx[i]; + errpos[errnum++] = s + rs - i - 1; } - } { - gf_single_t *errvals; - gf_single_t *eq; - -#ifndef STANDALONE - eq = xmalloc (rs * (errnum + 1) * sizeof (gf_single_t)); - errvals = xmalloc (errnum * sizeof (int)); -#else - eq = (void *) scratch; - scratch += rs * (errnum + 1) * sizeof (gf_single_t); - errvals = (void *) scratch; - scratch += errnum * sizeof (int); -#endif - for (j = 0; j < errnum; j++) - eq[j] = errpot[j]; - eq[errnum] = sy[0]; + eqstat[j] = 1; + eqstat[errnum] = sy[0]; for (i = 1; i < (int) rs; i++) { for (j = 0; j < (int) errnum; j++) - eq[(errnum + 1) * i + j] = gf_mul (errpot[j], - eq[(errnum + 1) * (i - 1) + j]); - eq[(errnum + 1) * i + errnum] = sy[i]; + eqstat[(errnum + 1) * i + j] = gf_mul (errpot[j], + eqstat[(errnum + 1) * (i - 1) + + j]); + eqstat[(errnum + 1) * i + errnum] = sy[i]; } - gauss_solve (eq, rs, errnum, errvals); + gauss_solve (eqstat, rs, errnum, errvals); for (i = 0; i < (int) errnum; i++) - m[errpos[i]] ^= errvals[i]; -#ifndef STANDALONE - free (eq); - free (errvals); -#else - scratch -= rs * (errnum + 1) * sizeof (gf_single_t); - scratch -= errnum * sizeof (int); -#endif + mm[errpos[i]] ^= errvals[i]; } -#ifndef STANDALONE - free (sigma); - free (errpot); - free (errpos); - free (sy); -#else - scratch -= rs2 * sizeof (gf_single_t); - scratch -= rs2 * sizeof (gf_single_t); - scratch -= rs2 * sizeof (int); - scratch -= rs * sizeof (gf_single_t); -#endif } static void @@ -388,21 +288,20 @@ decode_block (gf_single_t *ptr, grub_size_t s, { grub_size_t ds = (s + SECTOR_SIZE - 1 - i) / SECTOR_SIZE; grub_size_t rr = (rs + SECTOR_SIZE - 1 - i) / SECTOR_SIZE; - gf_single_t m[ds + rr]; /* Nothing to do. */ if (!ds || !rr) continue; for (j = 0; j < (int) ds; j++) - m[j] = ptr[SECTOR_SIZE * j + i]; + mstat[j] = ptr[SECTOR_SIZE * j + i]; for (j = 0; j < (int) rr; j++) - m[j + ds] = rptr[SECTOR_SIZE * j + i]; + mstat[j + ds] = rptr[SECTOR_SIZE * j + i]; - rs_recover (m, ds, rr); + rs_recover (mstat, ds, rr); for (j = 0; j < (int) ds; j++) - ptr[SECTOR_SIZE * j + i] = m[j]; + ptr[SECTOR_SIZE * j + i] = mstat[j]; } } @@ -416,12 +315,18 @@ encode_block (gf_single_t *ptr, grub_size_t s, { grub_size_t ds = (s + SECTOR_SIZE - 1 - i) / SECTOR_SIZE; grub_size_t rr = (rs + SECTOR_SIZE - 1 - i) / SECTOR_SIZE; - gf_single_t m[ds + rr]; + gf_single_t *m; + + if (!ds || !rr) + continue; + + m = xmalloc (ds + rr); for (j = 0; j < ds; j++) m[j] = ptr[SECTOR_SIZE * j + i]; rs_encode (m, ds, rr); for (j = 0; j < rr; j++) rptr[SECTOR_SIZE * j + i] = m[j + ds]; + free (m); } } #endif @@ -435,6 +340,10 @@ grub_reed_solomon_add_redundancy (void *buffer, grub_size_t data_size, grub_size_t rs = redundancy; gf_single_t *ptr = buffer; gf_single_t *rptr = ptr + s; + void *tmp; + + tmp = xmalloc (data_size); + grub_memcpy (tmp, buffer, data_size); /* Nothing to do. */ if (!rs) @@ -460,6 +369,11 @@ grub_reed_solomon_add_redundancy (void *buffer, grub_size_t data_size, s -= cs; rs -= crs; } + +#ifndef TEST + assert (grub_memcmp (tmp, buffer, data_size) == 0); +#endif + free (tmp); } #endif @@ -506,14 +420,11 @@ main (int argc, char **argv) grub_memset (gf_powx, 0xee, sizeof (gf_powx)); grub_memset (gf_powx_inv, 0xdd, sizeof (gf_powx_inv)); -#ifdef STANDALONE - scratch = xmalloc (1048576); -#endif - #ifndef STANDALONE init_powx (); #endif +#ifndef STANDALONE in = fopen ("tst.bin", "rb"); if (!in) return 1; @@ -530,7 +441,19 @@ main (int argc, char **argv) out = fopen ("tst_rs.bin", "wb"); fwrite (buf, 1, s + rs, out); fclose (out); -#if 0 +#else + out = fopen ("tst_rs.bin", "rb"); + fseek (out, 0, SEEK_END); + s = ftell (out); + fseek (out, 0, SEEK_SET); + rs = 0x7007; + s -= rs; + + buf = xmalloc (s + rs + SECTOR_SIZE); + fread (buf, 1, s + rs, out); + fclose (out); +#endif +#if 1 grub_memset (buf + 512 * 15, 0, 512); #endif diff --git a/grub-core/lib/relocator.c b/grub-core/lib/relocator.c index aa404731f..c08fb958e 100644 --- a/grub-core/lib/relocator.c +++ b/grub-core/lib/relocator.c @@ -23,6 +23,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -524,9 +525,11 @@ malloc_in_range (struct grub_relocator *rel, #if GRUB_RELOCATOR_HAVE_FIRMWARE_REQUESTS for (r = grub_mm_base; r; r = r->next) { +#ifdef DEBUG_RELOCATOR_NOMEM_DPRINTF grub_dprintf ("relocator", "Blocking at 0x%lx-0x%lx\n", (unsigned long) r - r->pre_size, (unsigned long) (r + 1) + r->size); +#endif events[N].type = FIRMWARE_BLOCK_START; events[N].pos = (grub_addr_t) r - r->pre_size; N++; @@ -538,8 +541,10 @@ malloc_in_range (struct grub_relocator *rel, struct grub_relocator_extra_block *cur; for (cur = extra_blocks; cur; cur = cur->next) { +#ifdef DEBUG_RELOCATOR_NOMEM_DPRINTF grub_dprintf ("relocator", "Blocking at 0x%lx-0x%lx\n", (unsigned long) cur->start, (unsigned long) cur->end); +#endif events[N].type = FIRMWARE_BLOCK_START; events[N].pos = cur->start; N++; @@ -1204,14 +1209,14 @@ grub_relocator_alloc_chunk_addr (struct grub_relocator *rel, grub_phys_addr_t min_addr = 0, max_addr; if (target > ~size) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "address is out of range"); + return grub_error (GRUB_ERR_BUG, "address is out of range"); adjust_limits (rel, &min_addr, &max_addr, target, target); for (chunk = rel->chunks; chunk; chunk = chunk->next) if ((chunk->target <= target && target < chunk->target + chunk->size) || (target <= chunk->target && chunk->target < target + size)) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "overlap detected"); + return grub_error (GRUB_ERR_BUG, "overlap detected"); chunk = grub_malloc (sizeof (struct grub_relocator_chunk)); if (!chunk) @@ -1251,7 +1256,7 @@ grub_relocator_alloc_chunk_addr (struct grub_relocator *rel, grub_dprintf ("relocator", "not allocated\n"); grub_free (chunk); - return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); + return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); } while (0); @@ -1361,7 +1366,7 @@ grub_relocator_alloc_chunk_align (struct grub_relocator *rel, break; } - return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); + return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); } while (0); @@ -1481,7 +1486,7 @@ grub_relocator_prepare_relocs (struct grub_relocator *rel, grub_addr_t addr, if (!malloc_in_range (rel, 0, ~(grub_addr_t)0 - rel->relocators_size + 1, grub_relocator_align, rel->relocators_size, &movers_chunk, 1, 1)) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, "out of memory"); + return grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); movers_chunk.srcv = rels = rels0 = grub_map_memory (movers_chunk.src, movers_chunk.size); diff --git a/grub-core/lib/setjmp.S b/grub-core/lib/setjmp.S index fb7f94767..2e4974297 100644 --- a/grub-core/lib/setjmp.S +++ b/grub-core/lib/setjmp.S @@ -6,7 +6,7 @@ #include "./sparc64/setjmp.S" #elif defined(__mips__) #include "./mips/setjmp.S" -#elif defined(__powerpc__) +#elif defined(__powerpc__) || defined(__PPC__) #include "./powerpc/setjmp.S" #elif defined(__ia64__) #include "./ia64/setjmp.S" diff --git a/grub-core/lib/xzembed/xz.h b/grub-core/lib/xzembed/xz.h index f0a7dbbca..fe7158bb2 100644 --- a/grub-core/lib/xzembed/xz.h +++ b/grub-core/lib/xzembed/xz.h @@ -25,6 +25,13 @@ #define XZ_H #include +#include +#include +#include + +#ifndef GRUB_POSIX_BOOL_DEFINED +typedef enum { false = 0, true = 1 } bool; +#endif /** * enum xz_ret - Return codes diff --git a/grub-core/lib/xzembed/xz_config.h b/grub-core/lib/xzembed/xz_config.h index 0af0d2b81..55b88c476 100644 --- a/grub-core/lib/xzembed/xz_config.h +++ b/grub-core/lib/xzembed/xz_config.h @@ -26,27 +26,27 @@ /* Enable BCJ filter decoders. */ -#if defined(__i386__) || defined(__x86_64__) +#if defined(GRUB_TARGET_CPU_I386) || defined(GRUB_TARGET_CPU_X86_64) #define XZ_DEC_X86 #endif -#ifdef __powerpc__ +#ifdef GRUB_TARGET_CPU_POWERPC #define XZ_DEC_POWERPC #endif -#ifdef __ia64__ +#ifdef GRUB_TARGET_CPU_IA64 #define XZ_DEC_IA64 #endif -#ifdef __arm__ +#ifdef GRUB_TARGET_CPU_ARM #define XZ_DEC_ARM #endif -#ifdef __thumb__ +#if 0 #define XZ_DEC_ARMTHUMB #endif -#ifdef __sparc__ +#ifdef GRUB_TARGET_CPU_SPARC #define XZ_DEC_SPARC #endif diff --git a/grub-core/lib/xzembed/xz_dec_stream.c b/grub-core/lib/xzembed/xz_dec_stream.c index 09e5e513a..1d789d9ba 100644 --- a/grub-core/lib/xzembed/xz_dec_stream.c +++ b/grub-core/lib/xzembed/xz_dec_stream.c @@ -445,6 +445,8 @@ static enum xz_ret dec_stream_header(struct xz_dec *s) return XZ_FORMAT_ERROR; #ifndef GRUB_EMBED_DECOMPRESSOR + s->crc32 = grub_crypto_lookup_md_by_name ("CRC32"); + if (s->crc32) { uint64_t hash_context[(s->crc32->contextsize + 7) / 8]; @@ -958,10 +960,6 @@ struct xz_dec * xz_dec_init(uint32_t dict_max) memset (s, 0, sizeof (*s)); -#ifndef GRUB_EMBED_DECOMPRESSOR - s->crc32 = grub_crypto_lookup_md_by_name ("CRC32"); -#endif - s->single_call = dict_max == 0; #ifdef XZ_DEC_BCJ diff --git a/grub-core/loader/efi/appleloader.c b/grub-core/loader/efi/appleloader.c index db57a573c..f15edeac5 100644 --- a/grub-core/loader/efi/appleloader.c +++ b/grub-core/loader/efi/appleloader.c @@ -126,7 +126,7 @@ static struct piwg_full_device_path devpath_6 = MAKE_PIWG_PATH (0xffcc4000, struct devdata { - char *model; + const char *model; grub_efi_device_path_t *devpath; }; @@ -167,7 +167,7 @@ grub_cmd_appleloader (grub_command_t cmd __attribute__ ((unused)), goto fail; } - grub_printf ("Model : %s\n", pdev->model); + grub_dprintf ("appleload", "Model: %s\n", pdev->model); loaded_image = grub_efi_get_loaded_image (image_handle); if (! loaded_image) @@ -220,7 +220,7 @@ static grub_command_t cmd; GRUB_MOD_INIT(appleloader) { cmd = grub_register_command ("appleloader", grub_cmd_appleloader, - "[OPTS]", N_("Boot legacy system.")); + N_("[OPTS]"), N_("Boot BIOS-based system.")); my_mod = mod; } diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c index 3ecdca534..064bd7ce6 100644 --- a/grub-core/loader/efi/chainloader.c +++ b/grub-core/loader/efi/chainloader.c @@ -88,9 +88,9 @@ grub_chainloader_boot (void) grub_error (GRUB_ERR_BAD_OS, buf); grub_free (buf); } - else - grub_error (GRUB_ERR_BAD_OS, "unknown error"); } + else + grub_error (GRUB_ERR_BAD_OS, "unknown error"); } if (exit_data) @@ -197,7 +197,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), char *filename; if (argc == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); filename = argv[0]; grub_dl_ref (my_mod); @@ -241,7 +241,8 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), size = grub_file_size (file); if (!size) { - grub_error (GRUB_ERR_BAD_OS, "file is empty"); + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); goto fail; } pages = (((grub_efi_uintn_t) size + ((1 << 12) - 1)) >> 12); @@ -258,7 +259,8 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), if (grub_file_read (file, (void *) ((grub_addr_t) address), size) != size) { if (grub_errno == GRUB_ERR_NONE) - grub_error (GRUB_ERR_BAD_OS, "too small"); + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); goto fail; } diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c index 6746b3853..5fa06c31a 100644 --- a/grub-core/loader/i386/bsd.c +++ b/grub-core/loader/i386/bsd.c @@ -107,7 +107,7 @@ static const struct grub_arg_option freebsd_opts[] = {"nointr", 'n', 0, "", 0, 0}, {"pause", 'p', 0, N_("Wait for keypress after every line of output."), 0, 0}, {"quiet", 'q', 0, "", 0, 0}, - {"dfltroot", 'r', 0, N_("Use compiled-in rootdev."), 0, 0}, + {"dfltroot", 'r', 0, N_("Use compiled-in root device."), 0, 0}, {"single", 's', 0, N_("Boot into single mode."), 0, 0}, {"verbose", 'v', 0, N_("Boot with verbose messages."), 0, 0}, {0, 0, 0, 0, 0, 0} @@ -131,7 +131,11 @@ static const struct grub_arg_option openbsd_opts[] = {"kdb", 'd', 0, N_("Enter in KDB on boot."), 0, 0}, {"root", 'r', 0, N_("Set root device."), "wdXY", ARG_TYPE_STRING}, {"serial", 'h', GRUB_ARG_OPTION_OPTIONAL, - N_("Use serial console."), N_("comUNIT[,SPEED]"), ARG_TYPE_STRING}, + N_("Use serial console."), + /* TRANSLATORS: "com" is static and not to be translated. It refers to + serial ports e.g. com1. + */ + N_("comUNIT[,SPEED]"), ARG_TYPE_STRING}, {0, 0, 0, 0, 0, 0} }; @@ -157,10 +161,14 @@ static const struct grub_arg_option netbsd_opts[] = {"single", 's', 0, N_("Boot into single mode."), 0, 0}, {"verbose", 'v', 0, N_("Boot with verbose messages."), 0, 0}, {"debug", 'x', 0, N_("Boot with debug messages."), 0, 0}, - {"silent", 'z', 0, N_("Supress normal output (warnings remain)."), 0, 0}, + {"silent", 'z', 0, N_("Suppress normal output (warnings remain)."), 0, 0}, {"root", 'r', 0, N_("Set root device."), N_("DEVICE"), ARG_TYPE_STRING}, {"serial", 'h', GRUB_ARG_OPTION_OPTIONAL, - N_("Use serial console."), N_("[ADDR|comUNIT][,SPEED]"), ARG_TYPE_STRING}, + N_("Use serial console."), + /* TRANSLATORS: "com" is static and not to be translated. It refers to + serial ports e.g. com1. + */ + N_("[ADDR|comUNIT][,SPEED]"), ARG_TYPE_STRING}, {0, 0, 0, 0, 0, 0} }; @@ -206,7 +214,7 @@ grub_bsd_get_device (grub_uint32_t * biosdev, } grub_err_t -grub_bsd_add_meta (grub_uint32_t type, void *data, grub_uint32_t len) +grub_bsd_add_meta (grub_uint32_t type, const void *data, grub_uint32_t len) { struct bsd_tag *newtag; @@ -383,10 +391,11 @@ grub_bsd_add_mmap (void) } grub_err_t -grub_freebsd_add_meta_module (char *filename, char *type, int argc, char **argv, +grub_freebsd_add_meta_module (const char *filename, const char *type, + int argc, char **argv, grub_addr_t addr, grub_uint32_t size) { - char *name; + const char *name; name = grub_strrchr (filename, '/'); if (name) name++; @@ -1158,7 +1167,7 @@ grub_bsd_unload (void) } static grub_err_t -grub_bsd_load_aout (grub_file_t file) +grub_bsd_load_aout (grub_file_t file, const char *filename) { grub_addr_t load_addr, load_end; int ofs, align_page; @@ -1170,7 +1179,12 @@ grub_bsd_load_aout (grub_file_t file) return grub_errno; if (grub_file_read (file, &ah, sizeof (ah)) != sizeof (ah)) - return grub_error (GRUB_ERR_READ_ERROR, "cannot read the a.out header"); + { + if (!grub_errno) + grub_error (GRUB_ERR_READ_ERROR, N_("premature end of file %s"), + filename); + return grub_errno; + } if (grub_aout_get_type (&ah) != AOUT_TYPE_AOUT32) return grub_error (GRUB_ERR_BAD_OS, "invalid a.out header"); @@ -1308,7 +1322,7 @@ grub_bsd_elf64_hook (Elf64_Phdr * phdr, grub_addr_t * addr, int *do_load) } static grub_err_t -grub_bsd_load_elf (grub_elf_t elf) +grub_bsd_load_elf (grub_elf_t elf, const char *filename) { grub_err_t err; @@ -1320,7 +1334,8 @@ grub_bsd_load_elf (grub_elf_t elf) grub_relocator_chunk_t ch; entry = elf->ehdr.ehdr32.e_entry & 0xFFFFFF; - err = grub_elf32_phdr_iterate (elf, grub_bsd_elf32_size_hook, NULL); + err = grub_elf32_phdr_iterate (elf, filename, + grub_bsd_elf32_size_hook, NULL); if (err) return err; err = grub_relocator_alloc_chunk_addr (relocator, &ch, @@ -1330,12 +1345,12 @@ grub_bsd_load_elf (grub_elf_t elf) kern_chunk_src = get_virtual_current_address (ch); - err = grub_elf32_load (elf, grub_bsd_elf32_hook, 0, 0); + err = grub_elf32_load (elf, filename, grub_bsd_elf32_hook, 0, 0); if (err) return err; if (kernel_type != KERNEL_TYPE_OPENBSD) return GRUB_ERR_NONE; - return grub_openbsd_find_ramdisk32 (elf->file, kern_start, + return grub_openbsd_find_ramdisk32 (elf->file, filename, kern_start, kern_chunk_src, &openbsd_ramdisk); } else if (grub_elf_is_elf64 (elf)) @@ -1357,7 +1372,8 @@ grub_bsd_load_elf (grub_elf_t elf) entry_hi = 0; } - err = grub_elf64_phdr_iterate (elf, grub_bsd_elf64_size_hook, NULL); + err = grub_elf64_phdr_iterate (elf, filename, + grub_bsd_elf64_size_hook, NULL); if (err) return err; @@ -1373,16 +1389,17 @@ grub_bsd_load_elf (grub_elf_t elf) kern_chunk_src = get_virtual_current_address (ch); } - err = grub_elf64_load (elf, grub_bsd_elf64_hook, 0, 0); + err = grub_elf64_load (elf, filename, + grub_bsd_elf64_hook, 0, 0); if (err) return err; if (kernel_type != KERNEL_TYPE_OPENBSD) return GRUB_ERR_NONE; - return grub_openbsd_find_ramdisk64 (elf->file, kern_start, + return grub_openbsd_find_ramdisk64 (elf->file, filename, kern_start, kern_chunk_src, &openbsd_ramdisk); } else - return grub_error (GRUB_ERR_BAD_OS, "invalid ELF"); + return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch dependent ELF magic")); } static grub_err_t @@ -1399,7 +1416,7 @@ grub_bsd_load (int argc, char *argv[]) if (argc == 0) { - grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified"); + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); goto fail; } @@ -1414,18 +1431,18 @@ grub_bsd_load (int argc, char *argv[]) goto fail; } - elf = grub_elf_file (file); + elf = grub_elf_file (file, argv[0]); if (elf) { is_elf_kernel = 1; - grub_bsd_load_elf (elf); + grub_bsd_load_elf (elf, argv[0]); grub_elf_close (elf); } else { is_elf_kernel = 0; grub_errno = 0; - grub_bsd_load_aout (file); + grub_bsd_load_aout (file, argv[0]); grub_file_close (file); } @@ -1485,9 +1502,11 @@ grub_cmd_freebsd (grub_extcmd_context_t ctxt, int argc, char *argv[]) return grub_errno; if (is_64bit) - err = grub_freebsd_load_elf_meta64 (relocator, file, &kern_end); + err = grub_freebsd_load_elf_meta64 (relocator, file, argv[0], + &kern_end); else - err = grub_freebsd_load_elf_meta32 (relocator, file, &kern_end); + err = grub_freebsd_load_elf_meta32 (relocator, file, argv[0], + &kern_end); if (err) return err; @@ -1619,9 +1638,9 @@ grub_cmd_netbsd (grub_extcmd_context_t ctxt, int argc, char *argv[]) return grub_errno; if (is_64bit) - err = grub_netbsd_load_elf_meta64 (relocator, file, &kern_end); + err = grub_netbsd_load_elf_meta64 (relocator, file, argv[0], &kern_end); else - err = grub_netbsd_load_elf_meta32 (relocator, file, &kern_end); + err = grub_netbsd_load_elf_meta32 (relocator, file, argv[0], &kern_end); if (err) return err; } @@ -1711,7 +1730,7 @@ grub_cmd_freebsd_loadenv (grub_command_t cmd __attribute__ ((unused)), if (! grub_loader_is_loaded ()) return grub_error (GRUB_ERR_BAD_ARGUMENT, - "you need to load the kernel first"); + N_("you need to load the kernel first")); if (kernel_type != KERNEL_TYPE_FREEBSD) return grub_error (GRUB_ERR_BAD_ARGUMENT, @@ -1719,7 +1738,7 @@ grub_cmd_freebsd_loadenv (grub_command_t cmd __attribute__ ((unused)), if (argc == 0) { - grub_error (GRUB_ERR_BAD_ARGUMENT, "no filename"); + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); goto fail; } @@ -1806,7 +1825,7 @@ grub_cmd_freebsd_module (grub_command_t cmd __attribute__ ((unused)), grub_file_t file = 0; int modargc; char **modargv; - char *type; + const char *type; grub_err_t err; void *src; @@ -1944,7 +1963,7 @@ grub_cmd_freebsd_module_elf (grub_command_t cmd __attribute__ ((unused)), if (! grub_loader_is_loaded ()) return grub_error (GRUB_ERR_BAD_ARGUMENT, - "you need to load the kernel first"); + N_("you need to load the kernel first")); if (kernel_type != KERNEL_TYPE_FREEBSD) return grub_error (GRUB_ERR_BAD_ARGUMENT, @@ -1989,7 +2008,7 @@ grub_cmd_openbsd_ramdisk (grub_command_t cmd __attribute__ ((unused)), grub_size_t size; if (argc != 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); if (kernel_type != KERNEL_TYPE_OPENBSD) return grub_error (GRUB_ERR_BAD_OS, "no kOpenBSD loaded"); @@ -1999,8 +2018,7 @@ grub_cmd_openbsd_ramdisk (grub_command_t cmd __attribute__ ((unused)), file = grub_file_open (args[0]); if (! file) - return grub_error (GRUB_ERR_FILE_NOT_FOUND, - "couldn't load ramdisk"); + return grub_errno; size = grub_file_size (file); @@ -2016,8 +2034,9 @@ grub_cmd_openbsd_ramdisk (grub_command_t cmd __attribute__ ((unused)), != (grub_ssize_t) (size)) { grub_file_close (file); - grub_error_push (); - return grub_error (GRUB_ERR_BAD_OS, "couldn't read file %s", args[0]); + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), args[0]); + return grub_errno; } grub_memset (openbsd_ramdisk.target + size, 0, openbsd_ramdisk.max_size - size); diff --git a/grub-core/loader/i386/bsdXX.c b/grub-core/loader/i386/bsdXX.c index 92d267534..f28c53cc5 100644 --- a/grub-core/loader/i386/bsdXX.c +++ b/grub-core/loader/i386/bsdXX.c @@ -4,11 +4,12 @@ #include #include #include +#include #define ALIGN_PAGE(a) ALIGN_UP (a, 4096) static inline grub_err_t -load (grub_file_t file, void *where, grub_off_t off, grub_size_t size) +load (grub_file_t file, const char *filename, void *where, grub_off_t off, grub_size_t size) { if (grub_file_seek (file, off) == (grub_off_t) -1) return grub_errno; @@ -16,14 +17,14 @@ load (grub_file_t file, void *where, grub_off_t off, grub_size_t size) { if (grub_errno) return grub_errno; - else - return grub_error (GRUB_ERR_BAD_OS, "file is truncated"); + return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); } return GRUB_ERR_NONE; } static inline grub_err_t -read_headers (grub_file_t file, Elf_Ehdr *e, char **shdr) +read_headers (grub_file_t file, const char *filename, Elf_Ehdr *e, char **shdr) { if (grub_file_seek (file, 0) == (grub_off_t) -1) return grub_errno; @@ -32,8 +33,8 @@ read_headers (grub_file_t file, Elf_Ehdr *e, char **shdr) { if (grub_errno) return grub_errno; - else - return grub_error (GRUB_ERR_BAD_OS, "file is too short"); + return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); } if (e->e_ident[EI_MAG0] != ELFMAG0 @@ -42,10 +43,10 @@ read_headers (grub_file_t file, Elf_Ehdr *e, char **shdr) || e->e_ident[EI_MAG3] != ELFMAG3 || e->e_ident[EI_VERSION] != EV_CURRENT || e->e_version != EV_CURRENT) - return grub_error (GRUB_ERR_BAD_OS, "invalid arch independent ELF magic"); + return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch independent ELF magic")); if (e->e_ident[EI_CLASS] != SUFFIX (ELFCLASS)) - return grub_error (GRUB_ERR_BAD_OS, "invalid arch dependent ELF magic"); + return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch dependent ELF magic")); *shdr = grub_malloc (e->e_shnum * e->e_shentsize); if (! *shdr) @@ -59,8 +60,8 @@ read_headers (grub_file_t file, Elf_Ehdr *e, char **shdr) { if (grub_errno) return grub_errno; - else - return grub_error (GRUB_ERR_BAD_OS, "file is truncated"); + return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); } return GRUB_ERR_NONE; @@ -83,7 +84,7 @@ SUFFIX (grub_freebsd_load_elfmodule_obj) (struct grub_relocator *relocator, grub_size_t chunk_size = 0; void *chunk_src; - err = read_headers (file, &e, &shdr); + err = read_headers (file, argv[0], &e, &shdr); if (err) return err; @@ -131,7 +132,7 @@ SUFFIX (grub_freebsd_load_elfmodule_obj) (struct grub_relocator *relocator, { default: case SHT_PROGBITS: - err = load (file, (grub_uint8_t *) chunk_src + curload - *kern_end, + err = load (file, argv[0], (grub_uint8_t *) chunk_src + curload - *kern_end, s->sh_offset, s->sh_size); if (err) return err; @@ -176,7 +177,7 @@ SUFFIX (grub_freebsd_load_elfmodule) (struct grub_relocator *relocator, grub_size_t chunk_size = 0; void *chunk_src; - err = read_headers (file, &e, &shdr); + err = read_headers (file, argv[0], &e, &shdr); if (err) return err; @@ -229,7 +230,8 @@ SUFFIX (grub_freebsd_load_elfmodule) (struct grub_relocator *relocator, { default: case SHT_PROGBITS: - err = load (file, (grub_uint8_t *) chunk_src + module + err = load (file, argv[0], + (grub_uint8_t *) chunk_src + module + s->sh_addr - *kern_end, s->sh_offset, s->sh_size); if (err) @@ -244,16 +246,16 @@ SUFFIX (grub_freebsd_load_elfmodule) (struct grub_relocator *relocator, curload = module + s->sh_addr + s->sh_size; } - load (file, UINT_TO_PTR (module), 0, sizeof (e)); + load (file, argv[0], (grub_uint8_t *) chunk_src + module - *kern_end, 0, sizeof (e)); if (curload < module + sizeof (e)) curload = module + sizeof (e); - load (file, UINT_TO_PTR (curload), e.e_shoff, + load (file, argv[0], (grub_uint8_t *) chunk_src + curload - *kern_end, e.e_shoff, e.e_shnum * e.e_shentsize); e.e_shoff = curload - module; curload += e.e_shnum * e.e_shentsize; - load (file, UINT_TO_PTR (curload), e.e_phoff, + load (file, argv[0], (grub_uint8_t *) chunk_src + curload - *kern_end, e.e_phoff, e.e_phnum * e.e_phentsize); e.e_phoff = curload - module; curload += e.e_phnum * e.e_phentsize; @@ -263,14 +265,16 @@ SUFFIX (grub_freebsd_load_elfmodule) (struct grub_relocator *relocator, grub_freebsd_add_meta_module (argv[0], FREEBSD_MODTYPE_ELF_MODULE, argc - 1, argv + 1, module, curload - module); - return SUFFIX (grub_freebsd_load_elf_meta) (relocator, file, kern_end); + return SUFFIX (grub_freebsd_load_elf_meta) (relocator, file, argv[0], kern_end); } #endif grub_err_t SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator, - grub_file_t file, grub_addr_t *kern_end) + grub_file_t file, + const char *filename, + grub_addr_t *kern_end) { grub_err_t err; Elf_Ehdr e; @@ -286,7 +290,7 @@ SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator, unsigned i; grub_size_t chunk_size; - err = read_headers (file, &e, &shdr); + err = read_headers (file, filename, &e, &shdr); if (err) return err; @@ -303,7 +307,7 @@ SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator, break; if (s >= (Elf_Shdr *) ((char *) shdr + e.e_shnum * e.e_shentsize)) - return grub_error (GRUB_ERR_BAD_OS, "no symbol table"); + return grub_error (GRUB_ERR_BAD_OS, N_("no symbol table")); symoff = s->sh_offset; symsize = s->sh_size; symentsize = s->sh_entsize; @@ -338,7 +342,8 @@ SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator, if (grub_file_read (file, curload, symsize) != (grub_ssize_t) symsize) { if (! grub_errno) - return grub_error (GRUB_ERR_BAD_OS, "invalid ELF"); + return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); return grub_errno; } curload += symsize; @@ -351,7 +356,8 @@ SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator, if (grub_file_read (file, curload, strsize) != (grub_ssize_t) strsize) { if (! grub_errno) - return grub_error (GRUB_ERR_BAD_OS, "invalid ELF"); + return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); return grub_errno; } @@ -394,7 +400,8 @@ SUFFIX (grub_freebsd_load_elf_meta) (struct grub_relocator *relocator, grub_err_t SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator *relocator, - grub_file_t file, grub_addr_t *kern_end) + grub_file_t file, const char *filename, + grub_addr_t *kern_end) { grub_err_t err; Elf_Ehdr e; @@ -408,7 +415,7 @@ SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator *relocator, struct grub_netbsd_btinfo_symtab symtab; grub_addr_t symtarget; - err = read_headers (file, &e, &shdr); + err = read_headers (file, filename, &e, &shdr); if (err) return err; @@ -479,7 +486,8 @@ SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator *relocator, if (grub_file_read (file, curload, symsize) != (grub_ssize_t) symsize) { if (! grub_errno) - return grub_error (GRUB_ERR_BAD_OS, "invalid ELF"); + return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); return grub_errno; } curload += ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t)); @@ -489,7 +497,8 @@ SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator *relocator, if (grub_file_read (file, curload, strsize) != (grub_ssize_t) strsize) { if (! grub_errno) - return grub_error (GRUB_ERR_BAD_OS, "invalid ELF"); + return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); return grub_errno; } @@ -506,6 +515,7 @@ SUFFIX (grub_netbsd_load_elf_meta) (struct grub_relocator *relocator, grub_err_t SUFFIX(grub_openbsd_find_ramdisk) (grub_file_t file, + const char *filename, grub_addr_t kern_start, void *kern_chunk_src, struct grub_openbsd_ramdisk_descriptor *desc) @@ -518,7 +528,7 @@ SUFFIX(grub_openbsd_find_ramdisk) (grub_file_t file, Elf_Shdr *s; char *shdr = NULL; - err = read_headers (file, &e, &shdr); + err = read_headers (file, filename, &e, &shdr); if (err) return err; @@ -560,7 +570,8 @@ SUFFIX(grub_openbsd_find_ramdisk) (grub_file_t file, { grub_free (syms); if (! grub_errno) - return grub_error (GRUB_ERR_BAD_OS, "invalid ELF"); + return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); return grub_errno; } @@ -578,7 +589,8 @@ SUFFIX(grub_openbsd_find_ramdisk) (grub_file_t file, grub_free (syms); grub_free (strs); if (! grub_errno) - return grub_error (GRUB_ERR_BAD_OS, "invalid ELF"); + return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); return grub_errno; } diff --git a/grub-core/loader/i386/coreboot/chainloader.c b/grub-core/loader/i386/coreboot/chainloader.c index 3f85aa3a9..a66033b9a 100644 --- a/grub-core/loader/i386/coreboot/chainloader.c +++ b/grub-core/loader/i386/coreboot/chainloader.c @@ -88,7 +88,7 @@ grub_cmd_chain (grub_command_t cmd __attribute__ ((unused)), grub_elf_t elf; if (argc != 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "filename expected"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); grub_loader_unset (); @@ -103,7 +103,7 @@ grub_cmd_chain (grub_command_t cmd __attribute__ ((unused)), return grub_errno; } - elf = grub_elf_file (file); + elf = grub_elf_file (file, argv[0]); if (!elf) { grub_relocator_unload (relocator); @@ -120,7 +120,7 @@ grub_cmd_chain (grub_command_t cmd __attribute__ ((unused)), entry = elf->ehdr.ehdr32.e_entry & 0xFFFFFF; - err = grub_elf32_load (elf, grub_chain_elf32_hook, 0, 0); + err = grub_elf32_load (elf, argv[0], grub_chain_elf32_hook, 0, 0); grub_elf_close (elf); if (err) @@ -135,7 +135,12 @@ static grub_command_t cmd_chain; GRUB_MOD_INIT (chain) { cmd_chain = grub_register_command ("chainloader", grub_cmd_chain, - N_("FILE"), N_("Load another payload")); + N_("FILE"), + /* TRANSLATORS: "payload" is a term used + by coreboot and must be translated in + sync with coreboot. If unsure, + let it untranslated. */ + N_("Load another coreboot payload")); } GRUB_MOD_FINI (chain) diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c index 80ad542e3..c0fb530ff 100644 --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -639,7 +639,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), if (argc == 0) { - grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified"); + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); goto fail; } @@ -649,7 +649,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) { - grub_error (GRUB_ERR_READ_ERROR, "cannot read the Linux header"); + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + argv[0]); goto fail; } @@ -717,7 +719,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), len = 0x400 - sizeof (lh); if (grub_file_read (file, (char *) real_mode_mem + sizeof (lh), len) != len) { - grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file"); + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + argv[0]); goto fail; } @@ -908,8 +912,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), - (sizeof (LINUX_IMAGE) - 1)); len = prot_size; - if (grub_file_read (file, prot_mode_mem, len) != len) - grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file"); + if (grub_file_read (file, prot_mode_mem, len) != len && !grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + argv[0]); if (grub_errno == GRUB_ERR_NONE) { @@ -936,31 +941,42 @@ static grub_err_t grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) { - grub_file_t file = 0; - grub_ssize_t size; + grub_file_t *files = 0; + grub_size_t size = 0; grub_addr_t addr_min, addr_max; grub_addr_t addr; grub_err_t err; struct linux_kernel_header *lh; + int i; + int nfiles = 0; + grub_uint8_t *ptr; if (argc == 0) { - grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified"); + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); goto fail; } if (! loaded) { - grub_error (GRUB_ERR_BAD_ARGUMENT, "you need to load the kernel first"); + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first")); goto fail; } - grub_file_filter_disable_compression (); - file = grub_file_open (argv[0]); - if (! file) + files = grub_zalloc (argc * sizeof (files[0])); + if (!files) goto fail; - size = grub_file_size (file); + for (i = 0; i < argc; i++) + { + grub_file_filter_disable_compression (); + files[i] = grub_file_open (argv[i]); + if (! files[i]) + goto fail; + nfiles++; + size += grub_file_size (files[i]); + } + initrd_pages = (page_align (size) >> 12); lh = (struct linux_kernel_header *) real_mode_mem; @@ -1012,10 +1028,18 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), initrd_mem_target = get_physical_target_address (ch); } - if (grub_file_read (file, initrd_mem, size) != size) + ptr = initrd_mem; + for (i = 0; i < nfiles; i++) { - grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file"); - goto fail; + grub_ssize_t cursize = grub_file_size (files[i]); + if (grub_file_read (files[i], ptr, cursize) != cursize) + { + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), + argv[i]); + goto fail; + } + ptr += cursize; } grub_dprintf ("linux", "Initrd, addr=0x%x, size=0x%x\n", @@ -1026,8 +1050,9 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), lh->root_dev = 0x0100; /* XXX */ fail: - if (file) - grub_file_close (file); + for (i = 0; i < nfiles; i++) + grub_file_close (files[i]); + grub_free (files); return grub_errno; } diff --git a/grub-core/loader/i386/multiboot_mbi.c b/grub-core/loader/i386/multiboot_mbi.c index abd4ae96d..e41a4d895 100644 --- a/grub-core/loader/i386/multiboot_mbi.c +++ b/grub-core/loader/i386/multiboot_mbi.c @@ -34,6 +34,7 @@ #include #include #include +#include /* The bits in the required part of flags field we don't support. */ #define UNSUPPORTED_FLAGS 0x0000fff8 @@ -60,7 +61,7 @@ static void *elf_sections; grub_err_t -grub_multiboot_load (grub_file_t file) +grub_multiboot_load (grub_file_t file, const char *filename) { char *buffer; grub_ssize_t len; @@ -75,7 +76,10 @@ grub_multiboot_load (grub_file_t file) if (len < 32) { grub_free (buffer); - return grub_error (GRUB_ERR_BAD_OS, "file too small"); + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); + return grub_errno; } /* Look for the multiboot header in the buffer. The header should @@ -149,7 +153,7 @@ grub_multiboot_load (grub_file_t file) } else { - err = grub_multiboot_load_elf (file, buffer); + err = grub_multiboot_load_elf (file, filename, buffer); if (err) { grub_free (buffer); diff --git a/grub-core/loader/i386/pc/chainloader.c b/grub-core/loader/i386/pc/chainloader.c index 30b1e8b09..c79c4fe0f 100644 --- a/grub-core/loader/i386/pc/chainloader.c +++ b/grub-core/loader/i386/pc/chainloader.c @@ -182,8 +182,9 @@ grub_chainloader_cmd (const char *filename, grub_chainloader_flags_t flags) if (grub_file_read (file, bs, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE) { - if (grub_errno == GRUB_ERR_NONE) - grub_error (GRUB_ERR_BAD_OS, "too small"); + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); goto fail; } @@ -270,9 +271,9 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)), } if (argc == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified"); - else - grub_chainloader_cmd (argv[0], flags); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); + + grub_chainloader_cmd (argv[0], flags); return grub_errno; } diff --git a/grub-core/loader/i386/pc/freedos.c b/grub-core/loader/i386/pc/freedos.c index 1f088e2b5..f1eed57ba 100644 --- a/grub-core/loader/i386/pc/freedos.c +++ b/grub-core/loader/i386/pc/freedos.c @@ -83,7 +83,7 @@ grub_cmd_freedos (grub_command_t cmd __attribute__ ((unused)), grub_size_t kernelsyssize; if (argc == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); grub_dl_ref (my_mod); diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c index c7c099174..dfa6e6f30 100644 --- a/grub-core/loader/i386/pc/linux.c +++ b/grub-core/loader/i386/pc/linux.c @@ -98,7 +98,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), if (argc == 0) { - grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified"); + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); goto fail; } @@ -108,7 +108,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) { - grub_error (GRUB_ERR_READ_ERROR, "cannot read the Linux header"); + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + argv[0]); goto fail; } @@ -202,9 +204,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), goto fail; } - grub_printf (" [Linux-%s, setup=0x%x, size=0x%x]\n", - grub_linux_is_bzimage ? "bzImage" : "zImage", real_size, - grub_linux16_prot_size); + grub_dprintf ("linux", "[Linux-%s, setup=0x%x, size=0x%x]\n", + grub_linux_is_bzimage ? "bzImage" : "zImage", real_size, + grub_linux16_prot_size); relocator = grub_relocator_new (); if (!relocator) @@ -283,7 +285,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), len = real_size + GRUB_DISK_SECTOR_SIZE - sizeof (lh); if (grub_file_read (file, grub_linux_real_chunk + sizeof (lh), len) != len) { - grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file"); + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + argv[0]); goto fail; } @@ -321,8 +325,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), len = grub_linux16_prot_size; if (grub_file_read (file, grub_linux_prot_chunk, grub_linux16_prot_size) - != (grub_ssize_t) grub_linux16_prot_size) - grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file"); + != (grub_ssize_t) grub_linux16_prot_size && !grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + argv[0]); if (grub_errno == GRUB_ERR_NONE) { @@ -349,23 +354,25 @@ static grub_err_t grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) { - grub_file_t file = 0; - grub_ssize_t size; + grub_file_t *files = 0; + grub_size_t size = 0; grub_addr_t addr_max, addr_min; struct linux_kernel_header *lh; grub_uint8_t *initrd_chunk; grub_addr_t initrd_addr; grub_err_t err; + int i, nfiles = 0; + grub_uint8_t *ptr; if (argc == 0) { - grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified"); + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); goto fail; } if (!loaded) { - grub_error (GRUB_ERR_BAD_ARGUMENT, "you need to load the kernel first"); + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first")); goto fail; } @@ -403,12 +410,19 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), addr_min = GRUB_LINUX_BZIMAGE_ADDR + grub_linux16_prot_size; - grub_file_filter_disable_compression (); - file = grub_file_open (argv[0]); - if (!file) + files = grub_zalloc (argc * sizeof (files[0])); + if (!files) goto fail; - size = grub_file_size (file); + for (i = 0; i < argc; i++) + { + grub_file_filter_disable_compression (); + files[i] = grub_file_open (argv[i]); + if (! files[i]) + goto fail; + nfiles++; + size += grub_file_size (files[i]); + } { grub_relocator_chunk_t ch; @@ -422,18 +436,28 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), initrd_addr = get_physical_target_address (ch); } - if (grub_file_read (file, initrd_chunk, size) != size) + ptr = initrd_chunk; + + for (i = 0; i < nfiles; i++) { - grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file"); - goto fail; + grub_ssize_t cursize = grub_file_size (files[i]); + if (grub_file_read (files[i], ptr, cursize) != cursize) + { + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), + argv[i]); + goto fail; + } + ptr += cursize; } lh->ramdisk_image = initrd_addr; lh->ramdisk_size = size; fail: - if (file) - grub_file_close (file); + for (i = 0; i < nfiles; i++) + grub_file_close (files[i]); + grub_free (files); return grub_errno; } diff --git a/grub-core/loader/i386/pc/ntldr.c b/grub-core/loader/i386/pc/ntldr.c index 153b605ed..1b88f40d8 100644 --- a/grub-core/loader/i386/pc/ntldr.c +++ b/grub-core/loader/i386/pc/ntldr.c @@ -82,7 +82,7 @@ grub_cmd_ntldr (grub_command_t cmd __attribute__ ((unused)), grub_device_t dev; if (argc == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); grub_dl_ref (my_mod); diff --git a/grub-core/loader/i386/pc/plan9.c b/grub-core/loader/i386/pc/plan9.c index 5528b2c9f..baf029f90 100644 --- a/grub-core/loader/i386/pc/plan9.c +++ b/grub-core/loader/i386/pc/plan9.c @@ -260,7 +260,6 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[]) default: /* Not sure how to handle those. */ - case GRUB_DISK_DEVICE_PXE_ID: case GRUB_DISK_DEVICE_NAND_ID: if (!file_disk) { @@ -341,7 +340,7 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[]) } if (argc == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "no file specified"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); grub_dl_ref (my_mod); @@ -385,7 +384,12 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[]) goto fail; if (grub_file_read (file, &hdr, sizeof (hdr)) != (grub_ssize_t) sizeof (hdr)) - goto fail; + { + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + argv[0]); + goto fail; + } if (grub_be_to_cpu32 (hdr.magic) != GRUB_PLAN9_MAGIC || hdr.zero) @@ -463,7 +467,12 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[]) if (grub_file_read (file, ptr, grub_be_to_cpu32 (hdr.text_size)) != (grub_ssize_t) grub_be_to_cpu32 (hdr.text_size)) - goto fail; + { + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + argv[0]); + goto fail; + } ptr += grub_be_to_cpu32 (hdr.text_size); padsize = ALIGN_UP (grub_be_to_cpu32 (hdr.text_size) + sizeof (hdr), GRUB_PLAN9_ALIGN) - grub_be_to_cpu32 (hdr.text_size) @@ -474,7 +483,12 @@ grub_cmd_plan9 (grub_extcmd_context_t ctxt, int argc, char *argv[]) if (grub_file_read (file, ptr, grub_be_to_cpu32 (hdr.data_size)) != (grub_ssize_t) grub_be_to_cpu32 (hdr.data_size)) - goto fail; + { + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + argv[0]); + goto fail; + } ptr += grub_be_to_cpu32 (hdr.data_size); padsize = ALIGN_UP (grub_be_to_cpu32 (hdr.data_size), GRUB_PLAN9_ALIGN) - grub_be_to_cpu32 (hdr.data_size); diff --git a/grub-core/loader/i386/pc/pxechainloader.c b/grub-core/loader/i386/pc/pxechainloader.c new file mode 100644 index 000000000..4b528b6b8 --- /dev/null +++ b/grub-core/loader/i386/pc/pxechainloader.c @@ -0,0 +1,167 @@ +/* chainloader.c - boot another boot loader */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2004,2007,2009,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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License 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 + +static grub_dl_t my_mod; +static struct grub_relocator *rel; +static grub_uint32_t edx = 0xffffffff; +static char boot_file[128]; +static char server_name[64]; + +GRUB_MOD_LICENSE ("GPLv3+"); + +static grub_err_t +grub_pxechain_boot (void) +{ + struct grub_relocator16_state state = { + .cs = 0, + .ip = 0x7c00, + .ds = 0, + .es = 0, + .fs = 0, + .gs = 0, + .ss = 0, + .sp = 0x7c00, + .edx = edx + }; + struct grub_net_bootp_packet *bp; + + bp = grub_pxe_get_cached (GRUB_PXENV_PACKET_TYPE_DHCP_ACK); + + grub_video_set_mode ("text", 0, 0); + + if (bp && boot_file[0]) + grub_memcpy (bp->boot_file, boot_file, sizeof (bp->boot_file)); + if (bp && server_name[0]) + grub_memcpy (bp->server_name, server_name, sizeof (bp->server_name)); + + return grub_relocator16_boot (rel, state); +} + +static grub_err_t +grub_pxechain_unload (void) +{ + grub_relocator_unload (rel); + rel = NULL; + grub_dl_unref (my_mod); + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_pxechain (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + grub_file_t file = 0; + grub_err_t err; + void *image; + grub_size_t imagesize; + char *fname; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); + + grub_dl_ref (my_mod); + + rel = grub_relocator_new (); + if (!rel) + goto fail; + + file = grub_file_open (argv[0]); + if (! file) + goto fail; + + if (file->device->net && file->device->net->name) + fname = file->device->net->name; + else + { + fname = argv[0]; + if (fname[0] == '(') + { + fname = grub_strchr (fname, ')'); + if (fname) + fname++; + else + fname = argv[0]; + } + } + + grub_memset (boot_file, 0, sizeof (boot_file)); + grub_strncpy (boot_file, fname, sizeof (boot_file)); + + grub_memset (server_name, 0, sizeof (server_name)); + if (file->device->net && file->device->net->server) + grub_strncpy (server_name, file->device->net->server, sizeof (server_name)); + + edx = grub_get_root_biosnumber (); + + imagesize = grub_file_size (file); + { + grub_relocator_chunk_t ch; + err = grub_relocator_alloc_chunk_addr (rel, &ch, 0x7c00, imagesize); + if (err) + goto fail; + image = get_virtual_current_address (ch); + } + + if (grub_file_read (file, image, imagesize) != (grub_ssize_t) imagesize) + goto fail; + + grub_loader_set (grub_pxechain_boot, grub_pxechain_unload, 1); + return GRUB_ERR_NONE; + + fail: + + if (file) + grub_file_close (file); + + grub_pxechain_unload (); + + return grub_errno; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(pxechainloader) +{ + cmd = grub_register_command ("pxechainloader", grub_cmd_pxechain, + 0, N_("Load a PXE image.")); + my_mod = mod; +} + +GRUB_MOD_FINI(pxechainloader) +{ + grub_unregister_command (cmd); +} diff --git a/grub-core/loader/i386/xnu.c b/grub-core/loader/i386/xnu.c index 36893ae62..a94b6a48e 100644 --- a/grub-core/loader/i386/xnu.c +++ b/grub-core/loader/i386/xnu.c @@ -46,7 +46,7 @@ grub_uint32_t grub_xnu_entry_point, grub_xnu_arg1, grub_xnu_stack; struct tbl_alias { grub_efi_guid_t guid; - char *name; + const char *name; }; static struct tbl_alias table_aliases[] = @@ -58,6 +58,7 @@ static struct tbl_alias table_aliases[] = struct grub_xnu_devprop_device_descriptor { struct grub_xnu_devprop_device_descriptor *next; + struct grub_xnu_devprop_device_descriptor **prev; struct property_descriptor *properties; struct grub_efi_device_path *path; int pathlen; @@ -212,6 +213,7 @@ guessfsb (void) struct property_descriptor { struct property_descriptor *next; + struct property_descriptor **prev; grub_uint8_t *name; grub_uint16_t *name16; int name16len; @@ -226,7 +228,7 @@ grub_xnu_devprop_remove_property (struct grub_xnu_devprop_device_descriptor *dev char *name) { struct property_descriptor *prop; - prop = grub_named_list_find (GRUB_AS_NAMED_LIST_P (&dev->properties), name); + prop = grub_named_list_find (GRUB_AS_NAMED_LIST (dev->properties), name); if (!prop) return GRUB_ERR_NONE; @@ -234,7 +236,7 @@ grub_xnu_devprop_remove_property (struct grub_xnu_devprop_device_descriptor *dev grub_free (prop->name16); grub_free (prop->data); - grub_list_remove (GRUB_AS_LIST_P (&dev->properties), GRUB_AS_LIST (prop)); + grub_list_remove (GRUB_AS_LIST (prop)); return GRUB_ERR_NONE; } @@ -245,7 +247,7 @@ grub_xnu_devprop_remove_device (struct grub_xnu_devprop_device_descriptor *dev) void *t; struct property_descriptor *prop; - grub_list_remove (GRUB_AS_LIST_P (&devices), GRUB_AS_LIST (dev)); + grub_list_remove (GRUB_AS_LIST (dev)); for (prop = dev->properties; prop; ) { @@ -532,12 +534,11 @@ grub_cmd_devprop_load (grub_command_t cmd __attribute__ ((unused)), unsigned i, j; if (argc != 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); file = grub_file_open (args[0]); if (! file) - return grub_error (GRUB_ERR_FILE_NOT_FOUND, - "couldn't load device-propertie dump"); + return grub_errno; size = grub_file_size (file); buf = grub_malloc (size); if (!buf) @@ -734,18 +735,18 @@ grub_cpu_xnu_fill_devicetree (void) #else if (SIZEOF_OF_UINTN == 4) { - ptr = UINT_TO_PTR (((grub_efiemu_configuration_table32_t *) - SYSTEM_TABLE_PTR (configuration_table))[i] - .vendor_table); + ptr = (void *) (grub_addr_t) ((grub_efiemu_configuration_table32_t *) + SYSTEM_TABLE_PTR (configuration_table))[i] + .vendor_table; guid = ((grub_efiemu_configuration_table32_t *) SYSTEM_TABLE_PTR (configuration_table))[i].vendor_guid; } else { - ptr = UINT_TO_PTR (((grub_efiemu_configuration_table64_t *) - SYSTEM_TABLE_PTR (configuration_table))[i] - .vendor_table); + ptr = (void *) (grub_addr_t) ((grub_efiemu_configuration_table64_t *) + SYSTEM_TABLE_PTR (configuration_table))[i] + .vendor_table; guid = ((grub_efiemu_configuration_table64_t *) SYSTEM_TABLE_PTR (configuration_table))[i].vendor_guid; @@ -786,9 +787,9 @@ grub_cpu_xnu_fill_devicetree (void) if (! curval->data) return grub_errno; if (SIZEOF_OF_UINTN == 4) - *((grub_uint32_t *)curval->data) = PTR_TO_UINT32 (ptr); + *((grub_uint32_t *) curval->data) = (grub_addr_t) ptr; else - *((grub_uint64_t *)curval->data) = PTR_TO_UINT64 (ptr); + *((grub_uint64_t *) curval->data) = (grub_addr_t) ptr; /* Create alias. */ for (j = 0; j < sizeof (table_aliases) / sizeof (table_aliases[0]); j++) @@ -821,10 +822,10 @@ grub_cpu_xnu_fill_devicetree (void) return grub_errno; if (SIZEOF_OF_UINTN == 4) *((grub_uint32_t *) curval->data) - = PTR_TO_UINT32 (SYSTEM_TABLE_PTR (runtime_services)); + = (grub_addr_t) SYSTEM_TABLE_PTR (runtime_services); else *((grub_uint64_t *) curval->data) - = PTR_TO_UINT64 (SYSTEM_TABLE_PTR (runtime_services)); + = (grub_addr_t) SYSTEM_TABLE_PTR (runtime_services); return GRUB_ERR_NONE; } @@ -847,7 +848,6 @@ static grub_err_t grub_xnu_set_video (struct grub_xnu_boot_params *params) { struct grub_video_mode_info mode_info; - int ret; char *tmp; const char *modevar; void *framebuffer; @@ -876,9 +876,9 @@ grub_xnu_set_video (struct grub_xnu_boot_params *params) if (err) return err; - ret = grub_video_get_info (&mode_info); - if (ret) - return grub_error (GRUB_ERR_IO, "couldn't retrieve video parameters"); + err = grub_video_get_info (&mode_info); + if (err) + return err; if (grub_xnu_bitmap) { @@ -930,16 +930,16 @@ grub_xnu_set_video (struct grub_xnu_boot_params *params) bitmap = 0; } - ret = grub_video_get_info_and_fini (&mode_info, &framebuffer); - if (ret) - return grub_error (GRUB_ERR_IO, "couldn't retrieve video parameters"); + err = grub_video_get_info_and_fini (&mode_info, &framebuffer); + if (err) + return err; params->lfb_width = mode_info.width; params->lfb_height = mode_info.height; params->lfb_depth = mode_info.bpp; params->lfb_line_len = mode_info.pitch; - params->lfb_base = PTR_TO_UINT32 (framebuffer); + params->lfb_base = (grub_addr_t) framebuffer; params->lfb_mode = bitmap ? GRUB_XNU_VIDEO_SPLASH : GRUB_XNU_VIDEO_TEXT_IN_VIDEO; @@ -1001,7 +1001,7 @@ grub_xnu_boot (void) if (debug && (grub_strword (debug, "all") || grub_strword (debug, "xnu"))) { - grub_printf ("Press any key to launch xnu\n"); + grub_puts_ (N_("Press any key to launch xnu")); grub_getkey (); } @@ -1057,7 +1057,7 @@ grub_xnu_boot (void) if (err) return err; - bootparams->efi_system_table = PTR_TO_UINT32 (grub_autoefi_system_table); + bootparams->efi_system_table = (grub_addr_t) grub_autoefi_system_table; firstruntimepage = (((grub_addr_t) grub_xnu_heap_target_start + grub_xnu_heap_size + GRUB_XNU_PAGESIZE - 1) @@ -1077,11 +1077,11 @@ grub_xnu_boot (void) curdesc->virtual_start = curruntimepage << 12; curruntimepage += curdesc->num_pages; if (curdesc->physical_start - <= PTR_TO_UINT64 (grub_autoefi_system_table) + <= (grub_addr_t) grub_autoefi_system_table && curdesc->physical_start + (curdesc->num_pages << 12) - > PTR_TO_UINT64 (grub_autoefi_system_table)) + > (grub_addr_t) grub_autoefi_system_table) bootparams->efi_system_table - = PTR_TO_UINT64 (grub_autoefi_system_table) + = (grub_addr_t) grub_autoefi_system_table - curdesc->physical_start + curdesc->virtual_start; if (SIZEOF_OF_UINTN == 8 && grub_xnu_is_64bit) curdesc->virtual_start |= 0xffffff8000000000ULL; @@ -1127,7 +1127,10 @@ grub_cpu_xnu_init (void) { cmd_devprop_load = grub_register_command ("xnu_devprop_load", grub_cmd_devprop_load, - 0, N_("Load device-properties dump.")); + /* TRANSLATORS: `device-properties' + is a variable name, + not a program. */ + 0, N_("Load `device-properties' dump.")); } void diff --git a/grub-core/loader/ia64/efi/linux.c b/grub-core/loader/ia64/efi/linux.c index 247eebae5..e4ba6a269 100644 --- a/grub-core/loader/ia64/efi/linux.c +++ b/grub-core/loader/ia64/efi/linux.c @@ -30,9 +30,13 @@ #include #include #include +#include +#include GRUB_MOD_LICENSE ("GPLv3+"); +#pragma GCC diagnostic ignored "-Wcast-align" + #define ALIGN_MIN (256*1024*1024) #define GRUB_ELF_SEARCH 1024 @@ -57,21 +61,6 @@ struct ia64_boot_param grub_uint64_t fpswa; /* physical address of the fpswa interface */ grub_uint64_t initrd_start; grub_uint64_t initrd_size; - grub_uint64_t domain_start; /* boot domain address. */ - grub_uint64_t domain_size; /* how big is the boot domain */ - grub_uint64_t payloads_chain; - grub_uint64_t payloads_nbr; -}; - -struct ia64_boot_payload -{ - grub_uint64_t start; - grub_uint64_t length; - - /* Payload command line */ - grub_uint64_t cmdline; - - grub_uint64_t next; }; typedef struct @@ -101,13 +90,6 @@ static grub_efi_uintn_t initrd_size; static struct ia64_boot_param *boot_param; static grub_efi_uintn_t boot_param_pages; -static struct ia64_boot_payload *last_payload = NULL; - -/* Can linux kernel be relocated ? */ -#define RELOCATE_OFF 0 /* No. */ -#define RELOCATE_ON 1 /* Yes. */ -#define RELOCATE_FORCE 2 /* Always - used to debug. */ -static int relocate = RELOCATE_OFF; static inline grub_size_t page_align (grub_size_t size) @@ -133,18 +115,19 @@ query_fpswa (void) bs = grub_efi_system_table->boot_services; status = bs->locate_handle (GRUB_EFI_BY_PROTOCOL, - (void *)&fpswa_protocol, + (void *) &fpswa_protocol, NULL, &size, &fpswa_image); if (status != GRUB_EFI_SUCCESS) { - grub_printf("Could not locate FPSWA driver\n"); + grub_printf ("%s\n", _("Could not locate FPSWA driver")); return; } status = bs->handle_protocol (fpswa_image, - (void *)&fpswa_protocol, (void *)&fpswa); + (void *) &fpswa_protocol, (void *) &fpswa); if (status != GRUB_EFI_SUCCESS) { - grub_printf ("Fpswa protocol not able find the interface\n"); + grub_printf ("%s\n", + _("FPSWA protocol wasn't able to find the interface")); return; } } @@ -174,7 +157,10 @@ find_mmap_size (void) grub_free (mmap); if (ret < 0) - grub_fatal ("cannot get memory map"); + { + grub_error (GRUB_ERR_IO, "cannot get memory map"); + return 0; + } else if (ret > 0) break; @@ -205,24 +191,8 @@ free_pages (void) if (boot_param) { - struct ia64_boot_payload *payload; - struct ia64_boot_payload *next_payload; - - /* Free payloads. */ - payload = (struct ia64_boot_payload *)boot_param->payloads_chain; - while (payload != 0) - { - next_payload = (struct ia64_boot_payload *)payload->next; - - grub_efi_free_pages - (payload->start, page_align (payload->length) >> 12); - grub_efi_free_pages ((grub_efi_physical_address_t)payload, 1); - - payload = next_payload; - } - /* Free bootparam. */ - grub_efi_free_pages ((grub_efi_physical_address_t)boot_param, + grub_efi_free_pages ((grub_efi_physical_address_t) boot_param, boot_param_pages); boot_param = 0; } @@ -242,6 +212,8 @@ allocate_pages (grub_uint64_t align, grub_uint64_t size_pages, size = size_pages << 12; mmap_size = find_mmap_size (); + if (!mmap_size) + return 0; /* Read the memory map temporarily, to find free space. */ mmap = grub_malloc (mmap_size); @@ -250,7 +222,10 @@ allocate_pages (grub_uint64_t align, grub_uint64_t size_pages, tmp_mmap_size = mmap_size; if (grub_efi_get_memory_map (&tmp_mmap_size, mmap, 0, &desc_size, 0) <= 0) - grub_fatal ("cannot get memory map"); + { + grub_error (GRUB_ERR_IO, "cannot get memory map"); + goto fail; + } mmap_end = NEXT_MEMORY_DESCRIPTOR (mmap, tmp_mmap_size); @@ -278,7 +253,10 @@ allocate_pages (grub_uint64_t align, grub_uint64_t size_pages, continue; mem = grub_efi_allocate_pages (aligned_start, size_pages); if (! mem) - grub_fatal ("cannot allocate pages"); + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate memory"); + goto fail; + } break; } @@ -308,10 +286,10 @@ set_boot_param_console (void) != GRUB_EFI_SUCCESS) return; - grub_dprintf("linux", - "Console info: cols=%lu rows=%lu x=%u y=%u\n", - cols, rows, - conout->mode->cursor_column, conout->mode->cursor_row); + grub_dprintf ("linux", + "Console info: cols=%lu rows=%lu x=%u y=%u\n", + cols, rows, + conout->mode->cursor_column, conout->mode->cursor_row); boot_param->console_info.num_cols = cols; boot_param->console_info.num_rows = rows; @@ -339,17 +317,17 @@ grub_linux_boot (void) set_boot_param_console (); - grub_printf ("Jump to %016lx\n", entry); - - grub_machine_fini (); + grub_dprintf ("linux", "Jump to %016lx\n", entry); /* MDT. 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_errno; mmap_buf = grub_efi_allocate_pages (0, page_align (mmap_size) >> 12); if (! mmap_buf) - grub_fatal ("cannot allocate memory map"); + return grub_error (GRUB_ERR_IO, "cannot allocate memory map"); err = grub_efi_finish_boot_services (&mmap_size, mmap_buf, &map_key, &desc_size, &desc_version); if (err) @@ -377,7 +355,7 @@ grub_linux_unload (void) } static grub_err_t -grub_load_elf64 (grub_file_t file, void *buffer) +grub_load_elf64 (grub_file_t file, void *buffer, const char *filename) { Elf64_Ehdr *ehdr = (Elf64_Ehdr *) buffer; Elf64_Phdr *phdr; @@ -386,21 +364,25 @@ grub_load_elf64 (grub_file_t file, void *buffer) grub_uint64_t high_addr; grub_uint64_t align; grub_uint64_t reloc_offset; - - if (ehdr->e_ident[EI_CLASS] != ELFCLASS64) - return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF class"); + const char *relocate; if (ehdr->e_ident[EI_MAG0] != ELFMAG0 || ehdr->e_ident[EI_MAG1] != ELFMAG1 || ehdr->e_ident[EI_MAG2] != ELFMAG2 || ehdr->e_ident[EI_MAG3] != ELFMAG3 + || ehdr->e_ident[EI_DATA] != ELFDATA2LSB) + return grub_error(GRUB_ERR_UNKNOWN_OS, + N_("invalid arch independent ELF magic")); + + if (ehdr->e_ident[EI_CLASS] != ELFCLASS64 || ehdr->e_version != EV_CURRENT - || ehdr->e_ident[EI_DATA] != ELFDATA2LSB || ehdr->e_machine != EM_IA_64) - return grub_error(GRUB_ERR_UNKNOWN_OS, "no valid ELF header found"); + return grub_error (GRUB_ERR_UNKNOWN_OS, + N_("invalid arch dependent ELF magic")); if (ehdr->e_type != ET_EXEC) - return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF file type"); + return grub_error (GRUB_ERR_UNKNOWN_OS, + N_("this ELF file is not of the right type")); /* FIXME: Should we support program headers at strange locations? */ if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > GRUB_ELF_SEARCH) @@ -435,20 +417,22 @@ grub_load_elf64 (grub_file_t file, void *buffer) kernel_pages = page_align (high_addr - low_addr) >> 12; - if (relocate != RELOCATE_FORCE) + /* Undocumented on purpose. */ + relocate = grub_env_get ("linux_relocate"); + if (!relocate || grub_strcmp (relocate, "force") != 0) { kernel_mem = grub_efi_allocate_pages (low_addr, kernel_pages); reloc_offset = 0; } /* Try to relocate. */ - if (! kernel_mem && relocate != RELOCATE_OFF) + if (! kernel_mem && (!relocate || grub_strcmp (relocate, "off") != 0)) { kernel_mem = allocate_pages (align, kernel_pages, low_addr); if (kernel_mem) { reloc_offset = (grub_uint64_t)kernel_mem - low_addr; - grub_printf (" Relocated at %p (offset=%016lx)\n", - kernel_mem, reloc_offset); + grub_dprintf ("linux", " Relocated at %p (offset=%016lx)\n", + kernel_mem, reloc_offset); entry += reloc_offset; } } @@ -463,20 +447,23 @@ grub_load_elf64 (grub_file_t file, void *buffer) + i * ehdr->e_phentsize); if (phdr->p_type == PT_LOAD) { - grub_printf (" [paddr=%lx load=%lx memsz=%08lx " - "off=%lx flags=%x]\n", - phdr->p_paddr, phdr->p_paddr + reloc_offset, - phdr->p_memsz, phdr->p_offset, phdr->p_flags); - + grub_dprintf ("linux", " [paddr=%lx load=%lx memsz=%08lx " + "off=%lx flags=%x]\n", + phdr->p_paddr, phdr->p_paddr + reloc_offset, + phdr->p_memsz, phdr->p_offset, phdr->p_flags); + if (grub_file_seek (file, phdr->p_offset) == (grub_off_t)-1) - return grub_error (GRUB_ERR_BAD_OS, - "invalid offset in program header"); + return grub_errno; - if (grub_file_read (file, (void *)(phdr->p_paddr + reloc_offset), + if (grub_file_read (file, (void *) (phdr->p_paddr + reloc_offset), phdr->p_filesz) != (grub_ssize_t) phdr->p_filesz) - return grub_error (GRUB_ERR_BAD_OS, - "couldn't read segment from file"); + { + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); + return grub_errno; + } if (phdr->p_filesz < phdr->p_memsz) grub_memset @@ -509,33 +496,32 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), if (argc == 0) { - grub_error (GRUB_ERR_BAD_ARGUMENT, "No kernel specified"); + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); goto fail; } file = grub_file_open (argv[0]); if (! file) - { - grub_error (GRUB_ERR_BAD_ARGUMENT, "Couldn't open file"); - goto fail; - } + goto fail; len = grub_file_read (file, buffer, sizeof (buffer)); - if (len < (grub_ssize_t)sizeof (Elf64_Ehdr)) + if (len < (grub_ssize_t) sizeof (Elf64_Ehdr)) { - grub_error (GRUB_ERR_BAD_OS, "File too small"); + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + argv[0]); goto fail; } - grub_printf ("Loading linux: %s\n", argv[0]); + grub_dprintf ("linux", "Loading linux: %s\n", argv[0]); - if (grub_load_elf64 (file, buffer)) + if (grub_load_elf64 (file, buffer, argv[0])) goto fail; len = sizeof("BOOT_IMAGE=") + 8; for (i = 0; i < argc; i++) len += grub_strlen (argv[i]) + 1; - len += sizeof (struct ia64_boot_param) + 256; /* Room for extensions. */ + len += sizeof (struct ia64_boot_param) + 512; /* Room for extensions. */ boot_param_pages = page_align (len) >> 12; boot_param = grub_efi_allocate_pages (0, boot_param_pages); if (boot_param == 0) @@ -581,208 +567,96 @@ static grub_err_t grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) { - grub_file_t file = 0; + grub_file_t *files = 0; + int i; + int nfiles = 0; + grub_uint8_t *ptr; if (argc == 0) { - grub_error (GRUB_ERR_BAD_ARGUMENT, "No filename specified"); + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); goto fail; } if (! loaded) { - grub_error (GRUB_ERR_BAD_ARGUMENT, "You need to load the kernel first."); + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first")); goto fail; } - file = grub_file_open (argv[0]); - if (! file) + files = grub_zalloc (argc * sizeof (files[0])); + if (!files) goto fail; - grub_printf ("Loading initrd: %s\n",argv[0]); + initrd_size = 0; + grub_dprintf ("linux", "Loading initrd\n"); + for (i = 0; i < argc; i++) + { + grub_file_filter_disable_compression (); + files[i] = grub_file_open (argv[i]); + if (! files[i]) + goto fail; + nfiles++; + initrd_size += grub_file_size (files[i]); + grub_dprintf ("linux", "File %d: %s\n", i, argv[i]); + } - initrd_size = grub_file_size (file); initrd_pages = (page_align (initrd_size) >> 12); initrd_mem = grub_efi_allocate_pages (0, initrd_pages); if (! initrd_mem) - grub_fatal ("cannot allocate pages"); - - grub_printf (" [addr=0x%lx, size=0x%lx]\n", - (grub_uint64_t)initrd_mem, initrd_size); - - if (grub_file_read (file, initrd_mem, initrd_size) - != (grub_ssize_t)initrd_size) { - grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file"); + grub_error (GRUB_ERR_OUT_OF_MEMORY, "cannot allocate pages"); goto fail; } + + grub_dprintf ("linux", "[addr=0x%lx, size=0x%lx]\n", + (grub_uint64_t) initrd_mem, initrd_size); + + ptr = initrd_mem; + for (i = 0; i < nfiles; i++) + { + grub_ssize_t cursize = grub_file_size (files[i]); + if (grub_file_read (files[i], ptr, cursize) != cursize) + { + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), + argv[i]); + goto fail; + } + ptr += cursize; + } fail: - if (file) - grub_file_close (file); + for (i = 0; i < nfiles; i++) + grub_file_close (files[i]); + grub_free (files); return grub_errno; } -static grub_err_t -grub_cmd_payload (grub_command_t cmd __attribute__ ((unused)), - int argc, char *argv[]) -{ - grub_file_t file = 0; - grub_ssize_t size, len = 0; - char *base = 0, *cmdline = 0, *p; - struct ia64_boot_payload *payload = NULL; - int i; - - if (argc == 0) - { - grub_error (GRUB_ERR_BAD_ARGUMENT, "No module specified"); - goto fail; - } - - if (!boot_param) - { - grub_error (GRUB_ERR_BAD_ARGUMENT, - "You need to load the kernel first"); - goto fail; - } - - file = grub_file_open (argv[0]); - if (! file) - goto fail; - - size = grub_file_size (file); - base = grub_efi_allocate_pages (0, page_align (size) >> 12); - if (! base) - goto fail; - - grub_printf ("Payload %s [addr=%lx + %lx]\n", - argv[0], (grub_uint64_t)base, size); - - if (grub_file_read (file, base, size) != size) - { - grub_error (GRUB_ERR_FILE_READ_ERROR, "Couldn't read file"); - goto fail; - } - - len = sizeof (struct ia64_boot_payload); - for (i = 0; i < argc; i++) - len += grub_strlen (argv[i]) + 1; - - if (len > 4096) - { - grub_error (GRUB_ERR_OUT_OF_RANGE, "payload command line too long"); - goto fail; - } - payload = grub_efi_allocate_pages (0, 1); - if (! payload) - goto fail; - - p = (char *)(payload + 1); - - payload->start = (grub_uint64_t)base; - payload->length = size; - payload->cmdline = (grub_uint64_t)p; - payload->next = 0; - - if (last_payload) - last_payload->next = (grub_uint64_t)payload; - else - { - last_payload = payload; - boot_param->payloads_chain = (grub_uint64_t)payload; - } - boot_param->payloads_nbr++; - - /* Copy command line. */ - for (i = 0; i < argc; i++) - { - p = grub_stpcpy (p, argv[i]); - *(p++) = ' '; - } - - /* Remove the space after the last word. */ - *(--p) = '\0'; - - - fail: - if (file) - grub_file_close (file); - - if (grub_errno != GRUB_ERR_NONE) - { - grub_free (base); - grub_free (cmdline); - } - return grub_errno; -} - -static grub_err_t -grub_cmd_relocate (grub_command_t cmd __attribute__ ((unused)), - int argc, char *argv[]) -{ - static const char * const vals[] = { "off", "on", "force"}; - unsigned int i; - - if (argc == 0) - { - grub_printf ("relocate is %s\n", vals[relocate]); - return GRUB_ERR_NONE; - } - else if (argc == 1) - { - if (kernel_mem != NULL) - grub_printf ("Warning: kernel already loaded!\n"); - for (i = 0; i < sizeof (vals)/sizeof(vals[0]); i++) - if (grub_strcmp (argv[0], vals[i]) == 0) - { - relocate = i; - return GRUB_ERR_NONE; - } - return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown relocate value"); - } - else - { - return grub_error (GRUB_ERR_BAD_ARGUMENT, "accept 0 or 1 argument"); - } - -} - - static grub_err_t grub_cmd_fpswa (grub_command_t cmd __attribute__ ((unused)), - int argc, char *argv[] __attribute__((unused))) + int argc __attribute__((unused)), + char *argv[] __attribute__((unused))) { - if (argc != 0) - { - return grub_error (GRUB_ERR_BAD_ARGUMENT, "Arguments not expected"); - } query_fpswa (); if (fpswa == NULL) - grub_printf ("No FPSWA loaded\n"); + grub_puts_ (N_("No FPSWA found")); else - grub_printf ("FPSWA revision: %x\n", fpswa->revision); + grub_printf (_("FPSWA revision: %x\n"), fpswa->revision); return GRUB_ERR_NONE; } -static grub_command_t cmd_linux, cmd_initrd, cmd_payload, cmd_relocate, cmd_fpswa; +static grub_command_t cmd_linux, cmd_initrd, cmd_fpswa; GRUB_MOD_INIT(linux) { cmd_linux = grub_register_command ("linux", grub_cmd_linux, - "FILE [ARGS...]", "Load Linux."); + N_("FILE [ARGS...]"), N_("Load Linux.")); cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, - "FILE", "Load initrd."); - - cmd_payload = grub_register_command ("payload", grub_cmd_payload, - "FILE [ARGS...]", - "Load an additional file."); - - cmd_relocate = grub_register_command ("relocate", grub_cmd_relocate, - "[on|off|force]", - "Set relocate feature."); + N_("FILE"), N_("Load initrd.")); cmd_fpswa = grub_register_command ("fpswa", grub_cmd_fpswa, - "", "Display FPSWA version."); + "", N_("Display FPSWA version.")); my_mod = mod; } @@ -791,7 +665,5 @@ GRUB_MOD_FINI(linux) { grub_unregister_command (cmd_linux); grub_unregister_command (cmd_initrd); - grub_unregister_command (cmd_payload); - grub_unregister_command (cmd_relocate); grub_unregister_command (cmd_fpswa); } diff --git a/grub-core/loader/macho.c b/grub-core/loader/macho.c index ecf0d8c53..0a1717fbb 100644 --- a/grub-core/loader/macho.c +++ b/grub-core/loader/macho.c @@ -28,6 +28,7 @@ #include #include #include +#include grub_err_t grub_macho_close (grub_macho_t macho) @@ -46,7 +47,7 @@ grub_macho_close (grub_macho_t macho) } grub_macho_t -grub_macho_file (grub_file_t file) +grub_macho_file (grub_file_t file, const char *filename) { grub_macho_t macho; union grub_macho_filestart filestart; @@ -69,8 +70,9 @@ grub_macho_file (grub_file_t file) if (grub_file_read (macho->file, &filestart, sizeof (filestart)) != sizeof (filestart)) { - grub_error_push (); - grub_error (GRUB_ERR_READ_ERROR, "cannot read Mach-O header"); + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); goto fail; } @@ -90,11 +92,12 @@ grub_macho_file (grub_file_t file) goto fail; if (grub_file_read (macho->file, archs, sizeof (struct grub_macho_fat_arch) * narchs) - != (grub_ssize_t)sizeof(struct grub_macho_fat_arch) * narchs) + != (grub_ssize_t) sizeof(struct grub_macho_fat_arch) * narchs) { grub_free (archs); - grub_error_push (); - grub_error (GRUB_ERR_READ_ERROR, "cannot read Mach-O header"); + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); goto fail; } @@ -132,8 +135,8 @@ grub_macho_file (grub_file_t file) macho->end64 = grub_file_size (file); } - grub_macho_parse32 (macho); - grub_macho_parse64 (macho); + grub_macho_parse32 (macho, filename); + grub_macho_parse64 (macho, filename); return macho; @@ -152,7 +155,7 @@ grub_macho_open (const char *name) if (! file) return 0; - macho = grub_macho_file (file); + macho = grub_macho_file (file, name); if (! macho) grub_file_close (file); diff --git a/grub-core/loader/machoXX.c b/grub-core/loader/machoXX.c index 918ddbb20..58770ddf8 100644 --- a/grub-core/loader/machoXX.c +++ b/grub-core/loader/machoXX.c @@ -2,6 +2,7 @@ #include #include #include +#include #define min(a,b) (((a) < (b)) ? (a) : (b)) @@ -12,7 +13,7 @@ SUFFIX (grub_macho_contains_macho) (grub_macho_t macho) } void -SUFFIX (grub_macho_parse) (grub_macho_t macho) +SUFFIX (grub_macho_parse) (grub_macho_t macho, const char *filename) { grub_macho_header_t head; @@ -25,7 +26,9 @@ SUFFIX (grub_macho_parse) (grub_macho_t macho) || grub_file_read (macho->file, &head, sizeof (head)) != sizeof(head)) { - grub_error (GRUB_ERR_READ_ERROR, "cannot read Mach-O header"); + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); macho->offsetXX = -1; return; } @@ -41,15 +44,14 @@ SUFFIX (grub_macho_parse) (grub_macho_t macho) macho->cmdsizeXX = head.sizeofcmds; macho->cmdsXX = grub_malloc(macho->cmdsizeXX); if (! macho->cmdsXX) - { - grub_error (GRUB_ERR_OUT_OF_MEMORY, "not enough memory to read commands"); - return; - } + return; if (grub_file_read (macho->file, macho->cmdsXX, (grub_size_t) macho->cmdsizeXX) != (grub_ssize_t) macho->cmdsizeXX) { - grub_error (GRUB_ERR_READ_ERROR, "cannot read Mach-O header"); + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); macho->offsetXX = -1; } } @@ -87,7 +89,9 @@ SUFFIX (grub_macho_filesize) (grub_macho_t macho) } grub_err_t -SUFFIX (grub_macho_readfile) (grub_macho_t macho, void *dest) +SUFFIX (grub_macho_readfile) (grub_macho_t macho, + const char *filename, + void *dest) { grub_ssize_t read; if (! SUFFIX (grub_macho_contains_macho) (macho)) @@ -95,19 +99,16 @@ SUFFIX (grub_macho_readfile) (grub_macho_t macho, void *dest) "couldn't read architecture-specific part"); if (grub_file_seek (macho->file, macho->offsetXX) == (grub_off_t) -1) - { - grub_error_push (); - return grub_error (GRUB_ERR_BAD_OS, - "invalid offset in program header"); - } + return grub_errno; read = grub_file_read (macho->file, dest, macho->endXX - macho->offsetXX); if (read != (grub_ssize_t) (macho->endXX - macho->offsetXX)) { - grub_error_push (); - return grub_error (GRUB_ERR_BAD_OS, - "couldn't read architecture-specific part"); + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); + return grub_errno; } return GRUB_ERR_NONE; } @@ -162,9 +163,9 @@ SUFFIX (grub_macho_size) (grub_macho_t macho, grub_macho_addr_t *segments_start, /* Load every loadable segment into memory specified by `_load_hook'. */ grub_err_t -SUFFIX (grub_macho_load) (grub_macho_t macho, char *offset, int flags) +SUFFIX (grub_macho_load) (grub_macho_t macho, const char *filename, + char *offset, int flags) { - grub_err_t err = 0; auto int NESTED_FUNC_ATTR do_load(grub_macho_t _macho, struct grub_macho_cmd *hdr0, void *_arg __attribute__ ((unused))); @@ -184,12 +185,7 @@ SUFFIX (grub_macho_load) (grub_macho_t macho, char *offset, int flags) if (grub_file_seek (_macho->file, hdr->fileoff + _macho->offsetXX) == (grub_off_t) -1) - { - grub_error_push (); - grub_error (GRUB_ERR_BAD_OS, - "invalid offset in program header"); - return 1; - } + return 1; if (hdr->filesize) { @@ -199,11 +195,10 @@ SUFFIX (grub_macho_load) (grub_macho_t macho, char *offset, int flags) if (read != (grub_ssize_t) min (hdr->filesize, hdr->vmsize)) { /* XXX How can we free memory from `load_hook'? */ - grub_error_push (); - err=grub_error (GRUB_ERR_BAD_OS, - "couldn't read segment from file: " - "wanted 0x%lx bytes; read 0x%lx bytes", - hdr->filesize, read); + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + filename); + return 1; } } @@ -216,7 +211,7 @@ SUFFIX (grub_macho_load) (grub_macho_t macho, char *offset, int flags) grub_macho_cmds_iterate (macho, do_load, 0); - return err; + return grub_errno; } grub_macho_addr_t diff --git a/grub-core/loader/mips/linux.c b/grub-core/loader/mips/linux.c index 17c2656e2..a988808c8 100644 --- a/grub-core/loader/mips/linux.c +++ b/grub-core/loader/mips/linux.c @@ -31,6 +31,8 @@ GRUB_MOD_LICENSE ("GPLv3+"); +#pragma GCC diagnostic ignored "-Wcast-align" + /* For frequencies. */ #include @@ -132,7 +134,8 @@ grub_linux_unload (void) } static grub_err_t -grub_linux_load32 (grub_elf_t elf, void **extra_mem, grub_size_t extra_size) +grub_linux_load32 (grub_elf_t elf, const char *filename, + void **extra_mem, grub_size_t extra_size) { Elf32_Addr base; int extraoff; @@ -141,7 +144,7 @@ grub_linux_load32 (grub_elf_t elf, void **extra_mem, grub_size_t extra_size) /* Linux's entry point incorrectly contains a virtual address. */ entry_addr = elf->ehdr.ehdr32.e_entry; - linux_size = grub_elf32_size (elf, &base, 0); + linux_size = grub_elf32_size (elf, filename, &base, 0); if (linux_size == 0) return grub_errno; target_addr = base; @@ -183,11 +186,12 @@ grub_linux_load32 (grub_elf_t elf, void **extra_mem, grub_size_t extra_size) *addr = (grub_addr_t) (phdr->p_paddr - base + playground); return 0; } - return grub_elf32_load (elf, offset_phdr, 0, 0); + return grub_elf32_load (elf, filename, offset_phdr, 0, 0); } static grub_err_t -grub_linux_load64 (grub_elf_t elf, void **extra_mem, grub_size_t extra_size) +grub_linux_load64 (grub_elf_t elf, const char *filename, + void **extra_mem, grub_size_t extra_size) { Elf64_Addr base; int extraoff; @@ -196,7 +200,7 @@ grub_linux_load64 (grub_elf_t elf, void **extra_mem, grub_size_t extra_size) /* Linux's entry point incorrectly contains a virtual address. */ entry_addr = elf->ehdr.ehdr64.e_entry; - linux_size = grub_elf64_size (elf, &base, 0); + linux_size = grub_elf64_size (elf, filename, &base, 0); if (linux_size == 0) return grub_errno; target_addr = base; @@ -237,7 +241,7 @@ grub_linux_load64 (grub_elf_t elf, void **extra_mem, grub_size_t extra_size) *addr = (grub_addr_t) (phdr->p_paddr - base + playground); return 0; } - return grub_elf64_load (elf, offset_phdr, 0, 0); + return grub_elf64_load (elf, filename, offset_phdr, 0, 0); } static grub_err_t @@ -259,7 +263,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), #endif if (argc == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); elf = grub_elf_open (argv[0]); if (! elf) @@ -269,7 +273,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), { grub_elf_close (elf); return grub_error (GRUB_ERR_UNKNOWN_OS, - "this ELF file is not of the right type\n"); + N_("this ELF file is not of the right type")); } /* Release the previously used memory. */ @@ -314,12 +318,12 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), #endif if (grub_elf_is_elf32 (elf)) - err = grub_linux_load32 (elf, &extra, size); + err = grub_linux_load32 (elf, argv[0], &extra, size); else if (grub_elf_is_elf64 (elf)) - err = grub_linux_load64 (elf, &extra, size); + err = grub_linux_load64 (elf, argv[0], &extra, size); else - err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "unknown ELF class"); + err = grub_error (GRUB_ERR_BAD_OS, N_("invalid arch dependent ELF magic")); grub_elf_close (elf); @@ -435,27 +439,37 @@ static grub_err_t grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) { - grub_file_t file = 0; - grub_ssize_t size; + grub_file_t *files = 0; + grub_size_t size = 0; void *initrd_src; grub_addr_t initrd_dest; grub_err_t err; + int i; + int nfiles = 0; + grub_uint8_t *ptr; if (argc == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "no initrd specified"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); if (!loaded) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "you need to load Linux first."); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first")); if (initrd_loaded) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "only one initrd can be loaded."); + return grub_error (GRUB_ERR_BAD_ARGUMENT, "only one initrd command can be issued."); - grub_file_filter_disable_compression (); - file = grub_file_open (argv[0]); - if (! file) - return grub_errno; + files = grub_zalloc (argc * sizeof (files[0])); + if (!files) + goto fail; - size = grub_file_size (file); + for (i = 0; i < argc; i++) + { + grub_file_filter_disable_compression (); + files[i] = grub_file_open (argv[i]); + if (! files[i]) + goto fail; + nfiles++; + size += grub_file_size (files[i]); + } { grub_relocator_chunk_t ch; @@ -468,20 +482,23 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), GRUB_RELOCATOR_PREFERENCE_NONE); if (err) - { - grub_file_close (file); - return err; - } + goto fail; initrd_src = get_virtual_current_address (ch); initrd_dest = get_physical_target_address (ch) | 0x80000000; } - if (grub_file_read (file, initrd_src, size) != size) + ptr = initrd_src; + for (i = 0; i < nfiles; i++) { - grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file"); - grub_file_close (file); - - return grub_errno; + grub_ssize_t cursize = grub_file_size (files[i]); + if (grub_file_read (files[i], ptr, cursize) != cursize) + { + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), + argv[i]); + goto fail; + } + ptr += cursize; } #ifdef GRUB_MACHINE_MIPS_QEMU_MIPS @@ -491,10 +508,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), " rd_size=0x%" PRIxGRUB_ADDR, params, initrd_dest, size); if (!tmp) - { - grub_file_close (file); - return grub_errno; - } + goto fail; grub_free (params); params = tmp; } @@ -516,9 +530,12 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), initrd_loaded = 1; - grub_file_close (file); + fail: + for (i = 0; i < nfiles; i++) + grub_file_close (files[i]); + grub_free (files); - return GRUB_ERR_NONE; + return grub_errno; } static grub_command_t cmd_linux, cmd_initrd; diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c index 2de8e0909..d8951ce9e 100644 --- a/grub-core/loader/multiboot.c +++ b/grub-core/loader/multiboot.c @@ -90,7 +90,9 @@ grub_multiboot_set_video_mode (void) grub_err_t err; const char *modevar; - if (accepts_video || !GRUB_MACHINE_HAS_VGA_TEXT) +#if GRUB_MACHINE_HAS_VGA_TEXT + if (accepts_video) +#endif { modevar = grub_env_get ("gfxpayload"); if (! modevar || *modevar == 0) @@ -105,8 +107,10 @@ grub_multiboot_set_video_mode (void) grub_free (tmp); } } +#if GRUB_MACHINE_HAS_VGA_TEXT else err = grub_video_set_mode ("text", 0, 0); +#endif return err; } @@ -159,14 +163,15 @@ grub_multiboot_unload (void) /* Load ELF32 or ELF64. */ grub_err_t -grub_multiboot_load_elf (grub_file_t file, void *buffer) +grub_multiboot_load_elf (grub_file_t file, const char *filename, + void *buffer) { if (grub_multiboot_is_elf32 (buffer)) - return grub_multiboot_load_elf32 (file, buffer); + return grub_multiboot_load_elf32 (file, filename, buffer); else if (grub_multiboot_is_elf64 (buffer)) - return grub_multiboot_load_elf64 (file, buffer); + return grub_multiboot_load_elf64 (file, filename, buffer); - return grub_error (GRUB_ERR_UNKNOWN_OS, "unknown ELF class"); + return grub_error (GRUB_ERR_UNKNOWN_OS, N_("invalid arch dependent ELF magic")); } grub_err_t @@ -222,11 +227,11 @@ grub_cmd_multiboot (grub_command_t cmd __attribute__ ((unused)), grub_loader_unset (); if (argc == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); file = grub_file_open (argv[0]); if (! file) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "couldn't open file"); + return grub_errno; grub_dl_ref (my_mod); @@ -239,7 +244,7 @@ grub_cmd_multiboot (grub_command_t cmd __attribute__ ((unused)), if (!grub_multiboot_relocator) goto fail; - err = grub_multiboot_load (file); + err = grub_multiboot_load (file, argv[0]); if (err) goto fail; @@ -273,7 +278,7 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)), int nounzip = 0; if (argc == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); if (grub_strcmp (argv[0], "--nounzip") == 0) { @@ -283,11 +288,11 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)), } if (argc == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "no module specified"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); if (!grub_multiboot_relocator) return grub_error (GRUB_ERR_BAD_ARGUMENT, - "you need to load the multiboot kernel first"); + N_("you need to load the kernel first")); if (nounzip) grub_file_filter_disable_compression (); @@ -309,7 +314,7 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)), return err; } module = get_virtual_current_address (ch); - target = (grub_addr_t) get_virtual_current_address (ch); + target = get_physical_target_address (ch); } err = grub_multiboot_add_module (target, size, argc - 1, argv + 1); @@ -322,7 +327,10 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)), if (grub_file_read (file, module, size) != size) { grub_file_close (file); - return grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file"); + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), + argv[0]); + return grub_errno; } grub_file_close (file); diff --git a/grub-core/loader/multiboot_elfxx.c b/grub-core/loader/multiboot_elfxx.c index c6c88f177..3803bf37a 100644 --- a/grub-core/loader/multiboot_elfxx.c +++ b/grub-core/loader/multiboot_elfxx.c @@ -39,6 +39,8 @@ #define CONCAT(a,b) CONCAT_(a, b) #define CONCAT_(a,b) a ## b +#pragma GCC diagnostic ignored "-Wcast-align" + /* Check if BUFFER contains ELF32 (or ELF64). */ static int CONCAT(grub_multiboot_is_elf, XX) (void *buffer) @@ -49,39 +51,40 @@ CONCAT(grub_multiboot_is_elf, XX) (void *buffer) } static grub_err_t -CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, void *buffer) +CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, const char *filename, void *buffer) { Elf_Ehdr *ehdr = (Elf_Ehdr *) buffer; char *phdr_base; int i; - if (ehdr->e_ident[EI_CLASS] != ELFCLASSXX) - return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF class"); - if (ehdr->e_ident[EI_MAG0] != ELFMAG0 || ehdr->e_ident[EI_MAG1] != ELFMAG1 || ehdr->e_ident[EI_MAG2] != ELFMAG2 || ehdr->e_ident[EI_MAG3] != ELFMAG3 - || ehdr->e_version != EV_CURRENT - || ehdr->e_ident[EI_DATA] != ELFDATA2LSB - || ehdr->e_machine != E_MACHINE) - return grub_error(GRUB_ERR_UNKNOWN_OS, "no valid ELF header found"); + || ehdr->e_ident[EI_DATA] != ELFDATA2LSB) + return grub_error(GRUB_ERR_UNKNOWN_OS, N_("invalid arch independent ELF magic")); + + if (ehdr->e_ident[EI_CLASS] != ELFCLASSXX || ehdr->e_machine != E_MACHINE + || ehdr->e_version != EV_CURRENT) + return grub_error (GRUB_ERR_UNKNOWN_OS, N_("invalid arch dependent ELF magic")); if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) - return grub_error (GRUB_ERR_UNKNOWN_OS, "invalid ELF file type"); + return grub_error (GRUB_ERR_UNKNOWN_OS, N_("this ELF file is not of the right type")); /* FIXME: Should we support program headers at strange locations? */ if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > MULTIBOOT_SEARCH) return grub_error (GRUB_ERR_BAD_OS, "program header at a too high offset"); -#if defined (MULTIBOOT_LOAD_ELF64) && defined (__mips) +#ifdef MULTIBOOT_LOAD_ELF64 +# ifdef __mips /* We still in 32-bit mode. */ if (ehdr->e_entry < 0xffffffff80000000ULL) return grub_error (GRUB_ERR_BAD_OS, "invalid entry point for ELF64"); -#else +# else /* We still in 32-bit mode. */ if (ehdr->e_entry > 0xffffffff) return grub_error (GRUB_ERR_BAD_OS, "invalid entry point for ELF64"); +# endif #endif phdr_base = (char *) buffer + ehdr->e_phoff; @@ -115,13 +118,16 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, void *buffer) { if (grub_file_seek (file, (grub_off_t) phdr(i)->p_offset) == (grub_off_t) -1) - return grub_error (GRUB_ERR_BAD_OS, - "invalid offset in program header"); + return grub_errno; if (grub_file_read (file, source, phdr(i)->p_filesz) != (grub_ssize_t) phdr(i)->p_filesz) - return grub_error (GRUB_ERR_BAD_OS, - "couldn't read segment from file"); + { + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), + filename); + return grub_errno; + } } if (phdr(i)->p_filesz < phdr(i)->p_memsz) @@ -159,13 +165,16 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, void *buffer) return grub_errno; if (grub_file_seek (file, ehdr->e_shoff) == (grub_off_t) -1) - return grub_error (GRUB_ERR_BAD_OS, - "invalid offset to section headers"); + return grub_errno; if (grub_file_read (file, shdr, ehdr->e_shnum * ehdr->e_shentsize) != (grub_ssize_t) ehdr->e_shnum * ehdr->e_shentsize) - return grub_error (GRUB_ERR_BAD_OS, - "couldn't read sections headers from file"); + { + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), + filename); + return grub_errno; + } for (shdrptr = shdr, i = 0; i < ehdr->e_shnum; shdrptr += ehdr->e_shentsize, i++) @@ -202,13 +211,16 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, void *buffer) } if (grub_file_seek (file, sh->sh_offset) == (grub_off_t) -1) - return grub_error (GRUB_ERR_BAD_OS, - "invalid offset in section header"); + return grub_errno; if (grub_file_read (file, src, sh->sh_size) != (grub_ssize_t) sh->sh_size) - return grub_error (GRUB_ERR_BAD_OS, - "couldn't read segment from file"); + { + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), + filename); + return grub_errno; + } sh->sh_addr = target; } grub_multiboot_add_elfsyms (ehdr->e_shnum, ehdr->e_shentsize, diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c index 05f581bb6..62510288c 100644 --- a/grub-core/loader/multiboot_mbi2.c +++ b/grub-core/loader/multiboot_mbi2.c @@ -33,6 +33,7 @@ #include #include #include +#include #if defined (GRUB_MACHINE_EFI) #include @@ -76,9 +77,9 @@ grub_multiboot_add_elfsyms (grub_size_t num, grub_size_t entsize, } grub_err_t -grub_multiboot_load (grub_file_t file) +grub_multiboot_load (grub_file_t file, const char *filename) { - char *buffer; + grub_properly_aligned_t *buffer; grub_ssize_t len; struct multiboot_header *header; grub_err_t err; @@ -98,14 +99,16 @@ grub_multiboot_load (grub_file_t file) if (len < 32) { grub_free (buffer); - return grub_error (GRUB_ERR_BAD_OS, "file too small"); + return grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), filename); } + COMPILE_TIME_ASSERT (MULTIBOOT_HEADER_ALIGN % 4 == 0); + /* Look for the multiboot header in the buffer. The header should be at least 12 bytes and aligned on a 4-byte boundary. */ for (header = (struct multiboot_header *) buffer; - ((char *) header <= buffer + len - 12) || (header = 0); - header = (struct multiboot_header *) ((char *) header + MULTIBOOT_HEADER_ALIGN)) + ((char *) header <= (char *) buffer + len - 12) || (header = 0); + header = (struct multiboot_header *) ((grub_uint32_t *) header + MULTIBOOT_HEADER_ALIGN / 4)) { if (header->magic == MULTIBOOT_HEADER_MAGIC && !(header->magic + header->architecture @@ -120,9 +123,11 @@ grub_multiboot_load (grub_file_t file) return grub_error (GRUB_ERR_BAD_ARGUMENT, "no multiboot header found"); } + COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN % 4 == 0); + for (tag = (struct multiboot_header_tag *) (header + 1); tag->type != MULTIBOOT_TAG_TYPE_END; - tag = (struct multiboot_header_tag *) ((char *) tag + tag->size)) + tag = (struct multiboot_header_tag *) ((grub_uint32_t *) tag + ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) / 4)) switch (tag->type) { case MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST: @@ -208,7 +213,7 @@ grub_multiboot_load (grub_file_t file) if (addr_tag) { - int offset = ((char *) header - buffer - + int offset = ((char *) header - (char *) buffer - (addr_tag->header_addr - addr_tag->load_addr)); int load_size = ((addr_tag->load_end_addr == 0) ? file->size - offset : addr_tag->load_end_addr - addr_tag->load_addr); @@ -251,7 +256,7 @@ grub_multiboot_load (grub_file_t file) } else { - err = grub_multiboot_load_elf (file, buffer); + err = grub_multiboot_load_elf (file, filename, buffer); if (err) { grub_free (buffer); @@ -415,7 +420,7 @@ fill_vbe_tag (struct multiboot_tag_vbe *tag) #endif static grub_err_t -retrieve_video_parameters (grub_uint8_t **ptrorig) +retrieve_video_parameters (grub_properly_aligned_t **ptrorig) { grub_err_t err; struct grub_video_mode_info mode_info; @@ -493,7 +498,8 @@ retrieve_video_parameters (grub_uint8_t **ptrorig) tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT; tag->common.size = sizeof (tag->common); tag->common.reserved = 0; - *ptrorig += ALIGN_UP (tag->common.size, MULTIBOOT_TAG_ALIGN); + *ptrorig += ALIGN_UP (tag->common.size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } return GRUB_ERR_NONE; } @@ -508,7 +514,8 @@ retrieve_video_parameters (grub_uint8_t **ptrorig) fill_vbe_tag (tag_vbe); - *ptrorig += ALIGN_UP (tag_vbe->size, MULTIBOOT_TAG_ALIGN); + *ptrorig += ALIGN_UP (tag_vbe->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } #endif @@ -559,7 +566,8 @@ retrieve_video_parameters (grub_uint8_t **ptrorig) tag->common.size = sizeof (struct multiboot_tag_framebuffer_common) + 6; } - *ptrorig += ALIGN_UP (tag->common.size, MULTIBOOT_TAG_ALIGN); + *ptrorig += ALIGN_UP (tag->common.size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); return GRUB_ERR_NONE; } @@ -567,14 +575,16 @@ retrieve_video_parameters (grub_uint8_t **ptrorig) grub_err_t grub_multiboot_make_mbi (grub_uint32_t *target) { - grub_uint8_t *ptrorig; - grub_uint8_t *mbistart; + grub_properly_aligned_t *ptrorig; + grub_properly_aligned_t *mbistart; grub_err_t err; grub_size_t bufsize; grub_relocator_chunk_t ch; bufsize = grub_multiboot_get_mbi_size (); + COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN % sizeof (grub_properly_aligned_t) == 0); + err = grub_relocator_alloc_chunk_align (grub_multiboot_relocator, &ch, 0, 0xffffffff - bufsize, bufsize, MULTIBOOT_TAG_ALIGN, @@ -592,14 +602,19 @@ grub_multiboot_make_mbi (grub_uint32_t *target) #endif mbistart = ptrorig; - ptrorig += 2 * sizeof (grub_uint32_t); + COMPILE_TIME_ASSERT ((2 * sizeof (grub_uint32_t)) + % sizeof (grub_properly_aligned_t) == 0); + COMPILE_TIME_ASSERT (MULTIBOOT_TAG_ALIGN + % sizeof (grub_properly_aligned_t) == 0); + ptrorig += (2 * sizeof (grub_uint32_t)) / sizeof (grub_properly_aligned_t); { struct multiboot_tag_string *tag = (struct multiboot_tag_string *) ptrorig; tag->type = MULTIBOOT_TAG_TYPE_CMDLINE; tag->size = sizeof (struct multiboot_tag_string) + cmdline_size; grub_memcpy (tag->string, cmdline, cmdline_size); - ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } { @@ -607,7 +622,8 @@ grub_multiboot_make_mbi (grub_uint32_t *target) tag->type = MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME; tag->size = sizeof (struct multiboot_tag_string) + sizeof (PACKAGE_STRING); grub_memcpy (tag->string, PACKAGE_STRING, sizeof (PACKAGE_STRING)); - ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } #ifdef GRUB_MACHINE_PCBIOS @@ -630,7 +646,8 @@ grub_multiboot_make_mbi (grub_uint32_t *target) tag->cseg_16_len = info.cseg_16_len; tag->version = info.version; - ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } } #endif @@ -648,14 +665,16 @@ grub_multiboot_make_mbi (grub_uint32_t *target) tag->mod_start = cur->start; tag->mod_end = tag->mod_start + cur->size; grub_memcpy (tag->cmdline, cur->cmdline, cur->cmdline_size); - ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } } { struct multiboot_tag_mmap *tag = (struct multiboot_tag_mmap *) ptrorig; grub_fill_multiboot_mmap (tag); - ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } { @@ -668,7 +687,8 @@ grub_multiboot_make_mbi (grub_uint32_t *target) tag->num = elf_sec_num; tag->entsize = elf_sec_entsize; tag->shndx = elf_sec_shstrndx; - ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } { @@ -680,7 +700,8 @@ grub_multiboot_make_mbi (grub_uint32_t *target) /* Convert from bytes to kilobytes. */ tag->mem_lower = grub_mmap_get_lower () / 1024; tag->mem_upper = grub_mmap_get_upper () / 1024; - ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } if (bootdev_set) @@ -693,7 +714,8 @@ grub_multiboot_make_mbi (grub_uint32_t *target) tag->biosdev = biosdev; tag->slice = slice; tag->part = part; - ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } { @@ -711,7 +733,8 @@ grub_multiboot_make_mbi (grub_uint32_t *target) tag->type = MULTIBOOT_TAG_TYPE_EFI64; tag->size = sizeof (*tag); tag->pointer = (grub_addr_t) grub_efi_system_table; - ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } #endif @@ -721,7 +744,8 @@ grub_multiboot_make_mbi (grub_uint32_t *target) tag->type = MULTIBOOT_TAG_TYPE_EFI32; tag->size = sizeof (*tag); tag->pointer = (grub_addr_t) grub_efi_system_table; - ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } #endif @@ -735,7 +759,8 @@ grub_multiboot_make_mbi (grub_uint32_t *target) tag->type = MULTIBOOT_TAG_TYPE_ACPI_OLD; tag->size = sizeof (*tag) + sizeof (*a); grub_memcpy (tag->rsdp, a, sizeof (*a)); - ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } } @@ -748,7 +773,8 @@ grub_multiboot_make_mbi (grub_uint32_t *target) tag->type = MULTIBOOT_TAG_TYPE_ACPI_NEW; tag->size = sizeof (*tag) + a->length; grub_memcpy (tag->rsdp, a, a->length); - ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } } #endif @@ -757,10 +783,11 @@ grub_multiboot_make_mbi (grub_uint32_t *target) struct multiboot_tag *tag = (struct multiboot_tag *) ptrorig; tag->type = MULTIBOOT_TAG_TYPE_END; tag->size = sizeof (struct multiboot_tag); - ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN) + / sizeof (grub_properly_aligned_t); } - ((grub_uint32_t *) mbistart)[0] = ptrorig - mbistart; + ((grub_uint32_t *) mbistart)[0] = (char *) ptrorig - (char *) mbistart; ((grub_uint32_t *) mbistart)[1] = 0; return GRUB_ERR_NONE; diff --git a/grub-core/loader/powerpc/ieee1275/linux.c b/grub-core/loader/powerpc/ieee1275/linux.c index 12a3fa9f6..4bb0ccb05 100644 --- a/grub-core/loader/powerpc/ieee1275/linux.c +++ b/grub-core/loader/powerpc/ieee1275/linux.c @@ -76,6 +76,7 @@ grub_linux_claimmap_iterate (grub_addr_t target, grub_size_t size, found_addr = target; return 1; } + grub_print_error (); } /* Target below the memory chunk. */ if (target < addr && addr + size <= end) @@ -85,6 +86,7 @@ grub_linux_claimmap_iterate (grub_addr_t target, grub_size_t size, found_addr = addr; return 1; } + grub_print_error (); } return 0; } @@ -149,7 +151,7 @@ grub_linux_unload (void) } static grub_err_t -grub_linux_load32 (grub_elf_t elf) +grub_linux_load32 (grub_elf_t elf, const char *filename) { Elf32_Addr base_addr; grub_addr_t seg_addr; @@ -157,7 +159,7 @@ grub_linux_load32 (grub_elf_t elf) grub_uint32_t offset; Elf32_Addr entry; - linux_size = grub_elf32_size (elf, &base_addr, &align); + linux_size = grub_elf32_size (elf, filename, &base_addr, &align); if (linux_size == 0) return grub_errno; /* Pad it; the kernel scribbles over memory beyond its load address. */ @@ -193,11 +195,11 @@ grub_linux_load32 (grub_elf_t elf) *addr = (phdr->p_paddr - base_addr) + seg_addr; return 0; } - return grub_elf32_load (elf, offset_phdr, 0, 0); + return grub_elf32_load (elf, filename, offset_phdr, 0, 0); } static grub_err_t -grub_linux_load64 (grub_elf_t elf) +grub_linux_load64 (grub_elf_t elf, const char *filename) { Elf64_Addr base_addr; grub_addr_t seg_addr; @@ -205,7 +207,7 @@ grub_linux_load64 (grub_elf_t elf) grub_uint64_t offset; Elf64_Addr entry; - linux_size = grub_elf64_size (elf, &base_addr, &align); + linux_size = grub_elf64_size (elf, filename, &base_addr, &align); if (linux_size == 0) return grub_errno; /* Pad it; the kernel scribbles over memory beyond its load address. */ @@ -239,7 +241,7 @@ grub_linux_load64 (grub_elf_t elf) *addr = (phdr->p_paddr - base_addr) + seg_addr; return 0; } - return grub_elf64_load (elf, offset_phdr, 0, 0); + return grub_elf64_load (elf, filename, offset_phdr, 0, 0); } static grub_err_t @@ -253,7 +255,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), if (argc == 0) { - grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified"); + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); goto out; } @@ -264,7 +266,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), if (elf->ehdr.ehdr32.e_type != ET_EXEC && elf->ehdr.ehdr32.e_type != ET_DYN) { grub_error (GRUB_ERR_UNKNOWN_OS, - "this ELF file is not of the right type"); + N_("this ELF file is not of the right type")); goto out; } @@ -272,13 +274,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), grub_loader_unset (); if (grub_elf_is_elf32 (elf)) - grub_linux_load32 (elf); + grub_linux_load32 (elf, argv[0]); else if (grub_elf_is_elf64 (elf)) - grub_linux_load64 (elf); + grub_linux_load64 (elf, argv[0]); else { - grub_error (GRUB_ERR_BAD_FILE_TYPE, "unknown ELF class"); + grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("invalid arch dependent ELF magic")); goto out; } @@ -317,30 +319,41 @@ static grub_err_t grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) { - grub_file_t file = 0; - grub_ssize_t size; + grub_file_t *files = 0; + grub_size_t size = 0; grub_addr_t first_addr; grub_addr_t addr; + int i; + int nfiles = 0; + grub_uint8_t *ptr; if (argc == 0) { - grub_error (GRUB_ERR_BAD_ARGUMENT, "no initrd specified"); + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); goto fail; } if (!loaded) { - grub_error (GRUB_ERR_BAD_ARGUMENT, "you need to load the kernel first"); + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first")); goto fail; } - grub_file_filter_disable_compression (); - file = grub_file_open (argv[0]); - if (! file) + files = grub_zalloc (argc * sizeof (files[0])); + if (!files) goto fail; + for (i = 0; i < argc; i++) + { + grub_file_filter_disable_compression (); + files[i] = grub_file_open (argv[i]); + if (! files[i]) + goto fail; + nfiles++; + size += grub_file_size (files[i]); + } + first_addr = linux_addr + linux_size; - size = grub_file_size (file); /* Attempt to claim at a series of addresses until successful in the same way that grub_rescue_cmd_linux does. */ @@ -350,19 +363,28 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), grub_dprintf ("loader", "Loading initrd at 0x%x, size 0x%x\n", addr, size); - if (grub_file_read (file, (void *) addr, size) != size) + ptr = (void *) addr; + for (i = 0; i < nfiles; i++) { - grub_ieee1275_release (addr, size); - grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file"); - goto fail; + grub_ssize_t cursize = grub_file_size (files[i]); + if (grub_file_read (files[i], ptr, cursize) != cursize) + { + grub_ieee1275_release (addr, size); + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), + argv[i]); + goto fail; + } + ptr += cursize; } initrd_addr = addr; initrd_size = size; fail: - if (file) - grub_file_close (file); + for (i = 0; i < nfiles; i++) + grub_file_close (files[i]); + grub_free (files); return grub_errno; } diff --git a/grub-core/loader/sparc64/ieee1275/linux.c b/grub-core/loader/sparc64/ieee1275/linux.c index 8ed61f8bf..b321f356f 100644 --- a/grub-core/loader/sparc64/ieee1275/linux.c +++ b/grub-core/loader/sparc64/ieee1275/linux.c @@ -242,7 +242,7 @@ alloc_phys (grub_addr_t size) } static grub_err_t -grub_linux_load64 (grub_elf_t elf) +grub_linux_load64 (grub_elf_t elf, const char *filename) { grub_addr_t off, paddr, base; int ret; @@ -250,7 +250,7 @@ grub_linux_load64 (grub_elf_t elf) linux_entry = elf->ehdr.ehdr64.e_entry; linux_addr = 0x40004000; off = 0x4000; - linux_size = grub_elf64_size (elf, 0, 0); + linux_size = grub_elf64_size (elf, filename, 0, 0); if (linux_size == 0) return grub_errno; @@ -289,7 +289,7 @@ grub_linux_load64 (grub_elf_t elf) *addr = (phdr->p_paddr - base) + (linux_addr - off); return 0; } - return grub_elf64_load (elf, offset_phdr, 0, 0); + return grub_elf64_load (elf, filename, offset_phdr, 0, 0); } static grub_err_t @@ -304,7 +304,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), if (argc == 0) { - grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified"); + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); goto out; } @@ -312,14 +312,14 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), if (!file) goto out; - elf = grub_elf_file (file); + elf = grub_elf_file (file, argv[0]); if (! elf) goto out; if (elf->ehdr.ehdr32.e_type != ET_EXEC) { grub_error (GRUB_ERR_UNKNOWN_OS, - "this ELF file is not of the right type"); + N_("this ELF file is not of the right type")); goto out; } @@ -327,10 +327,10 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), grub_loader_unset (); if (grub_elf_is_elf64 (elf)) - grub_linux_load64 (elf); + grub_linux_load64 (elf, argv[0]); else { - grub_error (GRUB_ERR_BAD_FILE_TYPE, "unknown ELF class"); + grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("invalid arch dependent ELF magic")); goto out; } @@ -371,31 +371,42 @@ static grub_err_t grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) { - grub_file_t file = 0; - grub_ssize_t size; + grub_file_t *files = 0; + grub_size_t size = 0; grub_addr_t paddr; grub_addr_t addr; int ret; + int i; + int nfiles = 0; + grub_uint8_t *ptr; if (argc == 0) { - grub_error (GRUB_ERR_BAD_ARGUMENT, "no initrd specified"); + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); goto fail; } if (!loaded) { - grub_error (GRUB_ERR_BAD_ARGUMENT, "you need to load the kernel first"); + grub_error (GRUB_ERR_BAD_ARGUMENT, N_("you need to load the kernel first")); goto fail; } - grub_file_filter_disable_compression (); - file = grub_file_open (argv[0]); - if (! file) + files = grub_zalloc (argc * sizeof (files[0])); + if (!files) goto fail; + for (i = 0; i < argc; i++) + { + grub_file_filter_disable_compression (); + files[i] = grub_file_open (argv[i]); + if (! files[i]) + goto fail; + nfiles++; + size += grub_file_size (files[i]); + } + addr = 0x60000000; - size = grub_file_size (file); paddr = alloc_phys (size); if (paddr == (grub_addr_t) -1) @@ -415,10 +426,18 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), grub_dprintf ("loader", "Loading initrd at vaddr 0x%lx, paddr 0x%lx, size 0x%lx\n", addr, paddr, size); - if (grub_file_read (file, (void *) addr, size) != size) + ptr = (void *) addr; + for (i = 0; i < nfiles; i++) { - grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file"); - goto fail; + grub_ssize_t cursize = grub_file_size (files[i]); + if (grub_file_read (files[i], ptr, cursize) != cursize) + { + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), + argv[i]); + goto fail; + } + ptr += cursize; } initrd_addr = addr; @@ -426,8 +445,9 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), initrd_size = size; fail: - if (file) - grub_file_close (file); + for (i = 0; i < nfiles; i++) + grub_file_close (files[i]); + grub_free (files); return grub_errno; } diff --git a/grub-core/loader/xnu.c b/grub-core/loader/xnu.c index a98d60c20..bd4400188 100644 --- a/grub-core/loader/xnu.c +++ b/grub-core/loader/xnu.c @@ -50,7 +50,7 @@ grub_size_t grub_xnu_heap_size = 0; struct grub_relocator *grub_xnu_relocator; static grub_err_t -grub_xnu_register_memory (char *prefix, int *suffix, +grub_xnu_register_memory (const char *prefix, int *suffix, grub_addr_t addr, grub_size_t size); grub_err_t grub_xnu_heap_malloc (int size, void **src, grub_addr_t *target) @@ -103,7 +103,8 @@ grub_xnu_free_devtree (struct grub_xnu_devtree_key *cur) /* Compute the size of device tree in xnu format. */ static grub_size_t -grub_xnu_writetree_get_size (struct grub_xnu_devtree_key *start, char *name) +grub_xnu_writetree_get_size (struct grub_xnu_devtree_key *start, + const char *name) { grub_size_t ret; struct grub_xnu_devtree_key *cur; @@ -134,7 +135,8 @@ grub_xnu_writetree_get_size (struct grub_xnu_devtree_key *start, char *name) /* Write devtree in XNU format at curptr assuming the head is named NAME.*/ static void * grub_xnu_writetree_toheap_real (void *curptr, - struct grub_xnu_devtree_key *start, char *name) + struct grub_xnu_devtree_key *start, + const char *name) { struct grub_xnu_devtree_key *cur; int nkeys = 0, nvals = 0; @@ -187,10 +189,13 @@ grub_xnu_writetree_toheap_real (void *curptr, /* And then the keys. Recursively use this function. */ for (cur = start; cur; cur = cur->next) if (cur->datasize == -1) - if (!(curptr = grub_xnu_writetree_toheap_real (curptr, - cur->first_child, - cur->name))) - return 0; + { + curptr = grub_xnu_writetree_toheap_real (curptr, + cur->first_child, + cur->name); + if (!curptr) + return 0; + } return curptr; } @@ -219,17 +224,17 @@ grub_xnu_writetree_toheap (grub_addr_t *target, grub_size_t *size) driverkey = (struct grub_xnu_devtree_key *) grub_malloc (sizeof (*driverkey)); if (! driverkey) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, "can't write device tree"); + return grub_errno; driverkey->name = grub_strdup ("DeviceTree"); if (! driverkey->name) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, "can't write device tree"); + return grub_errno; driverkey->datasize = sizeof (*extdesc); driverkey->next = memorymap->first_child; memorymap->first_child = driverkey; driverkey->data = extdesc = (struct grub_xnu_extdesc *) grub_malloc (sizeof (*extdesc)); if (! driverkey->data) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, "can't write device tree"); + return grub_errno; /* Allocate the space based on the size with dummy value. */ *size = grub_xnu_writetree_get_size (grub_xnu_devtree_root, "/"); @@ -249,7 +254,7 @@ grub_xnu_writetree_toheap (grub_addr_t *target, grub_size_t *size) /* Find a key or value in parent key. */ struct grub_xnu_devtree_key * -grub_xnu_find_key (struct grub_xnu_devtree_key *parent, char *name) +grub_xnu_find_key (struct grub_xnu_devtree_key *parent, const char *name) { struct grub_xnu_devtree_key *cur; for (cur = parent; cur; cur = cur->next) @@ -259,7 +264,7 @@ grub_xnu_find_key (struct grub_xnu_devtree_key *parent, char *name) } struct grub_xnu_devtree_key * -grub_xnu_create_key (struct grub_xnu_devtree_key **parent, char *name) +grub_xnu_create_key (struct grub_xnu_devtree_key **parent, const char *name) { struct grub_xnu_devtree_key *ret; ret = grub_xnu_find_key (*parent, name); @@ -267,15 +272,11 @@ grub_xnu_create_key (struct grub_xnu_devtree_key **parent, char *name) return ret; ret = (struct grub_xnu_devtree_key *) grub_zalloc (sizeof (*ret)); if (! ret) - { - grub_error (GRUB_ERR_OUT_OF_MEMORY, "can't create key %s", name); - return 0; - } + return 0; ret->name = grub_strdup (name); if (! ret->name) { grub_free (ret); - grub_error (GRUB_ERR_OUT_OF_MEMORY, "can't create key %s", name); return 0; } ret->datasize = -1; @@ -285,7 +286,7 @@ grub_xnu_create_key (struct grub_xnu_devtree_key **parent, char *name) } struct grub_xnu_devtree_key * -grub_xnu_create_value (struct grub_xnu_devtree_key **parent, char *name) +grub_xnu_create_value (struct grub_xnu_devtree_key **parent, const char *name) { struct grub_xnu_devtree_key *ret; ret = grub_xnu_find_key (*parent, name); @@ -301,15 +302,11 @@ grub_xnu_create_value (struct grub_xnu_devtree_key **parent, char *name) } ret = (struct grub_xnu_devtree_key *) grub_zalloc (sizeof (*ret)); if (! ret) - { - grub_error (GRUB_ERR_OUT_OF_MEMORY, "can't create value %s", name); - return 0; - } + return 0; ret->name = grub_strdup (name); if (! ret->name) { grub_free (ret); - grub_error (GRUB_ERR_OUT_OF_MEMORY, "can't create value %s", name); return 0; } ret->next = *parent; @@ -349,7 +346,7 @@ grub_cmd_xnu_kernel (grub_command_t cmd __attribute__ ((unused)), grub_addr_t loadaddr_target; if (argc < 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); grub_xnu_unload (); @@ -389,7 +386,7 @@ grub_cmd_xnu_kernel (grub_command_t cmd __attribute__ ((unused)), } /* Load kernel. */ - err = grub_macho_load32 (macho, (char *) loadaddr - startcode, + err = grub_macho_load32 (macho, args[0], (char *) loadaddr - startcode, GRUB_MACHO_NOBSS); if (err) { @@ -459,7 +456,7 @@ grub_cmd_xnu_kernel64 (grub_command_t cmd __attribute__ ((unused)), grub_addr_t loadaddr_target; if (argc < 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); grub_xnu_unload (); @@ -502,7 +499,7 @@ grub_cmd_xnu_kernel64 (grub_command_t cmd __attribute__ ((unused)), } /* Load kernel. */ - err = grub_macho_load64 (macho, (char *) loadaddr - startcode, + err = grub_macho_load64 (macho, args[0], (char *) loadaddr - startcode, GRUB_MACHO_NOBSS); if (err) { @@ -562,7 +559,7 @@ grub_cmd_xnu_kernel64 (grub_command_t cmd __attribute__ ((unused)), /* Register a memory in a memory map under name PREFIXSUFFIX and increment SUFFIX. */ static grub_err_t -grub_xnu_register_memory (char *prefix, int *suffix, +grub_xnu_register_memory (const char *prefix, int *suffix, grub_addr_t addr, grub_size_t size) { struct grub_xnu_devtree_key *chosen; @@ -571,7 +568,7 @@ grub_xnu_register_memory (char *prefix, int *suffix, struct grub_xnu_extdesc *extdesc; if (! grub_xnu_heap_size) - return grub_error (GRUB_ERR_BAD_OS, "no xnu kernel loaded"); + return grub_error (GRUB_ERR_BAD_OS, N_("you need to load the kernel first")); chosen = grub_xnu_create_key (&grub_xnu_devtree_root, "chosen"); if (! chosen) @@ -582,24 +579,27 @@ grub_xnu_register_memory (char *prefix, int *suffix, driverkey = (struct grub_xnu_devtree_key *) grub_malloc (sizeof (*driverkey)); if (! driverkey) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, "can't register memory"); + return grub_errno; if (suffix) - { - driverkey->name = grub_xasprintf ("%s%d", prefix, (*suffix)++); - if (!driverkey->name) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, "can't register memory"); - } + driverkey->name = grub_xasprintf ("%s%d", prefix, (*suffix)++); else driverkey->name = grub_strdup (prefix); - if (! driverkey->name) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, "can't register extension"); + if (!driverkey->name) + { + grub_free (driverkey); + return grub_errno; + } driverkey->datasize = sizeof (*extdesc); driverkey->next = memorymap->first_child; - memorymap->first_child = driverkey; driverkey->data = extdesc = (struct grub_xnu_extdesc *) grub_malloc (sizeof (*extdesc)); if (! driverkey->data) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, "can't register extension"); + { + grub_free (driverkey->name); + grub_free (driverkey); + return grub_errno; + } + memorymap->first_child = driverkey; extdesc->addr = addr; extdesc->size = (grub_uint32_t) size; return GRUB_ERR_NONE; @@ -635,7 +635,8 @@ get_name_ptr (char *name) /* Load .kext. */ static grub_err_t -grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile) +grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile, + const char *filename) { grub_macho_t macho; grub_err_t err; @@ -660,12 +661,12 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile) neededspace += namelen + 1; if (! grub_xnu_heap_size) - return grub_error (GRUB_ERR_BAD_OS, "no xnu kernel loaded"); + return grub_error (GRUB_ERR_BAD_OS, N_("you need to load the kernel first")); /* Compute the needed space. */ if (binaryfile) { - macho = grub_macho_file (binaryfile); + macho = grub_macho_file (binaryfile, filename); if (! macho || ! grub_macho_contains_macho32 (macho)) { if (macho) @@ -714,9 +715,9 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile) exthead->binaryaddr = buf_target + (buf - (grub_uint8_t *) buf0); exthead->binarysize = machosize; if (grub_xnu_is_64bit) - err = grub_macho_readfile64 (macho, buf); + err = grub_macho_readfile64 (macho, filename, buf); else - err = grub_macho_readfile32 (macho, buf); + err = grub_macho_readfile32 (macho, filename, buf); if (err) { grub_macho_close (macho); @@ -736,9 +737,10 @@ grub_xnu_load_driver (char *infoplistname, grub_file_t binaryfile) != (grub_ssize_t) (infoplistsize)) { grub_file_close (infoplist); - grub_error_push (); - return grub_error (GRUB_ERR_BAD_OS, "couldn't read file %s: ", - infoplistname); + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), + infoplistname); + return grub_errno; } grub_file_close (infoplist); buf[infoplistsize] = 0; @@ -773,15 +775,14 @@ grub_cmd_xnu_mkext (grub_command_t cmd __attribute__ ((unused)), int narchs, i; if (argc != 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); if (! grub_xnu_heap_size) - return grub_error (GRUB_ERR_BAD_OS, "no xnu kernel loaded"); + return grub_error (GRUB_ERR_BAD_OS, N_("you need to load the kernel first")); file = grub_file_open (args[0]); if (! file) - return grub_error (GRUB_ERR_FILE_NOT_FOUND, - "couldn't load driver package"); + return grub_errno; /* Sometimes caches are fat binary. Errgh. */ if (grub_file_read (file, &head, sizeof (head)) @@ -790,8 +791,9 @@ grub_cmd_xnu_mkext (grub_command_t cmd __attribute__ ((unused)), /* I don't know the internal structure of package but can hardly imagine a valid package shorter than 20 bytes. */ grub_file_close (file); - grub_error_push (); - return grub_error (GRUB_ERR_BAD_OS, "couldn't read file %s", args[0]); + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), args[0]); + return grub_errno; } /* Find the corresponding architecture. */ @@ -802,9 +804,7 @@ grub_cmd_xnu_mkext (grub_command_t cmd __attribute__ ((unused)), if (! archs) { grub_file_close (file); - grub_error_push (); - return grub_error (GRUB_ERR_OUT_OF_MEMORY, - "couldn't read file %s", args[0]); + return grub_errno; } if (grub_file_read (file, archs, @@ -812,8 +812,10 @@ grub_cmd_xnu_mkext (grub_command_t cmd __attribute__ ((unused)), != (grub_ssize_t) sizeof(struct grub_macho_fat_arch) * narchs) { grub_free (archs); - grub_error_push (); - return grub_error (GRUB_ERR_READ_ERROR, "cannot read fat header"); + if (!grub_errno) + grub_error (GRUB_ERR_READ_ERROR, N_("premature end of file %s"), + args[0]); + return grub_errno; } for (i = 0; i < narchs; i++) { @@ -865,8 +867,9 @@ grub_cmd_xnu_mkext (grub_command_t cmd __attribute__ ((unused)), if (grub_file_read (file, loadto, readlen) != (grub_ssize_t) (readlen)) { grub_file_close (file); - grub_error_push (); - return grub_error (GRUB_ERR_BAD_OS, "couldn't read file %s", args[0]); + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), args[0]); + return grub_errno; } grub_file_close (file); @@ -886,15 +889,14 @@ grub_cmd_xnu_ramdisk (grub_command_t cmd __attribute__ ((unused)), grub_size_t size; if (argc != 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); if (! grub_xnu_heap_size) - return grub_error (GRUB_ERR_BAD_OS, "no xnu kernel loaded"); + return grub_error (GRUB_ERR_BAD_OS, N_("you need to load the kernel first")); file = grub_file_open (args[0]); if (! file) - return grub_error (GRUB_ERR_FILE_NOT_FOUND, - "couldn't load ramdisk"); + return grub_errno; err = grub_xnu_align_heap (GRUB_XNU_PAGESIZE); if (err) @@ -905,12 +907,12 @@ grub_cmd_xnu_ramdisk (grub_command_t cmd __attribute__ ((unused)), err = grub_xnu_heap_malloc (size, &loadto, &loadto_target); if (err) return err; - if (grub_file_read (file, loadto, size) - != (grub_ssize_t) (size)) + if (grub_file_read (file, loadto, size) != (grub_ssize_t) (size)) { grub_file_close (file); - grub_error_push (); - return grub_error (GRUB_ERR_BAD_OS, "couldn't read file %s", args[0]); + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), args[0]); + return grub_errno; } return grub_xnu_register_memory ("RAMDisk", 0, loadto_target, size); } @@ -918,7 +920,8 @@ grub_cmd_xnu_ramdisk (grub_command_t cmd __attribute__ ((unused)), /* Returns true if the kext should be loaded according to plist and osbundlereq. Also fill BINNAME. */ static int -grub_xnu_check_os_bundle_required (char *plistname, char *osbundlereq, +grub_xnu_check_os_bundle_required (char *plistname, + const char *osbundlereq, char **binname) { grub_file_t file; @@ -933,27 +936,20 @@ grub_xnu_check_os_bundle_required (char *plistname, char *osbundlereq, file = grub_file_open (plistname); if (! file) - { - grub_file_close (file); - grub_error_push (); - grub_error (GRUB_ERR_BAD_OS, "couldn't read file %s", plistname); - return 0; - } + return 0; size = grub_file_size (file); buf = grub_malloc (size); if (! buf) { grub_file_close (file); - grub_error_push (); - grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't read file %s", plistname); return 0; } if (grub_file_read (file, buf, size) != (grub_ssize_t) (size)) { grub_file_close (file); - grub_error_push (); - grub_error (GRUB_ERR_BAD_OS, "couldn't read file %s", plistname); + if (!grub_errno) + grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"), plistname); return 0; } grub_file_close (file); @@ -1033,7 +1029,7 @@ grub_xnu_check_os_bundle_required (char *plistname, char *osbundlereq, /* Load all loadable kexts placed under DIRNAME and matching OSBUNDLEREQUIRED */ grub_err_t -grub_xnu_scan_dir_for_kexts (char *dirname, char *osbundlerequired, +grub_xnu_scan_dir_for_kexts (char *dirname, const char *osbundlerequired, int maxrecursion) { grub_device_t dev; @@ -1075,7 +1071,7 @@ grub_xnu_scan_dir_for_kexts (char *dirname, char *osbundlerequired, } if (! grub_xnu_heap_size) - return grub_error (GRUB_ERR_BAD_OS, "no xnu kernel loaded"); + return grub_error (GRUB_ERR_BAD_OS, N_("you need to load the kernel first")); device_name = grub_file_get_device_name (dirname); dev = grub_device_open (device_name); @@ -1099,7 +1095,7 @@ grub_xnu_scan_dir_for_kexts (char *dirname, char *osbundlerequired, /* Load extension DIRNAME. (extensions are directories in xnu) */ grub_err_t -grub_xnu_load_kext_from_dir (char *dirname, char *osbundlerequired, +grub_xnu_load_kext_from_dir (char *dirname, const char *osbundlerequired, int maxrecursion) { grub_device_t dev; @@ -1147,7 +1143,7 @@ grub_xnu_load_kext_from_dir (char *dirname, char *osbundlerequired, newdirname = grub_malloc (grub_strlen (dirname) + 20); if (! newdirname) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't allocate buffer"); + return grub_errno; grub_strcpy (newdirname, dirname); newdirname[grub_strlen (dirname)] = '/'; newdirname[grub_strlen (dirname) + 1] = 0; @@ -1193,14 +1189,15 @@ grub_xnu_load_kext_from_dir (char *dirname, char *osbundlerequired, grub_errno = GRUB_ERR_NONE; /* Load the extension. */ - grub_xnu_load_driver (plistname, binfile); + grub_xnu_load_driver (plistname, binfile, + binname); grub_free (binname); grub_free (binsuffix); } else { grub_dprintf ("xnu", "%s:0\n", plistname); - grub_xnu_load_driver (plistname, 0); + grub_xnu_load_driver (plistname, 0, 0); } } grub_free (plistname); @@ -1223,7 +1220,7 @@ grub_cmd_xnu_kext (grub_command_t cmd __attribute__ ((unused)), grub_file_t binfile = 0; if (! grub_xnu_heap_size) - return grub_error (GRUB_ERR_BAD_OS, "no xnu kernel loaded"); + return grub_error (GRUB_ERR_BAD_OS, N_("you need to load the kernel first")); if (argc == 2) { @@ -1232,20 +1229,17 @@ grub_cmd_xnu_kext (grub_command_t cmd __attribute__ ((unused)), { binfile = grub_file_open (args[1]); if (! binfile) - { - grub_error (GRUB_ERR_BAD_OS, "can't open file"); - return GRUB_ERR_NONE; - } + return grub_errno; } return grub_xnu_load_driver (grub_strcmp (args[0], "-") ? args[0] : 0, - binfile); + binfile, args[1]); } /* load kext normally. */ if (argc == 1) return grub_xnu_load_kext_from_dir (args[0], 0, 10); - return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); } /* Load a directory containing kexts. */ @@ -1257,7 +1251,7 @@ grub_cmd_xnu_kextdir (grub_command_t cmd __attribute__ ((unused)), return grub_error (GRUB_ERR_BAD_ARGUMENT, "directory name required"); if (! grub_xnu_heap_size) - return grub_error (GRUB_ERR_BAD_OS, "no xnu kernel loaded"); + return grub_error (GRUB_ERR_BAD_OS, N_("you need to load the kernel first")); if (argc == 1) return grub_xnu_scan_dir_for_kexts (args[0], @@ -1268,8 +1262,7 @@ grub_cmd_xnu_kextdir (grub_command_t cmd __attribute__ ((unused)), char *osbundlerequired = grub_strdup (args[1]), *ptr; grub_err_t err; if (! osbundlerequired) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, - "couldn't allocate string temporary space"); + return grub_errno; for (ptr = osbundlerequired; *ptr; ptr++) *ptr = grub_tolower (*ptr); err = grub_xnu_scan_dir_for_kexts (args[0], osbundlerequired, 10); @@ -1387,7 +1380,7 @@ grub_xnu_bitmap_mode_t grub_xnu_bitmap_mode; static const struct grub_arg_option xnu_splash_cmd_options[] = { - {"mode", 'm', 0, "Background image mode.", "stretch|normal", + {"mode", 'm', 0, N_("Background image mode."), N_("stretch|normal"), ARG_TYPE_STRING}, {0, 0, 0, 0, 0, 0} }; @@ -1398,10 +1391,10 @@ grub_cmd_xnu_splash (grub_extcmd_context_t ctxt, { grub_err_t err; if (argc != 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); if (! grub_xnu_heap_size) - return grub_error (GRUB_ERR_BAD_OS, "no xnu kernel loaded"); + return grub_error (GRUB_ERR_BAD_OS, N_("you need to load the kernel first")); if (ctxt->state[XNU_SPLASH_CMD_ARGINDEX_MODE].set && grub_strcmp (ctxt->state[XNU_SPLASH_CMD_ARGINDEX_MODE].arg, @@ -1424,7 +1417,7 @@ grub_cmd_xnu_resume (grub_command_t cmd __attribute__ ((unused)), int argc, char *args[]) { if (argc != 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); return grub_xnu_resume (args[0]); } @@ -1461,11 +1454,16 @@ GRUB_MOD_INIT(xnu) cmd_kext = grub_register_command ("xnu_kext", grub_cmd_xnu_kext, 0, N_("Load XNU extension.")); cmd_kextdir = grub_register_command ("xnu_kextdir", grub_cmd_xnu_kextdir, + /* TRANSLATORS: OSBundleRequired is a + variable name in xnu extensions + manifests. It behaves mostly like + GNU/Linux runlevels. + */ N_("DIRECTORY [OSBundleRequired]"), N_("Load XNU extension directory.")); cmd_ramdisk = grub_register_command ("xnu_ramdisk", grub_cmd_xnu_ramdisk, 0, - "Load XNU ramdisk. " - "It will be seen as md0."); + N_("Load XNU ramdisk. " + "It will be available in OS as md0.")); cmd_splash = grub_register_extcmd ("xnu_splash", grub_cmd_xnu_splash, 0, 0, N_("Load a splash image for XNU."), @@ -1473,7 +1471,8 @@ GRUB_MOD_INIT(xnu) #ifndef GRUB_MACHINE_EMU cmd_resume = grub_register_command ("xnu_resume", grub_cmd_xnu_resume, - 0, N_("Load XNU hibernate image.")); + 0, N_("Load an image of hibernated" + " XNU image.")); #endif grub_cpu_xnu_init (); diff --git a/grub-core/loader/xnu_resume.c b/grub-core/loader/xnu_resume.c index 8f0e24483..d7f9adaaf 100644 --- a/grub-core/loader/xnu_resume.c +++ b/grub-core/loader/xnu_resume.c @@ -25,6 +25,7 @@ #include #include #include +#include static void *grub_xnu_hibernate_image; @@ -59,11 +60,13 @@ grub_xnu_resume (char *imagename) /* Read the header. */ if (grub_file_read (file, &hibhead, sizeof (hibhead)) - !=sizeof (hibhead)) + != sizeof (hibhead)) { grub_file_close (file); - return grub_error (GRUB_ERR_READ_ERROR, - "cannot read the hibernate header"); + if (!grub_errno) + grub_error (GRUB_ERR_READ_ERROR, + N_("premature end of file %s"), imagename); + return grub_errno; } /* Check the header. */ @@ -138,7 +141,10 @@ grub_xnu_resume (char *imagename) != (grub_ssize_t) codesize) { grub_file_close (file); - return grub_error (GRUB_ERR_READ_ERROR, "cannot read resume image"); + if (!grub_errno) + grub_error (GRUB_ERR_READ_ERROR, + N_("premature end of file %s"), imagename); + return grub_errno; } /* Read image. */ @@ -147,7 +153,10 @@ grub_xnu_resume (char *imagename) != (grub_ssize_t) hibhead.image_size) { grub_file_close (file); - return grub_error (GRUB_ERR_READ_ERROR, "cannot read resume image"); + if (!grub_errno) + grub_error (GRUB_ERR_READ_ERROR, + N_("premature end of file %s"), imagename); + return grub_errno; } grub_file_close (file); diff --git a/grub-core/mmap/efi/mmap.c b/grub-core/mmap/efi/mmap.c index 8e5cce0d0..773559753 100644 --- a/grub-core/mmap/efi/mmap.c +++ b/grub-core/mmap/efi/mmap.c @@ -212,7 +212,7 @@ grub_mmap_unregister (int handle) return GRUB_ERR_NONE; } } - return grub_error (GRUB_ERR_BAD_ARGUMENT, "handle %d not found", handle); + return grub_error (GRUB_ERR_BUG, "handle %d not found", handle); } /* Result is always page-aligned. */ @@ -272,7 +272,7 @@ grub_mmap_malign_and_register (grub_uint64_t align __attribute__ ((unused)), overlays = curover; *handle = curover->handle; - return UINT_TO_PTR (curover->address); + return (void *) (grub_addr_t) curover->address; } void diff --git a/grub-core/mmap/i386/mmap.c b/grub-core/mmap/i386/mmap.c index e9c030b7b..648a7df4b 100644 --- a/grub-core/mmap/i386/mmap.c +++ b/grub-core/mmap/i386/mmap.c @@ -54,7 +54,7 @@ grub_mmap_malign_and_register (grub_uint64_t align, grub_uint64_t size, { /* FIXME: use low-memory mm allocation once it's available. */ grub_mmap_iterate (find_hook); - ret = UINT_TO_PTR (highestlow); + ret = (void *) (grub_addr_t) highestlow; } else ret = grub_memalign (align, size); @@ -65,7 +65,7 @@ grub_mmap_malign_and_register (grub_uint64_t align, grub_uint64_t size, return 0; } - *handle = grub_mmap_register (PTR_TO_UINT64 (ret), size, type); + *handle = grub_mmap_register ((grub_addr_t) ret, size, type); if (! *handle) { grub_free (ret); @@ -93,7 +93,7 @@ grub_mmap_free_and_unregister (int handle) grub_mmap_unregister (handle); if (addr >= 0x100000) - grub_free (UINT_TO_PTR (addr)); + grub_free ((void *) (grub_addr_t) addr); } #endif diff --git a/grub-core/mmap/i386/pc/mmap.c b/grub-core/mmap/i386/pc/mmap.c index 8dec083f8..7f170b65d 100644 --- a/grub-core/mmap/i386/pc/mmap.c +++ b/grub-core/mmap/i386/pc/mmap.c @@ -101,8 +101,8 @@ preboot (int noreturn __attribute__ ((unused))) grub_memcpy (hooktarget, &grub_machine_mmaphook_start, &grub_machine_mmaphook_end - &grub_machine_mmaphook_start); - *((grub_uint16_t *) 0x4a) = PTR_TO_UINT32 (hooktarget) >> 4; - *((grub_uint16_t *) 0x56) = PTR_TO_UINT32 (hooktarget) >> 4; + *((grub_uint16_t *) 0x4a) = ((grub_addr_t) hooktarget) >> 4; + *((grub_uint16_t *) 0x56) = ((grub_addr_t) hooktarget) >> 4; *((grub_uint16_t *) 0x48) = &grub_machine_mmaphook_int12 - &grub_machine_mmaphook_start; *((grub_uint16_t *) 0x54) = &grub_machine_mmaphook_int15 @@ -191,7 +191,7 @@ grub_machine_mmap_register (grub_uint64_t start __attribute__ ((unused)), int handle __attribute__ ((unused))) { grub_err_t err; - static void *preb_handle = 0; + static struct grub_preboot *preb_handle = 0; err = malloc_hook (); if (err) diff --git a/grub-core/mmap/mmap.c b/grub-core/mmap/mmap.c index 07a71336b..0b734dde3 100644 --- a/grub-core/mmap/mmap.c +++ b/grub-core/mmap/mmap.c @@ -139,10 +139,7 @@ grub_mmap_iterate (grub_memory_hook_t hook) grub_malloc (sizeof (struct grub_mmap_scan) * 2 * mmap_num); if (! scanline_events) - { - return grub_error (GRUB_ERR_OUT_OF_MEMORY, - "couldn't allocate space for new memory map"); - } + return grub_errno; i = 0; #ifndef GRUB_MMAP_REGISTER_BY_FIRMWARE @@ -237,11 +234,7 @@ grub_mmap_register (grub_uint64_t start, grub_uint64_t size, int type) cur = (struct grub_mmap_region *) grub_malloc (sizeof (struct grub_mmap_region)); if (! cur) - { - grub_error (GRUB_ERR_OUT_OF_MEMORY, - "couldn't allocate memory map overlay"); - return 0; - } + return 0; cur->next = grub_mmap_overlays; cur->start = start; @@ -265,11 +258,12 @@ grub_mmap_unregister (int handle) { struct grub_mmap_region *cur, *prev; - for (cur = grub_mmap_overlays, prev = 0; cur; prev= cur, cur = cur->next) + for (cur = grub_mmap_overlays, prev = 0; cur; prev = cur, cur = cur->next) if (handle == cur->handle) { grub_err_t err; - if ((err = grub_machine_mmap_unregister (handle))) + err = grub_machine_mmap_unregister (handle); + if (err) return err; if (prev) @@ -279,7 +273,7 @@ grub_mmap_unregister (int handle) grub_free (cur); return GRUB_ERR_NONE; } - return grub_error (GRUB_ERR_BAD_ARGUMENT, "mmap overlay not found"); + return grub_error (GRUB_ERR_BUG, "mmap overlay not found"); } #endif /* ! GRUB_MMAP_REGISTER_BY_FIRMWARE */ @@ -367,7 +361,7 @@ grub_cmd_badram (grub_command_t cmd __attribute__ ((unused)), } if (argc != 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "badram string required"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); grub_dprintf ("badram", "executing badram\n"); @@ -449,7 +443,7 @@ grub_cmd_cutmem (grub_command_t cmd __attribute__ ((unused)), } if (argc != 2) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "argements required"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected")); from = parsemem (args[0]); if (grub_errno) @@ -471,7 +465,7 @@ GRUB_MOD_INIT(mmap) { cmd = grub_register_command ("badram", grub_cmd_badram, N_("ADDR1,MASK1[,ADDR2,MASK2[,...]]"), - N_("Declare memory regions as badram.")); + N_("Declare memory regions as faulty (badram).")); cmd_cut = grub_register_command ("cutmem", grub_cmd_cutmem, N_("FROM[K|M|G] TO[K|M|G]"), N_("Remove any memory regions in specified range.")); diff --git a/grub-core/net/arp.c b/grub-core/net/arp.c index d726f2c3a..3db852e74 100644 --- a/grub-core/net/arp.c +++ b/grub-core/net/arp.c @@ -1,3 +1,21 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + #include #include #include @@ -6,82 +24,74 @@ #include #include -static struct arp_entry arp_table[10]; -static grub_int8_t new_table_entry = -1; +/* ARP header operation codes */ +enum + { + ARP_REQUEST = 1, + ARP_REPLY = 2 + }; -static void -arp_init_table (void) -{ - grub_memset (arp_table, 0, sizeof (arp_table)); - new_table_entry = 0; -} +enum + { + /* IANA ARP constant to define hardware type as ethernet. */ + GRUB_NET_ARPHRD_ETHERNET = 1 + }; + +struct arphdr { + grub_uint16_t hrd; + grub_uint16_t pro; + grub_uint8_t hln; + grub_uint8_t pln; + grub_uint16_t op; +} __attribute__ ((packed)); -static struct arp_entry * -arp_find_entry (const grub_net_network_level_address_t *proto) -{ - unsigned i; - for (i = 0; i < ARRAY_SIZE (arp_table); i++) - { - if (arp_table[i].avail == 1 && - arp_table[i].nl_address.ipv4 == proto->ipv4) - return &(arp_table[i]); - } - return NULL; -} grub_err_t -grub_net_arp_resolve (struct grub_net_network_level_interface *inf, - const grub_net_network_level_address_t *proto_addr, - grub_net_link_level_address_t *hw_addr) +grub_net_arp_send_request (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *proto_addr) { - struct arp_entry *entry; struct grub_net_buff nb; struct arphdr *arp_header; grub_net_link_level_address_t target_hw_addr; - char *aux, arp_data[128]; + grub_uint8_t *aux, arp_data[128]; grub_err_t err; int i; + grub_size_t addrlen; + grub_uint16_t etherpro; + grub_uint8_t *nbd; - if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 - && proto_addr->ipv4 == 0xffffffff) + if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) { - hw_addr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; - grub_memset (hw_addr->mac, -1, 6); - return GRUB_ERR_NONE; + addrlen = 4; + etherpro = GRUB_NET_ETHERTYPE_IP; } + else + return grub_error (GRUB_ERR_BUG, "unsupported address family"); - /* Check cache table. */ - entry = arp_find_entry (proto_addr); - if (entry) - { - *hw_addr = entry->ll_address; - return GRUB_ERR_NONE; - } /* Build a request packet. */ nb.head = arp_data; nb.end = arp_data + sizeof (arp_data); grub_netbuff_clear (&nb); grub_netbuff_reserve (&nb, 128); - err = grub_netbuff_push (&nb, sizeof (*arp_header) + 2 * (6 + 4)); + err = grub_netbuff_push (&nb, sizeof (*arp_header) + 2 * (6 + addrlen)); if (err) return err; arp_header = (struct arphdr *) nb.data; arp_header->hrd = grub_cpu_to_be16 (GRUB_NET_ARPHRD_ETHERNET); - arp_header->pro = grub_cpu_to_be16 (GRUB_NET_ETHERTYPE_IP); - /* FIXME Add support to ipv6 address. */ arp_header->hln = 6; - arp_header->pln = 4; + arp_header->pro = grub_cpu_to_be16 (etherpro); + arp_header->pln = addrlen; arp_header->op = grub_cpu_to_be16 (ARP_REQUEST); - aux = (char *) arp_header + sizeof (*arp_header); + aux = (grub_uint8_t *) arp_header + sizeof (*arp_header); /* Sender hardware address. */ grub_memcpy (aux, &inf->hwaddress.mac, 6); aux += 6; /* Sender protocol address */ grub_memcpy (aux, &inf->address.ipv4, 4); - aux += 4; + aux += addrlen; /* Target hardware address */ for (i = 0; i < 6; i++) aux[i] = 0x00; @@ -90,77 +100,78 @@ grub_net_arp_resolve (struct grub_net_network_level_interface *inf, grub_memcpy (aux, &proto_addr->ipv4, 4); grub_memset (&target_hw_addr.mac, 0xff, 6); + nbd = nb.data; send_ethernet_packet (inf, &nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP); - for (i = 0; i < 3; i++) + for (i = 0; i < GRUB_NET_TRIES; i++) { - entry = arp_find_entry (proto_addr); - if (entry) - { - grub_memcpy (hw_addr, &entry->ll_address, sizeof (*hw_addr)); - return GRUB_ERR_NONE; - } - grub_net_poll_cards (200); + if (grub_net_link_layer_resolve_check (inf, proto_addr)) + return GRUB_ERR_NONE; + grub_net_poll_cards (GRUB_NET_INTERVAL); + if (grub_net_link_layer_resolve_check (inf, proto_addr)) + return GRUB_ERR_NONE; + nb.data = nbd; + send_ethernet_packet (inf, &nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP); } - return grub_error (GRUB_ERR_TIMEOUT, "timeout: could not resolve hardware address"); + return GRUB_ERR_NONE; } grub_err_t -grub_net_arp_receive (struct grub_net_buff *nb) +grub_net_arp_receive (struct grub_net_buff *nb, + struct grub_net_card *card) { struct arphdr *arp_header = (struct arphdr *) nb->data; - struct arp_entry *entry; - grub_uint8_t *sender_hardware_address, *sender_protocol_address; - grub_uint8_t *target_hardware_address, *target_protocol_address; - grub_net_network_level_address_t hwaddress; + grub_uint8_t *sender_hardware_address; + grub_uint8_t *target_hardware_address; + grub_net_network_level_address_t sender_addr, target_addr; + grub_net_link_level_address_t sender_hw_addr; struct grub_net_network_level_interface *inf; + grub_uint8_t *sender_protocol_address, *target_protocol_address; sender_hardware_address = (grub_uint8_t *) arp_header + sizeof (*arp_header); sender_protocol_address = sender_hardware_address + arp_header->hln; target_hardware_address = sender_protocol_address + arp_header->pln; target_protocol_address = target_hardware_address + arp_header->hln; - grub_memcpy (&hwaddress.ipv4, sender_protocol_address, 4); - - /* Check if the sender is in the cache table. */ - entry = arp_find_entry (&hwaddress); - /* Update sender hardware address. */ - if (entry) - grub_memcpy (entry->ll_address.mac, sender_hardware_address, 6); - else + if (grub_be_to_cpu16 (arp_header->pro) == GRUB_NET_ETHERTYPE_IP + && arp_header->pln == 4) { - /* Add sender to cache table. */ - if (new_table_entry == -1) - arp_init_table (); - entry = &(arp_table[new_table_entry]); - entry->avail = 1; - grub_memcpy (&entry->nl_address.ipv4, sender_protocol_address, 4); - grub_memcpy (entry->ll_address.mac, sender_hardware_address, 6); - new_table_entry++; - if (new_table_entry == ARRAY_SIZE (arp_table)) - new_table_entry = 0; + sender_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + target_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + grub_memcpy (&sender_addr.ipv4, sender_protocol_address, 4); + grub_memcpy (&target_addr.ipv4, target_protocol_address, 4); } + else + return GRUB_ERR_NONE; + + sender_hw_addr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + grub_memcpy (sender_hw_addr.mac, sender_hardware_address, + sizeof (sender_hw_addr.mac)); + grub_net_link_layer_add_address (card, &sender_addr, &sender_hw_addr, 1); FOR_NET_NETWORK_LEVEL_INTERFACES (inf) { /* Am I the protocol address target? */ - if (inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 - && grub_memcmp (target_protocol_address, &inf->address.ipv4, 4) == 0 + if (grub_net_addr_cmp (&inf->address, &target_addr) == 0 && grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST) { - grub_net_link_level_address_t aux; - /* Swap hardware fields */ - grub_memcpy (target_hardware_address, sender_hardware_address, - arp_header->hln); + grub_net_link_level_address_t target; + /* We've already checked that pln is either 4 or 16. */ + char tmp[arp_header->pln]; + + target.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + grub_memcpy (target.mac, sender_hardware_address, 6); + grub_memcpy (target_hardware_address, target.mac, 6); grub_memcpy (sender_hardware_address, inf->hwaddress.mac, 6); - grub_memcpy (aux.mac, sender_protocol_address, 6); + + grub_memcpy (tmp, sender_protocol_address, arp_header->pln); grub_memcpy (sender_protocol_address, target_protocol_address, arp_header->pln); - grub_memcpy (target_protocol_address, aux.mac, arp_header->pln); + grub_memcpy (target_protocol_address, tmp, arp_header->pln); + /* Change operation to REPLY and send packet */ arp_header->op = grub_be_to_cpu16 (ARP_REPLY); - grub_memcpy (aux.mac, target_hardware_address, 6); - send_ethernet_packet (inf, nb, aux, GRUB_NET_ETHERTYPE_ARP); + send_ethernet_packet (inf, nb, target, GRUB_NET_ETHERTYPE_ARP); } } return GRUB_ERR_NONE; diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c index ba6a29020..f1ac86a82 100644 --- a/grub-core/net/bootp.c +++ b/grub-core/net/bootp.c @@ -68,30 +68,59 @@ parse_dhcp_vendor (const char *name, void *vend, int limit) tagtype = *ptr++; /* Pad tag. */ - if (tagtype == 0) + if (tagtype == GRUB_NET_BOOTP_PAD) continue; /* End tag. */ - if (tagtype == 0xff) + if (tagtype == GRUB_NET_BOOTP_END) return; taglength = *ptr++; switch (tagtype) { - case 12: + case GRUB_NET_BOOTP_ROUTER: + if (taglength == 4) + { + grub_net_network_level_netaddress_t target; + grub_net_network_level_address_t gw; + char rname[grub_strlen (name) + sizeof (":default")]; + + target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + target.ipv4.base = 0; + target.ipv4.masksize = 0; + gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + grub_memcpy (&gw.ipv4, ptr, sizeof (gw.ipv4)); + grub_snprintf (rname, sizeof (rname), "%s:default", name); + grub_net_add_route_gw (rname, target, gw); + } + break; + case GRUB_NET_BOOTP_DNS: + { + int i; + for (i = 0; i < taglength / 4; i++) + { + struct grub_net_network_level_address s; + s.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + s.ipv4 = grub_get_unaligned32 (ptr); + grub_net_add_dns_server (&s); + ptr += 4; + } + } + break; + case GRUB_NET_BOOTP_HOSTNAME: set_env_limn_ro (name, "hostname", (char *) ptr, taglength); break; - case 15: + case GRUB_NET_BOOTP_DOMAIN: set_env_limn_ro (name, "domain", (char *) ptr, taglength); break; - case 17: + case GRUB_NET_BOOTP_ROOT_PATH: set_env_limn_ro (name, "rootpath", (char *) ptr, taglength); break; - case 18: + case GRUB_NET_BOOTP_EXTENSIONS_PATH: set_env_limn_ro (name, "extensionspath", (char *) ptr, taglength); break; @@ -130,27 +159,29 @@ grub_net_configure_by_dhcp_ack (const char *name, : sizeof (hwaddr.mac)); hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; - inter = grub_net_add_addr (name, card, addr, hwaddr, flags); - { - grub_net_network_level_netaddress_t target; - grub_net_network_level_address_t gw; - char rname[grub_strlen (name) + sizeof ("_gw")]; + inter = grub_net_add_addr (name, card, &addr, &hwaddr, flags); + if (bp->gateway_ip) + { + grub_net_network_level_netaddress_t target; + grub_net_network_level_address_t gw; + char rname[grub_strlen (name) + sizeof (":gw")]; - target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - target.ipv4.base = bp->server_ip; - target.ipv4.masksize = 32; - gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - gw.ipv4 = bp->gateway_ip; - grub_snprintf (rname, sizeof (rname), "%s_gw", name); - grub_net_add_route_gw (rname, target, gw); - } - { - grub_net_network_level_netaddress_t target; - target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; - target.ipv4.base = bp->gateway_ip; - target.ipv4.masksize = 32; - grub_net_add_route (name, target, inter); - } + target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + target.ipv4.base = bp->server_ip; + target.ipv4.masksize = 32; + gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + gw.ipv4 = bp->gateway_ip; + grub_snprintf (rname, sizeof (rname), "%s:gw", name); + grub_net_add_route_gw (rname, target, gw); + } + if (bp->gateway_ip || bp->server_ip) + { + grub_net_network_level_netaddress_t target; + target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + target.ipv4.base = bp->gateway_ip ? bp->gateway_ip : bp->server_ip; + target.ipv4.masksize = 32; + grub_net_add_route (name, target, inter); + } if (size > OFFSET_OF (boot_file, bp)) set_env_limn_ro (name, "boot_file", (char *) bp->boot_file, @@ -271,7 +302,8 @@ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)), grub_uint8_t taglength; if (argc < 4) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "4 arguments expected"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("four arguments expected")); FOR_NET_NETWORK_LEVEL_INTERFACES (inter) if (grub_strcmp (inter->name, args[1]) == 0) @@ -279,7 +311,7 @@ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)), if (!inter) return grub_error (GRUB_ERR_BAD_ARGUMENT, - N_("unrecognised interface %s"), args[1]); + N_("unrecognised network interface `%s'"), args[1]); if (!inter->dhcp_ack) return grub_error (GRUB_ERR_IO, N_("no DHCP info found")); @@ -374,9 +406,11 @@ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)), } return grub_error (GRUB_ERR_BAD_ARGUMENT, - "unrecognised format specification %s", args[3]); + N_("unrecognised DHCP option format specification `%s'"), + args[3]); } +/* FIXME: allow to specify mac address. */ static grub_err_t grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), int argc, char **args) @@ -439,6 +473,7 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), struct grub_net_buff *nb; struct udphdr *udph; grub_net_network_level_address_t target; + grub_net_link_level_address_t ll_target; if (!ifaces[j].prev) continue; @@ -473,7 +508,7 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), t = 0; } pack->ident = grub_cpu_to_be32 (t); - pack->seconds = 0;//grub_cpu_to_be16 (t); + pack->seconds = grub_cpu_to_be16 (t); grub_memcpy (&pack->mac_addr, &ifaces[j].hwaddress.mac, 6); @@ -484,11 +519,18 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), udph->dst = grub_cpu_to_be16 (67); udph->chksum = 0; udph->len = grub_cpu_to_be16 (nb->tail - nb->data); - target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; target.ipv4 = 0xffffffff; + err = grub_net_link_layer_resolve (&ifaces[j], &target, &ll_target); + if (err) + return err; - err = grub_net_send_ip_packet (&ifaces[j], &target, nb); + udph->chksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_UDP, + &ifaces[j].address, + &target); + + err = grub_net_send_ip_packet (&ifaces[j], &target, &ll_target, nb, + GRUB_NET_IP_UDP); grub_netbuff_free (nb); if (err) return err; @@ -506,7 +548,8 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), continue; grub_error_push (); grub_net_network_level_interface_unregister (&ifaces[j]); - err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "couldn't configure %s", + err = grub_error (GRUB_ERR_FILE_NOT_FOUND, + N_("couldn't autoconfigure %s"), ifaces[j].card->name); } @@ -514,7 +557,7 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)), return err; } -static grub_command_t cmd_dhcp, cmd_getdhcp, cmd_bootp; +static grub_command_t cmd_getdhcp, cmd_bootp; void grub_bootp_init (void) @@ -522,9 +565,6 @@ grub_bootp_init (void) cmd_bootp = grub_register_command ("net_bootp", grub_cmd_bootp, N_("[CARD]"), N_("perform a bootp autoconfiguration")); - cmd_dhcp = grub_register_command ("net_dhcp", grub_cmd_bootp, - N_("[CARD]"), - N_("perform a bootp autoconfiguration")); cmd_getdhcp = grub_register_command ("net_get_dhcp_option", grub_cmd_dhcpopt, N_("VAR INTERFACE NUMBER DESCRIPTION"), N_("retrieve DHCP option and save it into VAR. If VAR is - then print the value.")); @@ -534,6 +574,5 @@ void grub_bootp_fini (void) { grub_unregister_command (cmd_getdhcp); - grub_unregister_command (cmd_dhcp); grub_unregister_command (cmd_bootp); } diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c new file mode 100644 index 000000000..ee3029e0b --- /dev/null +++ b/grub-core/net/dns.c @@ -0,0 +1,698 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +struct dns_cache_element +{ + char *name; + grub_size_t naddresses; + struct grub_net_network_level_address *addresses; + grub_uint64_t limit_time; +}; + +#define DNS_CACHE_SIZE 1021 +#define DNS_HASH_BASE 423 + +static struct dns_cache_element dns_cache[DNS_CACHE_SIZE]; +static struct grub_net_network_level_address *dns_servers; +static grub_size_t dns_nservers, dns_servers_alloc; + +grub_err_t +grub_net_add_dns_server (const struct grub_net_network_level_address *s) +{ + if (dns_servers_alloc <= dns_nservers) + { + int na = dns_servers_alloc * 2; + struct grub_net_network_level_address *ns; + if (na < 8) + na = 8; + ns = grub_malloc (na * sizeof (ns[0])); + if (!ns) + return grub_errno; + dns_servers_alloc = na; + dns_servers = ns; + } + dns_servers[dns_nservers++] = *s; + return GRUB_ERR_NONE; +} + +void +grub_net_remove_dns_server (const struct grub_net_network_level_address *s) +{ + grub_size_t i; + for (i = 0; i < dns_nservers; i++) + if (grub_net_addr_cmp (s, &dns_servers[i]) == 0) + break; + if (i < dns_nservers) + { + dns_servers[i] = dns_servers[dns_nservers - 1]; + dns_nservers--; + } +} + +struct dns_header +{ + grub_uint16_t id; + grub_uint8_t flags; + grub_uint8_t ra_z_r_code; + grub_uint16_t qdcount; + grub_uint16_t ancount; + grub_uint16_t nscount; + grub_uint16_t arcount; +} __attribute__ ((packed)); + +enum + { + FLAGS_RESPONSE = 0x80, + FLAGS_OPCODE = 0x78, + FLAGS_RD = 0x01 + }; + +enum + { + ERRCODE_MASK = 0x0f + }; + +enum + { + DNS_PORT = 53 + }; + +struct recv_data +{ + grub_size_t *naddresses; + struct grub_net_network_level_address **addresses; + int cache; + grub_uint16_t id; + int dns_err; + char *name; + const char *oname; +}; + +static inline int +hash (const char *str) +{ + int v = 0, xn = 1; + const char *ptr; + for (ptr = str; *ptr; ) + { + v = (v + xn * *ptr); + xn = (DNS_HASH_BASE * xn) % DNS_CACHE_SIZE; + ptr++; + if (((ptr - str) & 0x3ff) == 0) + v %= DNS_CACHE_SIZE; + } + return v % DNS_CACHE_SIZE; +} + +static int +check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head, + const grub_uint8_t *tail, const char *check_with, + int *length, char *set) +{ + const char *readable_ptr = check_with; + const grub_uint8_t *ptr; + char *optr = set; + int bytes_processed = 0; + if (length) + *length = 0; + for (ptr = name_at; ptr < tail && bytes_processed < tail - head + 2; ) + { + /* End marker. */ + if (!*ptr) + { + if (length && *length) + (*length)--; + if (optr && optr != set) + optr--; + if (optr) + *optr = 0; + return !readable_ptr || (*readable_ptr == 0); + } + if (*ptr & 0xc0) + { + bytes_processed += 2; + if (ptr + 1 >= tail) + return 0; + ptr = head + (((ptr[0] & 0x3f) << 8) | ptr[1]); + continue; + } + if (readable_ptr && grub_memcmp (ptr + 1, readable_ptr, *ptr) != 0) + return 0; + if (grub_memchr (ptr + 1, 0, *ptr) + || grub_memchr (ptr + 1, '.', *ptr)) + return 0; + if (readable_ptr) + readable_ptr += *ptr; + if (readable_ptr && *readable_ptr != '.' && *readable_ptr != 0) + return 0; + bytes_processed += *ptr + 1; + if (length) + *length += *ptr + 1; + if (optr) + { + grub_memcpy (optr, ptr + 1, *ptr); + optr += *ptr; + } + if (optr) + *optr++ = '.'; + if (readable_ptr && *readable_ptr) + readable_ptr++; + ptr += *ptr + 1; + } + return 0; +} + +static int +check_name (const grub_uint8_t *name_at, const grub_uint8_t *head, + const grub_uint8_t *tail, const char *check_with) +{ + return check_name_real (name_at, head, tail, check_with, NULL, NULL); +} + +static char * +get_name (const grub_uint8_t *name_at, const grub_uint8_t *head, + const grub_uint8_t *tail) +{ + int length; + char *ret; + + if (!check_name_real (name_at, head, tail, NULL, &length, NULL)) + return NULL; + ret = grub_malloc (length + 1); + if (!ret) + return NULL; + if (!check_name_real (name_at, head, tail, NULL, NULL, ret)) + { + grub_free (ret); + return NULL; + } + return ret; +} + +enum + { + DNS_CLASS_A = 1, + DNS_CLASS_CNAME = 5, + DNS_CLASS_AAAA = 28 + }; + +static grub_err_t +recv_hook (grub_net_udp_socket_t sock __attribute__ ((unused)), + struct grub_net_buff *nb, + void *data_) +{ + struct dns_header *head; + struct recv_data *data = data_; + int i, j; + grub_uint8_t *ptr, *reparse_ptr; + int redirect_cnt = 0; + char *redirect_save = NULL; + grub_uint32_t ttl_all = ~0U; + + head = (struct dns_header *) nb->data; + ptr = (grub_uint8_t *) (head + 1); + if (ptr >= nb->tail) + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + + if (head->id != data->id) + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + if (!(head->flags & FLAGS_RESPONSE) || (head->flags & FLAGS_OPCODE)) + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + if (head->ra_z_r_code & ERRCODE_MASK) + { + data->dns_err = 1; + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + for (i = 0; i < grub_cpu_to_be16 (head->qdcount); i++) + { + if (ptr >= nb->tail) + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + while (ptr < nb->tail && !((*ptr & 0xc0) || *ptr == 0)) + ptr += *ptr + 1; + if (ptr < nb->tail && (*ptr & 0xc0)) + ptr++; + ptr++; + ptr += 4; + } + *data->addresses = grub_malloc (sizeof ((*data->addresses)[0]) + * grub_cpu_to_be16 (head->ancount)); + if (!*data->addresses) + { + grub_errno = GRUB_ERR_NONE; + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + reparse_ptr = ptr; + reparse: + for (i = 0, ptr = reparse_ptr; i < grub_cpu_to_be16 (head->ancount); i++) + { + int ignored = 0; + grub_uint8_t class; + grub_uint32_t ttl = 0; + grub_uint16_t length; + if (ptr >= nb->tail) + { + if (!*data->naddresses) + grub_free (*data->addresses); + return GRUB_ERR_NONE; + } + ignored = !check_name (ptr, nb->data, nb->tail, data->name); + while (ptr < nb->tail && !((*ptr & 0xc0) || *ptr == 0)) + ptr += *ptr + 1; + if (ptr < nb->tail && (*ptr & 0xc0)) + ptr++; + ptr++; + if (ptr + 10 >= nb->tail) + { + if (!*data->naddresses) + grub_free (*data->addresses); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + if (*ptr++ != 0) + ignored = 1; + class = *ptr++; + if (*ptr++ != 0) + ignored = 1; + if (*ptr++ != 1) + ignored = 1; + for (j = 0; j < 4; j++) + { + ttl <<= 8; + ttl |= *ptr++; + } + length = *ptr++ << 8; + length |= *ptr++; + if (ptr + length > nb->tail) + { + if (!*data->naddresses) + grub_free (*data->addresses); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + if (!ignored) + { + if (ttl_all > ttl) + ttl_all = ttl; + switch (class) + { + case DNS_CLASS_A: + if (length != 4) + break; + (*data->addresses)[*data->naddresses].type + = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + grub_memcpy (&(*data->addresses)[*data->naddresses].ipv4, + ptr, 4); + (*data->naddresses)++; + break; + case DNS_CLASS_AAAA: + if (length != 16) + break; + (*data->addresses)[*data->naddresses].type + = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; + grub_memcpy (&(*data->addresses)[*data->naddresses].ipv6, + ptr, 16); + (*data->naddresses)++; + break; + case DNS_CLASS_CNAME: + if (!(redirect_cnt & (redirect_cnt - 1))) + { + grub_free (redirect_save); + redirect_save = data->name; + } + else + grub_free (data->name); + redirect_cnt++; + data->name = get_name (ptr, nb->data, nb->tail); + if (!data->name) + { + data->dns_err = 1; + grub_errno = 0; + return GRUB_ERR_NONE; + } + grub_dprintf ("dns", "CNAME %s\n", data->name); + if (grub_strcmp (redirect_save, data->name) == 0) + { + data->dns_err = 1; + grub_free (redirect_save); + return GRUB_ERR_NONE; + } + goto reparse; + } + } + ptr += length; + } + if (ttl_all && *data->naddresses && data->cache) + { + int h; + grub_dprintf ("dns", "caching for %d seconds\n", ttl_all); + h = hash (data->oname); + grub_free (dns_cache[h].name); + dns_cache[h].name = 0; + grub_free (dns_cache[h].addresses); + dns_cache[h].addresses = 0; + dns_cache[h].name = grub_strdup (data->oname); + dns_cache[h].naddresses = *data->naddresses; + dns_cache[h].addresses = grub_malloc (*data->naddresses + * sizeof (dns_cache[h].addresses[0])); + dns_cache[h].limit_time = grub_get_time_ms () + 1000 * ttl_all; + if (!dns_cache[h].addresses || !dns_cache[h].name) + { + grub_free (dns_cache[h].name); + dns_cache[h].name = 0; + grub_free (dns_cache[h].addresses); + dns_cache[h].addresses = 0; + } + grub_memcpy (dns_cache[h].addresses, *data->addresses, + *data->naddresses + * sizeof (dns_cache[h].addresses[0])); + } + grub_netbuff_free (nb); + grub_free (redirect_save); + return GRUB_ERR_NONE; +} + +grub_err_t +grub_net_dns_lookup (const char *name, + const struct grub_net_network_level_address *servers, + grub_size_t n_servers, + grub_size_t *naddresses, + struct grub_net_network_level_address **addresses, + int cache) +{ + grub_size_t send_servers = 0; + grub_size_t i, j; + struct grub_net_buff *nb; + grub_net_udp_socket_t sockets[n_servers]; + grub_uint8_t *optr; + const char *iptr; + struct dns_header *head; + static grub_uint16_t id = 1; + grub_err_t err = GRUB_ERR_NONE; + struct recv_data data = {naddresses, addresses, cache, + grub_cpu_to_be16 (id++), 0, 0, name}; + grub_uint8_t *nbd; + int have_server = 0; + + if (!servers) + { + servers = dns_servers; + n_servers = dns_nservers; + } + + if (!n_servers) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("no DNS servers configured")); + + *naddresses = 0; + if (cache) + { + int h; + h = hash (name); + if (dns_cache[h].name && grub_strcmp (dns_cache[h].name, name) == 0 + && grub_get_time_ms () < dns_cache[h].limit_time) + { + grub_dprintf ("dns", "retrieved from cache\n"); + *addresses = grub_malloc (dns_cache[h].naddresses + * sizeof ((*addresses)[0])); + if (!*addresses) + return grub_errno; + *naddresses = dns_cache[h].naddresses; + grub_memcpy (*addresses, dns_cache[h].addresses, + dns_cache[h].naddresses + * sizeof ((*addresses)[0])); + return GRUB_ERR_NONE; + } + } + + data.name = grub_strdup (name); + if (!data.name) + return grub_errno; + + nb = grub_netbuff_alloc (GRUB_NET_OUR_MAX_IP_HEADER_SIZE + + GRUB_NET_MAX_LINK_HEADER_SIZE + + GRUB_NET_UDP_HEADER_SIZE + + sizeof (struct dns_header) + + grub_strlen (name) + 2 + 4 + + 2 + 4); + if (!nb) + { + grub_free (data.name); + return grub_errno; + } + grub_netbuff_reserve (nb, GRUB_NET_OUR_MAX_IP_HEADER_SIZE + + GRUB_NET_MAX_LINK_HEADER_SIZE + + GRUB_NET_UDP_HEADER_SIZE); + grub_netbuff_put (nb, sizeof (struct dns_header) + + grub_strlen (name) + 2 + 4 + 2 + 4); + head = (struct dns_header *) nb->data; + optr = (grub_uint8_t *) (head + 1); + for (iptr = name; *iptr; ) + { + const char *dot; + dot = grub_strchr (iptr, '.'); + if (!dot) + dot = iptr + grub_strlen (iptr); + if ((dot - iptr) >= 64) + { + grub_free (data.name); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("domain name component is too long")); + } + *optr = (dot - iptr); + optr++; + grub_memcpy (optr, iptr, dot - iptr); + optr += dot - iptr; + iptr = dot; + if (*iptr) + iptr++; + } + *optr++ = 0; + + /* Type: A. */ + *optr++ = 0; + *optr++ = 1; + + /* Class. */ + *optr++ = 0; + *optr++ = 1; + + /* Compressed name. */ + *optr++ = 0xc0; + *optr++ = 0x0c; + /* Type: AAAA. */ + *optr++ = 0; + *optr++ = 28; + + /* Class. */ + *optr++ = 0; + *optr++ = 1; + + head->id = data.id; + head->flags = FLAGS_RD; + head->ra_z_r_code = 0; + head->qdcount = grub_cpu_to_be16_compile_time (2); + head->ancount = grub_cpu_to_be16_compile_time (0); + head->nscount = grub_cpu_to_be16_compile_time (0); + head->arcount = grub_cpu_to_be16_compile_time (0); + + nbd = nb->data; + + for (i = 0; i < n_servers * 4; i++) + { + /* Connect to a next server. */ + while (!(i & 1) && send_servers < n_servers) + { + sockets[send_servers] = grub_net_udp_open (servers[send_servers], + DNS_PORT, + recv_hook, + &data); + send_servers++; + if (!sockets[send_servers - 1]) + { + err = grub_errno; + grub_errno = GRUB_ERR_NONE; + } + else + { + have_server = 1; + break; + } + } + if (!have_server) + goto out; + if (*data.naddresses) + goto out; + for (j = 0; j < send_servers; j++) + { + grub_err_t err2; + if (!sockets[j]) + continue; + nb->data = nbd; + err2 = grub_net_send_udp_packet (sockets[j], nb); + if (err2) + { + grub_errno = GRUB_ERR_NONE; + err = err2; + } + if (*data.naddresses) + goto out; + } + grub_net_poll_cards (200); + } + out: + grub_free (data.name); + grub_netbuff_free (nb); + for (j = 0; j < send_servers; j++) + grub_net_udp_close (sockets[j]); + + if (*data.naddresses) + return GRUB_ERR_NONE; + if (data.dns_err) + return grub_error (GRUB_ERR_NET_NO_DOMAIN, + N_("no DNS record found")); + + if (err) + { + grub_errno = err; + return err; + } + return grub_error (GRUB_ERR_TIMEOUT, + N_("no DNS reply received")); +} + +static grub_err_t +grub_cmd_nslookup (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + grub_err_t err; + struct grub_net_network_level_address server; + grub_size_t naddresses, i; + struct grub_net_network_level_address *addresses; + if (argc != 2) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected")); + err = grub_net_resolve_address (args[1], &server); + if (err) + return err; + + err = grub_net_dns_lookup (args[0], &server, 1, &naddresses, &addresses, 0); + if (err) + return err; + for (i = 0; i < naddresses; i++) + { + char buf[GRUB_NET_MAX_STR_ADDR_LEN]; + grub_net_addr_to_str (&addresses[i], buf); + grub_printf ("%s\n", buf); + } + grub_free (addresses); + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_list_dns (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + grub_size_t i; + for (i = 0; i < dns_nservers; i++) + { + char buf[GRUB_NET_MAX_STR_ADDR_LEN]; + grub_net_addr_to_str (&dns_servers[i], buf); + grub_printf ("%s\n", buf); + } + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_add_dns (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + grub_err_t err; + struct grub_net_network_level_address server; + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); + err = grub_net_resolve_address (args[0], &server); + if (err) + return err; + + return grub_net_add_dns_server (&server); +} + +static grub_err_t +grub_cmd_del_dns (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + grub_err_t err; + struct grub_net_network_level_address server; + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); + err = grub_net_resolve_address (args[1], &server); + if (err) + return err; + + return grub_net_add_dns_server (&server); +} + +static grub_command_t cmd, cmd_add, cmd_del, cmd_list; + +void +grub_dns_init (void) +{ + cmd = grub_register_command ("net_nslookup", grub_cmd_nslookup, + N_("ADDRESS DNSSERVER"), + N_("Perform a DNS lookup")); + cmd_add = grub_register_command ("net_add_dns", grub_cmd_add_dns, + N_("DNSSERVER"), + N_("Add a DNS server")); + cmd_del = grub_register_command ("net_del_dns", grub_cmd_del_dns, + N_("DNSSERVER"), + N_("Remove a DNS server")); + cmd_list = grub_register_command ("net_ls_dns", grub_cmd_list_dns, + NULL, N_("List DNS servers")); +} + +void +grub_dns_fini (void) +{ + grub_unregister_command (cmd); + grub_unregister_command (cmd_add); + grub_unregister_command (cmd_del); + grub_unregister_command (cmd_list); +} diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c index 5c6aac608..14ab1bc2c 100644 --- a/grub-core/net/drivers/efi/efinet.c +++ b/grub-core/net/drivers/efi/efinet.c @@ -22,6 +22,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -35,50 +36,83 @@ send_card_buffer (const struct grub_net_card *dev, { grub_efi_status_t st; grub_efi_simple_network_t *net = dev->efi_net; + grub_uint64_t limit_time = grub_get_time_ms () + 4000; st = efi_call_7 (net->transmit, net, 0, (pack->tail - pack->data), pack->data, NULL, NULL, NULL); if (st != GRUB_EFI_SUCCESS) - return grub_error (GRUB_ERR_IO, "Couldn't send network packet."); - return GRUB_ERR_NONE; + return grub_error (GRUB_ERR_IO, N_("couldn't send network packet")); + while (1) + { + void *txbuf = NULL; + st = efi_call_3 (net->get_status, net, 0, &txbuf); + if (st != GRUB_EFI_SUCCESS) + return grub_error (GRUB_ERR_IO, N_("couldn't send network packet")); + if (txbuf) + return GRUB_ERR_NONE; + if (limit_time < grub_get_time_ms ()) + return grub_error (GRUB_ERR_TIMEOUT, N_("couldn't send network packet")); + } } -static grub_ssize_t -get_card_packet (const struct grub_net_card *dev, - struct grub_net_buff *nb) +static struct grub_net_buff * +get_card_packet (const struct grub_net_card *dev) { grub_efi_simple_network_t *net = dev->efi_net; grub_err_t err; grub_efi_status_t st; - grub_efi_uintn_t bufsize = 1500; + grub_efi_uintn_t bufsize = 1536; + struct grub_net_buff *nb; - err = grub_netbuff_clear (nb); - if (err) - return -1; + nb = grub_netbuff_alloc (bufsize); + if (!nb) + return NULL; - err = grub_netbuff_put (nb, 1500); - if (err) - return -1; + /* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible + by 4. So that IP header is aligned on 4 bytes. */ + grub_netbuff_reserve (nb, 2); + if (!nb) + { + grub_netbuff_free (nb); + return NULL; + } st = efi_call_7 (net->receive, net, NULL, &bufsize, nb->data, NULL, NULL, NULL); if (st == GRUB_EFI_BUFFER_TOO_SMALL) { - err = grub_netbuff_put (nb, bufsize - 1500); - if (err) - return -1; + grub_netbuff_free (nb); + + bufsize = ALIGN_UP (bufsize, 32); + + nb = grub_netbuff_alloc (bufsize); + if (!nb) + return NULL; + + /* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible + by 4. So that IP header is aligned on 4 bytes. */ + grub_netbuff_reserve (nb, 2); + if (!nb) + { + grub_netbuff_free (nb); + return NULL; + } + st = efi_call_7 (net->receive, net, NULL, &bufsize, nb->data, NULL, NULL, NULL); } if (st != GRUB_EFI_SUCCESS) { - grub_netbuff_clear (nb); - return -1; + grub_netbuff_free (nb); + return NULL; } - err = grub_netbuff_unput (nb, (nb->tail - nb->data) - bufsize); + err = grub_netbuff_put (nb, bufsize); if (err) - return -1; + { + grub_netbuff_free (nb); + return NULL; + } - return bufsize; + return nb; } static struct grub_net_card_driver efidriver = @@ -136,6 +170,7 @@ grub_efinet_findcards (void) card->driver = &efidriver; card->flags = 0; card->default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + card->mtu = net->mode->max_packet_size; grub_memcpy (card->default_address.mac, net->mode->current_address, sizeof (card->default_address.mac)); diff --git a/grub-core/net/drivers/emu/emunet.c b/grub-core/net/drivers/emu/emunet.c index d1e49a2f4..245b8780a 100644 --- a/grub-core/net/drivers/emu/emunet.c +++ b/grub-core/net/drivers/emu/emunet.c @@ -1,3 +1,20 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ #include #include @@ -10,6 +27,9 @@ #include #include #include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); static int fd; @@ -21,24 +41,39 @@ send_card_buffer (const struct grub_net_card *dev __attribute__ ((unused)), actual = write (fd, pack->data, pack->tail - pack->data); if (actual < 0) - return grub_error (GRUB_ERR_IO, "couldn't send packets"); + return grub_error (GRUB_ERR_IO, N_("couldn't send network packet")); return GRUB_ERR_NONE; } -static grub_ssize_t -get_card_packet (const struct grub_net_card *dev __attribute__ ((unused)), - struct grub_net_buff *pack) +static struct grub_net_buff * +get_card_packet (const struct grub_net_card *dev __attribute__ ((unused))) { ssize_t actual; + struct grub_net_buff *nb; - grub_netbuff_clear (pack); - actual = read (fd, pack->data, 1500); + nb = grub_netbuff_alloc (1536); + if (!nb) + return NULL; + + /* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible + by 4. So that IP header is aligned on 4 bytes. */ + grub_netbuff_reserve (nb, 2); + if (!nb) + { + grub_netbuff_free (nb); + return NULL; + } + + actual = read (fd, nb->data, 1536); if (actual < 0) - return -1; - grub_netbuff_put (pack, actual); + { + grub_netbuff_free (nb); + return NULL; + } + grub_netbuff_put (nb, actual); - return actual; + return nb; } static struct grub_net_card_driver emudriver = @@ -52,6 +87,7 @@ static struct grub_net_card emucard = { .name = "emu0", .driver = &emudriver, + .mtu = 1500, .default_address = { .type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET, {.mac = {0, 1, 2, 3, 4, 5}} diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c index cd598ea72..9895de472 100644 --- a/grub-core/net/drivers/i386/pc/pxe.c +++ b/grub-core/net/drivers/i386/pc/pxe.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -164,14 +165,13 @@ grub_pxe_scan (void) return bangpxe; } -static grub_ssize_t -grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)), - struct grub_net_buff *buf) +static struct grub_net_buff * +grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused))) { struct grub_pxe_undi_isr *isr; static int in_progress = 0; - char *ptr, *end; - int len; + grub_uint8_t *ptr, *end; + struct grub_net_buff *buf; isr = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; @@ -180,10 +180,14 @@ grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)), grub_memset (isr, 0, sizeof (*isr)); isr->func_flag = GRUB_PXE_ISR_IN_START; grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry); - if (isr->status || isr->func_flag != GRUB_PXE_ISR_OUT_OURS) + /* Normally according to the specification we should also check + that isr->func_flag != GRUB_PXE_ISR_OUT_OURS but unfortunately it + breaks on intel cards. + */ + if (isr->status) { in_progress = 0; - return -1; + return NULL; } grub_memset (isr, 0, sizeof (*isr)); isr->func_flag = GRUB_PXE_ISR_IN_PROCESS; @@ -201,17 +205,27 @@ grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)), if (isr->status || isr->func_flag == GRUB_PXE_ISR_OUT_DONE) { in_progress = 0; - return -1; + return NULL; } grub_memset (isr, 0, sizeof (*isr)); isr->func_flag = GRUB_PXE_ISR_IN_GET_NEXT; grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry); } - grub_netbuff_put (buf, isr->frame_len); + buf = grub_netbuff_alloc (isr->frame_len); + if (!buf) + return NULL; + /* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible + by 4. So that IP header is aligned on 4 bytes. */ + grub_netbuff_reserve (buf, 2); + if (!buf) + { + grub_netbuff_free (buf); + return NULL; + } ptr = buf->data; end = ptr + isr->frame_len; - len = isr->frame_len; + grub_netbuff_put (buf, isr->frame_len); grub_memcpy (ptr, LINEAR (isr->buffer), isr->buffer_len); ptr += isr->buffer_len; while (ptr < end) @@ -222,7 +236,8 @@ grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)), if (isr->status || isr->func_flag != GRUB_PXE_ISR_OUT_RECEIVE) { in_progress = 1; - return -1; + grub_netbuff_free (buf); + return NULL; } grub_memcpy (ptr, LINEAR (isr->buffer), isr->buffer_len); @@ -230,7 +245,7 @@ grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)), } in_progress = 1; - return len; + return buf; } static grub_err_t @@ -255,8 +270,7 @@ grub_pxe_send (const struct grub_net_card *dev __attribute__ ((unused)), grub_pxe_call (GRUB_PXENV_UNDI_TRANSMIT, trans, pxe_rm_entry); if (trans->status) - return grub_error (GRUB_ERR_IO, "PXE send failed (status 0x%x)", - trans->status); + return grub_error (GRUB_ERR_IO, N_("couldn't send network packet")); return 0; } @@ -297,20 +311,29 @@ struct grub_net_card grub_pxe_card = .name = "pxe" }; -static void -grub_pc_net_config_real (char **device, char **path) +void * +grub_pxe_get_cached (grub_uint16_t type) { - struct grub_net_bootp_packet *bp; struct grub_pxenv_get_cached_info ci; - ci.packet_type = GRUB_PXENV_PACKET_TYPE_DHCP_ACK; + ci.packet_type = type; ci.buffer = 0; ci.buffer_size = 0; grub_pxe_call (GRUB_PXENV_GET_CACHED_INFO, &ci, pxe_rm_entry); if (ci.status) + return 0; + + return LINEAR (ci.buffer); +} + +static void +grub_pc_net_config_real (char **device, char **path) +{ + struct grub_net_bootp_packet *bp; + + bp = grub_pxe_get_cached (GRUB_PXENV_PACKET_TYPE_DHCP_ACK); + + if (!bp) return; - - bp = LINEAR (ci.buffer); - grub_net_configure_by_dhcp_ack ("pxe", &grub_pxe_card, 0, bp, GRUB_PXE_BOOTP_SIZE, 1, device, path); @@ -345,6 +368,7 @@ GRUB_MOD_INIT(pxe) if (i == sizeof (grub_pxe_card.default_address.mac)) grub_memcpy (grub_pxe_card.default_address.mac, ui->permanent_addr, sizeof (grub_pxe_card.default_address.mac)); + grub_pxe_card.mtu = ui->mtu; grub_pxe_card.default_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index 20d45ee3d..a1fcf0839 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -21,6 +21,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -28,7 +29,6 @@ struct grub_ofnetcard_data { char *path; grub_ieee1275_ihandle_t handle; - grub_uint32_t mtu; }; static grub_err_t @@ -70,29 +70,39 @@ send_card_buffer (const struct grub_net_card *dev, struct grub_net_buff *pack) pack->tail - pack->data, &actual); if (status) - return grub_error (GRUB_ERR_IO, "Couldn't send network packet."); + return grub_error (GRUB_ERR_IO, N_("couldn't send network packet")); return GRUB_ERR_NONE; } -static grub_ssize_t -get_card_packet (const struct grub_net_card *dev, struct grub_net_buff *nb) +static struct grub_net_buff * +get_card_packet (const struct grub_net_card *dev) { grub_ssize_t actual; int rc; struct grub_ofnetcard_data *data = dev->data; grub_uint64_t start_time; + struct grub_net_buff *nb; - grub_netbuff_clear (nb); + nb = grub_netbuff_alloc (dev->mtu + 64); + /* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible + by 4. So that IP header is aligned on 4 bytes. */ + grub_netbuff_reserve (nb, 2); + if (!nb) + { + grub_netbuff_free (nb); + return NULL; + } start_time = grub_get_time_ms (); do - rc = grub_ieee1275_read (data->handle, nb->data, data->mtu, &actual); + rc = grub_ieee1275_read (data->handle, nb->data, dev->mtu + 64, &actual); while ((actual <= 0 || rc < 0) && (grub_get_time_ms () - start_time < 200)); if (actual) { grub_netbuff_put (nb, actual); - return actual; + return nb; } - return -1; + grub_netbuff_free (nb); + return NULL; } static struct grub_net_card_driver ofdriver = @@ -106,7 +116,7 @@ static struct grub_net_card_driver ofdriver = static const struct { - char *name; + const char *name; int offset; } @@ -228,12 +238,15 @@ grub_ofnet_findcards (void) grub_ieee1275_finddevice (ofdata->path, &devhandle); - if (grub_ieee1275_get_integer_property - (devhandle, "max-frame-size", &(ofdata->mtu), - sizeof (ofdata->mtu), 0)) - { - ofdata->mtu = 1500; - } + { + grub_uint32_t t; + if (grub_ieee1275_get_integer_property (devhandle, + "max-frame-size", &t, + sizeof (t), 0)) + card->mtu = 1500; + else + card->mtu = t; + } if (grub_ieee1275_get_property (devhandle, "mac-address", &(lla.mac), 6, 0) diff --git a/grub-core/net/ethernet.c b/grub-core/net/ethernet.c index acd33bcf6..b38e2c83e 100644 --- a/grub-core/net/ethernet.c +++ b/grub-core/net/ethernet.c @@ -52,11 +52,13 @@ grub_err_t send_ethernet_packet (struct grub_net_network_level_interface *inf, struct grub_net_buff *nb, grub_net_link_level_address_t target_addr, - grub_uint16_t ethertype) + grub_net_ethertype_t ethertype) { struct etherhdr *eth; grub_err_t err; + COMPILE_TIME_ASSERT (sizeof (*eth) < GRUB_NET_MAX_LINK_HEADER_SIZE); + err = grub_netbuff_push (nb, sizeof (*eth)); if (err) return err; @@ -78,14 +80,15 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf, } grub_err_t -grub_net_recv_ethernet_packet (struct grub_net_buff * nb, - const struct grub_net_card * card) +grub_net_recv_ethernet_packet (struct grub_net_buff *nb, + struct grub_net_card *card) { struct etherhdr *eth; struct llchdr *llch; struct snaphdr *snaph; - grub_uint16_t type; + grub_net_ethertype_t type; grub_net_link_level_address_t hwaddress; + grub_net_link_level_address_t src_hwaddress; grub_err_t err; eth = (struct etherhdr *) nb->data; @@ -111,19 +114,20 @@ grub_net_recv_ethernet_packet (struct grub_net_buff * nb, hwaddress.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; grub_memcpy (hwaddress.mac, eth->dst, sizeof (hwaddress.mac)); + src_hwaddress.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + grub_memcpy (src_hwaddress.mac, eth->src, sizeof (src_hwaddress.mac)); - /* ARP packet. */ - if (type == GRUB_NET_ETHERTYPE_ARP) + switch (type) { - grub_net_arp_receive (nb); + /* ARP packet. */ + case GRUB_NET_ETHERTYPE_ARP: + grub_net_arp_receive (nb, card); grub_netbuff_free (nb); return GRUB_ERR_NONE; - } - /* IP packet. */ - if (type == GRUB_NET_ETHERTYPE_IP) - { - grub_net_recv_ip_packets (nb, card, &hwaddress); - return GRUB_ERR_NONE; + /* IP packet. */ + case GRUB_NET_ETHERTYPE_IP: + case GRUB_NET_ETHERTYPE_IP6: + return grub_net_recv_ip_packets (nb, card, &hwaddress, &src_hwaddress); } grub_netbuff_free (nb); return GRUB_ERR_NONE; diff --git a/grub-core/net/http.c b/grub-core/net/http.c new file mode 100644 index 000000000..49edeb1d9 --- /dev/null +++ b/grub-core/net/http.c @@ -0,0 +1,511 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +enum + { + HTTP_PORT = 80 + }; + + +typedef struct http_data +{ + char *current_line; + grub_size_t current_line_len; + int headers_recv; + int first_line_recv; + int size_recv; + grub_net_tcp_socket_t sock; + char *filename; + grub_err_t err; + char *errmsg; + int chunked; + grub_size_t chunk_rem; + int in_chunk_len; +} *http_data_t; + +static grub_off_t +have_ahead (struct grub_file *file) +{ + grub_net_t net = file->device->net; + grub_off_t ret = net->offset; + struct grub_net_packet *pack; + for (pack = net->packs.first; pack; pack = pack->next) + ret += pack->nb->tail - pack->nb->data; + return ret; +} + +static grub_err_t +parse_line (grub_file_t file, http_data_t data, char *ptr, grub_size_t len) +{ + char *end = ptr + len; + while (end > ptr && *(end - 1) == '\r') + end--; + *end = 0; + /* Trailing CRLF. */ + if (data->in_chunk_len == 1) + { + data->in_chunk_len = 2; + return GRUB_ERR_NONE; + } + if (data->in_chunk_len == 2) + { + data->chunk_rem = grub_strtoul (ptr, 0, 16); + grub_errno = GRUB_ERR_NONE; + if (data->chunk_rem == 0) + { + file->device->net->eof = 1; + if (file->size == GRUB_FILE_SIZE_UNKNOWN) + file->size = have_ahead (file); + } + data->in_chunk_len = 0; + return GRUB_ERR_NONE; + } + if (ptr == end) + { + data->headers_recv = 1; + if (data->chunked) + data->in_chunk_len = 2; + return GRUB_ERR_NONE; + } + + if (!data->first_line_recv) + { + int code; + if (grub_memcmp (ptr, "HTTP/1.1 ", sizeof ("HTTP/1.1 ") - 1) != 0) + return grub_error (GRUB_ERR_NET_INVALID_RESPONSE, + N_("unsupported HTTP response")); + ptr += sizeof ("HTTP/1.1 ") - 1; + code = grub_strtoul (ptr, &ptr, 10); + if (grub_errno) + return grub_errno; + switch (code) + { + case 200: + break; + case 404: + data->err = GRUB_ERR_FILE_NOT_FOUND; + data->errmsg = grub_xasprintf (_("file `%s' not found"), data->filename); + return GRUB_ERR_NONE; + default: + data->err = GRUB_ERR_NET_UNKNOWN_ERROR; + data->errmsg = grub_xasprintf (_("unsupported HTTP error %d: %s"), + code, ptr); + return GRUB_ERR_NONE; + } + data->first_line_recv = 1; + return GRUB_ERR_NONE; + } + if (grub_memcmp (ptr, "Content-Length: ", sizeof ("Content-Length: ") - 1) + == 0 && !data->size_recv) + { + ptr += sizeof ("Content-Length: ") - 1; + file->size = grub_strtoull (ptr, &ptr, 10); + data->size_recv = 1; + return GRUB_ERR_NONE; + } + if (grub_memcmp (ptr, "Transfer-Encoding: chunked", + sizeof ("Transfer-Encoding: chunked") - 1) == 0) + { + data->chunked = 1; + return GRUB_ERR_NONE; + } + + return GRUB_ERR_NONE; +} + +static void +http_err (grub_net_tcp_socket_t sock __attribute__ ((unused)), + void *f) +{ + grub_file_t file = f; + http_data_t data = file->data; + + if (data->sock) + grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); + if (data->current_line) + grub_free (data->current_line); + grub_free (data); + file->device->net->eof = 1; + if (file->size == GRUB_FILE_SIZE_UNKNOWN) + file->size = have_ahead (file); +} + +static grub_err_t +http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)), + struct grub_net_buff *nb, + void *f) +{ + grub_file_t file = f; + http_data_t data = file->data; + grub_err_t err; + + while (1) + { + char *ptr = (char *) nb->data; + if ((!data->headers_recv || data->in_chunk_len) && data->current_line) + { + int have_line = 1; + char *t; + ptr = grub_memchr (nb->data, '\n', nb->tail - nb->data); + if (ptr) + ptr++; + else + { + have_line = 0; + ptr = (char *) nb->tail; + } + t = grub_realloc (data->current_line, + data->current_line_len + (ptr - (char *) nb->data)); + if (!t) + { + grub_netbuff_free (nb); + grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); + return grub_errno; + } + + data->current_line = t; + grub_memcpy (data->current_line + data->current_line_len, + nb->data, ptr - (char *) nb->data); + data->current_line_len += ptr - (char *) nb->data; + if (!have_line) + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + err = parse_line (file, data, data->current_line, + data->current_line_len); + grub_free (data->current_line); + data->current_line = 0; + data->current_line_len = 0; + if (err) + { + grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); + grub_netbuff_free (nb); + return err; + } + } + + while (ptr < (char *) nb->tail && (!data->headers_recv + || data->in_chunk_len)) + { + char *ptr2; + ptr2 = grub_memchr (ptr, '\n', (char *) nb->tail - ptr); + if (!ptr2) + { + data->current_line = grub_malloc ((char *) nb->tail - ptr); + if (!data->current_line) + { + grub_netbuff_free (nb); + grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); + return grub_errno; + } + data->current_line_len = (char *) nb->tail - ptr; + grub_memcpy (data->current_line, ptr, data->current_line_len); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + err = parse_line (file, data, ptr, ptr2 - ptr); + if (err) + { + grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); + grub_netbuff_free (nb); + return err; + } + ptr = ptr2 + 1; + } + + if (((char *) nb->tail - ptr) <= 0) + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + err = grub_netbuff_pull (nb, ptr - (char *) nb->data); + if (err) + { + grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); + grub_netbuff_free (nb); + return err; + } + if (!(data->chunked && (grub_ssize_t) data->chunk_rem + < nb->tail - nb->data)) + { + grub_net_put_packet (&file->device->net->packs, nb); + if (data->chunked) + data->chunk_rem -= nb->tail - nb->data; + return GRUB_ERR_NONE; + } + if (data->chunk_rem) + { + struct grub_net_buff *nb2; + nb2 = grub_netbuff_alloc (data->chunk_rem); + if (!nb2) + return grub_errno; + grub_netbuff_put (nb2, data->chunk_rem); + grub_memcpy (nb2->data, nb->data, data->chunk_rem); + grub_net_put_packet (&file->device->net->packs, nb2); + grub_netbuff_pull (nb, data->chunk_rem); + } + data->in_chunk_len = 1; + } +} + +static grub_err_t +http_establish (struct grub_file *file, grub_off_t offset, int initial) +{ + http_data_t data = file->data; + grub_uint8_t *ptr; + int i; + struct grub_net_buff *nb; + grub_err_t err; + + nb = grub_netbuff_alloc (GRUB_NET_TCP_RESERVE_SIZE + + sizeof ("GET ") - 1 + + grub_strlen (data->filename) + + sizeof (" HTTP/1.1\r\nHost: ") - 1 + + grub_strlen (file->device->net->server) + + sizeof ("\r\nUser-Agent: " PACKAGE_STRING + "\r\n") - 1 + + sizeof ("Content-Range: bytes XXXXXXXXXXXXXXXXXXXX" + "-XXXXXXXXXXXXXXXXXXXX/" + "XXXXXXXXXXXXXXXXXXXX\r\n\r\n")); + if (!nb) + return grub_errno; + + grub_netbuff_reserve (nb, GRUB_NET_TCP_RESERVE_SIZE); + ptr = nb->tail; + err = grub_netbuff_put (nb, sizeof ("GET ") - 1); + if (err) + { + grub_netbuff_free (nb); + return err; + } + grub_memcpy (ptr, "GET ", sizeof ("GET ") - 1); + + ptr = nb->tail; + + err = grub_netbuff_put (nb, grub_strlen (data->filename)); + if (err) + { + grub_netbuff_free (nb); + return err; + } + grub_memcpy (ptr, data->filename, grub_strlen (data->filename)); + + ptr = nb->tail; + err = grub_netbuff_put (nb, sizeof (" HTTP/1.1\r\nHost: ") - 1); + if (err) + { + grub_netbuff_free (nb); + return err; + } + grub_memcpy (ptr, " HTTP/1.1\r\nHost: ", + sizeof (" HTTP/1.1\r\nHost: ") - 1); + + ptr = nb->tail; + err = grub_netbuff_put (nb, grub_strlen (file->device->net->server)); + if (err) + { + grub_netbuff_free (nb); + return err; + } + grub_memcpy (ptr, file->device->net->server, + grub_strlen (file->device->net->server)); + + ptr = nb->tail; + err = grub_netbuff_put (nb, + sizeof ("\r\nUser-Agent: " PACKAGE_STRING "\r\n") + - 1); + if (err) + { + grub_netbuff_free (nb); + return err; + } + grub_memcpy (ptr, "\r\nUser-Agent: " PACKAGE_STRING "\r\n", + sizeof ("\r\nUser-Agent: " PACKAGE_STRING "\r\n") - 1); + if (!initial) + { + ptr = nb->tail; + grub_snprintf ((char *) ptr, + sizeof ("Content-Range: bytes XXXXXXXXXXXXXXXXXXXX-" + "XXXXXXXXXXXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXX\r\n" + "\r\n"), + "Content-Range: bytes %" PRIuGRUB_UINT64_T "-%" + PRIuGRUB_UINT64_T "/%" PRIuGRUB_UINT64_T "\r\n\r\n", + offset, file->size - 1, file->size); + grub_netbuff_put (nb, grub_strlen ((char *) ptr)); + } + ptr = nb->tail; + grub_netbuff_put (nb, 2); + grub_memcpy (ptr, "\r\n", 2); + + data->sock = grub_net_tcp_open (file->device->net->server, + HTTP_PORT, http_receive, + http_err, http_err, + file); + if (!data->sock) + { + grub_netbuff_free (nb); + return grub_errno; + } + + // grub_net_poll_cards (5000); + + err = grub_net_send_tcp_packet (data->sock, nb, 1); + if (err) + { + grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); + return err; + } + + for (i = 0; !data->headers_recv && i < 100; i++) + { + grub_net_tcp_retransmit (); + grub_net_poll_cards (300); + } + + if (!data->headers_recv) + { + grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); + if (data->err) + { + char *str = data->errmsg; + err = grub_error (data->err, "%s", str); + grub_free (str); + return data->err; + } + return grub_error (GRUB_ERR_TIMEOUT, N_("time out opening `%s'"), data->filename); + } + return GRUB_ERR_NONE; +} + +static grub_err_t +http_seek (struct grub_file *file, grub_off_t off) +{ + struct http_data *old_data, *data; + grub_err_t err; + old_data = file->data; + /* FIXME: Reuse socket? */ + grub_net_tcp_close (old_data->sock, GRUB_NET_TCP_ABORT); + + while (file->device->net->packs.first) + { + grub_netbuff_free (file->device->net->packs.first->nb); + grub_net_remove_packet (file->device->net->packs.first); + } + + file->device->net->offset = off; + + data = grub_zalloc (sizeof (*data)); + if (!data) + return grub_errno; + + data->size_recv = 1; + data->filename = old_data->filename; + if (!data->filename) + { + grub_free (data); + return grub_errno; + } + grub_free (old_data); + + file->data = data; + err = http_establish (file, off, 0); + if (err) + { + grub_free (data->filename); + grub_free (data); + return err; + } + return GRUB_ERR_NONE; +} + +static grub_err_t +http_open (struct grub_file *file, const char *filename) +{ + grub_err_t err; + struct http_data *data; + + data = grub_zalloc (sizeof (*data)); + if (!data) + return grub_errno; + file->size = GRUB_FILE_SIZE_UNKNOWN; + + data->filename = grub_strdup (filename); + if (!data->filename) + { + grub_free (data); + return grub_errno; + } + + file->not_easily_seekable = 0; + file->data = data; + + err = http_establish (file, 0, 1); + if (err) + { + grub_free (data->filename); + grub_free (data); + return err; + } + + return GRUB_ERR_NONE; +} + +static grub_err_t +http_close (struct grub_file *file) +{ + http_data_t data = file->data; + + if (data->sock) + grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT); + if (data->current_line) + grub_free (data->current_line); + grub_free (data); + return GRUB_ERR_NONE; +} + +static struct grub_net_app_protocol grub_http_protocol = + { + .name = "http", + .open = http_open, + .close = http_close, + .seek = http_seek + }; + +GRUB_MOD_INIT (http) +{ + grub_net_app_level_register (&grub_http_protocol); +} + +GRUB_MOD_FINI (http) +{ + grub_net_app_level_unregister (&grub_http_protocol); +} diff --git a/grub-core/net/icmp.c b/grub-core/net/icmp.c new file mode 100644 index 000000000..e55a0d86a --- /dev/null +++ b/grub-core/net/icmp.c @@ -0,0 +1,122 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include + +struct icmp_header +{ + grub_uint8_t type; + grub_uint8_t code; + grub_uint16_t checksum; +} __attribute__ ((packed)); + +struct ping_header +{ + grub_uint16_t id; + grub_uint16_t seq; +} __attribute__ ((packed)); + +enum + { + ICMP_ECHO_REPLY = 0, + ICMP_ECHO = 8, + }; + +grub_err_t +grub_net_recv_icmp_packet (struct grub_net_buff *nb, + struct grub_net_network_level_interface *inf, + const grub_net_link_level_address_t *ll_src, + const grub_net_network_level_address_t *src) +{ + struct icmp_header *icmph; + grub_err_t err; + grub_uint16_t checksum; + + /* Ignore broadcast. */ + if (!inf) + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + + icmph = (struct icmp_header *) nb->data; + + if (nb->tail - nb->data < (grub_ssize_t) sizeof (*icmph)) + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + + checksum = icmph->checksum; + icmph->checksum = 0; + if (checksum != grub_net_ip_chksum (nb->data, nb->tail - nb->data)) + { + icmph->checksum = checksum; + return GRUB_ERR_NONE; + } + icmph->checksum = checksum; + + err = grub_netbuff_pull (nb, sizeof (*icmph)); + if (err) + return err; + + switch (icmph->type) + { + case ICMP_ECHO: + { + struct grub_net_buff *nb_reply; + struct icmp_header *icmphr; + if (icmph->code) + break; + nb_reply = grub_netbuff_alloc (nb->tail - nb->data + 512); + if (!nb_reply) + { + grub_netbuff_free (nb); + return grub_errno; + } + err = grub_netbuff_reserve (nb_reply, nb->tail - nb->data + 512); + if (err) + goto ping_fail; + err = grub_netbuff_push (nb_reply, nb->tail - nb->data); + if (err) + goto ping_fail; + grub_memcpy (nb_reply->data, nb->data, nb->tail - nb->data); + err = grub_netbuff_push (nb_reply, sizeof (*icmphr)); + if (err) + goto ping_fail; + icmphr = (struct icmp_header *) nb_reply->data; + icmphr->type = ICMP_ECHO_REPLY; + icmphr->code = 0; + icmphr->checksum = 0; + icmphr->checksum = grub_net_ip_chksum ((void *) nb_reply->data, + nb_reply->tail - nb_reply->data); + err = grub_net_send_ip_packet (inf, src, ll_src, + nb_reply, GRUB_NET_IP_ICMP); + + ping_fail: + grub_netbuff_free (nb); + grub_netbuff_free (nb_reply); + return err; + } + }; + + grub_netbuff_free (nb); + return GRUB_ERR_NONE; +} diff --git a/grub-core/net/icmp6.c b/grub-core/net/icmp6.c new file mode 100644 index 000000000..9a5f3cafe --- /dev/null +++ b/grub-core/net/icmp6.c @@ -0,0 +1,529 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include + +struct icmp_header +{ + grub_uint8_t type; + grub_uint8_t code; + grub_uint16_t checksum; +} __attribute__ ((packed)); + +struct ping_header +{ + grub_uint16_t id; + grub_uint16_t seq; +} __attribute__ ((packed)); + +struct router_adv +{ + grub_uint8_t ttl; + grub_uint8_t flags; + grub_uint16_t router_lifetime; + grub_uint32_t reachable_time; + grub_uint32_t retrans_timer; + grub_uint8_t options[0]; +} __attribute__ ((packed)); + +struct option_header +{ + grub_uint8_t type; + grub_uint8_t len; +} __attribute__ ((packed)); + +struct prefix_option +{ + struct option_header header; + grub_uint8_t prefixlen; + grub_uint8_t flags; + grub_uint32_t valid_lifetime; + grub_uint32_t prefered_lifetime; + grub_uint32_t reserved; + grub_uint64_t prefix[2]; +} __attribute__ ((packed)); + +struct neighbour_solicit +{ + grub_uint32_t reserved; + grub_uint64_t target[2]; +} __attribute__ ((packed)); + +struct neighbour_advertise +{ + grub_uint32_t flags; + grub_uint64_t target[2]; +} __attribute__ ((packed)); + +enum + { + FLAG_SLAAC = 0x40 + }; + +enum + { + ICMP6_ECHO = 128, + ICMP6_ECHO_REPLY = 129, + ICMP6_ROUTER_ADVERTISE = 134, + ICMP6_NEIGHBOUR_SOLICIT = 135, + ICMP6_NEIGHBOUR_ADVERTISE = 136, + }; + +enum + { + OPTION_SOURCE_LINK_LAYER_ADDRESS = 1, + OPTION_TARGET_LINK_LAYER_ADDRESS = 2, + OPTION_PREFIX = 3 + }; + +enum + { + FLAG_SOLICITED = (1 << 30), + FLAG_OVERRIDE = (1 << 29) + }; + +grub_err_t +grub_net_recv_icmp6_packet (struct grub_net_buff *nb, + struct grub_net_card *card, + struct grub_net_network_level_interface *inf, + const grub_net_link_level_address_t *ll_src, + const grub_net_network_level_address_t *source, + const grub_net_network_level_address_t *dest, + grub_uint8_t ttl) +{ + struct icmp_header *icmph; + grub_err_t err; + grub_uint16_t checksum; + + icmph = (struct icmp_header *) nb->data; + + if (nb->tail - nb->data < (grub_ssize_t) sizeof (*icmph)) + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + + checksum = icmph->checksum; + icmph->checksum = 0; + if (checksum != grub_net_ip_transport_checksum (nb, + GRUB_NET_IP_ICMPV6, + source, + dest)) + { + grub_dprintf ("net", "invalid ICMPv6 checksum: %04x instead of %04x\n", + checksum, + grub_net_ip_transport_checksum (nb, + GRUB_NET_IP_ICMPV6, + source, + dest)); + icmph->checksum = checksum; + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + icmph->checksum = checksum; + + err = grub_netbuff_pull (nb, sizeof (*icmph)); + if (err) + { + grub_netbuff_free (nb); + return err; + } + + grub_dprintf ("net", "ICMPv6 message: %02x, %02x\n", + icmph->type, icmph->code); + switch (icmph->type) + { + case ICMP6_ECHO: + /* Don't accept multicast pings. */ + if (!inf) + break; + { + struct grub_net_buff *nb_reply; + struct icmp_header *icmphr; + if (icmph->code) + break; + nb_reply = grub_netbuff_alloc (nb->tail - nb->data + 512); + if (!nb_reply) + { + grub_netbuff_free (nb); + return grub_errno; + } + err = grub_netbuff_reserve (nb_reply, nb->tail - nb->data + 512); + if (err) + goto ping_fail; + err = grub_netbuff_push (nb_reply, nb->tail - nb->data); + if (err) + goto ping_fail; + grub_memcpy (nb_reply->data, nb->data, nb->tail - nb->data); + err = grub_netbuff_push (nb_reply, sizeof (*icmphr)); + if (err) + goto ping_fail; + icmphr = (struct icmp_header *) nb_reply->data; + icmphr->type = ICMP6_ECHO_REPLY; + icmphr->code = 0; + icmphr->checksum = 0; + icmphr->checksum = grub_net_ip_transport_checksum (nb_reply, + GRUB_NET_IP_ICMPV6, + &inf->address, + source); + err = grub_net_send_ip_packet (inf, source, ll_src, nb_reply, + GRUB_NET_IP_ICMPV6); + + ping_fail: + grub_netbuff_free (nb); + grub_netbuff_free (nb_reply); + return err; + } + case ICMP6_NEIGHBOUR_SOLICIT: + { + struct neighbour_solicit *nbh; + struct grub_net_buff *nb_reply; + struct option_header *ohdr; + struct neighbour_advertise *adv; + struct icmp_header *icmphr; + grub_uint8_t *ptr; + + if (icmph->code) + break; + if (ttl != 0xff) + break; + nbh = (struct neighbour_solicit *) nb->data; + err = grub_netbuff_pull (nb, sizeof (struct router_adv)); + if (err) + { + grub_netbuff_free (nb); + return err; + } + for (ptr = (grub_uint8_t *) nb->data; ptr < nb->tail; + ptr += ohdr->len * 8) + { + ohdr = (struct option_header *) ptr; + if (ohdr->len == 0 || ptr + 8 * ohdr->len > nb->tail) + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + if (ohdr->type == OPTION_SOURCE_LINK_LAYER_ADDRESS + && ohdr->len == 1) + { + grub_net_link_level_address_t ll_address; + ll_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + grub_memcpy (ll_address.mac, ohdr + 1, sizeof (ll_address.mac)); + grub_net_link_layer_add_address (card, source, &ll_address, 0); + } + } + FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + { + if (inf->card == card + && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6 + && grub_memcmp (&inf->address.ipv6, &nbh->target, 16) == 0) + break; + } + if (!inf) + break; + + nb_reply = grub_netbuff_alloc (sizeof (struct neighbour_advertise) + + sizeof (struct option_header) + + 6 + + sizeof (struct icmp_header) + + GRUB_NET_OUR_IPV6_HEADER_SIZE + + GRUB_NET_MAX_LINK_HEADER_SIZE); + if (!nb_reply) + { + grub_netbuff_free (nb); + return grub_errno; + } + err = grub_netbuff_reserve (nb_reply, + sizeof (struct neighbour_advertise) + + sizeof (struct option_header) + + 6 + + sizeof (struct icmp_header) + + GRUB_NET_OUR_IPV6_HEADER_SIZE + + GRUB_NET_MAX_LINK_HEADER_SIZE); + if (err) + goto ndp_fail; + + err = grub_netbuff_push (nb_reply, 6); + if (err) + goto ndp_fail; + grub_memcpy (nb_reply->data, inf->hwaddress.mac, 6); + err = grub_netbuff_push (nb_reply, sizeof (*ohdr)); + if (err) + goto ndp_fail; + ohdr = (struct option_header *) nb_reply->data; + ohdr->type = OPTION_TARGET_LINK_LAYER_ADDRESS; + ohdr->len = 1; + err = grub_netbuff_push (nb_reply, sizeof (*adv)); + if (err) + goto ndp_fail; + adv = (struct neighbour_advertise *) nb_reply->data; + adv->flags = grub_cpu_to_be32_compile_time (FLAG_SOLICITED + | FLAG_OVERRIDE); + grub_memcpy (&adv->target, &nbh->target, 16); + + err = grub_netbuff_push (nb_reply, sizeof (*icmphr)); + if (err) + goto ndp_fail; + icmphr = (struct icmp_header *) nb_reply->data; + icmphr->type = ICMP6_NEIGHBOUR_ADVERTISE; + icmphr->code = 0; + icmphr->checksum = 0; + icmphr->checksum = grub_net_ip_transport_checksum (nb_reply, + GRUB_NET_IP_ICMPV6, + &inf->address, + source); + err = grub_net_send_ip_packet (inf, source, ll_src, nb_reply, + GRUB_NET_IP_ICMPV6); + + ndp_fail: + grub_netbuff_free (nb); + grub_netbuff_free (nb_reply); + return err; + } + case ICMP6_NEIGHBOUR_ADVERTISE: + { + struct neighbour_advertise *nbh; + grub_uint8_t *ptr; + struct option_header *ohdr; + + if (icmph->code) + break; + if (ttl != 0xff) + break; + nbh = (struct neighbour_advertise *) nb->data; + err = grub_netbuff_pull (nb, sizeof (*nbh)); + if (err) + { + grub_netbuff_free (nb); + return err; + } + + for (ptr = (grub_uint8_t *) nb->data; ptr < nb->tail; + ptr += ohdr->len * 8) + { + ohdr = (struct option_header *) ptr; + if (ohdr->len == 0 || ptr + 8 * ohdr->len > nb->tail) + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + if (ohdr->type == OPTION_TARGET_LINK_LAYER_ADDRESS + && ohdr->len == 1) + { + grub_net_link_level_address_t ll_address; + ll_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + grub_memcpy (ll_address.mac, ohdr + 1, sizeof (ll_address.mac)); + grub_net_link_layer_add_address (card, source, &ll_address, 0); + } + } + break; + } + case ICMP6_ROUTER_ADVERTISE: + { + grub_uint8_t *ptr; + struct option_header *ohdr; + if (icmph->code) + break; + err = grub_netbuff_pull (nb, sizeof (struct router_adv)); + if (err) + { + grub_netbuff_free (nb); + return err; + } + for (ptr = (grub_uint8_t *) nb->data; ptr < nb->tail; + ptr += ohdr->len * 8) + { + ohdr = (struct option_header *) ptr; + if (ohdr->len == 0 || ptr + 8 * ohdr->len > nb->tail) + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + if (ohdr->type == OPTION_SOURCE_LINK_LAYER_ADDRESS + && ohdr->len == 1) + { + grub_net_link_level_address_t ll_address; + ll_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + grub_memcpy (ll_address.mac, ohdr + 1, sizeof (ll_address.mac)); + grub_net_link_layer_add_address (card, source, &ll_address, 0); + } + if (ohdr->type == OPTION_PREFIX && ohdr->len == 4) + { + struct prefix_option *opt = (struct prefix_option *) ptr; + struct grub_net_slaac_mac_list *slaac; + if (!(opt->flags & FLAG_SLAAC) + || (grub_be_to_cpu64 (opt->prefix[0]) >> 48) == 0xfe80 + || (grub_be_to_cpu32 (opt->prefered_lifetime) + > grub_be_to_cpu32 (opt->valid_lifetime)) + || opt->prefixlen != 64) + { + grub_dprintf ("net", "discarded prefix: %d, %d, %d, %d\n", + !(opt->flags & FLAG_SLAAC), + (grub_be_to_cpu64 (opt->prefix[0]) >> 48) == 0xfe80, + (grub_be_to_cpu32 (opt->prefered_lifetime) + > grub_be_to_cpu32 (opt->valid_lifetime)), + opt->prefixlen != 64); + continue; + } + for (slaac = card->slaac_list; slaac; slaac = slaac->next) + { + grub_net_network_level_address_t addr; + grub_net_network_level_netaddress_t netaddr; + + if (slaac->address.type + != GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET) + continue; + addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; + addr.ipv6[0] = opt->prefix[0]; + addr.ipv6[1] = grub_net_ipv6_get_id (&slaac->address); + netaddr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; + netaddr.ipv6.base[0] = opt->prefix[0]; + netaddr.ipv6.base[1] = 0; + netaddr.ipv6.masksize = 64; + + FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + { + if (inf->card == card + && grub_net_addr_cmp (&inf->address, &addr) == 0) + break; + } + /* Update lease time if needed here once we have + lease times. */ + if (inf) + continue; + + grub_dprintf ("net", "creating slaac\n"); + + { + char name[grub_strlen (slaac->name) + + sizeof (":XXXXXXXXXXXXXXXXXXXX")]; + grub_snprintf (name, sizeof (name), "%s:%d", + slaac->name, slaac->slaac_counter++); + inf = grub_net_add_addr (name, + card, &addr, + &slaac->address, 0); + grub_net_add_route (name, netaddr, inf); + } + } + } + } + if (ptr != nb->tail) + break; + } + }; + + grub_netbuff_free (nb); + return GRUB_ERR_NONE; +} + +grub_err_t +grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *proto_addr) +{ + struct grub_net_buff *nb; + grub_err_t err = GRUB_ERR_NONE; + int i; + struct option_header *ohdr; + struct neighbour_solicit *sol; + struct icmp_header *icmphr; + grub_net_network_level_address_t multicast; + grub_net_link_level_address_t ll_multicast; + grub_uint8_t *nbd; + multicast.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; + multicast.ipv6[0] = grub_be_to_cpu64_compile_time (0xff02ULL << 48); + multicast.ipv6[1] = (grub_be_to_cpu64_compile_time (0x01ff000000ULL) + | (proto_addr->ipv6[1] + & grub_be_to_cpu64_compile_time (0xffffff))); + + err = grub_net_link_layer_resolve (inf, &multicast, &ll_multicast); + if (err) + return err; + + nb = grub_netbuff_alloc (sizeof (struct neighbour_solicit) + + sizeof (struct option_header) + + 6 + + sizeof (struct icmp_header) + + GRUB_NET_OUR_IPV6_HEADER_SIZE + + GRUB_NET_MAX_LINK_HEADER_SIZE); + if (!nb) + return grub_errno; + err = grub_netbuff_reserve (nb, + sizeof (struct neighbour_solicit) + + sizeof (struct option_header) + + 6 + + sizeof (struct icmp_header) + + GRUB_NET_OUR_IPV6_HEADER_SIZE + + GRUB_NET_MAX_LINK_HEADER_SIZE); + err = grub_netbuff_push (nb, 6); + if (err) + goto fail; + + grub_memcpy (nb->data, inf->hwaddress.mac, 6); + err = grub_netbuff_push (nb, sizeof (*ohdr)); + if (err) + goto fail; + + ohdr = (struct option_header *) nb->data; + ohdr->type = OPTION_SOURCE_LINK_LAYER_ADDRESS; + ohdr->len = 1; + err = grub_netbuff_push (nb, sizeof (*sol)); + if (err) + goto fail; + + sol = (struct neighbour_solicit *) nb->data; + sol->reserved = 0; + grub_memcpy (&sol->target, &proto_addr->ipv6, 16); + + err = grub_netbuff_push (nb, sizeof (*icmphr)); + if (err) + goto fail; + + icmphr = (struct icmp_header *) nb->data; + icmphr->type = ICMP6_NEIGHBOUR_SOLICIT; + icmphr->code = 0; + icmphr->checksum = 0; + icmphr->checksum = grub_net_ip_transport_checksum (nb, + GRUB_NET_IP_ICMPV6, + &inf->address, + &multicast); + nbd = nb->data; + err = grub_net_send_ip_packet (inf, &multicast, &ll_multicast, nb, + GRUB_NET_IP_ICMPV6); + if (err) + goto fail; + + for (i = 0; i < GRUB_NET_TRIES; i++) + { + if (grub_net_link_layer_resolve_check (inf, proto_addr)) + break; + grub_net_poll_cards (GRUB_NET_INTERVAL); + if (grub_net_link_layer_resolve_check (inf, proto_addr)) + break; + nb->data = nbd; + err = grub_net_send_ip_packet (inf, &multicast, &ll_multicast, nb, + GRUB_NET_IP_ICMPV6); + if (err) + break; + } + + fail: + grub_netbuff_free (nb); + return err; +} diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index 642a67f18..65a06fcee 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include struct iphdr { grub_uint8_t verhdrlen; @@ -35,46 +37,165 @@ struct iphdr { grub_uint8_t protocol; grub_uint16_t chksum; grub_uint32_t src; - grub_uint32_t dest; + grub_uint32_t dest; } __attribute__ ((packed)) ; -struct ip6hdr +enum { - grub_uint8_t version:4, priority:4; - grub_uint8_t flow_lbl[3]; - grub_uint16_t payload_len; - grub_uint8_t nexthdr; - grub_uint8_t hop_limit; - grub_uint8_t saddr[16]; - grub_uint8_t daddr[16]; -} __attribute__ ((packed)); + DONT_FRAGMENT = 0x4000, + MORE_FRAGMENTS = 0x2000, + OFFSET_MASK = 0x1fff +}; + +typedef grub_uint64_t ip6addr[2]; + +struct ip6hdr { + grub_uint32_t version_class_flow; + grub_uint16_t len; + grub_uint8_t protocol; + grub_uint8_t ttl; + ip6addr src; + ip6addr dest; +} __attribute__ ((packed)) ; + +static int +cmp (const void *a__, const void *b__) +{ + struct grub_net_buff *a_ = *(struct grub_net_buff **) a__; + struct grub_net_buff *b_ = *(struct grub_net_buff **) b__; + struct iphdr *a = (struct iphdr *) a_->data; + struct iphdr *b = (struct iphdr *) b_->data; + /* We want the first elements to be on top. */ + if ((grub_be_to_cpu16 (a->frags) & OFFSET_MASK) + < (grub_be_to_cpu16 (b->frags) & OFFSET_MASK)) + return +1; + if ((grub_be_to_cpu16 (a->frags) & OFFSET_MASK) + > (grub_be_to_cpu16 (b->frags) & OFFSET_MASK)) + return -1; + return 0; +} + +struct reassemble +{ + struct reassemble *next; + grub_uint32_t source; + grub_uint32_t dest; + grub_uint16_t id; + grub_uint8_t proto; + grub_uint64_t last_time; + grub_priority_queue_t pq; + grub_uint8_t *asm_buffer; + grub_size_t total_len; + grub_size_t cur_ptr; + grub_uint8_t ttl; +}; + +static struct reassemble *reassembles; grub_uint16_t -grub_net_ip_chksum (void *ipv, int len) +grub_net_ip_chksum (void *ipv, grub_size_t len) { grub_uint16_t *ip = (grub_uint16_t *) ipv; grub_uint32_t sum = 0; - len >>= 1; - while (len--) + for (; len >= 2; len -= 2) { - sum += grub_be_to_cpu16 (*(ip++)); + sum += grub_be_to_cpu16 (grub_get_unaligned16 (ip++)); + if (sum > 0xFFFF) + sum -= 0xFFFF; + } + if (len) + { + sum += *((grub_uint8_t *) ip) << 8; if (sum > 0xFFFF) sum -= 0xFFFF; } + if (sum >= 0xFFFF) + sum -= 0xFFFF; + return grub_cpu_to_be16 ((~sum) & 0x0000FFFF); } -grub_err_t -grub_net_send_ip_packet (struct grub_net_network_level_interface * inf, - const grub_net_network_level_address_t * target, - struct grub_net_buff * nb) +static int id = 0x2400; + +static grub_err_t +send_fragmented (struct grub_net_network_level_interface * inf, + const grub_net_network_level_address_t * target, + struct grub_net_buff * nb, + grub_net_ip_protocol_t proto, + grub_net_link_level_address_t ll_target_addr) +{ + grub_size_t off = 0; + grub_size_t fraglen; + grub_err_t err; + + fraglen = (inf->card->mtu - sizeof (struct iphdr)) & ~7; + id++; + + while (nb->tail - nb->data) + { + grub_size_t len = fraglen; + struct grub_net_buff *nb2; + struct iphdr *iph; + + if ((grub_ssize_t) len > nb->tail - nb->data) + len = nb->tail - nb->data; + nb2 = grub_netbuff_alloc (fraglen + sizeof (struct iphdr) + + GRUB_NET_MAX_LINK_HEADER_SIZE); + if (!nb2) + return grub_errno; + err = grub_netbuff_reserve (nb2, GRUB_NET_MAX_LINK_HEADER_SIZE); + if (err) + return err; + err = grub_netbuff_put (nb2, sizeof (struct iphdr)); + if (err) + return err; + + iph = (struct iphdr *) nb2->data; + iph->verhdrlen = ((4 << 4) | 5); + iph->service = 0; + iph->len = grub_cpu_to_be16 (len + sizeof (struct iphdr)); + iph->ident = grub_cpu_to_be16 (id); + iph->frags = grub_cpu_to_be16 (off | (((grub_ssize_t) len + == nb->tail - nb->data) + ? 0 : MORE_FRAGMENTS)); + iph->ttl = 0xff; + iph->protocol = proto; + iph->src = inf->address.ipv4; + iph->dest = target->ipv4; + off += len / 8; + + iph->chksum = 0; + iph->chksum = grub_net_ip_chksum ((void *) nb2->data, sizeof (*iph)); + err = grub_netbuff_put (nb2, len); + if (err) + return err; + grub_memcpy (iph + 1, nb->data, len); + err = grub_netbuff_pull (nb, len); + if (err) + return err; + err = send_ethernet_packet (inf, nb2, ll_target_addr, + GRUB_NET_ETHERTYPE_IP); + if (err) + return err; + } + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_net_send_ip4_packet (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *target, + const grub_net_link_level_address_t *ll_target_addr, + struct grub_net_buff *nb, + grub_net_ip_protocol_t proto) { struct iphdr *iph; - static int id = 0x2400; - grub_net_link_level_address_t ll_target_addr; - grub_err_t err; + + COMPILE_TIME_ASSERT (GRUB_NET_OUR_IPV4_HEADER_SIZE == sizeof (*iph)); + + if (nb->tail - nb->data + sizeof (struct iphdr) > inf->card->mtu) + return send_fragmented (inf, target, nb, proto, *ll_target_addr); grub_netbuff_push (nb, sizeof (*iph)); iph = (struct iphdr *) nb->data; @@ -85,75 +206,493 @@ grub_net_send_ip_packet (struct grub_net_network_level_interface * inf, iph->ident = grub_cpu_to_be16 (++id); iph->frags = 0; iph->ttl = 0xff; - iph->protocol = 0x11; + iph->protocol = proto; iph->src = inf->address.ipv4; iph->dest = target->ipv4; iph->chksum = 0; iph->chksum = grub_net_ip_chksum ((void *) nb->data, sizeof (*iph)); - /* Determine link layer target address via ARP. */ - err = grub_net_arp_resolve (inf, target, &ll_target_addr); - if (err) - return err; - return send_ethernet_packet (inf, nb, ll_target_addr, + return send_ethernet_packet (inf, nb, *ll_target_addr, GRUB_NET_ETHERTYPE_IP); } -grub_err_t -grub_net_recv_ip_packets (struct grub_net_buff * nb, - const struct grub_net_card * card, - const grub_net_link_level_address_t * hwaddress) +static grub_err_t +handle_dgram (struct grub_net_buff *nb, + struct grub_net_card *card, + const grub_net_link_level_address_t *source_hwaddress, + const grub_net_link_level_address_t *hwaddress, + grub_net_ip_protocol_t proto, + const grub_net_network_level_address_t *source, + const grub_net_network_level_address_t *dest, + grub_uint8_t ttl) { - struct iphdr *iph = (struct iphdr *) nb->data; - grub_err_t err; struct grub_net_network_level_interface *inf = NULL; - - err = grub_netbuff_pull (nb, sizeof (*iph)); - if (err) - return err; - + grub_err_t err; + int multicast = 0; + /* DHCP needs special treatment since we don't know IP yet. */ { struct udphdr *udph; udph = (struct udphdr *) nb->data; - if (iph->protocol == IP_UDP && grub_be_to_cpu16 (udph->dst) == 68) + if (proto == GRUB_NET_IP_UDP && grub_be_to_cpu16 (udph->dst) == 68) { FOR_NET_NETWORK_LEVEL_INTERFACES (inf) if (inf->card == card && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0) { + if (udph->chksum) + { + grub_uint16_t chk, expected; + chk = udph->chksum; + udph->chksum = 0; + expected = grub_net_ip_transport_checksum (nb, + GRUB_NET_IP_UDP, + source, + dest); + if (expected != chk) + { + grub_dprintf ("net", "Invalid UDP checksum. " + "Expected %x, got %x\n", + grub_be_to_cpu16 (expected), + grub_be_to_cpu16 (chk)); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + udph->chksum = chk; + } + err = grub_netbuff_pull (nb, sizeof (*udph)); if (err) return err; grub_net_process_dhcp (nb, inf->card); grub_netbuff_free (nb); + return GRUB_ERR_NONE; } + grub_netbuff_free (nb); return GRUB_ERR_NONE; } } - if (!inf) - { - FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + { + if (inf->card == card + && grub_net_addr_cmp (&inf->address, dest) == 0 + && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0) + break; + /* Solicited node multicast. */ + if (inf->card == card + && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6 + && dest->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6 + && dest->ipv6[0] == grub_be_to_cpu64_compile_time (0xff02ULL << 48) + && dest->ipv6[1] == (grub_be_to_cpu64_compile_time (0x01ff000000ULL) + | (inf->address.ipv6[1] + & grub_be_to_cpu64_compile_time (0xffffff))) + && hwaddress->type == GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET + && hwaddress->mac[0] == 0x33 && hwaddress->mac[1] == 0x33 + && hwaddress->mac[2] == 0xff + && hwaddress->mac[3] == ((grub_be_to_cpu64 (inf->address.ipv6[1]) + >> 16) & 0xff) + && hwaddress->mac[4] == ((grub_be_to_cpu64 (inf->address.ipv6[1]) + >> 8) & 0xff) + && hwaddress->mac[5] == ((grub_be_to_cpu64 (inf->address.ipv6[1]) + >> 0) & 0xff)) { - if (inf->card == card - && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 - && inf->address.ipv4 == iph->dest - && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0) - break; + multicast = 1; + break; } - } - - switch (iph->protocol) + } + + if (!inf && !(dest->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6 + && dest->ipv6[0] == grub_be_to_cpu64_compile_time (0xff02ULL + << 48) + && dest->ipv6[1] == grub_be_to_cpu64_compile_time (1))) { - case IP_UDP: - return grub_net_recv_udp_packet (nb, inf); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + if (multicast) + inf = NULL; + + switch (proto) + { + case GRUB_NET_IP_UDP: + return grub_net_recv_udp_packet (nb, inf, source); + case GRUB_NET_IP_TCP: + return grub_net_recv_tcp_packet (nb, inf, source); + case GRUB_NET_IP_ICMP: + return grub_net_recv_icmp_packet (nb, inf, source_hwaddress, source); + case GRUB_NET_IP_ICMPV6: + return grub_net_recv_icmp6_packet (nb, card, inf, source_hwaddress, + source, dest, ttl); default: grub_netbuff_free (nb); break; } - + return GRUB_ERR_NONE; +} + +static void +free_rsm (struct reassemble *rsm) +{ + struct grub_net_buff **nb; + while ((nb = grub_priority_queue_top (rsm->pq))) + { + grub_netbuff_free (*nb); + grub_priority_queue_pop (rsm->pq); + } + grub_free (rsm->asm_buffer); + grub_priority_queue_destroy (rsm->pq); +} + +static void +free_old_fragments (void) +{ + struct reassemble *rsm, **prev; + grub_uint64_t limit_time = grub_get_time_ms () - 90000; + + for (prev = &reassembles, rsm = *prev; rsm; prev = &rsm->next, rsm = *prev) + if (rsm->last_time < limit_time) + { + *prev = rsm->next; + free_rsm (rsm); + } +} + +static grub_err_t +grub_net_recv_ip4_packets (struct grub_net_buff *nb, + struct grub_net_card *card, + const grub_net_link_level_address_t *hwaddress, + const grub_net_link_level_address_t *src_hwaddress) +{ + struct iphdr *iph = (struct iphdr *) nb->data; + grub_err_t err; + struct reassemble *rsm, **prev; + + if ((iph->verhdrlen >> 4) != 4) + { + grub_dprintf ("net", "Bad IP version: %d\n", (iph->verhdrlen >> 4)); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + + if ((iph->verhdrlen & 0xf) < 5) + { + grub_dprintf ("net", "IP header too short: %d\n", + (iph->verhdrlen & 0xf)); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + + if (nb->tail - nb->data < (grub_ssize_t) ((iph->verhdrlen & 0xf) + * sizeof (grub_uint32_t))) + { + grub_dprintf ("net", "IP packet too short: %" PRIdGRUB_SSIZE "\n", + (nb->tail - nb->data)); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + + /* Check size. */ + { + grub_size_t expected_size = grub_be_to_cpu16 (iph->len); + grub_size_t actual_size = (nb->tail - nb->data); + if (actual_size > expected_size) + { + err = grub_netbuff_unput (nb, actual_size - expected_size); + if (err) + { + grub_netbuff_free (nb); + return err; + } + } + if (actual_size < expected_size) + { + grub_dprintf ("net", "Cut IP packet actual: %" PRIuGRUB_SIZE + ", expected %" PRIuGRUB_SIZE "\n", actual_size, + expected_size); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + } + + /* Unfragmented packet. Good. */ + if (((grub_be_to_cpu16 (iph->frags) & MORE_FRAGMENTS) == 0) + && (grub_be_to_cpu16 (iph->frags) & OFFSET_MASK) == 0) + { + grub_net_network_level_address_t source; + grub_net_network_level_address_t dest; + + err = grub_netbuff_pull (nb, ((iph->verhdrlen & 0xf) + * sizeof (grub_uint32_t))); + if (err) + { + grub_netbuff_free (nb); + return err; + } + + source.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + source.ipv4 = iph->src; + + dest.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + dest.ipv4 = iph->dest; + + return handle_dgram (nb, card, src_hwaddress, hwaddress, iph->protocol, + &source, &dest, iph->ttl); + } + + for (prev = &reassembles, rsm = *prev; rsm; prev = &rsm->next, rsm = *prev) + if (rsm->source == iph->src && rsm->dest == iph->dest + && rsm->id == iph->ident && rsm->proto == iph->protocol) + break; + if (!rsm) + { + rsm = grub_malloc (sizeof (*rsm)); + if (!rsm) + return grub_errno; + rsm->source = iph->src; + rsm->dest = iph->dest; + rsm->id = iph->ident; + rsm->proto = iph->protocol; + rsm->next = reassembles; + reassembles = rsm; + prev = &reassembles; + rsm->pq = grub_priority_queue_new (sizeof (struct grub_net_buff **), cmp); + if (!rsm->pq) + { + grub_free (rsm); + return grub_errno; + } + rsm->asm_buffer = 0; + rsm->total_len = 0; + rsm->cur_ptr = 0; + rsm->ttl = 0xff; + } + if (rsm->ttl > iph->ttl) + rsm->ttl = iph->ttl; + rsm->last_time = grub_get_time_ms (); + free_old_fragments (); + + err = grub_priority_queue_push (rsm->pq, &nb); + if (err) + return err; + + if (!(grub_be_to_cpu16 (iph->frags) & MORE_FRAGMENTS)) + { + rsm->total_len = (8 * (grub_be_to_cpu16 (iph->frags) & OFFSET_MASK) + + (nb->tail - nb->data)); + rsm->total_len -= ((iph->verhdrlen & 0xf) * sizeof (grub_uint32_t)); + rsm->asm_buffer = grub_zalloc (rsm->total_len); + if (!rsm->asm_buffer) + { + *prev = rsm->next; + free_rsm (rsm); + return grub_errno; + } + } + if (!rsm->asm_buffer) + return GRUB_ERR_NONE; + + while (1) + { + struct grub_net_buff **nb_top_p, *nb_top; + grub_size_t copy; + grub_uint8_t *res; + grub_size_t res_len; + struct grub_net_buff *ret; + grub_net_ip_protocol_t proto; + grub_uint32_t src; + grub_uint32_t dst; + grub_net_network_level_address_t source; + grub_net_network_level_address_t dest; + grub_uint8_t ttl; + + nb_top_p = grub_priority_queue_top (rsm->pq); + if (!nb_top_p) + return GRUB_ERR_NONE; + nb_top = *nb_top_p; + grub_priority_queue_pop (rsm->pq); + iph = (struct iphdr *) nb_top->data; + err = grub_netbuff_pull (nb_top, ((iph->verhdrlen & 0xf) + * sizeof (grub_uint32_t))); + if (err) + { + grub_netbuff_free (nb_top); + return err; + } + if (rsm->cur_ptr < (grub_size_t) 8 * (grub_be_to_cpu16 (iph->frags) + & OFFSET_MASK)) + return GRUB_ERR_NONE; + + rsm->cur_ptr = (8 * (grub_be_to_cpu16 (iph->frags) & OFFSET_MASK) + + (nb_top->tail - nb_top->head)); + if ((grub_size_t) 8 * (grub_be_to_cpu16 (iph->frags) & OFFSET_MASK) + >= rsm->total_len) + { + grub_netbuff_free (nb_top); + continue; + } + copy = nb_top->tail - nb_top->data; + if (rsm->total_len - 8 * (grub_be_to_cpu16 (iph->frags) & OFFSET_MASK) + < copy) + copy = rsm->total_len - 8 * (grub_be_to_cpu16 (iph->frags) + & OFFSET_MASK); + grub_memcpy (&rsm->asm_buffer[8 * (grub_be_to_cpu16 (iph->frags) + & OFFSET_MASK)], + nb_top->data, copy); + + if ((grub_be_to_cpu16 (iph->frags) & MORE_FRAGMENTS)) + continue; + + res = rsm->asm_buffer; + proto = rsm->proto; + src = rsm->source; + dst = rsm->dest; + ttl = rsm->ttl; + + rsm->asm_buffer = 0; + res_len = rsm->total_len; + *prev = rsm->next; + free_rsm (rsm); + ret = grub_malloc (sizeof (*ret)); + if (!ret) + { + grub_free (res); + return grub_errno; + } + ret->data = ret->head = res; + ret->tail = ret->end = res + res_len; + + source.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + source.ipv4 = src; + + dest.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + dest.ipv4 = dst; + + return handle_dgram (ret, card, src_hwaddress, + hwaddress, proto, &source, &dest, + ttl); + } +} + +static grub_err_t +grub_net_send_ip6_packet (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *target, + const grub_net_link_level_address_t *ll_target_addr, + struct grub_net_buff *nb, + grub_net_ip_protocol_t proto) +{ + struct ip6hdr *iph; + + COMPILE_TIME_ASSERT (GRUB_NET_OUR_IPV6_HEADER_SIZE == sizeof (*iph)); + + if (nb->tail - nb->data + sizeof (struct iphdr) > inf->card->mtu) + return grub_error (GRUB_ERR_NET_PACKET_TOO_BIG, "packet too big"); + + grub_netbuff_push (nb, sizeof (*iph)); + iph = (struct ip6hdr *) nb->data; + + iph->version_class_flow = grub_cpu_to_be32 ((6 << 28)); + iph->len = grub_cpu_to_be16 (nb->tail - nb->data - sizeof (*iph)); + iph->protocol = proto; + iph->ttl = 0xff; + grub_memcpy (&iph->src, inf->address.ipv6, sizeof (iph->src)); + grub_memcpy (&iph->dest, target->ipv6, sizeof (iph->dest)); + + return send_ethernet_packet (inf, nb, *ll_target_addr, + GRUB_NET_ETHERTYPE_IP6); +} + +grub_err_t +grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *target, + const grub_net_link_level_address_t *ll_target_addr, + struct grub_net_buff *nb, + grub_net_ip_protocol_t proto) +{ + switch (target->type) + { + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: + return grub_net_send_ip4_packet (inf, target, ll_target_addr, nb, proto); + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6: + return grub_net_send_ip6_packet (inf, target, ll_target_addr, nb, proto); + default: + return grub_error (GRUB_ERR_BUG, "not an IP"); + } +} + +static grub_err_t +grub_net_recv_ip6_packets (struct grub_net_buff *nb, + struct grub_net_card *card, + const grub_net_link_level_address_t *hwaddress, + const grub_net_link_level_address_t *src_hwaddress) +{ + struct ip6hdr *iph = (struct ip6hdr *) nb->data; + grub_err_t err; + grub_net_network_level_address_t source; + grub_net_network_level_address_t dest; + + if (nb->tail - nb->data < (grub_ssize_t) sizeof (*iph)) + { + grub_dprintf ("net", "IP packet too short: %" PRIdGRUB_SSIZE "\n", + nb->tail - nb->data); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + + err = grub_netbuff_pull (nb, sizeof (*iph)); + if (err) + { + grub_netbuff_free (nb); + return err; + } + + /* Check size. */ + { + grub_size_t expected_size = grub_be_to_cpu16 (iph->len); + grub_size_t actual_size = (nb->tail - nb->data); + if (actual_size > expected_size) + { + err = grub_netbuff_unput (nb, actual_size - expected_size); + if (err) + { + grub_netbuff_free (nb); + return err; + } + } + if (actual_size < expected_size) + { + grub_dprintf ("net", "Cut IP packet actual: %" PRIuGRUB_SIZE + ", expected %" PRIuGRUB_SIZE "\n", actual_size, + expected_size); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + } + + source.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; + dest.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; + grub_memcpy (source.ipv6, &iph->src, sizeof (source.ipv6)); + grub_memcpy (dest.ipv6, &iph->dest, sizeof (dest.ipv6)); + + return handle_dgram (nb, card, src_hwaddress, hwaddress, iph->protocol, + &source, &dest, iph->ttl); +} + +grub_err_t +grub_net_recv_ip_packets (struct grub_net_buff *nb, + struct grub_net_card *card, + const grub_net_link_level_address_t *hwaddress, + const grub_net_link_level_address_t *src_hwaddress) +{ + struct iphdr *iph = (struct iphdr *) nb->data; + + if ((iph->verhdrlen >> 4) == 4) + return grub_net_recv_ip4_packets (nb, card, hwaddress, src_hwaddress); + if ((iph->verhdrlen >> 4) == 6) + return grub_net_recv_ip6_packets (nb, card, hwaddress, src_hwaddress); + grub_dprintf ("net", "Bad IP version: %d\n", (iph->verhdrlen >> 4)); + grub_netbuff_free (nb); return GRUB_ERR_NONE; } diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 09acea900..b749e607d 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include #include @@ -38,6 +40,7 @@ char *grub_net_default_server; struct grub_net_route { struct grub_net_route *next; + struct grub_net_route **prev; grub_net_network_level_netaddress_t target; char *name; struct grub_net_network_level_protocol *prot; @@ -55,6 +58,142 @@ struct grub_net_card *grub_net_cards = NULL; struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL; static struct grub_fs grub_net_fs; +struct grub_net_link_layer_entry { + int avail; + grub_net_network_level_address_t nl_address; + grub_net_link_level_address_t ll_address; +}; + +#define LINK_LAYER_CACHE_SIZE 256 + +static struct grub_net_link_layer_entry * +link_layer_find_entry (const grub_net_network_level_address_t *proto, + const struct grub_net_card *card) +{ + unsigned i; + if (!card->link_layer_table) + return NULL; + for (i = 0; i < LINK_LAYER_CACHE_SIZE; i++) + { + if (card->link_layer_table[i].avail == 1 + && grub_net_addr_cmp (&card->link_layer_table[i].nl_address, + proto) == 0) + return &card->link_layer_table[i]; + } + return NULL; +} + +void +grub_net_link_layer_add_address (struct grub_net_card *card, + const grub_net_network_level_address_t *nl, + const grub_net_link_level_address_t *ll, + int override) +{ + struct grub_net_link_layer_entry *entry; + + /* Check if the sender is in the cache table. */ + entry = link_layer_find_entry (nl, card); + /* Update sender hardware address. */ + if (entry && override) + grub_memcpy (&entry->ll_address, ll, sizeof (entry->ll_address)); + if (entry) + return; + + /* Add sender to cache table. */ + if (card->link_layer_table == NULL) + card->link_layer_table = grub_zalloc (LINK_LAYER_CACHE_SIZE + * sizeof (card->link_layer_table[0])); + entry = &(card->link_layer_table[card->new_ll_entry]); + entry->avail = 1; + grub_memcpy (&entry->ll_address, ll, sizeof (entry->ll_address)); + grub_memcpy (&entry->nl_address, nl, sizeof (entry->nl_address)); + card->new_ll_entry++; + if (card->new_ll_entry == LINK_LAYER_CACHE_SIZE) + card->new_ll_entry = 0; +} + +int +grub_net_link_layer_resolve_check (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *proto_addr) +{ + struct grub_net_link_layer_entry *entry; + + if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 + && proto_addr->ipv4 == 0xffffffff) + return 1; + entry = link_layer_find_entry (proto_addr, inf->card); + if (entry) + return 1; + return 0; +} + +grub_err_t +grub_net_link_layer_resolve (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *proto_addr, + grub_net_link_level_address_t *hw_addr) +{ + struct grub_net_link_layer_entry *entry; + grub_err_t err; + + if ((proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 + && proto_addr->ipv4 == 0xffffffff) + || proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV + || (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6 + && proto_addr->ipv6[0] == grub_be_to_cpu64_compile_time (0xff02ULL + << 48) + && proto_addr->ipv6[1] == (grub_be_to_cpu64_compile_time (1)))) + { + hw_addr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + grub_memset (hw_addr->mac, -1, 6); + return GRUB_ERR_NONE; + } + + if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6 + && ((grub_be_to_cpu64 (proto_addr->ipv6[0]) >> 56) == 0xff)) + { + hw_addr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET; + hw_addr->mac[0] = 0x33; + hw_addr->mac[1] = 0x33; + hw_addr->mac[2] = ((grub_be_to_cpu64 (proto_addr->ipv6[1]) >> 24) & 0xff); + hw_addr->mac[3] = ((grub_be_to_cpu64 (proto_addr->ipv6[1]) >> 16) & 0xff); + hw_addr->mac[4] = ((grub_be_to_cpu64 (proto_addr->ipv6[1]) >> 8) & 0xff); + hw_addr->mac[5] = ((grub_be_to_cpu64 (proto_addr->ipv6[1]) >> 0) & 0xff); + return GRUB_ERR_NONE; + } + + /* Check cache table. */ + entry = link_layer_find_entry (proto_addr, inf->card); + if (entry) + { + *hw_addr = entry->ll_address; + return GRUB_ERR_NONE; + } + switch (proto_addr->type) + { + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: + err = grub_net_arp_send_request (inf, proto_addr); + break; + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6: + err = grub_net_icmp6_send_request (inf, proto_addr); + break; + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV: + return grub_error (GRUB_ERR_BUG, "shouldn't reach here"); + default: + return grub_error (GRUB_ERR_BUG, + "unsupported address type %d", proto_addr->type); + } + if (err) + return err; + entry = link_layer_find_entry (proto_addr, inf->card); + if (entry) + { + *hw_addr = entry->ll_address; + return GRUB_ERR_NONE; + } + return grub_error (GRUB_ERR_TIMEOUT, + N_("timeout: could not resolve hardware address")); +} + void grub_net_card_unregister (struct grub_net_card *card) { @@ -68,10 +207,155 @@ grub_net_card_unregister (struct grub_net_card *card) card->driver->close (card); card->opened = 0; } - grub_list_remove (GRUB_AS_LIST_P (&grub_net_cards), - GRUB_AS_LIST (card)); + grub_list_remove (GRUB_AS_LIST (card)); } +static struct grub_net_slaac_mac_list * +grub_net_ipv6_get_slaac (struct grub_net_card *card, + const grub_net_link_level_address_t *hwaddr) +{ + struct grub_net_slaac_mac_list *slaac; + char *ptr; + + for (slaac = card->slaac_list; slaac; slaac = slaac->next) + if (grub_net_hwaddr_cmp (&slaac->address, hwaddr) == 0) + return slaac; + + slaac = grub_zalloc (sizeof (*slaac)); + if (!slaac) + return NULL; + + slaac->name = grub_malloc (grub_strlen (card->name) + + GRUB_NET_MAX_STR_HWADDR_LEN + + sizeof (":slaac")); + ptr = grub_stpcpy (slaac->name, card->name); + if (grub_net_hwaddr_cmp (&card->default_address, hwaddr) != 0) + { + ptr = grub_stpcpy (ptr, ":"); + grub_net_hwaddr_to_str (hwaddr, ptr); + ptr += grub_strlen (ptr); + } + ptr = grub_stpcpy (ptr, ":slaac"); + + grub_memcpy (&slaac->address, hwaddr, sizeof (slaac->address)); + slaac->next = card->slaac_list; + card->slaac_list = slaac; + return slaac; +} + +struct grub_net_network_level_interface * +grub_net_ipv6_get_link_local (struct grub_net_card *card, + const grub_net_link_level_address_t *hwaddr) +{ + struct grub_net_network_level_interface *inf; + char name[grub_strlen (card->name) + + GRUB_NET_MAX_STR_HWADDR_LEN + + sizeof (":link")]; + char *ptr; + grub_net_network_level_address_t addr; + + addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; + addr.ipv6[0] = grub_cpu_to_be64 (0xfe80ULL << 48); + addr.ipv6[1] = grub_net_ipv6_get_id (hwaddr); + + FOR_NET_NETWORK_LEVEL_INTERFACES (inf) + { + if (inf->card == card + && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddr) == 0 + && grub_net_addr_cmp (&inf->address, &addr) == 0) + return inf; + } + + ptr = grub_stpcpy (name, card->name); + if (grub_net_hwaddr_cmp (&card->default_address, hwaddr) != 0) + { + ptr = grub_stpcpy (ptr, ":"); + grub_net_hwaddr_to_str (hwaddr, ptr); + ptr += grub_strlen (ptr); + } + ptr = grub_stpcpy (ptr, ":link"); + return grub_net_add_addr (name, card, &addr, hwaddr, 0); +} + +/* FIXME: allow to specify mac address. */ +static grub_err_t +grub_cmd_ipv6_autoconf (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_net_card *card; + struct grub_net_network_level_interface **ifaces; + grub_size_t ncards = 0; + unsigned j = 0; + int interval; + grub_err_t err; + struct grub_net_slaac_mac_list **slaacs; + + FOR_NET_CARDS (card) + { + if (argc > 0 && grub_strcmp (card->name, args[0]) != 0) + continue; + ncards++; + } + + ifaces = grub_zalloc (ncards * sizeof (ifaces[0])); + slaacs = grub_zalloc (ncards * sizeof (slaacs[0])); + if (!ifaces || !slaacs) + { + grub_free (ifaces); + grub_free (slaacs); + return grub_errno; + } + + FOR_NET_CARDS (card) + { + if (argc > 0 && grub_strcmp (card->name, args[0]) != 0) + continue; + ifaces[j] = grub_net_ipv6_get_link_local (card, &card->default_address); + if (!ifaces[j]) + { + grub_free (ifaces); + grub_free (slaacs); + return grub_errno; + } + slaacs[j] = grub_net_ipv6_get_slaac (card, &card->default_address); + if (!slaacs[j]) + { + grub_free (ifaces); + grub_free (slaacs); + return grub_errno; + } + j++; + } + + for (interval = 200; interval < 10000; interval *= 2) + { + /* FIXME: send router solicitation. */ + int done = 1; + for (j = 0; j < ncards; j++) + { + if (slaacs[j]->slaac_counter) + continue; + done = 0; + } + if (done) + break; + grub_net_poll_cards (interval); + } + + err = GRUB_ERR_NONE; + for (j = 0; j < ncards; j++) + { + if (slaacs[j]->slaac_counter) + continue; + err = grub_error (GRUB_ERR_FILE_NOT_FOUND, + N_("couldn't autoconfigure %s"), + ifaces[j]->card->name); + } + + grub_free (ifaces); + grub_free (slaacs); + return err; +} static inline void grub_net_route_register (struct grub_net_route *route) @@ -83,8 +367,7 @@ grub_net_route_register (struct grub_net_route *route) static inline void grub_net_route_unregister (struct grub_net_route *route) { - grub_list_remove (GRUB_AS_LIST_P (&grub_net_routes), - GRUB_AS_LIST (route)); + grub_list_remove (GRUB_AS_LIST (route)); } #define FOR_NET_ROUTES(var) for (var = grub_net_routes; var; var = var->next) @@ -93,18 +376,23 @@ static int parse_ip (const char *val, grub_uint32_t *ip, const char **rest) { grub_uint32_t newip = 0; - unsigned long t; int i; const char *ptr = val; for (i = 0; i < 4; i++) { + unsigned long t; t = grub_strtoul (ptr, (char **) &ptr, 0); if (grub_errno) { grub_errno = GRUB_ERR_NONE; return 0; } + if (*ptr != '.' && i == 0) + { + newip = t; + break; + } if (t & ~0xff) return 0; newip >>= 8; @@ -115,7 +403,56 @@ parse_ip (const char *val, grub_uint32_t *ip, const char **rest) } *ip = grub_cpu_to_le32 (newip); if (rest) - *rest = ptr - 1; + *rest = (ptr - 1); + return 1; +} + +static int +parse_ip6 (const char *val, grub_uint64_t *ip, const char **rest) +{ + grub_uint16_t newip[8]; + const char *ptr = val; + int word, quaddot = -1; + + if (ptr[0] == ':' && ptr[1] != ':') + return 0; + if (ptr[0] == ':') + ptr++; + + for (word = 0; word < 8; word++) + { + unsigned long t; + if (*ptr == ':') + { + quaddot = word; + word--; + ptr++; + continue; + } + t = grub_strtoul (ptr, (char **) &ptr, 16); + if (grub_errno) + { + grub_errno = GRUB_ERR_NONE; + break; + } + if (t & ~0xffff) + return 0; + newip[word] = grub_cpu_to_be16 (t); + if (*ptr != ':') + break; + ptr++; + } + if (quaddot == -1 && word < 7) + return 0; + if (quaddot != -1) + { + grub_memmove (&newip[quaddot + 7 - word], &newip[quaddot], + (word - quaddot + 1) * sizeof (newip[0])); + grub_memset (&newip[quaddot], 0, (7 - word) * sizeof (newip[0])); + } + grub_memcpy (ip, newip, 16); + if (rest) + *rest = ptr; return 1; } @@ -131,10 +468,30 @@ match_net (const grub_net_network_level_netaddress_t *net, return 0; case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: { - grub_int32_t mask = ((1 << net->ipv4.masksize) - 1) << (32 - net->ipv4.masksize); + grub_uint32_t mask = (0xffffffffU << (32 - net->ipv4.masksize)); + if (net->ipv4.masksize == 0) + mask = 0; return ((grub_be_to_cpu32 (net->ipv4.base) & mask) == (grub_be_to_cpu32 (addr->ipv4) & mask)); } + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6: + { + grub_uint64_t mask[2]; + if (net->ipv6.masksize <= 64) + { + mask[0] = 0xffffffffffffffffULL << (64 - net->ipv6.masksize); + mask[1] = 0; + } + else + { + mask[0] = 0xffffffffffffffffULL; + mask[1] = 0xffffffffffffffffULL << (128 - net->ipv6.masksize); + } + return (((grub_be_to_cpu64 (net->ipv6.base[0]) & mask[0]) + == (grub_be_to_cpu64 (addr->ipv6[0]) & mask[0])) + && ((grub_be_to_cpu64 (net->ipv6.base[1]) & mask[1]) + == (grub_be_to_cpu64 (addr->ipv6[1]) & mask[1]))); + } } return 0; } @@ -143,13 +500,31 @@ grub_err_t grub_net_resolve_address (const char *name, grub_net_network_level_address_t *addr) { - if (parse_ip (name, &addr->ipv4, NULL)) + const char *rest; + grub_err_t err; + grub_size_t naddresses; + struct grub_net_network_level_address *addresses; + + if (parse_ip (name, &addr->ipv4, &rest) && *rest == 0) { addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; return GRUB_ERR_NONE; } - return grub_error (GRUB_ERR_NET_BAD_ADDRESS, N_("unrecognised address %s"), - name); + if (parse_ip6 (name, addr->ipv6, &rest) && *rest == 0) + { + addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; + return GRUB_ERR_NONE; + } + err = grub_net_dns_lookup (name, 0, 0, &naddresses, &addresses, 1); + if (err) + return err; + if (!naddresses) + grub_error (GRUB_ERR_NET_BAD_ADDRESS, N_("unresolvable address %s"), + name); + /* FIXME: use other results as well. */ + *addr = addresses[0]; + grub_free (addresses); + return GRUB_ERR_NONE; } grub_err_t @@ -162,17 +537,71 @@ grub_net_resolve_net_address (const char *name, addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; if (*rest == '/') { - addr->ipv4.masksize = grub_strtoul (rest + 1, NULL, 0); - if (!grub_errno) - return GRUB_ERR_NONE; + addr->ipv4.masksize = grub_strtoul (rest + 1, (char **) &rest, 0); + if (!grub_errno && *rest == 0) + return GRUB_ERR_NONE; + grub_errno = GRUB_ERR_NONE; + } + else if (*rest == 0) + { + addr->ipv4.masksize = 32; + return GRUB_ERR_NONE; } - addr->ipv4.masksize = 32; - return GRUB_ERR_NONE; } - return grub_error (GRUB_ERR_NET_BAD_ADDRESS, N_("unrecognised address %s"), + if (parse_ip6 (name, addr->ipv6.base, &rest)) + { + addr->type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; + if (*rest == '/') + { + addr->ipv6.masksize = grub_strtoul (rest + 1, (char **) &rest, 0); + if (!grub_errno && *rest == 0) + return GRUB_ERR_NONE; + grub_errno = GRUB_ERR_NONE; + } + else if (*rest == 0) + { + addr->ipv6.masksize = 128; + return GRUB_ERR_NONE; + } + } + return grub_error (GRUB_ERR_NET_BAD_ADDRESS, + N_("unrecognised network address `%s'"), name); } +static int +route_cmp (const struct grub_net_route *a, const struct grub_net_route *b) +{ + if (a == NULL && b == NULL) + return 0; + if (b == NULL) + return +1; + if (a == NULL) + return -1; + if (a->target.type < b->target.type) + return -1; + if (a->target.type > b->target.type) + return +1; + switch (a->target.type) + { + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV: + break; + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6: + if (a->target.ipv6.masksize > b->target.ipv6.masksize) + return +1; + if (a->target.ipv6.masksize < b->target.ipv6.masksize) + return -1; + break; + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: + if (a->target.ipv4.masksize > b->target.ipv4.masksize) + return +1; + if (a->target.ipv4.masksize < b->target.ipv4.masksize) + return -1; + break; + } + return 0; +} + grub_err_t grub_net_route_address (grub_net_network_level_address_t addr, grub_net_network_level_address_t *gateway, @@ -191,28 +620,32 @@ grub_net_route_address (grub_net_network_level_address_t addr, for (depth = 0; depth < routecnt + 2; depth++) { + struct grub_net_route *bestroute = NULL; FOR_NET_ROUTES(route) { if (depth && prot != route->prot) continue; if (!match_net (&route->target, &curtarget)) continue; - - if (route->is_gateway) - { - if (depth == 0) - *gateway = route->gw; - curtarget = route->gw; - break; - } - *interf = route->interface; - return GRUB_ERR_NONE; + if (route_cmp (route, bestroute) > 0) + bestroute = route; } - if (route == NULL) - return grub_error (GRUB_ERR_NET_NO_ROUTE, "destination unreachable"); + if (bestroute == NULL) + return grub_error (GRUB_ERR_NET_NO_ROUTE, + N_("destination unreachable")); + + if (!bestroute->is_gateway) + { + *interf = bestroute->interface; + return GRUB_ERR_NONE; + } + if (depth == 0) + *gateway = bestroute->gw; + curtarget = bestroute->gw; } - return grub_error (GRUB_ERR_NET_ROUTE_LOOP, "route loop detected"); + return grub_error (GRUB_ERR_NET_ROUTE_LOOP, + N_("route loop detected")); } static grub_err_t @@ -247,8 +680,30 @@ grub_net_addr_to_str (const grub_net_network_level_address_t *target, char *buf) switch (target->type) { case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV: - grub_strcpy (buf, "temporary"); + /* TRANSLATORS: it refers to the network address. */ + grub_strcpy (buf, _("temporary")); return; + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6: + { + char *ptr = buf; + grub_uint64_t n = grub_be_to_cpu64 (target->ipv6[0]); + int i; + for (i = 0; i < 4; i++) + { + grub_snprintf (ptr, 6, "%" PRIxGRUB_UINT64_T ":", + (n >> (48 - 16 * i)) & 0xffff); + ptr += grub_strlen (ptr); + } + n = grub_be_to_cpu64 (target->ipv6[1]); + for (i = 0; i < 3; i++) + { + grub_snprintf (ptr, 6, "%" PRIxGRUB_UINT64_T ":", + (n >> (48 - 16 * i)) & 0xffff); + ptr += grub_strlen (ptr); + } + grub_snprintf (ptr, 5, "%" PRIxGRUB_UINT64_T, n & 0xffff); + return; + } case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: { grub_uint32_t n = grub_be_to_cpu32 (target->ipv4); @@ -258,18 +713,13 @@ grub_net_addr_to_str (const grub_net_network_level_address_t *target, char *buf) } return; } - grub_printf ("Unknown address type %d\n", target->type); + grub_snprintf (buf, GRUB_NET_MAX_STR_ADDR_LEN, + "Unknown address type %d", target->type); } -/* - Currently suppoerted adresses: - ethernet: XX:XX:XX:XX:XX:XX - */ -#define MAX_STR_HWADDR_LEN (sizeof ("XX:XX:XX:XX:XX:XX")) - -static void -hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str) +void +grub_net_hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str) { str[0] = 0; switch (addr->type) @@ -280,14 +730,14 @@ hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str) unsigned i; for (ptr = str, i = 0; i < ARRAY_SIZE (addr->mac); i++) { - grub_snprintf (ptr, MAX_STR_HWADDR_LEN - (ptr - str), + grub_snprintf (ptr, GRUB_NET_MAX_STR_HWADDR_LEN - (ptr - str), "%02x:", addr->mac[i] & 0xff); ptr += (sizeof ("XX:") - 1); } return; } } - grub_printf ("Unsupported hw address type %d\n", addr->type); + grub_printf (_("Unsupported hw address type %d\n"), addr->type); } int @@ -303,7 +753,28 @@ grub_net_hwaddr_cmp (const grub_net_link_level_address_t *a, case GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET: return grub_memcmp (a->mac, b->mac, sizeof (a->mac)); } - grub_printf ("Unsupported hw address type %d\n", a->type); + grub_printf (_("Unsupported hw address type %d\n"), a->type); + return 1; +} + +int +grub_net_addr_cmp (const grub_net_network_level_address_t *a, + const grub_net_network_level_address_t *b) +{ + if (a->type < b->type) + return -1; + if (a->type > b->type) + return +1; + switch (a->type) + { + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: + return grub_memcmp (&a->ipv4, &b->ipv4, sizeof (a->ipv4)); + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6: + return grub_memcmp (&a->ipv6, &b->ipv6, sizeof (a->ipv6)); + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV: + return 0; + } + grub_printf (_("Unsupported address type %d\n"), a->type); return 1; } @@ -327,9 +798,9 @@ static void grub_net_network_level_interface_register (struct grub_net_network_level_interface *inter) { { - char buf[MAX_STR_HWADDR_LEN]; + char buf[GRUB_NET_MAX_STR_HWADDR_LEN]; char name[grub_strlen (inter->name) + sizeof ("net__mac")]; - hwaddr_to_str (&inter->hwaddress, buf); + grub_net_hwaddr_to_str (&inter->hwaddress, buf); grub_snprintf (name, sizeof (name), "net_%s_mac", inter->name); grub_env_set (name, buf); grub_register_variable_hook (name, 0, hwaddr_set_env); @@ -355,8 +826,8 @@ grub_net_network_level_interface_register (struct grub_net_network_level_interfa struct grub_net_network_level_interface * grub_net_add_addr (const char *name, struct grub_net_card *card, - grub_net_network_level_address_t addr, - grub_net_link_level_address_t hwaddress, + const grub_net_network_level_address_t *addr, + const grub_net_link_level_address_t *hwaddress, grub_net_interface_flags_t flags) { struct grub_net_network_level_interface *inter; @@ -366,8 +837,8 @@ grub_net_add_addr (const char *name, return NULL; inter->name = grub_strdup (name); - grub_memcpy (&(inter->address), &addr, sizeof (inter->address)); - grub_memcpy (&(inter->hwaddress), &hwaddress, sizeof (inter->hwaddress)); + grub_memcpy (&(inter->address), addr, sizeof (inter->address)); + grub_memcpy (&(inter->hwaddress), hwaddress, sizeof (inter->hwaddress)); inter->flags = flags; inter->card = card; inter->dhcp_ack = NULL; @@ -375,6 +846,43 @@ grub_net_add_addr (const char *name, grub_net_network_level_interface_register (inter); + if (addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) + { + int mask = -1; + grub_uint32_t ip_cpu = grub_be_to_cpu32 (addr->ipv4); + if (!(ip_cpu & 0x80000000)) + mask = 8; + else if (!(ip_cpu & 0x40000000)) + mask = 16; + else if (!(ip_cpu & 0x20000000)) + mask = 24; + else + mask = -1; + if (mask != -1) + { + struct grub_net_route *route; + + route = grub_zalloc (sizeof (*route)); + if (!route) + return NULL; + + route->name = grub_xasprintf ("%s:local", name); + if (!route->name) + { + grub_free (route); + return NULL; + } + + route->target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; + route->target.ipv4.base = grub_cpu_to_be32 (ip_cpu & (0xffffffff << (32 - mask))); + route->target.ipv4.masksize = mask; + route->is_gateway = 0; + route->interface = inter; + + grub_net_route_register (route); + } + } + return inter; } @@ -408,7 +916,7 @@ grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)), if (card->flags & GRUB_NET_CARD_HWADDRESS_IMMUTABLE) flags |= GRUB_NET_INTERFACE_HWADDRESS_IMMUTABLE; - grub_net_add_addr (args[0], card, addr, card->default_address, + grub_net_add_addr (args[0], card, &addr, &card->default_address, flags); return grub_errno; } @@ -430,6 +938,8 @@ grub_cmd_delroute (struct grub_command *cmd __attribute__ ((unused)), *prev = route->next; grub_free (route->name); grub_free (route); + if (!*prev) + break; } return GRUB_ERR_NONE; @@ -496,7 +1006,7 @@ grub_cmd_addroute (struct grub_command *cmd __attribute__ ((unused)), grub_net_network_level_netaddress_t target; if (argc < 3) return grub_error (GRUB_ERR_BAD_ARGUMENT, - N_("At least 3 arguments are expected")); + N_("three arguments expected")); grub_net_resolve_net_address (args[1], &target); @@ -520,7 +1030,7 @@ grub_cmd_addroute (struct grub_command *cmd __attribute__ ((unused)), if (!inter) return grub_error (GRUB_ERR_BAD_ARGUMENT, - N_("unrecognised interface %s"), args[2]); + N_("unrecognised network interface `%s'"), args[2]); return grub_net_add_route (args[0], target, inter); } } @@ -531,8 +1041,9 @@ print_net_address (const grub_net_network_level_netaddress_t *target) switch (target->type) { case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV: - grub_printf ("temporary\n"); - break; + /* TRANSLATORS: it refers to the network address. */ + grub_printf ("%s\n", _("temporary")); + return; case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: { grub_uint32_t n = grub_be_to_cpu32 (target->ipv4.base); @@ -543,8 +1054,18 @@ print_net_address (const grub_net_network_level_netaddress_t *target) target->ipv4.masksize); } return; + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6: + { + char buf[GRUB_NET_MAX_STR_ADDR_LEN]; + struct grub_net_network_level_address base; + base.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; + grub_memcpy (&base.ipv6, &target->ipv6, 16); + grub_net_addr_to_str (&base, buf); + grub_printf ("%s/%d ", buf, target->ipv6.masksize); + } + return; } - grub_printf ("Unknown address type %d\n", target->type); + grub_printf (_("Unknown address type %d\n"), target->type); } static void @@ -585,8 +1106,8 @@ grub_cmd_listcards (struct grub_command *cmd __attribute__ ((unused)), struct grub_net_card *card; FOR_NET_CARDS(card) { - char buf[MAX_STR_HWADDR_LEN]; - hwaddr_to_str (&card->default_address, buf); + char buf[GRUB_NET_MAX_STR_HWADDR_LEN]; + grub_net_hwaddr_to_str (&card->default_address, buf); grub_printf ("%s %s\n", card->name, buf); } return GRUB_ERR_NONE; @@ -600,9 +1121,9 @@ grub_cmd_listaddrs (struct grub_command *cmd __attribute__ ((unused)), struct grub_net_network_level_interface *inf; FOR_NET_NETWORK_LEVEL_INTERFACES (inf) { - char bufh[MAX_STR_HWADDR_LEN]; + char bufh[GRUB_NET_MAX_STR_HWADDR_LEN]; char bufn[GRUB_NET_MAX_STR_ADDR_LEN]; - hwaddr_to_str (&inf->hwaddress, bufh); + grub_net_hwaddr_to_str (&inf->hwaddress, bufh); grub_net_addr_to_str (&inf->address, bufn); grub_printf ("%s %s %s\n", inf->name, bufh, bufn); } @@ -650,7 +1171,8 @@ grub_net_open_real (const char *name) } if (!server) { - grub_error (GRUB_ERR_NET_BAD_ADDRESS, "no server"); + grub_error (GRUB_ERR_NET_BAD_ADDRESS, + N_("no server is specified")); return NULL; } @@ -680,7 +1202,10 @@ grub_net_open_real (const char *name) return ret; } } - grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no such device"); + + /* Restore original error. */ + grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("disk `%s' not found"), + name); return NULL; } @@ -691,7 +1216,7 @@ grub_net_fs_dir (grub_device_t device, const char *path __attribute__ ((unused)) const struct grub_dirhook_info *info) __attribute__ ((unused))) { if (!device->net) - return grub_error (GRUB_ERR_BAD_FS, "invalid extent"); + return grub_error (GRUB_ERR_BUG, "invalid net device"); return GRUB_ERR_NONE; } @@ -764,23 +1289,20 @@ receive_packets (struct grub_net_card *card) /* Maybe should be better have a fixed number of packets for each card and just mark them as used and not used. */ struct grub_net_buff *nb; - grub_ssize_t actual; - nb = grub_netbuff_alloc (1500); + + nb = card->driver->recv (card); if (!nb) { - grub_print_error (); - card->last_poll = grub_get_time_ms (); - return; - } - - actual = card->driver->recv (card, nb); - if (actual < 0) - { - grub_netbuff_free (nb); card->last_poll = grub_get_time_ms (); break; } grub_net_recv_ethernet_packet (nb, card); + if (grub_errno) + { + grub_dprintf ("net", "error receiving: %d: %s\n", grub_errno, + grub_errmsg); + grub_errno = GRUB_ERR_NONE; + } } grub_print_error (); } @@ -796,6 +1318,7 @@ grub_net_poll_cards (unsigned time) while ((grub_get_time_ms () - start_time) < time) receive_packets (card); } + grub_net_tcp_retransmit (); } static void @@ -810,23 +1333,25 @@ grub_net_poll_cards_idle_real (void) || ctime >= card->last_poll + card->idle_poll_delay_ms) receive_packets (card); } + grub_net_tcp_retransmit (); } /* Read from the packets list*/ static grub_ssize_t grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len) { - grub_net_t sock = file->device->net; + grub_net_t net = file->device->net; struct grub_net_buff *nb; char *ptr = buf; grub_size_t amount, total = 0; int try = 0; - while (try <= 3) + + while (try <= GRUB_NET_TRIES) { - while (sock->packs.first) + while (net->packs.first) { try = 0; - nb = sock->packs.first->nb; + nb = net->packs.first->nb; amount = nb->tail - nb->data; if (amount > len) amount = len; @@ -841,7 +1366,7 @@ grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len) if (amount == (grub_size_t) (nb->tail - nb->data)) { grub_netbuff_free (nb); - grub_net_remove_packet (sock->packs.first); + grub_net_remove_packet (net->packs.first); } else nb->data += amount; @@ -849,47 +1374,67 @@ grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len) if (!len) return total; } - if (!sock->eof) + if (!net->eof) { try++; - grub_net_poll_cards (200); + grub_net_poll_cards (GRUB_NET_INTERVAL); } else return total; } - return total; + grub_error (GRUB_ERR_TIMEOUT, N_("timeout reading '%s'"), net->name); + return -1; +} + +static grub_off_t +have_ahead (struct grub_file *file) +{ + grub_net_t net = file->device->net; + grub_off_t ret = net->offset; + struct grub_net_packet *pack; + for (pack = net->packs.first; pack; pack = pack->next) + ret += pack->nb->tail - pack->nb->data; + return ret; } static grub_err_t grub_net_seek_real (struct grub_file *file, grub_off_t offset) { - grub_size_t len = offset - file->device->net->offset; - - if (!len) + if (offset == file->device->net->offset) return GRUB_ERR_NONE; - if (file->device->net->offset > offset) + if (offset > file->device->net->offset) { - grub_err_t err; - while (file->device->net->packs.first) + if (!file->device->net->protocol->seek || have_ahead (file) >= offset) { - grub_netbuff_free (file->device->net->packs.first->nb); - grub_net_remove_packet (file->device->net->packs.first); + grub_net_fs_read_real (file, NULL, + offset - file->device->net->offset); + return grub_errno; } - file->device->net->protocol->close (file); - - file->device->net->packs.first = NULL; - file->device->net->packs.last = NULL; - file->device->net->offset = 0; - file->device->net->eof = 0; - err = file->device->net->protocol->open (file, file->device->net->name); - if (err) - return err; - len = offset; + return file->device->net->protocol->seek (file, offset); } - grub_net_fs_read_real (file, NULL, len); - return GRUB_ERR_NONE; + { + grub_err_t err; + if (file->device->net->protocol->seek) + return file->device->net->protocol->seek (file, offset); + while (file->device->net->packs.first) + { + grub_netbuff_free (file->device->net->packs.first->nb); + grub_net_remove_packet (file->device->net->packs.first); + } + file->device->net->protocol->close (file); + + file->device->net->packs.first = NULL; + file->device->net->packs.last = NULL; + file->device->net->offset = 0; + file->device->net->eof = 0; + err = file->device->net->protocol->open (file, file->device->net->name); + if (err) + return err; + grub_net_fs_read_real (file, NULL, offset); + return grub_errno; + } } static grub_ssize_t @@ -937,17 +1482,22 @@ grub_net_restore_hw (void) return GRUB_ERR_NONE; } -static void *fini_hnd; +static struct grub_preboot *fini_hnd; static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute; static grub_command_t cmd_lsroutes, cmd_lscards; -static grub_command_t cmd_lsaddr; +static grub_command_t cmd_lsaddr, cmd_slaac; GRUB_MOD_INIT(net) { cmd_addaddr = grub_register_command ("net_add_addr", grub_cmd_addaddr, N_("SHORTNAME CARD ADDRESS [HWADDRESS]"), N_("Add a network address.")); + cmd_slaac = grub_register_command ("net_ipv6_autoconf", + grub_cmd_ipv6_autoconf, + N_("[CARD [HWADDRESS]]"), + N_("Perform an IPV6 autoconfiguration")); + cmd_deladdr = grub_register_command ("net_del_addr", grub_cmd_deladdr, N_("SHORTNAME"), N_("Delete a network address.")); @@ -964,8 +1514,8 @@ GRUB_MOD_INIT(net) cmd_lsaddr = grub_register_command ("net_ls_addr", grub_cmd_listaddrs, "", N_("list network addresses")); grub_bootp_init (); + grub_dns_init (); - grub_fs_register (&grub_net_fs); grub_net_open = grub_net_open_real; fini_hnd = grub_loader_register_preboot_hook (grub_net_fini_hw, grub_net_restore_hw, @@ -976,6 +1526,7 @@ GRUB_MOD_INIT(net) GRUB_MOD_FINI(net) { grub_bootp_fini (); + grub_dns_fini (); grub_unregister_command (cmd_addaddr); grub_unregister_command (cmd_deladdr); grub_unregister_command (cmd_addroute); @@ -983,6 +1534,7 @@ GRUB_MOD_FINI(net) grub_unregister_command (cmd_lsroutes); grub_unregister_command (cmd_lscards); grub_unregister_command (cmd_lsaddr); + grub_unregister_command (cmd_slaac); grub_fs_unregister (&grub_net_fs); grub_net_open = NULL; grub_net_fini_hw (0); diff --git a/grub-core/net/netbuff.c b/grub-core/net/netbuff.c index d20104ab0..f957cb9e5 100644 --- a/grub-core/net/netbuff.c +++ b/grub-core/net/netbuff.c @@ -21,13 +21,12 @@ #include #include - grub_err_t grub_netbuff_put (struct grub_net_buff *nb, grub_size_t len) { nb->tail += len; if (nb->tail > nb->end) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "put out of the packet range."); + return grub_error (GRUB_ERR_BUG, "put out of the packet range."); return GRUB_ERR_NONE; } @@ -36,7 +35,7 @@ grub_netbuff_unput (struct grub_net_buff *nb, grub_size_t len) { nb->tail -= len; if (nb->tail < nb->head) - return grub_error (GRUB_ERR_OUT_OF_RANGE, + return grub_error (GRUB_ERR_BUG, "unput out of the packet range."); return GRUB_ERR_NONE; } @@ -46,7 +45,7 @@ grub_netbuff_push (struct grub_net_buff *nb, grub_size_t len) { nb->data -= len; if (nb->data < nb->head) - return grub_error (GRUB_ERR_OUT_OF_RANGE, + return grub_error (GRUB_ERR_BUG, "push out of the packet range."); return GRUB_ERR_NONE; } @@ -56,7 +55,7 @@ grub_netbuff_pull (struct grub_net_buff *nb, grub_size_t len) { nb->data += len; if (nb->data > nb->end) - return grub_error (GRUB_ERR_OUT_OF_RANGE, + return grub_error (GRUB_ERR_BUG, "pull out of the packet range."); return GRUB_ERR_NONE; } @@ -67,7 +66,7 @@ grub_netbuff_reserve (struct grub_net_buff *nb, grub_size_t len) nb->data += len; nb->tail += len; if ((nb->tail > nb->end) || (nb->data > nb->end)) - return grub_error (GRUB_ERR_OUT_OF_RANGE, + return grub_error (GRUB_ERR_BUG, "reserve out of the packet range."); return GRUB_ERR_NONE; } @@ -78,6 +77,8 @@ grub_netbuff_alloc (grub_size_t len) struct grub_net_buff *nb; void *data; + COMPILE_TIME_ASSERT (NETBUFF_ALIGN % sizeof (grub_properly_aligned_t) == 0); + if (len < NETBUFFMINLEN) len = NETBUFFMINLEN; @@ -85,9 +86,10 @@ grub_netbuff_alloc (grub_size_t len) data = grub_memalign (NETBUFF_ALIGN, len + sizeof (*nb)); if (!data) return NULL; - nb = (struct grub_net_buff *) ((grub_uint8_t *) data + len); + nb = (struct grub_net_buff *) ((grub_properly_aligned_t *) data + + len / sizeof (grub_properly_aligned_t)); nb->head = nb->data = nb->tail = data; - nb->end = (char *) nb; + nb->end = (grub_uint8_t *) nb; return nb; } diff --git a/grub-core/net/tcp.c b/grub-core/net/tcp.c new file mode 100644 index 000000000..ae86d2b86 --- /dev/null +++ b/grub-core/net/tcp.c @@ -0,0 +1,977 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +#define TCP_SYN_RETRANSMISSION_TIMEOUT GRUB_NET_INTERVAL +#define TCP_SYN_RETRANSMISSION_COUNT GRUB_NET_TRIES +#define TCP_RETRANSMISSION_TIMEOUT GRUB_NET_INTERVAL +#define TCP_RETRANSMISSION_COUNT GRUB_NET_TRIES + +struct unacked +{ + struct unacked *next; + struct unacked **prev; + struct grub_net_buff *nb; + grub_uint64_t last_try; + int try_count; +}; + +enum + { + TCP_FIN = 0x1, + TCP_SYN = 0x2, + TCP_RST = 0x4, + TCP_PUSH = 0x8, + TCP_ACK = 0x10, + TCP_URG = 0x20, + }; + +struct grub_net_tcp_socket +{ + struct grub_net_tcp_socket *next; + struct grub_net_tcp_socket **prev; + + int established; + int i_closed; + int they_closed; + int in_port; + int out_port; + int errors; + int they_reseted; + int i_reseted; + grub_uint32_t my_start_seq; + grub_uint32_t my_cur_seq; + grub_uint32_t their_start_seq; + grub_uint32_t their_cur_seq; + grub_uint16_t my_window; + struct unacked *unack_first; + struct unacked *unack_last; + grub_err_t (*recv_hook) (grub_net_tcp_socket_t sock, struct grub_net_buff *nb, + void *recv); + void (*error_hook) (grub_net_tcp_socket_t sock, void *recv); + void (*fin_hook) (grub_net_tcp_socket_t sock, void *recv); + void *hook_data; + grub_net_network_level_address_t out_nla; + grub_net_link_level_address_t ll_target_addr; + struct grub_net_network_level_interface *inf; + grub_net_packets_t packs; + grub_priority_queue_t pq; +}; + +struct grub_net_tcp_listen +{ + struct grub_net_tcp_listen *next; + struct grub_net_tcp_listen **prev; + + grub_uint16_t port; + const struct grub_net_network_level_interface *inf; + + grub_err_t (*listen_hook) (grub_net_tcp_listen_t listen, + grub_net_tcp_socket_t sock, + void *data); + void *hook_data; +}; + +struct tcphdr +{ + grub_uint16_t src; + grub_uint16_t dst; + grub_uint32_t seqnr; + grub_uint32_t ack; + grub_uint16_t flags; + grub_uint16_t window; + grub_uint16_t checksum; + grub_uint16_t urgent; +} __attribute__ ((packed)); + +struct tcp_pseudohdr +{ + grub_uint32_t src; + grub_uint32_t dst; + grub_uint8_t zero; + grub_uint8_t proto; + grub_uint16_t tcp_length; +} __attribute__ ((packed)); + +struct tcp6_pseudohdr +{ + grub_uint64_t src[2]; + grub_uint64_t dst[2]; + grub_uint32_t tcp_length; + grub_uint8_t zero[3]; + grub_uint8_t proto; +} __attribute__ ((packed)); + +static struct grub_net_tcp_socket *tcp_sockets; +static struct grub_net_tcp_listen *tcp_listens; + +#define FOR_TCP_SOCKETS(var) FOR_LIST_ELEMENTS (var, tcp_sockets) +#define FOR_TCP_LISTENS(var) FOR_LIST_ELEMENTS (var, tcp_listens) + +grub_net_tcp_listen_t +grub_net_tcp_listen (grub_uint16_t port, + const struct grub_net_network_level_interface *inf, + grub_err_t (*listen_hook) (grub_net_tcp_listen_t listen, + grub_net_tcp_socket_t sock, + void *data), + void *hook_data) +{ + grub_net_tcp_listen_t ret; + ret = grub_malloc (sizeof (*ret)); + if (!ret) + return NULL; + ret->listen_hook = listen_hook; + ret->hook_data = hook_data; + ret->port = port; + ret->inf = inf; + grub_list_push (GRUB_AS_LIST_P (&tcp_listens), GRUB_AS_LIST (ret)); + return ret; +} + +void +grub_net_tcp_stop_listen (grub_net_tcp_listen_t listen) +{ + grub_list_remove (GRUB_AS_LIST (listen)); +} + +static inline void +tcp_socket_register (grub_net_tcp_socket_t sock) +{ + grub_list_push (GRUB_AS_LIST_P (&tcp_sockets), + GRUB_AS_LIST (sock)); +} + +static void +error (grub_net_tcp_socket_t sock) +{ + struct unacked *unack, *next; + + if (sock->error_hook) + sock->error_hook (sock, sock->hook_data); + + for (unack = sock->unack_first; unack; unack = next) + { + next = unack->next; + grub_netbuff_free (unack->nb); + grub_free (unack); + } + + sock->unack_first = NULL; + sock->unack_last = NULL; +} + +static grub_err_t +tcp_send (struct grub_net_buff *nb, grub_net_tcp_socket_t socket) +{ + grub_err_t err; + grub_uint8_t *nbd; + struct unacked *unack; + struct tcphdr *tcph; + grub_size_t size; + + tcph = (struct tcphdr *) nb->data; + + tcph->seqnr = grub_cpu_to_be32 (socket->my_cur_seq); + size = (nb->tail - nb->data - (grub_be_to_cpu16 (tcph->flags) >> 12) * 4); + if (grub_be_to_cpu16 (tcph->flags) & TCP_FIN) + size++; + socket->my_cur_seq += size; + tcph->src = grub_cpu_to_be16 (socket->in_port); + tcph->dst = grub_cpu_to_be16 (socket->out_port); + tcph->checksum = 0; + tcph->checksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_TCP, + &socket->inf->address, + &socket->out_nla); + nbd = nb->data; + if (size) + { + unack = grub_malloc (sizeof (*unack)); + if (!unack) + return grub_errno; + + unack->next = NULL; + unack->nb = nb; + unack->try_count = 1; + unack->last_try = grub_get_time_ms (); + if (!socket->unack_last) + socket->unack_first = socket->unack_last = unack; + else + socket->unack_last->next = unack; + } + + err = grub_net_send_ip_packet (socket->inf, &(socket->out_nla), + &(socket->ll_target_addr), nb, + GRUB_NET_IP_TCP); + if (err) + return err; + nb->data = nbd; + if (!size) + grub_netbuff_free (nb); + return GRUB_ERR_NONE; +} + +void +grub_net_tcp_close (grub_net_tcp_socket_t sock, + int discard_received) +{ + struct grub_net_buff *nb_fin; + struct tcphdr *tcph_fin; + grub_err_t err; + + if (discard_received != GRUB_NET_TCP_CONTINUE_RECEIVING) + { + sock->recv_hook = NULL; + sock->error_hook = NULL; + sock->fin_hook = NULL; + } + + if (discard_received == GRUB_NET_TCP_ABORT) + sock->i_reseted = 1; + + if (sock->i_closed) + return; + + sock->i_closed = 1; + + nb_fin = grub_netbuff_alloc (sizeof (*tcph_fin) + + GRUB_NET_OUR_MAX_IP_HEADER_SIZE + + GRUB_NET_MAX_LINK_HEADER_SIZE); + if (!nb_fin) + return; + err = grub_netbuff_reserve (nb_fin, GRUB_NET_OUR_MAX_IP_HEADER_SIZE + + GRUB_NET_MAX_LINK_HEADER_SIZE); + if (err) + { + grub_netbuff_free (nb_fin); + grub_dprintf ("net", "error closing socket\n"); + grub_errno = GRUB_ERR_NONE; + return; + } + + err = grub_netbuff_put (nb_fin, sizeof (*tcph_fin)); + if (err) + { + grub_netbuff_free (nb_fin); + grub_dprintf ("net", "error closing socket\n"); + grub_errno = GRUB_ERR_NONE; + return; + } + tcph_fin = (void *) nb_fin->data; + tcph_fin->ack = grub_cpu_to_be32 (sock->their_cur_seq); + tcph_fin->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_FIN + | TCP_ACK); + tcph_fin->window = grub_cpu_to_be16_compile_time (0); + tcph_fin->urgent = 0; + err = tcp_send (nb_fin, sock); + if (err) + { + grub_netbuff_free (nb_fin); + grub_dprintf ("net", "error closing socket\n"); + grub_errno = GRUB_ERR_NONE; + } + return; +} + +static void +ack_real (grub_net_tcp_socket_t sock, int res) +{ + struct grub_net_buff *nb_ack; + struct tcphdr *tcph_ack; + grub_err_t err; + + nb_ack = grub_netbuff_alloc (sizeof (*tcph_ack) + 128); + if (!nb_ack) + return; + err = grub_netbuff_reserve (nb_ack, 128); + if (err) + { + grub_netbuff_free (nb_ack); + grub_dprintf ("net", "error closing socket\n"); + grub_errno = GRUB_ERR_NONE; + return; + } + + err = grub_netbuff_put (nb_ack, sizeof (*tcph_ack)); + if (err) + { + grub_netbuff_free (nb_ack); + grub_dprintf ("net", "error closing socket\n"); + grub_errno = GRUB_ERR_NONE; + return; + } + tcph_ack = (void *) nb_ack->data; + if (res) + { + tcph_ack->ack = grub_cpu_to_be32_compile_time (0); + tcph_ack->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_RST); + tcph_ack->window = grub_cpu_to_be16_compile_time (0); + } + else + { + tcph_ack->ack = grub_cpu_to_be32 (sock->their_cur_seq); + tcph_ack->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_ACK); + tcph_ack->window = grub_cpu_to_be16 (sock->my_window); + } + tcph_ack->urgent = 0; + tcph_ack->src = grub_cpu_to_be16 (sock->in_port); + tcph_ack->dst = grub_cpu_to_be16 (sock->out_port); + err = tcp_send (nb_ack, sock); + if (err) + { + grub_dprintf ("net", "error acking socket\n"); + grub_errno = GRUB_ERR_NONE; + } +} + +static void +ack (grub_net_tcp_socket_t sock) +{ + ack_real (sock, 0); +} + +static void +reset (grub_net_tcp_socket_t sock) +{ + ack_real (sock, 1); +} + +void +grub_net_tcp_retransmit (void) +{ + grub_net_tcp_socket_t sock; + grub_uint64_t ctime = grub_get_time_ms (); + grub_uint64_t limit_time = ctime - TCP_RETRANSMISSION_TIMEOUT; + + FOR_TCP_SOCKETS (sock) + { + struct unacked *unack; + for (unack = sock->unack_first; unack; unack = unack->next) + { + struct tcphdr *tcph; + grub_uint8_t *nbd; + grub_err_t err; + + if (unack->last_try > limit_time) + continue; + + if (unack->try_count > TCP_RETRANSMISSION_COUNT) + { + error (sock); + break; + } + unack->try_count++; + unack->last_try = ctime; + nbd = unack->nb->data; + tcph = (struct tcphdr *) nbd; + + if ((tcph->flags & grub_cpu_to_be16_compile_time (TCP_ACK)) + && tcph->ack != grub_cpu_to_be32 (sock->their_cur_seq)) + { + tcph->checksum = 0; + tcph->checksum = grub_net_ip_transport_checksum (unack->nb, + GRUB_NET_IP_TCP, + &sock->inf->address, + &sock->out_nla); + } + + err = grub_net_send_ip_packet (sock->inf, &(sock->out_nla), + &(sock->ll_target_addr), unack->nb, + GRUB_NET_IP_TCP); + unack->nb->data = nbd; + if (err) + { + grub_dprintf ("net", "TCP retransmit failed: %s\n", grub_errmsg); + grub_errno = GRUB_ERR_NONE; + } + } + } +} + +grub_uint16_t +grub_net_ip_transport_checksum (struct grub_net_buff *nb, + grub_uint16_t proto, + const grub_net_network_level_address_t *src, + const grub_net_network_level_address_t *dst) +{ + grub_uint16_t a, b = 0; + grub_uint32_t c; + a = ~grub_be_to_cpu16 (grub_net_ip_chksum ((void *) nb->data, + nb->tail - nb->data)); + + switch (dst->type) + { + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4: + { + struct tcp_pseudohdr ph; + ph.src = src->ipv4; + ph.dst = dst->ipv4; + ph.zero = 0; + ph.tcp_length = grub_cpu_to_be16 (nb->tail - nb->data); + ph.proto = proto; + b = ~grub_be_to_cpu16 (grub_net_ip_chksum ((void *) &ph, sizeof (ph))); + break; + } + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6: + { + struct tcp6_pseudohdr ph; + grub_memcpy (ph.src, src->ipv6, sizeof (ph.src)); + grub_memcpy (ph.dst, dst->ipv6, sizeof (ph.dst)); + grub_memset (ph.zero, 0, sizeof (ph.zero)); + ph.tcp_length = grub_cpu_to_be32 (nb->tail - nb->data); + ph.proto = proto; + b = ~grub_be_to_cpu16 (grub_net_ip_chksum ((void *) &ph, sizeof (ph))); + break; + } + case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV: + b = 0; + break; + } + c = (grub_uint32_t) a + (grub_uint32_t) b; + if (c >= 0xffff) + c -= 0xffff; + return grub_cpu_to_be16 (~c); +} + +/* FIXME: overflow. */ +static int +cmp (const void *a__, const void *b__) +{ + struct grub_net_buff *a_ = *(struct grub_net_buff **) a__; + struct grub_net_buff *b_ = *(struct grub_net_buff **) b__; + struct tcphdr *a = (struct tcphdr *) a_->data; + struct tcphdr *b = (struct tcphdr *) b_->data; + /* We want the first elements to be on top. */ + if (grub_be_to_cpu32 (a->seqnr) < grub_be_to_cpu32 (b->seqnr)) + return +1; + if (grub_be_to_cpu32 (a->seqnr) > grub_be_to_cpu32 (b->seqnr)) + return -1; + return 0; +} + +static void +destroy_pq (grub_net_tcp_socket_t sock) +{ + struct grub_net_buff **nb_p; + while ((nb_p = grub_priority_queue_top (sock->pq))) + { + grub_netbuff_free (*nb_p); + grub_priority_queue_pop (sock->pq); + } + + grub_priority_queue_destroy (sock->pq); +} + +grub_err_t +grub_net_tcp_accept (grub_net_tcp_socket_t sock, + grub_err_t (*recv_hook) (grub_net_tcp_socket_t sock, + struct grub_net_buff *nb, + void *data), + void (*error_hook) (grub_net_tcp_socket_t sock, + void *data), + void (*fin_hook) (grub_net_tcp_socket_t sock, + void *data), + void *hook_data) +{ + struct grub_net_buff *nb_ack; + struct tcphdr *tcph; + grub_err_t err; + + sock->recv_hook = recv_hook; + sock->error_hook = error_hook; + sock->fin_hook = fin_hook; + sock->hook_data = hook_data; + nb_ack = grub_netbuff_alloc (sizeof (*tcph) + + GRUB_NET_OUR_MAX_IP_HEADER_SIZE + + GRUB_NET_MAX_LINK_HEADER_SIZE); + if (!nb_ack) + return grub_errno; + err = grub_netbuff_reserve (nb_ack, GRUB_NET_OUR_MAX_IP_HEADER_SIZE + + GRUB_NET_MAX_LINK_HEADER_SIZE); + if (err) + { + grub_netbuff_free (nb_ack); + return err; + } + + err = grub_netbuff_put (nb_ack, sizeof (*tcph)); + if (err) + { + grub_netbuff_free (nb_ack); + return err; + } + tcph = (void *) nb_ack->data; + tcph->ack = grub_cpu_to_be32 (sock->their_cur_seq); + tcph->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_SYN | TCP_ACK); + tcph->window = grub_cpu_to_be16 (sock->my_window); + tcph->urgent = 0; + sock->established = 1; + tcp_socket_register (sock); + err = tcp_send (nb_ack, sock); + if (err) + return err; + sock->my_cur_seq++; + return GRUB_ERR_NONE; +} + +grub_net_tcp_socket_t +grub_net_tcp_open (char *server, + grub_uint16_t out_port, + grub_err_t (*recv_hook) (grub_net_tcp_socket_t sock, + struct grub_net_buff *nb, + void *data), + void (*error_hook) (grub_net_tcp_socket_t sock, + void *data), + void (*fin_hook) (grub_net_tcp_socket_t sock, + void *data), + void *hook_data) +{ + grub_err_t err; + grub_net_network_level_address_t addr; + struct grub_net_network_level_interface *inf; + grub_net_network_level_address_t gateway; + grub_net_tcp_socket_t socket; + static grub_uint16_t in_port = 21550; + struct grub_net_buff *nb; + struct tcphdr *tcph; + int i; + grub_uint8_t *nbd; + grub_net_link_level_address_t ll_target_addr; + + err = grub_net_resolve_address (server, &addr); + if (err) + return NULL; + + if (addr.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 + && addr.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6) + { + grub_error (GRUB_ERR_BUG, "not an IP address"); + return NULL; + } + + err = grub_net_route_address (addr, &gateway, &inf); + if (err) + return NULL; + + err = grub_net_link_layer_resolve (inf, &gateway, &ll_target_addr); + if (err) + return NULL; + + socket = grub_zalloc (sizeof (*socket)); + if (socket == NULL) + return NULL; + + socket->out_port = out_port; + socket->inf = inf; + socket->out_nla = addr; + socket->ll_target_addr = ll_target_addr; + socket->in_port = in_port++; + socket->recv_hook = recv_hook; + socket->error_hook = error_hook; + socket->fin_hook = fin_hook; + socket->hook_data = hook_data; + + nb = grub_netbuff_alloc (sizeof (*tcph) + 128); + if (!nb) + return NULL; + err = grub_netbuff_reserve (nb, 128); + if (err) + { + grub_netbuff_free (nb); + return NULL; + } + + err = grub_netbuff_put (nb, sizeof (*tcph)); + if (err) + { + grub_netbuff_free (nb); + return NULL; + } + socket->pq = grub_priority_queue_new (sizeof (struct grub_net_buff *), cmp); + if (!socket->pq) + { + grub_netbuff_free (nb); + return NULL; + } + + tcph = (void *) nb->data; + socket->my_start_seq = grub_get_time_ms (); + socket->my_cur_seq = socket->my_start_seq + 1; + socket->my_window = 8192; + tcph->seqnr = grub_cpu_to_be32 (socket->my_start_seq); + tcph->ack = grub_cpu_to_be32_compile_time (0); + tcph->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_SYN); + tcph->window = grub_cpu_to_be16 (socket->my_window); + tcph->urgent = 0; + tcph->src = grub_cpu_to_be16 (socket->in_port); + tcph->dst = grub_cpu_to_be16 (socket->out_port); + tcph->checksum = 0; + tcph->checksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_TCP, + &socket->inf->address, + &socket->out_nla); + + tcp_socket_register (socket); + + nbd = nb->data; + for (i = 0; i < TCP_SYN_RETRANSMISSION_COUNT; i++) + { + int j; + nb->data = nbd; + err = grub_net_send_ip_packet (socket->inf, &(socket->out_nla), + &(socket->ll_target_addr), nb, + GRUB_NET_IP_TCP); + if (err) + { + grub_list_remove (GRUB_AS_LIST (socket)); + grub_free (socket); + grub_netbuff_free (nb); + return NULL; + } + for (j = 0; (j < TCP_SYN_RETRANSMISSION_TIMEOUT / 50 + && !socket->established); j++) + grub_net_poll_cards (50); + if (socket->established) + break; + } + if (!socket->established) + { + grub_list_remove (GRUB_AS_LIST (socket)); + if (socket->they_reseted) + grub_error (GRUB_ERR_NET_PORT_CLOSED, + N_("connection refused")); + else + grub_error (GRUB_ERR_NET_NO_ANSWER, + N_("connection timeout")); + + grub_netbuff_free (nb); + destroy_pq (socket); + grub_free (socket); + return NULL; + } + + grub_netbuff_free (nb); + return socket; +} + +grub_err_t +grub_net_send_tcp_packet (const grub_net_tcp_socket_t socket, + struct grub_net_buff *nb, int push) +{ + struct tcphdr *tcph; + grub_err_t err; + grub_ssize_t fraglen; + COMPILE_TIME_ASSERT (sizeof (struct tcphdr) == GRUB_NET_TCP_HEADER_SIZE); + if (socket->out_nla.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4) + fraglen = (socket->inf->card->mtu - GRUB_NET_OUR_IPV4_HEADER_SIZE + - sizeof (*tcph)); + else + fraglen = 1280 - GRUB_NET_OUR_IPV6_HEADER_SIZE; + + while (nb->tail - nb->data > fraglen) + { + struct grub_net_buff *nb2; + + nb2 = grub_netbuff_alloc (fraglen + sizeof (*tcph) + + GRUB_NET_OUR_MAX_IP_HEADER_SIZE + + GRUB_NET_MAX_LINK_HEADER_SIZE); + if (!nb2) + return grub_errno; + err = grub_netbuff_reserve (nb2, GRUB_NET_MAX_LINK_HEADER_SIZE + + GRUB_NET_OUR_MAX_IP_HEADER_SIZE); + if (err) + return err; + err = grub_netbuff_put (nb2, sizeof (*tcph)); + if (err) + return err; + + tcph = (struct tcphdr *) nb2->data; + tcph->ack = grub_cpu_to_be32 (socket->their_cur_seq); + tcph->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_ACK); + tcph->window = grub_cpu_to_be16 (socket->my_window); + tcph->urgent = 0; + err = grub_netbuff_put (nb2, fraglen); + if (err) + return err; + grub_memcpy (tcph + 1, nb->data, fraglen); + err = grub_netbuff_pull (nb, fraglen); + if (err) + return err; + + err = tcp_send (nb2, socket); + if (err) + return err; + } + + err = grub_netbuff_push (nb, sizeof (*tcph)); + if (err) + return err; + + tcph = (struct tcphdr *) nb->data; + tcph->ack = grub_cpu_to_be32 (socket->their_cur_seq); + tcph->flags = (grub_cpu_to_be16_compile_time ((5 << 12) | TCP_ACK) + | (push ? grub_cpu_to_be16_compile_time (TCP_PUSH) : 0)); + tcph->window = grub_cpu_to_be16 (socket->my_window); + tcph->urgent = 0; + return tcp_send (nb, socket); +} + +grub_err_t +grub_net_recv_tcp_packet (struct grub_net_buff *nb, + struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *source) +{ + struct tcphdr *tcph; + grub_net_tcp_socket_t sock; + grub_err_t err; + + /* Ignore broadcast. */ + if (!inf) + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + + tcph = (struct tcphdr *) nb->data; + if ((grub_be_to_cpu16 (tcph->flags) >> 12) < 5) + { + grub_dprintf ("net", "TCP header too short: %u\n", + grub_be_to_cpu16 (tcph->flags) >> 12); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + if (nb->tail - nb->data < (grub_ssize_t) ((grub_be_to_cpu16 (tcph->flags) + >> 12) * sizeof (grub_uint32_t))) + { + grub_dprintf ("net", "TCP packet too short: %" PRIuGRUB_SIZE "\n", + nb->tail - nb->data); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + + FOR_TCP_SOCKETS (sock) + { + if (!(grub_be_to_cpu16 (tcph->dst) == sock->in_port + && grub_be_to_cpu16 (tcph->src) == sock->out_port + && inf == sock->inf + && grub_net_addr_cmp (source, &sock->out_nla) == 0)) + continue; + if (tcph->checksum) + { + grub_uint16_t chk, expected; + chk = tcph->checksum; + tcph->checksum = 0; + expected = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_TCP, + &sock->out_nla, + &sock->inf->address); + if (expected != chk) + { + grub_dprintf ("net", "Invalid TCP checksum. " + "Expected %x, got %x\n", + grub_be_to_cpu16 (expected), + grub_be_to_cpu16 (chk)); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + tcph->checksum = chk; + } + + if ((grub_be_to_cpu16 (tcph->flags) & TCP_SYN) + && (grub_be_to_cpu16 (tcph->flags) & TCP_ACK) + && !sock->established) + { + sock->their_start_seq = grub_be_to_cpu32 (tcph->seqnr); + sock->their_cur_seq = sock->their_start_seq + 1; + sock->established = 1; + } + + if (grub_be_to_cpu16 (tcph->flags) & TCP_RST) + { + sock->they_reseted = 1; + + error (sock); + + grub_netbuff_free (nb); + + return GRUB_ERR_NONE; + } + + if (grub_be_to_cpu16 (tcph->flags) & TCP_ACK) + { + struct unacked *unack, *next; + grub_uint32_t acked = grub_be_to_cpu32 (tcph->ack); + for (unack = sock->unack_first; unack; unack = next) + { + grub_uint32_t seqnr; + struct tcphdr *unack_tcph; + next = unack->next; + seqnr = grub_be_to_cpu32 (((struct tcphdr *) unack->nb->data) + ->seqnr); + unack_tcph = (struct tcphdr *) unack->nb->data; + seqnr += (unack->nb->tail - unack->nb->data + - (grub_be_to_cpu16 (unack_tcph->flags) >> 12) * 4); + if (grub_be_to_cpu16 (unack_tcph->flags) & TCP_FIN) + seqnr++; + + if (seqnr > acked) + break; + grub_netbuff_free (unack->nb); + grub_free (unack); + } + sock->unack_first = unack; + if (!sock->unack_first) + sock->unack_last = NULL; + } + + if (grub_be_to_cpu32 (tcph->seqnr) < sock->their_cur_seq) + { + ack (sock); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + if (sock->i_reseted && (nb->tail - nb->data + - (grub_be_to_cpu16 (tcph->flags) + >> 12) * sizeof (grub_uint32_t)) > 0) + { + reset (sock); + } + + err = grub_priority_queue_push (sock->pq, &nb); + if (err) + { + grub_netbuff_free (nb); + return err; + } + + { + struct grub_net_buff **nb_top_p, *nb_top; + int do_ack = 0; + int just_closed = 0; + while (1) + { + nb_top_p = grub_priority_queue_top (sock->pq); + if (!nb_top_p) + return GRUB_ERR_NONE; + nb_top = *nb_top_p; + tcph = (struct tcphdr *) nb_top->data; + if (grub_be_to_cpu32 (tcph->seqnr) >= sock->their_cur_seq) + break; + grub_netbuff_free (nb_top); + grub_priority_queue_pop (sock->pq); + } + if (grub_be_to_cpu32 (tcph->seqnr) != sock->their_cur_seq) + return GRUB_ERR_NONE; + while (1) + { + nb_top_p = grub_priority_queue_top (sock->pq); + if (!nb_top_p) + break; + nb_top = *nb_top_p; + tcph = (struct tcphdr *) nb_top->data; + + if (grub_be_to_cpu32 (tcph->seqnr) != sock->their_cur_seq) + break; + grub_priority_queue_pop (sock->pq); + + err = grub_netbuff_pull (nb_top, (grub_be_to_cpu16 (tcph->flags) + >> 12) * sizeof (grub_uint32_t)); + if (err) + { + grub_netbuff_free (nb_top); + return err; + } + + sock->their_cur_seq += (nb_top->tail - nb_top->data); + if (grub_be_to_cpu16 (tcph->flags) & TCP_FIN) + { + sock->they_closed = 1; + just_closed = 1; + sock->their_cur_seq++; + do_ack = 1; + } + /* If there is data, puts packet in socket list. */ + if ((nb_top->tail - nb_top->data) > 0) + { + grub_net_put_packet (&sock->packs, nb_top); + do_ack = 1; + } + else + grub_netbuff_free (nb); + } + if (do_ack) + ack (sock); + while (sock->packs.first) + { + nb = sock->packs.first->nb; + if (sock->recv_hook) + sock->recv_hook (sock, sock->packs.first->nb, sock->hook_data); + else + grub_netbuff_free (nb); + grub_net_remove_packet (sock->packs.first); + } + + if (sock->fin_hook && just_closed) + sock->fin_hook (sock, sock->hook_data); + } + + return GRUB_ERR_NONE; + } + if (grub_be_to_cpu16 (tcph->flags) & TCP_SYN) + { + grub_net_tcp_listen_t listen; + + FOR_TCP_LISTENS (listen) + { + if (!(grub_be_to_cpu16 (tcph->dst) == listen->port + && (inf == listen->inf || listen->inf == NULL))) + continue; + sock = grub_zalloc (sizeof (*sock)); + if (sock == NULL) + return grub_errno; + + sock->out_port = grub_be_to_cpu16 (tcph->src); + sock->in_port = grub_be_to_cpu16 (tcph->dst); + sock->inf = inf; + sock->out_nla = *source; + sock->their_start_seq = grub_be_to_cpu32 (tcph->seqnr); + sock->their_cur_seq = sock->their_start_seq + 1; + sock->my_cur_seq = sock->my_start_seq = grub_get_time_ms (); + sock->my_window = 8192; + + sock->pq = grub_priority_queue_new (sizeof (struct grub_net_buff *), + cmp); + if (!sock->pq) + { + grub_netbuff_free (nb); + return grub_errno; + } + + err = listen->listen_hook (listen, sock, listen->hook_data); + + grub_netbuff_free (nb); + return err; + + } + } + grub_netbuff_free (nb); + return GRUB_ERR_NONE; +} diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c index be1534021..1992b8bfe 100644 --- a/grub-core/net/tftp.c +++ b/grub-core/net/tftp.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -40,7 +42,6 @@ enum enum { TFTP_DEFAULTSIZE_PACKET = 512, - TFTP_MAX_PACKET = 1432 }; enum @@ -80,7 +81,7 @@ struct tftphdr { grub_int8_t rrq[TFTP_DEFAULTSIZE_PACKET]; struct { grub_uint16_t block; - grub_int8_t download[TFTP_MAX_PACKET]; + grub_int8_t download[0]; } data; struct { grub_uint16_t block; @@ -102,24 +103,67 @@ typedef struct tftp_data grub_uint64_t block; grub_uint32_t block_size; int have_oack; - grub_net_socket_t sock; + struct grub_error_saved save_err; + grub_net_udp_socket_t sock; + grub_priority_queue_t pq; } *tftp_data_t; +static int +cmp (const void *a__, const void *b__) +{ + struct grub_net_buff *a_ = *(struct grub_net_buff **) a__; + struct grub_net_buff *b_ = *(struct grub_net_buff **) b__; + struct tftphdr *a = (struct tftphdr *) a_->data; + struct tftphdr *b = (struct tftphdr *) b_->data; + /* We want the first elements to be on top. */ + if (grub_be_to_cpu16 (a->u.data.block) < grub_be_to_cpu16 (b->u.data.block)) + return +1; + if (grub_be_to_cpu16 (a->u.data.block) > grub_be_to_cpu16 (b->u.data.block)) + return -1; + return 0; +} + static grub_err_t -tftp_receive (grub_net_socket_t sock __attribute__ ((unused)), +ack (grub_net_udp_socket_t sock, grub_uint16_t block) +{ + struct tftphdr *tftph_ack; + grub_uint8_t nbdata[512]; + struct grub_net_buff nb_ack; + grub_err_t err; + + nb_ack.head = nbdata; + nb_ack.end = nbdata + sizeof (nbdata); + grub_netbuff_clear (&nb_ack); + grub_netbuff_reserve (&nb_ack, 512); + err = grub_netbuff_push (&nb_ack, sizeof (tftph_ack->opcode) + + sizeof (tftph_ack->u.ack.block)); + if (err) + return err; + + tftph_ack = (struct tftphdr *) nb_ack.data; + tftph_ack->opcode = grub_cpu_to_be16 (TFTP_ACK); + tftph_ack->u.ack.block = block; + + err = grub_net_send_udp_packet (sock, &nb_ack); + return err; +} + +static grub_err_t +tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)), struct grub_net_buff *nb, void *f) { grub_file_t file = f; struct tftphdr *tftph = (void *) nb->data; - char nbdata[512]; tftp_data_t data = file->data; grub_err_t err; - char *ptr; - struct grub_net_buff nb_ack; + grub_uint8_t *ptr; - nb_ack.head = nbdata; - nb_ack.end = nbdata + sizeof (nbdata); + if (nb->tail - nb->data < (grub_ssize_t) sizeof (tftph->opcode)) + { + grub_dprintf ("tftp", "TFTP packet too small\n"); + return GRUB_ERR_NONE; + } tftph = (struct tftphdr *) nb->data; switch (grub_be_to_cpu16 (tftph->opcode)) @@ -130,76 +174,104 @@ tftp_receive (grub_net_socket_t sock __attribute__ ((unused)), for (ptr = nb->data + sizeof (tftph->opcode); ptr < nb->tail;) { if (grub_memcmp (ptr, "tsize\0", sizeof ("tsize\0") - 1) == 0) - { - data->file_size = grub_strtoul (ptr + sizeof ("tsize\0") - 1, - 0, 0); - } + data->file_size = grub_strtoul ((char *) ptr + sizeof ("tsize\0") + - 1, 0, 0); if (grub_memcmp (ptr, "blksize\0", sizeof ("blksize\0") - 1) == 0) - { - data->block_size = grub_strtoul (ptr + sizeof ("blksize\0") - 1, - 0, 0); - } + data->block_size = grub_strtoul ((char *) ptr + sizeof ("blksize\0") + - 1, 0, 0); while (ptr < nb->tail && *ptr) ptr++; ptr++; } data->block = 0; grub_netbuff_free (nb); - break; + err = ack (data->sock, 0); + grub_error_save (&data->save_err); + return GRUB_ERR_NONE; case TFTP_DATA: - err = grub_netbuff_pull (nb, sizeof (tftph->opcode) + - sizeof (tftph->u.data.block)); - if (err) - return err; - if (grub_be_to_cpu16 (tftph->u.data.block) == data->block + 1) + if (nb->tail - nb->data < (grub_ssize_t) (sizeof (tftph->opcode) + + sizeof (tftph->u.data.block))) { - unsigned size = nb->tail - nb->data; - data->block++; - if (size < data->block_size) - { - file->device->net->eof = 1; - } - /* Prevent garbage in broken cards. */ - if (size > data->block_size) - { - err = grub_netbuff_unput (nb, size - data->block_size); - if (err) - return err; - } - /* If there is data, puts packet in socket list. */ - if ((nb->tail - nb->data) > 0) - grub_net_put_packet (&file->device->net->packs, nb); - else - grub_netbuff_free (nb); - } - else - { - grub_netbuff_free (nb); + grub_dprintf ("tftp", "TFTP packet too small\n"); return GRUB_ERR_NONE; } - break; + err = ack (data->sock, tftph->u.data.block); + if (err) + return err; + + err = grub_priority_queue_push (data->pq, &nb); + if (err) + return err; + + { + struct grub_net_buff **nb_top_p, *nb_top; + while (1) + { + nb_top_p = grub_priority_queue_top (data->pq); + if (!nb_top_p) + return GRUB_ERR_NONE; + nb_top = *nb_top_p; + tftph = (struct tftphdr *) nb_top->data; + if (grub_be_to_cpu16 (tftph->u.data.block) >= data->block + 1) + break; + grub_priority_queue_pop (data->pq); + } + if (grub_be_to_cpu16 (tftph->u.data.block) == data->block + 1) + { + unsigned size; + + grub_priority_queue_pop (data->pq); + + err = grub_netbuff_pull (nb_top, sizeof (tftph->opcode) + + sizeof (tftph->u.data.block)); + if (err) + return err; + size = nb_top->tail - nb_top->data; + + data->block++; + if (size < data->block_size) + { + file->device->net->eof = 1; + grub_net_udp_close (data->sock); + data->sock = NULL; + } + /* Prevent garbage in broken cards. Is it still necessary + given that IP implementation has been fixed? + */ + if (size > data->block_size) + { + err = grub_netbuff_unput (nb_top, size - data->block_size); + if (err) + return err; + } + /* If there is data, puts packet in socket list. */ + if ((nb_top->tail - nb_top->data) > 0) + grub_net_put_packet (&file->device->net->packs, nb_top); + else + grub_netbuff_free (nb); + } + } + return GRUB_ERR_NONE; case TFTP_ERROR: + data->have_oack = 1; grub_netbuff_free (nb); - return grub_error (GRUB_ERR_IO, (char *) tftph->u.err.errmsg); + grub_error (GRUB_ERR_IO, (char *) tftph->u.err.errmsg); + grub_error_save (&data->save_err); + return GRUB_ERR_NONE; + default: + grub_netbuff_free (nb); + return GRUB_ERR_NONE; } - grub_netbuff_clear (&nb_ack); - grub_netbuff_reserve (&nb_ack, 512); - err = grub_netbuff_push (&nb_ack, sizeof (tftph->opcode) - + sizeof (tftph->u.ack.block)); - if (err) - return err; +} - tftph = (struct tftphdr *) nb_ack.data; - tftph->opcode = grub_cpu_to_be16 (TFTP_ACK); - tftph->u.ack.block = grub_cpu_to_be16 (data->block); +static void +destroy_pq (tftp_data_t data) +{ + struct grub_net_buff **nb_p; + while ((nb_p = grub_priority_queue_top (data->pq))) + grub_netbuff_free (*nb_p); - err = grub_net_send_udp_packet (data->sock, &nb_ack); - if (file->device->net->eof) - { - grub_net_udp_close (data->sock); - data->sock = NULL; - } - return err; + grub_priority_queue_destroy (data->pq); } static grub_err_t @@ -210,10 +282,12 @@ tftp_open (struct grub_file *file, const char *filename) int i; int rrqlen; int hdrlen; - char open_data[1500]; + grub_uint8_t open_data[1500]; struct grub_net_buff nb; tftp_data_t data; grub_err_t err; + grub_uint8_t *nbd; + grub_net_network_level_address_t addr; data = grub_zalloc (sizeof (*data)); if (!data) @@ -265,41 +339,55 @@ tftp_open (struct grub_file *file, const char *filename) file->not_easily_seekable = 1; file->data = data; - data->sock = grub_net_udp_open (file->device->net->server, - TFTP_SERVER_PORT, tftp_receive, - file); - if (!data->sock) + + data->pq = grub_priority_queue_new (sizeof (struct grub_net_buff *), cmp); + if (!data->pq) return grub_errno; - err = grub_net_send_udp_packet (data->sock, &nb); + err = grub_net_resolve_address (file->device->net->server, &addr); if (err) { - grub_net_udp_close (data->sock); + destroy_pq (data); return err; } - /* Receive OACK packet. */ - for (i = 0; i < 3; i++) + data->sock = grub_net_udp_open (addr, + TFTP_SERVER_PORT, tftp_receive, + file); + if (!data->sock) { - grub_net_poll_cards (100); - if (grub_errno) - return grub_errno; - if (data->have_oack) - break; - /* Retry. */ + destroy_pq (data); + return grub_errno; + } + + /* Receive OACK packet. */ + nbd = nb.data; + for (i = 0; i < GRUB_NET_TRIES; i++) + { + nb.data = nbd; err = grub_net_send_udp_packet (data->sock, &nb); if (err) { grub_net_udp_close (data->sock); + destroy_pq (data); return err; } + grub_net_poll_cards (GRUB_NET_INTERVAL); + if (data->have_oack) + break; } if (!data->have_oack) + grub_error (GRUB_ERR_TIMEOUT, N_("time out opening `%s'"), filename); + else + grub_error_load (&data->save_err); + if (grub_errno) { grub_net_udp_close (data->sock); - return grub_error (GRUB_ERR_TIMEOUT, "Time out opening tftp."); + destroy_pq (data); + return grub_errno; } + file->size = data->file_size; return GRUB_ERR_NONE; @@ -312,7 +400,7 @@ tftp_close (struct grub_file *file) if (data->sock) { - char nbdata[512]; + grub_uint8_t nbdata[512]; grub_err_t err; struct grub_net_buff nb_err; struct tftphdr *tftph; @@ -338,6 +426,7 @@ tftp_close (struct grub_file *file) grub_print_error (); grub_net_udp_close (data->sock); } + destroy_pq (data); grub_free (data); return GRUB_ERR_NONE; } diff --git a/grub-core/net/udp.c b/grub-core/net/udp.c index 47a67a967..919dca8db 100644 --- a/grub-core/net/udp.c +++ b/grub-core/net/udp.c @@ -1,96 +1,208 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License 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_net_socket_t -grub_net_udp_open (char *server, +struct grub_net_udp_socket +{ + struct grub_net_udp_socket *next; + struct grub_net_udp_socket **prev; + + enum { GRUB_NET_SOCKET_START, + GRUB_NET_SOCKET_ESTABLISHED, + GRUB_NET_SOCKET_CLOSED } status; + int in_port; + int out_port; + grub_err_t (*recv_hook) (grub_net_udp_socket_t sock, struct grub_net_buff *nb, + void *recv); + void *recv_hook_data; + grub_net_network_level_address_t out_nla; + grub_net_link_level_address_t ll_target_addr; + struct grub_net_network_level_interface *inf; +}; + +static struct grub_net_udp_socket *udp_sockets; + +#define FOR_UDP_SOCKETS(var) for (var = udp_sockets; var; var = var->next) + +static inline void +udp_socket_register (grub_net_udp_socket_t sock) +{ + grub_list_push (GRUB_AS_LIST_P (&udp_sockets), + GRUB_AS_LIST (sock)); +} + +void +grub_net_udp_close (grub_net_udp_socket_t sock) +{ + grub_list_remove (GRUB_AS_LIST (sock)); + grub_free (sock); +} + +grub_net_udp_socket_t +grub_net_udp_open (grub_net_network_level_address_t addr, grub_uint16_t out_port, - grub_err_t (*recv_hook) (grub_net_socket_t sock, + grub_err_t (*recv_hook) (grub_net_udp_socket_t sock, struct grub_net_buff *nb, void *data), void *recv_hook_data) { grub_err_t err; - grub_net_network_level_address_t addr; struct grub_net_network_level_interface *inf; grub_net_network_level_address_t gateway; - grub_net_socket_t socket; + grub_net_udp_socket_t socket; static int in_port = 25300; + grub_net_link_level_address_t ll_target_addr; - err = grub_net_resolve_address (server, &addr); - if (err) - return NULL; + if (addr.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 + && addr.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6) + { + grub_error (GRUB_ERR_BUG, "not an IP address"); + return NULL; + } err = grub_net_route_address (addr, &gateway, &inf); if (err) return NULL; + err = grub_net_link_layer_resolve (inf, &gateway, &ll_target_addr); + if (err) + return NULL; + socket = grub_zalloc (sizeof (*socket)); if (socket == NULL) return NULL; - socket->x_out_port = out_port; - socket->x_inf = inf; - socket->x_out_nla = addr; - socket->x_in_port = in_port++; - socket->x_status = GRUB_NET_SOCKET_START; + socket->out_port = out_port; + socket->inf = inf; + socket->out_nla = addr; + socket->ll_target_addr = ll_target_addr; + socket->in_port = in_port++; + socket->status = GRUB_NET_SOCKET_START; socket->recv_hook = recv_hook; socket->recv_hook_data = recv_hook_data; - grub_net_socket_register (socket); + udp_socket_register (socket); return socket; } grub_err_t -grub_net_send_udp_packet (const grub_net_socket_t socket, +grub_net_send_udp_packet (const grub_net_udp_socket_t socket, struct grub_net_buff *nb) { struct udphdr *udph; grub_err_t err; + COMPILE_TIME_ASSERT (GRUB_NET_UDP_HEADER_SIZE == sizeof (*udph)); + err = grub_netbuff_push (nb, sizeof (*udph)); if (err) return err; udph = (struct udphdr *) nb->data; - udph->src = grub_cpu_to_be16 (socket->x_in_port); - udph->dst = grub_cpu_to_be16 (socket->x_out_port); + udph->src = grub_cpu_to_be16 (socket->in_port); + udph->dst = grub_cpu_to_be16 (socket->out_port); - /* No chechksum. */ udph->chksum = 0; udph->len = grub_cpu_to_be16 (nb->tail - nb->data); - return grub_net_send_ip_packet (socket->x_inf, &(socket->x_out_nla), nb); + udph->chksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_UDP, + &socket->inf->address, + &socket->out_nla); + + return grub_net_send_ip_packet (socket->inf, &(socket->out_nla), + &(socket->ll_target_addr), nb, + GRUB_NET_IP_UDP); } grub_err_t -grub_net_recv_udp_packet (struct grub_net_buff * nb, - struct grub_net_network_level_interface * inf) +grub_net_recv_udp_packet (struct grub_net_buff *nb, + struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *source) { struct udphdr *udph; - grub_net_socket_t sock; + grub_net_udp_socket_t sock; grub_err_t err; - udph = (struct udphdr *) nb->data; - err = grub_netbuff_pull (nb, sizeof (*udph)); - if (err) - return err; - FOR_NET_SOCKETS (sock) + /* Ignore broadcast. */ + if (!inf) + { + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + + udph = (struct udphdr *) nb->data; + if (nb->tail - nb->data < (grub_ssize_t) sizeof (*udph)) + { + grub_dprintf ("net", "UDP packet too short: %" PRIuGRUB_SIZE "\n", + nb->tail - nb->data); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + + FOR_UDP_SOCKETS (sock) { - if (grub_be_to_cpu16 (udph->dst) == sock->x_in_port - && inf == sock->x_inf && sock->recv_hook) + if (grub_be_to_cpu16 (udph->dst) == sock->in_port + && inf == sock->inf + && grub_net_addr_cmp (source, &sock->out_nla) == 0 + && (sock->status == GRUB_NET_SOCKET_START + || grub_be_to_cpu16 (udph->src) == sock->out_port)) { - if (sock->x_status == GRUB_NET_SOCKET_START) + if (udph->chksum) { - sock->x_out_port = grub_be_to_cpu16 (udph->src); - sock->x_status = GRUB_NET_SOCKET_ESTABLISHED; + grub_uint16_t chk, expected; + chk = udph->chksum; + udph->chksum = 0; + expected = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_UDP, + &sock->out_nla, + &sock->inf->address); + if (expected != chk) + { + grub_dprintf ("net", "Invalid UDP checksum. " + "Expected %x, got %x\n", + grub_be_to_cpu16 (expected), + grub_be_to_cpu16 (chk)); + grub_netbuff_free (nb); + return GRUB_ERR_NONE; + } + udph->chksum = chk; } + if (sock->status == GRUB_NET_SOCKET_START) + { + sock->out_port = grub_be_to_cpu16 (udph->src); + sock->status = GRUB_NET_SOCKET_ESTABLISHED; + } + + err = grub_netbuff_pull (nb, sizeof (*udph)); + if (err) + return err; + /* App protocol remove its own reader. */ - sock->recv_hook (sock, nb, sock->recv_hook_data); + if (sock->recv_hook) + sock->recv_hook (sock, nb, sock->recv_hook_data); + else + grub_netbuff_free (nb); return GRUB_ERR_NONE; } } diff --git a/grub-core/normal/auth.c b/grub-core/normal/auth.c index 8e19568e2..c6bd96e28 100644 --- a/grub-core/normal/auth.c +++ b/grub-core/normal/auth.c @@ -28,6 +28,7 @@ struct grub_auth_user { struct grub_auth_user *next; + struct grub_auth_user **prev; char *name; grub_auth_callback_t callback; void *arg; @@ -73,7 +74,7 @@ grub_auth_unregister_authentication (const char *user) if (!cur->authenticated) { grub_free (cur->name); - grub_list_remove (GRUB_AS_LIST_P (&users), GRUB_AS_LIST (cur)); + grub_list_remove (GRUB_AS_LIST (cur)); grub_free (cur); } else @@ -121,7 +122,7 @@ grub_auth_deauthenticate (const char *user) if (!cur->callback) { grub_free (cur->name); - grub_list_remove (GRUB_AS_LIST_P (&users), GRUB_AS_LIST (cur)); + grub_list_remove (GRUB_AS_LIST (cur)); grub_free (cur); } else @@ -262,7 +263,8 @@ grub_normal_auth_init (void) { cmd = grub_register_command ("authenticate", grub_cmd_authenticate, - N_("[USERLIST]"), N_("Authenticate users")); + N_("[USERLIST]"), + N_("Check whether user is in USERLIST.")); } diff --git a/grub-core/normal/autofs.c b/grub-core/normal/autofs.c index e1d4c017c..8af2a95fd 100644 --- a/grub-core/normal/autofs.c +++ b/grub-core/normal/autofs.c @@ -57,7 +57,8 @@ read_fs_list (const char *prefix) { char *filename; - filename = grub_xasprintf ("%s/fs.lst", prefix); + filename = grub_xasprintf ("%s/" GRUB_TARGET_CPU "-" GRUB_PLATFORM + "/fs.lst", prefix); if (filename) { grub_file_t file; diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c index 85ead53c4..5792cee93 100644 --- a/grub-core/normal/charset.c +++ b/grub-core/normal/charset.c @@ -42,13 +42,6 @@ Most underline diacritics aren't displayed in gfxterm */ -/* Convert a (possibly null-terminated) UTF-8 string of at most SRCSIZE - bytes (if SRCSIZE is -1, it is ignored) in length to a UTF-16 string. - Return the number of characters converted. DEST must be able to hold - at least DESTSIZE characters. If an invalid sequence is found, return -1. - If SRCEND is not NULL, then *SRCEND is set to the next byte after the - last byte used in SRC. */ - #include #include #include @@ -60,7 +53,59 @@ #include "widthspec.h" #endif -grub_ssize_t +int +grub_utf8_process (grub_uint8_t c, grub_uint32_t *code, int *count) +{ + if (*count) + { + if ((c & GRUB_UINT8_2_LEADINGBITS) != GRUB_UINT8_1_LEADINGBIT) + { + *count = 0; + /* invalid */ + return 0; + } + else + { + *code <<= 6; + *code |= (c & GRUB_UINT8_6_TRAILINGBITS); + (*count)--; + return 1; + } + } + + if ((c & GRUB_UINT8_1_LEADINGBIT) == 0) + { + *code = c; + return 1; + } + if ((c & GRUB_UINT8_3_LEADINGBITS) == GRUB_UINT8_2_LEADINGBITS) + { + *count = 1; + *code = c & GRUB_UINT8_5_TRAILINGBITS; + return 1; + } + if ((c & GRUB_UINT8_4_LEADINGBITS) == GRUB_UINT8_3_LEADINGBITS) + { + *count = 2; + *code = c & GRUB_UINT8_4_TRAILINGBITS; + return 1; + } + if ((c & GRUB_UINT8_5_LEADINGBITS) == GRUB_UINT8_4_LEADINGBITS) + { + *count = 3; + *code = c & GRUB_UINT8_3_TRAILINGBITS; + return 1; + } + return 0; +} + +/* Convert a (possibly null-terminated) UTF-8 string of at most SRCSIZE + bytes (if SRCSIZE is -1, it is ignored) in length to a UTF-16 string. + Return the number of characters converted. DEST must be able to hold + at least DESTSIZE characters. If an invalid sequence is found, return -1. + If SRCEND is not NULL, then *SRCEND is set to the next byte after the + last byte used in SRC. */ +grub_size_t grub_utf8_to_utf16 (grub_uint16_t *dest, grub_size_t destsize, const grub_uint8_t *src, grub_size_t srcsize, const grub_uint8_t **srcend) @@ -74,64 +119,33 @@ grub_utf8_to_utf16 (grub_uint16_t *dest, grub_size_t destsize, while (srcsize && destsize) { - grub_uint32_t c = *src++; + int was_count = count; if (srcsize != (grub_size_t)-1) srcsize--; - if (count) + if (!grub_utf8_process (*src++, &code, &count)) { - if ((c & GRUB_UINT8_2_LEADINGBITS) != GRUB_UINT8_1_LEADINGBIT) - { - /* invalid */ - return -1; - } - else - { - code <<= 6; - code |= (c & GRUB_UINT8_6_TRAILINGBITS); - count--; - } + code = '?'; + count = 0; + /* Character c may be valid, don't eat it. */ + if (was_count) + src--; + } + if (count != 0) + continue; + if (code == 0) + break; + if (destsize < 2 && code >= GRUB_UCS2_LIMIT) + break; + if (code >= GRUB_UCS2_LIMIT) + { + *p++ = GRUB_UTF16_UPPER_SURROGATE (code); + *p++ = GRUB_UTF16_LOWER_SURROGATE (code); + destsize -= 2; } else { - if (c == 0) - break; - - if ((c & GRUB_UINT8_1_LEADINGBIT) == 0) - code = c; - else if ((c & GRUB_UINT8_3_LEADINGBITS) == GRUB_UINT8_2_LEADINGBITS) - { - count = 1; - code = c & GRUB_UINT8_5_TRAILINGBITS; - } - else if ((c & GRUB_UINT8_4_LEADINGBITS) == GRUB_UINT8_3_LEADINGBITS) - { - count = 2; - code = c & GRUB_UINT8_4_TRAILINGBITS; - } - else if ((c & GRUB_UINT8_5_LEADINGBITS) == GRUB_UINT8_4_LEADINGBITS) - { - count = 3; - code = c & GRUB_UINT8_3_TRAILINGBITS; - } - else - return -1; - } - - if (count == 0) - { - if (destsize < 2 && code >= GRUB_UCS2_LIMIT) - break; - if (code >= GRUB_UCS2_LIMIT) - { - *p++ = GRUB_UTF16_UPPER_SURROGATE (code); - *p++ = GRUB_UTF16_LOWER_SURROGATE (code); - destsize -= 2; - } - else - { - *p++ = code; - destsize--; - } + *p++ = code; + destsize--; } } @@ -140,9 +154,56 @@ grub_utf8_to_utf16 (grub_uint16_t *dest, grub_size_t destsize, return p - dest; } +/* Returns -2 if not enough space, -1 on invalid character. */ +grub_ssize_t +grub_encode_utf8_character (grub_uint8_t *dest, grub_uint8_t *destend, + grub_uint32_t code) +{ + if (dest >= destend) + return -2; + if (code <= 0x007F) + { + *dest++ = code; + return 1; + } + if (code <= 0x07FF) + { + if (dest + 1 >= destend) + return -2; + *dest++ = (code >> 6) | 0xC0; + *dest++ = (code & 0x3F) | 0x80; + return 2; + } + if ((code >= 0xDC00 && code <= 0xDFFF) + || (code >= 0xD800 && code <= 0xDBFF)) + { + /* No surrogates in UCS-4... */ + return -1; + } + if (code < 0x10000) + { + if (dest + 2 >= destend) + return -2; + *dest++ = (code >> 12) | 0xE0; + *dest++ = ((code >> 6) & 0x3F) | 0x80; + *dest++ = (code & 0x3F) | 0x80; + return 3; + } + { + if (dest + 3 >= destend) + return -2; + *dest++ = (code >> 18) | 0xF0; + *dest++ = ((code >> 12) & 0x3F) | 0x80; + *dest++ = ((code >> 6) & 0x3F) | 0x80; + *dest++ = (code & 0x3F) | 0x80; + return 4; + } + +} + /* Convert UCS-4 to UTF-8. */ void -grub_ucs4_to_utf8 (grub_uint32_t *src, grub_size_t size, +grub_ucs4_to_utf8 (const grub_uint32_t *src, grub_size_t size, grub_uint8_t *dest, grub_size_t destsize) { /* Keep last char for \0. */ @@ -151,49 +212,26 @@ grub_ucs4_to_utf8 (grub_uint32_t *src, grub_size_t size, while (size-- && dest < destend) { grub_uint32_t code = *src++; - - if (code <= 0x007F) - *dest++ = code; - else if (code <= 0x07FF) + grub_ssize_t s; + s = grub_encode_utf8_character (dest, destend, code); + if (s == -2) + break; + if (s == -1) { - if (dest + 1 >= destend) - break; - *dest++ = (code >> 6) | 0xC0; - *dest++ = (code & 0x3F) | 0x80; - } - else if ((code >= 0xDC00 && code <= 0xDFFF) - || (code >= 0xD800 && code <= 0xDBFF)) - { - /* No surrogates in UCS-4... */ *dest++ = '?'; + continue; } - else if (code < 0x10000) - { - if (dest + 2 >= destend) - break; - *dest++ = (code >> 12) | 0xE0; - *dest++ = ((code >> 6) & 0x3F) | 0x80; - *dest++ = (code & 0x3F) | 0x80; - } - else - { - if (dest + 3 >= destend) - break; - *dest++ = (code >> 18) | 0xF0; - *dest++ = ((code >> 12) & 0x3F) | 0x80; - *dest++ = ((code >> 6) & 0x3F) | 0x80; - *dest++ = (code & 0x3F) | 0x80; - } + dest += s; } *dest = 0; } /* Convert UCS-4 to UTF-8. */ char * -grub_ucs4_to_utf8_alloc (grub_uint32_t *src, grub_size_t size) +grub_ucs4_to_utf8_alloc (const grub_uint32_t *src, grub_size_t size) { grub_size_t remaining; - grub_uint32_t *ptr; + const grub_uint32_t *ptr; grub_size_t cnt = 0; grub_uint8_t *ret; @@ -230,53 +268,21 @@ grub_ucs4_to_utf8_alloc (grub_uint32_t *src, grub_size_t size) int grub_is_valid_utf8 (const grub_uint8_t *src, grub_size_t srcsize) { - grub_uint32_t code = 0; int count = 0; + grub_uint32_t code = 0; while (srcsize) { - grub_uint32_t c = *src++; if (srcsize != (grub_size_t)-1) srcsize--; - if (count) - { - if ((c & 0xc0) != 0x80) - { - /* invalid */ - return 0; - } - else - { - code <<= 6; - code |= (c & 0x3f); - count--; - } - } - else - { - if (c == 0) - break; - - if ((c & 0x80) == 0x00) - code = c; - else if ((c & 0xe0) == 0xc0) - { - count = 1; - code = c & 0x1f; - } - else if ((c & 0xf0) == 0xe0) - { - count = 2; - code = c & 0x0f; - } - else if ((c & 0xf8) == 0xf0) - { - count = 3; - code = c & 0x07; - } - else - return 0; - } + if (!grub_utf8_process (*src++, &code, &count)) + return 0; + if (count != 0) + continue; + if (code == 0) + return 1; + if (code > GRUB_UNICODE_LAST_VALID) + return 0; } return 1; @@ -322,63 +328,23 @@ grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize, while (srcsize && destsize) { - grub_uint32_t c = *src++; + int was_count = count; if (srcsize != (grub_size_t)-1) srcsize--; - if (count) + if (!grub_utf8_process (*src++, &code, &count)) { - if ((c & 0xc0) != 0x80) - { - /* invalid */ - code = '?'; - /* Character c may be valid, don't eat it. */ - src--; - if (srcsize != (grub_size_t)-1) - srcsize++; - count = 0; - } - else - { - code <<= 6; - code |= (c & 0x3f); - count--; - } - } - else - { - if (c == 0) - break; - - if ((c & 0x80) == 0x00) - code = c; - else if ((c & 0xe0) == 0xc0) - { - count = 1; - code = c & 0x1f; - } - else if ((c & 0xf0) == 0xe0) - { - count = 2; - code = c & 0x0f; - } - else if ((c & 0xf8) == 0xf0) - { - count = 3; - code = c & 0x07; - } - else - { - /* invalid */ - code = '?'; - count = 0; - } - } - - if (count == 0) - { - *p++ = code; - destsize--; + code = '?'; + count = 0; + /* Character c may be valid, don't eat it. */ + if (was_count) + src--; } + if (count != 0) + continue; + if (code == 0) + break; + *p++ = code; + destsize--; } if (srcend) @@ -400,9 +366,9 @@ unpack_join (void) grub_errno = GRUB_ERR_NONE; return; } - for (cur = grub_unicode_compact; cur->end; cur++) - for (i = cur->start; i <= cur->end - && i < GRUB_UNICODE_MAX_CACHED_CHAR; i++) + for (cur = grub_unicode_compact; cur->len; cur++) + for (i = cur->start; i < cur->start + (unsigned) cur->len + && i < GRUB_UNICODE_MAX_CACHED_CHAR; i++) join_types[i] = cur->join_type; } @@ -420,9 +386,9 @@ unpack_bidi (void) grub_errno = GRUB_ERR_NONE; return; } - for (cur = grub_unicode_compact; cur->end; cur++) - for (i = cur->start; i <= cur->end - && i < GRUB_UNICODE_MAX_CACHED_CHAR; i++) + for (cur = grub_unicode_compact; cur->len; cur++) + for (i = cur->start; i < cur->start + (unsigned) cur->len + && i < GRUB_UNICODE_MAX_CACHED_CHAR; i++) if (cur->bidi_mirror) bidi_types[i] = cur->bidi_type | 0x80; else @@ -440,8 +406,8 @@ get_bidi_type (grub_uint32_t c) if (bidi_types && c < GRUB_UNICODE_MAX_CACHED_CHAR) return bidi_types[c] & 0x7f; - for (cur = grub_unicode_compact; cur->end; cur++) - if (cur->start <= c && c <= cur->end) + for (cur = grub_unicode_compact; cur->len; cur++) + if (cur->start <= c && c < cur->start + (unsigned) cur->len) return cur->bidi_type; return GRUB_BIDI_TYPE_L; @@ -458,8 +424,8 @@ get_join_type (grub_uint32_t c) if (join_types && c < GRUB_UNICODE_MAX_CACHED_CHAR) return join_types[c]; - for (cur = grub_unicode_compact; cur->end; cur++) - if (cur->start <= c && c <= cur->end) + for (cur = grub_unicode_compact; cur->len; cur++) + if (cur->start <= c && c < cur->start + (unsigned) cur->len) return cur->join_type; return GRUB_JOIN_TYPE_NONJOINING; @@ -476,8 +442,8 @@ is_mirrored (grub_uint32_t c) if (bidi_types && c < GRUB_UNICODE_MAX_CACHED_CHAR) return !!(bidi_types[c] & 0x80); - for (cur = grub_unicode_compact; cur->end; cur++) - if (cur->start <= c && c <= cur->end) + for (cur = grub_unicode_compact; cur->len; cur++) + if (cur->start <= c && c < cur->start + (unsigned) cur->len) return cur->bidi_mirror; return 0; @@ -494,8 +460,8 @@ grub_unicode_get_comb_type (grub_uint32_t c) unsigned i; comb_types = grub_zalloc (GRUB_UNICODE_MAX_CACHED_CHAR); if (comb_types) - for (cur = grub_unicode_compact; cur->end; cur++) - for (i = cur->start; i <= cur->end + for (cur = grub_unicode_compact; cur->len; cur++) + for (i = cur->start; i < cur->start + (unsigned) cur->len && i < GRUB_UNICODE_MAX_CACHED_CHAR; i++) comb_types[i] = cur->comb_type; else @@ -505,8 +471,8 @@ grub_unicode_get_comb_type (grub_uint32_t c) if (comb_types && c < GRUB_UNICODE_MAX_CACHED_CHAR) return comb_types[c]; - for (cur = grub_unicode_compact; cur->end; cur++) - if (cur->start <= c && c <= cur->end) + for (cur = grub_unicode_compact; cur->len; cur++) + if (cur->start <= c && c < cur->start + (unsigned) cur->len) return cur->comb_type; return GRUB_UNICODE_COMB_NONE; @@ -939,6 +905,10 @@ grub_bidi_line_logical_to_visual (const grub_uint32_t *logical, continue; } + /* The tags: deprecated, never used. */ + if (*lptr >= GRUB_UNICODE_TAG_START && *lptr <= GRUB_UNICODE_TAG_END) + continue; + p = grub_unicode_aglomerate_comb (lptr, logical + logical_len - lptr, &visual[visual_len]); diff --git a/grub-core/normal/cmdline.c b/grub-core/normal/cmdline.c index ea06b4cc7..18314cdc0 100644 --- a/grub-core/normal/cmdline.c +++ b/grub-core/normal/cmdline.c @@ -211,7 +211,7 @@ struct cmdline_term otherwise return command line. */ /* FIXME: The dumb interface is not supported yet. */ char * -grub_cmdline_get (const char *prompt) +grub_cmdline_get (const char *prompt_translated) { grub_size_t lpos, llen; grub_size_t plen; @@ -228,7 +228,6 @@ grub_cmdline_get (const char *prompt) auto void cl_set_pos_all (void); auto void init_clterm (struct cmdline_term *cl_term_cur); auto void init_clterm_all (void); - const char *prompt_translated = _(prompt); struct cmdline_term *cl_terms; char *ret; unsigned nterms; diff --git a/grub-core/normal/color.c b/grub-core/normal/color.c index 2e6c80b94..06f1a877c 100644 --- a/grub-core/normal/color.c +++ b/grub-core/normal/color.c @@ -23,7 +23,7 @@ #include /* Borrowed from GRUB Legacy */ -static char *color_list[16] = +static const char *color_list[16] = { "black", "blue", diff --git a/grub-core/normal/completion.c b/grub-core/normal/completion.c index 67676dfe4..2a802390f 100644 --- a/grub-core/normal/completion.c +++ b/grub-core/normal/completion.c @@ -26,9 +26,10 @@ #include #include #include +#include /* The current word. */ -static char *current_word; +static const char *current_word; /* The matched string. */ static char *match; @@ -86,6 +87,7 @@ add_completion (const char *completion, const char *extra, s++; t++; } + s = match + grub_getend (match, s); *s = '\0'; } @@ -159,29 +161,43 @@ iterate_dev (const char *devname) /* Complete the partition part. */ dev = grub_device_open (devname); - if (dev) + if (!dev) { - char tmp[grub_strlen (devname) + sizeof (",")]; - - grub_memcpy (tmp, devname, grub_strlen (devname)); - - if (grub_strcmp (devname, current_word) == 0) - { - if (add_completion (devname, ")", GRUB_COMPLETION_TYPE_PARTITION)) - return 1; - - if (dev->disk) - if (grub_partition_iterate (dev->disk, iterate_partition)) - return 1; - } - else - { - grub_memcpy (tmp + grub_strlen (devname), "", sizeof ("")); - if (add_completion (tmp, "", GRUB_COMPLETION_TYPE_DEVICE)) - return 1; - } + grub_errno = GRUB_ERR_NONE; + return 0; } + { + char tmp[grub_strlen (devname) + sizeof (",")]; + grub_memcpy (tmp, devname, grub_strlen (devname)); + + if (grub_strcmp (devname, current_word) == 0) + { + if (add_completion (devname, ")", GRUB_COMPLETION_TYPE_PARTITION)) + { + grub_device_close (dev); + return 1; + } + + if (dev->disk) + if (grub_partition_iterate (dev->disk, iterate_partition)) + { + grub_device_close (dev); + return 1; + } + } + else + { + grub_memcpy (tmp + grub_strlen (devname), "", sizeof ("")); + if (add_completion (tmp, "", GRUB_COMPLETION_TYPE_DEVICE)) + { + grub_device_close (dev); + return 1; + } + } + } + + grub_device_close (dev); grub_errno = GRUB_ERR_NONE; return 0; } diff --git a/grub-core/normal/context.c b/grub-core/normal/context.c index 581316603..e9923ccdc 100644 --- a/grub-core/normal/context.c +++ b/grub-core/normal/context.c @@ -159,7 +159,7 @@ grub_env_extractor_close (int source) } err = grub_env_context_close (); - if (source) + if (source && menu) { grub_menu_t menu2; menu2 = grub_env_get_menu (); @@ -186,7 +186,7 @@ grub_cmd_export (struct grub_command *cmd __attribute__ ((unused)), if (argc < 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, - "no environment variable specified"); + N_("one argument expected")); for (i = 0; i < argc; i++) grub_env_export (args[i]); diff --git a/grub-core/normal/crypto.c b/grub-core/normal/crypto.c index 19dafd8a7..c87a55109 100644 --- a/grub-core/normal/crypto.c +++ b/grub-core/normal/crypto.c @@ -38,7 +38,14 @@ grub_crypto_autoload (const char *name) { struct load_spec *cur; grub_dl_t mod; - + static int depth = 0; + + /* Some bufio of filesystems may want some crypto modules. + It may result in infinite recursion. Hence this check. */ + if (depth) + return; + depth++; + for (cur = crypto_specs; cur; cur = cur->next) if (grub_strcasecmp (name, cur->name) == 0) { @@ -47,6 +54,7 @@ grub_crypto_autoload (const char *name) grub_dl_ref (mod); grub_errno = GRUB_ERR_NONE; } + depth--; } static void @@ -78,7 +86,8 @@ read_crypto_list (const char *prefix) return; } - filename = grub_xasprintf ("%s/crypto.lst", prefix); + filename = grub_xasprintf ("%s/" GRUB_TARGET_CPU "-" GRUB_PLATFORM + "/crypto.lst", prefix); if (!filename) { grub_errno = GRUB_ERR_NONE; diff --git a/grub-core/normal/datetime.c b/grub-core/normal/datetime.c index 8183601ba..bbc2cdea9 100644 --- a/grub-core/normal/datetime.c +++ b/grub-core/normal/datetime.c @@ -20,7 +20,7 @@ #include #include -static const char *grub_weekday_names[] = +static const char *const grub_weekday_names[] = { N_("Sunday"), N_("Monday"), diff --git a/grub-core/normal/dyncmd.c b/grub-core/normal/dyncmd.c index ed98855eb..de45b58d6 100644 --- a/grub-core/normal/dyncmd.c +++ b/grub-core/normal/dyncmd.c @@ -27,6 +27,32 @@ #include #include +grub_command_t +grub_dyncmd_get_cmd (grub_command_t cmd) +{ + grub_extcmd_t extcmd = cmd->data; + char *modname; + char *name; + grub_dl_t mod; + + modname = extcmd->data; + mod = grub_dl_load (modname); + if (!mod) + return NULL; + + grub_free (modname); + grub_dl_ref (mod); + + name = (char *) cmd->name; + grub_unregister_extcmd (extcmd); + + cmd = grub_command_find (name); + + grub_free (name); + + return cmd; +} + static grub_err_t grub_dyncmd_dispatcher (struct grub_extcmd_context *ctxt, int argc, char **args) @@ -36,36 +62,33 @@ grub_dyncmd_dispatcher (struct grub_extcmd_context *ctxt, grub_err_t ret; grub_extcmd_t extcmd = ctxt->extcmd; grub_command_t cmd = extcmd->cmd; + char *name; modname = extcmd->data; mod = grub_dl_load (modname); - if (mod) + if (!mod) + return grub_errno; + + grub_free (modname); + grub_dl_ref (mod); + + name = (char *) cmd->name; + grub_unregister_extcmd (extcmd); + + cmd = grub_command_find (name); + if (cmd) { - char *name; - - grub_free (modname); - grub_dl_ref (mod); - - name = (char *) cmd->name; - grub_unregister_extcmd (extcmd); - - cmd = grub_command_find (name); - if (cmd) - { - if (cmd->flags & GRUB_COMMAND_FLAG_BLOCKS && - cmd->flags & GRUB_COMMAND_FLAG_EXTCMD) - ret = grub_extcmd_dispatcher (cmd, argc, args, ctxt->script); - else - ret = (cmd->func) (cmd, argc, args); - } + if (cmd->flags & GRUB_COMMAND_FLAG_BLOCKS && + cmd->flags & GRUB_COMMAND_FLAG_EXTCMD) + ret = grub_extcmd_dispatcher (cmd, argc, args, ctxt->script); else - ret = grub_errno; - - grub_free (name); + ret = (cmd->func) (cmd, argc, args); } else ret = grub_errno; + grub_free (name); + return ret; } @@ -77,7 +100,8 @@ read_command_list (const char *prefix) { char *filename; - filename = grub_xasprintf ("%s/command.lst", prefix); + filename = grub_xasprintf ("%s/" GRUB_TARGET_CPU "-" GRUB_PLATFORM + "/command.lst", prefix); if (filename) { grub_file_t file; @@ -156,8 +180,8 @@ read_command_list (const char *prefix) GRUB_COMMAND_FLAG_BLOCKS | GRUB_COMMAND_FLAG_EXTCMD | GRUB_COMMAND_FLAG_DYNCMD, - 0, N_("not loaded"), 0, - prio); + 0, N_("module isn't loaded"), + 0, prio); if (! cmd) { grub_free (name); diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c index 281b1f4bc..707917013 100644 --- a/grub-core/normal/main.c +++ b/grub-core/normal/main.c @@ -385,9 +385,11 @@ grub_normal_read_line_real (char **line, int cont, int nested) const char *prompt; if (cont) - prompt = ">"; + /* TRANSLATORS: it's command line prompt. */ + prompt = _(">"); else - prompt = "grub>"; + /* TRANSLATORS: it's command line prompt. */ + prompt = _("grub>"); if (!prompt) return grub_errno; @@ -396,7 +398,7 @@ grub_normal_read_line_real (char **line, int cont, int nested) { *line = grub_cmdline_get (prompt); if (*line) - break; + return 0; if (cont || nested) { @@ -405,8 +407,7 @@ grub_normal_read_line_real (char **line, int cont, int nested) return grub_errno; } } - - return 0; + } static grub_err_t @@ -473,7 +474,7 @@ static grub_command_t cmd_clear; static void (*grub_xputs_saved) (const char *str); static const char *features[] = { - "feature_chainloader_bpb", "feature_ntldr" + "feature_chainloader_bpb", "feature_ntldr", "feature_platform_search_hint" }; GRUB_MOD_INIT(normal) @@ -527,6 +528,10 @@ GRUB_MOD_INIT(normal) grub_env_set (features[i], "y"); grub_env_export (features[i]); } + grub_env_set ("grub_cpu", GRUB_TARGET_CPU); + grub_env_export ("grub_cpu"); + grub_env_set ("grub_platform", GRUB_PLATFORM); + grub_env_export ("grub_platform"); } GRUB_MOD_FINI(normal) diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c index b75e9f523..100e8b3f3 100644 --- a/grub-core/normal/menu.c +++ b/grub-core/normal/menu.c @@ -52,12 +52,8 @@ grub_wait_after_message (void) endtime = grub_get_time_ms () + 10000; - while (grub_get_time_ms () < endtime) - if (grub_checkkey () >= 0) - { - grub_getkey (); - break; - } + while (grub_get_time_ms () < endtime + && grub_getkey_noblock () == GRUB_TERM_NO_KEY); grub_xputs ("\n"); } @@ -373,7 +369,9 @@ menu_init (int entry, grub_menu_t menu, int nested) } } else - grub_error (GRUB_ERR_BAD_MODULE, "no gfxmenu found"); + grub_error (GRUB_ERR_BAD_MODULE, + N_("module `%s' isn't loaded"), + "gfxmenu"); grub_print_error (); grub_wait_after_message (); } @@ -387,7 +385,7 @@ menu_init (int entry, grub_menu_t menu, int nested) grub_err_t err; if (grub_strcmp (term->name, "gfxterm") == 0 && gfxmenu) - break; + continue; err = grub_menu_try_text (term, entry, menu, nested); if(!err) @@ -558,10 +556,10 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) return default_entry; } - if (grub_checkkey () >= 0 || timeout < 0) - { - c = grub_getkey (); + c = grub_getkey_noblock (); + if (c != GRUB_TERM_NO_KEY) + { if (timeout >= 0) { grub_env_unset ("timeout"); @@ -666,7 +664,6 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) } /* Never reach here. */ - return -1; } /* Callback invoked immediately before a menu entry is executed. */ diff --git a/grub-core/normal/menu_entry.c b/grub-core/normal/menu_entry.c index dc5ab528f..7af093fd8 100644 --- a/grub-core/normal/menu_entry.c +++ b/grub-core/normal/menu_entry.c @@ -317,7 +317,7 @@ update_screen_all (struct screen *screen, } static int -insert_string (struct screen *screen, char *s, int update) +insert_string (struct screen *screen, const char *s, int update) { int region_start = screen->num_lines; int region_column = 0; @@ -397,7 +397,7 @@ insert_string (struct screen *screen, char *s, int update) else { /* All but LF. */ - char *p; + const char *p; struct line *current_linep; int size; int orig_num[screen->nterms], new_num[screen->nterms]; diff --git a/grub-core/normal/misc.c b/grub-core/normal/misc.c index 4a7e6a3ea..262f3eebd 100644 --- a/grub-core/normal/misc.c +++ b/grub-core/normal/misc.c @@ -109,13 +109,13 @@ grub_normal_print_device_info (const char *name) } } else - grub_printf ("%s", _("Not a known filesystem")); + grub_printf ("%s", _("No known filesystem detected")); if (dev->disk->partition) grub_printf (_(" - Partition start at %llu"), (unsigned long long) grub_partition_get_start (dev->disk->partition)); if (grub_disk_get_size (dev->disk) == GRUB_DISK_SIZE_UNKNOWN) - grub_puts_ (" - Total size unknown"); + grub_puts_ (N_(" - Total size unknown")); else grub_printf (_(" - Total size %llu sectors"), (unsigned long long) grub_disk_get_size (dev->disk)); diff --git a/grub-core/normal/term.c b/grub-core/normal/term.c index 922f8518f..d47bf3567 100644 --- a/grub-core/normal/term.c +++ b/grub-core/normal/term.c @@ -308,7 +308,8 @@ read_terminal_list (const char *prefix) return; } - filename = grub_xasprintf ("%s/terminal.lst", prefix); + filename = grub_xasprintf ("%s/" GRUB_TARGET_CPU "-" GRUB_PLATFORM + "/terminal.lst", prefix); if (!filename) { grub_errno = GRUB_ERR_NONE; diff --git a/grub-core/partmap/bsdlabel.c b/grub-core/partmap/bsdlabel.c index 490fbdd7b..c806f19a7 100644 --- a/grub-core/partmap/bsdlabel.c +++ b/grub-core/partmap/bsdlabel.c @@ -105,9 +105,10 @@ iterate_real (grub_disk_t disk, grub_disk_addr_t sector, int freebsd, char *partname; /* disk->partition != NULL as 0 < delta */ partname = disk->partition ? grub_partition_get_name (disk->partition) - : ""; + : 0; grub_util_warn (_("Discarding improperly nested partition (%s,%s,%s%d)"), - disk->name, partname, p.partmap->name, p.number + 1); + disk->name, partname ? : "", p.partmap->name, + p.number + 1); grub_free (partname); #endif continue; diff --git a/grub-core/partmap/dvh.c b/grub-core/partmap/dvh.c index 118401612..c8f467eb5 100644 --- a/grub-core/partmap/dvh.c +++ b/grub-core/partmap/dvh.c @@ -49,13 +49,13 @@ static struct grub_partition_map grub_dvh_partition_map; /* Verify checksum (true=ok). */ static int -grub_dvh_is_valid (struct grub_dvh_block *label) +grub_dvh_is_valid (grub_uint32_t *label) { grub_uint32_t *pos; grub_uint32_t sum = 0; - for (pos = (grub_uint32_t *) label; - pos < (grub_uint32_t *) (label + 1); + for (pos = label; + pos < (label + sizeof (struct grub_dvh_block) / 4); pos++) sum += *pos; @@ -68,7 +68,11 @@ dvh_partition_map_iterate (grub_disk_t disk, const grub_partition_t partition)) { struct grub_partition p; - struct grub_dvh_block block; + union + { + struct grub_dvh_block dvh; + grub_uint32_t raw[0]; + } block; unsigned partnum; grub_err_t err; @@ -78,24 +82,24 @@ dvh_partition_map_iterate (grub_disk_t disk, if (err) return err; - if (DVH_MAGIC != grub_be_to_cpu32 (block.magic)) + if (DVH_MAGIC != grub_be_to_cpu32 (block.dvh.magic)) return grub_error (GRUB_ERR_BAD_PART_TABLE, "not a dvh partition table"); - if (! grub_dvh_is_valid (&block)) + if (! grub_dvh_is_valid (block.raw)) return grub_error (GRUB_ERR_BAD_PART_TABLE, "invalid checksum"); /* Maybe another error value would be better, because partition table _is_ recognized but invalid. */ - for (partnum = 0; partnum < ARRAY_SIZE (block.parts); partnum++) + for (partnum = 0; partnum < ARRAY_SIZE (block.dvh.parts); partnum++) { - if (block.parts[partnum].length == 0) + if (block.dvh.parts[partnum].length == 0) continue; if (partnum == 10) continue; - p.start = grub_be_to_cpu32 (block.parts[partnum].start); - p.len = grub_be_to_cpu32 (block.parts[partnum].length); + p.start = grub_be_to_cpu32 (block.dvh.parts[partnum].start); + p.len = grub_be_to_cpu32 (block.dvh.parts[partnum].length); p.number = p.index = partnum; if (hook (disk, &p)) break; diff --git a/grub-core/partmap/gpt.c b/grub-core/partmap/gpt.c index 049fda850..db4b5d004 100644 --- a/grub-core/partmap/gpt.c +++ b/grub-core/partmap/gpt.c @@ -24,6 +24,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -45,10 +46,10 @@ static struct grub_partition_map grub_gpt_partition_map; -static grub_err_t -gpt_partition_map_iterate (grub_disk_t disk, - int (*hook) (grub_disk_t disk, - const grub_partition_t partition)) +grub_err_t +grub_gpt_partition_map_iterate (grub_disk_t disk, + int (*hook) (grub_disk_t disk, + const grub_partition_t partition)) { struct grub_partition part; struct grub_gpt_header gpt; @@ -126,7 +127,7 @@ gpt_partition_map_iterate (grub_disk_t disk, #ifdef GRUB_UTIL static grub_err_t -gpt_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, +gpt_partition_map_embed (struct grub_disk *disk_, unsigned int *nsectors, grub_embed_type_t embed_type, grub_disk_addr_t **sectors) { @@ -167,19 +168,19 @@ gpt_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "GPT currently supports only PC-BIOS embedding"); - err = gpt_partition_map_iterate (disk, find_usable_region); + err = grub_gpt_partition_map_iterate (disk_, find_usable_region); if (err) return err; if (len == 0) return grub_error (GRUB_ERR_FILE_NOT_FOUND, - "This GPT partition label has no BIOS Boot Partition;" - " embedding won't be possible!"); + N_("this GPT partition label has no BIOS Boot Partition;" + " embedding won't be possible")); if (len < *nsectors) return grub_error (GRUB_ERR_OUT_OF_RANGE, - "Your BIOS Boot Partition is too small;" - " embedding won't be possible!"); + N_("your BIOS Boot Partition is too small;" + " embedding won't be possible")); *nsectors = len; *sectors = grub_malloc (*nsectors * sizeof (**sectors)); @@ -197,7 +198,7 @@ gpt_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, static struct grub_partition_map grub_gpt_partition_map = { .name = "gpt", - .iterate = gpt_partition_map_iterate, + .iterate = grub_gpt_partition_map_iterate, #ifdef GRUB_UTIL .embed = gpt_partition_map_embed #endif diff --git a/grub-core/partmap/msdos.c b/grub-core/partmap/msdos.c index c8ab6acab..0049fbd46 100644 --- a/grub-core/partmap/msdos.c +++ b/grub-core/partmap/msdos.c @@ -23,6 +23,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -258,17 +259,17 @@ pc_partition_map_embed (struct grub_disk *disk, unsigned int *nsectors, if (end <= 1) return grub_error (GRUB_ERR_FILE_NOT_FOUND, - "This msdos-style partition label has no " - "post-MBR gap; embedding won't be possible!"); + N_("this msdos-style partition label has no " + "post-MBR gap; embedding won't be possible")); if (*nsectors > 62) return grub_error (GRUB_ERR_OUT_OF_RANGE, - "Your core.img is unusually large. " - "It won't fit in the embedding area."); + N_("your core.img is unusually large. " + "It won't fit in the embedding area")); return grub_error (GRUB_ERR_OUT_OF_RANGE, - "Your embedding area is unusually small. " - "core.img won't fit in it."); + N_("your embedding area is unusually small. " + "core.img won't fit in it.")); } #endif diff --git a/grub-core/partmap/sun.c b/grub-core/partmap/sun.c index c7ef681c4..dfe51f35d 100644 --- a/grub-core/partmap/sun.c +++ b/grub-core/partmap/sun.c @@ -71,13 +71,13 @@ static struct grub_partition_map grub_sun_partition_map; /* Verify checksum (true=ok). */ static int -grub_sun_is_valid (struct grub_sun_block *label) +grub_sun_is_valid (grub_uint16_t *label) { grub_uint16_t *pos; grub_uint16_t sum = 0; - for (pos = (grub_uint16_t *) label; - pos < (grub_uint16_t *) (label + 1); + for (pos = label; + pos < (label + sizeof (struct grub_sun_block) / 2); pos++) sum ^= *pos; @@ -90,7 +90,11 @@ sun_partition_map_iterate (grub_disk_t disk, const grub_partition_t partition)) { struct grub_partition p; - struct grub_sun_block block; + union + { + struct grub_sun_block sun; + grub_uint16_t raw[0]; + } block; int partnum; grub_err_t err; @@ -100,10 +104,10 @@ sun_partition_map_iterate (grub_disk_t disk, if (err) return err; - if (GRUB_PARTMAP_SUN_MAGIC != grub_be_to_cpu16 (block.magic)) + if (GRUB_PARTMAP_SUN_MAGIC != grub_be_to_cpu16 (block.sun.magic)) return grub_error (GRUB_ERR_BAD_PART_TABLE, "not a sun partition table"); - if (! grub_sun_is_valid (&block)) + if (! grub_sun_is_valid (block.raw)) return grub_error (GRUB_ERR_BAD_PART_TABLE, "invalid checksum"); /* Maybe another error value would be better, because partition @@ -112,14 +116,14 @@ sun_partition_map_iterate (grub_disk_t disk, { struct grub_sun_partition_descriptor *desc; - if (block.infos[partnum].id == 0 - || block.infos[partnum].id == GRUB_PARTMAP_SUN_WHOLE_DISK_ID) + if (block.sun.infos[partnum].id == 0 + || block.sun.infos[partnum].id == GRUB_PARTMAP_SUN_WHOLE_DISK_ID) continue; - desc = &block.partitions[partnum]; + desc = &block.sun.partitions[partnum]; p.start = ((grub_uint64_t) grub_be_to_cpu32 (desc->start_cylinder) - * grub_be_to_cpu16 (block.ntrks) - * grub_be_to_cpu16 (block.nsect)); + * grub_be_to_cpu16 (block.sun.ntrks) + * grub_be_to_cpu16 (block.sun.nsect)); p.len = grub_be_to_cpu32 (desc->num_sectors); p.number = p.index = partnum; if (p.len) diff --git a/grub-core/partmap/sunpc.c b/grub-core/partmap/sunpc.c index 28dc4f5be..1c1fdced0 100644 --- a/grub-core/partmap/sunpc.c +++ b/grub-core/partmap/sunpc.c @@ -53,13 +53,13 @@ static struct grub_partition_map grub_sun_pc_partition_map; /* Verify checksum (true=ok). */ static int -grub_sun_is_valid (struct grub_sun_pc_block *label) +grub_sun_is_valid (grub_uint16_t *label) { grub_uint16_t *pos; grub_uint16_t sum = 0; - for (pos = (grub_uint16_t *) label; - pos < (grub_uint16_t *) (label + 1); + for (pos = label; + pos < (label + sizeof (struct grub_sun_pc_block) / 2); pos++) sum ^= *pos; @@ -72,7 +72,11 @@ sun_pc_partition_map_iterate (grub_disk_t disk, const grub_partition_t partition)) { grub_partition_t p; - struct grub_sun_pc_block block; + union + { + struct grub_sun_pc_block sun; + grub_uint16_t raw[0]; + } block; int partnum; grub_err_t err; @@ -88,14 +92,14 @@ sun_pc_partition_map_iterate (grub_disk_t disk, return err; } - if (GRUB_PARTMAP_SUN_PC_MAGIC != grub_le_to_cpu16 (block.magic)) + if (GRUB_PARTMAP_SUN_PC_MAGIC != grub_le_to_cpu16 (block.sun.magic)) { grub_free (p); return grub_error (GRUB_ERR_BAD_PART_TABLE, "not a sun_pc partition table"); } - if (! grub_sun_is_valid (&block)) + if (! grub_sun_is_valid (block.raw)) { grub_free (p); return grub_error (GRUB_ERR_BAD_PART_TABLE, "invalid checksum"); @@ -107,11 +111,12 @@ sun_pc_partition_map_iterate (grub_disk_t disk, { struct grub_sun_pc_partition_descriptor *desc; - if (block.partitions[partnum].id == 0 - || block.partitions[partnum].id == GRUB_PARTMAP_SUN_PC_WHOLE_DISK_ID) + if (block.sun.partitions[partnum].id == 0 + || block.sun.partitions[partnum].id + == GRUB_PARTMAP_SUN_PC_WHOLE_DISK_ID) continue; - desc = &block.partitions[partnum]; + desc = &block.sun.partitions[partnum]; p->start = grub_le_to_cpu32 (desc->start_sector); p->len = grub_le_to_cpu32 (desc->num_sectors); p->number = partnum; diff --git a/grub-core/parttool/msdospart.c b/grub-core/parttool/msdospart.c index 3377a2ccc..3ae584829 100644 --- a/grub-core/parttool/msdospart.c +++ b/grub-core/parttool/msdospart.c @@ -48,7 +48,7 @@ static grub_err_t grub_pcpart_boot (const grub_device_t dev, struct grub_msdos_partition_mbr mbr; if (dev->disk->partition->offset) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "not a primary partition"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("not a primary partition")); index = dev->disk->partition->index; part = dev->disk->partition; @@ -85,7 +85,7 @@ static grub_err_t grub_pcpart_boot (const grub_device_t dev, static struct grub_parttool_argdesc grub_pcpart_typeargs[] = { {"type", N_("Change partition type"), GRUB_PARTTOOL_ARG_VAL}, - {"hidden", N_("Make partition hidden"), GRUB_PARTTOOL_ARG_BOOL}, + {"hidden", N_("Set `hidden' flag in partition type"), GRUB_PARTTOOL_ARG_BOOL}, {0, 0, 0} }; @@ -126,7 +126,9 @@ static grub_err_t grub_pcpart_type (const grub_device_t dev, || grub_msdos_partition_is_extended (type)) { dev->disk->partition = part; - return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid type"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("the partition type 0x%x isn't " + "valid")); } mbr.entries[index].type = type; diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c index 1fb5de6a3..27968e182 100644 --- a/grub-core/script/execute.c +++ b/grub-core/script/execute.c @@ -26,6 +26,7 @@ #include #include #include +#include /* Max digits for a char is 3 (0xFF is 255), similarly for an int it is sizeof (int) * 3, and one extra for a possible -ve sign. */ @@ -76,13 +77,23 @@ grub_script_break (grub_command_t cmd, int argc, char *argv[]) if (argc == 0) count = 1; - - else if ((argc > 1) || (count = grub_strtoul (argv[0], &p, 10)) == 0 || - (*p != '\0')) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad break"); + else if (argc > 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); + else + { + count = grub_strtoul (argv[0], &p, 10); + if (grub_errno) + return grub_errno; + if (*p != '\0') + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unrecognized number")); + if (count == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("can't break 0 loops")); + } is_continue = grub_strcmp (cmd->name, "break") ? 1 : 0; - active_breaks = grub_min (active_loops, count); + active_breaks = count; + if (active_breaks > active_loops) + active_breaks = active_loops; return GRUB_ERR_NONE; } @@ -155,20 +166,28 @@ grub_script_return (grub_command_t cmd __attribute__((unused)), unsigned long n; if (! scope || argc > 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "not in function scope"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("not in function scope")); if (argc == 0) { + const char *t; function_return = 1; - return grub_strtoul (grub_env_get ("?"), NULL, 10); + t = grub_env_get ("?"); + if (!t) + return GRUB_ERR_NONE; + return grub_strtoul (t, NULL, 10); } n = grub_strtoul (argv[0], &p, 10); + if (grub_errno) + return grub_errno; if (*p != '\0') - return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad argument"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("unrecognized number")); function_return = 1; - return n ? grub_error (GRUB_ERR_TEST_FAILURE, "false") : GRUB_ERR_NONE; + return n ? grub_error (n, N_("false")) : GRUB_ERR_NONE; } static int @@ -291,7 +310,8 @@ static grub_err_t grub_script_env_set (const char *name, const char *val) { if (grub_env_special (name)) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad variable name"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("invalid variable name `%s'"), name); return grub_env_set (name, val); } @@ -573,7 +593,8 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd) if (argv.argc < 2 || ! argv.args[1]) { grub_script_argv_free (&argv); - return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing arguments"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("no command is specified")); } invert = 1; @@ -638,7 +659,7 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd) if (ret == GRUB_ERR_TEST_FAILURE) grub_errno = ret = GRUB_ERR_NONE; else if (ret == GRUB_ERR_NONE) - ret = grub_error (GRUB_ERR_TEST_FAILURE, "false"); + ret = grub_error (GRUB_ERR_TEST_FAILURE, N_("false")); else { grub_print_error (); diff --git a/grub-core/script/function.c b/grub-core/script/function.c index 47b236652..d36655e51 100644 --- a/grub-core/script/function.c +++ b/grub-core/script/function.c @@ -20,6 +20,7 @@ #include #include #include +#include grub_script_function_t grub_script_function_list; @@ -99,7 +100,14 @@ grub_script_function_find (char *functionname) break; if (! func) - grub_error (GRUB_ERR_UNKNOWN_COMMAND, "unknown command `%.20s'", functionname); + { + char tmp[21]; + grub_strncpy (tmp, functionname, 20); + tmp[20] = 0; + /* Avoid truncating inside UTF-8 character. */ + tmp[grub_getend (tmp, tmp + grub_strlen (tmp))] = 0; + grub_error (GRUB_ERR_UNKNOWN_COMMAND, N_("can't find command `%s'"), tmp); + } return func; } diff --git a/grub-core/script/lexer.c b/grub-core/script/lexer.c index 53697c734..396d51277 100644 --- a/grub-core/script/lexer.c +++ b/grub-core/script/lexer.c @@ -23,6 +23,7 @@ #include #include #include +#include #define yytext_ptr char * #include "grub_script.tab.h" @@ -107,7 +108,9 @@ grub_script_lexer_record (struct grub_parser_param *parser, char *str) if (lexer->recordpos + len + 1 > lexer->recordlen) { old = lexer->recording; - lexer->recordlen = grub_max (len, lexer->recordlen) * 2; + if (lexer->recordlen < len) + lexer->recordlen = len; + lexer->recordlen *= 2; lexer->recording = grub_realloc (lexer->recording, lexer->recordlen); if (!lexer->recording) { @@ -127,7 +130,7 @@ int grub_script_lexer_yywrap (struct grub_parser_param *parserstate, const char *input) { - int len = 0; + grub_size_t len = 0; char *p = 0; char *line = 0; YY_BUFFER_STATE buffer; @@ -138,7 +141,7 @@ grub_script_lexer_yywrap (struct grub_parser_param *parserstate, if (! lexerstate->getline && ! input) { - grub_script_yyerror (parserstate, "unexpected end of file"); + grub_script_yyerror (parserstate, N_("unexpected end of file")); return 1; } @@ -148,14 +151,21 @@ grub_script_lexer_yywrap (struct grub_parser_param *parserstate, else line = grub_strdup (input); + if (! line) + { + grub_script_yyerror (parserstate, N_("out of memory")); + return 1; + } + + len = grub_strlen (line); + /* Ensure '\n' at the end. */ - if (line && line[0] == '\0') + if (line[0] == '\0') { grub_free (line); line = grub_strdup ("\n"); } - - if (line && (len = grub_strlen(line)) && line[len - 1] != '\n') + else if (len && line[len - 1] != '\n') { p = grub_realloc (line, len + 2); if (p) @@ -168,7 +178,7 @@ grub_script_lexer_yywrap (struct grub_parser_param *parserstate, if (! line) { - grub_script_yyerror (parserstate, "out of memory"); + grub_script_yyerror (parserstate, N_("out of memory")); return 1; } @@ -206,7 +216,7 @@ grub_script_lexer_yywrap (struct grub_parser_param *parserstate, struct grub_lexer_param * grub_script_lexer_init (struct grub_parser_param *parser, char *script, - grub_reader_getline_t getline) + grub_reader_getline_t arg_getline) { struct grub_lexer_param *lexerstate; @@ -222,7 +232,7 @@ grub_script_lexer_init (struct grub_parser_param *parser, char *script, return 0; } - lexerstate->getline = getline; /* rest are all zeros already */ + lexerstate->getline = arg_getline; /* rest are all zeros already */ if (yylex_init (&lexerstate->yyscanner)) { grub_free (lexerstate->text); diff --git a/grub-core/script/main.c b/grub-core/script/main.c index 482bb3fef..91ab55b6a 100644 --- a/grub-core/script/main.c +++ b/grub-core/script/main.c @@ -51,16 +51,18 @@ void grub_script_init (void) { cmd_break = grub_register_command ("break", grub_script_break, - N_("[n]"), N_("Exit from loops")); + N_("[NUM]"), N_("Exit from loops")); cmd_continue = grub_register_command ("continue", grub_script_break, - N_("[n]"), N_("Continue loops")); + N_("[NUM]"), N_("Continue loops")); cmd_shift = grub_register_command ("shift", grub_script_shift, - N_("[n]"), N_("Shift positional parameters.")); + N_("[NUM]"), + N_("Shift positional parameters.")); cmd_setparams = grub_register_command ("setparams", grub_script_setparams, N_("[VALUE]..."), N_("Set positional parameters.")); cmd_return = grub_register_command ("return", grub_script_return, - N_("[n]"), N_("Return from a function.")); + N_("[NUM]"), + N_("Return from a function.")); } void diff --git a/grub-core/script/parser.y b/grub-core/script/parser.y index cc20b5479..0c2d8867b 100644 --- a/grub-core/script/parser.y +++ b/grub-core/script/parser.y @@ -21,6 +21,7 @@ #include #include #include +#include #define YYFREE grub_free #define YYMALLOC grub_malloc @@ -28,6 +29,8 @@ #define YYENABLE_NLS 0 #include "grub_script.tab.h" + +#pragma GCC diagnostic ignored "-Wunreachable-code" %} %union { @@ -107,7 +110,7 @@ script: newlines0 | error { $$ = 0; - yyerror (state, "Incorrect command"); + yyerror (state, N_("Incorrect command")); yyerrok; } ; diff --git a/grub-core/script/yylex.l b/grub-core/script/yylex.l index 012d88dbc..ab913988a 100644 --- a/grub-core/script/yylex.l +++ b/grub-core/script/yylex.l @@ -22,6 +22,7 @@ #include #include #include +#include #include "grub_script.tab.h" #pragma GCC diagnostic ignored "-Wunused-parameter" @@ -37,7 +38,7 @@ */ #define YY_FATAL_ERROR(msg) \ do { \ - grub_printf ("fatal error: %s\n", msg); \ + grub_printf (_("fatal error: %s\n"), _(msg)); \ } while (0) #define COPY(str, hint) \ @@ -316,14 +317,16 @@ grub_lexer_yyrealloc (void *ptr, yy_size_t size, static void copy_string (struct grub_parser_param *parser, const char *str, unsigned hint) { - int size; + grub_size_t size; char *ptr; unsigned len; len = hint ? hint : grub_strlen (str); if (parser->lexerstate->used + len >= parser->lexerstate->size) { - size = grub_max (len, parser->lexerstate->size) * 2; + size = len * 2; + if (size < parser->lexerstate->size * 2) + size = parser->lexerstate->size * 2; ptr = grub_realloc (parser->lexerstate->text, size); if (!ptr) { @@ -362,7 +365,7 @@ grub_lexer_unput (const char *text, yyscan_t yyscanner) lexerstate->prefix = grub_strdup (text); if (! lexerstate->prefix) { - grub_script_yyerror (yyget_extra (yyscanner), "out of memory"); + grub_script_yyerror (yyget_extra (yyscanner), N_("out of memory")); return 1; } return 0; diff --git a/grub-core/term/at_keyboard.c b/grub-core/term/at_keyboard.c index b81e76230..bcd20d3ff 100644 --- a/grub-core/term/at_keyboard.c +++ b/grub-core/term/at_keyboard.c @@ -332,10 +332,10 @@ set_scancodes (void) return; } -#if !(defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_QEMU)) +#if !(defined (GRUB_MACHINE_MIPS_LOONGSON) || defined (GRUB_MACHINE_QEMU) || defined (GRUB_MACHINE_MIPS_QEMU_MIPS)) current_set = 1; return; -#endif +#else grub_keyboard_controller_write (grub_keyboard_controller_orig & ~KEYBOARD_AT_TRANSLATE); @@ -352,6 +352,7 @@ set_scancodes (void) if (current_set == 1) return; grub_printf ("No supported scancode set found\n"); +#endif } static void diff --git a/grub-core/kern/emu/console.c b/grub-core/term/emu/console.c similarity index 99% rename from grub-core/kern/emu/console.c rename to grub-core/term/emu/console.c index 7fd1fc0c9..55e3a6b7f 100644 --- a/grub-core/kern/emu/console.c +++ b/grub-core/term/emu/console.c @@ -116,7 +116,7 @@ grub_ncurses_getkey (struct grub_term_input *term __attribute__ ((unused))) switch (c) { case ERR: - return -1; + return GRUB_TERM_NO_KEY; case KEY_LEFT: c = GRUB_TERM_KEY_LEFT; break; diff --git a/grub-core/term/gfxterm.c b/grub-core/term/gfxterm.c index a10af5930..e0ddc1657 100644 --- a/grub-core/term/gfxterm.c +++ b/grub-core/term/gfxterm.c @@ -54,12 +54,6 @@ struct grub_colored_char /* Color values. */ grub_video_color_t fg_color; grub_video_color_t bg_color; - - /* The width of this character minus one. */ - unsigned char width; - - /* The column index of this character. */ - unsigned char index; }; struct grub_virtual_screen @@ -187,8 +181,6 @@ clear_char (struct grub_colored_char *c) grub_errno = GRUB_ERR_NONE; c->fg_color = virtual_screen.fg_color; c->bg_color = virtual_screen.bg_color; - c->width = 0; - c->index = 0; } static void @@ -621,7 +613,8 @@ paint_char (unsigned cx, unsigned cy) p = (virtual_screen.text_buffer + cx + (cy * virtual_screen.columns)); - p -= p->index; + if (!p->code) + return; /* Get glyph for character. */ glyph = grub_font_construct_glyph (virtual_screen.font, p->code); @@ -885,22 +878,18 @@ grub_gfxterm_putchar (struct grub_term_output *term, grub_errno = GRUB_ERR_NONE; p->fg_color = virtual_screen.fg_color; p->bg_color = virtual_screen.bg_color; - p->width = char_width - 1; - p->index = 0; /* If we have large glyph, add fixup info. */ if (char_width > 1) { unsigned i; - for (i = 1; i < char_width; i++) + for (i = 1; i < char_width && p + i < + virtual_screen.text_buffer + virtual_screen.columns + * virtual_screen.rows; i++) { grub_free (p[i].code); - p[i].code = grub_unicode_glyph_from_code (' '); - if (!p[i].code) - grub_errno = GRUB_ERR_NONE; - p[i].width = char_width - 1; - p[i].index = i; + p[i].code = NULL; } } @@ -1197,7 +1186,7 @@ grub_gfxterm_background_color_cmd (grub_command_t cmd __attribute__ ((unused)), struct grub_video_render_target *old_target; if (argc != 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing operand"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("one argument expected")); /* Check that we have video adapter active. */ if (grub_video_get_info (NULL) != GRUB_ERR_NONE) diff --git a/grub-core/term/ieee1275/ofconsole.c b/grub-core/term/ieee1275/console.c similarity index 77% rename from grub-core/term/ieee1275/ofconsole.c rename to grub-core/term/ieee1275/console.c index ab74f21da..d8c56e70d 100644 --- a/grub-core/term/ieee1275/ofconsole.c +++ b/grub-core/term/ieee1275/console.c @@ -1,4 +1,4 @@ -/* ofconsole.c -- Open Firmware console for GRUB. */ +/* console.c -- Open Firmware console for GRUB. */ /* * GRUB -- GRand Unified Bootloader * Copyright (C) 2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc. @@ -29,7 +29,7 @@ static grub_ieee1275_ihandle_t stdout_ihandle; static grub_ieee1275_ihandle_t stdin_ihandle; -extern struct grub_terminfo_output_state grub_ofconsole_terminfo_output; +extern struct grub_terminfo_output_state grub_console_terminfo_output; struct color { @@ -74,7 +74,7 @@ readkey (struct grub_term_input *term __attribute__ ((unused))) } static void -grub_ofconsole_dimensions (void) +grub_console_dimensions (void) { grub_ieee1275_ihandle_t options; grub_ssize_t lval; @@ -90,7 +90,7 @@ grub_ofconsole_dimensions (void) if (! grub_ieee1275_get_property (options, "screen-#columns", val, lval, 0)) - grub_ofconsole_terminfo_output.width + grub_console_terminfo_output.width = (grub_uint8_t) grub_strtoul (val, 0, 10); } if (! grub_ieee1275_get_property_length (options, "screen-#rows", &lval) @@ -99,20 +99,20 @@ grub_ofconsole_dimensions (void) char val[lval]; if (! grub_ieee1275_get_property (options, "screen-#rows", val, lval, 0)) - grub_ofconsole_terminfo_output.height + grub_console_terminfo_output.height = (grub_uint8_t) grub_strtoul (val, 0, 10); } } /* Use a small console by default. */ - if (! grub_ofconsole_terminfo_output.width) - grub_ofconsole_terminfo_output.width = 80; - if (! grub_ofconsole_terminfo_output.height) - grub_ofconsole_terminfo_output.height = 24; + if (! grub_console_terminfo_output.width) + grub_console_terminfo_output.width = 80; + if (! grub_console_terminfo_output.height) + grub_console_terminfo_output.height = 24; } static void -grub_ofconsole_setcursor (struct grub_term_output *term, +grub_console_setcursor (struct grub_term_output *term, int on) { grub_terminfo_setcursor (term, on); @@ -128,7 +128,7 @@ grub_ofconsole_setcursor (struct grub_term_output *term, } static grub_err_t -grub_ofconsole_init_input (struct grub_term_input *term) +grub_console_init_input (struct grub_term_input *term) { grub_ssize_t actual; @@ -141,7 +141,7 @@ grub_ofconsole_init_input (struct grub_term_input *term) } static grub_err_t -grub_ofconsole_init_output (struct grub_term_output *term) +grub_console_init_output (struct grub_term_output *term) { grub_ssize_t actual; @@ -168,7 +168,7 @@ grub_ofconsole_init_output (struct grub_term_output *term) grub_terminfo_setcolorstate (term, GRUB_TERM_COLOR_NORMAL); } - grub_ofconsole_dimensions (); + grub_console_dimensions (); grub_terminfo_output_init (term); @@ -177,39 +177,39 @@ grub_ofconsole_init_output (struct grub_term_output *term) -struct grub_terminfo_input_state grub_ofconsole_terminfo_input = +struct grub_terminfo_input_state grub_console_terminfo_input = { .readkey = readkey }; -struct grub_terminfo_output_state grub_ofconsole_terminfo_output = +struct grub_terminfo_output_state grub_console_terminfo_output = { .put = put, .width = 80, .height = 24 }; -static struct grub_term_input grub_ofconsole_term_input = +static struct grub_term_input grub_console_term_input = { - .name = "ofconsole", - .init = grub_ofconsole_init_input, + .name = "console", + .init = grub_console_init_input, .getkey = grub_terminfo_getkey, - .data = &grub_ofconsole_terminfo_input + .data = &grub_console_terminfo_input }; -static struct grub_term_output grub_ofconsole_term_output = +static struct grub_term_output grub_console_term_output = { - .name = "ofconsole", - .init = grub_ofconsole_init_output, + .name = "console", + .init = grub_console_init_output, .putchar = grub_terminfo_putchar, .getxy = grub_terminfo_getxy, .getwh = grub_terminfo_getwh, .gotoxy = grub_terminfo_gotoxy, .cls = grub_terminfo_cls, .setcolorstate = grub_terminfo_setcolorstate, - .setcursor = grub_ofconsole_setcursor, + .setcursor = grub_console_setcursor, .flags = GRUB_TERM_CODE_TYPE_ASCII, - .data = &grub_ofconsole_terminfo_output, + .data = &grub_console_terminfo_output, .normal_color = GRUB_TERM_DEFAULT_NORMAL_COLOR, .highlight_color = GRUB_TERM_DEFAULT_HIGHLIGHT_COLOR, }; @@ -220,8 +220,8 @@ void grub_terminfo_init (void); void grub_console_init_early (void) { - grub_term_register_input ("ofconsole", &grub_ofconsole_term_input); - grub_term_register_output ("ofconsole", &grub_ofconsole_term_output); + grub_term_register_input ("console", &grub_console_term_input); + grub_term_register_output ("console", &grub_console_term_output); } void @@ -235,15 +235,15 @@ grub_console_init_lately (void) type = "ieee1275"; grub_terminfo_init (); - grub_terminfo_output_register (&grub_ofconsole_term_output, type); + grub_terminfo_output_register (&grub_console_term_output, type); } void grub_console_fini (void) { - grub_term_unregister_input (&grub_ofconsole_term_input); - grub_term_unregister_output (&grub_ofconsole_term_output); - grub_terminfo_output_unregister (&grub_ofconsole_term_output); + grub_term_unregister_input (&grub_console_term_input); + grub_term_unregister_output (&grub_console_term_output); + grub_terminfo_output_unregister (&grub_console_term_output); grub_terminfo_fini (); } diff --git a/grub-core/term/ns8250.c b/grub-core/term/ns8250.c index 996fc81f3..e6947f5e6 100644 --- a/grub-core/term/ns8250.c +++ b/grub-core/term/ns8250.c @@ -24,6 +24,7 @@ #include #include #include +#include #ifdef GRUB_MACHINE_PCBIOS #include @@ -194,19 +195,23 @@ serial_hw_configure (struct grub_serial_port *port, divisor = serial_get_divisor (port, config); if (divisor == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad speed"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("unsupported serial port speed")); if (config->parity != GRUB_SERIAL_PARITY_NONE && config->parity != GRUB_SERIAL_PARITY_ODD && config->parity != GRUB_SERIAL_PARITY_EVEN) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "unsupported parity"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("unsupported serial port parity")); if (config->stop_bits != GRUB_SERIAL_STOP_BITS_1 && config->stop_bits != GRUB_SERIAL_STOP_BITS_2) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "unsupported stop bits"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("unsupported serial port stop bits number")); if (config->word_len < 5 || config->word_len > 8) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "unsupported word length"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("unsupported serial port word length")); port->config = *config; port->configured = 0; diff --git a/grub-core/term/serial.c b/grub-core/term/serial.c index 86935626c..cbcc5952f 100644 --- a/grub-core/term/serial.c +++ b/grub-core/term/serial.c @@ -126,7 +126,7 @@ static struct grub_term_output grub_serial_term_output = struct grub_serial_port * -grub_serial_find (char *name) +grub_serial_find (const char *name) { struct grub_serial_port *port; @@ -157,7 +157,7 @@ grub_cmd_serial (grub_extcmd_context_t ctxt, int argc, char **args) { struct grub_arg_list *state = ctxt->state; char pname[40]; - char *name = NULL; + const char *name = NULL; struct grub_serial_port *port; struct grub_serial_config config; grub_err_t err; @@ -184,7 +184,9 @@ grub_cmd_serial (grub_extcmd_context_t ctxt, int argc, char **args) port = grub_serial_find (name); if (!port) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown serial port"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("serial port `%s' isn't found"), + name); config = port->config; @@ -203,7 +205,8 @@ grub_cmd_serial (grub_extcmd_context_t ctxt, int argc, char **args) else if (! grub_strcmp (state[4].arg, "even")) config.parity = GRUB_SERIAL_PARITY_EVEN; else - return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad parity"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("unsupported serial port parity")); } if (state[5].set) @@ -213,7 +216,8 @@ grub_cmd_serial (grub_extcmd_context_t ctxt, int argc, char **args) else if (! grub_strcmp (state[5].arg, "2")) config.stop_bits = GRUB_SERIAL_STOP_BITS_2; else - return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad number of stop bits"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, + N_("unsupported serial port stop bits number")); } /* Initialize with new settings. */ @@ -350,7 +354,7 @@ grub_serial_unregister (struct grub_serial_port *port) if (port->term_out) grub_term_unregister_output (port->term_out); - grub_list_remove (GRUB_AS_LIST_P (&grub_serial_ports), GRUB_AS_LIST (port)); + grub_list_remove (GRUB_AS_LIST (port)); } void diff --git a/grub-core/term/terminfo.c b/grub-core/term/terminfo.c index f8b29ec2e..cee146fba 100644 --- a/grub-core/term/terminfo.c +++ b/grub-core/term/terminfo.c @@ -169,7 +169,8 @@ grub_terminfo_set_current (struct grub_term_output *term, return grub_errno; } - return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminfo type"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("unknown terminfo type `%s'"), + str); } grub_err_t @@ -204,7 +205,7 @@ grub_terminfo_output_unregister (struct grub_term_output *term) *ptr = ((struct grub_terminfo_output_state *) (*ptr)->data)->next; return GRUB_ERR_NONE; } - return grub_error (GRUB_ERR_BAD_ARGUMENT, "terminal not found"); + return grub_error (GRUB_ERR_BUG, "terminal not found"); } /* Wrapper for grub_putchar to write strings. */ @@ -235,7 +236,7 @@ grub_terminfo_gotoxy (struct grub_term_output *term, if (x > grub_term_width (term) || y > grub_term_height (term)) { - grub_error (GRUB_ERR_OUT_OF_RANGE, "invalid point (%u,%u)", x, y); + grub_error (GRUB_ERR_BUG, "invalid point (%u,%u)", x, y); return; } @@ -599,10 +600,10 @@ print_terminfo (void) [GRUB_TERM_CODE_TYPE_UTF8_LOGICAL >> GRUB_TERM_CODE_TYPE_SHIFT] = _("UTF-8"), [GRUB_TERM_CODE_TYPE_UTF8_VISUAL >> GRUB_TERM_CODE_TYPE_SHIFT] - = _("UTF-8 visual"), + = _("visually-ordered UTF-8"), [GRUB_TERM_CODE_TYPE_VISUAL_GLYPHS >> GRUB_TERM_CODE_TYPE_SHIFT] = "Glyph descriptors", - _("Unknown"), _("Unknown"), _("Unknown") + _("Unknown encoding"), _("Unknown encoding"), _("Unknown encoding") }; struct grub_term_output *cur; @@ -623,7 +624,7 @@ static const struct grub_arg_option options[] = {"utf8", 'u', 0, N_("Terminal is logical-ordered UTF-8."), 0, ARG_TYPE_NONE}, {"visual-utf8", 'v', 0, N_("Terminal is visually-ordered UTF-8."), 0, ARG_TYPE_NONE}, - {"geometry", 'g', 0, N_("Terminal has given geometry."), + {"geometry", 'g', 0, N_("Terminal has specified geometry."), N_("WIDTHxHEIGHT."), ARG_TYPE_STRING}, {0, 0, 0, 0, 0, 0} }; @@ -664,7 +665,7 @@ grub_cmd_terminfo (grub_extcmd_context_t ctxt, int argc, char **args) return grub_errno; if (*ptr != 'x') return grub_error (GRUB_ERR_BAD_ARGUMENT, - "incorrect geometry specification"); + N_("incorrect terminal dimensions specification")); ptr++; h = grub_strtoul (ptr, &ptr, 0); if (grub_errno) @@ -673,7 +674,9 @@ grub_cmd_terminfo (grub_extcmd_context_t ctxt, int argc, char **args) for (cur = terminfo_outputs; cur; cur = ((struct grub_terminfo_output_state *) cur->data)->next) - if (grub_strcmp (args[0], cur->name) == 0) + if (grub_strcmp (args[0], cur->name) == 0 + || (grub_strcmp (args[0], "ofconsole") == 0 + && grub_strcmp ("console", cur->name) == 0)) { cur->flags = (cur->flags & ~GRUB_TERM_CODE_TYPE_MASK) | encoding; @@ -692,7 +695,7 @@ grub_cmd_terminfo (grub_extcmd_context_t ctxt, int argc, char **args) } return grub_error (GRUB_ERR_BAD_ARGUMENT, - "no terminal %s found or it's not handled by terminfo", + N_("terminal %s isn't found or it's not handled by terminfo"), args[0]); } diff --git a/grub-core/term/tparm.c b/grub-core/term/tparm.c index 076a192a5..8c1c288a0 100644 --- a/grub-core/term/tparm.c +++ b/grub-core/term/tparm.c @@ -745,7 +745,7 @@ tparam_internal(const char *string, va_list ap) return (out_buff); } -char * +const char * grub_terminfo_tparm (const char *string, ...) { va_list ap; diff --git a/grub-core/tests/lib/test.c b/grub-core/tests/lib/test.c index 06d78b7d7..da688efc0 100644 --- a/grub-core/tests/lib/test.c +++ b/grub-core/tests/lib/test.c @@ -24,6 +24,7 @@ struct grub_test_failure { /* The next failure. */ struct grub_test_failure *next; + struct grub_test_failure **prev; /* The test source file name. */ char *file; @@ -124,7 +125,7 @@ grub_test_unregister (const char *name) if (test) { - grub_list_remove (GRUB_AS_LIST_P (&grub_test_list), GRUB_AS_LIST (test)); + grub_list_remove (GRUB_AS_LIST (test)); if (test->name) grub_free (test->name); diff --git a/grub-core/video/bitmap.c b/grub-core/video/bitmap.c index 32e9358a3..67de93d8c 100644 --- a/grub-core/video/bitmap.c +++ b/grub-core/video/bitmap.c @@ -22,6 +22,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -60,12 +61,12 @@ grub_video_bitmap_create (struct grub_video_bitmap **bitmap, unsigned int size; if (!bitmap) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid argument"); + return grub_error (GRUB_ERR_BUG, "invalid argument"); *bitmap = 0; if (width == 0 || height == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid argument"); + return grub_error (GRUB_ERR_BUG, "invalid argument"); *bitmap = (struct grub_video_bitmap *)grub_malloc (sizeof (struct grub_video_bitmap)); if (! *bitmap) @@ -130,7 +131,7 @@ grub_video_bitmap_create (struct grub_video_bitmap **bitmap, grub_free (*bitmap); *bitmap = 0; - return grub_error (GRUB_ERR_BAD_ARGUMENT, + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "unsupported bitmap format"); } @@ -190,7 +191,7 @@ grub_video_bitmap_load (struct grub_video_bitmap **bitmap, grub_video_bitmap_reader_t reader = bitmap_readers_list; if (!bitmap) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid argument"); + return grub_error (GRUB_ERR_BUG, "invalid argument"); *bitmap = 0; @@ -202,7 +203,9 @@ grub_video_bitmap_load (struct grub_video_bitmap **bitmap, reader = reader->next; } - return grub_error(GRUB_ERR_BAD_FILE_TYPE, "unsupported bitmap format"); + return grub_error (GRUB_ERR_BAD_FILE_TYPE, + N_("bitmap file `%s' is of" + " unsupported format"), filename); } /* Return bitmap width. */ diff --git a/grub-core/video/bitmap_scale.c b/grub-core/video/bitmap_scale.c index 8da5697f8..73f50f611 100644 --- a/grub-core/video/bitmap_scale.c +++ b/grub-core/video/bitmap_scale.c @@ -54,22 +54,22 @@ grub_video_bitmap_create_scaled (struct grub_video_bitmap **dst, /* Verify the simplifying assumptions. */ if (src == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, + return grub_error (GRUB_ERR_BUG, "null src bitmap in grub_video_bitmap_create_scaled"); if (src->mode_info.red_field_pos % 8 != 0 || src->mode_info.green_field_pos % 8 != 0 || src->mode_info.blue_field_pos % 8 != 0 || src->mode_info.reserved_field_pos % 8 != 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "src format not supported for scale"); if (src->mode_info.width == 0 || src->mode_info.height == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, "source bitmap has a zero dimension"); if (dst_width <= 0 || dst_height <= 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, + return grub_error (GRUB_ERR_BUG, "requested to scale to a size w/ a zero dimension"); if (src->mode_info.bytes_per_pixel * 8 != src->mode_info.bpp) - return grub_error (GRUB_ERR_BAD_ARGUMENT, + return grub_error (GRUB_ERR_BUG, "bitmap to scale has inconsistent Bpp and bpp"); /* Create the new bitmap. */ @@ -90,7 +90,7 @@ grub_video_bitmap_create_scaled (struct grub_video_bitmap **dst, ret = scale_bilinear (*dst, src); break; default: - ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid scale_method value"); + ret = grub_error (GRUB_ERR_BUG, "Invalid scale_method value"); break; } @@ -123,17 +123,19 @@ scale_nn (struct grub_video_bitmap *dst, struct grub_video_bitmap *src) { /* Verify the simplifying assumptions. */ if (dst == 0 || src == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "null bitmap in scale_nn"); + return grub_error (GRUB_ERR_BUG, "null bitmap in scale_nn"); if (dst->mode_info.red_field_pos % 8 != 0 || dst->mode_info.green_field_pos % 8 != 0 || dst->mode_info.blue_field_pos % 8 != 0 || dst->mode_info.reserved_field_pos % 8 != 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "dst format not supported"); + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "dst format not supported"); if (src->mode_info.red_field_pos % 8 != 0 || src->mode_info.green_field_pos % 8 != 0 || src->mode_info.blue_field_pos % 8 != 0 || src->mode_info.reserved_field_pos % 8 != 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "src format not supported"); + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "src format not supported"); if (dst->mode_info.red_field_pos != src->mode_info.red_field_pos || dst->mode_info.red_mask_size != src->mode_info.red_mask_size || dst->mode_info.green_field_pos != src->mode_info.green_field_pos @@ -144,12 +146,14 @@ scale_nn (struct grub_video_bitmap *dst, struct grub_video_bitmap *src) src->mode_info.reserved_field_pos || dst->mode_info.reserved_mask_size != src->mode_info.reserved_mask_size) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "dst and src not compatible"); + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "dst and src not compatible"); if (dst->mode_info.bytes_per_pixel != src->mode_info.bytes_per_pixel) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "dst and src not compatible"); + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "dst and src not compatible"); if (dst->mode_info.width == 0 || dst->mode_info.height == 0 || src->mode_info.width == 0 || src->mode_info.height == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "bitmap has a zero dimension"); + return grub_error (GRUB_ERR_BUG, "bitmap has a zero dimension"); grub_uint8_t *ddata = dst->data; grub_uint8_t *sdata = src->data; @@ -206,17 +210,17 @@ scale_bilinear (struct grub_video_bitmap *dst, struct grub_video_bitmap *src) { /* Verify the simplifying assumptions. */ if (dst == 0 || src == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "null bitmap in scale func"); + return grub_error (GRUB_ERR_BUG, "null bitmap in scale func"); if (dst->mode_info.red_field_pos % 8 != 0 || dst->mode_info.green_field_pos % 8 != 0 || dst->mode_info.blue_field_pos % 8 != 0 || dst->mode_info.reserved_field_pos % 8 != 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "dst format not supported"); + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "dst format not supported"); if (src->mode_info.red_field_pos % 8 != 0 || src->mode_info.green_field_pos % 8 != 0 || src->mode_info.blue_field_pos % 8 != 0 || src->mode_info.reserved_field_pos % 8 != 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "src format not supported"); + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "src format not supported"); if (dst->mode_info.red_field_pos != src->mode_info.red_field_pos || dst->mode_info.red_mask_size != src->mode_info.red_mask_size || dst->mode_info.green_field_pos != src->mode_info.green_field_pos @@ -227,12 +231,12 @@ scale_bilinear (struct grub_video_bitmap *dst, struct grub_video_bitmap *src) src->mode_info.reserved_field_pos || dst->mode_info.reserved_mask_size != src->mode_info.reserved_mask_size) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "dst and src not compatible"); + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "dst and src not compatible"); if (dst->mode_info.bytes_per_pixel != src->mode_info.bytes_per_pixel) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "dst and src not compatible"); + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "dst and src not compatible"); if (dst->mode_info.width == 0 || dst->mode_info.height == 0 || src->mode_info.width == 0 || src->mode_info.height == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "bitmap has a zero dimension"); + return grub_error (GRUB_ERR_BUG, "bitmap has a zero dimension"); grub_uint8_t *ddata = dst->data; grub_uint8_t *sdata = src->data; diff --git a/grub-core/video/colors.c b/grub-core/video/colors.c index 06625183e..76359eaf0 100644 --- a/grub-core/video/colors.c +++ b/grub-core/video/colors.c @@ -22,6 +22,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -244,11 +245,14 @@ grub_err_t grub_video_parse_color (const char *s, grub_video_rgba_color_t *color) { grub_video_rgba_color_t c; + const char *s0; /* Skip whitespace. */ while (*s && grub_isspace (*s)) s++; + s0 = s; + if (*s == '#') { /* HTML-style. Number if hex digits: @@ -288,23 +292,26 @@ grub_video_parse_color (const char *s, grub_video_rgba_color_t *color) } else return grub_error (GRUB_ERR_BAD_ARGUMENT, - "invalid HTML-type color string `%s'", s); + N_("invalid color specification `%s'"), s0); } else if (grub_isdigit (*s)) { /* Comma separated decimal values. */ c.red = grub_strtoul (s, 0, 0); - if ((s = grub_strchr (s, ',')) == 0) + s = grub_strchr (s, ','); + if (!s) return grub_error (GRUB_ERR_BAD_ARGUMENT, - "missing 1st comma separator in color `%s'", s); + N_("invalid color specification `%s'"), s0); s++; c.green = grub_strtoul (s, 0, 0); - if ((s = grub_strchr (s, ',')) == 0) + s = grub_strchr (s, ','); + if (!s) return grub_error (GRUB_ERR_BAD_ARGUMENT, - "missing 2nd comma separator in color `%s'", s); + N_("invalid color specification `%s'"), s0); s++; c.blue = grub_strtoul (s, 0, 0); - if ((s = grub_strchr (s, ',')) == 0) + s = grub_strchr (s, ','); + if (!s) c.alpha = 255; else { @@ -316,7 +323,7 @@ grub_video_parse_color (const char *s, grub_video_rgba_color_t *color) { if (! grub_video_get_named_color (s, &c)) return grub_error (GRUB_ERR_BAD_ARGUMENT, - "invalid named color `%s'", s); + N_("invalid color specification `%s'"), s0); } if (grub_errno == GRUB_ERR_NONE) diff --git a/grub-core/video/fb/fbblit.c b/grub-core/video/fb/fbblit.c index 15797be97..4d262d710 100644 --- a/grub-core/video/fb/fbblit.c +++ b/grub-core/video/fb/fbblit.c @@ -80,13 +80,14 @@ grub_video_fbblit_replace_directN (struct grub_video_fbblit_info *dst, int bpp; bpp = src->mode_info->bytes_per_pixel; + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { - srcptr = (grub_uint32_t *)grub_video_fb_get_video_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint32_t *)grub_video_fb_get_video_ptr (dst, x, y + j); - grub_memmove (dstptr, srcptr, width * bpp); + GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, src->mode_info->pitch); + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dst->mode_info->pitch); } } @@ -101,7 +102,7 @@ grub_video_fbblit_replace_32bit_1bit (struct grub_video_fbblit_info *dst, int i; int j; grub_uint8_t *srcptr; - grub_uint8_t *dstptr; + grub_uint32_t *dstptr; grub_uint8_t srcmask; unsigned int dstrowskip; unsigned int srcrowskipbyte, srcrowskipbit; @@ -117,7 +118,7 @@ grub_video_fbblit_replace_32bit_1bit (struct grub_video_fbblit_info *dst, bit_index = offset_y * src->mode_info->width + offset_x; srcptr = (grub_uint8_t *) src->data + (bit_index >> 3); srcmask = 1 << (~bit_index & 7); - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); fgcolor = grub_video_fb_map_rgba (src->mode_info->fg_red, src->mode_info->fg_green, @@ -134,9 +135,9 @@ grub_video_fbblit_replace_32bit_1bit (struct grub_video_fbblit_info *dst, for (i = 0; i < width; i++) { if (*srcptr & srcmask) - *(grub_uint32_t *) dstptr = fgcolor; + *dstptr = fgcolor; else - *(grub_uint32_t *) dstptr = bgcolor; + *dstptr = bgcolor; srcmask >>= 1; if (!srcmask) { @@ -144,7 +145,7 @@ grub_video_fbblit_replace_32bit_1bit (struct grub_video_fbblit_info *dst, srcmask = 0x80; } - dstptr += 4; + dstptr++; } srcptr += srcrowskipbyte; @@ -155,11 +156,12 @@ grub_video_fbblit_replace_32bit_1bit (struct grub_video_fbblit_info *dst, srcptr++; srcmask <<= 8 - srcrowskipbit; } - dstptr += dstrowskip; + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip); } } +#ifdef GRUB_HAVE_UNALIGNED_ACCESS /* Optimized replacing blitter for 1-bit to 24-bit. */ void grub_video_fbblit_replace_24bit_1bit (struct grub_video_fbblit_info *dst, @@ -187,7 +189,7 @@ grub_video_fbblit_replace_24bit_1bit (struct grub_video_fbblit_info *dst, bit_index = offset_y * src->mode_info->width + offset_x; srcptr = (grub_uint8_t *) src->data + (bit_index >> 3); srcmask = 1 << (~bit_index & 7); - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); fgcolor = grub_video_fb_map_rgba (src->mode_info->fg_red, src->mode_info->fg_green, @@ -247,6 +249,7 @@ grub_video_fbblit_replace_24bit_1bit (struct grub_video_fbblit_info *dst, dstptr += dstrowskip; } } +#endif /* Optimized replacing blitter for 1-bit to 16-bit. */ void @@ -259,7 +262,7 @@ grub_video_fbblit_replace_16bit_1bit (struct grub_video_fbblit_info *dst, int i; int j; grub_uint8_t *srcptr; - grub_uint8_t *dstptr; + grub_uint16_t *dstptr; grub_uint8_t srcmask; unsigned int dstrowskip; unsigned int srcrowskipbyte, srcrowskipbit; @@ -275,7 +278,7 @@ grub_video_fbblit_replace_16bit_1bit (struct grub_video_fbblit_info *dst, bit_index = offset_y * src->mode_info->width + offset_x; srcptr = (grub_uint8_t *) src->data + (bit_index >> 3); srcmask = 1 << (~bit_index & 7); - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); fgcolor = grub_video_fb_map_rgba (src->mode_info->fg_red, src->mode_info->fg_green, @@ -292,9 +295,9 @@ grub_video_fbblit_replace_16bit_1bit (struct grub_video_fbblit_info *dst, for (i = 0; i < width; i++) { if (*srcptr & srcmask) - *(grub_uint16_t *) dstptr = fgcolor; + *dstptr = fgcolor; else - *(grub_uint16_t *) dstptr = bgcolor; + *dstptr = bgcolor; srcmask >>= 1; if (!srcmask) { @@ -302,7 +305,7 @@ grub_video_fbblit_replace_16bit_1bit (struct grub_video_fbblit_info *dst, srcmask = 0x80; } - dstptr += 2; + dstptr++; } srcptr += srcrowskipbyte; @@ -313,7 +316,7 @@ grub_video_fbblit_replace_16bit_1bit (struct grub_video_fbblit_info *dst, srcptr++; srcmask <<= 8 - srcrowskipbit; } - dstptr += dstrowskip; + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip); } } @@ -344,7 +347,7 @@ grub_video_fbblit_replace_8bit_1bit (struct grub_video_fbblit_info *dst, bit_index = offset_y * src->mode_info->width + offset_x; srcptr = (grub_uint8_t *) src->data + (bit_index >> 3); srcmask = 1 << (~bit_index & 7); - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); fgcolor = grub_video_fb_map_rgba (src->mode_info->fg_red, src->mode_info->fg_green, @@ -361,9 +364,9 @@ grub_video_fbblit_replace_8bit_1bit (struct grub_video_fbblit_info *dst, for (i = 0; i < width; i++) { if (*srcptr & srcmask) - *(grub_uint8_t *) dstptr = fgcolor; + *dstptr = fgcolor; else - *(grub_uint8_t *) dstptr = bgcolor; + *dstptr = bgcolor; srcmask >>= 1; if (!srcmask) { @@ -406,8 +409,8 @@ grub_video_fbblit_replace_BGRX8888_RGBX8888 (struct grub_video_fbblit_info *dst, srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; - srcptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (src, offset_x, offset_y); - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { @@ -449,8 +452,8 @@ grub_video_fbblit_replace_BGRX8888_RGB888 (struct grub_video_fbblit_info *dst, srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; - srcptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (src, offset_x, offset_y); - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { @@ -493,8 +496,8 @@ grub_video_fbblit_replace_BGR888_RGBX8888 (struct grub_video_fbblit_info *dst, srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; - srcptr = (grub_uint32_t *) grub_video_fb_get_video_ptr (src, offset_x, offset_y); - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { @@ -516,7 +519,7 @@ grub_video_fbblit_replace_BGR888_RGBX8888 (struct grub_video_fbblit_info *dst, *dstptr++ = sr; } - srcptr = (grub_uint32_t *) (((grub_uint8_t *) srcptr) + srcrowskip); + GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip); dstptr += dstrowskip; } } @@ -541,8 +544,8 @@ grub_video_fbblit_replace_BGR888_RGB888 (struct grub_video_fbblit_info *dst, srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; - srcptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (src, offset_x, offset_y); - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { @@ -578,12 +581,16 @@ grub_video_fbblit_replace_RGBX8888_RGB888 (struct grub_video_fbblit_info *dst, unsigned int sr; unsigned int sg; unsigned int sb; + grub_size_t srcrowskip; + grub_size_t dstrowskip; + + srcrowskip = src->mode_info->pitch - 3 * width; + dstrowskip = dst->mode_info->pitch - 4 * width; + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { - srcptr = (grub_uint8_t *)grub_video_fb_get_video_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint32_t *)grub_video_fb_get_video_ptr (dst, x, y + j); - for (i = 0; i < width; i++) { sr = *srcptr++; @@ -595,6 +602,8 @@ grub_video_fbblit_replace_RGBX8888_RGB888 (struct grub_video_fbblit_info *dst, *dstptr++ = color; } + GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip); + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip); } } @@ -614,12 +623,16 @@ grub_video_fbblit_replace_RGB888_RGBX8888 (struct grub_video_fbblit_info *dst, unsigned int sr; unsigned int sg; unsigned int sb; + grub_size_t srcrowskip; + grub_size_t dstrowskip; + + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); + srcrowskip = src->mode_info->pitch - 4 * width; + dstrowskip = dst->mode_info->pitch - 3 * width; for (j = 0; j < height; j++) { - srcptr = (grub_uint32_t *)grub_video_fb_get_video_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint8_t *)grub_video_fb_get_video_ptr (dst, x, y + j); - for (i = 0; i < width; i++) { color = *srcptr++; @@ -632,6 +645,8 @@ grub_video_fbblit_replace_RGB888_RGBX8888 (struct grub_video_fbblit_info *dst, *dstptr++ = sg; *dstptr++ = sb; } + GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip); + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip); } } @@ -651,12 +666,17 @@ grub_video_fbblit_replace_index_RGBX8888 (struct grub_video_fbblit_info *dst, unsigned int sr; unsigned int sg; unsigned int sb; + grub_size_t srcrowskip; + grub_size_t dstrowskip; + + srcrowskip = src->mode_info->pitch - 4 * width; + dstrowskip = dst->mode_info->pitch - width; + + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { - srcptr = (grub_uint32_t *)grub_video_fb_get_video_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint8_t *)grub_video_fb_get_video_ptr (dst, x, y + j); - for (i = 0; i < width; i++) { color = *srcptr++; @@ -668,6 +688,8 @@ grub_video_fbblit_replace_index_RGBX8888 (struct grub_video_fbblit_info *dst, color = grub_video_fb_map_rgb(sr, sg, sb); *dstptr++ = color & 0xFF; } + GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip); + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip); } } @@ -687,12 +709,17 @@ grub_video_fbblit_replace_index_RGB888 (struct grub_video_fbblit_info *dst, unsigned int sr; unsigned int sg; unsigned int sb; + grub_size_t srcrowskip; + grub_size_t dstrowskip; + + srcrowskip = src->mode_info->pitch - 3 * width; + dstrowskip = dst->mode_info->pitch - width; + + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { - srcptr = (grub_uint8_t *)grub_video_fb_get_video_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint8_t *)grub_video_fb_get_video_ptr (dst, x, y + j); - for (i = 0; i < width; i++) { sr = *srcptr++; @@ -703,6 +730,8 @@ grub_video_fbblit_replace_index_RGB888 (struct grub_video_fbblit_info *dst, *dstptr++ = color & 0xFF; } + GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip); + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip); } } @@ -787,8 +816,8 @@ grub_video_fbblit_blend_BGRA8888_RGBA8888 (struct grub_video_fbblit_info *dst, srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; - srcptr = (grub_uint32_t *) grub_video_fb_get_video_ptr (src, offset_x, offset_y); - dstptr = (grub_uint32_t *) grub_video_fb_get_video_ptr (dst, x, y); + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { @@ -843,8 +872,8 @@ grub_video_fbblit_blend_BGRA8888_RGBA8888 (struct grub_video_fbblit_info *dst, *dstptr++ = color; } - srcptr = (grub_uint32_t *) (((grub_uint8_t *) srcptr) + srcrowskip); - dstptr = (grub_uint32_t *) (((grub_uint8_t *) dstptr) + dstrowskip); + GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip); + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip); } } @@ -868,8 +897,8 @@ grub_video_fbblit_blend_BGR888_RGBA8888 (struct grub_video_fbblit_info *dst, srcrowskip = src->mode_info->pitch - src->mode_info->bytes_per_pixel * width; dstrowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; - srcptr = (grub_uint32_t *) grub_video_fb_get_video_ptr (src, offset_x, offset_y); - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { @@ -924,7 +953,7 @@ grub_video_fbblit_blend_BGR888_RGBA8888 (struct grub_video_fbblit_info *dst, *dstptr++ = dr; } - srcptr = (grub_uint32_t *) (((grub_uint8_t *) srcptr) + srcrowskip); + GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip); dstptr += dstrowskip; } } @@ -949,12 +978,17 @@ grub_video_fbblit_blend_RGBA8888_RGBA8888 (struct grub_video_fbblit_info *dst, unsigned int dr; unsigned int dg; unsigned int db; + grub_size_t srcrowskip; + grub_size_t dstrowskip; + + srcrowskip = src->mode_info->pitch - 4 * width; + dstrowskip = dst->mode_info->pitch - 4 * width; + + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { - srcptr = (grub_uint32_t *)grub_video_fb_get_video_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint32_t *)grub_video_fb_get_video_ptr (dst, x, y + j); - for (i = 0; i < width; i++) { color = *srcptr++; @@ -991,6 +1025,8 @@ grub_video_fbblit_blend_RGBA8888_RGBA8888 (struct grub_video_fbblit_info *dst, *dstptr++ = color; } + GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip); + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip); } } @@ -1014,12 +1050,17 @@ grub_video_fbblit_blend_RGB888_RGBA8888 (struct grub_video_fbblit_info *dst, unsigned int dr; unsigned int dg; unsigned int db; + grub_size_t srcrowskip; + grub_size_t dstrowskip; + + srcrowskip = src->mode_info->pitch - 4 * width; + dstrowskip = dst->mode_info->pitch - 3 * width; + + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { - srcptr = (grub_uint32_t *)grub_video_fb_get_video_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint8_t *)grub_video_fb_get_video_ptr (dst, x, y + j); - for (i = 0; i < width; i++) { color = *srcptr++; @@ -1057,6 +1098,8 @@ grub_video_fbblit_blend_RGB888_RGBA8888 (struct grub_video_fbblit_info *dst, *dstptr++ = dg; *dstptr++ = db; } + GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip); + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip); } } @@ -1081,12 +1124,17 @@ grub_video_fbblit_blend_index_RGBA8888 (struct grub_video_fbblit_info *dst, unsigned char dg; unsigned char db; unsigned char da; + grub_size_t srcrowskip; + grub_size_t dstrowskip; + + srcrowskip = src->mode_info->pitch - 4 * width; + dstrowskip = dst->mode_info->pitch - width; + + srcptr = grub_video_fb_get_video_ptr (src, offset_x, offset_y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { - srcptr = (grub_uint32_t *)grub_video_fb_get_video_ptr (src, offset_x, j + offset_y); - dstptr = (grub_uint8_t *)grub_video_fb_get_video_ptr (dst, x, y + j); - for (i = 0; i < width; i++) { color = *srcptr++; @@ -1120,6 +1168,8 @@ grub_video_fbblit_blend_index_RGBA8888 (struct grub_video_fbblit_info *dst, *dstptr++ = color & 0xFF; } + GRUB_VIDEO_FB_ADVANCE_POINTER (srcptr, srcrowskip); + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip); } } @@ -1134,7 +1184,7 @@ grub_video_fbblit_blend_XXXA8888_1bit (struct grub_video_fbblit_info *dst, int i; int j; grub_uint8_t *srcptr; - grub_uint8_t *dstptr; + grub_uint32_t *dstptr; grub_uint8_t srcmask; unsigned int dstrowskip; unsigned int srcrowskipbyte, srcrowskipbit; @@ -1150,7 +1200,7 @@ grub_video_fbblit_blend_XXXA8888_1bit (struct grub_video_fbblit_info *dst, bit_index = offset_y * src->mode_info->width + offset_x; srcptr = (grub_uint8_t *) src->data + (bit_index >> 3); srcmask = 1 << (~bit_index & 7); - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); fgcolor = grub_video_fb_map_rgba (src->mode_info->fg_red, src->mode_info->fg_green, @@ -1181,23 +1231,22 @@ grub_video_fbblit_blend_XXXA8888_1bit (struct grub_video_fbblit_info *dst, } if (a == 255) - *(grub_uint32_t *) dstptr = color; + *dstptr = color; else if (a != 0) { grub_uint8_t s1 = (color >> 0) & 0xFF; grub_uint8_t s2 = (color >> 8) & 0xFF; grub_uint8_t s3 = (color >> 16) & 0xFF; - grub_uint8_t d1 = (*(grub_uint32_t *) dstptr >> 0) & 0xFF; - grub_uint8_t d2 = (*(grub_uint32_t *) dstptr >> 8) & 0xFF; - grub_uint8_t d3 = (*(grub_uint32_t *) dstptr >> 16) & 0xFF; + grub_uint8_t d1 = (*dstptr >> 0) & 0xFF; + grub_uint8_t d2 = (*dstptr >> 8) & 0xFF; + grub_uint8_t d3 = (*dstptr >> 16) & 0xFF; d1 = (d1 * (255 - a) + s1 * a) / 255; d2 = (d2 * (255 - a) + s2 * a) / 255; d3 = (d3 * (255 - a) + s3 * a) / 255; - *(grub_uint32_t *) dstptr = (a << 24) | (d3 << 16) | (d2 << 8) - | d1; + *dstptr = (a << 24) | (d3 << 16) | (d2 << 8) | d1; } srcmask >>= 1; @@ -1207,7 +1256,7 @@ grub_video_fbblit_blend_XXXA8888_1bit (struct grub_video_fbblit_info *dst, srcmask = 0x80; } - dstptr += 4; + dstptr++; } srcptr += srcrowskipbyte; @@ -1218,11 +1267,12 @@ grub_video_fbblit_blend_XXXA8888_1bit (struct grub_video_fbblit_info *dst, srcptr++; srcmask <<= 8 - srcrowskipbit; } - dstptr += dstrowskip; + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip); } } /* Optimized blending blitter for 1-bit to XXX888. */ +#ifdef GRUB_HAVE_UNALIGNED_ACCESS void grub_video_fbblit_blend_XXX888_1bit (struct grub_video_fbblit_info *dst, struct grub_video_fbblit_info *src, @@ -1249,7 +1299,7 @@ grub_video_fbblit_blend_XXX888_1bit (struct grub_video_fbblit_info *dst, bit_index = offset_y * src->mode_info->width + offset_x; srcptr = (grub_uint8_t *) src->data + (bit_index >> 3); srcmask = 1 << (~bit_index & 7); - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); fgcolor = grub_video_fb_map_rgba (src->mode_info->fg_red, src->mode_info->fg_green, @@ -1320,6 +1370,7 @@ grub_video_fbblit_blend_XXX888_1bit (struct grub_video_fbblit_info *dst, dstptr += dstrowskip; } } +#endif /* Optimized blending blitter for 1-bit to XXX888. */ void @@ -1332,7 +1383,7 @@ grub_video_fbblit_blend_XXX565_1bit (struct grub_video_fbblit_info *dst, int i; int j; grub_uint8_t *srcptr; - grub_uint8_t *dstptr; + grub_uint16_t *dstptr; grub_uint8_t srcmask; unsigned int dstrowskip; unsigned int srcrowskipbyte, srcrowskipbit; @@ -1348,7 +1399,7 @@ grub_video_fbblit_blend_XXX565_1bit (struct grub_video_fbblit_info *dst, bit_index = offset_y * src->mode_info->width + offset_x; srcptr = (grub_uint8_t *) src->data + (bit_index >> 3); srcmask = 1 << (~bit_index & 7); - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); fgcolor = grub_video_fb_map_rgba (src->mode_info->fg_red, src->mode_info->fg_green, @@ -1378,23 +1429,22 @@ grub_video_fbblit_blend_XXX565_1bit (struct grub_video_fbblit_info *dst, } if (a == 255) - *(grub_uint16_t *) dstptr = color; + *dstptr = color; else if (a != 0) { grub_uint8_t s1 = (color >> 0) & 0x1F; grub_uint8_t s2 = (color >> 5) & 0x3F; grub_uint8_t s3 = (color >> 11) & 0x1F; - grub_uint8_t d1 = (*(grub_uint16_t *) dstptr >> 0) & 0x1F; - grub_uint8_t d2 = (*(grub_uint16_t *) dstptr >> 5) & 0x3F; - grub_uint8_t d3 = (*(grub_uint16_t *) dstptr >> 11) & 0x1F; + grub_uint8_t d1 = (*dstptr >> 0) & 0x1F; + grub_uint8_t d2 = (*dstptr >> 5) & 0x3F; + grub_uint8_t d3 = (*dstptr >> 11) & 0x1F; d1 = (d1 * (255 - a) + s1 * a) / 255; d2 = (d2 * (255 - a) + s2 * a) / 255; d3 = (d3 * (255 - a) + s3 * a) / 255; - *(grub_uint16_t *) dstptr = (d1 & 0x1f) | ((d2 & 0x3f) << 5) - | ((d3 & 0x1f) << 11); + *dstptr = (d1 & 0x1f) | ((d2 & 0x3f) << 5) | ((d3 & 0x1f) << 11); } srcmask >>= 1; @@ -1404,7 +1454,7 @@ grub_video_fbblit_blend_XXX565_1bit (struct grub_video_fbblit_info *dst, srcmask = 0x80; } - dstptr += 2; + dstptr++; } srcptr += srcrowskipbyte; @@ -1415,6 +1465,6 @@ grub_video_fbblit_blend_XXX565_1bit (struct grub_video_fbblit_info *dst, srcptr++; srcmask <<= 8 - srcrowskipbit; } - dstptr += dstrowskip; + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, dstrowskip); } } diff --git a/grub-core/video/fb/fbfill.c b/grub-core/video/fb/fbfill.c index a4ca7c2a1..5f3e55fae 100644 --- a/grub-core/video/fb/fbfill.c +++ b/grub-core/video/fb/fbfill.c @@ -64,7 +64,7 @@ grub_video_fbfill_direct32 (struct grub_video_fbblit_info *dst, rowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; /* Get the start address. */ - dstptr = (grub_uint32_t *) grub_video_fb_get_video_ptr (dst, x, y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { @@ -72,7 +72,7 @@ grub_video_fbfill_direct32 (struct grub_video_fbblit_info *dst, *dstptr++ = color; /* Advance the dest pointer to the right location on the next line. */ - dstptr = (grub_uint32_t *) (((char *) dstptr) + rowskip); + GRUB_VIDEO_FB_ADVANCE_POINTER (dstptr, rowskip); } } @@ -96,7 +96,7 @@ grub_video_fbfill_direct24 (struct grub_video_fbblit_info *dst, rowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; /* Get the start address. */ - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { @@ -131,7 +131,7 @@ grub_video_fbfill_direct16 (struct grub_video_fbblit_info *dst, rowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; /* Get the start address. */ - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { @@ -164,7 +164,7 @@ grub_video_fbfill_direct8 (struct grub_video_fbblit_info *dst, rowskip = dst->mode_info->pitch - dst->mode_info->bytes_per_pixel * width; /* Get the start address. */ - dstptr = (grub_uint8_t *) grub_video_fb_get_video_ptr (dst, x, y); + dstptr = grub_video_fb_get_video_ptr (dst, x, y); for (j = 0; j < height; j++) { diff --git a/grub-core/video/fb/fbutil.c b/grub-core/video/fb/fbutil.c index 511beaafc..c7fb08702 100644 --- a/grub-core/video/fb/fbutil.c +++ b/grub-core/video/fb/fbutil.c @@ -31,7 +31,7 @@ #include #include -grub_uint8_t * +void * grub_video_fb_get_video_ptr (struct grub_video_fbblit_info *source, unsigned int x, unsigned int y) { diff --git a/grub-core/video/fb/video_fb.c b/grub-core/video/fb/video_fb.c index 2cffcb3d9..2ab403db2 100644 --- a/grub-core/video/fb/video_fb.c +++ b/grub-core/video/fb/video_fb.c @@ -622,6 +622,7 @@ common_blitter (struct grub_video_fbblit_info *target, offset_x, offset_y); return; } +#ifdef GRUB_HAVE_UNALIGNED_ACCESS else if (target->mode_info->bpp == 24) { grub_video_fbblit_replace_24bit_1bit (target, source, @@ -629,6 +630,7 @@ common_blitter (struct grub_video_fbblit_info *target, offset_x, offset_y); return; } +#endif else if (target->mode_info->bpp == 16) { grub_video_fbblit_replace_16bit_1bit (target, source, @@ -743,6 +745,7 @@ common_blitter (struct grub_video_fbblit_info *target, offset_x, offset_y); return; } +#ifdef GRUB_HAVE_UNALIGNED_ACCESS else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_888 || target->mode_info->blit_format @@ -753,6 +756,7 @@ common_blitter (struct grub_video_fbblit_info *target, offset_x, offset_y); return; } +#endif else if (target->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGR_565 || target->mode_info->blit_format @@ -1126,7 +1130,7 @@ grub_video_fb_create_render_target (struct grub_video_fbrender_target **result, if ((! result) || (width == 0) || (height == 0)) - return grub_error (GRUB_ERR_BAD_ARGUMENT, + return grub_error (GRUB_ERR_BUG, "invalid argument given"); /* Allocate memory for render target. */ @@ -1195,6 +1199,15 @@ grub_video_fb_create_render_target_from_pointer (struct grub_video_fbrender_targ struct grub_video_fbrender_target *target; unsigned y; +#ifndef GRUB_HAVE_UNALIGNED_ACCESS + if (!(mode_info->bytes_per_pixel & (mode_info->bytes_per_pixel - 1)) + && ((grub_addr_t) ptr & (mode_info->bytes_per_pixel - 1))) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "unaligned pointer"); + if (!(mode_info->bytes_per_pixel & (mode_info->bytes_per_pixel - 1)) + && (mode_info->pitch & (mode_info->bytes_per_pixel - 1))) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "unaligned pitch"); +#endif + /* Allocate memory for render target. */ target = grub_malloc (sizeof (struct grub_video_fbrender_target)); if (! target) @@ -1250,7 +1263,7 @@ grub_video_fb_set_active_render_target (struct grub_video_fbrender_target *targe target = framebuffer.back_target; if (! target->data) - return grub_error (GRUB_ERR_BAD_ARGUMENT, + return grub_error (GRUB_ERR_BUG, "invalid render target given"); framebuffer.render_target = target; diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c index 92dd7ec07..51815d962 100644 --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -434,7 +434,7 @@ grub_vbe_get_preferred_mode (unsigned int *width, unsigned int *height) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "cannot get preferred mode"); } -grub_err_t +static grub_err_t grub_vbe_set_video_mode (grub_uint32_t vbe_mode, struct grub_vbe_mode_info_block *vbe_mode_info) { diff --git a/grub-core/video/radeon_fuloong2e.c b/grub-core/video/radeon_fuloong2e.c index 3a65b6720..0d78267bc 100644 --- a/grub-core/video/radeon_fuloong2e.c +++ b/grub-core/video/radeon_fuloong2e.c @@ -98,7 +98,7 @@ grub_video_radeon_fuloong2e_setup (unsigned int width, unsigned int height, if ((width != 640 && width != 0) || (height != 480 && height != 0) || (depth != 16 && depth != 0)) return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "Only 1024x600x16 is supported"); + "Only 640x480x16 is supported"); grub_pci_iterate (find_card); if (!found) diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c index f2351dee9..f5e63aee2 100644 --- a/grub-core/video/readers/jpeg.c +++ b/grub-core/video/readers/jpeg.c @@ -773,7 +773,7 @@ grub_cmd_jpegtest (grub_command_t cmd __attribute__ ((unused)), struct grub_video_bitmap *bitmap = 0; if (argc != 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); grub_video_reader_jpeg (&bitmap, args[0]); if (grub_errno != GRUB_ERR_NONE) diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c index ae9879b16..7ef7e3b4c 100644 --- a/grub-core/video/readers/png.c +++ b/grub-core/video/readers/png.c @@ -877,7 +877,7 @@ grub_cmd_pngtest (grub_command_t cmd __attribute__ ((unused)), struct grub_video_bitmap *bitmap = 0; if (argc != 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected")); grub_video_reader_png (&bitmap, args[0]); if (grub_errno != GRUB_ERR_NONE) diff --git a/grub-core/video/sis315pro.c b/grub-core/video/sis315pro.c index 22064c91e..c8e63a5a4 100644 --- a/grub-core/video/sis315pro.c +++ b/grub-core/video/sis315pro.c @@ -128,7 +128,7 @@ grub_video_sis315pro_setup (unsigned int width, unsigned int height, if ((width != 640 && width != 0) || (height != 480 && height != 0) || (depth != 8 && depth != 0)) return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "Only 640x400x8 is supported"); + "Only 640x480x8 is supported"); grub_pci_iterate (find_card); if (!found) diff --git a/grub-core/video/sm712.c b/grub-core/video/sm712.c index 60f2c9089..bc38b2e92 100644 --- a/grub-core/video/sm712.c +++ b/grub-core/video/sm712.c @@ -30,6 +30,8 @@ #include "sm712_init.c" +#pragma GCC diagnostic ignored "-Wcast-align" + #define GRUB_SM712_TOTAL_MEMORY_SPACE 0x700400 #define GRUB_SM712_REG_BASE 0x700000 #define GRUB_SM712_PCIID 0x0712126f diff --git a/grub-core/video/video.c b/grub-core/video/video.c index ad87a69ff..cfcb70e4f 100644 --- a/grub-core/video/video.c +++ b/grub-core/video/video.c @@ -21,6 +21,7 @@ #include #include #include +#include GRUB_MOD_LICENSE ("GPLv3+"); @@ -440,7 +441,7 @@ parse_modespec (const char *current_mode, int *width, int *height, int *depth) param = grub_strchr(param, 'x'); if (param == NULL) return grub_error (GRUB_ERR_BAD_ARGUMENT, - "Invalid mode: %s\n", + N_("invalid video mode specification `%s'"), current_mode); param++; @@ -448,7 +449,7 @@ parse_modespec (const char *current_mode, int *width, int *height, int *depth) *width = grub_strtoul (value, 0, 0); if (grub_errno != GRUB_ERR_NONE) return grub_error (GRUB_ERR_BAD_ARGUMENT, - "Invalid mode: %s\n", + N_("invalid video mode specification `%s'"), current_mode); /* Find height value. */ @@ -459,7 +460,7 @@ parse_modespec (const char *current_mode, int *width, int *height, int *depth) *height = grub_strtoul (value, 0, 0); if (grub_errno != GRUB_ERR_NONE) return grub_error (GRUB_ERR_BAD_ARGUMENT, - "Invalid mode: %s\n", + N_("invalid video mode specification `%s'"), current_mode); } else @@ -470,7 +471,7 @@ parse_modespec (const char *current_mode, int *width, int *height, int *depth) *height = grub_strtoul (value, 0, 0); if (grub_errno != GRUB_ERR_NONE) return grub_error (GRUB_ERR_BAD_ARGUMENT, - "Invalid mode: %s\n", + N_("invalid video mode specification `%s'"), current_mode); /* Convert color depth value. */ @@ -478,7 +479,7 @@ parse_modespec (const char *current_mode, int *width, int *height, int *depth) *depth = grub_strtoul (value, 0, 0); if (grub_errno != GRUB_ERR_NONE) return grub_error (GRUB_ERR_BAD_ARGUMENT, - "Invalid mode: %s\n", + N_("invalid video mode specification `%s'"), current_mode); } return GRUB_ERR_NONE; @@ -503,8 +504,7 @@ grub_video_set_mode (const char *modestring, next_mode = modevar; if (! modevar) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, - "couldn't allocate space for local modevar copy"); + return grub_errno; if (grub_memcmp (next_mode, "keep", sizeof ("keep")) == 0 || grub_memcmp (next_mode, "keep,", sizeof ("keep,") - 1) == 0 @@ -541,7 +541,7 @@ grub_video_set_mode (const char *modestring, grub_free (modevar); return grub_error (GRUB_ERR_BAD_ARGUMENT, - "no suitable mode found"); + N_("no suitable video mode found")); } /* Skip separator. */ @@ -705,7 +705,7 @@ grub_video_set_mode (const char *modestring, grub_free (modevar); return grub_error (GRUB_ERR_BAD_ARGUMENT, - "no suitable mode found"); + N_("no suitable video mode found")); } /* Initialize Video API module. */ diff --git a/include/grub/arc/arc.h b/include/grub/arc/arc.h index aae73052b..a825a9877 100644 --- a/include/grub/arc/arc.h +++ b/include/grub/arc/arc.h @@ -139,6 +139,13 @@ enum GRUB_ARC_COMPONENT_TYPE_MEMORY_UNIT, }; +enum grub_arc_file_access + { + GRUB_ARC_FILE_ACCESS_OPEN_RO, + GRUB_ARC_FILE_ACCESS_OPEN_WO, + GRUB_ARC_FILE_ACCESS_OPEN_RW, + }; + struct grub_arc_fileinfo { grub_arc_ularge_t start; @@ -195,7 +202,7 @@ struct grub_arc_firmware_vector grub_arc_ulong_t n, grub_arc_ulong_t *count); grub_arc_err_t (*get_read_status) (grub_arc_fileno_t fileno); - grub_arc_err_t (*write) (grub_arc_fileno_t fileno, void *buf, + grub_arc_err_t (*write) (grub_arc_fileno_t fileno, const void *buf, grub_arc_ulong_t n, grub_arc_ulong_t *count); diff --git a/include/grub/ata.h b/include/grub/ata.h index 1a19f27aa..efba7b71d 100644 --- a/include/grub/ata.h +++ b/include/grub/ata.h @@ -182,6 +182,8 @@ struct grub_ata int dma; + grub_size_t maxbuffer; + int *present; void *data; diff --git a/include/grub/charset.h b/include/grub/charset.h index c8247f78a..3036d1693 100644 --- a/include/grub/charset.h +++ b/include/grub/charset.h @@ -36,20 +36,48 @@ #define GRUB_UINT8_5_TRAILINGBITS 0x1f #define GRUB_UINT8_6_TRAILINGBITS 0x3f +#define GRUB_MAX_UTF8_PER_UTF16 4 + #define GRUB_UCS2_LIMIT 0x10000 #define GRUB_UTF16_UPPER_SURROGATE(code) \ (0xD800 + ((((code) - GRUB_UCS2_LIMIT) >> 12) & 0xfff)) #define GRUB_UTF16_LOWER_SURROGATE(code) \ (0xDC00 + (((code) - GRUB_UCS2_LIMIT) & 0xfff)) -grub_ssize_t +grub_size_t grub_utf8_to_utf16 (grub_uint16_t *dest, grub_size_t destsize, const grub_uint8_t *src, grub_size_t srcsize, const grub_uint8_t **srcend); +/* Determine the last position where the UTF-8 string [beg, end) can + be safely cut. */ +static inline grub_size_t +grub_getend (const char *beg, const char *end) +{ + const char *ptr; + for (ptr = end - 1; ptr >= beg; ptr--) + if ((*ptr & GRUB_UINT8_2_LEADINGBITS) != GRUB_UINT8_1_LEADINGBIT) + break; + if (ptr < beg) + return 0; + if ((*ptr & GRUB_UINT8_1_LEADINGBIT) == 0) + return ptr + 1 - beg; + if ((*ptr & GRUB_UINT8_3_LEADINGBITS) == GRUB_UINT8_2_LEADINGBITS + && ptr + 2 <= end) + return ptr + 2 - beg; + if ((*ptr & GRUB_UINT8_4_LEADINGBITS) == GRUB_UINT8_3_LEADINGBITS + && ptr + 3 <= end) + return ptr + 3 - beg; + if ((*ptr & GRUB_UINT8_5_LEADINGBITS) == GRUB_UINT8_4_LEADINGBITS + && ptr + 4 <= end) + return ptr + 4 - beg; + /* Invalid character or incomplete. Cut before it. */ + return ptr - beg; +} + /* Convert UTF-16 to UTF-8. */ static inline grub_uint8_t * -grub_utf16_to_utf8 (grub_uint8_t *dest, grub_uint16_t *src, +grub_utf16_to_utf8 (grub_uint8_t *dest, const grub_uint16_t *src, grub_size_t size) { grub_uint32_t code_high = 0; @@ -74,6 +102,8 @@ grub_utf16_to_utf8 (grub_uint8_t *dest, grub_uint16_t *src, { /* Error... */ *dest++ = '?'; + /* *src may be valid. Don't eat it. */ + src--; } code_high = 0; @@ -116,19 +146,52 @@ grub_utf16_to_utf8 (grub_uint8_t *dest, grub_uint16_t *src, return dest; } +#define GRUB_MAX_UTF8_PER_LATIN1 2 + +/* Convert Latin1 to UTF-8. */ +static inline grub_uint8_t * +grub_latin1_to_utf8 (grub_uint8_t *dest, const grub_uint8_t *src, + grub_size_t size) +{ + while (size--) + { + if (!(*src & 0x80)) + *dest++ = *src; + else + { + *dest++ = (*src >> 6) | 0xC0; + *dest++ = (*src & 0x3F) | 0x80; + } + src++; + } + + return dest; +} + /* Convert UCS-4 to UTF-8. */ -char *grub_ucs4_to_utf8_alloc (grub_uint32_t *src, grub_size_t size); +char *grub_ucs4_to_utf8_alloc (const grub_uint32_t *src, grub_size_t size); int grub_is_valid_utf8 (const grub_uint8_t *src, grub_size_t srcsize); int grub_utf8_to_ucs4_alloc (const char *msg, grub_uint32_t **unicode_msg, grub_uint32_t **last_position); + +/* Process one character from UTF8 sequence. + At beginning set *code = 0, *count = 0. Returns 0 on failure and + 1 on success. *count holds the number of trailing bytes. */ +int +grub_utf8_process (grub_uint8_t c, grub_uint32_t *code, int *count); + void -grub_ucs4_to_utf8 (grub_uint32_t *src, grub_size_t size, +grub_ucs4_to_utf8 (const grub_uint32_t *src, grub_size_t size, grub_uint8_t *dest, grub_size_t destsize); grub_size_t grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize, const grub_uint8_t *src, grub_size_t srcsize, const grub_uint8_t **srcend); +/* Returns -2 if not enough space, -1 on invalid character. */ +grub_ssize_t +grub_encode_utf8_character (grub_uint8_t *dest, grub_uint8_t *destend, + grub_uint32_t code); #endif diff --git a/include/grub/command.h b/include/grub/command.h index 19622752e..57c06da46 100644 --- a/include/grub/command.h +++ b/include/grub/command.h @@ -49,6 +49,7 @@ struct grub_command { /* The next element. */ struct grub_command *next; + struct grub_command **prev; /* The name. */ const char *name; diff --git a/include/grub/crypto.h b/include/grub/crypto.h index b8a5b3a22..67e0a1bf4 100644 --- a/include/grub/crypto.h +++ b/include/grub/crypto.h @@ -198,8 +198,40 @@ grub_crypto_cipher_close (grub_crypto_cipher_handle_t cipher) grub_free (cipher); } -void -grub_crypto_xor (void *out, const void *in1, const void *in2, grub_size_t size); +static inline void +grub_crypto_xor (void *out, const void *in1, const void *in2, grub_size_t size) +{ + const grub_uint8_t *in1ptr = in1, *in2ptr = in2; + grub_uint8_t *outptr = out; + while (size && (((grub_addr_t) in1ptr & (sizeof (grub_uint64_t) - 1)) + || ((grub_addr_t) in2ptr & (sizeof (grub_uint64_t) - 1)) + || ((grub_addr_t) outptr & (sizeof (grub_uint64_t) - 1)))) + { + *outptr = *in1ptr ^ *in2ptr; + in1ptr++; + in2ptr++; + outptr++; + size--; + } + while (size >= sizeof (grub_uint64_t)) + { + *(grub_uint64_t *) (void *) outptr + = (*(grub_uint64_t *) (void *) in1ptr + ^ *(grub_uint64_t *) (void *) in2ptr); + in1ptr += sizeof (grub_uint64_t); + in2ptr += sizeof (grub_uint64_t); + outptr += sizeof (grub_uint64_t); + size -= sizeof (grub_uint64_t); + } + while (size) + { + *outptr = *in1ptr ^ *in2ptr; + in1ptr++; + in2ptr++; + outptr++; + size--; + } +} gcry_err_code_t grub_crypto_ecb_decrypt (grub_crypto_cipher_handle_t cipher, @@ -283,7 +315,7 @@ int grub_password_get (char buf[], unsigned buf_size); /* For indistinguishibility. */ -#define GRUB_ACCESS_DENIED grub_error (GRUB_ERR_ACCESS_DENIED, "Access denied.") +#define GRUB_ACCESS_DENIED grub_error (GRUB_ERR_ACCESS_DENIED, N_("access denied")) extern void (*grub_crypto_autoload_hook) (const char *name); diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h index c6d1ce8de..0bb5d444e 100644 --- a/include/grub/cryptodisk.h +++ b/include/grub/cryptodisk.h @@ -59,6 +59,7 @@ typedef gcry_err_code_t struct grub_cryptodisk { struct grub_cryptodisk *next; + struct grub_cryptodisk **prev; char *source; grub_disk_addr_t offset; @@ -96,6 +97,7 @@ typedef struct grub_cryptodisk *grub_cryptodisk_t; struct grub_cryptodisk_dev { struct grub_cryptodisk_dev *next; + struct grub_cryptodisk_dev **prev; grub_cryptodisk_t (*scan) (grub_disk_t disk, const char *check_uuid, int boot_only); @@ -116,7 +118,7 @@ grub_cryptodisk_dev_register (grub_cryptodisk_dev_t cr) static inline void grub_cryptodisk_dev_unregister (grub_cryptodisk_dev_t cr) { - grub_list_remove (GRUB_AS_LIST_P (&grub_cryptodisk_list), GRUB_AS_LIST (cr)); + grub_list_remove (GRUB_AS_LIST (cr)); } #define FOR_CRYPTODISK_DEVS(var) FOR_LIST_ELEMENTS((var), (grub_cryptodisk_list)) diff --git a/include/grub/cs5536.h b/include/grub/cs5536.h index fcacb23e8..6b5b424c8 100644 --- a/include/grub/cs5536.h +++ b/include/grub/cs5536.h @@ -91,6 +91,7 @@ #define GRUB_CS5536_MSR_USB_CONTROLLER_BASE 0x4000000a #define GRUB_CS5536_MSR_USB_OPTION_CONTROLLER_BASE 0x4000000b #define GRUB_CS5536_MSR_USB_BASE_ADDR_MASK 0x00ffffff00ULL +#define GRUB_CS5536_MSR_USB_BASE_SMI_ENABLE 0x3f000000000000ULL #define GRUB_CS5536_MSR_USB_BASE_BUS_MASTER 0x0400000000ULL #define GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE 0x0200000000ULL #define GRUB_CS5536_MSR_USB_BASE_PME_ENABLED 0x0800000000ULL diff --git a/include/grub/datetime.h b/include/grub/datetime.h index a7154fa1a..4accd9cbd 100644 --- a/include/grub/datetime.h +++ b/include/grub/datetime.h @@ -85,14 +85,14 @@ grub_datetime2unixtime (const struct grub_datetime *datetime, grub_int32_t *nix) /* In the period of validity of unixtime all years divisible by 4 are bissextile*/ /* Convenience: let's have 3 consecutive non-bissextile years - at the beginning of the epoch. So count from 1971 instead of 1970 */ - ret = 2 * SECPERYEAR + SECPERDAY; + at the beginning of the epoch. So count from 1973 instead of 1970 */ + ret = 3 * SECPERYEAR + SECPERDAY; /* Transform C divisions and modulos to mathematical ones */ - y4 = (datetime->year - 1972) / 4; - if (datetime->year < 1972) + y4 = (datetime->year - 1973) / 4; + if (datetime->year < 1973) y4--; - ay = datetime->year - 1972 - 4 * y4; + ay = datetime->year - 1973 - 4 * y4; ret += y4 * SECPER4YEARS; ret += ay * SECPERYEAR; @@ -125,7 +125,7 @@ grub_datetime2unixtime (const struct grub_datetime *datetime, grub_int32_t *nix) return 1; } -#if defined (__powerpc__) || defined (__sparc__) +#if (defined (__powerpc__) || defined (__sparc__)) && !defined (GRUB_UTIL) grub_err_t grub_get_datetime_cmos (struct grub_datetime *datetime); grub_err_t diff --git a/include/grub/deflate.h b/include/grub/deflate.h index ae4a1f244..6ec4eaa99 100644 --- a/include/grub/deflate.h +++ b/include/grub/deflate.h @@ -23,8 +23,4 @@ grub_ssize_t grub_zlib_decompress (char *inbuf, grub_size_t insize, grub_off_t off, char *outbuf, grub_size_t outsize); -grub_err_t -grub_zlib_disk_read (grub_disk_t disk, grub_disk_addr_t zlibstart, - grub_off_t off, char *outbuf, grub_size_t outsize); - #endif diff --git a/include/grub/disk.h b/include/grub/disk.h index d9afd5b7b..096173d9b 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -32,18 +32,15 @@ enum grub_disk_dev_id GRUB_DISK_DEVICE_OFDISK_ID, GRUB_DISK_DEVICE_LOOPBACK_ID, GRUB_DISK_DEVICE_EFIDISK_ID, - GRUB_DISK_DEVICE_RAID_ID, - GRUB_DISK_DEVICE_LVM_ID, + GRUB_DISK_DEVICE_DISKFILTER_ID, GRUB_DISK_DEVICE_HOST_ID, GRUB_DISK_DEVICE_ATA_ID, GRUB_DISK_DEVICE_MEMDISK_ID, GRUB_DISK_DEVICE_NAND_ID, - GRUB_DISK_DEVICE_UUID_ID, - GRUB_DISK_DEVICE_PXE_ID, GRUB_DISK_DEVICE_SCSI_ID, - GRUB_DISK_DEVICE_FILE_ID, GRUB_DISK_DEVICE_CRYPTODISK_ID, GRUB_DISK_DEVICE_ARCDISK_ID, + GRUB_DISK_DEVICE_HOSTDISK_ID, }; struct grub_disk; @@ -96,6 +93,8 @@ struct grub_disk_dev }; typedef struct grub_disk_dev *grub_disk_dev_t; +extern grub_disk_dev_t EXPORT_VAR (grub_disk_dev_list); + struct grub_partition; /* Disk. */ @@ -158,7 +157,19 @@ void grub_disk_cache_invalidate_all (void); void EXPORT_FUNC(grub_disk_dev_register) (grub_disk_dev_t dev); void EXPORT_FUNC(grub_disk_dev_unregister) (grub_disk_dev_t dev); -int EXPORT_FUNC(grub_disk_dev_iterate) (int (*hook) (const char *name)); +static inline int +grub_disk_dev_iterate (int (*hook) (const char *name)) +{ + grub_disk_dev_t p; + grub_disk_pull_t pull; + + for (pull = 0; pull < GRUB_DISK_PULL_MAX; pull++) + for (p = grub_disk_dev_list; p; p = p->next) + if (p->iterate && (p->iterate) (hook, pull)) + return 1; + + return 0; +} grub_disk_t EXPORT_FUNC(grub_disk_open) (const char *name); void EXPORT_FUNC(grub_disk_close) (grub_disk_t disk); @@ -183,15 +194,17 @@ EXPORT_FUNC(grub_disk_cache_get_performance) (unsigned long *hits, unsigned long extern void (* EXPORT_VAR(grub_disk_firmware_fini)) (void); extern int EXPORT_VAR(grub_disk_firmware_is_tainted); -#if defined (GRUB_UTIL) || defined (GRUB_MACHINE_EMU) +#if defined (GRUB_UTIL) void grub_lvm_init (void); +void grub_ldm_init (void); void grub_mdraid09_init (void); void grub_mdraid1x_init (void); -void grub_raid_init (void); +void grub_diskfilter_init (void); void grub_lvm_fini (void); +void grub_ldm_fini (void); void grub_mdraid09_fini (void); void grub_mdraid1x_fini (void); -void grub_raid_fini (void); +void grub_diskfilter_fini (void); #endif #endif /* ! GRUB_DISK_HEADER */ diff --git a/include/grub/diskfilter.h b/include/grub/diskfilter.h new file mode 100644 index 000000000..2155a24e2 --- /dev/null +++ b/include/grub/diskfilter.h @@ -0,0 +1,196 @@ +/* diskfilter.h - On disk structures for RAID. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006,2007,2008,2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_DISKFILTER_H +#define GRUB_DISKFILTER_H 1 + +#include +#include + +enum + { + GRUB_RAID_LAYOUT_RIGHT_MASK = 1, + GRUB_RAID_LAYOUT_SYMMETRIC_MASK = 2, + GRUB_RAID_LAYOUT_MUL_FROM_POS = 4, + + GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC = 0, + GRUB_RAID_LAYOUT_RIGHT_ASYMMETRIC = GRUB_RAID_LAYOUT_RIGHT_MASK, + GRUB_RAID_LAYOUT_LEFT_SYMMETRIC = GRUB_RAID_LAYOUT_SYMMETRIC_MASK, + GRUB_RAID_LAYOUT_RIGHT_SYMMETRIC = (GRUB_RAID_LAYOUT_RIGHT_MASK + | GRUB_RAID_LAYOUT_SYMMETRIC_MASK) + }; + + +struct grub_diskfilter_vg { + char *uuid; + grub_size_t uuid_len; + /* Optional. */ + char *name; + int extent_size; + struct grub_diskfilter_pv *pvs; + struct grub_diskfilter_lv *lvs; + struct grub_diskfilter_vg *next; + +#ifdef GRUB_UTIL + struct grub_diskfilter *driver; +#endif +}; + +struct grub_diskfilter_pv_id { + union + { + char *uuid; + int id; + }; + grub_size_t uuidlen; +}; + +struct grub_diskfilter_pv { + struct grub_diskfilter_pv_id id; + /* Optional. */ + char *name; + grub_disk_t disk; + grub_disk_addr_t part_start; + grub_disk_addr_t part_size; + grub_disk_addr_t start_sector; /* Sector number where the data area starts. */ + struct grub_diskfilter_pv *next; + /* Optional. */ + grub_uint8_t *internal_id; +#ifdef GRUB_UTIL + char **partmaps; +#endif +}; + +struct grub_diskfilter_lv { + /* Name used for disk. */ + char *fullname; + /* Optional. */ + char *name; + int number; + unsigned int segment_count; + grub_size_t segment_alloc; + grub_uint64_t size; + int became_readable_at; + + int visible; + + /* Pointer to segment_count segments. */ + struct grub_diskfilter_segment *segments; + struct grub_diskfilter_vg *vg; + struct grub_diskfilter_lv *next; + + /* Optional. */ + char *internal_id; +}; + +struct grub_diskfilter_segment { + unsigned int start_extent; + unsigned int extent_count; + enum + { + GRUB_DISKFILTER_STRIPED = 0, + GRUB_DISKFILTER_MIRROR = 1, + GRUB_DISKFILTER_RAID4 = 4, + GRUB_DISKFILTER_RAID5 = 5, + GRUB_DISKFILTER_RAID6 = 6, + GRUB_DISKFILTER_RAID10 = 10, + } type; + int layout; + /* valid only for raid10. */ + grub_uint64_t raid_member_size; + + unsigned int node_count; + unsigned int node_alloc; + struct grub_diskfilter_node *nodes; + + unsigned int stripe_size; +}; + +struct grub_diskfilter_node { + grub_disk_addr_t start; + /* Optional. */ + char *name; + struct grub_diskfilter_pv *pv; + struct grub_diskfilter_lv *lv; +}; + +struct grub_diskfilter_vg * +grub_diskfilter_get_vg_by_uuid (grub_size_t uuidlen, char *uuid); + +struct grub_diskfilter +{ + struct grub_diskfilter *next; + struct grub_diskfilter **prev; + + const char *name; + + struct grub_diskfilter_vg * (*detect) (grub_disk_t disk, + struct grub_diskfilter_pv_id *id, + grub_disk_addr_t *start_sector); +}; +typedef struct grub_diskfilter *grub_diskfilter_t; + +extern grub_diskfilter_t grub_diskfilter_list; +static inline void +grub_diskfilter_register (grub_diskfilter_t diskfilter) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_diskfilter_list), + GRUB_AS_LIST (diskfilter)); +} +static inline void +grub_diskfilter_unregister (grub_diskfilter_t diskfilter) +{ + grub_list_remove (GRUB_AS_LIST (diskfilter)); +} + +struct grub_diskfilter_vg * +grub_diskfilter_make_raid (grub_size_t uuidlen, char *uuid, int nmemb, + char *name, grub_uint64_t disk_size, + grub_uint64_t stripe_size, + int layout, int level); + +typedef grub_err_t (*grub_raid5_recover_func_t) (struct grub_diskfilter_segment *array, + int disknr, char *buf, + grub_disk_addr_t sector, + int size); + +typedef grub_err_t (*grub_raid6_recover_func_t) (struct grub_diskfilter_segment *array, + int disknr, int p, char *buf, + grub_disk_addr_t sector, + int size); + +extern grub_raid5_recover_func_t grub_raid5_recover_func; +extern grub_raid6_recover_func_t grub_raid6_recover_func; + +grub_err_t grub_diskfilter_vg_register (struct grub_diskfilter_vg *vg); + +grub_err_t +grub_diskfilter_read_node (const struct grub_diskfilter_node *node, + grub_disk_addr_t sector, + grub_size_t size, char *buf); + +#ifdef GRUB_UTIL +struct grub_diskfilter_pv * +grub_diskfilter_get_pv_from_disk (grub_disk_t disk, + struct grub_diskfilter_vg **vg); +void +grub_diskfilter_print_partmap (grub_disk_t disk); +#endif + +#endif /* ! GRUB_RAID_H */ diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h index b20baa015..b3ec6636b 100644 --- a/include/grub/efi/api.h +++ b/include/grub/efi/api.h @@ -371,7 +371,7 @@ struct grub_efi_memory_descriptor grub_efi_virtual_address_t virtual_start; grub_efi_uint64_t num_pages; grub_efi_uint64_t attribute; -}; +} __attribute__ ((packed)); typedef struct grub_efi_memory_descriptor grub_efi_memory_descriptor_t; /* Device Path definitions. */ @@ -416,7 +416,7 @@ struct grub_efi_pci_device_path grub_efi_device_path_t header; grub_efi_uint8_t function; grub_efi_uint8_t device; -}; +} __attribute__ ((packed)); typedef struct grub_efi_pci_device_path grub_efi_pci_device_path_t; #define GRUB_EFI_PCCARD_DEVICE_PATH_SUBTYPE 2 @@ -425,7 +425,7 @@ struct grub_efi_pccard_device_path { grub_efi_device_path_t header; grub_efi_uint8_t function; -}; +} __attribute__ ((packed)); typedef struct grub_efi_pccard_device_path grub_efi_pccard_device_path_t; #define GRUB_EFI_MEMORY_MAPPED_DEVICE_PATH_SUBTYPE 3 @@ -433,10 +433,10 @@ typedef struct grub_efi_pccard_device_path grub_efi_pccard_device_path_t; struct grub_efi_memory_mapped_device_path { grub_efi_device_path_t header; - grub_efi_memory_type_t memory_type; + grub_efi_uint32_t memory_type; grub_efi_physical_address_t start_address; grub_efi_physical_address_t end_address; -}; +} __attribute__ ((packed)); typedef struct grub_efi_memory_mapped_device_path grub_efi_memory_mapped_device_path_t; #define GRUB_EFI_VENDOR_DEVICE_PATH_SUBTYPE 4 @@ -446,7 +446,7 @@ struct grub_efi_vendor_device_path grub_efi_device_path_t header; grub_efi_guid_t vendor_guid; grub_efi_uint8_t vendor_defined_data[0]; -}; +} __attribute__ ((packed)); typedef struct grub_efi_vendor_device_path grub_efi_vendor_device_path_t; #define GRUB_EFI_CONTROLLER_DEVICE_PATH_SUBTYPE 5 @@ -455,7 +455,7 @@ struct grub_efi_controller_device_path { grub_efi_device_path_t header; grub_efi_uint32_t controller_number; -}; +} __attribute__ ((packed)); typedef struct grub_efi_controller_device_path grub_efi_controller_device_path_t; /* ACPI Device Path. */ @@ -468,7 +468,7 @@ struct grub_efi_acpi_device_path grub_efi_device_path_t header; grub_efi_uint32_t hid; grub_efi_uint32_t uid; -}; +} __attribute__ ((packed)); typedef struct grub_efi_acpi_device_path grub_efi_acpi_device_path_t; #define GRUB_EFI_EXPANDED_ACPI_DEVICE_PATH_SUBTYPE 2 @@ -479,8 +479,8 @@ struct grub_efi_expanded_acpi_device_path grub_efi_uint32_t hid; grub_efi_uint32_t uid; grub_efi_uint32_t cid; - char hidstr[1]; -}; + char hidstr[0]; +} __attribute__ ((packed)); typedef struct grub_efi_expanded_acpi_device_path grub_efi_expanded_acpi_device_path_t; #define GRUB_EFI_EXPANDED_ACPI_HIDSTR(dp) \ @@ -503,7 +503,7 @@ struct grub_efi_atapi_device_path grub_efi_uint8_t primary_secondary; grub_efi_uint8_t slave_master; grub_efi_uint16_t lun; -}; +} __attribute__ ((packed)); typedef struct grub_efi_atapi_device_path grub_efi_atapi_device_path_t; #define GRUB_EFI_SCSI_DEVICE_PATH_SUBTYPE 2 @@ -513,7 +513,7 @@ struct grub_efi_scsi_device_path grub_efi_device_path_t header; grub_efi_uint16_t pun; grub_efi_uint16_t lun; -}; +} __attribute__ ((packed)); typedef struct grub_efi_scsi_device_path grub_efi_scsi_device_path_t; #define GRUB_EFI_FIBRE_CHANNEL_DEVICE_PATH_SUBTYPE 3 @@ -524,7 +524,7 @@ struct grub_efi_fibre_channel_device_path grub_efi_uint32_t reserved; grub_efi_uint64_t wwn; grub_efi_uint64_t lun; -}; +} __attribute__ ((packed)); typedef struct grub_efi_fibre_channel_device_path grub_efi_fibre_channel_device_path_t; #define GRUB_EFI_1394_DEVICE_PATH_SUBTYPE 4 @@ -534,7 +534,7 @@ struct grub_efi_1394_device_path grub_efi_device_path_t header; grub_efi_uint32_t reserved; grub_efi_uint64_t guid; -}; +} __attribute__ ((packed)); typedef struct grub_efi_1394_device_path grub_efi_1394_device_path_t; #define GRUB_EFI_USB_DEVICE_PATH_SUBTYPE 5 @@ -544,7 +544,7 @@ struct grub_efi_usb_device_path grub_efi_device_path_t header; grub_efi_uint8_t parent_port_number; grub_efi_uint8_t interface; -}; +} __attribute__ ((packed)); typedef struct grub_efi_usb_device_path grub_efi_usb_device_path_t; #define GRUB_EFI_USB_CLASS_DEVICE_PATH_SUBTYPE 15 @@ -557,7 +557,7 @@ struct grub_efi_usb_class_device_path grub_efi_uint8_t device_class; grub_efi_uint8_t device_subclass; grub_efi_uint8_t device_protocol; -}; +} __attribute__ ((packed)); typedef struct grub_efi_usb_class_device_path grub_efi_usb_class_device_path_t; #define GRUB_EFI_I2O_DEVICE_PATH_SUBTYPE 6 @@ -566,7 +566,7 @@ struct grub_efi_i2o_device_path { grub_efi_device_path_t header; grub_efi_uint32_t tid; -}; +} __attribute__ ((packed)); typedef struct grub_efi_i2o_device_path grub_efi_i2o_device_path_t; #define GRUB_EFI_MAC_ADDRESS_DEVICE_PATH_SUBTYPE 11 @@ -576,7 +576,7 @@ struct grub_efi_mac_address_device_path grub_efi_device_path_t header; grub_efi_mac_address_t mac_address; grub_efi_uint8_t if_type; -}; +} __attribute__ ((packed)); typedef struct grub_efi_mac_address_device_path grub_efi_mac_address_device_path_t; #define GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE 12 @@ -590,7 +590,7 @@ struct grub_efi_ipv4_device_path grub_efi_uint16_t remote_port; grub_efi_uint16_t protocol; grub_efi_uint8_t static_ip_address; -}; +} __attribute__ ((packed)); typedef struct grub_efi_ipv4_device_path grub_efi_ipv4_device_path_t; #define GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE 13 @@ -604,7 +604,7 @@ struct grub_efi_ipv6_device_path grub_efi_uint16_t remote_port; grub_efi_uint16_t protocol; grub_efi_uint8_t static_ip_address; -}; +} __attribute__ ((packed)); typedef struct grub_efi_ipv6_device_path grub_efi_ipv6_device_path_t; #define GRUB_EFI_INFINIBAND_DEVICE_PATH_SUBTYPE 9 @@ -617,7 +617,7 @@ struct grub_efi_infiniband_device_path grub_efi_uint64_t remote_id; grub_efi_uint64_t target_port_id; grub_efi_uint64_t device_id; -}; +} __attribute__ ((packed)); typedef struct grub_efi_infiniband_device_path grub_efi_infiniband_device_path_t; #define GRUB_EFI_UART_DEVICE_PATH_SUBTYPE 14 @@ -630,7 +630,7 @@ struct grub_efi_uart_device_path grub_efi_uint8_t data_bits; grub_efi_uint8_t parity; grub_efi_uint8_t stop_bits; -}; +} __attribute__ ((packed)); typedef struct grub_efi_uart_device_path grub_efi_uart_device_path_t; #define GRUB_EFI_VENDOR_MESSAGING_DEVICE_PATH_SUBTYPE 10 @@ -640,7 +640,7 @@ struct grub_efi_vendor_messaging_device_path grub_efi_device_path_t header; grub_efi_guid_t vendor_guid; grub_efi_uint8_t vendor_defined_data[0]; -}; +} __attribute__ ((packed)); typedef struct grub_efi_vendor_messaging_device_path grub_efi_vendor_messaging_device_path_t; /* Media Device Path. */ @@ -657,7 +657,7 @@ struct grub_efi_hard_drive_device_path grub_efi_uint8_t partition_signature[8]; grub_efi_uint8_t mbr_type; grub_efi_uint8_t signature_type; -}; +} __attribute__ ((packed)); typedef struct grub_efi_hard_drive_device_path grub_efi_hard_drive_device_path_t; #define GRUB_EFI_CDROM_DEVICE_PATH_SUBTYPE 2 @@ -668,7 +668,7 @@ struct grub_efi_cdrom_device_path grub_efi_uint32_t boot_entry; grub_efi_lba_t partition_start; grub_efi_lba_t partition_size; -}; +} __attribute__ ((packed)); typedef struct grub_efi_cdrom_device_path grub_efi_cdrom_device_path_t; #define GRUB_EFI_VENDOR_MEDIA_DEVICE_PATH_SUBTYPE 3 @@ -678,7 +678,7 @@ struct grub_efi_vendor_media_device_path grub_efi_device_path_t header; grub_efi_guid_t vendor_guid; grub_efi_uint8_t vendor_defined_data[0]; -}; +} __attribute__ ((packed)); typedef struct grub_efi_vendor_media_device_path grub_efi_vendor_media_device_path_t; #define GRUB_EFI_FILE_PATH_DEVICE_PATH_SUBTYPE 4 @@ -687,7 +687,7 @@ struct grub_efi_file_path_device_path { grub_efi_device_path_t header; grub_efi_char16_t path_name[0]; -}; +} __attribute__ ((packed)); typedef struct grub_efi_file_path_device_path grub_efi_file_path_device_path_t; #define GRUB_EFI_PROTOCOL_DEVICE_PATH_SUBTYPE 5 @@ -696,7 +696,7 @@ struct grub_efi_protocol_device_path { grub_efi_device_path_t header; grub_efi_guid_t guid; -}; +} __attribute__ ((packed)); typedef struct grub_efi_protocol_device_path grub_efi_protocol_device_path_t; #define GRUB_EFI_PIWG_DEVICE_PATH_SUBTYPE 6 @@ -705,7 +705,7 @@ struct grub_efi_piwg_device_path { grub_efi_device_path_t header; grub_efi_guid_t guid __attribute__ ((packed)); -}; +} __attribute__ ((packed)); typedef struct grub_efi_piwg_device_path grub_efi_piwg_device_path_t; @@ -720,7 +720,7 @@ struct grub_efi_bios_device_path grub_efi_uint16_t device_type; grub_efi_uint16_t status_flags; char description[0]; -}; +} __attribute__ ((packed)); typedef struct grub_efi_bios_device_path grub_efi_bios_device_path_t; struct grub_efi_open_protocol_information_entry @@ -1301,7 +1301,9 @@ struct grub_efi_simple_network void (*statistics) (void); void (*mcastiptomac) (void); void (*nvdata) (void); - void (*getstatus) (void); + grub_efi_status_t (*get_status) (struct grub_efi_simple_network *this, + grub_uint32_t *int_status, + void **txbuf); grub_efi_status_t (*transmit) (struct grub_efi_simple_network *this, grub_efi_uintn_t header_size, grub_efi_uintn_t buffer_size, diff --git a/include/grub/efi/memory.h b/include/grub/efi/memory.h index 133f9504c..20526b146 100644 --- a/include/grub/efi/memory.h +++ b/include/grub/efi/memory.h @@ -24,15 +24,8 @@ #define GRUB_MMAP_REGISTER_BY_FIRMWARE 1 -grub_err_t grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, - grub_uint64_t, - grub_uint32_t)); grub_err_t grub_machine_mmap_register (grub_uint64_t start, grub_uint64_t size, int type, int handle); grub_err_t grub_machine_mmap_unregister (int handle); -grub_uint64_t grub_mmap_get_post64 (void); -grub_uint64_t grub_mmap_get_upper (void); -grub_uint64_t grub_mmap_get_lower (void); - #endif /* ! GRUB_MEMORY_MACHINE_HEADER */ diff --git a/include/grub/efiemu/efiemu.h b/include/grub/efiemu/efiemu.h index 9cedc3226..4ce3fc92d 100644 --- a/include/grub/efiemu/efiemu.h +++ b/include/grub/efiemu/efiemu.h @@ -114,9 +114,9 @@ extern grub_efi_system_table64_t *grub_efiemu_system_table64; : (grub_efiemu_system_table32->x \ = (y))) #define GRUB_EFIEMU_SYSTEM_TABLE_PTR(x) ((grub_efiemu_sizeof_uintn_t () == 8)\ - ? UINT_TO_PTR \ + ? (void *) (grub_addr_t) \ (grub_efiemu_system_table64->x) \ - : UINT_TO_PTR \ + : (void *) (grub_addr_t) \ (grub_efiemu_system_table32->x)) #define GRUB_EFIEMU_SYSTEM_TABLE_VAR(x) ((grub_efiemu_sizeof_uintn_t () == 8) \ ? (void *) \ @@ -152,9 +152,12 @@ struct grub_efiemu_elf_sym int grub_efiemu_check_header32 (void *ehdr, grub_size_t size); int grub_efiemu_check_header64 (void *ehdr, grub_size_t size); -grub_err_t grub_efiemu_loadcore_init32 (void *core, grub_size_t core_size, +grub_err_t grub_efiemu_loadcore_init32 (void *core, + const char *filename, + grub_size_t core_size, grub_efiemu_segment_t *segments); -grub_err_t grub_efiemu_loadcore_init64 (void *core, grub_size_t core_size, +grub_err_t grub_efiemu_loadcore_init64 (void *core, const char *filename, + grub_size_t core_size, grub_efiemu_segment_t *segments); grub_err_t grub_efiemu_loadcore_load32 (void *core, grub_size_t core_size, @@ -165,7 +168,8 @@ grub_err_t grub_efiemu_loadcore_load64 (void *core, grub_err_t grub_efiemu_loadcore_unload32 (void); grub_err_t grub_efiemu_loadcore_unload64 (void); grub_err_t grub_efiemu_loadcore_unload(void); -grub_err_t grub_efiemu_loadcore_init (grub_file_t file); +grub_err_t grub_efiemu_loadcore_init (grub_file_t file, + const char *filename); grub_err_t grub_efiemu_loadcore_load (void); /* Configuration tables manipulation. Definitions and functions */ @@ -200,15 +204,9 @@ grub_efiemu_register_configuration_table (grub_efi_guid_t guid, int grub_efiemu_request_memalign (grub_size_t align, grub_size_t size, grub_efi_memory_type_t type); void *grub_efiemu_mm_obtain_request (int handle); -int grub_efiemu_get_memory_map (grub_efi_uintn_t *memory_map_size, - grub_efi_memory_descriptor_t *memory_map, - grub_efi_uintn_t *map_key, - grub_efi_uintn_t *descriptor_size, - grub_efi_uint32_t *descriptor_version); grub_err_t grub_efiemu_mm_unload (void); grub_err_t grub_efiemu_mm_do_alloc (void); grub_err_t grub_efiemu_mm_init (void); -void *grub_efiemu_mm_obtain_request (int handle); void grub_efiemu_mm_return_request (int handle); grub_efi_memory_type_t grub_efiemu_mm_get_type (int handle); @@ -271,8 +269,7 @@ grub_err_t grub_efiemu_write_value (void * addr, grub_uint32_t value, int minus_handle, int ptv_needed, int size); grub_err_t grub_efiemu_write_sym_markers (void); grub_err_t grub_efiemu_pnvram (void); -grub_err_t grub_efiemu_prepare (void); -char *grub_efiemu_get_default_core_name (void); +const char *grub_efiemu_get_default_core_name (void); void grub_efiemu_pnvram_cmd_unregister (void); grub_err_t grub_efiemu_autocore (void); grub_err_t grub_efiemu_crc32 (void); diff --git a/include/grub/elfload.h b/include/grub/elfload.h index 579656f23..aae95f564 100644 --- a/include/grub/elfload.h +++ b/include/grub/elfload.h @@ -42,24 +42,32 @@ typedef grub_err_t (*grub_elf64_load_hook_t) (Elf64_Phdr *phdr, grub_addr_t *addr, int *load); grub_elf_t grub_elf_open (const char *); -grub_elf_t grub_elf_file (grub_file_t); +grub_elf_t grub_elf_file (grub_file_t file, const char *filename); grub_err_t grub_elf_close (grub_elf_t); int grub_elf_is_elf32 (grub_elf_t); -grub_size_t grub_elf32_size (grub_elf_t, Elf32_Addr *, grub_uint32_t *); -grub_err_t grub_elf32_load (grub_elf_t, grub_elf32_load_hook_t, grub_addr_t *, +grub_size_t grub_elf32_size (grub_elf_t, + const char *filename, + Elf32_Addr *, grub_uint32_t *); +grub_err_t grub_elf32_load (grub_elf_t, const char *filename, + grub_elf32_load_hook_t, grub_addr_t *, grub_size_t *); int grub_elf_is_elf64 (grub_elf_t); -grub_size_t grub_elf64_size (grub_elf_t, Elf64_Addr *, grub_uint64_t *); -grub_err_t grub_elf64_load (grub_elf_t, grub_elf64_load_hook_t, grub_addr_t *, +grub_size_t grub_elf64_size (grub_elf_t, + const char *filename, + Elf64_Addr *, grub_uint64_t *); +grub_err_t grub_elf64_load (grub_elf_t, const char *filename, + grub_elf64_load_hook_t, grub_addr_t *, grub_size_t *); 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); 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); diff --git a/include/grub/emu/getroot.h b/include/grub/emu/getroot.h index 6921e567c..83455ddda 100644 --- a/include/grub/emu/getroot.h +++ b/include/grub/emu/getroot.h @@ -30,7 +30,7 @@ enum grub_dev_abstraction_types { }; char *grub_find_device (const char *dir, dev_t dev); -char *grub_guess_root_device (const char *dir); +char **grub_guess_root_devices (const char *dir); int grub_util_get_dev_abstraction (const char *os_dev); char *grub_util_get_grub_dev (const char *os_dev); char *grub_make_system_path_relative_to_its_root (const char *path); diff --git a/include/grub/emu/hostdisk.h b/include/grub/emu/hostdisk.h index 719faa29b..b3db85902 100644 --- a/include/grub/emu/hostdisk.h +++ b/include/grub/emu/hostdisk.h @@ -21,6 +21,7 @@ #define GRUB_BIOSDISK_MACHINE_UTIL_HEADER 1 #include +#include #include void grub_util_biosdisk_init (const char *dev_map); @@ -29,17 +30,38 @@ char *grub_util_biosdisk_get_grub_dev (const char *os_dev); const char *grub_util_biosdisk_get_osdev (grub_disk_t disk); int grub_util_biosdisk_is_present (const char *name); int grub_util_biosdisk_is_floppy (grub_disk_t disk); +const char * +grub_util_biosdisk_get_compatibility_hint (grub_disk_t disk); grub_err_t grub_util_biosdisk_flush (struct grub_disk *disk); void grub_util_pull_device (const char *osname); grub_err_t grub_util_fd_seek (int fd, const char *name, grub_uint64_t sector); ssize_t grub_util_fd_read (int fd, char *buf, size_t len); +ssize_t grub_util_fd_write (int fd, const char *buf, size_t len); grub_err_t grub_cryptodisk_cheat_mount (const char *sourcedev, const char *cheat); void grub_util_cryptodisk_print_uuid (grub_disk_t disk); +char * +grub_util_get_ldm (grub_disk_t disk, grub_disk_addr_t start); +int +grub_util_is_ldm (grub_disk_t disk); +#ifdef GRUB_UTIL +grub_err_t +grub_util_ldm_embed (struct grub_disk *disk, unsigned int *nsectors, + grub_embed_type_t embed_type, + grub_disk_addr_t **sectors); +#endif +grub_disk_addr_t +grub_hostdisk_find_partition_start (const char *dev); +const char * +grub_hostdisk_os_dev_to_grub_drive (const char *os_dev, int add); + #if !defined(__MINGW32__) grub_uint64_t -grub_util_get_fd_sectors (int fd, unsigned *log_secsize); +grub_util_get_fd_sectors (int fd, const char *name, unsigned *log_secsize); #endif +char * +grub_util_get_os_disk (const char *os_dev); + #endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */ diff --git a/include/grub/emu/misc.h b/include/grub/emu/misc.h index b4b8f7d28..6423eb963 100644 --- a/include/grub/emu/misc.h +++ b/include/grub/emu/misc.h @@ -60,11 +60,11 @@ grub_util_device_is_mapped (const char *dev); void * EXPORT_FUNC(xmalloc) (grub_size_t size) __attribute__ ((warn_unused_result)); void * EXPORT_FUNC(xrealloc) (void *ptr, grub_size_t size) __attribute__ ((warn_unused_result)); char * EXPORT_FUNC(xstrdup) (const char *str) __attribute__ ((warn_unused_result)); -char * EXPORT_FUNC(xasprintf) (const char *fmt, ...) __attribute__ ((warn_unused_result)); +char * EXPORT_FUNC(xasprintf) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))) __attribute__ ((warn_unused_result)); -void EXPORT_FUNC(grub_util_warn) (const char *fmt, ...); -void EXPORT_FUNC(grub_util_info) (const char *fmt, ...); -void EXPORT_FUNC(grub_util_error) (const char *fmt, ...) __attribute__ ((noreturn)); +void EXPORT_FUNC(grub_util_warn) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); +void EXPORT_FUNC(grub_util_info) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); +void EXPORT_FUNC(grub_util_error) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2), noreturn)); #ifndef HAVE_VASPRINTF int EXPORT_FUNC(vasprintf) (char **buf, const char *fmt, va_list ap); @@ -80,9 +80,4 @@ extern char * canonicalize_file_name (const char *path); int grub_device_mapper_supported (void); #endif -char *grub_find_root_device_from_mountinfo (const char *dir, char **relroot); - -void EXPORT_FUNC(grub_reboot) (void); - - #endif /* GRUB_EMU_MISC_H */ diff --git a/include/grub/err.h b/include/grub/err.h index 40f39dd5d..cf96cd563 100644 --- a/include/grub/err.h +++ b/include/grub/err.h @@ -22,6 +22,8 @@ #include +#define GRUB_MAX_ERRMSG 256 + typedef enum { GRUB_ERR_NONE = 0, @@ -59,13 +61,25 @@ typedef enum GRUB_ERR_NET_BAD_ADDRESS, GRUB_ERR_NET_ROUTE_LOOP, GRUB_ERR_NET_NO_ROUTE, + GRUB_ERR_NET_NO_ANSWER, GRUB_ERR_WAIT, - GRUB_ERR_BUG + GRUB_ERR_BUG, + GRUB_ERR_NET_PORT_CLOSED, + GRUB_ERR_NET_INVALID_RESPONSE, + GRUB_ERR_NET_UNKNOWN_ERROR, + GRUB_ERR_NET_PACKET_TOO_BIG, + GRUB_ERR_NET_NO_DOMAIN } grub_err_t; +struct grub_error_saved +{ + grub_err_t grub_errno; + char errmsg[GRUB_MAX_ERRMSG]; +}; + extern grub_err_t EXPORT_VAR(grub_errno); -extern char EXPORT_VAR(grub_errmsg)[]; +extern char EXPORT_VAR(grub_errmsg)[GRUB_MAX_ERRMSG]; grub_err_t EXPORT_FUNC(grub_error) (grub_err_t n, const char *fmt, ...); void EXPORT_FUNC(grub_fatal) (const char *fmt, ...) __attribute__ ((noreturn)); diff --git a/include/grub/fbutil.h b/include/grub/fbutil.h index 065ccf9e3..f68db43b1 100644 --- a/include/grub/fbutil.h +++ b/include/grub/fbutil.h @@ -31,8 +31,17 @@ struct grub_video_fbblit_info grub_uint8_t *data; }; -grub_uint8_t *grub_video_fb_get_video_ptr (struct grub_video_fbblit_info *source, - unsigned int x, unsigned int y); +void *grub_video_fb_get_video_ptr (struct grub_video_fbblit_info *source, + unsigned int x, unsigned int y); + +/* Advance pointer by VAL bytes. If there is no unaligned access available, + VAL has to be divisible by size of pointed type. + */ +#ifdef GRUB_HAVE_UNALIGNED_ACCESS +#define GRUB_VIDEO_FB_ADVANCE_POINTER(ptr, val) ((ptr) = (typeof (ptr)) ((char *) ptr + val)) +#else +#define GRUB_VIDEO_FB_ADVANCE_POINTER(ptr, val) ((ptr) += (val) / sizeof (*(ptr))) +#endif grub_video_color_t get_pixel (struct grub_video_fbblit_info *source, unsigned int x, unsigned int y); diff --git a/include/grub/fs.h b/include/grub/fs.h index dd274e151..10374ed90 100644 --- a/include/grub/fs.h +++ b/include/grub/fs.h @@ -46,6 +46,7 @@ struct grub_fs { /* The next filesystem. */ struct grub_fs *next; + struct grub_fs **prev; /* My name. */ const char *name; @@ -111,7 +112,7 @@ grub_fs_register (grub_fs_t fs) static inline void grub_fs_unregister (grub_fs_t fs) { - grub_list_remove (GRUB_AS_LIST_P (&grub_fs_list), GRUB_AS_LIST (fs)); + grub_list_remove (GRUB_AS_LIST (fs)); } #define FOR_FILESYSTEMS(var) FOR_LIST_ELEMENTS((var), (grub_fs_list)) diff --git a/include/grub/gpt_partition.h b/include/grub/gpt_partition.h index 5f8ddead7..83e3b3192 100644 --- a/include/grub/gpt_partition.h +++ b/include/grub/gpt_partition.h @@ -20,6 +20,7 @@ #define GRUB_GPT_PARTITION_HEADER 1 #include +#include struct grub_gpt_part_type { @@ -36,10 +37,19 @@ typedef struct grub_gpt_part_type grub_gpt_part_type_t; } #define GRUB_GPT_PARTITION_TYPE_BIOS_BOOT \ - { grub_cpu_to_le32_compile_time (0x21686148), grub_cpu_to_le16_compile_time (0x6449), grub_cpu_to_le16_compile_time (0x6e6f), \ + { grub_cpu_to_le32_compile_time (0x21686148), \ + grub_cpu_to_le16_compile_time (0x6449), \ + grub_cpu_to_le16_compile_time (0x6e6f), \ { 0x74, 0x4e, 0x65, 0x65, 0x64, 0x45, 0x46, 0x49 } \ } +#define GRUB_GPT_PARTITION_TYPE_LDM \ + { grub_cpu_to_le32_compile_time (0x5808C8AAU),\ + grub_cpu_to_le16_compile_time (0x7E8F), \ + grub_cpu_to_le16_compile_time (0x42E0), \ + { 0x85, 0xD2, 0xE1, 0xE9, 0x04, 0x34, 0xCF, 0xB3 } \ + } + struct grub_gpt_header { grub_uint8_t magic[8]; @@ -68,4 +78,10 @@ struct grub_gpt_partentry char name[72]; } __attribute__ ((packed)); +grub_err_t +grub_gpt_partition_map_iterate (grub_disk_t disk, + int (*hook) (grub_disk_t disk, + const grub_partition_t partition)); + + #endif /* ! GRUB_GPT_PARTITION_HEADER */ diff --git a/include/grub/i386/bsd.h b/include/grub/i386/bsd.h index 53008cdaf..665248d03 100644 --- a/include/grub/i386/bsd.h +++ b/include/grub/i386/bsd.h @@ -81,21 +81,25 @@ grub_err_t grub_freebsd_load_elfmodule_obj64 (struct grub_relocator *relocator, grub_addr_t *kern_end); grub_err_t grub_freebsd_load_elf_meta32 (struct grub_relocator *relocator, grub_file_t file, + const char *filename, grub_addr_t *kern_end); grub_err_t grub_freebsd_load_elf_meta64 (struct grub_relocator *relocator, grub_file_t file, + const char *filename, grub_addr_t *kern_end); grub_err_t grub_netbsd_load_elf_meta32 (struct grub_relocator *relocator, grub_file_t file, + const char *filename, grub_addr_t *kern_end); grub_err_t grub_netbsd_load_elf_meta64 (struct grub_relocator *relocator, grub_file_t file, + const char *filename, grub_addr_t *kern_end); grub_err_t grub_bsd_add_meta (grub_uint32_t type, - void *data, grub_uint32_t len); -grub_err_t grub_freebsd_add_meta_module (char *filename, char *type, + const void *data, grub_uint32_t len); +grub_err_t grub_freebsd_add_meta_module (const char *filename, const char *type, int argc, char **argv, grub_addr_t addr, grub_uint32_t size); @@ -107,10 +111,12 @@ struct grub_openbsd_ramdisk_descriptor }; grub_err_t grub_openbsd_find_ramdisk32 (grub_file_t file, + const char *filename, grub_addr_t kern_start, void *kern_chunk_src, struct grub_openbsd_ramdisk_descriptor *desc); grub_err_t grub_openbsd_find_ramdisk64 (grub_file_t file, + const char *filename, grub_addr_t kern_start, void *kern_chunk_src, struct grub_openbsd_ramdisk_descriptor *desc); diff --git a/include/grub/i386/pc/pxe.h b/include/grub/i386/pc/pxe.h index 376a18962..96f65acf9 100644 --- a/include/grub/i386/pc/pxe.h +++ b/include/grub/i386/pc/pxe.h @@ -157,9 +157,6 @@ #define GRUB_PXE_BOOTP_SIZE (312 + 236) /* DHCP standard vendor field size. */ #endif -#define GRUB_PXE_MIN_BLKSIZE 512 -#define GRUB_PXE_MAX_BLKSIZE 1432 - #define GRUB_PXE_TFTP_PORT 69 #define GRUB_PXE_ERR_LEN 0xFFFFFFFF @@ -287,6 +284,9 @@ int EXPORT_FUNC(grub_pxe_call) (int func, void * data, grub_uint32_t pxe_rm_entr extern struct grub_pxe_bangpxe *grub_pxe_pxenv; +void * +grub_pxe_get_cached (grub_uint16_t type); + #endif #endif /* GRUB_CPU_PXE_H */ diff --git a/include/grub/i386/pc/vbe.h b/include/grub/i386/pc/vbe.h index 09ad7eb64..570bb0fa6 100644 --- a/include/grub/i386/pc/vbe.h +++ b/include/grub/i386/pc/vbe.h @@ -221,8 +221,6 @@ grub_vbe_status_t grub_vbe_bios_getset_dac_palette_width (int set, int *width); #define grub_vbe_bios_set_dac_palette_width(width) grub_vbe_bios_getset_dac_palette_width(1, (width)) grub_err_t grub_vbe_probe (struct grub_vbe_info_block *info_block); -grub_err_t grub_vbe_set_video_mode (grub_uint32_t mode, - struct grub_vbe_mode_info_block *mode_info); grub_err_t grub_vbe_get_video_mode (grub_uint32_t *mode); grub_err_t grub_vbe_get_video_mode_info (grub_uint32_t mode, struct grub_vbe_mode_info_block *mode_info); diff --git a/include/grub/i386/qemu/memory.h b/include/grub/i386/qemu/memory.h index 2003e4934..f152cd782 100644 --- a/include/grub/i386/qemu/memory.h +++ b/include/grub/i386/qemu/memory.h @@ -33,10 +33,4 @@ #define GRUB_MEMORY_MACHINE_UPPER_START 0x100000 /* 1 MiB */ #define GRUB_MEMORY_MACHINE_LOWER_SIZE GRUB_MEMORY_MACHINE_UPPER_START -#ifndef ASM_FILE - -void grub_machine_mmap_init (void); - -#endif - #endif /* ! _GRUB_MEMORY_MACHINE_HEADER */ diff --git a/include/grub/i386/relocator_private.h b/include/grub/i386/relocator_private.h new file mode 100644 index 000000000..b7c96a664 --- /dev/null +++ b/include/grub/i386/relocator_private.h @@ -0,0 +1 @@ +#define GRUB_RELOCATOR16_STACK_SIZE 4096 diff --git a/include/grub/i386/types.h b/include/grub/i386/types.h index 0ac64734c..c20063f31 100644 --- a/include/grub/i386/types.h +++ b/include/grub/i386/types.h @@ -28,4 +28,6 @@ /* i386 is little-endian. */ #undef GRUB_TARGET_WORDS_BIGENDIAN +#define GRUB_HAVE_UNALIGNED_ACCESS 1 + #endif /* ! GRUB_TYPES_CPU_HEADER */ diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h index be3835a42..fb85db9f1 100644 --- a/include/grub/ieee1275/ieee1275.h +++ b/include/grub/ieee1275/ieee1275.h @@ -125,7 +125,7 @@ extern void EXPORT_FUNC(grub_ieee1275_set_flag) (enum grub_ieee1275_flag flag); void EXPORT_FUNC(grub_ieee1275_init) (void); -int EXPORT_FUNC(grub_ieee1275_finddevice) (char *name, +int EXPORT_FUNC(grub_ieee1275_finddevice) (const char *name, grub_ieee1275_phandle_t *phandlep); int EXPORT_FUNC(grub_ieee1275_get_property) (grub_ieee1275_phandle_t phandle, const char *property, void *buf, @@ -148,7 +148,7 @@ int EXPORT_FUNC(grub_ieee1275_instance_to_path) (grub_ieee1275_ihandle_t ihandle, char *path, grub_size_t len, grub_ssize_t *actual); int EXPORT_FUNC(grub_ieee1275_write) (grub_ieee1275_ihandle_t ihandle, - void *buffer, grub_size_t len, + const void *buffer, grub_size_t len, grub_ssize_t *actualp); int EXPORT_FUNC(grub_ieee1275_read) (grub_ieee1275_ihandle_t ihandle, void *buffer, grub_size_t len, @@ -184,11 +184,9 @@ int EXPORT_FUNC(grub_ieee1275_milliseconds) (grub_uint32_t *msecs); int EXPORT_FUNC(grub_devalias_iterate) (int (*hook) (struct grub_ieee1275_devalias *alias)); -int EXPORT_FUNC(grub_children_iterate) (char *devpath, +int EXPORT_FUNC(grub_children_iterate) (const char *devpath, int (*hook) (struct grub_ieee1275_devalias *alias)); -grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate) - (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); -int EXPORT_FUNC(grub_claimmap) (grub_addr_t addr, grub_size_t size); +grub_err_t EXPORT_FUNC(grub_claimmap) (grub_addr_t addr, grub_size_t size); int EXPORT_FUNC(grub_ieee1275_map) (grub_addr_t phys, grub_addr_t virt, diff --git a/include/grub/kernel.h b/include/grub/kernel.h index f9fc817db..4c8b29c8b 100644 --- a/include/grub/kernel.h +++ b/include/grub/kernel.h @@ -77,12 +77,12 @@ extern grub_addr_t EXPORT_VAR (grub_modbase); var && (grub_addr_t) var \ < (grub_modbase + (((struct grub_module_info *) grub_modbase)->size)); \ var = (struct grub_module_header *) \ - ((char *) var + ((struct grub_module_header *) var)->size)) + ((grub_uint32_t *) var + ((struct grub_module_header *) var)->size / 4)) grub_addr_t grub_modules_get_end (void); /* The start point of the C code. */ -void grub_main (void); +void grub_main (void) __attribute__ ((noreturn)); /* The machine-specific initialization. This must initialize memory. */ void grub_machine_init (void); diff --git a/include/grub/lib/arg.h b/include/grub/lib/arg.h index b61f6f30e..f81af85ee 100644 --- a/include/grub/lib/arg.h +++ b/include/grub/lib/arg.h @@ -53,8 +53,8 @@ struct grub_arg_option const char *longarg; int shortarg; int flags; - char *doc; - char *arg; + const char *doc; + const char *arg; grub_arg_type_t type; }; diff --git a/include/grub/list.h b/include/grub/list.h index 75353010c..54f528a05 100644 --- a/include/grub/list.h +++ b/include/grub/list.h @@ -27,11 +27,30 @@ struct grub_list { struct grub_list *next; + struct grub_list **prev; }; typedef struct grub_list *grub_list_t; -void EXPORT_FUNC(grub_list_push) (grub_list_t *head, grub_list_t item); -void EXPORT_FUNC(grub_list_remove) (grub_list_t *head, grub_list_t item); +static inline void +grub_list_push (grub_list_t *head, grub_list_t item) +{ + item->prev = head; + if (*head) + (*head)->prev = &item->next; + item->next = *head; + *head = item; +} + +static inline void +grub_list_remove (grub_list_t item) +{ + if (item->prev) + *item->prev = item->next; + if (item->next) + item->next->prev = item->prev; + item->next = 0; + item->prev = 0; +} #define FOR_LIST_ELEMENTS(var, list) for ((var) = (list); (var); (var) = (var)->next) @@ -53,16 +72,17 @@ grub_bad_type_cast_real (int line, const char *file) ((char *) &(ptr)->field == (char *) &((type) (ptr))->field) #define GRUB_AS_LIST(ptr) \ - (GRUB_FIELD_MATCH (ptr, grub_list_t, next) ? \ - (grub_list_t) ptr : grub_bad_type_cast ()) + (GRUB_FIELD_MATCH (ptr, grub_list_t, next) && GRUB_FIELD_MATCH (ptr, grub_list_t, prev) ? \ + (grub_list_t) ptr : (grub_list_t) grub_bad_type_cast ()) #define GRUB_AS_LIST_P(pptr) \ - (GRUB_FIELD_MATCH (*pptr, grub_list_t, next) ? \ - (grub_list_t *) (void *) pptr : grub_bad_type_cast ()) + (GRUB_FIELD_MATCH (*pptr, grub_list_t, next) && GRUB_FIELD_MATCH (*pptr, grub_list_t, prev) ? \ + (grub_list_t *) (void *) pptr : (grub_list_t *) grub_bad_type_cast ()) struct grub_named_list { struct grub_named_list *next; + struct grub_named_list **prev; char *name; }; typedef struct grub_named_list *grub_named_list_t; @@ -71,14 +91,16 @@ void * EXPORT_FUNC(grub_named_list_find) (grub_named_list_t head, const char *name); #define GRUB_AS_NAMED_LIST(ptr) \ - ((GRUB_FIELD_MATCH (ptr, grub_named_list_t, next) && \ - GRUB_FIELD_MATCH (ptr, grub_named_list_t, name))? \ - (grub_named_list_t) ptr : grub_bad_type_cast ()) + ((GRUB_FIELD_MATCH (ptr, grub_named_list_t, next) \ + && GRUB_FIELD_MATCH (ptr, grub_named_list_t, prev) \ + && GRUB_FIELD_MATCH (ptr, grub_named_list_t, name))? \ + (grub_named_list_t) ptr : (grub_named_list_t) grub_bad_type_cast ()) #define GRUB_AS_NAMED_LIST_P(pptr) \ - ((GRUB_FIELD_MATCH (*pptr, grub_named_list_t, next) && \ - GRUB_FIELD_MATCH (*pptr, grub_named_list_t, name))? \ - (grub_named_list_t *) (void *) pptr : grub_bad_type_cast ()) + ((GRUB_FIELD_MATCH (*pptr, grub_named_list_t, next) \ + && GRUB_FIELD_MATCH (*pptr, grub_named_list_t, prev) \ + && GRUB_FIELD_MATCH (*pptr, grub_named_list_t, name))? \ + (grub_named_list_t *) (void *) pptr : (grub_named_list_t *) grub_bad_type_cast ()) #define GRUB_PRIO_LIST_PRIO_MASK 0xff #define GRUB_PRIO_LIST_FLAG_ACTIVE 0x100 @@ -86,6 +108,7 @@ void * EXPORT_FUNC(grub_named_list_find) (grub_named_list_t head, struct grub_prio_list { struct grub_prio_list *next; + struct grub_prio_list **prev; char *name; int prio; }; @@ -95,23 +118,27 @@ void EXPORT_FUNC(grub_prio_list_insert) (grub_prio_list_t *head, grub_prio_list_t item); static inline void -grub_prio_list_remove (grub_prio_list_t *head, grub_prio_list_t item) +grub_prio_list_remove (grub_prio_list_t item) { if ((item->prio & GRUB_PRIO_LIST_FLAG_ACTIVE) && (item->next)) item->next->prio |= GRUB_PRIO_LIST_FLAG_ACTIVE; - grub_list_remove (GRUB_AS_LIST_P (head), GRUB_AS_LIST (item)); + grub_list_remove (GRUB_AS_LIST (item)); } #define GRUB_AS_PRIO_LIST(ptr) \ - ((GRUB_FIELD_MATCH (ptr, grub_prio_list_t, next) && \ - GRUB_FIELD_MATCH (ptr, grub_prio_list_t, name) && \ - GRUB_FIELD_MATCH (ptr, grub_prio_list_t, prio))? \ - (grub_prio_list_t) ptr : grub_bad_type_cast ()) + ((GRUB_FIELD_MATCH (ptr, grub_prio_list_t, next) \ + && GRUB_FIELD_MATCH (ptr, grub_prio_list_t, prev) \ + && GRUB_FIELD_MATCH (ptr, grub_prio_list_t, name) \ + && GRUB_FIELD_MATCH (ptr, grub_prio_list_t, prio))? \ + (grub_prio_list_t) ptr \ + : (grub_prio_list_t) grub_bad_type_cast ()) #define GRUB_AS_PRIO_LIST_P(pptr) \ - ((GRUB_FIELD_MATCH (*pptr, grub_prio_list_t, next) && \ - GRUB_FIELD_MATCH (*pptr, grub_prio_list_t, name) && \ - GRUB_FIELD_MATCH (*pptr, grub_prio_list_t, prio))? \ - (grub_prio_list_t *) (void *) pptr : grub_bad_type_cast ()) + ((GRUB_FIELD_MATCH (*pptr, grub_prio_list_t, next) \ + && GRUB_FIELD_MATCH (*pptr, grub_prio_list_t, prev) \ + && GRUB_FIELD_MATCH (*pptr, grub_prio_list_t, name) \ + && GRUB_FIELD_MATCH (*pptr, grub_prio_list_t, prio)) ? \ + (grub_prio_list_t *) (void *) pptr \ + : (grub_prio_list_t *) grub_bad_type_cast ()) #endif /* ! GRUB_LIST_HEADER */ diff --git a/include/grub/loader.h b/include/grub/loader.h index f38deb96a..1d70ef049 100644 --- a/include/grub/loader.h +++ b/include/grub/loader.h @@ -56,11 +56,13 @@ typedef enum { } grub_loader_preboot_hook_prio_t; /* Register a preboot hook. */ -void *EXPORT_FUNC(grub_loader_register_preboot_hook) (grub_err_t (*preboot_func) (int noret), - grub_err_t (*preboot_rest_func) (void), - grub_loader_preboot_hook_prio_t prio); +struct grub_preboot; + +struct grub_preboot *EXPORT_FUNC(grub_loader_register_preboot_hook) (grub_err_t (*preboot_func) (int noret), + grub_err_t (*preboot_rest_func) (void), + grub_loader_preboot_hook_prio_t prio); /* Unregister given preboot hook. */ -void EXPORT_FUNC (grub_loader_unregister_preboot_hook) (void *hnd); +void EXPORT_FUNC (grub_loader_unregister_preboot_hook) (struct grub_preboot *hnd); #endif /* ! GRUB_LOADER_HEADER */ diff --git a/include/grub/lvm.h b/include/grub/lvm.h index d77b88ff5..2d4ab6ff3 100644 --- a/include/grub/lvm.h +++ b/include/grub/lvm.h @@ -21,60 +21,11 @@ #define GRUB_LVM_H 1 #include +#include /* Length of ID string, excluding terminating zero. */ #define GRUB_LVM_ID_STRLEN 38 -struct grub_lvm_vg { - char id[GRUB_LVM_ID_STRLEN+1]; - char *name; - int extent_size; - struct grub_lvm_pv *pvs; - struct grub_lvm_lv *lvs; - struct grub_lvm_vg *next; -}; - -struct grub_lvm_pv { - char id[GRUB_LVM_ID_STRLEN+1]; - char *name; - grub_disk_t disk; - grub_disk_addr_t start; /* Sector number where the data area starts. */ - struct grub_lvm_pv *next; -}; - -struct grub_lvm_lv { - char *name; - char *fullname; - char *compatname; - unsigned int number; - unsigned int segment_count; - grub_uint64_t size; - - int visible; - - struct grub_lvm_segment *segments; /* Pointer to segment_count segments. */ - struct grub_lvm_vg *vg; - struct grub_lvm_lv *next; -}; - -struct grub_lvm_segment { - unsigned int start_extent; - unsigned int extent_count; - enum { GRUB_LVM_STRIPED, GRUB_LVM_MIRROR } type; - - unsigned int node_count; - struct grub_lvm_node *nodes; - - unsigned int stripe_size; -}; - -struct grub_lvm_node { - grub_disk_addr_t start; - char *name; - struct grub_lvm_pv *pv; - struct grub_lvm_lv *lv; -}; - #define GRUB_LVM_LABEL_SIZE GRUB_DISK_SECTOR_SIZE #define GRUB_LVM_LABEL_SCAN_SECTORS 4L diff --git a/include/grub/machoload.h b/include/grub/machoload.h index 8410162fb..9ad509b6e 100644 --- a/include/grub/machoload.h +++ b/include/grub/machoload.h @@ -42,7 +42,7 @@ struct grub_macho_file typedef struct grub_macho_file *grub_macho_t; grub_macho_t grub_macho_open (const char *); -grub_macho_t grub_macho_file (grub_file_t); +grub_macho_t grub_macho_file (grub_file_t file, const char *filename); grub_err_t grub_macho_close (grub_macho_t); int grub_macho_contains_macho32 (grub_macho_t); @@ -57,17 +57,21 @@ grub_uint64_t grub_macho_get_entry_point64 (grub_macho_t macho); /* Ignore BSS segments when loading. */ #define GRUB_MACHO_NOBSS 0x1 -grub_err_t grub_macho_load32 (grub_macho_t macho, char *offset, int flags); -grub_err_t grub_macho_load64 (grub_macho_t macho, char *offset, int flags); +grub_err_t grub_macho_load32 (grub_macho_t macho, const char *filename, + char *offset, int flags); +grub_err_t grub_macho_load64 (grub_macho_t macho, const char *filename, + char *offset, int flags); /* Like filesize and file_read but take only 32-bit part for current architecture. */ grub_size_t grub_macho_filesize32 (grub_macho_t macho); -grub_err_t grub_macho_readfile32 (grub_macho_t macho, void *dest); +grub_err_t grub_macho_readfile32 (grub_macho_t macho, const char *filename, + void *dest); grub_size_t grub_macho_filesize64 (grub_macho_t macho); -grub_err_t grub_macho_readfile64 (grub_macho_t macho, void *dest); +grub_err_t grub_macho_readfile64 (grub_macho_t macho, const char *filename, + void *dest); -void grub_macho_parse32 (grub_macho_t macho); -void grub_macho_parse64 (grub_macho_t macho); +void grub_macho_parse32 (grub_macho_t macho, const char *filename); +void grub_macho_parse64 (grub_macho_t macho, const char *filename); #endif /* ! GRUB_MACHOLOAD_HEADER */ diff --git a/include/grub/mips/kernel.h b/include/grub/mips/kernel.h index d351f17cb..07b08848d 100644 --- a/include/grub/mips/kernel.h +++ b/include/grub/mips/kernel.h @@ -21,10 +21,4 @@ #include -#ifndef ASM_FILE - -void EXPORT_FUNC (grub_halt) (void) __attribute__ ((noreturn)); - -#endif - #endif /* ! GRUB_KERNEL_MACHINE_HEADER */ diff --git a/include/grub/mips/loongson/kernel.h b/include/grub/mips/loongson/kernel.h index ba94e4331..5e6e6fdfb 100644 --- a/include/grub/mips/loongson/kernel.h +++ b/include/grub/mips/loongson/kernel.h @@ -28,7 +28,7 @@ #ifndef ASM_FILE -extern grub_uint32_t EXPORT_VAR (grub_arch_machine); +extern grub_uint32_t EXPORT_VAR (grub_arch_machine) __attribute__ ((section(".text"))); #endif diff --git a/include/grub/mips/loongson/memory.h b/include/grub/mips/loongson/memory.h index a288eb6ab..aa41fa626 100644 --- a/include/grub/mips/loongson/memory.h +++ b/include/grub/mips/loongson/memory.h @@ -43,8 +43,8 @@ grub_machine_mmap_unregister (int handle __attribute__ ((unused))) return GRUB_ERR_NONE; } -extern grub_uint32_t EXPORT_VAR (grub_arch_memsize); -extern grub_uint32_t EXPORT_VAR (grub_arch_highmemsize); +extern grub_uint32_t EXPORT_VAR (grub_arch_memsize) __attribute__ ((section(".text"))); +extern grub_uint32_t EXPORT_VAR (grub_arch_highmemsize) __attribute__ ((section(".text"))); #endif diff --git a/include/grub/mips/loongson/time.h b/include/grub/mips/loongson/time.h index 8b8ee42c4..098573261 100644 --- a/include/grub/mips/loongson/time.h +++ b/include/grub/mips/loongson/time.h @@ -22,6 +22,6 @@ #include #include -extern grub_uint32_t EXPORT_VAR (grub_arch_busclock); +extern grub_uint32_t EXPORT_VAR (grub_arch_busclock) __attribute__ ((section(".text"))); #endif /* ! KERNEL_MACHINE_TIME_HEADER */ diff --git a/include/grub/mips/qemu_mips/kernel.h b/include/grub/mips/qemu_mips/kernel.h index 1e7e32401..8b8b0149e 100644 --- a/include/grub/mips/qemu_mips/kernel.h +++ b/include/grub/mips/qemu_mips/kernel.h @@ -23,7 +23,6 @@ #ifndef ASM_FILE -void EXPORT_FUNC (grub_halt) (void); void grub_qemu_init_cirrus (void); #endif diff --git a/include/grub/mips/qemu_mips/memory.h b/include/grub/mips/qemu_mips/memory.h index 48a9b69f0..29b04a5ad 100644 --- a/include/grub/mips/qemu_mips/memory.h +++ b/include/grub/mips/qemu_mips/memory.h @@ -30,7 +30,7 @@ #ifndef ASM_FILE -extern grub_uint32_t grub_arch_memsize; +extern grub_uint32_t grub_arch_memsize __attribute__ ((section(".text"))); static inline grub_err_t grub_machine_mmap_register (grub_uint64_t start __attribute__ ((unused)), diff --git a/include/grub/mips/time.h b/include/grub/mips/time.h index 1139b24bb..f5c891a3a 100644 --- a/include/grub/mips/time.h +++ b/include/grub/mips/time.h @@ -26,7 +26,7 @@ /* Return the real time in ticks. */ grub_uint64_t EXPORT_FUNC (grub_get_rtc) (void); -extern grub_uint32_t EXPORT_VAR (grub_arch_cpuclock); +extern grub_uint32_t EXPORT_VAR (grub_arch_cpuclock) __attribute__ ((section(".text"))); #endif static inline void diff --git a/include/grub/misc.h b/include/grub/misc.h index 358f73258..be5fa6007 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -24,6 +24,7 @@ #include #include #include +#include /* GCC version checking borrowed from glibc. */ #if defined(__GNUC__) && defined(__GNUC_MINOR__) @@ -175,6 +176,18 @@ grub_isalpha (int c) return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } +static inline int +grub_islower (int c) +{ + return (c >= 'a' && c <= 'z'); +} + +static inline int +grub_isupper (int c) +{ + return (c >= 'A' && c <= 'Z'); +} + static inline int grub_isgraph (int c) { @@ -250,27 +263,6 @@ grub_strncasecmp (const char *s1, const char *s2, grub_size_t n) return (int) grub_tolower (*s1) - (int) grub_tolower (*s2); } -/* Replace all `ch' characters of `input' with `with' and copy the - result into `output'; return EOS address of `output'. */ -static inline char * -grub_strchrsub (char *output, const char *input, char ch, const char *with) -{ - grub_size_t grub_strlen (const char *s); - while (*input) - { - if (*input == ch) - { - grub_strcpy (output, with); - output += grub_strlen (with); - input++; - continue; - } - *output++ = *input++; - } - *output = '\0'; - return output; -} - unsigned long EXPORT_FUNC(grub_strtoul) (const char *str, char **end, int base); unsigned long long EXPORT_FUNC(grub_strtoull) (const char *str, char **end, int base); @@ -294,7 +286,7 @@ grub_strtol (const char *str, char **end, int base) { if (magnitude > (unsigned long) GRUB_LONG_MAX + 1) { - grub_error (GRUB_ERR_OUT_OF_RANGE, "negative overflow"); + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); return GRUB_LONG_MIN; } return -((long) magnitude); @@ -303,7 +295,7 @@ grub_strtol (const char *str, char **end, int base) { if (magnitude > GRUB_LONG_MAX) { - grub_error (GRUB_ERR_OUT_OF_RANGE, "positive overflow"); + grub_error (GRUB_ERR_OUT_OF_RANGE, N_("overflow is detected")); return GRUB_LONG_MAX; } return (long) magnitude; @@ -317,6 +309,26 @@ grub_size_t EXPORT_FUNC(grub_strlen) (const char *s) __attribute__ ((warn_unused int EXPORT_FUNC(grub_printf) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); int EXPORT_FUNC(grub_printf_) (const char *fmt, ...) __attribute__ ((format (printf, 1, 2))); +/* Replace all `ch' characters of `input' with `with' and copy the + result into `output'; return EOS address of `output'. */ +static inline char * +grub_strchrsub (char *output, const char *input, char ch, const char *with) +{ + while (*input) + { + if (*input == ch) + { + grub_strcpy (output, with); + output += grub_strlen (with); + input++; + continue; + } + *output++ = *input++; + } + *output = '\0'; + return output; +} + extern void (*EXPORT_VAR (grub_xputs)) (const char *str); static inline int @@ -348,17 +360,31 @@ grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n, grub_uint64_t d, grub_uint64_t *r); -#if NEED_ENABLE_EXECUTE_STACK && !defined(GRUB_UTIL) +#if !defined(GRUB_UTIL) && NEED_ENABLE_EXECUTE_STACK void EXPORT_FUNC(__enable_execute_stack) (void *addr); #endif -#if NEED_REGISTER_FRAME_INFO && !defined(GRUB_UTIL) +#if !defined(GRUB_UTIL) && NEED_REGISTER_FRAME_INFO void EXPORT_FUNC (__register_frame_info) (void); void EXPORT_FUNC (__deregister_frame_info) (void); #endif /* Inline functions. */ +static inline char * +grub_memchr (const void *p, int c, grub_size_t len) +{ + const char *s = p; + const char *e = s + len; + + for (; s < e; s++) + if (*s == c) + return (char *) s; + + return 0; +} + + static inline unsigned int grub_abs (int x) { @@ -368,24 +394,6 @@ grub_abs (int x) return (unsigned int) x; } -static inline long -grub_min (long x, long y) -{ - if (x < y) - return x; - else - return y; -} - -static inline long -grub_max (long x, long y) -{ - if (x > y) - return x; - else - return y; -} - /* Rounded-up division */ static inline unsigned int grub_div_roundup (unsigned int x, unsigned int y) @@ -394,12 +402,18 @@ grub_div_roundup (unsigned int x, unsigned int y) } /* Reboot the machine. */ +#if defined (GRUB_MACHINE_EMU) || defined (GRUB_MACHINE_QEMU_MIPS) +void EXPORT_FUNC(grub_reboot) (void) __attribute__ ((noreturn)); +#else void grub_reboot (void) __attribute__ ((noreturn)); +#endif #ifdef GRUB_MACHINE_PCBIOS /* Halt the system, using APM if possible. If NO_APM is true, don't * use APM even if it is available. */ void grub_halt (int no_apm) __attribute__ ((noreturn)); +#elif defined (__mips__) +void EXPORT_FUNC (grub_halt) (void) __attribute__ ((noreturn)); #else void grub_halt (void) __attribute__ ((noreturn)); #endif @@ -411,4 +425,19 @@ extern int EXPORT_VAR(grub_no_autoload); #define grub_no_autoload 0 #endif +static inline void +grub_error_save (struct grub_error_saved *save) +{ + grub_memcpy (save->errmsg, grub_errmsg, sizeof (save->errmsg)); + save->grub_errno = grub_errno; + grub_errno = GRUB_ERR_NONE; +} + +static inline void +grub_error_load (const struct grub_error_saved *save) +{ + grub_memcpy (grub_errmsg, save->errmsg, sizeof (grub_errmsg)); + grub_errno = save->grub_errno; +} + #endif /* ! GRUB_MISC_HEADER */ diff --git a/include/grub/multiboot.h b/include/grub/multiboot.h index 9a0b57359..af6b0a0df 100644 --- a/include/grub/multiboot.h +++ b/include/grub/multiboot.h @@ -80,10 +80,11 @@ grub_multiboot_set_console (int console_type, int accepted_consoles, int width, int height, int depth, int console_required); grub_err_t -grub_multiboot_load (grub_file_t file); +grub_multiboot_load (grub_file_t file, const char *filename); /* Load ELF32 or ELF64. */ grub_err_t -grub_multiboot_load_elf (grub_file_t file, void *buffer); +grub_multiboot_load_elf (grub_file_t file, const char *filename, + void *buffer); extern grub_size_t grub_multiboot_pure_size; extern grub_size_t grub_multiboot_alloc_mbi; extern grub_uint32_t grub_multiboot_payload_eip; diff --git a/include/grub/net.h b/include/grub/net.h index 45d08f3f5..7d6f06733 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -27,6 +27,19 @@ #include #include +enum + { + GRUB_NET_MAX_LINK_HEADER_SIZE = 64, + GRUB_NET_UDP_HEADER_SIZE = 8, + GRUB_NET_TCP_HEADER_SIZE = 20, + GRUB_NET_OUR_IPV4_HEADER_SIZE = 20, + GRUB_NET_OUR_IPV6_HEADER_SIZE = 40, + GRUB_NET_OUR_MAX_IP_HEADER_SIZE = 40, + GRUB_NET_TCP_RESERVE_SIZE = GRUB_NET_TCP_HEADER_SIZE + + GRUB_NET_OUR_IPV4_HEADER_SIZE + + GRUB_NET_MAX_LINK_HEADER_SIZE + }; + typedef enum grub_link_level_protocol_id { GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET @@ -59,13 +72,13 @@ struct grub_net_card; struct grub_net_card_driver { struct grub_net_card_driver *next; - char *name; + struct grub_net_card_driver **prev; + const char *name; grub_err_t (*open) (const struct grub_net_card *dev); void (*close) (const struct grub_net_card *dev); grub_err_t (*send) (const struct grub_net_card *dev, struct grub_net_buff *buf); - grub_ssize_t (*recv) (const struct grub_net_card *dev, - struct grub_net_buff *buf); + struct grub_net_buff * (*recv) (const struct grub_net_card *dev); }; typedef struct grub_net_packet @@ -86,10 +99,22 @@ typedef struct grub_net_packets #include #endif +struct grub_net_slaac_mac_list +{ + struct grub_net_slaac_mac_list *next; + struct grub_net_slaac_mac_list **prev; + grub_net_link_level_address_t address; + int slaac_counter; + char *name; +}; + +struct grub_net_link_layer_entry; + struct grub_net_card { struct grub_net_card *next; - char *name; + struct grub_net_card **prev; + const char *name; struct grub_net_card_driver *driver; grub_net_link_level_address_t default_address; grub_net_card_flags_t flags; @@ -97,6 +122,10 @@ struct grub_net_card int opened; unsigned idle_poll_delay_ms; grub_uint64_t last_poll; + grub_size_t mtu; + struct grub_net_slaac_mac_list *slaac_list; + grub_ssize_t new_ll_entry; + struct grub_net_link_layer_entry *link_layer_table; union { #ifdef GRUB_MACHINE_EFI @@ -116,7 +145,8 @@ struct grub_net_network_level_interface; typedef enum grub_network_level_protocol_id { GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV, - GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4 + GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4, + GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6 } grub_network_level_protocol_id_t; typedef struct grub_net_network_level_address @@ -125,6 +155,7 @@ typedef struct grub_net_network_level_address union { grub_uint32_t ipv4; + grub_uint64_t ipv6[2]; }; } grub_net_network_level_address_t; @@ -137,6 +168,10 @@ typedef struct grub_net_network_level_netaddress grub_uint32_t base; int masksize; } ipv4; + struct { + grub_uint64_t base[2]; + int masksize; + } ipv6; }; } grub_net_network_level_netaddress_t; @@ -188,48 +223,16 @@ typedef struct grub_net_socket *grub_net_socket_t; struct grub_net_app_protocol { struct grub_net_app_protocol *next; - char *name; + struct grub_net_app_protocol **prev; + const char *name; grub_err_t (*dir) (grub_device_t device, const char *path, int (*hook) (const char *filename, const struct grub_dirhook_info *info)); grub_err_t (*open) (struct grub_file *file, const char *filename); + grub_err_t (*seek) (struct grub_file *file, grub_off_t off); grub_err_t (*close) (struct grub_file *file); }; -struct grub_net_socket -{ - struct grub_net_socket *next; - - enum { GRUB_NET_SOCKET_START, - GRUB_NET_SOCKET_ESTABLISHED, - GRUB_NET_SOCKET_CLOSED } x_status; - int x_in_port; - int x_out_port; - grub_err_t (*recv_hook) (grub_net_socket_t sock, struct grub_net_buff *nb, - void *recv); - void *recv_hook_data; - grub_net_network_level_address_t x_out_nla; - struct grub_net_network_level_interface *x_inf; -}; - -extern struct grub_net_socket *grub_net_sockets; - -static inline void -grub_net_socket_register (grub_net_socket_t sock) -{ - grub_list_push (GRUB_AS_LIST_P (&grub_net_sockets), - GRUB_AS_LIST (sock)); -} - -static inline void -grub_net_socket_unregister (grub_net_socket_t sock) -{ - grub_list_remove (GRUB_AS_LIST_P (&grub_net_sockets), - GRUB_AS_LIST (sock)); -} - -#define FOR_NET_SOCKETS(var) for (var = grub_net_sockets; var; var = var->next) - typedef struct grub_net { char *server; @@ -297,11 +300,14 @@ grub_net_session_recv (struct grub_net_session *session, void *buf, struct grub_net_network_level_interface * grub_net_add_addr (const char *name, struct grub_net_card *card, - grub_net_network_level_address_t addr, - grub_net_link_level_address_t hwaddress, + const grub_net_network_level_address_t *addr, + const grub_net_link_level_address_t *hwaddress, grub_net_interface_flags_t flags); extern struct grub_net_network_level_interface *grub_net_network_level_interfaces; +#define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_level_interfaces; var; var = var->next) +#define FOR_NET_NETWORK_LEVEL_INTERFACES_SAFE(var,next) for (var = grub_net_network_level_interfaces, next = (var ? var->next : 0); var; var = next, next = (var ? var->next : 0)) + extern grub_net_app_level_t grub_net_app_level_list; @@ -317,8 +323,7 @@ grub_net_app_level_register (grub_net_app_level_t proto) static inline void grub_net_app_level_unregister (grub_net_app_level_t proto) { - grub_list_remove (GRUB_AS_LIST_P (&grub_net_app_level_list), - GRUB_AS_LIST (proto)); + grub_list_remove (GRUB_AS_LIST (proto)); } #define FOR_NET_APP_LEVEL(var) FOR_LIST_ELEMENTS((var), \ @@ -337,7 +342,7 @@ void grub_net_card_unregister (struct grub_net_card *card); #define FOR_NET_CARDS(var) for (var = grub_net_cards; var; var = var->next) -#define FOR_NET_CARDS_SAFE(var, next) for (var = grub_net_cards, next = var->next; var; var = next, next = var->next) +#define FOR_NET_CARDS_SAFE(var, next) for (var = grub_net_cards, next = (var ? var->next : 0); var; var = next, next = (var ? var->next : 0)) struct grub_net_session * @@ -396,6 +401,18 @@ struct grub_net_bootp_packet #define GRUB_NET_BOOTP_RFC1048_MAGIC_2 0x53 #define GRUB_NET_BOOTP_RFC1048_MAGIC_3 0x63 +enum + { + GRUB_NET_BOOTP_PAD = 0x00, + GRUB_NET_BOOTP_ROUTER = 0x03, + GRUB_NET_BOOTP_DNS = 0x06, + GRUB_NET_BOOTP_HOSTNAME = 0x0c, + GRUB_NET_BOOTP_DOMAIN = 0x0f, + GRUB_NET_BOOTP_ROOT_PATH = 0x11, + GRUB_NET_BOOTP_EXTENSIONS_PATH = 0x12, + GRUB_NET_BOOTP_END = 0xff + }; + struct grub_net_network_level_interface * grub_net_configure_by_dhcp_ack (const char *name, struct grub_net_card *card, @@ -411,22 +428,30 @@ grub_net_process_dhcp (struct grub_net_buff *nb, int grub_net_hwaddr_cmp (const grub_net_link_level_address_t *a, const grub_net_link_level_address_t *b); +int +grub_net_addr_cmp (const grub_net_network_level_address_t *a, + const grub_net_network_level_address_t *b); /* - Currently suppoerted adresses: + Currently supported adresses: IPv4: XXX.XXX.XXX.XXX + IPv6: XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX */ -#define GRUB_NET_MAX_STR_ADDR_LEN sizeof ("XXX.XXX.XXX.XXX") +#define GRUB_NET_MAX_STR_ADDR_LEN sizeof ("XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX") + +/* + Currently suppoerted adresses: + ethernet: XX:XX:XX:XX:XX:XX + */ + +#define GRUB_NET_MAX_STR_HWADDR_LEN (sizeof ("XX:XX:XX:XX:XX:XX")) void grub_net_addr_to_str (const grub_net_network_level_address_t *target, char *buf); - -extern struct grub_net_network_level_interface *grub_net_network_level_interfaces; -#define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_level_interfaces; var; var = var->next) - -#define FOR_NET_NETWORK_LEVEL_INTERFACES_SAFE(var,next) for (var = grub_net_network_level_interfaces, next = var->next; var; var = next, next = var->next) +void +grub_net_hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str); void grub_net_poll_cards (unsigned time); @@ -434,6 +459,9 @@ grub_net_poll_cards (unsigned time); void grub_bootp_init (void); void grub_bootp_fini (void); +void grub_dns_init (void); +void grub_dns_fini (void); + static inline void grub_net_network_level_interface_unregister (struct grub_net_network_level_interface *inter) { @@ -445,6 +473,37 @@ grub_net_network_level_interface_unregister (struct grub_net_network_level_inter inter->prev = 0; } +void +grub_net_tcp_retransmit (void); + +void +grub_net_link_layer_add_address (struct grub_net_card *card, + const grub_net_network_level_address_t *nl, + const grub_net_link_level_address_t *ll, + int override); +int +grub_net_link_layer_resolve_check (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *proto_addr); +grub_err_t +grub_net_link_layer_resolve (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *proto_addr, + grub_net_link_level_address_t *hw_addr); +grub_err_t +grub_net_dns_lookup (const char *name, + const struct grub_net_network_level_address *servers, + grub_size_t n_servers, + grub_size_t *naddresses, + struct grub_net_network_level_address **addresses, + int cache); +grub_err_t +grub_net_add_dns_server (const struct grub_net_network_level_address *s); +void +grub_net_remove_dns_server (const struct grub_net_network_level_address *s); + + extern char *grub_net_default_server; +#define GRUB_NET_TRIES 40 +#define GRUB_NET_INTERVAL 400 + #endif /* ! GRUB_NET_HEADER */ diff --git a/include/grub/net/arp.h b/include/grub/net/arp.h index c60ea333f..bb1703622 100644 --- a/include/grub/net/arp.h +++ b/include/grub/net/arp.h @@ -1,36 +1,31 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + #ifndef GRUB_NET_ARP_HEADER #define GRUB_NET_ARP_HEADER 1 #include #include -enum -{ -/* IANA ARP constant to define hardware type as ethernet. */ - GRUB_NET_ARPHRD_ETHERNET = 1 -}; +extern grub_err_t grub_net_arp_receive (struct grub_net_buff *nb, + struct grub_net_card *card); -/* ARP header operation codes */ -#define ARP_REQUEST 1 -#define ARP_REPLY 2 - -struct arp_entry { - int avail; - grub_net_network_level_address_t nl_address; - grub_net_link_level_address_t ll_address; -}; - -struct arphdr { - grub_uint16_t hrd; - grub_uint16_t pro; - grub_uint8_t hln; - grub_uint8_t pln; - grub_uint16_t op; -} __attribute__ ((packed)); - -extern grub_err_t grub_net_arp_receive(struct grub_net_buff *nb); - -extern grub_err_t grub_net_arp_resolve(struct grub_net_network_level_interface *inf, - const grub_net_network_level_address_t *addr, - grub_net_link_level_address_t *hw_addr); +grub_err_t +grub_net_arp_send_request (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *proto_addr); #endif diff --git a/include/grub/net/ethernet.h b/include/grub/net/ethernet.h index a68aafd96..23a935e98 100644 --- a/include/grub/net/ethernet.h +++ b/include/grub/net/ethernet.h @@ -22,19 +22,20 @@ #include /* IANA Ethertype */ -enum -{ - GRUB_NET_ETHERTYPE_IP = 0x0800, - GRUB_NET_ETHERTYPE_ARP = 0x0806 -}; +typedef enum + { + GRUB_NET_ETHERTYPE_IP = 0x0800, + GRUB_NET_ETHERTYPE_ARP = 0x0806, + GRUB_NET_ETHERTYPE_IP6 = 0x86DD, + } grub_net_ethertype_t; grub_err_t send_ethernet_packet (struct grub_net_network_level_interface *inf, struct grub_net_buff *nb, grub_net_link_level_address_t target_addr, - grub_uint16_t ethertype); + grub_net_ethertype_t ethertype); grub_err_t grub_net_recv_ethernet_packet (struct grub_net_buff *nb, - const struct grub_net_card *card); + struct grub_net_card *card); #endif diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h index 9bed1e19c..7a8e61479 100644 --- a/include/grub/net/ip.h +++ b/include/grub/net/ip.h @@ -21,22 +21,75 @@ #include #include -enum +typedef enum grub_net_ip_protocol { - IP_UDP = 0x11 /* UDP protocol */ - }; -#define IP_BROADCAST 0xFFFFFFFF + GRUB_NET_IP_ICMP = 1, + GRUB_NET_IP_TCP = 6, + GRUB_NET_IP_UDP = 17, + GRUB_NET_IP_ICMPV6 = 58 + } grub_net_ip_protocol_t; +#define GRUB_NET_IP_BROADCAST 0xFFFFFFFF -grub_uint16_t grub_net_ip_chksum(void *ipv, int len); +static inline grub_uint64_t +grub_net_ipv6_get_id (const grub_net_link_level_address_t *addr) +{ + return grub_cpu_to_be64 (((grub_uint64_t) (addr->mac[0] ^ 2) << 56) + | ((grub_uint64_t) addr->mac[1] << 48) + | ((grub_uint64_t) addr->mac[2] << 40) + | 0xfffe000000ULL + | ((grub_uint64_t) addr->mac[3] << 16) + | ((grub_uint64_t) addr->mac[4] << 8) + | ((grub_uint64_t) addr->mac[5])); +} + +grub_uint16_t grub_net_ip_chksum(void *ipv, grub_size_t len); grub_err_t grub_net_recv_ip_packets (struct grub_net_buff *nb, - const struct grub_net_card *card, - const grub_net_link_level_address_t *hwaddress); + struct grub_net_card *card, + const grub_net_link_level_address_t *hwaddress, + const grub_net_link_level_address_t *src_hwaddress); grub_err_t grub_net_send_ip_packet (struct grub_net_network_level_interface *inf, const grub_net_network_level_address_t *target, - struct grub_net_buff *nb); + const grub_net_link_level_address_t *ll_target_addr, + struct grub_net_buff *nb, + grub_net_ip_protocol_t proto); + +grub_err_t +grub_net_recv_icmp_packet (struct grub_net_buff *nb, + struct grub_net_network_level_interface *inf, + const grub_net_link_level_address_t *ll_src, + const grub_net_network_level_address_t *src); +grub_err_t +grub_net_recv_icmp6_packet (struct grub_net_buff *nb, + struct grub_net_card *card, + struct grub_net_network_level_interface *inf, + const grub_net_link_level_address_t *ll_src, + const grub_net_network_level_address_t *source, + const grub_net_network_level_address_t *dest, + grub_uint8_t ttl); +grub_err_t +grub_net_recv_udp_packet (struct grub_net_buff *nb, + struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *src); +grub_err_t +grub_net_recv_tcp_packet (struct grub_net_buff *nb, + struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *source); + +grub_uint16_t +grub_net_ip_transport_checksum (struct grub_net_buff *nb, + grub_uint16_t proto, + const grub_net_network_level_address_t *src, + const grub_net_network_level_address_t *dst); + +struct grub_net_network_level_interface * +grub_net_ipv6_get_link_local (struct grub_net_card *card, + const grub_net_link_level_address_t *hwaddr); +grub_err_t +grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf, + const grub_net_network_level_address_t *proto_addr); #endif diff --git a/include/grub/net/netbuff.h b/include/grub/net/netbuff.h index 245e813c3..c745d51d7 100644 --- a/include/grub/net/netbuff.h +++ b/include/grub/net/netbuff.h @@ -8,23 +8,23 @@ struct grub_net_buff { - /*Pointer to the start of the buffer*/ - char *head; - /*Pointer to the data */ - char *data; - /*Pointer to the tail */ - char *tail; - /*Pointer to the end of the buffer*/ - char *end; + /* Pointer to the start of the buffer. */ + grub_uint8_t *head; + /* Pointer to the data. */ + grub_uint8_t *data; + /* Pointer to the tail. */ + grub_uint8_t *tail; + /* Pointer to the end of the buffer. */ + grub_uint8_t *end; }; -grub_err_t grub_netbuff_put (struct grub_net_buff *net_buff ,grub_size_t len); -grub_err_t grub_netbuff_unput (struct grub_net_buff *net_buff ,grub_size_t len); -grub_err_t grub_netbuff_push (struct grub_net_buff *net_buff ,grub_size_t len); -grub_err_t grub_netbuff_pull (struct grub_net_buff *net_buff ,grub_size_t len); -grub_err_t grub_netbuff_reserve (struct grub_net_buff *net_buff ,grub_size_t len); +grub_err_t grub_netbuff_put (struct grub_net_buff *net_buff, grub_size_t len); +grub_err_t grub_netbuff_unput (struct grub_net_buff *net_buff, grub_size_t len); +grub_err_t grub_netbuff_push (struct grub_net_buff *net_buff, grub_size_t len); +grub_err_t grub_netbuff_pull (struct grub_net_buff *net_buff, grub_size_t len); +grub_err_t grub_netbuff_reserve (struct grub_net_buff *net_buff, grub_size_t len); grub_err_t grub_netbuff_clear (struct grub_net_buff *net_buff); -struct grub_net_buff * grub_netbuff_alloc ( grub_size_t len ); +struct grub_net_buff * grub_netbuff_alloc (grub_size_t len); grub_err_t grub_netbuff_free (struct grub_net_buff *net_buff); #endif diff --git a/include/grub/net/tcp.h b/include/grub/net/tcp.h new file mode 100644 index 000000000..62bfd2eba --- /dev/null +++ b/include/grub/net/tcp.h @@ -0,0 +1,79 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_NET_TCP_HEADER +#define GRUB_NET_TCP_HEADER 1 +#include +#include + +struct grub_net_tcp_socket; +typedef struct grub_net_tcp_socket *grub_net_tcp_socket_t; + +struct grub_net_tcp_listen; +typedef struct grub_net_tcp_listen *grub_net_tcp_listen_t; + +grub_net_tcp_socket_t +grub_net_tcp_open (char *server, + grub_uint16_t out_port, + grub_err_t (*recv_hook) (grub_net_tcp_socket_t sock, + struct grub_net_buff *nb, + void *data), + void (*error_hook) (grub_net_tcp_socket_t sock, + void *data), + void (*fin_hook) (grub_net_tcp_socket_t sock, + void *data), + void *hook_data); + +grub_net_tcp_listen_t +grub_net_tcp_listen (grub_uint16_t port, + const struct grub_net_network_level_interface *inf, + grub_err_t (*listen_hook) (grub_net_tcp_listen_t listen, + grub_net_tcp_socket_t sock, + void *data), + void *hook_data); + +void +grub_net_tcp_stop_listen (grub_net_tcp_listen_t listen); + +grub_err_t +grub_net_send_tcp_packet (const grub_net_tcp_socket_t socket, + struct grub_net_buff *nb, + int push); + +enum + { + GRUB_NET_TCP_CONTINUE_RECEIVING, + GRUB_NET_TCP_DISCARD, + GRUB_NET_TCP_ABORT + }; + +void +grub_net_tcp_close (grub_net_tcp_socket_t sock, int discard_received); + +grub_err_t +grub_net_tcp_accept (grub_net_tcp_socket_t sock, + grub_err_t (*recv_hook) (grub_net_tcp_socket_t sock, + struct grub_net_buff *nb, + void *data), + void (*error_hook) (grub_net_tcp_socket_t sock, + void *data), + void (*fin_hook) (grub_net_tcp_socket_t sock, + void *data), + void *hook_data); + +#endif diff --git a/include/grub/net/udp.h b/include/grub/net/udp.h index 5aacf8abb..1a7efa777 100644 --- a/include/grub/net/udp.h +++ b/include/grub/net/udp.h @@ -1,3 +1,21 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010,2011 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + #ifndef GRUB_NET_UDP_HEADER #define GRUB_NET_UDP_HEADER 1 #include @@ -11,28 +29,23 @@ struct udphdr grub_uint16_t chksum; } __attribute__ ((packed)); +struct grub_net_udp_socket; +typedef struct grub_net_udp_socket *grub_net_udp_socket_t; -grub_net_socket_t -grub_net_udp_open (char *server, +grub_net_udp_socket_t +grub_net_udp_open (grub_net_network_level_address_t addr, grub_uint16_t out_port, - grub_err_t (*recv_hook) (grub_net_socket_t sock, + grub_err_t (*recv_hook) (grub_net_udp_socket_t sock, struct grub_net_buff *nb, void *data), void *recv_hook_data); -static inline void -grub_net_udp_close (grub_net_socket_t sock) -{ - grub_net_socket_unregister (sock); - grub_free (sock); -} +void +grub_net_udp_close (grub_net_udp_socket_t sock); grub_err_t -grub_net_send_udp_packet (const grub_net_socket_t socket, struct grub_net_buff *nb); - -grub_err_t -grub_net_recv_udp_packet (struct grub_net_buff *nb, - struct grub_net_network_level_interface *inf); +grub_net_send_udp_packet (const grub_net_udp_socket_t socket, + struct grub_net_buff *nb); #endif diff --git a/include/grub/normal.h b/include/grub/normal.h index 08c14d209..b6b7d288d 100644 --- a/include/grub/normal.h +++ b/include/grub/normal.h @@ -28,9 +28,6 @@ #include #include -/* The maximum size of a command-line. */ -#define GRUB_MAX_CMDLINE 1600 - /* The standard left and right margin for some messages. */ #define STANDARD_MARGIN 6 @@ -135,4 +132,7 @@ void grub_normal_free_menu (grub_menu_t menu); void grub_normal_auth_init (void); void grub_normal_auth_fini (void); +grub_command_t +grub_dyncmd_get_cmd (grub_command_t cmd); + #endif /* ! GRUB_NORMAL_HEADER */ diff --git a/include/grub/ntfs.h b/include/grub/ntfs.h index cf90ce110..5cdd5f73f 100644 --- a/include/grub/ntfs.h +++ b/include/grub/ntfs.h @@ -81,7 +81,7 @@ enum #define GRUB_NTFS_BLK_SHR GRUB_DISK_SECTOR_BITS -#define GRUB_NTFS_MAX_MFT (1024 >> GRUB_NTFS_BLK_SHR) +#define GRUB_NTFS_MAX_MFT (4096 >> GRUB_NTFS_BLK_SHR) #define GRUB_NTFS_MAX_IDX (16384 >> GRUB_NTFS_BLK_SHR) #define GRUB_NTFS_COM_LEN 4096 @@ -157,7 +157,6 @@ struct grub_ntfs_data grub_uint32_t mft_size; grub_uint32_t idx_size; grub_uint32_t spc; - grub_uint32_t blocksize; grub_uint32_t mft_start; grub_uint64_t uuid; }; diff --git a/include/grub/offsets.h b/include/grub/offsets.h index 68ed084cb..d55e308c7 100644 --- a/include/grub/offsets.h +++ b/include/grub/offsets.h @@ -28,7 +28,12 @@ /* Offset of reed_solomon_redundancy. */ #define GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY 0x10 -#define GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART 0x6e0 +/* Offset of field holding no reed solomon length. */ +#define GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_LENGTH 0x14 + +#define GRUB_DECOMPRESSOR_I386_PC_BOOT_DEVICE 0x18 + +#define GRUB_DECOMPRESSOR_I386_PC_MAX_DECOMPRESSOR_SIZE (0x9000-0x8200) /* The segment where the kernel is loaded. */ #define GRUB_BOOT_I386_PC_KERNEL_SEG 0x800 diff --git a/include/grub/partition.h b/include/grub/partition.h index e7e00ef7f..7c1e7f6b3 100644 --- a/include/grub/partition.h +++ b/include/grub/partition.h @@ -38,6 +38,7 @@ struct grub_partition_map { /* The next partition map type. */ struct grub_partition_map *next; + struct grub_partition_map **prev; /* The name of the partition map type. */ const char *name; @@ -106,8 +107,7 @@ grub_partition_map_register (grub_partition_map_t partmap) static inline void grub_partition_map_unregister (grub_partition_map_t partmap) { - grub_list_remove (GRUB_AS_LIST_P (&grub_partition_map_list), - GRUB_AS_LIST (partmap)); + grub_list_remove (GRUB_AS_LIST (partmap)); } #define FOR_PARTITION_MAPS(var) FOR_LIST_ELEMENTS((var), (grub_partition_map_list)) diff --git a/include/grub/parttool.h b/include/grub/parttool.h index 8291e1161..4e8f8d5e5 100644 --- a/include/grub/parttool.h +++ b/include/grub/parttool.h @@ -21,8 +21,8 @@ struct grub_parttool_argdesc { - char *name; - char *desc; + const char *name; + const char *desc; enum {GRUB_PARTTOOL_ARG_END, GRUB_PARTTOOL_ARG_BOOL, GRUB_PARTTOOL_ARG_VAL} type; }; diff --git a/include/grub/pci.h b/include/grub/pci.h index f34e3d907..2c2806889 100644 --- a/include/grub/pci.h +++ b/include/grub/pci.h @@ -132,6 +132,21 @@ void EXPORT_FUNC(grub_dma_free) (struct grub_pci_dma_chunk *ch); volatile void *EXPORT_FUNC(grub_dma_get_virt) (struct grub_pci_dma_chunk *ch); grub_uint32_t EXPORT_FUNC(grub_dma_get_phys) (struct grub_pci_dma_chunk *ch); +static inline void * +grub_dma_phys2virt (grub_uint32_t phys, struct grub_pci_dma_chunk *chunk) +{ + return ((grub_uint8_t *) grub_dma_get_virt (chunk) + + (phys - grub_dma_get_phys (chunk))); +} + +static inline grub_uint32_t +grub_dma_virt2phys (volatile void *virt, struct grub_pci_dma_chunk *chunk) +{ + return (((grub_uint8_t *) virt - (grub_uint8_t *) grub_dma_get_virt (chunk)) + + grub_dma_get_phys (chunk)); +} + + #endif #endif /* GRUB_PCI_H */ diff --git a/include/grub/powerpc/ieee1275/biosdisk.h b/include/grub/powerpc/ieee1275/biosdisk.h deleted file mode 100644 index 30584d6b7..000000000 --- a/include/grub/powerpc/ieee1275/biosdisk.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2004,2007 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GRUB. If not, see . - */ - -#ifndef GRUB_BIOSDISK_MACHINE_HEADER -#define GRUB_BIOSDISK_MACHINE_HEADER 1 - -#define GRUB_BIOSDISK_FLAG_LBA 1 - -struct grub_biosdisk_data -{ - int drive; - unsigned long cylinders; - unsigned long heads; - unsigned long sectors; - unsigned long flags; -}; - -int grub_biosdisk_rw_int13_extensions (int ah, int drive, void *dap); -int grub_biosdisk_rw_standard (int ah, int drive, int coff, int hoff, - int soff, int nsec, int segment); -int grub_biosdisk_check_int13_extensions (int drive); -int grub_biosdisk_get_diskinfo_int13_extensions (int drive, void *drp); -int grub_biosdisk_get_diskinfo_standard (int drive, - unsigned long *cylinders, - unsigned long *heads, - unsigned long *sectors); -int grub_biosdisk_get_num_floppies (void); - -void grub_biosdisk_init (void); - -#endif /* ! GRUB_BIOSDISK_MACHINE_HEADER */ diff --git a/include/grub/priority_queue.h b/include/grub/priority_queue.h new file mode 100644 index 000000000..a5d98c8c9 --- /dev/null +++ b/include/grub/priority_queue.h @@ -0,0 +1,36 @@ +/* + * 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 . + */ + +#ifndef GRUB_PRIORITY_QUEUE_HEADER +#define GRUB_PRIORITY_QUEUE_HEADER 1 + +#include +#include + +struct grub_priority_queue; +typedef struct grub_priority_queue *grub_priority_queue_t; +typedef int (*grub_comparator_t) (const void *a, const void *b); + +grub_priority_queue_t grub_priority_queue_new (grub_size_t elsize, + grub_comparator_t cmp); +void grub_priority_queue_destroy (grub_priority_queue_t pq); +void *grub_priority_queue_top (grub_priority_queue_t pq); +void grub_priority_queue_pop (grub_priority_queue_t pq); +grub_err_t grub_priority_queue_push (grub_priority_queue_t pq, const void *el); + +#endif diff --git a/include/grub/raid.h b/include/grub/raid.h deleted file mode 100644 index 1eb43721a..000000000 --- a/include/grub/raid.h +++ /dev/null @@ -1,97 +0,0 @@ -/* raid.h - On disk structures for RAID. */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2006,2007,2008,2010 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GRUB. If not, see . - */ - -#ifndef GRUB_RAID_H -#define GRUB_RAID_H 1 - -#include - -#define GRUB_RAID_LAYOUT_LEFT_ASYMMETRIC 0 -#define GRUB_RAID_LAYOUT_RIGHT_ASYMMETRIC 1 -#define GRUB_RAID_LAYOUT_LEFT_SYMMETRIC 2 -#define GRUB_RAID_LAYOUT_RIGHT_SYMMETRIC 3 - -#define GRUB_RAID_LAYOUT_RIGHT_MASK 1 -#define GRUB_RAID_LAYOUT_SYMMETRIC_MASK 2 - -struct grub_raid_member -{ - grub_disk_t device; /* Array of total_devs devices. */ - grub_disk_addr_t start_sector; - /* Start of each device, in 512 byte sectors. */ -}; - -struct grub_raid_array -{ - int number; /* The device number, taken from md_minor so we - are consistent with the device name in - Linux. */ - int became_readable_at; - int level; /* RAID levels, only 0, 1 or 5 at the moment. */ - int layout; /* Layout for RAID 5/6. */ - unsigned int total_devs; /* Total number of devices in the array. */ - grub_size_t chunk_size; /* The size of a chunk, in 512 byte sectors. */ - grub_uint64_t disk_size; /* Size of an individual disk, in 512 byte - sectors. */ - unsigned int index; /* Index of current device. */ - int uuid_len; /* The length of uuid. */ - char *uuid; /* The UUID of the device. */ - - /* The following field is setup by the caller. */ - char *name; /* That will be "md". */ - unsigned int nr_devs; /* The number of devices we've found so far. */ - unsigned int allocated_devs; - struct grub_raid_member *members; - struct grub_raid_array *next; - -#ifdef GRUB_UTIL - struct grub_raid *driver; -#endif -}; - -struct grub_raid -{ - const char *name; - - grub_err_t (*detect) (grub_disk_t disk, struct grub_raid_array *array, - grub_disk_addr_t *start_sector); - - struct grub_raid *next; -}; -typedef struct grub_raid *grub_raid_t; - -void grub_raid_register (grub_raid_t raid); -void grub_raid_unregister (grub_raid_t raid); - -void grub_raid_block_xor (char *buf1, const char *buf2, int size); - -typedef grub_err_t (*grub_raid5_recover_func_t) (struct grub_raid_array *array, - int disknr, char *buf, - grub_disk_addr_t sector, - int size); - -typedef grub_err_t (*grub_raid6_recover_func_t) (struct grub_raid_array *array, - int disknr, int p, char *buf, - grub_disk_addr_t sector, - int size); - -extern grub_raid5_recover_func_t grub_raid5_recover_func; -extern grub_raid6_recover_func_t grub_raid6_recover_func; - -#endif /* ! GRUB_RAID_H */ diff --git a/include/grub/reader.h b/include/grub/reader.h index fd72a3252..cd92df8f2 100644 --- a/include/grub/reader.h +++ b/include/grub/reader.h @@ -24,6 +24,6 @@ typedef grub_err_t (*grub_reader_getline_t) (char **, int); -void grub_rescue_run (void); +void grub_rescue_run (void) __attribute__ ((noreturn)); #endif /* ! GRUB_READER_HEADER */ diff --git a/include/grub/scsi.h b/include/grub/scsi.h index dfee69c62..13300ca15 100644 --- a/include/grub/scsi.h +++ b/include/grub/scsi.h @@ -69,7 +69,7 @@ struct grub_scsi_dev /* Write SIZE bytes from BUF to the device SCSI after sending the command CMD of size CMDSIZE. */ grub_err_t (*write) (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, - grub_size_t size, char *buf); + grub_size_t size, const char *buf); /* The next scsi device. */ struct grub_scsi_dev *next; @@ -94,11 +94,11 @@ struct grub_scsi /* Set to 0 when not removable, 1 when removable. */ int removable; - /* Size of the device in blocks. */ - int size; + /* Size of the device in blocks - 1. */ + grub_uint64_t last_block; /* Size of one block. */ - int blocksize; + grub_uint32_t blocksize; /* Device-specific data. */ void *data; diff --git a/include/grub/scsicmd.h b/include/grub/scsicmd.h index 9cc5afe72..a3e79888a 100644 --- a/include/grub/scsicmd.h +++ b/include/grub/scsicmd.h @@ -85,7 +85,7 @@ struct grub_scsi_request_sense_data /* there can be additional sense field */ } __attribute__((packed)); -struct grub_scsi_read_capacity +struct grub_scsi_read_capacity10 { grub_uint8_t opcode; grub_uint8_t lun; /* 7-5 LUN, 4-1 reserved, 0 reserved */ @@ -97,12 +97,29 @@ struct grub_scsi_read_capacity grub_uint16_t pad; /* To be ATAPI compatible */ } __attribute__((packed)); -struct grub_scsi_read_capacity_data +struct grub_scsi_read_capacity10_data { - grub_uint32_t size; + grub_uint32_t last_block; grub_uint32_t blocksize; } __attribute__((packed)); +struct grub_scsi_read_capacity16 +{ + grub_uint8_t opcode; + grub_uint8_t lun; /* 7-5 LUN, 4-0 0x10 */ + grub_uint64_t logical_block_addr; /* only if PMI=1 */ + grub_uint32_t alloc_len; + grub_uint8_t PMI; + grub_uint8_t control; +} __attribute__((packed)); + +struct grub_scsi_read_capacity16_data +{ + grub_uint64_t last_block; + grub_uint32_t blocksize; + grub_uint8_t pad[20]; +} __attribute__((packed)); + struct grub_scsi_read10 { grub_uint8_t opcode; @@ -124,6 +141,16 @@ struct grub_scsi_read12 grub_uint8_t control; } __attribute__((packed)); +struct grub_scsi_read16 +{ + grub_uint8_t opcode; + grub_uint8_t lun; + grub_uint64_t lba; + grub_uint32_t size; + grub_uint8_t reserved; + grub_uint8_t control; +} __attribute__((packed)); + struct grub_scsi_write10 { grub_uint8_t opcode; @@ -145,14 +172,27 @@ struct grub_scsi_write12 grub_uint8_t control; } __attribute__((packed)); +struct grub_scsi_write16 +{ + grub_uint8_t opcode; + grub_uint8_t lun; + grub_uint64_t lba; + grub_uint32_t size; + grub_uint8_t reserved; + grub_uint8_t control; +} __attribute__((packed)); + typedef enum { grub_scsi_cmd_test_unit_ready = 0x00, grub_scsi_cmd_request_sense = 0x03, grub_scsi_cmd_inquiry = 0x12, - grub_scsi_cmd_read_capacity = 0x25, + grub_scsi_cmd_read_capacity10 = 0x25, grub_scsi_cmd_read10 = 0x28, grub_scsi_cmd_write10 = 0x2a, + grub_scsi_cmd_read16 = 0x88, + grub_scsi_cmd_write16 = 0x8a, + grub_scsi_cmd_read_capacity16 = 0x9e, grub_scsi_cmd_read12 = 0xa8, grub_scsi_cmd_write12 = 0xaa, } grub_scsi_cmd_t; diff --git a/include/grub/serial.h b/include/grub/serial.h index 49ac0623a..242823fab 100644 --- a/include/grub/serial.h +++ b/include/grub/serial.h @@ -63,6 +63,7 @@ struct grub_serial_config struct grub_serial_port { struct grub_serial_port *next; + struct grub_serial_port **prev; char *name; struct grub_serial_driver *driver; struct grub_serial_config config; @@ -143,7 +144,7 @@ grub_serial_config_defaults (struct grub_serial_port *port) void grub_ns8250_init (void); char *grub_serial_ns8250_add_port (grub_port_t port); -struct grub_serial_port *grub_serial_find (char *name); +struct grub_serial_port *grub_serial_find (const char *name); extern struct grub_serial_driver grub_ns8250_driver; void EXPORT_FUNC(grub_serial_unregister_driver) (struct grub_serial_driver *driver); diff --git a/include/grub/symbol.h b/include/grub/symbol.h index c6adb7ee3..ddbb9b53f 100644 --- a/include/grub/symbol.h +++ b/include/grub/symbol.h @@ -25,6 +25,7 @@ #define LOCAL(sym) L_ ## sym /* Add an underscore to a C symbol in assembler code if needed. */ +#ifndef GRUB_UTIL #if HAVE_ASM_USCORE # define EXT_C(sym) _ ## sym #else @@ -42,6 +43,7 @@ #define FUNCTION(x) .globl EXT_C(x) ; .def EXT_C(x); .scl 2; .type 32; .endef; EXT_C(x): #define VARIABLE(x) .globl EXT_C(x) ; .def EXT_C(x); .scl 2; .type 0; .endef; EXT_C(x): #endif +#endif /* Mark an exported symbol. */ #ifndef GRUB_SYMBOL_GENERATOR diff --git a/include/grub/term.h b/include/grub/term.h index 4c997cdaf..e73f8aa25 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -147,6 +147,7 @@ struct grub_term_input { /* The next terminal. */ struct grub_term_input *next; + struct grub_term_input **prev; /* The terminal name. */ const char *name; @@ -171,6 +172,7 @@ struct grub_term_output { /* The next terminal. */ struct grub_term_output *next; + struct grub_term_output **prev; /* The terminal name. */ const char *name; @@ -300,17 +302,15 @@ grub_term_register_output_active (const char *name __attribute__ ((unused)), static inline void grub_term_unregister_input (grub_term_input_t term) { - grub_list_remove (GRUB_AS_LIST_P (&grub_term_inputs), GRUB_AS_LIST (term)); - grub_list_remove (GRUB_AS_LIST_P (&grub_term_inputs_disabled), - GRUB_AS_LIST (term)); + grub_list_remove (GRUB_AS_LIST (term)); + grub_list_remove (GRUB_AS_LIST (term)); } static inline void grub_term_unregister_output (grub_term_output_t term) { - grub_list_remove (GRUB_AS_LIST_P (&grub_term_outputs), GRUB_AS_LIST (term)); - grub_list_remove (GRUB_AS_LIST_P (&(grub_term_outputs_disabled)), - GRUB_AS_LIST (term)); + grub_list_remove (GRUB_AS_LIST (term)); + grub_list_remove (GRUB_AS_LIST (term)); } #define FOR_ACTIVE_TERM_INPUTS(var) FOR_LIST_ELEMENTS((var), (grub_term_inputs)) @@ -320,7 +320,7 @@ grub_term_unregister_output (grub_term_output_t term) void grub_putcode (grub_uint32_t code, struct grub_term_output *term); int EXPORT_FUNC(grub_getkey) (void); -int EXPORT_FUNC(grub_checkkey) (void); +int EXPORT_FUNC(grub_getkey_noblock) (void); void grub_cls (void); void EXPORT_FUNC(grub_refresh) (void); void grub_puts_terminal (const char *str, struct grub_term_output *term); diff --git a/include/grub/test.h b/include/grub/test.h index 336d3b672..5d1ba7510 100644 --- a/include/grub/test.h +++ b/include/grub/test.h @@ -29,6 +29,7 @@ struct grub_test { /* The next test. */ struct grub_test *next; + struct grub_test **prev; /* The test name. */ char *name; @@ -58,6 +59,9 @@ void grub_test_nonzero (int cond, const char *file, ## __VA_ARGS__, \ "assert failed: %s", #cond) +void grub_unit_test_init (void); +void grub_unit_test_fini (void); + /* Macro to define a unit test. */ #define GRUB_UNIT_TEST(name, funp) \ void grub_unit_test_init (void) \ diff --git a/include/grub/tparm.h b/include/grub/tparm.h index 642a22f90..0c6f9e0f0 100644 --- a/include/grub/tparm.h +++ b/include/grub/tparm.h @@ -21,6 +21,6 @@ #define GRUB_TPARM_HEADER 1 /* Function prototypes. */ -char *grub_terminfo_tparm (const char *string, ...); +const char *grub_terminfo_tparm (const char *string, ...); #endif /* ! GRUB_TPARM_HEADER */ diff --git a/include/grub/types.h b/include/grub/types.h index f057dd3d3..94badaa1d 100644 --- a/include/grub/types.h +++ b/include/grub/types.h @@ -98,13 +98,15 @@ typedef grub_uint64_t grub_size_t; typedef grub_int64_t grub_ssize_t; # if GRUB_CPU_SIZEOF_LONG == 8 -# define PRIxGRUB_SIZE "lx" -# define PRIxGRUB_ADDR "lx" -# define PRIuGRUB_SIZE "lu" +# define PRIxGRUB_SIZE "lx" +# define PRIxGRUB_ADDR "lx" +# define PRIuGRUB_SIZE "lu" +# define PRIdGRUB_SSIZE "ld" # else -# define PRIxGRUB_SIZE "llx" -# define PRIxGRUB_ADDR "llx" -# define PRIuGRUB_SIZE "llu" +# define PRIxGRUB_SIZE "llx" +# define PRIxGRUB_ADDR "llx" +# define PRIuGRUB_SIZE "llu" +# define PRIdGRUB_SSIZE "lld" # endif #else typedef grub_uint32_t grub_addr_t; @@ -114,11 +116,14 @@ typedef grub_int32_t grub_ssize_t; # define PRIxGRUB_SIZE "x" # define PRIxGRUB_ADDR "x" # define PRIuGRUB_SIZE "u" +# define PRIdGRUB_SSIZE "d" #endif #define GRUB_UCHAR_MAX 0xFF #define GRUB_USHRT_MAX 65535 +#define GRUB_SHRT_MAX 0x7fff #define GRUB_UINT_MAX 4294967295U +#define GRUB_INT_MAX 0x7fffffff #if GRUB_CPU_SIZEOF_LONG == 8 # define GRUB_ULONG_MAX 18446744073709551615UL @@ -130,15 +135,9 @@ typedef grub_int32_t grub_ssize_t; # define GRUB_LONG_MIN (-2147483647L - 1) #endif -#if GRUB_CPU_SIZEOF_VOID_P == 4 -#define UINT_TO_PTR(x) ((void*)(grub_uint32_t)(x)) -#define PTR_TO_UINT64(x) ((grub_uint64_t)(grub_uint32_t)(x)) -#define PTR_TO_UINT32(x) ((grub_uint32_t)(x)) -#else -#define UINT_TO_PTR(x) ((void*)(grub_uint64_t)(x)) -#define PTR_TO_UINT64(x) ((grub_uint64_t)(x)) -#define PTR_TO_UINT32(x) ((grub_uint32_t)(grub_uint64_t)(x)) -#endif +typedef grub_uint64_t grub_properly_aligned_t; + +#define GRUB_PROPERLY_ALIGNED_ARRAY(name, size) grub_properly_aligned_t name[((size) + sizeof (grub_properly_aligned_t) - 1) / sizeof (grub_properly_aligned_t)] /* The type for representing a file offset. */ typedef grub_uint64_t grub_off_t; @@ -155,6 +154,18 @@ typedef grub_uint64_t grub_disk_addr_t; #define grub_swap_bytes16_compile_time(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8)) #define grub_swap_bytes32_compile_time(x) ((((x) & 0xff) << 24) | (((x) & 0xff00) << 8) | (((x) & 0xff0000) >> 8) | (((x) & 0xff000000UL) >> 24)) +#define grub_swap_bytes64_compile_time(x) \ +({ \ + grub_uint64_t _x = (x); \ + (grub_uint64_t) ((_x << 56) \ + | ((_x & (grub_uint64_t) 0xFF00ULL) << 40) \ + | ((_x & (grub_uint64_t) 0xFF0000ULL) << 24) \ + | ((_x & (grub_uint64_t) 0xFF000000ULL) << 8) \ + | ((_x & (grub_uint64_t) 0xFF00000000ULL) >> 8) \ + | ((_x & (grub_uint64_t) 0xFF0000000000ULL) >> 24) \ + | ((_x & (grub_uint64_t) 0xFF000000000000ULL) >> 40) \ + | (_x >> 56)); \ +}) #if defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3) static inline grub_uint32_t grub_swap_bytes32(grub_uint32_t x) @@ -203,6 +214,10 @@ static inline grub_uint64_t grub_swap_bytes64(grub_uint64_t x) # define grub_be_to_cpu16(x) ((grub_uint16_t) (x)) # define grub_be_to_cpu32(x) ((grub_uint32_t) (x)) # define grub_be_to_cpu64(x) ((grub_uint64_t) (x)) +# define grub_cpu_to_be16_compile_time(x) ((grub_uint16_t) (x)) +# define grub_cpu_to_be32_compile_time(x) ((grub_uint32_t) (x)) +# define grub_cpu_to_be64_compile_time(x) ((grub_uint64_t) (x)) +# define grub_be_to_cpu64_compile_time(x) ((grub_uint64_t) (x)) # define grub_cpu_to_le32_compile_time(x) grub_swap_bytes32_compile_time(x) # define grub_cpu_to_le16_compile_time(x) grub_swap_bytes16_compile_time(x) #else /* ! WORDS_BIGENDIAN */ @@ -218,35 +233,66 @@ static inline grub_uint64_t grub_swap_bytes64(grub_uint64_t x) # define grub_be_to_cpu16(x) grub_swap_bytes16(x) # define grub_be_to_cpu32(x) grub_swap_bytes32(x) # define grub_be_to_cpu64(x) grub_swap_bytes64(x) +# define grub_cpu_to_be16_compile_time(x) grub_swap_bytes16_compile_time(x) +# define grub_cpu_to_be32_compile_time(x) grub_swap_bytes32_compile_time(x) +# define grub_cpu_to_be64_compile_time(x) grub_swap_bytes64_compile_time(x) +# define grub_be_to_cpu64_compile_time(x) grub_swap_bytes64_compile_time(x) # define grub_cpu_to_le16_compile_time(x) ((grub_uint16_t) (x)) # define grub_cpu_to_le32_compile_time(x) ((grub_uint32_t) (x)) + #endif /* ! WORDS_BIGENDIAN */ -static inline grub_uint16_t grub_get_unaligned16(void *ptr) +static inline grub_uint16_t grub_get_unaligned16 (const void *ptr) { - struct - { - grub_uint16_t d; - } __attribute__((packed)) *dd = ptr; - return dd->d; + struct grub_unaligned_uint16_t + { + grub_uint16_t d; + } __attribute__ ((packed)); + const struct grub_unaligned_uint16_t *dd + = (const struct grub_unaligned_uint16_t *) ptr; + return dd->d; } -static inline grub_uint32_t grub_get_unaligned32(void *ptr) +static inline void grub_set_unaligned16 (void *ptr, grub_uint16_t val) { - struct - { - grub_uint32_t d; - } __attribute__((packed)) *dd = ptr; - return dd->d; + struct grub_unaligned_uint16_t + { + grub_uint16_t d; + } __attribute__ ((packed)); + struct grub_unaligned_uint16_t *dd = (struct grub_unaligned_uint16_t *) ptr; + dd->d = val; } -static inline grub_uint64_t grub_get_unaligned64(void *ptr) +static inline grub_uint32_t grub_get_unaligned32 (const void *ptr) { - struct - { - grub_uint64_t d; - } __attribute__((packed)) *dd = ptr; - return dd->d; + struct grub_unaligned_uint32_t + { + grub_uint32_t d; + } __attribute__ ((packed)); + const struct grub_unaligned_uint32_t *dd + = (const struct grub_unaligned_uint32_t *) ptr; + return dd->d; +} + +static inline void grub_set_unaligned32 (void *ptr, grub_uint32_t val) +{ + struct grub_unaligned_uint32_t + { + grub_uint32_t d; + } __attribute__ ((packed)); + struct grub_unaligned_uint32_t *dd = (struct grub_unaligned_uint32_t *) ptr; + dd->d = val; +} + +static inline grub_uint64_t grub_get_unaligned64 (const void *ptr) +{ + struct grub_unaligned_uint64_t + { + grub_uint64_t d; + } __attribute__ ((packed)); + const struct grub_unaligned_uint64_t *dd + = (const struct grub_unaligned_uint64_t *)ptr; + return dd->d; } #endif /* ! GRUB_TYPES_HEADER */ diff --git a/include/grub/unicode.h b/include/grub/unicode.h index 64769258a..24240a019 100644 --- a/include/grub/unicode.h +++ b/include/grub/unicode.h @@ -31,12 +31,12 @@ struct grub_unicode_bidi_pair struct grub_unicode_compact_range { - grub_uint32_t start:21; - grub_uint32_t end:21; - grub_uint8_t bidi_type:5; - grub_uint8_t comb_type; - grub_uint8_t bidi_mirror:1; - grub_uint8_t join_type:3; + unsigned start:21; + unsigned len:9; + unsigned bidi_type:5; + unsigned comb_type:8; + unsigned bidi_mirror:1; + unsigned join_type:3; } __attribute__ ((packed)); /* Old-style Arabic shaping. Used for "visual UTF-8" and @@ -206,8 +206,11 @@ enum GRUB_UNICODE_BLACK_LEFT_TRIANGLE = 0x25c4, GRUB_UNICODE_VARIATION_SELECTOR_1 = 0xfe00, GRUB_UNICODE_VARIATION_SELECTOR_16 = 0xfe0f, + GRUB_UNICODE_TAG_START = 0xe0000, + GRUB_UNICODE_TAG_END = 0xe007f, GRUB_UNICODE_VARIATION_SELECTOR_17 = 0xe0100, - GRUB_UNICODE_VARIATION_SELECTOR_256 = 0xe01ef + GRUB_UNICODE_VARIATION_SELECTOR_256 = 0xe01ef, + GRUB_UNICODE_LAST_VALID = 0x10ffff }; extern struct grub_unicode_compact_range grub_unicode_compact[]; diff --git a/include/grub/usb.h b/include/grub/usb.h index ee133dbf5..08d57b2be 100644 --- a/include/grub/usb.h +++ b/include/grub/usb.h @@ -198,6 +198,11 @@ struct grub_usb_device grub_uint32_t statuschange; struct grub_usb_desc_endp *hub_endpoint; + + /* EHCI Split Transfer information */ + int port; + + int hubaddr; }; @@ -246,7 +251,10 @@ typedef enum typedef enum { - GRUB_USBMS_PROTOCOL_BULK = 0x50 + GRUB_USBMS_PROTOCOL_BULK = 0x50, + /* Experimental support for Control/Bulk/Interrupt (CBI) devices */ + GRUB_USBMS_PROTOCOL_CBI = 0x00, /* CBI with interrupt */ + GRUB_USBMS_PROTOCOL_CB = 0x01 /* CBI wthout interrupt */ } grub_usbms_protocol_t; static inline struct grub_usb_desc_if * @@ -264,6 +272,7 @@ typedef int (*grub_usb_attach_hook_class) (grub_usb_device_t usbdev, struct grub_usb_attach_desc { struct grub_usb_attach_desc *next; + struct grub_usb_attach_desc **prev; int class; grub_usb_attach_hook_class hook; }; diff --git a/include/grub/util/deviceiter.h b/include/grub/util/deviceiter.h deleted file mode 100644 index a8af03cfe..000000000 --- a/include/grub/util/deviceiter.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef GRUB_DEVICEITER_MACHINE_UTIL_HEADER -#define GRUB_DEVICEITER_MACHINE_UTIL_HEADER 1 - -#include - -void grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int), - int floppy_disks); -void grub_util_emit_devicemap_entry (FILE *fp, char *name, int is_floppy, - int *num_fd, int *num_hd); - -#endif /* ! GRUB_DEVICEITER_MACHINE_UTIL_HEADER */ diff --git a/include/grub/util/misc.h b/include/grub/util/misc.h index 419c8661c..073493eed 100644 --- a/include/grub/util/misc.h +++ b/include/grub/util/misc.h @@ -31,14 +31,13 @@ #include char *grub_util_get_path (const char *dir, const char *file); -size_t grub_util_get_fp_size (FILE *fp); size_t grub_util_get_image_size (const char *path); -void grub_util_read_at (void *img, size_t len, off_t offset, FILE *fp); char *grub_util_read_image (const char *path); void grub_util_load_image (const char *path, char *buf); -void grub_util_write_image (const char *img, size_t size, FILE *out); +void grub_util_write_image (const char *img, size_t size, FILE *out, + const char *name); void grub_util_write_image_at (const void *img, size_t size, off_t offset, - FILE *out); + FILE *out, const char *name); #ifdef __MINGW32__ diff --git a/include/grub/video.h b/include/grub/video.h index 352544c85..b3709bceb 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -298,6 +298,7 @@ struct grub_video_adapter { /* The next video adapter. */ struct grub_video_adapter *next; + struct grub_video_adapter **prev; /* The video adapter name. */ const char *name; @@ -398,8 +399,7 @@ grub_video_register (grub_video_adapter_t adapter) static inline void grub_video_unregister (grub_video_adapter_t adapter) { - grub_list_remove (GRUB_AS_LIST_P (&grub_video_adapter_list), - GRUB_AS_LIST (adapter)); + grub_list_remove (GRUB_AS_LIST (adapter)); } #define FOR_VIDEO_ADAPTERS(var) FOR_LIST_ELEMENTS((var), (grub_video_adapter_list)) diff --git a/include/grub/x86_64/types.h b/include/grub/x86_64/types.h index bdee5a109..d53138ea3 100644 --- a/include/grub/x86_64/types.h +++ b/include/grub/x86_64/types.h @@ -28,4 +28,6 @@ /* x86_64 is little-endian. */ #undef GRUB_TARGET_WORDS_BIGENDIAN +#define GRUB_HAVE_UNALIGNED_ACCESS 1 + #endif /* ! GRUB_TYPES_CPU_HEADER */ diff --git a/include/grub/xnu.h b/include/grub/xnu.h index 076aeb5ed..2a096d803 100644 --- a/include/grub/xnu.h +++ b/include/grub/xnu.h @@ -81,7 +81,7 @@ struct grub_xnu_extheader } __attribute__ ((packed)); struct grub_xnu_devtree_key *grub_xnu_create_key (struct grub_xnu_devtree_key **parent, - char *name); + const char *name); extern struct grub_xnu_devtree_key *grub_xnu_devtree_root; @@ -89,18 +89,20 @@ void grub_xnu_free_devtree (struct grub_xnu_devtree_key *cur); grub_err_t grub_xnu_writetree_toheap (grub_addr_t *target, grub_size_t *size); struct grub_xnu_devtree_key *grub_xnu_create_value (struct grub_xnu_devtree_key **parent, - char *name); + const char *name); void grub_xnu_lock (void); void grub_xnu_unlock (void); grub_err_t grub_xnu_resume (char *imagename); grub_err_t grub_xnu_boot_resume (void); struct grub_xnu_devtree_key *grub_xnu_find_key (struct grub_xnu_devtree_key *parent, - char *name); + const char *name); grub_err_t grub_xnu_align_heap (int align); -grub_err_t grub_xnu_scan_dir_for_kexts (char *dirname, char *osbundlerequired, +grub_err_t grub_xnu_scan_dir_for_kexts (char *dirname, + const char *osbundlerequired, int maxrecursion); -grub_err_t grub_xnu_load_kext_from_dir (char *dirname, char *osbundlerequired, +grub_err_t grub_xnu_load_kext_from_dir (char *dirname, + const char *osbundlerequired, int maxrecursion); grub_err_t grub_xnu_heap_malloc (int size, void **src, grub_addr_t *target); grub_err_t grub_xnu_fill_devicetree (void); diff --git a/include/grub/zfs/dnode.h b/include/grub/zfs/dnode.h index 279c5451e..e4993df1e 100644 --- a/include/grub/zfs/dnode.h +++ b/include/grub/zfs/dnode.h @@ -29,12 +29,8 @@ * Fixed constants. */ #define DNODE_SHIFT 9 /* 512 bytes */ -#define DN_MIN_INDBLKSHIFT 10 /* 1k */ -#define DN_MAX_INDBLKSHIFT 14 /* 16k */ #define DNODE_BLOCK_SHIFT 14 /* 16k */ #define DNODE_CORE_SIZE 64 /* 64 bytes for dnode sans blkptrs */ -#define DN_MAX_OBJECT_SHIFT 48 /* 256 trillion (zfs_fid_t limit) */ -#define DN_MAX_OFFSET_SHIFT 64 /* 2^64 bytes in a dnode */ /* * Derived constants. @@ -42,11 +38,9 @@ #define DNODE_SIZE (1 << DNODE_SHIFT) #define DN_MAX_NBLKPTR ((DNODE_SIZE - DNODE_CORE_SIZE) >> SPA_BLKPTRSHIFT) #define DN_MAX_BONUSLEN (DNODE_SIZE - DNODE_CORE_SIZE - (1 << SPA_BLKPTRSHIFT)) -#define DN_MAX_OBJECT (1ULL << DN_MAX_OBJECT_SHIFT) #define DNODES_PER_BLOCK_SHIFT (DNODE_BLOCK_SHIFT - DNODE_SHIFT) #define DNODES_PER_BLOCK (1ULL << DNODES_PER_BLOCK_SHIFT) -#define DNODES_PER_LEVEL_SHIFT (DN_MAX_INDBLKSHIFT - SPA_BLKPTRSHIFT) #define DNODE_FLAG_SPILL_BLKPTR (1<<2) diff --git a/include/grub/zfs/spa.h b/include/grub/zfs/spa.h index 0e29fa44a..19a2b640a 100644 --- a/include/grub/zfs/spa.h +++ b/include/grub/zfs/spa.h @@ -66,17 +66,8 @@ #define BF64_SET_SB(x, low, len, shift, bias, val) \ BF64_SET(x, low, len, ((val) >> (shift)) - (bias)) -/* - * We currently support nine block sizes, from 512 bytes to 128K. - * We could go higher, but the benefits are near-zero and the cost - * of COWing a giant block to modify one byte would become excessive. - */ #define SPA_MINBLOCKSHIFT 9 -#define SPA_MAXBLOCKSHIFT 17 #define SPA_MINBLOCKSIZE (1ULL << SPA_MINBLOCKSHIFT) -#define SPA_MAXBLOCKSIZE (1ULL << SPA_MAXBLOCKSHIFT) - -#define SPA_BLOCKSIZES (SPA_MAXBLOCKSHIFT - SPA_MINBLOCKSHIFT + 1) /* * Size of block to hold the configuration data (a packed nvlist) diff --git a/include/grub/zfs/zap_impl.h b/include/grub/zfs/zap_impl.h index e42727ab6..0e985d9f9 100644 --- a/include/grub/zfs/zap_impl.h +++ b/include/grub/zfs/zap_impl.h @@ -28,8 +28,6 @@ #define ZAP_HASHBITS 28 #define MZAP_ENT_LEN 64 #define MZAP_NAME_LEN (MZAP_ENT_LEN - 8 - 4 - 2) -#define MZAP_MAX_BLKSHIFT SPA_MAXBLOCKSHIFT -#define MZAP_MAX_BLKSZ (1 << MZAP_MAX_BLKSHIFT) typedef struct mzap_ent_phys { grub_uint64_t mze_value; diff --git a/include/grub/zfs/zap_leaf.h b/include/grub/zfs/zap_leaf.h index 5adfdc290..f2b7cb1da 100644 --- a/include/grub/zfs/zap_leaf.h +++ b/include/grub/zfs/zap_leaf.h @@ -69,7 +69,8 @@ typedef struct zap_leaf_phys { * with the ZAP_LEAF_CHUNK() macro. */ - grub_uint16_t l_hash[1]; + grub_uint16_t l_hash[0]; + grub_properly_aligned_t l_entries[0]; } zap_leaf_phys_t; typedef union zap_leaf_chunk { diff --git a/include/grub/zfs/zio.h b/include/grub/zfs/zio.h index 8b645c063..b1c46da3a 100644 --- a/include/grub/zfs/zio.h +++ b/include/grub/zfs/zio.h @@ -30,7 +30,7 @@ typedef struct zio_eck { grub_uint64_t zec_magic; /* for validation, endianness */ zio_cksum_t zec_cksum; /* 256-bit checksum */ -} zio_eck_t; +} __attribute__ ((packed)) zio_eck_t; /* * Gang block headers are self-checksumming and contain an array diff --git a/include/grub/zfs/zio_checksum.h b/include/grub/zfs/zio_checksum.h index 0ef5a3ec7..e03c85a83 100644 --- a/include/grub/zfs/zio_checksum.h +++ b/include/grub/zfs/zio_checksum.h @@ -23,22 +23,6 @@ #ifndef _SYS_ZIO_CHECKSUM_H #define _SYS_ZIO_CHECKSUM_H -/* - * Signature for checksum functions. - */ -typedef void zio_checksum_t(const void *data, grub_uint64_t size, - grub_zfs_endian_t endian, zio_cksum_t *zcp); - -/* - * Information about each checksum function. - */ -typedef struct zio_checksum_info { - zio_checksum_t *ci_func; /* checksum function for each byteorder */ - int ci_correctable; /* number of correctable bits */ - int ci_eck; /* uses zio embedded checksum? */ - char *ci_name; /* descriptive name */ -} zio_checksum_info_t; - extern void zio_checksum_SHA256 (const void *, grub_uint64_t, grub_zfs_endian_t endian, zio_cksum_t *); extern void fletcher_2 (const void *, grub_uint64_t, grub_zfs_endian_t endian, diff --git a/po/Makefile.in.in b/po/Makefile.in.in index b0e7b8fa2..5a7c07c5b 100644 --- a/po/Makefile.in.in +++ b/po/Makefile.in.in @@ -165,7 +165,7 @@ $(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in $(srcdir)/POTFILES-shell --package-version='@VERSION@' \ --msgid-bugs-address="$$msgid_bugs_address" \ ;; \ - esac + esac; \ case `$(XGETTEXT) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \ '' | 0.[0-9] | 0.[0-9].* | 0.1[0-5] | 0.1[0-5].* | 0.16 | 0.16.[0-1]*) \ $(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \ @@ -187,7 +187,7 @@ $(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in $(srcdir)/POTFILES-shell --join-existing --language=Shell \ --keyword=gettext_quoted --keyword=gettext_printf \ ;; \ - esac + esac ; \ test ! -f $(DOMAIN).po || { \ sed -f grub.d.sed < $(DOMAIN).po > $(DOMAIN).1po && \ mv $(DOMAIN).1po $(DOMAIN).po; \ diff --git a/po/POTFILES-shell.in b/po/POTFILES-shell.in index 70c2a3fd4..46c589f03 100644 --- a/po/POTFILES-shell.in +++ b/po/POTFILES-shell.in @@ -1,7 +1,21 @@ -# List of files which contain translatable strings. Only files written in -# Shell language are included here. +util/grub.d/00_header.in util/grub.d/10_hurd.in +util/grub.d/10_illumos.in util/grub.d/10_kfreebsd.in util/grub.d/10_linux.in util/grub.d/10_netbsd.in +util/grub.d/10_windows.in util/grub.d/20_linux_xen.in +util/grub.d/30_os-prober.in +util/grub.d/40_custom.in +util/grub.d/41_custom.in +util/grub-install.in +util/grub-kbdcomp.in +util/grub-mkconfig.in +util/grub-mkconfig_lib.in +util/grub-mknetdir.in +util/grub-mkrescue.in +util/grub-mkstandalone.in +util/grub-reboot.in +util/grub-set-default.in +util/powerpc/ieee1275/grub-mkrescue.in diff --git a/po/POTFILES.in b/po/POTFILES.in index 1c718520b..c4d4b303e 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -5,6 +5,7 @@ ./grub-core/bus/cs5536.c ./grub-core/bus/emu/pci.c ./grub-core/bus/pci.c +./grub-core/bus/usb/ehci.c ./grub-core/bus/usb/emu/usb.c ./grub-core/bus/usb/ohci.c ./grub-core/bus/usb/serial/common.c @@ -19,6 +20,7 @@ ./grub-core/commands/arc/lsdev.c ./grub-core/commands/blocklist.c ./grub-core/commands/boot.c +./grub-core/commands/cacheinfo.c ./grub-core/commands/cat.c ./grub-core/commands/cmp.c ./grub-core/commands/configfile.c @@ -88,6 +90,7 @@ ./grub-core/disk/arc/arcdisk.c ./grub-core/disk/ata.c ./grub-core/disk/cryptodisk.c +./grub-core/disk/diskfilter.c ./grub-core/disk/dmraid_nvidia.c ./grub-core/disk/efi/efidisk.c ./grub-core/disk/geli.c @@ -95,6 +98,7 @@ ./grub-core/disk/i386/pc/biosdisk.c ./grub-core/disk/ieee1275/nand.c ./grub-core/disk/ieee1275/ofdisk.c +./grub-core/disk/ldm.c ./grub-core/disk/loopback.c ./grub-core/disk/luks.c ./grub-core/disk/lvm.c @@ -104,7 +108,6 @@ ./grub-core/disk/pata.c ./grub-core/disk/raid5_recover.c ./grub-core/disk/raid6_recover.c -./grub-core/disk/raid.c ./grub-core/disk/scsi.c ./grub-core/disk/usbms.c ./grub-core/efiemu/i386/coredetect.c @@ -127,8 +130,12 @@ ./grub-core/font/font.c ./grub-core/font/font_cmd.c ./grub-core/fs/affs.c +./grub-core/fs/afs.c +./grub-core/fs/bfs.c ./grub-core/fs/btrfs.c +./grub-core/fs/cpio_be.c ./grub-core/fs/cpio.c +./grub-core/fs/exfat.c ./grub-core/fs/ext2.c ./grub-core/fs/fat.c ./grub-core/fs/fshelp.c @@ -139,9 +146,11 @@ ./grub-core/fs/minix2.c ./grub-core/fs/minix3.c ./grub-core/fs/minix.c +./grub-core/fs/newc.c ./grub-core/fs/nilfs2.c ./grub-core/fs/ntfs.c ./grub-core/fs/ntfscomp.c +./grub-core/fs/odc.c ./grub-core/fs/reiserfs.c ./grub-core/fs/romfs.c ./grub-core/fs/sfs.c @@ -152,6 +161,7 @@ ./grub-core/fs/ufs.c ./grub-core/fs/xfs.c ./grub-core/fs/zfs/zfs.c +./grub-core/fs/zfs/zfscrypt.c ./grub-core/fs/zfs/zfs_fletcher.c ./grub-core/fs/zfs/zfsinfo.c ./grub-core/fs/zfs/zfs_lzjb.c @@ -231,6 +241,7 @@ ./grub-core/hook/datehook.c ./grub-core/io/bufio.c ./grub-core/io/gzio.c +./grub-core/io/lzopio.c ./grub-core/io/xzio.c ./grub-core/kern/command.c ./grub-core/kern/corecmd.c @@ -295,14 +306,17 @@ ./grub-core/kern/time.c ./grub-core/kern/vga_init.c ./grub-core/kern/x86_64/dl.c +./grub-core/lib/adler32.c ./grub-core/lib/arc/datetime.c ./grub-core/lib/arg.c ./grub-core/lib/cmdline.c ./grub-core/lib/cmos_datetime.c +./grub-core/lib/crc64.c ./grub-core/lib/crc.c ./grub-core/lib/crypto.c ./grub-core/lib/efi/datetime.c ./grub-core/lib/efi/halt.c +./grub-core/lib/efi/reboot.c ./grub-core/lib/efi/relocator.c ./grub-core/lib/emu/halt.c ./grub-core/lib/envblk.c @@ -310,10 +324,12 @@ ./grub-core/lib/i386/halt.c ./grub-core/lib/i386/pc/biosnum.c ./grub-core/lib/i386/pc/vesa_modes_table.c +./grub-core/lib/i386/reboot.c ./grub-core/lib/i386/relocator.c ./grub-core/lib/ieee1275/cmos.c ./grub-core/lib/ieee1275/datetime.c ./grub-core/lib/ieee1275/halt.c +./grub-core/lib/ieee1275/reboot.c ./grub-core/lib/ieee1275/relocator.c ./grub-core/lib/legacy_parse.c ./grub-core/lib/libgcrypt/cipher/ac.c @@ -376,9 +392,14 @@ ./grub-core/lib/LzFind.c ./grub-core/lib/LzmaDec.c ./grub-core/lib/LzmaEnc.c +./grub-core/lib/minilzo/minilzo.c +./grub-core/lib/mips/arc/reboot.c +./grub-core/lib/mips/loongson/reboot.c +./grub-core/lib/mips/qemu_mips/reboot.c ./grub-core/lib/mips/relocator.c ./grub-core/lib/pbkdf2.c ./grub-core/lib/powerpc/relocator.c +./grub-core/lib/priority_queue.c ./grub-core/lib/reed_solomon.c ./grub-core/lib/relocator.c ./grub-core/lib/xzembed/xz_dec_bcj.c @@ -399,6 +420,8 @@ ./grub-core/loader/i386/pc/freedos.c ./grub-core/loader/i386/pc/linux.c ./grub-core/loader/i386/pc/ntldr.c +./grub-core/loader/i386/pc/plan9.c +./grub-core/loader/i386/pc/pxechainloader.c ./grub-core/loader/i386/xnu.c ./grub-core/loader/ia64/efi/linux.c ./grub-core/loader/macho32.c @@ -421,14 +444,19 @@ ./grub-core/mmap/mmap.c ./grub-core/net/arp.c ./grub-core/net/bootp.c +./grub-core/net/dns.c ./grub-core/net/drivers/efi/efinet.c ./grub-core/net/drivers/emu/emunet.c ./grub-core/net/drivers/i386/pc/pxe.c ./grub-core/net/drivers/ieee1275/ofnet.c ./grub-core/net/ethernet.c +./grub-core/net/http.c +./grub-core/net/icmp6.c +./grub-core/net/icmp.c ./grub-core/net/ip.c ./grub-core/net/netbuff.c ./grub-core/net/net.c +./grub-core/net/tcp.c ./grub-core/net/tftp.c ./grub-core/net/udp.c ./grub-core/normal/auth.c @@ -454,6 +482,7 @@ ./grub-core/partmap/dvh.c ./grub-core/partmap/gpt.c ./grub-core/partmap/msdos.c +./grub-core/partmap/plan.c ./grub-core/partmap/sun.c ./grub-core/partmap/sunpc.c ./grub-core/parttool/msdospart.c @@ -470,7 +499,7 @@ ./grub-core/term/i386/pc/console.c ./grub-core/term/i386/pc/vga_text.c ./grub-core/term/i386/vga_common.c -./grub-core/term/ieee1275/ofconsole.c +./grub-core/term/ieee1275/console.c ./grub-core/term/ns8250.c ./grub-core/term/serial.c ./grub-core/term/terminfo.c @@ -496,6 +525,7 @@ ./grub-core/video/i386/pc/vbe.c ./grub-core/video/i386/pc/vga.c ./grub-core/video/ieee1275.c +./grub-core/video/radeon_fuloong2e.c ./grub-core/video/readers/jpeg.c ./grub-core/video/readers/png.c ./grub-core/video/readers/tga.c @@ -506,26 +536,26 @@ ./grub-core/video/video.c ./tests/example_unit_test.c ./tests/lib/unit_test.c +./tests/printf_unit_test.c +./util/argp_common.c ./util/bin2h.c -./util/deviceiter.c ./util/devicemap.c ./util/getroot.c ./util/grub-editenv.c ./util/grub-fstest.c ./util/grub-macho2img.c ./util/grub-menulst2cfg.c -./util/grub-mkdevicemap.c ./util/grub-mkfont.c ./util/grub-mkimage.c ./util/grub-mkimagexx.c ./util/grub-mklayout.c ./util/grub-mkpasswd-pbkdf2.c ./util/grub-mkrelpath.c +./util/grub-mount.c ./util/grub-pe2elf.c ./util/grub-probe.c ./util/grub-script-check.c ./util/grub-setup.c -./util/ieee1275/devicemap.c ./util/ieee1275/grub-ofpathname.c ./util/ieee1275/ofpath.c ./util/lvm.c diff --git a/tests/grub_script_echo1.in b/tests/grub_script_echo1.in index 9415a3f73..54395774f 100644 --- a/tests/grub_script_echo1.in +++ b/tests/grub_script_echo1.in @@ -99,3 +99,5 @@ echo one'two # # two" +if test x$grubshell = xyes; then insmod regexp; fi +echo /boot/grub/i386-pc/normal.mod diff --git a/tests/lib/unit_test.c b/tests/lib/unit_test.c index a780d6862..6adfd9922 100644 --- a/tests/lib/unit_test.c +++ b/tests/lib/unit_test.c @@ -30,9 +30,6 @@ main (int argc __attribute__ ((unused)), { int status = 0; - extern void grub_unit_test_init (void); - extern void grub_unit_test_fini (void); - grub_test_t test; grub_unit_test_init (); diff --git a/tests/util/grub-shell-tester.in b/tests/util/grub-shell-tester.in index 04d0ad5d9..80c883076 100644 --- a/tests/util/grub-shell-tester.in +++ b/tests/util/grub-shell-tester.in @@ -20,17 +20,16 @@ set -e # Initialize some variables. transform="@program_transform_name@" -prefix=@prefix@ -exec_prefix=@exec_prefix@ -bindir=@bindir@ -libdir=@libdir@ -builddir=@builddir@ +prefix="@prefix@" +exec_prefix="@exec_prefix@" +datarootdir="@datarootdir@" +builddir="@builddir@" PACKAGE_NAME=@PACKAGE_NAME@ PACKAGE_TARNAME=@PACKAGE_TARNAME@ PACKAGE_VERSION=@PACKAGE_VERSION@ # Force build directory components -PATH=${builddir}:$PATH +PATH="${builddir}:$PATH" export PATH # Usage: usage @@ -85,23 +84,23 @@ done if [ "x${source}" = x ] ; then tmpfile=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 while read REPLY; do - echo $REPLY >> ${tmpfile} + echo $REPLY >> "${tmpfile}" done - source=${tmpfile} + source="${tmpfile}" fi outfile1=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 -@builddir@/grub-shell --qemu-opts="${qemuopts}" --modules=${modules} ${source} >${outfile1} +"@builddir@/grub-shell" --qemu-opts="${qemuopts}" --modules=${modules} "${source}" >"${outfile1}" outfile2=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 -bash ${source} >${outfile2} +bash "${source}" >"${outfile2}" -if ! diff -q ${outfile1} ${outfile2} >/dev/null +if ! diff -q "${outfile1}" "${outfile2}" >/dev/null then echo "${source}: GRUB and BASH outputs did not match (see diff -u ${outfile1} ${outfile2})" status=1 else - rm -f ${outfile1} ${outfile2} + rm -f "${outfile1}" "${outfile2}" fi exit $status diff --git a/tests/util/grub-shell.in b/tests/util/grub-shell.in index 77853217f..abb3bff1f 100644 --- a/tests/util/grub-shell.in +++ b/tests/util/grub-shell.in @@ -20,11 +20,10 @@ set -e # Initialize some variables. transform="@program_transform_name@" -prefix=@prefix@ -exec_prefix=@exec_prefix@ -bindir=@bindir@ -libdir=@libdir@ -builddir=@builddir@ +prefix="@prefix@" +exec_prefix="@exec_prefix@" +datarootdir="@datarootdir@" +builddir="@builddir@" PACKAGE_NAME=@PACKAGE_NAME@ PACKAGE_TARNAME=@PACKAGE_TARNAME@ PACKAGE_VERSION=@PACKAGE_VERSION@ @@ -32,7 +31,7 @@ target_cpu=@target_cpu@ platform=@platform@ # Force build directory components -PATH=${builddir}:$PATH +PATH="${builddir}:$PATH" export PATH # Usage: usage @@ -141,9 +140,9 @@ EOF isofile=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 if [ x$boot != xnet ]; then - sh @builddir@/grub-mkrescue --grub-mkimage=${builddir}/grub-mkimage --output=${isofile} --override-directory=${builddir}/grub-core \ + sh "@builddir@/grub-mkrescue" "--grub-mkimage=${builddir}/grub-mkimage" "--output=${isofile}" "--override-directory=${builddir}/grub-core" \ --rom-directory="${rom_directory}" \ - /boot/grub/grub.cfg=${cfgfile} /boot/grub/testcase.cfg=${source} \ + "/boot/grub/grub.cfg=${cfgfile}" "/boot/grub/testcase.cfg=${source}" \ ${files} >/dev/null 2>&1 fi if [ x$boot = xhd ]; then @@ -174,12 +173,12 @@ fi if [ x$boot = xnet ]; then netdir=`mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 - sh @builddir@/grub-mknetdir --grub-mkimage=${builddir}/grub-mkimage --override-directory=${builddir}/grub-core --net-directory=$netdir - cp ${cfgfile} $netdir/boot/grub/grub.cfg - cp ${source} $netdir/boot/grub/testcase.cfg - ${qemu} ${qemuopts} -nographic -serial file:/dev/stdout -monitor file:/dev/null -boot n -net user,tftp=$netdir,bootfile=/boot/grub/$target_cpu-$platform/core.0 -net nic | cat | tr -d "\r" + sh "@builddir@/grub-mknetdir" "--grub-mkimage=${builddir}/grub-mkimage" "--override-directory=${builddir}/grub-core" "--net-directory=$netdir" + cp "${cfgfile}" "$netdir/boot/grub/grub.cfg" + cp "${source}" "$netdir/boot/grub/testcase.cfg" + "${qemu}" ${qemuopts} -nographic -serial file:/dev/stdout -monitor file:/dev/null -boot n -net "user,tftp=$netdir,bootfile=/boot/grub/$target_cpu-$platform/core.0" -net nic | cat | tr -d "\r" else - ${qemu} ${qemuopts} -nographic -serial file:/dev/stdout -monitor file:/dev/null -${device} ${isofile} ${bootdev} | cat | tr -d "\r" + "${qemu}" ${qemuopts} -nographic -serial file:/dev/stdout -monitor file:/dev/null -${device} ${isofile} ${bootdev} | cat | tr -d "\r" fi rm -f "${isofile}" "${imgfile}" rm -rf "${rom_directory}" diff --git a/unicode/ArabicShaping.txt b/unicode/ArabicShaping.txt index b851d3839..bab6a11f9 100644 --- a/unicode/ArabicShaping.txt +++ b/unicode/ArabicShaping.txt @@ -1,18 +1,18 @@ -# ArabicShaping-5.2.0.txt -# Date: 2009-08-17, 11:11:00 PDT [KW] +# ArabicShaping-6.0.0.txt +# Date: 2010-04-30, 13:47:00 PDT [KW] # # This file is a normative contributory data file in the # Unicode Character Database. # -# Copyright (c) 1991-2009 Unicode, Inc. +# Copyright (c) 1991-2010 Unicode, Inc. # For terms of use, see http://www.unicode.org/terms_of_use.html # # This file defines the shaping classes for Arabic, Syriac, and N'Ko # positional shaping, repeating in machine readable form the # information exemplified in Tables 8-3, 8-7, 8-8, 8-11, 8-12, -# 8-13, and 13-5 of The Unicode Standard, Version 5.2. +# 8-13, and 13-5 of The Unicode Standard, Version 6.0. # -# See sections 8.2, 8.3, and 13.5 of The Unicode Standard, Version 5.2 +# See sections 8.2, 8.3, and 13.5 of The Unicode Standard, Version 6.0 # for more information. # # Each line contains four fields, separated by a semicolon. @@ -22,6 +22,8 @@ # # Field 1: gives a short schematic name for that character, # abbreviated from the normative Unicode character name. +# Note that this schematic name is considered a comment, +# and does not constitute a formal property value. # # Field 2: defines the joining type (property name: Joining_Type) # R Right_Joining @@ -44,8 +46,8 @@ # # corresponds to [Joining_Group = Teh_Marbuta]. # -# Note: For historical reasons, the property value [Joining_Group = Hamza_On_Heh_Goal] -# is anachronistically named. It used to apply to both of the following characters +# Note: The property value now designated [Joining_Group = Teh_Marbuta_Goal] +# used to apply to both of the following characters # in earlier versions of the standard: # # U+06C2 ARABIC LETTER HEH GOAL WITH HAMZA ABOVE @@ -53,8 +55,10 @@ # # However, it currently applies only to U+06C3, and *not* to U+06C2. # To avoid destabilizing existing Joining_Group property aliases, the -# value Hamza_On_Heh_Goal has not been changed, despite the fact that it -# no longer applies to Hamza On Heh Goal, but only to Teh Marbuta Goal. +# prior Joining_Group value for U+06C3 (Hamza_On_Heh_Goal) has been +# retained as a property value alias, despite the fact that it +# no longer applies to its namesake character, U+06C2. +# See PropertyValueAliases.txt. # # When other cursive scripts are added to the Unicode Standard in # the future, the joining group value of all its letters will default @@ -88,6 +92,7 @@ 0603; ARABIC SIGN SAFHA; U; No_Joining_Group 0608; ARABIC RAY; U; No_Joining_Group 060B; AFGHANI SIGN; U; No_Joining_Group +0620; YEH WITH RING; D; YEH 0621; HAMZA; U; No_Joining_Group 0622; MADDA ON ALEF; R; ALEF 0623; HAMZA ON ALEF; R; ALEF @@ -214,7 +219,7 @@ 06C0; HAMZA ON HEH; R; TEH MARBUTA 06C1; HEH GOAL; D; HEH GOAL 06C2; HAMZA ON HEH GOAL; D; HEH GOAL -06C3; TEH MARBUTA GOAL; R; HAMZA ON HEH GOAL +06C3; TEH MARBUTA GOAL; R; TEH MARBUTA GOAL 06C4; WAW WITH RING; R; WAW 06C5; WAW WITH BAR; R; WAW 06C6; WAW WITH SMALL V; R; WAW diff --git a/unicode/BidiMirroring.txt b/unicode/BidiMirroring.txt index 81e838a7e..902f9a6b8 100644 --- a/unicode/BidiMirroring.txt +++ b/unicode/BidiMirroring.txt @@ -1,18 +1,19 @@ -# BidiMirroring-5.2.0.txt -# Date: 2009-05-22, 12:44:00 PDT [KW] +# BidiMirroring-6.0.0.txt +# Date: 2010-06-21, 12:09:00 PDT [KW] # # Bidi_Mirroring_Glyph Property # # This file is an informative contributory data file in the # Unicode Character Database. # -# Copyright (c) 1991-2009 Unicode, Inc. +# Copyright (c) 1991-2010 Unicode, Inc. # For terms of use, see http://www.unicode.org/terms_of_use.html # -# This data file lists characters that have the mirrored property -# where there is another Unicode character that typically has a glyph +# This data file lists characters that have the Bidi_Mirrored=True property +# value, for which there is another Unicode character that typically has a glyph # that is the mirror image of the original character's glyph. -# The repertoire covered by the file is Unicode 5.2.0. +# +# The repertoire covered by the file is Unicode 6.0.0. # # The file contains a list of lines with mappings from one code point # to another one for character-based mirroring. @@ -25,14 +26,22 @@ # variable-length hexadecimal value with 4 to 6 digits. # A comment indicates where the characters are "BEST FIT" mirroring. # -# Code points with the "mirrored" property but no appropriate mirrors are +# Code points for which Bidi_Mirrored=True, but for which no appropriate +# characters exist with mirrored glyphs, are # listed as comments at the end of the file. +# +# Formally, the default value of the Bidi_Mirroring_Glyph property +# for each code point is the code point itself, unless a mapping to +# some other character is specified in this data file. When a code +# point has the default value for the Bidi_Mirroring_Glyph property, +# that means that no other character exists whose glyph is suitable +# for character-based mirroring. # # For information on bidi mirroring, see UAX #9: Bidirectional Algorithm, # at http://www.unicode.org/unicode/reports/tr9/ # # This file was originally created by Markus Scherer. -# Extended for Unicode 3.2, 4.0, 4.1, 5.0, 5.1, and 5.2 by Ken Whistler. +# Extended for Unicode 3.2, 4.0, 4.1, 5.0, 5.1, 5.2, and 6.0 by Ken Whistler. # # ############################################################ @@ -464,8 +473,8 @@ FF63; FF62 # [BEST FIT] HALFWIDTH RIGHT CORNER BRACKET # 22FF; Z NOTATION BAG MEMBERSHIP # 2320; TOP HALF INTEGRAL # 2321; BOTTOM HALF INTEGRAL -# 27CC; LONG DIVISION # 27C0; THREE DIMENSIONAL ANGLE +# 27CC; LONG DIVISION # 27D3; LOWER RIGHT CORNER WITH DOT # 27D4; UPPER LEFT CORNER WITH DOT # 27DC; LEFT MULTIMAP diff --git a/unicode/COPYING b/unicode/COPYING index f81c87a27..ad63a2bbc 100644 --- a/unicode/COPYING +++ b/unicode/COPYING @@ -1,6 +1,6 @@ COPYRIGHT AND PERMISSION NOTICE -Copyright © 1991-2009 Unicode, Inc. All rights reserved. Distributed under the Terms of Use in http://www.unicode.org/copyright.html. +Copyright © 1991-2011 Unicode, Inc. All rights reserved. Distributed under the Terms of Use in http://www.unicode.org/copyright.html. Permission is hereby granted, free of charge, to any person obtaining a copy of the Unicode data files and any associated documentation (the "Data Files") or Unicode software and any associated documentation (the "Software") to deal in the Data Files or Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, and/or sell copies of the Data Files or Software, and to permit persons to whom the Data Files or Software are furnished to do so, provided that (a) the above copyright notice(s) and this permission notice appear with all copies of the Data Files or Software, (b) both the above copyright notice(s) and this permission notice appear in associated documentation, and (c) there is clear notice in each modified Data File or in the Software as well as in the documentation associated with the Data File(s) or Software that the data or software has been modified. diff --git a/unicode/UnicodeData.txt b/unicode/UnicodeData.txt index 6b01d90a7..8d7222b13 100644 --- a/unicode/UnicodeData.txt +++ b/unicode/UnicodeData.txt @@ -611,7 +611,7 @@ 0262;LATIN LETTER SMALL CAPITAL G;Ll;0;L;;;;;N;;;;; 0263;LATIN SMALL LETTER GAMMA;Ll;0;L;;;;;N;;;0194;;0194 0264;LATIN SMALL LETTER RAMS HORN;Ll;0;L;;;;;N;LATIN SMALL LETTER BABY GAMMA;;;; -0265;LATIN SMALL LETTER TURNED H;Ll;0;L;;;;;N;;;;; +0265;LATIN SMALL LETTER TURNED H;Ll;0;L;;;;;N;;;A78D;;A78D 0266;LATIN SMALL LETTER H WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER H HOOK;;;; 0267;LATIN SMALL LETTER HENG WITH HOOK;Ll;0;L;;;;;N;LATIN SMALL LETTER HENG HOOK;;;; 0268;LATIN SMALL LETTER I WITH STROKE;Ll;0;L;;;;;N;LATIN SMALL LETTER BARRED I;;0197;;0197 @@ -1306,6 +1306,8 @@ 0523;CYRILLIC SMALL LETTER EN WITH MIDDLE HOOK;Ll;0;L;;;;;N;;;0522;;0522 0524;CYRILLIC CAPITAL LETTER PE WITH DESCENDER;Lu;0;L;;;;;N;;;;0525; 0525;CYRILLIC SMALL LETTER PE WITH DESCENDER;Ll;0;L;;;;;N;;;0524;;0524 +0526;CYRILLIC CAPITAL LETTER SHHA WITH DESCENDER;Lu;0;L;;;;;N;;;;0527; +0527;CYRILLIC SMALL LETTER SHHA WITH DESCENDER;Ll;0;L;;;;;N;;;0526;;0526 0531;ARMENIAN CAPITAL LETTER AYB;Lu;0;L;;;;;N;;;;0561; 0532;ARMENIAN CAPITAL LETTER BEN;Lu;0;L;;;;;N;;;;0562; 0533;ARMENIAN CAPITAL LETTER GIM;Lu;0;L;;;;;N;;;;0563; @@ -1507,6 +1509,7 @@ 061B;ARABIC SEMICOLON;Po;0;AL;;;;;N;;;;; 061E;ARABIC TRIPLE DOT PUNCTUATION MARK;Po;0;AL;;;;;N;;;;; 061F;ARABIC QUESTION MARK;Po;0;AL;;;;;N;;;;; +0620;ARABIC LETTER KASHMIRI YEH;Lo;0;AL;;;;;N;;;;; 0621;ARABIC LETTER HAMZA;Lo;0;AL;;;;;N;ARABIC LETTER HAMZAH;;;; 0622;ARABIC LETTER ALEF WITH MADDA ABOVE;Lo;0;AL;0627 0653;;;;N;ARABIC LETTER MADDAH ON ALEF;;;; 0623;ARABIC LETTER ALEF WITH HAMZA ABOVE;Lo;0;AL;0627 0654;;;;N;ARABIC LETTER HAMZAH ON ALEF;;;; @@ -1569,6 +1572,7 @@ 065C;ARABIC VOWEL SIGN DOT BELOW;Mn;220;NSM;;;;;N;;;;; 065D;ARABIC REVERSED DAMMA;Mn;230;NSM;;;;;N;;;;; 065E;ARABIC FATHA WITH TWO DOTS;Mn;230;NSM;;;;;N;;;;; +065F;ARABIC WAVY HAMZA BELOW;Mn;220;NSM;;;;;N;;;;; 0660;ARABIC-INDIC DIGIT ZERO;Nd;0;AN;;0;0;0;N;;;;; 0661;ARABIC-INDIC DIGIT ONE;Nd;0;AN;;1;1;1;N;;;;; 0662;ARABIC-INDIC DIGIT TWO;Nd;0;AN;;2;2;2;N;;;;; @@ -1695,7 +1699,7 @@ 06DB;ARABIC SMALL HIGH THREE DOTS;Mn;230;NSM;;;;;N;;;;; 06DC;ARABIC SMALL HIGH SEEN;Mn;230;NSM;;;;;N;;;;; 06DD;ARABIC END OF AYAH;Cf;0;AN;;;;;N;;;;; -06DE;ARABIC START OF RUB EL HIZB;Me;0;NSM;;;;;N;;;;; +06DE;ARABIC START OF RUB EL HIZB;So;0;ON;;;;;N;;;;; 06DF;ARABIC SMALL HIGH ROUNDED ZERO;Mn;230;NSM;;;;;N;;;;; 06E0;ARABIC SMALL HIGH UPRIGHT RECTANGULAR ZERO;Mn;230;NSM;;;;;N;;;;; 06E1;ARABIC SMALL HIGH DOTLESS HEAD OF KHAH;Mn;230;NSM;;;;;N;;;;; @@ -1743,7 +1747,7 @@ 070B;SYRIAC HARKLEAN OBELUS;Po;0;AL;;;;;N;;;;; 070C;SYRIAC HARKLEAN METOBELUS;Po;0;AL;;;;;N;;;;; 070D;SYRIAC HARKLEAN ASTERISCUS;Po;0;AL;;;;;N;;;;; -070F;SYRIAC ABBREVIATION MARK;Cf;0;BN;;;;;N;;;;; +070F;SYRIAC ABBREVIATION MARK;Cf;0;AN;;;;;N;;;;; 0710;SYRIAC LETTER ALAPH;Lo;0;AL;;;;;N;;;;; 0711;SYRIAC LETTER SUPERSCRIPT ALAPH;Mn;36;NSM;;;;;N;;;;; 0712;SYRIAC LETTER BETH;Lo;0;AL;;;;;N;;;;; @@ -2024,6 +2028,35 @@ 083C;SAMARITAN PUNCTUATION ARKAANU;Po;0;R;;;;;N;;;;; 083D;SAMARITAN PUNCTUATION SOF MASHFAAT;Po;0;R;;;;;N;;;;; 083E;SAMARITAN PUNCTUATION ANNAAU;Po;0;R;;;;;N;;;;; +0840;MANDAIC LETTER HALQA;Lo;0;R;;;;;N;;;;; +0841;MANDAIC LETTER AB;Lo;0;R;;;;;N;;;;; +0842;MANDAIC LETTER AG;Lo;0;R;;;;;N;;;;; +0843;MANDAIC LETTER AD;Lo;0;R;;;;;N;;;;; +0844;MANDAIC LETTER AH;Lo;0;R;;;;;N;;;;; +0845;MANDAIC LETTER USHENNA;Lo;0;R;;;;;N;;;;; +0846;MANDAIC LETTER AZ;Lo;0;R;;;;;N;;;;; +0847;MANDAIC LETTER IT;Lo;0;R;;;;;N;;;;; +0848;MANDAIC LETTER ATT;Lo;0;R;;;;;N;;;;; +0849;MANDAIC LETTER AKSA;Lo;0;R;;;;;N;;;;; +084A;MANDAIC LETTER AK;Lo;0;R;;;;;N;;;;; +084B;MANDAIC LETTER AL;Lo;0;R;;;;;N;;;;; +084C;MANDAIC LETTER AM;Lo;0;R;;;;;N;;;;; +084D;MANDAIC LETTER AN;Lo;0;R;;;;;N;;;;; +084E;MANDAIC LETTER AS;Lo;0;R;;;;;N;;;;; +084F;MANDAIC LETTER IN;Lo;0;R;;;;;N;;;;; +0850;MANDAIC LETTER AP;Lo;0;R;;;;;N;;;;; +0851;MANDAIC LETTER ASZ;Lo;0;R;;;;;N;;;;; +0852;MANDAIC LETTER AQ;Lo;0;R;;;;;N;;;;; +0853;MANDAIC LETTER AR;Lo;0;R;;;;;N;;;;; +0854;MANDAIC LETTER ASH;Lo;0;R;;;;;N;;;;; +0855;MANDAIC LETTER AT;Lo;0;R;;;;;N;;;;; +0856;MANDAIC LETTER DUSHENNA;Lo;0;R;;;;;N;;;;; +0857;MANDAIC LETTER KAD;Lo;0;R;;;;;N;;;;; +0858;MANDAIC LETTER AIN;Lo;0;R;;;;;N;;;;; +0859;MANDAIC AFFRICATION MARK;Mn;220;NSM;;;;;N;;;;; +085A;MANDAIC VOCALIZATION MARK;Mn;220;NSM;;;;;N;;;;; +085B;MANDAIC GEMINATION MARK;Mn;220;NSM;;;;;N;;;;; +085E;MANDAIC PUNCTUATION;Po;0;R;;;;;N;;;;; 0900;DEVANAGARI SIGN INVERTED CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0901;DEVANAGARI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 0902;DEVANAGARI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; @@ -2082,6 +2115,8 @@ 0937;DEVANAGARI LETTER SSA;Lo;0;L;;;;;N;;;;; 0938;DEVANAGARI LETTER SA;Lo;0;L;;;;;N;;;;; 0939;DEVANAGARI LETTER HA;Lo;0;L;;;;;N;;;;; +093A;DEVANAGARI VOWEL SIGN OE;Mn;0;NSM;;;;;N;;;;; +093B;DEVANAGARI VOWEL SIGN OOE;Mc;0;L;;;;;N;;;;; 093C;DEVANAGARI SIGN NUKTA;Mn;7;NSM;;;;;N;;;;; 093D;DEVANAGARI SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 093E;DEVANAGARI VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; @@ -2101,12 +2136,15 @@ 094C;DEVANAGARI VOWEL SIGN AU;Mc;0;L;;;;;N;;;;; 094D;DEVANAGARI SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; 094E;DEVANAGARI VOWEL SIGN PRISHTHAMATRA E;Mc;0;L;;;;;N;;;;; +094F;DEVANAGARI VOWEL SIGN AW;Mc;0;L;;;;;N;;;;; 0950;DEVANAGARI OM;Lo;0;L;;;;;N;;;;; 0951;DEVANAGARI STRESS SIGN UDATTA;Mn;230;NSM;;;;;N;;;;; 0952;DEVANAGARI STRESS SIGN ANUDATTA;Mn;220;NSM;;;;;N;;;;; 0953;DEVANAGARI GRAVE ACCENT;Mn;230;NSM;;;;;N;;;;; 0954;DEVANAGARI ACUTE ACCENT;Mn;230;NSM;;;;;N;;;;; 0955;DEVANAGARI VOWEL SIGN CANDRA LONG E;Mn;0;NSM;;;;;N;;;;; +0956;DEVANAGARI VOWEL SIGN UE;Mn;0;NSM;;;;;N;;;;; +0957;DEVANAGARI VOWEL SIGN UUE;Mn;0;NSM;;;;;N;;;;; 0958;DEVANAGARI LETTER QA;Lo;0;L;0915 093C;;;;N;;;;; 0959;DEVANAGARI LETTER KHHA;Lo;0;L;0916 093C;;;;N;;;;; 095A;DEVANAGARI LETTER GHHA;Lo;0;L;0917 093C;;;;N;;;;; @@ -2134,6 +2172,11 @@ 0970;DEVANAGARI ABBREVIATION SIGN;Po;0;L;;;;;N;;;;; 0971;DEVANAGARI SIGN HIGH SPACING DOT;Lm;0;L;;;;;N;;;;; 0972;DEVANAGARI LETTER CANDRA A;Lo;0;L;;;;;N;;;;; +0973;DEVANAGARI LETTER OE;Lo;0;L;;;;;N;;;;; +0974;DEVANAGARI LETTER OOE;Lo;0;L;;;;;N;;;;; +0975;DEVANAGARI LETTER AW;Lo;0;L;;;;;N;;;;; +0976;DEVANAGARI LETTER UE;Lo;0;L;;;;;N;;;;; +0977;DEVANAGARI LETTER UUE;Lo;0;L;;;;;N;;;;; 0979;DEVANAGARI LETTER ZHA;Lo;0;L;;;;;N;;;;; 097A;DEVANAGARI LETTER HEAVY YA;Lo;0;L;;;;;N;;;;; 097B;DEVANAGARI LETTER GGA;Lo;0;L;;;;;N;;;;; @@ -2479,6 +2522,12 @@ 0B6F;ORIYA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 0B70;ORIYA ISSHAR;So;0;L;;;;;N;;;;; 0B71;ORIYA LETTER WA;Lo;0;L;;;;;N;;;;; +0B72;ORIYA FRACTION ONE QUARTER;No;0;L;;;;1/4;N;;;;; +0B73;ORIYA FRACTION ONE HALF;No;0;L;;;;1/2;N;;;;; +0B74;ORIYA FRACTION THREE QUARTERS;No;0;L;;;;3/4;N;;;;; +0B75;ORIYA FRACTION ONE SIXTEENTH;No;0;L;;;;1/16;N;;;;; +0B76;ORIYA FRACTION ONE EIGHTH;No;0;L;;;;1/8;N;;;;; +0B77;ORIYA FRACTION THREE SIXTEENTHS;No;0;L;;;;3/16;N;;;;; 0B82;TAMIL SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 0B83;TAMIL SIGN VISARGA;Lo;0;L;;;;;N;;;;; 0B85;TAMIL LETTER A;Lo;0;L;;;;;N;;;;; @@ -2728,8 +2777,8 @@ 0CED;KANNADA DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 0CEE;KANNADA DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 0CEF;KANNADA DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; -0CF1;KANNADA SIGN JIHVAMULIYA;So;0;ON;;;;;N;;;;; -0CF2;KANNADA SIGN UPADHMANIYA;So;0;ON;;;;;N;;;;; +0CF1;KANNADA SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;; +0CF2;KANNADA SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;; 0D02;MALAYALAM SIGN ANUSVARA;Mc;0;L;;;;;N;;;;; 0D03;MALAYALAM SIGN VISARGA;Mc;0;L;;;;;N;;;;; 0D05;MALAYALAM LETTER A;Lo;0;L;;;;;N;;;;; @@ -2766,6 +2815,7 @@ 0D26;MALAYALAM LETTER DA;Lo;0;L;;;;;N;;;;; 0D27;MALAYALAM LETTER DHA;Lo;0;L;;;;;N;;;;; 0D28;MALAYALAM LETTER NA;Lo;0;L;;;;;N;;;;; +0D29;MALAYALAM LETTER NNNA;Lo;0;L;;;;;N;;;;; 0D2A;MALAYALAM LETTER PA;Lo;0;L;;;;;N;;;;; 0D2B;MALAYALAM LETTER PHA;Lo;0;L;;;;;N;;;;; 0D2C;MALAYALAM LETTER BA;Lo;0;L;;;;;N;;;;; @@ -2782,6 +2832,7 @@ 0D37;MALAYALAM LETTER SSA;Lo;0;L;;;;;N;;;;; 0D38;MALAYALAM LETTER SA;Lo;0;L;;;;;N;;;;; 0D39;MALAYALAM LETTER HA;Lo;0;L;;;;;N;;;;; +0D3A;MALAYALAM LETTER TTTA;Lo;0;L;;;;;N;;;;; 0D3D;MALAYALAM SIGN AVAGRAHA;Lo;0;L;;;;;N;;;;; 0D3E;MALAYALAM VOWEL SIGN AA;Mc;0;L;;;;;N;;;;; 0D3F;MALAYALAM VOWEL SIGN I;Mc;0;L;;;;;N;;;;; @@ -2797,6 +2848,7 @@ 0D4B;MALAYALAM VOWEL SIGN OO;Mc;0;L;0D47 0D3E;;;;N;;;;; 0D4C;MALAYALAM VOWEL SIGN AU;Mc;0;L;0D46 0D57;;;;N;;;;; 0D4D;MALAYALAM SIGN VIRAMA;Mn;9;NSM;;;;;N;;;;; +0D4E;MALAYALAM LETTER DOT REPH;Lo;0;L;;;;;N;;;;; 0D57;MALAYALAM AU LENGTH MARK;Mc;0;L;;;;;N;;;;; 0D60;MALAYALAM LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; 0D61;MALAYALAM LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; @@ -3192,6 +3244,10 @@ 0F89;TIBETAN SIGN MCHU CAN;Lo;0;L;;;;;N;;;;; 0F8A;TIBETAN SIGN GRU CAN RGYINGS;Lo;0;L;;;;;N;;;;; 0F8B;TIBETAN SIGN GRU MED RGYINGS;Lo;0;L;;;;;N;;;;; +0F8C;TIBETAN SIGN INVERTED MCHU CAN;Lo;0;L;;;;;N;;;;; +0F8D;TIBETAN SUBJOINED SIGN LCE TSA CAN;Mn;0;NSM;;;;;N;;;;; +0F8E;TIBETAN SUBJOINED SIGN MCHU CAN;Mn;0;NSM;;;;;N;;;;; +0F8F;TIBETAN SUBJOINED SIGN INVERTED MCHU CAN;Mn;0;NSM;;;;;N;;;;; 0F90;TIBETAN SUBJOINED LETTER KA;Mn;0;NSM;;;;;N;;;;; 0F91;TIBETAN SUBJOINED LETTER KHA;Mn;0;NSM;;;;;N;;;;; 0F92;TIBETAN SUBJOINED LETTER GA;Mn;0;NSM;;;;;N;;;;; @@ -3262,6 +3318,8 @@ 0FD6;LEFT-FACING SVASTI SIGN;So;0;L;;;;;N;;;;; 0FD7;RIGHT-FACING SVASTI SIGN WITH DOTS;So;0;L;;;;;N;;;;; 0FD8;LEFT-FACING SVASTI SIGN WITH DOTS;So;0;L;;;;;N;;;;; +0FD9;TIBETAN MARK LEADING MCHAN RTAGS;Po;0;L;;;;;N;;;;; +0FDA;TIBETAN MARK TRAILING MCHAN RTAGS;Po;0;L;;;;;N;;;;; 1000;MYANMAR LETTER KA;Lo;0;L;;;;;N;;;;; 1001;MYANMAR LETTER KHA;Lo;0;L;;;;;N;;;;; 1002;MYANMAR LETTER GA;Lo;0;L;;;;;N;;;;; @@ -4087,6 +4145,8 @@ 1358;ETHIOPIC SYLLABLE RYA;Lo;0;L;;;;;N;;;;; 1359;ETHIOPIC SYLLABLE MYA;Lo;0;L;;;;;N;;;;; 135A;ETHIOPIC SYLLABLE FYA;Lo;0;L;;;;;N;;;;; +135D;ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK;Mn;230;NSM;;;;;N;;;;; +135E;ETHIOPIC COMBINING VOWEL LENGTH MARK;Mn;230;NSM;;;;;N;;;;; 135F;ETHIOPIC COMBINING GEMINATION MARK;Mn;230;NSM;;;;;N;;;;; 1360;ETHIOPIC SECTION MARK;So;0;L;;;;;N;;;;; 1361;ETHIOPIC WORDSPACE;Po;0;L;;;;;N;;;;; @@ -5580,9 +5640,9 @@ 19D7;NEW TAI LUE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 19D8;NEW TAI LUE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 19D9;NEW TAI LUE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; -19DA;NEW TAI LUE THAM DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; -19DE;NEW TAI LUE SIGN LAE;Po;0;ON;;;;;N;;;;; -19DF;NEW TAI LUE SIGN LAEV;Po;0;ON;;;;;N;;;;; +19DA;NEW TAI LUE THAM DIGIT ONE;No;0;L;;;1;1;N;;;;; +19DE;NEW TAI LUE SIGN LAE;So;0;ON;;;;;N;;;;; +19DF;NEW TAI LUE SIGN LAEV;So;0;ON;;;;;N;;;;; 19E0;KHMER SYMBOL PATHAMASAT;So;0;ON;;;;;N;;;;; 19E1;KHMER SYMBOL MUOY KOET;So;0;ON;;;;;N;;;;; 19E2;KHMER SYMBOL PII KOET;So;0;ON;;;;;N;;;;; @@ -5948,6 +6008,62 @@ 1BB7;SUNDANESE DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; 1BB8;SUNDANESE DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; 1BB9;SUNDANESE DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; +1BC0;BATAK LETTER A;Lo;0;L;;;;;N;;;;; +1BC1;BATAK LETTER SIMALUNGUN A;Lo;0;L;;;;;N;;;;; +1BC2;BATAK LETTER HA;Lo;0;L;;;;;N;;;;; +1BC3;BATAK LETTER SIMALUNGUN HA;Lo;0;L;;;;;N;;;;; +1BC4;BATAK LETTER MANDAILING HA;Lo;0;L;;;;;N;;;;; +1BC5;BATAK LETTER BA;Lo;0;L;;;;;N;;;;; +1BC6;BATAK LETTER KARO BA;Lo;0;L;;;;;N;;;;; +1BC7;BATAK LETTER PA;Lo;0;L;;;;;N;;;;; +1BC8;BATAK LETTER SIMALUNGUN PA;Lo;0;L;;;;;N;;;;; +1BC9;BATAK LETTER NA;Lo;0;L;;;;;N;;;;; +1BCA;BATAK LETTER MANDAILING NA;Lo;0;L;;;;;N;;;;; +1BCB;BATAK LETTER WA;Lo;0;L;;;;;N;;;;; +1BCC;BATAK LETTER SIMALUNGUN WA;Lo;0;L;;;;;N;;;;; +1BCD;BATAK LETTER PAKPAK WA;Lo;0;L;;;;;N;;;;; +1BCE;BATAK LETTER GA;Lo;0;L;;;;;N;;;;; +1BCF;BATAK LETTER SIMALUNGUN GA;Lo;0;L;;;;;N;;;;; +1BD0;BATAK LETTER JA;Lo;0;L;;;;;N;;;;; +1BD1;BATAK LETTER DA;Lo;0;L;;;;;N;;;;; +1BD2;BATAK LETTER RA;Lo;0;L;;;;;N;;;;; +1BD3;BATAK LETTER SIMALUNGUN RA;Lo;0;L;;;;;N;;;;; +1BD4;BATAK LETTER MA;Lo;0;L;;;;;N;;;;; +1BD5;BATAK LETTER SIMALUNGUN MA;Lo;0;L;;;;;N;;;;; +1BD6;BATAK LETTER SOUTHERN TA;Lo;0;L;;;;;N;;;;; +1BD7;BATAK LETTER NORTHERN TA;Lo;0;L;;;;;N;;;;; +1BD8;BATAK LETTER SA;Lo;0;L;;;;;N;;;;; +1BD9;BATAK LETTER SIMALUNGUN SA;Lo;0;L;;;;;N;;;;; +1BDA;BATAK LETTER MANDAILING SA;Lo;0;L;;;;;N;;;;; +1BDB;BATAK LETTER YA;Lo;0;L;;;;;N;;;;; +1BDC;BATAK LETTER SIMALUNGUN YA;Lo;0;L;;;;;N;;;;; +1BDD;BATAK LETTER NGA;Lo;0;L;;;;;N;;;;; +1BDE;BATAK LETTER LA;Lo;0;L;;;;;N;;;;; +1BDF;BATAK LETTER SIMALUNGUN LA;Lo;0;L;;;;;N;;;;; +1BE0;BATAK LETTER NYA;Lo;0;L;;;;;N;;;;; +1BE1;BATAK LETTER CA;Lo;0;L;;;;;N;;;;; +1BE2;BATAK LETTER NDA;Lo;0;L;;;;;N;;;;; +1BE3;BATAK LETTER MBA;Lo;0;L;;;;;N;;;;; +1BE4;BATAK LETTER I;Lo;0;L;;;;;N;;;;; +1BE5;BATAK LETTER U;Lo;0;L;;;;;N;;;;; +1BE6;BATAK SIGN TOMPI;Mn;7;NSM;;;;;N;;;;; +1BE7;BATAK VOWEL SIGN E;Mc;0;L;;;;;N;;;;; +1BE8;BATAK VOWEL SIGN PAKPAK E;Mn;0;NSM;;;;;N;;;;; +1BE9;BATAK VOWEL SIGN EE;Mn;0;NSM;;;;;N;;;;; +1BEA;BATAK VOWEL SIGN I;Mc;0;L;;;;;N;;;;; +1BEB;BATAK VOWEL SIGN KARO I;Mc;0;L;;;;;N;;;;; +1BEC;BATAK VOWEL SIGN O;Mc;0;L;;;;;N;;;;; +1BED;BATAK VOWEL SIGN KARO O;Mn;0;NSM;;;;;N;;;;; +1BEE;BATAK VOWEL SIGN U;Mc;0;L;;;;;N;;;;; +1BEF;BATAK VOWEL SIGN U FOR SIMALUNGUN SA;Mn;0;NSM;;;;;N;;;;; +1BF0;BATAK CONSONANT SIGN NG;Mn;0;NSM;;;;;N;;;;; +1BF1;BATAK CONSONANT SIGN H;Mn;0;NSM;;;;;N;;;;; +1BF2;BATAK PANGOLAT;Mc;9;L;;;;;N;;;;; +1BF3;BATAK PANONGONAN;Mc;9;L;;;;;N;;;;; +1BFC;BATAK SYMBOL BINDU NA METEK;Po;0;L;;;;;N;;;;; +1BFD;BATAK SYMBOL BINDU PINARBORAS;Po;0;L;;;;;N;;;;; +1BFE;BATAK SYMBOL BINDU JUDUL;Po;0;L;;;;;N;;;;; +1BFF;BATAK SYMBOL BINDU PANGOLAT;Po;0;L;;;;;N;;;;; 1C00;LEPCHA LETTER KA;Lo;0;L;;;;;N;;;;; 1C01;LEPCHA LETTER KLA;Lo;0;L;;;;;N;;;;; 1C02;LEPCHA LETTER KHA;Lo;0;L;;;;;N;;;;; @@ -6336,6 +6452,7 @@ 1DE4;COMBINING LATIN SMALL LETTER S;Mn;230;NSM;;;;;N;;;;; 1DE5;COMBINING LATIN SMALL LETTER LONG S;Mn;230;NSM;;;;;N;;;;; 1DE6;COMBINING LATIN SMALL LETTER Z;Mn;230;NSM;;;;;N;;;;; +1DFC;COMBINING DOUBLE INVERTED BREVE BELOW;Mn;233;NSM;;;;;N;;;;; 1DFD;COMBINING ALMOST EQUAL TO BELOW;Mn;220;NSM;;;;;N;;;;; 1DFE;COMBINING LEFT ARROWHEAD ABOVE;Mn;230;NSM;;;;;N;;;;; 1DFF;COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW;Mn;220;NSM;;;;;N;;;;; @@ -6969,6 +7086,14 @@ 2092;LATIN SUBSCRIPT SMALL LETTER O;Lm;0;L; 006F;;;;N;;;;; 2093;LATIN SUBSCRIPT SMALL LETTER X;Lm;0;L; 0078;;;;N;;;;; 2094;LATIN SUBSCRIPT SMALL LETTER SCHWA;Lm;0;L; 0259;;;;N;;;;; +2095;LATIN SUBSCRIPT SMALL LETTER H;Lm;0;L; 0068;;;;N;;;;; +2096;LATIN SUBSCRIPT SMALL LETTER K;Lm;0;L; 006B;;;;N;;;;; +2097;LATIN SUBSCRIPT SMALL LETTER L;Lm;0;L; 006C;;;;N;;;;; +2098;LATIN SUBSCRIPT SMALL LETTER M;Lm;0;L; 006D;;;;N;;;;; +2099;LATIN SUBSCRIPT SMALL LETTER N;Lm;0;L; 006E;;;;N;;;;; +209A;LATIN SUBSCRIPT SMALL LETTER P;Lm;0;L; 0070;;;;N;;;;; +209B;LATIN SUBSCRIPT SMALL LETTER S;Lm;0;L; 0073;;;;N;;;;; +209C;LATIN SUBSCRIPT SMALL LETTER T;Lm;0;L; 0074;;;;N;;;;; 20A0;EURO-CURRENCY SIGN;Sc;0;ET;;;;;N;;;;; 20A1;COLON SIGN;Sc;0;ET;;;;;N;;;;; 20A2;CRUZEIRO SIGN;Sc;0;ET;;;;;N;;;;; @@ -6994,6 +7119,7 @@ 20B6;LIVRE TOURNOIS SIGN;Sc;0;ET;;;;;N;;;;; 20B7;SPESMILO SIGN;Sc;0;ET;;;;;N;;;;; 20B8;TENGE SIGN;Sc;0;ET;;;;;N;;;;; +20B9;INDIAN RUPEE SIGN;Sc;0;ET;;;;;N;;;;; 20D0;COMBINING LEFT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING LEFT HARPOON ABOVE;;;; 20D1;COMBINING RIGHT HARPOON ABOVE;Mn;230;NSM;;;;;N;NON-SPACING RIGHT HARPOON ABOVE;;;; 20D2;COMBINING LONG VERTICAL LINE OVERLAY;Mn;1;NSM;;;;;N;NON-SPACING LONG VERTICAL BAR OVERLAY;;;; @@ -7051,7 +7177,7 @@ 2115;DOUBLE-STRUCK CAPITAL N;Lu;0;L; 004E;;;;N;DOUBLE-STRUCK N;;;; 2116;NUMERO SIGN;So;0;ON; 004E 006F;;;;N;NUMERO;;;; 2117;SOUND RECORDING COPYRIGHT;So;0;ON;;;;;N;;;;; -2118;SCRIPT CAPITAL P;So;0;ON;;;;;N;SCRIPT P;;;; +2118;SCRIPT CAPITAL P;Sm;0;ON;;;;;N;SCRIPT P;;;; 2119;DOUBLE-STRUCK CAPITAL P;Lu;0;L; 0050;;;;N;DOUBLE-STRUCK P;;;; 211A;DOUBLE-STRUCK CAPITAL Q;Lu;0;L; 0051;;;;N;DOUBLE-STRUCK Q;;;; 211B;SCRIPT CAPITAL R;Lu;0;L; 0052;;;;N;SCRIPT R;;;; @@ -7766,6 +7892,17 @@ 23E6;AC CURRENT;So;0;ON;;;;;N;;;;; 23E7;ELECTRICAL INTERSECTION;So;0;ON;;;;;N;;;;; 23E8;DECIMAL EXPONENT SYMBOL;So;0;ON;;;;;N;;;;; +23E9;BLACK RIGHT-POINTING DOUBLE TRIANGLE;So;0;ON;;;;;N;;;;; +23EA;BLACK LEFT-POINTING DOUBLE TRIANGLE;So;0;ON;;;;;N;;;;; +23EB;BLACK UP-POINTING DOUBLE TRIANGLE;So;0;ON;;;;;N;;;;; +23EC;BLACK DOWN-POINTING DOUBLE TRIANGLE;So;0;ON;;;;;N;;;;; +23ED;BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR;So;0;ON;;;;;N;;;;; +23EE;BLACK LEFT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR;So;0;ON;;;;;N;;;;; +23EF;BLACK RIGHT-POINTING TRIANGLE WITH DOUBLE VERTICAL BAR;So;0;ON;;;;;N;;;;; +23F0;ALARM CLOCK;So;0;ON;;;;;N;;;;; +23F1;STOPWATCH;So;0;ON;;;;;N;;;;; +23F2;TIMER CLOCK;So;0;ON;;;;;N;;;;; +23F3;HOURGLASS WITH FLOWING SAND;So;0;ON;;;;;N;;;;; 2400;SYMBOL FOR NULL;So;0;ON;;;;;N;GRAPHIC FOR NULL;;;; 2401;SYMBOL FOR START OF HEADING;So;0;ON;;;;;N;GRAPHIC FOR START OF HEADING;;;; 2402;SYMBOL FOR START OF TEXT;So;0;ON;;;;;N;GRAPHIC FOR START OF TEXT;;;; @@ -8438,6 +8575,7 @@ 26CB;WHITE DIAMOND IN SQUARE;So;0;ON;;;;;N;;;;; 26CC;CROSSING LANES;So;0;ON;;;;;N;;;;; 26CD;DISABLED CAR;So;0;ON;;;;;N;;;;; +26CE;OPHIUCHUS;So;0;ON;;;;;N;;;;; 26CF;PICK;So;0;ON;;;;;N;;;;; 26D0;CAR SLIDING;So;0;ON;;;;;N;;;;; 26D1;HELMET WITH WHITE CROSS;So;0;ON;;;;;N;;;;; @@ -8457,7 +8595,12 @@ 26DF;BLACK TRUCK;So;0;ON;;;;;N;;;;; 26E0;RESTRICTED LEFT ENTRY-1;So;0;ON;;;;;N;;;;; 26E1;RESTRICTED LEFT ENTRY-2;So;0;ON;;;;;N;;;;; +26E2;ASTRONOMICAL SYMBOL FOR URANUS;So;0;ON;;;;;N;;;;; 26E3;HEAVY CIRCLE WITH STROKE AND TWO DOTS ABOVE;So;0;ON;;;;;N;;;;; +26E4;PENTAGRAM;So;0;ON;;;;;N;;;;; +26E5;RIGHT-HANDED INTERLACED PENTAGRAM;So;0;ON;;;;;N;;;;; +26E6;LEFT-HANDED INTERLACED PENTAGRAM;So;0;ON;;;;;N;;;;; +26E7;INVERTED PENTAGRAM;So;0;ON;;;;;N;;;;; 26E8;BLACK CROSS ON SHIELD;So;0;ON;;;;;N;;;;; 26E9;SHINTO SHRINE;So;0;ON;;;;;N;;;;; 26EA;CHURCH;So;0;ON;;;;;N;;;;; @@ -8486,10 +8629,13 @@ 2702;BLACK SCISSORS;So;0;ON;;;;;N;;;;; 2703;LOWER BLADE SCISSORS;So;0;ON;;;;;N;;;;; 2704;WHITE SCISSORS;So;0;ON;;;;;N;;;;; +2705;WHITE HEAVY CHECK MARK;So;0;ON;;;;;N;;;;; 2706;TELEPHONE LOCATION SIGN;So;0;ON;;;;;N;;;;; 2707;TAPE DRIVE;So;0;ON;;;;;N;;;;; 2708;AIRPLANE;So;0;ON;;;;;N;;;;; 2709;ENVELOPE;So;0;ON;;;;;N;;;;; +270A;RAISED FIST;So;0;ON;;;;;N;;;;; +270B;RAISED HAND;So;0;ON;;;;;N;;;;; 270C;VICTORY HAND;So;0;ON;;;;;N;;;;; 270D;WRITING HAND;So;0;ON;;;;;N;;;;; 270E;LOWER RIGHT PENCIL;So;0;ON;;;;;N;;;;; @@ -8518,6 +8664,7 @@ 2725;FOUR CLUB-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 2726;BLACK FOUR POINTED STAR;So;0;ON;;;;;N;;;;; 2727;WHITE FOUR POINTED STAR;So;0;ON;;;;;N;;;;; +2728;SPARKLES;So;0;ON;;;;;N;;;;; 2729;STRESS OUTLINED WHITE STAR;So;0;ON;;;;;N;;;;; 272A;CIRCLED WHITE STAR;So;0;ON;;;;;N;;;;; 272B;OPEN CENTRE BLACK STAR;So;0;ON;;;;;N;OPEN CENTER BLACK STAR;;;; @@ -8553,11 +8700,16 @@ 2749;BALLOON-SPOKED ASTERISK;So;0;ON;;;;;N;;;;; 274A;EIGHT TEARDROP-SPOKED PROPELLER ASTERISK;So;0;ON;;;;;N;;;;; 274B;HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK;So;0;ON;;;;;N;;;;; +274C;CROSS MARK;So;0;ON;;;;;N;;;;; 274D;SHADOWED WHITE CIRCLE;So;0;ON;;;;;N;;;;; +274E;NEGATIVE SQUARED CROSS MARK;So;0;ON;;;;;N;;;;; 274F;LOWER RIGHT DROP-SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;; 2750;UPPER RIGHT DROP-SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;; 2751;LOWER RIGHT SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;; 2752;UPPER RIGHT SHADOWED WHITE SQUARE;So;0;ON;;;;;N;;;;; +2753;BLACK QUESTION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +2754;WHITE QUESTION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +2755;WHITE EXCLAMATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 2756;BLACK DIAMOND MINUS WHITE X;So;0;ON;;;;;N;;;;; 2757;HEAVY EXCLAMATION MARK SYMBOL;So;0;ON;;;;;N;;;;; 2758;LIGHT VERTICAL BAR;So;0;ON;;;;;N;;;;; @@ -8567,6 +8719,8 @@ 275C;HEAVY SINGLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 275D;HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 275E;HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +275F;HEAVY LOW SINGLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; +2760;HEAVY LOW DOUBLE COMMA QUOTATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 2761;CURVED STEM PARAGRAPH SIGN ORNAMENT;So;0;ON;;;;;N;;;;; 2762;HEAVY EXCLAMATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; 2763;HEAVY HEART EXCLAMATION MARK ORNAMENT;So;0;ON;;;;;N;;;;; @@ -8619,6 +8773,9 @@ 2792;DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT NINE;No;0;ON;;;9;9;N;INVERSE CIRCLED SANS-SERIF DIGIT NINE;;;; 2793;DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN;No;0;ON;;;;10;N;INVERSE CIRCLED SANS-SERIF NUMBER TEN;;;; 2794;HEAVY WIDE-HEADED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY WIDE-HEADED RIGHT ARROW;;;; +2795;HEAVY PLUS SIGN;So;0;ON;;;;;N;;;;; +2796;HEAVY MINUS SIGN;So;0;ON;;;;;N;;;;; +2797;HEAVY DIVISION SIGN;So;0;ON;;;;;N;;;;; 2798;HEAVY SOUTH EAST ARROW;So;0;ON;;;;;N;HEAVY LOWER RIGHT ARROW;;;; 2799;HEAVY RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY RIGHT ARROW;;;; 279A;HEAVY NORTH EAST ARROW;So;0;ON;;;;;N;HEAVY UPPER RIGHT ARROW;;;; @@ -8643,6 +8800,7 @@ 27AD;HEAVY LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY LOWER RIGHT-SHADOWED WHITE RIGHT ARROW;;;; 27AE;HEAVY UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY UPPER RIGHT-SHADOWED WHITE RIGHT ARROW;;;; 27AF;NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHT ARROW;;;; +27B0;CURLY LOOP;So;0;ON;;;;;N;;;;; 27B1;NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHT ARROW;;;; 27B2;CIRCLED HEAVY WHITE RIGHTWARDS ARROW;So;0;ON;;;;;N;CIRCLED HEAVY WHITE RIGHT ARROW;;;; 27B3;WHITE-FEATHERED RIGHTWARDS ARROW;So;0;ON;;;;;N;WHITE-FEATHERED RIGHT ARROW;;;; @@ -8657,6 +8815,7 @@ 27BC;WEDGE-TAILED RIGHTWARDS ARROW;So;0;ON;;;;;N;WEDGE-TAILED RIGHT ARROW;;;; 27BD;HEAVY WEDGE-TAILED RIGHTWARDS ARROW;So;0;ON;;;;;N;HEAVY WEDGE-TAILED RIGHT ARROW;;;; 27BE;OPEN-OUTLINED RIGHTWARDS ARROW;So;0;ON;;;;;N;OPEN-OUTLINED RIGHT ARROW;;;; +27BF;DOUBLE CURLY LOOP;So;0;ON;;;;;N;;;;; 27C0;THREE DIMENSIONAL ANGLE;Sm;0;ON;;;;;Y;;;;; 27C1;WHITE TRIANGLE CONTAINING SMALL WHITE TRIANGLE;Sm;0;ON;;;;;N;;;;; 27C2;PERPENDICULAR;Sm;0;ON;;;;;N;;;;; @@ -8669,6 +8828,8 @@ 27C9;SUPERSET PRECEDING SOLIDUS;Sm;0;ON;;;;;Y;;;;; 27CA;VERTICAL BAR WITH HORIZONTAL STROKE;Sm;0;ON;;;;;N;;;;; 27CC;LONG DIVISION;Sm;0;ON;;;;;Y;;;;; +27CE;SQUARED LOGICAL AND;Sm;0;ON;;;;;N;;;;; +27CF;SQUARED LOGICAL OR;Sm;0;ON;;;;;N;;;;; 27D0;WHITE DIAMOND WITH CENTRED DOT;Sm;0;ON;;;;;N;;;;; 27D1;AND WITH DOT;Sm;0;ON;;;;;N;;;;; 27D2;ELEMENT OF OPENING UPWARDS;Sm;0;ON;;;;;N;;;;; @@ -9912,6 +10073,8 @@ 2D64;TIFINAGH LETTER TAWELLEMET YAZ;Lo;0;L;;;;;N;;;;; 2D65;TIFINAGH LETTER YAZZ;Lo;0;L;;;;;N;;;;; 2D6F;TIFINAGH MODIFIER LETTER LABIALIZATION MARK;Lm;0;L; 2D61;;;;N;;;;; +2D70;TIFINAGH SEPARATOR MARK;Po;0;L;;;;;N;;;;; +2D7F;TIFINAGH CONSONANT JOINER;Mn;9;NSM;;;;;N;;;;; 2D80;ETHIOPIC SYLLABLE LOA;Lo;0;L;;;;;N;;;;; 2D81;ETHIOPIC SYLLABLE MOA;Lo;0;L;;;;;N;;;;; 2D82;ETHIOPIC SYLLABLE ROA;Lo;0;L;;;;;N;;;;; @@ -10842,6 +11005,9 @@ 31B5;BOPOMOFO FINAL LETTER T;Lo;0;L;;;;;N;;;;; 31B6;BOPOMOFO FINAL LETTER K;Lo;0;L;;;;;N;;;;; 31B7;BOPOMOFO FINAL LETTER H;Lo;0;L;;;;;N;;;;; +31B8;BOPOMOFO LETTER GH;Lo;0;L;;;;;N;;;;; +31B9;BOPOMOFO LETTER LH;Lo;0;L;;;;;N;;;;; +31BA;BOPOMOFO LETTER ZY;Lo;0;L;;;;;N;;;;; 31C0;CJK STROKE T;So;0;ON;;;;;N;;;;; 31C1;CJK STROKE WG;So;0;ON;;;;;N;;;;; 31C2;CJK STROKE XG;So;0;ON;;;;;N;;;;; @@ -13072,6 +13238,8 @@ A65C;CYRILLIC CAPITAL LETTER IOTIFIED CLOSED LITTLE YUS;Lu;0;L;;;;;N;;;;A65D; A65D;CYRILLIC SMALL LETTER IOTIFIED CLOSED LITTLE YUS;Ll;0;L;;;;;N;;;A65C;;A65C A65E;CYRILLIC CAPITAL LETTER YN;Lu;0;L;;;;;N;;;;A65F; A65F;CYRILLIC SMALL LETTER YN;Ll;0;L;;;;;N;;;A65E;;A65E +A660;CYRILLIC CAPITAL LETTER REVERSED TSE;Lu;0;L;;;;;N;;;;A661; +A661;CYRILLIC SMALL LETTER REVERSED TSE;Ll;0;L;;;;;N;;;A660;;A660 A662;CYRILLIC CAPITAL LETTER SOFT DE;Lu;0;L;;;;;N;;;;A663; A663;CYRILLIC SMALL LETTER SOFT DE;Ll;0;L;;;;;N;;;A662;;A662 A664;CYRILLIC CAPITAL LETTER SOFT EL;Lu;0;L;;;;;N;;;;A665; @@ -13347,6 +13515,21 @@ A789;MODIFIER LETTER COLON;Sk;0;L;;;;;N;;;;; A78A;MODIFIER LETTER SHORT EQUALS SIGN;Sk;0;L;;;;;N;;;;; A78B;LATIN CAPITAL LETTER SALTILLO;Lu;0;L;;;;;N;;;;A78C; A78C;LATIN SMALL LETTER SALTILLO;Ll;0;L;;;;;N;;;A78B;;A78B +A78D;LATIN CAPITAL LETTER TURNED H;Lu;0;L;;;;;N;;;;0265; +A78E;LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT;Ll;0;L;;;;;N;;;;; +A790;LATIN CAPITAL LETTER N WITH DESCENDER;Lu;0;L;;;;;N;;;;A791; +A791;LATIN SMALL LETTER N WITH DESCENDER;Ll;0;L;;;;;N;;;A790;;A790 +A7A0;LATIN CAPITAL LETTER G WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A1; +A7A1;LATIN SMALL LETTER G WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A0;;A7A0 +A7A2;LATIN CAPITAL LETTER K WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A3; +A7A3;LATIN SMALL LETTER K WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A2;;A7A2 +A7A4;LATIN CAPITAL LETTER N WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A5; +A7A5;LATIN SMALL LETTER N WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A4;;A7A4 +A7A6;LATIN CAPITAL LETTER R WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A7; +A7A7;LATIN SMALL LETTER R WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A6;;A7A6 +A7A8;LATIN CAPITAL LETTER S WITH OBLIQUE STROKE;Lu;0;L;;;;;N;;;;A7A9; +A7A9;LATIN SMALL LETTER S WITH OBLIQUE STROKE;Ll;0;L;;;;;N;;;A7A8;;A7A8 +A7FA;LATIN LETTER SMALL CAPITAL TURNED M;Ll;0;L;;;;;N;;;;; A7FB;LATIN EPIGRAPHIC LETTER REVERSED F;Lo;0;L;;;;;N;;;;; A7FC;LATIN EPIGRAPHIC LETTER REVERSED P;Lo;0;L;;;;;N;;;;; A7FD;LATIN EPIGRAPHIC LETTER INVERTED M;Lo;0;L;;;;;N;;;;; @@ -13959,6 +14142,38 @@ AADC;TAI VIET SYMBOL NUENG;Lo;0;L;;;;;N;;;;; AADD;TAI VIET SYMBOL SAM;Lm;0;L;;;;;N;;;;; AADE;TAI VIET SYMBOL HO HOI;Po;0;L;;;;;N;;;;; AADF;TAI VIET SYMBOL KOI KOI;Po;0;L;;;;;N;;;;; +AB01;ETHIOPIC SYLLABLE TTHU;Lo;0;L;;;;;N;;;;; +AB02;ETHIOPIC SYLLABLE TTHI;Lo;0;L;;;;;N;;;;; +AB03;ETHIOPIC SYLLABLE TTHAA;Lo;0;L;;;;;N;;;;; +AB04;ETHIOPIC SYLLABLE TTHEE;Lo;0;L;;;;;N;;;;; +AB05;ETHIOPIC SYLLABLE TTHE;Lo;0;L;;;;;N;;;;; +AB06;ETHIOPIC SYLLABLE TTHO;Lo;0;L;;;;;N;;;;; +AB09;ETHIOPIC SYLLABLE DDHU;Lo;0;L;;;;;N;;;;; +AB0A;ETHIOPIC SYLLABLE DDHI;Lo;0;L;;;;;N;;;;; +AB0B;ETHIOPIC SYLLABLE DDHAA;Lo;0;L;;;;;N;;;;; +AB0C;ETHIOPIC SYLLABLE DDHEE;Lo;0;L;;;;;N;;;;; +AB0D;ETHIOPIC SYLLABLE DDHE;Lo;0;L;;;;;N;;;;; +AB0E;ETHIOPIC SYLLABLE DDHO;Lo;0;L;;;;;N;;;;; +AB11;ETHIOPIC SYLLABLE DZU;Lo;0;L;;;;;N;;;;; +AB12;ETHIOPIC SYLLABLE DZI;Lo;0;L;;;;;N;;;;; +AB13;ETHIOPIC SYLLABLE DZAA;Lo;0;L;;;;;N;;;;; +AB14;ETHIOPIC SYLLABLE DZEE;Lo;0;L;;;;;N;;;;; +AB15;ETHIOPIC SYLLABLE DZE;Lo;0;L;;;;;N;;;;; +AB16;ETHIOPIC SYLLABLE DZO;Lo;0;L;;;;;N;;;;; +AB20;ETHIOPIC SYLLABLE CCHHA;Lo;0;L;;;;;N;;;;; +AB21;ETHIOPIC SYLLABLE CCHHU;Lo;0;L;;;;;N;;;;; +AB22;ETHIOPIC SYLLABLE CCHHI;Lo;0;L;;;;;N;;;;; +AB23;ETHIOPIC SYLLABLE CCHHAA;Lo;0;L;;;;;N;;;;; +AB24;ETHIOPIC SYLLABLE CCHHEE;Lo;0;L;;;;;N;;;;; +AB25;ETHIOPIC SYLLABLE CCHHE;Lo;0;L;;;;;N;;;;; +AB26;ETHIOPIC SYLLABLE CCHHO;Lo;0;L;;;;;N;;;;; +AB28;ETHIOPIC SYLLABLE BBA;Lo;0;L;;;;;N;;;;; +AB29;ETHIOPIC SYLLABLE BBU;Lo;0;L;;;;;N;;;;; +AB2A;ETHIOPIC SYLLABLE BBI;Lo;0;L;;;;;N;;;;; +AB2B;ETHIOPIC SYLLABLE BBAA;Lo;0;L;;;;;N;;;;; +AB2C;ETHIOPIC SYLLABLE BBEE;Lo;0;L;;;;;N;;;;; +AB2D;ETHIOPIC SYLLABLE BBE;Lo;0;L;;;;;N;;;;; +AB2E;ETHIOPIC SYLLABLE BBO;Lo;0;L;;;;;N;;;;; ABC0;MEETEI MAYEK LETTER KOK;Lo;0;L;;;;;N;;;;; ABC1;MEETEI MAYEK LETTER SAM;Lo;0;L;;;;;N;;;;; ABC2;MEETEI MAYEK LETTER LAI;Lo;0;L;;;;;N;;;;; @@ -14723,6 +14938,22 @@ FBAE;ARABIC LETTER YEH BARREE ISOLATED FORM;Lo;0;AL; 06D2;;;;N;;;;; FBAF;ARABIC LETTER YEH BARREE FINAL FORM;Lo;0;AL; 06D2;;;;N;;;;; FBB0;ARABIC LETTER YEH BARREE WITH HAMZA ABOVE ISOLATED FORM;Lo;0;AL; 06D3;;;;N;;;;; FBB1;ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM;Lo;0;AL; 06D3;;;;N;;;;; +FBB2;ARABIC SYMBOL DOT ABOVE;Sk;0;AL;;;;;N;;;;; +FBB3;ARABIC SYMBOL DOT BELOW;Sk;0;AL;;;;;N;;;;; +FBB4;ARABIC SYMBOL TWO DOTS ABOVE;Sk;0;AL;;;;;N;;;;; +FBB5;ARABIC SYMBOL TWO DOTS BELOW;Sk;0;AL;;;;;N;;;;; +FBB6;ARABIC SYMBOL THREE DOTS ABOVE;Sk;0;AL;;;;;N;;;;; +FBB7;ARABIC SYMBOL THREE DOTS BELOW;Sk;0;AL;;;;;N;;;;; +FBB8;ARABIC SYMBOL THREE DOTS POINTING DOWNWARDS ABOVE;Sk;0;AL;;;;;N;;;;; +FBB9;ARABIC SYMBOL THREE DOTS POINTING DOWNWARDS BELOW;Sk;0;AL;;;;;N;;;;; +FBBA;ARABIC SYMBOL FOUR DOTS ABOVE;Sk;0;AL;;;;;N;;;;; +FBBB;ARABIC SYMBOL FOUR DOTS BELOW;Sk;0;AL;;;;;N;;;;; +FBBC;ARABIC SYMBOL DOUBLE VERTICAL BAR BELOW;Sk;0;AL;;;;;N;;;;; +FBBD;ARABIC SYMBOL TWO DOTS VERTICALLY ABOVE;Sk;0;AL;;;;;N;;;;; +FBBE;ARABIC SYMBOL TWO DOTS VERTICALLY BELOW;Sk;0;AL;;;;;N;;;;; +FBBF;ARABIC SYMBOL RING;Sk;0;AL;;;;;N;;;;; +FBC0;ARABIC SYMBOL SMALL TAH ABOVE;Sk;0;AL;;;;;N;;;;; +FBC1;ARABIC SYMBOL SMALL TAH BELOW;Sk;0;AL;;;;;N;;;;; FBD3;ARABIC LETTER NG ISOLATED FORM;Lo;0;AL; 06AD;;;;N;;;;; FBD4;ARABIC LETTER NG FINAL FORM;Lo;0;AL; 06AD;;;;N;;;;; FBD5;ARABIC LETTER NG INITIAL FORM;Lo;0;AL; 06AD;;;;N;;;;; @@ -16933,6 +17164,114 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 10E7C;RUMI FRACTION ONE QUARTER;No;0;AN;;;;1/4;N;;;;; 10E7D;RUMI FRACTION ONE THIRD;No;0;AN;;;;1/3;N;;;;; 10E7E;RUMI FRACTION TWO THIRDS;No;0;AN;;;;2/3;N;;;;; +11000;BRAHMI SIGN CANDRABINDU;Mc;0;L;;;;;N;;;;; +11001;BRAHMI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; +11002;BRAHMI SIGN VISARGA;Mc;0;L;;;;;N;;;;; +11003;BRAHMI SIGN JIHVAMULIYA;Lo;0;L;;;;;N;;;;; +11004;BRAHMI SIGN UPADHMANIYA;Lo;0;L;;;;;N;;;;; +11005;BRAHMI LETTER A;Lo;0;L;;;;;N;;;;; +11006;BRAHMI LETTER AA;Lo;0;L;;;;;N;;;;; +11007;BRAHMI LETTER I;Lo;0;L;;;;;N;;;;; +11008;BRAHMI LETTER II;Lo;0;L;;;;;N;;;;; +11009;BRAHMI LETTER U;Lo;0;L;;;;;N;;;;; +1100A;BRAHMI LETTER UU;Lo;0;L;;;;;N;;;;; +1100B;BRAHMI LETTER VOCALIC R;Lo;0;L;;;;;N;;;;; +1100C;BRAHMI LETTER VOCALIC RR;Lo;0;L;;;;;N;;;;; +1100D;BRAHMI LETTER VOCALIC L;Lo;0;L;;;;;N;;;;; +1100E;BRAHMI LETTER VOCALIC LL;Lo;0;L;;;;;N;;;;; +1100F;BRAHMI LETTER E;Lo;0;L;;;;;N;;;;; +11010;BRAHMI LETTER AI;Lo;0;L;;;;;N;;;;; +11011;BRAHMI LETTER O;Lo;0;L;;;;;N;;;;; +11012;BRAHMI LETTER AU;Lo;0;L;;;;;N;;;;; +11013;BRAHMI LETTER KA;Lo;0;L;;;;;N;;;;; +11014;BRAHMI LETTER KHA;Lo;0;L;;;;;N;;;;; +11015;BRAHMI LETTER GA;Lo;0;L;;;;;N;;;;; +11016;BRAHMI LETTER GHA;Lo;0;L;;;;;N;;;;; +11017;BRAHMI LETTER NGA;Lo;0;L;;;;;N;;;;; +11018;BRAHMI LETTER CA;Lo;0;L;;;;;N;;;;; +11019;BRAHMI LETTER CHA;Lo;0;L;;;;;N;;;;; +1101A;BRAHMI LETTER JA;Lo;0;L;;;;;N;;;;; +1101B;BRAHMI LETTER JHA;Lo;0;L;;;;;N;;;;; +1101C;BRAHMI LETTER NYA;Lo;0;L;;;;;N;;;;; +1101D;BRAHMI LETTER TTA;Lo;0;L;;;;;N;;;;; +1101E;BRAHMI LETTER TTHA;Lo;0;L;;;;;N;;;;; +1101F;BRAHMI LETTER DDA;Lo;0;L;;;;;N;;;;; +11020;BRAHMI LETTER DDHA;Lo;0;L;;;;;N;;;;; +11021;BRAHMI LETTER NNA;Lo;0;L;;;;;N;;;;; +11022;BRAHMI LETTER TA;Lo;0;L;;;;;N;;;;; +11023;BRAHMI LETTER THA;Lo;0;L;;;;;N;;;;; +11024;BRAHMI LETTER DA;Lo;0;L;;;;;N;;;;; +11025;BRAHMI LETTER DHA;Lo;0;L;;;;;N;;;;; +11026;BRAHMI LETTER NA;Lo;0;L;;;;;N;;;;; +11027;BRAHMI LETTER PA;Lo;0;L;;;;;N;;;;; +11028;BRAHMI LETTER PHA;Lo;0;L;;;;;N;;;;; +11029;BRAHMI LETTER BA;Lo;0;L;;;;;N;;;;; +1102A;BRAHMI LETTER BHA;Lo;0;L;;;;;N;;;;; +1102B;BRAHMI LETTER MA;Lo;0;L;;;;;N;;;;; +1102C;BRAHMI LETTER YA;Lo;0;L;;;;;N;;;;; +1102D;BRAHMI LETTER RA;Lo;0;L;;;;;N;;;;; +1102E;BRAHMI LETTER LA;Lo;0;L;;;;;N;;;;; +1102F;BRAHMI LETTER VA;Lo;0;L;;;;;N;;;;; +11030;BRAHMI LETTER SHA;Lo;0;L;;;;;N;;;;; +11031;BRAHMI LETTER SSA;Lo;0;L;;;;;N;;;;; +11032;BRAHMI LETTER SA;Lo;0;L;;;;;N;;;;; +11033;BRAHMI LETTER HA;Lo;0;L;;;;;N;;;;; +11034;BRAHMI LETTER LLA;Lo;0;L;;;;;N;;;;; +11035;BRAHMI LETTER OLD TAMIL LLLA;Lo;0;L;;;;;N;;;;; +11036;BRAHMI LETTER OLD TAMIL RRA;Lo;0;L;;;;;N;;;;; +11037;BRAHMI LETTER OLD TAMIL NNNA;Lo;0;L;;;;;N;;;;; +11038;BRAHMI VOWEL SIGN AA;Mn;0;NSM;;;;;N;;;;; +11039;BRAHMI VOWEL SIGN BHATTIPROLU AA;Mn;0;NSM;;;;;N;;;;; +1103A;BRAHMI VOWEL SIGN I;Mn;0;NSM;;;;;N;;;;; +1103B;BRAHMI VOWEL SIGN II;Mn;0;NSM;;;;;N;;;;; +1103C;BRAHMI VOWEL SIGN U;Mn;0;NSM;;;;;N;;;;; +1103D;BRAHMI VOWEL SIGN UU;Mn;0;NSM;;;;;N;;;;; +1103E;BRAHMI VOWEL SIGN VOCALIC R;Mn;0;NSM;;;;;N;;;;; +1103F;BRAHMI VOWEL SIGN VOCALIC RR;Mn;0;NSM;;;;;N;;;;; +11040;BRAHMI VOWEL SIGN VOCALIC L;Mn;0;NSM;;;;;N;;;;; +11041;BRAHMI VOWEL SIGN VOCALIC LL;Mn;0;NSM;;;;;N;;;;; +11042;BRAHMI VOWEL SIGN E;Mn;0;NSM;;;;;N;;;;; +11043;BRAHMI VOWEL SIGN AI;Mn;0;NSM;;;;;N;;;;; +11044;BRAHMI VOWEL SIGN O;Mn;0;NSM;;;;;N;;;;; +11045;BRAHMI VOWEL SIGN AU;Mn;0;NSM;;;;;N;;;;; +11046;BRAHMI VIRAMA;Mn;9;NSM;;;;;N;;;;; +11047;BRAHMI DANDA;Po;0;L;;;;;N;;;;; +11048;BRAHMI DOUBLE DANDA;Po;0;L;;;;;N;;;;; +11049;BRAHMI PUNCTUATION DOT;Po;0;L;;;;;N;;;;; +1104A;BRAHMI PUNCTUATION DOUBLE DOT;Po;0;L;;;;;N;;;;; +1104B;BRAHMI PUNCTUATION LINE;Po;0;L;;;;;N;;;;; +1104C;BRAHMI PUNCTUATION CRESCENT BAR;Po;0;L;;;;;N;;;;; +1104D;BRAHMI PUNCTUATION LOTUS;Po;0;L;;;;;N;;;;; +11052;BRAHMI NUMBER ONE;No;0;ON;;;1;1;N;;;;; +11053;BRAHMI NUMBER TWO;No;0;ON;;;2;2;N;;;;; +11054;BRAHMI NUMBER THREE;No;0;ON;;;3;3;N;;;;; +11055;BRAHMI NUMBER FOUR;No;0;ON;;;4;4;N;;;;; +11056;BRAHMI NUMBER FIVE;No;0;ON;;;5;5;N;;;;; +11057;BRAHMI NUMBER SIX;No;0;ON;;;6;6;N;;;;; +11058;BRAHMI NUMBER SEVEN;No;0;ON;;;7;7;N;;;;; +11059;BRAHMI NUMBER EIGHT;No;0;ON;;;8;8;N;;;;; +1105A;BRAHMI NUMBER NINE;No;0;ON;;;9;9;N;;;;; +1105B;BRAHMI NUMBER TEN;No;0;ON;;;;10;N;;;;; +1105C;BRAHMI NUMBER TWENTY;No;0;ON;;;;20;N;;;;; +1105D;BRAHMI NUMBER THIRTY;No;0;ON;;;;30;N;;;;; +1105E;BRAHMI NUMBER FORTY;No;0;ON;;;;40;N;;;;; +1105F;BRAHMI NUMBER FIFTY;No;0;ON;;;;50;N;;;;; +11060;BRAHMI NUMBER SIXTY;No;0;ON;;;;60;N;;;;; +11061;BRAHMI NUMBER SEVENTY;No;0;ON;;;;70;N;;;;; +11062;BRAHMI NUMBER EIGHTY;No;0;ON;;;;80;N;;;;; +11063;BRAHMI NUMBER NINETY;No;0;ON;;;;90;N;;;;; +11064;BRAHMI NUMBER ONE HUNDRED;No;0;ON;;;;100;N;;;;; +11065;BRAHMI NUMBER ONE THOUSAND;No;0;ON;;;;1000;N;;;;; +11066;BRAHMI DIGIT ZERO;Nd;0;L;;0;0;0;N;;;;; +11067;BRAHMI DIGIT ONE;Nd;0;L;;1;1;1;N;;;;; +11068;BRAHMI DIGIT TWO;Nd;0;L;;2;2;2;N;;;;; +11069;BRAHMI DIGIT THREE;Nd;0;L;;3;3;3;N;;;;; +1106A;BRAHMI DIGIT FOUR;Nd;0;L;;4;4;4;N;;;;; +1106B;BRAHMI DIGIT FIVE;Nd;0;L;;5;5;5;N;;;;; +1106C;BRAHMI DIGIT SIX;Nd;0;L;;6;6;6;N;;;;; +1106D;BRAHMI DIGIT SEVEN;Nd;0;L;;7;7;7;N;;;;; +1106E;BRAHMI DIGIT EIGHT;Nd;0;L;;8;8;8;N;;;;; +1106F;BRAHMI DIGIT NINE;Nd;0;L;;9;9;9;N;;;;; 11080;KAITHI SIGN CANDRABINDU;Mn;0;NSM;;;;;N;;;;; 11081;KAITHI SIGN ANUSVARA;Mn;0;NSM;;;;;N;;;;; 11082;KAITHI SIGN VISARGA;Mc;0;L;;;;;N;;;;; @@ -19052,6 +19391,577 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1342C;EGYPTIAN HIEROGLYPH AA030;Lo;0;L;;;;;N;;;;; 1342D;EGYPTIAN HIEROGLYPH AA031;Lo;0;L;;;;;N;;;;; 1342E;EGYPTIAN HIEROGLYPH AA032;Lo;0;L;;;;;N;;;;; +16800;BAMUM LETTER PHASE-A NGKUE MFON;Lo;0;L;;;;;N;;;;; +16801;BAMUM LETTER PHASE-A GBIEE FON;Lo;0;L;;;;;N;;;;; +16802;BAMUM LETTER PHASE-A PON MFON PIPAEMGBIEE;Lo;0;L;;;;;N;;;;; +16803;BAMUM LETTER PHASE-A PON MFON PIPAEMBA;Lo;0;L;;;;;N;;;;; +16804;BAMUM LETTER PHASE-A NAA MFON;Lo;0;L;;;;;N;;;;; +16805;BAMUM LETTER PHASE-A SHUENSHUET;Lo;0;L;;;;;N;;;;; +16806;BAMUM LETTER PHASE-A TITA MFON;Lo;0;L;;;;;N;;;;; +16807;BAMUM LETTER PHASE-A NZA MFON;Lo;0;L;;;;;N;;;;; +16808;BAMUM LETTER PHASE-A SHINDA PA NJI;Lo;0;L;;;;;N;;;;; +16809;BAMUM LETTER PHASE-A PON PA NJI PIPAEMGBIEE;Lo;0;L;;;;;N;;;;; +1680A;BAMUM LETTER PHASE-A PON PA NJI PIPAEMBA;Lo;0;L;;;;;N;;;;; +1680B;BAMUM LETTER PHASE-A MAEMBGBIEE;Lo;0;L;;;;;N;;;;; +1680C;BAMUM LETTER PHASE-A TU MAEMBA;Lo;0;L;;;;;N;;;;; +1680D;BAMUM LETTER PHASE-A NGANGU;Lo;0;L;;;;;N;;;;; +1680E;BAMUM LETTER PHASE-A MAEMVEUX;Lo;0;L;;;;;N;;;;; +1680F;BAMUM LETTER PHASE-A MANSUAE;Lo;0;L;;;;;N;;;;; +16810;BAMUM LETTER PHASE-A MVEUAENGAM;Lo;0;L;;;;;N;;;;; +16811;BAMUM LETTER PHASE-A SEUNYAM;Lo;0;L;;;;;N;;;;; +16812;BAMUM LETTER PHASE-A NTOQPEN;Lo;0;L;;;;;N;;;;; +16813;BAMUM LETTER PHASE-A KEUKEUTNDA;Lo;0;L;;;;;N;;;;; +16814;BAMUM LETTER PHASE-A NKINDI;Lo;0;L;;;;;N;;;;; +16815;BAMUM LETTER PHASE-A SUU;Lo;0;L;;;;;N;;;;; +16816;BAMUM LETTER PHASE-A NGKUENZEUM;Lo;0;L;;;;;N;;;;; +16817;BAMUM LETTER PHASE-A LAPAQ;Lo;0;L;;;;;N;;;;; +16818;BAMUM LETTER PHASE-A LET KUT;Lo;0;L;;;;;N;;;;; +16819;BAMUM LETTER PHASE-A NTAP MFAA;Lo;0;L;;;;;N;;;;; +1681A;BAMUM LETTER PHASE-A MAEKEUP;Lo;0;L;;;;;N;;;;; +1681B;BAMUM LETTER PHASE-A PASHAE;Lo;0;L;;;;;N;;;;; +1681C;BAMUM LETTER PHASE-A GHEUAERAE;Lo;0;L;;;;;N;;;;; +1681D;BAMUM LETTER PHASE-A PAMSHAE;Lo;0;L;;;;;N;;;;; +1681E;BAMUM LETTER PHASE-A MON NGGEUAET;Lo;0;L;;;;;N;;;;; +1681F;BAMUM LETTER PHASE-A NZUN MEUT;Lo;0;L;;;;;N;;;;; +16820;BAMUM LETTER PHASE-A U YUQ NAE;Lo;0;L;;;;;N;;;;; +16821;BAMUM LETTER PHASE-A GHEUAEGHEUAE;Lo;0;L;;;;;N;;;;; +16822;BAMUM LETTER PHASE-A NTAP NTAA;Lo;0;L;;;;;N;;;;; +16823;BAMUM LETTER PHASE-A SISA;Lo;0;L;;;;;N;;;;; +16824;BAMUM LETTER PHASE-A MGBASA;Lo;0;L;;;;;N;;;;; +16825;BAMUM LETTER PHASE-A MEUNJOMNDEUQ;Lo;0;L;;;;;N;;;;; +16826;BAMUM LETTER PHASE-A MOOMPUQ;Lo;0;L;;;;;N;;;;; +16827;BAMUM LETTER PHASE-A KAFA;Lo;0;L;;;;;N;;;;; +16828;BAMUM LETTER PHASE-A PA LEERAEWA;Lo;0;L;;;;;N;;;;; +16829;BAMUM LETTER PHASE-A NDA LEERAEWA;Lo;0;L;;;;;N;;;;; +1682A;BAMUM LETTER PHASE-A PET;Lo;0;L;;;;;N;;;;; +1682B;BAMUM LETTER PHASE-A MAEMKPEN;Lo;0;L;;;;;N;;;;; +1682C;BAMUM LETTER PHASE-A NIKA;Lo;0;L;;;;;N;;;;; +1682D;BAMUM LETTER PHASE-A PUP;Lo;0;L;;;;;N;;;;; +1682E;BAMUM LETTER PHASE-A TUAEP;Lo;0;L;;;;;N;;;;; +1682F;BAMUM LETTER PHASE-A LUAEP;Lo;0;L;;;;;N;;;;; +16830;BAMUM LETTER PHASE-A SONJAM;Lo;0;L;;;;;N;;;;; +16831;BAMUM LETTER PHASE-A TEUTEUWEN;Lo;0;L;;;;;N;;;;; +16832;BAMUM LETTER PHASE-A MAENYI;Lo;0;L;;;;;N;;;;; +16833;BAMUM LETTER PHASE-A KET;Lo;0;L;;;;;N;;;;; +16834;BAMUM LETTER PHASE-A NDAANGGEUAET;Lo;0;L;;;;;N;;;;; +16835;BAMUM LETTER PHASE-A KUOQ;Lo;0;L;;;;;N;;;;; +16836;BAMUM LETTER PHASE-A MOOMEUT;Lo;0;L;;;;;N;;;;; +16837;BAMUM LETTER PHASE-A SHUM;Lo;0;L;;;;;N;;;;; +16838;BAMUM LETTER PHASE-A LOMMAE;Lo;0;L;;;;;N;;;;; +16839;BAMUM LETTER PHASE-A FIRI;Lo;0;L;;;;;N;;;;; +1683A;BAMUM LETTER PHASE-A ROM;Lo;0;L;;;;;N;;;;; +1683B;BAMUM LETTER PHASE-A KPOQ;Lo;0;L;;;;;N;;;;; +1683C;BAMUM LETTER PHASE-A SOQ;Lo;0;L;;;;;N;;;;; +1683D;BAMUM LETTER PHASE-A MAP PIEET;Lo;0;L;;;;;N;;;;; +1683E;BAMUM LETTER PHASE-A SHIRAE;Lo;0;L;;;;;N;;;;; +1683F;BAMUM LETTER PHASE-A NTAP;Lo;0;L;;;;;N;;;;; +16840;BAMUM LETTER PHASE-A SHOQ NSHUT YUM;Lo;0;L;;;;;N;;;;; +16841;BAMUM LETTER PHASE-A NYIT MONGKEUAEQ;Lo;0;L;;;;;N;;;;; +16842;BAMUM LETTER PHASE-A PAARAE;Lo;0;L;;;;;N;;;;; +16843;BAMUM LETTER PHASE-A NKAARAE;Lo;0;L;;;;;N;;;;; +16844;BAMUM LETTER PHASE-A UNKNOWN;Lo;0;L;;;;;N;;;;; +16845;BAMUM LETTER PHASE-A NGGEN;Lo;0;L;;;;;N;;;;; +16846;BAMUM LETTER PHASE-A MAESI;Lo;0;L;;;;;N;;;;; +16847;BAMUM LETTER PHASE-A NJAM;Lo;0;L;;;;;N;;;;; +16848;BAMUM LETTER PHASE-A MBANYI;Lo;0;L;;;;;N;;;;; +16849;BAMUM LETTER PHASE-A NYET;Lo;0;L;;;;;N;;;;; +1684A;BAMUM LETTER PHASE-A TEUAEN;Lo;0;L;;;;;N;;;;; +1684B;BAMUM LETTER PHASE-A SOT;Lo;0;L;;;;;N;;;;; +1684C;BAMUM LETTER PHASE-A PAAM;Lo;0;L;;;;;N;;;;; +1684D;BAMUM LETTER PHASE-A NSHIEE;Lo;0;L;;;;;N;;;;; +1684E;BAMUM LETTER PHASE-A MAEM;Lo;0;L;;;;;N;;;;; +1684F;BAMUM LETTER PHASE-A NYI;Lo;0;L;;;;;N;;;;; +16850;BAMUM LETTER PHASE-A KAQ;Lo;0;L;;;;;N;;;;; +16851;BAMUM LETTER PHASE-A NSHA;Lo;0;L;;;;;N;;;;; +16852;BAMUM LETTER PHASE-A VEE;Lo;0;L;;;;;N;;;;; +16853;BAMUM LETTER PHASE-A LU;Lo;0;L;;;;;N;;;;; +16854;BAMUM LETTER PHASE-A NEN;Lo;0;L;;;;;N;;;;; +16855;BAMUM LETTER PHASE-A NAQ;Lo;0;L;;;;;N;;;;; +16856;BAMUM LETTER PHASE-A MBAQ;Lo;0;L;;;;;N;;;;; +16857;BAMUM LETTER PHASE-B NSHUET;Lo;0;L;;;;;N;;;;; +16858;BAMUM LETTER PHASE-B TU MAEMGBIEE;Lo;0;L;;;;;N;;;;; +16859;BAMUM LETTER PHASE-B SIEE;Lo;0;L;;;;;N;;;;; +1685A;BAMUM LETTER PHASE-B SET TU;Lo;0;L;;;;;N;;;;; +1685B;BAMUM LETTER PHASE-B LOM NTEUM;Lo;0;L;;;;;N;;;;; +1685C;BAMUM LETTER PHASE-B MBA MAELEE;Lo;0;L;;;;;N;;;;; +1685D;BAMUM LETTER PHASE-B KIEEM;Lo;0;L;;;;;N;;;;; +1685E;BAMUM LETTER PHASE-B YEURAE;Lo;0;L;;;;;N;;;;; +1685F;BAMUM LETTER PHASE-B MBAARAE;Lo;0;L;;;;;N;;;;; +16860;BAMUM LETTER PHASE-B KAM;Lo;0;L;;;;;N;;;;; +16861;BAMUM LETTER PHASE-B PEESHI;Lo;0;L;;;;;N;;;;; +16862;BAMUM LETTER PHASE-B YAFU LEERAEWA;Lo;0;L;;;;;N;;;;; +16863;BAMUM LETTER PHASE-B LAM NSHUT NYAM;Lo;0;L;;;;;N;;;;; +16864;BAMUM LETTER PHASE-B NTIEE SHEUOQ;Lo;0;L;;;;;N;;;;; +16865;BAMUM LETTER PHASE-B NDU NJAA;Lo;0;L;;;;;N;;;;; +16866;BAMUM LETTER PHASE-B GHEUGHEUAEM;Lo;0;L;;;;;N;;;;; +16867;BAMUM LETTER PHASE-B PIT;Lo;0;L;;;;;N;;;;; +16868;BAMUM LETTER PHASE-B TU NSIEE;Lo;0;L;;;;;N;;;;; +16869;BAMUM LETTER PHASE-B SHET NJAQ;Lo;0;L;;;;;N;;;;; +1686A;BAMUM LETTER PHASE-B SHEUAEQTU;Lo;0;L;;;;;N;;;;; +1686B;BAMUM LETTER PHASE-B MFON TEUAEQ;Lo;0;L;;;;;N;;;;; +1686C;BAMUM LETTER PHASE-B MBIT MBAAKET;Lo;0;L;;;;;N;;;;; +1686D;BAMUM LETTER PHASE-B NYI NTEUM;Lo;0;L;;;;;N;;;;; +1686E;BAMUM LETTER PHASE-B KEUPUQ;Lo;0;L;;;;;N;;;;; +1686F;BAMUM LETTER PHASE-B GHEUGHEN;Lo;0;L;;;;;N;;;;; +16870;BAMUM LETTER PHASE-B KEUYEUX;Lo;0;L;;;;;N;;;;; +16871;BAMUM LETTER PHASE-B LAANAE;Lo;0;L;;;;;N;;;;; +16872;BAMUM LETTER PHASE-B PARUM;Lo;0;L;;;;;N;;;;; +16873;BAMUM LETTER PHASE-B VEUM;Lo;0;L;;;;;N;;;;; +16874;BAMUM LETTER PHASE-B NGKINDI MVOP;Lo;0;L;;;;;N;;;;; +16875;BAMUM LETTER PHASE-B NGGEU MBU;Lo;0;L;;;;;N;;;;; +16876;BAMUM LETTER PHASE-B WUAET;Lo;0;L;;;;;N;;;;; +16877;BAMUM LETTER PHASE-B SAKEUAE;Lo;0;L;;;;;N;;;;; +16878;BAMUM LETTER PHASE-B TAAM;Lo;0;L;;;;;N;;;;; +16879;BAMUM LETTER PHASE-B MEUQ;Lo;0;L;;;;;N;;;;; +1687A;BAMUM LETTER PHASE-B NGGUOQ;Lo;0;L;;;;;N;;;;; +1687B;BAMUM LETTER PHASE-B NGGUOQ LARGE;Lo;0;L;;;;;N;;;;; +1687C;BAMUM LETTER PHASE-B MFIYAQ;Lo;0;L;;;;;N;;;;; +1687D;BAMUM LETTER PHASE-B SUE;Lo;0;L;;;;;N;;;;; +1687E;BAMUM LETTER PHASE-B MBEURI;Lo;0;L;;;;;N;;;;; +1687F;BAMUM LETTER PHASE-B MONTIEEN;Lo;0;L;;;;;N;;;;; +16880;BAMUM LETTER PHASE-B NYAEMAE;Lo;0;L;;;;;N;;;;; +16881;BAMUM LETTER PHASE-B PUNGAAM;Lo;0;L;;;;;N;;;;; +16882;BAMUM LETTER PHASE-B MEUT NGGEET;Lo;0;L;;;;;N;;;;; +16883;BAMUM LETTER PHASE-B FEUX;Lo;0;L;;;;;N;;;;; +16884;BAMUM LETTER PHASE-B MBUOQ;Lo;0;L;;;;;N;;;;; +16885;BAMUM LETTER PHASE-B FEE;Lo;0;L;;;;;N;;;;; +16886;BAMUM LETTER PHASE-B KEUAEM;Lo;0;L;;;;;N;;;;; +16887;BAMUM LETTER PHASE-B MA NJEUAENA;Lo;0;L;;;;;N;;;;; +16888;BAMUM LETTER PHASE-B MA NJUQA;Lo;0;L;;;;;N;;;;; +16889;BAMUM LETTER PHASE-B LET;Lo;0;L;;;;;N;;;;; +1688A;BAMUM LETTER PHASE-B NGGAAM;Lo;0;L;;;;;N;;;;; +1688B;BAMUM LETTER PHASE-B NSEN;Lo;0;L;;;;;N;;;;; +1688C;BAMUM LETTER PHASE-B MA;Lo;0;L;;;;;N;;;;; +1688D;BAMUM LETTER PHASE-B KIQ;Lo;0;L;;;;;N;;;;; +1688E;BAMUM LETTER PHASE-B NGOM;Lo;0;L;;;;;N;;;;; +1688F;BAMUM LETTER PHASE-C NGKUE MAEMBA;Lo;0;L;;;;;N;;;;; +16890;BAMUM LETTER PHASE-C NZA;Lo;0;L;;;;;N;;;;; +16891;BAMUM LETTER PHASE-C YUM;Lo;0;L;;;;;N;;;;; +16892;BAMUM LETTER PHASE-C WANGKUOQ;Lo;0;L;;;;;N;;;;; +16893;BAMUM LETTER PHASE-C NGGEN;Lo;0;L;;;;;N;;;;; +16894;BAMUM LETTER PHASE-C NDEUAEREE;Lo;0;L;;;;;N;;;;; +16895;BAMUM LETTER PHASE-C NGKAQ;Lo;0;L;;;;;N;;;;; +16896;BAMUM LETTER PHASE-C GHARAE;Lo;0;L;;;;;N;;;;; +16897;BAMUM LETTER PHASE-C MBEEKEET;Lo;0;L;;;;;N;;;;; +16898;BAMUM LETTER PHASE-C GBAYI;Lo;0;L;;;;;N;;;;; +16899;BAMUM LETTER PHASE-C NYIR MKPARAQ MEUN;Lo;0;L;;;;;N;;;;; +1689A;BAMUM LETTER PHASE-C NTU MBIT;Lo;0;L;;;;;N;;;;; +1689B;BAMUM LETTER PHASE-C MBEUM;Lo;0;L;;;;;N;;;;; +1689C;BAMUM LETTER PHASE-C PIRIEEN;Lo;0;L;;;;;N;;;;; +1689D;BAMUM LETTER PHASE-C NDOMBU;Lo;0;L;;;;;N;;;;; +1689E;BAMUM LETTER PHASE-C MBAA CABBAGE-TREE;Lo;0;L;;;;;N;;;;; +1689F;BAMUM LETTER PHASE-C KEUSHEUAEP;Lo;0;L;;;;;N;;;;; +168A0;BAMUM LETTER PHASE-C GHAP;Lo;0;L;;;;;N;;;;; +168A1;BAMUM LETTER PHASE-C KEUKAQ;Lo;0;L;;;;;N;;;;; +168A2;BAMUM LETTER PHASE-C YU MUOMAE;Lo;0;L;;;;;N;;;;; +168A3;BAMUM LETTER PHASE-C NZEUM;Lo;0;L;;;;;N;;;;; +168A4;BAMUM LETTER PHASE-C MBUE;Lo;0;L;;;;;N;;;;; +168A5;BAMUM LETTER PHASE-C NSEUAEN;Lo;0;L;;;;;N;;;;; +168A6;BAMUM LETTER PHASE-C MBIT;Lo;0;L;;;;;N;;;;; +168A7;BAMUM LETTER PHASE-C YEUQ;Lo;0;L;;;;;N;;;;; +168A8;BAMUM LETTER PHASE-C KPARAQ;Lo;0;L;;;;;N;;;;; +168A9;BAMUM LETTER PHASE-C KAA;Lo;0;L;;;;;N;;;;; +168AA;BAMUM LETTER PHASE-C SEUX;Lo;0;L;;;;;N;;;;; +168AB;BAMUM LETTER PHASE-C NDIDA;Lo;0;L;;;;;N;;;;; +168AC;BAMUM LETTER PHASE-C TAASHAE;Lo;0;L;;;;;N;;;;; +168AD;BAMUM LETTER PHASE-C NJUEQ;Lo;0;L;;;;;N;;;;; +168AE;BAMUM LETTER PHASE-C TITA YUE;Lo;0;L;;;;;N;;;;; +168AF;BAMUM LETTER PHASE-C SUAET;Lo;0;L;;;;;N;;;;; +168B0;BAMUM LETTER PHASE-C NGGUAEN NYAM;Lo;0;L;;;;;N;;;;; +168B1;BAMUM LETTER PHASE-C VEUX;Lo;0;L;;;;;N;;;;; +168B2;BAMUM LETTER PHASE-C NANSANAQ;Lo;0;L;;;;;N;;;;; +168B3;BAMUM LETTER PHASE-C MA KEUAERI;Lo;0;L;;;;;N;;;;; +168B4;BAMUM LETTER PHASE-C NTAA;Lo;0;L;;;;;N;;;;; +168B5;BAMUM LETTER PHASE-C NGGUON;Lo;0;L;;;;;N;;;;; +168B6;BAMUM LETTER PHASE-C LAP;Lo;0;L;;;;;N;;;;; +168B7;BAMUM LETTER PHASE-C MBIRIEEN;Lo;0;L;;;;;N;;;;; +168B8;BAMUM LETTER PHASE-C MGBASAQ;Lo;0;L;;;;;N;;;;; +168B9;BAMUM LETTER PHASE-C NTEUNGBA;Lo;0;L;;;;;N;;;;; +168BA;BAMUM LETTER PHASE-C TEUTEUX;Lo;0;L;;;;;N;;;;; +168BB;BAMUM LETTER PHASE-C NGGUM;Lo;0;L;;;;;N;;;;; +168BC;BAMUM LETTER PHASE-C FUE;Lo;0;L;;;;;N;;;;; +168BD;BAMUM LETTER PHASE-C NDEUT;Lo;0;L;;;;;N;;;;; +168BE;BAMUM LETTER PHASE-C NSA;Lo;0;L;;;;;N;;;;; +168BF;BAMUM LETTER PHASE-C NSHAQ;Lo;0;L;;;;;N;;;;; +168C0;BAMUM LETTER PHASE-C BUNG;Lo;0;L;;;;;N;;;;; +168C1;BAMUM LETTER PHASE-C VEUAEPEN;Lo;0;L;;;;;N;;;;; +168C2;BAMUM LETTER PHASE-C MBERAE;Lo;0;L;;;;;N;;;;; +168C3;BAMUM LETTER PHASE-C RU;Lo;0;L;;;;;N;;;;; +168C4;BAMUM LETTER PHASE-C NJAEM;Lo;0;L;;;;;N;;;;; +168C5;BAMUM LETTER PHASE-C LAM;Lo;0;L;;;;;N;;;;; +168C6;BAMUM LETTER PHASE-C TITUAEP;Lo;0;L;;;;;N;;;;; +168C7;BAMUM LETTER PHASE-C NSUOT NGOM;Lo;0;L;;;;;N;;;;; +168C8;BAMUM LETTER PHASE-C NJEEEE;Lo;0;L;;;;;N;;;;; +168C9;BAMUM LETTER PHASE-C KET;Lo;0;L;;;;;N;;;;; +168CA;BAMUM LETTER PHASE-C NGGU;Lo;0;L;;;;;N;;;;; +168CB;BAMUM LETTER PHASE-C MAESI;Lo;0;L;;;;;N;;;;; +168CC;BAMUM LETTER PHASE-C MBUAEM;Lo;0;L;;;;;N;;;;; +168CD;BAMUM LETTER PHASE-C LU;Lo;0;L;;;;;N;;;;; +168CE;BAMUM LETTER PHASE-C KUT;Lo;0;L;;;;;N;;;;; +168CF;BAMUM LETTER PHASE-C NJAM;Lo;0;L;;;;;N;;;;; +168D0;BAMUM LETTER PHASE-C NGOM;Lo;0;L;;;;;N;;;;; +168D1;BAMUM LETTER PHASE-C WUP;Lo;0;L;;;;;N;;;;; +168D2;BAMUM LETTER PHASE-C NGGUEET;Lo;0;L;;;;;N;;;;; +168D3;BAMUM LETTER PHASE-C NSOM;Lo;0;L;;;;;N;;;;; +168D4;BAMUM LETTER PHASE-C NTEN;Lo;0;L;;;;;N;;;;; +168D5;BAMUM LETTER PHASE-C KUOP NKAARAE;Lo;0;L;;;;;N;;;;; +168D6;BAMUM LETTER PHASE-C NSUN;Lo;0;L;;;;;N;;;;; +168D7;BAMUM LETTER PHASE-C NDAM;Lo;0;L;;;;;N;;;;; +168D8;BAMUM LETTER PHASE-C MA NSIEE;Lo;0;L;;;;;N;;;;; +168D9;BAMUM LETTER PHASE-C YAA;Lo;0;L;;;;;N;;;;; +168DA;BAMUM LETTER PHASE-C NDAP;Lo;0;L;;;;;N;;;;; +168DB;BAMUM LETTER PHASE-C SHUEQ;Lo;0;L;;;;;N;;;;; +168DC;BAMUM LETTER PHASE-C SETFON;Lo;0;L;;;;;N;;;;; +168DD;BAMUM LETTER PHASE-C MBI;Lo;0;L;;;;;N;;;;; +168DE;BAMUM LETTER PHASE-C MAEMBA;Lo;0;L;;;;;N;;;;; +168DF;BAMUM LETTER PHASE-C MBANYI;Lo;0;L;;;;;N;;;;; +168E0;BAMUM LETTER PHASE-C KEUSEUX;Lo;0;L;;;;;N;;;;; +168E1;BAMUM LETTER PHASE-C MBEUX;Lo;0;L;;;;;N;;;;; +168E2;BAMUM LETTER PHASE-C KEUM;Lo;0;L;;;;;N;;;;; +168E3;BAMUM LETTER PHASE-C MBAA PICKET;Lo;0;L;;;;;N;;;;; +168E4;BAMUM LETTER PHASE-C YUWOQ;Lo;0;L;;;;;N;;;;; +168E5;BAMUM LETTER PHASE-C NJEUX;Lo;0;L;;;;;N;;;;; +168E6;BAMUM LETTER PHASE-C MIEE;Lo;0;L;;;;;N;;;;; +168E7;BAMUM LETTER PHASE-C MUAE;Lo;0;L;;;;;N;;;;; +168E8;BAMUM LETTER PHASE-C SHIQ;Lo;0;L;;;;;N;;;;; +168E9;BAMUM LETTER PHASE-C KEN LAW;Lo;0;L;;;;;N;;;;; +168EA;BAMUM LETTER PHASE-C KEN FATIGUE;Lo;0;L;;;;;N;;;;; +168EB;BAMUM LETTER PHASE-C NGAQ;Lo;0;L;;;;;N;;;;; +168EC;BAMUM LETTER PHASE-C NAQ;Lo;0;L;;;;;N;;;;; +168ED;BAMUM LETTER PHASE-C LIQ;Lo;0;L;;;;;N;;;;; +168EE;BAMUM LETTER PHASE-C PIN;Lo;0;L;;;;;N;;;;; +168EF;BAMUM LETTER PHASE-C PEN;Lo;0;L;;;;;N;;;;; +168F0;BAMUM LETTER PHASE-C TET;Lo;0;L;;;;;N;;;;; +168F1;BAMUM LETTER PHASE-D MBUO;Lo;0;L;;;;;N;;;;; +168F2;BAMUM LETTER PHASE-D WAP;Lo;0;L;;;;;N;;;;; +168F3;BAMUM LETTER PHASE-D NJI;Lo;0;L;;;;;N;;;;; +168F4;BAMUM LETTER PHASE-D MFON;Lo;0;L;;;;;N;;;;; +168F5;BAMUM LETTER PHASE-D NJIEE;Lo;0;L;;;;;N;;;;; +168F6;BAMUM LETTER PHASE-D LIEE;Lo;0;L;;;;;N;;;;; +168F7;BAMUM LETTER PHASE-D NJEUT;Lo;0;L;;;;;N;;;;; +168F8;BAMUM LETTER PHASE-D NSHEE;Lo;0;L;;;;;N;;;;; +168F9;BAMUM LETTER PHASE-D NGGAAMAE;Lo;0;L;;;;;N;;;;; +168FA;BAMUM LETTER PHASE-D NYAM;Lo;0;L;;;;;N;;;;; +168FB;BAMUM LETTER PHASE-D WUAEN;Lo;0;L;;;;;N;;;;; +168FC;BAMUM LETTER PHASE-D NGKUN;Lo;0;L;;;;;N;;;;; +168FD;BAMUM LETTER PHASE-D SHEE;Lo;0;L;;;;;N;;;;; +168FE;BAMUM LETTER PHASE-D NGKAP;Lo;0;L;;;;;N;;;;; +168FF;BAMUM LETTER PHASE-D KEUAETMEUN;Lo;0;L;;;;;N;;;;; +16900;BAMUM LETTER PHASE-D TEUT;Lo;0;L;;;;;N;;;;; +16901;BAMUM LETTER PHASE-D SHEUAE;Lo;0;L;;;;;N;;;;; +16902;BAMUM LETTER PHASE-D NJAP;Lo;0;L;;;;;N;;;;; +16903;BAMUM LETTER PHASE-D SUE;Lo;0;L;;;;;N;;;;; +16904;BAMUM LETTER PHASE-D KET;Lo;0;L;;;;;N;;;;; +16905;BAMUM LETTER PHASE-D YAEMMAE;Lo;0;L;;;;;N;;;;; +16906;BAMUM LETTER PHASE-D KUOM;Lo;0;L;;;;;N;;;;; +16907;BAMUM LETTER PHASE-D SAP;Lo;0;L;;;;;N;;;;; +16908;BAMUM LETTER PHASE-D MFEUT;Lo;0;L;;;;;N;;;;; +16909;BAMUM LETTER PHASE-D NDEUX;Lo;0;L;;;;;N;;;;; +1690A;BAMUM LETTER PHASE-D MALEERI;Lo;0;L;;;;;N;;;;; +1690B;BAMUM LETTER PHASE-D MEUT;Lo;0;L;;;;;N;;;;; +1690C;BAMUM LETTER PHASE-D SEUAEQ;Lo;0;L;;;;;N;;;;; +1690D;BAMUM LETTER PHASE-D YEN;Lo;0;L;;;;;N;;;;; +1690E;BAMUM LETTER PHASE-D NJEUAEM;Lo;0;L;;;;;N;;;;; +1690F;BAMUM LETTER PHASE-D KEUOT MBUAE;Lo;0;L;;;;;N;;;;; +16910;BAMUM LETTER PHASE-D NGKEURI;Lo;0;L;;;;;N;;;;; +16911;BAMUM LETTER PHASE-D TU;Lo;0;L;;;;;N;;;;; +16912;BAMUM LETTER PHASE-D GHAA;Lo;0;L;;;;;N;;;;; +16913;BAMUM LETTER PHASE-D NGKYEE;Lo;0;L;;;;;N;;;;; +16914;BAMUM LETTER PHASE-D FEUFEUAET;Lo;0;L;;;;;N;;;;; +16915;BAMUM LETTER PHASE-D NDEE;Lo;0;L;;;;;N;;;;; +16916;BAMUM LETTER PHASE-D MGBOFUM;Lo;0;L;;;;;N;;;;; +16917;BAMUM LETTER PHASE-D LEUAEP;Lo;0;L;;;;;N;;;;; +16918;BAMUM LETTER PHASE-D NDON;Lo;0;L;;;;;N;;;;; +16919;BAMUM LETTER PHASE-D MONI;Lo;0;L;;;;;N;;;;; +1691A;BAMUM LETTER PHASE-D MGBEUN;Lo;0;L;;;;;N;;;;; +1691B;BAMUM LETTER PHASE-D PUUT;Lo;0;L;;;;;N;;;;; +1691C;BAMUM LETTER PHASE-D MGBIEE;Lo;0;L;;;;;N;;;;; +1691D;BAMUM LETTER PHASE-D MFO;Lo;0;L;;;;;N;;;;; +1691E;BAMUM LETTER PHASE-D LUM;Lo;0;L;;;;;N;;;;; +1691F;BAMUM LETTER PHASE-D NSIEEP;Lo;0;L;;;;;N;;;;; +16920;BAMUM LETTER PHASE-D MBAA;Lo;0;L;;;;;N;;;;; +16921;BAMUM LETTER PHASE-D KWAET;Lo;0;L;;;;;N;;;;; +16922;BAMUM LETTER PHASE-D NYET;Lo;0;L;;;;;N;;;;; +16923;BAMUM LETTER PHASE-D TEUAEN;Lo;0;L;;;;;N;;;;; +16924;BAMUM LETTER PHASE-D SOT;Lo;0;L;;;;;N;;;;; +16925;BAMUM LETTER PHASE-D YUWOQ;Lo;0;L;;;;;N;;;;; +16926;BAMUM LETTER PHASE-D KEUM;Lo;0;L;;;;;N;;;;; +16927;BAMUM LETTER PHASE-D RAEM;Lo;0;L;;;;;N;;;;; +16928;BAMUM LETTER PHASE-D TEEEE;Lo;0;L;;;;;N;;;;; +16929;BAMUM LETTER PHASE-D NGKEUAEQ;Lo;0;L;;;;;N;;;;; +1692A;BAMUM LETTER PHASE-D MFEUAE;Lo;0;L;;;;;N;;;;; +1692B;BAMUM LETTER PHASE-D NSIEET;Lo;0;L;;;;;N;;;;; +1692C;BAMUM LETTER PHASE-D KEUP;Lo;0;L;;;;;N;;;;; +1692D;BAMUM LETTER PHASE-D PIP;Lo;0;L;;;;;N;;;;; +1692E;BAMUM LETTER PHASE-D PEUTAE;Lo;0;L;;;;;N;;;;; +1692F;BAMUM LETTER PHASE-D NYUE;Lo;0;L;;;;;N;;;;; +16930;BAMUM LETTER PHASE-D LET;Lo;0;L;;;;;N;;;;; +16931;BAMUM LETTER PHASE-D NGGAAM;Lo;0;L;;;;;N;;;;; +16932;BAMUM LETTER PHASE-D MFIEE;Lo;0;L;;;;;N;;;;; +16933;BAMUM LETTER PHASE-D NGGWAEN;Lo;0;L;;;;;N;;;;; +16934;BAMUM LETTER PHASE-D YUOM;Lo;0;L;;;;;N;;;;; +16935;BAMUM LETTER PHASE-D PAP;Lo;0;L;;;;;N;;;;; +16936;BAMUM LETTER PHASE-D YUOP;Lo;0;L;;;;;N;;;;; +16937;BAMUM LETTER PHASE-D NDAM;Lo;0;L;;;;;N;;;;; +16938;BAMUM LETTER PHASE-D NTEUM;Lo;0;L;;;;;N;;;;; +16939;BAMUM LETTER PHASE-D SUAE;Lo;0;L;;;;;N;;;;; +1693A;BAMUM LETTER PHASE-D KUN;Lo;0;L;;;;;N;;;;; +1693B;BAMUM LETTER PHASE-D NGGEUX;Lo;0;L;;;;;N;;;;; +1693C;BAMUM LETTER PHASE-D NGKIEE;Lo;0;L;;;;;N;;;;; +1693D;BAMUM LETTER PHASE-D TUOT;Lo;0;L;;;;;N;;;;; +1693E;BAMUM LETTER PHASE-D MEUN;Lo;0;L;;;;;N;;;;; +1693F;BAMUM LETTER PHASE-D KUQ;Lo;0;L;;;;;N;;;;; +16940;BAMUM LETTER PHASE-D NSUM;Lo;0;L;;;;;N;;;;; +16941;BAMUM LETTER PHASE-D TEUN;Lo;0;L;;;;;N;;;;; +16942;BAMUM LETTER PHASE-D MAENJET;Lo;0;L;;;;;N;;;;; +16943;BAMUM LETTER PHASE-D NGGAP;Lo;0;L;;;;;N;;;;; +16944;BAMUM LETTER PHASE-D LEUM;Lo;0;L;;;;;N;;;;; +16945;BAMUM LETTER PHASE-D NGGUOM;Lo;0;L;;;;;N;;;;; +16946;BAMUM LETTER PHASE-D NSHUT;Lo;0;L;;;;;N;;;;; +16947;BAMUM LETTER PHASE-D NJUEQ;Lo;0;L;;;;;N;;;;; +16948;BAMUM LETTER PHASE-D GHEUAE;Lo;0;L;;;;;N;;;;; +16949;BAMUM LETTER PHASE-D KU;Lo;0;L;;;;;N;;;;; +1694A;BAMUM LETTER PHASE-D REN OLD;Lo;0;L;;;;;N;;;;; +1694B;BAMUM LETTER PHASE-D TAE;Lo;0;L;;;;;N;;;;; +1694C;BAMUM LETTER PHASE-D TOQ;Lo;0;L;;;;;N;;;;; +1694D;BAMUM LETTER PHASE-D NYI;Lo;0;L;;;;;N;;;;; +1694E;BAMUM LETTER PHASE-D RII;Lo;0;L;;;;;N;;;;; +1694F;BAMUM LETTER PHASE-D LEEEE;Lo;0;L;;;;;N;;;;; +16950;BAMUM LETTER PHASE-D MEEEE;Lo;0;L;;;;;N;;;;; +16951;BAMUM LETTER PHASE-D M;Lo;0;L;;;;;N;;;;; +16952;BAMUM LETTER PHASE-D SUU;Lo;0;L;;;;;N;;;;; +16953;BAMUM LETTER PHASE-D MU;Lo;0;L;;;;;N;;;;; +16954;BAMUM LETTER PHASE-D SHII;Lo;0;L;;;;;N;;;;; +16955;BAMUM LETTER PHASE-D SHEUX;Lo;0;L;;;;;N;;;;; +16956;BAMUM LETTER PHASE-D KYEE;Lo;0;L;;;;;N;;;;; +16957;BAMUM LETTER PHASE-D NU;Lo;0;L;;;;;N;;;;; +16958;BAMUM LETTER PHASE-D SHU;Lo;0;L;;;;;N;;;;; +16959;BAMUM LETTER PHASE-D NTEE;Lo;0;L;;;;;N;;;;; +1695A;BAMUM LETTER PHASE-D PEE;Lo;0;L;;;;;N;;;;; +1695B;BAMUM LETTER PHASE-D NI;Lo;0;L;;;;;N;;;;; +1695C;BAMUM LETTER PHASE-D SHOQ;Lo;0;L;;;;;N;;;;; +1695D;BAMUM LETTER PHASE-D PUQ;Lo;0;L;;;;;N;;;;; +1695E;BAMUM LETTER PHASE-D MVOP;Lo;0;L;;;;;N;;;;; +1695F;BAMUM LETTER PHASE-D LOQ;Lo;0;L;;;;;N;;;;; +16960;BAMUM LETTER PHASE-D REN MUCH;Lo;0;L;;;;;N;;;;; +16961;BAMUM LETTER PHASE-D TI;Lo;0;L;;;;;N;;;;; +16962;BAMUM LETTER PHASE-D NTUU;Lo;0;L;;;;;N;;;;; +16963;BAMUM LETTER PHASE-D MBAA SEVEN;Lo;0;L;;;;;N;;;;; +16964;BAMUM LETTER PHASE-D SAQ;Lo;0;L;;;;;N;;;;; +16965;BAMUM LETTER PHASE-D FAA;Lo;0;L;;;;;N;;;;; +16966;BAMUM LETTER PHASE-E NDAP;Lo;0;L;;;;;N;;;;; +16967;BAMUM LETTER PHASE-E TOON;Lo;0;L;;;;;N;;;;; +16968;BAMUM LETTER PHASE-E MBEUM;Lo;0;L;;;;;N;;;;; +16969;BAMUM LETTER PHASE-E LAP;Lo;0;L;;;;;N;;;;; +1696A;BAMUM LETTER PHASE-E VOM;Lo;0;L;;;;;N;;;;; +1696B;BAMUM LETTER PHASE-E LOON;Lo;0;L;;;;;N;;;;; +1696C;BAMUM LETTER PHASE-E PAA;Lo;0;L;;;;;N;;;;; +1696D;BAMUM LETTER PHASE-E SOM;Lo;0;L;;;;;N;;;;; +1696E;BAMUM LETTER PHASE-E RAQ;Lo;0;L;;;;;N;;;;; +1696F;BAMUM LETTER PHASE-E NSHUOP;Lo;0;L;;;;;N;;;;; +16970;BAMUM LETTER PHASE-E NDUN;Lo;0;L;;;;;N;;;;; +16971;BAMUM LETTER PHASE-E PUAE;Lo;0;L;;;;;N;;;;; +16972;BAMUM LETTER PHASE-E TAM;Lo;0;L;;;;;N;;;;; +16973;BAMUM LETTER PHASE-E NGKA;Lo;0;L;;;;;N;;;;; +16974;BAMUM LETTER PHASE-E KPEUX;Lo;0;L;;;;;N;;;;; +16975;BAMUM LETTER PHASE-E WUO;Lo;0;L;;;;;N;;;;; +16976;BAMUM LETTER PHASE-E SEE;Lo;0;L;;;;;N;;;;; +16977;BAMUM LETTER PHASE-E NGGEUAET;Lo;0;L;;;;;N;;;;; +16978;BAMUM LETTER PHASE-E PAAM;Lo;0;L;;;;;N;;;;; +16979;BAMUM LETTER PHASE-E TOO;Lo;0;L;;;;;N;;;;; +1697A;BAMUM LETTER PHASE-E KUOP;Lo;0;L;;;;;N;;;;; +1697B;BAMUM LETTER PHASE-E LOM;Lo;0;L;;;;;N;;;;; +1697C;BAMUM LETTER PHASE-E NSHIEE;Lo;0;L;;;;;N;;;;; +1697D;BAMUM LETTER PHASE-E NGOP;Lo;0;L;;;;;N;;;;; +1697E;BAMUM LETTER PHASE-E MAEM;Lo;0;L;;;;;N;;;;; +1697F;BAMUM LETTER PHASE-E NGKEUX;Lo;0;L;;;;;N;;;;; +16980;BAMUM LETTER PHASE-E NGOQ;Lo;0;L;;;;;N;;;;; +16981;BAMUM LETTER PHASE-E NSHUE;Lo;0;L;;;;;N;;;;; +16982;BAMUM LETTER PHASE-E RIMGBA;Lo;0;L;;;;;N;;;;; +16983;BAMUM LETTER PHASE-E NJEUX;Lo;0;L;;;;;N;;;;; +16984;BAMUM LETTER PHASE-E PEEM;Lo;0;L;;;;;N;;;;; +16985;BAMUM LETTER PHASE-E SAA;Lo;0;L;;;;;N;;;;; +16986;BAMUM LETTER PHASE-E NGGURAE;Lo;0;L;;;;;N;;;;; +16987;BAMUM LETTER PHASE-E MGBA;Lo;0;L;;;;;N;;;;; +16988;BAMUM LETTER PHASE-E GHEUX;Lo;0;L;;;;;N;;;;; +16989;BAMUM LETTER PHASE-E NGKEUAEM;Lo;0;L;;;;;N;;;;; +1698A;BAMUM LETTER PHASE-E NJAEMLI;Lo;0;L;;;;;N;;;;; +1698B;BAMUM LETTER PHASE-E MAP;Lo;0;L;;;;;N;;;;; +1698C;BAMUM LETTER PHASE-E LOOT;Lo;0;L;;;;;N;;;;; +1698D;BAMUM LETTER PHASE-E NGGEEEE;Lo;0;L;;;;;N;;;;; +1698E;BAMUM LETTER PHASE-E NDIQ;Lo;0;L;;;;;N;;;;; +1698F;BAMUM LETTER PHASE-E TAEN NTEUM;Lo;0;L;;;;;N;;;;; +16990;BAMUM LETTER PHASE-E SET;Lo;0;L;;;;;N;;;;; +16991;BAMUM LETTER PHASE-E PUM;Lo;0;L;;;;;N;;;;; +16992;BAMUM LETTER PHASE-E NDAA SOFTNESS;Lo;0;L;;;;;N;;;;; +16993;BAMUM LETTER PHASE-E NGGUAESHAE NYAM;Lo;0;L;;;;;N;;;;; +16994;BAMUM LETTER PHASE-E YIEE;Lo;0;L;;;;;N;;;;; +16995;BAMUM LETTER PHASE-E GHEUN;Lo;0;L;;;;;N;;;;; +16996;BAMUM LETTER PHASE-E TUAE;Lo;0;L;;;;;N;;;;; +16997;BAMUM LETTER PHASE-E YEUAE;Lo;0;L;;;;;N;;;;; +16998;BAMUM LETTER PHASE-E PO;Lo;0;L;;;;;N;;;;; +16999;BAMUM LETTER PHASE-E TUMAE;Lo;0;L;;;;;N;;;;; +1699A;BAMUM LETTER PHASE-E KEUAE;Lo;0;L;;;;;N;;;;; +1699B;BAMUM LETTER PHASE-E SUAEN;Lo;0;L;;;;;N;;;;; +1699C;BAMUM LETTER PHASE-E TEUAEQ;Lo;0;L;;;;;N;;;;; +1699D;BAMUM LETTER PHASE-E VEUAE;Lo;0;L;;;;;N;;;;; +1699E;BAMUM LETTER PHASE-E WEUX;Lo;0;L;;;;;N;;;;; +1699F;BAMUM LETTER PHASE-E LAAM;Lo;0;L;;;;;N;;;;; +169A0;BAMUM LETTER PHASE-E PU;Lo;0;L;;;;;N;;;;; +169A1;BAMUM LETTER PHASE-E TAAQ;Lo;0;L;;;;;N;;;;; +169A2;BAMUM LETTER PHASE-E GHAAMAE;Lo;0;L;;;;;N;;;;; +169A3;BAMUM LETTER PHASE-E NGEUREUT;Lo;0;L;;;;;N;;;;; +169A4;BAMUM LETTER PHASE-E SHEUAEQ;Lo;0;L;;;;;N;;;;; +169A5;BAMUM LETTER PHASE-E MGBEN;Lo;0;L;;;;;N;;;;; +169A6;BAMUM LETTER PHASE-E MBEE;Lo;0;L;;;;;N;;;;; +169A7;BAMUM LETTER PHASE-E NZAQ;Lo;0;L;;;;;N;;;;; +169A8;BAMUM LETTER PHASE-E NKOM;Lo;0;L;;;;;N;;;;; +169A9;BAMUM LETTER PHASE-E GBET;Lo;0;L;;;;;N;;;;; +169AA;BAMUM LETTER PHASE-E TUM;Lo;0;L;;;;;N;;;;; +169AB;BAMUM LETTER PHASE-E KUET;Lo;0;L;;;;;N;;;;; +169AC;BAMUM LETTER PHASE-E YAP;Lo;0;L;;;;;N;;;;; +169AD;BAMUM LETTER PHASE-E NYI CLEAVER;Lo;0;L;;;;;N;;;;; +169AE;BAMUM LETTER PHASE-E YIT;Lo;0;L;;;;;N;;;;; +169AF;BAMUM LETTER PHASE-E MFEUQ;Lo;0;L;;;;;N;;;;; +169B0;BAMUM LETTER PHASE-E NDIAQ;Lo;0;L;;;;;N;;;;; +169B1;BAMUM LETTER PHASE-E PIEEQ;Lo;0;L;;;;;N;;;;; +169B2;BAMUM LETTER PHASE-E YUEQ;Lo;0;L;;;;;N;;;;; +169B3;BAMUM LETTER PHASE-E LEUAEM;Lo;0;L;;;;;N;;;;; +169B4;BAMUM LETTER PHASE-E FUE;Lo;0;L;;;;;N;;;;; +169B5;BAMUM LETTER PHASE-E GBEUX;Lo;0;L;;;;;N;;;;; +169B6;BAMUM LETTER PHASE-E NGKUP;Lo;0;L;;;;;N;;;;; +169B7;BAMUM LETTER PHASE-E KET;Lo;0;L;;;;;N;;;;; +169B8;BAMUM LETTER PHASE-E MAE;Lo;0;L;;;;;N;;;;; +169B9;BAMUM LETTER PHASE-E NGKAAMI;Lo;0;L;;;;;N;;;;; +169BA;BAMUM LETTER PHASE-E GHET;Lo;0;L;;;;;N;;;;; +169BB;BAMUM LETTER PHASE-E FA;Lo;0;L;;;;;N;;;;; +169BC;BAMUM LETTER PHASE-E NTUM;Lo;0;L;;;;;N;;;;; +169BD;BAMUM LETTER PHASE-E PEUT;Lo;0;L;;;;;N;;;;; +169BE;BAMUM LETTER PHASE-E YEUM;Lo;0;L;;;;;N;;;;; +169BF;BAMUM LETTER PHASE-E NGGEUAE;Lo;0;L;;;;;N;;;;; +169C0;BAMUM LETTER PHASE-E NYI BETWEEN;Lo;0;L;;;;;N;;;;; +169C1;BAMUM LETTER PHASE-E NZUQ;Lo;0;L;;;;;N;;;;; +169C2;BAMUM LETTER PHASE-E POON;Lo;0;L;;;;;N;;;;; +169C3;BAMUM LETTER PHASE-E MIEE;Lo;0;L;;;;;N;;;;; +169C4;BAMUM LETTER PHASE-E FUET;Lo;0;L;;;;;N;;;;; +169C5;BAMUM LETTER PHASE-E NAE;Lo;0;L;;;;;N;;;;; +169C6;BAMUM LETTER PHASE-E MUAE;Lo;0;L;;;;;N;;;;; +169C7;BAMUM LETTER PHASE-E GHEUAE;Lo;0;L;;;;;N;;;;; +169C8;BAMUM LETTER PHASE-E FU I;Lo;0;L;;;;;N;;;;; +169C9;BAMUM LETTER PHASE-E MVI;Lo;0;L;;;;;N;;;;; +169CA;BAMUM LETTER PHASE-E PUAQ;Lo;0;L;;;;;N;;;;; +169CB;BAMUM LETTER PHASE-E NGKUM;Lo;0;L;;;;;N;;;;; +169CC;BAMUM LETTER PHASE-E KUT;Lo;0;L;;;;;N;;;;; +169CD;BAMUM LETTER PHASE-E PIET;Lo;0;L;;;;;N;;;;; +169CE;BAMUM LETTER PHASE-E NTAP;Lo;0;L;;;;;N;;;;; +169CF;BAMUM LETTER PHASE-E YEUAET;Lo;0;L;;;;;N;;;;; +169D0;BAMUM LETTER PHASE-E NGGUP;Lo;0;L;;;;;N;;;;; +169D1;BAMUM LETTER PHASE-E PA PEOPLE;Lo;0;L;;;;;N;;;;; +169D2;BAMUM LETTER PHASE-E FU CALL;Lo;0;L;;;;;N;;;;; +169D3;BAMUM LETTER PHASE-E FOM;Lo;0;L;;;;;N;;;;; +169D4;BAMUM LETTER PHASE-E NJEE;Lo;0;L;;;;;N;;;;; +169D5;BAMUM LETTER PHASE-E A;Lo;0;L;;;;;N;;;;; +169D6;BAMUM LETTER PHASE-E TOQ;Lo;0;L;;;;;N;;;;; +169D7;BAMUM LETTER PHASE-E O;Lo;0;L;;;;;N;;;;; +169D8;BAMUM LETTER PHASE-E I;Lo;0;L;;;;;N;;;;; +169D9;BAMUM LETTER PHASE-E LAQ;Lo;0;L;;;;;N;;;;; +169DA;BAMUM LETTER PHASE-E PA PLURAL;Lo;0;L;;;;;N;;;;; +169DB;BAMUM LETTER PHASE-E TAA;Lo;0;L;;;;;N;;;;; +169DC;BAMUM LETTER PHASE-E TAQ;Lo;0;L;;;;;N;;;;; +169DD;BAMUM LETTER PHASE-E NDAA MY HOUSE;Lo;0;L;;;;;N;;;;; +169DE;BAMUM LETTER PHASE-E SHIQ;Lo;0;L;;;;;N;;;;; +169DF;BAMUM LETTER PHASE-E YEUX;Lo;0;L;;;;;N;;;;; +169E0;BAMUM LETTER PHASE-E NGUAE;Lo;0;L;;;;;N;;;;; +169E1;BAMUM LETTER PHASE-E YUAEN;Lo;0;L;;;;;N;;;;; +169E2;BAMUM LETTER PHASE-E YOQ SWIMMING;Lo;0;L;;;;;N;;;;; +169E3;BAMUM LETTER PHASE-E YOQ COVER;Lo;0;L;;;;;N;;;;; +169E4;BAMUM LETTER PHASE-E YUQ;Lo;0;L;;;;;N;;;;; +169E5;BAMUM LETTER PHASE-E YUN;Lo;0;L;;;;;N;;;;; +169E6;BAMUM LETTER PHASE-E KEUX;Lo;0;L;;;;;N;;;;; +169E7;BAMUM LETTER PHASE-E PEUX;Lo;0;L;;;;;N;;;;; +169E8;BAMUM LETTER PHASE-E NJEE EPOCH;Lo;0;L;;;;;N;;;;; +169E9;BAMUM LETTER PHASE-E PUE;Lo;0;L;;;;;N;;;;; +169EA;BAMUM LETTER PHASE-E WUE;Lo;0;L;;;;;N;;;;; +169EB;BAMUM LETTER PHASE-E FEE;Lo;0;L;;;;;N;;;;; +169EC;BAMUM LETTER PHASE-E VEE;Lo;0;L;;;;;N;;;;; +169ED;BAMUM LETTER PHASE-E LU;Lo;0;L;;;;;N;;;;; +169EE;BAMUM LETTER PHASE-E MI;Lo;0;L;;;;;N;;;;; +169EF;BAMUM LETTER PHASE-E REUX;Lo;0;L;;;;;N;;;;; +169F0;BAMUM LETTER PHASE-E RAE;Lo;0;L;;;;;N;;;;; +169F1;BAMUM LETTER PHASE-E NGUAET;Lo;0;L;;;;;N;;;;; +169F2;BAMUM LETTER PHASE-E NGA;Lo;0;L;;;;;N;;;;; +169F3;BAMUM LETTER PHASE-E SHO;Lo;0;L;;;;;N;;;;; +169F4;BAMUM LETTER PHASE-E SHOQ;Lo;0;L;;;;;N;;;;; +169F5;BAMUM LETTER PHASE-E FU REMEDY;Lo;0;L;;;;;N;;;;; +169F6;BAMUM LETTER PHASE-E NA;Lo;0;L;;;;;N;;;;; +169F7;BAMUM LETTER PHASE-E PI;Lo;0;L;;;;;N;;;;; +169F8;BAMUM LETTER PHASE-E LOQ;Lo;0;L;;;;;N;;;;; +169F9;BAMUM LETTER PHASE-E KO;Lo;0;L;;;;;N;;;;; +169FA;BAMUM LETTER PHASE-E MEN;Lo;0;L;;;;;N;;;;; +169FB;BAMUM LETTER PHASE-E MA;Lo;0;L;;;;;N;;;;; +169FC;BAMUM LETTER PHASE-E MAQ;Lo;0;L;;;;;N;;;;; +169FD;BAMUM LETTER PHASE-E TEU;Lo;0;L;;;;;N;;;;; +169FE;BAMUM LETTER PHASE-E KI;Lo;0;L;;;;;N;;;;; +169FF;BAMUM LETTER PHASE-E MON;Lo;0;L;;;;;N;;;;; +16A00;BAMUM LETTER PHASE-E TEN;Lo;0;L;;;;;N;;;;; +16A01;BAMUM LETTER PHASE-E FAQ;Lo;0;L;;;;;N;;;;; +16A02;BAMUM LETTER PHASE-E GHOM;Lo;0;L;;;;;N;;;;; +16A03;BAMUM LETTER PHASE-F KA;Lo;0;L;;;;;N;;;;; +16A04;BAMUM LETTER PHASE-F U;Lo;0;L;;;;;N;;;;; +16A05;BAMUM LETTER PHASE-F KU;Lo;0;L;;;;;N;;;;; +16A06;BAMUM LETTER PHASE-F EE;Lo;0;L;;;;;N;;;;; +16A07;BAMUM LETTER PHASE-F REE;Lo;0;L;;;;;N;;;;; +16A08;BAMUM LETTER PHASE-F TAE;Lo;0;L;;;;;N;;;;; +16A09;BAMUM LETTER PHASE-F NYI;Lo;0;L;;;;;N;;;;; +16A0A;BAMUM LETTER PHASE-F LA;Lo;0;L;;;;;N;;;;; +16A0B;BAMUM LETTER PHASE-F RII;Lo;0;L;;;;;N;;;;; +16A0C;BAMUM LETTER PHASE-F RIEE;Lo;0;L;;;;;N;;;;; +16A0D;BAMUM LETTER PHASE-F MEEEE;Lo;0;L;;;;;N;;;;; +16A0E;BAMUM LETTER PHASE-F TAA;Lo;0;L;;;;;N;;;;; +16A0F;BAMUM LETTER PHASE-F NDAA;Lo;0;L;;;;;N;;;;; +16A10;BAMUM LETTER PHASE-F NJAEM;Lo;0;L;;;;;N;;;;; +16A11;BAMUM LETTER PHASE-F M;Lo;0;L;;;;;N;;;;; +16A12;BAMUM LETTER PHASE-F SUU;Lo;0;L;;;;;N;;;;; +16A13;BAMUM LETTER PHASE-F SHII;Lo;0;L;;;;;N;;;;; +16A14;BAMUM LETTER PHASE-F SI;Lo;0;L;;;;;N;;;;; +16A15;BAMUM LETTER PHASE-F SEUX;Lo;0;L;;;;;N;;;;; +16A16;BAMUM LETTER PHASE-F KYEE;Lo;0;L;;;;;N;;;;; +16A17;BAMUM LETTER PHASE-F KET;Lo;0;L;;;;;N;;;;; +16A18;BAMUM LETTER PHASE-F NUAE;Lo;0;L;;;;;N;;;;; +16A19;BAMUM LETTER PHASE-F NU;Lo;0;L;;;;;N;;;;; +16A1A;BAMUM LETTER PHASE-F NJUAE;Lo;0;L;;;;;N;;;;; +16A1B;BAMUM LETTER PHASE-F YOQ;Lo;0;L;;;;;N;;;;; +16A1C;BAMUM LETTER PHASE-F SHU;Lo;0;L;;;;;N;;;;; +16A1D;BAMUM LETTER PHASE-F YA;Lo;0;L;;;;;N;;;;; +16A1E;BAMUM LETTER PHASE-F NSHA;Lo;0;L;;;;;N;;;;; +16A1F;BAMUM LETTER PHASE-F PEUX;Lo;0;L;;;;;N;;;;; +16A20;BAMUM LETTER PHASE-F NTEE;Lo;0;L;;;;;N;;;;; +16A21;BAMUM LETTER PHASE-F WUE;Lo;0;L;;;;;N;;;;; +16A22;BAMUM LETTER PHASE-F PEE;Lo;0;L;;;;;N;;;;; +16A23;BAMUM LETTER PHASE-F RU;Lo;0;L;;;;;N;;;;; +16A24;BAMUM LETTER PHASE-F NI;Lo;0;L;;;;;N;;;;; +16A25;BAMUM LETTER PHASE-F REUX;Lo;0;L;;;;;N;;;;; +16A26;BAMUM LETTER PHASE-F KEN;Lo;0;L;;;;;N;;;;; +16A27;BAMUM LETTER PHASE-F NGKWAEN;Lo;0;L;;;;;N;;;;; +16A28;BAMUM LETTER PHASE-F NGGA;Lo;0;L;;;;;N;;;;; +16A29;BAMUM LETTER PHASE-F SHO;Lo;0;L;;;;;N;;;;; +16A2A;BAMUM LETTER PHASE-F PUAE;Lo;0;L;;;;;N;;;;; +16A2B;BAMUM LETTER PHASE-F FOM;Lo;0;L;;;;;N;;;;; +16A2C;BAMUM LETTER PHASE-F WA;Lo;0;L;;;;;N;;;;; +16A2D;BAMUM LETTER PHASE-F LI;Lo;0;L;;;;;N;;;;; +16A2E;BAMUM LETTER PHASE-F LOQ;Lo;0;L;;;;;N;;;;; +16A2F;BAMUM LETTER PHASE-F KO;Lo;0;L;;;;;N;;;;; +16A30;BAMUM LETTER PHASE-F MBEN;Lo;0;L;;;;;N;;;;; +16A31;BAMUM LETTER PHASE-F REN;Lo;0;L;;;;;N;;;;; +16A32;BAMUM LETTER PHASE-F MA;Lo;0;L;;;;;N;;;;; +16A33;BAMUM LETTER PHASE-F MO;Lo;0;L;;;;;N;;;;; +16A34;BAMUM LETTER PHASE-F MBAA;Lo;0;L;;;;;N;;;;; +16A35;BAMUM LETTER PHASE-F TET;Lo;0;L;;;;;N;;;;; +16A36;BAMUM LETTER PHASE-F KPA;Lo;0;L;;;;;N;;;;; +16A37;BAMUM LETTER PHASE-F SAMBA;Lo;0;L;;;;;N;;;;; +16A38;BAMUM LETTER PHASE-F VUEQ;Lo;0;L;;;;;N;;;;; +1B000;KATAKANA LETTER ARCHAIC E;Lo;0;L;;;;;N;;;;; +1B001;HIRAGANA LETTER ARCHAIC YE;Lo;0;L;;;;;N;;;;; 1D000;BYZANTINE MUSICAL SYMBOL PSILI;So;0;L;;;;;N;;;;; 1D001;BYZANTINE MUSICAL SYMBOL DASEIA;So;0;L;;;;;N;;;;; 1D002;BYZANTINE MUSICAL SYMBOL PERISPOMENI;So;0;L;;;;;N;;;;; @@ -20833,6 +21743,65 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F091;DOMINO TILE VERTICAL-06-04;So;0;ON;;;;;N;;;;; 1F092;DOMINO TILE VERTICAL-06-05;So;0;ON;;;;;N;;;;; 1F093;DOMINO TILE VERTICAL-06-06;So;0;ON;;;;;N;;;;; +1F0A0;PLAYING CARD BACK;So;0;ON;;;;;N;;;;; +1F0A1;PLAYING CARD ACE OF SPADES;So;0;ON;;;;;N;;;;; +1F0A2;PLAYING CARD TWO OF SPADES;So;0;ON;;;;;N;;;;; +1F0A3;PLAYING CARD THREE OF SPADES;So;0;ON;;;;;N;;;;; +1F0A4;PLAYING CARD FOUR OF SPADES;So;0;ON;;;;;N;;;;; +1F0A5;PLAYING CARD FIVE OF SPADES;So;0;ON;;;;;N;;;;; +1F0A6;PLAYING CARD SIX OF SPADES;So;0;ON;;;;;N;;;;; +1F0A7;PLAYING CARD SEVEN OF SPADES;So;0;ON;;;;;N;;;;; +1F0A8;PLAYING CARD EIGHT OF SPADES;So;0;ON;;;;;N;;;;; +1F0A9;PLAYING CARD NINE OF SPADES;So;0;ON;;;;;N;;;;; +1F0AA;PLAYING CARD TEN OF SPADES;So;0;ON;;;;;N;;;;; +1F0AB;PLAYING CARD JACK OF SPADES;So;0;ON;;;;;N;;;;; +1F0AC;PLAYING CARD KNIGHT OF SPADES;So;0;ON;;;;;N;;;;; +1F0AD;PLAYING CARD QUEEN OF SPADES;So;0;ON;;;;;N;;;;; +1F0AE;PLAYING CARD KING OF SPADES;So;0;ON;;;;;N;;;;; +1F0B1;PLAYING CARD ACE OF HEARTS;So;0;ON;;;;;N;;;;; +1F0B2;PLAYING CARD TWO OF HEARTS;So;0;ON;;;;;N;;;;; +1F0B3;PLAYING CARD THREE OF HEARTS;So;0;ON;;;;;N;;;;; +1F0B4;PLAYING CARD FOUR OF HEARTS;So;0;ON;;;;;N;;;;; +1F0B5;PLAYING CARD FIVE OF HEARTS;So;0;ON;;;;;N;;;;; +1F0B6;PLAYING CARD SIX OF HEARTS;So;0;ON;;;;;N;;;;; +1F0B7;PLAYING CARD SEVEN OF HEARTS;So;0;ON;;;;;N;;;;; +1F0B8;PLAYING CARD EIGHT OF HEARTS;So;0;ON;;;;;N;;;;; +1F0B9;PLAYING CARD NINE OF HEARTS;So;0;ON;;;;;N;;;;; +1F0BA;PLAYING CARD TEN OF HEARTS;So;0;ON;;;;;N;;;;; +1F0BB;PLAYING CARD JACK OF HEARTS;So;0;ON;;;;;N;;;;; +1F0BC;PLAYING CARD KNIGHT OF HEARTS;So;0;ON;;;;;N;;;;; +1F0BD;PLAYING CARD QUEEN OF HEARTS;So;0;ON;;;;;N;;;;; +1F0BE;PLAYING CARD KING OF HEARTS;So;0;ON;;;;;N;;;;; +1F0C1;PLAYING CARD ACE OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0C2;PLAYING CARD TWO OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0C3;PLAYING CARD THREE OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0C4;PLAYING CARD FOUR OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0C5;PLAYING CARD FIVE OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0C6;PLAYING CARD SIX OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0C7;PLAYING CARD SEVEN OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0C8;PLAYING CARD EIGHT OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0C9;PLAYING CARD NINE OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0CA;PLAYING CARD TEN OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0CB;PLAYING CARD JACK OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0CC;PLAYING CARD KNIGHT OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0CD;PLAYING CARD QUEEN OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0CE;PLAYING CARD KING OF DIAMONDS;So;0;ON;;;;;N;;;;; +1F0CF;PLAYING CARD BLACK JOKER;So;0;ON;;;;;N;;;;; +1F0D1;PLAYING CARD ACE OF CLUBS;So;0;ON;;;;;N;;;;; +1F0D2;PLAYING CARD TWO OF CLUBS;So;0;ON;;;;;N;;;;; +1F0D3;PLAYING CARD THREE OF CLUBS;So;0;ON;;;;;N;;;;; +1F0D4;PLAYING CARD FOUR OF CLUBS;So;0;ON;;;;;N;;;;; +1F0D5;PLAYING CARD FIVE OF CLUBS;So;0;ON;;;;;N;;;;; +1F0D6;PLAYING CARD SIX OF CLUBS;So;0;ON;;;;;N;;;;; +1F0D7;PLAYING CARD SEVEN OF CLUBS;So;0;ON;;;;;N;;;;; +1F0D8;PLAYING CARD EIGHT OF CLUBS;So;0;ON;;;;;N;;;;; +1F0D9;PLAYING CARD NINE OF CLUBS;So;0;ON;;;;;N;;;;; +1F0DA;PLAYING CARD TEN OF CLUBS;So;0;ON;;;;;N;;;;; +1F0DB;PLAYING CARD JACK OF CLUBS;So;0;ON;;;;;N;;;;; +1F0DC;PLAYING CARD KNIGHT OF CLUBS;So;0;ON;;;;;N;;;;; +1F0DD;PLAYING CARD QUEEN OF CLUBS;So;0;ON;;;;;N;;;;; +1F0DE;PLAYING CARD KING OF CLUBS;So;0;ON;;;;;N;;;;; +1F0DF;PLAYING CARD WHITE JOKER;So;0;ON;;;;;N;;;;; 1F100;DIGIT ZERO FULL STOP;No;0;EN; 0030 002E;;0;0;N;;;;; 1F101;DIGIT ZERO COMMA;No;0;EN; 0030 002C;;0;0;N;;;;; 1F102;DIGIT ONE COMMA;No;0;EN; 0031 002C;;1;1;N;;;;; @@ -20875,28 +21844,136 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F12C;CIRCLED ITALIC LATIN CAPITAL LETTER R;So;0;L; 0052;;;;N;;;;; 1F12D;CIRCLED CD;So;0;L; 0043 0044;;;;N;;;;; 1F12E;CIRCLED WZ;So;0;L; 0057 005A;;;;N;;;;; +1F130;SQUARED LATIN CAPITAL LETTER A;So;0;L; 0041;;;;N;;;;; 1F131;SQUARED LATIN CAPITAL LETTER B;So;0;L; 0042;;;;N;;;;; +1F132;SQUARED LATIN CAPITAL LETTER C;So;0;L; 0043;;;;N;;;;; +1F133;SQUARED LATIN CAPITAL LETTER D;So;0;L; 0044;;;;N;;;;; +1F134;SQUARED LATIN CAPITAL LETTER E;So;0;L; 0045;;;;N;;;;; +1F135;SQUARED LATIN CAPITAL LETTER F;So;0;L; 0046;;;;N;;;;; +1F136;SQUARED LATIN CAPITAL LETTER G;So;0;L; 0047;;;;N;;;;; +1F137;SQUARED LATIN CAPITAL LETTER H;So;0;L; 0048;;;;N;;;;; +1F138;SQUARED LATIN CAPITAL LETTER I;So;0;L; 0049;;;;N;;;;; +1F139;SQUARED LATIN CAPITAL LETTER J;So;0;L; 004A;;;;N;;;;; +1F13A;SQUARED LATIN CAPITAL LETTER K;So;0;L; 004B;;;;N;;;;; +1F13B;SQUARED LATIN CAPITAL LETTER L;So;0;L; 004C;;;;N;;;;; +1F13C;SQUARED LATIN CAPITAL LETTER M;So;0;L; 004D;;;;N;;;;; 1F13D;SQUARED LATIN CAPITAL LETTER N;So;0;L; 004E;;;;N;;;;; +1F13E;SQUARED LATIN CAPITAL LETTER O;So;0;L; 004F;;;;N;;;;; 1F13F;SQUARED LATIN CAPITAL LETTER P;So;0;L; 0050;;;;N;;;;; +1F140;SQUARED LATIN CAPITAL LETTER Q;So;0;L; 0051;;;;N;;;;; +1F141;SQUARED LATIN CAPITAL LETTER R;So;0;L; 0052;;;;N;;;;; 1F142;SQUARED LATIN CAPITAL LETTER S;So;0;L; 0053;;;;N;;;;; +1F143;SQUARED LATIN CAPITAL LETTER T;So;0;L; 0054;;;;N;;;;; +1F144;SQUARED LATIN CAPITAL LETTER U;So;0;L; 0055;;;;N;;;;; +1F145;SQUARED LATIN CAPITAL LETTER V;So;0;L; 0056;;;;N;;;;; 1F146;SQUARED LATIN CAPITAL LETTER W;So;0;L; 0057;;;;N;;;;; +1F147;SQUARED LATIN CAPITAL LETTER X;So;0;L; 0058;;;;N;;;;; +1F148;SQUARED LATIN CAPITAL LETTER Y;So;0;L; 0059;;;;N;;;;; +1F149;SQUARED LATIN CAPITAL LETTER Z;So;0;L; 005A;;;;N;;;;; 1F14A;SQUARED HV;So;0;L; 0048 0056;;;;N;;;;; 1F14B;SQUARED MV;So;0;L; 004D 0056;;;;N;;;;; 1F14C;SQUARED SD;So;0;L; 0053 0044;;;;N;;;;; 1F14D;SQUARED SS;So;0;L; 0053 0053;;;;N;;;;; 1F14E;SQUARED PPV;So;0;L; 0050 0050 0056;;;;N;;;;; +1F14F;SQUARED WC;So;0;L; 0057 0043;;;;N;;;;; +1F150;NEGATIVE CIRCLED LATIN CAPITAL LETTER A;So;0;L;;;;;N;;;;; +1F151;NEGATIVE CIRCLED LATIN CAPITAL LETTER B;So;0;L;;;;;N;;;;; +1F152;NEGATIVE CIRCLED LATIN CAPITAL LETTER C;So;0;L;;;;;N;;;;; +1F153;NEGATIVE CIRCLED LATIN CAPITAL LETTER D;So;0;L;;;;;N;;;;; +1F154;NEGATIVE CIRCLED LATIN CAPITAL LETTER E;So;0;L;;;;;N;;;;; +1F155;NEGATIVE CIRCLED LATIN CAPITAL LETTER F;So;0;L;;;;;N;;;;; +1F156;NEGATIVE CIRCLED LATIN CAPITAL LETTER G;So;0;L;;;;;N;;;;; 1F157;NEGATIVE CIRCLED LATIN CAPITAL LETTER H;So;0;L;;;;;N;;;;; +1F158;NEGATIVE CIRCLED LATIN CAPITAL LETTER I;So;0;L;;;;;N;;;;; +1F159;NEGATIVE CIRCLED LATIN CAPITAL LETTER J;So;0;L;;;;;N;;;;; +1F15A;NEGATIVE CIRCLED LATIN CAPITAL LETTER K;So;0;L;;;;;N;;;;; +1F15B;NEGATIVE CIRCLED LATIN CAPITAL LETTER L;So;0;L;;;;;N;;;;; +1F15C;NEGATIVE CIRCLED LATIN CAPITAL LETTER M;So;0;L;;;;;N;;;;; +1F15D;NEGATIVE CIRCLED LATIN CAPITAL LETTER N;So;0;L;;;;;N;;;;; +1F15E;NEGATIVE CIRCLED LATIN CAPITAL LETTER O;So;0;L;;;;;N;;;;; 1F15F;NEGATIVE CIRCLED LATIN CAPITAL LETTER P;So;0;L;;;;;N;;;;; +1F160;NEGATIVE CIRCLED LATIN CAPITAL LETTER Q;So;0;L;;;;;N;;;;; +1F161;NEGATIVE CIRCLED LATIN CAPITAL LETTER R;So;0;L;;;;;N;;;;; +1F162;NEGATIVE CIRCLED LATIN CAPITAL LETTER S;So;0;L;;;;;N;;;;; +1F163;NEGATIVE CIRCLED LATIN CAPITAL LETTER T;So;0;L;;;;;N;;;;; +1F164;NEGATIVE CIRCLED LATIN CAPITAL LETTER U;So;0;L;;;;;N;;;;; +1F165;NEGATIVE CIRCLED LATIN CAPITAL LETTER V;So;0;L;;;;;N;;;;; +1F166;NEGATIVE CIRCLED LATIN CAPITAL LETTER W;So;0;L;;;;;N;;;;; +1F167;NEGATIVE CIRCLED LATIN CAPITAL LETTER X;So;0;L;;;;;N;;;;; +1F168;NEGATIVE CIRCLED LATIN CAPITAL LETTER Y;So;0;L;;;;;N;;;;; +1F169;NEGATIVE CIRCLED LATIN CAPITAL LETTER Z;So;0;L;;;;;N;;;;; +1F170;NEGATIVE SQUARED LATIN CAPITAL LETTER A;So;0;L;;;;;N;;;;; +1F171;NEGATIVE SQUARED LATIN CAPITAL LETTER B;So;0;L;;;;;N;;;;; +1F172;NEGATIVE SQUARED LATIN CAPITAL LETTER C;So;0;L;;;;;N;;;;; +1F173;NEGATIVE SQUARED LATIN CAPITAL LETTER D;So;0;L;;;;;N;;;;; +1F174;NEGATIVE SQUARED LATIN CAPITAL LETTER E;So;0;L;;;;;N;;;;; +1F175;NEGATIVE SQUARED LATIN CAPITAL LETTER F;So;0;L;;;;;N;;;;; +1F176;NEGATIVE SQUARED LATIN CAPITAL LETTER G;So;0;L;;;;;N;;;;; +1F177;NEGATIVE SQUARED LATIN CAPITAL LETTER H;So;0;L;;;;;N;;;;; +1F178;NEGATIVE SQUARED LATIN CAPITAL LETTER I;So;0;L;;;;;N;;;;; 1F179;NEGATIVE SQUARED LATIN CAPITAL LETTER J;So;0;L;;;;;N;;;;; +1F17A;NEGATIVE SQUARED LATIN CAPITAL LETTER K;So;0;L;;;;;N;;;;; 1F17B;NEGATIVE SQUARED LATIN CAPITAL LETTER L;So;0;L;;;;;N;;;;; 1F17C;NEGATIVE SQUARED LATIN CAPITAL LETTER M;So;0;L;;;;;N;;;;; +1F17D;NEGATIVE SQUARED LATIN CAPITAL LETTER N;So;0;L;;;;;N;;;;; +1F17E;NEGATIVE SQUARED LATIN CAPITAL LETTER O;So;0;L;;;;;N;;;;; 1F17F;NEGATIVE SQUARED LATIN CAPITAL LETTER P;So;0;L;;;;;N;;;;; +1F180;NEGATIVE SQUARED LATIN CAPITAL LETTER Q;So;0;L;;;;;N;;;;; +1F181;NEGATIVE SQUARED LATIN CAPITAL LETTER R;So;0;L;;;;;N;;;;; +1F182;NEGATIVE SQUARED LATIN CAPITAL LETTER S;So;0;L;;;;;N;;;;; +1F183;NEGATIVE SQUARED LATIN CAPITAL LETTER T;So;0;L;;;;;N;;;;; +1F184;NEGATIVE SQUARED LATIN CAPITAL LETTER U;So;0;L;;;;;N;;;;; +1F185;NEGATIVE SQUARED LATIN CAPITAL LETTER V;So;0;L;;;;;N;;;;; +1F186;NEGATIVE SQUARED LATIN CAPITAL LETTER W;So;0;L;;;;;N;;;;; +1F187;NEGATIVE SQUARED LATIN CAPITAL LETTER X;So;0;L;;;;;N;;;;; +1F188;NEGATIVE SQUARED LATIN CAPITAL LETTER Y;So;0;L;;;;;N;;;;; +1F189;NEGATIVE SQUARED LATIN CAPITAL LETTER Z;So;0;L;;;;;N;;;;; 1F18A;CROSSED NEGATIVE SQUARED LATIN CAPITAL LETTER P;So;0;L;;;;;N;;;;; 1F18B;NEGATIVE SQUARED IC;So;0;L;;;;;N;;;;; 1F18C;NEGATIVE SQUARED PA;So;0;L;;;;;N;;;;; 1F18D;NEGATIVE SQUARED SA;So;0;L;;;;;N;;;;; +1F18E;NEGATIVE SQUARED AB;So;0;L;;;;;N;;;;; +1F18F;NEGATIVE SQUARED WC;So;0;L;;;;;N;;;;; 1F190;SQUARE DJ;So;0;L; 0044 004A;;;;N;;;;; +1F191;SQUARED CL;So;0;L;;;;;N;;;;; +1F192;SQUARED COOL;So;0;L;;;;;N;;;;; +1F193;SQUARED FREE;So;0;L;;;;;N;;;;; +1F194;SQUARED ID;So;0;L;;;;;N;;;;; +1F195;SQUARED NEW;So;0;L;;;;;N;;;;; +1F196;SQUARED NG;So;0;L;;;;;N;;;;; +1F197;SQUARED OK;So;0;L;;;;;N;;;;; +1F198;SQUARED SOS;So;0;L;;;;;N;;;;; +1F199;SQUARED UP WITH EXCLAMATION MARK;So;0;L;;;;;N;;;;; +1F19A;SQUARED VS;So;0;L;;;;;N;;;;; +1F1E6;REGIONAL INDICATOR SYMBOL LETTER A;So;0;L;;;;;N;;;;; +1F1E7;REGIONAL INDICATOR SYMBOL LETTER B;So;0;L;;;;;N;;;;; +1F1E8;REGIONAL INDICATOR SYMBOL LETTER C;So;0;L;;;;;N;;;;; +1F1E9;REGIONAL INDICATOR SYMBOL LETTER D;So;0;L;;;;;N;;;;; +1F1EA;REGIONAL INDICATOR SYMBOL LETTER E;So;0;L;;;;;N;;;;; +1F1EB;REGIONAL INDICATOR SYMBOL LETTER F;So;0;L;;;;;N;;;;; +1F1EC;REGIONAL INDICATOR SYMBOL LETTER G;So;0;L;;;;;N;;;;; +1F1ED;REGIONAL INDICATOR SYMBOL LETTER H;So;0;L;;;;;N;;;;; +1F1EE;REGIONAL INDICATOR SYMBOL LETTER I;So;0;L;;;;;N;;;;; +1F1EF;REGIONAL INDICATOR SYMBOL LETTER J;So;0;L;;;;;N;;;;; +1F1F0;REGIONAL INDICATOR SYMBOL LETTER K;So;0;L;;;;;N;;;;; +1F1F1;REGIONAL INDICATOR SYMBOL LETTER L;So;0;L;;;;;N;;;;; +1F1F2;REGIONAL INDICATOR SYMBOL LETTER M;So;0;L;;;;;N;;;;; +1F1F3;REGIONAL INDICATOR SYMBOL LETTER N;So;0;L;;;;;N;;;;; +1F1F4;REGIONAL INDICATOR SYMBOL LETTER O;So;0;L;;;;;N;;;;; +1F1F5;REGIONAL INDICATOR SYMBOL LETTER P;So;0;L;;;;;N;;;;; +1F1F6;REGIONAL INDICATOR SYMBOL LETTER Q;So;0;L;;;;;N;;;;; +1F1F7;REGIONAL INDICATOR SYMBOL LETTER R;So;0;L;;;;;N;;;;; +1F1F8;REGIONAL INDICATOR SYMBOL LETTER S;So;0;L;;;;;N;;;;; +1F1F9;REGIONAL INDICATOR SYMBOL LETTER T;So;0;L;;;;;N;;;;; +1F1FA;REGIONAL INDICATOR SYMBOL LETTER U;So;0;L;;;;;N;;;;; +1F1FB;REGIONAL INDICATOR SYMBOL LETTER V;So;0;L;;;;;N;;;;; +1F1FC;REGIONAL INDICATOR SYMBOL LETTER W;So;0;L;;;;;N;;;;; +1F1FD;REGIONAL INDICATOR SYMBOL LETTER X;So;0;L;;;;;N;;;;; +1F1FE;REGIONAL INDICATOR SYMBOL LETTER Y;So;0;L;;;;;N;;;;; +1F1FF;REGIONAL INDICATOR SYMBOL LETTER Z;So;0;L;;;;;N;;;;; 1F200;SQUARE HIRAGANA HOKA;So;0;L; 307B 304B;;;;N;;;;; +1F201;SQUARED KATAKANA KOKO;So;0;L; 30B3 30B3;;;;N;;;;; +1F202;SQUARED KATAKANA SA;So;0;L; 30B5;;;;N;;;;; 1F210;SQUARED CJK UNIFIED IDEOGRAPH-624B;So;0;L; 624B;;;;N;;;;; 1F211;SQUARED CJK UNIFIED IDEOGRAPH-5B57;So;0;L; 5B57;;;;N;;;;; 1F212;SQUARED CJK UNIFIED IDEOGRAPH-53CC;So;0;L; 53CC;;;;N;;;;; @@ -20931,6 +22008,15 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F22F;SQUARED CJK UNIFIED IDEOGRAPH-6307;So;0;L; 6307;;;;N;;;;; 1F230;SQUARED CJK UNIFIED IDEOGRAPH-8D70;So;0;L; 8D70;;;;N;;;;; 1F231;SQUARED CJK UNIFIED IDEOGRAPH-6253;So;0;L; 6253;;;;N;;;;; +1F232;SQUARED CJK UNIFIED IDEOGRAPH-7981;So;0;L; 7981;;;;N;;;;; +1F233;SQUARED CJK UNIFIED IDEOGRAPH-7A7A;So;0;L; 7A7A;;;;N;;;;; +1F234;SQUARED CJK UNIFIED IDEOGRAPH-5408;So;0;L; 5408;;;;N;;;;; +1F235;SQUARED CJK UNIFIED IDEOGRAPH-6E80;So;0;L; 6E80;;;;N;;;;; +1F236;SQUARED CJK UNIFIED IDEOGRAPH-6709;So;0;L; 6709;;;;N;;;;; +1F237;SQUARED CJK UNIFIED IDEOGRAPH-6708;So;0;L; 6708;;;;N;;;;; +1F238;SQUARED CJK UNIFIED IDEOGRAPH-7533;So;0;L; 7533;;;;N;;;;; +1F239;SQUARED CJK UNIFIED IDEOGRAPH-5272;So;0;L; 5272;;;;N;;;;; +1F23A;SQUARED CJK UNIFIED IDEOGRAPH-55B6;So;0;L; 55B6;;;;N;;;;; 1F240;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C;So;0;L; 3014 672C 3015;;;;N;;;;; 1F241;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-4E09;So;0;L; 3014 4E09 3015;;;;N;;;;; 1F242;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-4E8C;So;0;L; 3014 4E8C 3015;;;;N;;;;; @@ -20940,10 +22026,792 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;; 1F246;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-76D7;So;0;L; 3014 76D7 3015;;;;N;;;;; 1F247;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-52DD;So;0;L; 3014 52DD 3015;;;;N;;;;; 1F248;TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557;So;0;L; 3014 6557 3015;;;;N;;;;; +1F250;CIRCLED IDEOGRAPH ADVANTAGE;So;0;L; 5F97;;;;N;;;;; +1F251;CIRCLED IDEOGRAPH ACCEPT;So;0;L; 53EF;;;;N;;;;; +1F300;CYCLONE;So;0;ON;;;;;N;;;;; +1F301;FOGGY;So;0;ON;;;;;N;;;;; +1F302;CLOSED UMBRELLA;So;0;ON;;;;;N;;;;; +1F303;NIGHT WITH STARS;So;0;ON;;;;;N;;;;; +1F304;SUNRISE OVER MOUNTAINS;So;0;ON;;;;;N;;;;; +1F305;SUNRISE;So;0;ON;;;;;N;;;;; +1F306;CITYSCAPE AT DUSK;So;0;ON;;;;;N;;;;; +1F307;SUNSET OVER BUILDINGS;So;0;ON;;;;;N;;;;; +1F308;RAINBOW;So;0;ON;;;;;N;;;;; +1F309;BRIDGE AT NIGHT;So;0;ON;;;;;N;;;;; +1F30A;WATER WAVE;So;0;ON;;;;;N;;;;; +1F30B;VOLCANO;So;0;ON;;;;;N;;;;; +1F30C;MILKY WAY;So;0;ON;;;;;N;;;;; +1F30D;EARTH GLOBE EUROPE-AFRICA;So;0;ON;;;;;N;;;;; +1F30E;EARTH GLOBE AMERICAS;So;0;ON;;;;;N;;;;; +1F30F;EARTH GLOBE ASIA-AUSTRALIA;So;0;ON;;;;;N;;;;; +1F310;GLOBE WITH MERIDIANS;So;0;ON;;;;;N;;;;; +1F311;NEW MOON SYMBOL;So;0;ON;;;;;N;;;;; +1F312;WAXING CRESCENT MOON SYMBOL;So;0;ON;;;;;N;;;;; +1F313;FIRST QUARTER MOON SYMBOL;So;0;ON;;;;;N;;;;; +1F314;WAXING GIBBOUS MOON SYMBOL;So;0;ON;;;;;N;;;;; +1F315;FULL MOON SYMBOL;So;0;ON;;;;;N;;;;; +1F316;WANING GIBBOUS MOON SYMBOL;So;0;ON;;;;;N;;;;; +1F317;LAST QUARTER MOON SYMBOL;So;0;ON;;;;;N;;;;; +1F318;WANING CRESCENT MOON SYMBOL;So;0;ON;;;;;N;;;;; +1F319;CRESCENT MOON;So;0;ON;;;;;N;;;;; +1F31A;NEW MOON WITH FACE;So;0;ON;;;;;N;;;;; +1F31B;FIRST QUARTER MOON WITH FACE;So;0;ON;;;;;N;;;;; +1F31C;LAST QUARTER MOON WITH FACE;So;0;ON;;;;;N;;;;; +1F31D;FULL MOON WITH FACE;So;0;ON;;;;;N;;;;; +1F31E;SUN WITH FACE;So;0;ON;;;;;N;;;;; +1F31F;GLOWING STAR;So;0;ON;;;;;N;;;;; +1F320;SHOOTING STAR;So;0;ON;;;;;N;;;;; +1F330;CHESTNUT;So;0;ON;;;;;N;;;;; +1F331;SEEDLING;So;0;ON;;;;;N;;;;; +1F332;EVERGREEN TREE;So;0;ON;;;;;N;;;;; +1F333;DECIDUOUS TREE;So;0;ON;;;;;N;;;;; +1F334;PALM TREE;So;0;ON;;;;;N;;;;; +1F335;CACTUS;So;0;ON;;;;;N;;;;; +1F337;TULIP;So;0;ON;;;;;N;;;;; +1F338;CHERRY BLOSSOM;So;0;ON;;;;;N;;;;; +1F339;ROSE;So;0;ON;;;;;N;;;;; +1F33A;HIBISCUS;So;0;ON;;;;;N;;;;; +1F33B;SUNFLOWER;So;0;ON;;;;;N;;;;; +1F33C;BLOSSOM;So;0;ON;;;;;N;;;;; +1F33D;EAR OF MAIZE;So;0;ON;;;;;N;;;;; +1F33E;EAR OF RICE;So;0;ON;;;;;N;;;;; +1F33F;HERB;So;0;ON;;;;;N;;;;; +1F340;FOUR LEAF CLOVER;So;0;ON;;;;;N;;;;; +1F341;MAPLE LEAF;So;0;ON;;;;;N;;;;; +1F342;FALLEN LEAF;So;0;ON;;;;;N;;;;; +1F343;LEAF FLUTTERING IN WIND;So;0;ON;;;;;N;;;;; +1F344;MUSHROOM;So;0;ON;;;;;N;;;;; +1F345;TOMATO;So;0;ON;;;;;N;;;;; +1F346;AUBERGINE;So;0;ON;;;;;N;;;;; +1F347;GRAPES;So;0;ON;;;;;N;;;;; +1F348;MELON;So;0;ON;;;;;N;;;;; +1F349;WATERMELON;So;0;ON;;;;;N;;;;; +1F34A;TANGERINE;So;0;ON;;;;;N;;;;; +1F34B;LEMON;So;0;ON;;;;;N;;;;; +1F34C;BANANA;So;0;ON;;;;;N;;;;; +1F34D;PINEAPPLE;So;0;ON;;;;;N;;;;; +1F34E;RED APPLE;So;0;ON;;;;;N;;;;; +1F34F;GREEN APPLE;So;0;ON;;;;;N;;;;; +1F350;PEAR;So;0;ON;;;;;N;;;;; +1F351;PEACH;So;0;ON;;;;;N;;;;; +1F352;CHERRIES;So;0;ON;;;;;N;;;;; +1F353;STRAWBERRY;So;0;ON;;;;;N;;;;; +1F354;HAMBURGER;So;0;ON;;;;;N;;;;; +1F355;SLICE OF PIZZA;So;0;ON;;;;;N;;;;; +1F356;MEAT ON BONE;So;0;ON;;;;;N;;;;; +1F357;POULTRY LEG;So;0;ON;;;;;N;;;;; +1F358;RICE CRACKER;So;0;ON;;;;;N;;;;; +1F359;RICE BALL;So;0;ON;;;;;N;;;;; +1F35A;COOKED RICE;So;0;ON;;;;;N;;;;; +1F35B;CURRY AND RICE;So;0;ON;;;;;N;;;;; +1F35C;STEAMING BOWL;So;0;ON;;;;;N;;;;; +1F35D;SPAGHETTI;So;0;ON;;;;;N;;;;; +1F35E;BREAD;So;0;ON;;;;;N;;;;; +1F35F;FRENCH FRIES;So;0;ON;;;;;N;;;;; +1F360;ROASTED SWEET POTATO;So;0;ON;;;;;N;;;;; +1F361;DANGO;So;0;ON;;;;;N;;;;; +1F362;ODEN;So;0;ON;;;;;N;;;;; +1F363;SUSHI;So;0;ON;;;;;N;;;;; +1F364;FRIED SHRIMP;So;0;ON;;;;;N;;;;; +1F365;FISH CAKE WITH SWIRL DESIGN;So;0;ON;;;;;N;;;;; +1F366;SOFT ICE CREAM;So;0;ON;;;;;N;;;;; +1F367;SHAVED ICE;So;0;ON;;;;;N;;;;; +1F368;ICE CREAM;So;0;ON;;;;;N;;;;; +1F369;DOUGHNUT;So;0;ON;;;;;N;;;;; +1F36A;COOKIE;So;0;ON;;;;;N;;;;; +1F36B;CHOCOLATE BAR;So;0;ON;;;;;N;;;;; +1F36C;CANDY;So;0;ON;;;;;N;;;;; +1F36D;LOLLIPOP;So;0;ON;;;;;N;;;;; +1F36E;CUSTARD;So;0;ON;;;;;N;;;;; +1F36F;HONEY POT;So;0;ON;;;;;N;;;;; +1F370;SHORTCAKE;So;0;ON;;;;;N;;;;; +1F371;BENTO BOX;So;0;ON;;;;;N;;;;; +1F372;POT OF FOOD;So;0;ON;;;;;N;;;;; +1F373;COOKING;So;0;ON;;;;;N;;;;; +1F374;FORK AND KNIFE;So;0;ON;;;;;N;;;;; +1F375;TEACUP WITHOUT HANDLE;So;0;ON;;;;;N;;;;; +1F376;SAKE BOTTLE AND CUP;So;0;ON;;;;;N;;;;; +1F377;WINE GLASS;So;0;ON;;;;;N;;;;; +1F378;COCKTAIL GLASS;So;0;ON;;;;;N;;;;; +1F379;TROPICAL DRINK;So;0;ON;;;;;N;;;;; +1F37A;BEER MUG;So;0;ON;;;;;N;;;;; +1F37B;CLINKING BEER MUGS;So;0;ON;;;;;N;;;;; +1F37C;BABY BOTTLE;So;0;ON;;;;;N;;;;; +1F380;RIBBON;So;0;ON;;;;;N;;;;; +1F381;WRAPPED PRESENT;So;0;ON;;;;;N;;;;; +1F382;BIRTHDAY CAKE;So;0;ON;;;;;N;;;;; +1F383;JACK-O-LANTERN;So;0;ON;;;;;N;;;;; +1F384;CHRISTMAS TREE;So;0;ON;;;;;N;;;;; +1F385;FATHER CHRISTMAS;So;0;ON;;;;;N;;;;; +1F386;FIREWORKS;So;0;ON;;;;;N;;;;; +1F387;FIREWORK SPARKLER;So;0;ON;;;;;N;;;;; +1F388;BALLOON;So;0;ON;;;;;N;;;;; +1F389;PARTY POPPER;So;0;ON;;;;;N;;;;; +1F38A;CONFETTI BALL;So;0;ON;;;;;N;;;;; +1F38B;TANABATA TREE;So;0;ON;;;;;N;;;;; +1F38C;CROSSED FLAGS;So;0;ON;;;;;N;;;;; +1F38D;PINE DECORATION;So;0;ON;;;;;N;;;;; +1F38E;JAPANESE DOLLS;So;0;ON;;;;;N;;;;; +1F38F;CARP STREAMER;So;0;ON;;;;;N;;;;; +1F390;WIND CHIME;So;0;ON;;;;;N;;;;; +1F391;MOON VIEWING CEREMONY;So;0;ON;;;;;N;;;;; +1F392;SCHOOL SATCHEL;So;0;ON;;;;;N;;;;; +1F393;GRADUATION CAP;So;0;ON;;;;;N;;;;; +1F3A0;CAROUSEL HORSE;So;0;ON;;;;;N;;;;; +1F3A1;FERRIS WHEEL;So;0;ON;;;;;N;;;;; +1F3A2;ROLLER COASTER;So;0;ON;;;;;N;;;;; +1F3A3;FISHING POLE AND FISH;So;0;ON;;;;;N;;;;; +1F3A4;MICROPHONE;So;0;ON;;;;;N;;;;; +1F3A5;MOVIE CAMERA;So;0;ON;;;;;N;;;;; +1F3A6;CINEMA;So;0;ON;;;;;N;;;;; +1F3A7;HEADPHONE;So;0;ON;;;;;N;;;;; +1F3A8;ARTIST PALETTE;So;0;ON;;;;;N;;;;; +1F3A9;TOP HAT;So;0;ON;;;;;N;;;;; +1F3AA;CIRCUS TENT;So;0;ON;;;;;N;;;;; +1F3AB;TICKET;So;0;ON;;;;;N;;;;; +1F3AC;CLAPPER BOARD;So;0;ON;;;;;N;;;;; +1F3AD;PERFORMING ARTS;So;0;ON;;;;;N;;;;; +1F3AE;VIDEO GAME;So;0;ON;;;;;N;;;;; +1F3AF;DIRECT HIT;So;0;ON;;;;;N;;;;; +1F3B0;SLOT MACHINE;So;0;ON;;;;;N;;;;; +1F3B1;BILLIARDS;So;0;ON;;;;;N;;;;; +1F3B2;GAME DIE;So;0;ON;;;;;N;;;;; +1F3B3;BOWLING;So;0;ON;;;;;N;;;;; +1F3B4;FLOWER PLAYING CARDS;So;0;ON;;;;;N;;;;; +1F3B5;MUSICAL NOTE;So;0;ON;;;;;N;;;;; +1F3B6;MULTIPLE MUSICAL NOTES;So;0;ON;;;;;N;;;;; +1F3B7;SAXOPHONE;So;0;ON;;;;;N;;;;; +1F3B8;GUITAR;So;0;ON;;;;;N;;;;; +1F3B9;MUSICAL KEYBOARD;So;0;ON;;;;;N;;;;; +1F3BA;TRUMPET;So;0;ON;;;;;N;;;;; +1F3BB;VIOLIN;So;0;ON;;;;;N;;;;; +1F3BC;MUSICAL SCORE;So;0;ON;;;;;N;;;;; +1F3BD;RUNNING SHIRT WITH SASH;So;0;ON;;;;;N;;;;; +1F3BE;TENNIS RACQUET AND BALL;So;0;ON;;;;;N;;;;; +1F3BF;SKI AND SKI BOOT;So;0;ON;;;;;N;;;;; +1F3C0;BASKETBALL AND HOOP;So;0;ON;;;;;N;;;;; +1F3C1;CHEQUERED FLAG;So;0;ON;;;;;N;;;;; +1F3C2;SNOWBOARDER;So;0;ON;;;;;N;;;;; +1F3C3;RUNNER;So;0;ON;;;;;N;;;;; +1F3C4;SURFER;So;0;ON;;;;;N;;;;; +1F3C6;TROPHY;So;0;ON;;;;;N;;;;; +1F3C7;HORSE RACING;So;0;ON;;;;;N;;;;; +1F3C8;AMERICAN FOOTBALL;So;0;ON;;;;;N;;;;; +1F3C9;RUGBY FOOTBALL;So;0;ON;;;;;N;;;;; +1F3CA;SWIMMER;So;0;ON;;;;;N;;;;; +1F3E0;HOUSE BUILDING;So;0;ON;;;;;N;;;;; +1F3E1;HOUSE WITH GARDEN;So;0;ON;;;;;N;;;;; +1F3E2;OFFICE BUILDING;So;0;ON;;;;;N;;;;; +1F3E3;JAPANESE POST OFFICE;So;0;ON;;;;;N;;;;; +1F3E4;EUROPEAN POST OFFICE;So;0;ON;;;;;N;;;;; +1F3E5;HOSPITAL;So;0;ON;;;;;N;;;;; +1F3E6;BANK;So;0;ON;;;;;N;;;;; +1F3E7;AUTOMATED TELLER MACHINE;So;0;ON;;;;;N;;;;; +1F3E8;HOTEL;So;0;ON;;;;;N;;;;; +1F3E9;LOVE HOTEL;So;0;ON;;;;;N;;;;; +1F3EA;CONVENIENCE STORE;So;0;ON;;;;;N;;;;; +1F3EB;SCHOOL;So;0;ON;;;;;N;;;;; +1F3EC;DEPARTMENT STORE;So;0;ON;;;;;N;;;;; +1F3ED;FACTORY;So;0;ON;;;;;N;;;;; +1F3EE;IZAKAYA LANTERN;So;0;ON;;;;;N;;;;; +1F3EF;JAPANESE CASTLE;So;0;ON;;;;;N;;;;; +1F3F0;EUROPEAN CASTLE;So;0;ON;;;;;N;;;;; +1F400;RAT;So;0;ON;;;;;N;;;;; +1F401;MOUSE;So;0;ON;;;;;N;;;;; +1F402;OX;So;0;ON;;;;;N;;;;; +1F403;WATER BUFFALO;So;0;ON;;;;;N;;;;; +1F404;COW;So;0;ON;;;;;N;;;;; +1F405;TIGER;So;0;ON;;;;;N;;;;; +1F406;LEOPARD;So;0;ON;;;;;N;;;;; +1F407;RABBIT;So;0;ON;;;;;N;;;;; +1F408;CAT;So;0;ON;;;;;N;;;;; +1F409;DRAGON;So;0;ON;;;;;N;;;;; +1F40A;CROCODILE;So;0;ON;;;;;N;;;;; +1F40B;WHALE;So;0;ON;;;;;N;;;;; +1F40C;SNAIL;So;0;ON;;;;;N;;;;; +1F40D;SNAKE;So;0;ON;;;;;N;;;;; +1F40E;HORSE;So;0;ON;;;;;N;;;;; +1F40F;RAM;So;0;ON;;;;;N;;;;; +1F410;GOAT;So;0;ON;;;;;N;;;;; +1F411;SHEEP;So;0;ON;;;;;N;;;;; +1F412;MONKEY;So;0;ON;;;;;N;;;;; +1F413;ROOSTER;So;0;ON;;;;;N;;;;; +1F414;CHICKEN;So;0;ON;;;;;N;;;;; +1F415;DOG;So;0;ON;;;;;N;;;;; +1F416;PIG;So;0;ON;;;;;N;;;;; +1F417;BOAR;So;0;ON;;;;;N;;;;; +1F418;ELEPHANT;So;0;ON;;;;;N;;;;; +1F419;OCTOPUS;So;0;ON;;;;;N;;;;; +1F41A;SPIRAL SHELL;So;0;ON;;;;;N;;;;; +1F41B;BUG;So;0;ON;;;;;N;;;;; +1F41C;ANT;So;0;ON;;;;;N;;;;; +1F41D;HONEYBEE;So;0;ON;;;;;N;;;;; +1F41E;LADY BEETLE;So;0;ON;;;;;N;;;;; +1F41F;FISH;So;0;ON;;;;;N;;;;; +1F420;TROPICAL FISH;So;0;ON;;;;;N;;;;; +1F421;BLOWFISH;So;0;ON;;;;;N;;;;; +1F422;TURTLE;So;0;ON;;;;;N;;;;; +1F423;HATCHING CHICK;So;0;ON;;;;;N;;;;; +1F424;BABY CHICK;So;0;ON;;;;;N;;;;; +1F425;FRONT-FACING BABY CHICK;So;0;ON;;;;;N;;;;; +1F426;BIRD;So;0;ON;;;;;N;;;;; +1F427;PENGUIN;So;0;ON;;;;;N;;;;; +1F428;KOALA;So;0;ON;;;;;N;;;;; +1F429;POODLE;So;0;ON;;;;;N;;;;; +1F42A;DROMEDARY CAMEL;So;0;ON;;;;;N;;;;; +1F42B;BACTRIAN CAMEL;So;0;ON;;;;;N;;;;; +1F42C;DOLPHIN;So;0;ON;;;;;N;;;;; +1F42D;MOUSE FACE;So;0;ON;;;;;N;;;;; +1F42E;COW FACE;So;0;ON;;;;;N;;;;; +1F42F;TIGER FACE;So;0;ON;;;;;N;;;;; +1F430;RABBIT FACE;So;0;ON;;;;;N;;;;; +1F431;CAT FACE;So;0;ON;;;;;N;;;;; +1F432;DRAGON FACE;So;0;ON;;;;;N;;;;; +1F433;SPOUTING WHALE;So;0;ON;;;;;N;;;;; +1F434;HORSE FACE;So;0;ON;;;;;N;;;;; +1F435;MONKEY FACE;So;0;ON;;;;;N;;;;; +1F436;DOG FACE;So;0;ON;;;;;N;;;;; +1F437;PIG FACE;So;0;ON;;;;;N;;;;; +1F438;FROG FACE;So;0;ON;;;;;N;;;;; +1F439;HAMSTER FACE;So;0;ON;;;;;N;;;;; +1F43A;WOLF FACE;So;0;ON;;;;;N;;;;; +1F43B;BEAR FACE;So;0;ON;;;;;N;;;;; +1F43C;PANDA FACE;So;0;ON;;;;;N;;;;; +1F43D;PIG NOSE;So;0;ON;;;;;N;;;;; +1F43E;PAW PRINTS;So;0;ON;;;;;N;;;;; +1F440;EYES;So;0;ON;;;;;N;;;;; +1F442;EAR;So;0;ON;;;;;N;;;;; +1F443;NOSE;So;0;ON;;;;;N;;;;; +1F444;MOUTH;So;0;ON;;;;;N;;;;; +1F445;TONGUE;So;0;ON;;;;;N;;;;; +1F446;WHITE UP POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; +1F447;WHITE DOWN POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; +1F448;WHITE LEFT POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; +1F449;WHITE RIGHT POINTING BACKHAND INDEX;So;0;ON;;;;;N;;;;; +1F44A;FISTED HAND SIGN;So;0;ON;;;;;N;;;;; +1F44B;WAVING HAND SIGN;So;0;ON;;;;;N;;;;; +1F44C;OK HAND SIGN;So;0;ON;;;;;N;;;;; +1F44D;THUMBS UP SIGN;So;0;ON;;;;;N;;;;; +1F44E;THUMBS DOWN SIGN;So;0;ON;;;;;N;;;;; +1F44F;CLAPPING HANDS SIGN;So;0;ON;;;;;N;;;;; +1F450;OPEN HANDS SIGN;So;0;ON;;;;;N;;;;; +1F451;CROWN;So;0;ON;;;;;N;;;;; +1F452;WOMANS HAT;So;0;ON;;;;;N;;;;; +1F453;EYEGLASSES;So;0;ON;;;;;N;;;;; +1F454;NECKTIE;So;0;ON;;;;;N;;;;; +1F455;T-SHIRT;So;0;ON;;;;;N;;;;; +1F456;JEANS;So;0;ON;;;;;N;;;;; +1F457;DRESS;So;0;ON;;;;;N;;;;; +1F458;KIMONO;So;0;ON;;;;;N;;;;; +1F459;BIKINI;So;0;ON;;;;;N;;;;; +1F45A;WOMANS CLOTHES;So;0;ON;;;;;N;;;;; +1F45B;PURSE;So;0;ON;;;;;N;;;;; +1F45C;HANDBAG;So;0;ON;;;;;N;;;;; +1F45D;POUCH;So;0;ON;;;;;N;;;;; +1F45E;MANS SHOE;So;0;ON;;;;;N;;;;; +1F45F;ATHLETIC SHOE;So;0;ON;;;;;N;;;;; +1F460;HIGH-HEELED SHOE;So;0;ON;;;;;N;;;;; +1F461;WOMANS SANDAL;So;0;ON;;;;;N;;;;; +1F462;WOMANS BOOTS;So;0;ON;;;;;N;;;;; +1F463;FOOTPRINTS;So;0;ON;;;;;N;;;;; +1F464;BUST IN SILHOUETTE;So;0;ON;;;;;N;;;;; +1F465;BUSTS IN SILHOUETTE;So;0;ON;;;;;N;;;;; +1F466;BOY;So;0;ON;;;;;N;;;;; +1F467;GIRL;So;0;ON;;;;;N;;;;; +1F468;MAN;So;0;ON;;;;;N;;;;; +1F469;WOMAN;So;0;ON;;;;;N;;;;; +1F46A;FAMILY;So;0;ON;;;;;N;;;;; +1F46B;MAN AND WOMAN HOLDING HANDS;So;0;ON;;;;;N;;;;; +1F46C;TWO MEN HOLDING HANDS;So;0;ON;;;;;N;;;;; +1F46D;TWO WOMEN HOLDING HANDS;So;0;ON;;;;;N;;;;; +1F46E;POLICE OFFICER;So;0;ON;;;;;N;;;;; +1F46F;WOMAN WITH BUNNY EARS;So;0;ON;;;;;N;;;;; +1F470;BRIDE WITH VEIL;So;0;ON;;;;;N;;;;; +1F471;PERSON WITH BLOND HAIR;So;0;ON;;;;;N;;;;; +1F472;MAN WITH GUA PI MAO;So;0;ON;;;;;N;;;;; +1F473;MAN WITH TURBAN;So;0;ON;;;;;N;;;;; +1F474;OLDER MAN;So;0;ON;;;;;N;;;;; +1F475;OLDER WOMAN;So;0;ON;;;;;N;;;;; +1F476;BABY;So;0;ON;;;;;N;;;;; +1F477;CONSTRUCTION WORKER;So;0;ON;;;;;N;;;;; +1F478;PRINCESS;So;0;ON;;;;;N;;;;; +1F479;JAPANESE OGRE;So;0;ON;;;;;N;;;;; +1F47A;JAPANESE GOBLIN;So;0;ON;;;;;N;;;;; +1F47B;GHOST;So;0;ON;;;;;N;;;;; +1F47C;BABY ANGEL;So;0;ON;;;;;N;;;;; +1F47D;EXTRATERRESTRIAL ALIEN;So;0;ON;;;;;N;;;;; +1F47E;ALIEN MONSTER;So;0;ON;;;;;N;;;;; +1F47F;IMP;So;0;ON;;;;;N;;;;; +1F480;SKULL;So;0;ON;;;;;N;;;;; +1F481;INFORMATION DESK PERSON;So;0;ON;;;;;N;;;;; +1F482;GUARDSMAN;So;0;ON;;;;;N;;;;; +1F483;DANCER;So;0;ON;;;;;N;;;;; +1F484;LIPSTICK;So;0;ON;;;;;N;;;;; +1F485;NAIL POLISH;So;0;ON;;;;;N;;;;; +1F486;FACE MASSAGE;So;0;ON;;;;;N;;;;; +1F487;HAIRCUT;So;0;ON;;;;;N;;;;; +1F488;BARBER POLE;So;0;ON;;;;;N;;;;; +1F489;SYRINGE;So;0;ON;;;;;N;;;;; +1F48A;PILL;So;0;ON;;;;;N;;;;; +1F48B;KISS MARK;So;0;ON;;;;;N;;;;; +1F48C;LOVE LETTER;So;0;L;;;;;N;;;;; +1F48D;RING;So;0;ON;;;;;N;;;;; +1F48E;GEM STONE;So;0;ON;;;;;N;;;;; +1F48F;KISS;So;0;ON;;;;;N;;;;; +1F490;BOUQUET;So;0;ON;;;;;N;;;;; +1F491;COUPLE WITH HEART;So;0;ON;;;;;N;;;;; +1F492;WEDDING;So;0;ON;;;;;N;;;;; +1F493;BEATING HEART;So;0;ON;;;;;N;;;;; +1F494;BROKEN HEART;So;0;ON;;;;;N;;;;; +1F495;TWO HEARTS;So;0;ON;;;;;N;;;;; +1F496;SPARKLING HEART;So;0;ON;;;;;N;;;;; +1F497;GROWING HEART;So;0;ON;;;;;N;;;;; +1F498;HEART WITH ARROW;So;0;ON;;;;;N;;;;; +1F499;BLUE HEART;So;0;ON;;;;;N;;;;; +1F49A;GREEN HEART;So;0;ON;;;;;N;;;;; +1F49B;YELLOW HEART;So;0;ON;;;;;N;;;;; +1F49C;PURPLE HEART;So;0;ON;;;;;N;;;;; +1F49D;HEART WITH RIBBON;So;0;ON;;;;;N;;;;; +1F49E;REVOLVING HEARTS;So;0;ON;;;;;N;;;;; +1F49F;HEART DECORATION;So;0;ON;;;;;N;;;;; +1F4A0;DIAMOND SHAPE WITH A DOT INSIDE;So;0;ON;;;;;N;;;;; +1F4A1;ELECTRIC LIGHT BULB;So;0;ON;;;;;N;;;;; +1F4A2;ANGER SYMBOL;So;0;ON;;;;;N;;;;; +1F4A3;BOMB;So;0;ON;;;;;N;;;;; +1F4A4;SLEEPING SYMBOL;So;0;ON;;;;;N;;;;; +1F4A5;COLLISION SYMBOL;So;0;ON;;;;;N;;;;; +1F4A6;SPLASHING SWEAT SYMBOL;So;0;ON;;;;;N;;;;; +1F4A7;DROPLET;So;0;ON;;;;;N;;;;; +1F4A8;DASH SYMBOL;So;0;ON;;;;;N;;;;; +1F4A9;PILE OF POO;So;0;ON;;;;;N;;;;; +1F4AA;FLEXED BICEPS;So;0;ON;;;;;N;;;;; +1F4AB;DIZZY SYMBOL;So;0;ON;;;;;N;;;;; +1F4AC;SPEECH BALLOON;So;0;ON;;;;;N;;;;; +1F4AD;THOUGHT BALLOON;So;0;ON;;;;;N;;;;; +1F4AE;WHITE FLOWER;So;0;ON;;;;;N;;;;; +1F4AF;HUNDRED POINTS SYMBOL;So;0;ON;;;;;N;;;;; +1F4B0;MONEY BAG;So;0;ON;;;;;N;;;;; +1F4B1;CURRENCY EXCHANGE;So;0;ON;;;;;N;;;;; +1F4B2;HEAVY DOLLAR SIGN;So;0;ON;;;;;N;;;;; +1F4B3;CREDIT CARD;So;0;ON;;;;;N;;;;; +1F4B4;BANKNOTE WITH YEN SIGN;So;0;ON;;;;;N;;;;; +1F4B5;BANKNOTE WITH DOLLAR SIGN;So;0;ON;;;;;N;;;;; +1F4B6;BANKNOTE WITH EURO SIGN;So;0;ON;;;;;N;;;;; +1F4B7;BANKNOTE WITH POUND SIGN;So;0;ON;;;;;N;;;;; +1F4B8;MONEY WITH WINGS;So;0;ON;;;;;N;;;;; +1F4B9;CHART WITH UPWARDS TREND AND YEN SIGN;So;0;ON;;;;;N;;;;; +1F4BA;SEAT;So;0;ON;;;;;N;;;;; +1F4BB;PERSONAL COMPUTER;So;0;ON;;;;;N;;;;; +1F4BC;BRIEFCASE;So;0;ON;;;;;N;;;;; +1F4BD;MINIDISC;So;0;ON;;;;;N;;;;; +1F4BE;FLOPPY DISK;So;0;ON;;;;;N;;;;; +1F4BF;OPTICAL DISC;So;0;ON;;;;;N;;;;; +1F4C0;DVD;So;0;ON;;;;;N;;;;; +1F4C1;FILE FOLDER;So;0;ON;;;;;N;;;;; +1F4C2;OPEN FILE FOLDER;So;0;ON;;;;;N;;;;; +1F4C3;PAGE WITH CURL;So;0;ON;;;;;N;;;;; +1F4C4;PAGE FACING UP;So;0;ON;;;;;N;;;;; +1F4C5;CALENDAR;So;0;ON;;;;;N;;;;; +1F4C6;TEAR-OFF CALENDAR;So;0;ON;;;;;N;;;;; +1F4C7;CARD INDEX;So;0;ON;;;;;N;;;;; +1F4C8;CHART WITH UPWARDS TREND;So;0;ON;;;;;N;;;;; +1F4C9;CHART WITH DOWNWARDS TREND;So;0;ON;;;;;N;;;;; +1F4CA;BAR CHART;So;0;ON;;;;;N;;;;; +1F4CB;CLIPBOARD;So;0;ON;;;;;N;;;;; +1F4CC;PUSHPIN;So;0;ON;;;;;N;;;;; +1F4CD;ROUND PUSHPIN;So;0;ON;;;;;N;;;;; +1F4CE;PAPERCLIP;So;0;ON;;;;;N;;;;; +1F4CF;STRAIGHT RULER;So;0;ON;;;;;N;;;;; +1F4D0;TRIANGULAR RULER;So;0;ON;;;;;N;;;;; +1F4D1;BOOKMARK TABS;So;0;ON;;;;;N;;;;; +1F4D2;LEDGER;So;0;ON;;;;;N;;;;; +1F4D3;NOTEBOOK;So;0;ON;;;;;N;;;;; +1F4D4;NOTEBOOK WITH DECORATIVE COVER;So;0;ON;;;;;N;;;;; +1F4D5;CLOSED BOOK;So;0;ON;;;;;N;;;;; +1F4D6;OPEN BOOK;So;0;ON;;;;;N;;;;; +1F4D7;GREEN BOOK;So;0;ON;;;;;N;;;;; +1F4D8;BLUE BOOK;So;0;ON;;;;;N;;;;; +1F4D9;ORANGE BOOK;So;0;ON;;;;;N;;;;; +1F4DA;BOOKS;So;0;ON;;;;;N;;;;; +1F4DB;NAME BADGE;So;0;ON;;;;;N;;;;; +1F4DC;SCROLL;So;0;ON;;;;;N;;;;; +1F4DD;MEMO;So;0;ON;;;;;N;;;;; +1F4DE;TELEPHONE RECEIVER;So;0;ON;;;;;N;;;;; +1F4DF;PAGER;So;0;ON;;;;;N;;;;; +1F4E0;FAX MACHINE;So;0;ON;;;;;N;;;;; +1F4E1;SATELLITE ANTENNA;So;0;ON;;;;;N;;;;; +1F4E2;PUBLIC ADDRESS LOUDSPEAKER;So;0;ON;;;;;N;;;;; +1F4E3;CHEERING MEGAPHONE;So;0;ON;;;;;N;;;;; +1F4E4;OUTBOX TRAY;So;0;ON;;;;;N;;;;; +1F4E5;INBOX TRAY;So;0;ON;;;;;N;;;;; +1F4E6;PACKAGE;So;0;ON;;;;;N;;;;; +1F4E7;E-MAIL SYMBOL;So;0;ON;;;;;N;;;;; +1F4E8;INCOMING ENVELOPE;So;0;ON;;;;;N;;;;; +1F4E9;ENVELOPE WITH DOWNWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;; +1F4EA;CLOSED MAILBOX WITH LOWERED FLAG;So;0;ON;;;;;N;;;;; +1F4EB;CLOSED MAILBOX WITH RAISED FLAG;So;0;ON;;;;;N;;;;; +1F4EC;OPEN MAILBOX WITH RAISED FLAG;So;0;ON;;;;;N;;;;; +1F4ED;OPEN MAILBOX WITH LOWERED FLAG;So;0;ON;;;;;N;;;;; +1F4EE;POSTBOX;So;0;ON;;;;;N;;;;; +1F4EF;POSTAL HORN;So;0;ON;;;;;N;;;;; +1F4F0;NEWSPAPER;So;0;ON;;;;;N;;;;; +1F4F1;MOBILE PHONE;So;0;ON;;;;;N;;;;; +1F4F2;MOBILE PHONE WITH RIGHTWARDS ARROW AT LEFT;So;0;ON;;;;;N;;;;; +1F4F3;VIBRATION MODE;So;0;ON;;;;;N;;;;; +1F4F4;MOBILE PHONE OFF;So;0;ON;;;;;N;;;;; +1F4F5;NO MOBILE PHONES;So;0;ON;;;;;N;;;;; +1F4F6;ANTENNA WITH BARS;So;0;ON;;;;;N;;;;; +1F4F7;CAMERA;So;0;ON;;;;;N;;;;; +1F4F9;VIDEO CAMERA;So;0;ON;;;;;N;;;;; +1F4FA;TELEVISION;So;0;ON;;;;;N;;;;; +1F4FB;RADIO;So;0;ON;;;;;N;;;;; +1F4FC;VIDEOCASSETTE;So;0;ON;;;;;N;;;;; +1F500;TWISTED RIGHTWARDS ARROWS;So;0;ON;;;;;N;;;;; +1F501;CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS;So;0;ON;;;;;N;;;;; +1F502;CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS WITH CIRCLED ONE OVERLAY;So;0;ON;;;;;N;;;;; +1F503;CLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS;So;0;ON;;;;;N;;;;; +1F504;ANTICLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS;So;0;ON;;;;;N;;;;; +1F505;LOW BRIGHTNESS SYMBOL;So;0;ON;;;;;N;;;;; +1F506;HIGH BRIGHTNESS SYMBOL;So;0;ON;;;;;N;;;;; +1F507;SPEAKER WITH CANCELLATION STROKE;So;0;ON;;;;;N;;;;; +1F508;SPEAKER;So;0;ON;;;;;N;;;;; +1F509;SPEAKER WITH ONE SOUND WAVE;So;0;ON;;;;;N;;;;; +1F50A;SPEAKER WITH THREE SOUND WAVES;So;0;ON;;;;;N;;;;; +1F50B;BATTERY;So;0;ON;;;;;N;;;;; +1F50C;ELECTRIC PLUG;So;0;ON;;;;;N;;;;; +1F50D;LEFT-POINTING MAGNIFYING GLASS;So;0;ON;;;;;N;;;;; +1F50E;RIGHT-POINTING MAGNIFYING GLASS;So;0;ON;;;;;N;;;;; +1F50F;LOCK WITH INK PEN;So;0;ON;;;;;N;;;;; +1F510;CLOSED LOCK WITH KEY;So;0;ON;;;;;N;;;;; +1F511;KEY;So;0;ON;;;;;N;;;;; +1F512;LOCK;So;0;ON;;;;;N;;;;; +1F513;OPEN LOCK;So;0;ON;;;;;N;;;;; +1F514;BELL;So;0;ON;;;;;N;;;;; +1F515;BELL WITH CANCELLATION STROKE;So;0;ON;;;;;N;;;;; +1F516;BOOKMARK;So;0;ON;;;;;N;;;;; +1F517;LINK SYMBOL;So;0;ON;;;;;N;;;;; +1F518;RADIO BUTTON;So;0;ON;;;;;N;;;;; +1F519;BACK WITH LEFTWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;; +1F51A;END WITH LEFTWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;; +1F51B;ON WITH EXCLAMATION MARK WITH LEFT RIGHT ARROW ABOVE;So;0;ON;;;;;N;;;;; +1F51C;SOON WITH RIGHTWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;; +1F51D;TOP WITH UPWARDS ARROW ABOVE;So;0;ON;;;;;N;;;;; +1F51E;NO ONE UNDER EIGHTEEN SYMBOL;So;0;ON;;;;;N;;;;; +1F51F;KEYCAP TEN;So;0;ON;;;;;N;;;;; +1F520;INPUT SYMBOL FOR LATIN CAPITAL LETTERS;So;0;ON;;;;;N;;;;; +1F521;INPUT SYMBOL FOR LATIN SMALL LETTERS;So;0;ON;;;;;N;;;;; +1F522;INPUT SYMBOL FOR NUMBERS;So;0;ON;;;;;N;;;;; +1F523;INPUT SYMBOL FOR SYMBOLS;So;0;ON;;;;;N;;;;; +1F524;INPUT SYMBOL FOR LATIN LETTERS;So;0;L;;;;;N;;;;; +1F525;FIRE;So;0;ON;;;;;N;;;;; +1F526;ELECTRIC TORCH;So;0;ON;;;;;N;;;;; +1F527;WRENCH;So;0;ON;;;;;N;;;;; +1F528;HAMMER;So;0;ON;;;;;N;;;;; +1F529;NUT AND BOLT;So;0;ON;;;;;N;;;;; +1F52A;HOCHO;So;0;ON;;;;;N;;;;; +1F52B;PISTOL;So;0;ON;;;;;N;;;;; +1F52C;MICROSCOPE;So;0;ON;;;;;N;;;;; +1F52D;TELESCOPE;So;0;ON;;;;;N;;;;; +1F52E;CRYSTAL BALL;So;0;ON;;;;;N;;;;; +1F52F;SIX POINTED STAR WITH MIDDLE DOT;So;0;ON;;;;;N;;;;; +1F530;JAPANESE SYMBOL FOR BEGINNER;So;0;ON;;;;;N;;;;; +1F531;TRIDENT EMBLEM;So;0;ON;;;;;N;;;;; +1F532;BLACK SQUARE BUTTON;So;0;ON;;;;;N;;;;; +1F533;WHITE SQUARE BUTTON;So;0;ON;;;;;N;;;;; +1F534;LARGE RED CIRCLE;So;0;ON;;;;;N;;;;; +1F535;LARGE BLUE CIRCLE;So;0;ON;;;;;N;;;;; +1F536;LARGE ORANGE DIAMOND;So;0;ON;;;;;N;;;;; +1F537;LARGE BLUE DIAMOND;So;0;ON;;;;;N;;;;; +1F538;SMALL ORANGE DIAMOND;So;0;ON;;;;;N;;;;; +1F539;SMALL BLUE DIAMOND;So;0;ON;;;;;N;;;;; +1F53A;UP-POINTING RED TRIANGLE;So;0;ON;;;;;N;;;;; +1F53B;DOWN-POINTING RED TRIANGLE;So;0;ON;;;;;N;;;;; +1F53C;UP-POINTING SMALL RED TRIANGLE;So;0;ON;;;;;N;;;;; +1F53D;DOWN-POINTING SMALL RED TRIANGLE;So;0;ON;;;;;N;;;;; +1F550;CLOCK FACE ONE OCLOCK;So;0;ON;;;;;N;;;;; +1F551;CLOCK FACE TWO OCLOCK;So;0;ON;;;;;N;;;;; +1F552;CLOCK FACE THREE OCLOCK;So;0;ON;;;;;N;;;;; +1F553;CLOCK FACE FOUR OCLOCK;So;0;ON;;;;;N;;;;; +1F554;CLOCK FACE FIVE OCLOCK;So;0;ON;;;;;N;;;;; +1F555;CLOCK FACE SIX OCLOCK;So;0;ON;;;;;N;;;;; +1F556;CLOCK FACE SEVEN OCLOCK;So;0;ON;;;;;N;;;;; +1F557;CLOCK FACE EIGHT OCLOCK;So;0;ON;;;;;N;;;;; +1F558;CLOCK FACE NINE OCLOCK;So;0;ON;;;;;N;;;;; +1F559;CLOCK FACE TEN OCLOCK;So;0;ON;;;;;N;;;;; +1F55A;CLOCK FACE ELEVEN OCLOCK;So;0;ON;;;;;N;;;;; +1F55B;CLOCK FACE TWELVE OCLOCK;So;0;ON;;;;;N;;;;; +1F55C;CLOCK FACE ONE-THIRTY;So;0;ON;;;;;N;;;;; +1F55D;CLOCK FACE TWO-THIRTY;So;0;ON;;;;;N;;;;; +1F55E;CLOCK FACE THREE-THIRTY;So;0;ON;;;;;N;;;;; +1F55F;CLOCK FACE FOUR-THIRTY;So;0;ON;;;;;N;;;;; +1F560;CLOCK FACE FIVE-THIRTY;So;0;ON;;;;;N;;;;; +1F561;CLOCK FACE SIX-THIRTY;So;0;ON;;;;;N;;;;; +1F562;CLOCK FACE SEVEN-THIRTY;So;0;ON;;;;;N;;;;; +1F563;CLOCK FACE EIGHT-THIRTY;So;0;ON;;;;;N;;;;; +1F564;CLOCK FACE NINE-THIRTY;So;0;ON;;;;;N;;;;; +1F565;CLOCK FACE TEN-THIRTY;So;0;ON;;;;;N;;;;; +1F566;CLOCK FACE ELEVEN-THIRTY;So;0;ON;;;;;N;;;;; +1F567;CLOCK FACE TWELVE-THIRTY;So;0;ON;;;;;N;;;;; +1F5FB;MOUNT FUJI;So;0;ON;;;;;N;;;;; +1F5FC;TOKYO TOWER;So;0;ON;;;;;N;;;;; +1F5FD;STATUE OF LIBERTY;So;0;ON;;;;;N;;;;; +1F5FE;SILHOUETTE OF JAPAN;So;0;ON;;;;;N;;;;; +1F5FF;MOYAI;So;0;ON;;;;;N;;;;; +1F601;GRINNING FACE WITH SMILING EYES;So;0;ON;;;;;N;;;;; +1F602;FACE WITH TEARS OF JOY;So;0;ON;;;;;N;;;;; +1F603;SMILING FACE WITH OPEN MOUTH;So;0;ON;;;;;N;;;;; +1F604;SMILING FACE WITH OPEN MOUTH AND SMILING EYES;So;0;ON;;;;;N;;;;; +1F605;SMILING FACE WITH OPEN MOUTH AND COLD SWEAT;So;0;ON;;;;;N;;;;; +1F606;SMILING FACE WITH OPEN MOUTH AND TIGHTLY-CLOSED EYES;So;0;ON;;;;;N;;;;; +1F607;SMILING FACE WITH HALO;So;0;ON;;;;;N;;;;; +1F608;SMILING FACE WITH HORNS;So;0;ON;;;;;N;;;;; +1F609;WINKING FACE;So;0;ON;;;;;N;;;;; +1F60A;SMILING FACE WITH SMILING EYES;So;0;ON;;;;;N;;;;; +1F60B;FACE SAVOURING DELICIOUS FOOD;So;0;ON;;;;;N;;;;; +1F60C;RELIEVED FACE;So;0;ON;;;;;N;;;;; +1F60D;SMILING FACE WITH HEART-SHAPED EYES;So;0;ON;;;;;N;;;;; +1F60E;SMILING FACE WITH SUNGLASSES;So;0;ON;;;;;N;;;;; +1F60F;SMIRKING FACE;So;0;ON;;;;;N;;;;; +1F610;NEUTRAL FACE;So;0;ON;;;;;N;;;;; +1F612;UNAMUSED FACE;So;0;ON;;;;;N;;;;; +1F613;FACE WITH COLD SWEAT;So;0;ON;;;;;N;;;;; +1F614;PENSIVE FACE;So;0;ON;;;;;N;;;;; +1F616;CONFOUNDED FACE;So;0;ON;;;;;N;;;;; +1F618;FACE THROWING A KISS;So;0;ON;;;;;N;;;;; +1F61A;KISSING FACE WITH CLOSED EYES;So;0;ON;;;;;N;;;;; +1F61C;FACE WITH STUCK-OUT TONGUE AND WINKING EYE;So;0;ON;;;;;N;;;;; +1F61D;FACE WITH STUCK-OUT TONGUE AND TIGHTLY-CLOSED EYES;So;0;ON;;;;;N;;;;; +1F61E;DISAPPOINTED FACE;So;0;ON;;;;;N;;;;; +1F620;ANGRY FACE;So;0;ON;;;;;N;;;;; +1F621;POUTING FACE;So;0;ON;;;;;N;;;;; +1F622;CRYING FACE;So;0;ON;;;;;N;;;;; +1F623;PERSEVERING FACE;So;0;ON;;;;;N;;;;; +1F624;FACE WITH LOOK OF TRIUMPH;So;0;ON;;;;;N;;;;; +1F625;DISAPPOINTED BUT RELIEVED FACE;So;0;ON;;;;;N;;;;; +1F628;FEARFUL FACE;So;0;ON;;;;;N;;;;; +1F629;WEARY FACE;So;0;ON;;;;;N;;;;; +1F62A;SLEEPY FACE;So;0;ON;;;;;N;;;;; +1F62B;TIRED FACE;So;0;ON;;;;;N;;;;; +1F62D;LOUDLY CRYING FACE;So;0;ON;;;;;N;;;;; +1F630;FACE WITH OPEN MOUTH AND COLD SWEAT;So;0;ON;;;;;N;;;;; +1F631;FACE SCREAMING IN FEAR;So;0;ON;;;;;N;;;;; +1F632;ASTONISHED FACE;So;0;ON;;;;;N;;;;; +1F633;FLUSHED FACE;So;0;ON;;;;;N;;;;; +1F635;DIZZY FACE;So;0;ON;;;;;N;;;;; +1F636;FACE WITHOUT MOUTH;So;0;ON;;;;;N;;;;; +1F637;FACE WITH MEDICAL MASK;So;0;ON;;;;;N;;;;; +1F638;GRINNING CAT FACE WITH SMILING EYES;So;0;ON;;;;;N;;;;; +1F639;CAT FACE WITH TEARS OF JOY;So;0;ON;;;;;N;;;;; +1F63A;SMILING CAT FACE WITH OPEN MOUTH;So;0;ON;;;;;N;;;;; +1F63B;SMILING CAT FACE WITH HEART-SHAPED EYES;So;0;ON;;;;;N;;;;; +1F63C;CAT FACE WITH WRY SMILE;So;0;ON;;;;;N;;;;; +1F63D;KISSING CAT FACE WITH CLOSED EYES;So;0;ON;;;;;N;;;;; +1F63E;POUTING CAT FACE;So;0;ON;;;;;N;;;;; +1F63F;CRYING CAT FACE;So;0;ON;;;;;N;;;;; +1F640;WEARY CAT FACE;So;0;ON;;;;;N;;;;; +1F645;FACE WITH NO GOOD GESTURE;So;0;ON;;;;;N;;;;; +1F646;FACE WITH OK GESTURE;So;0;ON;;;;;N;;;;; +1F647;PERSON BOWING DEEPLY;So;0;ON;;;;;N;;;;; +1F648;SEE-NO-EVIL MONKEY;So;0;ON;;;;;N;;;;; +1F649;HEAR-NO-EVIL MONKEY;So;0;ON;;;;;N;;;;; +1F64A;SPEAK-NO-EVIL MONKEY;So;0;ON;;;;;N;;;;; +1F64B;HAPPY PERSON RAISING ONE HAND;So;0;ON;;;;;N;;;;; +1F64C;PERSON RAISING BOTH HANDS IN CELEBRATION;So;0;ON;;;;;N;;;;; +1F64D;PERSON FROWNING;So;0;ON;;;;;N;;;;; +1F64E;PERSON WITH POUTING FACE;So;0;ON;;;;;N;;;;; +1F64F;PERSON WITH FOLDED HANDS;So;0;ON;;;;;N;;;;; +1F680;ROCKET;So;0;ON;;;;;N;;;;; +1F681;HELICOPTER;So;0;ON;;;;;N;;;;; +1F682;STEAM LOCOMOTIVE;So;0;ON;;;;;N;;;;; +1F683;RAILWAY CAR;So;0;ON;;;;;N;;;;; +1F684;HIGH-SPEED TRAIN;So;0;ON;;;;;N;;;;; +1F685;HIGH-SPEED TRAIN WITH BULLET NOSE;So;0;ON;;;;;N;;;;; +1F686;TRAIN;So;0;ON;;;;;N;;;;; +1F687;METRO;So;0;ON;;;;;N;;;;; +1F688;LIGHT RAIL;So;0;ON;;;;;N;;;;; +1F689;STATION;So;0;ON;;;;;N;;;;; +1F68A;TRAM;So;0;ON;;;;;N;;;;; +1F68B;TRAM CAR;So;0;ON;;;;;N;;;;; +1F68C;BUS;So;0;ON;;;;;N;;;;; +1F68D;ONCOMING BUS;So;0;ON;;;;;N;;;;; +1F68E;TROLLEYBUS;So;0;ON;;;;;N;;;;; +1F68F;BUS STOP;So;0;ON;;;;;N;;;;; +1F690;MINIBUS;So;0;ON;;;;;N;;;;; +1F691;AMBULANCE;So;0;ON;;;;;N;;;;; +1F692;FIRE ENGINE;So;0;ON;;;;;N;;;;; +1F693;POLICE CAR;So;0;ON;;;;;N;;;;; +1F694;ONCOMING POLICE CAR;So;0;ON;;;;;N;;;;; +1F695;TAXI;So;0;ON;;;;;N;;;;; +1F696;ONCOMING TAXI;So;0;ON;;;;;N;;;;; +1F697;AUTOMOBILE;So;0;ON;;;;;N;;;;; +1F698;ONCOMING AUTOMOBILE;So;0;ON;;;;;N;;;;; +1F699;RECREATIONAL VEHICLE;So;0;ON;;;;;N;;;;; +1F69A;DELIVERY TRUCK;So;0;ON;;;;;N;;;;; +1F69B;ARTICULATED LORRY;So;0;ON;;;;;N;;;;; +1F69C;TRACTOR;So;0;ON;;;;;N;;;;; +1F69D;MONORAIL;So;0;ON;;;;;N;;;;; +1F69E;MOUNTAIN RAILWAY;So;0;ON;;;;;N;;;;; +1F69F;SUSPENSION RAILWAY;So;0;ON;;;;;N;;;;; +1F6A0;MOUNTAIN CABLEWAY;So;0;ON;;;;;N;;;;; +1F6A1;AERIAL TRAMWAY;So;0;ON;;;;;N;;;;; +1F6A2;SHIP;So;0;ON;;;;;N;;;;; +1F6A3;ROWBOAT;So;0;ON;;;;;N;;;;; +1F6A4;SPEEDBOAT;So;0;ON;;;;;N;;;;; +1F6A5;HORIZONTAL TRAFFIC LIGHT;So;0;ON;;;;;N;;;;; +1F6A6;VERTICAL TRAFFIC LIGHT;So;0;ON;;;;;N;;;;; +1F6A7;CONSTRUCTION SIGN;So;0;ON;;;;;N;;;;; +1F6A8;POLICE CARS REVOLVING LIGHT;So;0;ON;;;;;N;;;;; +1F6A9;TRIANGULAR FLAG ON POST;So;0;ON;;;;;N;;;;; +1F6AA;DOOR;So;0;ON;;;;;N;;;;; +1F6AB;NO ENTRY SIGN;So;0;ON;;;;;N;;;;; +1F6AC;SMOKING SYMBOL;So;0;ON;;;;;N;;;;; +1F6AD;NO SMOKING SYMBOL;So;0;ON;;;;;N;;;;; +1F6AE;PUT LITTER IN ITS PLACE SYMBOL;So;0;ON;;;;;N;;;;; +1F6AF;DO NOT LITTER SYMBOL;So;0;ON;;;;;N;;;;; +1F6B0;POTABLE WATER SYMBOL;So;0;ON;;;;;N;;;;; +1F6B1;NON-POTABLE WATER SYMBOL;So;0;ON;;;;;N;;;;; +1F6B2;BICYCLE;So;0;ON;;;;;N;;;;; +1F6B3;NO BICYCLES;So;0;ON;;;;;N;;;;; +1F6B4;BICYCLIST;So;0;ON;;;;;N;;;;; +1F6B5;MOUNTAIN BICYCLIST;So;0;ON;;;;;N;;;;; +1F6B6;PEDESTRIAN;So;0;ON;;;;;N;;;;; +1F6B7;NO PEDESTRIANS;So;0;ON;;;;;N;;;;; +1F6B8;CHILDREN CROSSING;So;0;ON;;;;;N;;;;; +1F6B9;MENS SYMBOL;So;0;ON;;;;;N;;;;; +1F6BA;WOMENS SYMBOL;So;0;ON;;;;;N;;;;; +1F6BB;RESTROOM;So;0;ON;;;;;N;;;;; +1F6BC;BABY SYMBOL;So;0;ON;;;;;N;;;;; +1F6BD;TOILET;So;0;ON;;;;;N;;;;; +1F6BE;WATER CLOSET;So;0;ON;;;;;N;;;;; +1F6BF;SHOWER;So;0;ON;;;;;N;;;;; +1F6C0;BATH;So;0;ON;;;;;N;;;;; +1F6C1;BATHTUB;So;0;ON;;;;;N;;;;; +1F6C2;PASSPORT CONTROL;So;0;ON;;;;;N;;;;; +1F6C3;CUSTOMS;So;0;ON;;;;;N;;;;; +1F6C4;BAGGAGE CLAIM;So;0;ON;;;;;N;;;;; +1F6C5;LEFT LUGGAGE;So;0;ON;;;;;N;;;;; +1F700;ALCHEMICAL SYMBOL FOR QUINTESSENCE;So;0;ON;;;;;N;;;;; +1F701;ALCHEMICAL SYMBOL FOR AIR;So;0;ON;;;;;N;;;;; +1F702;ALCHEMICAL SYMBOL FOR FIRE;So;0;ON;;;;;N;;;;; +1F703;ALCHEMICAL SYMBOL FOR EARTH;So;0;ON;;;;;N;;;;; +1F704;ALCHEMICAL SYMBOL FOR WATER;So;0;ON;;;;;N;;;;; +1F705;ALCHEMICAL SYMBOL FOR AQUAFORTIS;So;0;ON;;;;;N;;;;; +1F706;ALCHEMICAL SYMBOL FOR AQUA REGIA;So;0;ON;;;;;N;;;;; +1F707;ALCHEMICAL SYMBOL FOR AQUA REGIA-2;So;0;ON;;;;;N;;;;; +1F708;ALCHEMICAL SYMBOL FOR AQUA VITAE;So;0;ON;;;;;N;;;;; +1F709;ALCHEMICAL SYMBOL FOR AQUA VITAE-2;So;0;ON;;;;;N;;;;; +1F70A;ALCHEMICAL SYMBOL FOR VINEGAR;So;0;ON;;;;;N;;;;; +1F70B;ALCHEMICAL SYMBOL FOR VINEGAR-2;So;0;ON;;;;;N;;;;; +1F70C;ALCHEMICAL SYMBOL FOR VINEGAR-3;So;0;ON;;;;;N;;;;; +1F70D;ALCHEMICAL SYMBOL FOR SULFUR;So;0;ON;;;;;N;;;;; +1F70E;ALCHEMICAL SYMBOL FOR PHILOSOPHERS SULFUR;So;0;ON;;;;;N;;;;; +1F70F;ALCHEMICAL SYMBOL FOR BLACK SULFUR;So;0;ON;;;;;N;;;;; +1F710;ALCHEMICAL SYMBOL FOR MERCURY SUBLIMATE;So;0;ON;;;;;N;;;;; +1F711;ALCHEMICAL SYMBOL FOR MERCURY SUBLIMATE-2;So;0;ON;;;;;N;;;;; +1F712;ALCHEMICAL SYMBOL FOR MERCURY SUBLIMATE-3;So;0;ON;;;;;N;;;;; +1F713;ALCHEMICAL SYMBOL FOR CINNABAR;So;0;ON;;;;;N;;;;; +1F714;ALCHEMICAL SYMBOL FOR SALT;So;0;ON;;;;;N;;;;; +1F715;ALCHEMICAL SYMBOL FOR NITRE;So;0;ON;;;;;N;;;;; +1F716;ALCHEMICAL SYMBOL FOR VITRIOL;So;0;ON;;;;;N;;;;; +1F717;ALCHEMICAL SYMBOL FOR VITRIOL-2;So;0;ON;;;;;N;;;;; +1F718;ALCHEMICAL SYMBOL FOR ROCK SALT;So;0;ON;;;;;N;;;;; +1F719;ALCHEMICAL SYMBOL FOR ROCK SALT-2;So;0;ON;;;;;N;;;;; +1F71A;ALCHEMICAL SYMBOL FOR GOLD;So;0;ON;;;;;N;;;;; +1F71B;ALCHEMICAL SYMBOL FOR SILVER;So;0;ON;;;;;N;;;;; +1F71C;ALCHEMICAL SYMBOL FOR IRON ORE;So;0;ON;;;;;N;;;;; +1F71D;ALCHEMICAL SYMBOL FOR IRON ORE-2;So;0;ON;;;;;N;;;;; +1F71E;ALCHEMICAL SYMBOL FOR CROCUS OF IRON;So;0;ON;;;;;N;;;;; +1F71F;ALCHEMICAL SYMBOL FOR REGULUS OF IRON;So;0;ON;;;;;N;;;;; +1F720;ALCHEMICAL SYMBOL FOR COPPER ORE;So;0;ON;;;;;N;;;;; +1F721;ALCHEMICAL SYMBOL FOR IRON-COPPER ORE;So;0;ON;;;;;N;;;;; +1F722;ALCHEMICAL SYMBOL FOR SUBLIMATE OF COPPER;So;0;ON;;;;;N;;;;; +1F723;ALCHEMICAL SYMBOL FOR CROCUS OF COPPER;So;0;ON;;;;;N;;;;; +1F724;ALCHEMICAL SYMBOL FOR CROCUS OF COPPER-2;So;0;ON;;;;;N;;;;; +1F725;ALCHEMICAL SYMBOL FOR COPPER ANTIMONIATE;So;0;ON;;;;;N;;;;; +1F726;ALCHEMICAL SYMBOL FOR SALT OF COPPER ANTIMONIATE;So;0;ON;;;;;N;;;;; +1F727;ALCHEMICAL SYMBOL FOR SUBLIMATE OF SALT OF COPPER;So;0;ON;;;;;N;;;;; +1F728;ALCHEMICAL SYMBOL FOR VERDIGRIS;So;0;ON;;;;;N;;;;; +1F729;ALCHEMICAL SYMBOL FOR TIN ORE;So;0;ON;;;;;N;;;;; +1F72A;ALCHEMICAL SYMBOL FOR LEAD ORE;So;0;ON;;;;;N;;;;; +1F72B;ALCHEMICAL SYMBOL FOR ANTIMONY ORE;So;0;ON;;;;;N;;;;; +1F72C;ALCHEMICAL SYMBOL FOR SUBLIMATE OF ANTIMONY;So;0;ON;;;;;N;;;;; +1F72D;ALCHEMICAL SYMBOL FOR SALT OF ANTIMONY;So;0;ON;;;;;N;;;;; +1F72E;ALCHEMICAL SYMBOL FOR SUBLIMATE OF SALT OF ANTIMONY;So;0;ON;;;;;N;;;;; +1F72F;ALCHEMICAL SYMBOL FOR VINEGAR OF ANTIMONY;So;0;ON;;;;;N;;;;; +1F730;ALCHEMICAL SYMBOL FOR REGULUS OF ANTIMONY;So;0;ON;;;;;N;;;;; +1F731;ALCHEMICAL SYMBOL FOR REGULUS OF ANTIMONY-2;So;0;ON;;;;;N;;;;; +1F732;ALCHEMICAL SYMBOL FOR REGULUS;So;0;ON;;;;;N;;;;; +1F733;ALCHEMICAL SYMBOL FOR REGULUS-2;So;0;ON;;;;;N;;;;; +1F734;ALCHEMICAL SYMBOL FOR REGULUS-3;So;0;ON;;;;;N;;;;; +1F735;ALCHEMICAL SYMBOL FOR REGULUS-4;So;0;ON;;;;;N;;;;; +1F736;ALCHEMICAL SYMBOL FOR ALKALI;So;0;ON;;;;;N;;;;; +1F737;ALCHEMICAL SYMBOL FOR ALKALI-2;So;0;ON;;;;;N;;;;; +1F738;ALCHEMICAL SYMBOL FOR MARCASITE;So;0;ON;;;;;N;;;;; +1F739;ALCHEMICAL SYMBOL FOR SAL-AMMONIAC;So;0;ON;;;;;N;;;;; +1F73A;ALCHEMICAL SYMBOL FOR ARSENIC;So;0;ON;;;;;N;;;;; +1F73B;ALCHEMICAL SYMBOL FOR REALGAR;So;0;ON;;;;;N;;;;; +1F73C;ALCHEMICAL SYMBOL FOR REALGAR-2;So;0;ON;;;;;N;;;;; +1F73D;ALCHEMICAL SYMBOL FOR AURIPIGMENT;So;0;ON;;;;;N;;;;; +1F73E;ALCHEMICAL SYMBOL FOR BISMUTH ORE;So;0;ON;;;;;N;;;;; +1F73F;ALCHEMICAL SYMBOL FOR TARTAR;So;0;ON;;;;;N;;;;; +1F740;ALCHEMICAL SYMBOL FOR TARTAR-2;So;0;ON;;;;;N;;;;; +1F741;ALCHEMICAL SYMBOL FOR QUICK LIME;So;0;ON;;;;;N;;;;; +1F742;ALCHEMICAL SYMBOL FOR BORAX;So;0;ON;;;;;N;;;;; +1F743;ALCHEMICAL SYMBOL FOR BORAX-2;So;0;ON;;;;;N;;;;; +1F744;ALCHEMICAL SYMBOL FOR BORAX-3;So;0;ON;;;;;N;;;;; +1F745;ALCHEMICAL SYMBOL FOR ALUM;So;0;ON;;;;;N;;;;; +1F746;ALCHEMICAL SYMBOL FOR OIL;So;0;ON;;;;;N;;;;; +1F747;ALCHEMICAL SYMBOL FOR SPIRIT;So;0;ON;;;;;N;;;;; +1F748;ALCHEMICAL SYMBOL FOR TINCTURE;So;0;ON;;;;;N;;;;; +1F749;ALCHEMICAL SYMBOL FOR GUM;So;0;ON;;;;;N;;;;; +1F74A;ALCHEMICAL SYMBOL FOR WAX;So;0;ON;;;;;N;;;;; +1F74B;ALCHEMICAL SYMBOL FOR POWDER;So;0;ON;;;;;N;;;;; +1F74C;ALCHEMICAL SYMBOL FOR CALX;So;0;ON;;;;;N;;;;; +1F74D;ALCHEMICAL SYMBOL FOR TUTTY;So;0;ON;;;;;N;;;;; +1F74E;ALCHEMICAL SYMBOL FOR CAPUT MORTUUM;So;0;ON;;;;;N;;;;; +1F74F;ALCHEMICAL SYMBOL FOR SCEPTER OF JOVE;So;0;ON;;;;;N;;;;; +1F750;ALCHEMICAL SYMBOL FOR CADUCEUS;So;0;ON;;;;;N;;;;; +1F751;ALCHEMICAL SYMBOL FOR TRIDENT;So;0;ON;;;;;N;;;;; +1F752;ALCHEMICAL SYMBOL FOR STARRED TRIDENT;So;0;ON;;;;;N;;;;; +1F753;ALCHEMICAL SYMBOL FOR LODESTONE;So;0;ON;;;;;N;;;;; +1F754;ALCHEMICAL SYMBOL FOR SOAP;So;0;ON;;;;;N;;;;; +1F755;ALCHEMICAL SYMBOL FOR URINE;So;0;ON;;;;;N;;;;; +1F756;ALCHEMICAL SYMBOL FOR HORSE DUNG;So;0;ON;;;;;N;;;;; +1F757;ALCHEMICAL SYMBOL FOR ASHES;So;0;ON;;;;;N;;;;; +1F758;ALCHEMICAL SYMBOL FOR POT ASHES;So;0;ON;;;;;N;;;;; +1F759;ALCHEMICAL SYMBOL FOR BRICK;So;0;ON;;;;;N;;;;; +1F75A;ALCHEMICAL SYMBOL FOR POWDERED BRICK;So;0;ON;;;;;N;;;;; +1F75B;ALCHEMICAL SYMBOL FOR AMALGAM;So;0;ON;;;;;N;;;;; +1F75C;ALCHEMICAL SYMBOL FOR STRATUM SUPER STRATUM;So;0;ON;;;;;N;;;;; +1F75D;ALCHEMICAL SYMBOL FOR STRATUM SUPER STRATUM-2;So;0;ON;;;;;N;;;;; +1F75E;ALCHEMICAL SYMBOL FOR SUBLIMATION;So;0;ON;;;;;N;;;;; +1F75F;ALCHEMICAL SYMBOL FOR PRECIPITATE;So;0;ON;;;;;N;;;;; +1F760;ALCHEMICAL SYMBOL FOR DISTILL;So;0;ON;;;;;N;;;;; +1F761;ALCHEMICAL SYMBOL FOR DISSOLVE;So;0;ON;;;;;N;;;;; +1F762;ALCHEMICAL SYMBOL FOR DISSOLVE-2;So;0;ON;;;;;N;;;;; +1F763;ALCHEMICAL SYMBOL FOR PURIFY;So;0;ON;;;;;N;;;;; +1F764;ALCHEMICAL SYMBOL FOR PUTREFACTION;So;0;ON;;;;;N;;;;; +1F765;ALCHEMICAL SYMBOL FOR CRUCIBLE;So;0;ON;;;;;N;;;;; +1F766;ALCHEMICAL SYMBOL FOR CRUCIBLE-2;So;0;ON;;;;;N;;;;; +1F767;ALCHEMICAL SYMBOL FOR CRUCIBLE-3;So;0;ON;;;;;N;;;;; +1F768;ALCHEMICAL SYMBOL FOR CRUCIBLE-4;So;0;ON;;;;;N;;;;; +1F769;ALCHEMICAL SYMBOL FOR CRUCIBLE-5;So;0;ON;;;;;N;;;;; +1F76A;ALCHEMICAL SYMBOL FOR ALEMBIC;So;0;ON;;;;;N;;;;; +1F76B;ALCHEMICAL SYMBOL FOR BATH OF MARY;So;0;ON;;;;;N;;;;; +1F76C;ALCHEMICAL SYMBOL FOR BATH OF VAPOURS;So;0;ON;;;;;N;;;;; +1F76D;ALCHEMICAL SYMBOL FOR RETORT;So;0;ON;;;;;N;;;;; +1F76E;ALCHEMICAL SYMBOL FOR HOUR;So;0;ON;;;;;N;;;;; +1F76F;ALCHEMICAL SYMBOL FOR NIGHT;So;0;ON;;;;;N;;;;; +1F770;ALCHEMICAL SYMBOL FOR DAY-NIGHT;So;0;ON;;;;;N;;;;; +1F771;ALCHEMICAL SYMBOL FOR MONTH;So;0;ON;;;;;N;;;;; +1F772;ALCHEMICAL SYMBOL FOR HALF DRAM;So;0;ON;;;;;N;;;;; +1F773;ALCHEMICAL SYMBOL FOR HALF OUNCE;So;0;ON;;;;;N;;;;; 20000;;Lo;0;L;;;;;N;;;;; 2A6D6;;Lo;0;L;;;;;N;;;;; 2A700;;Lo;0;L;;;;;N;;;;; 2B734;;Lo;0;L;;;;;N;;;;; +2B740;;Lo;0;L;;;;;N;;;;; +2B81D;;Lo;0;L;;;;;N;;;;; 2F800;CJK COMPATIBILITY IDEOGRAPH-2F800;Lo;0;L;4E3D;;;;N;;;;; 2F801;CJK COMPATIBILITY IDEOGRAPH-2F801;Lo;0;L;4E38;;;;N;;;;; 2F802;CJK COMPATIBILITY IDEOGRAPH-2F802;Lo;0;L;4E41;;;;N;;;;; diff --git a/include/grub/powerpc/ieee1275/util/biosdisk.h b/util/argp_common.c similarity index 52% rename from include/grub/powerpc/ieee1275/util/biosdisk.h rename to util/argp_common.c index f4262a0a4..b1caf1b0d 100644 --- a/include/grub/powerpc/ieee1275/util/biosdisk.h +++ b/util/argp_common.c @@ -1,7 +1,7 @@ -/* biosdisk.h - emulate biosdisk */ +/* grub-setup.c - make GRUB usable */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2004,2007 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,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 @@ -17,11 +17,19 @@ * along with GRUB. If not, see . */ -#ifndef GRUB_BIOSDISK_MACHINE_UTIL_HEADER -#define GRUB_BIOSDISK_MACHINE_UTIL_HEADER 1 +#include -void grub_util_biosdisk_init (const char *dev_map); -void grub_util_biosdisk_fini (void); -char *grub_util_biosdisk_get_grub_dev (const char *os_dev); +#define _GNU_SOURCE 1 +#include "progname.h" +#include -#endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */ +/* Print the version information. */ +static void +print_version (FILE *stream, struct argp_state *state) +{ + fprintf (stream, "%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); +} +void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version; + +/* Set the bug report address */ +const char *argp_program_bug_address = "<"PACKAGE_BUGREPORT">"; diff --git a/util/deviceiter.c b/util/deviceiter.c deleted file mode 100644 index 208dcfdde..000000000 --- a/util/deviceiter.c +++ /dev/null @@ -1,953 +0,0 @@ -/* deviceiter.c - iterate over system devices */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,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 - -#include -#include -#include -#include -#include - -#ifdef __linux__ -# 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)) */ -# 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 FLOPPY_MAJOR -# define FLOPPY_MAJOR 2 /* the major number for floppy */ -# endif /* ! FLOPPY_MAJOR */ -# ifndef MAJOR -# define MAJOR(dev) \ - ({ \ - unsigned long long __dev = (dev); \ - (unsigned) ((__dev >> 8) & 0xfff) \ - | ((unsigned int) (__dev >> 32) & ~0xfff); \ - }) -# endif /* ! MAJOR */ -# ifndef MINOR -# define MINOR(dev) \ - ({ \ - unsigned long long __dev = (dev); \ - (unsigned) (__dev & 0xff) | ((unsigned int) (__dev >> 12) & ~0xff); \ - }) -# endif /* ! MINOR */ -# ifndef CDROM_GET_CAPABILITY -# define CDROM_GET_CAPABILITY 0x5331 /* get capabilities */ -# endif /* ! CDROM_GET_CAPABILITY */ -# ifndef BLKGETSIZE -# define BLKGETSIZE _IO(0x12,96) /* return device size */ -# endif /* ! BLKGETSIZE */ - -#ifdef HAVE_DEVICE_MAPPER -# include -#endif -#endif /* __linux__ */ - -/* Use __FreeBSD_kernel__ instead of __FreeBSD__ for compatibility with - kFreeBSD-based non-FreeBSD systems (e.g. GNU/kFreeBSD) */ -#if defined(__FreeBSD__) && ! defined(__FreeBSD_kernel__) -# define __FreeBSD_kernel__ -#endif -#ifdef __FreeBSD_kernel__ - /* Obtain version of kFreeBSD headers */ -# include -# ifndef __FreeBSD_kernel_version -# define __FreeBSD_kernel_version __FreeBSD_version -# endif - - /* Runtime detection of kernel */ -# include -int -get_kfreebsd_version (void) -{ - struct utsname uts; - int major; - int minor; - int v[2]; - - uname (&uts); - sscanf (uts.release, "%d.%d", &major, &minor); - - if (major >= 9) - major = 9; - if (major >= 5) - { - v[0] = minor/10; v[1] = minor%10; - } - else - { - v[0] = minor%10; v[1] = minor/10; - } - return major*100000+v[0]*10000+v[1]*1000; -} -#endif /* __FreeBSD_kernel__ */ - -#if defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) -# include /* ioctl */ -# include -# include /* CDIOCCLRDEBUG */ -# if defined(__FreeBSD_kernel__) -# include -# if __FreeBSD_kernel_version >= 500040 -# include -# endif -# endif /* __FreeBSD_kernel__ */ -#endif /* __FreeBSD_kernel__ || __NetBSD__ || __OpenBSD__ */ - -#ifdef HAVE_OPENDISK -# include -#endif /* HAVE_OPENDISK */ - -#ifdef __linux__ -/* Check if we have devfs support. */ -static int -have_devfs (void) -{ - struct stat st; - return stat ("/dev/.devfsd", &st) == 0; -} -#endif /* __linux__ */ - -/* These three functions are quite different among OSes. */ -static void -get_floppy_disk_name (char *name, int unit) -{ -#if defined(__linux__) - /* GNU/Linux */ - if (have_devfs ()) - sprintf (name, "/dev/floppy/%d", unit); - else - sprintf (name, "/dev/fd%d", unit); -#elif defined(__GNU__) - /* GNU/Hurd */ - sprintf (name, "/dev/fd%d", unit); -#elif defined(__FreeBSD_kernel__) - /* kFreeBSD */ - if (get_kfreebsd_version () >= 400000) - sprintf (name, "/dev/fd%d", unit); - else - sprintf (name, "/dev/rfd%d", unit); -#elif defined(__NetBSD__) - /* NetBSD */ - /* opendisk() doesn't work for floppies. */ - sprintf (name, "/dev/rfd%da", unit); -#elif defined(__OpenBSD__) - /* OpenBSD */ - sprintf (name, "/dev/rfd%dc", unit); -#elif defined(__QNXNTO__) - /* QNX RTP */ - sprintf (name, "/dev/fd%d", unit); -#elif defined(__CYGWIN__) - /* Cygwin */ - sprintf (name, "/dev/fd%d", unit); -#elif defined(__MINGW32__) - (void) unit; - *name = 0; -#else -# warning "BIOS floppy drives cannot be guessed in your operating system." - /* Set NAME to a bogus string. */ - *name = 0; -#endif -} - -static void -get_ide_disk_name (char *name, int unit) -{ -#if defined(__linux__) - /* GNU/Linux */ - sprintf (name, "/dev/hd%c", unit + 'a'); -#elif defined(__GNU__) - /* GNU/Hurd */ - sprintf (name, "/dev/hd%d", unit); -#elif defined(__FreeBSD_kernel__) - /* kFreeBSD */ - if (get_kfreebsd_version () >= 400000) - sprintf (name, "/dev/ad%d", unit); - else - sprintf (name, "/dev/rwd%d", unit); -#elif defined(__NetBSD__) && defined(HAVE_OPENDISK) - /* NetBSD */ - char shortname[16]; - int fd; - - sprintf (shortname, "wd%d", unit); - fd = opendisk (shortname, O_RDONLY, name, - 16, /* length of NAME */ - 0 /* char device */ - ); - close (fd); -#elif defined(__OpenBSD__) - /* OpenBSD */ - sprintf (name, "/dev/rwd%dc", unit); -#elif defined(__QNXNTO__) - /* QNX RTP */ - /* Actually, QNX RTP doesn't distinguish IDE from SCSI, so this could - contain SCSI disks. */ - sprintf (name, "/dev/hd%d", unit); -#elif defined(__CYGWIN__) - /* Cygwin emulates all disks as /dev/sdX. */ - (void) unit; - *name = 0; -#elif defined(__MINGW32__) - sprintf (name, "//./PHYSICALDRIVE%d", unit); -#else -# warning "BIOS IDE drives cannot be guessed in your operating system." - /* Set NAME to a bogus string. */ - *name = 0; -#endif -} - -static void -get_scsi_disk_name (char *name, int unit) -{ -#if defined(__linux__) - /* GNU/Linux */ - sprintf (name, "/dev/sd%c", unit + 'a'); -#elif defined(__GNU__) - /* GNU/Hurd */ - sprintf (name, "/dev/sd%d", unit); -#elif defined(__FreeBSD_kernel__) - /* kFreeBSD */ - if (get_kfreebsd_version () >= 400000) - sprintf (name, "/dev/da%d", unit); - else - sprintf (name, "/dev/rda%d", unit); -#elif defined(__NetBSD__) && defined(HAVE_OPENDISK) - /* NetBSD */ - char shortname[16]; - int fd; - - sprintf (shortname, "sd%d", unit); - fd = opendisk (shortname, O_RDONLY, name, - 16, /* length of NAME */ - 0 /* char device */ - ); - close (fd); -#elif defined(__OpenBSD__) - /* OpenBSD */ - sprintf (name, "/dev/rsd%dc", unit); -#elif defined(__QNXNTO__) - /* QNX RTP */ - /* QNX RTP doesn't distinguish SCSI from IDE, so it is better to - disable the detection of SCSI disks here. */ - *name = 0; -#elif defined(__CYGWIN__) - /* Cygwin emulates all disks as /dev/sdX. */ - sprintf (name, "/dev/sd%c", unit + 'a'); -#elif defined(__MINGW32__) - (void) unit; - *name = 0; -#else -# warning "BIOS SCSI drives cannot be guessed in your operating system." - /* Set NAME to a bogus string. */ - *name = 0; -#endif -} - -#ifdef __FreeBSD_kernel__ -static void -get_ada_disk_name (char *name, int unit) -{ - sprintf (name, "/dev/ada%d", unit); -} - -static void -get_ataraid_disk_name (char *name, int unit) -{ - sprintf (name, "/dev/ar%d", unit); -} - -static void -get_mfi_disk_name (char *name, int unit) -{ - sprintf (name, "/dev/mfid%d", unit); -} -#endif - -#ifdef __linux__ -static void -get_virtio_disk_name (char *name, int unit) -{ -#ifdef __sparc__ - sprintf (name, "/dev/vdisk%c", unit + 'a'); -#else - sprintf (name, "/dev/vd%c", unit + 'a'); -#endif -} - -static void -get_dac960_disk_name (char *name, int controller, int drive) -{ - sprintf (name, "/dev/rd/c%dd%d", controller, drive); -} - -static void -get_acceleraid_disk_name (char *name, int controller, int drive) -{ - sprintf (name, "/dev/rs/c%dd%d", controller, drive); -} - -static void -get_ataraid_disk_name (char *name, int unit) -{ - sprintf (name, "/dev/ataraid/d%c", unit + '0'); -} - -static void -get_i2o_disk_name (char *name, char unit) -{ - sprintf (name, "/dev/i2o/hd%c", unit); -} - -static void -get_cciss_disk_name (char *name, int controller, int drive) -{ - sprintf (name, "/dev/cciss/c%dd%d", controller, drive); -} - -static void -get_ida_disk_name (char *name, int controller, int drive) -{ - sprintf (name, "/dev/ida/c%dd%d", controller, drive); -} - -static void -get_mmc_disk_name (char *name, int unit) -{ - sprintf (name, "/dev/mmcblk%d", unit); -} - -static void -get_xvd_disk_name (char *name, int unit) -{ - sprintf (name, "/dev/xvd%c", unit + 'a'); -} -#endif - -static struct seen_device -{ - struct seen_device *next; - const char *name; -} *seen; - -/* Check if DEVICE can be read. Skip any DEVICE that we have already seen. - If an error occurs, return zero, otherwise return non-zero. */ -static int -check_device_readable_unique (const char *device) -{ - char *real_device; - char buf[512]; - FILE *fp; - struct seen_device *seen_elt; - - /* If DEVICE is empty, just return error. */ - if (*device == 0) - return 0; - - /* Have we seen this device already? */ - real_device = canonicalize_file_name (device); - if (! real_device) - return 0; - if (grub_named_list_find (GRUB_AS_NAMED_LIST (seen), real_device)) - { - grub_dprintf ("deviceiter", "Already seen %s (%s)\n", - device, real_device); - goto fail; - } - - fp = fopen (device, "r"); - if (! fp) - { - switch (errno) - { -#ifdef ENOMEDIUM - case ENOMEDIUM: -# if 0 - /* At the moment, this finds only CDROMs, which can't be - read anyway, so leave it out. Code should be - reactivated if `removable disks' and CDROMs are - supported. */ - /* Accept it, it may be inserted. */ - return 1; -# endif - break; -#endif /* ENOMEDIUM */ - default: - /* Break case and leave. */ - break; - } - /* Error opening the device. */ - goto fail; - } - - /* Make sure CD-ROMs don't get assigned a BIOS disk number - before SCSI disks! */ -#ifdef __linux__ -# ifdef CDROM_GET_CAPABILITY - if (ioctl (fileno (fp), CDROM_GET_CAPABILITY, 0) >= 0) - goto fail; -# else /* ! CDROM_GET_CAPABILITY */ - /* Check if DEVICE is a CD-ROM drive by the HDIO_GETGEO ioctl. */ - { - struct hd_geometry hdg; - struct stat st; - - if (fstat (fileno (fp), &st)) - goto fail; - - /* If it is a block device and isn't a floppy, check if HDIO_GETGEO - succeeds. */ - if (S_ISBLK (st.st_mode) - && MAJOR (st.st_rdev) != FLOPPY_MAJOR - && ioctl (fileno (fp), HDIO_GETGEO, &hdg)) - goto fail; - } -# endif /* ! CDROM_GET_CAPABILITY */ -#endif /* __linux__ */ - -#if defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) -# ifdef CDIOCCLRDEBUG - if (ioctl (fileno (fp), CDIOCCLRDEBUG, 0) >= 0) - goto fail; -# endif /* CDIOCCLRDEBUG */ -#endif /* __FreeBSD_kernel__ || __NetBSD__ || __OpenBSD__ */ - - /* Attempt to read the first sector. */ - if (fread (buf, 1, 512, fp) != 512) - { - fclose (fp); - goto fail; - } - - /* Remember that we've seen this device. */ - seen_elt = xmalloc (sizeof (*seen_elt)); - seen_elt->name = real_device; /* steal memory */ - grub_list_push (GRUB_AS_LIST_P (&seen), GRUB_AS_LIST (seen_elt)); - - fclose (fp); - return 1; - -fail: - free (real_device); - return 0; -} - -static void -clear_seen_devices (void) -{ - while (seen) - { - struct seen_device *seen_elt = seen; - seen = seen->next; - free (seen_elt); - } - seen = NULL; -} - -#ifdef __linux__ -struct device -{ - char *stable; - char *kernel; -}; - -/* Sort by the kernel name for preference since that most closely matches - older device.map files, but sort by stable by-id names as a fallback. - This is because /dev/disk/by-id/ usually has a few alternative - identifications of devices (e.g. ATA vs. SATA). - check_device_readable_unique will ensure that we only get one for any - given disk, but sort the list so that the choice of which one we get is - stable. */ -static int -compare_devices (const void *a, const void *b) -{ - const struct device *left = (const struct device *) a; - const struct device *right = (const struct device *) b; - - if (left->kernel && right->kernel) - { - int ret = strcmp (left->kernel, right->kernel); - if (ret) - return ret; - } - - return strcmp (left->stable, right->stable); -} -#endif /* __linux__ */ - -void -grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int), - int floppy_disks) -{ - int i; - - clear_seen_devices (); - - /* Floppies. */ - for (i = 0; i < floppy_disks; i++) - { - char name[16]; - struct stat st; - - get_floppy_disk_name (name, i); - if (stat (name, &st) < 0) - 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)) - goto out; - } - -#ifdef __linux__ - { - DIR *dir = opendir ("/dev/disk/by-id"); - - if (dir) - { - struct dirent *entry; - struct device *devs; - size_t devs_len = 0, devs_max = 1024, i; - - devs = xmalloc (devs_max * sizeof (*devs)); - - /* Dump all the directory entries into names, resizing if - necessary. */ - for (entry = readdir (dir); entry; entry = readdir (dir)) - { - /* Skip current and parent directory entries. */ - if (strcmp (entry->d_name, ".") == 0 || - strcmp (entry->d_name, "..") == 0) - continue; - /* Skip partition entries. */ - if (strstr (entry->d_name, "-part")) - continue; - /* Skip device-mapper entries; we'll handle the ones we want - later. */ - if (strncmp (entry->d_name, "dm-", sizeof ("dm-") - 1) == 0) - continue; - /* Skip RAID entries; they are handled by upper layers. */ - if (strncmp (entry->d_name, "md-", sizeof ("md-") - 1) == 0) - continue; - if (devs_len >= devs_max) - { - devs_max *= 2; - devs = xrealloc (devs, devs_max * sizeof (*devs)); - } - devs[devs_len].stable = - xasprintf ("/dev/disk/by-id/%s", entry->d_name); - devs[devs_len].kernel = - canonicalize_file_name (devs[devs_len].stable); - devs_len++; - } - - qsort (devs, devs_len, sizeof (*devs), &compare_devices); - - closedir (dir); - - /* Now add all the devices in sorted order. */ - for (i = 0; i < devs_len; ++i) - { - if (check_device_readable_unique (devs[i].stable)) - { - if (hook (devs[i].stable, 0)) - goto out; - } - free (devs[i].stable); - free (devs[i].kernel); - } - free (devs); - } - } - - if (have_devfs ()) - { - i = 0; - while (1) - { - char discn[32]; - char name[PATH_MAX]; - struct stat st; - - /* Linux creates symlinks "/dev/discs/discN" for convenience. - The way to number disks is the same as GRUB's. */ - sprintf (discn, "/dev/discs/disc%d", i++); - if (stat (discn, &st) < 0) - break; - - if (realpath (discn, name)) - { - strcat (name, "/disc"); - if (hook (name, 0)) - goto out; - } - } - goto out; - } -#endif /* __linux__ */ - - /* IDE disks. */ - for (i = 0; i < 96; i++) - { - char name[16]; - - get_ide_disk_name (name, i); - if (check_device_readable_unique (name)) - { - if (hook (name, 0)) - goto out; - } - } - -#ifdef __FreeBSD_kernel__ - /* IDE disks using ATA Direct Access driver. */ - if (get_kfreebsd_version () >= 800000) - for (i = 0; i < 96; i++) - { - char name[16]; - - get_ada_disk_name (name, i); - if (check_device_readable_unique (name)) - { - if (hook (name, 0)) - goto out; - } - } - - /* ATARAID disks. */ - for (i = 0; i < 8; i++) - { - char name[20]; - - get_ataraid_disk_name (name, i); - if (check_device_readable_unique (name)) - { - if (hook (name, 0)) - goto out; - } - } - - /* LSI MegaRAID SAS. */ - for (i = 0; i < 32; i++) - { - char name[20]; - - get_mfi_disk_name (name, i); - if (check_device_readable_unique (name)) - { - if (hook (name, 0)) - goto out; - } - } -#endif - -#ifdef __linux__ - /* Virtio disks. */ - for (i = 0; i < 26; i++) - { - char name[16]; - - get_virtio_disk_name (name, i); - if (check_device_readable_unique (name)) - { - if (hook (name, 0)) - goto out; - } - } - - /* ATARAID disks. */ - for (i = 0; i < 8; i++) - { - char name[20]; - - get_ataraid_disk_name (name, i); - if (check_device_readable_unique (name)) - { - if (hook (name, 0)) - goto out; - } - } - - /* Xen virtual block devices. */ - for (i = 0; i < 26; i++) - { - char name[16]; - - get_xvd_disk_name (name, i); - if (check_device_readable_unique (name)) - { - if (hook (name, 0)) - goto out; - } - } -#endif /* __linux__ */ - - /* The rest is SCSI disks. */ - for (i = 0; i < 48; i++) - { - char name[16]; - - get_scsi_disk_name (name, i); - if (check_device_readable_unique (name)) - { - if (hook (name, 0)) - goto out; - } - } - -#ifdef __linux__ - /* This is for DAC960 - we have - /dev/rd/cdp. - - DAC960 driver currently supports up to 8 controllers, 32 logical - drives, and 7 partitions. */ - { - int controller, drive; - - for (controller = 0; controller < 8; controller++) - { - for (drive = 0; drive < 15; drive++) - { - char name[24]; - - get_dac960_disk_name (name, controller, drive); - if (check_device_readable_unique (name)) - { - if (hook (name, 0)) - goto out; - } - } - } - } - - /* This is for Mylex Acceleraid - we have - /dev/rd/cdp. */ - { - int controller, drive; - - for (controller = 0; controller < 8; controller++) - { - for (drive = 0; drive < 15; drive++) - { - char name[24]; - - get_acceleraid_disk_name (name, controller, drive); - if (check_device_readable_unique (name)) - { - if (hook (name, 0)) - goto out; - } - } - } - } - - /* This is for CCISS - we have - /dev/cciss/cdp. */ - { - int controller, drive; - - for (controller = 0; controller < 3; controller++) - { - for (drive = 0; drive < 16; drive++) - { - char name[24]; - - get_cciss_disk_name (name, controller, drive); - if (check_device_readable_unique (name)) - { - if (hook (name, 0)) - goto out; - } - } - } - } - - /* This is for Compaq Intelligent Drive Array - we have - /dev/ida/cdp. */ - { - int controller, drive; - - for (controller = 0; controller < 3; controller++) - { - for (drive = 0; drive < 16; drive++) - { - char name[24]; - - get_ida_disk_name (name, controller, drive); - if (check_device_readable_unique (name)) - { - if (hook (name, 0)) - goto out; - } - } - } - } - - /* This is for I2O - we have /dev/i2o/hd */ - { - char unit; - - for (unit = 'a'; unit < 'f'; unit++) - { - char name[24]; - - get_i2o_disk_name (name, unit); - if (check_device_readable_unique (name)) - { - if (hook (name, 0)) - goto out; - } - } - } - - /* MultiMediaCard (MMC). */ - for (i = 0; i < 10; i++) - { - char name[16]; - - get_mmc_disk_name (name, i); - if (check_device_readable_unique (name)) - { - if (hook (name, 0)) - goto out; - } - } - -# ifdef HAVE_DEVICE_MAPPER -# define dmraid_check(cond, ...) \ - if (! (cond)) \ - { \ - grub_dprintf ("deviceiter", __VA_ARGS__); \ - goto dmraid_end; \ - } - - /* DM-RAID. */ - if (grub_device_mapper_supported ()) - { - struct dm_tree *tree = NULL; - struct dm_task *task = NULL; - struct dm_names *names = NULL; - unsigned int next = 0; - void *top_handle, *second_handle; - struct dm_tree_node *root, *top, *second; - - /* Build DM tree for all devices. */ - tree = dm_tree_create (); - dmraid_check (tree, "dm_tree_create failed\n"); - task = dm_task_create (DM_DEVICE_LIST); - dmraid_check (task, "dm_task_create failed\n"); - dmraid_check (dm_task_run (task), "dm_task_run failed\n"); - names = dm_task_get_names (task); - dmraid_check (names, "dm_task_get_names failed\n"); - dmraid_check (names->dev, "No DM devices found\n"); - do - { - names = (void *) names + next; - dmraid_check (dm_tree_add_dev (tree, MAJOR (names->dev), - MINOR (names->dev)), - "dm_tree_add_dev (%s) failed\n", names->name); - next = names->next; - } - while (next); - - /* Walk the second-level children of the inverted tree; that is, devices - which are directly composed of non-DM devices such as hard disks. - This class includes all DM-RAID disks and excludes all DM-RAID - partitions. */ - root = dm_tree_find_node (tree, 0, 0); - top_handle = NULL; - top = dm_tree_next_child (&top_handle, root, 1); - while (top) - { - second_handle = NULL; - second = dm_tree_next_child (&second_handle, top, 1); - while (second) - { - const char *node_name, *node_uuid; - char *name; - - node_name = dm_tree_node_get_name (second); - dmraid_check (node_name, "dm_tree_node_get_name failed\n"); - node_uuid = dm_tree_node_get_uuid (second); - dmraid_check (node_uuid, "dm_tree_node_get_uuid failed\n"); - if (strncmp (node_uuid, "DMRAID-", 7) != 0) - { - grub_dprintf ("deviceiter", "%s is not DM-RAID\n", node_name); - goto dmraid_next_child; - } - - name = xasprintf ("/dev/mapper/%s", node_name); - if (check_device_readable_unique (name)) - { - if (hook (name, 0)) - { - free (name); - if (task) - dm_task_destroy (task); - if (tree) - dm_tree_free (tree); - goto out; - } - } - free (name); - -dmraid_next_child: - second = dm_tree_next_child (&second_handle, top, 1); - } - top = dm_tree_next_child (&top_handle, root, 1); - } - -dmraid_end: - if (task) - dm_task_destroy (task); - if (tree) - dm_tree_free (tree); - } -# endif /* HAVE_DEVICE_MAPPER */ -#endif /* __linux__ */ - -out: - clear_seen_devices (); -} - diff --git a/util/getroot.c b/util/getroot.c index 96879f545..c93ecd59e 100644 --- a/util/getroot.c +++ b/util/getroot.c @@ -32,6 +32,9 @@ #include #include #include +#ifdef HAVE_LIMITS_H +#include +#endif #include #include #include @@ -73,6 +76,72 @@ #include #include +#ifdef __linux__ +# include /* ioctl */ +# include +# ifndef MAJOR +# ifndef MINORBITS +# define MINORBITS 8 +# endif /* ! MINORBITS */ +# define MAJOR(dev) ((unsigned) ((dev) >> MINORBITS)) +# endif /* ! MAJOR */ +# ifndef FLOPPY_MAJOR +# define FLOPPY_MAJOR 2 +# endif /* ! FLOPPY_MAJOR */ +#endif + +#ifdef __CYGWIN__ +# include +# include /* BLKGETSIZE64 */ +# include /* HDIO_GETGEO */ +# define MAJOR(dev) ((unsigned) ((dev) >> 16)) +# define FLOPPY_MAJOR 2 +#endif + +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +# include /* DIOCGMEDIASIZE */ +# include +# include +# include +#include +# define MAJOR(dev) major(dev) +# define FLOPPY_MAJOR 2 +#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 FLOPPY_MAJOR +# define FLOPPY_MAJOR 2 +# endif /* ! FLOPPY_MAJOR */ +# ifndef RAW_FLOPPY_MAJOR +# define RAW_FLOPPY_MAJOR 9 +# endif /* ! RAW_FLOPPY_MAJOR */ +#endif /* defined(__NetBSD__) */ + static void strip_extra_slashes (char *dir) { @@ -112,14 +181,160 @@ xgetcwd (void) return path; } +static char ** +find_root_devices_from_poolname (char *poolname) +{ + char **devices = 0; + size_t ndevices = 0; + size_t devices_allocated = 0; + +#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) + zpool_handle_t *zpool; + libzfs_handle_t *libzfs; + nvlist_t *config, *vdev_tree; + nvlist_t **children, **path; + unsigned int nvlist_count; + unsigned int i; + char *device = 0; + + libzfs = grub_get_libzfs_handle (); + if (! libzfs) + return NULL; + + zpool = zpool_open (libzfs, poolname); + config = zpool_get_config (zpool, NULL); + + if (nvlist_lookup_nvlist (config, "vdev_tree", &vdev_tree) != 0) + error (1, errno, "nvlist_lookup_nvlist (\"vdev_tree\")"); + + if (nvlist_lookup_nvlist_array (vdev_tree, "children", &children, &nvlist_count) != 0) + error (1, errno, "nvlist_lookup_nvlist_array (\"children\")"); + assert (nvlist_count > 0); + + while (nvlist_lookup_nvlist_array (children[0], "children", + &children, &nvlist_count) == 0) + assert (nvlist_count > 0); + + for (i = 0; i < nvlist_count; i++) + { + if (nvlist_lookup_string (children[i], "path", &device) != 0) + error (1, errno, "nvlist_lookup_string (\"path\")"); + + struct stat st; + if (stat (device, &st) == 0) + { +#ifdef __sun__ + if (grub_memcmp (device, "/dev/dsk/", sizeof ("/dev/dsk/") - 1) + == 0) + device = xasprintf ("/dev/rdsk/%s", + device + sizeof ("/dev/dsk/") - 1); + else if (grub_memcmp (device, "/devices", sizeof ("/devices") - 1) + == 0 + && grub_memcmp (device + strlen (device) - 4, + ",raw", 4) != 0) + device = xasprintf ("%s,raw", device); + else +#endif + device = xstrdup (device); + if (ndevices >= devices_allocated) + { + devices_allocated = 2 * (devices_allocated + 8); + devices = xrealloc (devices, sizeof (devices[0]) + * devices_allocated); + } + devices[ndevices++] = device; + } + + device = NULL; + } + + zpool_close (zpool); +#else + char *cmd; + FILE *fp; + int ret; + char *line; + size_t len; + int st; + + char name[PATH_MAX + 1], state[257], readlen[257], writelen[257]; + char cksum[257], notes[257]; + unsigned int dummy; + + cmd = xasprintf ("zpool status %s", poolname); + fp = popen (cmd, "r"); + free (cmd); + + st = 0; + while (1) + { + line = NULL; + ret = getline (&line, &len, fp); + if (ret == -1) + break; + + if (sscanf (line, " %s %256s %256s %256s %256s %256s", + name, state, readlen, writelen, cksum, notes) >= 5) + switch (st) + { + case 0: + if (!strcmp (name, "NAME") + && !strcmp (state, "STATE") + && !strcmp (readlen, "READ") + && !strcmp (writelen, "WRITE") + && !strcmp (cksum, "CKSUM")) + st++; + break; + case 1: + if (!strcmp (name, poolname)) + st++; + break; + case 2: + if (strcmp (name, "mirror") && !sscanf (name, "mirror-%u", &dummy) + && !sscanf (name, "raidz%u", &dummy) + && !sscanf (name, "raidz1%u", &dummy) + && !sscanf (name, "raidz2%u", &dummy) + && !sscanf (name, "raidz3%u", &dummy) + && !strcmp (state, "ONLINE")) + { + if (ndevices >= devices_allocated) + { + devices_allocated = 2 * (devices_allocated + 8); + devices = xrealloc (devices, sizeof (devices[0]) + * devices_allocated); + } + devices[ndevices++] = xasprintf ("/dev/%s", name); + } + break; + } + + free (line); + } + + pclose (fp); +#endif + if (devices) + { + if (ndevices >= devices_allocated) + { + devices_allocated = 2 * (devices_allocated + 8); + devices = xrealloc (devices, sizeof (devices[0]) + * devices_allocated); + } + devices[ndevices++] = 0; + } + return devices; +} + #ifdef __linux__ +#define ESCAPED_PATH_MAX (4 * PATH_MAX) struct mountinfo_entry { int id; int major, minor; - char enc_root[PATH_MAX], enc_path[PATH_MAX]; - char fstype[PATH_MAX], device[PATH_MAX]; + char enc_root[ESCAPED_PATH_MAX + 1], enc_path[ESCAPED_PATH_MAX + 1]; + char fstype[ESCAPED_PATH_MAX + 1], device[ESCAPED_PATH_MAX + 1]; }; /* Statting something on a btrfs filesystem always returns a virtual device @@ -150,14 +365,14 @@ unescape (char *str) *optr = 0; } -char * -grub_find_root_device_from_mountinfo (const char *dir, char **relroot) +static char ** +grub_find_root_devices_from_mountinfo (const char *dir, char **relroot) { FILE *fp; char *buf = NULL; size_t len = 0; - char *ret = NULL; - int entry_len = 0, entry_max = 4; + char **ret = NULL; + grub_size_t entry_len = 0, entry_max = 4; struct mountinfo_entry *entries; struct mountinfo_entry parent_entry = { 0, 0, 0, "", "", "", "" }; int i; @@ -259,9 +474,33 @@ grub_find_root_device_from_mountinfo (const char *dir, char **relroot) if (!*entries[i].device) continue; - ret = strdup (entries[i].device); - if (relroot) - *relroot = strdup (entries[i].enc_root); + if (grub_strcmp (entries[i].fstype, "fuse.zfs") == 0) + { + char *slash; + slash = strchr (entries[i].device, '/'); + if (slash) + *slash = 0; + ret = find_root_devices_from_poolname (entries[i].device); + if (slash) + *slash = '/'; + if (relroot) + { + if (!slash) + *relroot = xasprintf ("/@%s", entries[i].enc_root); + else if (strchr (slash + 1, '@')) + *relroot = xasprintf ("/%s%s", slash + 1, entries[i].enc_root); + else + *relroot = xasprintf ("/%s@%s", slash + 1, entries[i].enc_root); + } + } + else + { + ret = xmalloc (2 * sizeof (ret[0])); + ret[0] = strdup (entries[i].device); + ret[1] = 0; + if (relroot) + *relroot = strdup (entries[i].enc_root); + } break; } @@ -273,11 +512,10 @@ grub_find_root_device_from_mountinfo (const char *dir, char **relroot) #endif /* __linux__ */ -#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) -static char * -find_root_device_from_libzfs (const char *dir) +static char ** +find_root_devices_from_libzfs (const char *dir) { - char *device = NULL; + char **devices = NULL; char *poolname; char *poolfs; @@ -285,69 +523,14 @@ find_root_device_from_libzfs (const char *dir) if (! poolname) return NULL; - { - zpool_handle_t *zpool; - libzfs_handle_t *libzfs; - nvlist_t *config, *vdev_tree; - nvlist_t **children, **path; - unsigned int nvlist_count; - unsigned int i; - - libzfs = grub_get_libzfs_handle (); - if (! libzfs) - return NULL; - - zpool = zpool_open (libzfs, poolname); - config = zpool_get_config (zpool, NULL); - - if (nvlist_lookup_nvlist (config, "vdev_tree", &vdev_tree) != 0) - error (1, errno, "nvlist_lookup_nvlist (\"vdev_tree\")"); - - if (nvlist_lookup_nvlist_array (vdev_tree, "children", &children, &nvlist_count) != 0) - error (1, errno, "nvlist_lookup_nvlist_array (\"children\")"); - assert (nvlist_count > 0); - - while (nvlist_lookup_nvlist_array (children[0], "children", - &children, &nvlist_count) == 0) - assert (nvlist_count > 0); - - for (i = 0; i < nvlist_count; i++) - { - if (nvlist_lookup_string (children[i], "path", &device) != 0) - error (1, errno, "nvlist_lookup_string (\"path\")"); - - struct stat st; - if (stat (device, &st) == 0) - { -#ifdef __sun__ - if (grub_memcmp (device, "/dev/dsk/", sizeof ("/dev/dsk/") - 1) - == 0) - device = xasprintf ("/dev/rdsk/%s", - device + sizeof ("/dev/dsk/") - 1); - else if (grub_memcmp (device, "/devices", sizeof ("/devices") - 1) - == 0 - && grub_memcmp (device + strlen (device) - 4, - ",raw", 4) != 0) - device = xasprintf ("%s,raw", device); - else -#endif - device = xstrdup (device); - break; - } - - device = NULL; - } - - zpool_close (zpool); - } + devices = find_root_devices_from_poolname (poolname); free (poolname); if (poolfs) free (poolfs); - return device; + return devices; } -#endif #ifdef __MINGW32__ @@ -429,7 +612,8 @@ grub_find_device (const char *dir, dev_t dev) if (res) { if (chdir (saved_cwd) < 0) - grub_util_error ("cannot restore the original directory"); + grub_util_error ("%s", + _("cannot restore the original directory")); free (saved_cwd); closedir (dp); @@ -479,7 +663,7 @@ grub_find_device (const char *dir, dev_t dev) continue; if (chdir (saved_cwd) < 0) - grub_util_error (_("cannot restore the original directory")); + grub_util_error ("%s", _("cannot restore the original directory")); free (saved_cwd); closedir (dp); @@ -488,7 +672,7 @@ grub_find_device (const char *dir, dev_t dev) } if (chdir (saved_cwd) < 0) - grub_util_error (_("cannot restore the original directory")); + grub_util_error ("%s", _("cannot restore the original directory")); free (saved_cwd); closedir (dp); @@ -581,10 +765,10 @@ grub_find_device (const char *path, dev_t dev) #endif /* __CYGWIN__ */ -char * -grub_guess_root_device (const char *dir) +char ** +grub_guess_root_devices (const char *dir) { - char *os_dev = NULL; + char **os_dev = NULL; #ifdef __GNU__ file_t file; mach_port_t *ports; @@ -618,9 +802,11 @@ grub_guess_root_device (const char *dir) if (data[name_len - 1] != '\0') grub_util_error (_("Storage name for `%s' not NUL-terminated"), dir); - os_dev = xmalloc (strlen ("/dev/") + data_len); - memcpy (os_dev, "/dev/", strlen ("/dev/")); - memcpy (os_dev + strlen ("/dev/"), data, data_len); + os_dev = xmalloc (2 * sizeof (os_dev[0])); + os_dev[0] = xmalloc (sizeof ("/dev/") - 1 + data_len); + memcpy (os_dev[0], "/dev/", sizeof ("/dev/") - 1); + memcpy (os_dev[0] + sizeof ("/dev/") - 1, data, data_len); + os_dev[1] = 0; if (ports && num_ports > 0) { @@ -647,50 +833,58 @@ grub_guess_root_device (const char *dir) #ifdef __linux__ if (!os_dev) - os_dev = grub_find_root_device_from_mountinfo (dir, NULL); + os_dev = grub_find_root_devices_from_mountinfo (dir, NULL); #endif /* __linux__ */ -#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) if (!os_dev) - os_dev = find_root_device_from_libzfs (dir); -#endif + os_dev = find_root_devices_from_libzfs (dir); if (os_dev) { - char *tmp = os_dev; - os_dev = canonicalize_file_name (os_dev); - free (tmp); - } - - if (os_dev) - { - int dm = (strncmp (os_dev, "/dev/dm-", sizeof ("/dev/dm-") - 1) == 0); - int root = (strcmp (os_dev, "/dev/root") == 0); - if (!dm && !root) - return os_dev; - if (stat (os_dev, &st) >= 0) + char **cur; + for (cur = os_dev; *cur; cur++) { - free (os_dev); + char *tmp = *cur; + int root, dm; + *cur = canonicalize_file_name (tmp); + if (*cur == NULL) + grub_util_error (_("failed to get canonical path of %s"), tmp); + free (tmp); + root = (strcmp (*cur, "/dev/root") == 0); + dm = (strncmp (*cur, "/dev/dm-", sizeof ("/dev/dm-") - 1) == 0); + if (!dm && !root) + continue; + if (stat (*cur, &st) < 0) + break; + free (*cur); dev = st.st_rdev; - return grub_find_device (dm ? "/dev/mapper" : "/dev", dev); + *cur = grub_find_device (dm ? "/dev/mapper" : "/dev", dev); } + if (!*cur) + return os_dev; + for (cur = os_dev; *cur; cur++) + free (*cur); free (os_dev); + os_dev = 0; } if (stat (dir, &st) < 0) - grub_util_error (_("cannot stat `%s'"), dir); + grub_util_error (_("cannot stat `%s': %s"), dir, strerror (errno)); dev = st.st_dev; + + os_dev = xmalloc (2 * sizeof (os_dev[0])); #ifdef __CYGWIN__ /* Cygwin specific function. */ - os_dev = grub_find_device (dir, dev); + os_dev[0] = grub_find_device (dir, dev); #else /* This might be truly slow, but is there any better way? */ - os_dev = grub_find_device ("/dev", dev); + os_dev[0] = grub_find_device ("/dev", dev); #endif + os_dev[1] = 0; #endif /* !__GNU__ */ return os_dev; @@ -717,7 +911,7 @@ grub_util_open_dm (const char *os_dev, struct dm_tree **tree, *tree = dm_tree_create (); if (! *tree) { - grub_puts_ (N_("Failed to create tree")); + grub_puts_ (N_("Failed to create `device-mapper' tree")); grub_dprintf ("hostdisk", "dm_tree_create failed\n"); return 0; } @@ -833,6 +1027,9 @@ grub_util_get_geom_abstraction (const char *dev) error = geom_gettree (&mesh); if (error != 0) + /* TRANSLATORS: geom is the name of (k)FreeBSD device framework. + Usually left untranslated. + */ grub_util_error (_("couldn't open geom")); LIST_FOREACH (class, &mesh.lg_class, lg_class) @@ -947,7 +1144,6 @@ get_mdadm_uuid (const char *os_dev) if (strncmp (buf, "MD_UUID=", sizeof ("MD_UUID=") - 1) == 0) { char *name_start, *ptri, *ptro; - size_t name_len; free (name); name_start = buf + sizeof ("MD_UUID=") - 1; @@ -997,6 +1193,9 @@ grub_util_pull_device (const char *os_dev) error = geom_gettree (&mesh); if (error != 0) + /* TRANSLATORS: geom is the name of (k)FreeBSD device framework. + Usually left untranslated. + */ grub_util_error (_("couldn't open geom")); LIST_FOREACH (class, &mesh.lg_class, lg_class) @@ -1035,7 +1234,8 @@ grub_util_pull_device (const char *os_dev) grub_err_t err; err = grub_cryptodisk_cheat_mount (grdev, os_dev); if (err) - grub_util_error (_("Can't mount crypto: %s"), _(grub_errmsg)); + grub_util_error (_("can't mount crypto volume `%s': %s"), + lastsubdev, grub_errmsg); } grub_free (grdev); @@ -1079,7 +1279,8 @@ grub_util_pull_device (const char *os_dev) grub_err_t err; err = grub_cryptodisk_cheat_mount (grdev, os_dev); if (err) - grub_util_error (_("Can't mount crypto: %s"), _(grub_errmsg)); + grub_util_error (_("can't mount crypto volume `%s': %s"), + lastsubdev, grub_errmsg); } grub_free (grdev); } @@ -1101,11 +1302,828 @@ grub_util_pull_device (const char *os_dev) return; default: /* GRUB_DEV_ABSTRACTION_NONE */ - grub_util_biosdisk_get_grub_dev (os_dev); + free (grub_util_biosdisk_get_grub_dev (os_dev)); return; } } +#ifdef HAVE_DEVICE_MAPPER +static int +grub_util_get_dm_node_linear_info (const char *dev, + int *maj, int *min) +{ + struct dm_task *dmt; + void *next = NULL; + uint64_t length, start; + char *target, *params; + char *ptr; + int major, minor; + + dmt = dm_task_create(DM_DEVICE_TABLE); + if (!dmt) + return 0; + + if (!dm_task_set_name(dmt, dev)) + { + dm_task_destroy (dmt); + return 0; + } + dm_task_no_open_count(dmt); + if (!dm_task_run(dmt)) + { + dm_task_destroy (dmt); + return 0; + } + next = dm_get_next_target(dmt, next, &start, &length, + &target, ¶ms); + if (grub_strcmp (target, "linear") != 0) + { + dm_task_destroy (dmt); + return 0; + } + 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, 0, 10); + if (grub_errno) + { + grub_errno = GRUB_ERR_NONE; + dm_task_destroy (dmt); + return 0; + } + if (maj) + *maj = major; + if (min) + *min = minor; + dm_task_destroy (dmt); + return 1; +} +#endif + +int +grub_util_biosdisk_is_floppy (grub_disk_t disk) +{ + struct stat st; + int fd; + const char *dname; + + dname = grub_util_biosdisk_get_osdev (disk); + + if (!dname) + return 0; + + fd = open (dname, O_RDONLY); + /* Shouldn't happen. */ + if (fd == -1) + return 0; + + /* Shouldn't happen either. */ + if (fstat (fd, &st) < 0) + { + close (fd); + return 0; + } + + close (fd); + +#if defined(__NetBSD__) + if (major(st.st_rdev) == RAW_FLOPPY_MAJOR) + return 1; +#endif + +#if defined(FLOPPY_MAJOR) + if (major(st.st_rdev) == FLOPPY_MAJOR) +#else + /* Some kernels (e.g. kFreeBSD) don't have a static major number + for floppies, but they still use a "fd[0-9]" pathname. */ + if (map[disk->id].device[5] == 'f' + && map[disk->id].device[6] == 'd' + && map[disk->id].device[7] >= '0' + && map[disk->id].device[7] <= '9') +#endif + return 1; + + return 0; +} + +static char * +convert_system_partition_to_system_disk (const char *os_dev, struct stat *st) +{ +#if defined(__linux__) + char *path = xmalloc (PATH_MAX); + if (! realpath (os_dev, path)) + return NULL; + + if (strncmp ("/dev/", path, 5) == 0) + { + char *p = path + 5; + + /* If this is an IDE disk. */ + if (strncmp ("ide/", p, 4) == 0) + { + p = strstr (p, "part"); + if (p) + strcpy (p, "disc"); + + return path; + } + + /* If this is a SCSI disk. */ + if (strncmp ("scsi/", p, 5) == 0) + { + p = strstr (p, "part"); + if (p) + strcpy (p, "disc"); + + return path; + } + + /* If this is a DAC960 disk. */ + if (strncmp ("rd/c", p, 4) == 0) + { + /* /dev/rd/c[0-9]+d[0-9]+(p[0-9]+)? */ + p = strchr (p, 'p'); + if (p) + *p = '\0'; + + return path; + } + + /* If this is a Mylex AcceleRAID Array. */ + if (strncmp ("rs/c", p, 4) == 0) + { + /* /dev/rd/c[0-9]+d[0-9]+(p[0-9]+)? */ + p = strchr (p, 'p'); + if (p) + *p = '\0'; + + return path; + } + /* If this is a CCISS disk. */ + if (strncmp ("cciss/c", p, sizeof ("cciss/c") - 1) == 0) + { + /* /dev/cciss/c[0-9]+d[0-9]+(p[0-9]+)? */ + p = strchr (p, 'p'); + if (p) + *p = '\0'; + + return path; + } + + /* If this is a Compaq Intelligent Drive Array. */ + if (strncmp ("ida/c", p, sizeof ("ida/c") - 1) == 0) + { + /* /dev/ida/c[0-9]+d[0-9]+(p[0-9]+)? */ + p = strchr (p, 'p'); + if (p) + *p = '\0'; + + return path; + } + + /* If this is an I2O disk. */ + if (strncmp ("i2o/hd", p, sizeof ("i2o/hd") - 1) == 0) + { + /* /dev/i2o/hd[a-z]([0-9]+)? */ + p[sizeof ("i2o/hda") - 1] = '\0'; + return path; + } + + /* If this is a MultiMediaCard (MMC). */ + if (strncmp ("mmcblk", p, sizeof ("mmcblk") - 1) == 0) + { + /* /dev/mmcblk[0-9]+(p[0-9]+)? */ + p = strchr (p, 'p'); + if (p) + *p = '\0'; + + return path; + } + + if (strncmp ("md", p, 2) == 0 + && p[2] >= '0' && p[2] <= '9') + { + char *ptr = p + 2; + while (*ptr >= '0' && *ptr <= '9') + ptr++; + *ptr = 0; + return path; + } + + /* If this is an IDE, SCSI or Virtio disk. */ + if (strncmp ("vdisk", p, 5) == 0 + && p[5] >= 'a' && p[5] <= 'z') + { + /* /dev/vdisk[a-z][0-9]* */ + p[6] = '\0'; + return path; + } + if ((strncmp ("hd", p, 2) == 0 + || strncmp ("vd", p, 2) == 0 + || strncmp ("sd", p, 2) == 0) + && p[2] >= 'a' && p[2] <= 'z') + { + char *pp = p + 2; + while (*pp >= 'a' && *pp <= 'z') + pp++; + /* /dev/[hsv]d[a-z]+[0-9]* */ + *pp = '\0'; + return path; + } + + /* If this is a Xen virtual block device. */ + if ((strncmp ("xvd", p, 3) == 0) && p[3] >= 'a' && p[3] <= 'z') + { + char *pp = p + 3; + while (*pp >= 'a' && *pp <= 'z') + pp++; + /* /dev/xvd[a-z]+[0-9]* */ + *pp = '\0'; + return path; + } + +#ifdef HAVE_DEVICE_MAPPER + /* If this is a DM-RAID device. + Compare os_dev rather than path here, since nodes under + /dev/mapper/ are often symlinks. */ + if ((strncmp ("/dev/mapper/", os_dev, 12) == 0)) + { + struct dm_tree *tree; + uint32_t maj, min; + struct dm_tree_node *node = NULL, *child; + void *handle; + const char *node_uuid, *mapper_name = NULL, *child_uuid, *child_name; + + tree = dm_tree_create (); + if (! tree) + { + grub_dprintf ("hostdisk", "dm_tree_create failed\n"); + goto devmapper_out; + } + + maj = major (st->st_rdev); + min = minor (st->st_rdev); + if (! dm_tree_add_dev (tree, maj, min)) + { + grub_dprintf ("hostdisk", "dm_tree_add_dev failed\n"); + goto devmapper_out; + } + + node = dm_tree_find_node (tree, maj, min); + if (! node) + { + grub_dprintf ("hostdisk", "dm_tree_find_node failed\n"); + goto devmapper_out; + } + node_uuid = dm_tree_node_get_uuid (node); + if (! node_uuid) + { + grub_dprintf ("hostdisk", "%s has no DM uuid\n", path); + node = NULL; + goto devmapper_out; + } + if (strncmp (node_uuid, "LVM-", 4) == 0) + { + grub_dprintf ("hostdisk", "%s is an LVM\n", path); + node = NULL; + goto devmapper_out; + } + if (strncmp (node_uuid, "mpath-", 6) == 0) + { + /* Multipath partitions have partN-mpath-* UUIDs, and are + linear mappings so are handled by + grub_util_get_dm_node_linear_info. Multipath disks are not + linear mappings and must be handled specially. */ + grub_dprintf ("hostdisk", "%s is a multipath disk\n", path); + mapper_name = dm_tree_node_get_name (node); + goto devmapper_out; + } + if (strncmp (node_uuid, "DMRAID-", 7) != 0) + { + int major, minor; + const char *node_name; + grub_dprintf ("hostdisk", "%s is not DM-RAID\n", path); + + if ((node_name = dm_tree_node_get_name (node)) + && grub_util_get_dm_node_linear_info (node_name, + &major, &minor)) + { + if (tree) + dm_tree_free (tree); + free (path); + char *ret = grub_find_device ("/dev", + (major << 8) | minor); + return ret; + } + + node = NULL; + goto devmapper_out; + } + + handle = NULL; + /* Counter-intuitively, device-mapper refers to the disk-like + device containing a DM-RAID partition device as a "child" of + the partition device. */ + child = dm_tree_next_child (&handle, node, 0); + if (! child) + { + grub_dprintf ("hostdisk", "%s has no DM children\n", path); + goto devmapper_out; + } + child_uuid = dm_tree_node_get_uuid (child); + if (! child_uuid) + { + grub_dprintf ("hostdisk", "%s child has no DM uuid\n", path); + goto devmapper_out; + } + else if (strncmp (child_uuid, "DMRAID-", 7) != 0) + { + grub_dprintf ("hostdisk", "%s child is not DM-RAID\n", path); + goto devmapper_out; + } + child_name = dm_tree_node_get_name (child); + if (! child_name) + { + grub_dprintf ("hostdisk", "%s child has no DM name\n", path); + goto devmapper_out; + } + mapper_name = child_name; + +devmapper_out: + if (! mapper_name && node) + { + /* This is a DM-RAID disk, not a partition. */ + mapper_name = dm_tree_node_get_name (node); + if (! mapper_name) + grub_dprintf ("hostdisk", "%s has no DM name\n", path); + } + if (tree) + dm_tree_free (tree); + free (path); + if (mapper_name) + return xasprintf ("/dev/mapper/%s", mapper_name); + else + return NULL; + } +#endif /* HAVE_DEVICE_MAPPER */ + } + + return path; + +#elif defined(__GNU__) + char *path = xstrdup (os_dev); + if (strncmp ("/dev/sd", path, 7) == 0 || strncmp ("/dev/hd", path, 7) == 0) + { + char *p = strchr (path + 7, 's'); + if (p) + *p = '\0'; + } + return path; + +#elif defined(__CYGWIN__) + char *path = xstrdup (os_dev); + if (strncmp ("/dev/sd", path, 7) == 0 && 'a' <= path[7] && path[7] <= 'z') + path[8] = 0; + return path; + +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + char *out, *out2; + if (strncmp (os_dev, "/dev/", sizeof ("/dev/") - 1) != 0) + return xstrdup (os_dev); + grub_util_follow_gpart_up (os_dev + sizeof ("/dev/") - 1, NULL, &out); + + out2 = xasprintf ("/dev/%s", out); + free (out); + + return out2; +#elif defined(__APPLE__) + char *path = xstrdup (os_dev); + if (strncmp ("/dev/", path, 5) == 0) + { + char *p; + for (p = path + 5; *p; ++p) + if (grub_isdigit(*p)) + { + p = strpbrk (p, "sp"); + if (p) + *p = '\0'; + break; + } + } + return path; + +#elif defined(__NetBSD__) + int rawpart = -1; +# ifdef HAVE_GETRAWPARTITION + rawpart = getrawpartition(); +# endif /* HAVE_GETRAWPARTITION */ + if (rawpart < 0) + return xstrdup (os_dev); + + /* NetBSD disk wedges are of the form "/dev/rdk.*". */ + if (strncmp ("/dev/rdk", os_dev, sizeof("/dev/rdk") - 1) == 0) + { + struct dkwedge_info dkw; + int fd; + + fd = open (os_dev, O_RDONLY); + if (fd == -1) + { + grub_error (GRUB_ERR_BAD_DEVICE, + N_("cannot open `%s': %s"), os_dev, + strerror (errno)); + return xstrdup (os_dev); + } + /* We don't call configure_device_driver since this isn't a floppy device name. */ + if (ioctl (fd, DIOCGWEDGEINFO, &dkw) == -1) + { + grub_error (GRUB_ERR_BAD_DEVICE, + "cannot get disk wedge info of `%s'", os_dev); + close (fd); + return xstrdup (os_dev); + } + close (fd); + return xasprintf ("/dev/r%s%c", dkw.dkw_parent, 'a' + rawpart); + } + + /* NetBSD (disk label) partitions are of the form "/dev/r[a-z]+[0-9][a-z]". */ + if (strncmp ("/dev/r", os_dev, sizeof("/dev/r") - 1) == 0 && + (os_dev[sizeof("/dev/r") - 1] >= 'a' && os_dev[sizeof("/dev/r") - 1] <= 'z') && + strncmp ("fd", os_dev + sizeof("/dev/r") - 1, sizeof("fd") - 1) != 0) /* not a floppy device name */ + { + char *path = xstrdup (os_dev); + char *p; + for (p = path + sizeof("/dev/r"); *p >= 'a' && *p <= 'z'; p++); + if (grub_isdigit(*p)) + { + p++; + if ((*p >= 'a' && *p <= 'z') && (*(p+1) == '\0')) + { + /* path matches the required regular expression and + p points to its last character. */ + *p = 'a' + rawpart; + } + } + return path; + } + + return xstrdup (os_dev); + +#elif defined (__sun__) + char *colon = grub_strrchr (os_dev, ':'); + if (grub_memcmp (os_dev, "/devices", sizeof ("/devices") - 1) == 0 + && colon) + { + char *ret = xmalloc (colon - os_dev + sizeof (":q,raw")); + grub_memcpy (ret, os_dev, colon - os_dev); + grub_memcpy (ret + (colon - os_dev), ":q,raw", sizeof (":q,raw")); + return ret; + } + else + return xstrdup (os_dev); +#else +# warning "The function `convert_system_partition_to_system_disk' might not work on your OS correctly." + return xstrdup (os_dev); +#endif +} + +static const char * +find_system_device (const char *os_dev, struct stat *st, int convert, int add) +{ + char *os_disk; + const char *drive; + + if (convert) + os_disk = convert_system_partition_to_system_disk (os_dev, st); + else + os_disk = xstrdup (os_dev); + if (! os_disk) + return NULL; + + drive = grub_hostdisk_os_dev_to_grub_drive (os_disk, add); + free (os_disk); + return drive; +} + +/* + * Note: we do not use the new partition naming scheme as dos_part does not + * necessarily correspond to an msdos partition. + */ +static char * +make_device_name (const char *drive, int dos_part, int bsd_part) +{ + char *ret, *ptr, *end; + const char *iptr; + + ret = xmalloc (strlen (drive) * 2 + + sizeof (",XXXXXXXXXXXXXXXXXXXXXXXXXX" + ",XXXXXXXXXXXXXXXXXXXXXXXXXX")); + end = (ret + strlen (drive) * 2 + + sizeof (",XXXXXXXXXXXXXXXXXXXXXXXXXX" + ",XXXXXXXXXXXXXXXXXXXXXXXXXX")); + ptr = ret; + for (iptr = drive; *iptr; iptr++) + { + if (*iptr == ',') + *ptr++ = '\\'; + *ptr++ = *iptr; + } + *ptr = 0; + if (dos_part >= 0) + snprintf (ptr, end - ptr, ",%d", dos_part + 1); + ptr += strlen (ptr); + if (bsd_part >= 0) + snprintf (ptr, end - ptr, ",%d", bsd_part + 1); + + return ret; +} + +#if defined(__sun__) +static int +device_is_wholedisk (const char *os_dev) +{ + if (grub_memcmp (os_dev, "/devices/", sizeof ("/devices/") - 1) != 0) + return 1; + if (grub_memcmp (os_dev + strlen (os_dev) - (sizeof (":q,raw") - 1), + ":q,raw", (sizeof (":q,raw") - 1)) == 0) + return 1; + return 0; +} +#endif + +#if defined(__linux__) || defined(__CYGWIN__) +static int +device_is_wholedisk (const char *os_dev) +{ + int len = strlen (os_dev); + + if (os_dev[len - 1] < '0' || os_dev[len - 1] > '9') + return 1; + return 0; +} +#endif + +#if defined(__NetBSD__) +/* Try to determine whether a given device name corresponds to a whole disk. + This function should give in most cases a definite answer, but it may + actually give an approximate one in the following sense: if the return + value is 0 then the device name does not correspond to a whole disk. */ +static int +device_is_wholedisk (const char *os_dev) +{ + int len = strlen (os_dev); + int rawpart = -1; + +# ifdef HAVE_GETRAWPARTITION + rawpart = getrawpartition(); +# endif /* HAVE_GETRAWPARTITION */ + if (rawpart < 0) + return 1; + return (os_dev[len - 1] == ('a' + rawpart)); +} +#endif /* defined(__NetBSD__) */ + +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +static int +device_is_wholedisk (const char *os_dev) +{ + const char *p; + + if (strncmp (os_dev, "/dev/", sizeof ("/dev/") - 1) != 0) + return 0; + + for (p = os_dev + sizeof ("/dev/") - 1; *p; ++p) + if (grub_isdigit (*p)) + { + if (strchr (p, 's')) + return 0; + break; + } + + return 1; +} +#endif /* defined(__FreeBSD__) || defined(__FreeBSD_kernel__) */ + +char * +grub_util_get_os_disk (const char *os_dev) +{ + struct stat st; + + grub_util_info ("Looking for %s", os_dev); + + if (stat (os_dev, &st) < 0) + { + const char *errstr = strerror (errno); + grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot stat `%s': %s"), + os_dev, errstr); + grub_util_info (_("cannot stat `%s': %s"), os_dev, errstr); + return 0; + } + + return convert_system_partition_to_system_disk (os_dev, &st); +} + +char * +grub_util_biosdisk_get_grub_dev (const char *os_dev) +{ + struct stat st; + const char *drive; + char *sys_disk; + + grub_util_info ("Looking for %s", os_dev); + + if (stat (os_dev, &st) < 0) + { + const char *errstr = strerror (errno); + grub_error (GRUB_ERR_BAD_DEVICE, N_("cannot stat `%s': %s"), os_dev, + errstr); + grub_util_info (_("cannot stat `%s': %s"), os_dev, errstr); + return 0; + } + + drive = find_system_device (os_dev, &st, 1, 1); + sys_disk = convert_system_partition_to_system_disk (os_dev, &st); + if (grub_strcmp (os_dev, sys_disk) == 0) + { + free (sys_disk); + return make_device_name (drive, -1, -1); + } + free (sys_disk); + +#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 + return make_device_name (drive, -1, -1); + +#if defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined (__sun__) + + /* Linux counts partitions uniformly, whether a BSD partition or a DOS + partition, so mapping them to GRUB devices is not trivial. + Here, get the start sector of a partition by HDIO_GETGEO, and + compare it with each partition GRUB recognizes. + + Cygwin /dev/sdXN emulation uses Windows partition mapping. It + does not count the extended partition and missing primary + partitions. Use same method as on Linux here. + + For NetBSD and FreeBSD, proceed as for Linux, except that the start + sector is obtained from the disk label. */ + { + char *name, *partname; + grub_disk_t disk; + grub_disk_addr_t start; + auto int find_partition (grub_disk_t dsk, + const grub_partition_t partition); + + int find_partition (grub_disk_t dsk __attribute__ ((unused)), + const grub_partition_t partition) + { + grub_disk_addr_t part_start = 0; + grub_util_info ("Partition %d starts from %" PRIuGRUB_UINT64_T, + partition->number, partition->start); + + part_start = grub_partition_get_start (partition); + + if (start == part_start) + { + partname = grub_partition_get_name (partition); + return 1; + } + + return 0; + } + + name = make_device_name (drive, -1, -1); + +# if !defined(HAVE_DIOCGDINFO) && !defined(__sun__) + if (MAJOR (st.st_rdev) == FLOPPY_MAJOR) + return name; +# else /* defined(HAVE_DIOCGDINFO) */ + /* Since os_dev and convert_system_partition_to_system_disk (os_dev) are + * different, we know that os_dev cannot be a floppy device. */ +# endif /* !defined(HAVE_DIOCGDINFO) */ + + start = grub_hostdisk_find_partition_start (os_dev); + if (grub_errno != GRUB_ERR_NONE) + { + free (name); + return 0; + } + + grub_util_info ("%s starts from %" PRIuGRUB_UINT64_T, os_dev, start); + + if (start == 0 && device_is_wholedisk (os_dev)) + return name; + + grub_util_info ("opening the device %s", name); + disk = grub_disk_open (name); + free (name); + + if (! disk) + { + /* We already know that the partition exists. Given that we already + checked the device map above, we can only get + GRUB_ERR_UNKNOWN_DEVICE at this point if the disk does not exist. + This can happen on Xen, where disk images in the host can be + assigned to devices that have partition-like names in the guest + but are really more like disks. */ + if (grub_errno == GRUB_ERR_UNKNOWN_DEVICE) + { + grub_util_warn + (_("disk does not exist, so falling back to partition device %s"), + os_dev); + + drive = find_system_device (os_dev, &st, 0, 1); + return make_device_name (drive, -1, -1); + } + else + return 0; + } + + name = grub_util_get_ldm (disk, start); + if (name) + return name; + + partname = NULL; + + grub_partition_iterate (disk, find_partition); + if (grub_errno != GRUB_ERR_NONE) + { + grub_disk_close (disk); + return 0; + } + + if (partname == NULL) + { + grub_disk_close (disk); + grub_util_info ("cannot find the partition of `%s'", os_dev); + grub_error (GRUB_ERR_BAD_DEVICE, + "cannot find the partition of `%s'", os_dev); + return 0; + } + + name = grub_xasprintf ("%s,%s", disk->name, partname); + free (partname); + grub_disk_close (disk); + return name; + } + +#elif defined(__GNU__) + /* GNU uses "/dev/[hs]d[0-9]+(s[0-9]+[a-z]?)?". */ + { + char *p; + int dos_part = -1; + int bsd_part = -1; + + p = strrchr (os_dev, 's'); + if (p) + { + long int n; + char *q; + + p++; + n = strtol (p, &q, 10); + if (p != q && n != GRUB_LONG_MIN && n != GRUB_LONG_MAX) + { + dos_part = (int) n - 1; + + if (*q >= 'a' && *q <= 'g') + bsd_part = *q - 'a'; + } + } + + return make_device_name (drive, dos_part, bsd_part); + } + +#else +# warning "The function `grub_util_biosdisk_get_grub_dev' might not work on your OS correctly." + return make_device_name (drive, -1, -1); +#endif +} + +int +grub_util_biosdisk_is_present (const char *os_dev) +{ + struct stat st; + + if (stat (os_dev, &st) < 0) + return 0; + + return find_system_device (os_dev, &st, 1, 0) != NULL; +} + char * grub_util_get_grub_dev (const char *os_dev) { @@ -1119,7 +2137,7 @@ grub_util_get_grub_dev (const char *os_dev) case GRUB_DEV_ABSTRACTION_LVM: { - unsigned short i, len; + unsigned short len; grub_size_t offset = sizeof (LVM_DEV_MAPPER_STRING) - 1; len = strlen (os_dev) - offset + 1; @@ -1167,6 +2185,9 @@ grub_util_get_grub_dev (const char *os_dev) error = geom_gettree (&mesh); if (error != 0) + /* TRANSLATORS: geom is the name of (k)FreeBSD device framework. + Usually left untranslated. + */ grub_util_error (_("couldn't open geom")); LIST_FOREACH (class, &mesh.lg_class, lg_class) @@ -1278,7 +2299,6 @@ grub_util_get_grub_dev (const char *os_dev) { char *mdadm_name = get_mdadm_uuid (os_dev); - struct stat st; if (mdadm_name) { @@ -1316,7 +2336,8 @@ grub_util_check_block_device (const char *blk_dev) struct stat st; if (stat (blk_dev, &st) < 0) - grub_util_error (_("cannot stat `%s'"), blk_dev); + grub_util_error (_("cannot stat `%s': %s"), blk_dev, + strerror (errno)); if (S_ISBLK (st.st_mode)) return (blk_dev); @@ -1330,7 +2351,7 @@ grub_util_check_char_device (const char *blk_dev) struct stat st; if (stat (blk_dev, &st) < 0) - grub_util_error (_("cannot stat `%s'"), blk_dev); + grub_util_error (_("cannot stat `%s': %s"), blk_dev, strerror (errno)); if (S_ISCHR (st.st_mode)) return (blk_dev); @@ -1383,7 +2404,6 @@ grub_get_libzfs_handle (void) } #endif /* HAVE_LIBZFS */ -#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) /* ZFS has similar problems to those of btrfs (see above). */ void grub_find_zpool_from_dir (const char *dir, char **poolname, char **poolfs) @@ -1444,7 +2464,6 @@ grub_find_zpool_from_dir (const char *dir, char **poolname, char **poolfs) else *poolfs = xstrdup (""); } -#endif /* This function never prints trailing slashes (so that its output can be appended a slash unconditionally). */ @@ -1456,30 +2475,25 @@ grub_make_system_path_relative_to_its_root (const char *path) uintptr_t offset = 0; dev_t num; size_t len; - -#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) char *poolfs = NULL; -#endif /* canonicalize. */ p = canonicalize_file_name (path); if (p == NULL) grub_util_error (_("failed to get canonical path of %s"), path); -#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) /* For ZFS sub-pool filesystems, could be extended to others (btrfs?). */ { char *dummy; grub_find_zpool_from_dir (p, &dummy, &poolfs); } -#endif len = strlen (p) + 1; buf = xstrdup (p); free (p); if (stat (buf, &st) < 0) - grub_util_error (_("cannot stat %s: %s"), buf, strerror (errno)); + grub_util_error (_("cannot stat `%s': %s"), buf, strerror (errno)); buf2 = xstrdup (buf); num = st.st_dev; @@ -1491,14 +2505,15 @@ grub_make_system_path_relative_to_its_root (const char *path) p = strrchr (buf, '/'); if (p == NULL) /* This should never happen. */ - grub_util_error (_("FIXME: no / in buf. (make_system_path_relative_to_its_root)")); + grub_util_error ("%s", + _("FIXME: no / in buf. (make_system_path_relative_to_its_root)")); if (p != buf) *p = 0; else *++p = 0; if (stat (buf, &st) < 0) - grub_util_error (_("cannot stat %s: %s"), buf, strerror (errno)); + grub_util_error (_("cannot stat `%s': %s"), buf, strerror (errno)); /* buf is another filesystem; we found it. */ if (st.st_dev != num) @@ -1514,7 +2529,7 @@ grub_make_system_path_relative_to_its_root (const char *path) #ifdef __linux__ { char *bind; - grub_free (grub_find_root_device_from_mountinfo (buf2, &bind)); + grub_free (grub_find_root_devices_from_mountinfo (buf2, &bind)); if (bind && bind[0] && bind[1]) { buf3 = bind; @@ -1524,10 +2539,8 @@ grub_make_system_path_relative_to_its_root (const char *path) } #endif free (buf2); -#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) if (poolfs) return xasprintf ("/%s/@", poolfs); -#endif return xstrdup (""); } else @@ -1549,7 +2562,7 @@ grub_make_system_path_relative_to_its_root (const char *path) #ifdef __linux__ { char *bind; - grub_free (grub_find_root_device_from_mountinfo (buf2, &bind)); + grub_free (grub_find_root_devices_from_mountinfo (buf2, &bind)); if (bind && bind[0] && bind[1]) { char *temp = buf3; @@ -1584,14 +2597,12 @@ grub_make_system_path_relative_to_its_root (const char *path) len--; } -#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) if (poolfs) { ret = xasprintf ("/%s/@%s", poolfs, buf3); free (buf3); } else -#endif ret = buf3; return ret; diff --git a/util/grub-editenv.c b/util/grub-editenv.c index 2bff80612..cb212f0b9 100644 --- a/util/grub-editenv.c +++ b/util/grub-editenv.c @@ -47,7 +47,7 @@ static struct argp_option options[] = { N_("Delete variables."), 0}, {0, 0, 0, OPTION_DOC, N_("Options:"), -1}, - {"verbose", 'v', 0, 0, N_("Print verbose messages."), 0}, + {"verbose", 'v', 0, 0, N_("print verbose messages."), 0}, { 0, 0, 0, 0, 0, 0 } }; @@ -63,7 +63,7 @@ void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version; /* Set the bug report address */ const char *argp_program_bug_address = "<"PACKAGE_BUGREPORT">"; -error_t argp_parser (int key, char *arg, struct argp_state *state) +static error_t argp_parser (int key, char *arg, struct argp_state *state) { switch (key) { @@ -113,21 +113,21 @@ create_envblk_file (const char *name) char *buf; char *namenew; - buf = malloc (DEFAULT_ENVBLK_SIZE); - if (! buf) - grub_util_error (_("out of memory")); + buf = xmalloc (DEFAULT_ENVBLK_SIZE); namenew = xasprintf ("%s.new", name); fp = fopen (namenew, "wb"); if (! fp) - grub_util_error (_("cannot open the file %s"), namenew); + grub_util_error (_("cannot open `%s': %s"), namenew, + strerror (errno)); memcpy (buf, GRUB_ENVBLK_SIGNATURE, sizeof (GRUB_ENVBLK_SIGNATURE) - 1); memset (buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1, '#', DEFAULT_ENVBLK_SIZE - sizeof (GRUB_ENVBLK_SIGNATURE) + 1); if (fwrite (buf, 1, DEFAULT_ENVBLK_SIZE, fp) != DEFAULT_ENVBLK_SIZE) - grub_util_error (_("cannot write to the file %s"), namenew); + grub_util_error (_("cannot write to `%s': %s"), namenew, + strerror (errno)); fsync (fileno (fp)); free (buf); @@ -153,29 +153,31 @@ open_envblk_file (const char *name) create_envblk_file (name); fp = fopen (name, "rb"); if (! fp) - grub_util_error (_("cannot open the file %s"), name); + grub_util_error (_("cannot open `%s': %s"), name, + strerror (errno)); } if (fseek (fp, 0, SEEK_END) < 0) - grub_util_error (_("cannot seek the file %s"), name); + grub_util_error (_("cannot seek `%s': %s"), name, + strerror (errno)); size = (size_t) ftell (fp); if (fseek (fp, 0, SEEK_SET) < 0) - grub_util_error (_("cannot seek the file %s"), name); + grub_util_error (_("cannot seek `%s': %s"), name, + strerror (errno)); - buf = malloc (size); - if (! buf) - grub_util_error (_("out of memory")); + buf = xmalloc (size); if (fread (buf, 1, size, fp) != size) - grub_util_error (_("cannot read the file %s"), name); + grub_util_error (_("cannot read `%s': %s"), name, + strerror (errno)); fclose (fp); envblk = grub_envblk_open (buf, size); if (! envblk) - grub_util_error (_("invalid environment block")); + grub_util_error ("%s", _("invalid environment block")); return envblk; } @@ -185,10 +187,10 @@ list_variables (const char *name) { grub_envblk_t envblk; - auto int print_var (const char *name, const char *value); - int print_var (const char *name, const char *value) + auto int print_var (const char *varname, const char *value); + int print_var (const char *varname, const char *value) { - printf ("%s=%s\n", name, value); + printf ("%s=%s\n", varname, value); return 0; } @@ -204,11 +206,13 @@ write_envblk (const char *name, grub_envblk_t envblk) fp = fopen (name, "wb"); if (! fp) - grub_util_error (_("cannot open the file %s"), name); + grub_util_error (_("cannot open `%s': %s"), name, + strerror (errno)); if (fwrite (grub_envblk_buffer (envblk), 1, grub_envblk_size (envblk), fp) != grub_envblk_size (envblk)) - grub_util_error (_("cannot write to the file %s"), name); + grub_util_error (_("cannot write to `%s': %s"), name, + strerror (errno)); fsync (fileno (fp)); fclose (fp); @@ -231,7 +235,7 @@ set_variables (const char *name, int argc, char *argv[]) *(p++) = 0; if (! grub_envblk_set (envblk, argv[0], p)) - grub_util_error (_("environment block too small")); + grub_util_error ("%s", _("environment block too small")); argc--; argv++; @@ -262,34 +266,34 @@ unset_variables (const char *name, int argc, char *argv[]) int main (int argc, char *argv[]) { - char *filename; + const char *filename; char *command; - int index, arg_count; + int curindex, arg_count; set_program_name (argv[0]); grub_util_init_nls (); /* Parse our arguments */ - if (argp_parse (&argp, argc, argv, 0, &index, 0) != 0) + if (argp_parse (&argp, argc, argv, 0, &curindex, 0) != 0) { fprintf (stderr, "%s", _("Error in parsing command line arguments\n")); exit(1); } - arg_count = argc - index; + arg_count = argc - curindex; if (arg_count == 1) { filename = DEFAULT_ENVBLK_PATH; - command = argv[index++]; + command = argv[curindex++]; } else { - filename = argv[index++]; + filename = argv[curindex++]; if (strcmp (filename, "-") == 0) filename = DEFAULT_ENVBLK_PATH; - command = argv[index++]; + command = argv[curindex++]; } if (strcmp (command, "create") == 0) @@ -297,9 +301,9 @@ main (int argc, char *argv[]) else if (strcmp (command, "list") == 0) list_variables (filename); else if (strcmp (command, "set") == 0) - set_variables (filename, argc - index, argv + index); + set_variables (filename, argc - curindex, argv + curindex); else if (strcmp (command, "unset") == 0) - unset_variables (filename, argc - index, argv + index); + unset_variables (filename, argc - curindex, argv + curindex); else { char *program = xstrdup(program_name); diff --git a/util/grub-fstest.c b/util/grub-fstest.c index 886155fe2..1ce41ee8b 100644 --- a/util/grub-fstest.c +++ b/util/grub-fstest.c @@ -44,13 +44,13 @@ #include "argp.h" static grub_err_t -execute_command (char *name, int n, char **args) +execute_command (const char *name, int n, char **args) { grub_command_t cmd; cmd = grub_command_find (name); if (! cmd) - grub_util_error (_("can\'t find command %s"), name); + grub_util_error (_("can't find command `%s'"), name); return (cmd->func) (cmd, n, args); } @@ -77,7 +77,6 @@ read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len)) { static char buf[BUF_SIZE]; grub_file_t file; - grub_off_t ofs, len; if ((pathname[0] == '-') && (pathname[1] == 0)) { @@ -85,7 +84,7 @@ read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len)) dev = grub_device_open (0); if ((! dev) || (! dev->disk)) - grub_util_error (_("can\'t open device")); + grub_util_error ("%s", grub_errmsg); grub_util_info ("total sectors : %lld", (unsigned long long) dev->disk->total_sectors); @@ -119,7 +118,7 @@ read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len)) file = grub_file_open (pathname); if (!file) { - grub_util_error (_("cannot open file %s:%s"), pathname, + grub_util_error (_("cannot open `%s': %s"), pathname, grub_errmsg); return; } @@ -132,31 +131,34 @@ read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len)) return; } - ofs = skip; - len = file->size - skip; - if ((leng) && (leng < len)) - len = leng; + { + grub_off_t ofs, len; + ofs = skip; + len = file->size - skip; + if ((leng) && (leng < len)) + len = leng; - file->offset = skip; + file->offset = skip; - while (len) - { - grub_ssize_t sz; + while (len) + { + grub_ssize_t sz; - sz = grub_file_read (file, buf, (len > BUF_SIZE) ? BUF_SIZE : len); - if (sz < 0) - { - grub_util_error (_("read error at offset %llu: %s"), ofs, - grub_errmsg); + sz = grub_file_read (file, buf, (len > BUF_SIZE) ? BUF_SIZE : len); + if (sz < 0) + { + grub_util_error (_("read error at offset %llu: %s"), ofs, + grub_errmsg); + break; + } + + if ((sz == 0) || (hook (ofs, buf, sz))) break; - } - if ((sz == 0) || (hook (ofs, buf, sz))) - break; - - ofs += sz; - len -= sz; - } + ofs += sz; + len -= sz; + } + } grub_file_close (file); } @@ -173,7 +175,8 @@ cmd_cp (char *src, char *dest) if ((int) fwrite (buf, 1, len, ff) != len) { - grub_util_error (_("write error")); + grub_util_error (_("cannot write to `%s': %s"), + dest, strerror (errno)); return 1; } @@ -183,7 +186,7 @@ cmd_cp (char *src, char *dest) ff = fopen (dest, "wb"); if (ff == NULL) { - grub_util_error (_("OS file %s open error: %s"), dest, + grub_util_error (_("cannot open OS file `%s': %s"), dest, strerror (errno)); return; } @@ -201,7 +204,8 @@ cmd_cat (char *src) if ((int) fwrite (buf, 1, len, stdout) != len) { - grub_util_error (_("write error")); + grub_util_error (_("cannot write to the stdout: %s"), + strerror (errno)); return 1; } @@ -222,7 +226,8 @@ cmd_cmp (char *src, char *dest) { if ((int) fread (buf_1, 1, len, ff) != len) { - grub_util_error (_("read error at offset %llu: %s"), ofs, grub_errmsg); + grub_util_error (_("read error at offset %llu: %s"), ofs, + grub_errmsg); return 1; } @@ -249,7 +254,8 @@ cmd_cmp (char *src, char *dest) } if ((skip) && (fseeko (ff, skip, SEEK_SET))) - grub_util_error (_("seek error")); + grub_util_error (_("cannot seek `%s': %s"), dest, + strerror (errno)); read_file (src, cmp_hook); @@ -258,7 +264,7 @@ cmd_cmp (char *src, char *dest) pre = ftell (ff); fseek (ff, 0, SEEK_END); if (pre != ftell (ff)) - grub_util_error (_("unexpected end of file")); + grub_util_error ("%s", _("unexpected end of file")); } fclose (ff); } @@ -297,7 +303,7 @@ cmd_crc (char *pathname) grub_be_to_cpu32(*(grub_uint32_t*)GRUB_MD_CRC32->read(crc32_context))); } -static char *root = NULL; +static const char *root = NULL; static int args_count = 0; static int nparm = 0; static int num_disks = 1; @@ -308,7 +314,7 @@ static char **args = NULL; static int mount_crypt = 0; static void -fstest (int n, char **args) +fstest (int n) { char *host_file; char *loop_name; @@ -319,39 +325,43 @@ fstest (int n, char **args) char *argv[2]; loop_name = grub_xasprintf ("loop%d", i); if (!loop_name) - grub_util_error (grub_errmsg); + grub_util_error ("%s", grub_errmsg); host_file = grub_xasprintf ("(host)%s", images[i]); if (!host_file) - grub_util_error (grub_errmsg); + grub_util_error ("%s", grub_errmsg); argv[0] = loop_name; argv[1] = host_file; if (execute_command ("loopback", 2, argv)) - grub_util_error (_("loopback command fails")); + grub_util_error (_("`loopback' command fails: %s"), grub_errmsg); grub_free (loop_name); grub_free (host_file); } { - char *argv[2] = { "-a", NULL}; if (mount_crypt) { + char *argv[2] = { xstrdup ("-a"), NULL}; if (execute_command ("cryptomount", 1, argv)) - grub_util_error (_("cryptomount command fails: %s"), grub_errmsg); + grub_util_error (_("`cryptomount' command fails: %s"), + grub_errmsg); + free (argv[0]); } } + grub_ldm_fini (); grub_lvm_fini (); grub_mdraid09_fini (); grub_mdraid1x_fini (); - grub_raid_fini (); - grub_raid_init (); + grub_diskfilter_fini (); + grub_diskfilter_init (); grub_mdraid09_init (); grub_mdraid1x_init (); grub_lvm_init (); + grub_ldm_init (); switch (cmd) { @@ -387,21 +397,22 @@ fstest (int n, char **args) grub_device_t dev; grub_fs_t fs; char *uuid = 0; - char *argv[3] = { "-l", NULL, NULL}; + char *argv[3] = { xstrdup ("-l"), NULL, NULL}; dev = grub_device_open (n ? args[0] : 0); if (!dev) - grub_util_error (grub_errmsg); + grub_util_error ("%s", grub_errmsg); fs = grub_fs_probe (dev); if (!fs) - grub_util_error (grub_errmsg); + grub_util_error ("%s", grub_errmsg); if (!fs->uuid) - grub_util_error (_("couldn't retrieve UUID")); + grub_util_error ("%s", _("couldn't retrieve UUID")); if (fs->uuid (dev, &uuid)) - grub_util_error (grub_errmsg); + grub_util_error ("%s", grub_errmsg); if (!uuid) - grub_util_error (_("couldn't retrieve UUID")); + grub_util_error ("%s", _("couldn't retrieve UUID")); argv[1] = uuid; execute_command ("xnu_uuid", 2, argv); + grub_free (argv[0]); grub_free (uuid); grub_device_close (dev); } @@ -413,14 +424,15 @@ fstest (int n, char **args) loop_name = grub_xasprintf ("loop%d", i); if (!loop_name) - grub_util_error (grub_errmsg); + grub_util_error ("%s", grub_errmsg); - argv[0] = "-d"; + argv[0] = xstrdup ("-d"); argv[1] = loop_name; execute_command ("loopback", 2, argv); grub_free (loop_name); + grub_free (argv[0]); } } @@ -430,19 +442,21 @@ static struct argp_option options[] = { {N_("cp FILE LOCAL"), 0, 0, OPTION_DOC, N_("Copy FILE to local file LOCAL."), 1}, {N_("cat FILE"), 0, 0 , OPTION_DOC, N_("Copy FILE to standard output."), 1}, {N_("cmp FILE LOCAL"), 0, 0, OPTION_DOC, N_("Compare FILE with local file LOCAL."), 1}, - {N_("hex FILE"), 0, 0 , OPTION_DOC, N_("Hex dump FILE."), 1}, + {N_("hex FILE"), 0, 0 , OPTION_DOC, N_("Show contents of FILE in hex."), 1}, {N_("crc FILE"), 0, 0 , OPTION_DOC, N_("Get crc32 checksum of FILE."), 1}, {N_("blocklist FILE"), 0, 0, OPTION_DOC, N_("Display blocklist of FILE."), 1}, - {N_("xnu_uuid"), 0, 0, OPTION_DOC, N_("Compute XNU UUID of the device."), 1}, + {N_("xnu_uuid DEVICE"), 0, 0, OPTION_DOC, N_("Compute XNU UUID of the device."), 1}, {"root", 'r', N_("DEVICE_NAME"), 0, N_("Set root device."), 2}, {"skip", 's', "N", 0, N_("Skip N bytes from output file."), 2}, {"length", 'n', "N", 0, N_("Handle N bytes in output file."), 2}, - {"diskcount", 'c', "N", 0, N_("N input files."), 2}, + {"diskcount", 'c', "N", 0, N_("Specify the number of input files."), 2}, {"debug", 'd', "S", 0, N_("Set debug environment variable."), 2}, {"crypto", 'C', NULL, OPTION_ARG_OPTIONAL, N_("Mount crypto devices."), 2}, - {"zfs-key", 'K', N_("FILE|prompt"), 0, N_("Load zfs crypto key."), 2}, - {"verbose", 'v', NULL, OPTION_ARG_OPTIONAL, N_("Print verbose messages."), 2}, + {"zfs-key", 'K', + /* TRANSLATORS: "prompt" is a keyword. */ + N_("FILE|prompt"), 0, N_("Load zfs crypto key."), 2}, + {"verbose", 'v', NULL, OPTION_ARG_OPTIONAL, N_("print verbose messages."), 2}, {"uncompress", 'u', NULL, OPTION_ARG_OPTIONAL, N_("Uncompress data."), 2}, {0, 0, 0, 0, 0, 0} }; @@ -455,7 +469,7 @@ print_version (FILE *stream, struct argp_state *state) } void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version; -error_t +static error_t argp_parser (int key, char *arg, struct argp_state *state) { char *p; @@ -484,13 +498,17 @@ argp_parser (int key, char *arg, struct argp_state *state) f = fopen (arg, "rb"); if (!f) { - printf (_("Error loading file %s: %s\n"), arg, strerror (errno)); + printf (_("%s: error:"), program_name); + printf (_("cannot open `%s': %s"), arg, strerror (errno)); + printf ("\n"); return 0; } real_size = fread (buf, 1, 1024, f); if (real_size < 0) { - printf (_("Error loading file %s: %s\n"), arg, strerror (errno)); + printf (_("%s: error:"), program_name); + printf (_("cannot read `%s': %s"), arg, strerror (errno)); + printf ("\n"); fclose (f); return 0; } @@ -523,6 +541,9 @@ argp_parser (int key, char *arg, struct argp_state *state) } if (args_count != 0) { + /* TRANSLATORS: disk count is optional but if it's there it must + be before disk list. So please don't imply disk count as mandatory. + */ fprintf (stderr, "%s", _("Disk count must precede disks list.\n")); argp_usage (state); } @@ -642,7 +663,8 @@ struct argp argp = { int main (int argc, char *argv[]) { - char *default_root, *alloc_root; + const char *default_root; + char *alloc_root; set_program_name (argv[0]); @@ -680,7 +702,7 @@ main (int argc, char *argv[]) free (alloc_root); /* Do it. */ - fstest (args_count - 1 - num_disks, args); + fstest (args_count - 1 - num_disks); /* Free resources. */ grub_gcry_fini_all (); diff --git a/util/grub-install.in b/util/grub-install.in index ea8699a44..747ef1729 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -21,6 +21,7 @@ transform="@program_transform_name@" prefix="@prefix@" exec_prefix="@exec_prefix@" +datarootdir="@datarootdir@" sbindir="@sbindir@" bindir="@bindir@" libdir="@libdir@" @@ -31,15 +32,17 @@ PACKAGE_VERSION=@PACKAGE_VERSION@ target_cpu=@target_cpu@ platform=@platform@ host_os=@host_os@ -datarootdir=@datarootdir@ pkglibdir="${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}`" +datadir="@datadir@" +if [ "x$pkgdatadir" = x ]; then + pkgdatadir="${datadir}/`echo @PACKAGE_TARNAME@ | sed "${transform}"`" +fi localedir="@datadir@/locale" self="`basename $0`" grub_setup="${sbindir}/`echo grub-setup | sed ${transform}`" grub_mkimage="${bindir}/`echo grub-mkimage | sed ${transform}`" -grub_mkdevicemap="${sbindir}/`echo grub-mkdevicemap | sed ${transform}`" grub_probe="${sbindir}/`echo grub-probe | sed ${transform}`" grub_editenv="${bindir}/`echo grub-editenv | sed ${transform}`" grub_mkrelpath="${bindir}/`echo grub-mkrelpath | sed ${transform}`" @@ -49,7 +52,6 @@ grubdir="`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'`" modules= install_device= -no_floppy= force_lba= recheck=no debug=no @@ -78,63 +80,51 @@ else disk_module=native fi +. "${pkgdatadir}/grub-mkconfig_lib" + # Usage: usage # Print the usage. usage () { -if [ "${target_cpu}-${platform}" = "i386-pc" ] \ - || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ]; then - cat <. -EOF +gettext_printf "%s copies GRUB images into %s, and uses grub-setup +to install grub into the boot sector.\n" "$self" "$grubdir";echo +echo +gettext "Report bugs to ."; echo } argument () { @@ -142,7 +132,7 @@ argument () { shift if test $# -eq 0; then - echo "$0: option requires an argument -- '$opt'" 1>&2 + gettext_printf "%s: option requires an argument -- '%s'" "$0" "$opt" 1>&2 exit 1 fi echo "$1" @@ -206,10 +196,11 @@ do --grub-mkrelpath=*) grub_mkrelpath="`echo "$option" | sed 's/--grub-mkrelpath=//'`" ;; + # Ignore: for compatibility --grub-mkdevicemap) - grub_mkdevicemap="`argument "$option" "$@"`"; shift;; + shift;; --grub-mkdevicemap=*) - grub_mkdevicemap="`echo "$option" | sed 's/--grub-mkdevicemap=//'`" ;; + ;; --grub-probe) grub_probe="`argument "$option" "$@"`"; shift;; @@ -217,7 +208,7 @@ do grub_probe="`echo "$option" | sed 's/--grub-probe=//'`" ;; --no-floppy) - no_floppy="--no-floppy" ;; + ;; --recheck) recheck=yes ;; --removable) @@ -250,13 +241,14 @@ do setup_force="--force" ;; -*) - echo "Unrecognized option \`$option'" 1>&2 + gettext_printf "Unrecognized option \`%s'\n" "$option" 1>&2 usage exit 1 ;; *) if test "x$install_device" != x; then - echo "More than one install_devices?" 1>&2 + gettext "More than one install_devices?" 1>&2 + echo 1>&2 usage exit 1 fi @@ -264,17 +256,18 @@ do esac done -. ${libdir}/@PACKAGE@/grub-mkconfig_lib - if test "x$install_device" = x && ([ "${target_cpu}-${platform}" = "i386-pc" ] \ || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ]); then - echo "install_device not specified." 1>&2 + gettext "Install device isn't specified." 1>&2 + echo 1>&2 usage exit 1 fi if ! ([ "${target_cpu}-${platform}" = "i386-pc" ] \ - || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ]); then + || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] \ + || [ "${target_cpu}-${platform}" = "powerpc-ieee1275" ] \ + || [ "${target_cpu}-${platform}" = "mips-arc" ]); then install_device= fi @@ -319,35 +312,27 @@ else exit 1 fi -set "$grub_mkdevicemap" dummy -if test -f "$1"; then - : -else - echo "$1: Not found." 1>&2 - exit 1 -fi - if [ x"$platform" = xefi ]; then # Find the EFI System Partition. efidir= if test -d "${bootdir}/efi"; then - install_device="`"$grub_mkdevicemap" --device-map=/dev/stdout | "$grub_probe" --target=device --device-map=/dev/stdin "${bootdir}/efi"`" + install_device="`"$grub_probe" --target=device --device-map= "${bootdir}/efi"`" # Is it a mount point? - if test "x$install_device" != "x`"$grub_mkdevicemap" --device-map=/dev/stdout | "$grub_probe" --target=device --device-map=/dev/stdin "${bootdir}"`"; then + if test "x$install_device" != "x`"$grub_probe" --target=device --device-map= "${bootdir}"`"; then efidir="${bootdir}/efi" fi elif test -d "${bootdir}/EFI"; then - install_device="`"$grub_mkdevicemap" --device-map=/dev/stdout | "$grub_probe" --target=device --device-map=/dev/stdin "${bootdir}/EFI"`" + install_device="`"$grub_probe" --target=device --device-map= "${bootdir}/EFI"`" # Is it a mount point? - if test "x$install_device" != "x`"$grub_mkdevicemap" --device-map=/dev/stdout | "$grub_probe" --target=device --device-map=/dev/stdin "${bootdir}"`"; then + if test "x$install_device" != "x`"$grub_probe" --target=device --device-map= "${bootdir}"`"; then efidir="${bootdir}/EFI" fi elif test -n "$rootdir" && test "x$rootdir" != "x/"; then # The EFI System Partition may have been given directly using # --root-directory. - install_device="`"$grub_mkdevicemap" --device-map=/dev/stdout | "$grub_probe" --target=device --device-map=/dev/stdin "${rootdir}"`" + install_device="`"$grub_probe" --target=device --device-map= "${rootdir}"`" # Is it a mount point? - if test "x$install_device" != "x`"$grub_mkdevicemap" --device-map=/dev/stdout | "$grub_probe" --target=device --device-map=/dev/stdin "${rootdir}/.."`"; then + if test "x$install_device" != "x`"$grub_probe" --target=device --device-map= "${rootdir}/.."`"; then efidir="${rootdir}" fi fi @@ -355,7 +340,7 @@ if [ x"$platform" = xefi ]; then if test -n "$efidir"; then efi_fs=`"$grub_probe" --target=fs "--device-map=${device_map}" "${efidir}"` if test "x$efi_fs" = xfat; then :; else - echo "${efidir} doesn't look like an EFI partition." 1>&2 + gettext_printf "%s doesn't look like an EFI partition.\n" "${efidir}" 1>&2 efidir= fi fi @@ -416,6 +401,7 @@ fi # Create the GRUB directory if it is not present. mkdir -p "$grubdir" || exit 1 +mkdir -p "$grubdir/${target_cpu}-$platform" || exit 1 # If --recheck is specified, remove the device map, if present. if test $recheck = yes; then @@ -424,35 +410,30 @@ fi # Create the device map file if it is not present. if test -f "$device_map"; then - : + # Make sure that there is no duplicated entry. + tmp=`sed -n '/^([fh]d[0-9]*)/s/\(^(.*)\).*/\1/p' "$device_map" \ + | sort | uniq -d | sed -n 1p` + if test -n "$tmp"; then + gettext_printf "The drive %s is defined multiple times in the device map %s\n" "$tmp" "$device_map" 1>&2 + exit 1 + fi else - # Create a safe temporary file. - test -n "$mklog" && log_file=`$mklog` - - "$grub_mkdevicemap" "--device-map=$device_map" $no_floppy || exit 1 -fi - -# Make sure that there is no duplicated entry. -tmp=`sed -n '/^([fh]d[0-9]*)/s/\(^(.*)\).*/\1/p' "$device_map" \ - | sort | uniq -d | sed -n 1p` -if test -n "$tmp"; then - echo "The drive $tmp is defined multiple times in the device map $device_map" 1>&2 - exit 1 + device_map= fi # Copy the GRUB images to the GRUB directory. -for file in "${grubdir}"/*.mod "${grubdir}"/*.lst "${grubdir}"/*.img "${grubdir}"/efiemu??.o; do +for file in "${grubdir}"/*.mod "${grubdir}"/*.lst "${grubdir}"/*.img "${grubdir}"/efiemu??.o "${grubdir}"/${target_cpu}-$platform/*.mod "${grubdir}"/${target_cpu}-$platform/*.lst "${grubdir}"/${target_cpu}-$platform/*.img "${grubdir}"/${target_cpu}-$platform/efiemu??.o; do if test -f "$file" && [ "`basename $file`" != menu.lst ]; then rm -f "$file" || exit 1 fi done for file in "${pkglibdir}"/*.mod "${pkglibdir}"/*.lst; do - cp -f "$file" "${grubdir}" || exit 1 + cp -f "$file" "${grubdir}/${target_cpu}-$platform" || exit 1 done if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then for file in "${pkglibdir}"/*.img "${pkglibdir}"/efiemu??.o; do if test -f "$file"; then - cp -f "$file" "${grubdir}" || exit 1 + cp -f "$file" "${grubdir}/${target_cpu}-$platform" || exit 1 fi done fi @@ -465,7 +446,7 @@ for dir in "${localedir}"/*; do fi done -is_path_readable_by_grub "${grubdir}" || (echo "${grubdir}" not readable 1>&2 ; exit 1) +is_path_readable_by_grub "${grubdir}/${target_cpu}-$platform" || (echo "${grubdir}" not readable 1>&2 ; exit 1) # Write device to a variable so we don't have to traverse /dev every time. grub_device="`"$grub_probe" --device-map="${device_map}" --target=device "${grubdir}"`" || exit 1 @@ -475,11 +456,12 @@ if ! test -f "${grubdir}"/grubenv; then fi # Create the core image. First, auto-detect the filesystem module. -fs_module="`"$grub_probe" --device-map="${device_map}" --target=fs --device "${grub_device}"`" +fs_module="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=fs --device `" if test "x$fs_module" = x ; then - echo "Auto-detection of a filesystem of ${grub_device} failed." 1>&2 - echo "Try with --recheck." 1>&2 - echo "If the problem persists please report this together with the output of \"$grub_probe --device-map=\"${device_map}\" --target=fs -v ${grubdir}\" to " 1>&2 + gettext_printf "Auto-detection of a filesystem of %s failed.\n" "${grub_device}" 1>&2 + gettext "Try with --recheck." 1>&2 + echo 1>&2 + gettext_printf "If the problem persists please report this together with the output of %s to <%s>" "\"$grub_probe --device-map=\"${device_map}\" --target=fs -v ${grubdir}\"" "bug-grub@gnu.org" 1>&2 exit 1 fi @@ -487,7 +469,7 @@ fi # this command is allowed to fail (--target=fs already grants us that the # filesystem will be accessible). partmap_module= -for x in `"$grub_probe" --device-map="${device_map}" --target=partmap --device "${grub_device}" 2> /dev/null`; do +for x in `echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=partmap --device 2> /dev/null`; do case "$x" in netbsd | openbsd) partmap_module="$partmap_module part_bsd";; @@ -498,7 +480,7 @@ for x in `"$grub_probe" --device-map="${device_map}" --target=partmap --device " done # Device abstraction module, if any (lvm, raid). -devabstraction_module="`"$grub_probe" --device-map="${device_map}" --target=abstraction --device "${grub_device}"`" +devabstraction_module="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=abstraction --device`" if [ "x$disk_module" = xata ]; then disk_module=pata @@ -524,11 +506,11 @@ fi prefix_drive= config_opt= -rm -f "${grubdir}/load.cfg" +rm -f "${grubdir}/${target_cpu}-$platform/load.cfg" if [ "x${debug_image}" != x ]; then - echo "set debug='${debug_image}'" >> "${grubdir}/load.cfg" - config_opt="-c ${grubdir}/load.cfg " + echo "set debug='${debug_image}'" >> "${grubdir}/${target_cpu}-$platform/load.cfg" + config_opt="-c ${grubdir}/${target_cpu}-$platform/load.cfg " fi if [ "x${devabstraction_module}" = "x" ] ; then @@ -538,46 +520,64 @@ if [ "x${devabstraction_module}" = "x" ] ; then else install_drive="`"$grub_probe" --device-map="${device_map}" --target=drive --device "${install_device}"`" || exit 1 fi - install_drive="`echo "${install_drive}" | sed -e s/,[a-z0-9,]*//g`" + install_drive="`echo "${install_drive}" | sed -e 's/^(\(\([^,\\\\]\|\\\\\\\\\|\\\\,\)*\)\(\(,[a-zA-Z0-9]*\)*\))$/\1/'`" fi - grub_drive="`"$grub_probe" --device-map="${device_map}" --target=drive --device "${grub_device}"`" || exit 1 + grub_drive="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=drive --device`" || exit 1 # Strip partition number - grub_partition="`echo "${grub_drive}" | sed -e 's/^[^,]*[,)]//; s/)$//'`" - grub_drive="`echo "${grub_drive}" | sed -e s/,[a-z0-9,]*//g`" + grub_partition="`echo "${grub_drive}" | sed -e 's/^(\(\([^,\\\\]\|\\\\\\\\\|\\\\,\)*\)\(\(,[a-zA-Z0-9]*\)*\))$/\3/'`" + grub_drive="`echo "${grub_drive}" | sed -e 's/^(\(\([^,\\\\]\|\\\\\\\\\|\\\\,\)*\)\(\(,[a-zA-Z0-9]*\)*\))$/\1/'`" if ([ "x$disk_module" != x ] && [ "x$disk_module" != xbiosdisk ]) || [ "x${grub_drive}" != "x${install_drive}" ] || ([ "x$platform" != xefi ] && [ "x$platform" != xpc ] && [ x"${platform}" != x"ieee1275" ]); then # generic method (used on coreboot and ata mod) - uuid="`"$grub_probe" --device-map="${device_map}" --target=fs_uuid --device "${grub_device}"`" + uuid="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=fs_uuid --device`" if [ "x${uuid}" = "x" ] ; then if [ "x$platform" != xefi ] && [ "x$platform" != xpc ] && [ x"${platform}" != x"ieee1275" ]; then - echo "UUID needed with $platform, but the filesystem containing ${grubdir} does not support UUIDs." 1>&2 + gettext_printf "UUID needed with $platform, but the filesystem containing %s does not support UUIDs.\n" "${grubdir}" 1>&2 elif [ "$disk_module" = ata ]; then - echo "UUID needed with ata mod, but the filesystem containing ${grubdir} does not support UUIDs." 1>&2 + gettext_printf "UUID needed with ata mod, but the filesystem containing %s does not support UUIDs.\n" "${grubdir}" 1>&2 else - echo "UUID needed with cross-disk installs, but the filesystem containing ${grubdir} does not support UUIDs." 1>&2 + # TRANSLATORS: cross-disk refers to /boot being on one disk + # but MBR on another. + gettext_printf "UUID needed with cross-disk installs, but the filesystem containing %s does not support UUIDs.\n" "${grubdir}" 1>&2 fi exit 1 fi - echo "search.fs_uuid ${uuid} root " >> "${grubdir}/load.cfg" - echo 'set prefix=($root)'"${relative_grubdir}" >> "${grubdir}/load.cfg" - config_opt="-c ${grubdir}/load.cfg " + if [ x"$disk_module" != x ] && [ x"$disk_module" != xbiosdisk ]; then + hints="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=baremetal_hints --device`" + elif [ x"$platform" = xpc ]; then + hints="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=bios_hints --device`" + elif [ x"$platform" = xefi ]; then + hints="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=efi_hints --device`" + elif [ x"$platform" = xieee1275 ]; then + hints="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=ieee1275_hints --device`" + elif [ x"$platform" = xloongson ] || [ x"$platform" = xqemu ] || [ x"$platform" = xcoreboot ] || [ x"$platform" = xmultiboot ] || [ x"$platform" = xqemu-mips ]; then + hints="`echo "${grub_device}" | xargs "$grub_probe" --device-map="${device_map}" --target=baremetal_hints --device`" + else + gettext "No hints available for your platform. Expect reduced performance" 1>&2 + echo 1>&2 + hints= + fi + echo "search.fs_uuid ${uuid} root $hints " >> "${grubdir}/${target_cpu}-$platform/load.cfg" + echo 'set prefix=($root)'"${relative_grubdir}" >> "${grubdir}/${target_cpu}-$platform/load.cfg" + config_opt="-c ${grubdir}/${target_cpu}-$platform/load.cfg " modules="$modules search_fs_uuid" else # we need to hardcode the partition number in the core image's prefix. if [ x"$grub_partition" = x ]; then prefix_drive="()" else - prefix_drive="(,$grub_partition)" + # Comma is already there + prefix_drive="($grub_partition)" fi fi else if [ x$GRUB_CRYPTODISK_ENABLE = xy ]; then - for uuid in "`"${grub_probe}" --device "${grub_device}" --target=cryptodisk_uuid`"; do - echo "cryptomount -u $uuid" >> "${grubdir}/load.cfg" + for uuid in "`echo "${grub_device}" | xargs "${grub_probe}" --target=cryptodisk_uuid --device`"; do + echo "cryptomount -u $uuid" >> "${grubdir}/${target_cpu}-$platform/load.cfg" done - config_opt="-c ${grubdir}/load.cfg " + config_opt="-c ${grubdir}/${target_cpu}-$platform/load.cfg " fi prefix_drive=`"$grub_probe" --device-map="${device_map}" --target=drive --device "${grub_device}"` || exit 1 @@ -597,22 +597,22 @@ case "${target_cpu}-${platform}" in esac -"$grub_mkimage" ${config_opt} -d "${pkglibdir}" -O ${mkimage_target} --output="${grubdir}/core.${imgext}" --prefix="${prefix_drive}${relative_grubdir}" $modules || exit 1 +"$grub_mkimage" ${config_opt} -d "${pkglibdir}" -O ${mkimage_target} --output="${grubdir}/${target_cpu}-$platform/core.${imgext}" --prefix="${prefix_drive}${relative_grubdir}" $modules || exit 1 # Backward-compatibility kludges if [ "${target_cpu}-${platform}" = "mipsel-loongson" ]; then - cp "${grubdir}/core.${imgext}" "${bootdir}"/grub.elf + cp "${grubdir}/${target_cpu}-$platform/core.${imgext}" "${bootdir}"/grub.elf elif [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${platform}" = "powerpc-ieee1275" ]; then - cp "${grubdir}/core.${imgext}" "${grubdir}/grub" + cp "${grubdir}/${target_cpu}-$platform/core.${imgext}" "${grubdir}/grub" elif [ "${target_cpu}-${platform}" = "i386-efi" ] || [ "${target_cpu}-${platform}" = "x86_64-efi" ]; then - "$grub_mkimage" ${config_opt} -d "${pkglibdir}" -O ${mkimage_target} --output="${grubdir}/grub.efi" --prefix="" $modules || exit 1 + "$grub_mkimage" ${config_opt} -d "${pkglibdir}" -O ${mkimage_target} --output="${grubdir}/${target_cpu}-$platform/grub.efi" --prefix="" $modules || exit 1 fi # Perform the platform-dependent install if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then # Now perform the installation. - "$grub_setup" ${allow_floppy} ${setup_verbose} ${setup_force} --directory="${grubdir}" \ + "$grub_setup" ${allow_floppy} ${setup_verbose} ${setup_force} --directory="${grubdir}/${target_cpu}-$platform" \ --device-map="${device_map}" "${install_device}" || exit 1 elif [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${platform}" = "powerpc-ieee1275" ]; then if [ x"$update_nvram" = xyes ]; then @@ -636,28 +636,56 @@ elif [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${pla dev="`echo $grub_device | sed -e 's/\/dev\///' -e 's/[0-9]\+//'`" partno="`echo $grub_device | sed -e 's/.*[^0-9]\([0-9]\+\)$/\1/'`" ofpath="`$ofpathname $dev`" || { - echo "Couldn't find Open Firmware device tree path for $dev." - echo "You will have to set boot-device manually." + gettext_printf "Couldn't find IEEE1275 device tree path for %s.\nYou will have to set \`boot-device' variable manually.\n" "$dev" 1>&2 exit 1 } # Point boot-device at the new grub install - boot_device="$ofpath:$partno,"`"$grub_mkrelpath" "${grubdir}/core.${imgext}" | sed 's,/,\\\\,g'` + boot_device="$ofpath:$partno,"`"$grub_mkrelpath" "${grubdir}/${target_cpu}-$platform/core.${imgext}" | sed 's,/,\\\\,g'` + + # If a install device is defined, copy the core.elf to PReP partition. + if [ "${target_cpu}-${platform}" = "powerpc-ieee1275" ] \ + && [ -n "${install_device}" ]; then + if [ "$("${grub_probe}" -m "${device_map}" -d "${install_device}" -t msdos_parttype)" != "41" ]; then + gettext "The chosen partition is not a PReP partition." 1>&2 + echo 1>&2 + exit 1 + fi + + if [ "$(file -s "${install_device}" -b | awk '{ print $1 }')" = ELF ] || [ $(cmp /dev/zero "${install_device}" &>/dev/null) ]; then + # Change boot device to the harddisk root + boot_device="$ofpath" + dd if="${grubdir}/${target_cpu}-$platform/core.${imgext}" of="${install_device}" status=noxfer || { + gettext "Failed to copy Grub to the PReP partition." 1>&2 + echo 1>&2 + exit 1 + } + else + gettext "The PReP partition is not empty. If you are sure you want to use it, run dd to clear it:" 1>&2 + echo 1>&2 + echo " dd if=/dev/zero of=${install_device}" + exit 1 + fi + fi + "$nvsetenv" boot-device "$boot_device" || { - echo "$nvsetenv failed." - echo "You will have to set boot-device manually. At the Open Firmware prompt, type:" - echo " setenv boot-device $boot_device" + # TRANSLATORS: The %s will be replaced by an external program name. + gettext_printf "\`%s' failed.\n" "$nvsetenv" 1>&2 + gettext "You will have to set \`boot-device' variable manually. At the IEEE1275 prompt, type:" 1>&2 + echo 1>&2 + echo " setenv boot-device $boot_device" 1>&2 exit 1 } fi elif [ x"${target_cpu}-${platform}" = xmips-arc ]; then - dvhtool -d "${install_device}" --unix-to-vh "{grubdir}/core.${imgext}" grub - echo "You will have to set SystemPartition and OSLoader manually." + dvhtool -d "${install_device}" --unix-to-vh "{grubdir}/${target_cpu}-$platform/core.${imgext}" grub + gettext "You will have to set SystemPartition and OSLoader manually." 1>&2 + echo 1>&2 elif [ x"$platform" = xefi ]; then - cp "${grubdir}/core.${imgext}" "${efidir}/${efi_file}" + cp "${grubdir}/${target_cpu}-$platform/core.${imgext}" "${efidir}/${efi_file}" # For old macs. Suggested by Peter Jones. if [ x$target_cpu = xi386 ]; then - cp "${grubdir}/core.${imgext}" "${efidir}/boot.efi" + cp "${grubdir}/${target_cpu}-$platform/core.${imgext}" "${efidir}/boot.efi" fi # Try to make this image bootable using the EFI Boot Manager, if available. @@ -681,20 +709,23 @@ elif [ x"$platform" = xefi ]; then # fiddle about with grub-probe to get hold of this reasonably reliably. # Use fresh device map text to avoid any problems with stale data, since # all we need here is a one-to-one mapping. - clean_devmap="$($grub_mkdevicemap --device-map=/dev/stdout)" - efidir_drive="$(echo "$clean_devmap" | "$grub_probe" --device-map="${device_map}" --target=drive --device-map=/dev/stdin "$efidir")" - if test -z "$efidir_drive"; then - echo "Can't find GRUB drive for $efidir; unable to create EFI Boot Manager entry." >&2 + efidir_drive="$("$grub_probe" --target=drive --device-map= "$efidir")" + efidir_disk="$("$grub_probe" --target=disk --device-map= "$efidir")" + if test -z "$efidir_drive" || test -z "$efidir_disk"; then + gettext_printf "Can't find GRUB drive for %s; unable to create EFI Boot Manager entry.\n" "$efidir" >&2 else - efidir_disk="$(echo "$clean_devmap" | grep "^$(echo "$efidir_drive" | sed 's/,[^)]*//')" | cut -f2)" efidir_part="$(echo "$efidir_drive" | sed 's/^([^,]*,[^0-9]*//; s/[^0-9].*//')" efibootmgr $efi_quiet -c -d "$efidir_disk" -p "$efidir_part" -w \ -L "$bootloader_id" -l "\\EFI\\$efi_distributor\\$efi_file" fi fi +else + gettext "WARNING: no platform-specific install was performed" 1>&2 + echo 1>&2 fi -echo "Installation finished. No error reported." +gettext "Installation finished. No error reported." 1>&2 +echo 1>&2 # Bye. exit 0 diff --git a/util/grub-kbdcomp.in b/util/grub-kbdcomp.in index 05e516d23..393873443 100644 --- a/util/grub-kbdcomp.in +++ b/util/grub-kbdcomp.in @@ -5,8 +5,72 @@ transform="@program_transform_name@" prefix="@prefix@" exec_prefix="@exec_prefix@" bindir="@bindir@" +datarootdir="@datarootdir@" +datadir="@datadir@" +if [ "x$pkgdatadir" = x ]; then + pkgdatadir="${datadir}/`echo @PACKAGE_TARNAME@ | sed "${transform}"`" +fi -grub_mklayout=${bindir}/`echo grub-mklayout | sed ${transform}` +grub_mklayout="${bindir}/`echo grub-mklayout | sed ${transform}`" -ckbcomp "$@" | $grub_mklayout -o "$1".gkb +ckbcomp_options="" + +. "${pkgdatadir}/grub-mkconfig_lib" + +self=`basename $0` + +usage () { + gettext_printf "Usage: %s -o OUTPUT CKBMAP_ARGUMENTS...\n" "$self" + gettext "Make GRUB layout file."; echo + echo + printf " -h, --help %s\n" "$(gettext "print this message and exit")" + printf " -v, --version %s\n" "$(gettext "print the version information and exit")" + printf " -o, --output=%-11s%s\n" "$(gettext FILE)" "$(gettext "save output in FILE [required]")" + echo + gettext_printf "%s generates a keyboard layout for GRUB using ckbcomp\n" "$self" + echo + gettext "Report bugs to ."; echo +} + +argument () { + opt=$1 + shift + + if test $# -eq 0; then + gettext_printf "%s: option requires an argument -- '%s'\n" "$0" "$opt" 1>&2 + exit 1 + fi + echo $1 +} + +output= + +while test $# -gt 0 +do + option=$1 + shift + case "$option" in + -h | --help) + usage + exit 0 ;; + -v | --version) + echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" + exit 0 ;; + -o | --output) + output=`argument $option "$@"`; shift ;; + --output=*) + output=`echo "$option" | sed 's/--output=//'` ;; + *) + ckbcomp_options="$ckbcomp_options $option";; + esac +done + +if [ "x${output}" = x ] ; then + gettext "output file must be specified" >&2 + echo >&2 + usage + exit 1 +fi + +ckbcomp $ckbcomp_options | "$grub_mklayout" -o "${output}" diff --git a/util/grub-menulst2cfg.c b/util/grub-menulst2cfg.c index aeabad976..1f41ee8f5 100644 --- a/util/grub-menulst2cfg.c +++ b/util/grub-menulst2cfg.c @@ -47,7 +47,7 @@ main (int argc, char **argv) in = fopen (argv[1], "r"); if (!in) { - fprintf (stderr, _("Couldn't open %s for reading: %s\n"), + fprintf (stderr, _("cannot open `%s': %s"), argv[1], strerror (errno)); return 1; } @@ -62,7 +62,7 @@ main (int argc, char **argv) { if (in != stdin) fclose (in); - fprintf (stderr, _("Couldn't open %s for writing: %s\n"), + fprintf (stderr, _("cannot open `%s': %s"), argv[2], strerror (errno)); return 1; } diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in index e317279f4..b5144e3a4 100644 --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in @@ -18,43 +18,45 @@ set -e # along with GRUB. If not, see . transform="@program_transform_name@" +prefix="@prefix@" +exec_prefix="@exec_prefix@" +datarootdir="@datarootdir@" -prefix=@prefix@ -exec_prefix=@exec_prefix@ -sbindir=@sbindir@ -bindir=@bindir@ -libdir=@libdir@ -sysconfdir=@sysconfdir@ +prefix="@prefix@" +exec_prefix="@exec_prefix@" +sbindir="@sbindir@" +bindir="@bindir@" +sysconfdir="@sysconfdir@" PACKAGE_NAME=@PACKAGE_NAME@ PACKAGE_VERSION=@PACKAGE_VERSION@ host_os=@host_os@ -datarootdir=@datarootdir@ -datadir=@datadir@ -pkgdatadir=${datadir}/`echo @PACKAGE_TARNAME@ | sed "${transform}"` +datadir="@datadir@" +if [ "x$pkgdatadir" = x ]; then + pkgdatadir="${datadir}/`echo @PACKAGE_TARNAME@ | sed "${transform}"`" +fi grub_cfg="" -grub_mkconfig_dir=${sysconfdir}/grub.d +grub_mkconfig_dir="${sysconfdir}"/grub.d self=`basename $0` -grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed "${transform}"` -grub_probe=${sbindir}/`echo grub-probe | sed "${transform}"` +grub_probe="${sbindir}/`echo grub-probe | sed "${transform}"`" grub_script_check="${bindir}/`echo grub-script-check | sed "${transform}"`" GRUB_PREFIX=`echo '/@bootdirname@/@grubdirname@' | sed "s,//*,/,g"` +. "${pkgdatadir}/grub-mkconfig_lib" + # Usage: usage # Print the usage. usage () { - cat <. -EOF + gettext_printf "Usage: %s [OPTION]\n" "$self" + gettext "Generate a grub config file"; echo + echo + printf " -o, --output=%-11s%s\n" "$(gettext FILE)" "$(gettext "output generated config to FILE [default=stdout]")" + printf " -h, --help %s\n" "$(gettext "print this message and exit")" + printf " -v, --version %s\n" "$(gettext "print the version information and exit")" + echo + gettext "Report bugs to ."; echo } argument () { @@ -62,7 +64,7 @@ argument () { shift if test $# -eq 0; then - echo "$0: option requires an argument -- '$opt'" 1>&2 + gettext_printf "%s: option requires an argument -- '%s'" "$0" "$opt" 1>&2 exit 1 fi echo $1 @@ -87,7 +89,7 @@ do grub_cfg=`echo "$option" | sed 's/--output=//'` ;; -*) - echo "Unrecognized option \`$option'" 1>&2 + gettext_printf "Unrecognized option \`%s'\n" "$option" 1>&2 usage exit 1 ;; @@ -95,8 +97,6 @@ do esac done -. ${libdir}/@PACKAGE@/grub-mkconfig_lib - if [ "x$EUID" = "x" ] ; then EUID=`id -u` fi @@ -113,33 +113,21 @@ if [ "$EUID" != 0 ] ; then done ;; esac if [ $root != t ] ; then - echo "$self: You must run this as root" >&2 + gettext_printf "%s: You must run this as root\n" "$self" >&2 exit 1 fi fi -set $grub_mkdevicemap dummy -if test -f "$1"; then - : -else - echo "$1: Not found." 1>&2 - exit 1 -fi - set $grub_probe dummy if test -f "$1"; then : else - echo "$1: Not found." 1>&2 + gettext_print "%s: Not found.\n" "$1" 1>&2 exit 1 fi mkdir -p ${GRUB_PREFIX} -if test -e ${GRUB_PREFIX}/device.map ; then : ; else - ${grub_mkdevicemap} -fi - # Device containing our userland. Typically used for root= parameter. GRUB_DEVICE="`${grub_probe} --target=device /`" GRUB_DEVICE_UUID="`${grub_probe} --device ${GRUB_DEVICE} --target=fs_uuid 2> /dev/null`" || true @@ -196,7 +184,7 @@ for x in ${GRUB_TERMINAL_OUTPUT}; do fi if [ -z "${GRUB_FONT_PATH}" ] ; then if [ "x$termoutdefault" != "x1" ]; then - echo "No font for gfxterm found." >&2 ; exit 1 + gettext "No font for video terminal found." >&2; echo >&2 ; exit 1 fi GRUB_TERMINAL_OUTPUT= fi @@ -260,15 +248,13 @@ export GRUB_DEFAULT \ GRUB_BADRAM if test "x${grub_cfg}" != "x"; then - rm -f ${grub_cfg}.new - exec > ${grub_cfg}.new - - # Allow this to fail, since /boot/grub/ might need to be fatfs to support some - # firmware implementations (e.g. OFW or EFI). - chmod 400 ${grub_cfg}.new || grub_warn "Could not make ${grub_cfg}.new readable by only root.\ - This means that if the generated config contains a password it is readable by everyone" + rm -f "${grub_cfg}.new" + oldumask=$(umask); umask 077 + exec > "${grub_cfg}.new" + umask $oldumask fi -echo "Generating grub.cfg ..." >&2 +gettext "Generating grub.cfg ..." >&2 +echo >&2 cat << EOF # @@ -298,14 +284,15 @@ done if test "x${grub_cfg}" != "x" ; then if ! ${grub_script_check} ${grub_cfg}.new; then - echo "Syntax errors are detected in generated GRUB config file." >&2 - echo "Ensure that there are no errors in /etc/default/grub" >&2 - echo "and /etc/grub.d/* files or please file a bug report with" >&2 - echo "${grub_cfg}.new file attached." >&2 + gettext_printf "Syntax errors are detected in generated GRUB config file. +Ensure that there are no errors in /etc/default/grub +and /etc/grub.d/* files or please file a bug report with +%s file attached." "${grub_cfg}.new" >&2 else # none of the children aborted with error, install the new grub.cfg mv -f ${grub_cfg}.new ${grub_cfg} fi fi -echo "done" >&2 +gettext "done" >&2 +echo >&2 diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in index 5a9bf90c0..a32a2b2bb 100644 --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in @@ -31,15 +31,17 @@ if test "x$grub_mkrelpath" = x; then grub_mkrelpath="${bindir}/`echo grub-mkrelpath | sed "${transform}"`" fi -if $(which gettext >/dev/null 2>/dev/null) ; then - gettext="gettext" +if which gettext >/dev/null 2>/dev/null; then + : else - gettext="echo" + gettext () { + echo -n "$@" + } fi grub_warn () { - echo "Warning: $@" >&2 + echo "$(gettext "Warning:")" "$@" >&2 } make_system_path_relative_to_its_root () @@ -146,9 +148,17 @@ prepare_grub_to_access_device () # If there's a filesystem UUID that GRUB is capable of identifying, use it; # otherwise set root as per value in device.map. - echo "set root='`"${grub_probe}" --device "${device}" --target=drive`'" + fs_hint="`"${grub_probe}" --device "${device}" --target=compatibility_hint`" + if [ "x$fs_hint" != x ]; then + echo "set root='$fs_hint'" + fi if fs_uuid="`"${grub_probe}" --device "${device}" --target=fs_uuid 2> /dev/null`" ; then - echo "search --no-floppy --fs-uuid --set=root ${fs_uuid}" + hints="`"${grub_probe}" --device "${device}" --target=hints_string 2> /dev/null`" + echo "if [ x\$feature_platform_search_hint = xy ]; then" + echo " search --no-floppy --fs-uuid --set=root ${hints} ${fs_uuid}" + echo "else" + echo " search --no-floppy --fs-uuid --set=root ${fs_uuid}" + echo "fi" fi } @@ -198,8 +208,8 @@ version_test_gt () fi case "$version_test_gt_a:$version_test_gt_b" in *.old:*.old) ;; - *.old:*) version_test_gt_a="`echo -n "$version_test_gt_a" | sed -e 's/\.old$//'`" ; cmp=gt ;; - *:*.old) version_test_gt_b="`echo -n "$version_test_gt_b" | sed -e 's/\.old$//'`" ; cmp=ge ;; + *.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 version_test_numeric "$version_test_gt_a" "$version_test_gt_cmp" "$version_test_gt_b" return "$?" @@ -220,7 +230,7 @@ version_find_latest () # printf; so this turns ' into \'. Note that you must use the output of # this function in a printf format string. gettext_quoted () { - "$gettext" "$@" | sed "s/'/'\\\\\\\\''/g" + gettext "$@" | sed "s/'/'\\\\\\\\''/g" } # Run the first argument through gettext_quoted, and then pass that and all diff --git a/util/grub-mkdevicemap.c b/util/grub-mkdevicemap.c deleted file mode 100644 index bdf8ef1c6..000000000 --- a/util/grub-mkdevicemap.c +++ /dev/null @@ -1,171 +0,0 @@ -/* grub-mkdevicemap.c - make a device map file automatically */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2009,2010 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GRUB. If not, see . - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#define _GNU_SOURCE 1 -#include - -#include "progname.h" - -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; - } - - if (strcmp (device_map, "-") == 0) - fp = stdout; - else - fp = fopen (device_map, "w"); - - if (! fp) - grub_util_error (_("cannot open %s"), device_map); - - grub_util_iterate_devices (process_device, floppy_disks); - - if (fp != stdout) - fclose (fp); -} - -static struct option options[] = - { - {"device-map", required_argument, 0, 'm'}, - {"probe-second-floppy", no_argument, 0, 's'}, - {"no-floppy", no_argument, 0, 'n'}, - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'V'}, - {"verbose", no_argument, 0, 'v'}, - {0, 0, 0, 0} - }; - -static void -usage (int status) -{ - if (status) - fprintf (stderr, - _("Try `%s --help' for more information.\n"), program_name); - else - printf (_("\ -Usage: %s [OPTION]...\n\ -\n\ -Generate a device map file automatically.\n\ -\n\ - -n, --no-floppy do not probe any floppy drive\n\ - -s, --probe-second-floppy probe the second floppy drive\n\ - -m, --device-map=FILE use FILE as the device map [default=%s]\n\ - -h, --help display this message and exit\n\ - -V, --version print version information and exit\n\ - -v, --verbose print verbose messages\n\ -\n\ -Report bugs to <%s>.\n\ -"), program_name, - DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT); - - exit (status); -} - -int -main (int argc, char *argv[]) -{ - char *dev_map = 0; - int floppy_disks = 1; - - set_program_name (argv[0]); - - grub_util_init_nls (); - - /* Check for options. */ - while (1) - { - int c = getopt_long (argc, argv, "snm:r:hVv", options, 0); - - if (c == -1) - break; - else - switch (c) - { - case 'm': - if (dev_map) - free (dev_map); - - dev_map = xstrdup (optarg); - break; - - case 'n': - floppy_disks = 0; - break; - - case 's': - floppy_disks = 2; - break; - - case 'h': - usage (0); - break; - - case 'V': - printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); - return 0; - - case 'v': - verbosity++; - break; - - default: - usage (1); - break; - } - } - - if (verbosity > 1) - grub_env_set ("debug", "all"); - - make_device_map (dev_map ? : DEFAULT_DEVICE_MAP, floppy_disks); - - free (dev_map); - - return 0; -} diff --git a/util/grub-mkfont.c b/util/grub-mkfont.c index 1fad15660..e86e37c92 100644 --- a/util/grub-mkfont.c +++ b/util/grub-mkfont.c @@ -30,7 +30,10 @@ #include #include #include -#include + +#define _GNU_SOURCE 1 +#include +#include #include #include FT_FREETYPE_H @@ -77,7 +80,7 @@ enum file_formats struct grub_font_info { - char* name; + const char *name; int style; int desc; int asce; @@ -94,62 +97,9 @@ struct grub_font_info int num_glyphs; }; -static struct option options[] = -{ - {"output", required_argument, 0, 'o'}, - {"name", required_argument, 0, 'n'}, - {"index", required_argument, 0, 'i'}, - {"range", required_argument, 0, 'r'}, - {"size", required_argument, 0, 's'}, - {"desc", required_argument, 0, 'd'}, - {"asce", required_argument, 0, 'c'}, - {"bold", no_argument, 0, 'b'}, - {"no-bitmap", no_argument, 0, 0x100}, - {"no-hinting", no_argument, 0, 0x101}, - {"force-autohint", no_argument, 0, 'a'}, - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'V'}, - {"verbose", no_argument, 0, 'v'}, - {"ascii-bitmaps", no_argument, 0, 0x102}, - {"width-spec", no_argument, 0, 0x103}, - {0, 0, 0, 0} -}; - -int font_verbosity; +static int font_verbosity; static void -usage (int status) -{ - if (status) - fprintf (stderr, _("Try `%s --help' for more information.\n"), - program_name); - else - printf (_("\ -Usage: %s [OPTIONS] FONT_FILES\n\ -\nOptions:\n\ - -o, --output=FILE_NAME set output file name\n\ - --ascii-bitmaps save only the ASCII bitmaps\n\ - --width-spec create width summary file\n\ - -i, --index=N set face index\n\ - -r, --range=A-B[,C-D] set font range\n\ - -n, --name=S set font family name\n\ - -s, --size=N set font size\n\ - -d, --desc=N set font descent\n\ - -c, --asce=N set font ascent\n\ - -b, --bold convert to bold font\n\ - -a, --force-autohint force autohint\n\ - --no-hinting disable hinting\n\ - --no-bitmap ignore bitmap strikes when loading\n\ - -h, --help display this message and exit\n\ - -V, --version print version information and exit\n\ - -v, --verbose print verbose messages\n\ -\n\ -Report bugs to <%s>.\n"), program_name, PACKAGE_BUGREPORT); - - exit (status); -} - -void add_pixel (grub_uint8_t **data, int *mask, int not_blank) { if (*mask == 0) @@ -607,7 +557,7 @@ process_cursive (struct gsub_feature *feature, } } -void +static void add_font (struct grub_font_info *font_info, FT_Face face, int nocut) { struct gsub_header *gsub = NULL; @@ -641,7 +591,7 @@ add_font (struct grub_font_info *font_info, FT_Face face, int nocut) grub_uint32_t feattag = grub_be_to_cpu32 (features->features[i].feature_tag); if (feature->params) - printf (_("WARNING: unsupported feature parameters: %x\n"), + printf (_("WARNING: unsupported font feature parameters: %x\n"), grub_be_to_cpu16 (feature->params)); switch (feattag) { @@ -671,7 +621,8 @@ add_font (struct grub_font_info *font_info, FT_Face face, int nocut) for (j = 0; j < 4; j++) if (!grub_isgraph (str[j])) str[j] = '?'; - printf (_("Unknown gsub feature 0x%x (%s)\n"), feattag, str); + printf (_("Unknown gsub font feature 0x%x (%s)\n"), + feattag, str); } } } @@ -698,36 +649,39 @@ add_font (struct grub_font_info *font_info, FT_Face face, int nocut) } } -void -write_string_section (char *name, char *str, int* offset, FILE* file) +static void +write_string_section (const char *name, const char *str, + int *offset, FILE *file, + const char *filename) { grub_uint32_t leng, leng_be32; leng = strlen (str) + 1; leng_be32 = grub_cpu_to_be32 (leng); - grub_util_write_image (name, 4, file); - grub_util_write_image ((char *) &leng_be32, 4, file); - grub_util_write_image (str, leng, file); + grub_util_write_image (name, 4, file, filename); + grub_util_write_image ((char *) &leng_be32, 4, file, filename); + grub_util_write_image (str, leng, file, filename); *offset += 8 + leng; } -void -write_be16_section (char *name, grub_uint16_t data, int* offset, FILE* file) +static void +write_be16_section (const char *name, grub_uint16_t data, int* offset, + FILE *file, const char *filename) { grub_uint32_t leng; leng = grub_cpu_to_be32 (2); data = grub_cpu_to_be16 (data); - grub_util_write_image (name, 4, file); - grub_util_write_image ((char *) &leng, 4, file); - grub_util_write_image ((char *) &data, 2, file); + grub_util_write_image (name, 4, file, filename); + grub_util_write_image ((char *) &leng, 4, file, filename); + grub_util_write_image ((char *) &data, 2, file, filename); *offset += 10; } -void +static void print_glyphs (struct grub_font_info *font_info) { int num; @@ -740,8 +694,8 @@ print_glyphs (struct grub_font_info *font_info) int x, y, xmax, xmin, ymax, ymin; grub_uint8_t *bitmap, mask; - printf (_("\nGlyph #%d, U+%04x\n"), num, glyph->char_code); - printf (_("Width %d, Height %d, X offset %d, Y offset %d, Device width %d\n"), + printf ("\nGlyph #%d, U+%04x\n", num, glyph->char_code); + printf ("Width %d, Height %d, X offset %d, Y offset %d, Device width %d\n", glyph->width, glyph->height, glyph->x_ofs, glyph->y_ofs, glyph->device_width); @@ -799,7 +753,7 @@ print_glyphs (struct grub_font_info *font_info) } } -void +static void write_font_ascii_bitmap (struct grub_font_info *font_info, char *output_file) { FILE *file; @@ -808,7 +762,8 @@ write_font_ascii_bitmap (struct grub_font_info *font_info, char *output_file) file = fopen (output_file, "wb"); if (! file) - grub_util_error (_("Can\'t write to file %s."), output_file); + grub_util_error (_("cannot write to `%s': %s"), output_file, + strerror (errno)); int correct_size; for (glyph = font_info->glyphs_sorted, num = 0; num < font_info->num_glyphs; @@ -832,7 +787,7 @@ write_font_ascii_bitmap (struct grub_font_info *font_info, char *output_file) fclose (file); } -void +static void write_font_width_spec (struct grub_font_info *font_info, char *output_file) { FILE *file; @@ -844,7 +799,8 @@ write_font_width_spec (struct grub_font_info *font_info, char *output_file) file = fopen (output_file, "wb"); if (! file) - grub_util_error (_("Can\'t write to file %s."), output_file); + grub_util_error (_("cannot write to `%s': %s"), output_file, + strerror (errno)); for (glyph = font_info->glyphs_sorted; glyph < font_info->glyphs_sorted + font_info->num_glyphs; glyph++) @@ -856,7 +812,7 @@ write_font_width_spec (struct grub_font_info *font_info, char *output_file) free (out); } -void +static void write_font_pf2 (struct grub_font_info *font_info, char *output_file) { FILE *file; @@ -867,15 +823,17 @@ write_font_pf2 (struct grub_font_info *font_info, char *output_file) file = fopen (output_file, "wb"); if (! file) - grub_util_error (_("Can\'t write to file %s."), output_file); + grub_util_error (_("cannot write to `%s': %s"), output_file, + strerror (errno)); offset = 0; leng = grub_cpu_to_be32 (4); grub_util_write_image (FONT_FORMAT_SECTION_NAMES_FILE, - sizeof(FONT_FORMAT_SECTION_NAMES_FILE) - 1, file); - grub_util_write_image ((char *) &leng, 4, file); - grub_util_write_image (FONT_FORMAT_PFF2_MAGIC, 4, file); + sizeof(FONT_FORMAT_SECTION_NAMES_FILE) - 1, file, + output_file); + grub_util_write_image ((char *) &leng, 4, file, output_file); + grub_util_write_image (FONT_FORMAT_PFF2_MAGIC, 4, file, output_file); offset += 12; if (! font_info->name) @@ -898,24 +856,24 @@ write_font_pf2 (struct grub_font_info *font_info, char *output_file) font_info->size); write_string_section (FONT_FORMAT_SECTION_NAMES_FONT_NAME, - font_name, &offset, file); + font_name, &offset, file, output_file); write_string_section (FONT_FORMAT_SECTION_NAMES_FAMILY, - font_info->name, &offset, file); + font_info->name, &offset, file, output_file); write_string_section (FONT_FORMAT_SECTION_NAMES_WEIGHT, (font_info->style & FT_STYLE_FLAG_BOLD) ? "bold" : "normal", - &offset, file); + &offset, file, output_file); write_string_section (FONT_FORMAT_SECTION_NAMES_SLAN, (font_info->style & FT_STYLE_FLAG_ITALIC) ? "italic" : "normal", - &offset, file); + &offset, file, output_file); write_be16_section (FONT_FORMAT_SECTION_NAMES_POINT_SIZE, - font_info->size, &offset, file); + font_info->size, &offset, file, output_file); write_be16_section (FONT_FORMAT_SECTION_NAMES_MAX_CHAR_WIDTH, - font_info->max_width, &offset, file); + font_info->max_width, &offset, file, output_file); write_be16_section (FONT_FORMAT_SECTION_NAMES_MAX_CHAR_HEIGHT, - font_info->max_height, &offset, file); + font_info->max_height, &offset, file, output_file); if (! font_info->desc) { @@ -934,9 +892,9 @@ write_font_pf2 (struct grub_font_info *font_info, char *output_file) } write_be16_section (FONT_FORMAT_SECTION_NAMES_ASCENT, - font_info->asce, &offset, file); + font_info->asce, &offset, file, output_file); write_be16_section (FONT_FORMAT_SECTION_NAMES_DESCENT, - font_info->desc, &offset, file); + font_info->desc, &offset, file, output_file); if (font_verbosity > 0) { @@ -953,8 +911,8 @@ write_font_pf2 (struct grub_font_info *font_info, char *output_file) leng = grub_cpu_to_be32 (font_info->num_glyphs * 9); grub_util_write_image (FONT_FORMAT_SECTION_NAMES_CHAR_INDEX, sizeof(FONT_FORMAT_SECTION_NAMES_CHAR_INDEX) - 1, - file); - grub_util_write_image ((char *) &leng, 4, file); + file, output_file); + grub_util_write_image ((char *) &leng, 4, file, output_file); offset += 8 + font_info->num_glyphs * 9 + 8; for (cur = font_info->glyphs_sorted; @@ -963,229 +921,277 @@ write_font_pf2 (struct grub_font_info *font_info, char *output_file) grub_uint32_t data32; grub_uint8_t data8; data32 = grub_cpu_to_be32 (cur->char_code); - grub_util_write_image ((char *) &data32, 4, file); + grub_util_write_image ((char *) &data32, 4, file, output_file); data8 = 0; - grub_util_write_image ((char *) &data8, 1, file); + grub_util_write_image ((char *) &data8, 1, file, output_file); data32 = grub_cpu_to_be32 (offset); - grub_util_write_image ((char *) &data32, 4, file); + grub_util_write_image ((char *) &data32, 4, file, output_file); offset += 10 + cur->bitmap_size; } leng = 0xffffffff; grub_util_write_image (FONT_FORMAT_SECTION_NAMES_DATA, - sizeof(FONT_FORMAT_SECTION_NAMES_DATA) - 1, file); - grub_util_write_image ((char *) &leng, 4, file); + sizeof(FONT_FORMAT_SECTION_NAMES_DATA) - 1, + file, output_file); + grub_util_write_image ((char *) &leng, 4, file, output_file); for (cur = font_info->glyphs_sorted; cur < font_info->glyphs_sorted + font_info->num_glyphs; cur++) { grub_uint16_t data; data = grub_cpu_to_be16 (cur->width); - grub_util_write_image ((char *) &data, 2, file); + grub_util_write_image ((char *) &data, 2, file, output_file); data = grub_cpu_to_be16 (cur->height); - grub_util_write_image ((char *) &data, 2, file); + grub_util_write_image ((char *) &data, 2, file, output_file); data = grub_cpu_to_be16 (cur->x_ofs); - grub_util_write_image ((char *) &data, 2, file); + grub_util_write_image ((char *) &data, 2, file, output_file); data = grub_cpu_to_be16 (cur->y_ofs); - grub_util_write_image ((char *) &data, 2, file); + grub_util_write_image ((char *) &data, 2, file, output_file); data = grub_cpu_to_be16 (cur->device_width); - grub_util_write_image ((char *) &data, 2, file); - grub_util_write_image ((char *) &cur->bitmap[0], cur->bitmap_size, file); + grub_util_write_image ((char *) &data, 2, file, output_file); + grub_util_write_image ((char *) &cur->bitmap[0], cur->bitmap_size, + file, output_file); } fclose (file); } +static struct argp_option options[] = { + {"output", 'o', N_("FILE"), 0, N_("save output in FILE [required]"), 0}, + {"ascii-bitmaps", 0x102, 0, 0, N_("save only the ASCII bitmaps"), 0}, + {"width-spec", 0x103, 0, 0, N_("create width summary file"), 0}, + {"index", 'i', N_("NUM"), 0, N_("set face index"), 0}, + {"range", 'r', N_("FROM-TO[,FROM-TO]"), 0, N_("set font range"), 0}, + {"name", 'n', N_("NAME"), 0, N_("set font family name"), 0}, + {"size", 's', N_("SIZE"), 0, N_("set font size"), 0}, + {"desc", 'd', N_("NUM"), 0, N_("set font descent"), 0}, + {"asce", 'c', N_("NUM"), 0, N_("set font ascent"), 0}, + {"bold", 'b', 0, 0, N_("convert to bold font"), 0}, + {"force-autohint", 'a', 0, 0, N_("force autohint"), 0}, + {"no-hinting", 0x101, 0, 0, N_("disable hinting"), 0}, + {"no-bitmap", 0x100, 0, 0, N_("ignore bitmap strikes when loading"), 0}, + {"verbose", 'v', 0, 0, N_("print verbose messages."), 0}, + { 0, 0, 0, 0, 0, 0 } +}; + +struct arguments +{ + struct grub_font_info font_info; + size_t nfiles; + size_t files_max; + char **files; + char *output_file; + int font_index; + int font_size; + enum file_formats file_format; +}; + +static error_t +argp_parser (int key, char *arg, struct argp_state *state) +{ + /* Get the input argument from argp_parse, which we + know is a pointer to our arguments structure. */ + struct arguments *arguments = state->input; + + switch (key) + { + case 'b': + arguments->font_info.flags |= GRUB_FONT_FLAG_BOLD; + break; + + case 0x100: + arguments->font_info.flags |= GRUB_FONT_FLAG_NOBITMAP; + break; + + case 0x101: + arguments->font_info.flags |= GRUB_FONT_FLAG_NOHINTING; + break; + + case 'a': + arguments->font_info.flags |= GRUB_FONT_FLAG_FORCEHINT; + break; + + case 'o': + arguments->output_file = xstrdup (arg); + break; + + case 'n': + arguments->font_info.name = xstrdup (arg); + break; + + case 'i': + arguments->font_index = strtoul (arg, NULL, 0); + break; + + case 's': + arguments->font_size = strtoul (arg, NULL, 0); + break; + + case 'r': + { + char *p = arg; + + while (1) + { + grub_uint32_t a, b; + + a = strtoul (p, &p, 0); + if (*p != '-') + grub_util_error ("%s", _("invalid font range")); + b = strtoul (p + 1, &p, 0); + if ((arguments->font_info.num_range + & (GRUB_FONT_RANGE_BLOCK - 1)) == 0) + arguments->font_info.ranges = xrealloc (arguments->font_info.ranges, + (arguments->font_info.num_range + + GRUB_FONT_RANGE_BLOCK) * + sizeof (grub_uint32_t) * 2); + + arguments->font_info.ranges[arguments->font_info.num_range * 2] = a; + arguments->font_info.ranges[arguments->font_info.num_range * 2 + 1] = b; + arguments->font_info.num_range++; + + if (*p) + { + if (*p != ',') + grub_util_error ("%s", _("invalid font range")); + p++; + } + else + break; + } + break; + } + + case 'd': + arguments->font_info.desc = strtoul (arg, NULL, 0); + break; + + case 'e': + arguments->font_info.asce = strtoul (arg, NULL, 0); + break; + + case 'v': + font_verbosity++; + break; + + case 0x102: + arguments->file_format = ASCII_BITMAPS; + break; + + case 0x103: + arguments->file_format = WIDTH_SPEC; + break; + + case ARGP_KEY_ARG: + assert (arguments->nfiles < arguments->files_max); + arguments->files[arguments->nfiles++] = xstrdup(arg); + break; + + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +static struct argp argp = { + options, argp_parser, N_("[OPTIONS] FONT_FILES"), + N_("Convert common font file formats into PF2"), + NULL, NULL, NULL +}; + int main (int argc, char *argv[]) { - struct grub_font_info font_info; FT_Library ft_lib; - int font_index = 0; - int font_size = 0; - char *output_file = NULL; - enum file_formats file_format = PF2; - - memset (&font_info, 0, sizeof (font_info)); + struct arguments arguments; set_program_name (argv[0]); grub_util_init_nls (); - /* Check for options. */ - while (1) + memset (&arguments, 0, sizeof (struct arguments)); + arguments.file_format = PF2; + arguments.files_max = argc + 1; + arguments.files = xmalloc ((arguments.files_max + 1) + * sizeof (arguments.files[0])); + memset (arguments.files, 0, (arguments.files_max + 1) + * sizeof (arguments.files[0])); + + if (argp_parse (&argp, argc, argv, 0, 0, &arguments) != 0) { - int c = getopt_long (argc, argv, "bao:n:i:s:d:r:hVv", options, 0); - - if (c == -1) - break; - else - switch (c) - { - case 'b': - font_info.flags |= GRUB_FONT_FLAG_BOLD; - break; - - case 0x100: - font_info.flags |= GRUB_FONT_FLAG_NOBITMAP; - break; - - case 0x101: - font_info.flags |= GRUB_FONT_FLAG_NOHINTING; - break; - - case 'a': - font_info.flags |= GRUB_FONT_FLAG_FORCEHINT; - break; - - case 'o': - output_file = optarg; - break; - - case 'n': - font_info.name = optarg; - break; - - case 'i': - font_index = strtoul (optarg, NULL, 0); - break; - - case 's': - font_size = strtoul (optarg, NULL, 0); - break; - - case 'r': - { - char *p = optarg; - - while (1) - { - grub_uint32_t a, b; - - a = strtoul (p, &p, 0); - if (*p != '-') - grub_util_error (_("invalid font range")); - b = strtoul (p + 1, &p, 0); - if ((font_info.num_range & (GRUB_FONT_RANGE_BLOCK - 1)) == 0) - font_info.ranges = xrealloc (font_info.ranges, - (font_info.num_range + - GRUB_FONT_RANGE_BLOCK) * - sizeof (grub_uint32_t) * 2); - - font_info.ranges[font_info.num_range * 2] = a; - font_info.ranges[font_info.num_range * 2 + 1] = b; - font_info.num_range++; - - if (*p) - { - if (*p != ',') - grub_util_error (_("invalid font range")); - else - p++; - } - else - break; - } - break; - } - - case 'd': - font_info.desc = strtoul (optarg, NULL, 0); - break; - - case 'e': - font_info.asce = strtoul (optarg, NULL, 0); - break; - - case 'h': - usage (0); - break; - - case 'V': - printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); - return 0; - - case 'v': - font_verbosity++; - break; - - case 0x102: - file_format = ASCII_BITMAPS; - break; - - case 0x103: - file_format = WIDTH_SPEC; - break; - - default: - usage (1); - break; - } + fprintf (stderr, "%s", _("Error in parsing command line arguments\n")); + exit(1); } - if (file_format == ASCII_BITMAPS && font_info.num_range > 0) + if (arguments.file_format == ASCII_BITMAPS + && arguments.font_info.num_range > 0) { - grub_util_error (_("Option --ascii-bitmaps doesn't accept ranges (use ASCII).")); + grub_util_error ("%s", _("Option --ascii-bitmaps doesn't accept ranges (it always uses ASCII).")); return 1; } - - else if (file_format == ASCII_BITMAPS) + else if (arguments.file_format == ASCII_BITMAPS) { - font_info.ranges = xrealloc (font_info.ranges, - GRUB_FONT_RANGE_BLOCK * - sizeof (grub_uint32_t) * 2); - - font_info.ranges[0] = (grub_uint32_t) 0x00; - font_info.ranges[1] = (grub_uint32_t) 0x7f; - font_info.num_range = 1; + arguments.font_info.ranges = xrealloc (arguments.font_info.ranges, + GRUB_FONT_RANGE_BLOCK * + sizeof (grub_uint32_t) * 2); + + arguments.font_info.ranges[0] = (grub_uint32_t) 0x00; + arguments.font_info.ranges[1] = (grub_uint32_t) 0x7f; + arguments.font_info.num_range = 1; } - if (! output_file) - grub_util_error (_("no output file is specified")); + if (! arguments.output_file) + grub_util_error ("%s", _("output file must be specified")); if (FT_Init_FreeType (&ft_lib)) - grub_util_error (_("FT_Init_FreeType fails")); + grub_util_error ("%s", _("FT_Init_FreeType fails")); - for (; optind < argc; optind++) - { - FT_Face ft_face; - int size; - FT_Error err; + { + size_t i; + for (i = 0; i < arguments.nfiles; i++) + { + FT_Face ft_face; + int size; + FT_Error err; - err = FT_New_Face (ft_lib, argv[optind], font_index, &ft_face); - if (err) - { - grub_printf (_("can't open file %s, index %d: error %d"), - argv[optind], font_index, err); - if (err > 0 && err < (signed) ARRAY_SIZE (ft_errmsgs)) - printf (": %s\n", ft_errmsgs[err]); - else - printf ("\n"); + err = FT_New_Face (ft_lib, arguments.files[i], + arguments.font_index, &ft_face); + if (err) + { + grub_printf (_("can't open file %s, index %d: error %d"), + arguments.files[i], + arguments.font_index, err); + if (err > 0 && err < (signed) ARRAY_SIZE (ft_errmsgs)) + printf (": %s\n", ft_errmsgs[err]); + else + printf ("\n"); - continue; - } + continue; + } - if ((! font_info.name) && (ft_face->family_name)) - font_info.name = xstrdup (ft_face->family_name); + if ((! arguments.font_info.name) && (ft_face->family_name)) + arguments.font_info.name = xstrdup (ft_face->family_name); - size = font_size; - if (! size) - { - if ((ft_face->face_flags & FT_FACE_FLAG_SCALABLE) || - (! ft_face->num_fixed_sizes)) - size = GRUB_FONT_DEFAULT_SIZE; - else - size = ft_face->available_sizes[0].height; - } + size = arguments.font_size; + if (! size) + { + if ((ft_face->face_flags & FT_FACE_FLAG_SCALABLE) || + (! ft_face->num_fixed_sizes)) + size = GRUB_FONT_DEFAULT_SIZE; + else + size = ft_face->available_sizes[0].height; + } - font_info.style = ft_face->style_flags; - font_info.size = size; + arguments.font_info.style = ft_face->style_flags; + arguments.font_info.size = size; - if (FT_Set_Pixel_Sizes (ft_face, size, size)) - grub_util_error (_("can't set %dx%d font size"), size, size); - add_font (&font_info, ft_face, file_format != PF2); - FT_Done_Face (ft_face); - } + if (FT_Set_Pixel_Sizes (ft_face, size, size)) + grub_util_error (_("can't set %dx%d font size"), + size, size); + add_font (&arguments.font_info, ft_face, arguments.file_format != PF2); + FT_Done_Face (ft_face); + } + } FT_Done_FreeType (ft_lib); @@ -1196,46 +1202,52 @@ main (int argc, char *argv[]) memset (counter, 0, sizeof (counter)); - for (cur = font_info.glyphs_unsorted; cur; cur = cur->next) + for (cur = arguments.font_info.glyphs_unsorted; cur; cur = cur->next) counter[(cur->char_code & 0xffff) + 1]++; for (i = 0; i < 0x10000; i++) counter[i+1] += counter[i]; - tmp = xmalloc (font_info.num_glyphs + tmp = xmalloc (arguments.font_info.num_glyphs * sizeof (tmp[0])); - for (cur = font_info.glyphs_unsorted; cur; cur = cur->next) + for (cur = arguments.font_info.glyphs_unsorted; cur; cur = cur->next) tmp[counter[(cur->char_code & 0xffff)]++] = *cur; memset (counter, 0, sizeof (counter)); - for (cur = tmp; cur < tmp + font_info.num_glyphs; cur++) + for (cur = tmp; cur < tmp + arguments.font_info.num_glyphs; cur++) counter[((cur->char_code & 0xffff0000) >> 16) + 1]++; for (i = 0; i < 0x10000; i++) counter[i+1] += counter[i]; - font_info.glyphs_sorted = xmalloc (font_info.num_glyphs - * sizeof (font_info.glyphs_sorted[0])); - for (cur = tmp; cur < tmp + font_info.num_glyphs; cur++) - font_info.glyphs_sorted[counter[(cur->char_code & 0xffff0000) >> 16]++] - = *cur; + arguments.font_info.glyphs_sorted = xmalloc (arguments.font_info.num_glyphs + * sizeof (arguments.font_info.glyphs_sorted[0])); + for (cur = tmp; cur < tmp + arguments.font_info.num_glyphs; cur++) + arguments.font_info.glyphs_sorted[counter[(cur->char_code & 0xffff0000) + >> 16]++] = *cur; free (tmp); } - switch (file_format) + switch (arguments.file_format) { case PF2: - write_font_pf2 (&font_info, output_file); + write_font_pf2 (&arguments.font_info, arguments.output_file); break; case ASCII_BITMAPS: - write_font_ascii_bitmap (&font_info, output_file); + write_font_ascii_bitmap (&arguments.font_info, arguments.output_file); break; case WIDTH_SPEC: - write_font_width_spec (&font_info, output_file); + write_font_width_spec (&arguments.font_info, arguments.output_file); break; } if (font_verbosity > 1) - print_glyphs (&font_info); + print_glyphs (&arguments.font_info); + + { + size_t i; + for (i = 0; i < arguments.nfiles; i++) + free (arguments.files[i]); + } return 0; } diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 0ffeb909e..34f4730f5 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -41,7 +42,7 @@ #include #define _GNU_SOURCE 1 -#include +#include #include "progname.h" @@ -150,7 +151,8 @@ struct image_target_desc image_targets[] = .decompressor_uncompressed_addr = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, - .link_addr = GRUB_KERNEL_I386_PC_LINK_ADDR + .link_addr = GRUB_KERNEL_I386_PC_LINK_ADDR, + .default_compression = COMPRESSION_LZMA }, { .dirname = "i386-pc", @@ -165,7 +167,8 @@ struct image_target_desc image_targets[] = .decompressor_uncompressed_addr = TARGET_NO_FIELD, .section_align = 1, .vaddr_offset = 0, - .link_addr = GRUB_KERNEL_I386_PC_LINK_ADDR + .link_addr = GRUB_KERNEL_I386_PC_LINK_ADDR, + .default_compression = COMPRESSION_LZMA }, { .dirname = "i386-efi", @@ -593,7 +596,7 @@ compress_kernel_lzma (char *kernel_img, size_t kernel_size, kernel_size, &props, out_props, &out_props_size, 0, NULL, &g_Alloc, &g_Alloc) != SZ_OK) - grub_util_error (_("cannot compress the kernel image")); + grub_util_error ("%s", _("cannot compress the kernel image")); } #ifdef HAVE_LIBLZMA @@ -694,7 +697,8 @@ struct fixup_block_list #undef MKIMAGE_ELF64 static void -generate_image (const char *dir, char *prefix, FILE *out, char *mods[], +generate_image (const char *dir, const char *prefix, + FILE *out, const char *outname, char *mods[], char *memdisk_path, char *config_path, struct image_target_desc *image_target, int note, grub_compression_t comp) @@ -710,7 +714,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], grub_uint64_t start_address; void *rel_section; grub_size_t reloc_size, align; - size_t decompress_size; + size_t decompress_size = 0; if (comp == COMPRESSION_AUTO) comp = image_target->default_compression; @@ -731,7 +735,8 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], if (memdisk_path) { memdisk_size = ALIGN_UP(grub_util_get_image_size (memdisk_path), 512); - grub_util_info ("the size of memory disk is 0x%x", memdisk_size); + grub_util_info ("the size of memory disk is 0x%llx", + (unsigned long long) memdisk_size); total_module_size += memdisk_size + sizeof (struct grub_module_header); } @@ -739,7 +744,8 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], { config_size_pure = grub_util_get_image_size (config_path) + 1; config_size = ALIGN_ADDR (config_size_pure); - grub_util_info ("the size of config file is 0x%x", config_size); + grub_util_info ("the size of config file is 0x%llx", + (unsigned long long) config_size); total_module_size += config_size + sizeof (struct grub_module_header); } @@ -753,7 +759,8 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], total_module_size += (ALIGN_ADDR (grub_util_get_image_size (p->name)) + sizeof (struct grub_module_header)); - grub_util_info ("the total module size is 0x%x", total_module_size); + grub_util_info ("the total module size is 0x%llx", + (unsigned long long) total_module_size); if (image_target->voidp_sizeof == 4) kernel_img = load_image32 (kernel_path, &exec_size, &kernel_size, &bss_size, @@ -870,12 +877,13 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], offset += prefix_size; } - grub_util_info ("kernel_img=%p, kernel_size=0x%x", kernel_img, kernel_size); + grub_util_info ("kernel_img=%p, kernel_size=0x%llx", kernel_img, + (unsigned long long) kernel_size); compress_kernel (image_target, kernel_img, kernel_size + total_module_size, &core_img, &core_size, comp); free (kernel_img); - grub_util_info ("the core size is 0x%x", core_size); + grub_util_info ("the core size is 0x%llx", (unsigned long long) core_size); if (!(image_target->flags & PLATFORM_FLAGS_DECOMPRESSORS) && image_target->total_module_size != TARGET_NO_FIELD) @@ -911,7 +919,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], if ((image_target->id == IMAGE_I386_PC || image_target->id == IMAGE_I386_PC_PXE) && decompress_size > GRUB_KERNEL_I386_PC_LINK_ADDR - 0x8200) - grub_util_error (_("Decompressor is too big")); + grub_util_error ("%s", _("Decompressor is too big")); if (image_target->decompressor_compressed_size != TARGET_NO_FIELD) *((grub_uint32_t *) (decompress_img @@ -958,27 +966,39 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], char *boot_path, *boot_img; size_t boot_size; - if (GRUB_KERNEL_I386_PC_LINK_ADDR + core_size > GRUB_MEMORY_I386_PC_UPPER) - grub_util_error (_("core image is too big (%p > %p)"), + if (GRUB_KERNEL_I386_PC_LINK_ADDR + core_size > 0x78000 + || (core_size > (0xffff << GRUB_DISK_SECTOR_BITS))) + grub_util_error (_("core image is too big (0x%x > 0x%x)"), GRUB_KERNEL_I386_PC_LINK_ADDR + core_size, - GRUB_MEMORY_I386_PC_UPPER); + 0x78000); num = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS); - if (num > 0xffff) - grub_util_error (_("the core image is too big")); - if (image_target->id == IMAGE_I386_PC_PXE) { char *pxeboot_path, *pxeboot_img; size_t pxeboot_size; + grub_uint32_t *ptr; pxeboot_path = grub_util_get_path (dir, "pxeboot.img"); pxeboot_size = grub_util_get_image_size (pxeboot_path); pxeboot_img = grub_util_read_image (pxeboot_path); - grub_util_write_image (pxeboot_img, pxeboot_size, out); + grub_util_write_image (pxeboot_img, pxeboot_size, out, + outname); free (pxeboot_img); free (pxeboot_path); + + /* Remove Multiboot header to avoid confusing ipxe. */ + for (ptr = (grub_uint32_t *) core_img; + ptr < (grub_uint32_t *) (core_img + MULTIBOOT_SEARCH); ptr++) + if (*ptr == grub_host_to_target32 (MULTIBOOT_HEADER_MAGIC) + && grub_target_to_host32 (ptr[0]) + + grub_target_to_host32 (ptr[1]) + + grub_target_to_host32 (ptr[2]) == 0) + { + *ptr = 0; + break; + } } boot_path = grub_util_get_path (dir, "diskboot.img"); @@ -1002,7 +1022,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], + (GRUB_DISK_SECTOR_SIZE >> 4))); } - grub_util_write_image (boot_img, boot_size, out); + grub_util_write_image (boot_img, boot_size, out, outname); free (boot_img); free (boot_path); } @@ -1037,8 +1057,8 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], image_target->section_align); pe_img = xmalloc (reloc_addr + reloc_size); memset (pe_img, 0, header_size); - memcpy (pe_img + header_size, core_img, core_size); - memcpy (pe_img + reloc_addr, rel_section, reloc_size); + memcpy ((char *) pe_img + header_size, core_img, core_size); + memcpy ((char *) pe_img + reloc_addr, rel_section, reloc_size); header = pe_img; /* The magic. */ @@ -1249,7 +1269,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], aout_head->a_text = grub_host_to_target32 (core_size); aout_head->a_entry = grub_host_to_target32 (GRUB_BOOT_SPARC64_IEEE1275_IMAGE_ADDRESS); - memcpy (aout_img + sizeof (*aout_head), core_img, core_size); + memcpy ((char *) aout_img + sizeof (*aout_head), core_img, core_size); free (core_img); core_img = aout_img; @@ -1268,7 +1288,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], boot_path = grub_util_get_path (dir, "diskboot.img"); boot_size = grub_util_get_image_size (boot_path); if (boot_size != GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("diskboot.img is not one sector size")); + grub_util_error ("%s", _("diskboot.img is not one sector size")); boot_img = grub_util_read_image (boot_path); @@ -1276,7 +1296,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], - GRUB_BOOT_SPARC64_IEEE1275_LIST_SIZE + 8)) = grub_host_to_target32 (num); - grub_util_write_image (boot_img, boot_size, out); + grub_util_write_image (boot_img, boot_size, out, outname); free (boot_img); free (boot_path); } @@ -1333,11 +1353,12 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], GRUB_MD_SHA512->final (context); if (grub_memcmp (GRUB_MD_SHA512->read (context), fwstart_good_hash, GRUB_MD_SHA512->mdlen) != 0) - grub_util_warn (_("fwstart.img doesn't match the known good version. " + grub_util_warn ("%s", + _("fwstart.img doesn't match the known good version. " "proceed at your own risk")); if (core_size + boot_size > 512 * 1024) - grub_util_error (_("firmware image is too big")); + grub_util_error ("%s", _("firmware image is too big")); rom_size = 512 * 1024; rom_img = xmalloc (rom_size); @@ -1361,7 +1382,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], size_t rom_size; if (core_size > 512 * 1024) - grub_util_error (_("firmware image is too big")); + grub_util_error ("%s", _("firmware image is too big")); rom_size = 512 * 1024; rom_img = xmalloc (rom_size); @@ -1568,21 +1589,21 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], if (note) { int note_size = sizeof (struct grub_ieee1275_note); - struct grub_ieee1275_note *note = (struct grub_ieee1275_note *) + struct grub_ieee1275_note *note_ptr = (struct grub_ieee1275_note *) (elf_img + program_size + header_size); grub_util_info ("adding CHRP NOTE segment"); - note->header.namesz = grub_host_to_target32 (sizeof (GRUB_IEEE1275_NOTE_NAME)); - note->header.descsz = grub_host_to_target32 (note_size); - note->header.type = grub_host_to_target32 (GRUB_IEEE1275_NOTE_TYPE); - strcpy (note->header.name, GRUB_IEEE1275_NOTE_NAME); - note->descriptor.real_mode = grub_host_to_target32 (0xffffffff); - note->descriptor.real_base = grub_host_to_target32 (0x00c00000); - note->descriptor.real_size = grub_host_to_target32 (0xffffffff); - note->descriptor.virt_base = grub_host_to_target32 (0xffffffff); - note->descriptor.virt_size = grub_host_to_target32 (0xffffffff); - note->descriptor.load_base = grub_host_to_target32 (0x00004000); + note_ptr->header.namesz = grub_host_to_target32 (sizeof (GRUB_IEEE1275_NOTE_NAME)); + note_ptr->header.descsz = grub_host_to_target32 (note_size); + note_ptr->header.type = grub_host_to_target32 (GRUB_IEEE1275_NOTE_TYPE); + strcpy (note_ptr->header.name, GRUB_IEEE1275_NOTE_NAME); + note_ptr->descriptor.real_mode = grub_host_to_target32 (0xffffffff); + note_ptr->descriptor.real_base = grub_host_to_target32 (0x00c00000); + note_ptr->descriptor.real_size = grub_host_to_target32 (0xffffffff); + note_ptr->descriptor.virt_base = grub_host_to_target32 (0xffffffff); + note_ptr->descriptor.virt_size = grub_host_to_target32 (0xffffffff); + note_ptr->descriptor.load_base = grub_host_to_target32 (0x00004000); phdr++; phdr->p_type = grub_host_to_target32 (PT_NOTE); @@ -1602,7 +1623,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], break; } - grub_util_write_image (core_img, core_size, out); + grub_util_write_image (core_img, core_size, out, outname); free (core_img); free (kernel_path); @@ -1617,227 +1638,245 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], -static struct option options[] = - { - {"directory", required_argument, 0, 'd'}, - {"prefix", required_argument, 0, 'p'}, - {"memdisk", required_argument, 0, 'm'}, - {"font", required_argument, 0, 'f'}, - {"config", required_argument, 0, 'c'}, - {"output", required_argument, 0, 'o'}, - {"note", no_argument, 0, 'n'}, - {"format", required_argument, 0, 'O'}, - {"compression", required_argument, 0, 'C'}, - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'V'}, - {"verbose", no_argument, 0, 'v'}, - {0, 0, 0, 0} - }; +static struct argp_option options[] = { + {"directory", 'd', N_("DIR"), 0, N_("use images and modules under DIR [default=%s/]"), 0}, + {"prefix", 'p', N_("DIR"), 0, N_("set prefix directory [default=%s]"), 0}, + {"memdisk", 'm', N_("FILE"), 0, N_("embed FILE as a memdisk image"), 0}, + {"config", 'c', N_("FILE"), 0, N_("embed FILE as an early config"), 0}, + /* TRANSLATORS: NOTE is a name of segment. */ + {"note", 'n', 0, 0, N_("add NOTE segment for CHRP IEEE1275"), 0}, + {"output", 'o', N_("FILE"), 0, N_("output a generated image to FILE [default=stdout]"), 0}, + {"format", 'O', N_("FORMAT"), 0, 0, 0}, + {"compression", 'C', "(xz|none|auto)", 0, N_("choose the compression to use"), 0}, + {"verbose", 'v', 0, 0, N_("print verbose messages."), 0}, + { 0, 0, 0, 0, 0, 0 } +}; -static void -usage (int status) +static char * +help_filter (int key, const char *text, void *input __attribute__ ((unused))) { - if (status) - fprintf (stderr, _("Try `%s --help' for more information.\n"), program_name); - else + switch (key) { - int format_len = 0; - char *formats; - char *ptr; - unsigned i; - for (i = 0; i < ARRAY_SIZE (image_targets); i++) - format_len += strlen (image_targets[i].names[0]) + 2; - ptr = formats = xmalloc (format_len); - for (i = 0; i < ARRAY_SIZE (image_targets); i++) - { - strcpy (ptr, image_targets[i].names[0]); - ptr += strlen (image_targets[i].names[0]); - *ptr++ = ','; - *ptr++ = ' '; - } - ptr[-2] = 0; - - printf (_("\ -Usage: %s [OPTION]... [MODULES]\n\ -\n\ -Make a bootable image of GRUB.\n\ -\n\ - -d, --directory=DIR use images and modules under DIR [default=%s/@platform@]\n\ - -p, --prefix=DIR set grub_prefix directory [default=%s]\n\ - -m, --memdisk=FILE embed FILE as a memdisk image\n\ - -c, --config=FILE embed FILE as boot config\n\ - -n, --note add NOTE segment for CHRP Open Firmware\n\ - -o, --output=FILE output a generated image to FILE [default=stdout]\n\ - -O, --format=FORMAT generate an image in format\n\ - available formats: %s\n\ - -C, --compression=(xz|none|auto) choose the compression to use\n\ - -h, --help display this message and exit\n\ - -V, --version print version information and exit\n\ - -v, --verbose print verbose messages\n\ -\n\ -Report bugs to <%s>.\n\ -"), - program_name, GRUB_PKGLIBROOTDIR, DEFAULT_DIRECTORY, - formats, - PACKAGE_BUGREPORT); - free (formats); + case 'd': + return xasprintf (text, GRUB_PKGLIBROOTDIR); + case 'p': + return xasprintf (text, DEFAULT_DIRECTORY); + case 'O': + { + int format_len = 0; + char *formats; + char *ptr; + char *ret; + unsigned i; + for (i = 0; i < ARRAY_SIZE (image_targets); i++) + format_len += strlen (image_targets[i].names[0]) + 2; + ptr = formats = xmalloc (format_len); + for (i = 0; i < ARRAY_SIZE (image_targets); i++) + { + strcpy (ptr, image_targets[i].names[0]); + ptr += strlen (image_targets[i].names[0]); + *ptr++ = ','; + *ptr++ = ' '; + } + ptr[-2] = 0; + ret = xasprintf ("%s\n%s %s", _("generate an image in format"), + _("available formats:"), formats); + free (formats); + return ret; + } + default: + return (char *) text; } - exit (status); } +struct arguments +{ + size_t nmodules; + size_t modules_max; + char **modules; + char *output; + char *dir; + char *prefix; + char *memdisk; + char *font; + char *config; + int note; + struct image_target_desc *image_target; + grub_compression_t comp; +}; + +static error_t +argp_parser (int key, char *arg, struct argp_state *state) +{ + /* Get the input argument from argp_parse, which we + know is a pointer to our arguments structure. */ + struct arguments *arguments = state->input; + + switch (key) + { + case 'o': + if (arguments->output) + free (arguments->output); + + arguments->output = xstrdup (arg); + break; + + case 'O': + { + unsigned i, j; + for (i = 0; i < ARRAY_SIZE (image_targets); i++) + for (j = 0; image_targets[i].names[j] + && j < ARRAY_SIZE (image_targets[i].names); j++) + if (strcmp (arg, image_targets[i].names[j]) == 0) + arguments->image_target = &image_targets[i]; + if (!arguments->image_target) + { + printf (_("unknown target format %s\n"), arg); + argp_usage (state); + exit (1); + } + break; + } + case 'd': + if (arguments->dir) + free (arguments->dir); + + arguments->dir = xstrdup (arg); + break; + + case 'n': + arguments->note = 1; + break; + + case 'm': + if (arguments->memdisk) + free (arguments->memdisk); + + arguments->memdisk = xstrdup (arg); + + if (arguments->prefix) + free (arguments->prefix); + + arguments->prefix = xstrdup ("(memdisk)/boot/grub"); + break; + + case 'c': + if (arguments->config) + free (arguments->config); + + arguments->config = xstrdup (arg); + break; + + case 'C': + if (grub_strcmp (arg, "xz") == 0) + { +#ifdef HAVE_LIBLZMA + arguments->comp = COMPRESSION_XZ; +#else + grub_util_error ("%s", + _("grub-mkimage is compiled without XZ support")); +#endif + } + else if (grub_strcmp (arg, "none") == 0) + arguments->comp = COMPRESSION_NONE; + else if (grub_strcmp (arg, "auto") == 0) + arguments->comp = COMPRESSION_AUTO; + else + grub_util_error (_("Unknown compression format %s"), arg); + break; + + case 'p': + if (arguments->prefix) + free (arguments->prefix); + + arguments->prefix = xstrdup (arg); + break; + + case 'v': + verbosity++; + break; + case ARGP_KEY_ARG: + assert (arguments->nmodules < arguments->modules_max); + arguments->modules[arguments->nmodules++] = xstrdup(arg); + break; + + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +static struct argp argp = { + options, argp_parser, N_("[OPTION]... [MODULES]"), + N_("Make a bootable image of GRUB."), + NULL, help_filter, NULL +}; + int main (int argc, char *argv[]) { - char *output = NULL; - char *dir = NULL; - char *prefix = NULL; - char *memdisk = NULL; - char *font = NULL; - char *config = NULL; FILE *fp = stdout; - int note = 0; - struct image_target_desc *image_target = NULL; - grub_compression_t comp = COMPRESSION_AUTO; + struct arguments arguments; set_program_name (argv[0]); grub_util_init_nls (); - while (1) + memset (&arguments, 0, sizeof (struct arguments)); + arguments.comp = COMPRESSION_AUTO; + arguments.modules_max = argc + 1; + arguments.modules = xmalloc ((arguments.modules_max + 1) + * sizeof (arguments.modules[0])); + memset (arguments.modules, 0, (arguments.modules_max + 1) + * sizeof (arguments.modules[0])); + + if (argp_parse (&argp, argc, argv, 0, 0, &arguments) != 0) { - int c = getopt_long (argc, argv, "d:p:m:c:o:O:f:C:hVvn", options, 0); - - if (c == -1) - break; - else - switch (c) - { - case 'o': - if (output) - free (output); - - output = xstrdup (optarg); - break; - - case 'O': - { - unsigned i, j; - for (i = 0; i < ARRAY_SIZE (image_targets); i++) - for (j = 0; image_targets[i].names[j] - && j < ARRAY_SIZE (image_targets[i].names); j++) - if (strcmp (optarg, image_targets[i].names[j]) == 0) - image_target = &image_targets[i]; - if (!image_target) - { - printf (_("unknown target format %s\n"), optarg); - usage (1); - } - break; - } - case 'd': - if (dir) - free (dir); - - dir = xstrdup (optarg); - break; - - case 'n': - note = 1; - break; - - case 'm': - if (memdisk) - free (memdisk); - - memdisk = xstrdup (optarg); - - if (prefix) - free (prefix); - - prefix = xstrdup ("(memdisk)/boot/grub"); - break; - - case 'c': - if (config) - free (config); - - config = xstrdup (optarg); - break; - - case 'C': - if (grub_strcmp (optarg, "xz") == 0) - { -#ifdef HAVE_LIBLZMA - comp = COMPRESSION_XZ; -#else - grub_util_error (_("grub-mkimage is compiled without XZ support"), - optarg); -#endif - } - else if (grub_strcmp (optarg, "none") == 0) - comp = COMPRESSION_NONE; - else - grub_util_error (_("Unknown compression format %s"), optarg); - break; - - case 'h': - usage (0); - break; - - case 'p': - if (prefix) - free (prefix); - - prefix = xstrdup (optarg); - break; - - case 'V': - printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); - return 0; - - case 'v': - verbosity++; - break; - - default: - usage (1); - break; - } + fprintf (stderr, "%s", _("Error in parsing command line arguments\n")); + exit(1); } - if (!image_target) + if (!arguments.image_target) { - printf (_("Target format not specified (use the -O option).\n")); - usage (1); + char *program = xstrdup(program_name); + printf ("%s\n", _("Target format not specified (use the -O option).")); + argp_help (&argp, stderr, ARGP_HELP_STD_USAGE, program); + free (program); + exit(1); } - if (output) + if (arguments.output) { - fp = fopen (output, "wb"); + fp = fopen (arguments.output, "wb"); if (! fp) - grub_util_error (_("cannot open %s"), output); - free (output); + grub_util_error (_("cannot open `%s': %s"), arguments.output, + strerror (errno)); + free (arguments.output); } - if (!dir) + if (!arguments.dir) { - dir = xmalloc (sizeof (GRUB_PKGLIBROOTDIR) - + grub_strlen (image_target->dirname) + 1); - memcpy (dir, GRUB_PKGLIBROOTDIR, sizeof (GRUB_PKGLIBROOTDIR) - 1); - *(dir + sizeof (GRUB_PKGLIBROOTDIR) - 1) = '/'; - strcpy (dir + sizeof (GRUB_PKGLIBROOTDIR), image_target->dirname); + arguments.dir = xmalloc (sizeof (GRUB_PKGLIBROOTDIR) + + grub_strlen (arguments.image_target->dirname) + + 1); + memcpy (arguments.dir, GRUB_PKGLIBROOTDIR, + sizeof (GRUB_PKGLIBROOTDIR) - 1); + *(arguments.dir + sizeof (GRUB_PKGLIBROOTDIR) - 1) = '/'; + strcpy (arguments.dir + sizeof (GRUB_PKGLIBROOTDIR), + arguments.image_target->dirname); } - generate_image (dir, prefix ? : DEFAULT_DIRECTORY, fp, - argv + optind, memdisk, config, - image_target, note, comp); + generate_image (arguments.dir, arguments.prefix ? : DEFAULT_DIRECTORY, fp, + arguments.output, + arguments.modules, arguments.memdisk, arguments.config, + arguments.image_target, arguments.note, arguments.comp); fflush (fp); fsync (fileno (fp)); fclose (fp); - if (dir) - free (dir); + if (arguments.dir) + free (arguments.dir); return 0; } diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c index 352291070..2aa386fbc 100644 --- a/util/grub-mkimagexx.c +++ b/util/grub-mkimagexx.c @@ -83,28 +83,28 @@ SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections, i < num_syms; i++, sym = (Elf_Sym *) ((char *) sym + sym_size)) { - Elf_Section index; + Elf_Section cur_index; const char *name; name = strtab + grub_target_to_host32 (sym->st_name); - index = grub_target_to_host16 (sym->st_shndx); - if (index == STN_ABS) + cur_index = grub_target_to_host16 (sym->st_shndx); + if (cur_index == STN_ABS) { continue; } - else if ((index == STN_UNDEF)) + else if ((cur_index == STN_UNDEF)) { if (sym->st_name) grub_util_error ("undefined symbol %s", name); else continue; } - else if (index >= num_sections) - grub_util_error ("section %d does not exist", index); + else if (cur_index >= num_sections) + grub_util_error ("section %d does not exist", cur_index); sym->st_value = (grub_target_to_host (sym->st_value) - + section_addresses[index]); + + section_addresses[cur_index]); if (image_target->elf_target == EM_IA_64 && ELF_ST_TYPE (sym->st_info) == STT_FUNC) @@ -115,7 +115,9 @@ SUFFIX (relocate_symbols) (Elf_Ehdr *e, Elf_Shdr *sections, *jptr = 0; jptr++; } - grub_util_info ("locating %s at 0x%x", name, sym->st_value, section_addresses[index]); + grub_util_info ("locating %s at 0x%llx (0x%llx)", name, + (unsigned long long) sym->st_value, + (unsigned long long) section_addresses[cur_index]); if (! start_address) if (strcmp (name, "_start") == 0 || strcmp (name, "start") == 0) @@ -146,13 +148,13 @@ SUFFIX (get_target_address) (Elf_Ehdr *e, Elf_Shdr *s, Elf_Addr offset, return (Elf_Addr *) ((char *) e + grub_target_to_host32 (s->sh_offset) + offset); } +#ifdef MKIMAGE_ELF64 static Elf_Addr SUFFIX (count_funcs) (Elf_Ehdr *e, Elf_Shdr *symtab_section, struct image_target_desc *image_target) { Elf_Word symtab_size, sym_size, num_syms; Elf_Off symtab_offset; - Elf_Addr start_address = 0; Elf_Sym *sym; Elf_Word i; int ret = 0; @@ -170,6 +172,7 @@ SUFFIX (count_funcs) (Elf_Ehdr *e, Elf_Shdr *symtab_section, return ret; } +#endif #ifdef MKIMAGE_ELF64 struct unaligned_uint32 @@ -179,6 +182,7 @@ struct unaligned_uint32 #define MASK20 ((1 << 20) - 1) #define MASK19 ((1 << 19) - 1) +#define MASK3 (~(grub_addr_t) 3) static void add_value_to_slot_20b (grub_addr_t addr, grub_uint32_t value) @@ -187,17 +191,17 @@ add_value_to_slot_20b (grub_addr_t addr, grub_uint32_t value) switch (addr & 3) { case 0: - p = (struct unaligned_uint32 *) ((addr & ~3ULL) + 2); + p = (struct unaligned_uint32 *) ((addr & MASK3) + 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 = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & MASK3) + 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 = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & MASK3) + 12); p->val = ((((((p->val >> 4) & MASK20) + value) & MASK20) << 4) | (p->val & ~(MASK20 << 4))); break; @@ -224,15 +228,15 @@ add_value_to_slot_21 (grub_addr_t addr, grub_uint32_t value) switch (addr & 3) { case 0: - p = (struct unaligned_uint32 *) ((addr & ~3ULL) + 2); + p = (struct unaligned_uint32 *) ((addr & MASK3) + 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 = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & MASK3) + 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 = (struct unaligned_uint32 *) ((grub_uint8_t *) (addr & MASK3) + 12); p->val = ((add_value_to_slot_21_real (((p->val >> 4) & MASKF21), value) & MASKF21) << 4) | (p->val & ~(MASKF21 << 4)); break; } @@ -307,8 +311,10 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections, { Elf_Half i; Elf_Shdr *s; +#ifdef MKIMAGE_ELF64 struct ia64_kernel_trampoline *tr = (void *) (pe_target + tramp_off); grub_uint64_t *gpptr = (void *) (pe_target + got_off); +#endif for (i = 0, s = sections; i < num_sections; @@ -375,8 +381,9 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections, /* This is absolute. */ *target = grub_host_to_target32 (grub_target_to_host32 (*target) + addend + sym_addr); - grub_util_info ("relocating an R_386_32 entry to 0x%x at the offset 0x%x", - *target, offset); + grub_util_info ("relocating an R_386_32 entry to 0x%llx at the offset 0x%llx", + (unsigned long long) *target, + (unsigned long long) offset); break; case R_386_PC32: @@ -385,15 +392,17 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections, + addend + sym_addr - target_section_addr - offset - image_target->vaddr_offset); - grub_util_info ("relocating an R_386_PC32 entry to 0x%x at the offset 0x%x", - *target, offset); + grub_util_info ("relocating an R_386_PC32 entry to 0x%llx at the offset 0x%llx", + (unsigned long long) *target, + (unsigned long long) offset); break; default: - grub_util_error ("unknown relocation type 0x%x", + grub_util_error (_("relocation 0x%x is not implemented yet"), ELF_R_TYPE (info)); break; } break; +#ifdef MKIMAGE_ELF64 case EM_X86_64: switch (ELF_R_TYPE (info)) { @@ -405,7 +414,8 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections, *target = grub_host_to_target64 (grub_target_to_host64 (*target) + addend + sym_addr); grub_util_info ("relocating an R_X86_64_64 entry to 0x%llx at the offset 0x%llx", - *target, offset); + (unsigned long long) *target, + (unsigned long long) offset); break; case R_X86_64_PC32: @@ -416,7 +426,7 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections, - target_section_addr - offset - image_target->vaddr_offset); grub_util_info ("relocating an R_X86_64_PC32 entry to 0x%x at the offset 0x%llx", - *t32, offset); + *t32, (unsigned long long) offset); break; } @@ -427,17 +437,16 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections, *t32 = grub_host_to_target64 (grub_target_to_host32 (*t32) + addend + sym_addr); grub_util_info ("relocating an R_X86_64_32(S) entry to 0x%x at the offset 0x%llx", - *t32, offset); + *t32, (unsigned long long) offset); break; } default: - grub_util_error ("unknown relocation type %d", + grub_util_error (_("relocation 0x%x is not implemented yet"), ELF_R_TYPE (info)); break; } break; -#ifdef MKIMAGE_ELF64 case EM_IA_64: switch (ELF_R_TYPE (info)) { @@ -449,8 +458,8 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections, - target_section_addr - (offset & ~3)) >> 4; tr++; if (noff & ~MASK19) - grub_util_error ("trampoline offset too big (%lx)", - noff); + grub_util_error ("trampoline offset too big (%" + PRIxGRUB_UINT64_T ")", noff); add_value_to_slot_20b ((grub_addr_t) target, noff); } break; @@ -496,8 +505,8 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections, *target = grub_host_to_target64 (grub_target_to_host64 (*target) + addend + sym_addr); grub_util_info ("relocating a direct entry to 0x%" - PRIxGRUB_UINT64_T " at the offset 0x%x", - *target, offset); + PRIxGRUB_UINT64_T " at the offset 0x%llx", + *target, (unsigned long long) offset); break; /* We treat LTOFF22X as LTOFF22, so we can ignore LDXMOV. */ @@ -505,7 +514,7 @@ SUFFIX (relocate_addresses) (Elf_Ehdr *e, Elf_Shdr *sections, break; default: - grub_util_error ("unknown relocation type 0x%x", + grub_util_error (_("relocation 0x%x is not implemented yet"), ELF_R_TYPE (info)); break; } @@ -543,17 +552,17 @@ SUFFIX (add_fixup_entry) (struct fixup_block_list **cblock, grub_uint16_t type, with a section boundary. */ Elf_Addr next_address; unsigned padding_size; - size_t index; + size_t cur_index; next_address = current_address + b->block_size; padding_size = ((ALIGN_UP (next_address, image_target->section_align) - next_address) >> 1); - index = ((b->block_size - sizeof (*b)) >> 1); + cur_index = ((b->block_size - sizeof (*b)) >> 1); grub_util_info ("adding %d padding fixup entries", padding_size); while (padding_size--) { - b->entries[index++] = 0; + b->entries[cur_index++] = 0; b->block_size += 2; } } @@ -561,11 +570,11 @@ SUFFIX (add_fixup_entry) (struct fixup_block_list **cblock, grub_uint16_t type, { /* If not aligned with a 32-bit boundary, add a padding entry. */ - size_t index; + size_t cur_index; grub_util_info ("adding a padding fixup entry"); - index = ((b->block_size - sizeof (*b)) >> 1); - b->entries[index] = 0; + cur_index = ((b->block_size - sizeof (*b)) >> 1); + b->entries[cur_index] = 0; b->block_size += 2; } @@ -587,7 +596,7 @@ SUFFIX (add_fixup_entry) (struct fixup_block_list **cblock, grub_uint16_t type, if (! flush) { grub_uint16_t entry; - size_t index; + size_t cur_index; /* If not allocated yet, allocate a block with enough entries. */ if (! (*cblock)->state) @@ -605,9 +614,9 @@ SUFFIX (add_fixup_entry) (struct fixup_block_list **cblock, grub_uint16_t type, grub_util_error ("too many fixup entries"); /* Add a new entry. */ - index = ((b->block_size - sizeof (*b)) >> 1); + cur_index = ((b->block_size - sizeof (*b)) >> 1); entry = GRUB_PE32_FIXUP_ENTRY (type, addr - b->page_rva); - b->entries[index] = grub_host_to_target16 (entry); + b->entries[cur_index] = grub_host_to_target16 (entry); b->block_size += 2; } @@ -671,7 +680,8 @@ SUFFIX (make_reloc_section) (Elf_Ehdr *e, void **out, Elf_Addr addr; addr = section_address + offset; - grub_util_info ("adding a relocation entry for 0x%x", addr); + grub_util_info ("adding a relocation entry for 0x%llx", + (unsigned long long) addr); current_address = SUFFIX (add_fixup_entry) (&lst, GRUB_PE32_REL_BASED_HIGHLOW, @@ -690,7 +700,8 @@ SUFFIX (make_reloc_section) (Elf_Ehdr *e, void **out, Elf_Addr addr; addr = section_address + offset; - grub_util_info ("adding a relocation entry for 0x%llx", addr); + grub_util_info ("adding a relocation entry for 0x%llx", + (unsigned long long) addr); current_address = SUFFIX (add_fixup_entry) (&lst, GRUB_PE32_REL_BASED_DIR64, @@ -719,7 +730,8 @@ SUFFIX (make_reloc_section) (Elf_Ehdr *e, void **out, Elf_Addr addr; addr = section_address + offset; - grub_util_info ("adding a relocation entry for 0x%llx", addr); + grub_util_info ("adding a relocation entry for 0x%llx", + (unsigned long long) addr); current_address = SUFFIX (add_fixup_entry) (&lst, GRUB_PE32_REL_BASED_DIR64, @@ -730,7 +742,7 @@ SUFFIX (make_reloc_section) (Elf_Ehdr *e, void **out, #endif break; default: - grub_util_error ("unknown relocation type 0x%x", + grub_util_error (_("relocation 0x%x is not implemented yet"), ELF_R_TYPE (info)); break; } @@ -760,11 +772,7 @@ SUFFIX (make_reloc_section) (Elf_Ehdr *e, void **out, memcpy (ptr, &lst->b, grub_target_to_host32 (lst->b.block_size)); ptr += grub_target_to_host32 (lst->b.block_size); } - if (current_address + *out != ptr) - { - grub_util_error ("Bug detected %d != %d\n", ptr - (grub_uint8_t *) *out, - current_address); - } + assert ((current_address + (grub_uint8_t *) *out) == ptr); } return current_address; @@ -853,8 +861,8 @@ SUFFIX (locate_sections) (Elf_Shdr *sections, Elf_Half section_entsize, if (align) current_address = ALIGN_UP (current_address + image_target->vaddr_offset, align) - image_target->vaddr_offset; - grub_util_info ("locating the section %s at 0x%x", - name, current_address); + grub_util_info ("locating the section %s at 0x%llx", + name, (unsigned long long) current_address); section_addresses[i] = current_address; current_address += grub_host_to_target_addr (s->sh_size); } @@ -878,8 +886,8 @@ SUFFIX (locate_sections) (Elf_Shdr *sections, Elf_Half section_entsize, align) - image_target->vaddr_offset; - grub_util_info ("locating the section %s at 0x%x", - name, current_address); + grub_util_info ("locating the section %s at 0x%llx", + name, (unsigned long long) current_address); section_addresses[i] = current_address; current_address += grub_host_to_target_addr (s->sh_size); } @@ -912,7 +920,7 @@ SUFFIX (load_image) (const char *kernel_path, grub_size_t *exec_size, grub_size_t kernel_size; grub_size_t ia64jmp_off = 0, ia64_toff = 0, ia64_got_off = 0; unsigned ia64jmpnum = 0; - Elf_Shdr *symtab_section; + Elf_Shdr *symtab_section = 0; grub_size_t got = 0; *start = 0; @@ -930,7 +938,7 @@ SUFFIX (load_image) (const char *kernel_path, grub_size_t *exec_size, num_sections = grub_target_to_host16 (e->e_shnum); if (kernel_size < section_offset + section_entsize * num_sections) - grub_util_error ("invalid ELF format"); + grub_util_error (_("premature end of file %s"), kernel_path); sections = (Elf_Shdr *) (kernel_img + section_offset); @@ -958,16 +966,17 @@ SUFFIX (load_image) (const char *kernel_path, grub_size_t *exec_size, i++, s = (Elf_Shdr *) ((char *) s + section_entsize)) if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS) { - Elf_Word align = grub_host_to_target_addr (s->sh_addralign); + Elf_Word sec_align = grub_host_to_target_addr (s->sh_addralign); const char *name = strtab + grub_host_to_target32 (s->sh_name); - if (align) + if (sec_align) current_address = ALIGN_UP (current_address - + image_target->vaddr_offset, align) + + image_target->vaddr_offset, + sec_align) - image_target->vaddr_offset; - grub_util_info ("locating the section %s at 0x%x", - name, current_address); + grub_util_info ("locating the section %s at 0x%llx", + name, (unsigned long long) current_address); section_vaddresses[i] = current_address + image_target->vaddr_offset; current_address += grub_host_to_target_addr (s->sh_size); @@ -1016,7 +1025,7 @@ SUFFIX (load_image) (const char *kernel_path, grub_size_t *exec_size, #endif if (! symtab_section) - grub_util_error ("no symbol table"); + grub_util_error ("%s", _("no symbol table")); } else { diff --git a/util/grub-mklayout.c b/util/grub-mklayout.c index 8de07747d..74e08a160 100644 --- a/util/grub-mklayout.c +++ b/util/grub-mklayout.c @@ -23,28 +23,36 @@ #include #include +#define _GNU_SOURCE 1 + #include #include #include -#include +#include #include #include #include "progname.h" -#define CKBCOMP "ckbcomp" +struct arguments +{ + char *input; + char *output; + int verbosity; +}; -static struct option options[] = { - {"output", required_argument, 0, 'o'}, - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'V'}, - {"verbose", no_argument, 0, 'v'}, - {0, 0, 0, 0} +static struct argp_option options[] = { + {"input", 'i', N_("FILE"), 0, + N_("set input filename. Default is STDIN"), 0}, + {"output", 'o', N_("FILE"), 0, + N_("set output filename. Default is STDOUT"), 0}, + {"verbose", 'v', 0, 0, N_("print verbose messages."), 0}, + { 0, 0, 0, 0, 0, 0 } }; struct console_grub_equivalence { - char *layout; + const char *layout; grub_uint32_t grub; }; @@ -256,25 +264,6 @@ static grub_uint8_t linux_to_usb_map[128] = { /* 0x6e */ GRUB_KEYBOARD_KEY_INSERT, GRUB_KEYBOARD_KEY_DELETE }; -static void -usage (int status) -{ - if (status) - fprintf (stderr, _("Try `%s --help' for more information.\n"), program_name); - else - printf (_("\ -Usage: %s [OPTIONS]\n\ - -i, --input set input filename. Default is STDIN\n\ - -o, --output set output filename. Default is STDOUT\n\ - -h, --help display this message and exit.\n\ - -V, --version print version information and exit.\n\ - -v, --verbose print verbose messages.\n\ -\n\ -Report bugs to <%s>.\n"), program_name, PACKAGE_BUGREPORT); - - exit (status); -} - static void add_special_keys (struct grub_keyboard_layout *layout) { @@ -300,7 +289,7 @@ lookup (char *code, int shift) if (strcmp (code, console_grub_equivalences_common[i].layout) == 0) return console_grub_equivalences_common[i].grub; - fprintf (stderr, _("Unknown key %s\n"), code); + fprintf (stderr, _("Unknown keyboard scan identifier %s\n"), code); return '\0'; } @@ -396,7 +385,7 @@ write_keymaps (FILE *in, FILE *out) if (keycode_usb == 0 || keycode_usb >= GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE) { - fprintf (stderr, _("Unknown keycode 0x%02x\n"), keycode_linux); + fprintf (stderr, _("Unknown keyboard scan code 0x%02x\n"), keycode_linux); continue; } if (keycode_usb < GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE) @@ -414,8 +403,7 @@ write_keymaps (FILE *in, FILE *out) if (ok == 0) { - fprintf (stderr, _("ERROR: no keycodes found. Check output of %s.\n"), - CKBCOMP); + fprintf (stderr, "%s", _("ERROR: no valid keyboard layout found. Check the input.\n")); exit (1); } @@ -424,65 +412,67 @@ write_keymaps (FILE *in, FILE *out) write_file (out, &layout); } +static error_t +argp_parser (int key, char *arg, struct argp_state *state) +{ + /* Get the input argument from argp_parse, which we + know is a pointer to our arguments structure. */ + struct arguments *arguments = state->input; + + switch (key) + { + case 'i': + arguments->input = xstrdup (arg); + break; + + case 'o': + arguments->output = xstrdup (arg); + break; + + case 'v': + arguments->verbosity++; + break; + + default: + return ARGP_ERR_UNKNOWN; + } + + return 0; +} + +static struct argp argp = { + options, argp_parser, N_("[OPTIONS]"), + N_("Generate GRUB keyboard layout from Linux console one."), + NULL, NULL, NULL +}; + int main (int argc, char *argv[]) { - int verbosity; - char *infile_name = NULL; - char *outfile_name = NULL; FILE *in, *out; + struct arguments arguments; set_program_name (argv[0]); - verbosity = 0; - /* Check for options. */ - while (1) + memset (&arguments, 0, sizeof (struct arguments)); + if (argp_parse (&argp, argc, argv, 0, 0, &arguments) != 0) { - int c = getopt_long (argc, argv, "o:i:hVv", options, 0); - - if (c == -1) - break; - else - switch (c) - { - case 'h': - usage (0); - break; - - case 'i': - infile_name = optarg; - break; - - case 'o': - outfile_name = optarg; - break; - - case 'V': - printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, - PACKAGE_VERSION); - return 0; - - case 'v': - verbosity++; - break; - - default: - usage (1); - break; - } + fprintf (stderr, "%s", _("Error in parsing command line arguments\n")); + exit(1); } - if (infile_name) - in = fopen (infile_name, "r"); + if (arguments.input) + in = fopen (arguments.input, "r"); else in = stdin; if (!in) - grub_util_error (_("Couldn't open input file: %s\n"), strerror (errno)); + grub_util_error (_("cannot open `%s': %s"), arguments.input ? : "stdin", + strerror (errno)); - if (outfile_name) - out = fopen (outfile_name, "wb"); + if (arguments.output) + out = fopen (arguments.output, "wb"); else out = stdout; @@ -490,7 +480,8 @@ main (int argc, char *argv[]) { if (in != stdin) fclose (in); - grub_util_error (_("Couldn't open output file: %s\n"), strerror (errno)); + grub_util_error (_("cannot open `%s': %s"), arguments.output ? : "stdout", + strerror (errno)); } write_keymaps (in, out); diff --git a/util/grub-mknetdir.in b/util/grub-mknetdir.in index e5a2172fd..eec170a74 100644 --- a/util/grub-mknetdir.in +++ b/util/grub-mknetdir.in @@ -19,22 +19,24 @@ # Initialize some variables. transform="@program_transform_name@" -prefix=@prefix@ -exec_prefix=@exec_prefix@ -sbindir=@sbindir@ -bindir=@bindir@ -libdir=@libdir@ +prefix="@prefix@" +exec_prefix="@exec_prefix@" +datarootdir="@datarootdir@" +bindir="@bindir@" +libdir="@libdir@" PACKAGE_NAME=@PACKAGE_NAME@ PACKAGE_TARNAME=@PACKAGE_TARNAME@ PACKAGE_VERSION=@PACKAGE_VERSION@ host_os=@host_os@ -localedir=@datadir@/locale -datarootdir=@datarootdir@ pkglib_DATA="moddep.lst command.lst fs.lst partmap.lst parttool.lst handler.lst video.lst crypto.lst terminal.lst" +datadir="@datadir@" +if [ "x$pkgdatadir" = x ]; then + pkgdatadir="${datadir}/`echo @PACKAGE_TARNAME@ | sed "${transform}"`" +fi self=`basename $0` -grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` +grub_mkimage="${bindir}/`echo grub-mkimage | sed ${transform}`" rootdir=/srv/tftp grub_prefix=`echo /boot/grub | sed ${transform}` modules= @@ -45,32 +47,32 @@ recheck=no debug=no debug_image= subdir=`echo /boot/grub | sed ${transform}` -pc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-pc -ppc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/powerpc-ieee1275 -sparc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/sparc64-ieee1275 -i386_ieee1275_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-ieee1275 -efi32_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-efi -efi64_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/x86_64-efi -itanium_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/ia64-efi +pc_dir="${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-pc" +ppc_dir="${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/powerpc-ieee1275" +sparc_dir="${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/sparc64-ieee1275" +i386_ieee1275_dir="${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-ieee1275" +efi32_dir="${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-efi" +efi64_dir="${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/x86_64-efi" +itanium_dir="${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/ia64-efi" + +. "${pkgdatadir}/grub-mkconfig_lib" # Usage: usage # Print the usage. usage () { - cat <. -EOF + gettext_printf "Usage: %s [OPTION] install_device\n" "$self" + gettext; echo "Install GRUB on your drive."; echo + echo + printf " -h, --help %s\n" "$(gettext "print this message and exit")" + printf " -v, --version %s\n" "$(gettext "print the version information and exit")" + printf " --modules=%-14s%s\n" "$(gettext "MODULES")" "$(gettext "pre-load specified modules MODULES")" + printf " --net-directory=%-8s%s\n" "$(gettext "DIR")" "$(gettext "root directory of TFTP server")" + printf " --subdir=%-15s%s\n" "$(gettext "DIR")" "$(gettext "relative subdirectory on network server")" + printf " --grub-mkimage=%-9s%s" "$(gettext "FILE")" "$(gettext "use FILE as grub-mkimage")" + echo + gettext_printf "%s copies GRUB images into net_directory/subdir/target_cpu-platform\n" "$self" + echo + gettext "Report bugs to ."; echo } argument () { @@ -78,7 +80,7 @@ argument () { shift if test $# -eq 0; then - echo "$0: option requires an argument -- '$opt'" 1>&2 + gettext_printf "%s: option requires an argument -- '%s'\n" "$0" "$opt" 1>&2 exit 1 fi echo $1 @@ -140,7 +142,7 @@ do ;; -*) - echo "Unrecognized option \`$option'" 1>&2 + gettext_printf "Unrecognized option \`%s'\n" "$option" 1>&2 usage exit 1 ;; @@ -158,7 +160,7 @@ set $grub_mkimage dummy if test -f "$1"; then : else - echo "$1: Not found." 1>&2 + gettext_printf "%s: Not found.\n" "$1" 1>&2 exit 1 fi @@ -173,12 +175,12 @@ process_input_dir () config_opt= mkdir -p "$grubdir" || exit 1 - for file in ${grubdir}/*.mod ${grubdir}/*.lst ${grubdir}/*.img ${grubdir}/efiemu??.o; do - if test -f $file && [ "`basename $file`" != menu.lst ]; then - rm -f $file || exit 1 + for file in "${grubdir}"/*.mod "${grubdir}"/*.lst "${grubdir}"/*.img "${grubdir}"/efiemu??.o; do + if test -f "$file" && [ "`basename $file`" != menu.lst ]; then + rm -f "$file" || exit 1 fi done - for file in ${input_dir}/*.mod; do + for file in "${input_dir}"/*.mod; do if test -f "$file"; then cp -f "$file" "$grubdir/" fi @@ -203,7 +205,7 @@ process_input_dir () config_opt="-c ${grubdir}/load.cfg " fi - prefix="/${subdir}/${platform}"; + prefix="/${subdir}"; case "${platform}" in i386-pc) mkimage_target=i386-pc-pxe; netmodules="pxe"; @@ -217,7 +219,7 @@ process_input_dir () *-efi) mkimage_target="${platform}"; netmodules="efinet"; ext=efi ;; - *) echo Unsupported platform ${platform}; + *) gettext_printf "Unsupported platform %s\n" ${platform}; exit 1;; esac @@ -225,8 +227,8 @@ process_input_dir () source ${subdir}/grub.cfg EOF - $grub_mkimage ${config_opt} -d "${input_dir}" -O ${mkimage_target} --output=${grubdir}/core.$ext --prefix=$prefix $modules $netmodules tftp || exit 1 - echo "Netboot directory for ${platform} created. Configure your DHCP server to point to ${subdir}/${platform}/core.$ext" + "$grub_mkimage" ${config_opt} -d "${input_dir}" -O ${mkimage_target} "--output=${grubdir}/core.$ext" "--prefix=$prefix" $modules $netmodules tftp || exit 1 + gettext_printf "Netboot directory for %s created. Configure your DHCP server to point to %s\n" "${platform}" "${subdir}/${platform}/core.$ext" } if [ "${override_dir}" = "" ] ; then @@ -252,7 +254,7 @@ if [ "${override_dir}" = "" ] ; then process_input_dir "${itanium_dir}" ia64-efi fi else - source "${override_dir}"/modinfo.sh + . "${override_dir}"/modinfo.sh process_input_dir "${override_dir}" ${grub_modinfo_target_cpu}-${grub_modinfo_platform} fi diff --git a/util/grub-mkpasswd-pbkdf2.c b/util/grub-mkpasswd-pbkdf2.c index 9c676a100..681b76a6d 100644 --- a/util/grub-mkpasswd-pbkdf2.c +++ b/util/grub-mkpasswd-pbkdf2.c @@ -29,38 +29,60 @@ #include #include #include -#include + +#define _GNU_SOURCE 1 + +#include #include "progname.h" -static struct option options[] = - { - {"iteration_count", required_argument, 0, 'c'}, - {"buflen", required_argument, 0, 'l'}, - {"saltlen", required_argument, 0, 's'}, - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'V'}, - }; +static struct argp_option options[] = { + {"iteration-count", 'c', N_("NUM"), 0, N_("Number of PBKDF2 iterations"), 0}, + {"buflen", 'l', N_("NUM"), 0, N_("Length of generated hash"), 0}, + {"salt", 's', N_("NUM"), 0, N_("Length of salt"), 0}, + { 0, 0, 0, 0, 0, 0 } +}; -static void -usage (int status) +struct arguments { - if (status) - fprintf (stderr, _("Try `%s --help' for more information.\n"), - program_name); - else - printf (_("\ -Usage: %s [OPTIONS]\n\ -\nOptions:\n\ - -c number, --iteration-count=number Number of PBKDF2 iterations\n\ - -l number, --buflen=number Length of generated hash\n\ - -s number, --salt=number Length of salt\n\ -\n\ -Report bugs to <%s>.\n"), program_name, PACKAGE_BUGREPORT); + unsigned int count; + unsigned int buflen; + unsigned int saltlen; +}; - exit (status); +static error_t +argp_parser (int key, char *arg, struct argp_state *state) +{ + /* Get the input argument from argp_parse, which we + know is a pointer to our arguments structure. */ + struct arguments *arguments = state->input; + + switch (key) + { + case 'c': + arguments->count = strtoul (arg, NULL, 0); + break; + + case 'l': + arguments->buflen = strtoul (arg, NULL, 0); + break; + + case 's': + arguments->saltlen = strtoul (arg, NULL, 0); + break; + default: + return ARGP_ERR_UNKNOWN; + } + return 0; } +static struct argp argp = { + options, argp_parser, N_("[OPTIONS]"), + N_("Generate PBKDF2 password hash."), + NULL, NULL, NULL +}; + + static void hexify (char *hex, grub_uint8_t *bin, grub_size_t n) { @@ -85,11 +107,14 @@ hexify (char *hex, grub_uint8_t *bin, grub_size_t n) int main (int argc, char *argv[]) { - unsigned int count = 10000, buflen = 64, saltlen = 64; - char *bufhex, *salthex; + struct arguments arguments = { + .count = 10000, + .buflen = 64, + .saltlen = 64 + }; + char *bufhex, *salthex, *result; gcry_err_code_t gcry_err; grub_uint8_t *buf, *salt; - ssize_t nr; char pass1[GRUB_AUTH_MAX_PASSLEN]; char pass2[GRUB_AUTH_MAX_PASSLEN]; @@ -98,67 +123,16 @@ main (int argc, char *argv[]) grub_util_init_nls (); /* Check for options. */ - while (1) + if (argp_parse (&argp, argc, argv, 0, 0, &arguments) != 0) { - int c = getopt_long (argc, argv, "c:l:s:hvV", options, 0); - - if (c == -1) - break; - - switch (c) - { - case 'c': - count = strtoul (optarg, NULL, 0); - break; - - case 'l': - buflen = strtoul (optarg, NULL, 0); - break; - - case 's': - saltlen = strtoul (optarg, NULL, 0); - break; - - case 'h': - usage (0); - return 0; - - case 'V': - printf ("%s (%s) %s\n", program_name, - PACKAGE_NAME, PACKAGE_VERSION); - return 0; - - default: - usage (1); - return 1; - } + fprintf (stderr, "%s", _("Error in parsing command line arguments\n")); + exit(1); } - bufhex = malloc (buflen * 2 + 1); - if (!bufhex) - grub_util_error (_("out of memory")); - buf = malloc (buflen); - if (!buf) - { - free (bufhex); - grub_util_error (_("out of memory")); - } - - salt = malloc (saltlen); - if (!salt) - { - free (bufhex); - free (buf); - grub_util_error (_("out of memory")); - } - salthex = malloc (saltlen * 2 + 1); - if (!salthex) - { - free (salt); - free (bufhex); - free (buf); - grub_util_error (_("out of memory")); - } + bufhex = xmalloc (arguments.buflen * 2 + 1); + buf = xmalloc (arguments.buflen); + salt = xmalloc (arguments.saltlen); + salthex = xmalloc (arguments.saltlen * 2 + 1); printf ("%s", _("Enter password: ")); if (!grub_password_get (pass1, GRUB_AUTH_MAX_PASSLEN)) @@ -167,7 +141,7 @@ main (int argc, char *argv[]) free (bufhex); free (salthex); free (salt); - grub_util_error (_("failure to read password")); + grub_util_error ("%s", _("failure to read password")); } printf ("\n%s", _("Reenter password: ")); if (!grub_password_get (pass2, GRUB_AUTH_MAX_PASSLEN)) @@ -176,7 +150,7 @@ main (int argc, char *argv[]) free (bufhex); free (salthex); free (salt); - grub_util_error (_("failure to read password")); + grub_util_error ("%s", _("failure to read password")); } if (strcmp (pass1, pass2) != 0) @@ -187,7 +161,7 @@ main (int argc, char *argv[]) free (bufhex); free (salthex); free (salt); - grub_util_error (_("passwords don't match")); + grub_util_error ("%s", _("passwords don't match")); } memset (pass2, 0, sizeof (pass2)); @@ -207,10 +181,10 @@ main (int argc, char *argv[]) free (salthex); free (salt); fclose (f); - grub_util_error (_("couldn't retrieve random data for salt")); + grub_util_error ("%s", _("couldn't retrieve random data for salt")); } - rd = fread (salt, 1, saltlen, f); - if (rd != saltlen) + rd = fread (salt, 1, arguments.saltlen, f); + if (rd != arguments.saltlen) { fclose (f); memset (pass1, 0, sizeof (pass1)); @@ -218,41 +192,47 @@ main (int argc, char *argv[]) free (bufhex); free (salthex); free (salt); - grub_util_error (_("couldn't retrieve random data for salt")); + grub_util_error ("%s", _("couldn't retrieve random data for salt")); } fclose (f); } gcry_err = grub_crypto_pbkdf2 (GRUB_MD_SHA512, (grub_uint8_t *) pass1, strlen (pass1), - salt, saltlen, - count, buf, buflen); + salt, arguments.saltlen, + arguments.count, buf, arguments.buflen); memset (pass1, 0, sizeof (pass1)); if (gcry_err) { - memset (buf, 0, buflen); - memset (bufhex, 0, 2 * buflen); + memset (buf, 0, arguments.buflen); + memset (bufhex, 0, 2 * arguments.buflen); free (buf); free (bufhex); - memset (salt, 0, saltlen); - memset (salthex, 0, 2 * saltlen); + memset (salt, 0, arguments.saltlen); + memset (salthex, 0, 2 * arguments.saltlen); free (salt); free (salthex); grub_util_error (_("cryptographic error number %d"), gcry_err); } - hexify (bufhex, buf, buflen); - hexify (salthex, salt, saltlen); + hexify (bufhex, buf, arguments.buflen); + hexify (salthex, salt, arguments.saltlen); - printf (_("Your PBKDF2 is grub.pbkdf2.sha512.%d.%s.%s\n"), - count, salthex, bufhex); - memset (buf, 0, buflen); - memset (bufhex, 0, 2 * buflen); + result = xmalloc (sizeof ("grub.pbkdf2.sha512.XXXXXXXXXXXXXXXXXXX.S.S") + + arguments.buflen * 2 + arguments.saltlen * 2); + snprintf (result, sizeof ("grub.pbkdf2.sha512.XXXXXXXXXXXXXXXXXXX.S.S") + + arguments.buflen * 2 + arguments.saltlen * 2, + "grub.pbkdf2.sha512.%d.%s.%s", + arguments.count, salthex, bufhex); + + printf (_("PBKDF2 hash of your password is %s\n"), result); + memset (buf, 0, arguments.buflen); + memset (bufhex, 0, 2 * arguments.buflen); free (buf); free (bufhex); - memset (salt, 0, saltlen); - memset (salthex, 0, 2 * saltlen); + memset (salt, 0, arguments.saltlen); + memset (salthex, 0, 2 * arguments.saltlen); free (salt); free (salthex); diff --git a/util/grub-mkrelpath.c b/util/grub-mkrelpath.c index 788db38a2..1d5a81039 100644 --- a/util/grub-mkrelpath.c +++ b/util/grub-mkrelpath.c @@ -20,88 +20,81 @@ #include #include +#include #include #include #include -#include + +#define _GNU_SOURCE 1 +#include #include "progname.h" -static struct option options[] = - { - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'V'}, - {0, 0, 0, 0}, - }; - -static void -usage (int status) +struct arguments { - if (status) - fprintf (stderr, _("Try `%s --help' for more information.\n"), program_name); - else - printf (_("\ -Usage: %s [OPTIONS] PATH\n\ -\n\ -Make a system path relative to its root.\n\ -\n\ -Options:\n\ - -h, --help display this message and exit\n\ - -V, --version print version information and exit\n\ -\n\ -Report bugs to <%s>.\n"), program_name, PACKAGE_BUGREPORT); + char *pathname; +}; - exit (status); +static struct argp_option options[] = { + { 0, 0, 0, 0, 0, 0 } +}; + +static error_t +argp_parser (int key, char *arg, struct argp_state *state) +{ + /* Get the input argument from argp_parse, which we + know is a pointer to our arguments structure. */ + struct arguments *arguments = state->input; + + switch (key) + { + case ARGP_KEY_ARG: + if (state->arg_num == 0) + arguments->pathname = xstrdup (arg); + else + { + /* Too many arguments. */ + fprintf (stderr, _("Unknown extra argument `%s'.\n"), arg); + argp_usage (state); + } + break; + case ARGP_KEY_NO_ARGS: + fprintf (stderr, "%s", _("No path is specified.\n")); + argp_usage (state); + exit (1); + break; + default: + return ARGP_ERR_UNKNOWN; + } + return 0; } +static struct argp argp = { + options, argp_parser, N_("PATH"), + N_("Transform a sytem filename into GRUB one."), + NULL, NULL, NULL +}; + int main (int argc, char *argv[]) { - char *argument, *relpath; + char *relpath; + struct arguments arguments; set_program_name (argv[0]); grub_util_init_nls (); + memset (&arguments, 0, sizeof (struct arguments)); + /* Check for options. */ - while (1) + if (argp_parse (&argp, argc, argv, 0, 0, &arguments) != 0) { - int c = getopt_long (argc, argv, "hV", options, 0); - - if (c == -1) - break; - else - switch (c) - { - case 'h': - usage (0); - break; - - case 'V': - printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); - return 0; - - default: - usage (1); - break; - } + fprintf (stderr, "%s", _("Error in parsing command line arguments\n")); + exit(1); } - if (optind >= argc) - { - fprintf (stderr, _("No path is specified.\n")); - usage (1); - } - - if (optind + 1 != argc) - { - fprintf (stderr, _("Unknown extra argument `%s'.\n"), argv[optind + 1]); - usage (1); - } - - argument = argv[optind]; - - relpath = grub_make_system_path_relative_to_its_root (argument); + relpath = grub_make_system_path_relative_to_its_root (arguments.pathname); printf ("%s\n", relpath); free (relpath); diff --git a/util/grub-mkrescue.in b/util/grub-mkrescue.in index eff77088f..cd57d41a0 100644 --- a/util/grub-mkrescue.in +++ b/util/grub-mkrescue.in @@ -18,15 +18,21 @@ set -e # along with GRUB. If not, see . # Initialize some variables. + transform="@program_transform_name@" -prefix=@prefix@ -exec_prefix=@exec_prefix@ -bindir=@bindir@ -libdir=@libdir@ +prefix="@prefix@" +exec_prefix="@exec_prefix@" +datarootdir="@datarootdir@" +bindir="@bindir@" +libdir="@libdir@" PACKAGE_NAME=@PACKAGE_NAME@ PACKAGE_TARNAME=@PACKAGE_TARNAME@ PACKAGE_VERSION=@PACKAGE_VERSION@ +datadir="@datadir@" +if [ "x$pkgdatadir" = x ]; then + pkgdatadir="${datadir}/`echo @PACKAGE_TARNAME@ | sed "${transform}"`" +fi pkglib_DATA="moddep.lst command.lst fs.lst partmap.lst parttool.lst handler.lst video.lst crypto.lst terminal.lst" self=`basename $0` @@ -43,29 +49,28 @@ grub_mkimage="${bindir}/`echo grub-mkimage | sed ${transform}`" xorriso=xorriso +. "${pkgdatadir}/grub-mkconfig_lib" + # Usage: usage # Print the usage. usage () { - cat <. -Mail xorriso support requests to . -EOF + gettext_printf "Usage: %s [OPTION] SOURCE...\n" "$self" + gettext "Make GRUB CDROM, disk, pendrive and floppy bootable image."; echo + echo + printf " -h, --help %s\n" "$(gettext "print this message and exit")" + printf " -v, --version %s\n" "$(gettext "print the version information and exit")" + printf " -o, --output=%-11s%s\n" "$(gettext FILE)" "$(gettext "save output in FILE [required]")" + printf " --modules=%-14s%s\n" "$(gettext "MODULES")" "$(gettext "pre-load specified modules MODULES")" + printf " --rom-directory=%-8s%s\n" "$(gettext "DIR")" "$(gettext "save rom images in DIR [optional]")" + printf " --xorriso=%-14s%s\n" "$(gettext "FILE")" "$(gettext "use FILE as xorriso [optional]")" + printf " --grub-mkimage=%-9s%s\n" "$(gettext "FILE")" "$(gettext "use FILE as grub-mkimage")" + 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" + echo + gettext "Option -- switches to native xorriso command mode."; echo + echo + gettext "Report bugs to ."; echo + gettext "Mail xorriso support requests to ."; echo } argument () { @@ -73,7 +78,7 @@ argument () { shift if test $# -eq 0; then - echo "$0: option requires an argument -- '$opt'" 1>&2 + gettext_printf "%s: option requires an argument -- '%s'\n" "$0" "$opt" 1>&2 exit 1 fi echo $1 @@ -137,7 +142,8 @@ do done if [ "x${output_image}" = x ] ; then - echo "output file must be given" >&2 + gettext "output file must be specified" >&2 + echo >&2 usage exit 1 fi @@ -146,7 +152,7 @@ set $grub_mkimage dummy if test -f "$1"; then : else - echo "$1: Not found." 1>&2 + gettext_printf "%s: Not found.\n" "$1" 1>&2 exit 1 fi @@ -157,20 +163,20 @@ process_input_dir () { input_dir="$1" platform="$2" - mkdir -p ${iso9660_dir}/boot/grub/${platform} + mkdir -p "${iso9660_dir}/boot/grub/${platform}" for file in "${input_dir}/"*.mod "${input_dir}/"efiemu32.o "${input_dir}/"efiemu64.o; do if test -f "$file"; then - cp -f "$file" ${iso9660_dir}/boot/grub/${platform}/ + cp -f "$file" "${iso9660_dir}/boot/grub/${platform}/" fi done for file in ${pkglib_DATA}; do if test -f "${input_dir}/${file}"; then - cp -f "${input_dir}/${file}" ${iso9660_dir}/boot/grub/${platform}/ + cp -f "${input_dir}/${file}" "${iso9660_dir}/boot/grub/${platform}/" fi done - mkdir -p ${iso9660_dir}/boot/grub/locale - for file in ${input_dir}/po/*.mo; do + mkdir -p "${iso9660_dir}/boot/grub/locale" + for file in "${input_dir}"/po/*.mo; do if test -f "$file"; then cp -f "$file" ${iso9660_dir}/boot/grub/locale/ fi @@ -185,28 +191,27 @@ make_image () return; fi - echo "Enabling $2 support ..." + gettext_printf "Enabling %s support ...\n" "$2" - memdisk_img=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 - memdisk_dir=`mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 - mkdir -p ${memdisk_dir}/boot/grub + memdisk_img="`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"`" || exit 1 + memdisk_dir="`mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"`" || exit 1 + mkdir -p "${memdisk_dir}/boot/grub" - cat << EOF > ${memdisk_dir}/boot/grub/grub.cfg + (cat << EOF search --fs-uuid --set=root ${iso_uuid} -set prefix=(\${root})/boot/grub/${platform} -source \$prefix/grub.cfg +set prefix=(\${root})/boot/grub EOF - (for i in $(cat ${source_directory}/partmap.lst) ${modules} ; do + for i in $(cat "${source_directory}/partmap.lst") ${modules} ; do echo "insmod $i" done ; \ - echo "source /boot/grub/grub.cfg") \ - > ${iso9660_dir}/boot/grub/${platform}/grub.cfg + echo "source \$prefix/grub.cfg") \ + > "${memdisk_dir}/boot/grub/grub.cfg" (cd "${memdisk_dir}"; tar -cf - boot) > "${memdisk_img}" - rm -rf ${memdisk_dir} - $grub_mkimage -O ${platform} -d "${source_directory}" -m "${memdisk_img}" -o "$3" --prefix='(memdisk)/boot/grub' \ + rm -rf "${memdisk_dir}" + "$grub_mkimage" -O ${platform} -d "${source_directory}" -m "${memdisk_img}" -o "$3" --prefix='(memdisk)/boot/grub' \ search iso9660 configfile normal memdisk tar $4 - rm -rf ${memdisk_img} + rm -rf "${memdisk_img}" } if [ "${override_dir}" = "" ] ; then @@ -253,22 +258,22 @@ grub_mkisofs_arguments="${grub_mkisofs_arguments} --modification-date=$(echo ${i # build BIOS core.img if test -e "${pc_dir}" ; then - echo "Enabling BIOS support ..." - core_img=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 - $grub_mkimage -O i386-pc -d ${pc_dir}/ -o ${core_img} --prefix=/boot/grub/i386-pc \ - iso9660 biosdisk - cat ${pc_dir}/cdboot.img ${core_img} > ${iso9660_dir}/boot/grub/i386-pc/eltorito.img + gettext_printf "Enabling %s support ...\n" "BIOS" + load_cfg="`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"`" + core_img="`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"`" || exit 1 - embed_img=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 - cat ${pc_dir}/boot.img ${core_img} > ${embed_img} - - rm -f ${core_img} - - (for i in $(cat ${pc_dir}/partmap.lst) ${modules} ; do + (for i in $(cat "${pc_dir}/partmap.lst") ${modules} ; do echo "insmod $i" - done ; \ - echo "source /boot/grub/grub.cfg") \ - > ${iso9660_dir}/boot/grub/i386-pc/grub.cfg + done ;) > "${load_cfg}" + + "$grub_mkimage" -O i386-pc -d "${pc_dir}/" -o "${core_img}" -c "$load_cfg" --prefix=/boot/grub \ + iso9660 biosdisk + cat "${pc_dir}/cdboot.img" "${core_img}" > "${iso9660_dir}/boot/grub/i386-pc/eltorito.img" + + embed_img="`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"`" || exit 1 + cat "${pc_dir}/boot.img" "${core_img}" > "${embed_img}" + + rm -f "${core_img}" grub_mkisofs_arguments="${grub_mkisofs_arguments} -b boot/grub/i386-pc/eltorito.img -no-emul-boot -boot-info-table \ --embedded-boot ${embed_img}" @@ -306,9 +311,9 @@ if [ -e "${iso9660_dir}/boot/coreboot.elf" ] && [ -d "${rom_directory}" ]; then fi # build iso image -"${xorriso}" -as mkisofs -graft-points ${grub_mkisofs_arguments} --protective-msdos-label -o ${output_image} -r ${iso9660_dir} --sort-weight 0 / --sort-weight 1 /boot ${source} -rm -rf ${iso9660_dir} +"${xorriso}" -as mkisofs -graft-points ${grub_mkisofs_arguments} --protective-msdos-label -o "${output_image}" -r "${iso9660_dir}" --sort-weight 0 / --sort-weight 1 /boot ${source} +rm -rf "${iso9660_dir}" -rm -f ${embed_img} +rm -f "${embed_img}" exit 0 diff --git a/util/grub-mkstandalone.in b/util/grub-mkstandalone.in index e140ecc82..235147797 100644 --- a/util/grub-mkstandalone.in +++ b/util/grub-mkstandalone.in @@ -2,7 +2,7 @@ set -e # Make GRUB rescue image -# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc. +# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010,2011,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 @@ -18,46 +18,56 @@ set -e # along with GRUB. If not, see . # Initialize some variables. + transform="@program_transform_name@" -prefix=@prefix@ -exec_prefix=@exec_prefix@ -bindir=@bindir@ -libdir=@libdir@ +prefix="@prefix@" +exec_prefix="@exec_prefix@" +datarootdir="@datarootdir@" +bindir="@bindir@" +libdir="@libdir@" PACKAGE_NAME=@PACKAGE_NAME@ PACKAGE_TARNAME=@PACKAGE_TARNAME@ PACKAGE_VERSION=@PACKAGE_VERSION@ pkglib_DATA="moddep.lst command.lst fs.lst partmap.lst parttool.lst handler.lst video.lst crypto.lst terminal.lst" +datadir="@datadir@" +if [ "x$pkgdatadir" = x ]; then + pkgdatadir="${datadir}/`echo @PACKAGE_TARNAME@ | sed "${transform}"`" +fi self=`basename $0` -source_dirrectory= +source_directory= compression=auto format= -grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` +grub_mkimage="${bindir}/`echo grub-mkimage | sed ${transform}`" source= +. "${pkgdatadir}/grub-mkconfig_lib" + # Usage: usage # Print the usage. usage () { - cat <. -EOF + formats="i386-coreboot i386-multiboot i386-pc i386-pc-pxe i386-efi i386-ieee1275 i386-qemu x86_64-efi mipsel-yeeloong-flash mipsel-fuloong2f-flash mipsel-loongson-elf powerpc-ieee1275 sparc64-ieee1275-raw sparc64-ieee1275-aout ia64-efi mips-arc mipsel-qemu_mips-elf mips-qemu_mips-flash mipsel-qemu_mips-flash mips-qemu_mips-elf" + gettext_printf "Usage: %s [OPTION] SOURCE...\n" "$self" + gettext "Generate a standalone image (containing all modules) in the selected format" + echo + gettext "Make GRUB rescue image."; echo + echo + printf " -h, --help %s\n" "$(gettext "print this message and exit")" + printf " -v, --version %s\n" "$(gettext "print the version information and exit")" + printf " -o, --output=%-11s%s\n" "$(gettext FILE)" "$(gettext "save output in FILE [required]")" + dir_msg="$(gettext_printf "use images and modules under DIR [default=%s/]" "${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})")" + printf " -d, --directory=%-8s%s\n" \ + "DIR" "$dir_msg" + printf " -O, --format=%-11s%s" "$(gettext "FORMAT")" "$(gettext "generate an image in format")"; echo + printf " %s %s\n" "$(gettext "available formats:")" "$formats" + echo + printf " -C, --compression=(xz|none|auto) %s\n" "$(gettext "choose the compression to use")" + printf " --modules=%-14s%s\n" "$(gettext "MODULES")" "$(gettext "pre-load specified modules MODULES")" + printf " --grub-mkimage=%-9s%s\n" "$(gettext "FILE")" "$(gettext "use FILE as grub-mkimage")" + echo + gettext "Report bugs to ."; echo } argument () { @@ -65,7 +75,7 @@ argument () { shift if test $# -eq 0; then - echo "$0: option requires an argument -- '$opt'" 1>&2 + gettext_printf "%s: option requires an argument -- '%s'\n" "$0" "$opt" 1>&2 exit 1 fi echo $1 @@ -86,7 +96,7 @@ do exit 0 ;; --modules) - modules=`argument $option "$@"`; shift ;; + modules=`argument $option "$@"`; shift ;; --modules=*) modules=`echo "$option" | sed 's/--modules=//'` ;; @@ -96,9 +106,9 @@ do output_image=`echo "$option" | sed 's/--output=//'` ;; --directory | -d) - source_directory=`argument $option "$@"`; shift ;; + source_directory=`argument $option "$@"`; shift ;; --directory=*) - source_directory=`echo "$option" | sed 's/--rom-directory=//'` ;; + source_directory=`echo "$option" | sed 's/--directory=//'` ;; --grub-mkimage) grub_mkimage=`argument $option "$@"`; shift ;; @@ -108,12 +118,12 @@ do --compression | -C) compression=`argument $option "$@"`; shift ;; --compression=*) - compression=`echo "${option}/" | sed 's/--xorriso=//'` ;; + compression=`echo "${option}" | sed 's/--compression=//'` ;; --format | -O) format=`argument $option "$@"`; shift ;; --format=*) - format=`echo "${option}/" | sed 's/--xorriso=//'` ;; + format=`echo "${option}" | sed 's/--format=//'` ;; *) source="${source} ${option} $@"; break ;; @@ -121,14 +131,15 @@ do done if [ "x${output_image}" = x ] ; then - echo "output file must be given" >&2 + gettext "output file must be specified" >&2 + echo >&2 usage exit 1 fi if [ "x${format}" = x ] ; then - echo "format must be given" >&2 - usage + gettext "Target format not specified (use the -O option)." >&2 + echo >&2 exit 1 fi @@ -146,6 +157,8 @@ if [ "x$source_directory" = x ] ; then source_directory="${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/$cpu-$platform" fi +. "${source_directory}"/modinfo.sh + set $grub_mkimage dummy if test -f "$1"; then : @@ -155,16 +168,17 @@ else fi memdisk_dir="`mktemp -d "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"`" || exit 1 -mkdir -p "${memdisk_dir}"/boot/grub +mkdir -p "${memdisk_dir}"/boot/grub/"${grub_modinfo_target_cpu}-${grub_modinfo_platform}" for file in "${source_directory}/"*.mod "${source_directory}/"efiemu32.o "${source_directory}/"efiemu64.o; do if test -f "$file"; then - cp -f "$file" "${memdisk_dir}"/boot/grub/ + cp -f "$file" "${memdisk_dir}"/boot/grub/"${grub_modinfo_target_cpu}-${grub_modinfo_platform}" fi done + for file in ${pkglib_DATA}; do if test -f "${source_directory}/${file}"; then - cp -f "${source_directory}/${file}" "${memdisk_dir}"/boot/grub/ + cp -f "${source_directory}/${file}" "${memdisk_dir}"/boot/grub/"${grub_modinfo_target_cpu}-${grub_modinfo_platform}" fi done @@ -183,7 +197,7 @@ memdisk_img=`mktemp "${TMPDIR:-/tmp}/tmp.XXXXXXXXXX"` || exit 1 (cd "${memdisk_dir}"; tar -cf - * $source) > "${memdisk_img}" rm -rf "${memdisk_dir}" -$grub_mkimage -O "${format}" -C "$compression" -d "${source_directory}" -m "${memdisk_img}" -o "$output_image" --prefix='(memdisk)/boot/grub' memdisk tar $modules +"$grub_mkimage" -O "${format}" -C "$compression" -d "${source_directory}" -m "${memdisk_img}" -o "$output_image" --prefix='(memdisk)/boot/grub' memdisk tar $modules rm -rf "${memdisk_img}" exit 0 diff --git a/util/grub-mount.c b/util/grub-mount.c index da7d604a2..9093e264c 100644 --- a/util/grub-mount.c +++ b/util/grub-mount.c @@ -44,7 +44,7 @@ #include "progname.h" #include "argp.h" -static char *root = NULL; +static const char *root = NULL; grub_device_t dev = NULL; grub_fs_t fs = NULL; static char **images = NULL; @@ -55,13 +55,13 @@ static int num_disks = 0; static int mount_crypt = 0; static grub_err_t -execute_command (char *name, int n, char **args) +execute_command (const char *name, int n, char **args) { grub_command_t cmd; cmd = grub_command_find (name); if (! cmd) - grub_util_error (_("can\'t find command %s"), name); + grub_util_error (_("can't find command `%s'"), name); return (cmd->func) (cmd, n, args); } @@ -338,17 +338,17 @@ fuse_init (void) char *loop_name; loop_name = grub_xasprintf ("loop%d", i); if (!loop_name) - grub_util_error (grub_errmsg); + grub_util_error ("%s", grub_errmsg); host_file = grub_xasprintf ("(host)%s", images[i]); if (!host_file) - grub_util_error (grub_errmsg); + grub_util_error ("%s", grub_errmsg); argv[0] = loop_name; argv[1] = host_file; if (execute_command ("loopback", 2, argv)) - grub_util_error (_("loopback command fails")); + grub_util_error ("%s", _("loopback command fails")); grub_free (loop_name); grub_free (host_file); @@ -356,16 +356,17 @@ fuse_init (void) if (mount_crypt) { - char *argv[2] = { "-a", NULL}; + char *argv[2] = { xstrdup ("-a"), NULL}; if (execute_command ("cryptomount", 1, argv)) grub_util_error (_("cryptomount command fails: %s"), grub_errmsg); + free (argv[0]); } grub_lvm_fini (); grub_mdraid09_fini (); grub_mdraid1x_fini (); - grub_raid_fini (); - grub_raid_init (); + grub_diskfilter_fini (); + grub_diskfilter_init (); grub_mdraid09_init (); grub_mdraid1x_init (); grub_lvm_init (); @@ -390,13 +391,14 @@ fuse_init (void) loop_name = grub_xasprintf ("loop%d", i); if (!loop_name) - grub_util_error (grub_errmsg); + grub_util_error ("%s", grub_errmsg); - argv[0] = "-d"; + argv[0] = xstrdup ("-d"); argv[1] = loop_name; execute_command ("loopback", 2, argv); + grub_free (argv[0]); grub_free (loop_name); } @@ -407,8 +409,10 @@ static struct argp_option options[] = { {"root", 'r', N_("DEVICE_NAME"), 0, N_("Set root device."), 2}, {"debug", 'd', "S", 0, N_("Set debug environment variable."), 2}, {"crypto", 'C', NULL, OPTION_ARG_OPTIONAL, N_("Mount crypto devices."), 2}, - {"zfs-key", 'K', N_("FILE|prompt"), 0, N_("Load zfs crypto key."), 2}, - {"verbose", 'v', NULL, OPTION_ARG_OPTIONAL, N_("Print verbose messages."), 2}, + {"zfs-key", 'K', + /* TRANSLATORS: "prompt" is a keyword. */ + N_("FILE|prompt"), 0, N_("Load zfs crypto key."), 2}, + {"verbose", 'v', NULL, OPTION_ARG_OPTIONAL, N_("print verbose messages."), 2}, {0, 0, 0, 0, 0, 0} }; @@ -420,11 +424,9 @@ print_version (FILE *stream, struct argp_state *state) } void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version; -error_t +static error_t argp_parser (int key, char *arg, struct argp_state *state) { - char *p; - switch (key) { case 'r': @@ -449,13 +451,18 @@ argp_parser (int key, char *arg, struct argp_state *state) f = fopen (arg, "rb"); if (!f) { - printf (_("Error loading file %s: %s\n"), arg, strerror (errno)); + printf (_("%s: error:"), program_name); + printf (_("cannot open `%s': %s"), arg, strerror (errno)); + printf ("\n"); return 0; } real_size = fread (buf, 1, 1024, f); if (real_size < 0) { - printf (_("Error loading file %s: %s\n"), arg, strerror (errno)); + printf (_("%s: error:"), program_name); + printf (_("cannot read `%s': %s"), arg, + strerror (errno)); + printf ("\n"); fclose (f); return 0; } @@ -505,7 +512,8 @@ struct argp argp = { int main (int argc, char *argv[]) { - char *default_root, *alloc_root; + const char *default_root; + char *alloc_root; set_program_name (argv[0]); @@ -521,7 +529,7 @@ main (int argc, char *argv[]) argp_parse (&argp, argc, argv, 0, 0, 0); if (num_disks < 2) - grub_util_error (_("need an image and mountpoint")); + grub_util_error ("%s", _("need an image and mountpoint")); fuse_args = xrealloc (fuse_args, (fuse_argc + 2) * sizeof (fuse_args[0])); fuse_args[fuse_argc] = images[num_disks - 1]; fuse_argc++; diff --git a/util/grub-pe2elf.c b/util/grub-pe2elf.c index 51d41c9f0..d63e8d78e 100644 --- a/util/grub-pe2elf.c +++ b/util/grub-pe2elf.c @@ -86,6 +86,8 @@ Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT); #define STRTAB_SECTION 9 #define REL_SECTION 10 + +/* 10 normal section + up to 4 relocation (.text, .rdata, .data, .symtab). */ #define MAX_SECTIONS 16 #define STRTAB_BLOCK 256 @@ -93,10 +95,10 @@ Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT); static char *strtab; static int strtab_max, strtab_len; -Elf32_Ehdr ehdr; -Elf32_Shdr shdr[MAX_SECTIONS]; -int num_sections; -grub_uint32_t offset; +static Elf32_Ehdr ehdr; +static Elf32_Shdr shdr[MAX_SECTIONS]; +static int num_sections; +static grub_uint32_t offset; static int insert_string (const char *name) @@ -121,7 +123,7 @@ insert_string (const char *name) } static int * -write_section_data (FILE* fp, char *image, +write_section_data (FILE* fp, const char *name, char *image, struct grub_pe32_coff_header *pe_chdr, struct grub_pe32_section_table *pe_shdr) { @@ -190,7 +192,8 @@ write_section_data (FILE* fp, char *image, { shdr[idx].sh_offset = offset; grub_util_write_image_at (image + pe_shdr->raw_data_offset, - pe_shdr->raw_data_size, offset, fp); + pe_shdr->raw_data_size, offset, fp, + name); offset += pe_shdr->raw_data_size; } @@ -220,7 +223,7 @@ write_section_data (FILE* fp, char *image, } static void -write_reloc_section (FILE* fp, char *image, +write_reloc_section (FILE* fp, const char *name, char *image, struct grub_pe32_coff_header *pe_chdr, struct grub_pe32_section_table *pe_shdr, Elf32_Sym *symtab, @@ -294,7 +297,7 @@ write_reloc_section (FILE* fp, char *image, grub_util_write_image_at (image + pe_sec->raw_data_offset, shdr[shdr[i].sh_info].sh_size, shdr[shdr[i].sh_info].sh_offset, - fp); + fp, name); shdr[i].sh_type = SHT_REL; shdr[i].sh_offset = offset; @@ -303,14 +306,14 @@ write_reloc_section (FILE* fp, char *image, shdr[i].sh_entsize = sizeof (Elf32_Rel); shdr[i].sh_size = num_rels * sizeof (Elf32_Rel); - grub_util_write_image_at (rel, shdr[i].sh_size, offset, fp); + grub_util_write_image_at (rel, shdr[i].sh_size, offset, fp, name); offset += shdr[i].sh_size; free (rel); } } static void -write_symbol_table (FILE* fp, char *image, +write_symbol_table (FILE* fp, const char *name, char *image, struct grub_pe32_coff_header *pe_chdr, struct grub_pe32_section_table *pe_shdr, int *section_map) @@ -401,7 +404,7 @@ write_symbol_table (FILE* fp, char *image, shdr[SYMTAB_SECTION].sh_addralign = 4; grub_util_write_image_at (symtab, shdr[SYMTAB_SECTION].sh_size, - offset, fp); + offset, fp, name); offset += shdr[SYMTAB_SECTION].sh_size; free (symtab); @@ -409,21 +412,22 @@ write_symbol_table (FILE* fp, char *image, } static void -write_string_table (FILE* fp) +write_string_table (FILE *fp, const char *name) { shdr[STRTAB_SECTION].sh_name = insert_string (".strtab"); shdr[STRTAB_SECTION].sh_type = SHT_STRTAB; shdr[STRTAB_SECTION].sh_offset = offset; shdr[STRTAB_SECTION].sh_size = strtab_len; shdr[STRTAB_SECTION].sh_addralign = 1; - grub_util_write_image_at (strtab, strtab_len, offset, fp); + grub_util_write_image_at (strtab, strtab_len, offset, fp, + name); offset += strtab_len; free (strtab); } static void -write_section_header (FILE* fp) +write_section_header (FILE *fp, const char *name) { ehdr.e_ident[EI_MAG0] = ELFMAG0; ehdr.e_ident[EI_MAG1] = ELFMAG1; @@ -444,13 +448,13 @@ write_section_header (FILE* fp) ehdr.e_shoff = offset; ehdr.e_shnum = num_sections; grub_util_write_image_at (&shdr, sizeof (Elf32_Shdr) * num_sections, - offset, fp); + offset, fp, name); - grub_util_write_image_at (&ehdr, sizeof (Elf32_Ehdr), 0, fp); + grub_util_write_image_at (&ehdr, sizeof (Elf32_Ehdr), 0, fp, name); } static void -convert_pe (FILE* fp, char *image) +convert_pe (FILE* fp, const char *name, char *image) { struct grub_pe32_coff_header *pe_chdr; struct grub_pe32_section_table *pe_shdr; @@ -469,14 +473,14 @@ convert_pe (FILE* fp, char *image) pe_shdr = (struct grub_pe32_section_table *) (pe_chdr + 1); num_sections = REL_SECTION; - section_map = write_section_data (fp, image, pe_chdr, pe_shdr); + section_map = write_section_data (fp, name, image, pe_chdr, pe_shdr); - write_symbol_table (fp, image, pe_chdr, pe_shdr, section_map); + write_symbol_table (fp, name, image, pe_chdr, pe_shdr, section_map); free (section_map); - write_string_table (fp); + write_string_table (fp, name); - write_section_header (fp); + write_section_header (fp, name); } int @@ -531,7 +535,7 @@ main (int argc, char *argv[]) if (! fp) grub_util_error ("cannot open %s", argv[optind]); - convert_pe (fp, image); + convert_pe (fp, argv[optind], image); fclose (fp); diff --git a/util/grub-probe.c b/util/grub-probe.c index 795a9344e..4db2b357e 100644 --- a/util/grub-probe.c +++ b/util/grub-probe.c @@ -31,8 +31,10 @@ #include #include #include -#include +#include #include +#include +#include #include #include @@ -41,9 +43,10 @@ #include #include #include +#include #define _GNU_SOURCE 1 -#include +#include #include "progname.h" @@ -55,10 +58,19 @@ enum { PRINT_DEVICE, PRINT_PARTMAP, PRINT_ABSTRACTION, - PRINT_CRYPTODISK_UUID + PRINT_CRYPTODISK_UUID, + PRINT_HINT_STR, + PRINT_BIOS_HINT, + PRINT_IEEE1275_HINT, + PRINT_BAREMETAL_HINT, + PRINT_EFI_HINT, + PRINT_ARC_HINT, + PRINT_COMPATIBILITY_HINT, + PRINT_MSDOS_PARTTYPE, + PRINT_DISK }; -int print = PRINT_FS; +static int print = PRINT_FS; static unsigned int argument_is_device = 0; static void @@ -75,6 +87,9 @@ probe_partmap (grub_disk_t disk) for (part = disk->partition; part; part = part->parent) printf ("%s ", part->partmap->name); + if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID) + grub_diskfilter_print_partmap (disk); + /* In case of LVM/RAID, check the member devices as well. */ if (disk->dev->memberlist) { @@ -118,12 +133,149 @@ probe_raid_level (grub_disk_t disk) if (!disk) return -1; - if (disk->dev->id != GRUB_DISK_DEVICE_RAID_ID) + if (disk->dev->id != GRUB_DISK_DEVICE_DISKFILTER_ID) return -1; - return ((struct grub_raid_array *) disk->data)->level; + if (disk->name[0] != 'm' || disk->name[1] != 'd') + return -1; + + if (!((struct grub_diskfilter_lv *) disk->data)->segments) + return -1; + return ((struct grub_diskfilter_lv *) disk->data)->segments->type; } +/* Since OF path names can have "," characters in them, and GRUB + internally uses "," to indicate partitions (unlike OF which uses + ":" for this purpose) we escape such commas. */ +static char * +escape_of_path (const char *orig_path) +{ + char *new_path, *d, c; + const char *p; + + if (!strchr (orig_path, ',')) + return (char *) xstrdup (orig_path); + + new_path = xmalloc (strlen (orig_path) * 2 + sizeof ("ieee1275/")); + + p = orig_path; + grub_strcpy (new_path, "ieee1275/"); + d = new_path + sizeof ("ieee1275/") - 1; + while ((c = *p++) != '\0') + { + if (c == ',') + *d++ = '\\'; + *d++ = c; + } + *d = 0; + + free ((char *) orig_path); + + return new_path; +} + +static char * +guess_bios_drive (const char *orig_path) +{ + char *canon; + char *ptr; + canon = canonicalize_file_name (orig_path); + if (!canon) + return NULL; + ptr = strrchr (orig_path, '/'); + if (ptr) + ptr++; + else + ptr = canon; + if ((ptr[0] == 's' || ptr[0] == 'h') && ptr[1] == 'd') + { + int num = ptr[2] - 'a'; + free (canon); + return xasprintf ("hd%d", num); + } + if (ptr[0] == 'f' && ptr[1] == 'd') + { + int num = atoi (ptr + 2); + free (canon); + return xasprintf ("fd%d", num); + } + free (canon); + return NULL; +} + +static char * +guess_efi_drive (const char *orig_path) +{ + char *canon; + char *ptr; + canon = canonicalize_file_name (orig_path); + if (!canon) + return NULL; + ptr = strrchr (orig_path, '/'); + if (ptr) + ptr++; + else + ptr = canon; + if ((ptr[0] == 's' || ptr[0] == 'h') && ptr[1] == 'd') + { + int num = ptr[2] - 'a'; + free (canon); + return xasprintf ("hd%d", num); + } + if (ptr[0] == 'f' && ptr[1] == 'd') + { + int num = atoi (ptr + 2); + free (canon); + return xasprintf ("fd%d", num); + } + free (canon); + return NULL; +} + +static char * +guess_baremetal_drive (const char *orig_path) +{ + char *canon; + char *ptr; + canon = canonicalize_file_name (orig_path); + if (!canon) + return NULL; + ptr = strrchr (orig_path, '/'); + if (ptr) + ptr++; + else + ptr = canon; + if (ptr[0] == 'h' && ptr[1] == 'd') + { + int num = ptr[2] - 'a'; + free (canon); + return xasprintf ("ata%d", num); + } + if (ptr[0] == 's' && ptr[1] == 'd') + { + int num = ptr[2] - 'a'; + free (canon); + return xasprintf ("ahci%d", num); + } + free (canon); + return NULL; +} + +static void +print_full_name (const char *drive, grub_device_t dev) +{ + char *dname = escape_of_path (drive); + if (dev->disk->partition) + { + char *pname = grub_partition_get_name (dev->disk->partition); + printf ("%s,%s", dname, pname); + free (pname); + } + else + printf ("%s", dname); + free (dname); +} + static void probe_abstraction (grub_disk_t disk) { @@ -141,16 +293,21 @@ probe_abstraction (grub_disk_t disk) list = tmp; } - if (disk->dev->id == GRUB_DISK_DEVICE_LVM_ID) + if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID + && grub_memcmp (disk->name, "lvm/", sizeof ("lvm/") - 1) == 0) printf ("lvm "); + if (disk->dev->id == GRUB_DISK_DEVICE_DISKFILTER_ID + && grub_memcmp (disk->name, "ldm/", sizeof ("ldm/") - 1) == 0) + printf ("ldm "); + if (disk->dev->id == GRUB_DISK_DEVICE_CRYPTODISK_ID) grub_util_cryptodisk_print_abstraction (disk); raid_level = probe_raid_level (disk); if (raid_level >= 0) { - printf ("raid "); + printf ("diskfilter "); if (disk->dev->raidname) printf ("%s ", disk->dev->raidname (disk)); } @@ -161,245 +318,534 @@ probe_abstraction (grub_disk_t disk) } static void -probe (const char *path, char *device_name) +probe (const char *path, char **device_names, char delim) { - char *drive_name = NULL; + char **drives_names = NULL; + char **curdev, **curdrive; char *grub_path = NULL; - char *filebuf_via_grub = NULL, *filebuf_via_sys = NULL; - grub_device_t dev = NULL; - grub_fs_t fs; + int ndev = 0; - if (path == NULL) - { -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__sun__) - if (! grub_util_check_char_device (device_name)) - grub_util_error (_("%s is not a character device"), device_name); -#else - if (! grub_util_check_block_device (device_name)) - grub_util_error (_("%s is not a block device"), device_name); -#endif - } - else + if (path != NULL) { grub_path = canonicalize_file_name (path); - device_name = grub_guess_root_device (grub_path); + if (! grub_path) + grub_util_error (_("failed to get canonical path of %s"), path); + device_names = grub_guess_root_devices (grub_path); + free (grub_path); } - if (! device_name) + if (! device_names) grub_util_error (_("cannot find a device for %s (is /dev mounted?)"), path); if (print == PRINT_DEVICE) { - printf ("%s\n", device_name); - goto end; + for (curdev = device_names; *curdev; curdev++) + { + printf ("%s", *curdev); + putchar (delim); + } + return; } - drive_name = grub_util_get_grub_dev (device_name); - if (! drive_name) - grub_util_error (_("cannot find a GRUB drive for %s. Check your device.map"), - device_name); + if (print == PRINT_DISK) + { + for (curdev = device_names; *curdev; curdev++) + { + char *disk; + disk = grub_util_get_os_disk (*curdev); + if (!disk) + { + grub_print_error (); + continue; + } + printf ("%s", disk); + putchar (delim); + } + return; + } + + for (curdev = device_names; *curdev; curdev++) + { + grub_util_pull_device (*curdev); + ndev++; + } + + drives_names = xmalloc (sizeof (drives_names[0]) * (ndev + 1)); + + for (curdev = device_names, curdrive = drives_names; *curdev; curdev++, + curdrive++) + { + *curdrive = grub_util_get_grub_dev (*curdev); + if (! *curdrive) + grub_util_error (_("cannot find a GRUB drive for %s. Check your device.map"), + *curdev); + } + *curdrive = 0; if (print == PRINT_DRIVE) { - printf ("(%s)\n", drive_name); + for (curdrive = drives_names; *curdrive; curdrive++) + { + printf ("(%s)", *curdrive); + putchar (delim); + } goto end; } - grub_util_info ("opening %s", drive_name); - dev = grub_device_open (drive_name); - if (! dev) - grub_util_error ("%s", _(grub_errmsg)); - - if (print == PRINT_ABSTRACTION) + if (print == PRINT_FS || print == PRINT_FS_UUID + || print == PRINT_FS_LABEL) { - probe_abstraction (dev->disk); - printf ("\n"); - goto end; - } + grub_device_t dev = NULL; + grub_fs_t fs; - if (print == PRINT_CRYPTODISK_UUID) - { - probe_cryptodisk_uuid (dev->disk); - printf ("\n"); - goto end; - } - - if (print == PRINT_PARTMAP) - { - /* Check if dev->disk itself is contained in a partmap. */ - probe_partmap (dev->disk); - printf ("\n"); - goto end; - } - - fs = grub_fs_probe (dev); - if (! fs) - grub_util_error ("%s", _(grub_errmsg)); - - if (print == PRINT_FS) - { - printf ("%s\n", fs->name); - } - else if (print == PRINT_FS_UUID) - { - char *uuid; - if (! fs->uuid) - grub_util_error (_("%s does not support UUIDs"), fs->name); - - if (fs->uuid (dev, &uuid) != GRUB_ERR_NONE) + grub_util_info ("opening %s", drives_names[0]); + dev = grub_device_open (drives_names[0]); + if (! dev) + grub_util_error ("%s", grub_errmsg); + + fs = grub_fs_probe (dev); + if (! fs) grub_util_error ("%s", grub_errmsg); - printf ("%s\n", uuid); + if (print == PRINT_FS) + { + printf ("%s", fs->name); + putchar (delim); + } + else if (print == PRINT_FS_UUID) + { + char *uuid; + if (! fs->uuid) + grub_util_error (_("%s does not support UUIDs"), fs->name); + + if (fs->uuid (dev, &uuid) != GRUB_ERR_NONE) + grub_util_error ("%s", grub_errmsg); + + printf ("%s", uuid); + putchar (delim); + } + else if (print == PRINT_FS_LABEL) + { + char *label; + if (! fs->label) + grub_util_error (_("filesystem `%s' does not support labels"), + fs->name); + + if (fs->label (dev, &label) != GRUB_ERR_NONE) + grub_util_error ("%s", grub_errmsg); + + printf ("%s", label); + putchar (delim); + } + goto end; } - else if (print == PRINT_FS_LABEL) + + for (curdrive = drives_names, curdev = device_names; *curdrive; + curdrive++, curdev++) { - char *label; - if (! fs->label) - grub_util_error (_("%s does not support labels"), fs->name); + grub_device_t dev = NULL; - if (fs->label (dev, &label) != GRUB_ERR_NONE) - grub_util_error ("%s", _(grub_errmsg)); + grub_util_info ("opening %s", *curdrive); + dev = grub_device_open (*curdrive); + if (! dev) + grub_util_error ("%s", grub_errmsg); - printf ("%s\n", label); + if (print == PRINT_HINT_STR) + { + const char *osdev = grub_util_biosdisk_get_osdev (dev->disk); + const char *ofpath = osdev ? grub_util_devname_to_ofpath (osdev) : 0; + char *biosname, *bare, *efi; + const char *map; + + if (ofpath) + { + printf ("--hint-ieee1275='"); + print_full_name (ofpath, dev); + printf ("' "); + } + + biosname = guess_bios_drive (*curdev); + if (biosname) + { + printf ("--hint-bios="); + print_full_name (biosname, dev); + printf (" "); + } + free (biosname); + + efi = guess_efi_drive (*curdev); + if (efi) + { + printf ("--hint-efi="); + print_full_name (efi, dev); + printf (" "); + } + free (efi); + + bare = guess_baremetal_drive (*curdev); + if (bare) + { + printf ("--hint-baremetal="); + print_full_name (bare, dev); + printf (" "); + } + free (bare); + + /* FIXME: Add ARC hint. */ + + map = grub_util_biosdisk_get_compatibility_hint (dev->disk); + if (map) + { + printf ("--hint='"); + print_full_name (map, dev); + printf ("' "); + } + printf ("\n"); + + grub_device_close (dev); + continue; + } + + if ((print == PRINT_COMPATIBILITY_HINT || print == PRINT_BIOS_HINT + || print == PRINT_IEEE1275_HINT || print == PRINT_BAREMETAL_HINT + || print == PRINT_EFI_HINT || print == PRINT_ARC_HINT) + && dev->disk->dev->id != GRUB_DISK_DEVICE_HOSTDISK_ID) + { + print_full_name (dev->disk->name, dev); + putchar (delim); + continue; + } + + if (print == PRINT_COMPATIBILITY_HINT) + { + const char *map; + char *biosname; + map = grub_util_biosdisk_get_compatibility_hint (dev->disk); + if (map) + { + print_full_name (map, dev); + putchar (delim); + grub_device_close (dev); + /* Compatibility hint is one device only. */ + break; + } + biosname = guess_bios_drive (*curdev); + if (biosname) + { + print_full_name (biosname, dev); + putchar (delim); + } + free (biosname); + grub_device_close (dev); + /* Compatibility hint is one device only. */ + if (biosname) + break; + continue; + } + + if (print == PRINT_BIOS_HINT) + { + char *biosname; + biosname = guess_bios_drive (*curdev); + if (biosname) + { + print_full_name (biosname, dev); + putchar (delim); + } + free (biosname); + grub_device_close (dev); + continue; + } + if (print == PRINT_IEEE1275_HINT) + { + const char *osdev = grub_util_biosdisk_get_osdev (dev->disk); + const char *ofpath = grub_util_devname_to_ofpath (osdev); + const char *map; + + map = grub_util_biosdisk_get_compatibility_hint (dev->disk); + if (map) + { + print_full_name (map, dev); + putchar (delim); + } + + if (ofpath) + { + print_full_name (ofpath, dev); + putchar (delim); + } + + grub_device_close (dev); + continue; + } + if (print == PRINT_EFI_HINT) + { + char *biosname; + const char *map; + biosname = guess_efi_drive (*curdev); + + map = grub_util_biosdisk_get_compatibility_hint (dev->disk); + if (map) + { + print_full_name (map, dev); + putchar (delim); + } + if (biosname) + { + print_full_name (biosname, dev); + putchar (delim); + } + + free (biosname); + grub_device_close (dev); + continue; + } + + if (print == PRINT_BAREMETAL_HINT) + { + char *biosname; + const char *map; + + biosname = guess_baremetal_drive (*curdev); + + map = grub_util_biosdisk_get_compatibility_hint (dev->disk); + if (map) + { + print_full_name (map, dev); + putchar (delim); + } + if (biosname) + { + print_full_name (biosname, dev); + putchar (delim); + } + + free (biosname); + grub_device_close (dev); + continue; + } + + if (print == PRINT_ARC_HINT) + { + const char *map; + + map = grub_util_biosdisk_get_compatibility_hint (dev->disk); + if (map) + { + print_full_name (map, dev); + putchar (delim); + } + + /* FIXME */ + grub_device_close (dev); + continue; + } + + if (print == PRINT_ABSTRACTION) + { + probe_abstraction (dev->disk); + putchar (delim); + grub_device_close (dev); + continue; + } + + if (print == PRINT_CRYPTODISK_UUID) + { + probe_cryptodisk_uuid (dev->disk); + putchar (delim); + grub_device_close (dev); + continue; + } + + if (print == PRINT_PARTMAP) + { + /* Check if dev->disk itself is contained in a partmap. */ + probe_partmap (dev->disk); + putchar (delim); + grub_device_close (dev); + continue; + } + + if (print == PRINT_MSDOS_PARTTYPE) + { + if (dev->disk->partition + && strcmp(dev->disk->partition->partmap->name, "msdos") == 0) + printf ("%02x", dev->disk->partition->msdostype); + + putchar (delim); + grub_device_close (dev); + continue; + } } end: - if (dev) - grub_device_close (dev); - free (grub_path); - free (filebuf_via_grub); - free (filebuf_via_sys); - free (drive_name); + for (curdrive = drives_names; *curdrive; curdrive++) + free (*curdrive); + free (drives_names); } -static struct option options[] = - { - {"device", no_argument, 0, 'd'}, - {"device-map", required_argument, 0, 'm'}, - {"target", required_argument, 0, 't'}, - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'V'}, - {"verbose", no_argument, 0, 'v'}, - {0, 0, 0, 0} - }; +static struct argp_option options[] = { + {"device", 'd', 0, 0, + N_("given argument is a system device, not a path"), 0}, + {"device-map", 'm', N_("FILE"), 0, + N_("use FILE as the device map [default=%s]"), 0}, + {"target", 't', "(fs|fs_uuid|fs_label|drive|device|partmap|abstraction|cryptodisk_uuid|msdos_parttype)", 0, + N_("print filesystem module, GRUB drive, system device, partition map module, abstraction module or cryptographic container UUID [default=fs]"), 0}, + {"verbose", 'v', 0, 0, N_("print verbose messages."), 0}, + { 0, 0, 0, 0, 0, 0 } +}; -static void -usage (int status) +static char * +help_filter (int key, const char *text, void *input __attribute__ ((unused))) { - if (status) - fprintf (stderr, - _("Try `%s --help' for more information.\n"), program_name); - else - printf (_("\ -Usage: %s [OPTION]... [PATH|DEVICE]\n\ -\n\ -Probe device information for a given path (or device, if the -d option is given).\n\ -\n\ - -d, --device given argument is a system device, not a path\n\ - -m, --device-map=FILE use FILE as the device map [default=%s]\n\ - -t, --target=(fs|fs_uuid|fs_label|drive|device|partmap|abstraction|cryptodisk_uuid)\n\ - print filesystem module, GRUB drive, system device, partition map module, abstraction module or CRYPTO UUID [default=fs]\n\ - -h, --help display this message and exit\n\ - -V, --version print version information and exit\n\ - -v, --verbose print verbose messages\n\ -\n\ -Report bugs to <%s>.\n\ -"), program_name, - DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT); + switch (key) + { + case 'm': + return xasprintf (text, DEFAULT_DEVICE_MAP); - exit (status); + default: + return (char *) text; + } } +struct arguments +{ + char **devices; + size_t device_max; + size_t ndevices; + char *dev_map; + int zero_delim; +}; + +static error_t +argp_parser (int key, char *arg, struct argp_state *state) +{ + /* Get the input argument from argp_parse, which we + know is a pointer to our arguments structure. */ + struct arguments *arguments = state->input; + + switch (key) + { + case 'd': + argument_is_device = 1; + break; + + case 'm': + if (arguments->dev_map) + free (arguments->dev_map); + + arguments->dev_map = xstrdup (arg); + break; + + case 't': + if (!strcmp (arg, "fs")) + print = PRINT_FS; + else if (!strcmp (arg, "fs_uuid")) + print = PRINT_FS_UUID; + else if (!strcmp (arg, "fs_label")) + print = PRINT_FS_LABEL; + else if (!strcmp (arg, "drive")) + print = PRINT_DRIVE; + else if (!strcmp (arg, "device")) + print = PRINT_DEVICE; + else if (!strcmp (arg, "partmap")) + print = PRINT_PARTMAP; + else if (!strcmp (arg, "abstraction")) + print = PRINT_ABSTRACTION; + else if (!strcmp (arg, "cryptodisk_uuid")) + print = PRINT_CRYPTODISK_UUID; + else if (!strcmp (arg, "msdos_parttype")) + print = PRINT_MSDOS_PARTTYPE; + else if (!strcmp (arg, "hints_string")) + print = PRINT_HINT_STR; + else if (!strcmp (arg, "bios_hints")) + print = PRINT_BIOS_HINT; + else if (!strcmp (arg, "ieee1275_hints")) + print = PRINT_IEEE1275_HINT; + else if (!strcmp (arg, "baremetal_hints")) + print = PRINT_BAREMETAL_HINT; + else if (!strcmp (arg, "efi_hints")) + print = PRINT_EFI_HINT; + else if (!strcmp (arg, "arc_hints")) + print = PRINT_ARC_HINT; + else if (!strcmp (arg, "compatibility_hint")) + print = PRINT_COMPATIBILITY_HINT; + else if (!strcmp (arg, "disk")) + print = PRINT_DISK; + else + argp_usage (state); + break; + + case '0': + arguments->zero_delim = 1; + break; + + case 'v': + verbosity++; + break; + + case ARGP_KEY_NO_ARGS: + fprintf (stderr, "%s", _("No path or device is specified.\n")); + argp_usage (state); + break; + + case ARGP_KEY_ARG: + assert (arguments->ndevices < arguments->device_max); + arguments->devices[arguments->ndevices++] = xstrdup(arg); + break; + + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +static struct argp argp = { + options, argp_parser, N_("[OPTION]... [PATH|DEVICE]"), + N_("\ +Probe device information for a given path (or device, if the -d option is given)."), + NULL, help_filter, NULL +}; + int main (int argc, char *argv[]) { - char *dev_map = 0; - char *argument; + char delim; + struct arguments arguments; set_program_name (argv[0]); grub_util_init_nls (); - /* Check for options. */ - while (1) + memset (&arguments, 0, sizeof (struct arguments)); + arguments.device_max = argc + 1; + arguments.devices = xmalloc ((arguments.device_max + 1) + * sizeof (arguments.devices[0])); + memset (arguments.devices, 0, (arguments.device_max + 1) + * sizeof (arguments.devices[0])); + + /* Parse our arguments */ + if (argp_parse (&argp, argc, argv, 0, 0, &arguments) != 0) { - int c = getopt_long (argc, argv, "dm:t:hVv", options, 0); - - if (c == -1) - break; - else - switch (c) - { - case 'd': - argument_is_device = 1; - break; - - case 'm': - if (dev_map) - free (dev_map); - - dev_map = xstrdup (optarg); - break; - - case 't': - if (!strcmp (optarg, "fs")) - print = PRINT_FS; - else if (!strcmp (optarg, "fs_uuid")) - print = PRINT_FS_UUID; - else if (!strcmp (optarg, "fs_label")) - print = PRINT_FS_LABEL; - else if (!strcmp (optarg, "drive")) - print = PRINT_DRIVE; - else if (!strcmp (optarg, "device")) - print = PRINT_DEVICE; - else if (!strcmp (optarg, "partmap")) - print = PRINT_PARTMAP; - else if (!strcmp (optarg, "abstraction")) - print = PRINT_ABSTRACTION; - else if (!strcmp (optarg, "cryptodisk_uuid")) - print = PRINT_CRYPTODISK_UUID; - else - usage (1); - break; - - case 'h': - usage (0); - break; - - case 'V': - printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); - return 0; - - case 'v': - verbosity++; - break; - - default: - usage (1); - break; - } + fprintf (stderr, "%s", _("Error in parsing command line arguments\n")); + exit(1); } if (verbosity > 1) grub_env_set ("debug", "all"); /* Obtain ARGUMENT. */ - if (optind >= argc) - { - fprintf (stderr, _("No path or device is specified.\n")); - usage (1); - } - - if (optind + 1 != argc) + if (arguments.ndevices != 1 && !argument_is_device) { + char *program = xstrdup(program_name); fprintf (stderr, _("Unknown extra argument `%s'.\n"), argv[optind + 1]); - usage (1); + argp_help (&argp, stderr, ARGP_HELP_STD_USAGE, program); + free (program); + exit(1); } - argument = argv[optind]; - /* Initialize the emulated biosdisk driver. */ - grub_util_biosdisk_init (dev_map ? : DEFAULT_DEVICE_MAP); + grub_util_biosdisk_init (arguments.dev_map ? : DEFAULT_DEVICE_MAP); /* Initialize all modules. */ grub_init_all (); @@ -408,24 +854,48 @@ main (int argc, char *argv[]) grub_lvm_fini (); grub_mdraid09_fini (); grub_mdraid1x_fini (); - grub_raid_fini (); - grub_raid_init (); + grub_diskfilter_fini (); + grub_diskfilter_init (); grub_mdraid09_init (); grub_mdraid1x_init (); grub_lvm_init (); + if (print == PRINT_BIOS_HINT + || print == PRINT_IEEE1275_HINT || print == PRINT_BAREMETAL_HINT + || print == PRINT_EFI_HINT || print == PRINT_ARC_HINT) + delim = ' '; + else + delim = '\n'; + + if (arguments.zero_delim) + delim = '\0'; + /* Do it. */ if (argument_is_device) - probe (NULL, argument); + probe (NULL, arguments.devices, delim); else - probe (argument, NULL); + probe (arguments.devices[0], NULL, delim); + + if (!arguments.zero_delim && (print == PRINT_BIOS_HINT + || print == PRINT_IEEE1275_HINT + || print == PRINT_BAREMETAL_HINT + || print == PRINT_EFI_HINT + || print == PRINT_ARC_HINT)) + putchar ('\n'); /* Free resources. */ grub_gcry_fini_all (); grub_fini_all (); grub_util_biosdisk_fini (); - free (dev_map); + { + size_t i; + for (i = 0; i < arguments.ndevices; i++) + free (arguments.devices[i]); + } + free (arguments.devices); + + free (arguments.dev_map); return 0; } diff --git a/util/grub-reboot.in b/util/grub-reboot.in index 929cf5202..1dfa382b8 100644 --- a/util/grub-reboot.in +++ b/util/grub-reboot.in @@ -24,6 +24,11 @@ exec_prefix=@exec_prefix@ bindir=@bindir@ PACKAGE_NAME=@PACKAGE_NAME@ PACKAGE_VERSION=@PACKAGE_VERSION@ +datarootdir="@datarootdir@" +datadir="@datadir@" +if [ "x$pkgdatadir" = x ]; then + pkgdatadir="${datadir}/`echo @PACKAGE_TARNAME@ | sed "${transform}"`" +fi self=`basename $0` @@ -32,22 +37,22 @@ rootdir= bootdir= grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'` +. "${pkgdatadir}/grub-mkconfig_lib" + # Usage: usage # Print the usage. usage () { - cat <. -EOF + gettext_printf "Usage: %s [OPTION] entry\n" "$self" + gettext "Set the default boot entry for GRUB, for the next boot only."; echo + echo + printf " -h, --help %s\n" "$(gettext "print this message and exit")" + printf " -v, --version %s\n" "$(gettext "print the version information and exit")" + dirmsg="$(gettext_printf "expect GRUB images under the directory DIR/%s instead of the %s directory" "@grubdirname@" "$grubdir")" + printf " --boot-directory=%-7s%s\n" "$(gettext "DIR")" "$dirmsg" + echo + gettext "ENTRY is a number or a menu item title."; echo + echo + gettext "Report bugs to ."; echo } argument () { @@ -55,7 +60,7 @@ argument () { shift if test $# -eq 0; then - echo "$0: option requires an argument -- '$opt'" 1>&2 + gettext_printf "%s: option requires an argument -- '%s'\n" "$0" "$opt" 1>&2 exit 1 fi echo $1 @@ -87,13 +92,14 @@ do bootdir=`echo "$option" | sed 's/--boot-directory=//'` ;; -*) - echo "Unrecognized option \`$option'" 1>&2 + gettext_printf "Unrecognized option \`%s'" "$option" 1>&2 usage exit 1 ;; *) if test "x$entry" != x; then - echo "More than one entry?" 1>&2 + gettext "More than one entry?" 1>&2 + echo >&2 usage exit 1 fi @@ -102,7 +108,8 @@ do done if test "x$entry" = x; then - echo "entry not specified." 1>&2 + gettext "entry not specified." 1>&2 + echo >&2 usage exit 1 fi diff --git a/util/grub-script-check.c b/util/grub-script-check.c index 25358a553..97b9969ef 100644 --- a/util/grub-script-check.c +++ b/util/grub-script-check.c @@ -34,48 +34,63 @@ #include #include #include -#include +#include #include "progname.h" -static struct option options[] = - { - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'V'}, - {"verbose", no_argument, 0, 'v'}, - {0, 0, 0, 0} - }; - -static void -usage (int status) +struct arguments { - if (status) - fprintf (stderr, - _("Try ``%s --help'' for more information.\n"), program_name); - else - printf (_("\ -Usage: %s [PATH]\n\ -\n\ -Checks GRUB script configuration file for syntax errors.\n\ -\n\ - -h, --help display this message and exit\n\ - -V, --version print version information and exit\n\ - -v, --verbose print the script as it is being processed\n\ -\n\ -Report bugs to <%s>.\n\ -"), program_name, - PACKAGE_BUGREPORT); - exit (status); + int verbose; + char *filename; +}; + +static struct argp_option options[] = { + {"verbose", 'v', 0, 0, N_("print verbose messages."), 0}, + { 0, 0, 0, 0, 0, 0 } +}; + +static error_t +argp_parser (int key, char *arg, struct argp_state *state) +{ + /* Get the input argument from argp_parse, which we + know is a pointer to our arguments structure. */ + struct arguments *arguments = state->input; + + switch (key) + { + case 'v': + arguments->verbose = 1; + break; + + case ARGP_KEY_ARG: + if (state->arg_num == 0) + arguments->filename = xstrdup (arg); + else + { + /* Too many arguments. */ + fprintf (stderr, _("Unknown extra argument `%s'.\n"), arg); + argp_usage (state); + } + break; + default: + return ARGP_ERR_UNKNOWN; + } + return 0; } +static struct argp argp = { + options, argp_parser, N_("[PATH]"), + N_("Checks GRUB script configuration file for syntax errors."), + NULL, NULL, NULL +}; + int main (int argc, char *argv[]) { - char *argument; char *input; int lineno = 0; FILE *file = 0; - int verbose = 0; + struct arguments arguments; int found_input = 0; struct grub_script *script = NULL; @@ -85,10 +100,10 @@ main (int argc, char *argv[]) int i; char *cmdline = 0; size_t len = 0; - ssize_t read; + ssize_t curread; - read = getline(&cmdline, &len, (file ?: stdin)); - if (read == -1) + curread = getline(&cmdline, &len, (file ?: stdin)); + if (curread == -1) { *line = 0; grub_errno = GRUB_ERR_READ_ERROR; @@ -98,7 +113,7 @@ main (int argc, char *argv[]) return grub_errno; } - if (verbose) + if (arguments.verbose) grub_printf("%s", cmdline); for (i = 0; cmdline[i] != '\0'; i++) @@ -122,52 +137,31 @@ main (int argc, char *argv[]) set_program_name (argv[0]); grub_util_init_nls (); + memset (&arguments, 0, sizeof (struct arguments)); + /* Check for options. */ - while (1) + if (argp_parse (&argp, argc, argv, 0, 0, &arguments) != 0) { - int c = getopt_long (argc, argv, "hvV", options, 0); - - if (c == -1) - break; - else - switch (c) - { - case 'h': - usage (0); - break; - - case 'V': - printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); - return 0; - - case 'v': - verbose = 1; - break; - - default: - usage (1); - break; - } + fprintf (stderr, "%s", _("Error in parsing command line arguments\n")); + exit(1); } /* Obtain ARGUMENT. */ - if (optind >= argc) + if (!arguments.filename) { file = 0; /* read from stdin */ } - else if (optind + 1 != argc) - { - fprintf (stderr, _("Unknown extra argument `%s'.\n"), argv[optind + 1]); - usage (1); - } else { - argument = argv[optind]; - file = fopen (argument, "r"); + file = fopen (arguments.filename, "r"); if (! file) { - fprintf (stderr, "%s: %s: %s\n", program_name, argument, strerror(errno)); - usage (1); + char *program = xstrdup(program_name); + fprintf (stderr, "%s: %s: %s\n", program_name, + arguments.filename, strerror(errno)); + argp_help (&argp, stderr, ARGP_HELP_STD_USAGE, program); + free(program); + exit(1); } } diff --git a/util/grub-set-default.in b/util/grub-set-default.in index b09727de2..49e7a4d1e 100644 --- a/util/grub-set-default.in +++ b/util/grub-set-default.in @@ -24,6 +24,11 @@ exec_prefix=@exec_prefix@ bindir=@bindir@ PACKAGE_NAME=@PACKAGE_NAME@ PACKAGE_VERSION=@PACKAGE_VERSION@ +datarootdir="@datarootdir@" +datadir="@datadir@" +if [ "x$pkgdatadir" = x ]; then + pkgdatadir="${datadir}/`echo @PACKAGE_TARNAME@ | sed "${transform}"`" +fi self=`basename $0` @@ -32,22 +37,22 @@ rootdir= bootdir= grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'` +. "${pkgdatadir}/grub-mkconfig_lib" + # Usage: usage # Print the usage. usage () { - cat <. -EOF + gettext_printf "Usage: %s [OPTION] entry\n" "$self" + gettext "Set the default boot entry for GRUB."; echo + echo + printf " -h, --help %s\n" "$(gettext "print this message and exit")" + printf " -v, --version %s\n" "$(gettext "print the version information and exit")" + dirmsg="$(printf "expect GRUB images under the directory DIR/%s instead of the %s directory" "@grubdirname@" "$grubdir")" + printf " --boot-directory=%-7s%s\n" "$(gettext "DIR")" "$dirmsg" + echo + gettext "ENTRY is a number or a menu item title."; echo + echo + gettext "Report bugs to ."; echo } argument () { @@ -55,7 +60,7 @@ argument () { shift if test $# -eq 0; then - echo "$0: option requires an argument -- '$opt'" 1>&2 + gettext_printf "%s: option requires an argument -- '%s'\n" "$0" "$opt" 1>&2 exit 1 fi echo $1 @@ -87,13 +92,14 @@ do bootdir=`echo "$option" | sed 's/--boot-directory=//'` ;; -*) - echo "Unrecognized option \`$option'" 1>&2 + gettext_printf "Unrecognized option \`%s'" "$option" 1>&2 usage exit 1 ;; *) if test "x$entry" != x; then - echo "More than one entry?" 1>&2 + gettext "More than one entry?" 1>&2 + echo >&2 usage exit 1 fi @@ -102,7 +108,8 @@ do done if test "x$entry" = x; then - echo "entry not specified." 1>&2 + gettext "entry not specified." 1>&2 + echo >&2 usage exit 1 fi diff --git a/util/grub-setup.c b/util/grub-setup.c index 055543f2d..66f705015 100644 --- a/util/grub-setup.c +++ b/util/grub-setup.c @@ -133,17 +133,17 @@ write_rootdev (char *core_img, grub_device_t root_dev, static void setup (const char *dir, const char *boot_file, const char *core_file, - const char *root, const char *dest, int must_embed, int force, + const char *dest, int force, int fs_probe, int allow_floppy) { char *boot_path, *core_path, *core_path_dev, *core_path_dev_full; char *boot_img, *core_img; + char *root = 0; size_t boot_size, core_size; grub_uint16_t core_sectors; - grub_device_t root_dev, dest_dev; + grub_device_t root_dev = 0, dest_dev; struct grub_boot_blocklist *first_block, *block; char *tmp_img; - int i; grub_disk_addr_t first_sector; #ifdef GRUB_MACHINE_PCBIOS grub_uint16_t current_segment @@ -164,11 +164,11 @@ setup (const char *dir, unsigned offset, unsigned length) { - grub_util_info ("the first sector is <%llu,%u,%u>", + grub_util_info ("the first sector is <%" PRIuGRUB_UINT64_T ",%u,%u>", sector, offset, length); if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("the first sector of the core file is not sector-aligned")); + grub_util_error ("%s", _("the first sector of the core file is not sector-aligned")); first_sector = sector; } @@ -179,15 +179,19 @@ setup (const char *dir, { struct grub_boot_blocklist *prev = block + 1; - grub_util_info ("saving <%llu,%u,%u>", sector, offset, length); + grub_util_info ("saving <%" PRIuGRUB_UINT64_T ",%u,%u>", + sector, offset, length); if (offset != 0 || last_length != GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("non-sector-aligned data is found in the core file")); + grub_util_error ("%s", _("non-sector-aligned data is found in the core file")); if (block != first_block && (grub_target_to_host64 (prev->start) + grub_target_to_host16 (prev->len)) == sector) - prev->len = grub_host_to_target16 (grub_target_to_host16 (prev->len) + 1); + { + grub_uint16_t t = grub_target_to_host16 (prev->len) + 1; + prev->len = grub_host_to_target16 (t); + } else { block->start = grub_host_to_target64 (sector); @@ -198,7 +202,7 @@ setup (const char *dir, block--; if (block->len) - grub_util_error (_("the sectors of the core file are too fragmented")); + grub_util_error ("%s", _("the sectors of the core file are too fragmented")); } last_length = length; @@ -235,26 +239,65 @@ setup (const char *dir, - sizeof (*block)); grub_util_info ("root is `%s', dest is `%s'", root, dest); - /* Open the root device and the destination device. */ - grub_util_info ("Opening root"); - root_dev = grub_device_open (root); - if (! root_dev) - grub_util_error ("%s", _(grub_errmsg)); - grub_util_info ("Opening dest"); dest_dev = grub_device_open (dest); if (! dest_dev) - grub_util_error ("%s", _(grub_errmsg)); + grub_util_error ("%s", grub_errmsg); + + { + char **root_devices = grub_guess_root_devices (dir); + char **cur; + int found = 0; + + for (cur = root_devices; *cur; cur++) + { + char *drive; + grub_device_t try_dev; + + drive = grub_util_get_grub_dev (*cur); + if (!drive) + continue; + try_dev = grub_device_open (drive); + if (! try_dev) + continue; + if (!found && try_dev->disk->id == dest_dev->disk->id + && try_dev->disk->dev->id == dest_dev->disk->dev->id) + { + if (root_dev) + grub_device_close (root_dev); + free (root); + root_dev = try_dev; + root = drive; + found = 1; + continue; + } + if (!root_dev) + { + root_dev = try_dev; + root = drive; + continue; + } + grub_device_close (try_dev); + free (drive); + } + if (!root_dev) + { + grub_util_error ("guessing the root device failed, because of `%s'", + grub_errmsg); + } + grub_util_info ("guessed root_dev `%s' from " + "dir `%s'", root_dev->disk->name, dir); + } grub_util_info ("setting the root device to `%s'", root); if (grub_env_set ("root", root) != GRUB_ERR_NONE) - grub_util_error ("%s", _(grub_errmsg)); + grub_util_error ("%s", grub_errmsg); #ifdef GRUB_MACHINE_PCBIOS /* Read the original sector from the disk. */ tmp_img = xmalloc (GRUB_DISK_SECTOR_SIZE); if (grub_disk_read (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, tmp_img)) - grub_util_error ("%s", _(grub_errmsg)); + grub_util_error ("%s", grub_errmsg); #endif #ifdef GRUB_MACHINE_PCBIOS @@ -281,6 +324,7 @@ setup (const char *dir, grub_partition_map_t dest_partmap = NULL; grub_partition_t container = dest_dev->disk->partition; int multiple_partmaps = 0; + int is_ldm; grub_err_t err; grub_disk_addr_t *sectors; int i; @@ -320,7 +364,7 @@ setup (const char *dir, && (container->msdostype == GRUB_PC_PARTITION_TYPE_NETBSD || container->msdostype == GRUB_PC_PARTITION_TYPE_OPENBSD)) { - grub_util_warn (_("Attempting to install GRUB to a disk with multiple partition labels or both partition label and filesystem. This is not supported yet.")); + grub_util_warn ("%s", _("Attempting to install GRUB to a disk with multiple partition labels or both partition label and filesystem. This is not supported yet.")); goto unable_to_embed; } @@ -328,6 +372,8 @@ setup (const char *dir, if (!fs) grub_errno = GRUB_ERR_NONE; + is_ldm = grub_util_is_ldm (dest_dev->disk); + #ifdef GRUB_MACHINE_PCBIOS if (fs_probe) { @@ -352,6 +398,17 @@ setup (const char *dir, "result in FILESYSTEM DESTRUCTION if valuable data is overwritten " "by grub-setup (--skip-fs-probe disables this " "check, use at your own risk)"), dest_dev->disk->name, dest_partmap->name); + if (is_ldm && dest_partmap && strcmp (dest_partmap->name, "msdos") != 0 + && strcmp (dest_partmap->name, "gpt") != 0) + grub_util_error (_("%s appears to contain a %s partition map and " + "LDM which isn't known to be a safe combination." + " Installing GRUB there could " + "result in FILESYSTEM DESTRUCTION if valuable data" + " is overwritten " + "by grub-setup (--skip-fs-probe disables this " + "check, use at your own risk)"), + dest_dev->disk->name, dest_partmap->name); + } #endif @@ -364,33 +421,36 @@ setup (const char *dir, free (tmp_img); - if (! dest_partmap && ! fs) + if (! dest_partmap && ! fs && !is_ldm) { - grub_util_warn (_("Attempting to install GRUB to a partitionless disk or to a partition. This is a BAD idea.")); + grub_util_warn ("%s", _("Attempting to install GRUB to a partitionless disk or to a partition. This is a BAD idea.")); goto unable_to_embed; } - if (multiple_partmaps || (dest_partmap && fs)) + if (multiple_partmaps || (dest_partmap && fs) || (is_ldm && fs)) { - grub_util_warn (_("Attempting to install GRUB to a disk with multiple partition labels or both partition label and filesystem. This is not supported yet.")); + grub_util_warn ("%s", _("Attempting to install GRUB to a disk with multiple partition labels. This is not supported yet.")); goto unable_to_embed; } if (dest_partmap && !dest_partmap->embed) { - grub_util_warn (_("Partition style '%s' doesn't support embeding"), + grub_util_warn (_("Partition style '%s' doesn't support embedding"), dest_partmap->name); goto unable_to_embed; } if (fs && !fs->embed) { - grub_util_warn (_("File system '%s' doesn't support embeding"), + grub_util_warn (_("File system '%s' doesn't support embedding"), fs->name); goto unable_to_embed; } nsec = core_sectors; - if (dest_partmap) + if (is_ldm) + err = grub_util_ldm_embed (dest_dev->disk, &nsec, + GRUB_EMBED_PCBIOS, §ors); + else if (dest_partmap) err = dest_partmap->embed (dest_dev->disk, &nsec, GRUB_EMBED_PCBIOS, §ors); else @@ -405,13 +465,17 @@ setup (const char *dir, if (err) { - grub_util_warn ("%s", _(grub_errmsg)); + grub_util_warn ("%s", grub_errmsg); grub_errno = GRUB_ERR_NONE; goto unable_to_embed; } if (nsec > 2 * core_sectors) nsec = 2 * core_sectors; + if (nsec > ((0x78000 - GRUB_KERNEL_I386_PC_LINK_ADDR) + >> GRUB_DISK_SECTOR_BITS)) + nsec = ((0x78000 - GRUB_KERNEL_I386_PC_LINK_ADDR) + >> GRUB_DISK_SECTOR_BITS); /* Clean out the blocklists. */ block = first_block; @@ -422,7 +486,7 @@ setup (const char *dir, block--; if ((char *) block <= core_img) - grub_util_error (_("No terminator in the core image")); + grub_util_error ("%s", _("no terminator in the core image")); } save_first_sector (sectors[0] + grub_partition_get_start (container), @@ -440,14 +504,26 @@ setup (const char *dir, + GRUB_DISK_SECTOR_SIZE - sizeof (*block)); + grub_size_t no_rs_length; *(grub_uint32_t *) (core_img + GRUB_DISK_SECTOR_SIZE + GRUB_KERNEL_I386_PC_REED_SOLOMON_REDUNDANCY) = grub_host_to_target32 (nsec * GRUB_DISK_SECTOR_SIZE - core_size); + no_rs_length = grub_target_to_host16 + (*(grub_uint16_t *) (core_img + + GRUB_DISK_SECTOR_SIZE + + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_LENGTH)); - grub_reed_solomon_add_redundancy (core_img + GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART + GRUB_DISK_SECTOR_SIZE, - core_size - GRUB_KERNEL_I386_PC_NO_REED_SOLOMON_PART - GRUB_DISK_SECTOR_SIZE, + if (no_rs_length == 0xffff) + grub_util_error ("%s", _("core.img version mismatch")); + + void *tmp = xmalloc (core_size); + grub_memcpy (tmp, core_img, core_size); + grub_reed_solomon_add_redundancy (core_img + no_rs_length + GRUB_DISK_SECTOR_SIZE, + core_size - no_rs_length - GRUB_DISK_SECTOR_SIZE, nsec * GRUB_DISK_SECTOR_SIZE - core_size); + assert (grub_memcmp (tmp, core_img, core_size) == 0); + free (tmp); /* Make sure that the second blocklist is a terminator. */ block = first_block - 1; @@ -465,25 +541,28 @@ setup (const char *dir, goto finish; } -#endif unable_to_embed: - - if (must_embed) - grub_util_error (_("embedding is not possible, but this is required when " - "the root device is on a RAID array or LVM volume")); - -#ifdef GRUB_MACHINE_PCBIOS - if (dest_dev->disk->id != root_dev->disk->id) - grub_util_error (_("embedding is not possible, but this is required for " - "cross-disk install")); #endif - grub_util_warn (_("Embedding is not possible. GRUB can only be installed in this " - "setup by using blocklists. However, blocklists are UNRELIABLE and " - "their use is discouraged.")); + if (dest_dev->disk->dev->id != root_dev->disk->dev->id) + grub_util_error ("%s", _("embedding is not possible, but this is required for " + "RAID and LVM install")); + +#ifdef GRUB_MACHINE_PCBIOS + if (dest_dev->disk->id != root_dev->disk->id + || dest_dev->disk->dev->id != root_dev->disk->dev->id) + /* TRANSLATORS: cross-disk refers to /boot being on one disk + but MBR on another. */ + grub_util_error ("%s", _("embedding is not possible, but this is required for " + "cross-disk install")); +#endif + + grub_util_warn ("%s", _("Embedding is not possible. GRUB can only be installed in this " + "setup by using blocklists. However, blocklists are UNRELIABLE and " + "their use is discouraged.")); if (! force) - grub_util_error (_("will not proceed with blocklists")); + grub_util_error ("%s", _("will not proceed with blocklists")); /* The core image must be put on a filesystem unfortunately. */ grub_util_info ("will leave the core image on the filesystem"); @@ -497,70 +576,72 @@ unable_to_embed: grub_util_biosdisk_flush (root_dev->disk); #define MAX_TRIES 5 + { + int i; + for (i = 0; i < MAX_TRIES; i++) + { + grub_util_info ((i == 0) ? _("attempting to read the core image `%s' from GRUB") + : _("attempting to read the core image `%s' from GRUB again"), + core_path_dev); - for (i = 0; i < MAX_TRIES; i++) - { - grub_util_info ((i == 0) ? _("attempting to read the core image `%s' from GRUB") - : _("attempting to read the core image `%s' from GRUB again"), - core_path_dev); + grub_disk_cache_invalidate_all (); - grub_disk_cache_invalidate_all (); - - grub_file_filter_disable_compression (); - file = grub_file_open (core_path_dev); - if (file) - { - if (grub_file_size (file) != core_size) - grub_util_info ("succeeded in opening the core image but the size is different (%d != %d)", - (int) grub_file_size (file), (int) core_size); - else if (grub_file_read (file, tmp_img, core_size) - != (grub_ssize_t) core_size) - grub_util_info ("succeeded in opening the core image but cannot read %d bytes", - (int) core_size); - else if (memcmp (core_img, tmp_img, core_size) != 0) - { + grub_file_filter_disable_compression (); + file = grub_file_open (core_path_dev); + if (file) + { + if (grub_file_size (file) != core_size) + grub_util_info ("succeeded in opening the core image but the size is different (%d != %d)", + (int) grub_file_size (file), (int) core_size); + else if (grub_file_read (file, tmp_img, core_size) + != (grub_ssize_t) core_size) + grub_util_info ("succeeded in opening the core image but cannot read %d bytes", + (int) core_size); + else if (memcmp (core_img, tmp_img, core_size) != 0) + { #if 0 - FILE *dump; - FILE *dump2; + FILE *dump; + FILE *dump2; - dump = fopen ("dump.img", "wb"); - if (dump) - { - fwrite (tmp_img, 1, core_size, dump); - fclose (dump); - } + dump = fopen ("dump.img", "wb"); + if (dump) + { + fwrite (tmp_img, 1, core_size, dump); + fclose (dump); + } - dump2 = fopen ("dump2.img", "wb"); - if (dump2) - { - fwrite (core_img, 1, core_size, dump2); - fclose (dump2); - } + dump2 = fopen ("dump2.img", "wb"); + if (dump2) + { + fwrite (core_img, 1, core_size, dump2); + fclose (dump2); + } #endif - grub_util_info ("succeeded in opening the core image but the data is different"); - } - else - { - grub_file_close (file); - break; - } + grub_util_info ("succeeded in opening the core image but the data is different"); + } + else + { + grub_file_close (file); + break; + } - grub_file_close (file); - } - else - grub_util_info ("couldn't open the core image"); + grub_file_close (file); + } + else + grub_util_info ("couldn't open the core image"); - if (grub_errno) - grub_util_info ("error message = %s", grub_errmsg); + if (grub_errno) + grub_util_info ("error message = %s", grub_errmsg); - grub_errno = GRUB_ERR_NONE; - grub_util_biosdisk_flush (root_dev->disk); - sleep (1); - } + grub_errno = GRUB_ERR_NONE; + grub_util_biosdisk_flush (root_dev->disk); + sleep (1); + } - if (i == MAX_TRIES) - grub_util_error (_("cannot read `%s' correctly"), core_path_dev); + if (i == MAX_TRIES) + grub_util_error (_("cannot read `%s' correctly"), core_path_dev); + } /* Clean out the blocklists. */ block = first_block; @@ -575,25 +656,25 @@ unable_to_embed: block--; if ((char *) block <= core_img) - grub_util_error (_("no terminator in the core image")); + grub_util_error ("%s", _("no terminator in the core image")); } /* Now read the core image to determine where the sectors are. */ grub_file_filter_disable_compression (); file = grub_file_open (core_path_dev); if (! file) - grub_util_error ("%s", _(grub_errmsg)); + grub_util_error ("%s", grub_errmsg); file->read_hook = save_first_sector; if (grub_file_read (file, tmp_img, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("failed to read the first sector of the core image")); + grub_util_error ("%s", _("failed to read the first sector of the core image")); block = first_block; file->read_hook = save_blocklists; if (grub_file_read (file, tmp_img, core_size - GRUB_DISK_SECTOR_SIZE) != (grub_ssize_t) core_size - GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("failed to read the rest sectors of the core image")); + grub_util_error ("%s", _("failed to read the rest sectors of the core image")); #ifdef GRUB_MACHINE_IEEE1275 { @@ -601,11 +682,12 @@ unable_to_embed: boot_devpath = (char *) (boot_img + GRUB_BOOT_AOUT_HEADER_SIZE + GRUB_BOOT_MACHINE_BOOT_DEVPATH); - if (file->device->disk->id != dest_dev->disk->id) + if (dest_dev->disk->id != root_dev->disk->id + || dest_dev->disk->dev->id != root_dev->disk->dev->id) { const char *dest_ofpath; dest_ofpath - = grub_util_devname_to_ofpath (grub_util_biosdisk_get_osdev (file->device->disk)); + = grub_util_devname_to_ofpath (grub_util_biosdisk_get_osdev (root_dev->disk)); grub_util_info ("dest_ofpath is `%s'", dest_ofpath); strncpy (boot_devpath, dest_ofpath, GRUB_BOOT_MACHINE_BOOT_DEVPATH_END - GRUB_BOOT_MACHINE_BOOT_DEVPATH - 1); @@ -633,17 +715,20 @@ unable_to_embed: grub_util_info ("opening the core image `%s'", core_path); fp = fopen (core_path, "r+b"); if (! fp) - grub_util_error (_("cannot open `%s'"), core_path); + grub_util_error (_("cannot open `%s': %s"), core_path, + strerror (errno)); - grub_util_write_image (core_img, GRUB_DISK_SECTOR_SIZE * 2, fp); + grub_util_write_image (core_img, GRUB_DISK_SECTOR_SIZE * 2, fp, core_path); fclose (fp); +#ifdef GRUB_MACHINE_PCBIOS finish: +#endif /* Write the boot image onto the disk. */ if (grub_disk_write (dest_dev->disk, BOOT_SECTOR, 0, GRUB_DISK_SECTOR_SIZE, boot_img)) - grub_util_error ("%s", _(grub_errmsg)); + grub_util_error ("%s", grub_errmsg); grub_util_biosdisk_flush (root_dev->disk); grub_util_biosdisk_flush (dest_dev->disk); @@ -663,15 +748,12 @@ static struct argp_option options[] = { {"directory", 'd', N_("DIR"), 0, N_("Use GRUB files in the directory DIR [default=%s]"), 0}, {"device-map", 'm', N_("FILE"), 0, - N_("Use FILE as the device map [default=%s]"), 0}, - {"root-device", 'r', N_("DEV"), 0, - N_("Use DEV as the root device [default=guessed]"), 0}, + N_("use FILE as the device map [default=%s]"), 0}, {"force", 'f', 0, 0, - N_("Install even if problems are detected"), 0}, + N_("install even if problems are detected"), 0}, {"skip-fs-probe",'s',0, 0, N_("Do not probe for filesystems in DEVICE"), 0}, - {"verbose", 'v', 0, 0, - N_("Print verbose messages."), 0}, + {"verbose", 'v', 0, 0, N_("print verbose messages."), 0}, {"allow-floppy", 'a', 0, 0, N_("Make the drive also bootable as floppy (default for fdX devices). May break on some BIOSes."), 0}, @@ -706,24 +788,12 @@ struct arguments char *core_file; char *dir; char *dev_map; - char *root_dev; int force; int fs_probe; int allow_floppy; char *device; }; -/* Print the version information. */ -static void -print_version (FILE *stream, struct argp_state *state) -{ - fprintf (stream, "%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); -} -void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version; - -/* Set the bug report address */ -const char *argp_program_bug_address = "<"PACKAGE_BUGREPORT">"; - static error_t argp_parser (int key, char *arg, struct argp_state *state) { @@ -731,8 +801,6 @@ argp_parser (int key, char *arg, struct argp_state *state) know is a pointer to our arguments structure. */ struct arguments *arguments = state->input; - char *p; - switch (key) { case 'a': @@ -767,13 +835,6 @@ argp_parser (int key, char *arg, struct argp_state *state) arguments->dev_map = xstrdup (arg); break; - case 'r': - if (arguments->root_dev) - free (arguments->root_dev); - - arguments->root_dev = xstrdup (arg); - break; - case 'f': arguments->force = 1; break; @@ -800,6 +861,7 @@ argp_parser (int key, char *arg, struct argp_state *state) case ARGP_KEY_NO_ARGS: fprintf (stderr, "%s", _("No device is specified.\n")); argp_usage (state); + exit (1); break; default: @@ -837,7 +899,6 @@ main (int argc, char *argv[]) { char *root_dev = NULL; char *dest_dev = NULL; - int must_embed = 0; struct arguments arguments; set_program_name (argv[0]); @@ -872,8 +933,8 @@ main (int argc, char *argv[]) grub_lvm_fini (); grub_mdraid09_fini (); grub_mdraid1x_fini (); - grub_raid_fini (); - grub_raid_init (); + grub_diskfilter_fini (); + grub_diskfilter_init (); grub_mdraid09_init (); grub_mdraid1x_init (); grub_lvm_init (); @@ -901,80 +962,12 @@ main (int argc, char *argv[]) grub_util_info ("Using `%s' as GRUB device", dest_dev); } - if (arguments.root_dev) - { - root_dev = get_device_name (arguments.root_dev); - - if (! root_dev) - grub_util_error (_("invalid root device `%s'"), arguments.root_dev); - - root_dev = xstrdup (root_dev); - } - else - { - char *root_device = - grub_guess_root_device (arguments.dir ? : DEFAULT_DIRECTORY); - - root_dev = grub_util_get_grub_dev (root_device); - if (! root_dev) - { - grub_util_info ("guessing the root device failed, because of `%s'", - grub_errmsg); - grub_util_error (_("cannot guess the root device. Specify the option " - "`--root-device'")); - } - grub_util_info ("guessed root device `%s' and root_dev `%s' from " - "dir `%s'", root_device, root_dev, - arguments.dir ? : DEFAULT_DIRECTORY); - } - -#if defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) - if (grub_util_lvm_isvolume (root_dev)) - must_embed = 1; -#endif - -#ifdef __linux__ - if (root_dev[0] == 'm' && root_dev[1] == 'd' - && ((root_dev[2] >= '0' && root_dev[2] <= '9') || root_dev[2] == '/')) - { - /* FIXME: we can avoid this on RAID1. */ - must_embed = 1; - } - - if (dest_dev[0] == 'm' && dest_dev[1] == 'd' - && ((dest_dev[2] >= '0' && dest_dev[2] <= '9') || dest_dev[2] == '/')) - { - char **devicelist; - int i; - - if (arguments.device[0] == '/') - devicelist = grub_util_raid_getmembers (arguments.device, 1); - else - { - char *devname; - devname = xasprintf ("/dev/%s", dest_dev); - devicelist = grub_util_raid_getmembers (dest_dev, 1); - free (devname); - } - - for (i = 0; devicelist[i]; i++) - { - setup (arguments.dir ? : DEFAULT_DIRECTORY, - arguments.boot_file ? : DEFAULT_BOOT_FILE, - arguments.core_file ? : DEFAULT_CORE_FILE, - root_dev, grub_util_get_grub_dev (devicelist[i]), 1, - arguments.force, arguments.fs_probe, - arguments.allow_floppy); - } - } - else -#endif - /* Do the real work. */ - setup (arguments.dir ? : DEFAULT_DIRECTORY, - arguments.boot_file ? : DEFAULT_BOOT_FILE, - arguments.core_file ? : DEFAULT_CORE_FILE, - root_dev, dest_dev, must_embed, arguments.force, - arguments.fs_probe, arguments.allow_floppy); + /* Do the real work. */ + setup (arguments.dir ? : DEFAULT_DIRECTORY, + arguments.boot_file ? : DEFAULT_BOOT_FILE, + arguments.core_file ? : DEFAULT_CORE_FILE, + dest_dev, arguments.force, + arguments.fs_probe, arguments.allow_floppy); /* Free resources. */ grub_fini_all (); @@ -983,7 +976,6 @@ main (int argc, char *argv[]) free (arguments.boot_file); free (arguments.core_file); free (arguments.dir); - free (arguments.root_dev); free (arguments.dev_map); free (arguments.device); free (root_dev); diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in index 54012f854..d9bcc15bc 100644 --- a/util/grub.d/00_header.in +++ b/util/grub.d/00_header.in @@ -19,13 +19,13 @@ set -e transform="@program_transform_name@" -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ +prefix="@prefix@" +exec_prefix="@exec_prefix@" +datarootdir="@datarootdir@" locale_dir=`echo ${GRUB_PREFIX}/locale | sed ${transform}` grub_lang=`echo $LANG | cut -d . -f 1` -. ${libdir}/@PACKAGE@/grub-mkconfig_lib +. "@datadir@/@PACKAGE@/grub-mkconfig_lib" # Do this as early as possible, since other commands might depend on it. # (e.g. the `loadfont' command might need lvm or raid modules) @@ -112,12 +112,12 @@ for x in ${GRUB_TERMINAL_INPUT} ${GRUB_TERMINAL_OUTPUT}; do done if [ "x$serial" = x1 ]; then - if ! test -e ${GRUB_PREFIX}/serial.mod ; then - echo "Serial terminal not available on this platform." >&2 ; exit 1 + if ! test -e "${GRUB_PREFIX}/serial.mod" ; then + gettext "Serial terminal not available on this platform." >&2 ; echo >&2; exit 1 fi if [ "x${GRUB_SERIAL_COMMAND}" = "x" ] ; then - grub_warn "Requested serial terminal but GRUB_SERIAL_COMMAND is unspecified. Default parameters will be used." + grub_warn "$(gettext "Requested serial terminal but GRUB_SERIAL_COMMAND is unspecified. Default parameters will be used.")" GRUB_SERIAL_COMMAND=serial fi echo "${GRUB_SERIAL_COMMAND}" @@ -174,7 +174,8 @@ esac if [ "x$gfxterm" = x1 ]; then if [ "x$GRUB_THEME" != x ] && [ -f "$GRUB_THEME" ] \ && is_path_readable_by_grub "$GRUB_THEME"; then - echo "Found theme: $GRUB_THEME" >&2 + gettext_printf "Found theme: %s\n" "$GRUB_THEME" >&2 + prepare_grub_to_access_device `${grub_probe} --target=device "$GRUB_THEME"` cat << EOF insmod gfxmenu @@ -208,12 +209,12 @@ set theme=(\$root)`make_system_path_relative_to_its_root $GRUB_THEME` EOF elif [ "x$GRUB_BACKGROUND" != x ] && [ -f "$GRUB_BACKGROUND" ] \ && is_path_readable_by_grub "$GRUB_BACKGROUND"; then - echo "Found background: $GRUB_BACKGROUND" >&2 + gettext_printf "Found background: %s\n" "$GRUB_BACKGROUND" >&2 case "$GRUB_BACKGROUND" in *.png) reader=png ;; *.tga) reader=tga ;; *.jpg|*.jpeg) reader=jpeg ;; - *) echo "Unsupported image format" >&2; exit 1 ;; + *) gettext "Unsupported image format" >&2; echo >&2; exit 1 ;; esac prepare_grub_to_access_device `${grub_probe} --target=device "$GRUB_BACKGROUND"` cat << EOF diff --git a/util/grub.d/10_hurd.in b/util/grub.d/10_hurd.in index d04b0a4fe..23099f225 100644 --- a/util/grub.d/10_hurd.in +++ b/util/grub.d/10_hurd.in @@ -17,11 +17,10 @@ set -e # You should have received a copy of the GNU General Public License # along with GRUB. If not, see . -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -datarootdir=@datarootdir@ -. ${libdir}/@PACKAGE@/grub-mkconfig_lib +prefix="@prefix@" +exec_prefix="@exec_prefix@" +datarootdir="@datarootdir@" +. "@datadir@/@PACKAGE@/grub-mkconfig_lib" CLASS="--class gnu --class os" @@ -42,7 +41,8 @@ for i in /boot/gnumach* ; do basename=`basename $i` dirname=`dirname $i` rel_dirname=`make_system_path_relative_to_its_root $dirname` - echo "Found GNU Mach: $i" >&2 + gettext_printf "Found GNU Mach: %s" "$i" >&2 + echo >&2 kernels="${kernels} ${rel_dirname}/${basename}" at_least_one=true fi @@ -56,7 +56,8 @@ esac for i in /hurd/${hurd_fs}.static /hurd/exec ; do if test -e "$i" ; then - echo "Found Hurd module: $i" >&2 + gettext_printf "Found Hurd module: %s" "$i" >&2 + echo >&2 at_least_one=true else all_of_them=false @@ -69,7 +70,8 @@ if ${at_least_one} ; then : ; else fi if ${all_of_them} && test -e /lib/ld.so.1 ; then : ; else - echo "Some Hurd stuff found, but not enough to boot." >&2 + gettext "Some Hurd stuff found, but not enough to boot." >&2 + echo >&2 exit 1 fi diff --git a/util/grub.d/10_illumos.in b/util/grub.d/10_illumos.in index 2b87dfa4f..a4be7ba14 100644 --- a/util/grub.d/10_illumos.in +++ b/util/grub.d/10_illumos.in @@ -17,15 +17,13 @@ set -e # You should have received a copy of the GNU General Public License # along with GRUB. If not, see . -prefix=@prefix@ -exec_prefix=@exec_prefix@ -bindir=@bindir@ -libdir=@libdir@ -datarootdir=@datarootdir@ -. ${libdir}/@PACKAGE@/grub-mkconfig_lib +prefix="@prefix@" +exec_prefix="@exec_prefix@" +datarootdir="@datarootdir@" +. "@datadir@/@PACKAGE@/grub-mkconfig_lib" export TEXTDOMAIN=@PACKAGE@ -export TEXTDOMAINDIR=@localedir@ +export TEXTDOMAINDIR="@localedir@" CLASS="--class os" diff --git a/util/grub.d/10_kfreebsd.in b/util/grub.d/10_kfreebsd.in index a1b86b82b..c31551206 100644 --- a/util/grub.d/10_kfreebsd.in +++ b/util/grub.d/10_kfreebsd.in @@ -17,15 +17,13 @@ set -e # You should have received a copy of the GNU General Public License # along with GRUB. If not, see . -prefix=@prefix@ -exec_prefix=@exec_prefix@ -bindir=@bindir@ -libdir=@libdir@ -datarootdir=@datarootdir@ -. ${libdir}/@PACKAGE@/grub-mkconfig_lib +prefix="@prefix@" +exec_prefix="@exec_prefix@" +datarootdir="@datarootdir@" +. "@datadir@/@PACKAGE@/grub-mkconfig_lib" export TEXTDOMAIN=@PACKAGE@ -export TEXTDOMAINDIR=@localedir@ +export TEXTDOMAINDIR="@localedir@" CLASS="--class os" @@ -137,7 +135,7 @@ prepare_boot_cache= while [ "x$list" != "x" ] ; do kfreebsd=`version_find_latest $list` - echo "Found kernel of FreeBSD: $kfreebsd" >&2 + gettext_printf "Found kernel of FreeBSD: %s\n" "$kfreebsd" >&2 basename=`basename $kfreebsd` dirname=`dirname $kfreebsd` rel_dirname=`make_system_path_relative_to_its_root $dirname` @@ -186,7 +184,7 @@ while [ "x$list" != "x" ] ; do fi done if test -n "${module_dir}" ; then - echo "Found kernel module directory: ${module_dir}" >&2 + gettext_printf "Found kernel module directory: %s\n" "${module_dir}" >&2 module_dir_rel=$(make_system_path_relative_to_its_root $module_dir) fi diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in index fe4f0e730..bc738f205 100644 --- a/util/grub.d/10_linux.in +++ b/util/grub.d/10_linux.in @@ -17,15 +17,14 @@ set -e # You should have received a copy of the GNU General Public License # along with GRUB. If not, see . -prefix=@prefix@ -exec_prefix=@exec_prefix@ -bindir=@bindir@ -libdir=@libdir@ -datarootdir=@datarootdir@ -. ${libdir}/@PACKAGE@/grub-mkconfig_lib +prefix="@prefix@" +exec_prefix="@exec_prefix@" +datarootdir="@datarootdir@" + +. "@datadir@/@PACKAGE@/grub-mkconfig_lib" export TEXTDOMAIN=@PACKAGE@ -export TEXTDOMAINDIR=@localedir@ +export TEXTDOMAINDIR="@localedir@" CLASS="--class gnu-linux --class gnu --class os" @@ -147,7 +146,7 @@ prepare_root_cache= while [ "x$list" != "x" ] ; do linux=`version_find_latest $list` - echo "Found linux image: $linux" >&2 + gettext_printf "Found linux image: %s\n" "$linux" >&2 basename=`basename $linux` dirname=`dirname $linux` rel_dirname=`make_system_path_relative_to_its_root $dirname` @@ -182,7 +181,7 @@ while [ "x$list" != "x" ] ; do fi if test -n "${initrd}" ; then - echo "Found initrd image: ${dirname}/${initrd}" >&2 + gettext_printf "Found initrd image: %s\n" "${dirname}/${initrd}" >&2 elif test -z "${initramfs}" ; then # "UUID=" magic is parsed by initrd or initramfs. Since there's # no initrd or builtin initramfs, it can't work here. diff --git a/util/grub.d/10_netbsd.in b/util/grub.d/10_netbsd.in index 8c232b01b..236842da1 100644 --- a/util/grub.d/10_netbsd.in +++ b/util/grub.d/10_netbsd.in @@ -17,15 +17,13 @@ set -e # You should have received a copy of the GNU General Public License # along with GRUB. If not, see . -prefix=@prefix@ -exec_prefix=@exec_prefix@ -bindir=@bindir@ -libdir=@libdir@ -datarootdir=@datarootdir@ -. ${libdir}/@PACKAGE@/grub-mkconfig_lib +prefix="@prefix@" +exec_prefix="@exec_prefix@" +datarootdir="@datarootdir@" +. "@datadir@/@PACKAGE@/grub-mkconfig_lib" export TEXTDOMAIN=@PACKAGE@ -export TEXTDOMAINDIR=@localedir@ +export TEXTDOMAINDIR="@localedir@" if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then OS="NetBSD" @@ -134,7 +132,7 @@ for k in $(ls -t /netbsd*) ; do continue fi - echo "Found NetBSD kernel: $k" >&2 + gettext_printf "Found NetBSD kernel: %s\n" "$k" >&2 netbsd_entry "knetbsd" "$k" false "${GRUB_CMDLINE_NETBSD_DEFAULT}" netbsd_entry "multiboot" "$k" false "${GRUB_CMDLINE_NETBSD_DEFAULT}" if [ "x${GRUB_DISABLE_RECOVERY}" != "xtrue" ]; then diff --git a/util/grub.d/10_windows.in b/util/grub.d/10_windows.in index 20fd4e044..4d8331dda 100644 --- a/util/grub.d/10_windows.in +++ b/util/grub.d/10_windows.in @@ -17,11 +17,11 @@ set -e # You should have received a copy of the GNU General Public License # along with GRUB. If not, see . -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -datarootdir=@datarootdir@ -. ${libdir}/@PACKAGE@/grub-mkconfig_lib +prefix="@prefix@" +exec_prefix="@exec_prefix@" +datarootdir="@datarootdir@" + +. "@datadir@/@PACKAGE@/grub-mkconfig_lib" case "`uname 2>/dev/null`" in CYGWIN*) ;; @@ -63,21 +63,21 @@ for drv in $drives ; do # Check for Vista bootmgr. if [ -f "$dir"/bootmgr -a -f "$dir"/boot/bcd ] ; then - OS="Windows Vista bootmgr" + OS="$(gettext_quoted "Windows Vista/7 (loader)")" # Check for NTLDR. elif [ -f "$dir"/ntldr -a -f "$dir"/ntdetect.com -a -f "$dir"/boot.ini ] ; then - OS=`get_os_name_from_boot_ini "$dir"/boot.ini` || OS="Windows NT/2000/XP loader" + OS=`get_os_name_from_boot_ini "$dir"/boot.ini` || OS="$(gettext_quoted "Windows NT/2000/XP (loader)")" needmap=t else continue fi - # Get boot /dev/ice. + # Get boot device. dev=`${grub_probe} -t device "$dir" 2>/dev/null` || continue - echo "Found $OS on $drv ($dev)" >&2 + gettext_printf "Found %s on %s (%s)\n" "$OS" "$drv" "$dev" >&2 cat << EOF menuentry "$OS" { EOF diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in index 2f1b4af88..56771abca 100644 --- a/util/grub.d/20_linux_xen.in +++ b/util/grub.d/20_linux_xen.in @@ -17,15 +17,14 @@ set -e # You should have received a copy of the GNU General Public License # along with GRUB. If not, see . -prefix=@prefix@ -exec_prefix=@exec_prefix@ -bindir=@bindir@ -libdir=@libdir@ -datarootdir=@datarootdir@ -. ${libdir}/@PACKAGE@/grub-mkconfig_lib +prefix="@prefix@" +exec_prefix="@exec_prefix@" +datarootdir="@datarootdir@" + +. "@datadir@/@PACKAGE@/grub-mkconfig_lib" export TEXTDOMAIN=@PACKAGE@ -export TEXTDOMAINDIR=@localedir@ +export TEXTDOMAINDIR="@localedir@" CLASS="--class gnu-linux --class gnu --class os --class xen" @@ -143,7 +142,7 @@ while [ "x${xen_list}" != "x" ] ; do echo "submenu \"Xen ${xen_version}\" {" while [ "x$list" != "x" ] ; do linux=`version_find_latest $list` - echo "Found linux image: $linux" >&2 + gettext_printf "Found linux image: %s\n" "$linux" >&2 basename=`basename $linux` dirname=`dirname $linux` rel_dirname=`make_system_path_relative_to_its_root $dirname` @@ -163,7 +162,7 @@ while [ "x${xen_list}" != "x" ] ; do fi done if test -n "${initrd}" ; then - echo "Found initrd image: ${dirname}/${initrd}" >&2 + gettext_printf "Found initrd image: %s\n" "${dirname}/${initrd}" >&2 else # "UUID=" magic is parsed by initrds. Since there's no initrd, it can't work here. linux_root_device_thisversion=${GRUB_DEVICE} diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in index c0b5d7cd7..63800c10b 100644 --- a/util/grub.d/30_os-prober.in +++ b/util/grub.d/30_os-prober.in @@ -17,11 +17,11 @@ set -e # You should have received a copy of the GNU General Public License # along with GRUB. If not, see . -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ +prefix="@prefix@" +exec_prefix="@exec_prefix@" +datarootdir="@datarootdir@" -. ${libdir}/@PACKAGE@/grub-mkconfig_lib +. "@datadir@/@PACKAGE@/grub-mkconfig_lib" if [ "x${GRUB_DISABLE_OS_PROBER}" = "xtrue" ]; then exit 0 @@ -39,8 +39,17 @@ if [ -z "${OSPROBED}" ] ; then fi osx_entry() { + if [ x$2 = x32 ]; then + # TRANSLATORS: it refers to kernel architecture (32-bit) + bitstr="$(gettext "(32-bit)")" + else + # TRANSLATORS: it refers to kernel architecture (64-bit) + bitstr="$(gettext "(64-bit)")" + fi + # TRANSLATORS: it refers on the OS residing on device %s + onstr="$(gettext_printf "(on %s)" "${DEVICE}")" cat << EOF -menuentry "${LONGNAME} (${2}-bit) (on ${DEVICE})" --class osx --class darwin --class os { +menuentry "${LONGNAME} $bitstr $onstr" --class osx --class darwin --class os { EOF save_default_entry | sed -e "s/^/\t/" prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/" @@ -99,13 +108,14 @@ for OS in ${OSPROBED} ; do LONGNAME="${LABEL}" fi - echo "Found ${LONGNAME} on ${DEVICE}" >&2 + gettext_printf "Found %s on %s\n" "${LONGNAME}" "${DEVICE}" >&2 case ${BOOT} in chain) + onstr="$(gettext_printf "(on %s)" "${DEVICE}")" cat << EOF -menuentry "${LONGNAME} (on ${DEVICE})" --class windows --class os { +menuentry "${LONGNAME} $onstr" --class windows --class os { EOF save_default_entry | sed -e "s/^/\t/" prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/" @@ -146,8 +156,9 @@ EOF LINITRD="${LINITRD#/boot}" fi + onstr="$(gettext_printf "(on %s)" "${DEVICE}")" cat << EOF -menuentry "${LLABEL} (on ${DEVICE})" --class gnu-linux --class gnu --class os { +menuentry "${LLABEL} $onstr" --class gnu-linux --class gnu --class os { EOF save_default_entry | sed -e "s/^/\t/" if [ -z "${prepare_boot_cache}" ]; then @@ -168,13 +179,14 @@ EOF done ;; macosx) - OSXUUID="`grub-probe --target=fs_uuid --device ${DEVICE} 2> /dev/null`" + OSXUUID="`${grub_probe} --target=fs_uuid --device ${DEVICE} 2> /dev/null`" osx_entry xnu_kernel 32 osx_entry xnu_kernel64 64 ;; hurd) + onstr="$(gettext_printf "(on %s)" "${DEVICE}")" cat << EOF -menuentry "${LONGNAME} (on ${DEVICE})" --class hurd --class gnu --class os { +menuentry "${LONGNAME} $onstr" --class hurd --class gnu --class os { EOF save_default_entry | sed -e "s/^/\t/" prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/" @@ -198,7 +210,8 @@ EOF EOF ;; *) - echo " ${LONGNAME} is not yet supported by grub-mkconfig." >&2 + echo -n " " + gettext_printf "%s is not yet supported by grub-mkconfig.\n" "${LONGNAME}" >&2 ;; esac done diff --git a/util/ieee1275/devicemap.c b/util/ieee1275/devicemap.c deleted file mode 100644 index 19ab746ef..000000000 --- a/util/ieee1275/devicemap.c +++ /dev/null @@ -1,49 +0,0 @@ -#include -#include -#include -#include -#include -#include - -/* Since OF path names can have "," characters in them, and GRUB - internally uses "," to indicate partitions (unlike OF which uses - ":" for this purpose) we escape such commas. */ - -static char * -escape_of_path (const char *orig_path) -{ - char *new_path, *d, c; - const char *p; - - if (!strchr (orig_path, ',')) - return (char *) orig_path; - - new_path = xmalloc (strlen (orig_path) * 2); - - p = orig_path; - d = new_path; - while ((c = *p++) != '\0') - { - if (c == ',') - *d++ = '\\'; - *d++ = c; - } - - free ((char *) orig_path); - - return new_path; -} - -void -grub_util_emit_devicemap_entry (FILE *fp, char *name, - int is_floppy __attribute__((unused)), - int *num_fd __attribute__((unused)), - int *num_hd __attribute__((unused))) -{ - const char *orig_path = grub_util_devname_to_ofpath (name); - char *ofpath = escape_of_path (orig_path); - - fprintf(fp, "(%s)\t%s\n", ofpath, name); - - free (ofpath); -} diff --git a/util/ieee1275/ofpath.c b/util/ieee1275/ofpath.c index 20a571191..1d39ac38b 100644 --- a/util/ieee1275/ofpath.c +++ b/util/ieee1275/ofpath.c @@ -54,6 +54,18 @@ grub_util_error (const char *fmt, ...) exit (1); } +void +grub_util_info (const char *fmt, ...) +{ + va_list ap; + + fprintf (stderr, "ofpath: info: "); + va_start (ap, fmt); + vfprintf (stderr, fmt, ap); + va_end (ap); + fputc ('\n', stderr); +} + #define _(x) x #endif @@ -83,64 +95,95 @@ trim_newline (char *path) *end-- = '\0'; } -#define OF_PATH_MAX 256 +#define MAX_DISK_CAT 64 -static void -find_obppath(char *of_path, const char *sysfs_path_orig) +static char * +find_obppath (const char *sysfs_path_orig) { char *sysfs_path, *path; + size_t path_size = strlen (sysfs_path_orig) + sizeof ("/obppath"); - sysfs_path = xmalloc (PATH_MAX); - path = xmalloc (PATH_MAX); + sysfs_path = xstrdup (sysfs_path_orig); + path = xmalloc (path_size); - strcpy(sysfs_path, sysfs_path_orig); while (1) { int fd; + char *of_path; + struct stat st; + size_t size; - snprintf(path, PATH_MAX, "%s/obppath", sysfs_path); + snprintf(path, path_size, "%s/obppath", sysfs_path); #if 0 printf("Trying %s\n", path); #endif fd = open(path, O_RDONLY); - if (fd < 0) + if (fd < 0 || fstat (fd, &st) < 0) { kill_trailing_dir(sysfs_path); if (!strcmp(sysfs_path, "/sys")) - grub_util_error(_("'obppath' not found in parent dirs of %s"), - sysfs_path_orig); + { + grub_util_info (_("'obppath' not found in parent dirs of %s," + " no IEEE1275 name discovery"), + sysfs_path_orig); + free (path); + free (sysfs_path); + return NULL; + } continue; } - memset(of_path, 0, OF_PATH_MAX); - read(fd, of_path, OF_PATH_MAX); + size = st.st_size; + of_path = xmalloc (size + MAX_DISK_CAT + 1); + memset(of_path, 0, size + MAX_DISK_CAT + 1); + read(fd, of_path, size); close(fd); trim_newline(of_path); - break; + free (path); + free (sysfs_path); + return of_path; } - - free (path); - free (sysfs_path); } -static void -block_device_get_sysfs_path_and_link(const char *devicenode, - char *sysfs_path, int sysfs_path_len) +static char * +xrealpath (const char *in) { - char *rpath = xmalloc (PATH_MAX); + char *out; +#ifdef PATH_MAX + out = xmalloc (PATH_MAX); + out = realpath (in, out); +#else + out = realpath (in, NULL); +#endif + if (!out) + grub_util_error (_("failed to get canonical path of %s"), in); + return out; +} - snprintf(sysfs_path, sysfs_path_len, "/sys/block/%s", devicenode); +static char * +block_device_get_sysfs_path_and_link(const char *devicenode) +{ + char *rpath; + char *rpath2; + char *ret; + size_t tmp_size = strlen (devicenode) + sizeof ("/sys/block/"); + char *tmp = xmalloc (tmp_size); - if (!realpath (sysfs_path, rpath)) - grub_util_error (_("cannot get the real path of `%s'"), sysfs_path); + memcpy (tmp, "/sys/block/", sizeof ("/sys/block/")); + strcat (tmp, devicenode); - strcat(rpath, "/device"); + rpath = xrealpath (tmp); + rpath2 = xmalloc (strlen (rpath) + sizeof ("/device")); + strcpy (rpath2, rpath); + strcat (rpath2, "/device"); - if (!realpath (rpath, sysfs_path)) - grub_util_error (_("cannot get the real path of `%s'"), rpath); + ret = xrealpath (rpath2); + free (tmp); free (rpath); + free (rpath2); + return ret; } static const char * @@ -159,28 +202,31 @@ trailing_digits (const char *p) return end + 1; } -static void -__of_path_common(char *of_path, char *sysfs_path, +static char * +__of_path_common(char *sysfs_path, const char *device, int devno) { const char *digit_string; - char disk[64]; + char disk[MAX_DISK_CAT]; + char *of_path = find_obppath(sysfs_path); - find_obppath(of_path, sysfs_path); + if (!of_path) + return NULL; digit_string = trailing_digits (device); if (*digit_string == '\0') { - sprintf(disk, "/disk@%d", devno); + snprintf(disk, sizeof (disk), "/disk@%d", devno); } else { int part; sscanf(digit_string, "%d", &part); - sprintf(disk, "/disk@%d:%c", devno, 'a' + (part - 1)); + snprintf(disk, sizeof (disk), "/disk@%d:%c", devno, 'a' + (part - 1)); } strcat(of_path, disk); + return of_path; } static char * @@ -198,71 +244,70 @@ get_basename(char *p) return ret; } -static void -of_path_of_vdisk(char *of_path, - const char *devname __attribute__((unused)), +static char * +of_path_of_vdisk(const char *devname __attribute__((unused)), const char *device, const char *devnode __attribute__((unused)), const char *devicenode) { char *sysfs_path, *p; int devno, junk; + char *ret; - sysfs_path = xmalloc (PATH_MAX); - block_device_get_sysfs_path_and_link(devicenode, - sysfs_path, PATH_MAX); + sysfs_path = block_device_get_sysfs_path_and_link(devicenode); p = get_basename (sysfs_path); sscanf(p, "vdc-port-%d-%d", &devno, &junk); - __of_path_common(of_path, sysfs_path, device, devno); + ret = __of_path_common (sysfs_path, device, devno); free (sysfs_path); + return ret; } -static void -of_path_of_ide(char *of_path, - const char *devname __attribute__((unused)), const char *device, +static char * +of_path_of_ide(const char *devname __attribute__((unused)), const char *device, const char *devnode __attribute__((unused)), const char *devicenode) { char *sysfs_path, *p; int chan, devno; + char *ret; - sysfs_path = xmalloc (PATH_MAX); - block_device_get_sysfs_path_and_link(devicenode, - sysfs_path, PATH_MAX); + sysfs_path = block_device_get_sysfs_path_and_link(devicenode); p = get_basename (sysfs_path); sscanf(p, "%d.%d", &chan, &devno); - __of_path_common(of_path, sysfs_path, device, devno); + ret = __of_path_common(sysfs_path, device, 2 * chan + devno); free (sysfs_path); + return ret; } static int vendor_is_ATA(const char *path) { int fd, err; - char *buf; + char *bufname; + char bufcont[3]; + size_t path_size; - buf = xmalloc (PATH_MAX); + path_size = strlen (path) + sizeof ("/vendor"); - snprintf(buf, PATH_MAX, "%s/vendor", path); - fd = open(buf, O_RDONLY); + bufname = xmalloc (path_size); + + snprintf (bufname, path_size, "%s/vendor", path); + fd = open (bufname, O_RDONLY); if (fd < 0) - grub_util_error (_("cannot open 'vendor' node of `%s'"), path); + grub_util_error (_("cannot open `%s': %s"), bufname, strerror (errno)); - memset(buf, 0, PATH_MAX); - err = read(fd, buf, PATH_MAX); + memset(bufcont, 0, sizeof (bufcont)); + err = read(fd, bufcont, sizeof (bufcont)); if (err < 0) - grub_util_error (_("cannot read 'vendor' node of `%s'"), path); + grub_util_error (_("cannot open `%s': %s"), bufname, strerror (errno)); close(fd); + free (bufname); - free (buf); - - if (!strncmp(buf, "ATA", 3)) - return 1; - return 0; + return (memcmp(bufcont, "ATA", 3) == 0); } static void @@ -272,6 +317,7 @@ check_sas (char *sysfs_path, int *tgt) char *p, *q, *path; char phy[16]; int fd; + size_t path_size; if (!ed) return; @@ -285,12 +331,14 @@ check_sas (char *sysfs_path, int *tgt) q++; *q = '\0'; - path = xmalloc (PATH_MAX); - sprintf (path, "%s/sas_device:%s/phy_identifier", p, ed); + path_size = (strlen (p) + strlen (ed) + + sizeof ("%s/sas_device:%s/phy_identifier")); + path = xmalloc (path_size); + snprintf (path, path_size, "%s/sas_device:%s/phy_identifier", p, ed); - fd = open(path, O_RDONLY); + fd = open (path, O_RDONLY); if (fd < 0) - grub_util_error(_("cannot open SAS PHY ID `%s'\n"), path); + grub_util_error (_("cannot open `%s': %s"), path, strerror (errno)); memset (phy, 0, sizeof (phy)); read (fd, phy, sizeof (phy)); @@ -302,33 +350,32 @@ check_sas (char *sysfs_path, int *tgt) close (fd); } -static void -of_path_of_scsi(char *of_path, - const char *devname __attribute__((unused)), const char *device, +static char * +of_path_of_scsi(const char *devname __attribute__((unused)), const char *device, const char *devnode __attribute__((unused)), const char *devicenode) { const char *p, *digit_string, *disk_name; int host, bus, tgt, lun; - char *sysfs_path, disk[64]; + char *sysfs_path, disk[MAX_DISK_CAT - sizeof ("/fp@0,0")]; + char *of_path; - sysfs_path = xmalloc (PATH_MAX); - - block_device_get_sysfs_path_and_link(devicenode, - sysfs_path, PATH_MAX); + sysfs_path = block_device_get_sysfs_path_and_link(devicenode); p = get_basename (sysfs_path); sscanf(p, "%d:%d:%d:%d", &host, &bus, &tgt, &lun); check_sas (sysfs_path, &tgt); if (vendor_is_ATA(sysfs_path)) { - __of_path_common(of_path, sysfs_path, device, tgt); + of_path = __of_path_common(sysfs_path, device, tgt); free (sysfs_path); - return; + return of_path; } - find_obppath(of_path, sysfs_path); + of_path = find_obppath(sysfs_path); free (sysfs_path); + if (!of_path) + return NULL; if (strstr (of_path, "qlc")) strcat (of_path, "/fp@0,0"); @@ -341,16 +388,18 @@ of_path_of_scsi(char *of_path, digit_string = trailing_digits (device); if (*digit_string == '\0') { - sprintf(disk, "/%s@%x,%d", disk_name, tgt, lun); + snprintf(disk, sizeof (disk), "/%s@%x,%d", disk_name, tgt, lun); } else { int part; sscanf(digit_string, "%d", &part); - sprintf(disk, "/%s@%x,%d:%c", disk_name, tgt, lun, 'a' + (part - 1)); + snprintf(disk, sizeof (disk), + "/%s@%x,%d:%c", disk_name, tgt, lun, 'a' + (part - 1)); } strcat(of_path, disk); + return of_path; } static char * @@ -375,32 +424,30 @@ grub_util_devname_to_ofpath (const char *devname) { char *name_buf, *device, *devnode, *devicenode, *ofpath; - name_buf = xmalloc (PATH_MAX); - name_buf = realpath (devname, name_buf); - if (! name_buf) - grub_util_error (_("cannot get the real path of `%s'"), devname); + name_buf = xrealpath (devname); device = get_basename (name_buf); devnode = strip_trailing_digits (name_buf); devicenode = strip_trailing_digits (device); - ofpath = xmalloc (OF_PATH_MAX); - if (device[0] == 'h' && device[1] == 'd') - of_path_of_ide(ofpath, name_buf, device, devnode, devicenode); + ofpath = of_path_of_ide(name_buf, device, devnode, devicenode); else if (device[0] == 's' && (device[1] == 'd' || device[1] == 'r')) - of_path_of_scsi(ofpath, name_buf, device, devnode, devicenode); + ofpath = of_path_of_scsi(name_buf, device, devnode, devicenode); else if (device[0] == 'v' && device[1] == 'd' && device[2] == 'i' && device[3] == 's' && device[4] == 'k') - of_path_of_vdisk(ofpath, name_buf, device, devnode, devicenode); + ofpath = of_path_of_vdisk(name_buf, device, devnode, devicenode); else if (device[0] == 'f' && device[1] == 'd' && device[2] == '0' && device[3] == '\0') /* All the models I've seen have a devalias "floppy". New models have no floppy at all. */ - strcpy (ofpath, "floppy"); + ofpath = xstrdup ("floppy"); else - grub_util_error (_("unknown device type %s\n"), device); + { + grub_util_warn (_("unknown device type %s\n"), device); + return NULL; + } free (devnode); free (devicenode); @@ -421,7 +468,8 @@ int main(int argc, char **argv) } of_path = grub_util_devname_to_ofpath (argv[1]); - printf("%s\n", of_path); + if (of_path) + printf("%s\n", of_path); free (of_path); return 0; diff --git a/util/import_gcry.py b/util/import_gcry.py index ec34d16b5..3493361d7 100644 --- a/util/import_gcry.py +++ b/util/import_gcry.py @@ -105,8 +105,6 @@ for cipher_file in cipher_files: fw.write ("/* This file was automatically imported with \n") fw.write (" import_gcry.py. Please don't modify it */\n") fw.write ("#include \n") - if cipher_file == "camellia.c": - fw.write ("#include \"camellia.h\"\n") if cipher_file == "camellia.h": fw.write ("#include \n") fw.write ("void camellia_setup128(const unsigned char *key, grub_uint32_t *subkey);\n") @@ -192,8 +190,10 @@ for cipher_file in cipher_files: if hold: hold = False # We're optimising for size. - if not re.match ("(run_selftests|selftest|_gcry_aes_c.._..c|_gcry_[a-z0-9]*_hash_buffer|tripledes_set2keys|do_tripledes_set_extra_info)", line) is None: + if not re.match ("(run_selftests|selftest|_gcry_aes_c.._..c|_gcry_[a-z0-9]*_hash_buffer|tripledes_set2keys|do_tripledes_set_extra_info|_gcry_rmd160_mixblock|serpent_test)", line) is None: skip = True + if not re.match ("serpent_test", line) is None: + fw.write ("static const char *serpent_test (void) { return 0; }\n"); fname = re.match ("[a-zA-Z0-9_]*", line).group () chmsg = "(%s): Removed." % fname if nch: @@ -323,7 +323,11 @@ for cipher_file in cipher_files: for src in modfiles.split(): conf.write (" common = %s;\n" % src) confutil.write (" common = grub-core/%s;\n" % src) - conf.write (" cflags = '$(CFLAGS_GCRY)';\n"); + if modname == "gcry_rijndael" or modname == "gcry_md4" or modname == "gcry_md5" or modname == "gcry_rmd160" or modname == "gcry_sha1" or modname == "gcry_sha256" or modname == "gcry_sha512" or modname == "gcry_tiger": + # Alignment checked by hand + conf.write (" cflags = '$(CFLAGS_GCRY) -Wno-cast-align -Wno-strict-aliasing';\n"); + else: + conf.write (" cflags = '$(CFLAGS_GCRY)';\n"); conf.write (" cppflags = '$(CPPFLAGS_GCRY)';\n"); conf.write ("};\n\n") elif isc and cipher_file != "camellia.c": @@ -372,6 +376,7 @@ outfile = os.path.join (cipher_dir_out, "ChangeLog") conf.close (); initfile = codecs.open (os.path.join (cipher_dir_out, "init.c"), "w", "utf-8") +initfile.write ("#include \n") for module in modules: initfile.write ("extern void grub_%s_init (void);\n" % module) initfile.write ("extern void grub_%s_fini (void);\n" % module) diff --git a/util/import_unicode.py b/util/import_unicode.py index 8d17e7ef6..ec3db0842 100644 --- a/util/import_unicode.py +++ b/util/import_unicode.py @@ -130,9 +130,13 @@ for line in infile: if begincode != -2 and (lastbiditype != "L" or lastcombtype != 0 or \ lastmirrortype): outfile.write (("{0x%x, 0x%x, GRUB_BIDI_TYPE_%s, %d, %d, GRUB_JOIN_TYPE_%s},\n" \ - % (begincode, lastcode, lastbiditype, \ + % (begincode, lastcode - begincode + 1, \ + lastbiditype, \ lastcombtype, lastmirrortype, \ lastjoin))) + if lastcode - begincode + 1 >= 0x200: + print "Too long range" + raise begincode = curcode lastcode = curcode lastjoin = curjoin diff --git a/util/misc.c b/util/misc.c index 6ebaf30bc..93fa0b4bd 100644 --- a/util/misc.c +++ b/util/misc.c @@ -83,20 +83,6 @@ grub_util_get_path (const char *dir, const char *file) return path; } -size_t -grub_util_get_fp_size (FILE *fp) -{ - struct stat st; - - if (fflush (fp) == EOF) - grub_util_error (_("fflush failed")); - - if (fstat (fileno (fp), &st) == -1) - grub_util_error (_("fstat failed")); - - return st.st_size; -} - size_t grub_util_get_image_size (const char *path) { @@ -105,21 +91,11 @@ grub_util_get_image_size (const char *path) grub_util_info ("getting the size of %s", path); if (stat (path, &st) == -1) - grub_util_error (_("cannot stat %s"), path); + grub_util_error (_("cannot stat `%s': %s"), path, strerror (errno)); return st.st_size; } -void -grub_util_read_at (void *img, size_t size, off_t offset, FILE *fp) -{ - if (fseeko (fp, offset, SEEK_SET) == -1) - grub_util_error (_("seek failed")); - - if (fread (img, 1, size, fp) != size) - grub_util_error (_("read failed")); -} - char * grub_util_read_image (const char *path) { @@ -134,9 +110,12 @@ grub_util_read_image (const char *path) fp = fopen (path, "rb"); if (! fp) - grub_util_error (_("cannot open %s"), path); + grub_util_error (_("cannot open `%s': %s"), path, + strerror (errno)); - grub_util_read_at (img, size, 0, fp); + if (fread (img, 1, size, fp) != size) + grub_util_error (_("cannot read `%s': %s"), path, + strerror (errno)); fclose (fp); @@ -155,36 +134,44 @@ grub_util_load_image (const char *path, char *buf) fp = fopen (path, "rb"); if (! fp) - grub_util_error (_("cannot open %s"), path); + grub_util_error (_("cannot open `%s': %s"), path, + strerror (errno)); if (fread (buf, 1, size, fp) != size) - grub_util_error (_("cannot read %s"), path); + grub_util_error (_("cannot read `%s': %s"), path, + strerror (errno)); fclose (fp); } void -grub_util_write_image_at (const void *img, size_t size, off_t offset, FILE *out) +grub_util_write_image_at (const void *img, size_t size, off_t offset, FILE *out, + const char *name) { - grub_util_info ("writing 0x%x bytes at offset 0x%x", size, offset); + grub_util_info ("writing 0x%" PRIxGRUB_SIZE " bytes at offset 0x%llx", + size, (unsigned long long) offset); if (fseeko (out, offset, SEEK_SET) == -1) - grub_util_error (_("seek failed")); + grub_util_error (_("cannot seek `%s': %s"), + name, strerror (errno)); if (fwrite (img, 1, size, out) != size) - grub_util_error (_("write failed")); + grub_util_error (_("cannot write to `%s': %s"), + name, strerror (errno)); } void -grub_util_write_image (const char *img, size_t size, FILE *out) +grub_util_write_image (const char *img, size_t size, FILE *out, + const char *name) { - grub_util_info ("writing 0x%x bytes", size); + grub_util_info ("writing 0x%" PRIxGRUB_SIZE " bytes", size); if (fwrite (img, 1, size, out) != size) - grub_util_error (_("write failed")); -} - -char * -grub_script_execute_argument_to_string (struct grub_script_arg *arg __attribute__ ((unused))) -{ - return 0; + { + if (!name) + grub_util_error (_("cannot write to the stdout: %s"), + strerror (errno)); + else + grub_util_error (_("cannot write to `%s': %s"), + name, strerror (errno)); + } } grub_err_t @@ -217,12 +204,6 @@ grub_script_execute_cmdwhile (struct grub_script_cmd *cmd __attribute__ ((unused return 0; } -grub_err_t -grub_script_execute_menuentry (struct grub_script_cmd *cmd __attribute__ ((unused))) -{ - return 0; -} - grub_err_t grub_script_execute (struct grub_script *script) { @@ -232,12 +213,6 @@ grub_script_execute (struct grub_script *script) return script->cmd->exec (script->cmd); } -void -grub_putchar (int c) -{ - putchar (c); -} - int grub_getkey (void) { diff --git a/util/powerpc/ieee1275/grub-mkrescue.in b/util/powerpc/ieee1275/grub-mkrescue.in index d688431c3..7742906b3 100644 --- a/util/powerpc/ieee1275/grub-mkrescue.in +++ b/util/powerpc/ieee1275/grub-mkrescue.in @@ -20,39 +20,42 @@ set -e # Initialize some variables. transform="@program_transform_name@" -prefix=@prefix@ -exec_prefix=@exec_prefix@ -bindir=@bindir@ -libdir=@libdir@ +prefix="@prefix@" +exec_prefix="@exec_prefix@" +bindir="@bindir@" +libdir="@libdir@" PACKAGE_NAME=@PACKAGE_NAME@ PACKAGE_TARNAME=@PACKAGE_TARNAME@ PACKAGE_VERSION=@PACKAGE_VERSION@ target_cpu=@target_cpu@ platform=@platform@ pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}` +datarootdir="@datarootdir@" +datadir="@datadir@" +if [ "x$pkgdatadir" = x ]; then + pkgdatadir="${datadir}/`echo @PACKAGE_TARNAME@ | sed "${transform}"`" +fi self=`basename $0` -grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` +grub_mkimage="${bindir}/`echo grub-mkimage | sed ${transform}`" + +. "${pkgdatadir}/grub-mkconfig_lib" # Usage: usage # Print the usage. usage () { - cat <. -EOF + gettext_printf "Usage: %s [OPTION] SOURCE...\n" "$self" + gettext "Make GRUB CDROM, disk, pendrive and floppy bootable image."; echo + echo + printf " -h, --help %s\n" "$(gettext "print this message and exit")" + printf " -v, --version %s\n" "$(gettext "print the version information and exit")" + printf " --modules=%-14s%s\n" "$(gettext "MODULES")" "$(gettext "pre-load specified modules MODULES")" + printf " --grub-mkimage=%-9s%s\n" "$(gettext "FILE")" "$(gettext "use FILE as grub-mkimage")" + 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" "genisoimage -help" "$self" + echo + gettext "Report bugs to ."; echo } argument () { @@ -60,7 +63,7 @@ argument () { shift if test $# -eq 0; then - echo "$0: option requires an argument -- '$opt'" 1>&2 + gettext_printf "%s: option requires an argument -- '%s'\n" "$0" "$opt" 1>&2 exit 1 fi echo $1 @@ -68,6 +71,9 @@ argument () { input_dir=${pkglibdir} +source= +output_image= + # Check the arguments. while test $# -gt 0 do @@ -87,28 +93,23 @@ do --modules=*) modules=`echo "$option" | sed 's/--modules=//'` ;; - --pkglibdir) + --override-directory) input_dir=`argument $option "$@"`; shift ;; - --pkglibdir=*) - input_dir=`echo "$option" | sed 's/--pkglibdir=//'` ;; + --override-directory=*) + input_dir=`echo "$option" | sed 's/--override-directory=//'` ;; --grub-mkimage) grub_mkimage=`argument $option "$@"`; shift ;; --grub-mkimage=*) grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;; - -*) - echo "Unrecognized option \`$option'" 1>&2 - usage - exit 1 - ;; + -o | --output) + output_image=`argument $option "$@"`; shift ;; + --output=*) + output_image=`echo "$option" | sed 's/--output=//'` ;; + *) - if test "x$output_image" != x; then - echo "Unrecognized option \`$option'" 1>&2 - usage - exit 1 - fi - output_image="${option}" ;; + source="${source} ${option} $@"; break ;; esac done @@ -135,7 +136,7 @@ core_img=${boot_dir}/grub.img ${grub_mkimage} -O powerpc-ieee1275 -n -d ${input_dir}/ -o ${core_img} ${modules} genisoimage -hfs -part -no-desktop -r -J -o ${output_image} \ -map ${map_file} -hfs-bless ${boot_dir} -chrp-boot -sysid PPC \ - ${iso_dir} + ${iso_dir} ${source} rm -rf ${iso_dir} rm -f ${map_file} diff --git a/util/raid.c b/util/raid.c index 8de5fbac0..0851bff96 100644 --- a/util/raid.c +++ b/util/raid.c @@ -47,7 +47,7 @@ grub_util_raid_getmembers (const char *name, int bootable) fd = open (name, O_RDONLY); if (fd == -1) - grub_util_error (_("can't open %s: %s"), name, strerror (errno)); + grub_util_error (_("cannot open `%s': %s"), name, strerror (errno)); ret = ioctl (fd, RAID_VERSION, &version); if (ret != 0) diff --git a/util/resolve.c b/util/resolve.c index 3eb8bfb14..a07c454b9 100644 --- a/util/resolve.c +++ b/util/resolve.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -241,7 +242,7 @@ grub_util_resolve_dependencies (const char *prefix, path = grub_util_get_path (prefix, dep_list_file); fp = fopen (path, "r"); if (! fp) - grub_util_error (_("cannot open %s"), path); + grub_util_error (_("cannot open `%s': %s"), path, strerror (errno)); free (path); dep_list = read_dep_list (fp); diff --git a/util/update-grub_lib.in b/util/update-grub_lib.in deleted file mode 100644 index 430ce1308..000000000 --- a/util/update-grub_lib.in +++ /dev/null @@ -1,23 +0,0 @@ -# stub for new grub-mkconfig_lib -# Copyright (C) 2007,2008 Free Software Foundation, Inc. -# -# GRUB is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# GRUB is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GRUB. If not, see . - -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ - -. ${libdir}/@PACKAGE@/grub-mkconfig_lib - -grub_warn "update-grub_lib is deprecated, use grub-mkconfig_lib instead"