diff --git a/.bzrignore b/.bzrignore index cfdd069fd..5c121e652 100644 --- a/.bzrignore +++ b/.bzrignore @@ -4,6 +4,8 @@ 30_os-prober 40_custom 41_custom +*.1 +*.8 aclocal.m4 ascii.bitmaps ascii.h @@ -18,8 +20,6 @@ config.log config.status config.sub configure -conf/*.mk -*.d DISTLIST docs/*.info docs/stamp-vti @@ -58,11 +58,15 @@ grub-set-default grub-setup grub_setup_init.c grub_setup_init.h +grub-shell +grub-shell-tester *.img +*.image include/grub/cpu include/grub/machine install-sh lib/libgcrypt-grub +libgrub_a_init.c *.lst Makefile *.mod @@ -76,6 +80,7 @@ stamp-h stamp-h1 stamp-h.in symlist.c +symlist.h trigtables.c update-grub_lib unidata.c @@ -99,3 +104,4 @@ grub-core/Makefile.gcry.am grub-core/Makefile.gcry.def grub-core/*.module grub-core/*.pp +util/bash-completion.d/grub diff --git a/ChangeLog b/ChangeLog index 0f79aaa87..ddf61f442 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,786 @@ +2010-09-19 Colin Watson +2010-09-19 Vladimir Serbinenko + + * Makefile.util.def (grub-install): Use util/grub-install.in on all + platforms. + * util/grub-install.in: Add EFI and IEEE1275 support. + * util/i386/efi/grub-install.in: Removed. + * util/ieee1275/grub-install.in: Likewise. + +2010-09-19 Vladimir Serbinenko + + * grub-core/commands/i386/cmostest.c (+parse_args): New function. + (grub_cmd_cmosclean): Likewise. + (GRUB_MOD_INIT): Register command cmosclean. + * util/grub-mkconfig.in: Export GRUB_BUTTON_CMOS_CLEAN. + * util/grub.d/00_header.in: Handle GRUB_BUTTON_CMOS_CLEAN. + +2010-09-18 Carles Pina i Estany +2010-09-18 Aleš Nesrsta +2010-09-18 Vladimir Serbinenko + + Add keyboard layouts support. + + * Makefile.util.def (grub-mklayout): New file. + (grub-kbdcomp): New script. + * grub-core/Makefile.am (KERNEL_HEADER_FILES) [COND_mips_yeeloong]: + Add keyboard_layouts.h. + * grub-core/Makefile.core.def (kernel): Add commands/keylayouts.c and + commands/boot.c on yeeloong. + (keylayouts): New module. + * grub-core/bus/usb/ohci.c + * grub-core/bus/usb/uhci.c + * grub-core/bus/usb/usbhub.c (rescan): New variable. + (grub_usb_add_hub): Poll interrupt pipe for device handling. + (attach_root_port): Likewise. + (poll_nonroot_hub): Likewise. + (grub_usb_poll_devices): Likewise. + (detach_device): Close transfer. + * grub-core/bus/usb/usbtrans.c (grub_usb_execute_and_wait_transfer): New + function. + (grub_usb_bulk_setup_readwrite): Likewise. + (grub_usb_bulk_finish_readwrite): Likewise. + * grub-core/commands/keylayouts.c: New file. + * grub-core/commands/keystatus.c (grub_getkeystatus): New function. + * grub-core/commands/menuentry.c (hotkey_aliases): All several new + aliases. + * grub-core/term/at_keyboard.c: Restructured to use keylayouts and + support scancode 2. + * grub-core/term/usb_keyboard.c: Restructured to use keylayouts. + * include/grub/keyboard_layouts.h: New file. + * util/grub-mklayout.c: New file. + * util/grub-kbdcomp.in: Likewise. + +2010-09-18 Vladimir Serbinenko + + Unify memory types. + + * grub-core/Makefile.am (KERNEL_HEADER_FILES): Include memory.h. + * grub-core/commands/lsmmap.c (grub_cmd_lsmmap): Output user-readable + types. + * grub-core/kern/i386/multiboot_mmap.c (grub_lower_mem): Removed. + (grub_upper_mem): Likewise. + * grub-core/kern/ieee1275/init.c (grub_upper_mem): Likewise. + * include/grub/memory.h (grub_memory_type_t): New enum. + All users updated. + +2010-09-18 Vladimir Serbinenko + + * grub-core/Makefile.core.def (lsapm): New module. + * grub-core/commands/i386/pc/lsapm.c: New file. + * grub-core/loader/i386/multiboot_mbi.c (make_mbi) [GRUB_MACHINE_PCBIOS]: Pass APM info. + * grub-core/loader/multiboot_mbi2.c (make_mbi) [GRUB_MACHINE_PCBIOS]: + Likewise. + * include/grub/i386/pc/apm.h: New file. + * include/multiboot.h (multiboot_apm_info): New struct. + +2010-09-18 Vladimir Serbinenko + + GRUB-legacy configuration file support. + + * Makefile.util.def (grub-menulst2cfg): New util. + * docs/man/grub-menulst2cfg.h2m: New file. + * grub-core/Makefile.core.def (legacycfg): New module. + * grub-core/commands/legacycfg.c: New file. + * grub-core/commands/menuentry.c (append_menu_entry): Rename to ... + (grub_normal_add_menu_entry): ... this. + * grub-core/commands/password.c (grub_cmd_password): Split main part to ... + (grub_normal_set_password): ...this. + * grub-core/commands/videoinfo.c (grub_cmd_videoinfo): Support MODE. + * grub-core/loader/i386/linux.c (linux_vesafb_res): Move to .., + * grub-core/lib/i386/pc/vesa_modes_table.c: ... here. + * grub-core/lib/legacy_parse.c: New file. + * grub-core/normal/auth.c (grub_cmd_authenticate): New command. + * include/grub/i386/pc/vesa_modes_table.h: New file. + * include/grub/legacy_parse.h: Likewise. + * include/grub/normal.h (grub_normal_add_menu_entry): New proto. + * util/grub-menulst2cfg.c: New file. + +2010-09-17 Colin Watson + + * grub-core/kern/emu/hostdisk.c + (convert_system_partition_to_system_disk): Initialise node. + +2010-09-17 Colin Watson + + * grub-core/kern/emu/hostdisk.c + (convert_system_partition_to_system_disk): Fix devmapper memory pool + leak. + Reported and based on patch by: Modestas Vainius. + +2010-09-17 Colin Watson + + Fix DM-RAID probing with recent versions of device-mapper udev + rules. + + * grub-core/kern/emu/hostdisk.c (read_device_map): Don't + canonicalise device paths under /dev/mapper/. + (convert_system_partition_to_system_disk): Compare the + uncanonicalised path to /dev/mapper/ rather than the canonicalised + path, since device nodes under /dev/mapper/ are often symlinks. + +2010-09-17 Yves Blusseau + + * .bzrignore: *.d removed (old rule), add *.image and symlist.h. + +2010-09-16 Yves Blusseau + + * configure.ac: Avoid some annoying error messages if freetype-config + program is not found. + +2010-09-16 Colin Watson + + Support RAID on virtio devices, and others. + + * grub-core/kern/emu/getroot.c [__MINGW32__] (find_root_device): + Rename to ... + [__MINGW32__] (grub_find_device): ... this. + [! __MINGW32__ && ! __CYGWIN__] (find_root_device): Rename to ... + [! __MINGW32__ && ! __CYGWIN__] (grub_find_device): ... this. Use a + reasonable default if dir is NULL. + [! __MINGW32__ && __CYGWIN__] (find_cygwin_root_device): Rename to + ... + [! __MINGW32__ && __CYGWIN__] (grub_find_device): ... this. + (grub_guess_root_device): Update callers. + * include/grub/emu/getroot.h (grub_find_device): Add prototype. + + * util/raid.c (grub_util_getdiskname): Remove. + (grub_util_raid_getmembers): Use grub_find_device rather than + grub_util_getdiskname. + +2010-09-16 Colin Watson + + * docs/grub.texi (serial): Remove obsolete comment about GRUB + needing to be compiled with serial support. + (ls): Indicate that multiple files are accepted. + * grub-core/commands/ls.c (GRUB_MOD_INIT): Update help text to + indicate that multiple files are accepted. + +2010-09-16 Colin Watson + + * .bzrignore: Add *.1, *.8, grub-shell, grub-shell-tester, + libgrub_a_init.c, and util/bash-completion.d/grub. + +2010-09-15 Vladimir Serbinenko + + * util/grub-setup.c (setup): Fix incorrect container semantics. + +2010-09-15 Vladimir Serbinenko + + * grub-core/commands/parttool.c (grub_cmd_parttool): Fix a variable + misusage. + Reported by: J. Nick Terry + +2010-09-15 Vladimir Serbinenko + + Move embedding routines to partmap sources files. + + * grub-core/partmap/gpt.c (grub_gpt_partition_type_bios_boot) + [GRUB_UTIL]: New variable. + (gpt_partition_map_iterate): Set part.parent. + (gpt_partition_map_embed) [GRUB_UTIL]: New function. + (grub_gpt_partition_map) [GRUB_UTIL]: Set .embed. + * grub-core/partmap/msdos.c (pc_partition_map_embed) [GRUB_UTIL]: + New function. + (grub_msdos_partition_map) [GRUB_UTIL]: Set .embed. + * include/grub/partition.h (grub_embed_type_t) [GRUB_UTIL]: New type. + (grub_partition_map) [GRUB_UTIL]: New field embed. + * util/grub-setup.c (grub_gpt_partition_type_bios_boot): Removed. + (setup): Use ->embed. + +2010-09-15 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_is_floppy): New + function. + * include/grub/emu/hostdisk.h (grub_util_biosdisk_is_floppy): New proto. + * util/grub-setup.c (setup): Use grub_util_biosdisk_is_floppy. + +2010-09-15 Yves Blusseau + + Add function to get completions from usage. + + * util/bash-completion.d/grub-completion.bash.in: Add function to get + completions from usage. Use LC_ALL=C to get options properly. + +2010-09-15 Vladimir Serbinenko + + * grub-core/gnulib/basename-lgpl.c: Imported. + * grub-core/gnulib/basename.c: Likewise. + * grub-core/gnulib/dirname-lgpl.c: Likewise. + * grub-core/gnulib/dirname.c: Likewise. + * grub-core/gnulib/dirname.h: Likewise. + * grub-core/gnulib/stripslash.c: Likewise. + +2010-09-15 Vladimir Serbinenko + + * grub-core/gnulib/error.c: Resynced. + * grub-core/gnulib/getopt.c: Likewise. + * grub-core/gnulib/getopt_int.h: Likewise. + * grub-core/gnulib/regex.h: Likewise. + * grub-core/gnulib/regex_internal.c: Likewise. + * grub-core/gnulib/regex_internal.h: Likewise. + +2010-09-15 Szymon Janc + + * grub-core/lib/xzembed/xz_dec_stream.c (dec_main): Fix index and block + CRC calculations and validity checks. + * grub-core/lib/xzembed/xz_dec_stream.c (dec_index): Fix index CRC + calculations. + +2010-09-15 Szymon Janc + + * grub-core/lib/xzembed/xz_dec_stream.c (xz_dec_end): Fix memory leak. + +2010-09-14 Vladimir Serbinenko + + Fix incorrect echo options handling. + Reported by: Yves Blusseau. + + * include/grub/command.h (grub_command_flags_t): New flags + GRUB_COMMAND_ACCEPT_DASH and GRUB_COMMAND_OPTIONS_AT_START. + * grub-core/lib/arg.c (grub_arg_parse): Handle new flags. + * grub-core/commands/echo.c (GRUB_MOD_INIT): Use new flags. + +2010-09-14 Vladimir Serbinenko + + * include/grub/command.h (GRUB_COMMAND_FLAG_CMDLINE): Removed. All + users updated. + (GRUB_COMMAND_FLAG_MENU): Likewise. + (GRUB_COMMAND_FLAG_BOTH): Likewise. + (GRUB_COMMAND_FLAG_TITLE): Removed. + (GRUB_COMMAND_FLAG_NO_ECHO): Likewise. + (GRUB_COMMAND_FLAG_EXTCMD): Moved into enum. + (GRUB_COMMAND_FLAG_DYNCMD): Likewise. + (GRUB_COMMAND_FLAG_BLOCKS): Likewise. + (grub_command_flags_t): New enum. All users updated. + +2010-09-14 Seth Goldberg + + Fix solaris compilation. + + * grub-core/Makefile.core.def (kernel): Include gnulib/error.c on emu. + (grub-emu): Add LIBZFS and LIBNVPAIR to ldadd. + (grub-emu-list): Likewise. + +2010-09-14 Vladimir Serbinenko + + Remove deprecated root command. + + * grub-core/commands/minicmd.c (grub_mini_cmd_root): Removed. All users + updated. + +2010-09-14 Vladimir Serbinenko + + * util/i386/pc/grub-setup.c: Merge this ... + * util/sparc64/ieee1275/grub-setup.c: ... and this ... + * util/grub-setup.c: ... into this. + * include/grub/sparc64/ieee1275/boot.h (grub_boot_blocklist) [ASM_FILE]: + New struct. + +2010-09-14 Vladimir Serbinenko + + * grub-core/fs/ext2.c (grub_ext2_open): Use return error value when + possible. + +2010-09-14 Vladimir Serbinenko + + * grub-core/partmap/sun.c (sun_partition_map_iterate): Don't needlesly + allocate p. + +2010-09-14 Vladimir Serbinenko + + * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Add + explicit root argument to set to prevent UUID to be interpreted as + argument to set. + +2010-09-14 Vladimir Serbinenko + + * grub-core/kern/sparc64/ieee1275/crt0.S: Align stack. + +2010-09-14 Vladimir Serbinenko + + Don't export grub_gate_a20. + + * grub-core/kern/i386/pc/init.c: Remove leftovers. + * grub-core/kern/i386/pc/startup.S (FUNCTION(grub_gate_a20)): Rename + to ... + (grub_gate_a20): ... this. All users updated. + * include/grub/i386/pc/init.h: Removed. All users updated. + +2010-09-14 Vladimir Serbinenko + + Create euro.pf2 which supports most European languages. + + * Makefile.am (grubdata_DATA): Add euro.pf2. + (euro.pf2): New target. + (CLEANFILES): Add euro.pf2. + +2010-09-14 Vladimir Serbinenko + + * configure.ac: Disable emu-usb by default to prevent inadvertent + device takeover. + +2010-09-13 Vladimir Serbinenko + + Disable usbserial on grub-emu since our libusb code isn't good enough + yet. + + * grub-core/Makefile.core.def (usbserial_common): Disable on emu. + (usbserial_pl2303): Likewise. + (usbserial_ftdi): Likewise. + +2010-09-13 Vladimir Serbinenko + + * include/grub/disk.h (grub_disk): Remove has_partitions. + All users updated. + * disk/loopback.c (grub_loopback): Remove has_partitions. + All users updated. + (options): Remove partitions. All users updated. + * util/grub-fstest.c (fstest): Don't pass "-p" to loopback. + * util/i386/pc/grub-setup.c (setup): copy partition table only when + actual partition table is found. + +2010-09-13 Vladimir Serbinenko + + Remove readability checks (too many false negatives). + + * util/grub-install.in: Remove readability checks. + * util/grub-mkconfig.in: Likewise. + * util/grub.d/10_hurd.in: Likewise. + * util/grub.d/10_kfreebsd.in: Likewise. + * util/grub.d/10_linux.in: Likewise. + * util/grub-mkconfig_lib.in (is_path_readable_by_grub): Revert to old + way. + +2010-09-13 Vladimir Serbinenko + + Enable acpi shutdown on all ACPI platforms. + + * grub-core/Makefile.core.def (halt): Inlude commands/acpihalt.c + on coreboo, multiboot and EFI. + * grub-core/commands/acpihalt.c (get_sleep_type): Add missing casts. + (grub_acpi_halt): Likewise. + * grub-core/commands/i386/pc/halt.c (grub_halt): Call grub_acpi_halt. + (grub_cmd_halt): Don't call grub_acpi_halt directly. + * grub-core/lib/efi/halt.c (grub_halt): Call grub_acpi_halt. + * grub-core/lib/i386/halt.c (grub_halt) + [GRUB_MACHINE_COREBOOT || GRUB_MACHINE_MULTIBOOT]: Likewise. + +2010-09-13 Vladimir Serbinenko + + * grub-core/commands/iorw.c (grub_cmd_read): Declare buf in smallest + context. + +2010-09-13 Vladimir Serbinenko + + * grub-core/video/efi_gop.c: Fix over-80-chars line. + * grub-core/video/efi_uga.c: Likewise. + +2010-09-13 Vladimir Serbinenko + + Filter devaliases and never open same device twice. + + * grub-core/disk/ieee1275/ofdisk.c (last_devpath): New variable. + (last_ihandle): Likewise. + (ofdisk_hash_ent): New member shortest. + (ofdisk_hash_add): Add canonical path too. + (scan): New function. + (grub_ofdisk_iterate): Iterate over hashed entries. + (compute_dev_path): Don't add :0. + (grub_ofdisk_open): Don't really open the disk. + (grub_ofdisk_close): Avoid closing unrelated disk. + (grub_ofdisk_read): Implement reopen logic. + * grub-core/kern/ieee1275/openfw.c (grub_ieee1275_canonicalise_devname): + New function. + * include/grub/ieee1275/ieee1275.h (grub_ieee1275_canonicalise_devname): + New proto. + +2010-09-13 Vladimir Serbinenko + + Fix sparc64. + + * configure.ac (GRUB_KERNEL_MACHINE_LINK_ADDR): Removed. + * grub-core/Makefile.core.def (kernel): Make ldflags just use the + right address. Add sparc64_ieee1275_ldflags. + * grub-core/loader/sparc64/ieee1275/linux.c: Remove leftover include. + * util/grub-mkimagexx.c (locate_sections): Correct grub_host_to_target32 + to grub_host_to_target_addr + (load_image): Likewise. + +2010-09-13 Vladimir Serbinenko + + * grub-core/normal/completion.c (complete_file): Handle device + containing slash. + Fix based on patch by Doug Nazar. + +2010-09-13 Vladimir Serbinenko + + grub-mknetdir script. + + * Makefile.util.def (grub-mknetdir): New module. + * tests/util/grub-shell.in: Support boot=net + * util/grub-mknetdir.in: New file. + +2010-09-13 Vladimir Serbinenko + + videoinfo on non-vbe. + + * grub-core/Makefile.core.def (vbeinfo): Removed. + (vbetest): Removed. + (videoinfo): New module. + * grub-core/commands/i386/pc/vbeinfo.c: Removed. + * grub-core/commands/i386/pc/vbetest.c: Removed. + * grub-core/commands/videoinfo.c: New file. + * grub-core/commands/videotest.c (grub_cmd_videotest): Support mode + specification. + (grub_cmd_videotest) [GRUB_MACHINE_PCBIOS]: Load vbe.mod when invoked + as vbetest. + (GRUB_MOD_INIT) [GRUB_MACHINE_PCBIOS]: New command vbetest. + (GRUB_MOD_FINI) [GRUB_MACHINE_PCBIOS]: Unregister vbetest. + * grub-core/video/efi_gop.c (grub_video_gop_fill_mode_info): Fill + mode_number. New parameter mode. All users updated. + (grub_video_gop_iterate): New function. + (grub_video_efi_gop): New member iterate. + * grub-core/video/i386/pc/vbe.c (framebuffer): Removed leftover fields. + (grub_vbe_set_video_mode): Remove setting useless fields. + (vbe2videoinfo): New function. + (grub_video_vbe_iterate): Likewise. + (grub_video_vbe_setup): Use vbe2videoinfo. + (grub_video_vbe_print_adapter_specific_info): New function. + (grub_video_vbe_adapter): New fields iterate and + print_adapter_specific_info. + * include/grub/video.h (GRUB_VIDEO_MODE_*): Transform into enum. + All users updated. + (grub_video_mode_info): New field mode_number. + (grub_video_adapter): New fields iterate and + print_adapter_specific_info. + +2010-09-13 Tristan Gingold +2010-09-13 Robert Millan +2010-09-13 Vladimir Serbinenko + + * grub-core/commands/efi/lsefisystab.c: New file. + * grub-core/commands/efi/lssal.c: Likewise. + * grub-core/Makefile.core.def (lsacpi): New module. + (lsefisystab): Likewise. + * include/grub/efi/api.h (GRUB_EFI_SAL_TABLE_GUID): New definition. + (GRUB_EFI_HCDP_TABLE_GUID): Likewise. + (grub_efi_sal_system_table): New struct. + (grub_efi_sal_system_table_entrypoint_descriptor): Likewise. + (grub_efi_sal_system_table_memory_descriptor): Likewise. + (grub_efi_sal_system_table_platform_features): Likewise. + (grub_efi_sal_system_table_translation_register_descriptor): Likewise. + (grub_efi_sal_system_table_purge_translation_coherence): Likewise. + (grub_efi_sal_system_table_ap_wakeup): Likewise. + * include/grub/types.h (PRIuGRUB_UINT64_T): New definition. + +2010-09-13 Vladimir Serbinenko + + Support explicit user claim that a device is BIOS-visible. + + * grub-core/kern/emu/getroot.c (grub_util_get_dev_abstraction): + Return GRUB_DEV_ABSTRACTION_NONE if device is in device.map. + * grub-core/kern/emu/hostdisk.c + (convert_system_partition_to_system_disk): Support mdX. + (find_system_device): New parameter add. All users updated. + (grub_util_biosdisk_is_present): New function. + * include/grub/emu/hostdisk.h (grub_util_biosdisk_is_present): New + proto. + +2010-09-13 Vladimir Serbinenko + + Search hints support. + + * commands/search.c (FUNC_NAME): New arguments hints and nhints. + All users updated. + +2010-09-13 Yves Blusseau + + Bash completion script for util commands + + * Makefile.am: Add util/bash-completion.d directory + * configure.ac: Likewise. + * util/bash-completion.d/Makefile.am: New file. + * util/bash-completion.d/grub-completion.bash.in: Likewise. + +2010-09-12 Vladimir Serbinenko + + * grub-core/normal/term.c (put_glyphs_terminal): Correct sign. + (print_backlog): set backlog_ucs4 and backlog_glyphs. + Reported by: Yves Blusseau. + +2010-09-12 Vladimir Serbinenko + + * grub-core/normal/misc.c (grub_normal_print_device_info): Show + partition size and offset. + +2010-09-12 Vladimir Serbinenko + + * grub-core/commands/wildcard.c (make_regex): Escape brackets. + +2010-09-12 Vladimir Serbinenko + + * grub-core/commands/ls.c (grub_cmd_ls): Accept multiple files. + +2010-09-12 Vladimir Serbinenko + + * grub-core/kern/misc.c (grub_vprintf): Use va_copy when necessary. + (grub_xvasprintf): Likewise. + +2010-09-12 Vladimir Serbinenko + + * grub-core/kern/emu/main.c (main): Call hostfs_init only after init_all. + +2010-09-12 Vladimir Serbinenko + + * grub-core/commands/menuentry.c (append_menu_entry): Don't rely on + args ending with NULL. + +2010-09-12 Vladimir Serbinenko + + * grub-core/lib/xzembed/xz_dec_stream.c (xz_dec_reset): Preserve context + pointer. + +2010-09-11 Szymon Janc + + * grub-core/commands/lsacpi.c (grub_cmd_lsacpi): Fix prototype. + +2010-09-11 Vladimir Serbinenko + + Shutdown using ACPI. + + * grub-core/Makefile.core.def (halt): Add commands/acpihalt.c on i386-pc. + * grub-core/commands/acpihalt.c: New file. + * grub-core/commands/i386/pc/halt.c (grub_cmd_halt): Call grub_acpi_halt. + * include/grub/acpi.h (grub_acpi_fadt): New member pm1a. + (grub_acpi_halt): New proto. + (GRUB_ACPI_SLP_EN): New const. + (GRUB_ACPI_SLP_TYP_OFFSET): Likewise. + (GRUB_ACPI_OPCODE_*): New enum. + (GRUB_ACPI_EXTOPCODE_*): Likewise. + +2010-09-11 Tristan Gingold +2010-09-11 Robert Millan +2010-09-11 Vladimir Serbinenko + + * commands/lsacpi.c: New file. + * grub-core/Makefile.core.def (lsacpi): New module. + * include/grub/acpi.h (GRUB_ACPI_FADT_SIGNATURE): New definition. + (GRUB_ACPI_MADT_SIGNATURE): Likewise. + (grub_acpi_madt_entry_header): New struct. + (grub_acpi_madt): Likewise. + (grub_acpi_madt_entry_interrupt_override): Likewise. + (grub_acpi_madt_entry_sapic): Likewise. + (grub_acpi_madt_entry_lsapic): Likewise. + (grub_acpi_madt_entry_platform_int_source): Likewise. + * include/grub/types.h (PRIxGRUB_UINT32_T): New definition. + (PRIuGRUB_UINT32_T): Likewise. + (PRIxGRUB_UINT64_T): Likewise. + +2010-09-11 Vladimir Serbinenko + + Implement loading palette on ieee1275_fb. + + * grub-core/video/ieee1275.c (stdout_ihandle): New variable. + (have_setcolors): Likewise. + (grub_video_ieee1275_init): Fill stdout_ihandle and have_setcolors. + (grub_video_ieee1275_setup): Use grub_video_ieee1275_set_palette. + (grub_video_ieee1275_set_palette): Implement. + +2010-09-11 Vladimir Serbinenko +2010-09-11 Colin Watson + + * util/grub-install.in (grub_partition): New variable. + Set prefix_drive on EFI and PC to (,$grub_partition) as last resort. + * util/i386/pc/grub-setup.c (setup): Don't touch prefix. + Fixes a bug reported by Yves Blusseau. + +2010-09-11 Vladimir Serbinenko + + Fix emu on mipsel. + + * conf/Makefile.common (CFLAGS_PLATFORM): Add -mflush-func + =grub_cpu_flush_cache on all mips and not only yeeloong. + * configure.ac (COND_mips): New conditional. + * grub-core/Makefile.am (KERNEL_HEADER_FILES): Add libgcc on all + platforms. + * grub-core/kern/emu/cache.S (__mips__): Use _flush_cache. + * grub-core/kern/emu/full.c (grub_arch_dl_init_linker) + [GRUB_LINKER_HAVE_INIT]: New function. + (grub_emu_post_init): Likewise. + * grub-core/kern/emu/lite.c (grub_emu_post_init): Likewise. + * grub-core/kern/emu/main.c: Use grub_emu_post_init. + * include/grub/cache.h (_mips): Include mips/cache.h. + * include/grub/disk.h [GRUB_UTIL || GRUB_MACHINE_EMU]: Add missing + LVM and RAID prototypes. + * include/grub/emu/misc.h (grub_emu_post_init): New proto. + * include/grub/mips/time.h (grub_cpu_idle) [GRUB_MACHINE_EMU]: New + function. + +2010-09-10 Colin Watson + + * util/grub-install.in: Don't try to verify core.img until after + running grub-mkimage to create it. + +2010-09-10 Robert Millan + + * util/grub.d/10_hurd.in: Add misc readability checks. + * util/grub.d/10_kfreebsd.in: Likewise. + * util/grub.d/10_linux.in: Likewise. + +2010-09-10 Colin Watson + + * util/grub-install.in: ${imgext} won't be defined here until the + install branch is merged. For the meantime, only verify core.img on + i386-pc and sparc64-ieee1275 platforms. + +2010-09-10 Robert Millan + + Solaris support in grub_find_zpool_from_dir(). Thanks + Seth Goldberg for referring to getextmntent() facility. + + * configure.ac: Check for getextmntent(), `sys/mnttab.h' and + `sys/mkdev.h'. + * grub-core/kern/emu/misc.c [HAVE_SYS_MNTTAB_H]: Include + `'. + [HAVE_SYS_MKDEV_H]: Include `'. + [HAVE_GETEXTMNTENT] (grub_find_zpool_from_dir): Add getextmntent() + method for finding zpool name. + +2010-09-10 Colin Watson + + grub-fstest needs the host and hostfs modules while other utilities + actively require those modules to be absent, so grub-fstest needs + its own initialisation and finalisation code. + + * Makefile.am (grub_fstest.pp): New target. + (grub_fstest_init.lst): Likewise. + (grub_fstest_init.c): Likewise. + * Makefile.util.def (grub-fstest): Add grub_fstest_init.c. + +2010-09-10 Robert Millan + + * configure.ac: Check for `struct statfs.f_fstypename' and + `struct statfs.f_mntfromname'. + + * grub-core/kern/emu/misc.c (grub_find_zpool_from_dir): Conditionalize + kFreeBSD-specific code. + +2010-09-10 Robert Millan + + * util/grub.d/10_kfreebsd.in: Fix ${kfreebsd_device} initialization + on ZFS. Now non-main filesystems are supported as / too. + +2010-09-09 Colin Watson + + * Makefile.util.def (libgrub.a): Move grub-core/kern/emu/hostfs.c + and grub-core/disk/host.c to ... + (grub-fstest): ... here. Having the host disk implementation + present confuses grub-probe and other utility programs. + + * util/grub-mkconfig.in: Only verify readability of grub.cfg.new + when writing to a file, not when writing to stdout. + +2010-09-09 BVK Chaitanya + + * tests/partmap_test.in: New test for partitions. + * Makefile.util.def: Rules for new test. + +2010-09-09 Robert Millan + + * util/grub-probe.c (probe): Fix a pair of unhandled error + conditions. + +2010-09-09 Robert Millan + + Basic Btrfs support (detection and UUID). + + * grub-core/fs/btrfs.c: New file. + * Makefile.util.def (library): Register btrfs.c. + * grub-core/Makefile.core.def: Likewise. + +2010-09-08 Robert Millan + + * util/grub-mkconfig_lib.in (is_path_readable_by_grub): Improve + with (optional) parameters to specify device and relative path. + * util/grub-install.in: Use is_path_readable_by_grub() to + verify readability of a few critical files. + * util/grub-mkconfig.in: Use is_path_readable_by_grub() to + verify readability of grub.cfg.new. + +2010-09-08 Vladimir Serbinenko + + Split minix.mod into minix.mod and minix2.mod. + + * Makefile.util.def (libgrub.a): Add grub-core/fs/minix2.c. + * grub-core/Makefile.core.def (minix2): New module. + * grub-core/fs/minix.c: Use definitions instead of runtime version + checking. + * grub-core/fs/minix2.c: New file. + +2010-09-08 Yves Blusseau + + Add new --boot-directory option to replace --root-directory + + * util/grub-install.in: Add new --boot-directory option + * util/grub-reboot.in: Likewise. + * util/grub-set-default.in: Likewise. + +2010-09-08 Yves Blusseau + + * util/grub-mkconfig.in: Use new variable. + +2010-09-08 Yves Blusseau + + * configure.ac: Define some useful variables. + +2010-09-08 Vladimir Serbinenko + + * grub-core/kern/ieee1275/cmain.c (grub_ieee1275_find_options): Set + GRUB_IEEE1275_FLAG_HAS_CURSORONOFF when appropriate. + * grub-core/term/ieee1275/ofconsole.c (grub_ofconsole_setcursor): + Use terminfo and don't use cursor-on/cursor-off unless it's known + to work. + * include/grub/ieee1275/ieee1275.h (grub_ieee1275_flag): New element + GRUB_IEEE1275_FLAG_HAS_CURSORONOFF. + +2010-09-08 Colin Watson + + * grub-core/kern/efi/init.c (grub_efi_set_prefix): If the prefix + starts with "(,", fill the drive containing the loaded image in + between those two characters, but expect that a full partition + specification including partition map names will follow. + +2010-09-08 Robert Millan + + * configure.ac: Remove `--enable-grub-fstest' option. + * Makefile.util.def (grub-fstest): Remove COND_GRUB_FSTEST condition. + + * util/grub-mkconfig_lib.in (is_path_readable_by_grub): Use + `grub-fstest' instead of `grub-probe' for readability verification. + * util/grub-probe.c (probe): Remove readability verification kludge. + +2010-09-08 Robert Millan + + * util/grub-mkconfig.in: Pass `--device ${GRUB_DEVICE}' when + initializing `GRUB_FS'. + +2010-09-08 BVK Chaitanya + + Not command (!) support to GRUB script. + + * tests/grub_script_not.in: New test. + * Makefile.util.def: Rules for new test. + + * grub-core/script/execute.c (grub_script_execute_cmdline): Handle + ! command as a special case. + * grub-core/script/yylex.l (GRUB_PARSER_TOKEN_NOT): Removed. + +2010-09-07 BVK Chaitanya + + * grub-core/commands/wildcard.c (wildcard_expand): Fix wrong + grub_free. + 2010-09-07 BVK Chaitanya * docs/grub.texi (Shell-like scripting): Fix @dots to @dots{}. @@ -677,6 +1460,15 @@ * util/grub-mkimage.c (generate_image): Remove font support. All users updated. +2010-08-30 Vladimir Serbinenko + + Remove leftover embedding of font objects. + + * include/grub/kernel.h (OBJ_TYPE_FONT): Removed. + * util/grub-install.in (font): Removed. + * util/grub-mkimage.c (generate_image): Remove font support. All users + updated. + 2010-08-30 Vladimir Serbinenko * docs/grub.texi (Network): Fix reference to pxe_blksize. diff --git a/Makefile.am b/Makefile.am index 1cf2297bd..9ef8feaac 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,7 @@ AUTOMAKE_OPTIONS = subdir-objects DEPDIR = .deps-util -SUBDIRS = . grub-core po docs +SUBDIRS = . grub-core po docs util/bash-completion.d include $(top_srcdir)/conf/Makefile.common include $(top_srcdir)/conf/Makefile.extra-dist @@ -44,9 +44,23 @@ libgrub_a_init.c: libgrub_a_init.lst $(top_srcdir)/geninit.sh sh $(top_srcdir)/geninit.sh `cat $<` > $@ || (rm -f $@; exit 1) CLEANFILES += libgrub_a_init.c +# For grub-fstest +grub_fstest.pp: $(grub_fstest_SOURCES) + $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(grub_fstest_CPPFLAGS) $(CPPFLAGS) \ + -D'GRUB_MOD_INIT(x)=@MARKER@x@' $^ > $@ || (rm -f $@; exit 1) +CLEANFILES += grub_fstest.pp + +grub_fstest_init.lst: libgrub.pp grub_fstest.pp + cat $^ | grep '@MARKER@' | sed 's/@MARKER@\(.*\)@/\1/g' | sort -u > $@ || (rm -f $@; exit 1) +CLEANFILES += grub_fstest_init.lst + +grub_fstest_init.c: grub_fstest_init.lst $(top_srcdir)/geninit.sh + sh $(top_srcdir)/geninit.sh `cat $<` > $@ || (rm -f $@; exit 1) +CLEANFILES += grub_fstest_init.c + if COND_GRUB_MKFONT if COND_HAVE_FONT_SOURCE -grubdata_DATA = unicode.pf2 ascii.pf2 ascii.h widthspec.h +grubdata_DATA = unicode.pf2 ascii.pf2 euro.pf2 ascii.h widthspec.h endif endif @@ -62,6 +76,10 @@ ascii.pf2: $(FONT_SOURCE) grub-mkfont $(builddir)/grub-mkfont -o $@ $(FONT_SOURCE) -r 0x0-0x7f,$(UNICODE_ARROWS),$(UNICODE_LINES) CLEANFILES += ascii.pf2 +euro.pf2: $(FONT_SOURCE) grub-mkfont + $(builddir)/grub-mkfont -o $@ $(FONT_SOURCE) -r 0x0-0x4ff,0x1e00-0x1fff,$(UNICODE_ARROWS),$(UNICODE_LINES) +CLEANFILES += euro.pf2 + ascii.bitmaps: $(FONT_SOURCE) grub-mkfont $(builddir)/grub-mkfont --ascii-bitmaps -o $@ $(FONT_SOURCE) CLEANFILES += ascii.bitmaps diff --git a/Makefile.util.def b/Makefile.util.def index dd38774fd..36df8ca28 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -23,7 +23,6 @@ library = { common = grub-core/kern/misc.c; common = grub-core/kern/emu/mm.c; common = grub-core/kern/emu/misc.c; - common = grub-core/kern/emu/hostfs.c; common = grub-core/kern/emu/getroot.c; common = grub-core/kern/emu/hostdisk.c; @@ -31,7 +30,6 @@ library = { common = grub-core/commands/extcmd.c; common = grub-core/commands/ls.c; common = grub-core/disk/dmraid_nvidia.c; - common = grub-core/disk/host.c; common = grub-core/disk/loopback.c; common = grub-core/disk/lvm.c; common = grub-core/disk/mdraid_linux.c; @@ -43,6 +41,7 @@ library = { common = grub-core/fs/afs.c; common = grub-core/fs/befs_be.c; common = grub-core/fs/befs.c; + common = grub-core/fs/btrfs.c; common = grub-core/fs/cpio.c; common = grub-core/fs/ext2.c; common = grub-core/fs/fat.c; @@ -52,6 +51,7 @@ library = { common = grub-core/fs/iso9660.c; common = grub-core/fs/jfs.c; common = grub-core/fs/minix.c; + common = grub-core/fs/minix2.c; common = grub-core/fs/nilfs2.c; common = grub-core/fs/ntfs.c; common = grub-core/fs/ntfscomp.c; @@ -179,11 +179,13 @@ program = { program = { name = grub-fstest; mansection = 1; + common_nodist = grub_fstest_init.c; common = util/grub-fstest.c; + common = grub-core/kern/emu/hostfs.c; + common = grub-core/disk/host.c; ldadd = libgrub.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER)'; - condition = COND_GRUB_FSTEST; }; program = { @@ -230,14 +232,11 @@ program = { name = grub-setup; installdir = sbin; mansection = 8; - i386_pc = util/i386/pc/grub-setup.c; - i386_pc = util/raid.c; - i386_pc = util/lvm.c; + common = util/grub-setup.c; + common = util/raid.c; + common = util/lvm.c; sparc64_ieee1275 = util/ieee1275/ofpath.c; - sparc64_ieee1275 = util/sparc64/ieee1275/grub-setup.c; - sparc64_ieee1275 = util/raid.c; - sparc64_ieee1275 = util/lvm.c; ldadd = libgrub.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL)'; @@ -257,6 +256,16 @@ program = { enable = sparc64_ieee1275; }; +program = { + name = grub-mklayout; + mansection = 1; + + common = util/grub-mklayout.c; + + ldadd = libgrub.a; + ldadd = '$(LIBINTL) $(LIBDEVMAPPER)'; +}; + data = { common = util/grub.d/README; installdir = grubconf; @@ -346,20 +355,18 @@ script = { installdir = sbin; name = grub-install; - mips = util/grub-install.in; - i386_pc = util/grub-install.in; - i386_qemu = util/grub-install.in; - i386_coreboot = util/grub-install.in; - i386_multiboot = util/grub-install.in; - sparc64_ieee1275 = util/grub-install.in; - - x86_efi = util/i386/efi/grub-install.in; - i386_ieee1275 = util/ieee1275/grub-install.in; - powerpc_ieee1275 = util/ieee1275/grub-install.in; - + common = util/grub-install.in; enable = noemu; }; +script = { + mansection = 8; + installdir = sbin; + name = grub-mknetdir; + + common = util/grub-mknetdir.in; +}; + script = { name = grub-mkconfig; common = util/grub-mkconfig.in; @@ -393,6 +400,11 @@ script = { installdir = noinst; }; +script = { + name = grub-kbdcomp; + common = util/grub-kbdcomp.in; +}; + script = { name = grub-shell; common = tests/util/grub-shell.in; @@ -531,6 +543,18 @@ script = { common = tests/grub_script_expansion.in; }; +script = { + testcase; + name = grub_script_not; + common = tests/grub_script_not.in; +}; + +script = { + testcase; + name = partmap_test; + common = tests/partmap_test.in; +}; + program = { testcase; name = example_unit_test; @@ -543,3 +567,14 @@ program = { ldadd = libgrub.a; ldadd = '$(LIBDEVMAPPER)'; }; + +program = { + name = grub-menulst2cfg; + mansection = 1; + common = util/grub-menulst2cfg.c; + common = grub-core/lib/legacy_parse.c; + common = grub-core/lib/i386/pc/vesa_modes_table.c; + + ldadd = libgrub.a; + ldflags = '$(LIBDEVMAPPER)'; +}; diff --git a/conf/Makefile.common b/conf/Makefile.common index fca0f67ae..afa57b986 100644 --- a/conf/Makefile.common +++ b/conf/Makefile.common @@ -1,8 +1,10 @@ # -*- makefile -*- +CFLAGS_PLATFORM= + # Platform specific options if COND_i386_pc - CFLAGS_PLATFORM = -mrtd -mregparm=3 + CFLAGS_PLATFORM += -mrtd -mregparm=3 endif if COND_i386_efi LDFLAGS_PLATFORM = -melf_i386 @@ -11,21 +13,24 @@ if COND_x86_64_efi LDFLAGS_PLATFORM = -melf_x86_64 endif if COND_i386_qemu - CFLAGS_PLATFORM = -mrtd -mregparm=3 + CFLAGS_PLATFORM += -mrtd -mregparm=3 endif if COND_i386_coreboot - CFLAGS_PLATFORM = -mrtd -mregparm=3 + CFLAGS_PLATFORM += -mrtd -mregparm=3 endif if COND_i386_ieee1275 - CFLAGS_PLATFORM = -mrtd -mregparm=3 + CFLAGS_PLATFORM += -mrtd -mregparm=3 endif if COND_mips_yeeloong - CFLAGS_PLATFORM = -march=mips3 -mexplicit-relocs -mflush-func=grub_cpu_flush_cache + CFLAGS_PLATFORM += -march=mips3 -mexplicit-relocs CPPFLAGS_PLATFORM = -DUSE_ASCII_FAILBACK CCASFLAGS_PLATFORM = -march=mips3 endif +if COND_mips + CFLAGS_PLATFORM += -mflush-func=grub_cpu_flush_cache +endif if COND_sparc64_ieee1275 - CFLAGS_PLATFORM = -mno-app-regs + CFLAGS_PLATFORM += -mno-app-regs LDFLAGS_PLATFORM = -melf64_sparc -mno-relax endif diff --git a/configure.ac b/configure.ac index d362f68a5..57df640b8 100644 --- a/configure.ac +++ b/configure.ac @@ -176,6 +176,19 @@ AC_SUBST(host_kernel) AC_SUBST(target_cpu) AC_SUBST(platform) +# Define default variables +case "$host_os" in + netbsd* | openbsd*) + # Because /boot is used for the boot block in NetBSD and OpenBSD, + bootdirname='' ;; + *) bootdirname='boot' ;; +esac +bootdirname=`echo "$bootdirname" | sed "$program_transform_name"` +AC_SUBST(bootdirname) + +grubdirname=`echo "$PACKAGE" | sed "$program_transform_name"` +AC_SUBST(grubdirname) + # # Checks for build programs. # @@ -264,8 +277,16 @@ else fi # Check for functions and headers. -AC_CHECK_FUNCS(posix_memalign memalign asprintf vasprintf) -AC_CHECK_HEADERS(libzfs.h libnvpair.h sys/param.h sys/mount.h) +AC_CHECK_FUNCS(posix_memalign memalign asprintf vasprintf getextmntent) +AC_CHECK_HEADERS(libzfs.h libnvpair.h sys/param.h sys/mount.h sys/mnttab.h sys/mkdev.h) + +AC_CHECK_MEMBERS([struct statfs.f_fstypename],,,[$ac_includes_default +#include +#include ]) + +AC_CHECK_MEMBERS([struct statfs.f_mntfromname],,,[$ac_includes_default +#include +#include ]) # For opendisk() and getrawpartition() on NetBSD. # Used in util/deviceiter.c and in util/hostdisk.c. @@ -677,8 +698,8 @@ if test x"$missing_ncurses" = xtrue ; then AC_MSG_ERROR([grub-emu can't be compiled without ncurses]) fi -if test x"$enable_grub_emu_usb" = xno ; then - grub_emu_usb_excuse="explicitly disabled" +if test x"$enable_grub_emu_usb" != xyes ; then + grub_emu_usb_excuse="not enabled" fi if test x"$enable_grub_emu_pci" = xyes ; then @@ -762,19 +783,6 @@ AC_SUBST([enable_grub_emu_usb]) AC_SUBST([enable_grub_emu_pci]) fi -AC_ARG_ENABLE([grub-fstest], - [AS_HELP_STRING([--enable-grub-fstest], - [build and install the `grub-fstest' debugging utility (default=guessed)])]) -if test x"$enable_grub_fstest" = xno ; then - grub_fstest_excuse="explicitly disabled" -fi -if test x"$grub_fstest_excuse" = x ; then -enable_grub_fstest=yes -else -enable_grub_fstest=no -fi -AC_SUBST([enable_grub_fstest]) - AC_ARG_ENABLE([grub-mkfont], [AS_HELP_STRING([--enable-grub-mkfont], [build and install the `grub-mkfont' utility (default=guessed)])]) @@ -788,12 +796,12 @@ if test x"$grub_mkfont_excuse" = x ; then if test "x$FREETYPE" = x ; then grub_mkfont_excuse=["need freetype2 library"] fi - freetype_cflags=`freetype-config --cflags` - freetype_libs=`freetype-config --libs` fi if test x"$grub_mkfont_excuse" = x ; then # Check for freetype libraries. + freetype_cflags=`freetype-config --cflags` + freetype_libs=`freetype-config --libs` SAVED_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $freetype_cflags" AC_CHECK_HEADERS([ft2build.h], [], @@ -859,20 +867,8 @@ pkglibrootdir='$(libdir)'/`echo $PACKAGE | sed "$program_transform_name"` AC_SUBST(pkglibrootdir) AC_SUBST([FONT_SOURCE]) -AS_IF([test x$target_cpu = xi386 -a x$platform = xpc], - [AC_SUBST([GRUB_KERNEL_MACHINE_LINK_ADDR], 0x8200)]) -AS_IF([test x$target_cpu = xi386 -a x$platform = xcoreboot], - [AC_SUBST([GRUB_KERNEL_MACHINE_LINK_ADDR], 0x8200)]) -AS_IF([test x$target_cpu = xi386 -a x$platform = xmultiboot], - [AC_SUBST([GRUB_KERNEL_MACHINE_LINK_ADDR], 0x8200)]) -AS_IF([test x$target_cpu = xmips -a x$platform = xyeeloong], - [AC_SUBST([GRUB_KERNEL_MACHINE_LINK_ADDR], 0x80200000)]) -AS_IF([test x$target_cpu = xpowerpc -a x$platform = xieee1275], - [AC_SUBST([GRUB_KERNEL_MACHINE_LINK_ADDR], 0x200000)]) AS_IF([test x$target_cpu = xi386 -a x$platform = xqemu], [AC_SUBST([GRUB_BOOT_MACHINE_LINK_ADDR], 0xffe00)]) -AS_IF([test x$target_cpu = xi386 -a x$platform = xieee1275], - [AC_SUBST([GRUB_KERNEL_MACHINE_LINK_ADDR], 0x10000)]) AS_IF([test x$TARGET_APPLE_CC = x1], [AC_SUBST([USE_APPLE_CC_FIXES], yes)]) @@ -892,6 +888,7 @@ AM_CONDITIONAL([COND_mips_yeeloong], [test x$target_cpu = xmips -a x$platform = AM_CONDITIONAL([COND_mips_qemu_mips], [test x$target_cpu = xmips -a x$platform = xqemu_mips]) AM_CONDITIONAL([COND_sparc64_ieee1275], [test x$target_cpu = xsparc64 -a x$platform = xieee1275]) AM_CONDITIONAL([COND_powerpc_ieee1275], [test x$target_cpu = xpowerpc -a x$platform = xieee1275]) +AM_CONDITIONAL([COND_mips], [test x$target_cpu = xmips]) AM_CONDITIONAL([COND_HOST_HURD], [test x$host_kernel = xhurd]) AM_CONDITIONAL([COND_HOST_LINUX], [test x$host_kernel = xlinux]) @@ -905,7 +902,6 @@ AM_CONDITIONAL([COND_GRUB_EMU_SDL], [test x$enable_grub_emu_sdl = xyes]) AM_CONDITIONAL([COND_GRUB_EMU_PCI], [test x$enable_grub_emu_pci = xyes]) AM_CONDITIONAL([COND_GRUB_MKFONT], [test x$enable_grub_mkfont = xyes]) AM_CONDITIONAL([COND_HAVE_FONT_SOURCE], [test x$FONT_SOURCE != x]) -AM_CONDITIONAL([COND_GRUB_FSTEST], [test x$enable_grub_fstest = xyes]) AM_CONDITIONAL([COND_GRUB_PE2ELF], [test x$TARGET_OBJ2ELF != x]) AM_CONDITIONAL([COND_APPLE_CC], [test x$TARGET_APPLE_CC = x1]) AM_CONDITIONAL([COND_ENABLE_EFIEMU], [test x$enable_efiemu = xyes]) @@ -931,6 +927,7 @@ AC_CONFIG_FILES([Makefile]) AC_CONFIG_FILES([grub-core/Makefile]) AC_CONFIG_FILES([po/Makefile]) AC_CONFIG_FILES([docs/Makefile]) +AC_CONFIG_FILES([util/bash-completion.d/Makefile]) AC_CONFIG_FILES([stamp-h], [echo timestamp > stamp-h]) AC_OUTPUT @@ -970,11 +967,6 @@ echo efiemu runtime: Yes else echo efiemu runtime: No "($efiemu_excuse)" fi -if [ x"$grub_fstest_excuse" = x ]; then -echo grub-fstest: Yes -else -echo grub-fstest: No "($grub_fstest_excuse)" -fi if [ x"$grub_mkfont_excuse" = x ]; then echo grub-mkfont: Yes else diff --git a/docs/grub.texi b/docs/grub.texi index af6d42ccb..076adfd6c 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -2415,8 +2415,7 @@ The serial port is not used as a communication channel unless the @command{terminal_input} or @command{terminal_output} command is used (@pxref{terminal_input}, @pxref{terminal_output}). -This command is only available if GRUB is compiled with serial -support. See also @ref{Serial terminal}. +See also @ref{Serial terminal}. @end deffn @@ -2907,7 +2906,7 @@ This command is only available on x86 systems. @node ls @subsection ls -@deffn Command ls [arg] +@deffn Command ls [arg @dots{}] List devices or files. With no arguments, print all devices known to GRUB. diff --git a/docs/man/grub-menulst2cfg.h2m b/docs/man/grub-menulst2cfg.h2m new file mode 100644 index 000000000..0c0570f27 --- /dev/null +++ b/docs/man/grub-menulst2cfg.h2m @@ -0,0 +1,3 @@ +[NAME] +grub-menulst2cfg \- transform legacy menu.lst into grub.cfg + diff --git a/docs/man/grub-mklayout.h2m b/docs/man/grub-mklayout.h2m new file mode 100644 index 000000000..e0ae9dedb --- /dev/null +++ b/docs/man/grub-mklayout.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-mklayout \- generate a GRUB keyboard layout file diff --git a/docs/man/grub-mknetdir.h2m b/docs/man/grub-mknetdir.h2m new file mode 100644 index 000000000..26defe876 --- /dev/null +++ b/docs/man/grub-mknetdir.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-mknetdir \- prepare a GRUB netboot directory. diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index 5d13d0313..566a0cb0a 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -74,9 +74,10 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/boot.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h if COND_i386_pc -KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/loader.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pxe.h @@ -92,24 +93,20 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h endif if COND_i386_coreboot -KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h endif if COND_i386_multiboot -KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h endif if COND_i386_qemu -KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h endif if COND_i386_ieee1275 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h -KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h endif @@ -122,8 +119,8 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h endif if COND_mips_yeeloong +KERNEL_HEADER_FILES += $(top_builddir)/include/grub/keyboard_layouts.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h -KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/cpu/cache.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bitmap.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h @@ -132,19 +129,17 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/font.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bitmap_scale.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/cs5536.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pci.h -KERNEL_HEADER_FILES += $(top_builddir)/include/grub/serial.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/serial.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h endif if COND_powerpc_ieee1275 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h endif if COND_sparc64_ieee1275 -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sparc64/ieee1275/ieee1275.h endif diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 59d99a326..b9abac40d 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -10,20 +10,20 @@ kernel = { x86_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment'; i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; - i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),$(GRUB_KERNEL_MACHINE_LINK_ADDR)'; + i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200'; i386_qemu_ldflags = '$(TARGET_IMG_LDFLAGS)'; - i386_qemu_ldflags = '$(TARGET_IMG_BASE_LDOPT),$(GRUB_KERNEL_MACHINE_LINK_ADDR)'; + i386_qemu_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200'; - i386_coreboot_ldflags = '-Wl,-Ttext=$(GRUB_KERNEL_MACHINE_LINK_ADDR)'; - i386_multiboot_ldflags = '-Wl,-Ttext=$(GRUB_KERNEL_MACHINE_LINK_ADDR)'; - i386_ieee1275_ldflags = '-Wl,-Ttext=$(GRUB_KERNEL_MACHINE_LINK_ADDR)'; - mips_yeeloong_ldflags = '-Wl,-Ttext,$(GRUB_KERNEL_MACHINE_LINK_ADDR)'; - powerpc_ieee1275_ldflags = '-Wl,-Ttext,$(GRUB_KERNEL_MACHINE_LINK_ADDR)'; + i386_coreboot_ldflags = '-Wl,-Ttext=0x8200'; + i386_multiboot_ldflags = '-Wl,-Ttext=0x8200'; + i386_ieee1275_ldflags = '-Wl,-Ttext=0x10000'; + mips_yeeloong_ldflags = '-Wl,-Ttext,0x80200000'; + powerpc_ieee1275_ldflags = '-Wl,-Ttext,0x200000'; + sparc64_ieee1275_ldflags = '-Wl,-Ttext,0x4400'; mips_yeeloong_cppflags = '-DUSE_ASCII_FAILBACK'; i386_qemu_cppflags = '-DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR)'; - i386_qemu_ccasflags = '-DGRUB_KERNEL_MACHINE_LINK_ADDR=$(GRUB_KERNEL_MACHINE_LINK_ADDR)'; emu_cflags = '$(CFLAGS_GNULIB)'; emu_cppflags = '$(CPPFLAGS_GNULIB)'; @@ -138,6 +138,7 @@ kernel = { mips_yeeloong = term/serial.c; mips_yeeloong = video/sm712.c; extra_dist = video/sm712_init.c; + mips_yeeloong = commands/keylayouts.c; powerpc_ieee1275 = kern/ieee1275/init.c; powerpc_ieee1275 = kern/powerpc/cache.S; @@ -150,6 +151,7 @@ kernel = { emu = disk/host.c; emu = gnulib/progname.c; + emu = gnulib/error.c; emu = kern/emu/console.c; emu = kern/emu/getroot.c; emu = kern/emu/hostdisk.c; @@ -173,6 +175,8 @@ kernel = { videoinkernel = video/fb/video_fb.c; videoinkernel = video/video.c; + videoinkernel = commands/boot.c; + extra_dist = kern/i386/realmode.S; extra_dist = kern/i386/pc/lzma_decode.S; extra_dist = kern/mips/cache_flush.S; @@ -187,7 +191,7 @@ program = { ldadd = 'kernel.img$(EXEEXT)'; ldadd = '$(MODULE_FILES)'; - ldadd = '$(LIBUTIL) $(LIBCURSES) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER)'; + ldadd = '$(LIBUTIL) $(LIBCURSES) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)'; enable = emu; }; @@ -200,7 +204,7 @@ program = { emu_nodist = symlist.c; ldadd = 'kernel.img$(EXEEXT)'; - ldadd = '$(LIBUTIL) $(LIBCURSES) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER)'; + ldadd = '$(LIBUTIL) $(LIBCURSES) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)'; enable = emu; }; @@ -319,25 +323,19 @@ module = { module = { name = usbserial_common; common = bus/usb/serial/common.c; - enable = emu; enable = usb; - emu_condition = COND_GRUB_EMU_USB; }; module = { name = usbserial_pl2303; common = bus/usb/serial/pl2303.c; - enable = emu; enable = usb; - emu_condition = COND_GRUB_EMU_USB; }; module = { name = usbserial_ftdi; common = bus/usb/serial/ftdi.c; - enable = emu; enable = usb; - emu_condition = COND_GRUB_EMU_USB; }; module = { @@ -404,7 +402,7 @@ module = { module = { name = acpi; - x86 = commands/acpi.c; + common = commands/acpi.c; x86_efi = commands/efi/acpi.c; i386_pc = commands/i386/pc/acpi.c; i386_coreboot = commands/i386/pc/acpi.c; @@ -416,6 +414,33 @@ module = { enable = i386_multiboot; }; +module = { + name = lsacpi; + + common = commands/lsacpi.c; + + enable = x86_efi; + enable = i386_pc; + enable = i386_coreboot; + enable = i386_multiboot; +}; + +module = { + name = lsefisystab; + + common = commands/efi/lsefisystab.c; + + enable = x86_efi; +}; + +module = { + name = lssal; + + common = commands/efi/lssal.c; + + enable = x86_efi; +}; + module = { name = blocklist; common = commands/blocklist.c; @@ -425,6 +450,7 @@ module = { name = boot; common = commands/boot.c; i386_pc = lib/i386/pc/biosnum.c; + enable = videomodules; }; module = { @@ -493,6 +519,10 @@ module = { name = halt; nopc = commands/halt.c; i386_pc = commands/i386/pc/halt.c; + i386_pc = commands/acpihalt.c; + i386_coreboot = commands/acpihalt.c; + i386_multiboot = commands/acpihalt.c; + x86_efi = commands/acpihalt.c; i386_multiboot = lib/i386/halt.c; i386_coreboot = lib/i386/halt.c; i386_qemu = lib/i386/halt.c; @@ -673,15 +703,8 @@ module = { }; module = { - name = vbeinfo; - i386_pc = commands/i386/pc/vbeinfo.c; - enable = i386_pc; -}; - -module = { - name = vbetest; - i386_pc = commands/i386/pc/vbetest.c; - enable = i386_pc; + name = videoinfo; + common = commands/videoinfo.c; }; module = { @@ -835,6 +858,11 @@ module = { common = fs/befs_be.c; }; +module = { + name = btrfs; + common = fs/btrfs.c; +}; + module = { name = cpio; common = fs/cpio.c; @@ -880,6 +908,11 @@ module = { common = fs/minix.c; }; +module = { + name = minix2; + common = fs/minix2.c; +}; + module = { name = nilfs2; common = fs/nilfs2.c; @@ -1089,6 +1122,7 @@ module = { module = { name = linux; x86 = loader/i386/linux.c; + i386_pc = lib/i386/pc/vesa_modes_table.c; mips = loader/mips/linux.c; powerpc_ieee1275 = loader/powerpc/ieee1275/linux.c; sparc64_ieee1275 = loader/sparc64/ieee1275/linux.c; @@ -1384,6 +1418,14 @@ module = { common = hook/datehook.c; }; +module = { + name = legacycfg; + common = commands/legacycfg.c; + common = lib/legacy_parse.c; + enable = i386_pc; + enable = emu; +}; + module = { name = test_blockarg; common = tests/test_blockarg.c; @@ -1402,3 +1444,15 @@ module = { name = testload; common = commands/testload.c; }; + +module = { + name = lsapm; + common = commands/i386/pc/lsapm.c; + enable = i386_pc; +}; + +module = { + name = keylayouts; + common = commands/keylayouts.c; + enable = videomodules; +}; diff --git a/grub-core/boot/i386/qemu/boot.S b/grub-core/boot/i386/qemu/boot.S index fe14f0f06..97aeab9e6 100644 --- a/grub-core/boot/i386/qemu/boot.S +++ b/grub-core/boot/i386/qemu/boot.S @@ -18,6 +18,7 @@ #include #include +#include #include #include #include diff --git a/grub-core/bus/usb/ohci.c b/grub-core/bus/usb/ohci.c index 587a36420..b07e30403 100644 --- a/grub-core/bus/usb/ohci.c +++ b/grub-core/bus/usb/ohci.c @@ -98,7 +98,6 @@ struct grub_ohci struct grub_pci_dma_chunk *td_chunk; struct grub_ohci *next; grub_ohci_td_t td_free; /* Pointer to first free TD */ - int bad_OHCI; }; static struct grub_ohci *ohci; @@ -149,8 +148,8 @@ typedef enum #define GRUB_OHCI_REG_CONTROL_CONTROL_ENABLE (1 << 4) #define GRUB_OHCI_RESET_CONNECT_CHANGE (1 << 16) -#define GRUB_OHCI_CTRL_EDS 16 -#define GRUB_OHCI_BULK_EDS 16 +#define GRUB_OHCI_CTRL_EDS 256 +#define GRUB_OHCI_BULK_EDS 510 #define GRUB_OHCI_TDS 256 #define GRUB_OHCI_ED_ADDR_MASK 0x7ff @@ -442,8 +441,10 @@ grub_ohci_pci_iter (grub_pci_device_t dev, (grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBA) & ~GRUB_OHCI_RHUB_PORT_POWER_MASK) | GRUB_OHCI_RHUB_PORT_ALL_POWERED); +#if 0 /* We don't need it at all, handled via hotplugging */ /* Now we have hot-plugging, we need to wait for stable power only */ grub_millisleep (100); +#endif /* Link to ohci now that initialisation is successful. */ o->next = ohci; @@ -623,7 +624,8 @@ grub_ohci_transaction (grub_ohci_td_t td, break; } - /* Set the token (Always generate interrupt - bits 21-23 = 0). */ + /* Set the token */ + token |= ( 7 << 21); /* Never generate interrupt */ token |= toggle << 24; token |= 1 << 25; @@ -652,36 +654,31 @@ grub_ohci_transaction (grub_ohci_td_t td, td->next_td = 0; } +struct grub_ohci_transfer_controller_data +{ + grub_uint32_t tderr_phys; + grub_uint32_t td_last_phys; + grub_ohci_ed_t ed_virt; + grub_ohci_td_t td_current_virt; + grub_ohci_td_t td_head_virt; +}; + static grub_usb_err_t -grub_ohci_transfer (grub_usb_controller_t dev, - grub_usb_transfer_t transfer, int timeout, - grub_size_t *actual) +grub_ohci_setup_transfer (grub_usb_controller_t dev, + grub_usb_transfer_t transfer) { struct grub_ohci *o = (struct grub_ohci *) dev->data; - grub_ohci_ed_t ed_virt; int bulk = 0; - grub_ohci_td_t td_head_virt; - grub_ohci_td_t td_current_virt; grub_ohci_td_t td_next_virt; - grub_ohci_td_t tderr_virt = NULL; grub_uint32_t target; grub_uint32_t td_head_phys; grub_uint32_t td_tail_phys; - grub_uint32_t td_last_phys; - grub_uint32_t tderr_phys = 0; - grub_uint32_t status; - grub_uint32_t control; - grub_uint8_t errcode = 0; - grub_usb_err_t err = GRUB_USB_ERR_NONE; int i; - grub_uint64_t maxtime; - grub_uint64_t bad_OHCI_delay = 0; - int err_halt = 0; - int err_timeout = 0; - int err_unrec = 0; - grub_uint32_t intstatus; + struct grub_ohci_transfer_controller_data *cdata; - *actual = 0; + cdata = grub_zalloc (sizeof (*cdata)); + if (!cdata) + return GRUB_USB_ERR_INTERNAL; /* Pre-set target for ED - we need it to find proper ED */ /* Set the device address. */ @@ -703,21 +700,23 @@ grub_ohci_transfer (grub_usb_controller_t dev, case GRUB_USB_TRANSACTION_TYPE_CONTROL: break; - default : + default: + grub_free (cdata); return GRUB_USB_ERR_INTERNAL; } /* Find proper ED or add new ED */ - ed_virt = grub_ohci_find_ed (o, bulk, target); - if (!ed_virt) + cdata->ed_virt = grub_ohci_find_ed (o, bulk, target); + if (!cdata->ed_virt) { grub_dprintf ("ohci","Fatal: No free ED !\n"); + grub_free (cdata); return GRUB_USB_ERR_INTERNAL; } /* Take pointer to first TD from ED */ - td_head_phys = grub_le_to_cpu32 (ed_virt->td_head) & ~0xf; - td_tail_phys = grub_le_to_cpu32 (ed_virt->td_tail) & ~0xf; + td_head_phys = grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xf; + td_tail_phys = grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xf; /* Sanity check - td_head should be equal to td_tail */ if (td_head_phys != td_tail_phys) /* Should never happen ! */ @@ -726,6 +725,7 @@ grub_ohci_transfer (grub_usb_controller_t dev, grub_dprintf ("ohci", "HEAD = 0x%02x, TAIL = 0x%02x\n", td_head_phys, td_tail_phys); /* XXX: Fix: What to do ? */ + grub_free (cdata); return GRUB_USB_ERR_INTERNAL; } @@ -733,65 +733,62 @@ grub_ohci_transfer (grub_usb_controller_t dev, * we must allocate the first TD. */ if (!td_head_phys) { - td_head_virt = grub_ohci_alloc_td (o); - if (!td_head_virt) + cdata->td_head_virt = grub_ohci_alloc_td (o); + if (!cdata->td_head_virt) return GRUB_USB_ERR_INTERNAL; /* We don't need de-allocate ED */ /* We can set td_head only when ED is not active, i.e. * when it is newly allocated. */ - ed_virt->td_head = grub_cpu_to_le32 ( grub_ohci_td_virt2phys (o, - td_head_virt) ); - ed_virt->td_tail = ed_virt->td_head; + cdata->ed_virt->td_head + = grub_cpu_to_le32 (grub_ohci_td_virt2phys (o, cdata->td_head_virt)); + cdata->ed_virt->td_tail = cdata->ed_virt->td_head; } else - td_head_virt = grub_ohci_td_phys2virt ( o, td_head_phys ); + cdata->td_head_virt = grub_ohci_td_phys2virt ( o, td_head_phys ); /* Set TDs */ - td_last_phys = td_head_phys; /* initial value to make compiler happy... */ - for (i = 0, td_current_virt = td_head_virt; + cdata->td_last_phys = td_head_phys; /* initial value to make compiler happy... */ + for (i = 0, cdata->td_current_virt = cdata->td_head_virt; i < transfer->transcnt; i++) { grub_usb_transaction_t tr = &transfer->transactions[i]; - grub_ohci_transaction (td_current_virt, tr->pid, tr->toggle, + grub_ohci_transaction (cdata->td_current_virt, tr->pid, tr->toggle, tr->size, tr->data); /* Set index of TD in transfer */ - td_current_virt->tr_index = (grub_uint32_t) i; - - /* No IRQ request in TD if bad_OHCI set */ - if (o->bad_OHCI) - td_current_virt->token |= grub_cpu_to_le32 ( 7 << 21); + cdata->td_current_virt->tr_index = (grub_uint32_t) i; /* Remember last used (processed) TD phys. addr. */ - td_last_phys = grub_ohci_td_virt2phys (o, td_current_virt); + cdata->td_last_phys = grub_ohci_td_virt2phys (o, cdata->td_current_virt); /* Allocate next TD */ td_next_virt = grub_ohci_alloc_td (o); if (!td_next_virt) /* No free TD, cancel transfer and free TDs except head TD */ { if (i) /* if i==0 we have nothing to free... */ - grub_ohci_free_tds (o, - grub_ohci_td_phys2virt(o, - grub_le_to_cpu32 (td_head_virt->next_td) ) ); + grub_ohci_free_tds (o, grub_ohci_td_phys2virt(o, + grub_le_to_cpu32 (cdata->td_head_virt->next_td))); /* Reset head TD */ - grub_memset ( (void*)td_head_virt, 0, + grub_memset ( (void*)cdata->td_head_virt, 0, sizeof(struct grub_ohci_td) ); grub_dprintf ("ohci", "Fatal: No free TD !"); + grub_free (cdata); return GRUB_USB_ERR_INTERNAL; } /* Chain TDs */ - td_current_virt->link_td = td_next_virt; - td_current_virt->next_td = grub_cpu_to_le32 ( + + cdata->td_current_virt->link_td = td_next_virt; + cdata->td_current_virt->next_td = grub_cpu_to_le32 ( grub_ohci_td_virt2phys (o, td_next_virt) ); td_next_virt->prev_td_phys = grub_ohci_td_virt2phys (o, - td_current_virt); - td_current_virt = td_next_virt; + cdata->td_current_virt); + cdata->td_current_virt = td_next_virt; } grub_dprintf ("ohci", "Tail TD (not processed) = %p\n", - td_current_virt); + cdata->td_current_virt); /* Setup the Endpoint Descriptor for transfer. */ /* First set necessary fields in TARGET but keep (or set) skip bit */ @@ -799,12 +796,12 @@ grub_ohci_transfer (grub_usb_controller_t dev, * size never change after first allocation of ED. * But unfortunately max. packet size may change during initial * setup sequence and we must handle it. */ - ed_virt->target = grub_cpu_to_le32 (target | (1 << 14)); + cdata->ed_virt->target = grub_cpu_to_le32 (target | (1 << 14)); /* Set td_tail */ - ed_virt->td_tail - = grub_cpu_to_le32 (grub_ohci_td_virt2phys (o, td_current_virt)); + cdata->ed_virt->td_tail + = grub_cpu_to_le32 (grub_ohci_td_virt2phys (o, cdata->td_current_virt)); /* Now reset skip bit */ - ed_virt->target = grub_cpu_to_le32 (target); + cdata->ed_virt->target = grub_cpu_to_le32 (target); /* ed_virt->td_head = grub_cpu_to_le32 (td_head); Must not be changed, it is maintained by OHCI */ /* ed_virt->next_ed = grub_cpu_to_le32 (0); Handled by grub_ohci_find_ed, do not change ! */ @@ -834,93 +831,21 @@ grub_ohci_transfer (grub_usb_controller_t dev, } } - /* Safety measure to avoid a hang. */ - maxtime = grub_get_time_ms () + timeout; - - /* Wait until the transfer is completed or STALLs. */ - do - { - /* Check transfer status */ - intstatus = grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); - if (!o->bad_OHCI && (intstatus & 0x2) != 0) - { - /* Remember last successful TD */ - tderr_phys = grub_le_to_cpu32 (o->hcca->donehead) & ~0xf; - /* Reset DoneHead */ - o->hcca->donehead = 0; - grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1)); - /* Read back of register should ensure it is really written */ - grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); - /* if TD is last, finish */ - if (tderr_phys == td_last_phys) - { - if (grub_le_to_cpu32 (ed_virt->td_head) & 1) - err_halt = 1; - break; - } - continue; - } + transfer->controller_data = cdata; - if ((intstatus & 0x10) != 0) - { /* Unrecoverable error - only reset can help...! */ - err_unrec = 1; - break; - } + return GRUB_USB_ERR_NONE; +} - /* Detected a HALT. */ - if (err_halt || (grub_le_to_cpu32 (ed_virt->td_head) & 1)) - { - err_halt = 1; - /* ED is halted, but donehead event can happened in the meantime */ - intstatus = grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); - if (!o->bad_OHCI && (intstatus & 0x2) != 0) - /* Don't break loop now, first do donehead action(s) */ - continue; - break; - } - - /* bad OHCI handling */ - if ( (grub_le_to_cpu32 (ed_virt->td_head) & ~0xf) == - (grub_le_to_cpu32 (ed_virt->td_tail) & ~0xf) ) /* Empty ED */ - { - if (o->bad_OHCI) /* Bad OHCI detected previously */ - { - /* Try get last successful TD. */ - tderr_phys = grub_le_to_cpu32 (o->hcca->donehead) & ~0xf; - if (tderr_phys)/* Reset DoneHead if we were successful */ - { - o->hcca->donehead = 0; - grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1)); - /* Read back of register should ensure it is really written */ - grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); - } - /* Check the HALT bit */ - if (grub_le_to_cpu32 (ed_virt->td_head) & 1) - err_halt = 1; - break; - } - else /* Detection of bad OHCI */ - /* We should wait short time (~2ms) before we say that - * it is bad OHCI to prevent some hazard - - * donehead can react in the meantime. This waiting is done - * only once per OHCI driver "live cycle". */ - if (!bad_OHCI_delay) /* Set delay time */ - bad_OHCI_delay = grub_get_time_ms () + 2; - else if (grub_get_time_ms () >= bad_OHCI_delay) - o->bad_OHCI = 1; - continue; - } - - /* Timeout ? */ - if (grub_get_time_ms () > maxtime) - { - err_timeout = 1; - break; - } - - grub_cpu_idle (); - } - while (1); +static void +pre_finish_transfer (grub_usb_controller_t dev, + grub_usb_transfer_t transfer) +{ + struct grub_ohci *o = dev->data; + struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data; + grub_uint32_t target; + grub_uint32_t status; + grub_uint32_t control; + grub_uint32_t intstatus; /* There are many ways how the loop above can finish: * - normally without any error via INTSTATUS WDH bit @@ -952,8 +877,8 @@ grub_ohci_transfer (grub_usb_controller_t dev, /* Remember target for debug and set skip flag in ED */ /* It should be normaly not necessary but we need it at least * in case of timeout */ - target = grub_le_to_cpu32 ( ed_virt->target ); - ed_virt->target = grub_cpu_to_le32 (target | (1 << 14)); + target = grub_le_to_cpu32 ( cdata->ed_virt->target ); + cdata->ed_virt->target = grub_cpu_to_le32 (target | (1 << 14)); /* Read registers for debug - they should be read now because * debug prints case unwanted delays, so something can happen * in the meantime... */ @@ -963,253 +888,321 @@ grub_ohci_transfer (grub_usb_controller_t dev, /* Now print debug values - to have full info what happened */ grub_dprintf ("ohci", "loop finished: control=0x%02x status=0x%02x\n", control, status); - grub_dprintf ("ohci", "intstatus=0x%02x \n\t\t tderr_phys=0x%02x, td_last_phys=0x%02x\n", - intstatus, tderr_phys, td_last_phys); - grub_dprintf ("ohci", "err_unrec=%d, err_timeout=%d \n\t\t err_halt=%d, bad_OHCI=%d\n", - err_unrec, err_timeout, err_halt, o->bad_OHCI); + grub_dprintf ("ohci", "intstatus=0x%02x, td_last_phys=0x%02x\n", + intstatus, cdata->td_last_phys); grub_dprintf ("ohci", "TARGET=0x%02x, HEAD=0x%02x, TAIL=0x%02x\n", target, - grub_le_to_cpu32 (ed_virt->td_head), - grub_le_to_cpu32 (ed_virt->td_tail) ); + grub_le_to_cpu32 (cdata->ed_virt->td_head), + grub_le_to_cpu32 (cdata->ed_virt->td_tail) ); - if (!err_halt && !err_unrec && !err_timeout) /* normal finish */ - { - /* Simple workaround if donehead is not working */ - if (o->bad_OHCI && - ( !tderr_phys || (tderr_phys != td_last_phys) ) ) - { - grub_dprintf ("ohci", "normal finish, but tderr_phys corrected\n"); - tderr_phys = td_last_phys; - /* I hope we can do it as transfer (most probably) finished OK */ - } - /* Prepare pointer to last processed TD */ - tderr_virt = grub_ohci_td_phys2virt (o, tderr_phys); - /* Set index of last processed TD */ - if (tderr_virt) - transfer->last_trans = tderr_virt->tr_index; - else - transfer->last_trans = -1; - *actual = transfer->size + 1; - } +} - else if (err_halt) /* error, ED is halted by OHCI, i.e. can be modified */ - { - /* First we must get proper tderr_phys value */ - if (o->bad_OHCI) /* In case of bad_OHCI tderr_phys can be wrong */ - { - if ( tderr_phys ) /* check if tderr_phys points to TD with error */ - errcode = grub_le_to_cpu32 ( grub_ohci_td_phys2virt (o, - tderr_phys)->token ) - >> 28; - if ( !tderr_phys || !errcode ) /* tderr_phys not valid or points to wrong TD */ - { /* Retired TD with error should be previous TD to ED->td_head */ - tderr_phys = grub_ohci_td_phys2virt (o, - grub_le_to_cpu32 ( ed_virt->td_head) & ~0xf ) - ->prev_td_phys; - } - } - - /* Even if we have "good" OHCI, in some cases - * tderr_phys can be zero, check it */ - else if ( !tderr_phys ) - { /* Retired TD with error should be previous TD to ED->td_head */ - tderr_phys = grub_ohci_td_phys2virt (o, - grub_le_to_cpu32 ( ed_virt->td_head) & ~0xf ) - ->prev_td_phys; - } - - /* Prepare pointer to last processed TD and get error code */ - tderr_virt = grub_ohci_td_phys2virt (o, tderr_phys); - /* Set index of last processed TD */ - if (tderr_virt) - { - errcode = grub_le_to_cpu32 ( tderr_virt->token ) >> 28; - transfer->last_trans = tderr_virt->tr_index; - } - else - transfer->last_trans = -1; - - /* Evaluation of error code */ - grub_dprintf ("ohci", "OHCI tderr_phys=0x%02x, errcode=0x%02x\n", - tderr_phys, errcode); - switch (errcode) - { - case 0: - /* XXX: Should not happen! */ - grub_error (GRUB_ERR_IO, "OHCI failed without reporting the reason"); - err = GRUB_USB_ERR_INTERNAL; - break; - - case 1: - /* XXX: CRC error. */ - err = GRUB_USB_ERR_TIMEOUT; - break; - - case 2: - err = GRUB_USB_ERR_BITSTUFF; - break; - - case 3: - /* XXX: Data Toggle error. */ - err = GRUB_USB_ERR_DATA; - break; - - case 4: - err = GRUB_USB_ERR_STALL; - break; - - case 5: - /* XXX: Not responding. */ - err = GRUB_USB_ERR_TIMEOUT; - break; - - case 6: - /* XXX: PID Check bits failed. */ - err = GRUB_USB_ERR_BABBLE; - break; - - case 7: - /* XXX: PID unexpected failed. */ - err = GRUB_USB_ERR_BABBLE; - break; - - case 8: - /* XXX: Data overrun error. */ - err = GRUB_USB_ERR_DATA; - grub_dprintf ("ohci", "Overrun, failed TD address: %p, index: %d\n", - tderr_virt, tderr_virt->tr_index); - break; - - case 9: - /* XXX: Data underrun error. */ - grub_dprintf ("ohci", "Underrun, failed TD address: %p, index: %d\n", - tderr_virt, tderr_virt->tr_index); - if (transfer->last_trans == -1) - break; - *actual = transfer->transactions[transfer->last_trans].size - - (grub_le_to_cpu32 (tderr_virt->buffer_end) - - grub_le_to_cpu32 (tderr_virt->buffer)) - + transfer->transactions[transfer->last_trans].preceding; - break; - - case 10: - /* XXX: Reserved. */ - err = GRUB_USB_ERR_NAK; - break; - - case 11: - /* XXX: Reserved. */ - err = GRUB_USB_ERR_NAK; - break; - - case 12: - /* XXX: Buffer overrun. */ - err = GRUB_USB_ERR_DATA; - break; - - case 13: - /* XXX: Buffer underrun. */ - err = GRUB_USB_ERR_DATA; - break; - - default: - err = GRUB_USB_ERR_NAK; - break; - } - - } - - else if (err_unrec) - { - /* Don't try to get error code and last processed TD for proper - * toggle bit value - anything can be invalid */ - err = GRUB_USB_ERR_UNRECOVERABLE; - grub_dprintf("ohci", "Unrecoverable error!"); - - /* Do OHCI reset in case of unrecoverable error - maybe we will need - * do more - re-enumerate bus etc. (?) */ - - /* Suspend the OHCI by issuing a reset. */ - grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, 1); /* XXX: Magic. */ - /* Read back of register should ensure it is really written */ - grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS); - grub_millisleep (1); - grub_dprintf ("ohci", "Unrecoverable error - OHCI reset\n"); - - /* Misc. resets. */ - o->hcca->donehead = 0; - grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, 0x7f); /* Clears everything */ - grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD, o->ed_ctrl_addr); - grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLCURR, 0); - grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, o->ed_bulk_addr); - grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKCURR, 0); - /* Read back of register should ensure it is really written */ - grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); - - /* Enable the OHCI. */ - grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, - (2 << 6) - | GRUB_OHCI_REG_CONTROL_CONTROL_ENABLE - | GRUB_OHCI_REG_CONTROL_BULK_ENABLE ); - } - - else if (err_timeout) - { - /* In case of timeout do not detect error from TD */ - err = GRUB_ERR_TIMEOUT; - grub_dprintf("ohci", "Timeout !\n"); - - /* We should wait for next SOF to be sure that ED is unaccessed - * by OHCI */ - /* SF bit reset. (SF bit indicates Start Of Frame (SOF) packet) */ - grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1<<2)); - /* Wait for new SOF */ - while ((grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS) & 0x4) == 0); - - /* Now we must find last processed TD if bad_OHCI == TRUE */ - if (o->bad_OHCI) - { /* Retired TD with error should be previous TD to ED->td_head */ - tderr_phys = grub_ohci_td_phys2virt (o, - grub_le_to_cpu32 ( ed_virt->td_head) & ~0xf) - ->prev_td_phys; - } - tderr_virt = grub_ohci_td_phys2virt (o, tderr_phys); - if (tderr_virt) - transfer->last_trans = tderr_virt->tr_index; - else - transfer->last_trans = -1; - } +static void +finish_transfer (grub_usb_controller_t dev, + grub_usb_transfer_t transfer) +{ + struct grub_ohci *o = dev->data; + struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data; /* Set empty ED - set HEAD = TAIL = last (not processed) TD */ - ed_virt->td_head = grub_cpu_to_le32 (grub_le_to_cpu32 (ed_virt->td_tail) & ~0xf); + cdata->ed_virt->td_head = grub_cpu_to_le32 (grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xf); /* At this point always should be: * ED has skip bit set and halted or empty or after next SOF, * i.e. it is safe to free all TDs except last not processed * ED HEAD == TAIL == phys. addr. of td_current_virt */ - /* Reset DoneHead - sanity cleanup */ + /* Un-chainig of last TD */ + if (cdata->td_current_virt->prev_td_phys) + { + grub_ohci_td_t td_prev_virt + = grub_ohci_td_phys2virt (o, cdata->td_current_virt->prev_td_phys); + + if (cdata->td_current_virt == (grub_ohci_td_t) td_prev_virt->link_td) + td_prev_virt->link_td = 0; + + cdata->td_current_virt->prev_td_phys = 0; + } + + grub_dprintf ("ohci", "OHCI finished, freeing\n"); + grub_ohci_free_tds (o, cdata->td_head_virt); + grub_free (cdata); +} + +static grub_usb_err_t +parse_halt (grub_usb_controller_t dev, + grub_usb_transfer_t transfer, + grub_size_t *actual) +{ + struct grub_ohci *o = dev->data; + struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data; + grub_uint8_t errcode = 0; + grub_usb_err_t err = GRUB_USB_ERR_NAK; + grub_ohci_td_t tderr_virt = NULL; + + *actual = 0; + + pre_finish_transfer (dev, transfer); + + /* First we must get proper tderr_phys value */ + /* Retired TD with error should be previous TD to ED->td_head */ + cdata->tderr_phys = grub_ohci_td_phys2virt (o, + grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xf ) + ->prev_td_phys; + + /* Prepare pointer to last processed TD and get error code */ + tderr_virt = grub_ohci_td_phys2virt (o, cdata->tderr_phys); + /* Set index of last processed TD */ + if (tderr_virt) + { + errcode = grub_le_to_cpu32 (tderr_virt->token) >> 28; + transfer->last_trans = tderr_virt->tr_index; + } + else + transfer->last_trans = -1; + + /* Evaluation of error code */ + grub_dprintf ("ohci", "OHCI tderr_phys=0x%02x, errcode=0x%02x\n", + cdata->tderr_phys, errcode); + switch (errcode) + { + case 0: + /* XXX: Should not happen! */ + grub_error (GRUB_ERR_IO, "OHCI failed without reporting the reason"); + err = GRUB_USB_ERR_INTERNAL; + break; + + case 1: + /* XXX: CRC error. */ + err = GRUB_USB_ERR_TIMEOUT; + break; + + case 2: + err = GRUB_USB_ERR_BITSTUFF; + break; + + case 3: + /* XXX: Data Toggle error. */ + err = GRUB_USB_ERR_DATA; + break; + + case 4: + err = GRUB_USB_ERR_STALL; + break; + + case 5: + /* XXX: Not responding. */ + err = GRUB_USB_ERR_TIMEOUT; + break; + + case 6: + /* XXX: PID Check bits failed. */ + err = GRUB_USB_ERR_BABBLE; + break; + + case 7: + /* XXX: PID unexpected failed. */ + err = GRUB_USB_ERR_BABBLE; + break; + + case 8: + /* XXX: Data overrun error. */ + err = GRUB_USB_ERR_DATA; + grub_dprintf ("ohci", "Overrun, failed TD address: %p, index: %d\n", + tderr_virt, tderr_virt->tr_index); + break; + + case 9: + /* XXX: Data underrun error. */ + grub_dprintf ("ohci", "Underrun, failed TD address: %p, index: %d\n", + tderr_virt, tderr_virt->tr_index); + if (transfer->last_trans == -1) + break; + *actual = transfer->transactions[transfer->last_trans].size + - (grub_le_to_cpu32 (tderr_virt->buffer_end) + - grub_le_to_cpu32 (tderr_virt->buffer)) + + transfer->transactions[transfer->last_trans].preceding; + err = GRUB_USB_ERR_NONE; + break; + + case 10: + /* XXX: Reserved. */ + err = GRUB_USB_ERR_NAK; + break; + + case 11: + /* XXX: Reserved. */ + err = GRUB_USB_ERR_NAK; + break; + + case 12: + /* XXX: Buffer overrun. */ + err = GRUB_USB_ERR_DATA; + break; + + case 13: + /* XXX: Buffer underrun. */ + err = GRUB_USB_ERR_DATA; + break; + + default: + err = GRUB_USB_ERR_NAK; + break; + } + + finish_transfer (dev, transfer); + + return err; +} + +static grub_usb_err_t +parse_success (grub_usb_controller_t dev, + grub_usb_transfer_t transfer, + grub_size_t *actual) +{ + struct grub_ohci *o = dev->data; + struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data; + grub_ohci_td_t tderr_virt = NULL; + + pre_finish_transfer (dev, transfer); + + /* I hope we can do it as transfer (most probably) finished OK */ + cdata->tderr_phys = cdata->td_last_phys; + + /* Prepare pointer to last processed TD */ + tderr_virt = grub_ohci_td_phys2virt (o, cdata->tderr_phys); + + /* Set index of last processed TD */ + if (tderr_virt) + transfer->last_trans = tderr_virt->tr_index; + else + transfer->last_trans = -1; + *actual = transfer->size + 1; + + finish_transfer (dev, transfer); + + return GRUB_USB_ERR_NONE; +} + +static grub_usb_err_t +parse_unrec (grub_usb_controller_t dev, + grub_usb_transfer_t transfer, + grub_size_t *actual) +{ + struct grub_ohci *o = dev->data; + + *actual = 0; + + pre_finish_transfer (dev, transfer); + + /* Don't try to get error code and last processed TD for proper + * toggle bit value - anything can be invalid */ + grub_dprintf("ohci", "Unrecoverable error!"); + + /* Do OHCI reset in case of unrecoverable error - maybe we will need + * do more - re-enumerate bus etc. (?) */ + + /* Suspend the OHCI by issuing a reset. */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, 1); /* XXX: Magic. */ + /* Read back of register should ensure it is really written */ + grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS); + grub_millisleep (1); + grub_dprintf ("ohci", "Unrecoverable error - OHCI reset\n"); + + /* Misc. resets. */ o->hcca->donehead = 0; - grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1)); + grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, 0x7f); /* Clears everything */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD, o->ed_ctrl_addr); + grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLCURR, 0); + grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, o->ed_bulk_addr); + grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKCURR, 0); /* Read back of register should ensure it is really written */ grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); - /* Un-chainig of last TD */ - if (td_current_virt->prev_td_phys) - { - grub_ohci_td_t td_prev_virt - = grub_ohci_td_phys2virt (o, td_current_virt->prev_td_phys); + /* Enable the OHCI. */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, + (2 << 6) + | GRUB_OHCI_REG_CONTROL_CONTROL_ENABLE + | GRUB_OHCI_REG_CONTROL_BULK_ENABLE ); + finish_transfer (dev, transfer); - td_next_virt = (grub_ohci_td_t) td_prev_virt->link_td; - if (td_current_virt == td_next_virt) - td_prev_virt->link_td = 0; + return GRUB_USB_ERR_UNRECOVERABLE; +} + +static grub_usb_err_t +grub_ohci_check_transfer (grub_usb_controller_t dev, + grub_usb_transfer_t transfer, + grub_size_t *actual) +{ + struct grub_ohci *o = dev->data; + struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data; + grub_uint32_t intstatus; + + /* Check transfer status */ + intstatus = grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); + + if ((intstatus & 0x10) != 0) + /* Unrecoverable error - only reset can help...! */ + return parse_unrec (dev, transfer, actual); + + /* Detected a HALT. */ + if ((grub_le_to_cpu32 (cdata->ed_virt->td_head) & 1)) + return parse_halt (dev, transfer, actual); + + /* Finished ED detection */ + if ( (grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xf) == + (grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xf) ) /* Empty ED */ + { + /* Check the HALT bit */ + /* It looks like nonsense - it was tested previously... + * but it can change because OHCI is working + * simultaneously via DMA... */ + if (grub_le_to_cpu32 (cdata->ed_virt->td_head) & 1) + return parse_halt (dev, transfer, actual); + else + return parse_success (dev, transfer, actual); } - grub_dprintf ("ohci", "OHCI finished, freeing, err=0x%02x, errcode=0x%02x\n", - err, errcode); - grub_ohci_free_tds (o, td_head_virt); + return GRUB_USB_ERR_WAIT; +} - return err; +static grub_usb_err_t +grub_ohci_cancel_transfer (grub_usb_controller_t dev, + grub_usb_transfer_t transfer) +{ + struct grub_ohci *o = dev->data; + struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data; + grub_ohci_td_t tderr_virt = NULL; + + pre_finish_transfer (dev, transfer); + + grub_dprintf("ohci", "Timeout !\n"); + + /* We should wait for next SOF to be sure that ED is unaccessed + * by OHCI */ + /* SF bit reset. (SF bit indicates Start Of Frame (SOF) packet) */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1<<2)); + /* Wait for new SOF */ + while ((grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS) & 0x4) == 0); + + /* Possible retired TD with error should be previous TD to ED->td_head */ + cdata->tderr_phys + = grub_ohci_td_phys2virt (o, grub_le_to_cpu32 (cdata->ed_virt->td_head) + & ~0xf)->prev_td_phys; + + tderr_virt = grub_ohci_td_phys2virt (o,cdata-> tderr_phys); + + grub_dprintf ("ohci", "Cancel: tderr_phys=0x%08x, tderr_virt=0x%08x\n", + cdata->tderr_phys, (unsigned int)tderr_virt); + + if (tderr_virt) + transfer->last_trans = tderr_virt->tr_index; + else + transfer->last_trans = -1; + + finish_transfer (dev, transfer); + + return GRUB_USB_ERR_NONE; } static grub_err_t @@ -1218,6 +1211,7 @@ grub_ohci_portstatus (grub_usb_controller_t dev, { struct grub_ohci *o = (struct grub_ohci *) dev->data; grub_uint64_t endtime; + int i; grub_dprintf ("ohci", "begin of portstatus=0x%02x\n", grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port)); @@ -1238,31 +1232,47 @@ grub_ohci_portstatus (grub_usb_controller_t dev, return GRUB_ERR_NONE; } - /* Reset the port */ - grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, - GRUB_OHCI_SET_PORT_RESET); - grub_millisleep (50); /* For root hub should be nominaly 50ms */ - - /* End the reset signaling. */ - grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, - GRUB_OHCI_SET_PORT_RESET_STATUS_CHANGE); - grub_millisleep (10); + /* OHCI does one reset signal 10ms long but USB spec. + * requests 50ms for root hub (no need to be continuous). + * So, we do reset 5 times... */ + for (i = 0; i < 5; i++) + { + /* Reset the port - timing of reset is done by OHCI */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, + GRUB_OHCI_SET_PORT_RESET); - /* Enable the port and wait for it. */ + /* Wait for reset completion */ + endtime = grub_get_time_ms () + 1000; + while (! (grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port) + & GRUB_OHCI_SET_PORT_RESET_STATUS_CHANGE)) + if (grub_get_time_ms () > endtime) + return grub_error (GRUB_ERR_IO, "OHCI Timed out - reset"); + + /* End the reset signaling - reset the reset status change */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, + GRUB_OHCI_SET_PORT_RESET_STATUS_CHANGE); + grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port); + } + + /* Enable port */ grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, GRUB_OHCI_SET_PORT_ENABLE); + grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port); + + /* Wait for signal enabled */ endtime = grub_get_time_ms () + 1000; while (! (grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port) & (1 << 1))) if (grub_get_time_ms () > endtime) return grub_error (GRUB_ERR_IO, "OHCI Timed out - enable"); - grub_millisleep (10); - /* Reset bit Connect Status Change */ grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, GRUB_OHCI_RESET_CONNECT_CHANGE); + /* "Reset recovery time" (USB spec.) */ + grub_millisleep (10); + grub_dprintf ("ohci", "end of portstatus=0x%02x\n", grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port)); @@ -1279,8 +1289,16 @@ grub_ohci_detect_dev (grub_usb_controller_t dev, int port, int *changed) grub_dprintf ("ohci", "detect_dev status=0x%02x\n", status); - /* Connect Status Change bit - it detects change of connection */ - *changed = ((status & GRUB_OHCI_RESET_CONNECT_CHANGE) != 0); + /* Connect Status Change bit - it detects change of connection */ + if (status & GRUB_OHCI_RESET_CONNECT_CHANGE) + { + *changed = 1; + /* Reset bit Connect Status Change */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, + GRUB_OHCI_RESET_CONNECT_CHANGE); + } + else + *changed = 0; if (! (status & 1)) return GRUB_USB_SPEED_NONE; @@ -1398,7 +1416,9 @@ static struct grub_usb_controller_dev usb_controller = { .name = "ohci", .iterate = grub_ohci_iterate, - .transfer = grub_ohci_transfer, + .setup_transfer = grub_ohci_setup_transfer, + .check_transfer = grub_ohci_check_transfer, + .cancel_transfer = grub_ohci_cancel_transfer, .hubports = grub_ohci_hubports, .portstatus = grub_ohci_portstatus, .detect_dev = grub_ohci_detect_dev diff --git a/grub-core/bus/usb/uhci.c b/grub-core/bus/usb/uhci.c index 1fe86f5d4..2265ebed0 100644 --- a/grub-core/bus/usb/uhci.c +++ b/grub-core/bus/usb/uhci.c @@ -28,6 +28,8 @@ #define GRUB_UHCI_IOMASK (0x7FF << 5) +#define N_QH 256 + typedef enum { GRUB_UHCI_REG_USBCMD = 0x00, @@ -39,6 +41,21 @@ typedef enum #define GRUB_UHCI_LINK_TERMINATE 1 #define GRUB_UHCI_LINK_QUEUE_HEAD 2 +enum + { + GRUB_UHCI_REG_PORTSC_CONNECT_CHANGED = 0x0002, + GRUB_UHCI_REG_PORTSC_PORT_ENABLED = 0x0004, + GRUB_UHCI_REG_PORTSC_RESUME = 0x0040, + GRUB_UHCI_REG_PORTSC_RESET = 0x0200, + GRUB_UHCI_REG_PORTSC_SUSPEND = 0x1000, + GRUB_UHCI_REG_PORTSC_RW = GRUB_UHCI_REG_PORTSC_PORT_ENABLED + | GRUB_UHCI_REG_PORTSC_RESUME | GRUB_UHCI_REG_PORTSC_RESET + | GRUB_UHCI_REG_PORTSC_SUSPEND, + /* These bits should not be written as 1 unless we really need it */ + GRUB_UHCI_PORTSC_RWC = ((1 << 1) | (1 << 3) | (1 << 11) | (3 << 13)) + }; + +#define /* UHCI Queue Head. */ struct grub_uhci_qh @@ -87,7 +104,7 @@ struct grub_uhci int iobase; grub_uint32_t *framelist; - /* 256 Queue Heads. */ + /* N_QH Queue Heads. */ grub_uhci_qh_t qh; /* 256 Transfer Descriptors. */ @@ -96,6 +113,8 @@ struct grub_uhci /* Free Transfer Descriptors. */ grub_uhci_td_t tdfree; + int qh_busy[N_QH]; + struct grub_uhci *next; }; @@ -248,7 +267,7 @@ grub_uhci_pci_iter (grub_pci_device_t dev, (grub_uint32_t) (grub_addr_t) u->framelist); /* Make the Queue Heads point to each other. */ - for (i = 0; i < 256; i++) + for (i = 0; i < N_QH; i++) { /* Point to the next QH. */ u->qh[i].linkptr = (grub_uint32_t) (grub_addr_t) (&u->qh[i + 1]) & (~15); @@ -261,9 +280,8 @@ grub_uhci_pci_iter (grub_pci_device_t dev, u->qh[i].elinkptr = 1; } - /* The last Queue Head should terminate. 256 are too many QHs so - just use 50. */ - u->qh[50 - 1].linkptr = 1; + /* The last Queue Head should terminate. */ + u->qh[N_QH - 1].linkptr = 1; /* Enable UHCI again. */ grub_uhci_writereg16 (u, GRUB_UHCI_REG_USBCMD, 1 | (1 << 7)); @@ -332,11 +350,13 @@ grub_free_td (struct grub_uhci *u, grub_uhci_td_t td) } static void -grub_free_queue (struct grub_uhci *u, grub_uhci_td_t td, +grub_free_queue (struct grub_uhci *u, grub_uhci_qh_t qh, grub_uhci_td_t td, grub_usb_transfer_t transfer, grub_size_t *actual) { int i; /* Index of TD in transfer */ + u->qh_busy[qh - u->qh] = 0; + *actual = 0; /* Free the TDs in this queue and set last_trans. */ @@ -375,19 +395,21 @@ grub_alloc_qh (struct grub_uhci *u, #endif i = 1; - for (; i < 255; i++) + for (; i < N_QH; i++) { - if (u->qh[i].elinkptr & 1) + if (!u->qh_busy[i]) break; } qh = &u->qh[i]; - if (! (qh->elinkptr & 1)) + if (i == N_QH) { grub_error (GRUB_ERR_OUT_OF_MEMORY, "no free queue heads available"); return NULL; } + u->qh_busy[qh - u->qh] = 1; + return qh; } @@ -395,7 +417,7 @@ static grub_uhci_td_t grub_uhci_transaction (struct grub_uhci *u, unsigned int endp, grub_transfer_type_t type, unsigned int addr, unsigned int toggle, grub_size_t size, - grub_uint32_t data) + grub_uint32_t data, grub_usb_speed_t speed) { grub_uhci_td_t td; static const unsigned int tf[] = { 0x69, 0xE1, 0x2D }; @@ -420,7 +442,8 @@ grub_uhci_transaction (struct grub_uhci *u, unsigned int endp, td->linkptr = 1; /* Active! Only retry a transfer 3 times. */ - td->ctrl_status = (1 << 23) | (3 << 27); + td->ctrl_status = (1 << 23) | (3 << 27) | + ((speed == GRUB_USB_SPEED_LOW) ? (1 << 26) : 0); /* If zero bytes are transmitted, size is 0x7FF. Otherwise size is size-1. */ @@ -438,26 +461,35 @@ grub_uhci_transaction (struct grub_uhci *u, unsigned int endp, return td; } +struct grub_uhci_transfer_controller_data +{ + grub_uhci_qh_t qh; + grub_uhci_td_t td_first; +}; + static grub_usb_err_t -grub_uhci_transfer (grub_usb_controller_t dev, - grub_usb_transfer_t transfer, - int timeout, grub_size_t *actual) +grub_uhci_setup_transfer (grub_usb_controller_t dev, + grub_usb_transfer_t transfer) { struct grub_uhci *u = (struct grub_uhci *) dev->data; - grub_uhci_qh_t qh; grub_uhci_td_t td; - grub_uhci_td_t td_first = NULL; grub_uhci_td_t td_prev = NULL; - grub_usb_err_t err = GRUB_USB_ERR_NONE; int i; - grub_uint64_t endtime; + struct grub_uhci_transfer_controller_data *cdata; - *actual = 0; + cdata = grub_malloc (sizeof (*cdata)); + if (!cdata) + return GRUB_USB_ERR_INTERNAL; + + cdata->td_first = NULL; /* Allocate a queue head for the transfer queue. */ - qh = grub_alloc_qh (u, GRUB_USB_TRANSACTION_TYPE_CONTROL); - if (! qh) - return GRUB_USB_ERR_INTERNAL; + cdata->qh = grub_alloc_qh (u, GRUB_USB_TRANSACTION_TYPE_CONTROL); + if (! cdata->qh) + { + grub_free (cdata); + return GRUB_USB_ERR_INTERNAL; + } grub_dprintf ("uhci", "transfer, iobase:%08x\n", u->iobase); @@ -465,23 +497,26 @@ grub_uhci_transfer (grub_usb_controller_t dev, { grub_usb_transaction_t tr = &transfer->transactions[i]; - td = grub_uhci_transaction (u, transfer->endpoint, tr->pid, + td = grub_uhci_transaction (u, transfer->endpoint & 15, tr->pid, transfer->devaddr, tr->toggle, - tr->size, tr->data); + tr->size, tr->data, + transfer->dev->speed); if (! td) { + grub_size_t actual = 0; /* Terminate and free. */ td_prev->linkptr2 = 0; td_prev->linkptr = 1; - if (td_first) - grub_free_queue (u, td_first, NULL, actual); + if (cdata->td_first) + grub_free_queue (u, cdata->qh, cdata->td_first, NULL, &actual); + grub_free (cdata); return GRUB_USB_ERR_INTERNAL; } - if (! td_first) - td_first = td; + if (! cdata->td_first) + cdata->td_first = td; else { td_prev->linkptr2 = (grub_uint32_t) (grub_addr_t) td; @@ -497,81 +532,112 @@ grub_uhci_transfer (grub_usb_controller_t dev, /* Link it into the queue and terminate. Now the transaction can take place. */ - qh->elinkptr = (grub_uint32_t) (grub_addr_t) td_first; + cdata->qh->elinkptr = (grub_uint32_t) (grub_addr_t) cdata->td_first; grub_dprintf ("uhci", "initiate transaction\n"); - /* Wait until either the transaction completed or an error - occurred. */ - endtime = grub_get_time_ms () + timeout; - for (;;) + transfer->controller_data = cdata; + + return GRUB_USB_ERR_NONE; +} + +static grub_usb_err_t +grub_uhci_check_transfer (grub_usb_controller_t dev, + grub_usb_transfer_t transfer, + grub_size_t *actual) +{ + struct grub_uhci *u = (struct grub_uhci *) dev->data; + grub_uhci_td_t errtd; + struct grub_uhci_transfer_controller_data *cdata = transfer->controller_data; + + *actual = 0; + + errtd = (grub_uhci_td_t) (cdata->qh->elinkptr & ~0x0f); + + grub_dprintf ("uhci", ">t status=0x%02x data=0x%02x td=%p\n", + errtd->ctrl_status, errtd->buffer & (~15), errtd); + + /* Check if the transaction completed. */ + if (cdata->qh->elinkptr & 1) { - grub_uhci_td_t errtd; + grub_dprintf ("uhci", "transaction complete\n"); - errtd = (grub_uhci_td_t) (grub_addr_t) (qh->elinkptr & ~0x0f); + /* Place the QH back in the free list and deallocate the associated + TDs. */ + cdata->qh->elinkptr = 1; + grub_free_queue (u, cdata->qh, cdata->td_first, transfer, actual); + grub_free (cdata); + return GRUB_USB_ERR_NONE; + } - grub_dprintf ("uhci", ">t status=0x%02x data=0x%02x td=%p\n", - errtd->ctrl_status, errtd->buffer & (~15), errtd); + grub_dprintf ("uhci", "t status=0x%02x\n", errtd->ctrl_status); - /* Check if the transaction completed. */ - if (qh->elinkptr & 1) - break; - - grub_dprintf ("uhci", "t status=0x%02x\n", errtd->ctrl_status); + if (!(errtd->ctrl_status & (1 << 23))) + { + grub_usb_err_t err = GRUB_USB_ERR_NONE; /* Check if the endpoint is stalled. */ if (errtd->ctrl_status & (1 << 22)) err = GRUB_USB_ERR_STALL; - + /* Check if an error related to the data buffer occurred. */ - if (errtd->ctrl_status & (1 << 21)) + else if (errtd->ctrl_status & (1 << 21)) err = GRUB_USB_ERR_DATA; - + /* Check if a babble error occurred. */ - if (errtd->ctrl_status & (1 << 20)) + else if (errtd->ctrl_status & (1 << 20)) err = GRUB_USB_ERR_BABBLE; - + /* Check if a NAK occurred. */ - if (errtd->ctrl_status & (1 << 19)) + else if (errtd->ctrl_status & (1 << 19)) err = GRUB_USB_ERR_NAK; - + /* Check if a timeout occurred. */ - if (errtd->ctrl_status & (1 << 18)) + else if (errtd->ctrl_status & (1 << 18)) err = GRUB_USB_ERR_TIMEOUT; - + /* Check if a bitstuff error occurred. */ - if (errtd->ctrl_status & (1 << 17)) + else if (errtd->ctrl_status & (1 << 17)) err = GRUB_USB_ERR_BITSTUFF; - + if (err) - goto fail; - - /* Fall through, no errors occurred, so the QH might be - updated. */ - grub_dprintf ("uhci", "transaction fallthrough\n"); - - if (grub_get_time_ms () > endtime) { - err = GRUB_USB_ERR_STALL; - grub_dprintf ("uhci", "transaction timed out\n"); - goto fail; + grub_dprintf ("uhci", "transaction failed\n"); + + /* Place the QH back in the free list and deallocate the associated + TDs. */ + cdata->qh->elinkptr = 1; + grub_free_queue (u, cdata->qh, cdata->td_first, transfer, actual); + grub_free (cdata); + + return err; } - grub_cpu_idle (); } - grub_dprintf ("uhci", "transaction complete\n"); + /* Fall through, no errors occurred, so the QH might be + updated. */ + grub_dprintf ("uhci", "transaction fallthrough\n"); - fail: + return GRUB_USB_ERR_WAIT; +} - if (err != GRUB_USB_ERR_NONE) - grub_dprintf ("uhci", "transaction failed\n"); +static grub_usb_err_t +grub_uhci_cancel_transfer (grub_usb_controller_t dev, + grub_usb_transfer_t transfer) +{ + struct grub_uhci *u = (struct grub_uhci *) dev->data; + grub_size_t actual; + struct grub_uhci_transfer_controller_data *cdata = transfer->controller_data; + + grub_dprintf ("uhci", "transaction cancel\n"); /* Place the QH back in the free list and deallocate the associated TDs. */ - qh->elinkptr = 1; - grub_free_queue (u, td_first, transfer, actual); + cdata->qh->elinkptr = 1; + grub_free_queue (u, cdata->qh, cdata->td_first, transfer, &actual); + grub_free (cdata); - return err; + return GRUB_USB_ERR_NONE; } static int @@ -622,7 +688,7 @@ grub_uhci_portstatus (grub_usb_controller_t dev, endtime = grub_get_time_ms () + 1000; while ((grub_uhci_readreg16 (u, reg) & (1 << 2))) if (grub_get_time_ms () > endtime) - return grub_error (GRUB_ERR_IO, "UHCI Timed out"); + return grub_error (GRUB_ERR_IO, "UHCI Timed out - disable"); status = grub_uhci_readreg16 (u, reg); grub_dprintf ("uhci", ">3detect=0x%02x\n", status); @@ -630,28 +696,37 @@ grub_uhci_portstatus (grub_usb_controller_t dev, } /* Reset the port. */ - grub_uhci_writereg16 (u, reg, 1 << 9); + status = grub_uhci_readreg16 (u, reg) & ~GRUB_UHCI_PORTSC_RWC; + grub_uhci_writereg16 (u, reg, status | (1 << 9)); + grub_uhci_readreg16 (u, reg); /* Ensure it is writen... */ /* Wait for the reset to complete. XXX: How long exactly? */ grub_millisleep (50); /* For root hub should be nominaly 50ms */ - status = grub_uhci_readreg16 (u, reg); + status = grub_uhci_readreg16 (u, reg) & ~GRUB_UHCI_PORTSC_RWC; grub_uhci_writereg16 (u, reg, status & ~(1 << 9)); - grub_dprintf ("uhci", "reset completed\n"); - grub_millisleep (10); + grub_uhci_readreg16 (u, reg); /* Ensure it is writen... */ + + /* Note: some debug prints were removed because they affected reset/enable timing. */ + + grub_millisleep (1); /* Probably not needed at all or only few microsecs. */ + + /* Reset bits Connect & Enable Status Change */ + status = grub_uhci_readreg16 (u, reg) & ~GRUB_UHCI_PORTSC_RWC; + grub_uhci_writereg16 (u, reg, status | (1 << 3) | GRUB_UHCI_REG_PORTSC_CONNECT_CHANGED); + grub_uhci_readreg16 (u, reg); /* Ensure it is writen... */ /* Enable the port. */ - grub_uhci_writereg16 (u, reg, 1 << 2); - grub_millisleep (10); - - grub_dprintf ("uhci", "waiting for the port to be enabled\n"); + status = grub_uhci_readreg16 (u, reg) & ~GRUB_UHCI_PORTSC_RWC; + grub_uhci_writereg16 (u, reg, status | (1 << 2)); + grub_uhci_readreg16 (u, reg); /* Ensure it is writen... */ endtime = grub_get_time_ms () + 1000; while (! ((status = grub_uhci_readreg16 (u, reg)) & (1 << 2))) if (grub_get_time_ms () > endtime) - return grub_error (GRUB_ERR_IO, "UHCI Timed out"); + return grub_error (GRUB_ERR_IO, "UHCI Timed out - enable"); - /* Reset bit Connect Status Change */ - grub_uhci_writereg16 (u, reg, status | (1 << 1)); + /* Reset recovery time */ + grub_millisleep (10); /* Read final port status */ status = grub_uhci_readreg16 (u, reg); @@ -683,7 +758,15 @@ grub_uhci_detect_dev (grub_usb_controller_t dev, int port, int *changed) grub_dprintf ("uhci", "detect=0x%02x port=%d\n", status, port); /* Connect Status Change bit - it detects change of connection */ - *changed = ((status & (1 << 1)) != 0); + if (status & (1 << 1)) + { + *changed = 1; + /* Reset bit Connect Status Change */ + grub_uhci_writereg16 (u, reg, (status & GRUB_UHCI_REG_PORTSC_RW) + | GRUB_UHCI_REG_PORTSC_CONNECT_CHANGED); + } + else + *changed = 0; if (! (status & 1)) return GRUB_USB_SPEED_NONE; @@ -705,7 +788,9 @@ static struct grub_usb_controller_dev usb_controller = { .name = "uhci", .iterate = grub_uhci_iterate, - .transfer = grub_uhci_transfer, + .setup_transfer = grub_uhci_setup_transfer, + .check_transfer = grub_uhci_check_transfer, + .cancel_transfer = grub_uhci_cancel_transfer, .hubports = grub_uhci_hubports, .portstatus = grub_uhci_portstatus, .detect_dev = grub_uhci_detect_dev diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c index 7f2c8d24b..73d233642 100644 --- a/grub-core/bus/usb/usbhub.c +++ b/grub-core/bus/usb/usbhub.c @@ -28,6 +28,8 @@ /* USB Supports 127 devices, with device 0 as special case. */ static struct grub_usb_device *grub_usb_devs[GRUB_USBHUB_MAX_DEVICES]; +static int rescan = 0; + struct grub_usb_hub { struct grub_usb_hub *next; @@ -110,9 +112,6 @@ grub_usb_add_hub (grub_usb_device_t dev) struct grub_usb_usb_hubdesc hubdesc; grub_err_t err; int i; - grub_uint64_t timeout; - grub_usb_device_t next_dev; - grub_usb_device_t *attached_devices; err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN | GRUB_USB_REQTYPE_CLASS @@ -131,11 +130,9 @@ grub_usb_add_hub (grub_usb_device_t dev) grub_dprintf ("usb", "Hub set configuration\n"); grub_usb_set_configuration (dev, 1); - attached_devices = grub_zalloc (hubdesc.portcnt - * sizeof (attached_devices[0])); - if (!attached_devices) + dev->children = grub_zalloc (hubdesc.portcnt * sizeof (dev->children[0])); + if (!dev->children) return GRUB_USB_ERR_INTERNAL; - dev->children = attached_devices; dev->nports = hubdesc.portcnt; /* Power on all Hub ports. */ @@ -143,115 +140,36 @@ grub_usb_add_hub (grub_usb_device_t dev) { grub_dprintf ("usb", "Power on - port %d\n", i); /* Power on the port and wait for possible device connect */ - err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_OTHER), - GRUB_USB_REQ_SET_FEATURE, - GRUB_USB_HUB_FEATURE_PORT_POWER, - i, 0, NULL); - /* Just ignore the device if some error happened */ - if (err) - continue; + grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_SET_FEATURE, + GRUB_USB_HUB_FEATURE_PORT_POWER, + i, 0, NULL); } - /* Wait for port power-on */ - if (hubdesc.pwdgood >= 50) - grub_millisleep (hubdesc.pwdgood * 2); - else - grub_millisleep (100); - - /* Iterate over the Hub ports. */ - for (i = 1; i <= hubdesc.portcnt; i++) + + /* Rest will be done on next usb poll. */ + for (i = 0; i < dev->config[0].interf[0].descif->endpointcnt; + i++) { - grub_uint32_t status; + struct grub_usb_desc_endp *endp = NULL; + endp = &dev->config[0].interf[0].descendp[i]; - /* Get the port status. */ - err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_OTHER), - GRUB_USB_REQ_GET_STATUS, - 0, i, sizeof (status), (char *) &status); - /* Just ignore the device if the Hub does not report the - status. */ - if (err) - continue; - grub_dprintf ("usb", "Hub port %d status: 0x%02x\n", i, status); - - /* If connected, reset and enable the port. */ - if (status & GRUB_USB_HUB_STATUS_CONNECTED) + if ((endp->endp_addr & 128) && grub_usb_get_ep_type(endp) + == GRUB_USB_EP_INTERRUPT) { - grub_usb_speed_t speed; - - /* Determine the device speed. */ - if (status & GRUB_USB_HUB_STATUS_LOWSPEED) - speed = GRUB_USB_SPEED_LOW; - else - { - if (status & GRUB_USB_HUB_STATUS_HIGHSPEED) - speed = GRUB_USB_SPEED_HIGH; - else - speed = GRUB_USB_SPEED_FULL; - } - - /* A device is actually connected to this port. - * Now do reset of port. */ - grub_dprintf ("usb", "Reset hub port - port %d\n", i); - err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_OTHER), - GRUB_USB_REQ_SET_FEATURE, - GRUB_USB_HUB_FEATURE_PORT_RESET, - i, 0, 0); - /* If the Hub does not cooperate for this port, just skip - the port. */ - if (err) - continue; - - /* Wait for reset procedure done */ - timeout = grub_get_time_ms () + 1000; - do - { - /* Get the port status. */ - err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_OTHER), - GRUB_USB_REQ_GET_STATUS, - 0, i, sizeof (status), (char *) &status); - } - while (!err && - !(status & GRUB_USB_HUB_STATUS_C_PORT_RESET) && - (grub_get_time_ms() < timeout) ); - if (err || !(status & GRUB_USB_HUB_STATUS_C_PORT_RESET) ) - continue; - - /* Wait a recovery time after reset, spec. says 10ms */ - grub_millisleep (10); - - /* Do reset of connection change bit */ - err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_OTHER), - GRUB_USB_REQ_CLEAR_FEATURE, - GRUB_USB_HUB_FEATURE_C_CONNECTED, - i, 0, 0); - /* Just ignore the device if the Hub reports some error */ - if (err) - continue; - grub_dprintf ("usb", "Hub port - cleared connection change\n"); - - /* Add the device and assign a device address to it. */ - grub_dprintf ("usb", "Call hub_add_dev - port %d\n", i); - next_dev = grub_usb_hub_add_dev (&dev->controller, speed); - if (! next_dev) - continue; - - attached_devices[i - 1] = next_dev; - - /* If the device is a Hub, scan it for more devices. */ - if (next_dev->descdev.class == 0x09) - grub_usb_add_hub (next_dev); + dev->hub_endpoint = endp; + dev->hub_transfer + = grub_usb_bulk_read_background (dev, endp->endp_addr, + grub_min (endp->maxpacket, + sizeof (dev->statuschange)), + (char *) &dev->statuschange); + break; } } + rescan = 1; + return GRUB_ERR_NONE; } @@ -261,19 +179,45 @@ attach_root_port (struct grub_usb_hub *hub, int portno, { grub_usb_device_t dev; grub_err_t err; + int total, i; + grub_usb_speed_t current_speed = GRUB_USB_SPEED_NONE; + int changed=0; +#if 0 +/* Specification does not say about disabling of port when device + * connected. If disabling is really necessary for some devices, + * delete this #if 0 and related #endif */ /* Disable the port. XXX: Why? */ err = hub->controller->dev->portstatus (hub->controller, portno, 0); if (err) return; +#endif + /* Wait for completion of insertion and stable power (USB spec.) + * Should be at least 100ms, some devices requires more... + * There is also another thing - some devices have worse contacts + * and connected signal is unstable for some time - we should handle + * it - but prevent deadlock in case when device is too faulty... */ + for (total = i = 0; (i < 250) && (total < 2000); i++, total++) + { + grub_millisleep (1); + current_speed = hub->controller->dev->detect_dev + (hub->controller, portno, &changed); + if (current_speed == GRUB_USB_SPEED_NONE) + i = 0; + } + grub_dprintf ("usb", "total=%d\n", total); + if (total >= 2000) + return; /* Enable the port. */ err = hub->controller->dev->portstatus (hub->controller, portno, 1); if (err) return; + hub->controller->dev->pending_reset = grub_get_time_ms () + 5000; /* Enable the port and create a device. */ dev = grub_usb_hub_add_dev (hub->controller, speed); + hub->controller->dev->pending_reset = 0; if (! dev) return; @@ -320,11 +264,14 @@ grub_usb_root_hub (grub_usb_controller_t controller) for (i = 0; i < hub->nports; i++) { grub_usb_speed_t speed; - speed = controller->dev->detect_dev (hub->controller, i, - &changed); + if (!controller->dev->pending_reset) + { + speed = controller->dev->detect_dev (hub->controller, i, + &changed); - if (speed != GRUB_USB_SPEED_NONE) - attach_root_port (hub, i, speed); + if (speed != GRUB_USB_SPEED_NONE) + attach_root_port (hub, i, speed); + } } return GRUB_USB_ERR_NONE; @@ -341,6 +288,9 @@ detach_device (grub_usb_device_t dev) return; if (dev->descdev.class == GRUB_USB_CLASS_HUB) { + if (dev->hub_transfer) + grub_usb_cancel_transfer (dev->hub_transfer); + for (i = 0; i < dev->nports; i++) detach_device (dev->children[i]); grub_free (dev->children); @@ -361,14 +311,37 @@ poll_nonroot_hub (grub_usb_device_t dev) { grub_err_t err; unsigned i; - grub_uint64_t timeout; - grub_usb_device_t next_dev; - grub_usb_device_t *attached_devices = dev->children; - + grub_uint8_t changed; + grub_size_t actual; + int j, total; + + if (!dev->hub_transfer) + return; + + err = grub_usb_check_transfer (dev->hub_transfer, &actual); + + if (err == GRUB_USB_ERR_WAIT) + return; + + changed = dev->statuschange; + + dev->hub_transfer + = grub_usb_bulk_read_background (dev, dev->hub_endpoint->endp_addr, + grub_min (dev->hub_endpoint->maxpacket, + sizeof (dev->statuschange)), + (char *) &dev->statuschange); + + if (err || actual == 0 || changed == 0) + return; + /* Iterate over the Hub ports. */ for (i = 1; i <= dev->nports; i++) { grub_uint32_t status; + grub_uint32_t current_status = 0; + + if (!(changed & (1 << i))) + continue; /* Get the port status. */ err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN @@ -376,92 +349,140 @@ poll_nonroot_hub (grub_usb_device_t dev) | GRUB_USB_REQTYPE_TARGET_OTHER), GRUB_USB_REQ_GET_STATUS, 0, i, sizeof (status), (char *) &status); - /* Just ignore the device if the Hub does not report the - status. */ + + grub_printf ("dev = 0x%0x, i = %d, status = %08x\n", + (unsigned int) dev, i, status); + if (err) continue; - if (status & GRUB_USB_HUB_STATUS_C_CONNECTED) + /* FIXME: properly handle these conditions. */ + if (status & GRUB_USB_HUB_STATUS_C_PORT_ENABLED) + grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_CLEAR_FEATURE, + GRUB_USB_HUB_FEATURE_C_PORT_ENABLED, i, 0, 0); + + if (status & GRUB_USB_HUB_STATUS_C_PORT_SUSPEND) + grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_CLEAR_FEATURE, + GRUB_USB_HUB_FEATURE_C_PORT_SUSPEND, i, 0, 0); + + if (status & GRUB_USB_HUB_STATUS_C_PORT_OVERCURRENT) + grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_CLEAR_FEATURE, + GRUB_USB_HUB_FEATURE_C_PORT_OVERCURRENT, i, 0, 0); + + if (!dev->controller.dev->pending_reset && + (status & GRUB_USB_HUB_STATUS_C_PORT_CONNECTED)) { - detach_device (attached_devices[i-1]); - attached_devices[i - 1] = NULL; - } + grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_CLEAR_FEATURE, + GRUB_USB_HUB_FEATURE_C_PORT_CONNECTED, i, 0, 0); + + detach_device (dev->children[i - 1]); + dev->children[i - 1] = NULL; - /* Connected and status of connection changed ? */ - if ((status & GRUB_USB_HUB_STATUS_CONNECTED) - && (status & GRUB_USB_HUB_STATUS_C_CONNECTED)) - { - grub_usb_speed_t speed; - - /* Determine the device speed. */ - if (status & GRUB_USB_HUB_STATUS_LOWSPEED) - speed = GRUB_USB_SPEED_LOW; - else + /* Connected and status of connection changed ? */ + if (status & GRUB_USB_HUB_STATUS_PORT_CONNECTED) { - if (status & GRUB_USB_HUB_STATUS_HIGHSPEED) - speed = GRUB_USB_SPEED_HIGH; - else - speed = GRUB_USB_SPEED_FULL; + /* A device is actually connected to this port. */ + /* Wait for completion of insertion and stable power (USB spec.) + * Should be at least 100ms, some devices requires more... + * There is also another thing - some devices have worse contacts + * and connected signal is unstable for some time - we should handle + * it - but prevent deadlock in case when device is too faulty... */ + for (total = j = 0; (j < 250) && (total < 2000); j++, total++) + { + grub_millisleep (1); + /* Get the port status. */ + err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_GET_STATUS, + 0, i, + sizeof (current_status), + (char *) ¤t_status); + if (err) + { + total = 2000; + break; + } + if (!(current_status & GRUB_USB_HUB_STATUS_PORT_CONNECTED)) + j = 0; + } + grub_dprintf ("usb", "(non-root) total=%d\n", total); + if (total >= 2000) + continue; + + /* Now do reset of port. */ + grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_SET_FEATURE, + GRUB_USB_HUB_FEATURE_PORT_RESET, + i, 0, 0); + rescan = 1; + /* We cannot reset more than one device at the same time ! + * Resetting more devices together results in very bad + * situation: more than one device has default address 0 + * at the same time !!! + * Additionaly, we cannot perform another reset + * anywhere on the same OHCI controller until + * we will finish addressing of reseted device ! */ + dev->controller.dev->pending_reset = grub_get_time_ms () + 5000; + return; } + } - /* A device is actually connected to this port. - * Now do reset of port. */ - err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_OTHER), - GRUB_USB_REQ_SET_FEATURE, - GRUB_USB_HUB_FEATURE_PORT_RESET, - i, 0, 0); - /* If the Hub does not cooperate for this port, just skip - the port. */ - if (err) - continue; + if (status & GRUB_USB_HUB_STATUS_C_PORT_RESET) + { + grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_CLEAR_FEATURE, + GRUB_USB_HUB_FEATURE_C_PORT_RESET, i, 0, 0); - /* Wait for reset procedure done */ - timeout = grub_get_time_ms () + 1000; - do - { - /* Get the port status. */ - err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_OTHER), - GRUB_USB_REQ_GET_STATUS, - 0, i, sizeof (status), (char *) &status); - } - while (!err && - !(status & GRUB_USB_HUB_STATUS_C_PORT_RESET) && - (grub_get_time_ms() < timeout) ); - if (err || !(status & GRUB_USB_HUB_STATUS_C_PORT_RESET) ) - continue; + if (status & GRUB_USB_HUB_STATUS_PORT_CONNECTED) + { + grub_usb_speed_t speed; + grub_usb_device_t next_dev; - /* Wait a recovery time after reset, spec. says 10ms */ - grub_millisleep (10); + /* Determine the device speed. */ + if (status & GRUB_USB_HUB_STATUS_PORT_LOWSPEED) + speed = GRUB_USB_SPEED_LOW; + else + { + if (status & GRUB_USB_HUB_STATUS_PORT_HIGHSPEED) + speed = GRUB_USB_SPEED_HIGH; + else + speed = GRUB_USB_SPEED_FULL; + } - /* Do reset of connection change bit */ - err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_OTHER), - GRUB_USB_REQ_CLEAR_FEATURE, - GRUB_USB_HUB_FEATURE_C_CONNECTED, - i, 0, 0); - /* Just ignore the device if the Hub reports some error */ - if (err) - continue; + /* Wait a recovery time after reset, spec. says 10ms */ + grub_millisleep (10); - /* Add the device and assign a device address to it. */ - next_dev = grub_usb_hub_add_dev (&dev->controller, speed); - if (! next_dev) - continue; + /* Add the device and assign a device address to it. */ + next_dev = grub_usb_hub_add_dev (&dev->controller, speed); + dev->controller.dev->pending_reset = 0; + if (! next_dev) + continue; - attached_devices[i - 1] = next_dev; + dev->children[i - 1] = next_dev; - /* If the device is a Hub, scan it for more devices. */ - if (next_dev->descdev.class == 0x09) - grub_usb_add_hub (next_dev); + /* If the device is a Hub, scan it for more devices. */ + if (next_dev->descdev.class == 0x09) + grub_usb_add_hub (next_dev); + } } } - - return; } void @@ -476,12 +497,21 @@ grub_usb_poll_devices (void) /* No, it should be never changed, it should be constant. */ for (i = 0; i < hub->nports; i++) { - grub_usb_speed_t speed; + grub_usb_speed_t speed = GRUB_USB_SPEED_NONE; int changed = 0; - speed = hub->controller->dev->detect_dev (hub->controller, i, - &changed); - + if (!hub->controller->dev->pending_reset) + { + /* Check for possible timeout */ + if (grub_get_time_ms () > hub->controller->dev->pending_reset) + { + /* Something went wrong, reset device was not + * addressed properly, timeout happened */ + hub->controller->dev->pending_reset = 0; + speed = hub->controller->dev->detect_dev (hub->controller, + i, &changed); + } + } if (changed) { detach_device (hub->devices[i]); @@ -492,13 +522,21 @@ grub_usb_poll_devices (void) } } - /* We should check changes of non-root hubs too. */ - for (i = 0; i < GRUB_USBHUB_MAX_DEVICES; i++) + while (1) { - grub_usb_device_t dev = grub_usb_devs[i]; - - if (dev && dev->descdev.class == 0x09) - poll_nonroot_hub (dev); + rescan = 0; + + /* We should check changes of non-root hubs too. */ + for (i = 0; i < GRUB_USBHUB_MAX_DEVICES; i++) + { + grub_usb_device_t dev = grub_usb_devs[i]; + + if (dev && dev->descdev.class == 0x09) + poll_nonroot_hub (dev); + } + if (!rescan) + break; + grub_millisleep (50); } } diff --git a/grub-core/bus/usb/usbtrans.c b/grub-core/bus/usb/usbtrans.c index 13f5c28ed..afd2eb0a5 100644 --- a/grub-core/bus/usb/usbtrans.c +++ b/grub-core/bus/usb/usbtrans.c @@ -23,6 +23,41 @@ #include #include #include +#include + +static grub_usb_err_t +grub_usb_execute_and_wait_transfer (grub_usb_device_t dev, + grub_usb_transfer_t transfer, + int timeout, grub_size_t *actual) +{ + grub_usb_err_t err; + grub_uint64_t endtime; + + err = dev->controller.dev->setup_transfer (&dev->controller, transfer); + if (err) + return err; + /* endtime moved behind setup transfer to prevent false timeouts + * while debugging... */ + endtime = grub_get_time_ms () + timeout; + while (1) + { + err = dev->controller.dev->check_transfer (&dev->controller, transfer, + actual); + if (!err) + return GRUB_USB_ERR_NONE; + if (err != GRUB_USB_ERR_WAIT) + return err; + if (grub_get_time_ms () > endtime) + { + err = dev->controller.dev->cancel_transfer (&dev->controller, + transfer); + if (err) + return err; + return GRUB_USB_ERR_TIMEOUT; + } + grub_cpu_idle (); + } +} grub_usb_err_t grub_usb_control_msg (grub_usb_device_t dev, @@ -147,8 +182,8 @@ grub_usb_control_msg (grub_usb_device_t dev, transfer->transactions[datablocks + 1].toggle = 1; - err = dev->controller.dev->transfer (&dev->controller, transfer, - 1000, &actual); + err = grub_usb_execute_and_wait_transfer (dev, transfer, 1000, &actual); + grub_dprintf ("usb", "control: err=%d\n", err); grub_free (transfer->transactions); @@ -162,22 +197,20 @@ grub_usb_control_msg (grub_usb_device_t dev, return err; } -static grub_usb_err_t -grub_usb_bulk_readwrite (grub_usb_device_t dev, - int endpoint, grub_size_t size0, char *data_in, - grub_transfer_type_t type, int timeout, - grub_size_t *actual) +static grub_usb_transfer_t +grub_usb_bulk_setup_readwrite (grub_usb_device_t dev, + int endpoint, grub_size_t size0, char *data_in, + grub_transfer_type_t type) { int i; grub_usb_transfer_t transfer; int datablocks; unsigned int max; - grub_usb_err_t err; - int toggle = dev->toggle[endpoint]; volatile char *data; grub_uint32_t data_addr; struct grub_pci_dma_chunk *data_chunk; grub_size_t size = size0; + int toggle = dev->toggle[endpoint]; grub_dprintf ("usb", "bulk: size=0x%02lx type=%d\n", (unsigned long) size, type); @@ -185,7 +218,7 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, /* FIXME: avoid allocation any kind of buffer in a first place. */ data_chunk = grub_memalign_dma32 (128, size); if (!data_chunk) - return GRUB_USB_ERR_INTERNAL; + return NULL; data = grub_dma_get_virt (data_chunk); data_addr = grub_dma_get_phys (data_chunk); if (type == GRUB_USB_TRANSFER_TYPE_OUT) @@ -210,18 +243,21 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, if (! transfer) { grub_dma_free (data_chunk); - return grub_errno; + return NULL; } datablocks = ((size + max - 1) / max); transfer->transcnt = datablocks; transfer->size = size - 1; - transfer->endpoint = endpoint & 15; + transfer->endpoint = endpoint; transfer->devaddr = dev->addr; transfer->type = GRUB_USB_TRANSACTION_TYPE_BULK; + transfer->dir = type; transfer->max = max; transfer->dev = dev; transfer->last_trans = -1; /* Reset index of last processed transaction (TD) */ + transfer->data_chunk = data_chunk; + transfer->data = data_in; /* Allocate an array of transfer data structures. */ transfer->transactions = grub_malloc (transfer->transcnt @@ -230,7 +266,7 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, { grub_free (transfer); grub_dma_free (data_chunk); - return grub_errno; + return NULL; } /* Set up all transfers. */ @@ -248,25 +284,51 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, tr->preceding = i * max; size -= tr->size; } + return transfer; +} + +static void +grub_usb_bulk_finish_readwrite (grub_usb_transfer_t transfer) +{ + grub_usb_device_t dev = transfer->dev; + int toggle = dev->toggle[transfer->endpoint]; - err = dev->controller.dev->transfer (&dev->controller, transfer, timeout, - actual); /* We must remember proper toggle value even if some transactions * were not processed - correct value should be inversion of last * processed transaction (TD). */ if (transfer->last_trans >= 0) toggle = transfer->transactions[transfer->last_trans].toggle ? 0 : 1; else - toggle = dev->toggle[endpoint]; /* Nothing done, take original */ - grub_dprintf ("usb", "bulk: err=%d, toggle=%d\n", err, toggle); - dev->toggle[endpoint] = toggle; + toggle = dev->toggle[transfer->endpoint]; /* Nothing done, take original */ + grub_dprintf ("usb", "bulk: toggle=%d\n", toggle); + dev->toggle[transfer->endpoint] = toggle; + + if (transfer->dir == GRUB_USB_TRANSFER_TYPE_IN) + grub_memcpy (transfer->data, (void *) + grub_dma_get_virt (transfer->data_chunk), + transfer->size + 1); grub_free (transfer->transactions); grub_free (transfer); - grub_dma_free (data_chunk); + grub_dma_free (transfer->data_chunk); +} - if (type == GRUB_USB_TRANSFER_TYPE_IN) - grub_memcpy (data_in, (char *) data, size0); +static grub_usb_err_t +grub_usb_bulk_readwrite (grub_usb_device_t dev, + int endpoint, grub_size_t size0, char *data_in, + grub_transfer_type_t type, int timeout, + grub_size_t *actual) +{ + grub_usb_err_t err; + grub_usb_transfer_t transfer; + + transfer = grub_usb_bulk_setup_readwrite (dev, endpoint, size0, + data_in, type); + if (!transfer) + return GRUB_USB_ERR_INTERNAL; + err = grub_usb_execute_and_wait_transfer (dev, transfer, timeout, actual); + + grub_usb_bulk_finish_readwrite (transfer); return err; } @@ -298,6 +360,49 @@ grub_usb_bulk_read (grub_usb_device_t dev, return err; } +grub_usb_err_t +grub_usb_check_transfer (grub_usb_transfer_t transfer, grub_size_t *actual) +{ + grub_usb_err_t err; + grub_usb_device_t dev = transfer->dev; + + err = dev->controller.dev->check_transfer (&dev->controller, transfer, + actual); + if (err == GRUB_USB_ERR_WAIT) + return err; + + grub_usb_bulk_finish_readwrite (transfer); + + return err; +} + +grub_usb_transfer_t +grub_usb_bulk_read_background (grub_usb_device_t dev, + int endpoint, grub_size_t size, void *data) +{ + grub_usb_err_t err; + grub_usb_transfer_t transfer; + + transfer = grub_usb_bulk_setup_readwrite (dev, endpoint, size, + data, GRUB_USB_TRANSFER_TYPE_IN); + if (!transfer) + return NULL; + + err = dev->controller.dev->setup_transfer (&dev->controller, transfer); + if (err) + return NULL; + + return transfer; +} + +void +grub_usb_cancel_transfer (grub_usb_transfer_t transfer) +{ + grub_usb_device_t dev = transfer->dev; + dev->controller.dev->cancel_transfer (&dev->controller, transfer); + grub_errno = GRUB_ERR_NONE; +} + grub_usb_err_t grub_usb_bulk_read_extended (grub_usb_device_t dev, int endpoint, grub_size_t size, char *data, diff --git a/grub-core/commands/acpi.c b/grub-core/commands/acpi.c index b2edcc9cd..4f03997e0 100644 --- a/grub-core/commands/acpi.c +++ b/grub-core/commands/acpi.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -151,10 +150,10 @@ grub_acpi_create_ebda (void) auto int NESTED_FUNC_ATTR find_hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); int NESTED_FUNC_ATTR find_hook (grub_uint64_t start, grub_uint64_t size, - grub_uint32_t type) + grub_memory_type_t type) { grub_uint64_t end = start + size; - if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + if (type != GRUB_MEMORY_AVAILABLE) return 0; if (end > 0x100000) end = 0x100000; @@ -180,7 +179,7 @@ grub_acpi_create_ebda (void) "couldn't find space for the new EBDA"); mmapregion = grub_mmap_register (PTR_TO_UINT64 (targetebda), ebda_len, - GRUB_MACHINE_MEMORY_RESERVED); + GRUB_MEMORY_RESERVED); if (! mmapregion) return grub_errno; @@ -324,7 +323,7 @@ setup_common_tables (void) /* If it's FADT correct DSDT and FACS addresses. */ fadt = (struct grub_acpi_fadt *) cur->addr; - if (grub_memcmp (fadt->hdr.signature, "FACP", + if (grub_memcmp (fadt->hdr.signature, GRUB_ACPI_FADT_SIGNATURE, sizeof (fadt->hdr.signature)) == 0) { fadt->dsdt_addr = PTR_TO_UINT32 (table_dsdt); @@ -527,7 +526,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) struct grub_acpi_fadt *fadt = (struct grub_acpi_fadt *) curtable; /* Set root header variables to the same values - as FACP by default. */ + as FADT by default. */ grub_memcpy (&root_oemid, &(fadt->hdr.oemid), sizeof (root_oemid)); grub_memcpy (&root_oemtable, &(fadt->hdr.oemtable), @@ -704,7 +703,7 @@ grub_cmd_acpi (struct grub_extcmd_context *ctxt, int argc, char **args) playground = playground_ptr = grub_mmap_malign_and_register (1, playground_size, &mmapregion, - GRUB_MACHINE_MEMORY_ACPI, 0); + GRUB_MEMORY_ACPI, 0); if (! playground) { @@ -758,8 +757,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(acpi) { - cmd = grub_register_extcmd ("acpi", grub_cmd_acpi, - GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("acpi", grub_cmd_acpi, 0, N_("[-1|-2] [--exclude=TABLE1,TABLE2|" "--load-only=table1,table2] FILE1" " [FILE2] [...]"), diff --git a/grub-core/commands/acpihalt.c b/grub-core/commands/acpihalt.c new file mode 100644 index 000000000..0cd32f389 --- /dev/null +++ b/grub-core/commands/acpihalt.c @@ -0,0 +1,266 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include + +static inline grub_uint32_t +decode_length (const grub_uint8_t *ptr, int *numlen) +{ + int num_bytes, i; + grub_uint32_t ret; + if (*ptr < 64) + { + if (numlen) + *numlen = 1; + return *ptr; + } + num_bytes = *ptr >> 6; + if (numlen) + *numlen = num_bytes + 1; + ret = *ptr & 0xf; + ptr++; + for (i = 0; i < num_bytes; i++) + { + ret |= *ptr << (8 * i + 4); + ptr++; + } + return ret; +} + +static inline grub_uint32_t +skip_name_string (const grub_uint8_t *ptr, const grub_uint8_t *end) +{ + const grub_uint8_t *ptr0 = ptr; + + while (ptr < end && (*ptr == '^' || *ptr == '\\')) + ptr++; + switch (*ptr) + { + case '.': + ptr++; + ptr += 8; + break; + case '/': + ptr++; + ptr += 1 + (*ptr) * 4; + break; + case 0: + ptr++; + break; + default: + ptr += 4; + break; + } + return ptr - ptr0; +} + +static inline grub_uint32_t +skip_data_ref_object (const grub_uint8_t *ptr, const grub_uint8_t *end) +{ + grub_dprintf ("acpi", "data type = 0x%x\n", *ptr); + switch (*ptr) + { + case GRUB_ACPI_OPCODE_PACKAGE: + return 1 + decode_length (ptr + 1, 0); + case GRUB_ACPI_OPCODE_ZERO: + case GRUB_ACPI_OPCODE_ONES: + case GRUB_ACPI_OPCODE_ONE: + return 1; + case GRUB_ACPI_OPCODE_BYTE_CONST: + return 2; + case GRUB_ACPI_OPCODE_WORD_CONST: + return 3; + case GRUB_ACPI_OPCODE_DWORD_CONST: + return 5; + default: + if (*ptr == '^' || *ptr == '\\' || *ptr == '_' + || (*ptr >= 'A' && *ptr <= 'Z')) + return skip_name_string (ptr, end); + grub_printf ("Unknown opcode 0x%x\n", *ptr); + return 0; + } +} + +static inline grub_uint32_t +skip_ext_op (const grub_uint8_t *ptr, const grub_uint8_t *end) +{ + const grub_uint8_t *ptr0 = ptr; + int add; + grub_dprintf ("acpi", "Extended opcode: 0x%x\n", *ptr); + switch (*ptr) + { + case GRUB_ACPI_EXTOPCODE_MUTEX: + ptr++; + ptr += skip_name_string (ptr, end); + ptr++; + break; + case GRUB_ACPI_EXTOPCODE_OPERATION_REGION: + ptr++; + ptr += skip_name_string (ptr, end); + ptr++; + ptr += add = skip_data_ref_object (ptr, end); + if (!add) + return 0; + ptr += add = skip_data_ref_object (ptr, end); + if (!add) + return 0; + break; + case GRUB_ACPI_EXTOPCODE_FIELD_OP: + ptr++; + ptr += decode_length (ptr, 0); + break; + default: + grub_printf ("Unexpected extended opcode: 0x%x\n", *ptr); + return 0; + } + return ptr - ptr0; +} + +static int +get_sleep_type (grub_uint8_t *table, grub_uint8_t *end) +{ + grub_uint8_t *ptr, *prev; + int sleep_type = -1; + + ptr = table + sizeof (struct grub_acpi_table_header); + while (ptr < end && prev < ptr) + { + int add; + prev = ptr; + grub_dprintf ("acpi", "Opcode 0x%x\n", *ptr); + grub_dprintf ("acpi", "Tell %x\n", (unsigned) (ptr - table)); + switch (*ptr) + { + case GRUB_ACPI_OPCODE_EXTOP: + ptr++; + ptr += add = skip_ext_op (ptr, end); + if (!add) + return -1; + break; + case GRUB_ACPI_OPCODE_NAME: + ptr++; + if (memcmp (ptr, "_S5_", 4) == 0) + { + int ll; + grub_uint8_t *ptr2 = ptr; + ptr2 += 4; + if (*ptr2 != 0x12) + { + grub_printf ("Unknown opcode in _S5: 0x%x\n", *ptr2); + return -1; + } + ptr2++; + decode_length (ptr2, &ll); + ptr2 += ll; + ptr2++; + switch (*ptr2) + { + case GRUB_ACPI_OPCODE_ZERO: + sleep_type = 0; + break; + case GRUB_ACPI_OPCODE_ONE: + sleep_type = 1; + break; + case GRUB_ACPI_OPCODE_BYTE_CONST: + sleep_type = ptr2[1]; + break; + default: + grub_printf ("Unknown data type in _S5: 0x%x\n", *ptr2); + return -1; + } + } + ptr += add = skip_name_string (ptr, end); + if (!add) + return -1; + ptr += add = skip_data_ref_object (ptr, end); + if (!add) + return -1; + break; + case GRUB_ACPI_OPCODE_SCOPE: + case GRUB_ACPI_OPCODE_IF: + case GRUB_ACPI_OPCODE_METHOD: + { + ptr++; + ptr += decode_length (ptr, 0); + break; + } + } + } + + grub_dprintf ("acpi", "TYP = %d\n", sleep_type); + return sleep_type; +} + +void +grub_acpi_halt (void) +{ + struct grub_acpi_rsdp_v20 *rsdp2; + struct grub_acpi_rsdp_v10 *rsdp1; + struct grub_acpi_table_header *rsdt; + grub_uint32_t *entry_ptr; + + rsdp2 = grub_acpi_get_rsdpv2 (); + if (rsdp2) + rsdp1 = &(rsdp2->rsdpv1); + else + rsdp1 = grub_acpi_get_rsdpv1 (); + grub_dprintf ("acpi", "rsdp1=%p\n", rsdp1); + if (!rsdp1) + return; + + rsdt = (struct grub_acpi_table_header *) (grub_addr_t) rsdp1->rsdt_addr; + for (entry_ptr = (grub_uint32_t *) (rsdt + 1); + entry_ptr < (grub_uint32_t *) (((grub_uint8_t *) rsdt) + + rsdt->length); + entry_ptr++) + { + if (grub_memcmp ((void *) (grub_addr_t) *entry_ptr, "FACP", 4) == 0) + { + grub_uint32_t port; + struct grub_acpi_fadt *fadt + = ((struct grub_acpi_fadt *) (grub_addr_t) *entry_ptr); + struct grub_acpi_table_header *dsdt + = (struct grub_acpi_table_header *) (grub_addr_t) fadt->dsdt_addr; + int sleep_type = -1; + + port = fadt->pm1a; + + grub_dprintf ("acpi", "PM1a port=%x\n", port); + + if (grub_memcmp (dsdt->signature, "DSDT", + sizeof (dsdt->signature)) != 0) + break; + + sleep_type = get_sleep_type ((grub_uint8_t *) dsdt, + (grub_uint8_t *) dsdt + dsdt->length); + + if (sleep_type < 0 || sleep_type >= 8) + break; + + grub_dprintf ("acpi", "SLP_TYP = %d, port = 0x%x\n", + sleep_type, port); + + grub_outw (GRUB_ACPI_SLP_EN + | (sleep_type << GRUB_ACPI_SLP_TYP_OFFSET), port & 0xffff); + } + } + + grub_printf ("ACPI shutdown failed\n"); +} diff --git a/grub-core/commands/cat.c b/grub-core/commands/cat.c index 68ca83c5d..79ecf75c7 100644 --- a/grub-core/commands/cat.c +++ b/grub-core/commands/cat.c @@ -76,7 +76,7 @@ grub_cmd_cat (grub_extcmd_context_t ctxt, int argc, char **args) } while (grub_checkkey () >= 0 && - (key = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != GRUB_TERM_ESC) + (key = grub_getkey ()) != GRUB_TERM_ESC) ; } @@ -91,7 +91,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(cat) { - cmd = grub_register_extcmd ("cat", grub_cmd_cat, GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("cat", grub_cmd_cat, 0, N_("FILE"), N_("Show the contents of a file."), options); } diff --git a/grub-core/commands/echo.c b/grub-core/commands/echo.c index 6bc00eae8..13bc1c3fd 100644 --- a/grub-core/commands/echo.c +++ b/grub-core/commands/echo.c @@ -113,7 +113,9 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(echo) { - cmd = grub_register_extcmd ("echo", grub_cmd_echo, GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("echo", grub_cmd_echo, + GRUB_COMMAND_ACCEPT_DASH + | GRUB_COMMAND_OPTIONS_AT_START, N_("[-e|-n] STRING"), N_("Display a line of text."), options); } diff --git a/grub-core/commands/efi/lsefisystab.c b/grub-core/commands/efi/lsefisystab.c new file mode 100644 index 000000000..ac84fc426 --- /dev/null +++ b/grub-core/commands/efi/lsefisystab.c @@ -0,0 +1,107 @@ +/* systab.c - Display EFI systab. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ +#include +#include +#include +#include +#include +#include +#include + +struct guid_mapping +{ + grub_efi_guid_t guid; + const char *name; +}; + +static const struct guid_mapping guid_mappings[] = + { + { GRUB_EFI_ACPI_20_TABLE_GUID, "ACPI-2.0"}, + { GRUB_EFI_ACPI_TABLE_GUID, "ACPI-1.0"}, + { GRUB_EFI_SAL_TABLE_GUID, "SAL"}, + { GRUB_EFI_SMBIOS_TABLE_GUID, "SMBIOS"}, + { GRUB_EFI_MPS_TABLE_GUID, "MPS"}, + { GRUB_EFI_HCDP_TABLE_GUID, "HCDP"} + }; + +static grub_err_t +grub_cmd_lsefisystab (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + const grub_efi_system_table_t *st = grub_efi_system_table; + grub_efi_configuration_table_t *t; + unsigned int i; + + grub_printf ("Signature: %016" PRIxGRUB_UINT64_T " revision: %08x\n", + st->hdr.signature, st->hdr.revision); + { + char *vendor; + grub_uint16_t *vendor_utf16; + grub_printf ("Vendor: "); + + for (vendor_utf16 = st->firmware_vendor; *vendor_utf16; vendor_utf16++); + vendor = grub_malloc (4 * (vendor_utf16 - st->firmware_vendor) + 1); + if (!vendor) + return grub_errno; + *grub_utf16_to_utf8 ((grub_uint8_t *) vendor, st->firmware_vendor, + vendor_utf16 - st->firmware_vendor) = 0; + grub_printf ("%s", vendor); + grub_free (vendor); + } + + grub_printf (", Version=%x\n", st->firmware_revision); + + grub_printf ("%ld tables:\n", st->num_table_entries); + t = st->configuration_table; + for (i = 0; i < st->num_table_entries; i++) + { + unsigned int j; + + grub_printf ("%p ", t->vendor_table); + + grub_printf ("%08x-%04x-%04x-", + t->vendor_guid.data1, t->vendor_guid.data2, + t->vendor_guid.data3); + for (j = 0; j < 8; j++) + grub_printf ("%02x", t->vendor_guid.data4[j]); + + for (j = 0; j < ARRAY_SIZE (guid_mappings); j++) + if (grub_memcmp (&guid_mappings[j].guid, &t->vendor_guid, + sizeof (grub_efi_guid_t)) == 0) + grub_printf (" %s", guid_mappings[j].name); + + grub_printf ("\n"); + t++; + } + return GRUB_ERR_NONE; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(lsefisystab) +{ + cmd = grub_register_command ("lsefisystab", grub_cmd_lsefisystab, + "", "Display EFI system tables."); +} + +GRUB_MOD_FINI(lsefisystab) +{ + grub_unregister_command (cmd); +} diff --git a/grub-core/commands/efi/lssal.c b/grub-core/commands/efi/lssal.c new file mode 100644 index 000000000..245883f90 --- /dev/null +++ b/grub-core/commands/efi/lssal.c @@ -0,0 +1,162 @@ +/* systab.c - Display EFI systab. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ +#include +#include +#include +#include +#include +#include +#include + +static void +disp_sal (void *table) +{ + struct grub_efi_sal_system_table *t = table; + void *desc; + grub_uint32_t len, l; + + grub_printf ("SAL rev: %02x, signature: %x, len:%x\n", + t->sal_rev, t->signature, t->total_table_len); + grub_printf ("nbr entry: %d, chksum: %02x, SAL version A: %02x B: %02x\n", + t->entry_count, t->checksum, + t->sal_a_version, t->sal_b_version); + grub_printf ("OEM-ID: %-32s\n", t->oem_id); + grub_printf ("Product-ID: %-32s\n", t->product_id); + + desc = t->entries; + len = t->total_table_len - sizeof (struct grub_efi_sal_system_table); + while (len > 0) + { + switch (*(grub_uint8_t *) desc) + { + case GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_ENTRYPOINT_DESCRIPTOR: + { + struct grub_efi_sal_system_table_entrypoint_descriptor *c = desc; + l = sizeof (*c); + grub_printf (" Entry point: PAL=%016" PRIxGRUB_UINT64_T + " SAL=%016" PRIxGRUB_UINT64_T " GP=%016" + PRIxGRUB_UINT64_T "\n", + c->pal_proc_addr, c->sal_proc_addr, + c->global_data_ptr); + } + break; + case GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_MEMORY_DESCRIPTOR: + { + struct grub_efi_sal_system_table_memory_descriptor *c = desc; + l = sizeof (*c); + grub_printf (" Memory descriptor entry addr=%016" PRIxGRUB_UINT64_T + " len=%" PRIuGRUB_UINT64_T "KB\n", + c->addr, c->len * 4); + grub_printf (" sal_used=%d attr=%x AR=%x attr_mask=%x " + "type=%x usage=%x\n", + c->sal_used, c->attr, c->ar, c->attr_mask, c->mem_type, + c->usage); + } + break; + case GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_PLATFORM_FEATURES: + { + struct grub_efi_sal_system_table_platform_features *c = desc; + l = sizeof (*c); + grub_printf (" Platform features: %02x", c->flags); + if (c->flags & GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_BUSLOCK) + grub_printf (" BusLock"); + if (c->flags & GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_IRQREDIRECT) + grub_printf (" IrqRedirect"); + if (c->flags & GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_IPIREDIRECT) + + grub_printf (" IPIRedirect"); + if (c->flags & GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_ITCDRIFT) + + grub_printf (" ITCDrift"); + grub_printf ("\n"); + } + break; + case GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_TRANSLATION_REGISTER_DESCRIPTOR: + { + struct grub_efi_sal_system_table_translation_register_descriptor *c + = desc; + l = sizeof (*c); + grub_printf (" TR type=%d num=%d va=%016" PRIxGRUB_UINT64_T + " pte=%016" PRIxGRUB_UINT64_T "\n", + c->register_type, c->register_number, + c->addr, c->page_size); + } + break; + case GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_PURGE_TRANSLATION_COHERENCE: + { + struct grub_efi_sal_system_table_purge_translation_coherence *c + = desc; + l = sizeof (*c); + grub_printf (" PTC coherence nbr=%d addr=%016" PRIxGRUB_UINT64_T "\n", + c->ndomains, c->coherence); + } + break; + case GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_AP_WAKEUP: + { + struct grub_efi_sal_system_table_ap_wakeup *c = desc; + l = sizeof (*c); + grub_printf (" AP wake-up: mec=%d vect=%" PRIxGRUB_UINT64_T "\n", + c->mechanism, c->vector); + } + break; + default: + grub_printf (" unknown entry 0x%x\n", *(grub_uint8_t *)desc); + return; + } + desc = (grub_uint8_t *)desc + l; + len -= l; + } +} + +static grub_err_t +grub_cmd_lssal (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + const grub_efi_system_table_t *st = grub_efi_system_table; + grub_efi_configuration_table_t *t = st->configuration_table; + unsigned int i; + grub_efi_guid_t guid = GRUB_EFI_SAL_TABLE_GUID; + + for (i = 0; i < st->num_table_entries; i++) + { + if (grub_memcmp (&guid, &t->vendor_guid, + sizeof (grub_efi_guid_t)) == 0) + { + disp_sal (t->vendor_table); + return GRUB_ERR_NONE; + } + t++; + } + grub_printf ("SAL not found\n"); + return GRUB_ERR_NONE; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(lssal) +{ + cmd = grub_register_command ("lssal", grub_cmd_lssal, "", + "Display SAL system table."); +} + +GRUB_MOD_FINI(lssal) +{ + grub_unregister_command (cmd); +} diff --git a/grub-core/commands/extcmd.c b/grub-core/commands/extcmd.c index 44a4b6cfd..e9274fbab 100644 --- a/grub-core/commands/extcmd.c +++ b/grub-core/commands/extcmd.c @@ -66,7 +66,7 @@ grub_extcmd_dispatch (struct grub_command *cmd, int argc, char **args) grub_extcmd_t grub_register_extcmd_prio (const char *name, grub_extcmd_func_t func, - unsigned flags, const char *summary, + grub_command_flags_t flags, const char *summary, const char *description, const struct grub_arg_option *parser, int prio) @@ -99,7 +99,7 @@ grub_register_extcmd_prio (const char *name, grub_extcmd_func_t func, grub_extcmd_t grub_register_extcmd (const char *name, grub_extcmd_func_t func, - unsigned flags, const char *summary, + grub_command_flags_t flags, const char *summary, const char *description, const struct grub_arg_option *parser) { diff --git a/grub-core/commands/hashsum.c b/grub-core/commands/hashsum.c index 6f65b4ab3..e926c0435 100644 --- a/grub-core/commands/hashsum.c +++ b/grub-core/commands/hashsum.c @@ -252,26 +252,22 @@ static grub_extcmd_t cmd, cmd_md5, cmd_sha256, cmd_sha512; GRUB_MOD_INIT(hashsum) { - cmd = grub_register_extcmd ("hashsum", grub_cmd_hashsum, - GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("hashsum", grub_cmd_hashsum, 0, "hashsum -h HASH [-c FILE [-p PREFIX]] " "[FILE1 [FILE2 ...]]", "Compute or check hash checksum.", options); - cmd_md5 = grub_register_extcmd ("md5sum", grub_cmd_hashsum, - GRUB_COMMAND_FLAG_BOTH, + cmd_md5 = grub_register_extcmd ("md5sum", grub_cmd_hashsum, 0, N_("[-c FILE [-p PREFIX]] " "[FILE1 [FILE2 ...]]"), N_("Compute or check hash checksum."), options); - cmd_sha256 = grub_register_extcmd ("sha256sum", grub_cmd_hashsum, - GRUB_COMMAND_FLAG_BOTH, + cmd_sha256 = grub_register_extcmd ("sha256sum", grub_cmd_hashsum, 0, N_("[-c FILE [-p PREFIX]] " "[FILE1 [FILE2 ...]]"), "Compute or check hash checksum.", options); - cmd_sha512 = grub_register_extcmd ("sha512sum", grub_cmd_hashsum, - GRUB_COMMAND_FLAG_BOTH, + cmd_sha512 = grub_register_extcmd ("sha512sum", grub_cmd_hashsum, 0, N_("[-c FILE [-p PREFIX]] " "[FILE1 [FILE2 ...]]"), N_("Compute or check hash checksum."), diff --git a/grub-core/commands/hdparm.c b/grub-core/commands/hdparm.c index 54724077d..b6ab78755 100644 --- a/grub-core/commands/hdparm.c +++ b/grub-core/commands/hdparm.c @@ -409,8 +409,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(hdparm) { - cmd = grub_register_extcmd ("hdparm", grub_cmd_hdparm, - GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("hdparm", grub_cmd_hdparm, 0, N_("[OPTIONS] DISK"), N_("Get/set ATA disk parameters."), options); } diff --git a/grub-core/commands/help.c b/grub-core/commands/help.c index 1ca46aa7e..ff6d7ed2e 100644 --- a/grub-core/commands/help.c +++ b/grub-core/commands/help.c @@ -38,8 +38,7 @@ grub_cmd_help (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc, grub_command_t cmd; FOR_COMMANDS(cmd) { - if ((cmd->prio & GRUB_PRIO_LIST_FLAG_ACTIVE) && - (cmd->flags & GRUB_COMMAND_FLAG_CMDLINE)) + if ((cmd->prio & GRUB_PRIO_LIST_FLAG_ACTIVE)) { struct grub_term_output *term; const char *summary_translated = _(cmd->summary); @@ -131,8 +130,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(help) { - cmd = grub_register_extcmd ("help", grub_cmd_help, - GRUB_COMMAND_FLAG_CMDLINE, + cmd = grub_register_extcmd ("help", grub_cmd_help, 0, N_("[PATTERN ...]"), N_("Show a help message."), 0); } diff --git a/grub-core/commands/hexdump.c b/grub-core/commands/hexdump.c index 08a94eb64..629f2a069 100644 --- a/grub-core/commands/hexdump.c +++ b/grub-core/commands/hexdump.c @@ -119,8 +119,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT (hexdump) { - cmd = grub_register_extcmd ("hexdump", grub_cmd_hexdump, - GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("hexdump", grub_cmd_hexdump, 0, N_("[OPTIONS] FILE_OR_DEVICE"), N_("Dump the contents of a file or memory."), options); diff --git a/grub-core/commands/i386/cmostest.c b/grub-core/commands/i386/cmostest.c index 36c35e6c4..994da11b0 100644 --- a/grub-core/commands/i386/cmostest.c +++ b/grub-core/commands/i386/cmostest.c @@ -22,20 +22,32 @@ #include static grub_err_t -grub_cmd_cmostest (struct grub_command *cmd __attribute__ ((unused)), - int argc, char *argv[]) +parse_args (int argc, char *argv[], int *byte, int *bit) { - int byte, bit; char *rest; if (argc != 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "Address required."); - byte = grub_strtoul (argv[0], &rest, 0); + *byte = grub_strtoul (argv[0], &rest, 0); if (*rest != ':') return grub_error (GRUB_ERR_BAD_ARGUMENT, "Address required."); - bit = grub_strtoul (rest + 1, 0, 0); + *bit = grub_strtoul (rest + 1, 0, 0); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_cmostest (struct grub_command *cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + int byte, bit; + grub_err_t err; + + err = parse_args (argc, argv, &byte, &bit); + if (err) + return err; if (grub_cmos_read (byte) & (1 << bit)) return GRUB_ERR_NONE; @@ -43,7 +55,22 @@ grub_cmd_cmostest (struct grub_command *cmd __attribute__ ((unused)), return grub_error (GRUB_ERR_TEST_FAILURE, "false"); } -static grub_command_t cmd; +static grub_err_t +grub_cmd_cmosclean (struct grub_command *cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + int byte, bit; + grub_err_t err; + + err = parse_args (argc, argv, &byte, &bit); + if (err) + return err; + + grub_cmos_write (byte, grub_cmos_read (byte) & (~(1 << bit))); + return GRUB_ERR_NONE; +} + +static grub_command_t cmd, cmd_clean; GRUB_MOD_INIT(cmostest) @@ -51,9 +78,13 @@ GRUB_MOD_INIT(cmostest) cmd = grub_register_command ("cmostest", grub_cmd_cmostest, "cmostest BYTE:BIT", "Test bit at BYTE:BIT in CMOS."); + cmd_clean = grub_register_command ("cmosclean", grub_cmd_cmosclean, + "cmosclean BYTE:BIT", + "Clean bit at BYTE:BIT in CMOS."); } GRUB_MOD_FINI(cmostest) { grub_unregister_command (cmd); + grub_unregister_command (cmd_clean); } diff --git a/grub-core/commands/i386/cpuid.c b/grub-core/commands/i386/cpuid.c index 412b284d0..f5f0f15a8 100644 --- a/grub-core/commands/i386/cpuid.c +++ b/grub-core/commands/i386/cpuid.c @@ -88,7 +88,7 @@ GRUB_MOD_INIT(cpuid) done: #endif - cmd = grub_register_extcmd ("cpuid", grub_cmd_cpuid, GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("cpuid", grub_cmd_cpuid, 0, "[-l]", N_("Check for CPU features."), options); } diff --git a/grub-core/commands/i386/pc/drivemap.c b/grub-core/commands/i386/pc/drivemap.c index 7ecfe7454..ed4211cca 100644 --- a/grub-core/commands/i386/pc/drivemap.c +++ b/grub-core/commands/i386/pc/drivemap.c @@ -24,9 +24,10 @@ #include #include #include -#include #include #include +#include +#include /* Real mode IVT slot (seg:off far pointer) for interrupt 0x13. */ @@ -306,7 +307,7 @@ install_int13_handler (int noret __attribute__ ((unused))) grub_dprintf ("drivemap", "Payload is %u bytes long\n", total_size); handler_base = grub_mmap_malign_and_register (16, total_size, &drivemap_mmap, - GRUB_MACHINE_MEMORY_RESERVED, + GRUB_MEMORY_RESERVED, GRUB_MMAP_MALLOC_LOW); if (! handler_base) return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't reserve " @@ -401,8 +402,7 @@ GRUB_MOD_INIT (drivemap) { grub_get_root_biosnumber_saved = grub_get_root_biosnumber; grub_get_root_biosnumber = grub_get_root_biosnumber_drivemap; - cmd = grub_register_extcmd ("drivemap", grub_cmd_drivemap, - GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("drivemap", grub_cmd_drivemap, 0, N_("-l | -r | [-s] grubdev osdisk."), N_("Manage the BIOS drive mappings."), options); diff --git a/grub-core/commands/i386/pc/halt.c b/grub-core/commands/i386/pc/halt.c index 1e0aefa50..81eb6a1bb 100644 --- a/grub-core/commands/i386/pc/halt.c +++ b/grub-core/commands/i386/pc/halt.c @@ -22,6 +22,7 @@ #include #include #include +#include static const struct grub_arg_option options[] = { @@ -46,6 +47,8 @@ grub_halt (int no_apm) { struct grub_bios_int_registers regs; + grub_acpi_halt (); + if (no_apm) stop (); @@ -100,6 +103,7 @@ grub_cmd_halt (grub_extcmd_context_t ctxt, { struct grub_arg_list *state = ctxt->state; int no_apm = 0; + if (state[0].set) no_apm = 1; grub_halt (no_apm); @@ -110,8 +114,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(halt) { - cmd = grub_register_extcmd ("halt", grub_cmd_halt, GRUB_COMMAND_FLAG_BOTH, - "[-n]", + cmd = grub_register_extcmd ("halt", grub_cmd_halt, 0, "[-n]", N_("Halt the system, if possible using APM."), options); } diff --git a/grub-core/commands/i386/pc/lsapm.c b/grub-core/commands/i386/pc/lsapm.c new file mode 100644 index 000000000..30475d2ec --- /dev/null +++ b/grub-core/commands/i386/pc/lsapm.c @@ -0,0 +1,113 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include + +int +grub_apm_get_info (struct grub_apm_info *info) +{ + struct grub_bios_int_registers regs; + + /* detect APM */ + regs.eax = 0x5300; + regs.ebx = 0; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x15, ®s); + + if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY) + return 0; + info->version = regs.eax & 0xffff; + info->flags = regs.ecx & 0xffff; + + /* disconnect APM first */ + regs.eax = 0x5304; + regs.ebx = 0; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x15, ®s); + + /* connect APM */ + regs.eax = 0x5303; + regs.ebx = 0; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x15, ®s); + + if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY) + return 0; + + info->cseg = regs.eax & 0xffff; + info->offset = regs.ebx; + info->cseg_16 = regs.ecx & 0xffff; + info->dseg = regs.edx & 0xffff; + info->cseg_len = regs.esi >> 16; + info->cseg_16_len = regs.esi & 0xffff; + info->dseg_len = regs.edi; + + return 1; +} + +static grub_err_t +grub_cmd_lsapm (grub_command_t cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) +{ + struct grub_apm_info info; + if (!grub_apm_get_info (&info)) + return grub_error (GRUB_ERR_IO, "no APM found"); + + grub_printf ("Vesion %u.%u\n" + "32-bit CS = 0x%x, len = 0x%x, offset = 0x%x\n" + "16-bit CS = 0x%x, len = 0x%x\n" + "DS = 0x%x, len = 0x%x\n", + info.version >> 8, info.version & 0xff, + info.cseg, info.cseg_len, info.offset, + info.cseg_16, info.cseg_16_len, + info.dseg, info.dseg_len); + grub_xputs (info.flags & GRUB_APM_FLAGS_16BITPROTECTED_SUPPORTED + ? "16-bit protected interface supported\n" + : "16-bit protected interface unsupported\n"); + grub_xputs (info.flags & GRUB_APM_FLAGS_32BITPROTECTED_SUPPORTED + ? "32-bit protected interface supported\n" + : "32-bit protected interface unsupported\n"); + grub_xputs (info.flags & GRUB_APM_FLAGS_CPUIDLE_SLOWS_DOWN + ? "CPU Idle slows down processor\n" + : "CPU Idle doesn't slow down processor\n"); + grub_xputs (info.flags & GRUB_APM_FLAGS_DISABLED + ? "APM disabled\n" : "APM enabled\n"); + grub_xputs (info.flags & GRUB_APM_FLAGS_DISENGAGED + ? "APM disengaged\n" : "APM engaged\n"); + + return GRUB_ERR_NONE; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(lsapm) +{ + cmd = grub_register_command ("lsapm", grub_cmd_lsapm, 0, + N_("Show APM information.")); +} + +GRUB_MOD_FINI(lsapm) +{ + grub_unregister_command (cmd); +} + + diff --git a/grub-core/commands/i386/pc/sendkey.c b/grub-core/commands/i386/pc/sendkey.c index 1f506b3cd..c777ea60a 100644 --- a/grub-core/commands/i386/pc/sendkey.c +++ b/grub-core/commands/i386/pc/sendkey.c @@ -366,8 +366,7 @@ static void *preboot_hook; GRUB_MOD_INIT (sendkey) { - cmd = grub_register_extcmd ("sendkey", grub_cmd_sendkey, - GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("sendkey", grub_cmd_sendkey, 0, "sendkey [KEYSTROKE1] [KEYSTROKE2] ...", "Emulate a keystroke", options); diff --git a/grub-core/commands/i386/pc/vbeinfo.c b/grub-core/commands/i386/pc/vbeinfo.c deleted file mode 100644 index c266bbfcb..000000000 --- a/grub-core/commands/i386/pc/vbeinfo.c +++ /dev/null @@ -1,185 +0,0 @@ -/* vbeinfo.c - command to list compatible VBE video modes. */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2005,2007,2008,2009 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GRUB. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -static void * -real2pm (grub_vbe_farptr_t ptr) -{ - return (void *) ((((unsigned long) ptr & 0xFFFF0000) >> 12UL) - + ((unsigned long) ptr & 0x0000FFFF)); -} - -static grub_err_t -grub_cmd_vbeinfo (grub_command_t cmd __attribute__ ((unused)), - int argc __attribute__ ((unused)), - char **args __attribute__ ((unused))) -{ - struct grub_vbe_info_block controller_info; - struct grub_vbe_mode_info_block mode_info_tmp; - grub_uint32_t use_mode = GRUB_VBE_DEFAULT_VIDEO_MODE; - grub_uint16_t *video_mode_list; - grub_uint16_t *p; - grub_uint16_t *saved_video_mode_list; - grub_size_t video_mode_list_size; - grub_err_t err; - char *modevar; - - err = grub_vbe_probe (&controller_info); - if (err != GRUB_ERR_NONE) - return err; - - grub_printf ("VBE info: version: %d.%d OEM software rev: %d.%d\n", - controller_info.version >> 8, - controller_info.version & 0xFF, - controller_info.oem_software_rev >> 8, - controller_info.oem_software_rev & 0xFF); - - /* The total_memory field is in 64 KiB units. */ - grub_printf (" total memory: %d KiB\n", - (controller_info.total_memory << 16) / 1024); - - /* Because the information on video modes is stored in a temporary place, - it is better to copy it to somewhere safe. */ - p = video_mode_list = real2pm (controller_info.video_mode_ptr); - while (*p++ != 0xFFFF) - ; - - video_mode_list_size = (grub_addr_t) p - (grub_addr_t) video_mode_list; - saved_video_mode_list = grub_malloc (video_mode_list_size); - if (! saved_video_mode_list) - return grub_errno; - - grub_memcpy (saved_video_mode_list, video_mode_list, video_mode_list_size); - - grub_printf ("List of compatible video modes:\n"); - grub_printf ("Legend: P=Packed pixel, D=Direct color, " - "mask/pos=R/G/B/reserved\n"); - - /* Walk through all video modes listed. */ - for (p = saved_video_mode_list; *p != 0xFFFF; p++) - { - const char *memory_model = 0; - grub_uint32_t mode = (grub_uint32_t) *p; - - err = grub_vbe_get_video_mode_info (mode, &mode_info_tmp); - if (err != GRUB_ERR_NONE) - { - grub_errno = GRUB_ERR_NONE; - continue; - } - - if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_SUPPORTED) == 0) - /* If not available, skip it. */ - continue; - - if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_RESERVED_1) == 0) - /* Not enough information. */ - continue; - - if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_COLOR) == 0) - /* Monochrome is unusable. */ - continue; - - if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_LFB_AVAIL) == 0) - /* We support only linear frame buffer modes. */ - continue; - - if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_GRAPHICS) == 0) - /* We allow only graphical modes. */ - continue; - - switch (mode_info_tmp.memory_model) - { - case GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL: - memory_model = "Packed"; - break; - case GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR: - memory_model = "Direct"; - break; - - default: - break; - } - - if (! memory_model) - continue; - - grub_printf ("0x%03x: %4d x %4d x %2d %s", - mode, - mode_info_tmp.x_resolution, - mode_info_tmp.y_resolution, - mode_info_tmp.bits_per_pixel, - memory_model); - - /* Show mask and position details for direct color modes. */ - if (mode_info_tmp.memory_model == GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR) - grub_printf (", mask: %d/%d/%d/%d pos: %d/%d/%d/%d", - mode_info_tmp.red_mask_size, - mode_info_tmp.green_mask_size, - mode_info_tmp.blue_mask_size, - mode_info_tmp.rsvd_mask_size, - mode_info_tmp.red_field_position, - mode_info_tmp.green_field_position, - mode_info_tmp.blue_field_position, - mode_info_tmp.rsvd_field_position); - grub_printf ("\n"); - } - - grub_free (saved_video_mode_list); - - /* Check existence of vbe_mode environment variable. */ - modevar = grub_env_get ("vbe_mode"); - - if (modevar != 0) - { - unsigned long value; - - value = grub_strtoul (modevar, 0, 0); - if (grub_errno == GRUB_ERR_NONE) - use_mode = value; - else - grub_errno = GRUB_ERR_NONE; - } - - grub_printf ("Configured VBE mode (vbe_mode) = 0x%03x\n", use_mode); - - return 0; -} - -static grub_command_t cmd; - -GRUB_MOD_INIT(vbeinfo) -{ - cmd = - grub_register_command ("vbeinfo", grub_cmd_vbeinfo, 0, - N_("List compatible VESA BIOS extension video modes.")); -} - -GRUB_MOD_FINI(vbeinfo) -{ - grub_unregister_command (cmd); -} diff --git a/grub-core/commands/i386/pc/vbetest.c b/grub-core/commands/i386/pc/vbetest.c deleted file mode 100644 index d2921c09d..000000000 --- a/grub-core/commands/i386/pc/vbetest.c +++ /dev/null @@ -1,179 +0,0 @@ -/* vbetest.c - command to test VESA BIOS Extension 2.0+ support. */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2005,2007 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GRUB. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static grub_err_t -grub_cmd_vbetest (grub_command_t cmd __attribute__ ((unused)), - int argc __attribute__ ((unused)), - char **args __attribute__ ((unused))) -{ - grub_err_t err; - char *modevar; - struct grub_vbe_mode_info_block mode_info; - struct grub_vbe_info_block controller_info; - grub_uint32_t use_mode = GRUB_VBE_DEFAULT_VIDEO_MODE; - grub_uint32_t old_mode; - grub_uint8_t *framebuffer = 0; - grub_uint32_t bytes_per_scan_line = 0; - unsigned char *ptr; - int i; - - grub_printf ("Probing for VESA BIOS Extension ... "); - - /* Check if VESA BIOS exists. */ - err = grub_vbe_probe (&controller_info); - if (err != GRUB_ERR_NONE) - return err; - - grub_printf ("found!\n"); - - /* Dump out controller information. */ - grub_printf ("VBE signature = %c%c%c%c\n", - controller_info.signature[0], - controller_info.signature[1], - controller_info.signature[2], - controller_info.signature[3]); - - grub_printf ("VBE version = %d.%d\n", - controller_info.version >> 8, - controller_info.version & 0xFF); - grub_printf ("OEM string ptr = %08x\n", - controller_info.oem_string_ptr); - grub_printf ("Total memory = %d\n", - controller_info.total_memory); - - err = grub_vbe_get_video_mode (&old_mode); - grub_printf ("Get video mode err = %04x\n", err); - - if (err == GRUB_ERR_NONE) - grub_printf ("Old video mode = %04x\n", old_mode); - else - grub_errno = GRUB_ERR_NONE; - - /* Check existence of vbe_mode environment variable. */ - modevar = grub_env_get ("vbe_mode"); - if (modevar != 0) - { - unsigned long value; - - value = grub_strtoul (modevar, 0, 0); - if (grub_errno == GRUB_ERR_NONE) - use_mode = value; - else - grub_errno = GRUB_ERR_NONE; - } - - err = grub_vbe_get_video_mode_info (use_mode, &mode_info); - if (err != GRUB_ERR_NONE) - return err; - - /* Dump out details about the mode being tested. */ - grub_printf ("mode: 0x%03x\n", - use_mode); - grub_printf ("width : %d\n", - mode_info.x_resolution); - grub_printf ("height: %d\n", - mode_info.y_resolution); - grub_printf ("memory model: %02x\n", - mode_info.memory_model); - grub_printf ("bytes/scanline: %d\n", - mode_info.bytes_per_scan_line); - grub_printf ("bytes/scanline (lin): %d\n", - mode_info.lin_bytes_per_scan_line); - grub_printf ("base address: %08x\n", - mode_info.phys_base_addr); - grub_printf ("red mask/pos: %d/%d\n", - mode_info.red_mask_size, - mode_info.red_field_position); - grub_printf ("green mask/pos: %d/%d\n", - mode_info.green_mask_size, - mode_info.green_field_position); - grub_printf ("blue mask/pos: %d/%d\n", - mode_info.blue_mask_size, - mode_info.blue_field_position); - - grub_printf ("Press any key to continue.\n"); - - grub_getkey (); - - /* Setup GFX mode. */ - err = grub_vbe_set_video_mode (use_mode, &mode_info); - if (err != GRUB_ERR_NONE) - return err; - - /* Determine framebuffer address and how many bytes are in scan line. */ - framebuffer = (grub_uint8_t *) mode_info.phys_base_addr; - ptr = framebuffer; - - if (controller_info.version >= 0x300) - { - bytes_per_scan_line = mode_info.lin_bytes_per_scan_line; - } - else - { - bytes_per_scan_line = mode_info.bytes_per_scan_line; - } - - /* Draw some random data to screen. */ - for (i = 0; i < 256 * 256; i++) - { - ptr[i] = i & 0x0F; - } - - /* Draw white line to screen. */ - for (i = 0; i < 100; i++) - { - ptr[mode_info.bytes_per_scan_line * 50 + i] = 0x0F; - } - - /* Draw another white line to screen. */ - grub_memset (ptr + bytes_per_scan_line * 51, 0x0f, bytes_per_scan_line); - - grub_getkey (); - - grub_video_restore (); - - /* Restore old video mode. */ - grub_vbe_set_video_mode (old_mode, 0); - - return grub_errno; -} - -static grub_command_t cmd; - -GRUB_MOD_INIT(vbetest) -{ - cmd = grub_register_command ("vbetest", grub_cmd_vbetest, - 0, N_("Test VESA BIOS Extension 2.0+ support.")); -} - -GRUB_MOD_FINI(vbetest) -{ - grub_unregister_command (cmd); -} diff --git a/grub-core/commands/iorw.c b/grub-core/commands/iorw.c index bd0183794..20d203e92 100644 --- a/grub-core/commands/iorw.c +++ b/grub-core/commands/iorw.c @@ -40,7 +40,6 @@ grub_cmd_read (grub_extcmd_context_t ctxt, int argc, char **argv) { grub_target_addr_t addr; grub_uint32_t value = 0; - char buf[sizeof ("XXXXXXXX")]; if (argc != 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid number of arguments"); @@ -63,6 +62,7 @@ grub_cmd_read (grub_extcmd_context_t ctxt, int argc, char **argv) if (ctxt->state[0].set) { + char buf[sizeof ("XXXXXXXX")]; grub_snprintf (buf, sizeof (buf), "%x", value); grub_env_set (ctxt->state[0].arg, buf); } @@ -117,13 +117,13 @@ grub_cmd_write (grub_command_t cmd, int argc, char **argv) GRUB_MOD_INIT(memrw) { cmd_read_byte = - grub_register_extcmd ("inb", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH, + grub_register_extcmd ("inb", grub_cmd_read, 0, N_("PORT"), N_("Read byte from PORT."), options); cmd_read_word = - grub_register_extcmd ("inw", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH, + grub_register_extcmd ("inw", grub_cmd_read, 0, N_("PORT"), N_("Read word from PORT."), options); cmd_read_dword = - grub_register_extcmd ("inl", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH, + grub_register_extcmd ("inl", grub_cmd_read, 0, N_("PORT"), N_("Read dword from PORT."), options); cmd_write_byte = grub_register_command ("outb", grub_cmd_write, diff --git a/grub-core/commands/keylayouts.c b/grub-core/commands/keylayouts.c new file mode 100644 index 000000000..deb482a85 --- /dev/null +++ b/grub-core/commands/keylayouts.c @@ -0,0 +1,297 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2003,2005,2007,2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct grub_keyboard_layout layout_us = { + .keyboard_map = { + /* Keyboard errors. Handled by driver. */ + /* 0x00 */ 0, 0, 0, 0, + + /* 0x04 */ 'a', 'b', 'c', 'd', + /* 0x08 */ 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', + /* 0x10 */ 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', + /* 0x18 */ 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', + /* 0x20 */ '3', '4', '5', '6', '7', '8', '9', '0', + /* 0x28 */ '\n', '\e', '\b', '\t', ' ', '-', '=', '[', + /* According to usage table 0x31 should be mapped to '/' + but testing with real keyboard shows that 0x32 is remapped to '/'. + Map 0x31 to 0. + */ + /* 0x30 */ ']', 0, '\\', ';', '\'', '`', ',', '.', + /* 0x39 is CapsLock. Handled by driver. */ + /* 0x38 */ '/', 0, GRUB_TERM_KEY_F1, GRUB_TERM_KEY_F2, + /* 0x3c */ GRUB_TERM_KEY_F3, GRUB_TERM_KEY_F4, + /* 0x3e */ GRUB_TERM_KEY_F5, GRUB_TERM_KEY_F6, + /* 0x40 */ GRUB_TERM_KEY_F7, GRUB_TERM_KEY_F8, + /* 0x42 */ GRUB_TERM_KEY_F9, GRUB_TERM_KEY_F10, + /* 0x44 */ GRUB_TERM_KEY_F11, GRUB_TERM_KEY_F12, + /* PrtScr and ScrollLock. Not handled yet. */ + /* 0x46 */ 0, 0, + /* 0x48 is Pause. Not handled yet. */ + /* 0x48 */ 0, GRUB_TERM_KEY_INSERT, + /* 0x4a */ GRUB_TERM_KEY_HOME, GRUB_TERM_KEY_PPAGE, + /* 0x4c */ GRUB_TERM_KEY_DC, GRUB_TERM_KEY_END, + /* 0x4e */ GRUB_TERM_KEY_NPAGE, GRUB_TERM_KEY_RIGHT, + /* 0x50 */ GRUB_TERM_KEY_LEFT, GRUB_TERM_KEY_DOWN, + /* 0x53 is NumLock. Handled by driver. */ + /* 0x52 */ GRUB_TERM_KEY_UP, 0, + /* 0x54 */ '/', '*', + /* 0x56 */ '-', '+', + /* 0x58 */ '\n', GRUB_TERM_KEY_END, + /* 0x5a */ GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_NPAGE, + /* 0x5c */ GRUB_TERM_KEY_LEFT, GRUB_TERM_KEY_CENTER, + /* 0x5e */ GRUB_TERM_KEY_RIGHT, GRUB_TERM_KEY_HOME, + /* 0x60 */ GRUB_TERM_KEY_UP, GRUB_TERM_KEY_PPAGE, + /* 0x62 */ GRUB_TERM_KEY_INSERT, GRUB_TERM_KEY_DC, + /* 0x64 */ '\\' + }, + .keyboard_map_shift = { + /* Keyboard errors. Handled by driver. */ + /* 0x00 */ 0, 0, 0, 0, + + /* 0x04 */ 'A', 'B', 'C', 'D', + /* 0x08 */ 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', + /* 0x10 */ 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + /* 0x18 */ 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@', + /* 0x20 */ '#', '$', '%', '^', '&', '*', '(', ')', + /* 0x28 */ '\n' | GRUB_TERM_SHIFT, '\e' | GRUB_TERM_SHIFT, + /* 0x2a */ '\b' | GRUB_TERM_SHIFT, '\t' | GRUB_TERM_SHIFT, + /* 0x2c */ ' ' | GRUB_TERM_SHIFT, '_', '+', '{', + /* According to usage table 0x31 should be mapped to '/' + but testing with real keyboard shows that 0x32 is remapped to '/'. + Map 0x31 to 0. + */ + /* 0x30 */ '}', 0, '|', ':', '"', '~', '<', '>', + /* 0x39 is CapsLock. Handled by driver. */ + /* 0x38 */ '?', 0, + /* 0x3a */ GRUB_TERM_KEY_F1 | GRUB_TERM_SHIFT, + /* 0x3b */ GRUB_TERM_KEY_F2 | GRUB_TERM_SHIFT, + /* 0x3c */ GRUB_TERM_KEY_F3 | GRUB_TERM_SHIFT, + /* 0x3d */ GRUB_TERM_KEY_F4 | GRUB_TERM_SHIFT, + /* 0x3e */ GRUB_TERM_KEY_F5 | GRUB_TERM_SHIFT, + /* 0x3f */ GRUB_TERM_KEY_F6 | GRUB_TERM_SHIFT, + /* 0x40 */ GRUB_TERM_KEY_F7 | GRUB_TERM_SHIFT, + /* 0x41 */ GRUB_TERM_KEY_F8 | GRUB_TERM_SHIFT, + /* 0x42 */ GRUB_TERM_KEY_F9 | GRUB_TERM_SHIFT, + /* 0x43 */ GRUB_TERM_KEY_F10 | GRUB_TERM_SHIFT, + /* 0x44 */ GRUB_TERM_KEY_F11 | GRUB_TERM_SHIFT, + /* 0x45 */ GRUB_TERM_KEY_F12 | GRUB_TERM_SHIFT, + /* PrtScr and ScrollLock. Not handled yet. */ + /* 0x46 */ 0, 0, + /* 0x48 is Pause. Not handled yet. */ + /* 0x48 */ 0, GRUB_TERM_KEY_INSERT | GRUB_TERM_SHIFT, + /* 0x4a */ GRUB_TERM_KEY_HOME | GRUB_TERM_SHIFT, + /* 0x4b */ GRUB_TERM_KEY_PPAGE | GRUB_TERM_SHIFT, + /* 0x4c */ GRUB_TERM_KEY_DC | GRUB_TERM_SHIFT, + /* 0x4d */ GRUB_TERM_KEY_END | GRUB_TERM_SHIFT, + /* 0x4e */ GRUB_TERM_KEY_NPAGE | GRUB_TERM_SHIFT, + /* 0x4f */ GRUB_TERM_KEY_RIGHT | GRUB_TERM_SHIFT, + /* 0x50 */ GRUB_TERM_KEY_LEFT | GRUB_TERM_SHIFT, + /* 0x51 */ GRUB_TERM_KEY_DOWN | GRUB_TERM_SHIFT, + /* 0x53 is NumLock. Handled by driver. */ + /* 0x52 */ GRUB_TERM_KEY_UP | GRUB_TERM_SHIFT, 0, + /* 0x54 */ '/', '*', + /* 0x56 */ '-', '+', + /* 0x58 */ '\n' | GRUB_TERM_SHIFT, '1', '2', '3', '4', '5','6', '7', + /* 0x60 */ '8', '9', '0', '.', '|' + } +}; + +static struct grub_keyboard_layout *grub_current_layout = &layout_us; + +static int +map_key_core (int code, int status, int *alt_gr_consumed) +{ + *alt_gr_consumed = 0; + + if (status & GRUB_TERM_STATUS_RALT) + { + if (status & (GRUB_TERM_STATUS_LSHIFT | GRUB_TERM_STATUS_RSHIFT)) + { + if (grub_current_layout->keyboard_map_shift_l3[code]) + { + *alt_gr_consumed = 1; + return grub_current_layout->keyboard_map_shift_l3[code]; + } + } + else if (grub_current_layout->keyboard_map_l3[code]) + { + *alt_gr_consumed = 1; + return grub_current_layout->keyboard_map_l3[code]; + } + } + if (status & (GRUB_TERM_STATUS_LSHIFT | GRUB_TERM_STATUS_RSHIFT)) + return grub_current_layout->keyboard_map_shift[code]; + else + return grub_current_layout->keyboard_map[code]; +} + +unsigned +grub_term_map_key (grub_keyboard_key_t code, int status) +{ + int alt_gr_consumed = 0; + int key; + + if (code >= 0x59 && code <= 0x63 && (status & GRUB_TERM_STATUS_NUM)) + { + if (status & (GRUB_TERM_STATUS_RSHIFT | GRUB_TERM_STATUS_LSHIFT)) + status &= ~(GRUB_TERM_STATUS_RSHIFT | GRUB_TERM_STATUS_LSHIFT); + else + status |= GRUB_TERM_STATUS_RSHIFT; + } + + key = map_key_core (code, status, &alt_gr_consumed); + + if (key == 0 || key == GRUB_TERM_SHIFT) + grub_printf ("Unknown key 0x%x detected\n", code); + + if (status & GRUB_TERM_STATUS_CAPS) + { + if ((key >= 'a') && (key <= 'z')) + key += 'A' - 'a'; + else if ((key >= 'A') && (key <= 'Z')) + key += 'a' - 'A'; + } + + if ((status & GRUB_TERM_STATUS_LALT) || + ((status & GRUB_TERM_STATUS_RALT) && !alt_gr_consumed)) + key |= GRUB_TERM_ALT; + if (status & (GRUB_TERM_STATUS_LCTRL | GRUB_TERM_STATUS_RCTRL)) + key |= GRUB_TERM_CTRL; + + return key; +} + +static grub_err_t +grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + char *filename; + grub_file_t file; + grub_uint32_t version; + grub_uint8_t magic[GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE]; + struct grub_keyboard_layout *newmap = NULL; + unsigned i; + + if (argc < 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "file or layout name required"); + if (argv[0][0] != '(' && argv[0][0] != '/' && argv[0][0] != '+') + { + const char *prefix = grub_env_get ("prefix"); + if (!prefix) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "No prefix set"); + filename = grub_xasprintf ("%s/layouts/%s.gkb", prefix, argv[0]); + if (!filename) + return grub_errno; + } + else + filename = argv[0]; + + file = grub_file_open (filename); + if (! file) + goto fail; + + if (grub_file_read (file, magic, sizeof (magic)) != sizeof (magic)) + { + if (!grub_errno) + grub_error (GRUB_ERR_BAD_ARGUMENT, "file is too short"); + goto fail; + } + + if (grub_memcmp (magic, GRUB_KEYBOARD_LAYOUTS_FILEMAGIC, + GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE) != 0) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid magic"); + goto fail; + } + + if (grub_file_read (file, &version, sizeof (version)) != sizeof (version)) + { + if (!grub_errno) + grub_error (GRUB_ERR_BAD_ARGUMENT, "file is too short"); + goto fail; + } + + if (grub_le_to_cpu32 (version) != GRUB_KEYBOARD_LAYOUTS_VERSION) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid version"); + goto fail; + } + + newmap = grub_malloc (sizeof (*newmap)); + if (!newmap) + goto fail; + + if (grub_file_read (file, newmap, sizeof (*newmap)) != sizeof (*newmap)) + { + if (!grub_errno) + grub_error (GRUB_ERR_BAD_ARGUMENT, "file is too short"); + goto fail; + } + + for (i = 0; i < ARRAY_SIZE (newmap->keyboard_map); i++) + newmap->keyboard_map[i] = grub_le_to_cpu32(newmap->keyboard_map[i]); + + for (i = 0; i < ARRAY_SIZE (newmap->keyboard_map_shift); i++) + newmap->keyboard_map_shift[i] + = grub_le_to_cpu32(newmap->keyboard_map_shift[i]); + + for (i = 0; i < ARRAY_SIZE (newmap->keyboard_map_l3); i++) + newmap->keyboard_map_l3[i] + = grub_le_to_cpu32(newmap->keyboard_map_l3[i]); + + for (i = 0; i < ARRAY_SIZE (newmap->keyboard_map_shift_l3); i++) + newmap->keyboard_map_shift_l3[i] + = grub_le_to_cpu32(newmap->keyboard_map_shift_l3[i]); + + grub_current_layout = newmap; + + return GRUB_ERR_NONE; + + fail: + if (filename != argv[0]) + grub_free (filename); + grub_free (newmap); + if (file) + grub_file_close (file); + return grub_errno; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(keylayouts) +{ + cmd = grub_register_command ("keymap", grub_cmd_keymap, + 0, N_("Load a keyboard layout.")); +} + +GRUB_MOD_FINI(keylayouts) +{ + grub_unregister_command (cmd); +} diff --git a/grub-core/commands/keystatus.c b/grub-core/commands/keystatus.c index c83c00560..9e1486c9d 100644 --- a/grub-core/commands/keystatus.c +++ b/grub-core/commands/keystatus.c @@ -31,7 +31,23 @@ static const struct grub_arg_option options[] = {0, 0, 0, 0, 0, 0} }; -#define grub_cur_term_input grub_term_get_current_input () +static int +grub_getkeystatus (void) +{ + int status = 0; + grub_term_input_t term; + + if (grub_term_poll_usb) + grub_term_poll_usb (); + + FOR_ACTIVE_TERM_INPUTS(term) + { + if (term->getkeystatus) + status |= term->getkeystatus (term); + } + + return status; +} static grub_err_t grub_cmd_keystatus (grub_extcmd_context_t ctxt, @@ -43,11 +59,11 @@ grub_cmd_keystatus (grub_extcmd_context_t ctxt, int mods; if (state[0].set) - expect_mods |= GRUB_TERM_STATUS_SHIFT; + expect_mods |= (GRUB_TERM_STATUS_LSHIFT | GRUB_TERM_STATUS_RSHIFT); if (state[1].set) - expect_mods |= GRUB_TERM_STATUS_CTRL; + expect_mods |= (GRUB_TERM_STATUS_LCTRL | GRUB_TERM_STATUS_RCTRL); if (state[2].set) - expect_mods |= GRUB_TERM_STATUS_ALT; + expect_mods |= (GRUB_TERM_STATUS_LALT | GRUB_TERM_STATUS_RALT); grub_dprintf ("keystatus", "expect_mods: %d\n", expect_mods); @@ -80,8 +96,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(keystatus) { - cmd = grub_register_extcmd ("keystatus", grub_cmd_keystatus, - GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("keystatus", grub_cmd_keystatus, 0, N_("[--shift] [--ctrl] [--alt]"), N_("Check key modifier status."), options); diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c new file mode 100644 index 000000000..463297810 --- /dev/null +++ b/grub-core/commands/legacycfg.c @@ -0,0 +1,781 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2000, 2001, 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static grub_err_t +legacy_file (const char *filename) +{ + grub_file_t file; + char *entryname = NULL, *entrysrc = NULL; + grub_menu_t menu; + char *suffix = grub_strdup (""); + + auto grub_err_t getline (char **line, int cont); + grub_err_t getline (char **line, + int cont __attribute__ ((unused))) + { + *line = 0; + return GRUB_ERR_NONE; + } + + if (!suffix) + return grub_errno; + + file = grub_file_open (filename); + if (! file) + return grub_errno; + + menu = grub_env_get_menu (); + if (! menu) + { + menu = grub_zalloc (sizeof (*menu)); + if (! menu) + return grub_errno; + + grub_env_set_menu (menu); + } + + while (1) + { + char *buf = grub_file_getline (file); + char *parsed = NULL; + + if (!buf && grub_errno) + { + grub_file_close (file); + return grub_errno; + } + + if (!buf) + break; + + { + char *oldname = NULL; + char *newsuffix; + + oldname = entryname; + parsed = grub_legacy_parse (buf, &entryname, &newsuffix); + buf = NULL; + if (newsuffix) + { + char *t; + + t = suffix; + suffix = grub_realloc (suffix, grub_strlen (suffix) + + grub_strlen (newsuffix) + 1); + if (!suffix) + { + grub_free (t); + grub_free (entrysrc); + grub_free (parsed); + grub_free (newsuffix); + grub_free (suffix); + return grub_errno; + } + grub_memcpy (suffix + grub_strlen (suffix), newsuffix, + grub_strlen (newsuffix) + 1); + grub_free (newsuffix); + newsuffix = NULL; + } + if (oldname != entryname && oldname) + { + const char **args = grub_malloc (sizeof (args[0])); + if (!args) + { + grub_file_close (file); + return grub_errno; + } + args[0] = oldname; + grub_normal_add_menu_entry (1, args, NULL, NULL, NULL, NULL, + entrysrc); + grub_free (args); + entrysrc[0] = 0; + grub_free (oldname); + } + } + + if (parsed && !entryname) + { + grub_normal_parse_line (parsed, getline); + grub_print_error (); + grub_free (parsed); + parsed = NULL; + } + else if (parsed) + { + if (!entrysrc) + entrysrc = parsed; + else + { + char *t; + + t = entrysrc; + entrysrc = grub_realloc (entrysrc, grub_strlen (entrysrc) + + grub_strlen (parsed) + 1); + if (!entrysrc) + { + grub_free (t); + grub_free (parsed); + grub_free (suffix); + return grub_errno; + } + grub_memcpy (entrysrc + grub_strlen (entrysrc), parsed, + grub_strlen (parsed) + 1); + grub_free (parsed); + parsed = NULL; + } + } + } + grub_file_close (file); + + if (entryname) + { + const char **args = grub_malloc (sizeof (args[0])); + if (!args) + { + grub_file_close (file); + return grub_errno; + } + args[0] = entryname; + grub_normal_add_menu_entry (1, args, NULL, NULL, NULL, NULL, entrysrc); + grub_free (args); + } + + grub_normal_parse_line (suffix, getline); + grub_print_error (); + grub_free (suffix); + grub_free (entrysrc); + + if (menu && menu->size) + grub_show_menu (menu, 1); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_legacy_source (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); + return legacy_file (args[0]); +} + +static grub_err_t +grub_cmd_legacy_configfile (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + grub_err_t ret; + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); + + grub_cls (); + grub_env_context_open (1); + + ret = legacy_file (args[0]); + grub_env_context_close (); + + return ret; +} + +static enum + { + GUESS_IT, LINUX, MULTIBOOT, KFREEBSD, KNETBSD, KOPENBSD + } kernel_type; + +static grub_err_t +grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), + int argc, char **args) +{ + int i; + int no_mem_option = 0; + struct grub_command *cmd; + char **cutargs; + int cutargc; + + for (i = 0; i < 2; i++) + { + /* FIXME: really support this. */ + if (argc >= 1 && grub_strcmp (args[0], "--no-mem-option") == 0) + { + no_mem_option = 1; + argc--; + args++; + continue; + } + + /* linux16 handles both zImages and bzImages. */ + if (argc >= 1 && (grub_strcmp (args[0], "--type=linux") == 0 + || grub_strcmp (args[0], "--type=biglinux") == 0)) + { + kernel_type = LINUX; + argc--; + args++; + continue; + } + + if (argc >= 1 && grub_strcmp (args[0], "--type=multiboot") == 0) + { + kernel_type = MULTIBOOT; + argc--; + args++; + continue; + } + + if (argc >= 1 && grub_strcmp (args[0], "--type=freebsd") == 0) + { + kernel_type = KFREEBSD; + argc--; + args++; + continue; + } + + if (argc >= 1 && grub_strcmp (args[0], "--type=openbsd") == 0) + { + kernel_type = KOPENBSD; + argc--; + args++; + continue; + } + + if (argc >= 1 && grub_strcmp (args[0], "--type=netbsd") == 0) + { + kernel_type = KNETBSD; + argc--; + args++; + continue; + } + } + + if (argc < 2) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "filename required"); + + cutargs = grub_malloc (sizeof (cutargs[0]) * (argc - 1)); + cutargc = argc - 1; + grub_memcpy (cutargs + 1, args + 2, sizeof (cutargs[0]) * (argc - 2)); + cutargs[0] = args[0]; + + do + { + /* First try Linux. */ + if (kernel_type == GUESS_IT || kernel_type == LINUX) + { + cmd = grub_command_find ("linux16"); + if (cmd) + { + if (!(cmd->func) (cmd, cutargc, cutargs)) + { + kernel_type = LINUX; + return GRUB_ERR_NONE; + } + } + grub_errno = GRUB_ERR_NONE; + } + + /* Then multiboot. */ + if (kernel_type == GUESS_IT || kernel_type == MULTIBOOT) + { + cmd = grub_command_find ("multiboot"); + if (cmd) + { + if (!(cmd->func) (cmd, argc, args)) + { + kernel_type = MULTIBOOT; + return GRUB_ERR_NONE; + } + } + grub_errno = GRUB_ERR_NONE; + } + + { + int bsd_device = -1; + int bsd_slice = -1; + int bsd_part = -1; + { + grub_device_t dev; + char *hdbiasstr; + int hdbias = 0; + hdbiasstr = grub_env_get ("legacy_hdbias"); + if (hdbiasstr) + { + hdbias = grub_strtoul (hdbiasstr, 0, 0); + grub_errno = GRUB_ERR_NONE; + } + dev = grub_device_open (0); + if (dev && dev->disk + && dev->disk->dev->id == GRUB_DISK_DEVICE_BIOSDISK_ID + && dev->disk->dev->id >= 0x80 && dev->disk->dev->id <= 0x90) + { + struct grub_partition *part = dev->disk->partition; + bsd_device = dev->disk->id - 0x80 - hdbias; + if (part && (grub_strcmp (part->partmap->name, "netbsd") == 0 + || grub_strcmp (part->partmap->name, "openbsd") == 0 + || grub_strcmp (part->partmap->name, "bsd") == 0)) + { + bsd_part = part->number; + part = part->parent; + } + if (part && grub_strcmp (part->partmap->name, "msdos") == 0) + bsd_slice = part->number; + } + } + + /* k*BSD didn't really work well with grub-legacy. */ + if (kernel_type == GUESS_IT || kernel_type == KFREEBSD) + { + char buf[sizeof("adXXXXXXXXXXXXsXXXXXXXXXXXXYYY")]; + if (bsd_device != -1) + { + if (bsd_slice != -1 && bsd_part != -1) + grub_snprintf(buf, sizeof(buf), "ad%ds%d%c", bsd_device, + bsd_slice, 'a' + bsd_part); + else if (bsd_slice != -1) + grub_snprintf(buf, sizeof(buf), "ad%ds%d", bsd_device, + bsd_slice); + else + grub_snprintf(buf, sizeof(buf), "ad%d", bsd_device); + grub_env_set ("kFreeBSD.vfs.root.mountfrom", buf); + } + else + grub_env_unset ("kFreeBSD.vfs.root.mountfrom"); + cmd = grub_command_find ("kfreebsd"); + if (cmd) + { + if (!(cmd->func) (cmd, cutargc, cutargs)) + { + kernel_type = KFREEBSD; + return GRUB_ERR_NONE; + } + } + grub_errno = GRUB_ERR_NONE; + } + { + char **bsdargs; + int bsdargc; + char bsddevname[sizeof ("wdXXXXXXXXXXXXY")]; + if (bsd_device == -1) + { + bsdargs = cutargs; + bsdargc = cutargc; + } + else + { + bsdargc = cutargc + 2; + bsdargs = grub_malloc (sizeof (bsdargs[0]) * bsdargc); + grub_memcpy (bsdargs, args, argc * sizeof (bsdargs[0])); + bsdargs[argc] = "-r"; + bsdargs[argc + 1] = bsddevname; + grub_snprintf (bsddevname, sizeof (bsddevname), + "wd%d%c", bsd_device, + bsd_part != -1 ? bsd_part + 'a' : 'c'); + } + if (kernel_type == GUESS_IT || kernel_type == KNETBSD) + { + cmd = grub_command_find ("knetbsd"); + if (cmd) + { + if (!(cmd->func) (cmd, bsdargc, bsdargs)) + { + kernel_type = KNETBSD; + return GRUB_ERR_NONE; + } + } + grub_errno = GRUB_ERR_NONE; + } + if (kernel_type == GUESS_IT || kernel_type == KOPENBSD) + { + cmd = grub_command_find ("kopenbsd"); + if (cmd) + { + if (!(cmd->func) (cmd, bsdargc, bsdargs)) + { + kernel_type = KOPENBSD; + return GRUB_ERR_NONE; + } + } + grub_errno = GRUB_ERR_NONE; + } + if (bsdargs != cutargs) + grub_free (bsdargs); + } + } + } + while (0); + + return grub_error (GRUB_ERR_BAD_OS, "couldn't load file %s\n", + args[0]); +} + +static grub_err_t +grub_cmd_legacy_initrd (struct grub_command *mycmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_command *cmd; + + if (kernel_type == LINUX) + { + cmd = grub_command_find ("initrd16"); + if (!cmd) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "command initrd16 not found"); + + return cmd->func (cmd, argc, args); + } + if (kernel_type == MULTIBOOT) + { + cmd = grub_command_find ("module"); + if (!cmd) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "command module not found"); + + return cmd->func (cmd, argc, args); + } + + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "no kernel with module support is loaded in legacy way"); +} + +static grub_err_t +grub_cmd_legacy_initrdnounzip (struct grub_command *mycmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_command *cmd; + + if (kernel_type == LINUX) + { + cmd = grub_command_find ("initrd16"); + if (!cmd) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "command initrd16 not found"); + + return cmd->func (cmd, argc, args); + } + if (kernel_type == MULTIBOOT) + { + char **newargs; + grub_err_t err; + newargs = grub_malloc ((argc + 1) * sizeof (newargs[0])); + if (!newargs) + return grub_errno; + grub_memcpy (newargs + 1, args, argc * sizeof (newargs[0])); + newargs[0] = "--nounzip"; + cmd = grub_command_find ("module"); + if (!cmd) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "command module not found"); + + err = cmd->func (cmd, argc + 1, newargs); + grub_free (newargs); + return err; + } + + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "no kernel with module support is loaded in legacy way"); +} + +static grub_err_t +check_password_deny (const char *user __attribute__ ((unused)), + const char *entered __attribute__ ((unused)), + void *password __attribute__ ((unused))) +{ + return GRUB_ACCESS_DENIED; +} + +#define MD5_HASHLEN 16 + +struct legacy_md5_password +{ + grub_uint8_t *salt; + int saltlen; + grub_uint8_t hash[MD5_HASHLEN]; +}; + +static int +check_password_md5_real (const char *entered, + struct legacy_md5_password *pw) +{ + int enteredlen = grub_strlen (entered); + unsigned char alt_result[MD5_HASHLEN]; + unsigned char *digest; + grub_uint8_t ctx[GRUB_MD_MD5->contextsize]; + int i; + + GRUB_MD_MD5->init (ctx); + GRUB_MD_MD5->write (ctx, entered, enteredlen); + GRUB_MD_MD5->write (ctx, pw->salt + 3, pw->saltlen - 3); + GRUB_MD_MD5->write (ctx, entered, enteredlen); + digest = GRUB_MD_MD5->read (ctx); + GRUB_MD_MD5->final (ctx); + memcpy (alt_result, digest, MD5_HASHLEN); + + GRUB_MD_MD5->init (ctx); + GRUB_MD_MD5->write (ctx, entered, enteredlen); + GRUB_MD_MD5->write (ctx, pw->salt, pw->saltlen); /* include the $1$ header */ + for (i = enteredlen; i > 16; i -= 16) + GRUB_MD_MD5->write (ctx, alt_result, 16); + GRUB_MD_MD5->write (ctx, alt_result, i); + + for (i = enteredlen; i > 0; i >>= 1) + GRUB_MD_MD5->write (ctx, entered + ((i & 1) ? enteredlen : 0), 1); + digest = GRUB_MD_MD5->read (ctx); + GRUB_MD_MD5->final (ctx); + + for (i = 0; i < 1000; i++) + { + memcpy (alt_result, digest, 16); + + GRUB_MD_MD5->init (ctx); + if ((i & 1) != 0) + GRUB_MD_MD5->write (ctx, entered, enteredlen); + else + GRUB_MD_MD5->write (ctx, alt_result, 16); + + if (i % 3 != 0) + GRUB_MD_MD5->write (ctx, pw->salt + 3, pw->saltlen - 3); + + if (i % 7 != 0) + GRUB_MD_MD5->write (ctx, entered, enteredlen); + + if ((i & 1) != 0) + GRUB_MD_MD5->write (ctx, alt_result, 16); + else + GRUB_MD_MD5->write (ctx, entered, enteredlen); + digest = GRUB_MD_MD5->read (ctx); + GRUB_MD_MD5->final (ctx); + } + + return (grub_crypto_memcmp (digest, pw->hash, MD5_HASHLEN) == 0); +} + +static grub_err_t +check_password_md5 (const char *user, + const char *entered, + void *password) +{ + if (!check_password_md5_real (entered, password)) + return GRUB_ACCESS_DENIED; + + grub_auth_authenticate (user); + + return GRUB_ERR_NONE; +} + +static inline int +ib64t (char c) +{ + if (c == '.') + return 0; + if (c == '/') + return 1; + if (c >= '0' && c <= '9') + return c - '0' + 2; + if (c >= 'A' && c <= 'Z') + return c - 'A' + 12; + if (c >= 'a' && c <= 'z') + return c - 'a' + 38; + return -1; +} + +static struct legacy_md5_password * +parse_legacy_md5 (int argc, char **args) +{ + const char *salt, *saltend; + struct legacy_md5_password *pw = NULL; + int i; + const char *p; + + if (grub_memcmp (args[0], "--md5", sizeof ("--md5")) != 0) + goto fail; + if (argc == 1) + goto fail; + if (grub_strlen(args[1]) <= 3) + goto fail; + salt = args[1]; + saltend = grub_strchr (salt + 3, '$'); + if (!saltend) + goto fail; + pw = grub_malloc (sizeof (*pw)); + if (!pw) + goto fail; + + p = saltend + 1; + for (i = 0; i < 5; i++) + { + int n; + grub_uint32_t w = 0; + + for (n = 0; n < 4; n++) + { + int ww = ib64t(*p++); + if (ww == -1) + goto fail; + w |= ww << (n * 6); + } + pw->hash[i == 4 ? 5 : 12+i] = w & 0xff; + pw->hash[6+i] = (w >> 8) & 0xff; + pw->hash[i] = (w >> 16) & 0xff; + } + { + int n; + grub_uint32_t w = 0; + for (n = 0; n < 2; n++) + { + int ww = ib64t(*p++); + if (ww == -1) + goto fail; + w |= ww << (6 * n); + } + if (w >= 0x100) + goto fail; + pw->hash[11] = w; + } + + pw->saltlen = saltend - salt; + pw->salt = (grub_uint8_t *) grub_strndup (salt, pw->saltlen); + if (!pw->salt) + goto fail; + + return pw; + + fail: + grub_free (pw); + return NULL; +} + +static grub_err_t +grub_cmd_legacy_password (struct grub_command *mycmd __attribute__ ((unused)), + int argc, char **args) +{ + struct legacy_md5_password *pw = NULL; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments expected"); + if (args[0][0] != '-' || args[0][1] != '-') + return grub_normal_set_password ("legacy", args[0]); + + pw = parse_legacy_md5 (argc, args); + + if (pw) + return grub_auth_register_authentication ("legacy", check_password_md5, pw); + else + /* This is to imitate minor difference between grub-legacy in GRUB2. + If 2 password commands are executed in a row and second one fails + on GRUB2 the password of first one is used, whereas in grub-legacy + authenthication is denied. In case of no password command was executed + early both versions deny any access. */ + return grub_auth_register_authentication ("legacy", check_password_deny, + NULL); +} + +static grub_err_t +grub_cmd_legacy_check_password (struct grub_command *mycmd __attribute__ ((unused)), + int argc, char **args) +{ + struct legacy_md5_password *pw = NULL; + char entered[GRUB_AUTH_MAX_PASSLEN]; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments expected"); + grub_printf ("Enter password:"); + if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN)) + return GRUB_ACCESS_DENIED; + + if (args[0][0] != '-' || args[0][1] != '-') + { + char correct[GRUB_AUTH_MAX_PASSLEN]; + + grub_memset (correct, 0, sizeof (correct)); + grub_strncpy (correct, args[0], sizeof (correct)); + + if (grub_crypto_memcmp (entered, correct, GRUB_AUTH_MAX_PASSLEN) != 0) + return GRUB_ACCESS_DENIED; + return GRUB_ERR_NONE; + } + + pw = parse_legacy_md5 (argc, args); + + if (!pw) + return GRUB_ACCESS_DENIED; + + if (!check_password_md5_real (entered, pw)) + return GRUB_ACCESS_DENIED; + + return GRUB_ERR_NONE; +} + +static grub_command_t cmd_source, cmd_configfile, cmd_kernel, cmd_initrd; +static grub_command_t cmd_password, cmd_check_password, cmd_initrdnounzip; + +GRUB_MOD_INIT(legacycfg) +{ + cmd_source = grub_register_command ("legacy_source", + grub_cmd_legacy_source, + N_("FILE"), N_("Parse legacy config")); + cmd_configfile = grub_register_command ("legacy_configfile", + grub_cmd_legacy_configfile, + N_("FILE"), + N_("Parse legacy config")); + + cmd_kernel = grub_register_command ("legacy_kernel", + grub_cmd_legacy_kernel, + N_("[--no-mem-option] [--type=TYPE] FILE [ARG ...]"), + N_("Simulate grub-legacy kernel command")); + + cmd_initrd = grub_register_command ("legacy_initrd", + grub_cmd_legacy_initrd, + N_("FILE [ARG ...]"), + N_("Simulate grub-legacy initrd command")); + cmd_initrdnounzip = grub_register_command ("legacy_initrd_nounzip", + grub_cmd_legacy_initrdnounzip, + N_("FILE [ARG ...]"), + N_("Simulate grub-legacy modulenounzip command")); + + cmd_password = grub_register_command ("legacy_password", + grub_cmd_legacy_password, + N_("[--md5] PASSWD [FILE]"), + N_("Simulate grub-legacy password command")); + + cmd_check_password = grub_register_command ("legacy_check_password", + grub_cmd_legacy_check_password, + N_("[--md5] PASSWD [FILE]"), + N_("Simulate grub-legacy password command in menuentry mode")); + +} + +GRUB_MOD_FINI(legacycfg) +{ + grub_unregister_command (cmd_source); + grub_unregister_command (cmd_configfile); + grub_unregister_command (cmd_kernel); + grub_unregister_command (cmd_initrd); + grub_unregister_command (cmd_initrdnounzip); + grub_unregister_command (cmd_password); + grub_unregister_command (cmd_check_password); +} diff --git a/grub-core/commands/loadenv.c b/grub-core/commands/loadenv.c index 9a1873ba9..38b3a84c6 100644 --- a/grub-core/commands/loadenv.c +++ b/grub-core/commands/loadenv.c @@ -375,20 +375,15 @@ static grub_extcmd_t cmd_load, cmd_list, cmd_save; GRUB_MOD_INIT(loadenv) { cmd_load = - grub_register_extcmd ("load_env", grub_cmd_load_env, - GRUB_COMMAND_FLAG_BOTH, - N_("[-f FILE]"), + grub_register_extcmd ("load_env", grub_cmd_load_env, 0, N_("[-f FILE]"), N_("Load variables from environment block file."), options); cmd_list = - grub_register_extcmd ("list_env", grub_cmd_list_env, - GRUB_COMMAND_FLAG_BOTH, - N_("[-f FILE]"), + grub_register_extcmd ("list_env", grub_cmd_list_env, 0, N_("[-f FILE]"), N_("List variables from environment block file."), options); cmd_save = - grub_register_extcmd ("save_env", grub_cmd_save_env, - GRUB_COMMAND_FLAG_BOTH, + grub_register_extcmd ("save_env", grub_cmd_save_env, 0, N_("[-f FILE] variable_name [...]"), N_("Save variables to environment block file."), options); diff --git a/grub-core/commands/ls.c b/grub-core/commands/ls.c index 02915bac4..481d17db0 100644 --- a/grub-core/commands/ls.c +++ b/grub-core/commands/ls.c @@ -253,12 +253,14 @@ static grub_err_t grub_cmd_ls (grub_extcmd_context_t ctxt, int argc, char **args) { struct grub_arg_list *state = ctxt->state; + int i; if (argc == 0) grub_ls_list_devices (state[0].set); else - grub_ls_list_files (args[0], state[0].set, state[2].set, - state[1].set); + for (i = 0; i < argc; i++) + grub_ls_list_files (args[i], state[0].set, state[2].set, + state[1].set); return 0; } @@ -267,8 +269,8 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(ls) { - cmd = grub_register_extcmd ("ls", grub_cmd_ls, GRUB_COMMAND_FLAG_BOTH, - N_("[-l|-h|-a] [FILE]"), + cmd = grub_register_extcmd ("ls", grub_cmd_ls, 0, + N_("[-l|-h|-a] [FILE ...]"), N_("List devices and files."), options); } diff --git a/grub-core/commands/lsacpi.c b/grub-core/commands/lsacpi.c new file mode 100644 index 000000000..64b559665 --- /dev/null +++ b/grub-core/commands/lsacpi.c @@ -0,0 +1,250 @@ +/* acpi.c - Display acpi tables. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ +#include +#include +#include +#include +#include +#include +#include +#include + +static void +print_strn (grub_uint8_t *str, grub_size_t len) +{ + for (; *str && len; str++, len--) + grub_printf ("%c", *str); + for (len++; len; len--) + grub_printf (" "); +} + +#define print_field(x) print_strn(x, sizeof (x)) + +static void +disp_acpi_table (struct grub_acpi_table_header *t) +{ + print_field (t->signature); + grub_printf ("%4" PRIuGRUB_UINT32_T "B rev=%u OEM=", t->length, t->revision); + print_field (t->oemid); + print_field (t->oemtable); + grub_printf ("OEMrev=%08" PRIxGRUB_UINT32_T " ", t->oemrev); + print_field (t->creator_id); + grub_printf (" %08" PRIxGRUB_UINT32_T "\n", t->creator_rev); +} + +static void +disp_madt_table (struct grub_acpi_madt *t) +{ + struct grub_acpi_madt_entry_header *d; + grub_uint32_t len; + + disp_acpi_table (&t->hdr); + grub_printf ("Local APIC=%08" PRIxGRUB_UINT32_T " Flags=%08" + PRIxGRUB_UINT32_T "\n", + t->lapic_addr, t->flags); + len = t->hdr.length - sizeof (struct grub_acpi_madt); + d = t->entries; + for (;len > 0; len -= d->len, d = (void *) ((grub_uint8_t *) d + d->len)) + { + grub_printf (" type=%x l=%u ", d->type, d->len); + + switch (d->type) + { + case GRUB_ACPI_MADT_ENTRY_TYPE_INTERRUPT_OVERRIDE: + { + struct grub_acpi_madt_entry_interrupt_override *dt = (void *) d; + grub_printf ("Int Override bus=%x src=%x GSI=%08x Flags=%04x\n", + dt->bus, dt->source, dt->global_sys_interrupt, + dt->flags); + } + break; + case GRUB_ACPI_MADT_ENTRY_TYPE_SAPIC: + { + struct grub_acpi_madt_entry_sapic *dt = (void *) d; + grub_printf ("IOSAPIC Id=%02x GSI=%08x Addr=%016" PRIxGRUB_UINT64_T + "\n", + dt->id, dt->global_sys_interrupt_base, + dt->addr); + } + break; + case GRUB_ACPI_MADT_ENTRY_TYPE_LSAPIC: + { + struct grub_acpi_madt_entry_lsapic *dt = (void *) d; + grub_printf ("LSAPIC ProcId=%02x ID=%02x EID=%02x Flags=%x", + dt->cpu_id, dt->id, dt->eid, dt->flags); + if (dt->flags & GRUB_ACPI_MADT_ENTRY_SAPIC_FLAGS_ENABLED) + grub_printf (" Enabled\n"); + else + grub_printf (" Disabled\n"); + if (d->len > sizeof (struct grub_acpi_madt_entry_sapic)) + grub_printf (" UID val=%08x, Str=%s\n", dt->cpu_uid, + dt->cpu_uid_str); + } + break; + case GRUB_ACPI_MADT_ENTRY_TYPE_PLATFORM_INT_SOURCE: + { + struct grub_acpi_madt_entry_platform_int_source *dt = (void *) d; + static const char * const platint_type[] = + {"Nul", "PMI", "INIT", "CPEI"}; + + grub_printf ("Platform INT flags=%04x type=%02x (%s)" + " ID=%02x EID=%02x\n", + dt->flags, dt->inttype, + (dt->inttype < ARRAY_SIZE (platint_type)) + ? platint_type[dt->inttype] : "??", dt->cpu_id, + dt->cpu_eid); + grub_printf (" IOSAPIC Vec=%02x GSI=%08x source flags=%08x\n", + dt->sapic_vector, dt->global_sys_int, dt->src_flags); + } + break; + default: + grub_printf (" ??\n"); + } + } +} + +static void +disp_acpi_xsdt_table (struct grub_acpi_table_header *t) +{ + grub_uint32_t len; + grub_uint64_t *desc; + + disp_acpi_table (t); + len = t->length - sizeof (*t); + desc = (grub_uint64_t *) (t + 1); + for (; len > 0; desc++, len -= sizeof (*desc)) + { + if (sizeof (grub_addr_t) == 4 && *desc >= (1ULL << 32)) + { + grub_printf ("Unreachable table\n"); + continue; + } + t = (struct grub_acpi_table_header *) (grub_addr_t) *desc; + + if (t == NULL) + continue; + + if (grub_memcmp (t->signature, GRUB_ACPI_MADT_SIGNATURE, + sizeof (t->signature)) == 0) + disp_madt_table ((struct grub_acpi_madt *) t); + else + disp_acpi_table (t); + } +} + +static void +disp_acpi_rsdt_table (struct grub_acpi_table_header *t) +{ + grub_uint32_t len; + grub_uint32_t *desc; + + disp_acpi_table (t); + len = t->length - sizeof (*t); + desc = (grub_uint32_t *) (t + 1); + for (; len > 0; desc++, len -= sizeof (*desc)) + { + t = (struct grub_acpi_table_header *) (grub_addr_t) *desc; + + if (t == NULL) + continue; + + if (grub_memcmp (t->signature, GRUB_ACPI_MADT_SIGNATURE, + sizeof (t->signature)) == 0) + disp_madt_table ((struct grub_acpi_madt *) t); + else + disp_acpi_table (t); + } +} + +static void +disp_acpi_rsdpv1 (struct grub_acpi_rsdp_v10 *rsdp) +{ + print_field (rsdp->signature); + grub_printf ("chksum:%02x, OEM-ID: ", rsdp->checksum); + print_field (rsdp->oemid); + grub_printf ("rev=%d\n", rsdp->revision); + grub_printf ("RSDT=%08" PRIxGRUB_UINT32_T "\n", rsdp->rsdt_addr); +} + +static void +disp_acpi_rsdpv2 (struct grub_acpi_rsdp_v20 *rsdp) +{ + disp_acpi_rsdpv1 (&rsdp->rsdpv1); + grub_printf ("len=%d XSDT=%016" PRIxGRUB_UINT64_T "\n", rsdp->length, + rsdp->xsdt_addr); +} + +static const struct grub_arg_option options[] = { + {"v1", '1', 0, N_("Show v1 tables only."), 0, ARG_TYPE_NONE}, + {"v2", '2', 0, N_("Show v2 and v3 tablesv only."), 0, ARG_TYPE_NONE} +}; + +static grub_err_t +grub_cmd_lsacpi (struct grub_extcmd_context *ctxt, + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + if (!ctxt->state[1].set) + { + struct grub_acpi_rsdp_v10 *rsdp1 = grub_acpi_get_rsdpv1 (); + if (!rsdp1) + grub_printf ("No RSDPv1\n"); + else + { + grub_printf ("RSDPv1 signature:"); + disp_acpi_rsdpv1 (rsdp1); + disp_acpi_rsdt_table ((void *) (grub_addr_t) rsdp1->rsdt_addr); + } + } + + if (!ctxt->state[0].set) + { + struct grub_acpi_rsdp_v20 *rsdp2 = grub_acpi_get_rsdpv2 (); + if (!rsdp2) + grub_printf ("No RSDPv2\n"); + else + { + if (sizeof (grub_addr_t) == 4 && rsdp2->xsdt_addr >= (1ULL << 32)) + grub_printf ("Unreachable RSDPv2\n"); + else + { + grub_printf ("RSDPv2 signature:"); + disp_acpi_rsdpv2 (rsdp2); + disp_acpi_xsdt_table ((void *) (grub_addr_t) rsdp2->xsdt_addr); + grub_printf ("\n"); + } + } + } + return GRUB_ERR_NONE; +} + +static grub_extcmd_t cmd; + +GRUB_MOD_INIT(lsapi) +{ + cmd = grub_register_extcmd ("lsacpi", grub_cmd_lsacpi, 0, N_("[-1|-2]"), + N_("Show ACPI information."), options); +} + +GRUB_MOD_FINI(lsacpi) +{ + grub_unregister_extcmd (cmd); +} + + diff --git a/grub-core/commands/lsmmap.c b/grub-core/commands/lsmmap.c index 2755df9c4..657f81387 100644 --- a/grub-core/commands/lsmmap.c +++ b/grub-core/commands/lsmmap.c @@ -16,24 +16,39 @@ * along with GRUB. If not, see . */ -#ifndef GRUB_MACHINE_EMU -#include -#endif #include #include #include #include +#include + +static const char *names[] = + { + [GRUB_MEMORY_AVAILABLE] = "available", + [GRUB_MEMORY_RESERVED] = "reserved", + [GRUB_MEMORY_ACPI] = "ACPI reclamaible", + [GRUB_MEMORY_NVS] = "NVS", + [GRUB_MEMORY_BADRAM] = "BadRAM", + [GRUB_MEMORY_CODE] = "firmware code", + [GRUB_MEMORY_HOLE] = "hole" + }; static grub_err_t grub_cmd_lsmmap (grub_command_t cmd __attribute__ ((unused)), - int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) { - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); - int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_memory_type_t); + int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, + grub_memory_type_t type) { - grub_printf ("base_addr = 0x%llx, length = 0x%llx, type = 0x%x\n", - (long long) addr, (long long) size, type); + if (type < ARRAY_SIZE (names) && names[type]) + grub_printf ("base_addr = 0x%llx, length = 0x%llx, %s\n", + (long long) addr, (long long) size, names[type]); + else + grub_printf ("base_addr = 0x%llx, length = 0x%llx, type = 0x%x\n", + (long long) addr, (long long) size, type); return 0; } #ifndef GRUB_MACHINE_EMU diff --git a/grub-core/commands/lspci.c b/grub-core/commands/lspci.c index bc52e060a..fd2d4eaf2 100644 --- a/grub-core/commands/lspci.c +++ b/grub-core/commands/lspci.c @@ -224,8 +224,8 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(lspci) { - cmd = grub_register_extcmd ("lspci", grub_cmd_lspci, GRUB_COMMAND_FLAG_BOTH, - "[-i]", N_("List PCI devices."), options); + cmd = grub_register_extcmd ("lspci", grub_cmd_lspci, 0, "[-i]", + N_("List PCI devices."), options); } GRUB_MOD_FINI(lspci) diff --git a/grub-core/commands/memrw.c b/grub-core/commands/memrw.c index d28f45ec1..28aac7d81 100644 --- a/grub-core/commands/memrw.c +++ b/grub-core/commands/memrw.c @@ -119,13 +119,13 @@ grub_cmd_write (grub_command_t cmd, int argc, char **argv) GRUB_MOD_INIT(memrw) { cmd_read_byte = - grub_register_extcmd ("read_byte", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH, + grub_register_extcmd ("read_byte", grub_cmd_read, 0, N_("ADDR"), N_("Read byte from ADDR."), options); cmd_read_word = - grub_register_extcmd ("read_word", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH, + grub_register_extcmd ("read_word", grub_cmd_read, 0, N_("ADDR"), N_("Read word from ADDR."), options); cmd_read_dword = - grub_register_extcmd ("read_dword", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH, + grub_register_extcmd ("read_dword", grub_cmd_read, 0, N_("ADDR"), N_("Read dword from ADDR."), options); cmd_write_byte = grub_register_command ("write_byte", grub_cmd_write, diff --git a/grub-core/commands/menuentry.c b/grub-core/commands/menuentry.c index fc1ae71c7..b19257c8e 100644 --- a/grub-core/commands/menuentry.c +++ b/grub-core/commands/menuentry.c @@ -46,16 +46,29 @@ static struct { {"backspace", '\b'}, {"tab", '\t'}, - {"delete", GRUB_TERM_DC} + {"delete", GRUB_TERM_KEY_DC}, + {"insert", GRUB_TERM_KEY_INSERT}, + {"f1", GRUB_TERM_KEY_F1}, + {"f2", GRUB_TERM_KEY_F2}, + {"f3", GRUB_TERM_KEY_F3}, + {"f4", GRUB_TERM_KEY_F4}, + {"f5", GRUB_TERM_KEY_F5}, + {"f6", GRUB_TERM_KEY_F6}, + {"f7", GRUB_TERM_KEY_F7}, + {"f8", GRUB_TERM_KEY_F8}, + {"f9", GRUB_TERM_KEY_F9}, + {"f10", GRUB_TERM_KEY_F10}, + {"f11", GRUB_TERM_KEY_F11}, + {"f12", GRUB_TERM_KEY_F12}, }; /* Add a menu entry to the current menu context (as given by the environment variable data slot `menu'). As the configuration file is read, the script parser calls this when a menu entry is to be created. */ -static grub_err_t -append_menu_entry (int argc, const char **args, char **classes, - const char *users, const char *hotkey, - const char *prefix, const char *sourcecode) +grub_err_t +grub_normal_add_menu_entry (int argc, const char **args, char **classes, + const char *users, const char *hotkey, + const char *prefix, const char *sourcecode) { unsigned i; int menu_hotkey = 0; @@ -128,7 +141,7 @@ append_menu_entry (int argc, const char **args, char **classes, if (! menu_args) goto fail; - for (i = 0; args[i]; i++) + for (i = 0; i < argc; i++) { menu_args[i] = grub_strdup (args[i]); if (! menu_args[i]) @@ -243,9 +256,10 @@ grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args) return grub_error (GRUB_ERR_BAD_ARGUMENT, "no menuentry definition"); if (! ctxt->script) - return append_menu_entry (argc, (const char **) args, - ctxt->state[0].args, ctxt->state[1].arg, - ctxt->state[2].arg, 0, ctxt->state[3].arg); + return grub_normal_add_menu_entry (argc, (const char **) args, + ctxt->state[0].args, ctxt->state[1].arg, + ctxt->state[2].arg, 0, + ctxt->state[3].arg); src = args[argc - 1]; args[argc - 1] = NULL; @@ -258,9 +272,9 @@ grub_cmd_menuentry (grub_extcmd_context_t ctxt, int argc, char **args) if (! prefix) return grub_errno; - r = append_menu_entry (argc - 1, (const char **) args, - ctxt->state[0].args, ctxt->state[1].arg, - ctxt->state[2].arg, prefix, src + 1); + r = grub_normal_add_menu_entry (argc - 1, (const char **) args, + ctxt->state[0].args, ctxt->state[1].arg, + ctxt->state[2].arg, prefix, src + 1); src[len - 1] = ch; args[argc - 1] = src; @@ -274,7 +288,7 @@ void grub_menu_init (void) { cmd = grub_register_extcmd ("menuentry", grub_cmd_menuentry, - GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_BLOCKS, + GRUB_COMMAND_FLAG_BLOCKS, N_("BLOCK"), N_("Define a menuentry."), options); } diff --git a/grub-core/commands/minicmd.c b/grub-core/commands/minicmd.c index 3d5f59719..5cf109fde 100644 --- a/grub-core/commands/minicmd.c +++ b/grub-core/commands/minicmd.c @@ -108,40 +108,6 @@ grub_rescue_cmd_info (void) } #endif -/* root [DEVICE] */ -static grub_err_t -grub_mini_cmd_root (struct grub_command *cmd __attribute__ ((unused)), - int argc, char *argv[]) -{ - grub_device_t dev; - grub_fs_t fs; - - if (argc > 0) - { - char *device_name = grub_file_get_device_name (argv[0]); - if (! device_name) - return grub_errno; - - grub_env_set ("root", device_name); - grub_free (device_name); - } - - dev = grub_device_open (0); - if (! dev) - return grub_errno; - - fs = grub_fs_probe (dev); - if (grub_errno == GRUB_ERR_UNKNOWN_FS) - grub_errno = GRUB_ERR_NONE; - - grub_printf ("(%s): Filesystem is %s.\n", - grub_env_get ("root"), fs ? fs->name : "unknown"); - - grub_device_close (dev); - - return 0; -} - /* dump ADDRESS [SIZE] */ static grub_err_t grub_mini_cmd_dump (struct grub_command *cmd __attribute__ ((unused)), @@ -226,7 +192,7 @@ grub_mini_cmd_exit (struct grub_command *cmd __attribute__ ((unused)), return 0; } -static grub_command_t cmd_cat, cmd_help, cmd_root; +static grub_command_t cmd_cat, cmd_help; static grub_command_t cmd_dump, cmd_rmmod, cmd_lsmod, cmd_exit; GRUB_MOD_INIT(minicmd) @@ -237,9 +203,6 @@ GRUB_MOD_INIT(minicmd) cmd_help = grub_register_command ("help", grub_mini_cmd_help, 0, N_("Show this message.")); - cmd_root = - grub_register_command ("root", grub_mini_cmd_root, - N_("[DEVICE]"), N_("Set the root device.")); cmd_dump = grub_register_command ("dump", grub_mini_cmd_dump, N_("ADDR"), N_("Dump memory.")); @@ -258,7 +221,6 @@ GRUB_MOD_FINI(minicmd) { grub_unregister_command (cmd_cat); grub_unregister_command (cmd_help); - grub_unregister_command (cmd_root); grub_unregister_command (cmd_dump); grub_unregister_command (cmd_rmmod); grub_unregister_command (cmd_lsmod); diff --git a/grub-core/commands/parttool.c b/grub-core/commands/parttool.c index f2a62e581..31e768553 100644 --- a/grub-core/commands/parttool.c +++ b/grub-core/commands/parttool.c @@ -275,7 +275,7 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)), if (! parsed[j]) { for (curarg = ptool->args; curarg->name; curarg++) - if (grub_strncmp (curarg->name, args[i], + if (grub_strncmp (curarg->name, args[j], grub_strlen (curarg->name)) == 0 && ((curarg->type == GRUB_PARTTOOL_ARG_BOOL && (args[j][grub_strlen (curarg->name)] == '+' diff --git a/grub-core/commands/password.c b/grub-core/commands/password.c index 04285254e..db5951cbb 100644 --- a/grub-core/commands/password.c +++ b/grub-core/commands/password.c @@ -40,26 +40,22 @@ check_password (const char *user, const char *entered, return GRUB_ERR_NONE; } -static grub_err_t -grub_cmd_password (grub_command_t cmd __attribute__ ((unused)), - int argc, char **args) +grub_err_t +grub_normal_set_password (const char *user, const char *password) { grub_err_t err; char *pass; int copylen; - if (argc != 2) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "two arguments expected"); - pass = grub_zalloc (GRUB_AUTH_MAX_PASSLEN); if (!pass) return grub_errno; - copylen = grub_strlen (args[1]); + copylen = grub_strlen (password); if (copylen >= GRUB_AUTH_MAX_PASSLEN) copylen = GRUB_AUTH_MAX_PASSLEN - 1; - grub_memcpy (pass, args[1], copylen); + grub_memcpy (pass, password, copylen); - err = grub_auth_register_authentication (args[0], check_password, pass); + err = grub_auth_register_authentication (user, check_password, pass); if (err) { grub_free (pass); @@ -69,6 +65,15 @@ grub_cmd_password (grub_command_t cmd __attribute__ ((unused)), return GRUB_ERR_NONE; } +static grub_err_t +grub_cmd_password (grub_command_t cmd __attribute__ ((unused)), + int argc, char **args) +{ + if (argc != 2) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "two arguments expected"); + return grub_normal_set_password (args[0], args[1]); +} + static grub_command_t cmd; GRUB_MOD_INIT(password) diff --git a/grub-core/commands/probe.c b/grub-core/commands/probe.c index f3941e029..abe84895d 100644 --- a/grub-core/commands/probe.c +++ b/grub-core/commands/probe.c @@ -150,8 +150,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT (probe) { - cmd = grub_register_extcmd ("probe", grub_cmd_probe, GRUB_COMMAND_FLAG_BOTH, - N_("[DEVICE]"), + cmd = grub_register_extcmd ("probe", grub_cmd_probe, 0, N_("[DEVICE]"), N_("Retrieve device info."), options); } diff --git a/grub-core/commands/regexp.c b/grub-core/commands/regexp.c index 4329483af..f27a147af 100644 --- a/grub-core/commands/regexp.c +++ b/grub-core/commands/regexp.c @@ -136,8 +136,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(regexp) { - cmd = grub_register_extcmd ("regexp", grub_cmd_regexp, - GRUB_COMMAND_FLAG_BOTH, N_("REGEXP STRING"), + cmd = grub_register_extcmd ("regexp", grub_cmd_regexp, 0, N_("REGEXP STRING"), N_("Test if REGEXP matches STRING."), options); /* Setup GRUB script wildcard translator. */ diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c index 8a646b452..f265f86d6 100644 --- a/grub-core/commands/search.c +++ b/grub-core/commands/search.c @@ -28,9 +28,12 @@ #include #include #include +#include +#include void -FUNC_NAME (const char *key, const char *var, int no_floppy) +FUNC_NAME (const char *key, const char *var, int no_floppy, + char **hints, unsigned nhints) { int count = 0; grub_fs_autoload_hook_t saved_autoload; @@ -114,22 +117,86 @@ FUNC_NAME (const char *key, const char *var, int no_floppy) return (found && var); } + auto int part_hook (grub_disk_t disk, const grub_partition_t partition); + int part_hook (grub_disk_t disk, const grub_partition_t partition) + { + char *partition_name, *devname; + int ret; + + partition_name = grub_partition_get_name (partition); + if (! partition_name) + return 1; + + devname = grub_xasprintf ("%s,%s", disk->name, partition_name); + grub_free (partition_name); + if (!devname) + return 1; + ret = iterate_device (devname); + grub_free (devname); + + return ret; + } + + auto void try (void); + void try (void) + { + unsigned i; + for (i = 0; i < nhints; i++) + { + char *end; + if (!hints[i][0]) + continue; + end = hints[i] + grub_strlen (hints[i]) - 1; + if (*end == ',') + *end = 0; + if (iterate_device (hints[i])) + { + if (!*end) + *end = ','; + return; + } + if (!*end) + { + grub_device_t dev; + int ret; + dev = grub_device_open (hints[i]); + if (!dev) + { + *end = ','; + continue; + } + if (!dev->disk) + { + grub_device_close (dev); + *end = ','; + continue; + } + ret = grub_partition_iterate (dev->disk, part_hook); + *end = ','; + grub_device_close (dev); + if (ret) + return; + } + } + grub_device_iterate (iterate_device); + } + /* First try without autoloading if we're setting variable. */ if (var) { saved_autoload = grub_fs_autoload_hook; grub_fs_autoload_hook = 0; - grub_device_iterate (iterate_device); + try (); /* Restore autoload hook. */ grub_fs_autoload_hook = saved_autoload; /* Retry with autoload if nothing found. */ if (grub_errno == GRUB_ERR_NONE && count == 0) - grub_device_iterate (iterate_device); + try (); } else - grub_device_iterate (iterate_device); + try (); if (grub_errno == GRUB_ERR_NONE && count == 0) grub_error (GRUB_ERR_FILE_NOT_FOUND, "no such device: %s", key); @@ -142,7 +209,8 @@ grub_cmd_do_search (grub_command_t cmd __attribute__ ((unused)), int argc, if (argc == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, "no argument specified"); - FUNC_NAME (args[0], argc == 1 ? 0 : args[1], 0); + FUNC_NAME (args[0], argc == 1 ? 0 : args[1], 0, (args + 2), + argc > 2 ? argc - 2 : 0); return grub_errno; } @@ -159,7 +227,7 @@ GRUB_MOD_INIT(search_label) { cmd = grub_register_command (COMMAND_NAME, grub_cmd_do_search, - N_("NAME [VARIABLE]"), + N_("NAME [VARIABLE] [HINTS]"), HELP_MESSAGE); } diff --git a/grub-core/commands/search_wrap.c b/grub-core/commands/search_wrap.c index fff3fb47a..402421f65 100644 --- a/grub-core/commands/search_wrap.c +++ b/grub-core/commands/search_wrap.c @@ -37,6 +37,9 @@ static const struct grub_arg_option options[] = {"set", 's', GRUB_ARG_OPTION_OPTIONAL, N_("Set a variable to the first device found."), "VAR", ARG_TYPE_STRING}, {"no-floppy", 'n', 0, N_("Do not probe any floppy drive."), 0, 0}, + {"hint", 'h', GRUB_ARG_OPTION_REPEATABLE, + N_("First try the device HINT. If HINT ends in comma, " + "also try subpartitions"), N_("HINT"), ARG_TYPE_STRING}, {0, 0, 0, 0, 0, 0} }; @@ -47,6 +50,7 @@ enum options SEARCH_FS_UUID, SEARCH_SET, SEARCH_NO_FLOPPY, + SEARCH_HINT }; static grub_err_t @@ -54,6 +58,11 @@ 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; + + if (state[SEARCH_HINT].set) + while (state[SEARCH_HINT].args[nhints]) + nhints++; if (argc == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, "no argument specified"); @@ -62,11 +71,14 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args) var = state[SEARCH_SET].arg ? state[SEARCH_SET].arg : "root"; if (state[SEARCH_LABEL].set) - grub_search_label (args[0], var, state[SEARCH_NO_FLOPPY].set); + grub_search_label (args[0], var, state[SEARCH_NO_FLOPPY].set, + state[SEARCH_HINT].args, nhints); else if (state[SEARCH_FS_UUID].set) - grub_search_fs_uuid (args[0], var, state[SEARCH_NO_FLOPPY].set); + grub_search_fs_uuid (args[0], var, state[SEARCH_NO_FLOPPY].set, + state[SEARCH_HINT].args, nhints); else if (state[SEARCH_FILE].set) - grub_search_fs_file (args[0], var, state[SEARCH_NO_FLOPPY].set); + grub_search_fs_file (args[0], var, state[SEARCH_NO_FLOPPY].set, + state[SEARCH_HINT].args, nhints); else return grub_error (GRUB_ERR_INVALID_COMMAND, "unspecified search type"); @@ -78,9 +90,9 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(search) { cmd = - grub_register_extcmd ("search", grub_cmd_search, - GRUB_COMMAND_FLAG_BOTH, - N_("search [-f|-l|-u|-s|-n] NAME"), + grub_register_extcmd ("search", grub_cmd_search, 0, + N_("[-f|-l|-u|-s|-n] [--hint HINT [--hint HINT] ...]" + " NAME"), N_("Search devices by file, filesystem label" " or filesystem UUID." " If --set is specified, the first device found is" diff --git a/grub-core/commands/setpci.c b/grub-core/commands/setpci.c index 5e947cd7d..7b194ed17 100644 --- a/grub-core/commands/setpci.c +++ b/grub-core/commands/setpci.c @@ -329,7 +329,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(setpci) { - cmd = grub_register_extcmd ("setpci", grub_cmd_setpci, GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("setpci", grub_cmd_setpci, 0, N_("[-s POSITION] [-d DEVICE] [-v VAR] " "[REGISTER][=VALUE[:MASK]]"), N_("Manipulate PCI devices."), options); diff --git a/grub-core/commands/sleep.c b/grub-core/commands/sleep.c index ee0875cf7..da642fcd9 100644 --- a/grub-core/commands/sleep.c +++ b/grub-core/commands/sleep.c @@ -52,8 +52,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_TERM_ASCII_CHAR (grub_getkey ()) == GRUB_TERM_ESC) + if (grub_checkkey () >= 0 && grub_getkey () == GRUB_TERM_ESC) return 1; return 0; @@ -101,7 +100,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(sleep) { - cmd = grub_register_extcmd ("sleep", grub_cmd_sleep, GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("sleep", grub_cmd_sleep, 0, N_("NUMBER_OF_SECONDS"), N_("Wait for a specified number of seconds."), options); diff --git a/grub-core/commands/videoinfo.c b/grub-core/commands/videoinfo.c new file mode 100644 index 000000000..10f77915b --- /dev/null +++ b/grub-core/commands/videoinfo.c @@ -0,0 +1,184 @@ +/* videoinfo.c - command to list video modes. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2005,2007,2008,2009,2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +static unsigned height, width, depth; + +static int +hook (const struct grub_video_mode_info *info) +{ + if (height && width && (info->width != width || info->height != height)) + return 0; + + if (depth && info->bpp != depth) + return 0; + + if (info->mode_number == GRUB_VIDEO_MODE_NUMBER_INVALID) + grub_printf (" "); + else + grub_printf (" 0x%03x ", info->mode_number); + grub_printf ("%4d x %4d x %2d ", info->width, info->height, info->bpp); + + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT) + grub_printf ("Text-only "); + /* Show mask and position details for direct color modes. */ + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_RGB) + grub_printf ("Direct, mask: %d/%d/%d/%d pos: %d/%d/%d/%d", + info->red_mask_size, + info->green_mask_size, + info->blue_mask_size, + info->reserved_mask_size, + info->red_field_pos, + info->green_field_pos, + info->blue_field_pos, + info->reserved_field_pos); + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) + grub_printf ("Packed "); + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_YUV) + grub_printf ("YUV "); + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PLANAR) + grub_printf ("Planar "); + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_HERCULES) + grub_printf ("Hercules "); + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_CGA) + grub_printf ("CGA "); + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_NONCHAIN4) + grub_printf ("Non-chain 4 "); + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) + grub_printf ("Monochrome "); + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_UNKNOWN) + grub_printf ("Unknown "); + + grub_printf ("\n"); + + return 0; +} + +static grub_err_t +grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), + int argc, char **args) +{ + grub_video_adapter_t adapter; + grub_video_driver_id_t id; + + height = width = depth = 0; + if (argc) + { + char *ptr; + ptr = args[0]; + width = grub_strtoul (ptr, &ptr, 0); + if (grub_errno) + return grub_errno; + if (*ptr != 'x') + return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid mode specification"); + ptr++; + height = grub_strtoul (ptr, &ptr, 0); + if (grub_errno) + return grub_errno; + if (*ptr == 'x') + { + ptr++; + depth = grub_strtoul (ptr, &ptr, 0); + if (grub_errno) + return grub_errno; + } + } + +#ifdef GRUB_MACHINE_PCBIOS + if (grub_strcmp (cmd->name, "vbeinfo") == 0) + grub_dl_load ("vbe"); +#endif + + id = grub_video_get_driver_id (); + + grub_printf ("List of supported video modes:\n"); + grub_printf ("Legend: P=Packed pixel, D=Direct color, " + "mask/pos=R/G/B/reserved\n"); + + FOR_VIDEO_ADAPTERS (adapter) + { + grub_printf ("Adapter '%s':\n", adapter->name); + + if (!adapter->iterate) + { + grub_printf (" No info available\n"); + continue; + } + + if (adapter->id != id) + { + if (adapter->init ()) + { + grub_printf (" Failed\n"); + grub_errno = GRUB_ERR_NONE; + continue; + } + } + + if (adapter->print_adapter_specific_info) + adapter->print_adapter_specific_info (); + + adapter->iterate (hook); + + if (adapter->id != id) + { + if (adapter->fini ()) + { + grub_errno = GRUB_ERR_NONE; + continue; + } + } + } + return GRUB_ERR_NONE; +} + +static grub_command_t cmd; +#ifdef GRUB_MACHINE_PCBIOS +static grub_command_t cmd_vbe; +#endif + +GRUB_MOD_INIT(videoinfo) +{ + cmd = grub_register_command ("videoinfo", grub_cmd_videoinfo, "[WxH[xD]]", + N_("List available video modes. If " + "resolution is given show only modes" + " matching it.")); +#ifdef GRUB_MACHINE_PCBIOS + cmd_vbe = grub_register_command ("vbeinfo", grub_cmd_videoinfo, "[WxH[xD]]", + N_("List available video modes. If " + "resolution is given show only modes" + " matching it.")); +#endif +} + +GRUB_MOD_FINI(videoinfo) +{ + grub_unregister_command (cmd); +#ifdef GRUB_MACHINE_PCBIOS + grub_unregister_command (cmd_vbe); +#endif +} + diff --git a/grub-core/commands/videotest.c b/grub-core/commands/videotest.c index c544d1839..435ac2937 100644 --- a/grub-core/commands/videotest.c +++ b/grub-core/commands/videotest.c @@ -26,11 +26,11 @@ #include #include #include +#include static grub_err_t grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), - int argc __attribute__ ((unused)), - char **args __attribute__ ((unused))) + int argc, char **args) { grub_err_t err; grub_video_color_t color; @@ -41,8 +41,20 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), int i; struct grub_video_render_target *text_layer; grub_video_color_t palette[16]; + const char *mode = NULL; - err = grub_video_set_mode ("auto", GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0); +#ifdef GRUB_MACHINE_PCBIOS + if (grub_strcmp (cmd->name, "vbetest") == 0) + grub_dl_load ("vbe"); +#endif + + mode = grub_env_get ("gfxmode"); + if (argc) + mode = args[0]; + if (!mode) + mode = "auto"; + + err = grub_video_set_mode (mode, GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0); if (err) return err; @@ -180,14 +192,25 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), } static grub_command_t cmd; +#ifdef GRUB_MACHINE_PCBIOS +static grub_command_t cmd_vbe; +#endif GRUB_MOD_INIT(videotest) { cmd = grub_register_command ("videotest", grub_cmd_videotest, + "[WxH]", + N_("Test video subsystem in mode WxH.")); +#ifdef GRUB_MACHINE_PCBIOS + cmd_vbe = grub_register_command ("vbetest", grub_cmd_videotest, 0, N_("Test video subsystem.")); +#endif } GRUB_MOD_FINI(videotest) { grub_unregister_command (cmd); +#ifdef GRUB_MACHINE_PCBIOS + grub_unregister_command (cmd_vbe); +#endif } diff --git a/grub-core/commands/wildcard.c b/grub-core/commands/wildcard.c index cbe32e0ff..6eab333b3 100644 --- a/grub-core/commands/wildcard.c +++ b/grub-core/commands/wildcard.c @@ -137,8 +137,10 @@ make_regex (const char *start, const char *end, regex_t *regexp) break; case '.': + case '(': + case ')': buffer[i++] = '\\'; - buffer[i++] = '.'; + buffer[i++] = ch; break; case '*': @@ -152,6 +154,7 @@ make_regex (const char *start, const char *end, regex_t *regexp) } buffer[i++] = '$'; buffer[i] = '\0'; + grub_dprintf ("expand", "Regexp is %s\n", buffer); if (regcomp (regexp, buffer, RE_SYNTAX_GNU_AWK)) { @@ -224,6 +227,7 @@ match_devices (const regex_t *regexp, int noparts) grub_dprintf ("expand", "matching: %s\n", buffer); if (regexec (regexp, buffer, 0, 0, 0)) { + grub_dprintf ("expand", "not matched\n"); grub_free (buffer); return 0; } @@ -488,7 +492,7 @@ wildcard_expand (const char *s, char ***strs) for (i = 0; paths && paths[i]; i++) grub_free (paths[i]); - grub_free (paths[i]); + grub_free (paths); regfree (®exp); return grub_errno; } diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index cfd58a6d5..fe677e2a0 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -723,7 +723,6 @@ grub_ata_open (const char *name, grub_disk_t disk) disk->id = (unsigned long) dev; - disk->has_partitions = 1; disk->data = dev; return 0; diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c index f9c6f3153..7aec1efe8 100644 --- a/grub-core/disk/efi/efidisk.c +++ b/grub-core/disk/efi/efidisk.c @@ -514,16 +514,12 @@ grub_efidisk_open (const char *name, struct grub_disk *disk) switch (name[0]) { case 'f': - disk->has_partitions = 0; d = get_device (fd_devices, num); break; case 'c': - /* FIXME: a CDROM should have partitions, but not implemented yet. */ - disk->has_partitions = 0; d = get_device (cd_devices, num); break; case 'h': - disk->has_partitions = 1; d = get_device (hd_devices, num); break; default: diff --git a/grub-core/disk/host.c b/grub-core/disk/host.c index c4f3e7150..c51966293 100644 --- a/grub-core/disk/host.c +++ b/grub-core/disk/host.c @@ -43,7 +43,6 @@ grub_host_open (const char *name, grub_disk_t disk) disk->total_sectors = 0; disk->id = (unsigned long) "host"; - disk->has_partitions = 0; disk->data = 0; return GRUB_ERR_NONE; diff --git a/grub-core/disk/i386/pc/biosdisk.c b/grub-core/disk/i386/pc/biosdisk.c index 9c0209693..3f9015fb9 100644 --- a/grub-core/disk/i386/pc/biosdisk.c +++ b/grub-core/disk/i386/pc/biosdisk.c @@ -17,8 +17,8 @@ */ #include -#include #include +#include #include #include #include @@ -327,7 +327,6 @@ grub_biosdisk_open (const char *name, grub_disk_t disk) if (drive < 0) return grub_errno; - disk->has_partitions = 1; disk->id = drive; data = (struct grub_biosdisk_data *) grub_zalloc (sizeof (*data)); diff --git a/grub-core/disk/ieee1275/nand.c b/grub-core/disk/ieee1275/nand.c index df2ee81f3..a2c717cdb 100644 --- a/grub-core/disk/ieee1275/nand.c +++ b/grub-core/disk/ieee1275/nand.c @@ -113,7 +113,6 @@ grub_nand_open (const char *name, grub_disk_t disk) disk->id = dev_ihandle; - disk->has_partitions = 0; disk->data = data; return 0; diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c index d0d9e894f..85c34609e 100644 --- a/grub-core/disk/ieee1275/ofdisk.c +++ b/grub-core/disk/ieee1275/ofdisk.c @@ -23,9 +23,15 @@ #include #include +static char *last_devpath; +static grub_ieee1275_ihandle_t last_ihandle; + struct ofdisk_hash_ent { char *devpath; + /* Pointer to shortest available name on nodes representing canonical names, + otherwise NULL. */ + const char *shortest; struct ofdisk_hash_ent *next; }; @@ -59,60 +65,125 @@ static struct ofdisk_hash_ent * ofdisk_hash_add (char *devpath) { struct ofdisk_hash_ent **head = &ofdisk_hash[ofdisk_hash_fn(devpath)]; - struct ofdisk_hash_ent *p = grub_malloc(sizeof (*p)); + struct ofdisk_hash_ent *p, *pcan; + char *curcan; - if (p) + p = grub_malloc(sizeof (*p)); + if (!p) + return NULL; + + p->devpath = devpath; + p->next = *head; + p->shortest = 0; + *head = p; + + curcan = grub_ieee1275_canonicalise_devname (devpath); + if (!curcan) { - p->devpath = devpath; - p->next = *head; - *head = p; + grub_errno = GRUB_ERR_NONE; + return p; } + + pcan = ofdisk_hash_find (curcan); + if (!pcan) + pcan = ofdisk_hash_add (curcan); + else + grub_free (curcan); + + if (!pcan) + grub_errno = GRUB_ERR_NONE; + else + { + if (!pcan->shortest + || grub_strlen (pcan->shortest) > grub_strlen (devpath)) + pcan->shortest = devpath; + } + return p; } -static int -grub_ofdisk_iterate (int (*hook) (const char *name)) +static void +scan (void) { auto int dev_iterate (struct grub_ieee1275_devalias *alias); int dev_iterate (struct grub_ieee1275_devalias *alias) { - int ret = 0; + struct ofdisk_hash_ent *op; + + grub_dprintf ("disk", "device name = %s type = %s\n", alias->name, + alias->type); + + if (grub_strcmp (alias->type, "block") != 0) + return 0; grub_dprintf ("disk", "disk name = %s\n", alias->name); - if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY)) + op = ofdisk_hash_find (alias->path); + if (!op) { - grub_ieee1275_phandle_t dev; - char tmp[8]; - - if (grub_ieee1275_finddevice (alias->path, &dev)) + char *name = grub_strdup (alias->name); + if (!name) { - grub_dprintf ("disk", "finddevice (%s) failed\n", alias->path); - return 0; - } - - if (grub_ieee1275_get_property (dev, "iconname", tmp, - sizeof tmp, 0)) - { - grub_dprintf ("disk", "get iconname failed\n"); - return 0; - } - - if (grub_strcmp (tmp, "sdmmc")) - { - grub_dprintf ("disk", "device is not an SD card\n"); + grub_errno = GRUB_ERR_NONE; return 0; } + op = ofdisk_hash_add (name); } - - if (! grub_strcmp (alias->type, "block") && - grub_strncmp (alias->name, "cdrom", 5)) - ret = hook (alias->name); - return ret; + return 0; } - return grub_devalias_iterate (dev_iterate); + grub_devalias_iterate (dev_iterate); + grub_ieee1275_devices_iterate (dev_iterate); +} + +static int +grub_ofdisk_iterate (int (*hook) (const char *name)) +{ + unsigned i; + scan (); + + for (i = 0; i < ARRAY_SIZE (ofdisk_hash); i++) + { + static struct ofdisk_hash_ent *ent; + for (ent = ofdisk_hash[i]; ent; ent = ent->next) + { + if (!ent->shortest) + continue; + if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY)) + { + grub_ieee1275_phandle_t dev; + char tmp[8]; + + if (grub_ieee1275_finddevice (ent->devpath, &dev)) + { + grub_dprintf ("disk", "finddevice (%s) failed\n", + ent->devpath); + continue; + } + + if (grub_ieee1275_get_property (dev, "iconname", tmp, + sizeof tmp, 0)) + { + grub_dprintf ("disk", "get iconname failed\n"); + continue; + } + + if (grub_strcmp (tmp, "sdmmc") != 0) + { + grub_dprintf ("disk", "device is not an SD card\n"); + continue; + } + } + + if (grub_strncmp (ent->shortest, "cdrom", 5) == 0) + continue; + + if (hook (ent->shortest)) + return 1; + } + } + return 0; } static char * @@ -137,11 +208,6 @@ compute_dev_path (const char *name) *p++ = c; } - if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0)) - { - *p++ = ':'; - *p++ = '0'; - } *p++ = '\0'; return devpath; @@ -151,8 +217,6 @@ static grub_err_t grub_ofdisk_open (const char *name, grub_disk_t disk) { grub_ieee1275_phandle_t dev; - grub_ieee1275_ihandle_t dev_ihandle = 0; - struct ofdisk_hash_ent *op; char *devpath; /* XXX: This should be large enough for any possible case. */ char prop[64]; @@ -162,69 +226,50 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) if (! devpath) return grub_errno; - op = ofdisk_hash_find (devpath); - if (!op) - op = ofdisk_hash_add (devpath); + grub_dprintf ("disk", "Opening `%s'.\n", devpath); - grub_free (devpath); - if (!op) - return grub_errno; - - grub_dprintf ("disk", "Opening `%s'.\n", op->devpath); - - if (grub_ieee1275_finddevice (op->devpath, &dev)) - { - grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read device properties"); - goto fail; - } + if (grub_ieee1275_finddevice (devpath, &dev)) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read device properties"); if (grub_ieee1275_get_property (dev, "device_type", prop, sizeof (prop), &actual)) - { - grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read the device type"); - goto fail; - } + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read the device type"); if (grub_strcmp (prop, "block")) - { - grub_error (GRUB_ERR_BAD_DEVICE, "not a block device"); - goto fail; - } - - grub_ieee1275_open (op->devpath, &dev_ihandle); - if (! dev_ihandle) - { - grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); - goto fail; - } - - grub_dprintf ("disk", "Opened `%s' as handle %p.\n", op->devpath, - (void *) (unsigned long) dev_ihandle); + return grub_error (GRUB_ERR_BAD_DEVICE, "not a block device"); /* XXX: There is no property to read the number of blocks. There should be a property `#blocks', but it is not there. Perhaps it is possible to use seek for this. */ disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN; - disk->id = (unsigned long) op; + { + struct ofdisk_hash_ent *op; + op = ofdisk_hash_find (devpath); + if (!op) + op = ofdisk_hash_add (devpath); + else + grub_free (devpath); + if (!op) + return grub_errno; + disk->id = (unsigned long) op; + disk->data = op->devpath; + } - /* XXX: Read this, somehow. */ - disk->has_partitions = 1; - disk->data = (void *) (unsigned long) dev_ihandle; return 0; - - fail: - if (dev_ihandle) - grub_ieee1275_close (dev_ihandle); - return grub_errno; } static void grub_ofdisk_close (grub_disk_t disk) { - grub_dprintf ("disk", "Closing handle %p.\n", - (void *) disk->data); - grub_ieee1275_close ((grub_ieee1275_ihandle_t) (unsigned long) disk->data); + if (disk->data == last_devpath) + { + if (last_ihandle) + grub_ieee1275_close (last_ihandle); + last_ihandle = 0; + last_devpath = NULL; + } + disk->data = 0; } static grub_err_t @@ -234,16 +279,40 @@ grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector, grub_ssize_t status, actual; unsigned long long pos; + if (disk->data != last_devpath) + { + if (last_ihandle) + grub_ieee1275_close (last_ihandle); + last_ihandle = 0; + last_devpath = NULL; + + if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0)) + { + char name2[grub_strlen (disk->data) + 3]; + char *p; + + grub_strcpy (name2, disk->data); + p = name2 + grub_strlen (name2); + *p++ = ':'; + *p++ = '0'; + *p = 0; + grub_ieee1275_open (name2, &last_ihandle); + } + else + grub_ieee1275_open (disk->data, &last_ihandle); + if (! last_ihandle) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); + last_devpath = disk->data; + } + pos = sector * 512UL; - grub_ieee1275_seek ((grub_ieee1275_ihandle_t) (unsigned long) disk->data, - pos, &status); + grub_ieee1275_seek (last_ihandle, pos, &status); if (status < 0) return grub_error (GRUB_ERR_READ_ERROR, "seek error, can't seek block %llu", (long long) sector); - grub_ieee1275_read ((grub_ieee1275_ihandle_t) (unsigned long) disk->data, - buf, size * 512UL, &actual); + grub_ieee1275_read (last_ihandle, buf, size * 512UL, &actual); if (actual != (grub_ssize_t) (size * 512UL)) return grub_error (GRUB_ERR_READ_ERROR, "read error on block: %llu", (long long) sector); @@ -281,5 +350,10 @@ grub_ofdisk_init (void) void grub_ofdisk_fini (void) { + if (last_ihandle) + grub_ieee1275_close (last_ihandle); + last_ihandle = 0; + last_devpath = NULL; + grub_disk_dev_unregister (&grub_ofdisk_dev); } diff --git a/grub-core/disk/loopback.c b/grub-core/disk/loopback.c index 878369e5f..ae4cb9a9c 100644 --- a/grub-core/disk/loopback.c +++ b/grub-core/disk/loopback.c @@ -29,7 +29,6 @@ struct grub_loopback { char *devname; grub_file_t file; - int has_partitions; struct grub_loopback *next; }; @@ -38,7 +37,6 @@ static struct grub_loopback *loopback_list; static const struct grub_arg_option options[] = { {"delete", 'd', 0, N_("Delete the loopback device entry."), 0, 0}, - {"partitions", 'p', 0, N_("Simulate a hard drive with partitions."), 0, 0}, {0, 0, 0, 0, 0, 0} }; @@ -106,9 +104,6 @@ grub_cmd_loopback (grub_extcmd_context_t ctxt, int argc, char **args) grub_file_close (newdev->file); newdev->file = file; - /* Set has_partitions when `--partitions' was used. */ - newdev->has_partitions = state[1].set; - return 0; } @@ -126,9 +121,6 @@ grub_cmd_loopback (grub_extcmd_context_t ctxt, int argc, char **args) newdev->file = file; - /* Set has_partitions when `--partitions' was used. */ - newdev->has_partitions = state[1].set; - /* Add the new entry to the list. */ newdev->next = loopback_list; loopback_list = newdev; @@ -174,7 +166,6 @@ grub_loopback_open (const char *name, grub_disk_t disk) disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN; disk->id = (unsigned long) dev; - disk->has_partitions = dev->has_partitions; disk->data = dev->file; return 0; @@ -230,8 +221,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(loopback) { - cmd = grub_register_extcmd ("loopback", grub_cmd_loopback, - GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("loopback", grub_cmd_loopback, 0, N_("[-d|-p] DEVICENAME FILE."), N_("Make a device of a file."), options); grub_disk_dev_register (&grub_loopback_dev); diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c index 3981d9811..94cf9a1aa 100644 --- a/grub-core/disk/lvm.c +++ b/grub-core/disk/lvm.c @@ -150,7 +150,6 @@ grub_lvm_open (const char *name, grub_disk_t disk) if (! lv) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown LVM device %s", name); - disk->has_partitions = 0; disk->id = lv->number; disk->data = lv; disk->total_sectors = lv->size; @@ -280,7 +279,11 @@ grub_lvm_scan_device (const char *name) disk = grub_disk_open (name); if (!disk) - return 0; + { + if (grub_errno == GRUB_ERR_OUT_OF_RANGE) + grub_errno = GRUB_ERR_NONE; + return 0; + } /* Search for label. */ for (i = 0; i < GRUB_LVM_LABEL_SCAN_SECTORS; i++) @@ -725,6 +728,8 @@ grub_lvm_scan_device (const char *name) grub_free (metadatabuf); fail: grub_disk_close (disk); + if (grub_errno == GRUB_ERR_OUT_OF_RANGE) + grub_errno = GRUB_ERR_NONE; return 0; } diff --git a/grub-core/disk/memdisk.c b/grub-core/disk/memdisk.c index 2e8885020..e00280dd7 100644 --- a/grub-core/disk/memdisk.c +++ b/grub-core/disk/memdisk.c @@ -41,7 +41,6 @@ grub_memdisk_open (const char *name, grub_disk_t disk) disk->total_sectors = memdisk_size / GRUB_DISK_SECTOR_SIZE; disk->id = (unsigned long) "mdsk"; - disk->has_partitions = 0; return GRUB_ERR_NONE; } diff --git a/grub-core/disk/raid.c b/grub-core/disk/raid.c index 51a4b00e2..2fd6aa9de 100644 --- a/grub-core/disk/raid.c +++ b/grub-core/disk/raid.c @@ -126,7 +126,6 @@ grub_raid_open (const char *name, grub_disk_t disk) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown RAID device %s", name); - disk->has_partitions = 1; disk->id = array->number; disk->data = array; diff --git a/grub-core/disk/scsi.c b/grub-core/disk/scsi.c index 60192bef5..902ab12c3 100644 --- a/grub-core/disk/scsi.c +++ b/grub-core/disk/scsi.c @@ -431,12 +431,6 @@ grub_scsi_open (const char *name, grub_disk_t disk) "unknown SCSI device"); } - if (scsi->devtype == grub_scsi_devtype_cdrom) - disk->has_partitions = 0; - else - disk->has_partitions = 1; - - /* According to USB MS tests specification, issue Test Unit Ready * until OK */ maxtime = grub_get_time_ms () + 5000; /* It is safer value */ diff --git a/grub-core/efiemu/mm.c b/grub-core/efiemu/mm.c index de7d309be..3c1dc2946 100644 --- a/grub-core/efiemu/mm.c +++ b/grub-core/efiemu/mm.c @@ -29,8 +29,8 @@ #include #include #include -#include #include +#include struct grub_efiemu_memrequest { @@ -269,10 +269,11 @@ static grub_err_t grub_efiemu_mmap_init (void) { auto int NESTED_FUNC_ATTR bounds_hook (grub_uint64_t, grub_uint64_t, - grub_uint32_t); + grub_memory_type_t); int NESTED_FUNC_ATTR bounds_hook (grub_uint64_t addr __attribute__ ((unused)), grub_uint64_t size __attribute__ ((unused)), - grub_uint32_t type __attribute__ ((unused))) + grub_memory_type_t type + __attribute__ ((unused))) { mmap_reserved_size++; return 0; @@ -382,32 +383,29 @@ grub_efiemu_mm_init (void) static grub_err_t grub_efiemu_mmap_fill (void) { - auto int NESTED_FUNC_ATTR fill_hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + auto int NESTED_FUNC_ATTR fill_hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); int NESTED_FUNC_ATTR fill_hook (grub_uint64_t addr, grub_uint64_t size, - grub_uint32_t type) + grub_memory_type_t type) { switch (type) { - case GRUB_MACHINE_MEMORY_AVAILABLE: + case GRUB_MEMORY_AVAILABLE: return grub_efiemu_add_to_mmap (addr, size, GRUB_EFI_CONVENTIONAL_MEMORY); -#ifdef GRUB_MACHINE_MEMORY_ACPI - case GRUB_MACHINE_MEMORY_ACPI: + case GRUB_MEMORY_ACPI: return grub_efiemu_add_to_mmap (addr, size, GRUB_EFI_ACPI_RECLAIM_MEMORY); -#endif -#ifdef GRUB_MACHINE_MEMORY_NVS - case GRUB_MACHINE_MEMORY_NVS: + case GRUB_MEMORY_NVS: return grub_efiemu_add_to_mmap (addr, size, GRUB_EFI_ACPI_MEMORY_NVS); -#endif default: - grub_printf ("Unknown memory type %d. Marking as unusable\n", type); - case GRUB_MACHINE_MEMORY_RESERVED: + grub_printf ("Unknown memory type %d. Assuming unusable\n", type); + case GRUB_MEMORY_RESERVED: return grub_efiemu_add_to_mmap (addr, size, GRUB_EFI_UNUSABLE_MEMORY); } @@ -421,9 +419,7 @@ grub_efiemu_mmap_fill (void) } grub_err_t -grub_efiemu_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, - grub_uint64_t, - grub_uint32_t)) +grub_efiemu_mmap_iterate (grub_memory_hook_t hook) { unsigned i; @@ -432,18 +428,22 @@ grub_efiemu_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, { case GRUB_EFI_RUNTIME_SERVICES_CODE: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_EFIEMU_MEMORY_CODE); + GRUB_MEMORY_CODE); + break; + + case GRUB_EFI_UNUSABLE_MEMORY: + hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, + GRUB_MEMORY_BADRAM); break; case GRUB_EFI_RESERVED_MEMORY_TYPE: case GRUB_EFI_RUNTIME_SERVICES_DATA: - case GRUB_EFI_UNUSABLE_MEMORY: case GRUB_EFI_MEMORY_MAPPED_IO: case GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE: case GRUB_EFI_PAL_CODE: case GRUB_EFI_MAX_MEMORY_TYPE: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_EFIEMU_MEMORY_RESERVED); + GRUB_MEMORY_RESERVED); break; case GRUB_EFI_LOADER_CODE: @@ -452,17 +452,17 @@ grub_efiemu_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, case GRUB_EFI_BOOT_SERVICES_DATA: case GRUB_EFI_CONVENTIONAL_MEMORY: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_EFIEMU_MEMORY_AVAILABLE); + GRUB_MEMORY_AVAILABLE); break; case GRUB_EFI_ACPI_RECLAIM_MEMORY: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_EFIEMU_MEMORY_ACPI); + GRUB_MEMORY_ACPI); break; case GRUB_EFI_ACPI_MEMORY_NVS: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_EFIEMU_MEMORY_NVS); + GRUB_MEMORY_NVS); break; } diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c new file mode 100644 index 000000000..a50bae000 --- /dev/null +++ b/grub-core/fs/btrfs.c @@ -0,0 +1,132 @@ +/* btrfs.c - B-tree file system. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +#define BTRFS_SIGNATURE "_BHRfS_M" + +struct btrfs_superblock +{ + grub_uint8_t dummy1[32]; + grub_uint16_t uuid[8]; + grub_uint8_t dummy2[16]; + grub_uint8_t signature[sizeof (BTRFS_SIGNATURE) - 1]; +} __attribute__ ((packed)); + +struct grub_btrfs_data +{ + struct btrfs_superblock sblock; +}; + +static struct grub_btrfs_data * +grub_btrfs_mount (grub_disk_t disk) +{ + struct grub_btrfs_data *data = grub_malloc (sizeof (*data)); + if (! data) + return NULL; + + if (grub_disk_read (disk, 128, 0, sizeof (data->sblock), + &data->sblock) != GRUB_ERR_NONE) + goto fail; + + if (grub_strncmp ((char *) data->sblock.signature, BTRFS_SIGNATURE, sizeof (BTRFS_SIGNATURE) - 1)) + { + grub_error (GRUB_ERR_BAD_FS, "not a Btrfs filesystem"); + goto fail; + } + + return data; + + fail: + grub_free (data); + return NULL; +} + +static grub_err_t +grub_btrfs_open (struct grub_file *file __attribute__ ((unused)), + const char *name __attribute__ ((unused))) +{ + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "only detection is supported for Btrfs"); +} + +static grub_err_t +grub_btrfs_dir (grub_device_t device, + const char *path __attribute__ ((unused)), + int (*hook) (const char *filename, + const struct grub_dirhook_info *info) + __attribute__ ((unused))) +{ + struct grub_btrfs_data *data = grub_btrfs_mount (device->disk); + if (grub_errno) + return grub_errno; + + grub_free (data); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_btrfs_uuid (grub_device_t device, char **uuid) +{ + struct grub_btrfs_data *data; + + *uuid = NULL; + + data = grub_btrfs_mount (device->disk); + if (! data) + return grub_errno; + + *uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x", + grub_be_to_cpu16 (data->sblock.uuid[0]), + grub_be_to_cpu16 (data->sblock.uuid[1]), + grub_be_to_cpu16 (data->sblock.uuid[2]), + grub_be_to_cpu16 (data->sblock.uuid[3]), + grub_be_to_cpu16 (data->sblock.uuid[4]), + grub_be_to_cpu16 (data->sblock.uuid[5]), + grub_be_to_cpu16 (data->sblock.uuid[6]), + grub_be_to_cpu16 (data->sblock.uuid[7])); + + grub_free (data); + + return grub_errno; +} + +static struct grub_fs grub_btrfs_fs = + { + .name = "btrfs", + .dir = grub_btrfs_dir, + .open = grub_btrfs_open, + .uuid = grub_btrfs_uuid, + }; + +GRUB_MOD_INIT(btrfs) +{ + grub_fs_register (&grub_btrfs_fs); +} + +GRUB_MOD_FINI(btrfs) +{ + grub_fs_unregister (&grub_btrfs_fs); +} diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c index f2fec828a..dfc75c625 100644 --- a/grub-core/fs/ext2.c +++ b/grub-core/fs/ext2.c @@ -728,22 +728,27 @@ grub_ext2_open (struct grub_file *file, const char *name) { struct grub_ext2_data *data; struct grub_fshelp_node *fdiro = 0; + grub_err_t err; grub_dl_ref (my_mod); data = grub_ext2_mount (file->device->disk); if (! data) - goto fail; + { + err = grub_errno; + goto fail; + } - grub_fshelp_find_file (name, &data->diropen, &fdiro, grub_ext2_iterate_dir, - grub_ext2_read_symlink, GRUB_FSHELP_REG); - if (grub_errno) + err = grub_fshelp_find_file (name, &data->diropen, &fdiro, + grub_ext2_iterate_dir, + grub_ext2_read_symlink, GRUB_FSHELP_REG); + if (err) goto fail; if (! fdiro->inode_read) { - grub_ext2_read_inode (data, fdiro->ino, &fdiro->inode); - if (grub_errno) + err = grub_ext2_read_inode (data, fdiro->ino, &fdiro->inode); + if (err) goto fail; } @@ -763,7 +768,7 @@ grub_ext2_open (struct grub_file *file, const char *name) grub_dl_unref (my_mod); - return grub_errno; + return err; } static grub_err_t diff --git a/grub-core/fs/i386/pc/pxe.c b/grub-core/fs/i386/pc/pxe.c index baaff0ffc..cbb3c7d87 100644 --- a/grub-core/fs/i386/pc/pxe.c +++ b/grub-core/fs/i386/pc/pxe.c @@ -176,7 +176,6 @@ grub_pxe_open (const char *name, grub_disk_t disk) disk->total_sectors = 0; disk->id = (unsigned long) data; - disk->has_partitions = 0; disk->data = data; return GRUB_ERR_NONE; diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c index a856e38c4..aa5b9a0c9 100644 --- a/grub-core/fs/minix.c +++ b/grub-core/fs/minix.c @@ -25,10 +25,13 @@ #include #include +#ifdef MODE_MINIX2 +#define GRUB_MINIX_MAGIC 0x2468 +#define GRUB_MINIX_MAGIC_30 0x2478 +#else #define GRUB_MINIX_MAGIC 0x137F -#define GRUB_MINIX2_MAGIC 0x2468 #define GRUB_MINIX_MAGIC_30 0x138F -#define GRUB_MINIX2_MAGIC_30 0x2478 +#endif #define GRUB_MINIX_BSIZE 1024U #define GRUB_MINIX_LOG2_BSIZE 1 #define GRUB_MINIX_ROOT_INODE 1 @@ -38,20 +41,25 @@ #define GRUB_MINIX_IFDIR 0040000U #define GRUB_MINIX_IFLNK 0120000U -#define GRUB_MINIX_INODE(data,field) (data->version == 1 ? \ - data->inode. field : data->inode2. field) -#define GRUB_MINIX_INODE_ENDIAN(data,field,bits1,bits2) (data->version == 1 ? \ - grub_le_to_cpu##bits1 (data->inode.field) : \ - grub_le_to_cpu##bits2 (data->inode2.field)) -#define GRUB_MINIX_INODE_SIZE(data) GRUB_MINIX_INODE_ENDIAN (data,size,16,32) -#define GRUB_MINIX_INODE_MODE(data) GRUB_MINIX_INODE_ENDIAN (data,mode,16,16) -#define GRUB_MINIX_INODE_DIR_ZONES(data,blk) GRUB_MINIX_INODE_ENDIAN \ - (data,dir_zones[blk],16,32) -#define GRUB_MINIX_INODE_INDIR_ZONE(data) \ - GRUB_MINIX_INODE_ENDIAN (data,indir_zone,16,32) -#define GRUB_MINIX_INODE_DINDIR_ZONE(data) \ - GRUB_MINIX_INODE_ENDIAN (data,double_indir_zone,16,32) -#define GRUB_MINIX_INODE_BLKSZ(data) (data->version == 1 ? 2 : 4) +#ifdef MODE_MINIX2 +typedef grub_uint32_t grub_minix_uintn_t; +#define grub_minix_le_to_cpu_n grub_le_to_cpu32 +#else +typedef grub_uint16_t grub_minix_uintn_t; +#define grub_minix_le_to_cpu_n grub_le_to_cpu16 +#endif + +#define GRUB_MINIX_INODE_BLKSZ(data) sizeof (grub_minix_uintn_t) + +#define GRUB_MINIX_INODE_SIZE(data) (grub_minix_le_to_cpu_n (data->inode.size)) +#define GRUB_MINIX_INODE_MODE(data) (grub_le_to_cpu16 (data->inode.mode)) +#define GRUB_MINIX_INODE_DIR_ZONES(data,blk) (grub_minix_le_to_cpu_n \ + (data->inode.dir_zones[blk])) +#define GRUB_MINIX_INODE_INDIR_ZONE(data) (grub_minix_le_to_cpu_n \ + (data->inode.indir_zone)) +#define GRUB_MINIX_INODE_DINDIR_ZONE(data) (grub_minix_le_to_cpu_n \ + (data->inode.double_indir_zone)) + #define GRUB_MINIX_LOG2_ZONESZ (GRUB_MINIX_LOG2_BSIZE \ + grub_le_to_cpu16 (sblock->log2_zone_size)) #define GRUB_MINIX_ZONESZ (GRUB_MINIX_BSIZE \ @@ -69,6 +77,7 @@ struct grub_minix_sblock grub_uint16_t magic; }; +#ifndef MODE_MINIX2 struct grub_minix_inode { grub_uint16_t mode; @@ -82,7 +91,9 @@ struct grub_minix_inode grub_uint16_t double_indir_zone; }; -struct grub_minix2_inode +#else + +struct grub_minix_inode { grub_uint16_t mode; grub_uint16_t nlinks; @@ -99,16 +110,16 @@ struct grub_minix2_inode }; +#endif + /* Information about a "mounted" minix filesystem. */ struct grub_minix_data { struct grub_minix_sblock sblock; struct grub_minix_inode inode; - struct grub_minix2_inode inode2; int ino; int linknest; grub_disk_t disk; - int version; int filename_size; }; @@ -128,24 +139,12 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk) /* Read the block pointer in ZONE, on the offset NUM. */ int grub_get_indir (int zone, int num) { - if (data->version == 1) - { - grub_uint16_t indir16; - grub_disk_read (data->disk, - zone << GRUB_MINIX_LOG2_ZONESZ, - sizeof (grub_uint16_t) * num, - sizeof (grub_uint16_t), (char *) &indir16); - return grub_le_to_cpu16 (indir16); - } - else - { - grub_uint32_t indir32; - grub_disk_read (data->disk, - zone << GRUB_MINIX_LOG2_ZONESZ, - sizeof (grub_uint32_t) * num, - sizeof (grub_uint32_t), (char *) &indir32); - return grub_le_to_cpu32 (indir32); - } + grub_minix_uintn_t indirn; + grub_disk_read (data->disk, + zone << GRUB_MINIX_LOG2_ZONESZ, + sizeof (grub_minix_uintn_t) * num, + sizeof (grub_minix_uintn_t), (char *) &indirn); + return grub_minix_le_to_cpu_n (indirn); } /* Direct block. */ @@ -259,27 +258,13 @@ grub_minix_read_inode (struct grub_minix_data *data, int ino) + grub_le_to_cpu16 (sblock->zone_bmap_size)) << GRUB_MINIX_LOG2_BSIZE); - if (data->version == 1) - { - block += ino / (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode)); - int offs = (ino % (GRUB_DISK_SECTOR_SIZE - / sizeof (struct grub_minix_inode)) - * sizeof (struct grub_minix_inode)); - - grub_disk_read (data->disk, block, offs, - sizeof (struct grub_minix_inode), &data->inode); - } - else - { - block += ino / (GRUB_DISK_SECTOR_SIZE - / sizeof (struct grub_minix2_inode)); - int offs = (ino - % (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix2_inode)) - * sizeof (struct grub_minix2_inode)); - - grub_disk_read (data->disk, block, offs, - sizeof (struct grub_minix2_inode),&data->inode2); - } + block += ino / (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode)); + int offs = (ino % (GRUB_DISK_SECTOR_SIZE + / sizeof (struct grub_minix_inode)) + * sizeof (struct grub_minix_inode)); + + grub_disk_read (data->disk, block, offs, + sizeof (struct grub_minix_inode), &data->inode); return GRUB_ERR_NONE; } @@ -424,25 +409,9 @@ grub_minix_mount (grub_disk_t disk) goto fail; if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX_MAGIC) - { - data->version = 1; - data->filename_size = 14; - } - else if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX2_MAGIC) - { - data->version = 2; - data->filename_size = 14; - } + data->filename_size = 14; else if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX_MAGIC_30) - { - data->version = 1; - data->filename_size = 30; - } - else if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX2_MAGIC_30) - { - data->version = 2; - data->filename_size = 30; - } + data->filename_size = 30; else goto fail; @@ -453,7 +422,11 @@ grub_minix_mount (grub_disk_t disk) fail: grub_free (data); +#ifdef MODE_MINIX2 + grub_error (GRUB_ERR_BAD_FS, "not a minix2 filesystem"); +#else grub_error (GRUB_ERR_BAD_FS, "not a minix filesystem"); +#endif return 0; } @@ -583,32 +556,36 @@ grub_minix_close (grub_file_t file) } -static grub_err_t -grub_minix_label (grub_device_t device __attribute ((unused)), - char **label __attribute ((unused))) -{ - return GRUB_ERR_NONE; -} - static struct grub_fs grub_minix_fs = { +#ifdef MODE_MINIX2 + .name = "minix2", +#else .name = "minix", +#endif .dir = grub_minix_dir, .open = grub_minix_open, .read = grub_minix_read, .close = grub_minix_close, - .label = grub_minix_label, .next = 0 }; +#ifdef MODE_MINIX2 +GRUB_MOD_INIT(minix2) +#else GRUB_MOD_INIT(minix) +#endif { grub_fs_register (&grub_minix_fs); my_mod = mod; } +#ifdef MODE_MINIX2 +GRUB_MOD_FINI(minix2) +#else GRUB_MOD_FINI(minix) +#endif { grub_fs_unregister (&grub_minix_fs); } diff --git a/grub-core/fs/minix2.c b/grub-core/fs/minix2.c new file mode 100644 index 000000000..0fcd4b139 --- /dev/null +++ b/grub-core/fs/minix2.c @@ -0,0 +1,2 @@ +#define MODE_MINIX2 1 +#include "minix.c" diff --git a/grub-core/gnulib/basename-lgpl.c b/grub-core/gnulib/basename-lgpl.c new file mode 100644 index 000000000..a35ff01c2 --- /dev/null +++ b/grub-core/gnulib/basename-lgpl.c @@ -0,0 +1,75 @@ +/* basename.c -- return the last element in a file name + + Copyright (C) 1990, 1998-2001, 2003-2006, 2009-2010 Free Software + Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include "dirname.h" + +#include + +/* Return the address of the last file name component of NAME. If + NAME has no relative file name components because it is a file + system root, return the empty string. */ + +char * +last_component (char const *name) +{ + char const *base = name + FILE_SYSTEM_PREFIX_LEN (name); + char const *p; + bool saw_slash = false; + + while (ISSLASH (*base)) + base++; + + for (p = base; *p; p++) + { + if (ISSLASH (*p)) + saw_slash = true; + else if (saw_slash) + { + base = p; + saw_slash = false; + } + } + + return (char *) base; +} + +/* Return the length of the basename NAME. Typically NAME is the + value returned by base_name or last_component. Act like strlen + (NAME), except omit all trailing slashes. */ + +size_t +base_len (char const *name) +{ + size_t len; + size_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name); + + for (len = strlen (name); 1 < len && ISSLASH (name[len - 1]); len--) + continue; + + if (DOUBLE_SLASH_IS_DISTINCT_ROOT && len == 1 + && ISSLASH (name[0]) && ISSLASH (name[1]) && ! name[2]) + return 2; + + if (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE && prefix_len + && len == prefix_len && ISSLASH (name[prefix_len])) + return prefix_len + 1; + + return len; +} diff --git a/grub-core/gnulib/basename.c b/grub-core/gnulib/basename.c new file mode 100644 index 000000000..24da93ac4 --- /dev/null +++ b/grub-core/gnulib/basename.c @@ -0,0 +1,58 @@ +/* basename.c -- return the last element in a file name + + Copyright (C) 1990, 1998-2001, 2003-2006, 2009-2010 Free Software + Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include "dirname.h" + +#include +#include "xalloc.h" +#include "xstrndup.h" + +char * +base_name (char const *name) +{ + char const *base = last_component (name); + size_t length; + + /* If there is no last component, then name is a file system root or the + empty string. */ + if (! *base) + return xstrndup (name, base_len (name)); + + /* Collapse a sequence of trailing slashes into one. */ + length = base_len (base); + if (ISSLASH (base[length])) + length++; + + /* On systems with drive letters, `a/b:c' must return `./b:c' rather + than `b:c' to avoid confusion with a drive letter. On systems + with pure POSIX semantics, this is not an issue. */ + if (FILE_SYSTEM_PREFIX_LEN (base)) + { + char *p = xmalloc (length + 3); + p[0] = '.'; + p[1] = '/'; + memcpy (p + 2, base, length); + p[length + 2] = '\0'; + return p; + } + + /* Finally, copy the basename. */ + return xstrndup (base, length); +} diff --git a/grub-core/gnulib/dirname-lgpl.c b/grub-core/gnulib/dirname-lgpl.c new file mode 100644 index 000000000..d4506e060 --- /dev/null +++ b/grub-core/gnulib/dirname-lgpl.c @@ -0,0 +1,86 @@ +/* dirname.c -- return all but the last element in a file name + + Copyright (C) 1990, 1998, 2000-2001, 2003-2006, 2009-2010 Free Software + Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include "dirname.h" + +#include +#include + +/* Return the length of the prefix of FILE that will be used by + dir_name. If FILE is in the working directory, this returns zero + even though `dir_name (FILE)' will return ".". Works properly even + if there are trailing slashes (by effectively ignoring them). */ + +size_t +dir_len (char const *file) +{ + size_t prefix_length = FILE_SYSTEM_PREFIX_LEN (file); + size_t length; + + /* Advance prefix_length beyond important leading slashes. */ + prefix_length += (prefix_length != 0 + ? (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE + && ISSLASH (file[prefix_length])) + : (ISSLASH (file[0]) + ? ((DOUBLE_SLASH_IS_DISTINCT_ROOT + && ISSLASH (file[1]) && ! ISSLASH (file[2]) + ? 2 : 1)) + : 0)); + + /* Strip the basename and any redundant slashes before it. */ + for (length = last_component (file) - file; + prefix_length < length; length--) + if (! ISSLASH (file[length - 1])) + break; + return length; +} + + +/* In general, we can't use the builtin `dirname' function if available, + since it has different meanings in different environments. + In some environments the builtin `dirname' modifies its argument. + + Return the leading directories part of FILE, allocated with malloc. + Works properly even if there are trailing slashes (by effectively + ignoring them). Return NULL on failure. + + If lstat (FILE) would succeed, then { chdir (dir_name (FILE)); + lstat (base_name (FILE)); } will access the same file. Likewise, + if the sequence { chdir (dir_name (FILE)); + rename (base_name (FILE), "foo"); } succeeds, you have renamed FILE + to "foo" in the same directory FILE was in. */ + +char * +mdir_name (char const *file) +{ + size_t length = dir_len (file); + bool append_dot = (length == 0 + || (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE + && length == FILE_SYSTEM_PREFIX_LEN (file) + && file[2] != '\0' && ! ISSLASH (file[2]))); + char *dir = malloc (length + append_dot + 1); + if (!dir) + return NULL; + memcpy (dir, file, length); + if (append_dot) + dir[length++] = '.'; + dir[length] = '\0'; + return dir; +} diff --git a/grub-core/gnulib/dirname.c b/grub-core/gnulib/dirname.c new file mode 100644 index 000000000..953a9acc3 --- /dev/null +++ b/grub-core/gnulib/dirname.c @@ -0,0 +1,38 @@ +/* dirname.c -- return all but the last element in a file name + + Copyright (C) 1990, 1998, 2000-2001, 2003-2006, 2009-2010 Free Software + Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include "dirname.h" + +#include +#include +#include "xalloc.h" + +/* Just like mdir_name (dirname-lgpl.c), except, rather than + returning NULL upon malloc failure, here, we report the + "memory exhausted" condition and exit. */ + +char * +dir_name (char const *file) +{ + char *result = mdir_name (file); + if (!result) + xalloc_die (); + return result; +} diff --git a/grub-core/gnulib/dirname.h b/grub-core/gnulib/dirname.h new file mode 100644 index 000000000..fb19508f7 --- /dev/null +++ b/grub-core/gnulib/dirname.h @@ -0,0 +1,74 @@ +/* Take file names apart into directory and base names. + + Copyright (C) 1998, 2001, 2003-2006, 2009-2010 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef DIRNAME_H_ +# define DIRNAME_H_ 1 + +# include +# include + +# ifndef DIRECTORY_SEPARATOR +# define DIRECTORY_SEPARATOR '/' +# endif + +# ifndef ISSLASH +# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR) +# endif + +# ifndef FILE_SYSTEM_PREFIX_LEN +# if FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX + /* This internal macro assumes ASCII, but all hosts that support drive + letters use ASCII. */ +# define _IS_DRIVE_LETTER(c) (((unsigned int) (c) | ('a' - 'A')) - 'a' \ + <= 'z' - 'a') +# define FILE_SYSTEM_PREFIX_LEN(Filename) \ + (_IS_DRIVE_LETTER ((Filename)[0]) && (Filename)[1] == ':' ? 2 : 0) +# else +# define FILE_SYSTEM_PREFIX_LEN(Filename) 0 +# endif +# endif + +# ifndef FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE +# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0 +# endif + +# ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT +# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0 +# endif + +# if FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE +# define IS_ABSOLUTE_FILE_NAME(F) ISSLASH ((F)[FILE_SYSTEM_PREFIX_LEN (F)]) +# else +# define IS_ABSOLUTE_FILE_NAME(F) \ + (ISSLASH ((F)[0]) || 0 < FILE_SYSTEM_PREFIX_LEN (F)) +# endif +# define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F)) + +# if GNULIB_DIRNAME +char *base_name (char const *file); +char *dir_name (char const *file); +# endif + +char *mdir_name (char const *file); +size_t base_len (char const *file); +size_t dir_len (char const *file); +char *last_component (char const *file); + +bool strip_trailing_slashes (char *file); + +#endif /* not DIRNAME_H_ */ diff --git a/grub-core/gnulib/error.c b/grub-core/gnulib/error.c index c79e8d42c..ed9dba0d2 100644 --- a/grub-core/gnulib/error.c +++ b/grub-core/gnulib/error.c @@ -88,6 +88,15 @@ extern void __error_at_line (int status, int errnum, const char *file_name, # include # include +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +/* Get declarations of the Win32 API functions. */ +# define WIN32_LEAN_AND_MEAN +# include +# endif + +/* The gnulib override of fcntl is not needed in this file. */ +# undef fcntl + # if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P # ifndef HAVE_DECL_STRERROR_R "this configure-time declaration test was not run" @@ -104,10 +113,29 @@ extern char *program_name; # endif /* HAVE_STRERROR_R || defined strerror_r */ #endif /* not _LIBC */ +#if !_LIBC +/* Return non-zero if FD is open. */ +static inline int +is_open (int fd) +{ +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + /* On Win32: The initial state of unassigned standard file descriptors is + that they are open but point to an INVALID_HANDLE_VALUE. There is no + fcntl, and the gnulib replacement fcntl does not support F_GETFL. */ + return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE; +# else +# ifndef F_GETFL +# error Please port fcntl to your platform +# endif + return 0 <= fcntl (fd, F_GETFL); +# endif +} +#endif + static inline void flush_stdout (void) { -#if !_LIBC && defined F_GETFL +#if !_LIBC int stdout_fd; # if GNULIB_FREOPEN_SAFER @@ -124,7 +152,7 @@ flush_stdout (void) /* POSIX states that fflush (stdout) after fclose is unspecified; it is safe in glibc, but not on all other platforms. fflush (NULL) is always defined, but too draconian. */ - if (0 <= stdout_fd && 0 <= fcntl (stdout_fd, F_GETFL)) + if (0 <= stdout_fd && is_open (stdout_fd)) #endif fflush (stdout); } diff --git a/grub-core/gnulib/getopt.c b/grub-core/gnulib/getopt.c index aaabc8d19..3791f1293 100644 --- a/grub-core/gnulib/getopt.c +++ b/grub-core/gnulib/getopt.c @@ -348,8 +348,6 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, int long_only, struct _getopt_data *d, int posixly_correct) { int print_errors = d->opterr; - if (optstring[0] == ':') - print_errors = 0; if (argc < 1) return -1; @@ -364,6 +362,10 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, posixly_correct); d->__initialized = 1; } + else if (optstring[0] == '-' || optstring[0] == '+') + optstring++; + if (optstring[0] == ':') + print_errors = 0; /* Test whether ARGV[optind] points to a non-option argument. Either it does not have option syntax, or there is an environment flag @@ -633,8 +635,8 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, char *buf; if (__asprintf (&buf, _("\ -%s: option '%s' requires an argument\n"), - argv[0], argv[d->optind - 1]) >= 0) +%s: option '--%s' requires an argument\n"), + argv[0], pfound->name) >= 0) { _IO_flockfile (stderr); @@ -651,8 +653,8 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, } #else fprintf (stderr, - _("%s: option '%s' requires an argument\n"), - argv[0], argv[d->optind - 1]); + _("%s: option '--%s' requires an argument\n"), + argv[0], pfound->name); #endif } d->__nextchar += strlen (d->__nextchar); @@ -736,13 +738,13 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, { char c = *d->__nextchar++; - char *temp = strchr (optstring, c); + const char *temp = strchr (optstring, c); /* Increment `optind' when we start to process its last character. */ if (*d->__nextchar == '\0') ++d->optind; - if (temp == NULL || c == ':') + if (temp == NULL || c == ':' || c == ';') { if (print_errors) { @@ -864,7 +866,10 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, pfound = p; indfound = option_index; } - else + else if (long_only + || pfound->has_arg != p->has_arg + || pfound->flag != p->flag + || pfound->val != p->val) /* Second or later nonexact match found. */ ambig = 1; } @@ -876,7 +881,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, char *buf; if (__asprintf (&buf, _("%s: option '-W %s' is ambiguous\n"), - argv[0], argv[d->optind]) >= 0) + argv[0], d->optarg) >= 0) { _IO_flockfile (stderr); @@ -892,7 +897,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, } #else fprintf (stderr, _("%s: option '-W %s' is ambiguous\n"), - argv[0], argv[d->optind]); + argv[0], d->optarg); #endif } d->__nextchar += strlen (d->__nextchar); @@ -955,8 +960,8 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, char *buf; if (__asprintf (&buf, _("\ -%s: option '%s' requires an argument\n"), - argv[0], argv[d->optind - 1]) >= 0) +%s: option '-W %s' requires an argument\n"), + argv[0], pfound->name) >= 0) { _IO_flockfile (stderr); @@ -972,15 +977,17 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, free (buf); } #else - fprintf (stderr, - _("%s: option '%s' requires an argument\n"), - argv[0], argv[d->optind - 1]); + fprintf (stderr, _("\ +%s: option '-W %s' requires an argument\n"), + argv[0], pfound->name); #endif } d->__nextchar += strlen (d->__nextchar); return optstring[0] == ':' ? ':' : '?'; } } + else + d->optarg = NULL; d->__nextchar += strlen (d->__nextchar); if (longind != NULL) *longind = option_index; diff --git a/grub-core/gnulib/getopt_int.h b/grub-core/gnulib/getopt_int.h index 169def5b2..980b7507f 100644 --- a/grub-core/gnulib/getopt_int.h +++ b/grub-core/gnulib/getopt_int.h @@ -30,6 +30,40 @@ extern int _getopt_internal (int ___argc, char **___argv, /* Reentrant versions which can handle parsing multiple argument vectors at the same time. */ +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters, or by calling getopt. + + PERMUTE is the default. We permute the contents of ARGV as we + scan, so that eventually all the non-options are at the end. + This allows options to be given in any order, even with programs + that were not written to expect this. + + RETURN_IN_ORDER is an option available to programs that were + written to expect options and other ARGV-elements in any order + and that care about the ordering of the two. We describe each + non-option ARGV-element as if it were the argument of an option + with character code 1. Using `-' as the first character of the + list of option characters selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return -1 with `optind' != ARGC. */ + +enum __ord + { + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER + }; + /* Data type for reentrant functions. */ struct _getopt_data { @@ -54,39 +88,8 @@ struct _getopt_data by advancing to the next ARGV-element. */ char *__nextchar; - /* Describe how to deal with options that follow non-option ARGV-elements. - - If the caller did not specify anything, - the default is REQUIRE_ORDER if the environment variable - POSIXLY_CORRECT is defined, PERMUTE otherwise. - - REQUIRE_ORDER means don't recognize them as options; - stop option processing when the first non-option is seen. - This is what Unix does. - This mode of operation is selected by either setting the environment - variable POSIXLY_CORRECT, or using `+' as the first character - of the list of option characters, or by calling getopt. - - PERMUTE is the default. We permute the contents of ARGV as we - scan, so that eventually all the non-options are at the end. - This allows options to be given in any order, even with programs - that were not written to expect this. - - RETURN_IN_ORDER is an option available to programs that were - written to expect options and other ARGV-elements in any order - and that care about the ordering of the two. We describe each - non-option ARGV-element as if it were the argument of an option - with character code 1. Using `-' as the first character of the - list of option characters selects this mode of operation. - - The special argument `--' forces an end of option-scanning regardless - of the value of `ordering'. In the case of RETURN_IN_ORDER, only - `--' can cause `getopt' to return -1 with `optind' != ARGC. */ - - enum - { - REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER - } __ordering; + /* See __ord above. */ + enum __ord __ordering; /* If the POSIXLY_CORRECT environment variable is set or getopt was called. */ diff --git a/grub-core/gnulib/regex.h b/grub-core/gnulib/regex.h index 594d5e6aa..89a8143d4 100644 --- a/grub-core/gnulib/regex.h +++ b/grub-core/gnulib/regex.h @@ -114,10 +114,10 @@ typedef unsigned long int reg_syntax_t; /* If this bit is set, then ^ and $ are always anchors (outside bracket expressions, of course). If this bit is not set, then it depends: - ^ is an anchor if it is at the beginning of a regular - expression or after an open-group or an alternation operator; - $ is an anchor if it is at the end of a regular expression, or - before a close-group or an alternation operator. + ^ is an anchor if it is at the beginning of a regular + expression or after an open-group or an alternation operator; + $ is an anchor if it is at the end of a regular expression, or + before a close-group or an alternation operator. This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because POSIX draft 11.2 says that * etc. in leading positions is undefined. @@ -219,8 +219,8 @@ typedef unsigned long int reg_syntax_t; whether ^ should be special. */ # define RE_CARET_ANCHORS_HERE (RE_ICASE << 1) -/* If this bit is set, then \{ cannot be first in an bre or - immediately after an alternation or begin-group operator. */ +/* If this bit is set, then \{ cannot be first in a regex or + immediately after an alternation, open-group or \} operator. */ # define RE_CONTEXT_INVALID_DUP (RE_CARET_ANCHORS_HERE << 1) /* If this bit is set, then no_sub will be set to 1 during @@ -495,8 +495,8 @@ struct re_pattern_buffer #endif unsigned int _REG_RE_NAME (regs_allocated) : 2; - /* Set to zero when `regex_compile' compiles a pattern; set to one - by `re_compile_fastmap' if it updates the fastmap. */ + /* Set to zero when `re_compile_pattern' compiles a pattern; set to + one by `re_compile_fastmap' if it updates the fastmap. */ unsigned int _REG_RE_NAME (fastmap_accurate) : 1; /* If set, `re_match_2' does not return information about @@ -610,8 +610,8 @@ extern regoff_t re_match_2 (struct re_pattern_buffer *__buffer, register data. Unless this function is called, the first search or match using - PATTERN_BUFFER will allocate its own register data, without - freeing the old data. */ + BUFFER will allocate its own register data, without freeing the old + data. */ extern void re_set_registers (struct re_pattern_buffer *__buffer, struct re_registers *__regs, __re_size_t __num_regs, diff --git a/grub-core/gnulib/regex_internal.c b/grub-core/gnulib/regex_internal.c index 378b767d8..787a3a627 100644 --- a/grub-core/gnulib/regex_internal.c +++ b/grub-core/gnulib/regex_internal.c @@ -733,15 +733,17 @@ re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags) mbstate_t cur_state; wchar_t wc2; Idx mlen = raw + pstr->len - p; - unsigned char buf[6]; size_t mbclen; +#if 0 /* dead code: buf is set but never used */ + unsigned char buf[6]; if (BE (pstr->trans != NULL, 0)) { int i = mlen < 6 ? mlen : 6; while (--i >= 0) buf[i] = pstr->trans[p[i]]; } +#endif /* XXX Don't use mbrtowc, we know which conversion to use (UTF-8 -> UCS4). */ memset (&cur_state, 0, sizeof (cur_state)); diff --git a/grub-core/gnulib/regex_internal.h b/grub-core/gnulib/regex_internal.h index e1b4c61b3..dc94e2cbc 100644 --- a/grub-core/gnulib/regex_internal.h +++ b/grub-core/gnulib/regex_internal.h @@ -467,6 +467,8 @@ static unsigned int re_string_context_at (const re_string_t *input, Idx idx, # else /* alloca is implemented with malloc, so just use malloc. */ # define __libc_use_alloca(n) 0 +# undef alloca +# define alloca(n) malloc (n) # endif #endif diff --git a/grub-core/gnulib/stripslash.c b/grub-core/gnulib/stripslash.c new file mode 100644 index 000000000..3a5996fd9 --- /dev/null +++ b/grub-core/gnulib/stripslash.c @@ -0,0 +1,45 @@ +/* stripslash.c -- remove redundant trailing slashes from a file name + + Copyright (C) 1990, 2001, 2003-2006, 2009-2010 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +#include "dirname.h" + +/* Remove trailing slashes from FILE. Return true if a trailing slash + was removed. This is useful when using file name completion from a + shell that adds a "/" after directory names (such as tcsh and + bash), because on symlinks to directories, several system calls + have different semantics according to whether a trailing slash is + present. */ + +bool +strip_trailing_slashes (char *file) +{ + char *base = last_component (file); + char *base_lim; + bool had_slash; + + /* last_component returns "" for file system roots, but we need to turn + `///' into `/'. */ + if (! *base) + base = file; + base_lim = base + base_len (base); + had_slash = (*base_lim != '\0'); + *base_lim = '\0'; + return had_slash; +} diff --git a/grub-core/hello/hello.c b/grub-core/hello/hello.c index 183ee7798..77c4c96b1 100644 --- a/grub-core/hello/hello.c +++ b/grub-core/hello/hello.c @@ -39,8 +39,8 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(hello) { - cmd = grub_register_extcmd ("hello", grub_cmd_hello, GRUB_COMMAND_FLAG_BOTH, - 0, N_("Say \"Hello World\"."), 0); + cmd = grub_register_extcmd ("hello", grub_cmd_hello, 0, 0, + N_("Say \"Hello World\"."), 0); } GRUB_MOD_FINI(hello) diff --git a/grub-core/kern/command.c b/grub-core/kern/command.c index 477240d57..7f353b653 100644 --- a/grub-core/kern/command.c +++ b/grub-core/kern/command.c @@ -40,7 +40,7 @@ grub_register_command_prio (const char *name, cmd->summary = (summary) ? summary : ""; cmd->description = description; - cmd->flags = GRUB_COMMAND_FLAG_BOTH; + cmd->flags = 0; cmd->prio = prio; grub_prio_list_insert (GRUB_AS_PRIO_LIST_P (&grub_command_list), diff --git a/grub-core/kern/device.c b/grub-core/kern/device.c index 4273fedfe..9554ca76a 100644 --- a/grub-core/kern/device.c +++ b/grub-core/kern/device.c @@ -103,7 +103,7 @@ grub_device_iterate (int (*hook) (const char *name)) return 0; } - if (dev->disk && dev->disk->has_partitions) + if (dev->disk) { struct part_ent *p; int ret = 0; diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c index ccd5f200f..7cf29ae7c 100644 --- a/grub-core/kern/disk.c +++ b/grub-core/kern/disk.c @@ -281,12 +281,6 @@ grub_disk_open (const char *name) goto fail; } - if (p && ! disk->has_partitions) - { - grub_error (GRUB_ERR_BAD_DEVICE, "no partition on this disk"); - goto fail; - } - disk->dev = dev; if (p) diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c index c124aa292..1b0a872b4 100644 --- a/grub-core/kern/efi/init.c +++ b/grub-core/kern/efi/init.c @@ -66,10 +66,33 @@ grub_efi_set_prefix (void) path = grub_strdup (pptr); } - if (!device || !path) + if ((!device || device[0] == ',' || !device[0]) || !path) image = grub_efi_get_loaded_image (grub_efi_image_handle); - if (image && !device) - device = grub_efidisk_get_device_name (image->device_handle); + if (image) + { + if (!device) + device = grub_efidisk_get_device_name (image->device_handle); + else if (device[0] == ',' || !device[0]) + { + /* We have a partition, but still need to fill in the drive. */ + char *image_device, *comma, *new_device; + + image_device = grub_efidisk_get_device_name (image->device_handle); + comma = grub_strchr (image_device, ','); + if (comma) + { + char *drive = grub_strndup (image_device, comma - image_device); + new_device = grub_xasprintf ("%s%s", drive, device); + grub_free (drive); + } + else + new_device = grub_xasprintf ("%s%s", image_device, device); + + grub_free (image_device); + grub_free (device); + device = new_device; + } + } if (image && !path) { diff --git a/grub-core/kern/emu/cache.S b/grub-core/kern/emu/cache.S index 90a5b5396..abd81c910 100644 --- a/grub-core/kern/emu/cache.S +++ b/grub-core/kern/emu/cache.S @@ -7,7 +7,20 @@ #elif defined(__sparc__) #include "../sparc64/cache.S" #elif defined(__mips__) -#include "../mips/cache.S" +/* On MIPS we must go through standard functions. */ +#include + +FUNCTION (grub_cpu_flush_cache) +FUNCTION (grub_arch_sync_caches) + .set nomacro + .set noreorder + lui $t0, %hi(_flush_cache) + addui $t0, $t0, %lo(_flush_cache) + move $a3, $zero + jr $t0 + nop + .set reorder + .set macro #elif defined(__powerpc__) #include "../powerpc/cache.S" #else diff --git a/grub-core/kern/emu/console.c b/grub-core/kern/emu/console.c index f6b13b19b..0bf1e05f9 100644 --- a/grub-core/kern/emu/console.c +++ b/grub-core/kern/emu/console.c @@ -102,49 +102,18 @@ grub_ncurses_setcolorstate (struct grub_term_output *term, } } -static int saved_char = ERR; - -static int -grub_ncurses_checkkey (struct grub_term_input *term __attribute__ ((unused))) -{ - int c; - - /* Check for SAVED_CHAR. This should not be true, because this - means checkkey is called twice continuously. */ - if (saved_char != ERR) - return saved_char; - - wtimeout (stdscr, 100); - c = getch (); - /* If C is not ERR, then put it back in the input queue. */ - if (c != ERR) - { - saved_char = c; - return c; - } - - return -1; -} - static int grub_ncurses_getkey (struct grub_term_input *term __attribute__ ((unused))) { int c; - /* If checkkey has already got a character, then return it. */ - if (saved_char != ERR) - { - c = saved_char; - saved_char = ERR; - } - else - { - wtimeout (stdscr, -1); - c = getch (); - } + wtimeout (stdscr, 100); + c = getch (); switch (c) { + case ERR: + return -1; case KEY_LEFT: c = GRUB_TERM_LEFT; break; @@ -288,7 +257,6 @@ grub_ncurses_fini (struct grub_term_output *term __attribute__ ((unused))) static struct grub_term_input grub_ncurses_term_input = { .name = "console", - .checkkey = grub_ncurses_checkkey, .getkey = grub_ncurses_getkey, }; diff --git a/grub-core/kern/emu/full.c b/grub-core/kern/emu/full.c index 0bd33337f..a5801db2f 100644 --- a/grub-core/kern/emu/full.c +++ b/grub-core/kern/emu/full.c @@ -22,6 +22,7 @@ #include #include #include +#include void grub_register_exported_symbols (void) @@ -48,3 +49,21 @@ grub_emu_init (void) { grub_no_autoload = 1; } + +#ifdef GRUB_LINKER_HAVE_INIT +void +grub_arch_dl_init_linker (void) +{ +} +#endif + +void +grub_emu_post_init (void) +{ + grub_lvm_fini (); + grub_mdraid_fini (); + grub_raid_fini (); + grub_raid_init (); + grub_mdraid_init (); + grub_lvm_init (); +} diff --git a/grub-core/kern/emu/getroot.c b/grub-core/kern/emu/getroot.c index c0a10d22b..003fe9333 100644 --- a/grub-core/kern/emu/getroot.c +++ b/grub-core/kern/emu/getroot.c @@ -228,8 +228,8 @@ find_root_device_from_libzfs (const char *dir) #ifdef __MINGW32__ -static char * -find_root_device (const char *dir __attribute__ ((unused)), +char * +grub_find_device (const char *dir __attribute__ ((unused)), dev_t dev __attribute__ ((unused))) { return 0; @@ -237,13 +237,22 @@ find_root_device (const char *dir __attribute__ ((unused)), #elif ! defined(__CYGWIN__) -static char * -find_root_device (const char *dir, dev_t dev) +char * +grub_find_device (const char *dir, dev_t dev) { DIR *dp; char *saved_cwd; struct dirent *ent; + if (! dir) + { +#ifdef __CYGWIN__ + return NULL; +#else + dir = "/dev"; +#endif + } + dp = opendir (dir); if (! dp) return 0; @@ -292,7 +301,7 @@ find_root_device (const char *dir, dev_t dev) /* Find it recursively. */ char *res; - res = find_root_device (ent->d_name, dev); + res = grub_find_device (ent->d_name, dev); if (res) { @@ -402,8 +411,8 @@ get_bootsec_serial (const char *os_dev, int mbr) return serial; } -static char * -find_cygwin_root_device (const char *path, dev_t dev) +char * +grub_find_device (const char *path, dev_t dev) { /* No root device for /cygdrive. */ if (dev == (DEV_CYGDRIVE_MAJOR << 16)) @@ -424,7 +433,7 @@ find_cygwin_root_device (const char *path, dev_t dev) /* Cygwin returns the partition serial number in stat.st_dev. This is never identical to the device number of the emulated - /dev/sdXN device, so above find_root_device () does not work. + /dev/sdXN device, so above grub_find_device () does not work. Search the partition with the same serial in boot sector instead. */ char devpath[sizeof ("/dev/sda15") + 13]; /* Size + Paranoia. */ int d; @@ -529,12 +538,12 @@ grub_guess_root_device (const char *dir) #ifdef __CYGWIN__ /* Cygwin specific function. */ - os_dev = find_cygwin_root_device (dir, st.st_dev); + os_dev = grub_find_device (dir, st.st_dev); #else /* This might be truly slow, but is there any better way? */ - os_dev = find_root_device ("/dev", st.st_dev); + os_dev = grub_find_device ("/dev", st.st_dev); #endif #endif /* !__GNU__ */ @@ -572,6 +581,10 @@ int grub_util_get_dev_abstraction (const char *os_dev __attribute__((unused))) { #ifdef __linux__ + /* User explicitly claims that this drive is visible by BIOS. */ + if (grub_util_biosdisk_is_present (os_dev)) + return GRUB_DEV_ABSTRACTION_NONE; + /* Check for LVM. */ if (!strncmp (os_dev, "/dev/mapper/", 12) && ! grub_util_is_dmraid (os_dev) diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index 2cdf449e2..7d9d1dac1 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -221,7 +221,6 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no mapping exists for `%s'", name); - disk->has_partitions = 1; disk->id = drive; disk->data = data = xmalloc (sizeof (struct grub_util_biosdisk_data)); data->dev = NULL; @@ -956,13 +955,16 @@ read_device_map (const char *dev_map) #ifdef __linux__ /* On Linux, the devfs uses symbolic links horribly, and that confuses the interface very much, so use realpath to expand - symbolic links. */ - map[drive].device = xmalloc (PATH_MAX); - if (! realpath (p, map[drive].device)) - grub_util_error ("cannot get the real path of `%s'", p); -#else - map[drive].device = xstrdup (p); + symbolic links. Leave /dev/mapper/ alone, though. */ + if (strncmp (p, "/dev/mapper/", 12) != 0) + { + map[drive].device = xmalloc (PATH_MAX); + if (! realpath (p, map[drive].device)) + grub_util_error ("cannot get the real path of `%s'", p); + } + else #endif + map[drive].device = xstrdup (p); } fclose (fp); @@ -1117,6 +1119,16 @@ convert_system_partition_to_system_disk (const char *os_dev, struct stat *st) return path; } + if (strncmp ("md", p, 2) == 0 + && p[2] >= '0' && p[2] <= '9') + { + char *ptr = p + 2; + while (*ptr >= '0' && *ptr <= '9') + ptr++; + *ptr = 0; + return path; + } + /* If this is an IDE, SCSI or Virtio disk. */ if (strncmp ("vdisk", p, 5) == 0 && p[5] >= 'a' && p[5] <= 'z') @@ -1144,22 +1156,22 @@ convert_system_partition_to_system_disk (const char *os_dev, struct stat *st) } #ifdef HAVE_DEVICE_MAPPER - /* If this is a DM-RAID device. */ - if ((strncmp ("mapper/", p, 7) == 0)) + /* If this is a DM-RAID device. + Compare os_dev rather than path here, since nodes under + /dev/mapper/ are often symlinks. */ + if ((strncmp ("/dev/mapper/", os_dev, 12) == 0)) { - static struct dm_tree *tree = NULL; + struct dm_tree *tree; uint32_t maj, min; - struct dm_tree_node *node, *child; + struct dm_tree_node *node = NULL, *child; void *handle; - const char *node_uuid, *mapper_name, *child_uuid, *child_name; - - if (! tree) - tree = dm_tree_create (); + const char *node_uuid, *mapper_name = NULL, *child_uuid, *child_name; + tree = dm_tree_create (); if (! tree) { grub_dprintf ("hostdisk", "dm_tree_create failed\n"); - return NULL; + goto devmapper_out; } maj = major (st->st_rdev); @@ -1167,29 +1179,30 @@ convert_system_partition_to_system_disk (const char *os_dev, struct stat *st) if (! dm_tree_add_dev (tree, maj, min)) { grub_dprintf ("hostdisk", "dm_tree_add_dev failed\n"); - return NULL; + goto devmapper_out; } node = dm_tree_find_node (tree, maj, min); if (! node) { grub_dprintf ("hostdisk", "dm_tree_find_node failed\n"); - return NULL; + goto devmapper_out; } node_uuid = dm_tree_node_get_uuid (node); if (! node_uuid) { grub_dprintf ("hostdisk", "%s has no DM uuid\n", path); - return NULL; + node = NULL; + goto devmapper_out; } else if (strncmp (node_uuid, "DMRAID-", 7) != 0) { grub_dprintf ("hostdisk", "%s is not DM-RAID\n", path); - return NULL; + node = NULL; + goto devmapper_out; } handle = NULL; - mapper_name = NULL; /* Counter-intuitively, device-mapper refers to the disk-like device containing a DM-RAID partition device as a "child" of the partition device. */ @@ -1219,17 +1232,20 @@ convert_system_partition_to_system_disk (const char *os_dev, struct stat *st) mapper_name = child_name; devmapper_out: - if (! mapper_name) + if (! mapper_name && node) { /* This is a DM-RAID disk, not a partition. */ mapper_name = dm_tree_node_get_name (node); if (! mapper_name) - { - grub_dprintf ("hostdisk", "%s has no DM name\n", path); - return NULL; - } + grub_dprintf ("hostdisk", "%s has no DM name\n", path); } - return xasprintf ("/dev/mapper/%s", mapper_name); + if (tree) + dm_tree_free (tree); + free (path); + if (mapper_name) + return xasprintf ("/dev/mapper/%s", mapper_name); + else + return NULL; } #endif /* HAVE_DEVICE_MAPPER */ } @@ -1334,7 +1350,7 @@ device_is_wholedisk (const char *os_dev) #endif /* defined(__NetBSD__) */ static int -find_system_device (const char *os_dev, struct stat *st) +find_system_device (const char *os_dev, struct stat *st, int add) { unsigned int i; char *os_disk; @@ -1352,6 +1368,9 @@ find_system_device (const char *os_dev, struct stat *st) return i; } + if (!add) + return -1; + if (i == ARRAY_SIZE (map)) grub_util_error (_("device count exceeds limit")); @@ -1361,6 +1380,17 @@ find_system_device (const char *os_dev, struct stat *st) return i; } +int +grub_util_biosdisk_is_present (const char *os_dev) +{ + struct stat st; + + if (stat (os_dev, &st) < 0) + return 0; + + return find_system_device (os_dev, &st, 0) != -1; +} + char * grub_util_biosdisk_get_grub_dev (const char *os_dev) { @@ -1373,7 +1403,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev) return 0; } - drive = find_system_device (os_dev, &st); + drive = find_system_device (os_dev, &st, 1); if (drive < 0) { grub_error (GRUB_ERR_UNKNOWN_DEVICE, @@ -1552,3 +1582,29 @@ grub_util_biosdisk_get_osdev (grub_disk_t disk) { return map[disk->id].device; } + +int +grub_util_biosdisk_is_floppy (grub_disk_t disk) +{ + struct stat st; + int fd; + + fd = open (map[disk->id].device, O_RDONLY); + /* Shouldn't happen. */ + if (fd == -1) + return 0; + + /* Shouldn't happen either. */ + if (fstat (fd, &st) < 0) + return 0; + +#if defined(__NetBSD__) + if (major(st.st_rdev) == RAW_FLOPPY_MAJOR) + return 1; +#endif + + if (major(st.st_rdev) == FLOPPY_MAJOR) + return 1; + + return 0; +} diff --git a/grub-core/kern/emu/lite.c b/grub-core/kern/emu/lite.c index 9b3728717..32e12a079 100644 --- a/grub-core/kern/emu/lite.c +++ b/grub-core/kern/emu/lite.c @@ -38,3 +38,8 @@ grub_emu_init (void) { return; } + +void +grub_emu_post_init (void) +{ +} diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c index 8867f6101..c575beb4b 100644 --- a/grub-core/kern/emu/main.c +++ b/grub-core/kern/emu/main.c @@ -190,19 +190,15 @@ main (int argc, char *argv[]) grub_emu_init (); grub_console_init (); grub_host_init (); - grub_hostfs_init (); /* XXX: This is a bit unportable. */ grub_util_biosdisk_init (dev_map); grub_init_all (); - grub_lvm_fini (); - grub_mdraid_fini (); - grub_raid_fini (); - grub_raid_init (); - grub_mdraid_init (); - grub_lvm_init (); + grub_hostfs_init (); + + grub_emu_post_init (); /* Make sure that there is a root device. */ if (! root_dev) diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c index 82f579616..c710777ea 100644 --- a/grub-core/kern/emu/misc.c +++ b/grub-core/kern/emu/misc.c @@ -61,6 +61,15 @@ # include #endif +#ifdef HAVE_SYS_MNTTAB_H +# include /* Needed by sys/mnttab.h. */ +# include +#endif + +#ifdef HAVE_SYS_MKDEV_H +# include /* makedev */ +#endif + int verbosity; void @@ -282,18 +291,52 @@ grub_get_libzfs_handle (void) void grub_find_zpool_from_dir (const char *dir, char **poolname, char **poolfs) { - struct statfs mnt; char *slash; *poolname = *poolfs = NULL; - if (statfs (dir, &mnt) != 0) - return; +#if defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) && defined(HAVE_STRUCT_STATFS_F_MNTFROMNAME) + /* FreeBSD and GNU/kFreeBSD. */ + { + struct statfs mnt; - if (strcmp (mnt.f_fstypename, "zfs") != 0) - return; + if (statfs (dir, &mnt) != 0) + return; - *poolname = xstrdup (mnt.f_mntfromname); + if (strcmp (mnt.f_fstypename, "zfs") != 0) + return; + + *poolname = xstrdup (mnt.f_mntfromname); + } +#elif defined(HAVE_GETEXTMNTENT) + /* Solaris. */ + { + struct stat st; + struct extmnttab mnt; + + if (stat (dir, &st) != 0) + return; + + FILE *mnttab = fopen ("/etc/mnttab", "r"); + if (! mnttab) + return; + + while (getextmntent (mnttab, &mnt, sizeof (mnt)) == 0) + { + if (makedev (mnt.mnt_major, mnt.mnt_minor) == st.st_dev + && !strcmp (mnt.mnt_fstype, "zfs")) + { + *poolname = xstrdup (mnt.mnt_special); + break; + } + } + + fclose (mnttab); + } +#endif + + if (! *poolname) + return; slash = strchr (*poolname, '/'); if (slash) diff --git a/grub-core/kern/i386/coreboot/init.c b/grub-core/kern/i386/coreboot/init.c index 75f385b56..434b9b5a8 100644 --- a/grub-core/kern/i386/coreboot/init.c +++ b/grub-core/kern/i386/coreboot/init.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -64,8 +65,10 @@ grub_machine_init (void) /* Initialize the console as early as possible. */ grub_vga_text_init (); - auto int NESTED_FUNC_ATTR heap_init (grub_uint64_t, grub_uint64_t, grub_uint32_t); - int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) + auto int NESTED_FUNC_ATTR heap_init (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); + int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t size, + grub_memory_type_t type) { #if GRUB_CPU_SIZEOF_VOID_P == 4 /* Restrict ourselves to 32-bit memory space. */ @@ -75,7 +78,7 @@ grub_machine_init (void) size = GRUB_ULONG_MAX - addr; #endif - if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + if (type != GRUB_MEMORY_AVAILABLE) return 0; /* Avoid the lower memory. */ diff --git a/grub-core/kern/i386/coreboot/mmap.c b/grub-core/kern/i386/coreboot/mmap.c index d06627a08..8b0b20265 100644 --- a/grub-core/kern/i386/coreboot/mmap.c +++ b/grub-core/kern/i386/coreboot/mmap.c @@ -17,6 +17,7 @@ */ #include +#include #include #include #include @@ -74,7 +75,7 @@ signature_found: } grub_err_t -grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { mem_region_t mem_region; diff --git a/grub-core/kern/i386/coreboot/startup.S b/grub-core/kern/i386/coreboot/startup.S index 592073776..cac023ddf 100644 --- a/grub-core/kern/i386/coreboot/startup.S +++ b/grub-core/kern/i386/coreboot/startup.S @@ -17,6 +17,8 @@ */ #include +/* For stack parameters. */ +#include #include #include #include diff --git a/grub-core/kern/i386/ieee1275/startup.S b/grub-core/kern/i386/ieee1275/startup.S index 3ecf09598..82087323b 100644 --- a/grub-core/kern/i386/ieee1275/startup.S +++ b/grub-core/kern/i386/ieee1275/startup.S @@ -17,7 +17,7 @@ */ #include -#include +#include #include #include #include diff --git a/grub-core/kern/i386/multiboot_mmap.c b/grub-core/kern/i386/multiboot_mmap.c index 73c82049f..7f4bc3b5c 100644 --- a/grub-core/kern/i386/multiboot_mmap.c +++ b/grub-core/kern/i386/multiboot_mmap.c @@ -22,8 +22,6 @@ #include #include -grub_size_t grub_lower_mem, grub_upper_mem; - /* A pointer to the MBI in its initial location. */ struct multiboot_info *startup_multiboot_info; @@ -56,21 +54,10 @@ grub_machine_mmap_init () } grub_memmove (mmap_entries, (void *) kern_multiboot_info.mmap_addr, kern_multiboot_info.mmap_length); kern_multiboot_info.mmap_addr = (grub_uint32_t) mmap_entries; - - if ((kern_multiboot_info.flags & MULTIBOOT_INFO_MEMORY) == 0) - { - grub_lower_mem = GRUB_MEMORY_MACHINE_LOWER_USABLE; - grub_upper_mem = 0; - } - else - { - grub_lower_mem = kern_multiboot_info.mem_lower * 1024; - grub_upper_mem = kern_multiboot_info.mem_upper * 1024; - } } grub_err_t -grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { struct multiboot_mmap_entry *entry = (void *) kern_multiboot_info.mmap_addr; diff --git a/grub-core/kern/i386/pc/init.c b/grub-core/kern/i386/pc/init.c index 57e33569e..122c2c556 100644 --- a/grub-core/kern/i386/pc/init.c +++ b/grub-core/kern/i386/pc/init.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include @@ -171,11 +171,6 @@ grub_machine_init (void) if (grub_lower_mem < GRUB_MEMORY_MACHINE_RESERVED_END) grub_fatal ("too small memory"); -#if 0 - /* Turn on Gate A20 to access >1MB. */ - grub_gate_a20 (1); -#endif - /* FIXME: This prevents loader/i386/linux.c from using low memory. When our heap implements support for requesting a chunk in low memory, this should no longer be a problem. */ @@ -186,8 +181,10 @@ grub_machine_init (void) grub_lower_mem - GRUB_MEMORY_MACHINE_RESERVED_END); #endif - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); - int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); + int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, + grub_memory_type_t type) { /* Avoid the lower memory. */ if (addr < 0x100000) @@ -200,7 +197,7 @@ grub_machine_init (void) } /* Ignore >4GB. */ - if (addr <= 0xFFFFFFFF && type == GRUB_MACHINE_MEMORY_AVAILABLE) + if (addr <= 0xFFFFFFFF && type == GRUB_MEMORY_AVAILABLE) { grub_size_t len; diff --git a/grub-core/kern/i386/pc/mmap.c b/grub-core/kern/i386/pc/mmap.c index b174bc441..a305d4511 100644 --- a/grub-core/kern/i386/pc/mmap.c +++ b/grub-core/kern/i386/pc/mmap.c @@ -16,13 +16,26 @@ * along with GRUB. If not, see . */ -#include -#include #include +#include #include #include #include +struct grub_machine_mmap_entry +{ + grub_uint32_t size; + grub_uint64_t addr; + grub_uint64_t len; +#define GRUB_MACHINE_MEMORY_AVAILABLE 1 +#define GRUB_MACHINE_MEMORY_RESERVED 2 +#define GRUB_MACHINE_MEMORY_ACPI 3 +#define GRUB_MACHINE_MEMORY_NVS 4 +#define GRUB_MACHINE_MEMORY_BADRAM 5 + grub_uint32_t type; +} __attribute__((packed)); + + /* * grub_get_ext_memsize() : return the extended memory size in KB. * BIOS call "INT 15H, AH=88H" to get extended memory size @@ -110,7 +123,7 @@ grub_get_mmap_entry (struct grub_machine_mmap_entry *entry, } grub_err_t -grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { grub_uint32_t cont; struct grub_machine_mmap_entry *entry @@ -125,9 +138,9 @@ grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uin do { if (hook (entry->addr, entry->len, - /* Multiboot mmaps have been defined to match with the E820 definition. + /* GRUB mmaps have been defined to match with the E820 definition. Therefore, we can just pass type through. */ - entry->type)) + ((entry->type <= GRUB_MACHINE_MEMORY_BADRAM) && (entry->type >= GRUB_MACHINE_MEMORY_AVAILABLE)) ? entry->type : GRUB_MEMORY_RESERVED)) break; if (! cont) @@ -144,11 +157,12 @@ grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uin if (eisa_mmap) { - if (hook (0x100000, (eisa_mmap & 0xFFFF) << 10, GRUB_MACHINE_MEMORY_AVAILABLE) == 0) - hook (0x1000000, eisa_mmap & ~0xFFFF, GRUB_MACHINE_MEMORY_AVAILABLE); + if (hook (0x100000, (eisa_mmap & 0xFFFF) << 10, + GRUB_MEMORY_AVAILABLE) == 0) + hook (0x1000000, eisa_mmap & ~0xFFFF, GRUB_MEMORY_AVAILABLE); } else - hook (0x100000, grub_get_ext_memsize () << 10, GRUB_MACHINE_MEMORY_AVAILABLE); + hook (0x100000, grub_get_ext_memsize () << 10, GRUB_MEMORY_AVAILABLE); } return 0; diff --git a/grub-core/kern/i386/pc/startup.S b/grub-core/kern/i386/pc/startup.S index 9b53deeb2..46e6b1fac 100644 --- a/grub-core/kern/i386/pc/startup.S +++ b/grub-core/kern/i386/pc/startup.S @@ -202,7 +202,7 @@ LOCAL (codestart): .code32 incl %eax - call EXT_C(grub_gate_a20) + call grub_gate_a20 #ifdef ENABLE_LZMA movl $GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR, %edi @@ -292,7 +292,7 @@ VARIABLE(grub_boot_drive) * It also eats any keystrokes in the keyboard buffer. :-( */ -FUNCTION(grub_gate_a20) +grub_gate_a20: movl %eax, %edx gate_a20_test_current_state: @@ -478,7 +478,7 @@ FUNCTION(grub_chainloader_real_boot) /* Turn off Gate A20 */ xorl %eax, %eax - call EXT_C(grub_gate_a20) + call grub_gate_a20 /* set up to pass boot drive */ popl %edx @@ -576,62 +576,29 @@ FUNCTION(grub_console_putchar) ret +LOCAL(bypass_table): + .word 0x0100 | '\e',0x0f00 | '\t', 0x0e00 | '\b', 0x1c00 | '\r' + .word 0x1c00 | '\n' +LOCAL(bypass_table_end): + /* * int grub_console_getkey (void) + * if there is a character pending, return it; otherwise return -1 + * BIOS call "INT 16H Function 01H" to check whether a character is pending + * Call with %ah = 0x1 + * Return: + * If key waiting to be input: + * %ah = keyboard scan code + * %al = ASCII character + * Zero flag = clear + * else + * Zero flag = set * BIOS call "INT 16H Function 00H" to read character from keyboard * Call with %ah = 0x0 * Return: %ah = keyboard scan code * %al = ASCII character */ -/* this table is used in translate_keycode below */ -LOCAL (translation_table): - .word GRUB_CONSOLE_KEY_LEFT, GRUB_TERM_LEFT - .word GRUB_CONSOLE_KEY_RIGHT, GRUB_TERM_RIGHT - .word GRUB_CONSOLE_KEY_UP, GRUB_TERM_UP - .word GRUB_CONSOLE_KEY_DOWN, GRUB_TERM_DOWN - .word GRUB_CONSOLE_KEY_HOME, GRUB_TERM_HOME - .word GRUB_CONSOLE_KEY_END, GRUB_TERM_END - .word GRUB_CONSOLE_KEY_DC, GRUB_TERM_DC - .word GRUB_CONSOLE_KEY_BACKSPACE, GRUB_TERM_BACKSPACE - .word GRUB_CONSOLE_KEY_PPAGE, GRUB_TERM_PPAGE - .word GRUB_CONSOLE_KEY_NPAGE, GRUB_TERM_NPAGE - .word 0 - -/* - * translate_keycode translates the key code %dx to an ascii code. - */ - .code16 - -translate_keycode: - pushw %bx - pushw %si - -#ifdef __APPLE__ - movw $(ABS(LOCAL (translation_table)) - 0x10000), %si -#else - movw $ABS(LOCAL (translation_table)), %si -#endif - -1: lodsw - /* check if this is the end */ - testw %ax, %ax - jz 2f - /* load the ascii code into %ax */ - movw %ax, %bx - lodsw - /* check if this matches the key code */ - cmpw %bx, %dx - jne 1b - /* translate %dx, if successful */ - movw %ax, %dx - -2: popw %si - popw %bx - ret - - .code32 - FUNCTION(grub_console_getkey) pushl %ebp @@ -645,70 +612,54 @@ FUNCTION(grub_console_getkey) * INT 16/AH = 1 before calling INT 16/AH = 0. */ -1: movb $1, %ah int $0x16 - jnz 2f - hlt - jmp 1b - -2: + jz notpending movb $0, %ah int $0x16 + xorl %edx, %edx movw %ax, %dx /* real_to_prot uses %eax */ - call translate_keycode DATA32 call real_to_prot .code32 - movw %dx, %ax - - popl %ebp - ret - - -/* - * int grub_console_checkkey (void) - * if there is a character pending, return it; otherwise return -1 - * BIOS call "INT 16H Function 01H" to check whether a character is pending - * Call with %ah = 0x1 - * Return: - * If key waiting to be input: - * %ah = keyboard scan code - * %al = ASCII character - * Zero flag = clear - * else - * Zero flag = set - */ -FUNCTION(grub_console_checkkey) - pushl %ebp - xorl %edx, %edx - - call prot_to_real /* enter real mode */ - .code16 - - movb $0x1, %ah - int $0x16 - - jz notpending - - movw %ax, %dx - DATA32 jmp pending - -notpending: - decl %edx - -pending: - DATA32 call real_to_prot - .code32 + movl $0xff, %eax + testl %eax, %edx + jz 1f + andl %edx, %eax + cmp %eax, 0x20 + ja 2f movl %edx, %eax + leal LOCAL(bypass_table), %esi + movl $((LOCAL(bypass_table_end) - LOCAL(bypass_table)) / 2), %ecx + repne cmpsw + jz 3f + addl $('a' - 1 | GRUB_TERM_CTRL), %eax + jmp 2f +3: + andl $0xff, %eax + jmp 2f + +1: movl %edx, %eax + shrl $8, %eax + orl $GRUB_TERM_EXTENDED, %eax +2: popl %ebp ret +notpending: + .code16 + DATA32 call real_to_prot + .code32 +#if GRUB_TERM_NO_KEY != 0 +#error Fix this asm code +#endif + jmp 2b + /* * grub_uint16_t grub_console_getxy (void) diff --git a/grub-core/kern/i386/qemu/mmap.c b/grub-core/kern/i386/qemu/mmap.c index f8b4b9b4f..208f36b7e 100644 --- a/grub-core/kern/i386/qemu/mmap.c +++ b/grub-core/kern/i386/qemu/mmap.c @@ -16,12 +16,14 @@ * along with GRUB. If not, see . */ +#include #include #include #include #include #include #include +#include #define QEMU_CMOS_MEMSIZE_HIGH 0x35 #define QEMU_CMOS_MEMSIZE_LOW 0x34 @@ -60,38 +62,38 @@ grub_machine_mmap_init () } grub_err_t -grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { if (hook (0x0, (grub_addr_t) _start, - GRUB_MACHINE_MEMORY_AVAILABLE)) + GRUB_MEMORY_AVAILABLE)) return 1; if (hook ((grub_addr_t) _end, 0xa0000 - (grub_addr_t) _end, - GRUB_MACHINE_MEMORY_AVAILABLE)) + GRUB_MEMORY_AVAILABLE)) return 1; if (hook (GRUB_MEMORY_MACHINE_UPPER, 0x100000 - GRUB_MEMORY_MACHINE_UPPER, - GRUB_MACHINE_MEMORY_RESERVED)) + GRUB_MEMORY_RESERVED)) return 1; /* Everything else is free. */ if (hook (0x100000, min (mem_size, (grub_uint32_t) -GRUB_BOOT_MACHINE_SIZE) - 0x100000, - GRUB_MACHINE_MEMORY_AVAILABLE)) + GRUB_MEMORY_AVAILABLE)) return 1; /* Protect boot.img, which contains the gdt. It is mapped at the top of memory (it is also mapped below 0x100000, but we already reserved that area). */ if (hook ((grub_uint32_t) -GRUB_BOOT_MACHINE_SIZE, GRUB_BOOT_MACHINE_SIZE, - GRUB_MACHINE_MEMORY_RESERVED)) + GRUB_MEMORY_RESERVED)) return 1; if (above_4g != 0 && hook (0x100000000ULL, above_4g, - GRUB_MACHINE_MEMORY_AVAILABLE)) + GRUB_MEMORY_AVAILABLE)) return 1; return 0; diff --git a/grub-core/kern/i386/qemu/startup.S b/grub-core/kern/i386/qemu/startup.S index 680de9dc4..7834d1df5 100644 --- a/grub-core/kern/i386/qemu/startup.S +++ b/grub-core/kern/i386/qemu/startup.S @@ -18,6 +18,8 @@ #include #include + +#include #include #include diff --git a/grub-core/kern/ieee1275/cmain.c b/grub-core/kern/ieee1275/cmain.c index d3c3a8d88..30eacbbdd 100644 --- a/grub-core/kern/ieee1275/cmain.c +++ b/grub-core/kern/ieee1275/cmain.c @@ -138,11 +138,16 @@ grub_ieee1275_find_options (void) */ grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY); + grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_HAS_CURSORONOFF); } if (is_qemu) - /* OpenFirmware hangs on qemu if one requests any memory below 1.5 MiB. */ - grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM); + { + /* OpenFirmware hangs on qemu if one requests any memory below 1.5 MiB. */ + grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM); + + grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_HAS_CURSORONOFF); + } if (! grub_ieee1275_finddevice ("/rom/boot-rom", &bootrom)) { diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c index 99ce7179b..682a8b5a4 100644 --- a/grub-core/kern/ieee1275/init.c +++ b/grub-core/kern/ieee1275/init.c @@ -32,6 +32,7 @@ #include #include #include +#include /* The minimal heap size we can live with. */ #define HEAP_MIN_SIZE (unsigned long) (2 * 1024 * 1024) @@ -126,8 +127,10 @@ static void grub_claim_heap (void) { unsigned long total = 0; - auto int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type); - int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type) + auto int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t len, + grub_memory_type_t type); + int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t len, + grub_memory_type_t type) { if (type != 1) return 0; @@ -189,31 +192,6 @@ static void grub_claim_heap (void) grub_machine_mmap_iterate (heap_init); } -#ifdef __i386__ - -grub_uint32_t grub_upper_mem; - -/* We need to call this before grub_claim_memory. */ -static void -grub_get_extended_memory (void) -{ - auto int NESTED_FUNC_ATTR find_ext_mem (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type); - int NESTED_FUNC_ATTR find_ext_mem (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type) - { - if (type == 1 && addr == 0x100000) - { - grub_upper_mem = len; - return 1; - } - - return 0; - } - - grub_machine_mmap_iterate (find_ext_mem); -} - -#endif - static grub_uint64_t ieee1275_get_time_ms (void); void @@ -225,9 +203,6 @@ grub_machine_init (void) grub_ieee1275_init (); grub_console_init_early (); -#ifdef __i386__ - grub_get_extended_memory (); -#endif grub_claim_heap (); grub_console_init_lately (); grub_ofdisk_init (); diff --git a/grub-core/kern/ieee1275/mmap.c b/grub-core/kern/ieee1275/mmap.c index 6f0652770..942e5a354 100644 --- a/grub-core/kern/ieee1275/mmap.c +++ b/grub-core/kern/ieee1275/mmap.c @@ -16,12 +16,12 @@ * along with GRUB. If not, see . */ -#include +#include #include #include grub_err_t -grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { grub_ieee1275_phandle_t root; grub_ieee1275_phandle_t memory; @@ -66,7 +66,7 @@ grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uin if (size_cells == 2) size = (size << 32) | available[i++]; - if (hook (address, size, GRUB_MACHINE_MEMORY_AVAILABLE)) + if (hook (address, size, GRUB_MEMORY_AVAILABLE)) break; } diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c index fcd43f617..f5dc8efb1 100644 --- a/grub-core/kern/ieee1275/openfw.c +++ b/grub-core/kern/ieee1275/openfw.c @@ -423,3 +423,47 @@ grub_reboot (void) for (;;) ; } #endif + +/* Resolve aliases. */ +char * +grub_ieee1275_canonicalise_devname (const char *path) +{ + struct canon_args + { + struct grub_ieee1275_common_hdr common; + grub_ieee1275_cell_t path; + grub_ieee1275_cell_t buf; + grub_ieee1275_cell_t inlen; + grub_ieee1275_cell_t outlen; + } + args; + char *buf = NULL; + grub_size_t bufsize = 64; + int i; + + for (i = 0; i < 2; i++) + { + grub_free (buf); + + buf = grub_malloc (bufsize); + if (!buf) + return NULL; + + INIT_IEEE1275_COMMON (&args.common, "canon", 3, 1); + args.path = (grub_ieee1275_cell_t) path; + args.buf = (grub_ieee1275_cell_t) buf; + args.inlen = (grub_ieee1275_cell_t) (bufsize - 1); + + if (IEEE1275_CALL_ENTRY_FN (&args) == -1) + return 0; + if (args.outlen > bufsize - 1) + { + bufsize = args.outlen + 2; + continue; + } + return buf; + } + /* Shouldn't reach here. */ + grub_free (buf); + return NULL; +} diff --git a/grub-core/kern/mips/qemu-mips/init.c b/grub-core/kern/mips/qemu-mips/init.c index 866c7a82a..f2bb652a8 100644 --- a/grub-core/kern/mips/qemu-mips/init.c +++ b/grub-core/kern/mips/qemu-mips/init.c @@ -51,11 +51,8 @@ grub_reboot (void) } grub_err_t -grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, - grub_uint64_t, - grub_uint32_t)) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { - hook (0, RAMSIZE, - GRUB_MACHINE_MEMORY_AVAILABLE); + hook (0, RAMSIZE, GRUB_MEMORY_AVAILABLE); return GRUB_ERR_NONE; } diff --git a/grub-core/kern/mips/yeeloong/init.c b/grub-core/kern/mips/yeeloong/init.c index 523f90282..cc7c16806 100644 --- a/grub-core/kern/mips/yeeloong/init.c +++ b/grub-core/kern/mips/yeeloong/init.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -39,6 +40,7 @@ extern void grub_gfxterm_init (void); extern void grub_at_keyboard_init (void); extern void grub_serial_init (void); extern void grub_terminfo_init (void); +extern void grub_keylayouts_init (void); /* FIXME: use interrupt to count high. */ grub_uint64_t @@ -57,14 +59,12 @@ grub_get_rtc (void) } grub_err_t -grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, - grub_uint64_t, - grub_uint32_t)) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { hook (GRUB_ARCH_LOWMEMPSTART, grub_arch_memsize << 20, - GRUB_MACHINE_MEMORY_AVAILABLE); + GRUB_MEMORY_AVAILABLE); hook (GRUB_ARCH_HIGHMEMPSTART, grub_arch_highmemsize << 20, - GRUB_MACHINE_MEMORY_AVAILABLE); + GRUB_MEMORY_AVAILABLE); return GRUB_ERR_NONE; } @@ -205,6 +205,7 @@ grub_machine_init (void) grub_font_init (); grub_gfxterm_init (); + grub_keylayouts_init (); grub_at_keyboard_init (); grub_terminfo_init (); diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c index 0bfa08992..6e0eaf6a4 100644 --- a/grub-core/kern/misc.c +++ b/grub-core/kern/misc.c @@ -196,6 +196,8 @@ grub_vprintf (const char *fmt, va_list args) grub_size_t s; static char buf[PREALLOC_SIZE + 1]; char *curbuf = buf; + va_list ap2; + va_copy (ap2, args); s = grub_vsnprintf_real (buf, PREALLOC_SIZE, fmt, args); if (s > PREALLOC_SIZE) @@ -210,7 +212,7 @@ grub_vprintf (const char *fmt, va_list args) buf[PREALLOC_SIZE] = 0; } else - s = grub_vsnprintf_real (curbuf, s, fmt, args); + s = grub_vsnprintf_real (curbuf, s, fmt, ap2); } grub_xputs (curbuf); @@ -947,11 +949,13 @@ grub_xvasprintf (const char *fmt, va_list ap) while (1) { + va_list ap2; + va_copy (ap2, ap); ret = grub_malloc (as + 1); if (!ret) return NULL; - s = grub_vsnprintf_real (ret, as, fmt, ap); + s = grub_vsnprintf_real (ret, as, fmt, ap2); if (s <= as) return ret; diff --git a/grub-core/kern/rescue_reader.c b/grub-core/kern/rescue_reader.c index 531fcc8fa..a81008579 100644 --- a/grub-core/kern/rescue_reader.c +++ b/grub-core/kern/rescue_reader.c @@ -39,7 +39,7 @@ grub_rescue_read_line (char **line, int cont) grub_printf ((cont) ? "> " : "grub rescue> "); grub_memset (linebuf, 0, GRUB_RESCUE_BUF_SIZE); - while ((c = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != '\n' && c != '\r') + while ((c = grub_getkey ()) != '\n' && c != '\r') { if (grub_isprint (c)) { diff --git a/grub-core/kern/sparc64/ieee1275/crt0.S b/grub-core/kern/sparc64/ieee1275/crt0.S index f178f5d3c..cebdca2b6 100644 --- a/grub-core/kern/sparc64/ieee1275/crt0.S +++ b/grub-core/kern/sparc64/ieee1275/crt0.S @@ -61,9 +61,11 @@ codestart: /* Save ieee1275 stack for future use by booter. */ mov %o6, %o1 /* Our future stack. */ - sethi %hi(GRUB_KERNEL_MACHINE_STACK_SIZE - 2047), %o5 - or %o5, %lo(GRUB_KERNEL_MACHINE_STACK_SIZE - 2047), %o5 + sethi %hi(GRUB_KERNEL_MACHINE_STACK_SIZE), %o5 + or %o5, %lo(GRUB_KERNEL_MACHINE_STACK_SIZE), %o5 add %o3, %o5, %o6 + and %o6, ~0xff, %o6 + sub %o6, 2047, %o6 sub %o2, 4, %o2 sub %o3, 4, %o3 diff --git a/grub-core/kern/term.c b/grub-core/kern/term.c index 360539e50..7b3593161 100644 --- a/grub-core/kern/term.c +++ b/grub-core/kern/term.c @@ -78,65 +78,48 @@ grub_xputs_dumb (const char *str) void (*grub_xputs) (const char *str) = grub_xputs_dumb; -int -grub_getkey (void) -{ - grub_term_input_t term; - - grub_refresh (); - - while (1) - { - if (grub_term_poll_usb) - grub_term_poll_usb (); - - FOR_ACTIVE_TERM_INPUTS(term) - { - int key = term->checkkey (term); - if (key != -1) - return term->getkey (term); - } - - grub_cpu_idle (); - } -} +static int pending_key = GRUB_TERM_NO_KEY; int grub_checkkey (void) { grub_term_input_t term; + if (pending_key != GRUB_TERM_NO_KEY) + return pending_key; + if (grub_term_poll_usb) grub_term_poll_usb (); FOR_ACTIVE_TERM_INPUTS(term) { - int key = term->checkkey (term); - if (key != -1) - return key; + pending_key = term->getkey (term); + if (pending_key != GRUB_TERM_NO_KEY) + return pending_key; } return -1; } int -grub_getkeystatus (void) +grub_getkey (void) { - int status = 0; - grub_term_input_t term; + int ret; - if (grub_term_poll_usb) - grub_term_poll_usb (); + grub_refresh (); - FOR_ACTIVE_TERM_INPUTS(term) - { - if (term->getkeystatus) - status |= term->getkeystatus (term); - } - - return status; + grub_checkkey (); + while (pending_key == GRUB_TERM_NO_KEY) + { + grub_cpu_idle (); + grub_checkkey (); + } + ret = pending_key; + pending_key = GRUB_TERM_NO_KEY; + return ret; } + void grub_refresh (void) { diff --git a/grub-core/lib/arg.c b/grub-core/lib/arg.c index f3352520b..f487de7ad 100644 --- a/grub-core/lib/arg.c +++ b/grub-core/lib/arg.c @@ -231,7 +231,6 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, { int curarg; int arglen; - int complete = 0; char **argl = 0; int num = 0; auto grub_err_t add_arg (char *s); @@ -258,7 +257,8 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, char *option = 0; /* No option is used. */ - if (arg[0] != '-' || grub_strlen (arg) == 1) + if ((num && GRUB_COMMAND_OPTIONS_AT_START) + || arg[0] != '-' || grub_strlen (arg) == 1) { if (add_arg (arg) != 0) goto fail; @@ -269,11 +269,28 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, /* One or more short options. */ if (arg[1] != '-') { - char *curshort = arg + 1; + char *curshort; + + if (cmd->cmd->flags & GRUB_COMMAND_ACCEPT_DASH) + { + for (curshort = arg + 1; *curshort; curshort++) + if (!find_short (cmd->options, *curshort)) + break; + + if (*curshort) + { + if (add_arg (arg) != 0) + goto fail; + continue; + } + } + + curshort = arg + 1; while (1) { opt = find_short (cmd->options, *curshort); + if (! opt) { grub_error (GRUB_ERR_BAD_ARGUMENT, @@ -330,6 +347,14 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, } opt = find_long (cmd->options, arg + 2, arglen); + + if (!opt && (cmd->cmd->flags & GRUB_COMMAND_ACCEPT_DASH)) + { + if (add_arg (arg) != 0) + goto fail; + continue; + } + if (! opt) { grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown argument `%s'", arg); @@ -398,13 +423,12 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, } } - complete = 1; - *args = argl; *argnum = num; + return 1; fail: - return complete; + return 0; } struct grub_arg_list* diff --git a/grub-core/lib/crypto.c b/grub-core/lib/crypto.c index 6bd038168..f5768b8b5 100644 --- a/grub-core/lib/crypto.c +++ b/grub-core/lib/crypto.c @@ -420,7 +420,7 @@ grub_password_get (char buf[], unsigned buf_size) while (1) { - key = GRUB_TERM_ASCII_CHAR (grub_getkey ()); + key = grub_getkey (); if (key == '\n' || key == '\r') break; diff --git a/grub-core/lib/efi/halt.c b/grub-core/lib/efi/halt.c index ed3e1e1c0..c19536897 100644 --- a/grub-core/lib/efi/halt.c +++ b/grub-core/lib/efi/halt.c @@ -22,11 +22,13 @@ #include #include #include +#include void grub_halt (void) { grub_machine_fini (); + grub_acpi_halt (); efi_call_4 (grub_efi_system_table->runtime_services->reset_system, GRUB_EFI_RESET_SHUTDOWN, GRUB_EFI_SUCCESS, 0, NULL); diff --git a/grub-core/lib/i386/halt.c b/grub-core/lib/i386/halt.c index 74e0c7301..15c4ba0d6 100644 --- a/grub-core/lib/i386/halt.c +++ b/grub-core/lib/i386/halt.c @@ -18,6 +18,7 @@ #include #include +#include const char bochs_shutdown[] = "Shutdown"; @@ -40,6 +41,10 @@ grub_halt (void) { unsigned int i; +#if defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_MULTIBOOT) + grub_acpi_halt (); +#endif + /* Disable interrupts. */ __asm__ __volatile__ ("cli"); diff --git a/grub-core/lib/i386/pc/vesa_modes_table.c b/grub-core/lib/i386/pc/vesa_modes_table.c new file mode 100644 index 000000000..6dc4b7d8d --- /dev/null +++ b/grub-core/lib/i386/pc/vesa_modes_table.c @@ -0,0 +1,127 @@ + +#include + +/* This is the reverse of the table in [linux]/Documentation/fb/vesafb.txt + plus a few more modes based on the table in + http://en.wikipedia.org/wiki/VESA_BIOS_Extensions */ +struct grub_vesa_mode_table_entry +grub_vesa_mode_table[GRUB_VESA_MODE_TABLE_END + - GRUB_VESA_MODE_TABLE_START + 1] = + { + { 640, 400, 8 }, /* 0x300 */ + { 640, 480, 8 }, /* 0x301 */ + { 800, 600, 4 }, /* 0x302 */ + { 800, 600, 8 }, /* 0x303 */ + { 1024, 768, 4 }, /* 0x304 */ + { 1024, 768, 8 }, /* 0x305 */ + { 1280, 1024, 4 }, /* 0x306 */ + { 1280, 1024, 8 }, /* 0x307 */ + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 320, 200, 15 }, /* 0x30d */ + { 320, 200, 16 }, /* 0x30e */ + { 320, 200, 24 }, /* 0x30f */ + { 640, 480, 15 }, /* 0x310 */ + { 640, 480, 16 }, /* 0x311 */ + { 640, 480, 24 }, /* 0x312 */ + { 800, 600, 15 }, /* 0x313 */ + { 800, 600, 16 }, /* 0x314 */ + { 800, 600, 24 }, /* 0x315 */ + { 1024, 768, 15 }, /* 0x316 */ + { 1024, 768, 16 }, /* 0x317 */ + { 1024, 768, 24 }, /* 0x318 */ + { 1280, 1024, 15 }, /* 0x319 */ + { 1280, 1024, 16 }, /* 0x31a */ + { 1280, 1024, 24 }, /* 0x31b */ + { 1600, 1200, 8 }, /* 0x31c */ + { 1600, 1200, 15 }, /* 0x31d */ + { 1600, 1200, 16 }, /* 0x31e */ + { 1600, 1200, 24 }, /* 0x31f */ + { 0, 0, 0 }, + { 640, 400, 15 }, /* 0x321 */ + { 640, 400, 16 }, /* 0x322 */ + { 640, 400, 24 }, /* 0x323 */ + { 640, 400, 32 }, /* 0x324 */ + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 640, 480, 32 }, /* 0x329 */ + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 896, 672, 8 }, /* 0x32f */ + { 896, 672, 15 }, /* 0x330 */ + { 896, 672, 16 }, /* 0x331 */ + { 896, 672, 24 }, /* 0x332 */ + { 896, 672, 32 }, /* 0x333 */ + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 1600, 1200, 32 }, /* 0x342 */ + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 1440, 900, 8 }, /* 0x360 */ + { 1440, 900, 15 }, /* 0x361 */ + { 1440, 900, 16 }, /* 0x362 */ + { 1440, 900, 24 }, /* 0x363 */ + { 1440, 900, 32 }, /* 0x364 */ + { 1152, 720, 8 }, /* 0x365 */ + { 1152, 720, 15 }, /* 0x366 */ + { 1152, 720, 16 }, /* 0x367 */ + { 1152, 720, 24 }, /* 0x368 */ + { 1152, 720, 32 }, /* 0x369 */ + { 1024, 640, 8 }, /* 0x36a */ + { 1024, 640, 15 }, /* 0x36b */ + { 1024, 640, 16 }, /* 0x36c */ + { 1024, 640, 24 }, /* 0x36d */ + { 1024, 640, 32 }, /* 0x36e */ + { 800, 500, 8 }, /* 0x36f */ + { 800, 500, 15 }, /* 0x370 */ + { 800, 500, 16 }, /* 0x371 */ + { 800, 500, 24 }, /* 0x372 */ + { 800, 500, 32 }, /* 0x373 */ + }; diff --git a/grub-core/lib/ieee1275/relocator.c b/grub-core/lib/ieee1275/relocator.c index 947346d46..c09f1e9c5 100644 --- a/grub-core/lib/ieee1275/relocator.c +++ b/grub-core/lib/ieee1275/relocator.c @@ -27,10 +27,10 @@ grub_relocator_firmware_get_max_events (void) int counter = 0; auto int NESTED_FUNC_ATTR count (grub_uint64_t addr __attribute__ ((unused)), grub_uint64_t len __attribute__ ((unused)), - grub_uint32_t type __attribute__ ((unused))); + grub_memory_type_t type __attribute__ ((unused))); int NESTED_FUNC_ATTR count (grub_uint64_t addr __attribute__ ((unused)), grub_uint64_t len __attribute__ ((unused)), - grub_uint32_t type __attribute__ ((unused))) + grub_memory_type_t type __attribute__ ((unused))) { counter++; return 0; @@ -47,11 +47,11 @@ grub_relocator_firmware_fill_events (struct grub_relocator_mmap_event *events) { int counter = 0; auto int NESTED_FUNC_ATTR fill (grub_uint64_t addr, grub_uint64_t len, - grub_uint32_t type); + grub_memory_type_t type); int NESTED_FUNC_ATTR fill (grub_uint64_t addr, grub_uint64_t len, - grub_uint32_t type) + grub_memory_type_t type) { - if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + if (type != GRUB_MEMORY_AVAILABLE) return 0; if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM)) diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c new file mode 100644 index 000000000..6ad15dc49 --- /dev/null +++ b/grub-core/lib/legacy_parse.c @@ -0,0 +1,698 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2003,2004,2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +struct legacy_command +{ + const char *name; + const char *map; + const char *suffix; + unsigned suffixarg; + unsigned argc; + enum arg_type { + TYPE_VERBATIM, + TYPE_FORCE_OPTION, + TYPE_NOAPM_OPTION, + TYPE_TYPE_OR_NOMEM_OPTION, + TYPE_OPTION, + TYPE_FILE, + TYPE_FILE_NO_CONSUME, + TYPE_PARTITION, + TYPE_BOOL, + TYPE_INT, + TYPE_REST_VERBATIM, + TYPE_VBE_MODE + } argt[4]; + enum { + FLAG_IGNORE_REST = 1, + FLAG_FALLBACK_AVAILABLE = 4, + FLAG_FALLBACK = 8, + FLAG_COLOR_INVERT = 16, + FLAG_NO_MENUENTRY = 32, + FLAG_MENUENTRY_ONLY = 64, + } flags; + const char *shortdesc; + const char *longdesc; +}; + +struct legacy_command legacy_commands[] = + { + {"blocklist", "blocklist '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILE", + "Print the blocklist notation of the file FILE."}, + {"boot", "boot\n", NULL, 0, 0, {}, 0, 0, + "Boot the OS/chain-loader which has been loaded."}, + /* FIXME: bootp unsupported. */ + {"cat", "cat '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILE", + "Print the contents of the file FILE."}, + {"chainloader", "chainloader %s '%s'\n", NULL, 0, + 2, {TYPE_FORCE_OPTION, TYPE_FILE}, 0, "[--force] FILE", + "Load the chain-loader FILE. If --force is specified, then load it" + " forcibly, whether the boot loader signature is present or not."}, + {"cmp", "cmp '%s' '%s'\n", NULL, 0, + 2, {TYPE_FILE, TYPE_FILE}, FLAG_IGNORE_REST, "FILE1 FILE2", + "Compare the file FILE1 with the FILE2 and inform the different values" + " if any."}, + {"color", "set color_normal='%s'; set color_highlight='%s'\n", NULL, 0, + 2, {TYPE_VERBATIM, TYPE_VERBATIM}, + FLAG_IGNORE_REST | FLAG_FALLBACK_AVAILABLE, "NORMAL [HIGHLIGHT]", + "Change the menu colors. The color NORMAL is used for most" + " lines in the menu, and the color HIGHLIGHT is used to highlight the" + " line where the cursor points. If you omit HIGHLIGHT, then the" + " inverted color of NORMAL is used for the highlighted line." + " The format of a color is \"FG/BG\". FG and BG are symbolic color names." + " A symbolic color name must be one of these: black, blue, green," + " cyan, red, magenta, brown, light-gray, dark-gray, light-blue," + " light-green, light-cyan, light-red, light-magenta, yellow and white." + " But only the first eight names can be used for BG. You can prefix" + " \"blink-\" to FG if you want a blinking foreground color."}, + {"color", "set color_normal='%s'; set color_highlight='%s'\n", NULL, 0, + 1, {TYPE_VERBATIM}, + FLAG_IGNORE_REST | FLAG_FALLBACK | FLAG_COLOR_INVERT, NULL, NULL}, + {"configfile", "legacy_configfile '%s'\n", NULL, 0, 1, {TYPE_FILE}, + 0, "FILE", "Load FILE as the configuration file."}, + {"debug", + "if [ -z \"$debug\" ]; then set debug=all; else set debug=; fi\n", NULL, 0, + 0, {}, 0, 0, "Turn on/off the debug mode."}, + {"default", + "set default='%s'; if [ x\"$default\" = xsaved ]; then load_env; " + "set default=\"$saved_entry\"; fi\n", NULL, 0, 1, {TYPE_VERBATIM}, 0, + "[NUM | `saved']", + "Set the default entry to entry number NUM (if not specified, it is" + " 0, the first entry) or the entry number saved by savedefault."}, + /* FIXME: dhcp unsupported. */ + {"displayapm", "lsapm\n", NULL, 0, 0, {}, 0, 0, + "Display APM BIOS information."}, + {"displaymem", "lsmmap\n", NULL, 0, 0, {}, 0, 0, + "Display what GRUB thinks the system address space map of the" + " machine is, including all regions of physical RAM installed."}, + /* NOTE: embed unsupported. */ + {"fallback", "set fallback='%s'\n", NULL, 0, + 1, {TYPE_VERBATIM}, 0, "NUM...", + "Go into unattended boot mode: if the default boot entry has any" + " errors, instead of waiting for the user to do anything, it" + " immediately starts over using the NUM entry (same numbering as the" + " `default' command). This obviously won't help if the machine" + " was rebooted by a kernel that GRUB loaded."}, + {"find", "search -sf '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILENAME", + "Search for the filename FILENAME in all of partitions and print the list of" + " the devices which contain the file."}, + /* FIXME: fstest unsupported. */ + /* NOTE: The obsolete C/H/S geometry isn't shown anymore. */ + {"geometry", "insmod regexp; ls -l (%s*)\n", NULL, 0, 1, {TYPE_VERBATIM}, 0, "DRIVE", + "Print the information for a drive DRIVE. "}, + {"halt", "halt %s\n", NULL, 0, 1, {TYPE_NOAPM_OPTION}, 0, "[--no-apm]", + "Halt your system. If APM is available on it, turn off the power using" + " the APM BIOS, unless you specify the option `--no-apm'."}, + /* FIXME: help unsupported. */ /* NUL_TERMINATE */ + {"hiddenmenu", NULL, + "if sleep -i $timeout; then timeout=0; else timeout=-1; fi\n", 0, + 0, {}, 0, "", "Hide the menu."}, + {"hide", "parttool '%s' hidden+\n", NULL, 0, 1, {TYPE_PARTITION}, + 0, "PARTITION", + "Hide PARTITION by setting the \"hidden\" bit in" + " its partition type code."}, + /* FIXME: ifconfig unsupported. */ + /* FIXME: impsprobe unsupported. */ + {"initrd", "legacy_initrd '%s' %s\n", NULL, 0, 2, {TYPE_FILE_NO_CONSUME, + TYPE_REST_VERBATIM}, 0, + "FILE [ARG ...]", + "Load an initial ramdisk FILE for a Linux format boot image and set the" + " appropriate parameters in the Linux setup area in memory."}, + /* NOTE: install unsupported. */ + /* FIXME: ioprobe unsupported. */ + /* FIXME: really support --no-mem-option. */ + {"kernel", "legacy_kernel %s %s '%s' %s\n", NULL, 0, + 4, {TYPE_TYPE_OR_NOMEM_OPTION, TYPE_TYPE_OR_NOMEM_OPTION, + TYPE_FILE_NO_CONSUME, TYPE_REST_VERBATIM}, 0, + "[--no-mem-option] [--type=TYPE] FILE [ARG ...]", + "Attempt to load the primary boot image from FILE. The rest of the" + " line is passed verbatim as the \"kernel command line\". Any modules" + " must be reloaded after using this command. The option --type is used" + " to suggest what type of kernel to be loaded. TYPE must be either of" + " \"netbsd\", \"freebsd\", \"openbsd\", \"linux\", \"biglinux\" and" + " \"multiboot\". The option --no-mem-option tells GRUB not to pass a" + " Linux's mem option automatically."}, + {"lock", "if ! authenticate legacy; then return; fi", NULL, 0, 0, {}, 0, + 0, "Break a command execution unless the user is authenticated."}, + {"makeactive", "parttool \"$root\" boot+\n", NULL, 0, 0, {}, 0, 0, + "Set the active partition on the root disk to GRUB's root device." + " This command is limited to _primary_ PC partitions on a hard disk."}, + {"map", "drivemap '%s' '%s'\n", NULL, 0, + 2, {TYPE_PARTITION, TYPE_PARTITION}, + FLAG_IGNORE_REST, "TO_DRIVE FROM_DRIVE", + "Map the drive FROM_DRIVE to the drive TO_DRIVE. This is necessary" + " when you chain-load some operating systems, such as DOS, if such an" + " OS resides at a non-first drive."}, + /* NOTE: md5crypt unsupported since GRUB has not enough entropy and this + hash shouldn't be used anymore. */ + {"module", "legacy_initrd '%s' %s\n", NULL, 0, 2, {TYPE_FILE_NO_CONSUME, + TYPE_REST_VERBATIM}, 0, + "FILE [ARG ...]", + "Load a boot module FILE for a Multiboot format boot image (no" + " interpretation of the file contents is made, so users of this" + " command must know what the kernel in question expects). The" + " rest of the line is passed as the \"module command line\", like" + " the `kernel' command."}, + {"modulenounzip", "legacy_initrd_nounzip '%s' %s\n", NULL, 0, 2, + {TYPE_FILE_NO_CONSUME, TYPE_REST_VERBATIM}, 0, + "FILE [ARG ...]", + "The same as `module', except that automatic decompression is" + " disabled."}, + {"pager", "set pager=%s; if [ \"$pager\" = 0 ]; then " + " echo Internal pager is now off; else " + "echo Internal pager is now on; fi\n", NULL, 0, + 1, {TYPE_BOOL}, FLAG_FALLBACK_AVAILABLE, "[FLAG]", + "Toggle pager mode with no argument. If FLAG is given and its value" + " is `on', turn on the mode. If FLAG is `off', turn off the mode."}, + {"pager", + "if [ \"$pager\" = 1 ]; then pager=0; echo Internal pager is now off;" + "else pager=1; echo Internal pager is now on; fi\n", NULL, 0, 0, {}, + FLAG_FALLBACK, NULL, NULL}, + /* FIXME: partnew unsupported. */ + {"parttype", "parttool '%s' type=%s\n", NULL, 0, + 2, {TYPE_PARTITION, TYPE_INT}, 0, + "PART TYPE", "Change the type of the partition PART to TYPE."}, + {"password", "if [ \"$superusers\" = "" ]; then superusers=legacy; fi;\n" + "legacy_password %s '%s'\n", + "menuentry \"Superuser menu\" --users \"legacy\" { configfile '%s'; }\n", + 2, 3, {TYPE_OPTION, TYPE_VERBATIM, TYPE_FILE}, + FLAG_IGNORE_REST | FLAG_FALLBACK_AVAILABLE | FLAG_NO_MENUENTRY, + "[--md5] PASSWD [FILE]", + "If used in the first section of a menu file, disable all" + " interactive editing control (menu entry editor and" + " command line). If the password PASSWD is entered, it loads the" + " FILE as a new config file and restarts the GRUB Stage 2. If you" + " omit the argument FILE, then GRUB just unlocks privileged" + " instructions. You can also use it in the script section, in" + " which case it will ask for the password, before continuing." + " The option --md5 tells GRUB that PASSWD is encrypted with" + " md5crypt."}, + {"password", "if [ \"$superusers\" = "" ]; then superusers=legacy; fi;\n" + "legacy_password %s '%s'\n", NULL, 0, 2, {TYPE_OPTION, TYPE_VERBATIM}, + FLAG_IGNORE_REST | FLAG_FALLBACK | FLAG_NO_MENUENTRY, NULL, NULL}, + {"password", "if legacy_check_password %s '%s'; then configfile '%s'; " + "else return; fi\n", NULL, 2, 3, {TYPE_OPTION, TYPE_VERBATIM, TYPE_FILE}, + FLAG_IGNORE_REST | FLAG_FALLBACK_AVAILABLE | FLAG_MENUENTRY_ONLY, + NULL, NULL}, + {"password", "if ! legacy_check_password %s '%s'; then return fi;\n", + NULL, 0, 2, {TYPE_OPTION, TYPE_VERBATIM}, + FLAG_IGNORE_REST | FLAG_FALLBACK | FLAG_MENUENTRY_ONLY, NULL, NULL}, + /* NOTE: GRUB2 has a design principle of not eternally waiting for user + input. 60 seconds should be enough. + */ + {"pause", "echo %s; if ! sleep -i 60; then return; fi\n", NULL, 0, 1, + {TYPE_REST_VERBATIM}, 0, + "[MESSAGE ...]", "Print MESSAGE, then wait until a key is pressed."}, + /* FIXME: rarp unsupported. */ + {"read", "read_dword %s\n", NULL, 0, 1, {TYPE_INT}, 0, "ADDR", + "Read a 32-bit value from memory at address ADDR and" + " display it in hex format."}, + {"reboot", "reboot\n", NULL, 0, 0, {}, 0, 0, "Reboot your system."}, + {"root", "set root='%s'; set legacy_hdbias='%s'\n", NULL, 0, + 2, {TYPE_PARTITION, TYPE_INT}, FLAG_FALLBACK_AVAILABLE, + "[DEVICE [HDBIAS]]", + "Set the current \"root device\" to the device DEVICE, then" + " attempt to mount it to get the partition size (for passing the" + " partition descriptor in `ES:ESI', used by some chain-loaded" + " bootloaders), the BSD drive-type (for booting BSD kernels using" + " their native boot format), and correctly determine " + " the PC partition where a BSD sub-partition is located. The" + " optional HDBIAS parameter is a number to tell a BSD kernel" + " how many BIOS drive numbers are on controllers before the current" + " one. For example, if there is an IDE disk and a SCSI disk, and your" + " FreeBSD root partition is on the SCSI disk, then use a `1' for HDBIAS."}, + {"root", "echo \"$root\"\n", NULL, 0, 0, {}, FLAG_FALLBACK, NULL, NULL}, + {"rootnoverify", "set root='%s'; set legacy_hdbias='%s'\n", NULL, 0, + 2, {TYPE_PARTITION, TYPE_INT}, 0, + "[DEVICE [HDBIAS]]", + "Similar to `root', but don't attempt to mount the partition. This" + " is useful for when an OS is outside of the area of the disk that" + " GRUB can read, but setting the correct root device is still" + " desired. Note that the items mentioned in `root' which" + " derived from attempting the mount will NOT work correctly."}, + {"rootnoverify", "echo \"$root\"\n", NULL, 0, + 0, {}, FLAG_FALLBACK, NULL, NULL}, + /* FIXME: support saving NUM and fallback. */ + {"savedefault", "saved_entry=${chosen}; save_env saved_entry\n", NULL, 0, + 0, {}, 0, "[NUM | `fallback']", + "Save the current entry as the default boot entry if no argument is" + " specified. If a number is specified, this number is saved. If" + " `fallback' is used, next fallback entry is saved."}, + {"serial", "serial %s\n", NULL, 0, 1, {TYPE_REST_VERBATIM}, 0, + "[--unit=UNIT] [--port=PORT] [--speed=SPEED] [--word=WORD] " + "[--parity=PARITY] [--stop=STOP] [--device=DEV]", + "Initialize a serial device. UNIT is a digit that specifies which serial" + " device is used (e.g. 0 == COM1). If you need to specify the port number," + " set it by --port. SPEED is the DTE-DTE speed. WORD is the word length," + " PARITY is the type of parity, which is one of `no', `odd' and `even'." + " STOP is the length of stop bit(s). The option --device can be used only" + " in the grub shell, which specifies the file name of a tty device. The" + " default values are COM1, 9600, 8N1."}, + /* FIXME: setkey unsupported. */ /* NUL_TERMINATE */ + /* NOTE: setup unsupported. */ + /* FIXME: terminal unsupported. */ /* NUL_TERMINATE */ + /* FIXME: terminfo unsupported. */ /* NUL_TERMINATE */ + {"testload", "cat '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILE", + "Read the entire contents of FILE in several different ways and" + " compares them, to test the filesystem code. " + " If this test succeeds, then a good next" + " step is to try loading a kernel."}, + {"testvbe", "insmod vbe; videotest '%s'\n", NULL, 0, 1, {TYPE_VBE_MODE}, 0, + "MODE", "Test the VBE mode MODE. Hit any key to return."}, + /* FIXME: tftpserver unsupported. */ + {"timeout", "set timeout=%s\n", NULL, 0, 1, {TYPE_INT}, 0, "SEC", + "Set a timeout, in SEC seconds, before automatically booting the" + " default entry (normally the first entry defined)."}, + /* title is handled separately. */ + {"unhide", "parttool '%s' hidden-\n", NULL, 0, + 1, {TYPE_PARTITION}, 0, "PARTITION", + "Unhide PARTITION by clearing the \"hidden\" bit in its" + " partition type code."}, + /* FIXME: uppermem unsupported. */ + {"uuid", "search --set=root --fs-uuid '%s'\n", NULL, 0, 1, {TYPE_VERBATIM}, + 0, "UUID", "Find root by UUID"}, + {"vbeprobe", "insmod vbe; videoinfo '%s'\n", NULL, 0, 1, {TYPE_VBE_MODE}, + FLAG_FALLBACK_AVAILABLE, "[MODE]", + "Probe VBE information. If the mode number MODE is specified, show only" + " the information about only the mode."}, + {"vbeprobe", "insmod vbe; videoinfo\n", NULL, 0, 0, {}, + FLAG_FALLBACK, NULL, NULL} + }; + +char * +grub_legacy_escape (const char *in, grub_size_t len) +{ + const char *ptr; + char *ret, *outptr; + int overhead = 0; + for (ptr = in; ptr < in + len && *ptr; ptr++) + if (*ptr == '\'' || *ptr == '\\') + overhead++; + ret = grub_malloc (ptr - in + overhead + 1); + if (!ret) + return NULL; + outptr = ret; + for (ptr = in; ptr < in + len && *ptr; ptr++) + { + if (*ptr == '\'' || *ptr == '\\') + *outptr++ = '\\'; + + *outptr++ = *ptr; + } + *outptr++ = 0; + return ret; +} + +static char * +adjust_file (const char *in, grub_size_t len) +{ + const char *comma, *ptr, *rest; + char *ret, *outptr; + int overhead = 0; + int part = -1, subpart = -1; + if (in[0] != '(') + return grub_legacy_escape (in, len); + for (ptr = in + 1; ptr < in + len && *ptr && *ptr != ')' + && *ptr != ','; ptr++) + if (*ptr == '\'' || *ptr == '\\') + overhead++; + comma = ptr; + if (*comma != ',') + return grub_legacy_escape (in, len); + part = grub_strtoull (comma + 1, (char **) &rest, 0); + if (rest[0] == ',' && rest[1] >= 'a' && rest[1] <= 'z') + { + subpart = rest[1] - 'a'; + rest += 2; + } + for (ptr = rest; ptr < in + len && *ptr; ptr++) + if (*ptr == '\'' || *ptr == '\\') + overhead++; + + /* 35 is enough for any 2 numbers. */ + ret = grub_malloc (ptr - in + overhead + 35); + if (!ret) + return NULL; + + outptr = ret; + for (ptr = in; ptr < in + len && ptr <= comma; ptr++) + { + if (*ptr == '\'' || *ptr == '\\') + *outptr++ = '\\'; + + *outptr++ = *ptr; + } + if (subpart != -1) + grub_snprintf (outptr, 35, "%d,%d", part + 1, subpart + 1); + else + grub_snprintf (outptr, 35, "%d", part + 1); + while (*outptr) + outptr++; + for (ptr = rest; ptr < in + len; ptr++) + { + if (*ptr == '\'' || *ptr == '\\') + *outptr++ = '\\'; + + *outptr++ = *ptr; + } + *outptr = 0; + return ret; +} + +static int +check_option (const char *a, char *b, grub_size_t len) +{ + if (grub_strlen (b) != len) + return 0; + return grub_strncmp (a, b, len) == 0; +} + +static int +is_option (enum arg_type opt, const char *curarg, grub_size_t len) +{ + switch (opt) + { + case TYPE_NOAPM_OPTION: + return check_option (curarg, "--no-apm", len); + case TYPE_FORCE_OPTION: + return check_option (curarg, "--force", len); + case TYPE_TYPE_OR_NOMEM_OPTION: + return check_option (curarg, "--type=netbsd", len) + || check_option (curarg, "--type=freebsd", len) + || check_option (curarg, "--type=openbsd", len) + || check_option (curarg, "--type=linux", len) + || check_option (curarg, "--type=biglinux", len) + || check_option (curarg, "--type=multiboot", len) + || check_option (curarg, "--no-mem-option", len); + case TYPE_OPTION: + return (len >= 2 && curarg[0] == '-' && curarg[1] == '-'); + default: + return 0; + } +} + +char * +grub_legacy_parse (const char *buf, char **entryname, char **suffix) +{ + const char *ptr; + const char *cmdname; + unsigned i, cmdnum; + + *suffix = NULL; + + for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++); + if (!*ptr || *ptr == '#') + { + char *ret; + int len = grub_strlen (buf); + ret = grub_malloc (len + 2); + grub_memcpy (ret, buf, len); + if (len && ret[len - 1] == '\n') + ret[len] = 0; + else + { + ret[len] = '\n'; + ret[len + 1] = 0; + } + return ret; + } + + cmdname = ptr; + for (ptr = buf; *ptr && !grub_isspace (*ptr) && *ptr != '='; ptr++); + + if (entryname && grub_strncmp ("title", cmdname, ptr - cmdname) == 0 + && ptr - cmdname == sizeof ("title") - 1) + { + const char *ptr2; + for (; grub_isspace (*ptr) || *ptr == '='; ptr++); + ptr2 = ptr + grub_strlen (ptr); + while (ptr2 > ptr && grub_isspace (*(ptr2 - 1))) + ptr2--; + *entryname = grub_strndup (ptr, ptr2 - ptr); + return NULL; + } + + for (cmdnum = 0; cmdnum < ARRAY_SIZE (legacy_commands); cmdnum++) + if (grub_strncmp (legacy_commands[cmdnum].name, cmdname, ptr - cmdname) == 0 + && legacy_commands[cmdnum].name[ptr - cmdname] == 0 + && (!(*entryname != NULL && (legacy_commands[cmdnum].flags + & FLAG_NO_MENUENTRY))) + && (!(*entryname == NULL && (legacy_commands[cmdnum].flags + & FLAG_MENUENTRY_ONLY)))) + break; + if (cmdnum == ARRAY_SIZE (legacy_commands)) + return grub_xasprintf ("# Unsupported legacy command: %s\n", buf); + + for (; grub_isspace (*ptr) || *ptr == '='; ptr++); + + char *args[ARRAY_SIZE (legacy_commands[0].argt)]; + grub_memset (args, 0, sizeof (args)); + + { + int hold_arg = 0; + const char *curarg = NULL; + for (i = 0; i < legacy_commands[cmdnum].argc; i++) + { + grub_size_t curarglen; + if (hold_arg) + { + ptr = curarg; + hold_arg = 0; + } + for (; grub_isspace (*ptr); ptr++); + curarg = ptr; + if (!*curarg) + break; + for (; *ptr && !grub_isspace (*ptr); ptr++); + if (i != legacy_commands[cmdnum].argc - 1 + || (legacy_commands[cmdnum].flags & FLAG_IGNORE_REST)) + curarglen = ptr - curarg; + else + { + curarglen = grub_strlen (curarg); + while (curarglen > 0 && grub_isspace (curarg[curarglen - 1])) + curarglen--; + } + if (*ptr) + ptr++; + switch (legacy_commands[cmdnum].argt[i]) + { + case TYPE_FILE_NO_CONSUME: + hold_arg = 1; + case TYPE_PARTITION: + case TYPE_FILE: + args[i] = adjust_file (curarg, curarglen); + break; + + case TYPE_REST_VERBATIM: + { + char *outptr, *outptr0; + int overhead = 3; + ptr = curarg; + while (*ptr) + { + for (; *ptr && grub_isspace (*ptr); ptr++); + for (; *ptr && !grub_isspace (*ptr); ptr++) + if (*ptr == '\\' || *ptr == '\'') + overhead++; + if (*ptr) + ptr++; + overhead += 3; + } + outptr0 = args[i] = grub_malloc (overhead + (ptr - curarg)); + if (!outptr0) + return NULL; + ptr = curarg; + outptr = outptr0; + while (*ptr) + { + for (; *ptr && grub_isspace (*ptr); ptr++); + if (outptr != outptr0) + *outptr++ = ' '; + *outptr++ = '\''; + for (; *ptr && !grub_isspace (*ptr); ptr++) + { + if (*ptr == '\\' || *ptr == '\'') + *outptr++ = '\\'; + *outptr++ = *ptr; + } + *outptr++ = '\''; + if (*ptr) + ptr++; + } + *outptr++ = 0; + } + break; + + case TYPE_VERBATIM: + args[i] = grub_legacy_escape (curarg, curarglen); + break; + case TYPE_FORCE_OPTION: + case TYPE_NOAPM_OPTION: + case TYPE_TYPE_OR_NOMEM_OPTION: + case TYPE_OPTION: + if (is_option (legacy_commands[cmdnum].argt[i], curarg, curarglen)) + { + args[i] = grub_strndup (curarg, curarglen); + break; + } + args[i] = grub_strdup (""); + hold_arg = 1; + break; + case TYPE_INT: + { + const char *brk; + int base = 10; + brk = curarg; + if (brk[0] == '0' && brk[1] == 'x') + base = 16; + else if (brk[0] == '0') + base = 8; + for (; *brk && brk < curarg + curarglen; brk++) + { + if (base == 8 && (*brk == '8' || *brk == '9')) + break; + if (grub_isdigit (*brk)) + continue; + if (base != 16) + break; + if (!(*brk >= 'a' && *brk <= 'f') + && !(*brk >= 'A' && *brk <= 'F')) + break; + } + if (brk == curarg) + args[i] = grub_strdup ("0"); + else + args[i] = grub_strndup (curarg, brk - curarg); + } + break; + case TYPE_VBE_MODE: + { + unsigned mod; + struct grub_vesa_mode_table_entry *modedesc; + + mod = grub_strtoul (curarg, 0, 0); + if (grub_errno) + { + mod = 0; + grub_errno = GRUB_ERR_NONE; + } + if (mod < GRUB_VESA_MODE_TABLE_START + || mod > GRUB_VESA_MODE_TABLE_END) + { + args[i] = grub_strdup ("auto"); + break; + } + modedesc = &grub_vesa_mode_table[mod - GRUB_VESA_MODE_TABLE_START]; + if (!modedesc->width) + { + args[i] = grub_strdup ("auto"); + break; + } + args[i] = grub_xasprintf ("%ux%ux%u", + modedesc->width, modedesc->height, + modedesc->depth); + break; + } + case TYPE_BOOL: + if (curarglen == 2 && curarg[0] == 'o' && curarg[1] == 'n') + args[i] = grub_strdup ("1"); + else + args[i] = grub_strdup ("0"); + break; + } + } + } + + while (legacy_commands[cmdnum].argc > 0 + && args[legacy_commands[cmdnum].argc - 1] == NULL + && (legacy_commands[cmdnum].flags & FLAG_FALLBACK_AVAILABLE) + && args[legacy_commands[cmdnum + 1].argc] == NULL) + cmdnum++; + + for (; i < legacy_commands[cmdnum].argc; i++) + switch (legacy_commands[cmdnum].argt[i]) + { + case TYPE_FILE_NO_CONSUME: + case TYPE_PARTITION: + case TYPE_FILE: + case TYPE_REST_VERBATIM: + case TYPE_VERBATIM: + case TYPE_FORCE_OPTION: + case TYPE_NOAPM_OPTION: + case TYPE_TYPE_OR_NOMEM_OPTION: + case TYPE_OPTION: + args[i] = grub_strdup (""); + break; + case TYPE_BOOL: + case TYPE_INT: + args[i] = grub_strdup ("0"); + break; + case TYPE_VBE_MODE: + args[i] = grub_strdup ("auto"); + break; + } + + if (legacy_commands[cmdnum].flags & FLAG_COLOR_INVERT) + { + char *corig = args[legacy_commands[cmdnum].argc - 1]; + char *slash = grub_strchr (corig, '/'); + char *invert; + grub_size_t len; + + len = grub_strlen (corig); + if (!slash) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "bad color specification %s", + args[0]); + return NULL; + } + invert = grub_malloc (len + 1); + if (!invert) + return NULL; + grub_memcpy (invert, slash + 1, len - (slash - corig) - 1); + invert[len - (slash - args[0]) - 1] = '/'; + grub_memcpy (invert + len - (slash - corig), corig, slash - corig); + invert[len] = 0; + args[legacy_commands[cmdnum].argc] = invert; + } + + if (legacy_commands[cmdnum].suffix) + { + *suffix = grub_xasprintf (legacy_commands[cmdnum].suffix, + args[legacy_commands[cmdnum].suffixarg]); + if (*suffix) + return NULL; + } + + { + char *ret = grub_xasprintf (legacy_commands[cmdnum].map, args[0], args[1], + args[2], args[3]); + grub_free (args[0]); + grub_free (args[1]); + grub_free (args[2]); + grub_free (args[3]); + return ret; + } +} diff --git a/grub-core/lib/relocator.c b/grub-core/lib/relocator.c index 53acda52f..9a6941332 100644 --- a/grub-core/lib/relocator.c +++ b/grub-core/lib/relocator.c @@ -1379,11 +1379,13 @@ grub_relocator_alloc_chunk_align (struct grub_relocator *rel, { int found = 0; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); - int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t sz, grub_uint32_t type) + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); + int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t sz, + grub_memory_type_t type) { grub_uint64_t candidate; - if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + if (type != GRUB_MEMORY_AVAILABLE) return 0; candidate = ALIGN_UP (addr, align); if (candidate < min_addr) diff --git a/grub-core/lib/xzembed/xz_dec_stream.c b/grub-core/lib/xzembed/xz_dec_stream.c index 642492483..273041edb 100644 --- a/grub-core/lib/xzembed/xz_dec_stream.c +++ b/grub-core/lib/xzembed/xz_dec_stream.c @@ -270,7 +270,7 @@ static enum xz_ret dec_block(struct xz_dec *s, struct xz_buf *b) s->block.hash.uncompressed += s->block.uncompressed; GRUB_MD_CRC32->write(s->block.hash.crc32_context, - (const uint8_t *)&s->block.hash, sizeof(s->block.hash)); + (const uint8_t *)&s->block.hash, 2 * sizeof(vli_type)); ++s->block.count; } @@ -329,8 +329,7 @@ static enum xz_ret dec_index(struct xz_dec *s, struct xz_buf *b) s->index.hash.uncompressed += s->vli; GRUB_MD_CRC32->write(s->index.hash.crc32_context, - (const uint8_t *)&s->index.hash, - sizeof(s->index.hash)); + (const uint8_t *)&s->index.hash, 2 * sizeof(vli_type)); --s->index.count; s->index.sequence = SEQ_INDEX_UNPADDED; @@ -671,8 +670,17 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) index_update(s, b); /* Compare the hashes to validate the Index field. */ - if (! memeq(&s->block.hash, &s->index.hash, sizeof(s->block.hash))) + GRUB_MD_CRC32->final(s->block.hash.crc32_context); + GRUB_MD_CRC32->final(s->index.hash.crc32_context); + uint32_t block_crc = *(uint32_t*)GRUB_MD_CRC32->read(s->block.hash.crc32_context); + uint32_t index_crc = *(uint32_t*)GRUB_MD_CRC32->read(s->index.hash.crc32_context); + + if (s->block.hash.unpadded != s->index.hash.unpadded + || s->block.hash.uncompressed != s->index.hash.uncompressed + || block_crc != index_crc) + { return XZ_DATA_ERROR; + } s->sequence = SEQ_INDEX_CRC32; @@ -830,8 +838,15 @@ void xz_dec_reset(struct xz_dec *s) s->allow_buf_error = false; s->pos = 0; - memzero(&s->block, sizeof(s->block)); - memzero(&s->index, sizeof(s->index)); + { + uint8_t *t; + t = s->block.hash.crc32_context; + memzero(&s->block, sizeof(s->block)); + s->block.hash.crc32_context = t; + t = s->index.hash.crc32_context; + memzero(&s->index, sizeof(s->index)); + s->index.hash.crc32_context = t; + } s->temp.pos = 0; s->temp.size = STREAM_HEADER_SIZE; @@ -846,6 +861,9 @@ void xz_dec_end(struct xz_dec *s) { if (s != NULL) { xz_dec_lzma2_end(s->lzma2); + kfree(s->index.hash.crc32_context); + kfree(s->block.hash.crc32_context); + kfree(s->crc32_context); #ifdef XZ_DEC_BCJ xz_dec_bcj_end(s->bcj); #endif diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c index 2e92bc42f..456c5f36c 100644 --- a/grub-core/loader/i386/bsd.c +++ b/grub-core/loader/i386/bsd.c @@ -19,8 +19,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -261,37 +261,30 @@ generate_e820_mmap (grub_size_t *len, grub_size_t *cnt, void *buf) struct grub_e820_mmap *mmap = buf; struct grub_e820_mmap prev, cur; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, - grub_uint32_t type) + grub_memory_type_t type) { cur.addr = addr; cur.size = size; switch (type) { - case GRUB_MACHINE_MEMORY_AVAILABLE: + case GRUB_MEMORY_AVAILABLE: cur.type = GRUB_E820_RAM; break; -#ifdef GRUB_MACHINE_MEMORY_ACPI - case GRUB_MACHINE_MEMORY_ACPI: + case GRUB_MEMORY_ACPI: cur.type = GRUB_E820_ACPI; break; -#endif -#ifdef GRUB_MACHINE_MEMORY_NVS - case GRUB_MACHINE_MEMORY_NVS: + case GRUB_MEMORY_NVS: cur.type = GRUB_E820_NVS; break; -#endif default: -#ifdef GRUB_MACHINE_MEMORY_CODE - case GRUB_MACHINE_MEMORY_CODE: -#endif -#ifdef GRUB_MACHINE_MEMORY_RESERVED - case GRUB_MACHINE_MEMORY_RESERVED: -#endif + case GRUB_MEMORY_CODE: + case GRUB_MEMORY_RESERVED: cur.type = GRUB_E820_RESERVED; break; } @@ -1942,16 +1935,13 @@ GRUB_MOD_INIT (bsd) /* Net and OpenBSD kernels are often compressed. */ grub_dl_load ("gzio"); - cmd_freebsd = grub_register_extcmd ("kfreebsd", grub_cmd_freebsd, - GRUB_COMMAND_FLAG_BOTH, + cmd_freebsd = grub_register_extcmd ("kfreebsd", grub_cmd_freebsd, 0, N_("FILE"), N_("Load kernel of FreeBSD."), freebsd_opts); - cmd_openbsd = grub_register_extcmd ("kopenbsd", grub_cmd_openbsd, - GRUB_COMMAND_FLAG_BOTH, + cmd_openbsd = grub_register_extcmd ("kopenbsd", grub_cmd_openbsd, 0, N_("FILE"), N_("Load kernel of OpenBSD."), openbsd_opts); - cmd_netbsd = grub_register_extcmd ("knetbsd", grub_cmd_netbsd, - GRUB_COMMAND_FLAG_BOTH, + cmd_netbsd = grub_register_extcmd ("knetbsd", grub_cmd_netbsd, 0, N_("FILE"), N_("Load kernel of NetBSD."), netbsd_opts); cmd_freebsd_loadenv = diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c index cc2d20af3..4a6b7eafa 100644 --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -17,7 +17,6 @@ */ #include -#include #include #include #include @@ -35,6 +34,10 @@ #include #include +#ifdef GRUB_MACHINE_PCBIOS +#include +#endif + #ifdef GRUB_MACHINE_EFI #include #define HAS_VGA_TEXT 0 @@ -89,175 +92,6 @@ static struct idt_descriptor idt_desc = }; #endif -#ifdef GRUB_MACHINE_PCBIOS -struct linux_vesafb_res -{ - grub_uint16_t width; - grub_uint16_t height; -}; - -struct linux_vesafb_mode -{ - grub_uint8_t res_index; - grub_uint8_t depth; -}; - -enum vga_modes - { - VGA_320_200, - VGA_640_400, - VGA_640_480, - VGA_800_500, - VGA_800_600, - VGA_896_672, - VGA_1024_640, - VGA_1024_768, - VGA_1152_720, - VGA_1280_1024, - VGA_1440_900, - VGA_1600_1200, - }; - -static struct linux_vesafb_res linux_vesafb_res[] = - { - { 320, 200 }, - { 640, 400 }, - { 640, 480 }, - { 800, 500 }, - { 800, 600 }, - { 896, 672 }, - { 1024, 640 }, - { 1024, 768 }, - { 1152, 720 }, - { 1280, 1024 }, - { 1440, 900 }, - { 1600, 1200 }, - }; - -/* This is the reverse of the table in [linux]/Documentation/fb/vesafb.txt - plus a few more modes based on the table in - http://en.wikipedia.org/wiki/VESA_BIOS_Extensions */ -struct linux_vesafb_mode linux_vesafb_modes[] = - { - { VGA_640_400, 8 }, /* 0x300 */ - { VGA_640_480, 8 }, /* 0x301 */ - { VGA_800_600, 4 }, /* 0x302 */ - { VGA_800_600, 8 }, /* 0x303 */ - { VGA_1024_768, 4 }, /* 0x304 */ - { VGA_1024_768, 8 }, /* 0x305 */ - { VGA_1280_1024, 4 }, /* 0x306 */ - { VGA_1280_1024, 8 }, /* 0x307 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { VGA_320_200, 15 }, /* 0x30d */ - { VGA_320_200, 16 }, /* 0x30e */ - { VGA_320_200, 24 }, /* 0x30f */ - { VGA_640_480, 15 }, /* 0x310 */ - { VGA_640_480, 16 }, /* 0x311 */ - { VGA_640_480, 24 }, /* 0x312 */ - { VGA_800_600, 15 }, /* 0x313 */ - { VGA_800_600, 16 }, /* 0x314 */ - { VGA_800_600, 24 }, /* 0x315 */ - { VGA_1024_768, 15 }, /* 0x316 */ - { VGA_1024_768, 16 }, /* 0x317 */ - { VGA_1024_768, 24 }, /* 0x318 */ - { VGA_1280_1024, 15 }, /* 0x319 */ - { VGA_1280_1024, 16 }, /* 0x31a */ - { VGA_1280_1024, 24 }, /* 0x31b */ - { VGA_1600_1200, 8 }, /* 0x31c */ - { VGA_1600_1200, 15 }, /* 0x31d */ - { VGA_1600_1200, 16 }, /* 0x31e */ - { VGA_1600_1200, 24 }, /* 0x31f */ - { 0, 0 }, - { VGA_640_400, 15 }, /* 0x321 */ - { VGA_640_400, 16 }, /* 0x322 */ - { VGA_640_400, 24 }, /* 0x323 */ - { VGA_640_400, 32 }, /* 0x324 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { VGA_640_480, 32 }, /* 0x329 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { VGA_896_672, 8 }, /* 0x32f */ - { VGA_896_672, 15 }, /* 0x330 */ - { VGA_896_672, 16 }, /* 0x331 */ - { VGA_896_672, 24 }, /* 0x332 */ - { VGA_896_672, 32 }, /* 0x333 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { VGA_1600_1200, 32 }, /* 0x342 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { VGA_1440_900, 8 }, /* 0x360 */ - { VGA_1440_900, 15 }, /* 0x361 */ - { VGA_1440_900, 16 }, /* 0x362 */ - { VGA_1440_900, 24 }, /* 0x363 */ - { VGA_1440_900, 32 }, /* 0x364 */ - { VGA_1152_720, 8 }, /* 0x365 */ - { VGA_1152_720, 15 }, /* 0x366 */ - { VGA_1152_720, 16 }, /* 0x367 */ - { VGA_1152_720, 24 }, /* 0x368 */ - { VGA_1152_720, 32 }, /* 0x369 */ - { VGA_1024_640, 8 }, /* 0x36a */ - { VGA_1024_640, 15 }, /* 0x36b */ - { VGA_1024_640, 16 }, /* 0x36c */ - { VGA_1024_640, 24 }, /* 0x36d */ - { VGA_1024_640, 32 }, /* 0x36e */ - { VGA_800_500, 8 }, /* 0x36f */ - { VGA_800_500, 15 }, /* 0x370 */ - { VGA_800_500, 16 }, /* 0x371 */ - { VGA_800_500, 24 }, /* 0x372 */ - { VGA_800_500, 32 }, /* 0x373 */ - }; -#endif - static inline grub_size_t page_align (grub_size_t size) { @@ -312,10 +146,11 @@ find_mmap_size (void) { grub_size_t count = 0, mmap_size; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); int NESTED_FUNC_ATTR hook (grub_uint64_t addr __attribute__ ((unused)), grub_uint64_t size __attribute__ ((unused)), - grub_uint32_t type __attribute__ ((unused))) + grub_memory_type_t type __attribute__ ((unused))) { count++; return 0; @@ -379,12 +214,14 @@ allocate_pages (grub_size_t prot_size) /* FIXME: Should request low memory from the heap when this feature is implemented. */ - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); - int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); + int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, + grub_memory_type_t type) { /* We must put real mode code in the traditional space. */ - if (type == GRUB_MACHINE_MEMORY_AVAILABLE + if (type == GRUB_MEMORY_AVAILABLE && addr <= 0x90000) { if (addr < 0x10000) @@ -559,36 +396,32 @@ grub_linux_boot (void) grub_dprintf ("linux", "code32_start = %x\n", (unsigned) params->code32_start); - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); - int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); + int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, + grub_memory_type_t type) { switch (type) { - case GRUB_MACHINE_MEMORY_AVAILABLE: + case GRUB_MEMORY_AVAILABLE: grub_e820_add_region (params->e820_map, &e820_num, addr, size, GRUB_E820_RAM); break; -#ifdef GRUB_MACHINE_MEMORY_ACPI - case GRUB_MACHINE_MEMORY_ACPI: + case GRUB_MEMORY_ACPI: grub_e820_add_region (params->e820_map, &e820_num, addr, size, GRUB_E820_ACPI); break; -#endif -#ifdef GRUB_MACHINE_MEMORY_NVS - case GRUB_MACHINE_MEMORY_NVS: + case GRUB_MEMORY_NVS: grub_e820_add_region (params->e820_map, &e820_num, addr, size, GRUB_E820_NVS); break; -#endif -#ifdef GRUB_MACHINE_MEMORY_CODE - case GRUB_MACHINE_MEMORY_CODE: + case GRUB_MEMORY_CODE: grub_e820_add_region (params->e820_map, &e820_num, addr, size, GRUB_E820_EXEC_CODE); break; -#endif default: grub_e820_add_region (params->e820_map, &e820_num, @@ -882,7 +715,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), /* Video mode selection support. */ char *val = argv[i] + 4; unsigned vid_mode = GRUB_LINUX_VID_MODE_NORMAL; - struct linux_vesafb_mode *linux_mode; + struct grub_vesa_mode_table_entry *linux_mode; grub_err_t err; char *buf; @@ -925,9 +758,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), break; default: /* Ignore invalid values. */ - if (vid_mode < GRUB_LINUX_VID_MODE_VESA_START || - vid_mode >= GRUB_LINUX_VID_MODE_VESA_START + - ARRAY_SIZE (linux_vesafb_modes)) + if (vid_mode < GRUB_VESA_MODE_TABLE_START || + vid_mode > GRUB_VESA_MODE_TABLE_END) { grub_env_set ("gfxpayload", "text"); grub_printf ("%s is deprecated. Mode %d isn't recognized. " @@ -941,15 +773,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), is built-in because `vga=' parameter was used. */ params->have_vga = GRUB_VIDEO_LINUX_TYPE_VESA; - linux_mode - = &linux_vesafb_modes[vid_mode - GRUB_LINUX_VID_MODE_VESA_START]; + linux_mode = &grub_vesa_mode_table[vid_mode + - GRUB_VESA_MODE_TABLE_START]; buf = grub_xasprintf ("%ux%ux%u,%ux%u", - linux_vesafb_res[linux_mode->res_index].width, - linux_vesafb_res[linux_mode->res_index].height, + linux_mode->width, linux_mode->height, linux_mode->depth, - linux_vesafb_res[linux_mode->res_index].width, - linux_vesafb_res[linux_mode->res_index].height); + linux_mode->width, linux_mode->height); if (! buf) goto fail; diff --git a/grub-core/loader/i386/multiboot_mbi.c b/grub-core/loader/i386/multiboot_mbi.c index bf17863cf..1c9a77b8b 100644 --- a/grub-core/loader/i386/multiboot_mbi.c +++ b/grub-core/loader/i386/multiboot_mbi.c @@ -16,10 +16,10 @@ * along with GRUB. If not, see . */ -#include #include #ifdef GRUB_MACHINE_PCBIOS #include +#include #endif #include #include @@ -194,7 +194,8 @@ grub_multiboot_get_mbi_size (void) + ALIGN_UP (sizeof(PACKAGE_STRING), 4) + grub_get_multiboot_mmap_count () * sizeof (struct multiboot_mmap_entry) + elf_sec_entsize * elf_sec_num - + 256 * sizeof (struct multiboot_color); + + 256 * sizeof (struct multiboot_color) + + ALIGN_UP (sizeof (struct multiboot_apm_info), 4); } /* Fill previously allocated Multiboot mmap. */ @@ -203,28 +204,26 @@ grub_fill_multiboot_mmap (struct multiboot_mmap_entry *first_entry) { struct multiboot_mmap_entry *mmap_entry = (struct multiboot_mmap_entry *) first_entry; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); - int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); + int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, + grub_memory_type_t type) { mmap_entry->addr = addr; mmap_entry->len = size; switch (type) { - case GRUB_MACHINE_MEMORY_AVAILABLE: + case GRUB_MEMORY_AVAILABLE: mmap_entry->type = MULTIBOOT_MEMORY_AVAILABLE; break; -#ifdef GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE - case GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE: + case GRUB_MEMORY_ACPI: mmap_entry->type = MULTIBOOT_MEMORY_ACPI_RECLAIMABLE; break; -#endif -#ifdef GRUB_MACHINE_MEMORY_NVS - case GRUB_MACHINE_MEMORY_NVS: + case GRUB_MEMORY_NVS: mmap_entry->type = MULTIBOOT_MEMORY_NVS; break; -#endif default: mmap_entry->type = MULTIBOOT_MEMORY_RESERVED; @@ -356,6 +355,29 @@ grub_multiboot_make_mbi (grub_uint32_t *target) ptrorig += ALIGN_UP (sizeof(PACKAGE_STRING), 4); ptrdest += ALIGN_UP (sizeof(PACKAGE_STRING), 4); +#ifdef GRUB_MACHINE_PCBIOS + { + struct grub_apm_info info; + if (grub_apm_get_info (&info)) + { + struct multiboot_apm_info *mbinfo = (void *) ptrorig; + + mbinfo->cseg = info.cseg; + mbinfo->offset = info.offset; + mbinfo->cseg_16 = info.cseg_16; + mbinfo->dseg = info.dseg; + mbinfo->flags = info.flags; + mbinfo->cseg_len = info.cseg_len; + mbinfo->dseg_len = info.dseg_len; + mbinfo->cseg_16_len = info.cseg_16_len; + mbinfo->version = info.version; + + ptrorig += ALIGN_UP (sizeof (struct multiboot_apm_info), 4); + ptrdest += ALIGN_UP (sizeof (struct multiboot_apm_info), 4); + } + } +#endif + if (modcnt) { mbi->flags |= MULTIBOOT_INFO_MODS; diff --git a/grub-core/loader/i386/pc/chainloader.c b/grub-core/loader/i386/pc/chainloader.c index e76f84f08..fd99c81d5 100644 --- a/grub-core/loader/i386/pc/chainloader.c +++ b/grub-core/loader/i386/pc/chainloader.c @@ -20,19 +20,20 @@ #include #include #include +#include #include #include #include #include #include #include -#include #include -#include +#include #include #include #include #include +#include #include #include #include diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c index 2f5dfec70..90de70f66 100644 --- a/grub-core/loader/i386/pc/linux.c +++ b/grub-core/loader/i386/pc/linux.c @@ -25,8 +25,7 @@ #include #include #include -#include -#include +#include #include #include #include diff --git a/grub-core/loader/mips/linux.c b/grub-core/loader/mips/linux.c index 48f77dffb..44ab64eb5 100644 --- a/grub-core/loader/mips/linux.c +++ b/grub-core/loader/mips/linux.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include /* For frequencies. */ diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c index 8780ec061..c6182109b 100644 --- a/grub-core/loader/multiboot.c +++ b/grub-core/loader/multiboot.c @@ -21,17 +21,14 @@ * FIXME: The following features from the Multiboot specification still * need to be implemented: * - VBE support - * - symbol table * - drives table * - ROM configuration table - * - APM table */ #include #include #include #include -#include #include #include #include @@ -73,7 +70,7 @@ grub_get_multiboot_mmap_count (void) auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); int NESTED_FUNC_ATTR hook (grub_uint64_t addr __attribute__ ((unused)), grub_uint64_t size __attribute__ ((unused)), - grub_uint32_t type __attribute__ ((unused))) + grub_memory_type_t type __attribute__ ((unused))) { count++; return 0; diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c index f453dcc6a..08b882ed7 100644 --- a/grub-core/loader/multiboot_mbi2.c +++ b/grub-core/loader/multiboot_mbi2.c @@ -16,10 +16,11 @@ * along with GRUB. If not, see . */ -#include #include #ifdef GRUB_MACHINE_PCBIOS #include +#include +#include #endif #include #include @@ -279,7 +280,8 @@ grub_multiboot_get_mbi_size (void) + elf_sec_entsize * elf_sec_num + (sizeof (struct multiboot_tag_mmap) + grub_get_multiboot_mmap_count () * sizeof (struct multiboot_mmap_entry)) - + sizeof (struct multiboot_tag_vbe) + MULTIBOOT_TAG_ALIGN - 1; + + sizeof (struct multiboot_tag_vbe) + MULTIBOOT_TAG_ALIGN - 1 + + sizeof (struct multiboot_tag_apm) + MULTIBOOT_TAG_ALIGN - 1; } /* Fill previously allocated Multiboot mmap. */ @@ -288,28 +290,26 @@ grub_fill_multiboot_mmap (struct multiboot_tag_mmap *tag) { struct multiboot_mmap_entry *mmap_entry = tag->entries; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); - int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); + int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, + grub_memory_type_t type) { mmap_entry->addr = addr; mmap_entry->len = size; switch (type) { - case GRUB_MACHINE_MEMORY_AVAILABLE: + case GRUB_MEMORY_AVAILABLE: mmap_entry->type = MULTIBOOT_MEMORY_AVAILABLE; break; -#ifdef GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE - case GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE: + case GRUB_MEMORY_ACPI: mmap_entry->type = MULTIBOOT_MEMORY_ACPI_RECLAIMABLE; break; -#endif -#ifdef GRUB_MACHINE_MEMORY_NVS - case GRUB_MACHINE_MEMORY_NVS: + case GRUB_MEMORY_NVS: mmap_entry->type = MULTIBOOT_MEMORY_NVS; break; -#endif default: mmap_entry->type = MULTIBOOT_MEMORY_RESERVED; @@ -515,6 +515,31 @@ grub_multiboot_make_mbi (grub_uint32_t *target) ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); } +#ifdef GRUB_MACHINE_PCBIOS + { + struct grub_apm_info info; + if (grub_apm_get_info (&info)) + { + struct multiboot_tag_apm *tag = (struct multiboot_tag_apm *) ptrorig; + + tag->type = MULTIBOOT_TAG_TYPE_APM; + tag->size = sizeof (struct multiboot_tag_apm); + + tag->cseg = info.cseg; + tag->offset = info.offset; + tag->cseg_16 = info.cseg_16; + tag->dseg = info.dseg; + tag->flags = info.flags; + tag->cseg_len = info.cseg_len; + tag->dseg_len = info.dseg_len; + tag->cseg_16_len = info.cseg_16_len; + tag->version = info.version; + + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + } + } +#endif + { unsigned i; struct module *cur; diff --git a/grub-core/loader/sparc64/ieee1275/linux.c b/grub-core/loader/sparc64/ieee1275/linux.c index 177a6976e..d4b5f2aea 100644 --- a/grub-core/loader/sparc64/ieee1275/linux.c +++ b/grub-core/loader/sparc64/ieee1275/linux.c @@ -24,9 +24,9 @@ #include #include #include -#include #include #include +#include static grub_dl_t my_mod; @@ -182,8 +182,10 @@ alloc_phys (grub_addr_t size) { grub_addr_t ret = (grub_addr_t) -1; - auto int NESTED_FUNC_ATTR choose (grub_uint64_t addr, grub_uint64_t len __attribute__((unused)), grub_uint32_t type); - int NESTED_FUNC_ATTR choose (grub_uint64_t addr, grub_uint64_t len __attribute__((unused)), grub_uint32_t type) + auto int NESTED_FUNC_ATTR choose (grub_uint64_t addr, grub_uint64_t len, + grub_memory_type_t type); + int NESTED_FUNC_ATTR choose (grub_uint64_t addr, grub_uint64_t len, + grub_memory_type_t type) { grub_addr_t end = addr + len; diff --git a/grub-core/loader/xnu.c b/grub-core/loader/xnu.c index ece65611a..d0b32dc6f 100644 --- a/grub-core/loader/xnu.c +++ b/grub-core/loader/xnu.c @@ -1434,8 +1434,7 @@ GRUB_MOD_INIT(xnu) "Load XNU ramdisk. " "It will be seen as md0."); cmd_splash = grub_register_extcmd ("xnu_splash", - grub_cmd_xnu_splash, - GRUB_COMMAND_FLAG_BOTH, 0, + grub_cmd_xnu_splash, 0, 0, N_("Load a splash image for XNU."), xnu_splash_cmd_options); diff --git a/grub-core/mmap/efi/mmap.c b/grub-core/mmap/efi/mmap.c index 316c997c7..5b82a8717 100644 --- a/grub-core/mmap/efi/mmap.c +++ b/grub-core/mmap/efi/mmap.c @@ -29,9 +29,7 @@ ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size))) grub_err_t -grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, - grub_uint64_t, - grub_uint32_t)) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { grub_efi_uintn_t mmap_size = 0; grub_efi_memory_descriptor_t *map_buf = 0; @@ -69,7 +67,12 @@ grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, { case GRUB_EFI_RUNTIME_SERVICES_CODE: hook (desc->physical_start, desc->num_pages * 4096, - GRUB_MACHINE_MEMORY_CODE); + GRUB_MEMORY_CODE); + break; + + case GRUB_EFI_UNUSABLE_MEMORY: + hook (desc->physical_start, desc->num_pages * 4096, + GRUB_MEMORY_BADRAM); break; default: @@ -78,12 +81,11 @@ grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, case GRUB_EFI_RESERVED_MEMORY_TYPE: case GRUB_EFI_RUNTIME_SERVICES_DATA: - case GRUB_EFI_UNUSABLE_MEMORY: case GRUB_EFI_MEMORY_MAPPED_IO: case GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE: case GRUB_EFI_PAL_CODE: hook (desc->physical_start, desc->num_pages * 4096, - GRUB_MACHINE_MEMORY_RESERVED); + GRUB_MEMORY_RESERVED); break; case GRUB_EFI_LOADER_CODE: @@ -92,17 +94,17 @@ grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, case GRUB_EFI_BOOT_SERVICES_DATA: case GRUB_EFI_CONVENTIONAL_MEMORY: hook (desc->physical_start, desc->num_pages * 4096, - GRUB_MACHINE_MEMORY_AVAILABLE); + GRUB_MEMORY_AVAILABLE); break; case GRUB_EFI_ACPI_RECLAIM_MEMORY: hook (desc->physical_start, desc->num_pages * 4096, - GRUB_MACHINE_MEMORY_ACPI); + GRUB_MEMORY_ACPI); break; case GRUB_EFI_ACPI_MEMORY_NVS: hook (desc->physical_start, desc->num_pages * 4096, - GRUB_MACHINE_MEMORY_NVS); + GRUB_MEMORY_NVS); break; } } @@ -115,29 +117,26 @@ make_efi_memtype (int type) { switch (type) { - case GRUB_MACHINE_MEMORY_CODE: + case GRUB_MEMORY_CODE: return GRUB_EFI_RUNTIME_SERVICES_CODE; /* No way to remove a chunk of memory from EFI mmap. So mark it as unusable. */ - case GRUB_MACHINE_MEMORY_HOLE: - - default: - - case GRUB_MACHINE_MEMORY_RESERVED: + case GRUB_MEMORY_HOLE: + case GRUB_MEMORY_RESERVED: return GRUB_EFI_UNUSABLE_MEMORY; - case GRUB_MACHINE_MEMORY_AVAILABLE: + case GRUB_MEMORY_AVAILABLE: return GRUB_EFI_CONVENTIONAL_MEMORY; - case GRUB_MACHINE_MEMORY_ACPI: - return GRUB_EFI_ACPI_RECLAIM_MEMORY; - - case GRUB_MACHINE_MEMORY_NVS: + case GRUB_MEMORY_ACPI: return GRUB_EFI_ACPI_RECLAIM_MEMORY; + case GRUB_MEMORY_NVS: + return GRUB_EFI_ACPI_MEMORY_NVS; } + return GRUB_EFI_UNUSABLE_MEMORY; } struct overlay diff --git a/grub-core/mmap/i386/mmap.c b/grub-core/mmap/i386/mmap.c index f6e16129e..e9c030b7b 100644 --- a/grub-core/mmap/i386/mmap.c +++ b/grub-core/mmap/i386/mmap.c @@ -18,6 +18,7 @@ */ #include +#include #include #include #include @@ -33,12 +34,12 @@ grub_mmap_malign_and_register (grub_uint64_t align, grub_uint64_t size, grub_uint64_t highestlow = 0; auto int NESTED_FUNC_ATTR find_hook (grub_uint64_t, grub_uint64_t, - grub_uint32_t); + grub_memory_type_t); int NESTED_FUNC_ATTR find_hook (grub_uint64_t start, grub_uint64_t rangesize, - grub_uint32_t memtype) + grub_memory_type_t memtype) { grub_uint64_t end = start + rangesize; - if (memtype != GRUB_MACHINE_MEMORY_AVAILABLE) + if (memtype != GRUB_MEMORY_AVAILABLE) return 0; if (end > 0x100000) end = 0x100000; diff --git a/grub-core/mmap/i386/pc/mmap.c b/grub-core/mmap/i386/pc/mmap.c index 7d5a43fec..8dec083f8 100644 --- a/grub-core/mmap/i386/pc/mmap.c +++ b/grub-core/mmap/i386/pc/mmap.c @@ -57,7 +57,7 @@ preboot (int noreturn __attribute__ ((unused))) auto int NESTED_FUNC_ATTR fill_hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); int NESTED_FUNC_ATTR fill_hook (grub_uint64_t addr, grub_uint64_t size, - grub_uint32_t type) + grub_memory_type_t type) { grub_dprintf ("mmap", "mmap chunk %llx-%llx:%x\n", addr, addr + size, type); hookmmapcur->addr = addr; @@ -135,7 +135,7 @@ malloc_hook (void) grub_uint32_t); int NESTED_FUNC_ATTR count_hook (grub_uint64_t addr __attribute__ ((unused)), grub_uint64_t size __attribute__ ((unused)), - grub_uint32_t type __attribute__ ((unused))) + grub_memory_type_t type __attribute__ ((unused))) { regcount++; return 0; @@ -172,7 +172,7 @@ malloc_hook (void) reentry = 1; hooktarget = grub_mmap_malign_and_register (16, hooksize, &mmapregion, - GRUB_MACHINE_MEMORY_RESERVED, + GRUB_MEMORY_RESERVED, GRUB_MMAP_MALLOC_LOW); reentry = 0; diff --git a/grub-core/mmap/i386/uppermem.c b/grub-core/mmap/i386/uppermem.c index cd1a45239..2aa430155 100644 --- a/grub-core/mmap/i386/uppermem.c +++ b/grub-core/mmap/i386/uppermem.c @@ -18,6 +18,7 @@ */ #include +#include #include #include @@ -26,11 +27,12 @@ grub_mmap_get_lower (void) { grub_uint64_t lower = 0; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, - grub_uint32_t type) + grub_memory_type_t type) { - if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + if (type != GRUB_MEMORY_AVAILABLE) return 0; if (addr == 0) lower = size; @@ -48,11 +50,12 @@ grub_mmap_get_upper (void) { grub_uint64_t upper = 0; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, - grub_uint32_t type) + grub_memory_type_t type) { - if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + if (type != GRUB_MEMORY_AVAILABLE) return 0; if (addr <= 0x100000 && addr + size > 0x100000) upper = addr + size - 0x100000; @@ -69,11 +72,12 @@ grub_mmap_get_post64 (void) { grub_uint64_t post64 = 0; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, - grub_uint32_t type) + grub_memory_type_t type) { - if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + if (type != GRUB_MEMORY_AVAILABLE) return 0; if (addr <= 0x4000000 && addr + size > 0x4000000) post64 = addr + size - 0x4000000; diff --git a/grub-core/mmap/mips/yeeloong/uppermem.c b/grub-core/mmap/mips/yeeloong/uppermem.c index 3c5f814de..723b6a888 100644 --- a/grub-core/mmap/mips/yeeloong/uppermem.c +++ b/grub-core/mmap/mips/yeeloong/uppermem.c @@ -27,11 +27,12 @@ grub_mmap_get_lower (void) { grub_uint64_t lower = 0; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, - grub_uint32_t type) + grub_memory_type_t type) { - if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + if (type != GRUB_MEMORY_AVAILABLE) return 0; if (addr == 0) lower = size; @@ -49,11 +50,12 @@ grub_mmap_get_upper (void) { grub_uint64_t upper = 0; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, - grub_uint32_t type) + grub_memory_type_t type) { - if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + if (type != GRUB_MEMORY_AVAILABLE) return 0; if (addr <= GRUB_ARCH_HIGHMEMPSTART && addr + size > GRUB_ARCH_HIGHMEMPSTART) diff --git a/grub-core/mmap/mmap.c b/grub-core/mmap/mmap.c index a1afc8b06..7c3430e9f 100644 --- a/grub-core/mmap/mmap.c +++ b/grub-core/mmap/mmap.c @@ -17,8 +17,8 @@ * along with GRUB. If not, see . */ -#include #include +#include #include #include #include @@ -34,8 +34,7 @@ static int curhandle = 1; #endif grub_err_t -grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, - grub_uint64_t, grub_uint32_t)) +grub_mmap_iterate (grub_memory_hook_t hook) { /* This function resolves overlapping regions and sorts the memory map. @@ -48,27 +47,17 @@ grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, 3 - unusable memory 4 - a range deliberately empty */ - int priority[GRUB_MACHINE_MEMORY_MAX_TYPE + 2] = + int priority[] = { -#ifdef GRUB_MACHINE_MEMORY_AVAILABLE - [GRUB_MACHINE_MEMORY_AVAILABLE] = 1, -#endif -#if defined (GRUB_MACHINE_MEMORY_RESERVED) && GRUB_MACHINE_MEMORY_RESERVED != GRUB_MACHINE_MEMORY_HOLE - [GRUB_MACHINE_MEMORY_RESERVED] = 3, -#endif -#ifdef GRUB_MACHINE_MEMORY_ACPI - [GRUB_MACHINE_MEMORY_ACPI] = 2, -#endif -#ifdef GRUB_MACHINE_MEMORY_CODE - [GRUB_MACHINE_MEMORY_CODE] = 3, -#endif -#ifdef GRUB_MACHINE_MEMORY_NVS - [GRUB_MACHINE_MEMORY_NVS] = 3, -#endif - [GRUB_MACHINE_MEMORY_HOLE] = 4, + [GRUB_MEMORY_AVAILABLE] = 1, + [GRUB_MEMORY_RESERVED] = 3, + [GRUB_MEMORY_ACPI] = 2, + [GRUB_MEMORY_CODE] = 3, + [GRUB_MEMORY_NVS] = 3, + [GRUB_MEMORY_HOLE] = 4, }; - int i, k, done; + int i, done; /* Scanline events. */ struct grub_mmap_scan @@ -89,7 +78,7 @@ grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, /* Current scanline event. */ int curtype; /* How many regions of given type overlap at current location? */ - int present[GRUB_MACHINE_MEMORY_MAX_TYPE + 2]; + int present[ARRAY_SIZE (priority)]; /* Number of mmap chunks. */ int mmap_num; @@ -101,7 +90,7 @@ grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint32_t); int NESTED_FUNC_ATTR count_hook (grub_uint64_t addr __attribute__ ((unused)), grub_uint64_t size __attribute__ ((unused)), - grub_uint32_t type __attribute__ ((unused))) + grub_memory_type_t type __attribute__ ((unused))) { mmap_num++; return 0; @@ -111,17 +100,17 @@ grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint32_t); int NESTED_FUNC_ATTR fill_hook (grub_uint64_t addr, grub_uint64_t size, - grub_uint32_t type) + grub_memory_type_t type) { scanline_events[i].pos = addr; scanline_events[i].type = 0; - if (type <= GRUB_MACHINE_MEMORY_MAX_TYPE && priority[type]) + if (type < ARRAY_SIZE (priority) && priority[type]) scanline_events[i].memtype = type; else { grub_dprintf ("mmap", "Unknown memory type %d. Assuming unusable\n", type); - scanline_events[i].memtype = GRUB_MACHINE_MEMORY_RESERVED; + scanline_events[i].memtype = GRUB_MEMORY_RESERVED; } i++; @@ -160,12 +149,10 @@ grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, { scanline_events[i].pos = cur->start; scanline_events[i].type = 0; - if (cur->type == GRUB_MACHINE_MEMORY_HOLE - || (cur->type >= 0 && cur->type <= GRUB_MACHINE_MEMORY_MAX_TYPE - && priority[cur->type])) + if (cur->type < ARRAY_SIZE (priority) && priority[cur->type]) scanline_events[i].memtype = cur->type; else - scanline_events[i].memtype = GRUB_MACHINE_MEMORY_RESERVED; + scanline_events[i].memtype = GRUB_MEMORY_RESERVED; i++; scanline_events[i].pos = cur->end; @@ -201,6 +188,7 @@ grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, lasttype = scanline_events[0].memtype; for (i = 0; i < 2 * mmap_num; i++) { + unsigned k; /* Process event. */ if (scanline_events[i].type) present[scanline_events[i].memtype]--; @@ -209,7 +197,7 @@ grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, /* Determine current region type. */ curtype = -1; - for (k = 0; k <= GRUB_MACHINE_MEMORY_MAX_TYPE + 1; k++) + for (k = 0; k < ARRAY_SIZE (priority); k++) if (present[k] && (curtype == -1 || priority[k] > priority[curtype])) curtype = k; @@ -217,7 +205,7 @@ grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, if ((curtype == -1 || curtype != lasttype) && lastaddr != scanline_events[i].pos && lasttype != -1 - && lasttype != GRUB_MACHINE_MEMORY_HOLE + && lasttype != GRUB_MEMORY_HOLE && hook (lastaddr, scanline_events[i].pos - lastaddr, lasttype)) { grub_free (scanline_events); @@ -324,10 +312,11 @@ grub_cmd_badram (grub_command_t cmd __attribute__ ((unused)), char * str; grub_uint64_t badaddr, badmask; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, - grub_uint32_t type __attribute__ ((unused))) + grub_memory_type_t type __attribute__ ((unused))) { grub_uint64_t iterator, low, high, cur; int tail, var; @@ -370,7 +359,7 @@ grub_cmd_badram (grub_command_t cmd __attribute__ ((unused)), { grub_dprintf ("badram", "%llx (size %llx) is a badram range\n", (unsigned long long) cur, (1ULL << tail)); - grub_mmap_register (cur, (1ULL << tail), GRUB_MACHINE_MEMORY_HOLE); + grub_mmap_register (cur, (1ULL << tail), GRUB_MEMORY_HOLE); } return 0; } diff --git a/grub-core/normal/auth.c b/grub-core/normal/auth.c index bf1efbfdd..459d4cdbd 100644 --- a/grub-core/normal/auth.c +++ b/grub-core/normal/auth.c @@ -161,7 +161,7 @@ grub_username_get (char buf[], unsigned buf_size) while (1) { - key = GRUB_TERM_ASCII_CHAR (grub_getkey ()); + key = grub_getkey (); if (key == '\n' || key == '\r') break; @@ -248,3 +248,27 @@ grub_auth_check_authentication (const char *userlist) return GRUB_ACCESS_DENIED; } + +static grub_err_t +grub_cmd_authenticate (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + return grub_auth_check_authentication ((argc >= 1) ? args[0] : ""); +} + +static grub_command_t cmd; + +void +grub_normal_auth_init (void) +{ + cmd = grub_register_command ("authenticate", + grub_cmd_authenticate, + N_("[USERLIST]"), N_("Authenticate users")); + +} + +void +grub_normal_auth_fini (void) +{ + grub_unregister_command (cmd); +} diff --git a/grub-core/normal/cmdline.c b/grub-core/normal/cmdline.c index 3647dcd3a..b8c20d91c 100644 --- a/grub-core/normal/cmdline.c +++ b/grub-core/normal/cmdline.c @@ -388,16 +388,18 @@ grub_cmdline_get (const char *prompt) grub_refresh (); - while ((key = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != '\n' && key != '\r') + while ((key = grub_getkey ()) != '\n' && key != '\r') { switch (key) { - case 1: /* Ctrl-a */ + case GRUB_TERM_CTRL | 'a': + case GRUB_TERM_KEY_HOME: lpos = 0; cl_set_pos_all (); break; - case 2: /* Ctrl-b */ + case GRUB_TERM_CTRL | 'b': + case GRUB_TERM_KEY_LEFT: if (lpos > 0) { lpos--; @@ -405,12 +407,14 @@ grub_cmdline_get (const char *prompt) } break; - case 5: /* Ctrl-e */ + case GRUB_TERM_CTRL | 'e': + case GRUB_TERM_KEY_END: lpos = llen; cl_set_pos_all (); break; - case 6: /* Ctrl-f */ + case GRUB_TERM_CTRL | 'f': + case GRUB_TERM_KEY_RIGHT: if (lpos < llen) { lpos++; @@ -418,7 +422,8 @@ grub_cmdline_get (const char *prompt) } break; - case 9: /* Ctrl-i or TAB */ + case GRUB_TERM_CTRL | 'i': + case '\t': { int restore; char *insertu8; @@ -492,7 +497,7 @@ grub_cmdline_get (const char *prompt) } break; - case 11: /* Ctrl-k */ + case GRUB_TERM_CTRL | 'k': if (lpos < llen) { if (kill_buf) @@ -516,7 +521,8 @@ grub_cmdline_get (const char *prompt) } break; - case 14: /* Ctrl-n */ + case GRUB_TERM_CTRL | 'n': + case GRUB_TERM_KEY_DOWN: { grub_uint32_t *hist; @@ -534,7 +540,9 @@ grub_cmdline_get (const char *prompt) break; } - case 16: /* Ctrl-p */ + + case GRUB_TERM_KEY_UP: + case GRUB_TERM_CTRL | 'p': { grub_uint32_t *hist; @@ -553,7 +561,7 @@ grub_cmdline_get (const char *prompt) } break; - case 21: /* Ctrl-u */ + case GRUB_TERM_CTRL | 'u': if (lpos > 0) { grub_size_t n = lpos; @@ -579,7 +587,7 @@ grub_cmdline_get (const char *prompt) } break; - case 25: /* Ctrl-y */ + case GRUB_TERM_CTRL | 'y': if (kill_buf) cl_insert (kill_buf); break; @@ -598,7 +606,8 @@ grub_cmdline_get (const char *prompt) break; /* fall through */ - case 4: /* Ctrl-d */ + case GRUB_TERM_CTRL | 'd': + case GRUB_TERM_KEY_DC: if (lpos < llen) cl_delete (1); break; diff --git a/grub-core/normal/completion.c b/grub-core/normal/completion.c index 1b51dab3a..197cb1145 100644 --- a/grub-core/normal/completion.c +++ b/grub-core/normal/completion.c @@ -160,14 +160,23 @@ iterate_dev (const char *devname) if (dev) { - if (dev->disk && dev->disk->has_partitions) + char tmp[grub_strlen (devname) + sizeof (",")]; + + grub_memcpy (tmp, devname, grub_strlen (devname)); + + if (grub_strcmp (devname, current_word) == 0) { - if (add_completion (devname, ",", GRUB_COMPLETION_TYPE_DEVICE)) + if (add_completion (devname, ")", GRUB_COMPLETION_TYPE_PARTITION)) return 1; + + if (dev->disk) + if (grub_partition_iterate (dev->disk, iterate_partition)) + return 1; } else { - if (add_completion (devname, ")", GRUB_COMPLETION_TYPE_DEVICE)) + grub_memcpy (tmp + grub_strlen (devname), "", sizeof ("")); + if (add_completion (tmp, "", GRUB_COMPLETION_TYPE_DEVICE)) return 1; } } @@ -200,7 +209,7 @@ complete_device (void) if (dev) { - if (dev->disk && dev->disk->has_partitions) + if (dev->disk) { if (grub_partition_iterate (dev->disk, iterate_partition)) { @@ -247,7 +256,8 @@ complete_file (void) goto fail; } - dir = grub_strchr (current_word, '/'); + dir = grub_strchr (current_word + (device ? 2 + grub_strlen (device) : 0), + '/'); last_dir = grub_strrchr (current_word, '/'); if (dir) { @@ -419,11 +429,8 @@ grub_normal_do_completion (char *buf, int *restore, { if (cmd->prio & GRUB_PRIO_LIST_FLAG_ACTIVE) { - if (cmd->flags & GRUB_COMMAND_FLAG_CMDLINE) - { - if (add_completion (cmd->name, " ", GRUB_COMPLETION_TYPE_COMMAND)) - goto fail; - } + if (add_completion (cmd->name, " ", GRUB_COMPLETION_TYPE_COMMAND)) + goto fail; } } } diff --git a/grub-core/normal/dyncmd.c b/grub-core/normal/dyncmd.c index 3519253f6..ed98855eb 100644 --- a/grub-core/normal/dyncmd.c +++ b/grub-core/normal/dyncmd.c @@ -155,7 +155,6 @@ read_command_list (const char *prefix) grub_dyncmd_dispatcher, GRUB_COMMAND_FLAG_BLOCKS | GRUB_COMMAND_FLAG_EXTCMD - | GRUB_COMMAND_FLAG_CMDLINE | GRUB_COMMAND_FLAG_DYNCMD, 0, N_("not loaded"), 0, prio); diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c index c7e83fba0..f2e5eaf51 100644 --- a/grub-core/normal/main.c +++ b/grub-core/normal/main.c @@ -477,6 +477,7 @@ GRUB_MOD_INIT(normal) /* Previously many modules depended on gzio. Be nice to user and load it. */ grub_dl_load ("gzio"); + grub_normal_auth_init (); grub_context_init (); grub_script_init (); grub_menu_init (); @@ -520,6 +521,7 @@ GRUB_MOD_FINI(normal) grub_context_fini (); grub_script_fini (); grub_menu_fini (); + grub_normal_auth_fini (); grub_xputs = grub_xputs_saved; diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c index 6827a893f..62b0d0a6a 100644 --- a/grub-core/normal/menu.c +++ b/grub-core/normal/menu.c @@ -407,7 +407,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) if (grub_checkkey () >= 0 || timeout < 0) { - c = GRUB_TERM_ASCII_CHAR (grub_getkey ()); + c = grub_getkey (); if (timeout >= 0) { @@ -418,31 +418,36 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) switch (c) { - case GRUB_TERM_HOME: + case GRUB_TERM_KEY_HOME: + case GRUB_TERM_CTRL | 'a': current_entry = 0; menu_set_chosen_entry (current_entry); break; - case GRUB_TERM_END: + case GRUB_TERM_KEY_END: + case GRUB_TERM_CTRL | 'e': current_entry = menu->size - 1; menu_set_chosen_entry (current_entry); break; - case GRUB_TERM_UP: + case GRUB_TERM_KEY_UP: + case GRUB_TERM_CTRL | 'p': case '^': if (current_entry > 0) current_entry--; menu_set_chosen_entry (current_entry); break; - case GRUB_TERM_DOWN: + case GRUB_TERM_CTRL | 'n': + case GRUB_TERM_KEY_DOWN: case 'v': if (current_entry < menu->size - 1) current_entry++; menu_set_chosen_entry (current_entry); break; - case GRUB_TERM_PPAGE: + case GRUB_TERM_CTRL | 'g': + case GRUB_TERM_KEY_PPAGE: if (current_entry < GRUB_MENU_PAGE_SIZE) current_entry = 0; else @@ -450,7 +455,8 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) menu_set_chosen_entry (current_entry); break; - case GRUB_TERM_NPAGE: + case GRUB_TERM_CTRL | 'c': + case GRUB_TERM_KEY_NPAGE: if (current_entry + GRUB_MENU_PAGE_SIZE < menu->size) current_entry += GRUB_MENU_PAGE_SIZE; else @@ -460,7 +466,8 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) case '\n': case '\r': - case 6: + case GRUB_TERM_KEY_RIGHT: + case GRUB_TERM_CTRL | 'f': menu_fini (); *auto_boot = 0; return current_entry; diff --git a/grub-core/normal/menu_entry.c b/grub-core/normal/menu_entry.c index 238c94ecd..87292d445 100644 --- a/grub-core/normal/menu_entry.c +++ b/grub-core/normal/menu_entry.c @@ -1272,7 +1272,7 @@ grub_menu_entry_run (grub_menu_entry_t entry) while (1) { - int c = GRUB_TERM_ASCII_CHAR (grub_getkey ()); + int c = grub_getkey (); if (screen->completion_shown) { @@ -1288,70 +1288,79 @@ grub_menu_entry_run (grub_menu_entry_t entry) switch (c) { - case 16: /* C-p */ + case GRUB_TERM_KEY_UP: + case GRUB_TERM_CTRL | 'p': if (! previous_line (screen, 1)) goto fail; break; - case 14: /* C-n */ + case GRUB_TERM_CTRL | 'n': + case GRUB_TERM_KEY_DOWN: if (! next_line (screen, 1)) goto fail; break; - case 6: /* C-f */ + case GRUB_TERM_CTRL | 'f': + case GRUB_TERM_KEY_RIGHT: if (! forward_char (screen, 1)) goto fail; break; - case 2: /* C-b */ + case GRUB_TERM_CTRL | 'b': + case GRUB_TERM_KEY_LEFT: if (! backward_char (screen, 1)) goto fail; break; - case 1: /* C-a */ + case GRUB_TERM_CTRL | 'a': + case GRUB_TERM_KEY_HOME: if (! beginning_of_line (screen, 1)) goto fail; break; - case 5: /* C-e */ + case GRUB_TERM_CTRL | 'e': + case GRUB_TERM_KEY_END: if (! end_of_line (screen, 1)) goto fail; break; - case '\t': /* C-i */ + case GRUB_TERM_CTRL | 'i': + case '\t': if (! complete (screen, prev_c == c, 1)) goto fail; break; - case 4: /* C-d */ + case GRUB_TERM_CTRL | 'd': + case GRUB_TERM_KEY_DC: if (! delete_char (screen, 1)) goto fail; break; - case 8: /* C-h */ + case GRUB_TERM_CTRL | 'h': + case '\b': if (! backward_delete_char (screen, 1)) goto fail; break; - case 11: /* C-k */ + case GRUB_TERM_CTRL | 'k': if (! kill_line (screen, prev_c == c, 1)) goto fail; break; - case 21: /* C-u */ + case GRUB_TERM_CTRL | 'u': /* FIXME: What behavior is good for this key? */ break; - case 25: /* C-y */ + case GRUB_TERM_CTRL | 'y': if (! yank (screen, 1)) goto fail; break; - case 12: /* C-l */ + case GRUB_TERM_CTRL | 'l': /* FIXME: centering. */ goto refresh; - case 15: /* C-o */ + case GRUB_TERM_CTRL | 'o': if (! open_line (screen, 1)) goto fail; break; @@ -1366,11 +1375,13 @@ grub_menu_entry_run (grub_menu_entry_t entry) destroy_screen (screen); return; - case 3: /* C-c */ + case GRUB_TERM_CTRL | 'c': + case GRUB_TERM_KEY_F2: grub_cmdline_run (1); goto refresh; - case 24: /* C-x */ + case GRUB_TERM_CTRL | 'x': + case GRUB_TERM_KEY_F10: { int chars_before = grub_normal_get_char_counter (); run (screen); @@ -1380,9 +1391,9 @@ grub_menu_entry_run (grub_menu_entry_t entry) } goto refresh; - case 18: /* C-r */ - case 19: /* C-s */ - case 20: /* C-t */ + case GRUB_TERM_CTRL | 'r': + case GRUB_TERM_CTRL | 's': + case GRUB_TERM_CTRL | 't': /* FIXME */ break; diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c index 3e3e7e2fa..fc4a89196 100644 --- a/grub-core/normal/menu_text.c +++ b/grub-core/normal/menu_text.c @@ -120,17 +120,10 @@ print_message (int nested, int edit, struct grub_term_output *term) if (edit) { grub_putcode ('\n', term); -#ifdef GRUB_MACHINE_EFI grub_print_message_indented (_("Minimum Emacs-like screen editing is \ -supported. TAB lists completions. Press F1 to boot, F2=Ctrl-a, F3=Ctrl-e, \ -F4 for a command-line or ESC to discard edits and return to the GRUB menu."), - STANDARD_MARGIN, STANDARD_MARGIN, term); -#else - grub_print_message_indented (_("Minimum Emacs-like screen editing is \ -supported. TAB lists completions. Press Ctrl-x to boot, Ctrl-c for a \ +supported. TAB lists completions. Press Ctrl-x or F10 to boot, Ctrl-c or F2 for a \ command-line or ESC to discard edits and return to the GRUB menu."), STANDARD_MARGIN, STANDARD_MARGIN, term); -#endif } else { diff --git a/grub-core/normal/misc.c b/grub-core/normal/misc.c index 2b84b1c82..d81b6d26f 100644 --- a/grub-core/normal/misc.c +++ b/grub-core/normal/misc.c @@ -26,6 +26,7 @@ #include #include #include +#include /* Print the information on the device NAME. */ grub_err_t @@ -107,10 +108,18 @@ grub_normal_print_device_info (const char *name) grub_errno = GRUB_ERR_NONE; } } - else if (! dev->disk->has_partitions || dev->disk->partition) - grub_printf ("%s", _("Unknown filesystem")); else - grub_printf ("%s", _("Partition table")); + grub_printf ("%s", _("Not a known filesystem")); + + if (dev->disk->partition) + grub_printf (_(" - Partition start at %u"), + grub_partition_get_start (dev->disk->partition)); + if (grub_disk_get_size (dev->disk) == GRUB_DISK_SIZE_UNKNOWN) + grub_printf (_(" - Total size unknown"), + grub_disk_get_size (dev->disk)); + else + grub_printf (_(" - Total size %u sectors"), + grub_disk_get_size (dev->disk)); grub_device_close (dev); } diff --git a/grub-core/normal/term.c b/grub-core/normal/term.c index b55c0f06a..760900e86 100644 --- a/grub-core/normal/term.c +++ b/grub-core/normal/term.c @@ -657,7 +657,7 @@ put_glyphs_terminal (const struct grub_unicode_glyph *visual, >= (grub_ssize_t) grub_term_height (term) - 2) { state->backlog_glyphs = visual_ptr + 1; - state->backlog_len = visual_len - (visual - visual_ptr) - 1; + state->backlog_len = visual_len - (visual_ptr - visual) - 1; return 1; } @@ -688,6 +688,7 @@ print_backlog (struct grub_term_output *term, grub_free (state->free); state->free = NULL; state->backlog_len = 0; + state->backlog_ucs4 = 0; } return ret; } @@ -703,6 +704,7 @@ print_backlog (struct grub_term_output *term, grub_free (state->free); state->free = NULL; state->backlog_len = 0; + state->backlog_glyphs = 0; } return ret; } diff --git a/grub-core/partmap/gpt.c b/grub-core/partmap/gpt.c index 0dd670cce..c9393d932 100644 --- a/grub-core/partmap/gpt.c +++ b/grub-core/partmap/gpt.c @@ -32,6 +32,10 @@ static grub_uint8_t grub_gpt_magic[8] = static const grub_gpt_part_type_t grub_gpt_partition_type_empty = GRUB_GPT_PARTITION_TYPE_EMPTY; +#ifdef GRUB_UTIL +static const grub_gpt_part_type_t grub_gpt_partition_type_bios_boot = GRUB_GPT_PARTITION_TYPE_BIOS_BOOT; +#endif + /* 512 << 7 = 65536 byte sectors. */ #define MAX_SECTOR_LOG 7 @@ -97,6 +101,7 @@ gpt_partition_map_iterate (grub_disk_t disk, part.number = i; part.index = last_offset; part.partmap = &grub_gpt_partition_map; + part.parent = disk->partition; grub_dprintf ("gpt", "GPT entry %d: start=%lld, length=%lld\n", i, (unsigned long long) part.start, @@ -117,12 +122,73 @@ gpt_partition_map_iterate (grub_disk_t disk, return GRUB_ERR_NONE; } +#ifdef GRUB_UTIL +static grub_err_t +gpt_partition_map_embed (struct grub_disk *disk, unsigned int nsectors, + grub_embed_type_t embed_type, + grub_disk_addr_t *sectors) +{ + grub_disk_addr_t start = 0, len = 0; + unsigned i; + grub_err_t err; + + auto int NESTED_FUNC_ATTR find_usable_region (grub_disk_t disk, + const grub_partition_t p); + int NESTED_FUNC_ATTR find_usable_region (grub_disk_t disk __attribute__ ((unused)), + const grub_partition_t p) + { + struct grub_gpt_partentry gptdata; + + disk->partition = p->parent; + if (grub_disk_read (disk, p->offset, p->index, + sizeof (gptdata), &gptdata)) + return 0; + + /* If there's an embed region, it is in a dedicated partition. */ + if (! grub_memcmp (&gptdata.type, &grub_gpt_partition_type_bios_boot, 16)) + { + start = p->start; + len = p->len; + return 1; + } + + return 0; + } + + if (embed_type != GRUB_EMBED_PCBIOS) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "GPT curently supports only PC-BIOS embedding"); + + err = gpt_partition_map_iterate (disk, find_usable_region); + if (err) + return err; + + if (len == 0) + return grub_error (GRUB_ERR_FILE_NOT_FOUND, + "This GPT partition label has no BIOS Boot Partition;" + " embedding won't be possible!"); + + if (len < nsectors) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "Your BIOS Boot Partition is too small;" + " embedding won't be possible!"); + + for (i = 0; i < nsectors; i++) + sectors[i] = start + i; + + return GRUB_ERR_NONE; +} +#endif + /* Partition map type. */ static struct grub_partition_map grub_gpt_partition_map = { .name = "gpt", .iterate = gpt_partition_map_iterate, +#ifdef GRUB_UTIL + .embed = gpt_partition_map_embed +#endif }; GRUB_MOD_INIT(part_gpt) diff --git a/grub-core/partmap/msdos.c b/grub-core/partmap/msdos.c index 3898d09fa..7dab4aa0f 100644 --- a/grub-core/partmap/msdos.c +++ b/grub-core/partmap/msdos.c @@ -133,12 +133,128 @@ pc_partition_map_iterate (grub_disk_t disk, return grub_errno; } +#ifdef GRUB_UTIL +static grub_err_t +pc_partition_map_embed (struct grub_disk *disk, unsigned int nsectors, + grub_embed_type_t embed_type, + grub_disk_addr_t *sectors) +{ + grub_disk_addr_t end = ~0ULL; + struct grub_msdos_partition_mbr mbr; + int labeln = 0; + /* Any value different than `p.offset' will satisfy the check during + first loop. */ + grub_disk_addr_t lastaddr = 1; + grub_disk_addr_t ext_offset = 0; + grub_disk_addr_t offset = 0; + + if (embed_type != GRUB_EMBED_PCBIOS) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "PC-style partitions curently support " + "only PC-BIOS embedding"); + + if (disk->partition) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "Embedding on MSDOS subpartition isn't supported"); + + while (1) + { + int i; + struct grub_msdos_partition_entry *e; + grub_err_t err; + + /* Read the MBR. */ + err = grub_disk_read (disk, offset, 0, sizeof (mbr), &mbr); + if (err) + return err; + + /* This is our loop-detection algorithm. It works the following way: + It saves last position which was a power of two. Then it compares the + saved value with a current one. This way it's guaranteed that the loop + will be broken by at most third walk. + */ + if (labeln && lastaddr == offset) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "loop detected"); + + labeln++; + if ((labeln & (labeln - 1)) == 0) + lastaddr = offset; + + /* Check if it is valid. */ + if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE)) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature"); + + for (i = 0; i < 4; i++) + if (mbr.entries[i].flag & 0x7f) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "bad boot flag"); + + /* Analyze DOS partitions. */ + for (i = 0; i < 4; i++) + { + e = mbr.entries + i; + + if (!grub_msdos_partition_is_empty (e->type) + && end > offset + grub_le_to_cpu32 (e->start)) + end = offset + grub_le_to_cpu32 (e->start); + + /* If this is a GPT partition, this MBR is just a dummy. */ + if (e->type == GRUB_PC_PARTITION_TYPE_GPT_DISK && i == 0) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "dummy mbr"); + } + + /* Find an extended partition. */ + for (i = 0; i < 4; i++) + { + e = mbr.entries + i; + + if (grub_msdos_partition_is_extended (e->type)) + { + offset = ext_offset + grub_le_to_cpu32 (e->start); + if (! ext_offset) + ext_offset = offset; + + break; + } + } + + /* If no extended partition, the end. */ + if (i == 4) + break; + } + + if (end >= nsectors + 1) + { + int i; + for (i = 0; i < nsectors; i++) + sectors[i] = 1 + i; + return GRUB_ERR_NONE; + } + + if (end <= 1) + return grub_error (GRUB_ERR_FILE_NOT_FOUND, + "This msdos-style partition label has no " + "post-MBR gap; embedding won't be possible!"); + + if (nsectors > 62) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "Your core.img is unusually large. " + "It won't fit in the embedding area."); + + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "Your embedding area is unusually small. " + "core.img won't fit in it."); +} +#endif + /* Partition map type. */ static struct grub_partition_map grub_msdos_partition_map = { .name = "msdos", .iterate = pc_partition_map_iterate, +#ifdef GRUB_UTIL + .embed = pc_partition_map_embed +#endif }; GRUB_MOD_INIT(part_msdos) diff --git a/grub-core/partmap/sun.c b/grub-core/partmap/sun.c index 7a7eaef27..7af95c939 100644 --- a/grub-core/partmap/sun.c +++ b/grub-core/partmap/sun.c @@ -87,36 +87,23 @@ sun_partition_map_iterate (grub_disk_t disk, int (*hook) (grub_disk_t disk, const grub_partition_t partition)) { - grub_partition_t p; + struct grub_partition p; struct grub_sun_block block; int partnum; grub_err_t err; - p = (grub_partition_t) grub_zalloc (sizeof (struct grub_partition)); - if (! p) - return grub_errno; - - p->partmap = &grub_sun_partition_map; + p.partmap = &grub_sun_partition_map; err = grub_disk_read (disk, 0, 0, sizeof (struct grub_sun_block), &block); if (err) - { - grub_free (p); - return err; - } + return err; if (GRUB_PARTMAP_SUN_MAGIC != grub_be_to_cpu16 (block.magic)) - { - grub_free (p); - return grub_error (GRUB_ERR_BAD_PART_TABLE, "not a sun partition table"); - } + return grub_error (GRUB_ERR_BAD_PART_TABLE, "not a sun partition table"); if (! grub_sun_is_valid (&block)) - { - grub_free (p); return grub_error (GRUB_ERR_BAD_PART_TABLE, "invalid checksum"); - } - + /* Maybe another error value would be better, because partition table _is_ recognized but invalid. */ for (partnum = 0; partnum < GRUB_PARTMAP_SUN_MAX_PARTS; partnum++) @@ -128,20 +115,18 @@ sun_partition_map_iterate (grub_disk_t disk, continue; desc = &block.partitions[partnum]; - p->start = ((grub_uint64_t) grub_be_to_cpu32 (desc->start_cylinder) + p.start = ((grub_uint64_t) grub_be_to_cpu32 (desc->start_cylinder) * grub_be_to_cpu16 (block.ntrks) * grub_be_to_cpu16 (block.nsect)); - p->len = grub_be_to_cpu32 (desc->num_sectors); - p->number = p->index = partnum; - if (p->len) + p.len = grub_be_to_cpu32 (desc->num_sectors); + p.number = p.index = partnum; + if (p.len) { - if (hook (disk, p)) + if (hook (disk, &p)) partnum = GRUB_PARTMAP_SUN_MAX_PARTS; } } - grub_free (p); - return grub_errno; } diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c index a7baee96c..e24c4b1af 100644 --- a/grub-core/script/execute.c +++ b/grub-core/script/execute.c @@ -547,13 +547,32 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd) grub_script_function_t func = 0; char errnobuf[18]; char *cmdname; + int argc; + char **args; + int invert; struct grub_script_argv argv = { 0, 0, 0 }; /* Lookup the command. */ if (grub_script_arglist_to_argv (cmdline->arglist, &argv) || ! argv.args[0]) return grub_errno; + invert = 0; + argc = argv.argc - 1; + args = argv.args + 1; cmdname = argv.args[0]; + if (grub_strcmp (cmdname, "!") == 0) + { + if (argv.argc < 2 || ! argv.args[1]) + { + grub_script_argv_free (&argv); + return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing arguments"); + } + + invert = 1; + argc = argv.argc - 2; + args = argv.args + 2; + cmdname = argv.args[1]; + } grubcmd = grub_command_find (cmdname); if (! grubcmd) { @@ -594,13 +613,25 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd) { if ((grubcmd->flags & GRUB_COMMAND_FLAG_BLOCKS) && (grubcmd->flags & GRUB_COMMAND_FLAG_EXTCMD)) - ret = grub_extcmd_dispatcher (grubcmd, argv.argc - 1, argv.args + 1, - argv.script); + ret = grub_extcmd_dispatcher (grubcmd, argc, args, argv.script); else - ret = (grubcmd->func) (grubcmd, argv.argc - 1, argv.args + 1); + ret = (grubcmd->func) (grubcmd, argc, args); } else - ret = grub_script_function_call (func, argv.argc - 1, argv.args + 1); + ret = grub_script_function_call (func, argc, args); + + if (invert) + { + if (ret == GRUB_ERR_TEST_FAILURE) + grub_errno = ret = GRUB_ERR_NONE; + else if (ret == GRUB_ERR_NONE) + ret = grub_error (GRUB_ERR_TEST_FAILURE, "false"); + else + { + grub_print_error (); + ret = GRUB_ERR_NONE; + } + } /* Free arguments. */ grub_script_argv_free (&argv); diff --git a/grub-core/script/yylex.l b/grub-core/script/yylex.l index d4cad8097..55620b6bd 100644 --- a/grub-core/script/yylex.l +++ b/grub-core/script/yylex.l @@ -155,7 +155,6 @@ MULTILINE {WORD}?((\"{DQCHR}*)|(\'{SQCHR}*)|(\\\n)) ">" { RECORD; return GRUB_PARSER_TOKEN_GT; } /* Reserved words */ -"!" { RECORD; return GRUB_PARSER_TOKEN_NOT; } "{" { RECORD; return GRUB_PARSER_TOKEN_LBR; } "}" { RECORD; return GRUB_PARSER_TOKEN_RBR; } "[[" { RECORD; return GRUB_PARSER_TOKEN_RSQBR2; } diff --git a/grub-core/term/at_keyboard.c b/grub-core/term/at_keyboard.c index 25f32a0a5..1b130bd62 100644 --- a/grub-core/term/at_keyboard.c +++ b/grub-core/term/at_keyboard.c @@ -22,18 +22,13 @@ #include #include #include +#include +#include +#include static short at_keyboard_status = 0; -static int pending_key = -1; - -#define KEYBOARD_STATUS_SHIFT_L (1 << 0) -#define KEYBOARD_STATUS_SHIFT_R (1 << 1) -#define KEYBOARD_STATUS_ALT_L (1 << 2) -#define KEYBOARD_STATUS_ALT_R (1 << 3) -#define KEYBOARD_STATUS_CTRL_L (1 << 4) -#define KEYBOARD_STATUS_CTRL_R (1 << 5) -#define KEYBOARD_STATUS_CAPS_LOCK (1 << 6) -#define KEYBOARD_STATUS_NUM_LOCK (1 << 7) +static int e0_received = 0; +static int f0_received = 0; static grub_uint8_t led_status; @@ -41,36 +36,179 @@ static grub_uint8_t led_status; #define KEYBOARD_LED_NUM (1 << 1) #define KEYBOARD_LED_CAPS (1 << 2) -static char keyboard_map[128] = -{ - '\0', GRUB_TERM_ESC, '1', '2', '3', '4', '5', '6', - '7', '8', '9', '0', '-', '=', GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, - 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', - 'o', 'p', '[', ']', '\n', '\0', 'a', 's', - 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', - '\'', '`', '\0', '\\', 'z', 'x', 'c', 'v', - 'b', 'n', 'm', ',', '.', '/', '\0', '*', - '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0', - '\0', '\0', '\0', '\0', '\0', '\0', '\0', GRUB_TERM_HOME, - GRUB_TERM_UP, GRUB_TERM_NPAGE, '-', GRUB_TERM_LEFT, '\0', GRUB_TERM_RIGHT, '+', GRUB_TERM_END, - GRUB_TERM_DOWN, GRUB_TERM_PPAGE, '\0', GRUB_TERM_DC, '\0', '\0', '\0', '\0', - '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', - '\0', '\0', '\0', '\0', '\0', OLPC_UP, OLPC_DOWN, OLPC_LEFT, - OLPC_RIGHT -}; - -static char keyboard_map_shift[128] = -{ - '\0', '\0', '!', '@', '#', '$', '%', '^', - '&', '*', '(', ')', '_', '+', '\0', '\0', - 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', - 'O', 'P', '{', '}', '\n', '\0', 'A', 'S', - 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', - '\"', '~', '\0', '|', 'Z', 'X', 'C', 'V', - 'B', 'N', 'M', '<', '>', '?' -}; - static grub_uint8_t grub_keyboard_controller_orig; +static grub_uint8_t grub_keyboard_orig_set; +static grub_uint8_t current_set; + +static const grub_uint8_t set1_mapping[128] = + { + /* 0x00 */ 0 /* Unused */, GRUB_KEYBOARD_KEY_ESCAPE, + /* 0x02 */ GRUB_KEYBOARD_KEY_1, GRUB_KEYBOARD_KEY_2, + /* 0x04 */ GRUB_KEYBOARD_KEY_3, GRUB_KEYBOARD_KEY_4, + /* 0x06 */ GRUB_KEYBOARD_KEY_5, GRUB_KEYBOARD_KEY_6, + /* 0x08 */ GRUB_KEYBOARD_KEY_7, GRUB_KEYBOARD_KEY_8, + /* 0x0a */ GRUB_KEYBOARD_KEY_9, GRUB_KEYBOARD_KEY_0, + /* 0x0c */ GRUB_KEYBOARD_KEY_DASH, GRUB_KEYBOARD_KEY_EQUAL, + /* 0x0e */ GRUB_KEYBOARD_KEY_BACKSPACE, GRUB_KEYBOARD_KEY_TAB, + /* 0x10 */ GRUB_KEYBOARD_KEY_Q, GRUB_KEYBOARD_KEY_W, + /* 0x12 */ GRUB_KEYBOARD_KEY_E, GRUB_KEYBOARD_KEY_R, + /* 0x14 */ GRUB_KEYBOARD_KEY_T, GRUB_KEYBOARD_KEY_Y, + /* 0x16 */ GRUB_KEYBOARD_KEY_U, GRUB_KEYBOARD_KEY_I, + /* 0x18 */ GRUB_KEYBOARD_KEY_O, GRUB_KEYBOARD_KEY_P, + /* 0x1a */ GRUB_KEYBOARD_KEY_LBRACKET, GRUB_KEYBOARD_KEY_RBRACKET, + /* 0x1c */ GRUB_KEYBOARD_KEY_ENTER, GRUB_KEYBOARD_KEY_LEFT_CTRL, + /* 0x1e */ GRUB_KEYBOARD_KEY_A, GRUB_KEYBOARD_KEY_S, + /* 0x20 */ GRUB_KEYBOARD_KEY_D, GRUB_KEYBOARD_KEY_F, + /* 0x22 */ GRUB_KEYBOARD_KEY_G, GRUB_KEYBOARD_KEY_H, + /* 0x24 */ GRUB_KEYBOARD_KEY_J, GRUB_KEYBOARD_KEY_K, + /* 0x26 */ GRUB_KEYBOARD_KEY_L, GRUB_KEYBOARD_KEY_SEMICOLON, + /* 0x28 */ GRUB_KEYBOARD_KEY_DQUOTE, GRUB_KEYBOARD_KEY_RQUOTE, + /* 0x2a */ GRUB_KEYBOARD_KEY_LEFT_SHIFT, GRUB_KEYBOARD_KEY_BACKSLASH, + /* 0x2c */ GRUB_KEYBOARD_KEY_Z, GRUB_KEYBOARD_KEY_X, + /* 0x2e */ GRUB_KEYBOARD_KEY_C, GRUB_KEYBOARD_KEY_V, + /* 0x30 */ GRUB_KEYBOARD_KEY_B, GRUB_KEYBOARD_KEY_N, + /* 0x32 */ GRUB_KEYBOARD_KEY_M, GRUB_KEYBOARD_KEY_COMMA, + /* 0x34 */ GRUB_KEYBOARD_KEY_DOT, GRUB_KEYBOARD_KEY_SLASH, + /* 0x36 */ GRUB_KEYBOARD_KEY_RIGHT_SHIFT, GRUB_KEYBOARD_KEY_NUMMUL, + /* 0x38 */ GRUB_KEYBOARD_KEY_LEFT_ALT, GRUB_KEYBOARD_KEY_SPACE, + /* 0x3a */ GRUB_KEYBOARD_KEY_CAPS_LOCK, GRUB_KEYBOARD_KEY_F1, + /* 0x3c */ GRUB_KEYBOARD_KEY_F2, GRUB_KEYBOARD_KEY_F3, + /* 0x3e */ GRUB_KEYBOARD_KEY_F4, GRUB_KEYBOARD_KEY_F5, + /* 0x40 */ GRUB_KEYBOARD_KEY_F6, GRUB_KEYBOARD_KEY_F7, + /* 0x42 */ GRUB_KEYBOARD_KEY_F8, GRUB_KEYBOARD_KEY_F9, + /* 0x44 */ GRUB_KEYBOARD_KEY_F10, GRUB_KEYBOARD_KEY_NUM_LOCK, + /* 0x46 */ GRUB_KEYBOARD_KEY_SCROLL_LOCK, GRUB_KEYBOARD_KEY_NUM7, + /* 0x48 */ GRUB_KEYBOARD_KEY_NUM8, GRUB_KEYBOARD_KEY_NUM9, + /* 0x4a */ GRUB_KEYBOARD_KEY_NUMMINUS, GRUB_KEYBOARD_KEY_NUM4, + /* 0x4c */ GRUB_KEYBOARD_KEY_NUM5, GRUB_KEYBOARD_KEY_NUM6, + /* 0x4e */ GRUB_KEYBOARD_KEY_NUMPLUS, GRUB_KEYBOARD_KEY_NUM1, + /* 0x50 */ GRUB_KEYBOARD_KEY_NUM2, GRUB_KEYBOARD_KEY_NUM3, + /* 0x52 */ GRUB_KEYBOARD_KEY_NUMDOT, GRUB_KEYBOARD_KEY_NUMDOT, + /* 0x54 */ 0, 0, + /* 0x56 */ GRUB_KEYBOARD_KEY_102ND, GRUB_KEYBOARD_KEY_F11, + /* 0x58 */ GRUB_KEYBOARD_KEY_F12, 0, + /* 0x5a */ 0, 0, + /* 0x5c */ 0, 0, + /* 0x5e */ 0, 0, + /* 0x60 */ 0, 0, + /* 0x62 */ 0, 0, + /* OLPC keys. Just mapped to normal keys. */ + /* 0x64 */ 0, GRUB_KEYBOARD_KEY_UP, + /* 0x66 */ GRUB_KEYBOARD_KEY_DOWN, GRUB_KEYBOARD_KEY_LEFT, + /* 0x68 */ GRUB_KEYBOARD_KEY_RIGHT + }; + +static const struct +{ + grub_uint8_t from, to; +} set1_e0_mapping[] = + { + {0x1c, GRUB_KEYBOARD_KEY_NUMENTER}, + {0x1d, GRUB_KEYBOARD_KEY_RIGHT_CTRL}, + {0x35, GRUB_KEYBOARD_KEY_NUMSLASH }, + {0x38, GRUB_KEYBOARD_KEY_RIGHT_ALT}, + {0x47, GRUB_KEYBOARD_KEY_HOME}, + {0x48, GRUB_KEYBOARD_KEY_UP}, + {0x49, GRUB_KEYBOARD_KEY_NPAGE}, + {0x4b, GRUB_KEYBOARD_KEY_LEFT}, + {0x4d, GRUB_KEYBOARD_KEY_RIGHT}, + {0x4f, GRUB_KEYBOARD_KEY_END}, + {0x50, GRUB_KEYBOARD_KEY_DOWN}, + {0x51, GRUB_KEYBOARD_KEY_PPAGE}, + {0x52, GRUB_KEYBOARD_KEY_INSERT}, + {0x53, GRUB_KEYBOARD_KEY_DELETE}, + }; + +static const grub_uint8_t set2_mapping[256] = + { + /* 0x00 */ 0, GRUB_KEYBOARD_KEY_F9, + /* 0x02 */ 0, GRUB_KEYBOARD_KEY_F5, + /* 0x04 */ GRUB_KEYBOARD_KEY_F3, GRUB_KEYBOARD_KEY_F1, + /* 0x06 */ GRUB_KEYBOARD_KEY_F2, GRUB_KEYBOARD_KEY_F12, + /* 0x08 */ 0, GRUB_KEYBOARD_KEY_F10, + /* 0x0a */ GRUB_KEYBOARD_KEY_F8, GRUB_KEYBOARD_KEY_F6, + /* 0x0c */ GRUB_KEYBOARD_KEY_F4, GRUB_KEYBOARD_KEY_TAB, + /* 0x0e */ GRUB_KEYBOARD_KEY_RQUOTE, 0, + /* 0x10 */ 0, GRUB_KEYBOARD_KEY_LEFT_ALT, + /* 0x12 */ GRUB_KEYBOARD_KEY_LEFT_SHIFT, 0, + /* 0x14 */ GRUB_KEYBOARD_KEY_LEFT_CTRL, GRUB_KEYBOARD_KEY_Q, + /* 0x16 */ GRUB_KEYBOARD_KEY_1, 0, + /* 0x18 */ 0, 0, + /* 0x1a */ GRUB_KEYBOARD_KEY_Z, GRUB_KEYBOARD_KEY_S, + /* 0x1c */ GRUB_KEYBOARD_KEY_A, GRUB_KEYBOARD_KEY_W, + /* 0x1e */ GRUB_KEYBOARD_KEY_2, 0, + /* 0x20 */ 0, GRUB_KEYBOARD_KEY_C, + /* 0x22 */ GRUB_KEYBOARD_KEY_X, GRUB_KEYBOARD_KEY_D, + /* 0x24 */ GRUB_KEYBOARD_KEY_E, GRUB_KEYBOARD_KEY_4, + /* 0x26 */ GRUB_KEYBOARD_KEY_3, 0, + /* 0x28 */ 0, GRUB_KEYBOARD_KEY_SPACE, + /* 0x2a */ GRUB_KEYBOARD_KEY_V, GRUB_KEYBOARD_KEY_F, + /* 0x2c */ GRUB_KEYBOARD_KEY_T, GRUB_KEYBOARD_KEY_R, + /* 0x2e */ GRUB_KEYBOARD_KEY_5, 0, + /* 0x30 */ 0, GRUB_KEYBOARD_KEY_N, + /* 0x32 */ GRUB_KEYBOARD_KEY_B, GRUB_KEYBOARD_KEY_H, + /* 0x34 */ GRUB_KEYBOARD_KEY_G, GRUB_KEYBOARD_KEY_Y, + /* 0x36 */ GRUB_KEYBOARD_KEY_6, 0, + /* 0x38 */ 0, 0, + /* 0x3a */ GRUB_KEYBOARD_KEY_M, GRUB_KEYBOARD_KEY_J, + /* 0x3c */ GRUB_KEYBOARD_KEY_U, GRUB_KEYBOARD_KEY_7, + /* 0x3e */ GRUB_KEYBOARD_KEY_8, 0, + /* 0x40 */ 0, GRUB_KEYBOARD_KEY_COMMA, + /* 0x42 */ GRUB_KEYBOARD_KEY_K, GRUB_KEYBOARD_KEY_I, + /* 0x44 */ GRUB_KEYBOARD_KEY_O, GRUB_KEYBOARD_KEY_0, + /* 0x46 */ GRUB_KEYBOARD_KEY_9, 0, + /* 0x48 */ 0, GRUB_KEYBOARD_KEY_DOT, + /* 0x4a */ GRUB_KEYBOARD_KEY_SLASH, GRUB_KEYBOARD_KEY_L, + /* 0x4c */ GRUB_KEYBOARD_KEY_SEMICOLON, GRUB_KEYBOARD_KEY_P, + /* 0x4e */ GRUB_KEYBOARD_KEY_DASH, 0, + /* 0x50 */ 0, 0, + /* 0x52 */ GRUB_KEYBOARD_KEY_DQUOTE, 0, + /* 0x54 */ GRUB_KEYBOARD_KEY_LBRACKET, GRUB_KEYBOARD_KEY_EQUAL, + /* 0x56 */ 0, 0, + /* 0x58 */ GRUB_KEYBOARD_KEY_CAPS_LOCK, GRUB_KEYBOARD_KEY_RIGHT_SHIFT, + /* 0x5a */ GRUB_KEYBOARD_KEY_ENTER, GRUB_KEYBOARD_KEY_RBRACKET, + /* 0x5c */ 0, GRUB_KEYBOARD_KEY_BACKSLASH, + /* 0x5e */ 0, 0, + /* 0x60 */ 0, GRUB_KEYBOARD_KEY_102ND, + /* 0x62 */ 0, 0, + /* 0x64 */ 0, 0, + /* 0x66 */ GRUB_KEYBOARD_KEY_BACKSPACE, 0, + /* 0x68 */ 0, GRUB_KEYBOARD_KEY_NUM1, + /* 0x6a */ 0, GRUB_KEYBOARD_KEY_NUM4, + /* 0x6c */ GRUB_KEYBOARD_KEY_NUM7, 0, + /* 0x6e */ 0, 0, + /* 0x70 */ GRUB_KEYBOARD_KEY_NUMDOT, GRUB_KEYBOARD_KEY_NUM0, + /* 0x72 */ GRUB_KEYBOARD_KEY_NUM2, GRUB_KEYBOARD_KEY_NUM5, + /* 0x74 */ GRUB_KEYBOARD_KEY_NUM6, GRUB_KEYBOARD_KEY_NUM8, + /* 0x76 */ GRUB_KEYBOARD_KEY_ESCAPE, GRUB_KEYBOARD_KEY_NUM_LOCK, + /* 0x78 */ GRUB_KEYBOARD_KEY_F11, GRUB_KEYBOARD_KEY_NUMPLUS, + /* 0x7a */ GRUB_KEYBOARD_KEY_NUM3, GRUB_KEYBOARD_KEY_NUMMINUS, + /* 0x7c */ GRUB_KEYBOARD_KEY_NUMMUL, GRUB_KEYBOARD_KEY_NUM9, + /* 0x7e */ GRUB_KEYBOARD_KEY_SCROLL_LOCK, 0, + /* 0x80 */ 0, 0, + /* 0x82 */ 0, GRUB_KEYBOARD_KEY_F7, + }; + +static const struct +{ + grub_uint8_t from, to; +} set2_e0_mapping[] = + { + {0x11, GRUB_KEYBOARD_KEY_RIGHT_ALT}, + {0x14, GRUB_KEYBOARD_KEY_RIGHT_CTRL}, + {0x4a, GRUB_KEYBOARD_KEY_NUMSLASH}, + {0x5a, GRUB_KEYBOARD_KEY_NUMENTER}, + {0x69, GRUB_KEYBOARD_KEY_END}, + {0x6b, GRUB_KEYBOARD_KEY_LEFT}, + {0x6c, GRUB_KEYBOARD_KEY_HOME}, + {0x70, GRUB_KEYBOARD_KEY_INSERT}, + {0x71, GRUB_KEYBOARD_KEY_DELETE}, + {0x72, GRUB_KEYBOARD_KEY_DOWN}, + {0x74, GRUB_KEYBOARD_KEY_RIGHT}, + {0x75, GRUB_KEYBOARD_KEY_UP}, + {0x7a, GRUB_KEYBOARD_KEY_NPAGE}, + {0x7d, GRUB_KEYBOARD_KEY_PPAGE}, + }; static void keyboard_controller_wait_until_ready (void) @@ -78,22 +216,133 @@ keyboard_controller_wait_until_ready (void) while (! KEYBOARD_COMMAND_ISREADY (grub_inb (KEYBOARD_REG_STATUS))); } +static grub_uint8_t +wait_ack (void) +{ + grub_uint64_t endtime; + grub_uint8_t ack; + + endtime = grub_get_time_ms () + 20; + do + ack = grub_inb (KEYBOARD_REG_DATA); + while (ack != GRUB_AT_ACK && ack != GRUB_AT_NACK + && grub_get_time_ms () < endtime); + return ack; +} + +static int +at_command (grub_uint8_t data) +{ + unsigned i; + for (i = 0; i < GRUB_AT_TRIES; i++) + { + grub_uint8_t ack; + keyboard_controller_wait_until_ready (); + grub_outb (data, KEYBOARD_REG_STATUS); + ack = wait_ack (); + if (ack == GRUB_AT_NACK) + continue; + if (ack == GRUB_AT_ACK) + break; + return 0; + } + return (i != GRUB_AT_TRIES); +} + static void grub_keyboard_controller_write (grub_uint8_t c) { + at_command (KEYBOARD_COMMAND_WRITE); keyboard_controller_wait_until_ready (); - grub_outb (KEYBOARD_COMMAND_WRITE, KEYBOARD_REG_STATUS); grub_outb (c, KEYBOARD_REG_DATA); } static grub_uint8_t grub_keyboard_controller_read (void) { + at_command (KEYBOARD_COMMAND_READ); keyboard_controller_wait_until_ready (); - grub_outb (KEYBOARD_COMMAND_READ, KEYBOARD_REG_STATUS); return grub_inb (KEYBOARD_REG_DATA); } +static int +write_mode (int mode) +{ + unsigned i; + for (i = 0; i < GRUB_AT_TRIES; i++) + { + grub_uint8_t ack; + keyboard_controller_wait_until_ready (); + grub_outb (0xf0, KEYBOARD_REG_DATA); + keyboard_controller_wait_until_ready (); + grub_outb (mode, KEYBOARD_REG_DATA); + keyboard_controller_wait_until_ready (); + ack = wait_ack (); + if (ack == GRUB_AT_NACK) + continue; + if (ack == GRUB_AT_ACK) + break; + return 0; + } + + return (i != GRUB_AT_TRIES); +} + +static int +query_mode (void) +{ + grub_uint8_t ret; + int e; + + e = write_mode (0); + if (!e) + return 0; + + keyboard_controller_wait_until_ready (); + + do + ret = grub_inb (KEYBOARD_REG_DATA); + while (ret == GRUB_AT_ACK); + + /* QEMU translates the set even in no-translate mode. */ + if (ret == 0x43 || ret == 1) + return 1; + if (ret == 0x41 || ret == 2) + return 2; + if (ret == 0x3f || ret == 3) + return 3; + return 0; +} + +static void +set_scancodes (void) +{ + /* You must have visited computer museum. Keyboard without scancode set + knowledge. Assume XT. */ + if (!grub_keyboard_orig_set) + { + grub_dprintf ("atkeyb", "No sets support assumed\n"); + current_set = 1; + return; + } + + grub_keyboard_controller_write (grub_keyboard_controller_orig + & ~KEYBOARD_AT_TRANSLATE); + + write_mode (2); + current_set = query_mode (); + grub_dprintf ("atkeyb", "returned set %d\n", current_set); + if (current_set == 2) + return; + + write_mode (1); + current_set = query_mode (); + grub_dprintf ("atkeyb", "returned set %d\n", current_set); + if (current_set == 1) + return; + grub_printf ("No supported scancode set found\n"); +} + static void keyboard_controller_led (grub_uint8_t leds) { @@ -103,195 +352,271 @@ keyboard_controller_led (grub_uint8_t leds) grub_outb (leds & 0x7, KEYBOARD_REG_DATA); } +static int +fetch_key (int *is_break) +{ + int was_ext = 0; + grub_uint8_t at_key; + int ret = 0; + + if (! KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS))) + return -1; + at_key = grub_inb (KEYBOARD_REG_DATA); + if (at_key == 0xe0) + { + e0_received = 1; + return -1; + } + + if ((current_set == 2 || current_set == 3) && at_key == 0xf0) + { + f0_received = 1; + return -1; + } + + /* Setting LEDs may generate ACKs. */ + if (at_key == GRUB_AT_ACK) + return -1; + + was_ext = e0_received; + e0_received = 0; + + switch (current_set) + { + case 1: + *is_break = !!(at_key & 0x80); + if (!was_ext) + ret = set1_mapping[at_key & 0x7f]; + else + { + unsigned i; + for (i = 0; i < ARRAY_SIZE (set1_e0_mapping); i++) + if (set1_e0_mapping[i].from == (at_key & 0x7f)) + { + ret = set1_e0_mapping[i].to; + break; + } + } + break; + case 2: + *is_break = f0_received; + f0_received = 0; + if (!was_ext) + ret = set2_mapping[at_key]; + else + { + unsigned i; + for (i = 0; i < ARRAY_SIZE (set2_e0_mapping); i++) + if (set2_e0_mapping[i].from == at_key) + { + ret = set2_e0_mapping[i].to; + break; + } + } + break; + default: + return -1; + } + if (!ret) + { + if (was_ext) + grub_printf ("Unknown key 0xe0+0x%02x from set %d\n", + at_key, current_set); + else + grub_printf ("Unknown key 0x%02x from set %d\n", + at_key, current_set); + return -1; + } + return ret; +} + /* FIXME: This should become an interrupt service routine. For now it's just used to catch events from control keys. */ -static void -grub_keyboard_isr (char key) +static int +grub_keyboard_isr (grub_keyboard_key_t key, int is_break) { - char is_make = KEYBOARD_ISMAKE (key); - key = KEYBOARD_SCANCODE (key); - if (is_make) + if (!is_break) switch (key) { - case SHIFT_L: - at_keyboard_status |= KEYBOARD_STATUS_SHIFT_L; - break; - case SHIFT_R: - at_keyboard_status |= KEYBOARD_STATUS_SHIFT_R; - break; - case CTRL: - at_keyboard_status |= KEYBOARD_STATUS_CTRL_L; - break; - case ALT: - at_keyboard_status |= KEYBOARD_STATUS_ALT_L; - break; - default: - /* Skip grub_dprintf. */ - return; + case GRUB_KEYBOARD_KEY_LEFT_SHIFT: + at_keyboard_status |= GRUB_TERM_STATUS_LSHIFT; + return 1; + case GRUB_KEYBOARD_KEY_RIGHT_SHIFT: + at_keyboard_status |= GRUB_TERM_STATUS_RSHIFT; + return 1; + case GRUB_KEYBOARD_KEY_LEFT_CTRL: + at_keyboard_status |= GRUB_TERM_STATUS_LCTRL; + return 1; + case GRUB_KEYBOARD_KEY_RIGHT_CTRL: + at_keyboard_status |= GRUB_TERM_STATUS_RCTRL; + return 1; + case GRUB_KEYBOARD_KEY_RIGHT_ALT: + at_keyboard_status |= GRUB_TERM_STATUS_RALT; + return 1; + case GRUB_KEYBOARD_KEY_LEFT_ALT: + at_keyboard_status |= GRUB_TERM_STATUS_LALT; + return 1; + default: + return 0; } else switch (key) { - case SHIFT_L: - at_keyboard_status &= ~KEYBOARD_STATUS_SHIFT_L; - break; - case SHIFT_R: - at_keyboard_status &= ~KEYBOARD_STATUS_SHIFT_R; - break; - case CTRL: - at_keyboard_status &= ~KEYBOARD_STATUS_CTRL_L; - break; - case ALT: - at_keyboard_status &= ~KEYBOARD_STATUS_ALT_L; - break; - default: - /* Skip grub_dprintf. */ - return; + case GRUB_KEYBOARD_KEY_LEFT_SHIFT: + at_keyboard_status &= ~GRUB_TERM_STATUS_LSHIFT; + return 1; + case GRUB_KEYBOARD_KEY_RIGHT_SHIFT: + at_keyboard_status &= ~GRUB_TERM_STATUS_RSHIFT; + return 1; + case GRUB_KEYBOARD_KEY_LEFT_CTRL: + at_keyboard_status &= ~GRUB_TERM_STATUS_LCTRL; + return 1; + case GRUB_KEYBOARD_KEY_RIGHT_CTRL: + at_keyboard_status &= ~GRUB_TERM_STATUS_RCTRL; + return 1; + case GRUB_KEYBOARD_KEY_RIGHT_ALT: + at_keyboard_status &= ~GRUB_TERM_STATUS_RALT; + return 1; + case GRUB_KEYBOARD_KEY_LEFT_ALT: + at_keyboard_status &= ~GRUB_TERM_STATUS_LALT; + return 1; + default: + return 0; } -#ifdef DEBUG_AT_KEYBOARD - grub_dprintf ("atkeyb", "Control key 0x%0x was %s\n", key, is_make ? "pressed" : "unpressed"); -#endif } /* If there is a raw key pending, return it; otherwise return -1. */ static int grub_keyboard_getkey (void) { - grub_uint8_t key; - if (! KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS))) + int key; + int is_break; + + key = fetch_key (&is_break); + if (key == -1) return -1; - key = grub_inb (KEYBOARD_REG_DATA); - /* FIXME */ grub_keyboard_isr (key); - if (! KEYBOARD_ISMAKE (key)) + + if (grub_keyboard_isr (key, is_break)) return -1; - return (KEYBOARD_SCANCODE (key)); + if (is_break) + return -1; + return key; } -/* If there is a character pending, return it; otherwise return -1. */ +/* If there is a character pending, return it; + otherwise return GRUB_TERM_NO_KEY. */ static int -grub_at_keyboard_getkey_noblock (void) +grub_at_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused))) { - int code, key; + int code; code = grub_keyboard_getkey (); if (code == -1) - return -1; + return GRUB_TERM_NO_KEY; #ifdef DEBUG_AT_KEYBOARD grub_dprintf ("atkeyb", "Detected key 0x%x\n", key); #endif switch (code) { - case CAPS_LOCK: - at_keyboard_status ^= KEYBOARD_STATUS_CAPS_LOCK; + case GRUB_KEYBOARD_KEY_CAPS_LOCK: + at_keyboard_status ^= GRUB_TERM_STATUS_CAPS; led_status ^= KEYBOARD_LED_CAPS; keyboard_controller_led (led_status); #ifdef DEBUG_AT_KEYBOARD grub_dprintf ("atkeyb", "caps_lock = %d\n", !!(at_keyboard_status & KEYBOARD_STATUS_CAPS_LOCK)); #endif - key = -1; - break; - case NUM_LOCK: - at_keyboard_status ^= KEYBOARD_STATUS_NUM_LOCK; + return GRUB_TERM_NO_KEY; + case GRUB_KEYBOARD_KEY_NUM_LOCK: + at_keyboard_status ^= GRUB_TERM_STATUS_NUM; led_status ^= KEYBOARD_LED_NUM; keyboard_controller_led (led_status); #ifdef DEBUG_AT_KEYBOARD grub_dprintf ("atkeyb", "num_lock = %d\n", !!(at_keyboard_status & KEYBOARD_STATUS_NUM_LOCK)); #endif - key = -1; - break; - case SCROLL_LOCK: - /* For scroll lock we don't keep track of status. Only update its led. */ + return GRUB_TERM_NO_KEY; + case GRUB_KEYBOARD_KEY_SCROLL_LOCK: + at_keyboard_status ^= GRUB_TERM_STATUS_SCROLL; led_status ^= KEYBOARD_LED_SCROLL; keyboard_controller_led (led_status); - key = -1; - break; + return GRUB_TERM_NO_KEY; default: - if (at_keyboard_status & (KEYBOARD_STATUS_CTRL_L | KEYBOARD_STATUS_CTRL_R)) - key = keyboard_map[code] - 'a' + 1; - else if ((at_keyboard_status & (KEYBOARD_STATUS_SHIFT_L | KEYBOARD_STATUS_SHIFT_R)) - && keyboard_map_shift[code]) - key = keyboard_map_shift[code]; - else - key = keyboard_map[code]; - - if (key == 0) - grub_dprintf ("atkeyb", "Unknown key 0x%x detected\n", code); - - if (at_keyboard_status & KEYBOARD_STATUS_CAPS_LOCK) - { - if ((key >= 'a') && (key <= 'z')) - key += 'A' - 'a'; - else if ((key >= 'A') && (key <= 'Z')) - key += 'a' - 'A'; - } + return grub_term_map_key (code, at_keyboard_status); } - return key; -} - -static int -grub_at_keyboard_checkkey (struct grub_term_input *term __attribute__ ((unused))) -{ - if (pending_key != -1) - return 1; - - pending_key = grub_at_keyboard_getkey_noblock (); - - if (pending_key != -1) - return 1; - - return -1; -} - -static int -grub_at_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused))) -{ - int key; - if (pending_key != -1) - { - key = pending_key; - pending_key = -1; - return key; - } - do - { - key = grub_at_keyboard_getkey_noblock (); - } while (key == -1); - return key; } static grub_err_t grub_keyboard_controller_init (struct grub_term_input *term __attribute__ ((unused))) { - pending_key = -1; at_keyboard_status = 0; + /* Drain input buffer. */ + while (1) + { + keyboard_controller_wait_until_ready (); + if (! KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS))) + break; + keyboard_controller_wait_until_ready (); + grub_inb (KEYBOARD_REG_DATA); + } grub_keyboard_controller_orig = grub_keyboard_controller_read (); - grub_keyboard_controller_write (grub_keyboard_controller_orig | KEYBOARD_SCANCODE_SET1); + grub_keyboard_orig_set = query_mode (); + set_scancodes (); + keyboard_controller_led (led_status); + return GRUB_ERR_NONE; } static grub_err_t grub_keyboard_controller_fini (struct grub_term_input *term __attribute__ ((unused))) { + if (grub_keyboard_orig_set) + write_mode (grub_keyboard_orig_set); grub_keyboard_controller_write (grub_keyboard_controller_orig); return GRUB_ERR_NONE; } +static grub_err_t +grub_at_fini_hw (int noreturn __attribute__ ((unused))) +{ + return grub_keyboard_controller_fini (NULL); +} + +static grub_err_t +grub_at_restore_hw (void) +{ + /* Drain input buffer. */ + while (1) + { + keyboard_controller_wait_until_ready (); + if (! KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS))) + break; + keyboard_controller_wait_until_ready (); + grub_inb (KEYBOARD_REG_DATA); + } + set_scancodes (); + keyboard_controller_led (led_status); + + return GRUB_ERR_NONE; +} + + static struct grub_term_input grub_at_keyboard_term = { .name = "at_keyboard", .init = grub_keyboard_controller_init, .fini = grub_keyboard_controller_fini, - .checkkey = grub_at_keyboard_checkkey, - .getkey = grub_at_keyboard_getkey, + .getkey = grub_at_keyboard_getkey }; GRUB_MOD_INIT(at_keyboard) { grub_term_register_input ("at_keyboard", &grub_at_keyboard_term); + grub_loader_register_preboot_hook (grub_at_fini_hw, grub_at_restore_hw, + GRUB_LOADER_PREBOOT_HOOK_PRIO_CONSOLE); } GRUB_MOD_FINI(at_keyboard) { + grub_keyboard_controller_fini (NULL); grub_term_unregister_input (&grub_at_keyboard_term); } diff --git a/grub-core/term/efi/console.c b/grub-core/term/efi/console.c index 6027d0ab3..c92f6a75e 100644 --- a/grub-core/term/efi/console.c +++ b/grub-core/term/efi/console.c @@ -28,8 +28,6 @@ static const grub_uint8_t grub_console_standard_color = GRUB_EFI_TEXT_ATTR (GRUB_EFI_YELLOW, GRUB_EFI_BACKGROUND_BLACK); -static int read_key = -1; - static grub_uint32_t map_char (grub_uint32_t c) { @@ -103,8 +101,19 @@ grub_console_putchar (struct grub_term_output *term __attribute__ ((unused)), efi_call_2 (o->output_string, o, str); } +const unsigned efi_codes[] = + { + 0, GRUB_TERM_UP, GRUB_TERM_DOWN, GRUB_TERM_RIGHT, + GRUB_TERM_LEFT, GRUB_TERM_HOME, GRUB_TERM_END, GRUB_TERM_KEY_INSERT, + GRUB_TERM_DC, GRUB_TERM_KEY_PPAGE, GRUB_TERM_KEY_NPAGE, GRUB_TERM_KEY_F1, + GRUB_TERM_KEY_F2, GRUB_TERM_KEY_F3, GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5, + GRUB_TERM_KEY_F6, GRUB_TERM_KEY_F7, GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9, + GRUB_TERM_KEY_F10, 0, 0, '\e' + }; + + static int -grub_console_checkkey (struct grub_term_input *term __attribute__ ((unused))) +grub_console_getkey (struct grub_term_input *term __attribute__ ((unused))) { grub_efi_simple_input_interface_t *i; grub_efi_input_key_t key; @@ -113,129 +122,18 @@ grub_console_checkkey (struct grub_term_input *term __attribute__ ((unused))) if (grub_efi_is_finished) return 0; - if (read_key >= 0) - return 1; - i = grub_efi_system_table->con_in; status = efi_call_2 (i->read_key_stroke, i, &key); -#if 0 - switch (status) - { - case GRUB_EFI_SUCCESS: - { - grub_uint16_t xy; - xy = grub_getxy (); - grub_gotoxy (0, 0); - grub_printf ("scan_code=%x,unicode_char=%x ", - (unsigned) key.scan_code, - (unsigned) key.unicode_char); - grub_gotoxy (xy >> 8, xy & 0xff); - } - break; + if (status != GRUB_EFI_SUCCESS) + return GRUB_TERM_NO_KEY; - case GRUB_EFI_NOT_READY: - //grub_printf ("not ready "); - break; + if (key.scan_code == 0) + return key.unicode_char; + else if (key.scan_code < ARRAY_SIZE (efi_codes)) + return efi_codes[key.scan_code]; - default: - //grub_printf ("device error "); - break; - } -#endif - - if (status == GRUB_EFI_SUCCESS) - { - switch (key.scan_code) - { - case 0x00: - read_key = key.unicode_char; - break; - case 0x01: - read_key = GRUB_TERM_UP; - break; - case 0x02: - read_key = GRUB_TERM_DOWN; - break; - case 0x03: - read_key = GRUB_TERM_RIGHT; - break; - case 0x04: - read_key = GRUB_TERM_LEFT; - break; - case 0x05: - read_key = GRUB_TERM_HOME; - break; - case 0x06: - read_key = GRUB_TERM_END; - break; - case 0x07: - break; - case 0x08: - read_key = GRUB_TERM_DC; - break; - case 0x09: - break; - case 0x0a: - break; - case 0x0b: - read_key = 24; - break; - case 0x0c: - read_key = 1; - break; - case 0x0d: - read_key = 5; - break; - case 0x0e: - read_key = 3; - break; - case 0x17: - read_key = '\e'; - break; - default: - break; - } - } - - return read_key; -} - -static int -grub_console_getkey (struct grub_term_input *term) -{ - grub_efi_simple_input_interface_t *i; - grub_efi_boot_services_t *b; - grub_efi_uintn_t index; - grub_efi_status_t status; - int key; - - if (grub_efi_is_finished) - return 0; - - if (read_key >= 0) - { - key = read_key; - read_key = -1; - return key; - } - - i = grub_efi_system_table->con_in; - b = grub_efi_system_table->boot_services; - - do - { - status = efi_call_3 (b->wait_for_event, 1, &(i->wait_for_key), &index); - if (status != GRUB_EFI_SUCCESS) - return -1; - - grub_console_checkkey (term); - } - while (read_key < 0); - - key = read_key; - read_key = -1; - return key; + return GRUB_TERM_NO_KEY; } static grub_uint16_t @@ -353,7 +251,6 @@ grub_efi_console_fini (struct grub_term_output *term) static struct grub_term_input grub_console_term_input = { .name = "console", - .checkkey = grub_console_checkkey, .getkey = grub_console_getkey, }; diff --git a/grub-core/term/gfxterm.c b/grub-core/term/gfxterm.c index 3616eb453..9a10d47b0 100644 --- a/grub-core/term/gfxterm.c +++ b/grub-core/term/gfxterm.c @@ -1207,8 +1207,7 @@ GRUB_MOD_INIT(gfxterm) grub_term_register_output ("gfxterm", &grub_video_term); background_image_cmd_handle = grub_register_extcmd ("background_image", - grub_gfxterm_background_image_cmd, - GRUB_COMMAND_FLAG_BOTH, + grub_gfxterm_background_image_cmd, 0, N_("[-m (stretch|normal)] FILE"), N_("Load background image for active terminal."), background_image_cmd_options); diff --git a/grub-core/term/i386/pc/console.c b/grub-core/term/i386/pc/console.c index 19a8e3814..0efeafe4e 100644 --- a/grub-core/term/i386/pc/console.c +++ b/grub-core/term/i386/pc/console.c @@ -24,33 +24,18 @@ static const struct grub_machine_bios_data_area *bios_data_area = (struct grub_machine_bios_data_area *) GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR; -#define KEYBOARD_LEFT_SHIFT (1 << 0) -#define KEYBOARD_RIGHT_SHIFT (1 << 1) -#define KEYBOARD_CTRL (1 << 2) -#define KEYBOARD_ALT (1 << 3) - static int grub_console_getkeystatus (struct grub_term_input *term __attribute__ ((unused))) { - grub_uint8_t status = bios_data_area->keyboard_flag_lower; - int mods = 0; - - if (status & (KEYBOARD_LEFT_SHIFT | KEYBOARD_RIGHT_SHIFT)) - mods |= GRUB_TERM_STATUS_SHIFT; - if (status & KEYBOARD_CTRL) - mods |= GRUB_TERM_STATUS_CTRL; - if (status & KEYBOARD_ALT) - mods |= GRUB_TERM_STATUS_ALT; - - return mods; + /* conveniently GRUB keystatus is modelled after BIOS one. */ + return bios_data_area->keyboard_flag_lower & ~0x80; } static struct grub_term_input grub_console_term_input = { .name = "console", - .checkkey = grub_console_checkkey, .getkey = grub_console_getkey, - .getkeystatus = grub_console_getkeystatus, + .getkeystatus = grub_console_getkeystatus }; static struct grub_term_output grub_console_term_output = diff --git a/grub-core/term/ieee1275/ofconsole.c b/grub-core/term/ieee1275/ofconsole.c index 9ec85631b..226b78b71 100644 --- a/grub-core/term/ieee1275/ofconsole.c +++ b/grub-core/term/ieee1275/ofconsole.c @@ -117,9 +117,14 @@ grub_ofconsole_getwh (struct grub_term_output *term __attribute__ ((unused))) } static void -grub_ofconsole_setcursor (struct grub_term_output *term __attribute__ ((unused)), +grub_ofconsole_setcursor (struct grub_term_output *term, int on) { + grub_terminfo_setcursor (term, on); + + if (!grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_HAS_CURSORONOFF)) + return; + /* Understood by the Open Firmware flavour in OLPC. */ if (on) grub_ieee1275_interpret ("cursor-on", 0); @@ -189,7 +194,6 @@ static struct grub_term_input grub_ofconsole_term_input = { .name = "ofconsole", .init = grub_ofconsole_init_input, - .checkkey = grub_terminfo_checkkey, .getkey = grub_terminfo_getkey, .data = &grub_ofconsole_terminfo_input }; diff --git a/grub-core/term/ns8250.c b/grub-core/term/ns8250.c index f3a804d53..550ee6341 100644 --- a/grub-core/term/ns8250.c +++ b/grub-core/term/ns8250.c @@ -16,7 +16,6 @@ * along with GRUB. If not, see . */ -#include #include #include #include @@ -26,6 +25,7 @@ #include #ifdef GRUB_MACHINE_PCBIOS +#include static const unsigned short *serial_hw_io_addr = (const unsigned short *) GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR; #define GRUB_SERIAL_PORT_NUM 4 #else diff --git a/grub-core/term/serial.c b/grub-core/term/serial.c index 394fc1576..e318e4b43 100644 --- a/grub-core/term/serial.c +++ b/grub-core/term/serial.c @@ -99,7 +99,6 @@ static struct grub_term_input grub_serial_term_input = { .name = "serial", .init = grub_terminfo_input_init, - .checkkey = grub_terminfo_checkkey, .getkey = grub_terminfo_getkey, .data = &grub_serial_terminfo_input }; @@ -341,8 +340,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(serial) { - cmd = grub_register_extcmd ("serial", grub_cmd_serial, - GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("serial", grub_cmd_serial, 0, N_("[OPTIONS...]"), N_("Configure serial port."), options); #ifndef GRUB_MACHINE_EMU diff --git a/grub-core/term/terminfo.c b/grub-core/term/terminfo.c index 5691b9cc6..8dea7aea1 100644 --- a/grub-core/term/terminfo.c +++ b/grub-core/term/terminfo.c @@ -403,34 +403,34 @@ grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len, static struct { char key; - char ascii; + unsigned ascii; } three_code_table[] = { - {'4', GRUB_TERM_DC}, - {'A', GRUB_TERM_UP}, - {'B', GRUB_TERM_DOWN}, - {'C', GRUB_TERM_RIGHT}, - {'D', GRUB_TERM_LEFT}, - {'F', GRUB_TERM_END}, - {'H', GRUB_TERM_HOME}, - {'K', GRUB_TERM_END}, - {'P', GRUB_TERM_DC}, - {'?', GRUB_TERM_PPAGE}, - {'/', GRUB_TERM_NPAGE} + {'4', GRUB_TERM_KEY_DC}, + {'A', GRUB_TERM_KEY_UP}, + {'B', GRUB_TERM_KEY_DOWN}, + {'C', GRUB_TERM_KEY_RIGHT}, + {'D', GRUB_TERM_KEY_LEFT}, + {'F', GRUB_TERM_KEY_END}, + {'H', GRUB_TERM_KEY_HOME}, + {'K', GRUB_TERM_KEY_END}, + {'P', GRUB_TERM_KEY_DC}, + {'?', GRUB_TERM_KEY_PPAGE}, + {'/', GRUB_TERM_KEY_NPAGE} }; static struct { char key; - char ascii; + unsigned ascii; } four_code_table[] = { - {'1', GRUB_TERM_HOME}, - {'3', GRUB_TERM_DC}, - {'5', GRUB_TERM_PPAGE}, - {'6', GRUB_TERM_NPAGE} + {'1', GRUB_TERM_KEY_HOME}, + {'3', GRUB_TERM_KEY_DC}, + {'5', GRUB_TERM_KEY_PPAGE}, + {'6', GRUB_TERM_KEY_NPAGE} }; unsigned i; @@ -467,39 +467,30 @@ grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len, #undef CONTINUE_READ } -/* The terminfo version of checkkey. */ -int -grub_terminfo_checkkey (struct grub_term_input *termi) -{ - struct grub_terminfo_input_state *data - = (struct grub_terminfo_input_state *) (termi->data); - if (data->npending) - return data->input_buf[0]; - - grub_terminfo_readkey (termi, data->input_buf, - &data->npending, data->readkey); - - if (data->npending) - return data->input_buf[0]; - - return -1; -} - /* The terminfo version of getkey. */ int grub_terminfo_getkey (struct grub_term_input *termi) { struct grub_terminfo_input_state *data = (struct grub_terminfo_input_state *) (termi->data); - int ret; - while (! data->npending) - grub_terminfo_readkey (termi, data->input_buf, &data->npending, - data->readkey); + if (data->npending) + { + data->npending--; + grub_memmove (data->input_buf, data->input_buf + 1, data->npending); + return data->input_buf[0]; + } - ret = data->input_buf[0]; - data->npending--; - grub_memmove (data->input_buf, data->input_buf + 1, data->npending); - return ret; + grub_terminfo_readkey (termi, data->input_buf, + &data->npending, data->readkey); + + if (data->npending) + { + data->npending--; + grub_memmove (data->input_buf, data->input_buf + 1, data->npending); + return data->input_buf[0]; + } + + return GRUB_TERM_NO_KEY; } grub_err_t diff --git a/grub-core/term/usb_keyboard.c b/grub-core/term/usb_keyboard.c index d875ac00a..8a34ec552 100644 --- a/grub-core/term/usb_keyboard.c +++ b/grub-core/term/usb_keyboard.c @@ -25,36 +25,26 @@ #include #include #include +#include -static char keyboard_map[128] = + +enum { - '\0', '\0', '\0', '\0', 'a', 'b', 'c', 'd', - 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', - 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', - 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', - '3', '4', '5', '6', '7', '8', '9', '0', - '\n', GRUB_TERM_ESC, GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, ' ', '-', '=', '[', - ']', '\\', '#', ';', '\'', '`', ',', '.', - '/', '\0', '\0', '\0', '\0', '\0', '\0', '\0', - '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', - '\0', '\0', GRUB_TERM_HOME, GRUB_TERM_PPAGE, GRUB_TERM_DC, GRUB_TERM_END, GRUB_TERM_NPAGE, GRUB_TERM_RIGHT, - GRUB_TERM_LEFT, GRUB_TERM_DOWN, GRUB_TERM_UP + KEY_NO_KEY = 0x00, + KEY_ERR_BUFFER = 0x01, + KEY_ERR_POST = 0x02, + KEY_ERR_UNDEF = 0x03, + KEY_CAPS_LOCK = 0x39, + KEY_NUM_LOCK = 0x53, }; -static char keyboard_map_shift[128] = +enum { - '\0', '\0', '\0', '\0', 'A', 'B', 'C', 'D', - 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', - 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', - 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@', - '#', '$', '%', '^', '&', '*', '(', ')', - '\n', '\0', '\0', '\0', ' ', '_', '+', '{', - '}', '|', '#', ':', '"', '`', '<', '>', - '?' + LED_NUM_LOCK = 0x01, + LED_CAPS_LOCK = 0x02 }; - /* Valid values for bRequest. See HID definition version 1.11 section 7.2. */ #define USB_HID_GET_REPORT 0x01 #define USB_HID_GET_IDLE 0x02 @@ -66,28 +56,65 @@ static char keyboard_map_shift[128] = #define USB_HID_BOOT_SUBCLASS 0x01 #define USB_HID_KBD_PROTOCOL 0x01 -static int grub_usb_keyboard_checkkey (struct grub_term_input *term); -static int grub_usb_keyboard_getkey (struct grub_term_input *term); -static int grub_usb_keyboard_getkeystatus (struct grub_term_input *term); - -static struct grub_term_input grub_usb_keyboard_term = - { - .checkkey = grub_usb_keyboard_checkkey, - .getkey = grub_usb_keyboard_getkey, - .getkeystatus = grub_usb_keyboard_getkeystatus, - .next = 0 - }; +#define GRUB_USB_KEYBOARD_LEFT_CTRL 0x01 +#define GRUB_USB_KEYBOARD_LEFT_SHIFT 0x02 +#define GRUB_USB_KEYBOARD_LEFT_ALT 0x04 +#define GRUB_USB_KEYBOARD_RIGHT_CTRL 0x10 +#define GRUB_USB_KEYBOARD_RIGHT_SHIFT 0x20 +#define GRUB_USB_KEYBOARD_RIGHT_ALT 0x40 struct grub_usb_keyboard_data { grub_usb_device_t usbdev; grub_uint8_t status; - int key; + grub_uint16_t mods; + int interfno; struct grub_usb_desc_endp *endp; + grub_usb_transfer_t transfer; + grub_uint8_t report[8]; + int dead; + int last_key; + grub_uint64_t repeat_time; + grub_uint8_t current_report[8]; + grub_uint8_t last_report[8]; + int index; + int max_index; }; +static int grub_usb_keyboard_getkey (struct grub_term_input *term); +static int grub_usb_keyboard_getkeystatus (struct grub_term_input *term); + +static struct grub_term_input grub_usb_keyboard_term = + { + .getkey = grub_usb_keyboard_getkey, + .getkeystatus = grub_usb_keyboard_getkeystatus, + .next = 0 + }; + static struct grub_term_input grub_usb_keyboards[16]; +static int +interpret_status (grub_uint8_t data0) +{ + int mods = 0; + + /* Check Shift, Control, and Alt status. */ + if (data0 & GRUB_USB_KEYBOARD_LEFT_SHIFT) + mods |= GRUB_TERM_STATUS_LSHIFT; + if (data0 & GRUB_USB_KEYBOARD_RIGHT_SHIFT) + mods |= GRUB_TERM_STATUS_RSHIFT; + if (data0 & GRUB_USB_KEYBOARD_LEFT_CTRL) + mods |= GRUB_TERM_STATUS_LCTRL; + if (data0 & GRUB_USB_KEYBOARD_RIGHT_CTRL) + mods |= GRUB_TERM_STATUS_RCTRL; + if (data0 & GRUB_USB_KEYBOARD_LEFT_ALT) + mods |= GRUB_TERM_STATUS_LALT; + if (data0 & GRUB_USB_KEYBOARD_RIGHT_ALT) + mods |= GRUB_TERM_STATUS_RALT; + + return mods; +} + static void grub_usb_keyboard_detach (grub_usb_device_t usbdev, int config __attribute__ ((unused)), @@ -104,6 +131,9 @@ grub_usb_keyboard_detach (grub_usb_device_t usbdev, if (data->usbdev != usbdev) continue; + if (data->transfer) + grub_usb_cancel_transfer (data->transfer); + grub_term_unregister_input (&grub_usb_keyboards[i]); grub_free ((char *) grub_usb_keyboards[i].name); grub_usb_keyboards[i].name = NULL; @@ -163,15 +193,19 @@ grub_usb_keyboard_attach (grub_usb_device_t usbdev, int configno, int interfno) } data->usbdev = usbdev; + data->interfno = interfno; data->endp = endp; + /* Configure device */ + grub_usb_set_configuration (usbdev, configno + 1); + /* Place the device in boot mode. */ grub_usb_control_msg (usbdev, GRUB_USB_REQTYPE_CLASS_INTERFACE_OUT, - USB_HID_SET_PROTOCOL, 0, 0, 0, 0); + USB_HID_SET_PROTOCOL, 0, interfno, 0, 0); /* Reports every time an event occurs and not more often than that. */ grub_usb_control_msg (usbdev, GRUB_USB_REQTYPE_CLASS_INTERFACE_OUT, - USB_HID_SET_IDLE, 0<<8, 0, 0, 0); + USB_HID_SET_IDLE, 0<<8, interfno, 0, 0); grub_memcpy (&grub_usb_keyboards[curnum], &grub_usb_keyboard_term, sizeof (grub_usb_keyboards[curnum])); @@ -185,24 +219,41 @@ grub_usb_keyboard_attach (grub_usb_device_t usbdev, int configno, int interfno) return 0; } + /* Test showed that getting report may make the keyboard go nuts. + Moreover since we're reattaching keyboard it usually sends + an initial message on interrupt pipe and so we retrieve + the same keystatus. + */ +#if 0 { grub_uint8_t report[8]; grub_usb_err_t err; grub_memset (report, 0, sizeof (report)); err = grub_usb_control_msg (usbdev, GRUB_USB_REQTYPE_CLASS_INTERFACE_IN, - USB_HID_GET_REPORT, 0x0000, interfno, + USB_HID_GET_REPORT, 0x0100, interfno, sizeof (report), (char *) report); if (err) - { - data->status = 0; - data->key = -1; - } + data->status = 0; else - { - data->status = report[0]; - data->key = report[2] ? : -1; - } + data->status = report[0]; } +#else + data->status = 0; +#endif + + data->transfer = grub_usb_bulk_read_background (usbdev, + data->endp->endp_addr, + sizeof (data->report), + (char *) data->report); + if (!data->transfer) + { + grub_print_error (); + return 0; + } + + data->last_key = -1; + data->mods = 0; + data->dead = 0; grub_term_register_input_active ("usb_keyboard", &grub_usb_keyboards[curnum]); @@ -211,83 +262,176 @@ grub_usb_keyboard_attach (grub_usb_device_t usbdev, int configno, int interfno) -static int -grub_usb_keyboard_checkkey (struct grub_term_input *term) +static void +send_leds (struct grub_usb_keyboard_data *termdata) { - grub_uint8_t data[8]; - grub_usb_err_t err; - struct grub_usb_keyboard_data *termdata = term->data; - grub_size_t actual; - - if (termdata->key != -1) - return termdata->key; - - data[2] = 0; - /* Poll interrupt pipe. */ - err = grub_usb_bulk_read_extended (termdata->usbdev, - termdata->endp->endp_addr, sizeof (data), - (char *) data, 10, &actual); - if (err || actual < 1) - return -1; - - termdata->status = data[0]; - - if (actual < 3 || !data[2]) - return -1; - - grub_dprintf ("usb_keyboard", - "report: 0x%02x 0x%02x 0x%02x 0x%02x" - " 0x%02x 0x%02x 0x%02x 0x%02x\n", - data[0], data[1], data[2], data[3], - data[4], data[5], data[6], data[7]); - - /* Check if the Control or Shift key was pressed. */ - if (data[0] & 0x01 || data[0] & 0x10) - termdata->key = keyboard_map[data[2]] - 'a' + 1; - else if (data[0] & 0x02 || data[0] & 0x20) - termdata->key = keyboard_map_shift[data[2]]; - else - termdata->key = keyboard_map[data[2]]; - - if (termdata->key == 0) - grub_printf ("Unknown key 0x%x detected\n", data[2]); - + char report[1]; + report[0] = 0; + if (termdata->mods & GRUB_TERM_STATUS_CAPS) + report[0] |= LED_CAPS_LOCK; + if (termdata->mods & GRUB_TERM_STATUS_NUM) + report[0] |= LED_NUM_LOCK; + grub_usb_control_msg (termdata->usbdev, GRUB_USB_REQTYPE_CLASS_INTERFACE_OUT, + USB_HID_SET_REPORT, 0x0200, termdata->interfno, + sizeof (report), (char *) report); grub_errno = GRUB_ERR_NONE; +} - return termdata->key; +static int +parse_keycode (struct grub_usb_keyboard_data *termdata) +{ + int index = termdata->index; + int i, keycode; + + /* Sanity check */ + if (index < 2) + index = 2; + + for ( ; index < termdata->max_index; index++) + { + keycode = termdata->current_report[index]; + + if (keycode == KEY_NO_KEY + || keycode == KEY_ERR_BUFFER + || keycode == KEY_ERR_POST + || keycode == KEY_ERR_UNDEF) + { + /* Don't parse (rest of) this report */ + termdata->index = 0; + if (keycode != KEY_NO_KEY) + /* Don't replace last report with current faulty report + * in future ! */ + grub_memcpy (termdata->current_report, + termdata->last_report, + sizeof (termdata->report)); + return GRUB_TERM_NO_KEY; + } + + /* Try to find current keycode in last report. */ + for (i = 2; i < 8; i++) + if (keycode == termdata->last_report[i]) + break; + if (i < 8) + /* Keycode is in last report, it means it was not released, + * ignore it. */ + continue; + + if (keycode == KEY_CAPS_LOCK) + { + termdata->mods ^= GRUB_TERM_STATUS_CAPS; + send_leds (termdata); + continue; + } + + if (keycode == KEY_NUM_LOCK) + { + termdata->mods ^= GRUB_TERM_STATUS_NUM; + send_leds (termdata); + continue; + } + + termdata->last_key = grub_term_map_key (keycode, + interpret_status (termdata->current_report[0]) + | termdata->mods); + termdata->repeat_time = grub_get_time_ms () + GRUB_TERM_REPEAT_PRE_INTERVAL; + + grub_errno = GRUB_ERR_NONE; + + index++; + if (index >= termdata->max_index) + termdata->index = 0; + else + termdata->index = index; + + return termdata->last_key; + } + + /* All keycodes parsed */ + termdata->index = 0; + return GRUB_TERM_NO_KEY; } static int grub_usb_keyboard_getkey (struct grub_term_input *term) { - int ret; + grub_usb_err_t err; struct grub_usb_keyboard_data *termdata = term->data; + grub_size_t actual; + int keycode = GRUB_TERM_NO_KEY; - while (termdata->key == -1) - grub_usb_keyboard_checkkey (term); + if (termdata->dead) + return GRUB_TERM_NO_KEY; - ret = termdata->key; + if (termdata->index) + keycode = parse_keycode (termdata); + if (keycode != GRUB_TERM_NO_KEY) + return keycode; + + /* Poll interrupt pipe. */ + err = grub_usb_check_transfer (termdata->transfer, &actual); - termdata->key = -1; + if (err == GRUB_USB_ERR_WAIT) + { + if (termdata->last_key != -1 + && grub_get_time_ms () > termdata->repeat_time) + { + termdata->repeat_time = grub_get_time_ms () + + GRUB_TERM_REPEAT_INTERVAL; + return termdata->last_key; + } + return GRUB_TERM_NO_KEY; + } - return ret; + if (!err && (actual >= 3)) + grub_memcpy (termdata->last_report, + termdata->current_report, + sizeof (termdata->report)); + + grub_memcpy (termdata->current_report, + termdata->report, + sizeof (termdata->report)); + + termdata->transfer = grub_usb_bulk_read_background (termdata->usbdev, + termdata->endp->endp_addr, + sizeof (termdata->report), + (char *) termdata->report); + if (!termdata->transfer) + { + grub_printf ("%s failed. Stopped\n", term->name); + termdata->dead = 1; + } + + termdata->last_key = -1; + + grub_dprintf ("usb_keyboard", + "err = %d, actual = %d report: 0x%02x 0x%02x 0x%02x 0x%02x" + " 0x%02x 0x%02x 0x%02x 0x%02x\n", + err, actual, + termdata->current_report[0], termdata->current_report[1], + termdata->current_report[2], termdata->current_report[3], + termdata->current_report[4], termdata->current_report[5], + termdata->current_report[6], termdata->current_report[7]); + + if (err || actual < 1) + return GRUB_TERM_NO_KEY; + + termdata->status = termdata->current_report[0]; + + if (actual < 3) + return GRUB_TERM_NO_KEY; + + termdata->index = 2; /* New data received. */ + termdata->max_index = actual; + + return parse_keycode (termdata); } static int grub_usb_keyboard_getkeystatus (struct grub_term_input *term) { struct grub_usb_keyboard_data *termdata = term->data; - int mods = 0; - /* Check Shift, Control, and Alt status. */ - if (termdata->status & 0x02 || termdata->status & 0x20) - mods |= GRUB_TERM_STATUS_SHIFT; - if (termdata->status & 0x01 || termdata->status & 0x10) - mods |= GRUB_TERM_STATUS_CTRL; - if (termdata->status & 0x04 || termdata->status & 0x40) - mods |= GRUB_TERM_STATUS_ALT; - - return mods; + return interpret_status (termdata->status) | termdata->mods; } struct grub_usb_attach_desc attach_hook = @@ -307,9 +451,18 @@ GRUB_MOD_FINI(usb_keyboard) for (i = 0; i < ARRAY_SIZE (grub_usb_keyboards); i++) if (grub_usb_keyboards[i].data) { + struct grub_usb_keyboard_data *data = grub_usb_keyboards[i].data; + + if (!data) + continue; + + if (data->transfer) + grub_usb_cancel_transfer (data->transfer); + grub_term_unregister_input (&grub_usb_keyboards[i]); grub_free ((char *) grub_usb_keyboards[i].name); grub_usb_keyboards[i].name = NULL; + grub_free (grub_usb_keyboards[i].data); grub_usb_keyboards[i].data = 0; } grub_usb_unregister_attach_hook_class (&attach_hook); diff --git a/grub-core/tests/lib/functional_test.c b/grub-core/tests/lib/functional_test.c index 82bf372c0..521f4ad22 100644 --- a/grub-core/tests/lib/functional_test.c +++ b/grub-core/tests/lib/functional_test.c @@ -37,8 +37,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT (functional_test) { - cmd = grub_register_extcmd ("functional_test", grub_functional_test, - GRUB_COMMAND_FLAG_CMDLINE, 0, + cmd = grub_register_extcmd ("functional_test", grub_functional_test, 0, 0, "Run all functional tests.", 0); } diff --git a/grub-core/tests/test_blockarg.c b/grub-core/tests/test_blockarg.c index bb6f3c3f0..41460fb7e 100644 --- a/grub-core/tests/test_blockarg.c +++ b/grub-core/tests/test_blockarg.c @@ -40,7 +40,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(test_blockarg) { cmd = grub_register_extcmd ("test_blockarg", test_blockarg, - GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_BLOCKS, + GRUB_COMMAND_FLAG_BLOCKS, N_("BLOCK"), N_("Print and execute block argument."), 0); } diff --git a/grub-core/video/efi_gop.c b/grub-core/video/efi_gop.c index 4e79b8521..f02dc9cb6 100644 --- a/grub-core/video/efi_gop.c +++ b/grub-core/video/efi_gop.c @@ -127,9 +127,11 @@ grub_video_gop_get_bitmask (grub_uint32_t mask, unsigned int *mask_size, } static grub_err_t -grub_video_gop_fill_mode_info (struct grub_efi_gop_mode_info *in, +grub_video_gop_fill_mode_info (unsigned mode, + struct grub_efi_gop_mode_info *in, struct grub_video_mode_info *out) { + out->mode_number = mode; out->number_of_colors = 256; out->width = in->width; out->height = in->height; @@ -183,9 +185,43 @@ grub_video_gop_fill_mode_info (struct grub_efi_gop_mode_info *in, return GRUB_ERR_NONE; } +static int +grub_video_gop_iterate (int (*hook) (const struct grub_video_mode_info *info)) +{ + unsigned mode; + + for (mode = 0; mode < gop->mode->max_mode; mode++) + { + grub_efi_uintn_t size; + grub_efi_status_t status; + struct grub_efi_gop_mode_info *info = NULL; + grub_err_t err; + struct grub_video_mode_info mode_info; + + status = efi_call_4 (gop->query_mode, gop, mode, &size, &info); + + if (status) + { + info = 0; + continue; + } + + err = grub_video_gop_fill_mode_info (mode, info, &mode_info); + if (err) + { + grub_errno = GRUB_ERR_NONE; + continue; + } + if (hook (&mode_info)) + return 1; + } + return 0; +} + static grub_err_t grub_video_gop_setup (unsigned int width, unsigned int height, - unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused))) + unsigned int mode_type, + unsigned int mode_mask __attribute__ ((unused))) { unsigned int depth; struct grub_efi_gop_mode_info *info = NULL; @@ -226,7 +262,7 @@ grub_video_gop_setup (unsigned int width, unsigned int height, if (status) { info = 0; - break; + continue; } grub_dprintf ("video", "GOP: mode %d: %dx%d\n", mode, info->width, @@ -281,7 +317,8 @@ grub_video_gop_setup (unsigned int width, unsigned int height, info = gop->mode->info; - err = grub_video_gop_fill_mode_info (info, &framebuffer.mode_info); + err = grub_video_gop_fill_mode_info (gop->mode->mode, info, + &framebuffer.mode_info); if (err) { grub_dprintf ("video", "GOP: couldn't fill mode info\n"); @@ -379,6 +416,7 @@ static struct grub_video_adapter grub_video_gop_adapter = .delete_render_target = grub_video_fb_delete_render_target, .set_active_render_target = grub_video_gop_set_active_render_target, .get_active_render_target = grub_video_fb_get_active_render_target, + .iterate = grub_video_gop_iterate, .next = 0 }; diff --git a/grub-core/video/efi_uga.c b/grub-core/video/efi_uga.c index 6352d4342..a8f70edea 100644 --- a/grub-core/video/efi_uga.c +++ b/grub-core/video/efi_uga.c @@ -198,7 +198,8 @@ grub_video_uga_fini (void) static grub_err_t grub_video_uga_setup (unsigned int width, unsigned int height, - unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused))) + unsigned int mode_type, + unsigned int mode_mask __attribute__ ((unused))) { unsigned int depth; int found = 0; diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c index 3817b3f68..4bb46e4cd 100644 --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -33,7 +33,6 @@ static int vbe_detected = -1; static struct grub_vbe_info_block controller_info; -static struct grub_vbe_mode_info_block active_vbe_mode_info; /* Track last mode to support cards which fail on get_mode. */ static grub_uint32_t last_set_mode = 3; @@ -42,11 +41,7 @@ static struct { struct grub_video_mode_info mode_info; - unsigned int bytes_per_scan_line; - unsigned int bytes_per_pixel; - grub_uint32_t active_vbe_mode; grub_uint8_t *ptr; - int index_color_mode; } framebuffer; static grub_uint32_t initial_vbe_mode; @@ -332,21 +327,12 @@ grub_vbe_set_video_mode (grub_uint32_t vbe_mode, vbe_mode |= 1 << 14; /* Determine frame buffer pixel format. */ - switch (new_vbe_mode_info.memory_model) - { - case GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL: - framebuffer.index_color_mode = 1; - break; - - case GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR: - framebuffer.index_color_mode = 0; - break; - - default: - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "unsupported pixel format 0x%x", - new_vbe_mode_info.memory_model); - } + if (new_vbe_mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL + && new_vbe_mode_info.memory_model + != GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "unsupported pixel format 0x%x", + new_vbe_mode_info.memory_model); } /* Get current mode. */ @@ -360,24 +346,14 @@ grub_vbe_set_video_mode (grub_uint32_t vbe_mode, return grub_error (GRUB_ERR_BAD_DEVICE, "cannot set VBE mode %x", vbe_mode); last_set_mode = vbe_mode; - /* Save information for later usage. */ - framebuffer.active_vbe_mode = vbe_mode; - grub_memcpy (&active_vbe_mode_info, &new_vbe_mode_info, sizeof (active_vbe_mode_info)); - if (vbe_mode < 0x100) { /* If this is not a VESA mode, guess address. */ framebuffer.ptr = (grub_uint8_t *) GRUB_MEMORY_MACHINE_VGA_ADDR; - framebuffer.index_color_mode = 1; } else { framebuffer.ptr = (grub_uint8_t *) new_vbe_mode_info.phys_base_addr; - - if (controller_info.version >= 0x300) - framebuffer.bytes_per_scan_line = new_vbe_mode_info.lin_bytes_per_scan_line; - else - framebuffer.bytes_per_scan_line = new_vbe_mode_info.bytes_per_scan_line; } /* Check whether mode is text mode or graphics mode. */ @@ -392,25 +368,9 @@ grub_vbe_set_video_mode (grub_uint32_t vbe_mode, { /* Graphics mode. */ - /* Calculate bytes_per_pixel value. */ - switch(new_vbe_mode_info.bits_per_pixel) - { - case 32: framebuffer.bytes_per_pixel = 4; break; - case 24: framebuffer.bytes_per_pixel = 3; break; - case 16: framebuffer.bytes_per_pixel = 2; break; - case 15: framebuffer.bytes_per_pixel = 2; break; - case 8: framebuffer.bytes_per_pixel = 1; break; - default: - grub_vbe_bios_set_mode (old_vbe_mode, 0); - last_set_mode = old_vbe_mode; - return grub_error (GRUB_ERR_BAD_DEVICE, - "cannot set VBE mode %x", - vbe_mode); - break; - } - /* If video mode is in indexed color, setup default VGA palette. */ - if (framebuffer.index_color_mode) + if (vbe_mode < 0x100 || new_vbe_mode_info.memory_model + == GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL) { struct grub_vbe_palette_data *palette = (struct grub_vbe_palette_data *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; @@ -548,10 +508,13 @@ grub_video_vbe_fini (void) grub_err_t err; /* Restore old video mode. */ - status = grub_vbe_bios_set_mode (initial_vbe_mode, 0); - if (status != GRUB_VBE_STATUS_OK) - /* TODO: Decide, is this something we want to do. */ - return grub_errno; + if (last_set_mode != initial_vbe_mode) + { + status = grub_vbe_bios_set_mode (initial_vbe_mode, 0); + if (status != GRUB_VBE_STATUS_OK) + /* TODO: Decide, is this something we want to do. */ + return grub_errno; + } last_set_mode = initial_vbe_mode; /* TODO: Free any resources allocated by driver. */ @@ -583,6 +546,120 @@ doublebuf_pageflipping_set_page (int page) return 0; } +static void +vbe2videoinfo (grub_uint32_t mode, + const struct grub_vbe_mode_info_block *vbeinfo, + struct grub_video_mode_info *mode_info) +{ + mode_info->mode_number = mode; + + mode_info->width = vbeinfo->x_resolution; + mode_info->height = vbeinfo->y_resolution; + mode_info->mode_type = 0; + switch (vbeinfo->memory_model) + { + case GRUB_VBE_MEMORY_MODEL_TEXT: + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_PURE_TEXT; + break; + + /* CGA is basically 4-bit packed pixel. */ + case GRUB_VBE_MEMORY_MODEL_CGA: + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_CGA; + case GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL: + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; + break; + + case GRUB_VBE_MEMORY_MODEL_HERCULES: + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_HERCULES + | GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP; + break; + + /* Non chain 4 is a special case of planar. */ + case GRUB_VBE_MEMORY_MODEL_NONCHAIN4_256: + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_NONCHAIN4; + case GRUB_VBE_MEMORY_MODEL_PLANAR: + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_PLANAR + | GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; + break; + + case GRUB_VBE_MEMORY_MODEL_YUV: + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_YUV; + break; + + case GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR: + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_RGB; + break; + default: + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_UNKNOWN; + break; + } + + mode_info->bpp = vbeinfo->bits_per_pixel; + /* Calculate bytes_per_pixel value. */ + switch(vbeinfo->bits_per_pixel) + { + case 32: + mode_info->bytes_per_pixel = 4; + break; + case 24: + mode_info->bytes_per_pixel = 3; + break; + case 16: + mode_info->bytes_per_pixel = 2; + break; + case 15: + mode_info->bytes_per_pixel = 2; + break; + case 8: + mode_info->bytes_per_pixel = 1; + break; + case 4: + mode_info->bytes_per_pixel = 0; + break; + } + + if (controller_info.version >= 0x300) + mode_info->pitch = vbeinfo->lin_bytes_per_scan_line; + else + mode_info->pitch = vbeinfo->bytes_per_scan_line; + + mode_info->number_of_colors = 256; /* TODO: fix me. */ + mode_info->red_mask_size = vbeinfo->red_mask_size; + mode_info->red_field_pos = vbeinfo->red_field_position; + mode_info->green_mask_size = vbeinfo->green_mask_size; + mode_info->green_field_pos = vbeinfo->green_field_position; + mode_info->blue_mask_size = vbeinfo->blue_mask_size; + mode_info->blue_field_pos = vbeinfo->blue_field_position; + mode_info->reserved_mask_size = vbeinfo->rsvd_mask_size; + mode_info->reserved_field_pos = vbeinfo->rsvd_field_position; + + mode_info->blit_format = grub_video_get_blit_format (mode_info); +} + +static int +grub_video_vbe_iterate (int (*hook) (const struct grub_video_mode_info *info)) +{ + grub_uint16_t *p; + struct grub_vbe_mode_info_block vbe_mode_info; + struct grub_video_mode_info mode_info; + + for (p = vbe_mode_list; *p != 0xFFFF; p++) + { + grub_vbe_get_video_mode_info (*p, &vbe_mode_info); + if (grub_errno != GRUB_ERR_NONE) + { + /* Could not retrieve mode info, retreat. */ + grub_errno = GRUB_ERR_NONE; + break; + } + + vbe2videoinfo (*p, &vbe_mode_info, &mode_info); + if (hook (&mode_info)) + return 1; + } + return 0; +} + static grub_err_t grub_video_vbe_setup (unsigned int width, unsigned int height, unsigned int mode_type, unsigned int mode_mask) @@ -631,6 +708,14 @@ grub_video_vbe_setup (unsigned int width, unsigned int height, /* Not compatible memory model. */ continue; + if (vbe_mode_info.bits_per_pixel != 8 + && vbe_mode_info.bits_per_pixel != 15 + && vbe_mode_info.bits_per_pixel != 16 + && vbe_mode_info.bits_per_pixel != 24 + && vbe_mode_info.bits_per_pixel != 32) + /* Unsupported bitdepth . */ + continue; + if (((vbe_mode_info.x_resolution != width) || (vbe_mode_info.y_resolution != height)) && width != 0 && height != 0) /* Non matching resolution. */ @@ -676,36 +761,16 @@ grub_video_vbe_setup (unsigned int width, unsigned int height, if (best_vbe_mode != 0) { grub_err_t err; + static struct grub_vbe_mode_info_block active_vbe_mode_info; /* If this fails, then we have mode selection heuristics problem, or adapter failure. */ - /* grub_vbe_set_video_mode already sets active_vbe_mode_info. */ - grub_vbe_set_video_mode (best_vbe_mode, NULL); + grub_vbe_set_video_mode (best_vbe_mode, &active_vbe_mode_info); if (grub_errno != GRUB_ERR_NONE) return grub_errno; /* Fill mode info details. */ - framebuffer.mode_info.width = active_vbe_mode_info.x_resolution; - framebuffer.mode_info.height = active_vbe_mode_info.y_resolution; - - if (framebuffer.index_color_mode) - framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; - else - framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB; - - framebuffer.mode_info.bpp = active_vbe_mode_info.bits_per_pixel; - framebuffer.mode_info.bytes_per_pixel = framebuffer.bytes_per_pixel; - framebuffer.mode_info.pitch = framebuffer.bytes_per_scan_line; - framebuffer.mode_info.number_of_colors = 256; /* TODO: fix me. */ - framebuffer.mode_info.red_mask_size = active_vbe_mode_info.red_mask_size; - framebuffer.mode_info.red_field_pos = active_vbe_mode_info.red_field_position; - framebuffer.mode_info.green_mask_size = active_vbe_mode_info.green_mask_size; - framebuffer.mode_info.green_field_pos = active_vbe_mode_info.green_field_position; - framebuffer.mode_info.blue_mask_size = active_vbe_mode_info.blue_mask_size; - framebuffer.mode_info.blue_field_pos = active_vbe_mode_info.blue_field_position; - framebuffer.mode_info.reserved_mask_size = active_vbe_mode_info.rsvd_mask_size; - framebuffer.mode_info.reserved_field_pos = active_vbe_mode_info.rsvd_field_position; - - framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info); + vbe2videoinfo (best_vbe_mode, &active_vbe_mode_info, + &framebuffer.mode_info); { /* Get video RAM size in bytes. */ @@ -740,7 +805,7 @@ static grub_err_t grub_video_vbe_set_palette (unsigned int start, unsigned int count, struct grub_video_palette_data *palette_data) { - if (framebuffer.index_color_mode) + if (framebuffer.mode_info.mode_type == GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) { /* TODO: Implement setting indexed color mode palette to hardware. */ //status = grub_vbe_bios_set_palette_data (sizeof (vga_colors) @@ -764,6 +829,20 @@ grub_video_vbe_get_info_and_fini (struct grub_video_mode_info *mode_info, return grub_video_fb_get_info_and_fini (mode_info, framebuf); } +static void +grub_video_vbe_print_adapter_specific_info (void) +{ + grub_printf (" VBE info: version: %d.%d OEM software rev: %d.%d\n", + controller_info.version >> 8, + controller_info.version & 0xFF, + controller_info.oem_software_rev >> 8, + controller_info.oem_software_rev & 0xFF); + + /* The total_memory field is in 64 KiB units. */ + grub_printf (" total memory: %d KiB\n", + (controller_info.total_memory << 16) / 1024); +} + static struct grub_video_adapter grub_video_vbe_adapter = { .name = "VESA BIOS Extension Video Driver", @@ -793,6 +872,8 @@ static struct grub_video_adapter grub_video_vbe_adapter = .delete_render_target = grub_video_fb_delete_render_target, .set_active_render_target = grub_video_fb_set_active_render_target, .get_active_render_target = grub_video_fb_get_active_render_target, + .iterate = grub_video_vbe_iterate, + .print_adapter_specific_info = grub_video_vbe_print_adapter_specific_info, .next = 0 }; diff --git a/grub-core/video/ieee1275.c b/grub-core/video/ieee1275.c index 9c9477c2b..501ba7c2f 100644 --- a/grub-core/video/ieee1275.c +++ b/grub-core/video/ieee1275.c @@ -32,6 +32,8 @@ static unsigned old_width, old_height; static int restore_needed; static char *display; +static grub_ieee1275_ihandle_t stdout_ihandle; +static int have_setcolors = 0; static struct { @@ -72,7 +74,17 @@ find_display (void) static grub_err_t grub_video_ieee1275_init (void) { + grub_ssize_t actual; + grub_memset (&framebuffer, 0, sizeof(framebuffer)); + + if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_SET_COLORS) + && !grub_ieee1275_get_integer_property (grub_ieee1275_chosen, + "stdout", &stdout_ihandle, + sizeof (stdout_ihandle), &actual) + && actual == sizeof (stdout_ihandle)) + have_setcolors = 1; + return grub_video_fb_init (); } @@ -169,9 +181,6 @@ grub_video_ieee1275_setup (unsigned int width, unsigned int height, /* For some reason sparc64 uses 32-bit pointer too. */ framebuffer.ptr = (void *) (grub_addr_t) address; - grub_video_ieee1275_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, - grub_video_fbstd_colors); - grub_dprintf ("video", "IEEE1275: initialising FB @ %p %dx%dx%d\n", framebuffer.ptr, framebuffer.mode_info.width, framebuffer.mode_info.height, framebuffer.mode_info.bpp); @@ -192,15 +201,10 @@ grub_video_ieee1275_setup (unsigned int width, unsigned int height, grub_dprintf ("video", "IEEE1275: Couldn't set FB target\n"); return err; } - - err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, - grub_video_fbstd_colors); - if (err) - grub_dprintf ("video", "IEEE1275: Couldn't set palette\n"); - else - grub_dprintf ("video", "IEEE1275: Success\n"); - + grub_video_ieee1275_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, + grub_video_fbstd_colors); + return err; } @@ -243,9 +247,17 @@ grub_video_ieee1275_set_palette (unsigned int start, unsigned int count, if (err) return err; - grub_video_fb_get_palette (0, 256, fb_palette_data); + grub_video_fb_get_palette (0, ARRAY_SIZE (fb_palette_data), fb_palette_data); - /* TODO. */ + /* Set colors. */ + if (have_setcolors) + { + unsigned col; + for (col = 0; col < ARRAY_SIZE (fb_palette_data); col++) + grub_ieee1275_set_color (stdout_ihandle, col, fb_palette_data[col].r, + fb_palette_data[col].g, + fb_palette_data[col].b); + } return GRUB_ERR_NONE; } diff --git a/include/grub/acpi.h b/include/grub/acpi.h index 7933db824..aebc8dd4f 100644 --- a/include/grub/acpi.h +++ b/include/grub/acpi.h @@ -53,17 +53,92 @@ struct grub_acpi_table_header grub_uint32_t creator_rev; } __attribute__ ((packed)); +#define GRUB_ACPI_FADT_SIGNATURE "FACP" + struct grub_acpi_fadt { struct grub_acpi_table_header hdr; grub_uint32_t facs_addr; grub_uint32_t dsdt_addr; - grub_uint8_t somefields1[88]; + grub_uint8_t somefields1[20]; + grub_uint32_t pm1a; + grub_uint8_t somefields2[64]; grub_uint64_t facs_xaddr; grub_uint64_t dsdt_xaddr; - grub_uint8_t somefields2[96]; + grub_uint8_t somefields3[96]; } __attribute__ ((packed)); +#define GRUB_ACPI_MADT_SIGNATURE "APIC" + +struct grub_acpi_madt_entry_header +{ + grub_uint8_t type; + grub_uint8_t len; +}; + +struct grub_acpi_madt +{ + struct grub_acpi_table_header hdr; + grub_uint32_t lapic_addr; + grub_uint32_t flags; + struct grub_acpi_madt_entry_header entries[0]; +}; + +enum + { + GRUB_ACPI_MADT_ENTRY_TYPE_INTERRUPT_OVERRIDE = 2, + GRUB_ACPI_MADT_ENTRY_TYPE_SAPIC = 6, + GRUB_ACPI_MADT_ENTRY_TYPE_LSAPIC = 7, + GRUB_ACPI_MADT_ENTRY_TYPE_PLATFORM_INT_SOURCE = 8 + }; + +struct grub_acpi_madt_entry_interrupt_override +{ + struct grub_acpi_madt_entry_header hdr; + grub_uint8_t bus; + grub_uint8_t source; + grub_uint32_t global_sys_interrupt; + grub_uint16_t flags; +}; + +struct grub_acpi_madt_entry_sapic +{ + struct grub_acpi_madt_entry_header hdr; + grub_uint8_t id; + grub_uint8_t pad; + grub_uint32_t global_sys_interrupt_base; + grub_uint64_t addr; +}; + +struct grub_acpi_madt_entry_lsapic +{ + struct grub_acpi_madt_entry_header hdr; + grub_uint8_t cpu_id; + grub_uint8_t id; + grub_uint8_t eid; + grub_uint8_t pad[3]; + grub_uint32_t flags; + grub_uint32_t cpu_uid; + grub_uint8_t cpu_uid_str[0]; +}; + +struct grub_acpi_madt_entry_platform_int_source +{ + struct grub_acpi_madt_entry_header hdr; + grub_uint16_t flags; + grub_uint8_t inttype; + grub_uint8_t cpu_id; + grub_uint8_t cpu_eid; + grub_uint8_t sapic_vector; + grub_uint32_t global_sys_int; + grub_uint32_t src_flags; +}; + +enum + { + GRUB_ACPI_MADT_ENTRY_SAPIC_FLAGS_ENABLED = 1 + }; + struct grub_acpi_rsdp_v10 *grub_acpi_get_rsdpv1 (void); struct grub_acpi_rsdp_v20 *grub_acpi_get_rsdpv2 (void); struct grub_acpi_rsdp_v10 *grub_machine_acpi_get_rsdpv1 (void); @@ -72,4 +147,25 @@ grub_uint8_t grub_byte_checksum (void *base, grub_size_t size); grub_err_t grub_acpi_create_ebda (void); +void grub_acpi_halt (void); + +#define GRUB_ACPI_SLP_EN (1 << 13) +#define GRUB_ACPI_SLP_TYP_OFFSET 10 + +enum + { + GRUB_ACPI_OPCODE_ZERO = 0, GRUB_ACPI_OPCODE_ONE = 1, + GRUB_ACPI_OPCODE_NAME = 8, GRUB_ACPI_OPCODE_BYTE_CONST = 0x0a, + GRUB_ACPI_OPCODE_WORD_CONST = 0x0b, GRUB_ACPI_OPCODE_DWORD_CONST = 0x0c, + GRUB_ACPI_OPCODE_SCOPE = 0x10, GRUB_ACPI_OPCODE_PACKAGE = 0x12, + GRUB_ACPI_OPCODE_METHOD = 0x14, GRUB_ACPI_OPCODE_EXTOP = 0x5b, + GRUB_ACPI_OPCODE_IF = 0xa0, GRUB_ACPI_OPCODE_ONES = 0xff + }; +enum + { + GRUB_ACPI_EXTOPCODE_MUTEX = 0x01, + GRUB_ACPI_EXTOPCODE_OPERATION_REGION = 0x80, + GRUB_ACPI_EXTOPCODE_FIELD_OP = 0x81 + }; + #endif /* ! GRUB_ACPI_HEADER */ diff --git a/include/grub/at_keyboard.h b/include/grub/at_keyboard.h index 10421540a..65cf8a2a2 100644 --- a/include/grub/at_keyboard.h +++ b/include/grub/at_keyboard.h @@ -19,36 +19,20 @@ #ifndef GRUB_AT_KEYBOARD_HEADER #define GRUB_AT_KEYBOARD_HEADER 1 -#define SHIFT_L 0x2a -#define SHIFT_R 0x36 -#define CTRL 0x1d -#define ALT 0x38 -#define CAPS_LOCK 0x3a -#define NUM_LOCK 0x45 -#define SCROLL_LOCK 0x46 - /* Used for sending commands to the controller. */ #define KEYBOARD_COMMAND_ISREADY(x) !((x) & 0x02) #define KEYBOARD_COMMAND_READ 0x20 #define KEYBOARD_COMMAND_WRITE 0x60 #define KEYBOARD_COMMAND_REBOOT 0xfe -#define KEYBOARD_SCANCODE_SET1 0x40 +#define KEYBOARD_AT_TRANSLATE 0x40 + +#define GRUB_AT_ACK 0xfa +#define GRUB_AT_NACK 0xfe +#define GRUB_AT_TRIES 5 #define KEYBOARD_ISMAKE(x) !((x) & 0x80) #define KEYBOARD_ISREADY(x) ((x) & 0x01) #define KEYBOARD_SCANCODE(x) ((x) & 0x7f) -#ifdef GRUB_MACHINE_IEEE1275 -#define OLPC_UP GRUB_TERM_UP -#define OLPC_DOWN GRUB_TERM_DOWN -#define OLPC_LEFT GRUB_TERM_LEFT -#define OLPC_RIGHT GRUB_TERM_RIGHT -#else -#define OLPC_UP '\0' -#define OLPC_DOWN '\0' -#define OLPC_LEFT '\0' -#define OLPC_RIGHT '\0' -#endif - #endif diff --git a/include/grub/autoefi.h b/include/grub/autoefi.h index 740be3249..b75591176 100644 --- a/include/grub/autoefi.h +++ b/include/grub/autoefi.h @@ -34,17 +34,6 @@ static inline grub_err_t grub_autoefi_prepare (void) { return GRUB_ERR_NONE; }; -# define GRUB_AUTOEFI_MEMORY_AVAILABLE GRUB_MACHINE_MEMORY_AVAILABLE -# define GRUB_AUTOEFI_MEMORY_RESERVED GRUB_MACHINE_MEMORY_RESERVED -# ifdef GRUB_MACHINE_MEMORY_ACPI -# define GRUB_AUTOEFI_MEMORY_ACPI GRUB_MACHINE_MEMORY_ACPI -# endif -# ifdef GRUB_MACHINE_MEMORY_NVS -# define GRUB_AUTOEFI_MEMORY_NVS GRUB_MACHINE_MEMORY_NVS -# endif -# ifdef GRUB_MACHINE_MEMORY_CODE -# define GRUB_AUTOEFI_MEMORY_CODE GRUB_MACHINE_MEMORY_CODE -# endif # define SYSTEM_TABLE_SIZEOF(x) (sizeof(grub_efi_system_table->x)) # define SYSTEM_TABLE_VAR(x) ((void *)&(grub_efi_system_table->x)) # define SYSTEM_TABLE_PTR(x) ((void *)(grub_efi_system_table->x)) @@ -61,11 +50,6 @@ static inline grub_err_t grub_autoefi_prepare (void) # define grub_autoefi_mmap_iterate grub_efiemu_mmap_iterate # define grub_autoefi_prepare grub_efiemu_prepare # define grub_autoefi_set_virtual_address_map grub_efiemu_set_virtual_address_map -# define GRUB_AUTOEFI_MEMORY_AVAILABLE GRUB_EFIEMU_MEMORY_AVAILABLE -# define GRUB_AUTOEFI_MEMORY_RESERVED GRUB_EFIEMU_MEMORY_RESERVED -# define GRUB_AUTOEFI_MEMORY_ACPI GRUB_EFIEMU_MEMORY_ACPI -# define GRUB_AUTOEFI_MEMORY_NVS GRUB_EFIEMU_MEMORY_NVS -# define GRUB_AUTOEFI_MEMORY_CODE GRUB_EFIEMU_MEMORY_CODE # define SYSTEM_TABLE_SIZEOF GRUB_EFIEMU_SYSTEM_TABLE_SIZEOF # define SYSTEM_TABLE_VAR GRUB_EFIEMU_SYSTEM_TABLE_VAR # define SYSTEM_TABLE_PTR GRUB_EFIEMU_SYSTEM_TABLE_PTR diff --git a/include/grub/cache.h b/include/grub/cache.h index 27e44f0a2..4f913f5c8 100644 --- a/include/grub/cache.h +++ b/include/grub/cache.h @@ -23,6 +23,10 @@ #include #include +#ifdef _mips +#include +#endif + #if defined (__i386__) || defined (__x86_64__) static inline void grub_arch_sync_caches (void *address __attribute__ ((unused)), diff --git a/include/grub/command.h b/include/grub/command.h index 599b99437..3b7bf0a10 100644 --- a/include/grub/command.h +++ b/include/grub/command.h @@ -23,22 +23,19 @@ #include #include -/* Can be run in the command-line. */ -#define GRUB_COMMAND_FLAG_CMDLINE 0x1 -/* Can be run in the menu. */ -#define GRUB_COMMAND_FLAG_MENU 0x2 -/* Can be run in both interfaces. */ -#define GRUB_COMMAND_FLAG_BOTH 0x3 -/* Only for the command title. */ -#define GRUB_COMMAND_FLAG_TITLE 0x4 -/* Don't print the command on booting. */ -#define GRUB_COMMAND_FLAG_NO_ECHO 0x8 -/* This is an extended command. */ -#define GRUB_COMMAND_FLAG_EXTCMD 0x10 -/* This is an dynamic command. */ -#define GRUB_COMMAND_FLAG_DYNCMD 0x20 -/* This command accepts block arguments. */ -#define GRUB_COMMAND_FLAG_BLOCKS 0x40 +typedef enum grub_command_flags + { + /* This is an extended command. */ + GRUB_COMMAND_FLAG_EXTCMD = 0x10, + /* This is an dynamic command. */ + GRUB_COMMAND_FLAG_DYNCMD = 0x20, + /* This command accepts block arguments. */ + GRUB_COMMAND_FLAG_BLOCKS = 0x40, + /* This command accepts unknown arguments as direct parameters. */ + GRUB_COMMAND_ACCEPT_DASH = 0x80, + /* This command accepts only options preceding direct arguments. */ + GRUB_COMMAND_OPTIONS_AT_START = 0x100, + } grub_command_flags_t; struct grub_command; @@ -61,7 +58,7 @@ struct grub_command grub_command_func_t func; /* The flags. */ - unsigned flags; + grub_command_flags_t flags; /* The summary of the command usage. */ const char *summary; diff --git a/include/grub/disk.h b/include/grub/disk.h index e7f807e0e..e3a0160c4 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -99,9 +99,6 @@ struct grub_disk /* The total number of sectors. */ grub_uint64_t total_sectors; - /* If partitions can be stored. */ - int has_partitions; - /* The id used by the disk cache manager. */ unsigned long id; @@ -177,4 +174,13 @@ struct grub_disk_ata_pass_through_parms extern grub_err_t (* EXPORT_VAR(grub_disk_ata_pass_through)) (grub_disk_t, struct grub_disk_ata_pass_through_parms *); +#if defined (GRUB_UTIL) || defined (GRUB_MACHINE_EMU) +void grub_lvm_init (void); +void grub_mdraid_init (void); +void grub_raid_init (void); +void grub_lvm_fini (void); +void grub_mdraid_fini (void); +void grub_raid_fini (void); +#endif + #endif /* ! GRUB_DISK_HEADER */ diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h index 36363ae1e..5eededdc2 100644 --- a/include/grub/efi/api.h +++ b/include/grub/efi/api.h @@ -109,6 +109,109 @@ { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ } +#define GRUB_EFI_SAL_TABLE_GUID \ + { 0xeb9d2d32, 0x2d88, 0x11d3, \ + { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +#define GRUB_EFI_HCDP_TABLE_GUID \ + { 0xf951938d, 0x620b, 0x42ef, \ + { 0x82, 0x79, 0xa8, 0x4b, 0x79, 0x61, 0x78, 0x98 } \ + } + +struct grub_efi_sal_system_table +{ + grub_uint32_t signature; + grub_uint32_t total_table_len; + grub_uint16_t sal_rev; + grub_uint16_t entry_count; + grub_uint8_t checksum; + grub_uint8_t reserved1[7]; + grub_uint16_t sal_a_version; + grub_uint16_t sal_b_version; + grub_uint8_t oem_id[32]; + grub_uint8_t product_id[32]; + grub_uint8_t reserved2[8]; + grub_uint8_t entries[0]; +}; + +enum + { + GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_ENTRYPOINT_DESCRIPTOR = 0, + GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_MEMORY_DESCRIPTOR = 1, + GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_PLATFORM_FEATURES = 2, + GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_TRANSLATION_REGISTER_DESCRIPTOR = 3, + GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_PURGE_TRANSLATION_COHERENCE = 4, + GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_AP_WAKEUP = 5 + }; + +struct grub_efi_sal_system_table_entrypoint_descriptor +{ + grub_uint8_t type; + grub_uint8_t pad[7]; + grub_uint64_t pal_proc_addr; + grub_uint64_t sal_proc_addr; + grub_uint64_t global_data_ptr; + grub_uint64_t reserved[2]; +}; + +struct grub_efi_sal_system_table_memory_descriptor +{ + grub_uint8_t type; + grub_uint8_t sal_used; + grub_uint8_t attr; + grub_uint8_t ar; + grub_uint8_t attr_mask; + grub_uint8_t mem_type; + grub_uint8_t usage; + grub_uint8_t unknown; + grub_uint64_t addr; + grub_uint64_t len; + grub_uint64_t unknown2; +}; + +struct grub_efi_sal_system_table_platform_features +{ + grub_uint8_t type; + grub_uint8_t flags; + grub_uint8_t reserved[14]; +}; + +struct grub_efi_sal_system_table_translation_register_descriptor +{ + grub_uint8_t type; + grub_uint8_t register_type; + grub_uint8_t register_number; + grub_uint8_t reserved[5]; + grub_uint64_t addr; + grub_uint64_t page_size; + grub_uint64_t reserver; +}; + +struct grub_efi_sal_system_table_purge_translation_coherence +{ + grub_uint8_t type; + grub_uint8_t reserved[3]; + grub_uint32_t ndomains; + grub_uint64_t coherence; +}; + +struct grub_efi_sal_system_table_ap_wakeup +{ + grub_uint8_t type; + grub_uint8_t mechanism; + grub_uint8_t reserved[6]; + grub_uint64_t vector; +}; + +enum + { + GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_BUSLOCK = 1, + GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_IRQREDIRECT = 2, + GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_IPIREDIRECT = 4, + GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_ITCDRIFT = 8, + }; + /* Enumerations. */ enum grub_efi_timer_delay { diff --git a/include/grub/efi/memory.h b/include/grub/efi/memory.h index 285be8359..133f9504c 100644 --- a/include/grub/efi/memory.h +++ b/include/grub/efi/memory.h @@ -24,16 +24,6 @@ #define GRUB_MMAP_REGISTER_BY_FIRMWARE 1 -#define GRUB_MACHINE_MEMORY_AVAILABLE 1 -#define GRUB_MACHINE_MEMORY_RESERVED 2 -#define GRUB_MACHINE_MEMORY_ACPI 3 -#define GRUB_MACHINE_MEMORY_NVS 4 -#define GRUB_MACHINE_MEMORY_CODE 5 -#define GRUB_MACHINE_MEMORY_MAX_TYPE 5 - /* This one is special: it's used internally but is never reported - by firmware. */ -#define GRUB_MACHINE_MEMORY_HOLE 6 - grub_err_t grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); diff --git a/include/grub/efiemu/efiemu.h b/include/grub/efiemu/efiemu.h index 56d4ea8ee..8eee98b61 100644 --- a/include/grub/efiemu/efiemu.h +++ b/include/grub/efiemu/efiemu.h @@ -233,11 +233,6 @@ grub_efiemu_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, int grub_efiemu_sizeof_uintn_t (void); grub_err_t grub_efiemu_get_lower_upper_memory (grub_uint64_t *lower, grub_uint64_t *upper); -#define GRUB_EFIEMU_MEMORY_AVAILABLE 1 -#define GRUB_EFIEMU_MEMORY_RESERVED 2 -#define GRUB_EFIEMU_MEMORY_ACPI 3 -#define GRUB_EFIEMU_MEMORY_NVS 4 -#define GRUB_EFIEMU_MEMORY_CODE 5 /* efiemu main control definitions and functions*/ typedef enum {GRUB_EFIEMU_NOTLOADED, diff --git a/include/grub/emu/getroot.h b/include/grub/emu/getroot.h index 04a2805c8..581ea8056 100644 --- a/include/grub/emu/getroot.h +++ b/include/grub/emu/getroot.h @@ -19,12 +19,15 @@ #ifndef GRUB_UTIL_GETROOT_HEADER #define GRUB_UTIL_GETROOT_HEADER 1 +#include + enum grub_dev_abstraction_types { GRUB_DEV_ABSTRACTION_NONE, GRUB_DEV_ABSTRACTION_LVM, GRUB_DEV_ABSTRACTION_RAID, }; +char *grub_find_device (const char *dir, dev_t dev); char *grub_guess_root_device (const char *dir); int grub_util_get_dev_abstraction (const char *os_dev); char *grub_util_get_grub_dev (const char *os_dev); diff --git a/include/grub/emu/hostdisk.h b/include/grub/emu/hostdisk.h index 246046ee0..d8cc02e14 100644 --- a/include/grub/emu/hostdisk.h +++ b/include/grub/emu/hostdisk.h @@ -26,5 +26,7 @@ void grub_util_biosdisk_init (const char *dev_map); void grub_util_biosdisk_fini (void); char *grub_util_biosdisk_get_grub_dev (const char *os_dev); const char *grub_util_biosdisk_get_osdev (grub_disk_t disk); +int grub_util_biosdisk_is_present (const char *name); +int grub_util_biosdisk_is_floppy (grub_disk_t disk); #endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */ diff --git a/include/grub/emu/misc.h b/include/grub/emu/misc.h index e9038c916..972bc4efc 100644 --- a/include/grub/emu/misc.h +++ b/include/grub/emu/misc.h @@ -45,6 +45,7 @@ extern const char *program_name; void grub_emu_init (void); void grub_init_all (void); void grub_fini_all (void); +void grub_emu_post_init (void); void grub_find_zpool_from_dir (const char *dir, char **poolname, char **poolfs); diff --git a/include/grub/extcmd.h b/include/grub/extcmd.h index 773e47854..c34a1df66 100644 --- a/include/grub/extcmd.h +++ b/include/grub/extcmd.h @@ -57,14 +57,14 @@ typedef struct grub_extcmd_context *grub_extcmd_context_t; grub_extcmd_t grub_register_extcmd (const char *name, grub_extcmd_func_t func, - unsigned flags, + grub_command_flags_t flags, const char *summary, const char *description, const struct grub_arg_option *parser); grub_extcmd_t grub_register_extcmd_prio (const char *name, grub_extcmd_func_t func, - unsigned flags, + grub_command_flags_t flags, const char *summary, const char *description, const struct grub_arg_option *parser, diff --git a/include/grub/i386/coreboot/memory.h b/include/grub/i386/coreboot/memory.h index 664086a81..0642280b9 100644 --- a/include/grub/i386/coreboot/memory.h +++ b/include/grub/i386/coreboot/memory.h @@ -21,11 +21,11 @@ #define _GRUB_MEMORY_MACHINE_LB_HEADER 1 #include -#include #ifndef ASM_FILE #include #include +#include #endif #define GRUB_MEMORY_MACHINE_LOWER_USABLE 0x9fc00 /* 640 kiB - 1 kiB */ @@ -35,36 +35,21 @@ #ifndef ASM_FILE -struct grub_linuxbios_table_header -{ - char signature[4]; - grub_uint32_t size; -}; -typedef struct grub_linuxbios_table_header *grub_linuxbios_table_header_t; - -struct grub_linuxbios_table_item -{ -#define GRUB_LINUXBIOS_MEMBER_UNUSED 0x00 -#define GRUB_LINUXBIOS_MEMBER_MEMORY 0x01 -#define GRUB_LINUXBIOS_MEMBER_LINK 0x11 - grub_uint32_t tag; - grub_uint32_t size; -}; -typedef struct grub_linuxbios_table_item *grub_linuxbios_table_item_t; - -struct grub_linuxbios_mem_region -{ - grub_uint64_t addr; - grub_uint64_t size; -#define GRUB_MACHINE_MEMORY_AVAILABLE 1 - grub_uint32_t type; -}; -typedef struct grub_linuxbios_mem_region *mem_region_t; - void grub_machine_mmap_init (void); -grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate) - (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); +static inline grub_err_t +grub_machine_mmap_register (grub_uint64_t start __attribute__ ((unused)), + grub_uint64_t size __attribute__ ((unused)), + int type __attribute__ ((unused)), + int handle __attribute__ ((unused))) +{ + return GRUB_ERR_NONE; +} +static inline grub_err_t +grub_machine_mmap_unregister (int handle __attribute__ ((unused))) +{ + return GRUB_ERR_NONE; +} #endif diff --git a/include/grub/i386/ieee1275/memory.h b/include/grub/i386/ieee1275/memory.h index 386ee4a05..8dd6f7c8c 100644 --- a/include/grub/i386/ieee1275/memory.h +++ b/include/grub/i386/ieee1275/memory.h @@ -1 +1 @@ -#include +#include diff --git a/include/grub/i386/memory.h b/include/grub/i386/memory.h index 4f9a3c916..582226eed 100644 --- a/include/grub/i386/memory.h +++ b/include/grub/i386/memory.h @@ -30,6 +30,14 @@ #ifndef ASM_FILE +#define GRUB_MMAP_MALLOC_LOW 1 + +#include + +grub_uint64_t grub_mmap_get_upper (void); +grub_uint64_t grub_mmap_get_lower (void); +grub_uint64_t grub_mmap_get_post64 (void); + typedef grub_addr_t grub_phys_addr_t; static inline grub_phys_addr_t diff --git a/include/grub/i386/pc/init.h b/include/grub/i386/pc/apm.h similarity index 52% rename from include/grub/i386/pc/init.h rename to include/grub/i386/pc/apm.h index 4005a1772..6d9e8c61d 100644 --- a/include/grub/i386/pc/init.h +++ b/include/grub/i386/pc/apm.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2004,2005,2007,2008 Free Software Foundation, Inc. + * Copyright (C) 2010 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,15 +16,33 @@ * along with GRUB. If not, see . */ -#ifndef GRUB_INIT_MACHINE_HEADER -#define GRUB_INIT_MACHINE_HEADER 1 +#ifndef GRUB_APM_MACHINE_HEADER +#define GRUB_APM_MACHINE_HEADER 1 #include -#include -#include -#include -/* Turn on/off Gate A20. */ -void grub_gate_a20 (int on); +struct grub_apm_info +{ + grub_uint16_t cseg; + grub_uint32_t offset; + grub_uint16_t cseg_16; + grub_uint16_t dseg; + grub_uint16_t flags; + grub_uint16_t cseg_len; + grub_uint16_t cseg_16_len; + grub_uint16_t dseg_len; + grub_uint16_t version; +}; -#endif /* ! GRUB_INIT_MACHINE_HEADER */ +enum + { + GRUB_APM_FLAGS_16BITPROTECTED_SUPPORTED = 1, + GRUB_APM_FLAGS_32BITPROTECTED_SUPPORTED = 2, + GRUB_APM_FLAGS_CPUIDLE_SLOWS_DOWN = 4, + GRUB_APM_FLAGS_DISABLED = 8, + GRUB_APM_FLAGS_DISENGAGED = 16, + }; + +int grub_apm_get_info (struct grub_apm_info *info); + +#endif diff --git a/include/grub/i386/pc/console.h b/include/grub/i386/pc/console.h index 7f58344ec..1631a40ad 100644 --- a/include/grub/i386/pc/console.h +++ b/include/grub/i386/pc/console.h @@ -19,19 +19,6 @@ #ifndef GRUB_CONSOLE_MACHINE_HEADER #define GRUB_CONSOLE_MACHINE_HEADER 1 -/* Define scan codes. */ -#define GRUB_CONSOLE_KEY_LEFT 0x4B00 -#define GRUB_CONSOLE_KEY_RIGHT 0x4D00 -#define GRUB_CONSOLE_KEY_UP 0x4800 -#define GRUB_CONSOLE_KEY_DOWN 0x5000 -#define GRUB_CONSOLE_KEY_IC 0x5200 -#define GRUB_CONSOLE_KEY_DC 0x5300 -#define GRUB_CONSOLE_KEY_BACKSPACE 0x0008 -#define GRUB_CONSOLE_KEY_HOME 0x4700 -#define GRUB_CONSOLE_KEY_END 0x4F00 -#define GRUB_CONSOLE_KEY_NPAGE 0x5100 -#define GRUB_CONSOLE_KEY_PPAGE 0x4900 - #ifndef ASM_FILE #include @@ -40,7 +27,6 @@ #include /* These are global to share code between C and asm. */ -int grub_console_checkkey (struct grub_term_input *term); int grub_console_getkey (struct grub_term_input *term); grub_uint16_t grub_console_getxy (struct grub_term_output *term); void grub_console_gotoxy (struct grub_term_output *term, diff --git a/include/grub/i386/pc/int.h b/include/grub/i386/pc/int.h index e1c463925..de23775d0 100644 --- a/include/grub/i386/pc/int.h +++ b/include/grub/i386/pc/int.h @@ -20,6 +20,7 @@ #define GRUB_INTERRUPT_MACHINE_HEADER 1 #include +#include struct grub_bios_int_registers { diff --git a/include/grub/i386/pc/memory.h b/include/grub/i386/pc/memory.h index 68f5e8bc9..401c837fa 100644 --- a/include/grub/i386/pc/memory.h +++ b/include/grub/i386/pc/memory.h @@ -88,51 +88,9 @@ struct grub_machine_bios_data_area grub_uint8_t unused2[0xf0 - 0x18]; }; -struct grub_machine_mmap_entry -{ - grub_uint32_t size; - grub_uint64_t addr; - grub_uint64_t len; -#define GRUB_MACHINE_MEMORY_AVAILABLE 1 -#define GRUB_MACHINE_MEMORY_RESERVED 2 -#define GRUB_MACHINE_MEMORY_ACPI 3 -#define GRUB_MACHINE_MEMORY_NVS 4 -#define GRUB_MACHINE_MEMORY_MAX_TYPE 4 - /* This one is special: it's used internally but is never reported - by firmware. */ -#define GRUB_MACHINE_MEMORY_HOLE 5 - - grub_uint32_t type; -} __attribute__((packed)); - -grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate) - (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); - -grub_uint64_t grub_mmap_get_post64 (void); -grub_uint64_t grub_mmap_get_upper (void); -grub_uint64_t grub_mmap_get_lower (void); - -#define GRUB_MMAP_MALLOC_LOW 1 - -#ifdef GRUB_MACHINE_PCBIOS grub_err_t grub_machine_mmap_register (grub_uint64_t start, grub_uint64_t size, int type, int handle); grub_err_t grub_machine_mmap_unregister (int handle); -#else -static inline grub_err_t -grub_machine_mmap_register (grub_uint64_t start __attribute__ ((unused)), - grub_uint64_t size __attribute__ ((unused)), - int type __attribute__ ((unused)), - int handle __attribute__ ((unused))) -{ - return GRUB_ERR_NONE; -} -static inline grub_err_t -grub_machine_mmap_unregister (int handle __attribute__ ((unused))) -{ - return GRUB_ERR_NONE; -} -#endif #endif diff --git a/include/grub/i386/pc/vesa_modes_table.h b/include/grub/i386/pc/vesa_modes_table.h new file mode 100644 index 000000000..376ca376b --- /dev/null +++ b/include/grub/i386/pc/vesa_modes_table.h @@ -0,0 +1,19 @@ +#ifndef GRUB_VESA_MODE_TABLE_HEADER +#define GRUB_VESA_MODE_TABLE_HEADER 1 + +#include + +#define GRUB_VESA_MODE_TABLE_START 0x300 +#define GRUB_VESA_MODE_TABLE_END 0x373 + +struct grub_vesa_mode_table_entry { + grub_uint16_t width; + grub_uint16_t height; + grub_uint8_t depth; +}; + +extern struct grub_vesa_mode_table_entry +grub_vesa_mode_table[GRUB_VESA_MODE_TABLE_END + - GRUB_VESA_MODE_TABLE_START + 1]; + +#endif diff --git a/include/grub/i386/qemu/memory.h b/include/grub/i386/qemu/memory.h index de559443d..2003e4934 100644 --- a/include/grub/i386/qemu/memory.h +++ b/include/grub/i386/qemu/memory.h @@ -21,7 +21,7 @@ #define _GRUB_MEMORY_MACHINE_HEADER 1 #include -#include +#include #ifndef ASM_FILE #include @@ -37,9 +37,6 @@ void grub_machine_mmap_init (void); -grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate) - (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); - #endif #endif /* ! _GRUB_MEMORY_MACHINE_HEADER */ diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h index b30909c68..2592dd348 100644 --- a/include/grub/ieee1275/ieee1275.h +++ b/include/grub/ieee1275/ieee1275.h @@ -103,6 +103,9 @@ enum grub_ieee1275_flag /* OpenFirmware hangs on qemu if one requests any memory below 1.5 MiB. */ GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM, + + /* OLPC / XO firmware has the cursor ON/OFF routines. */ + GRUB_IEEE1275_FLAG_HAS_CURSORONOFF, }; extern int EXPORT_FUNC(grub_ieee1275_test_flag) (enum grub_ieee1275_flag flag); @@ -187,4 +190,6 @@ int EXPORT_FUNC(grub_ieee1275_devices_iterate) (int (*hook) (struct grub_ieee1275_devalias * alias)); +char *EXPORT_FUNC(grub_ieee1275_canonicalise_devname) (const char *path); + #endif /* ! GRUB_IEEE1275_HEADER */ diff --git a/include/grub/keyboard_layouts.h b/include/grub/keyboard_layouts.h new file mode 100644 index 000000000..24d4880af --- /dev/null +++ b/include/grub/keyboard_layouts.h @@ -0,0 +1,142 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_KEYBOARD_LAYOUTS_H +#define GRUB_KEYBOARD_LAYOUTS_H 1 + +#define GRUB_KEYBOARD_LAYOUTS_FILEMAGIC "GRUBLAYO" +#define GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE (sizeof(GRUB_KEYBOARD_LAYOUTS_FILEMAGIC) - 1) +#define GRUB_KEYBOARD_LAYOUTS_VERSION 8 + +#define GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE 128 + +struct grub_keyboard_layout +{ + grub_uint32_t keyboard_map[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; + grub_uint32_t keyboard_map_shift[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; + grub_uint32_t keyboard_map_l3[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; + grub_uint32_t keyboard_map_shift_l3[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; +}; + +typedef enum grub_keyboard_key + { + GRUB_KEYBOARD_KEY_A = 0x04, + GRUB_KEYBOARD_KEY_B = 0x05, + GRUB_KEYBOARD_KEY_C = 0x06, + GRUB_KEYBOARD_KEY_D = 0x07, + GRUB_KEYBOARD_KEY_E = 0x08, + GRUB_KEYBOARD_KEY_F = 0x09, + GRUB_KEYBOARD_KEY_G = 0x0a, + GRUB_KEYBOARD_KEY_H = 0x0b, + GRUB_KEYBOARD_KEY_I = 0x0c, + GRUB_KEYBOARD_KEY_J = 0x0d, + GRUB_KEYBOARD_KEY_K = 0x0e, + GRUB_KEYBOARD_KEY_L = 0x0f, + GRUB_KEYBOARD_KEY_M = 0x10, + GRUB_KEYBOARD_KEY_N = 0x11, + GRUB_KEYBOARD_KEY_O = 0x12, + GRUB_KEYBOARD_KEY_P = 0x13, + GRUB_KEYBOARD_KEY_Q = 0x14, + GRUB_KEYBOARD_KEY_R = 0x15, + GRUB_KEYBOARD_KEY_S = 0x16, + GRUB_KEYBOARD_KEY_T = 0x17, + GRUB_KEYBOARD_KEY_U = 0x18, + GRUB_KEYBOARD_KEY_V = 0x19, + GRUB_KEYBOARD_KEY_W = 0x1a, + GRUB_KEYBOARD_KEY_X = 0x1b, + GRUB_KEYBOARD_KEY_Y = 0x1c, + GRUB_KEYBOARD_KEY_Z = 0x1d, + GRUB_KEYBOARD_KEY_1 = 0x1e, + GRUB_KEYBOARD_KEY_2 = 0x1f, + GRUB_KEYBOARD_KEY_3 = 0x20, + GRUB_KEYBOARD_KEY_4 = 0x21, + GRUB_KEYBOARD_KEY_5 = 0x22, + GRUB_KEYBOARD_KEY_6 = 0x23, + GRUB_KEYBOARD_KEY_7 = 0x24, + GRUB_KEYBOARD_KEY_8 = 0x25, + GRUB_KEYBOARD_KEY_9 = 0x26, + GRUB_KEYBOARD_KEY_0 = 0x27, + GRUB_KEYBOARD_KEY_ENTER = 0x28, + GRUB_KEYBOARD_KEY_ESCAPE = 0x29, + GRUB_KEYBOARD_KEY_BACKSPACE = 0x2a, + GRUB_KEYBOARD_KEY_TAB = 0x2b, + GRUB_KEYBOARD_KEY_SPACE = 0x2c, + GRUB_KEYBOARD_KEY_DASH = 0x2d, + GRUB_KEYBOARD_KEY_EQUAL = 0x2e, + GRUB_KEYBOARD_KEY_LBRACKET = 0x2f, + GRUB_KEYBOARD_KEY_RBRACKET = 0x30, + GRUB_KEYBOARD_KEY_BACKSLASH = 0x32, + GRUB_KEYBOARD_KEY_SEMICOLON = 0x33, + GRUB_KEYBOARD_KEY_DQUOTE = 0x34, + GRUB_KEYBOARD_KEY_RQUOTE = 0x35, + GRUB_KEYBOARD_KEY_COMMA = 0x36, + GRUB_KEYBOARD_KEY_DOT = 0x37, + GRUB_KEYBOARD_KEY_SLASH = 0x38, + GRUB_KEYBOARD_KEY_CAPS_LOCK = 0x39, + GRUB_KEYBOARD_KEY_F1 = 0x3a, + GRUB_KEYBOARD_KEY_F2 = 0x3b, + GRUB_KEYBOARD_KEY_F3 = 0x3c, + GRUB_KEYBOARD_KEY_F4 = 0x3d, + GRUB_KEYBOARD_KEY_F5 = 0x3e, + GRUB_KEYBOARD_KEY_F6 = 0x3f, + GRUB_KEYBOARD_KEY_F7 = 0x40, + GRUB_KEYBOARD_KEY_F8 = 0x41, + GRUB_KEYBOARD_KEY_F9 = 0x42, + GRUB_KEYBOARD_KEY_F10 = 0x43, + GRUB_KEYBOARD_KEY_F11 = 0x44, + GRUB_KEYBOARD_KEY_F12 = 0x45, + GRUB_KEYBOARD_KEY_SCROLL_LOCK = 0x47, + GRUB_KEYBOARD_KEY_INSERT = 0x49, + GRUB_KEYBOARD_KEY_HOME = 0x4a, + GRUB_KEYBOARD_KEY_PPAGE = 0x4b, + GRUB_KEYBOARD_KEY_DELETE = 0x4c, + GRUB_KEYBOARD_KEY_END = 0x4d, + GRUB_KEYBOARD_KEY_NPAGE = 0x4e, + GRUB_KEYBOARD_KEY_RIGHT = 0x4f, + GRUB_KEYBOARD_KEY_LEFT = 0x50, + GRUB_KEYBOARD_KEY_DOWN = 0x51, + GRUB_KEYBOARD_KEY_UP = 0x52, + GRUB_KEYBOARD_KEY_NUM_LOCK = 0x53, + GRUB_KEYBOARD_KEY_NUMSLASH = 0x54, + GRUB_KEYBOARD_KEY_NUMMUL = 0x55, + GRUB_KEYBOARD_KEY_NUMMINUS = 0x56, + GRUB_KEYBOARD_KEY_NUMPLUS = 0x57, + GRUB_KEYBOARD_KEY_NUMENTER = 0x58, + GRUB_KEYBOARD_KEY_NUM1 = 0x59, + GRUB_KEYBOARD_KEY_NUM2 = 0x5a, + GRUB_KEYBOARD_KEY_NUM3 = 0x5b, + GRUB_KEYBOARD_KEY_NUM4 = 0x5c, + GRUB_KEYBOARD_KEY_NUM5 = 0x5d, + GRUB_KEYBOARD_KEY_NUM6 = 0x5e, + GRUB_KEYBOARD_KEY_NUM7 = 0x5f, + GRUB_KEYBOARD_KEY_NUM8 = 0x60, + GRUB_KEYBOARD_KEY_NUM9 = 0x61, + GRUB_KEYBOARD_KEY_NUM0 = 0x62, + GRUB_KEYBOARD_KEY_NUMDOT = 0x63, + GRUB_KEYBOARD_KEY_102ND = 0x64, + GRUB_KEYBOARD_KEY_LEFT_CTRL = 0xe0, + GRUB_KEYBOARD_KEY_LEFT_SHIFT = 0xe1, + GRUB_KEYBOARD_KEY_LEFT_ALT = 0xe2, + GRUB_KEYBOARD_KEY_RIGHT_CTRL = 0xe4, + GRUB_KEYBOARD_KEY_RIGHT_SHIFT = 0xe5, + GRUB_KEYBOARD_KEY_RIGHT_ALT = 0xe6, + } grub_keyboard_key_t; + +unsigned EXPORT_FUNC(grub_term_map_key) (grub_keyboard_key_t code, int status); + +#endif /* GRUB_KEYBOARD_LAYOUTS */ diff --git a/include/grub/sparc64/ieee1275/memory.h b/include/grub/legacy_parse.h similarity index 70% rename from include/grub/sparc64/ieee1275/memory.h rename to include/grub/legacy_parse.h index 25e31002e..a5e67a071 100644 --- a/include/grub/sparc64/ieee1275/memory.h +++ b/include/grub/legacy_parse.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2009 Free Software Foundation, Inc. + * Copyright (C) 2008 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,11 +16,12 @@ * along with GRUB. If not, see . */ -#ifndef GRUB_MEMORY_MACHINE_HEADER -#define GRUB_MEMORY_MACHINE_HEADER 1 +#ifndef GRUB_LEGACY_PARSE_HEADER +#define GRUB_LEGACY_PARSE_HEADER 1 -#include +#include -#define GRUB_MACHINE_MEMORY_AVAILABLE 1 +char *grub_legacy_parse (const char *buf, char **entryname, char **suffix); +char *grub_legacy_escape (const char *in, grub_size_t len); #endif diff --git a/include/grub/loader.h b/include/grub/loader.h index 319f3c551..c71e8dd10 100644 --- a/include/grub/loader.h +++ b/include/grub/loader.h @@ -26,16 +26,16 @@ #include /* Check if a loader is loaded. */ -int grub_loader_is_loaded (void); +int EXPORT_FUNC (grub_loader_is_loaded) (void); /* Set loader functions. NORETURN must be set to true, if BOOT won't return to the original state. */ -void grub_loader_set (grub_err_t (*boot) (void), - grub_err_t (*unload) (void), - int noreturn); +void EXPORT_FUNC (grub_loader_set) (grub_err_t (*boot) (void), + grub_err_t (*unload) (void), + int noreturn); /* Unset current loader, if any. */ -void grub_loader_unset (void); +void EXPORT_FUNC (grub_loader_unset) (void); /* Call the boot hook in current loader. This may or may not return, depending on the setting by grub_loader_set. */ @@ -56,7 +56,7 @@ typedef enum { } grub_loader_preboot_hook_prio_t; /* Register a preboot hook. */ -void *grub_loader_register_preboot_hook (grub_err_t (*preboot_func) (int noret), +void *EXPORT_FUNC(grub_loader_register_preboot_hook) (grub_err_t (*preboot_func) (int noret), grub_err_t (*preboot_rest_func) (void), grub_loader_preboot_hook_prio_t prio); diff --git a/include/grub/memory.h b/include/grub/memory.h index 43f90e1dd..d98386565 100644 --- a/include/grub/memory.h +++ b/include/grub/memory.h @@ -22,11 +22,32 @@ #include #include -#include -grub_err_t grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, - grub_uint64_t, - grub_uint32_t)); +typedef enum grub_memory_type + { + GRUB_MEMORY_AVAILABLE = 1, + GRUB_MEMORY_RESERVED = 2, + GRUB_MEMORY_ACPI = 3, + GRUB_MEMORY_NVS = 4, + GRUB_MEMORY_BADRAM = 5, + GRUB_MEMORY_CODE = 20, + /* This one is special: it's used internally but is never reported + by firmware. */ + GRUB_MEMORY_HOLE = 21 + } grub_memory_type_t; + +typedef int NESTED_FUNC_ATTR (*grub_memory_hook_t) (grub_uint64_t, + grub_uint64_t, + grub_memory_type_t); + +grub_err_t grub_mmap_iterate (grub_memory_hook_t hook); + +#if !defined (GRUB_MACHINE_EMU) && !defined (GRUB_MACHINE_EFI) +grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate) (grub_memory_hook_t hook); +#else +grub_err_t grub_machine_mmap_iterate (grub_memory_hook_t hook); +#endif + int grub_mmap_register (grub_uint64_t start, grub_uint64_t size, int type); grub_err_t grub_mmap_unregister (int handle); @@ -42,7 +63,7 @@ struct grub_mmap_region struct grub_mmap_region *next; grub_uint64_t start; grub_uint64_t end; - int type; + grub_memory_type_t type; int handle; }; diff --git a/include/grub/mips/qemu-mips/memory.h b/include/grub/mips/qemu-mips/memory.h index 87e68674e..99d9ef2be 100644 --- a/include/grub/mips/qemu-mips/memory.h +++ b/include/grub/mips/qemu-mips/memory.h @@ -28,8 +28,6 @@ #define GRUB_MACHINE_MEMORY_STACK_HIGH 0x80f00000 #define GRUB_MACHINE_MEMORY_USABLE 0x81000000 -#define GRUB_MACHINE_MEMORY_AVAILABLE 1 - #ifndef ASM_FILE grub_err_t EXPORT_FUNC (grub_machine_mmap_iterate) (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); diff --git a/include/grub/mips/time.h b/include/grub/mips/time.h index e69de29bb..b143a48e0 100644 --- a/include/grub/mips/time.h +++ b/include/grub/mips/time.h @@ -0,0 +1,6 @@ +#ifdef GRUB_MACHINE_EMU +static inline void +grub_cpu_idle(void) +{ +} +#endif diff --git a/include/grub/mips/yeeloong/memory.h b/include/grub/mips/yeeloong/memory.h index e7e995283..9d53b5e0e 100644 --- a/include/grub/mips/yeeloong/memory.h +++ b/include/grub/mips/yeeloong/memory.h @@ -31,13 +31,6 @@ #define GRUB_ARCH_LOWMEMMAXSIZE 0x10000000 #define GRUB_ARCH_HIGHMEMPSTART 0x10000000 -#define GRUB_MACHINE_MEMORY_AVAILABLE 1 -#define GRUB_MACHINE_MEMORY_MAX_TYPE 1 - /* This one is special: it's used internally but is never reported - by firmware. */ -#define GRUB_MACHINE_MEMORY_HOLE 2 -#define GRUB_MACHINE_MEMORY_RESERVED GRUB_MACHINE_MEMORY_HOLE - #ifndef ASM_FILE typedef grub_addr_t grub_phys_addr_t; diff --git a/include/grub/normal.h b/include/grub/normal.h index 51ab46b12..72912e524 100644 --- a/include/grub/normal.h +++ b/include/grub/normal.h @@ -115,4 +115,15 @@ void grub_normal_reset_more (void); void grub_xputs_normal (const char *str); +grub_err_t +grub_normal_add_menu_entry (int argc, const char **args, char **classes, + const char *users, const char *hotkey, + const char *prefix, const char *sourcecode); + +grub_err_t +grub_normal_set_password (const char *user, const char *password); + +void grub_normal_auth_init (void); +void grub_normal_auth_fini (void); + #endif /* ! GRUB_NORMAL_HEADER */ diff --git a/include/grub/partition.h b/include/grub/partition.h index 20705c527..a29a3440d 100644 --- a/include/grub/partition.h +++ b/include/grub/partition.h @@ -26,6 +26,13 @@ struct grub_disk; typedef struct grub_partition *grub_partition_t; +#ifdef GRUB_UTIL +typedef enum +{ + GRUB_EMBED_PCBIOS +} grub_embed_type_t; +#endif + /* Partition map type. */ struct grub_partition_map { @@ -39,6 +46,11 @@ struct grub_partition_map grub_err_t (*iterate) (struct grub_disk *disk, int (*hook) (struct grub_disk *disk, const grub_partition_t partition)); +#ifdef GRUB_UTIL + /* Determine sectors available for embedding. */ + grub_err_t (*embed) (struct grub_disk *disk, unsigned int nsectors, + grub_embed_type_t embed_type, grub_disk_addr_t *sectors); +#endif }; typedef struct grub_partition_map *grub_partition_map_t; diff --git a/include/grub/powerpc/ieee1275/memory.h b/include/grub/powerpc/ieee1275/memory.h deleted file mode 100644 index f8f2ff08d..000000000 --- a/include/grub/powerpc/ieee1275/memory.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2008 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GRUB. If not, see . - */ - -#ifndef GRUB_MEMORY_MACHINE_HEADER -#define GRUB_MEMORY_MACHINE_HEADER 1 - -#include - -#define GRUB_MACHINE_MEMORY_AVAILABLE 1 - -#endif diff --git a/include/grub/search.h b/include/grub/search.h index e8f9db285..d80347df3 100644 --- a/include/grub/search.h +++ b/include/grub/search.h @@ -19,8 +19,11 @@ #ifndef GRUB_SEARCH_HEADER #define GRUB_SEARCH_HEADER 1 -void grub_search_fs_file (const char *key, const char *var, int no_floppy); -void grub_search_fs_uuid (const char *key, const char *var, int no_floppy); -void grub_search_label (const char *key, const char *var, int no_floppy); +void grub_search_fs_file (const char *key, const char *var, int no_floppy, + char **hints, unsigned nhints); +void grub_search_fs_uuid (const char *key, const char *var, int no_floppy, + char **hints, unsigned nhints); +void grub_search_label (const char *key, const char *var, int no_floppy, + char **hints, unsigned nhints); #endif diff --git a/include/grub/sparc64/ieee1275/boot.h b/include/grub/sparc64/ieee1275/boot.h index bd0a7bf3c..112d19bc7 100644 --- a/include/grub/sparc64/ieee1275/boot.h +++ b/include/grub/sparc64/ieee1275/boot.h @@ -52,4 +52,13 @@ #define GRUB_BOOT_MACHINE_KERNEL_ADDR 0x4200 +#ifndef ASM_FILE +/* This is the blocklist used in the diskboot image. */ +struct grub_boot_blocklist +{ + grub_uint64_t start; + grub_uint32_t len; +} __attribute__ ((packed)); +#endif + #endif /* ! BOOT_MACHINE_HEADER */ diff --git a/include/grub/term.h b/include/grub/term.h index 734e4ab17..dbcb2f52c 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -19,19 +19,45 @@ #ifndef GRUB_TERM_HEADER #define GRUB_TERM_HEADER 1 +#define GRUB_TERM_NO_KEY 0 + /* Internal codes used by GRUB to represent terminal input. */ -#define GRUB_TERM_LEFT 2 -#define GRUB_TERM_RIGHT 6 -#define GRUB_TERM_UP 16 -#define GRUB_TERM_DOWN 14 -#define GRUB_TERM_HOME 1 -#define GRUB_TERM_END 5 -#define GRUB_TERM_DC 4 -#define GRUB_TERM_PPAGE 7 -#define GRUB_TERM_NPAGE 3 +/* Only for keys otherwise not having shifted modification. */ +#define GRUB_TERM_SHIFT 0x01000000 +#define GRUB_TERM_CTRL 0x02000000 +#define GRUB_TERM_ALT 0x04000000 + +/* Keys without associated character. */ +#define GRUB_TERM_EXTENDED 0x00800000 +#define GRUB_TERM_KEY_MASK 0x00ffffff + +#define GRUB_TERM_KEY_LEFT (GRUB_TERM_EXTENDED | 0x4b) +#define GRUB_TERM_KEY_RIGHT (GRUB_TERM_EXTENDED | 0x4d) +#define GRUB_TERM_KEY_UP (GRUB_TERM_EXTENDED | 0x48) +#define GRUB_TERM_KEY_DOWN (GRUB_TERM_EXTENDED | 0x50) +#define GRUB_TERM_KEY_HOME (GRUB_TERM_EXTENDED | 0x47) +#define GRUB_TERM_KEY_END (GRUB_TERM_EXTENDED | 0x4f) +#define GRUB_TERM_KEY_DC (GRUB_TERM_EXTENDED | 0x53) +#define GRUB_TERM_KEY_PPAGE (GRUB_TERM_EXTENDED | 0x49) +#define GRUB_TERM_KEY_NPAGE (GRUB_TERM_EXTENDED | 0x51) +#define GRUB_TERM_KEY_F1 (GRUB_TERM_EXTENDED | 0x3b) +#define GRUB_TERM_KEY_F2 (GRUB_TERM_EXTENDED | 0x3c) +#define GRUB_TERM_KEY_F3 (GRUB_TERM_EXTENDED | 0x3d) +#define GRUB_TERM_KEY_F4 (GRUB_TERM_EXTENDED | 0x3e) +#define GRUB_TERM_KEY_F5 (GRUB_TERM_EXTENDED | 0x3f) +#define GRUB_TERM_KEY_F6 (GRUB_TERM_EXTENDED | 0x40) +#define GRUB_TERM_KEY_F7 (GRUB_TERM_EXTENDED | 0x41) +#define GRUB_TERM_KEY_F8 (GRUB_TERM_EXTENDED | 0x42) +#define GRUB_TERM_KEY_F9 (GRUB_TERM_EXTENDED | 0x43) +#define GRUB_TERM_KEY_F10 (GRUB_TERM_EXTENDED | 0x44) +#define GRUB_TERM_KEY_F11 (GRUB_TERM_EXTENDED | 0x57) +#define GRUB_TERM_KEY_F12 (GRUB_TERM_EXTENDED | 0x58) +#define GRUB_TERM_KEY_INSERT (GRUB_TERM_EXTENDED | 0x52) +#define GRUB_TERM_KEY_CENTER (GRUB_TERM_EXTENDED | 0x4c) + #define GRUB_TERM_ESC '\e' #define GRUB_TERM_TAB '\t' -#define GRUB_TERM_BACKSPACE 8 +#define GRUB_TERM_BACKSPACE '\b' #ifndef ASM_FILE @@ -86,9 +112,15 @@ grub_term_color_state; /* Bitmasks for modifier keys returned by grub_getkeystatus. */ -#define GRUB_TERM_STATUS_SHIFT (1 << 0) -#define GRUB_TERM_STATUS_CTRL (1 << 1) -#define GRUB_TERM_STATUS_ALT (1 << 2) +#define GRUB_TERM_STATUS_RSHIFT (1 << 0) +#define GRUB_TERM_STATUS_LSHIFT (1 << 1) +#define GRUB_TERM_STATUS_RCTRL (1 << 2) +#define GRUB_TERM_STATUS_RALT (1 << 3) +#define GRUB_TERM_STATUS_SCROLL (1 << 4) +#define GRUB_TERM_STATUS_NUM (1 << 5) +#define GRUB_TERM_STATUS_CAPS (1 << 6) +#define GRUB_TERM_STATUS_LCTRL (1 << 8) +#define GRUB_TERM_STATUS_LALT (1 << 9) /* Menu-related geometrical constants. */ @@ -128,10 +160,7 @@ struct grub_term_input /* Clean up the terminal. */ grub_err_t (*fini) (struct grub_term_input *term); - /* Check if any input character is available. */ - int (*checkkey) (struct grub_term_input *term); - - /* Get a character. */ + /* Get a character if any input character is available. Otherwise return -1 */ int (*getkey) (struct grub_term_input *term); /* Get keyboard modifier status. */ @@ -279,7 +308,6 @@ grub_term_unregister_output (grub_term_output_t term) void grub_putcode (grub_uint32_t code, struct grub_term_output *term); int EXPORT_FUNC(grub_getkey) (void); int EXPORT_FUNC(grub_checkkey) (void); -int EXPORT_FUNC(grub_getkeystatus) (void); void grub_cls (void); void EXPORT_FUNC(grub_refresh) (void); void grub_puts_terminal (const char *str, struct grub_term_output *term); @@ -461,8 +489,8 @@ grub_print_spaces (struct grub_term_output *term, int number_spaces) extern void (*EXPORT_VAR (grub_term_poll_usb)) (void); -/* For convenience. */ -#define GRUB_TERM_ASCII_CHAR(c) ((c) & 0xff) +#define GRUB_TERM_REPEAT_PRE_INTERVAL 400 +#define GRUB_TERM_REPEAT_INTERVAL 50 #endif /* ! ASM_FILE */ diff --git a/include/grub/terminfo.h b/include/grub/terminfo.h index 85ddb5779..1962c71b7 100644 --- a/include/grub/terminfo.h +++ b/include/grub/terminfo.h @@ -64,7 +64,6 @@ void EXPORT_FUNC (grub_terminfo_setcolorstate) (struct grub_term_output *term, const grub_term_color_state state); -int EXPORT_FUNC (grub_terminfo_checkkey) (struct grub_term_input *term); grub_err_t EXPORT_FUNC (grub_terminfo_input_init) (struct grub_term_input *term); int EXPORT_FUNC (grub_terminfo_getkey) (struct grub_term_input *term); void EXPORT_FUNC (grub_terminfo_putchar) (struct grub_term_output *term, diff --git a/include/grub/types.h b/include/grub/types.h index 4499e4538..766eddf07 100644 --- a/include/grub/types.h +++ b/include/grub/types.h @@ -69,10 +69,16 @@ typedef long long grub_int64_t; typedef unsigned char grub_uint8_t; typedef unsigned short grub_uint16_t; typedef unsigned grub_uint32_t; +# define PRIxGRUB_UINT32_T "x" +# define PRIuGRUB_UINT32_T "u" #if GRUB_CPU_SIZEOF_LONG == 8 typedef unsigned long grub_uint64_t; +# define PRIxGRUB_UINT64_T "lx" +# define PRIuGRUB_UINT64_T "lu" #else typedef unsigned long long grub_uint64_t; +# define PRIxGRUB_UINT64_T "llx" +# define PRIuGRUB_UINT64_T "llu" #endif /* Misc types. */ diff --git a/include/grub/usb.h b/include/grub/usb.h index bb3336580..6f838e4f9 100644 --- a/include/grub/usb.h +++ b/include/grub/usb.h @@ -30,6 +30,7 @@ typedef struct grub_usb_controller_dev *grub_usb_controller_dev_t; typedef enum { GRUB_USB_ERR_NONE, + GRUB_USB_ERR_WAIT, GRUB_USB_ERR_INTERNAL, GRUB_USB_ERR_STALL, GRUB_USB_ERR_DATA, @@ -48,14 +49,6 @@ typedef enum GRUB_USB_SPEED_HIGH } grub_usb_speed_t; -enum - { - GRUB_USB_REQTYPE_CLASS_INTERFACE_OUT = 0x21, - GRUB_USB_REQTYPE_VENDOR_OUT = 0x40, - GRUB_USB_REQTYPE_CLASS_INTERFACE_IN = 0xa1, - GRUB_USB_REQTYPE_VENDOR_IN = 0xc0 - }; - /* Call HOOK with each device, until HOOK returns non-zero. */ int grub_usb_iterate (int (*hook) (grub_usb_device_t dev)); @@ -97,6 +90,7 @@ grub_usb_err_t grub_usb_root_hub (grub_usb_controller_t controller); + /* XXX: All handled by libusb for now. */ struct grub_usb_controller_dev { @@ -105,9 +99,15 @@ struct grub_usb_controller_dev int (*iterate) (int (*hook) (grub_usb_controller_t dev)); - grub_usb_err_t (*transfer) (grub_usb_controller_t dev, - grub_usb_transfer_t transfer, - int timeout, grub_size_t *actual); + grub_usb_err_t (*setup_transfer) (grub_usb_controller_t dev, + grub_usb_transfer_t transfer); + + grub_usb_err_t (*check_transfer) (grub_usb_controller_t dev, + grub_usb_transfer_t transfer, + grub_size_t *actual); + + grub_usb_err_t (*cancel_transfer) (grub_usb_controller_t dev, + grub_usb_transfer_t transfer); int (*hubports) (grub_usb_controller_t dev); @@ -116,6 +116,9 @@ struct grub_usb_controller_dev grub_usb_speed_t (*detect_dev) (grub_usb_controller_t dev, int port, int *changed); + /* Per controller flag - port reset pending, don't do another reset */ + grub_uint64_t pending_reset; + /* The next host controller. */ struct grub_usb_controller_dev *next; }; @@ -181,11 +184,19 @@ struct grub_usb_device /* Used by libusb wrapper. Schedulded for removal. */ void *data; + /* Hub information. */ + /* Array of children for a hub. */ grub_usb_device_t *children; /* Number of hub ports. */ unsigned nports; + + grub_usb_transfer_t hub_transfer; + + grub_uint32_t statuschange; + + struct grub_usb_desc_endp *hub_endpoint; }; @@ -266,5 +277,12 @@ grub_usb_err_t grub_usb_bulk_read_extended (grub_usb_device_t dev, int endpoint, grub_size_t size, char *data, int timeout, grub_size_t *actual); +grub_usb_transfer_t +grub_usb_bulk_read_background (grub_usb_device_t dev, + int endpoint, grub_size_t size, void *data); +grub_usb_err_t +grub_usb_check_transfer (grub_usb_transfer_t trans, grub_size_t *actual); +void +grub_usb_cancel_transfer (grub_usb_transfer_t trans); #endif /* GRUB_USB_H */ diff --git a/include/grub/usbtrans.h b/include/grub/usbtrans.h index a5bb2e8b2..5ee276d26 100644 --- a/include/grub/usbtrans.h +++ b/include/grub/usbtrans.h @@ -56,51 +56,89 @@ struct grub_usb_transfer grub_transaction_type_t type; + grub_transfer_type_t dir; + struct grub_usb_device *dev; struct grub_usb_transaction *transactions; int last_trans; /* Index of last processed transaction in OHCI/UHCI driver. */ + + void *controller_data; + + /* Used when finishing transfer to copy data back. */ + struct grub_pci_dma_chunk *data_chunk; + void *data; }; typedef struct grub_usb_transfer *grub_usb_transfer_t; -#define GRUB_USB_REQTYPE_IN (1 << 7) -#define GRUB_USB_REQTYPE_OUT (0 << 7) -#define GRUB_USB_REQTYPE_STANDARD (0 << 5) -#define GRUB_USB_REQTYPE_CLASS (1 << 5) -#define GRUB_USB_REQTYPE_VENDOR (2 << 5) -#define GRUB_USB_REQTYPE_TARGET_DEV (0 << 0) -#define GRUB_USB_REQTYPE_TARGET_INTERF (1 << 0) -#define GRUB_USB_REQTYPE_TARGET_ENDP (2 << 0) -#define GRUB_USB_REQTYPE_TARGET_OTHER (3 << 0) -#define GRUB_USB_REQ_GET_STATUS 0x00 -#define GRUB_USB_REQ_CLEAR_FEATURE 0x01 -#define GRUB_USB_REQ_SET_FEATURE 0x03 -#define GRUB_USB_REQ_SET_ADDRESS 0x05 -#define GRUB_USB_REQ_GET_DESCRIPTOR 0x06 -#define GRUB_USB_REQ_SET_DESCRIPTOR 0x07 -#define GRUB_USB_REQ_GET_CONFIGURATION 0x08 -#define GRUB_USB_REQ_SET_CONFIGURATION 0x09 -#define GRUB_USB_REQ_GET_INTERFACE 0x0A -#define GRUB_USB_REQ_SET_INTERFACE 0x0B -#define GRUB_USB_REQ_SYNC_FRAME 0x0C +enum + { + GRUB_USB_REQTYPE_TARGET_DEV = (0 << 0), + GRUB_USB_REQTYPE_TARGET_INTERF = (1 << 0), + GRUB_USB_REQTYPE_TARGET_ENDP = (2 << 0), + GRUB_USB_REQTYPE_TARGET_OTHER = (3 << 0), + GRUB_USB_REQTYPE_STANDARD = (0 << 5), + GRUB_USB_REQTYPE_CLASS = (1 << 5), + GRUB_USB_REQTYPE_VENDOR = (2 << 5), + GRUB_USB_REQTYPE_OUT = (0 << 7), + GRUB_USB_REQTYPE_IN = (1 << 7), + GRUB_USB_REQTYPE_CLASS_INTERFACE_OUT = GRUB_USB_REQTYPE_TARGET_INTERF + | GRUB_USB_REQTYPE_CLASS | GRUB_USB_REQTYPE_OUT, + GRUB_USB_REQTYPE_VENDOR_OUT = GRUB_USB_REQTYPE_VENDOR | GRUB_USB_REQTYPE_OUT, + GRUB_USB_REQTYPE_CLASS_INTERFACE_IN = GRUB_USB_REQTYPE_TARGET_INTERF + | GRUB_USB_REQTYPE_CLASS | GRUB_USB_REQTYPE_IN, + GRUB_USB_REQTYPE_VENDOR_IN = GRUB_USB_REQTYPE_VENDOR | GRUB_USB_REQTYPE_IN + }; + +enum + { + GRUB_USB_REQ_GET_STATUS = 0x00, + GRUB_USB_REQ_CLEAR_FEATURE = 0x01, + GRUB_USB_REQ_SET_FEATURE = 0x03, + GRUB_USB_REQ_SET_ADDRESS = 0x05, + GRUB_USB_REQ_GET_DESCRIPTOR = 0x06, + GRUB_USB_REQ_SET_DESCRIPTOR = 0x07, + GRUB_USB_REQ_GET_CONFIGURATION = 0x08, + GRUB_USB_REQ_SET_CONFIGURATION = 0x09, + GRUB_USB_REQ_GET_INTERFACE = 0x0A, + GRUB_USB_REQ_SET_INTERFACE = 0x0B, + GRUB_USB_REQ_SYNC_FRAME = 0x0C + }; #define GRUB_USB_FEATURE_ENDP_HALT 0x00 #define GRUB_USB_FEATURE_DEV_REMOTE_WU 0x01 #define GRUB_USB_FEATURE_TEST_MODE 0x02 -#define GRUB_USB_HUB_FEATURE_PORT_RESET 0x04 -#define GRUB_USB_HUB_FEATURE_PORT_POWER 0x08 -#define GRUB_USB_HUB_FEATURE_C_CONNECTED 0x10 +enum + { + GRUB_USB_HUB_FEATURE_PORT_RESET = 0x04, + GRUB_USB_HUB_FEATURE_PORT_POWER = 0x08, + GRUB_USB_HUB_FEATURE_C_PORT_CONNECTED = 0x10, + GRUB_USB_HUB_FEATURE_C_PORT_ENABLED = 0x11, + GRUB_USB_HUB_FEATURE_C_PORT_SUSPEND = 0x12, + GRUB_USB_HUB_FEATURE_C_PORT_OVERCURRENT = 0x13, + GRUB_USB_HUB_FEATURE_C_PORT_RESET = 0x14 + }; -#define GRUB_USB_HUB_STATUS_CONNECTED (1 << 0) -#define GRUB_USB_HUB_STATUS_LOWSPEED (1 << 9) -#define GRUB_USB_HUB_STATUS_HIGHSPEED (1 << 10) -#define GRUB_USB_HUB_STATUS_C_CONNECTED (1 << 16) -#define GRUB_USB_HUB_STATUS_C_PORT_RESET (1 << 20) +enum + { + GRUB_USB_HUB_STATUS_PORT_CONNECTED = (1 << 0), + GRUB_USB_HUB_STATUS_PORT_ENABLED = (1 << 1), + GRUB_USB_HUB_STATUS_PORT_SUSPEND = (1 << 2), + GRUB_USB_HUB_STATUS_PORT_OVERCURRENT = (1 << 3), + GRUB_USB_HUB_STATUS_PORT_POWERED = (1 << 8), + GRUB_USB_HUB_STATUS_PORT_LOWSPEED = (1 << 9), + GRUB_USB_HUB_STATUS_PORT_HIGHSPEED = (1 << 10), + GRUB_USB_HUB_STATUS_C_PORT_CONNECTED = (1 << 16), + GRUB_USB_HUB_STATUS_C_PORT_ENABLED = (1 << 17), + GRUB_USB_HUB_STATUS_C_PORT_SUSPEND = (1 << 18), + GRUB_USB_HUB_STATUS_C_PORT_OVERCURRENT = (1 << 19), + GRUB_USB_HUB_STATUS_C_PORT_RESET = (1 << 20) + }; struct grub_usb_packet_setup { diff --git a/include/grub/video.h b/include/grub/video.h index 24167281f..5350d87eb 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -38,20 +38,33 @@ struct grub_video_bitmap; /* If following is set render target contains currenly displayed image after swapping buffers (otherwise it contains previously displayed image). */ -#define GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP 0x00000080 -#define GRUB_VIDEO_MODE_TYPE_PURE_TEXT 0x00000040 -#define GRUB_VIDEO_MODE_TYPE_ALPHA 0x00000020 -#define GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED 0x00000010 -#define GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP 0x00000004 -#define GRUB_VIDEO_MODE_TYPE_INDEX_COLOR 0x00000002 -#define GRUB_VIDEO_MODE_TYPE_RGB 0x00000001 +typedef enum grub_video_mode_type + { + GRUB_VIDEO_MODE_TYPE_RGB = 0x00000001, + GRUB_VIDEO_MODE_TYPE_INDEX_COLOR = 0x00000002, + GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP = 0x00000004, + GRUB_VIDEO_MODE_TYPE_YUV = 0x00000008, -/* Defines used to mask flags. */ -#define GRUB_VIDEO_MODE_TYPE_COLOR_MASK 0x0000000F + /* Defines used to mask flags. */ + GRUB_VIDEO_MODE_TYPE_COLOR_MASK = 0x0000000F, -/* Defines used to specify requested bit depth. */ -#define GRUB_VIDEO_MODE_TYPE_DEPTH_MASK 0x0000ff00 -#define GRUB_VIDEO_MODE_TYPE_DEPTH_POS 8 + GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED = 0x00000010, + GRUB_VIDEO_MODE_TYPE_ALPHA = 0x00000020, + GRUB_VIDEO_MODE_TYPE_PURE_TEXT = 0x00000040, + GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP = 0x00000080, + GRUB_VIDEO_MODE_TYPE_OPERATIONAL_MASK = 0x000000F0, + + /* Defines used to specify requested bit depth. */ + GRUB_VIDEO_MODE_TYPE_DEPTH_MASK = 0x0000FF00, +#define GRUB_VIDEO_MODE_TYPE_DEPTH_POS 8 + + GRUB_VIDEO_MODE_TYPE_UNKNOWN = 0x00010000, + GRUB_VIDEO_MODE_TYPE_HERCULES = 0x00020000, + GRUB_VIDEO_MODE_TYPE_PLANAR = 0x00040000, + GRUB_VIDEO_MODE_TYPE_NONCHAIN4 = 0x00080000, + GRUB_VIDEO_MODE_TYPE_CGA = 0x00100000, + GRUB_VIDEO_MODE_TYPE_INFO_MASK = 0x00FF0000, + } grub_video_mode_type_t; /* The basic render target representing the whole display. This always renders to the back buffer when double-buffering is in use. */ @@ -103,7 +116,7 @@ struct grub_video_mode_info /* Mode type bitmask. Contains information like is it Index color or RGB mode. */ - unsigned int mode_type; + grub_video_mode_type_t mode_type; /* Bits per pixel. */ unsigned int bpp; @@ -117,6 +130,9 @@ struct grub_video_mode_info /* In index color mode, number of colors. In RGB mode this is 256. */ unsigned int number_of_colors; + unsigned int mode_number; +#define GRUB_VIDEO_MODE_NUMBER_INVALID 0xffffffff + /* Optimization hint how binary data is coded. */ enum grub_video_blit_format blit_format; @@ -225,7 +241,8 @@ struct grub_video_adapter grub_err_t (*fini) (void); grub_err_t (*setup) (unsigned int width, unsigned int height, - unsigned int mode_type, unsigned int mode_mask); + grub_video_mode_type_t mode_type, + grub_video_mode_type_t mode_mask); grub_err_t (*get_info) (struct grub_video_mode_info *mode_info); @@ -282,6 +299,10 @@ struct grub_video_adapter grub_err_t (*set_active_render_target) (struct grub_video_render_target *target); grub_err_t (*get_active_render_target) (struct grub_video_render_target **target); + + int (*iterate) (int (*hook) (const struct grub_video_mode_info *info)); + + void (*print_adapter_specific_info) (void); }; typedef struct grub_video_adapter *grub_video_adapter_t; @@ -398,8 +419,9 @@ grub_err_t EXPORT_FUNC (grub_video_set_mode) (const char *modestring, unsigned int modevalue); static inline int -grub_video_check_mode_flag (unsigned int flags, unsigned int mask, - unsigned int flag, int def) +grub_video_check_mode_flag (grub_video_mode_type_t flags, + grub_video_mode_type_t mask, + grub_video_mode_type_t flag, int def) { return (flag & mask) ? !! (flags & flag) : def; } diff --git a/include/multiboot.h b/include/multiboot.h index fda863e85..ed71e6b96 100644 --- a/include/multiboot.h +++ b/include/multiboot.h @@ -254,6 +254,20 @@ struct multiboot_mod_list }; typedef struct multiboot_mod_list multiboot_module_t; +/* APM BIOS info. */ +struct multiboot_apm_info +{ + grub_uint16_t version; + grub_uint16_t cseg; + grub_uint32_t offset; + grub_uint16_t cseg_16; + grub_uint16_t dseg; + grub_uint16_t flags; + grub_uint16_t cseg_len; + grub_uint16_t cseg_16_len; + grub_uint16_t dseg_len; +}; + #endif /* ! ASM_FILE */ #endif /* ! MULTIBOOT_HEADER */ diff --git a/tests/grub_script_not.in b/tests/grub_script_not.in new file mode 100644 index 000000000..ff71039a6 --- /dev/null +++ b/tests/grub_script_not.in @@ -0,0 +1,62 @@ +#! @builddir@/grub-shell-tester +# +# Copyright (C) 2010 Free Software Foundation, Inc. +# +# GRUB is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# GRUB is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GRUB. If not, see . + +true +echo $? + +! true +echo $? + +false +echo $? + +! false +echo $? + +# +# Negated forms (copied from grub_script_if.in) +# + +#basic if, execute +if ! true; then echo yes; fi + +#basic if, no execution +if ! false; then echo no; fi + +#if else, execute if path +if ! true; then echo yes; else echo no; fi + +#if else, execute else path +if ! false; then echo no; else echo yes; fi + +#if elif, execute elif +if ! false; then echo no; elif ! true; then echo yes; fi + +#if elif else, execute else +if ! false; then echo no; elif ! false; then echo no; else echo yes; fi + +#if elif(1) elif(2), execute elif(2) +if false; then echo no; elif ! false; then echo no; elif ! true; then echo yes; fi + +#if elif(1) elif(2) else, execute else +if false; then echo no; elif false; then echo no; elif ! false; then echo no; else echo yes; fi + +#if {if elif else}, execute elif +if true; then if false; then echo no; elif ! true; then echo yes; else echo no; fi; fi + +#if {if elif} else, execute elif. ofcourse no dangling-else problem due to "fi" +if true; then if ! false; then echo no; elif true; then echo yes; fi; else echo no; fi diff --git a/tests/partmap_test.in b/tests/partmap_test.in new file mode 100644 index 000000000..14897e9da --- /dev/null +++ b/tests/partmap_test.in @@ -0,0 +1,274 @@ +#! /bin/sh -e +# +# Copyright (C) 2010 Free Software Foundation, Inc. +# +# GRUB is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# GRUB is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GRUB. If not, see . + +parted=/sbin/parted +grubshell=@builddir@/grub-shell + +create_disk_image () { + name=$1 + size=$2 + qemu-img create ${name} ${size} >/dev/null +} + +check_output () { + outfile=$1 + shift + + for disk in $@; do + if ! grep "($disk)" ${outfile} >/dev/null + then + echo "($disk): disk/partiton not found" + exit 1 + fi + done +} + +list_parts () { + mod=$1; + shift; + imgfile=$1 + shift + outfile=$1 + shift + + echo ls | ${grubshell} --boot=cd --qemu-opts="-hda ${imgfile}" \ + --modules=$mod | tr -d "\n\r" > ${outfile} + cat ${outfile} + echo +} + +imgfile=`mktemp` +outfile=`mktemp` + +# +# MSDOS partition types +# + +echo "Checking MSDOS partition types..." + +# 0 primary +create_disk_image ${imgfile} 64M +${parted} -a none -s ${imgfile} mklabel msdos +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 + +# 1 primary +create_disk_image ${imgfile} 64M +${parted} -a none -s ${imgfile} mklabel msdos mkpart primary 0 10M +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,msdos1 + +# 2 primary +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel msdos mkpart primary 0 10M mkpart primary 10M 20M +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,msdos1 hd0,msdos2 + +# 3 primary +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel msdos mkpart primary 0 10M mkpart primary 10M 20M mkpart primary 20M 30M +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,msdos1 hd0,msdos2 hd0,msdos3 + +# 4 primary +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel msdos mkpart primary 0 10M mkpart primary 10M 20M mkpart primary 20M 30M mkpart primary 30M 40M +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,msdos1 hd0,msdos2 hd0,msdos3 hd0,msdos4 + +# 1 primary, 1 extended +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel msdos mkpart primary 0 10M mkpart primary 10M 20M mkpart extended 20M 100% +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,msdos1 + +# 1 primary, 1 extended, 1 logical +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel msdos mkpart primary 0 10M mkpart primary 10M 20M mkpart extended 20M 100% mkpart logical 20M 30M +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,msdos1 hd0,msdos5 + +# 1 primary, 1 extended, 2 logical +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel msdos mkpart primary 0 10M mkpart primary 10M 20M mkpart extended 20M 100% mkpart logical 20M 30M mkpart logical 30M 40M +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,msdos1 hd0,msdos5 hd0,msdos6 + +# 1 primary, 1 extended, 3 logical +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel msdos mkpart primary 0 10M mkpart primary 10M 20M mkpart extended 20M 100% mkpart logical 20M 30M mkpart logical 30M 40M mkpart logical 40M 50M +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,msdos1 hd0,msdos5 hd0,msdos6 hd0,msdos7 + +# 1 primary, 1 extended, 4 logical +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel msdos mkpart primary 0 10M mkpart primary 10M 20M mkpart extended 20M 100% mkpart logical 20M 30M mkpart logical 30M 40M mkpart logical 40M 50M mkpart logical 50M 60M +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,msdos1 hd0,msdos5 hd0,msdos6 hd0,msdos7 hd0,msdos8 + + +# +# GPT partition types +# + +echo "Checking GPT partition types..." + +# 0 parts +create_disk_image ${imgfile} 64M +${parted} -a none -s ${imgfile} mklabel gpt +list_parts part_gpt ${imgfile} ${outfile} +check_output ${outfile} hd0 + +# 1 parts +create_disk_image ${imgfile} 64M +${parted} -a none -s ${imgfile} mklabel gpt mkpart 1 0 10M +list_parts part_gpt ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,gpt1 + +# 2 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel gpt mkpart 1 0 10M mkpart 2 10M 20M +list_parts part_gpt ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,gpt1 hd0,gpt2 + +# 3 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel gpt mkpart 1 0 10M mkpart 2 10M 20M mkpart 3 20M 30M +list_parts part_gpt ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,gpt1 hd0,gpt2 hd0,gpt3 + +# 4 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel gpt mkpart 1 0 10M mkpart 2 10M 20M mkpart 4 20M 30M mkpart 5 30M 40M +list_parts part_gpt ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,gpt1 hd0,gpt2 hd0,gpt3 hd0,gpt4 + +# 5 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel gpt mkpart 1 0 10M mkpart 2 10M 20M mkpart 3 20M 30M mkpart 4 30M 40M mkpart 5 40M 50M +list_parts part_gpt ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,gpt1 hd0,gpt2 hd0,gpt3 hd0,gpt4 hd0,gpt5 + +# 6 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel gpt mkpart 1 0 10M mkpart 2 10M 20M mkpart 3 20M 30M mkpart 4 30M 40M mkpart 5 40M 50M mkpart 6 50M 60M +list_parts part_gpt ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,gpt1 hd0,gpt2 hd0,gpt3 hd0,gpt4 hd0,gpt5 hd0,gpt6 + + +# +# SUN partition types +# +# It seems partition #3 is reserved for whole disk by parted. +# + +echo "Checking SUN partition types..." + +# 0 parts +create_disk_image ${imgfile} 64M +${parted} -a none -s ${imgfile} mklabel sun +list_parts part_sun ${imgfile} ${outfile} +check_output ${outfile} hd0 + +# 1 parts +create_disk_image ${imgfile} 64M +${parted} -a none -s ${imgfile} mklabel sun mkpart 0 10M +list_parts part_sun ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,sun1 + +# 2 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel sun mkpart 0 10M mkpart 10M 20M +list_parts part_sun ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,sun1 hd0,sun2 + +# 3 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel sun mkpart 0 10M mkpart 10M 20M mkpart 20M 30M +list_parts part_sun ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,sun1 hd0,sun2 hd0,sun4 + +# 4 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel sun mkpart 0 10M mkpart 10M 20M mkpart 20M 30M mkpart 30M 40M +list_parts part_sun ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,sun1 hd0,sun2 hd0,sun4 hd0,sun5 + +# 5 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel sun mkpart 0 10M mkpart 10M 20M mkpart 20M 30M mkpart 30M 40M mkpart 40M 50M +list_parts part_sun ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,sun1 hd0,sun2 hd0,sun4 hd0,sun5 hd0,sun6 + +# 6 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel sun mkpart 0 10M mkpart 10M 20M mkpart 20M 30M mkpart 30M 40M mkpart 40M 50M mkpart 50M 60M +list_parts part_sun ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,sun1 hd0,sun2 hd0,sun4 hd0,sun5 hd0,sun6 hd0,sun7 + + +# +# Apple partition types +# +# Partition table itself is part of some partition, so there is always +# a partition by default. But I don't understand why GRUB displays +# two partitions by default :-( +# + +echo "Checking APPLE partition types..." + +# 0 parts +create_disk_image ${imgfile} 64M +${parted} -a none -s ${imgfile} mklabel mac +list_parts part_apple ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,apple1 hd0,apple2 + +# 1 parts +create_disk_image ${imgfile} 64M +${parted} -a none -s ${imgfile} mklabel mac mkpart a 1M 10M +list_parts part_apple ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,apple1 hd0,apple2 hd0,apple3 + +# 2 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel mac mkpart a 1M 10M mkpart b 10M 20M +list_parts part_apple ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,apple1 hd0,apple2 hd0,apple3 hd0,apple4 + +# 3 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel mac mkpart a 1M 10M mkpart b 10M 20M mkpart c 20M 30M +list_parts part_apple ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,apple1 hd0,apple2 hd0,apple4 hd0,apple5 + +# 4 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel mac mkpart a 1M 10M mkpart b 10M 20M mkpart c 20M 30M mkpart d 30M 40M +list_parts part_apple ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,apple1 hd0,apple2 hd0,apple4 hd0,apple5 hd0,apple6 + +# 5 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel mac mkpart a 1M 10M mkpart b 10M 20M mkpart c 20M 30M mkpart d 30M 40M mkpart e 40M 50M +list_parts part_apple ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,apple1 hd0,apple2 hd0,apple4 hd0,apple5 hd0,apple6 hd0,apple7 + +# 6 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel mac mkpart a 1M 10M mkpart b 10M 20M mkpart c 20M 30M mkpart d 30M 40M mkpart e 40M 50M mkpart f 50M 60M +list_parts part_apple ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,apple1 hd0,apple2 hd0,apple4 hd0,apple5 hd0,apple6 hd0,apple7 hd0,apple8 diff --git a/tests/util/grub-shell.in b/tests/util/grub-shell.in index 427b1ce9f..c8247d29d 100644 --- a/tests/util/grub-shell.in +++ b/tests/util/grub-shell.in @@ -28,6 +28,7 @@ PACKAGE_NAME=@PACKAGE_NAME@ PACKAGE_TARNAME=@PACKAGE_TARNAME@ PACKAGE_VERSION=@PACKAGE_VERSION@ target_cpu=@target_cpu@ +platform=@platform@ # Force build directory components PATH=${builddir}:$PATH @@ -42,7 +43,7 @@ Run GRUB script in a Qemu instance. -h, --help print this message and exit -v, --version print the version information and exit - --boot=[fd|hd|cd] boot method for Qemu instance + --boot=[fd|hd|cd|net] boot method for Qemu instance --modules=MODULES pre-load specified modules MODULES --qemu=FILE Name of qemu binary --qemu-opts=OPTIONS extra options to pass to Qemu instance @@ -83,6 +84,7 @@ for option in "$@"; do if [ "$dev" = "fd" ] ; then boot=fd; elif [ "$dev" = "hd" ] ; then boot=hd; elif [ "$dev" = "cd" ] ; then boot=cd; + elif [ "$dev" = "net" ] ; then boot=net; elif [ "$dev" = "qemu" ] ; then boot=qemu; elif [ "$dev" = "coreboot" ] ; then boot=coreboot; else @@ -134,10 +136,12 @@ halt EOF isofile=`mktemp` -sh @builddir@/grub-mkrescue --grub-mkimage=${builddir}/grub-mkimage --output=${isofile} --override-directory=${builddir}/grub-core \ - --rom-directory="${rom_directory}" \ - /boot/grub/grub.cfg=${cfgfile} /boot/grub/testcase.cfg=${source} \ - ${files} >/dev/null 2>&1 +if [ x$boot != xnet ]; then + sh @builddir@/grub-mkrescue --grub-mkimage=${builddir}/grub-mkimage --output=${isofile} --override-directory=${builddir}/grub-core \ + --rom-directory="${rom_directory}" \ + /boot/grub/grub.cfg=${cfgfile} /boot/grub/testcase.cfg=${source} \ + ${files} >/dev/null 2>&1 +fi if [ x$boot = xhd ]; then device=hda bootdev="-boot c" @@ -164,7 +168,15 @@ if [ x$boot = xcoreboot ]; then device=cdrom fi -${qemu} ${qemuopts} -nographic -serial file:/dev/stdout -monitor file:/dev/null -${device} ${isofile} ${bootdev} | cat | tr -d "\r" +if [ x$boot = xnet ]; then + netdir=`mktemp -d` + sh @builddir@/grub-mknetdir --grub-mkimage=${builddir}/grub-mkimage --override-directory=${builddir}/grub-core --net-directory=$netdir + cp ${cfgfile} $netdir/boot/grub/grub.cfg + cp ${source} $netdir/boot/grub/testcase.cfg + ${qemu} ${qemuopts} -nographic -serial file:/dev/stdout -monitor file:/dev/null -boot n -net user,tftp=$netdir,bootfile=/boot/grub/$target_cpu-$platform/core.0 -net nic | cat | tr -d "\r" +else + ${qemu} ${qemuopts} -nographic -serial file:/dev/stdout -monitor file:/dev/null -${device} ${isofile} ${bootdev} | cat | tr -d "\r" +fi rm -f "${isofile}" "${imgfile}" rm -rf "${rom_directory}" if [ x$boot = xcoreboot ]; then diff --git a/util/bash-completion.d/Makefile.am b/util/bash-completion.d/Makefile.am new file mode 100644 index 000000000..58171988d --- /dev/null +++ b/util/bash-completion.d/Makefile.am @@ -0,0 +1,13 @@ + +bash_completion_source = grub-completion.bash.in +bash_completion_script = grub + +EXTRA_DIST = $(bash_completion_source) + +CLEANFILES = $(bash_completion_script) + +bashcompletiondir = $(sysconfdir)/bash_completion.d +bashcompletion_DATA = $(bash_completion_script) + +$(bash_completion_script): $(bash_completion_source) $(top_builddir)/config.status + $(top_builddir)/config.status --file=$@:$< diff --git a/util/bash-completion.d/grub-completion.bash.in b/util/bash-completion.d/grub-completion.bash.in new file mode 100644 index 000000000..65cbb80ee --- /dev/null +++ b/util/bash-completion.d/grub-completion.bash.in @@ -0,0 +1,489 @@ +# +# Bash completion for grub +# +# Copyright (C) 2010 Free Software Foundation, Inc. +# +# GRUB is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# GRUB is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GRUB. If not, see . +# bash completion for grub + +__grub_dir() { + local i c=1 boot_dir + + for (( c=1; c <= ${#COMP_WORDS[@]}; c++ )); do + i="${COMP_WORDS[c]}" + case "$i" in + --boot-directory) + c=$((++c)) + i="${COMP_WORDS[c]}" + boot_dir="${i##*=}"; + break + ;; + esac + done + boot_dir=${boot_dir-/@bootdirname@} + echo "${boot_dir%/}/@grubdirname@" +} + + +# This function generates completion reply with compgen +# - arg: accepts 1, 2, 3, or 4 arguments +# $1 wordlist separate by space, tab or newline +# $2 (optional) prefix to add +# $3 (optional) current word to complete +# $4 (optional) suffix to add +__grubcomp () { + local cur="${COMP_WORDS[COMP_CWORD]}" + if [ $# -gt 2 ]; then + cur="$3" + fi + case "$cur" in + --*=) + COMPREPLY=() + ;; + *) + local IFS=' '$'\t'$'\n' + COMPREPLY=($(compgen -P "${2-}" -W "${1-}" -S "${4-}" -- "$cur")) + ;; + esac +} + +# Function that return long options from the help of the command +# - arg: $1 (optional) command to get the long options from +__grub_get_options_from_help () { + local prog + + if [ $# -ge 1 ]; then + prog="$1" + else + prog="${COMP_WORDS[0]}" + fi + + local i IFS=" "$'\t'$'\n' + for i in $(LC_ALL=C $prog --help) + do + case $i in + --*) echo "${i%=*}";; + esac + done +} + +# Function that return long options from the usage of the command +# - arg: $1 (optional) command to get the long options from +__grub_get_options_from_usage () { + local prog + + if [ $# -ge 1 ]; then + prog="$1" + else + prog="${COMP_WORDS[0]}" + fi + + local i IFS=" "$'\t'$'\n' + for i in $(LC_ALL=C $prog --usage) + do + case $i in + \[--*\]) i=${i#[} # Remove leading [ + echo ${i%%?(=*)]} # Remove optional value and trailing ] + ;; + esac + done +} + +__grub_get_last_option () { + local i + for (( i=$COMP_CWORD-1; i > 0; i-- )); do + if [[ "${COMP_WORDS[i]}" == -* ]]; then + echo "${COMP_WORDS[i]}" + break; + fi + done +} + +__grub_list_menuentries () { + local cur="${COMP_WORDS[COMP_CWORD]}" + local config_file=$(__grub_dir)/grub.cfg + + if [ -f "$config_file" ];then + local IFS=$'\n' + COMPREPLY=( $(compgen \ + -W "$( awk -F "[\"']" '/menuentry/ { print $2 }' $config_file )" \ + -- "$cur" )) #'# Help emacs syntax highlighting + fi +} + +__grub_list_modules () { + local grub_dir=$(__grub_dir) + local IFS=$'\n' + COMPREPLY=( $( compgen -f -X '!*/*.mod' -- "${grub_dir}/$cur" | { + while read -r tmp; do + [ -n $tmp ] && { + tmp=${tmp##*/} + printf '%s\n' ${tmp%.mod} + } + done + } + )) +} + +# +# grub-set-default & grub-reboot +# +_grub_set_entry () { + local cur prev split=false + + COMPREPLY=() + cur=`_get_cword` + prev=${COMP_WORDS[COMP_CWORD-1]} + + _split_longopt && split=true + + case "$prev" in + --boot-directory) + _filedir -d + return + ;; + esac + + $split && return 0 + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + # Default complete with a menuentry + __grub_list_menuentries + fi +} + +__grub_set_default_program=$( echo grub-set-default | sed "@program_transform_name@" ) +have ${__grub_set_default_program} && \ + complete -F _grub_set_entry -o filenames ${__grub_set_default_program} +unset __grub_set_default_program + +__grub_reboot_program=$( echo grub-reboot | sed "@program_transform_name@" ) +have ${__grub_reboot_program} && \ + complete -F _grub_set_entry -o filenames ${__grub_reboot_program} +unset __grub_reboot_program + + +# +# grub-editenv +# +_grub_editenv () { + local cur prev + + COMPREPLY=() + cur=`_get_cword` + prev=${COMP_WORDS[COMP_CWORD-1]} + + case "$prev" in + create|list|set|unset) + COMPREPLY=( "" ) + return + ;; + esac + + __grubcomp "$(__grub_get_options_from_help) + create list set unset" +} + +__grub_editenv_program=$( echo grub-editenv | sed "@program_transform_name@" ) +have ${__grub_editenv_program} && \ + complete -F _grub_editenv -o filenames ${__grub_editenv_program} +unset __grub_editenv_program + + +# +# grub-mkconfig +# +_grub_mkconfig () { + local cur prev + + COMPREPLY=() + cur=`_get_cword` + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + _filedir + fi +} +__grub_mkconfig_program=$( echo grub-mkconfig | sed "@program_transform_name@" ) +have ${__grub_mkconfig_program} && \ + complete -F _grub_mkconfig -o filenames ${__grub_mkconfig_program} +unset __grub_mkconfig_program + + +# +# grub-setup +# +_grub_setup () { + local cur prev split=false + + COMPREPLY=() + cur=`_get_cword` + prev=${COMP_WORDS[COMP_CWORD-1]} + + _split_longopt && split=true + + case "$prev" in + -d|--directory) + _filedir -d + return + ;; + esac + + $split && return 0 + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + # Default complete with a filename + _filedir + fi +} +__grub_setup_program=$( echo grub-setup | sed "@program_transform_name@" ) +have ${__grub_setup_program} && \ + complete -F _grub_setup -o filenames ${__grub_setup_program} +unset __grub_setup_program + + +# +# grub-install +# +_grub_install () { + local cur prev last split=false + + COMPREPLY=() + cur=`_get_cword` + prev=${COMP_WORDS[COMP_CWORD-1]} + last=$(__grub_get_last_option) + + _split_longopt && split=true + + case "$prev" in + --boot-directory) + _filedir -d + return + ;; + --disk-module) + __grubcomp "biosdisk ata" + return + ;; + esac + + $split && return 0 + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + case "$last" in + --modules) + __grub_list_modules + return + ;; + esac + + # Default complete with a filename + _filedir + fi +} +__grub_install_program=$( echo grub-install | sed "@program_transform_name@" ) +have ${__grub_install_program} && \ + complete -F _grub_install -o filenames ${__grub_install_program} +unset __grub_install_program + + +# +# grub-mkfont +# +_grub_mkfont () { + local cur + + COMPREPLY=() + cur=`_get_cword` + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + # Default complete with a filename + _filedir + fi +} +__grub_mkfont_program=$( echo grub-mkfont | sed "@program_transform_name@" ) +have ${__grub_mkfont_program} && \ + complete -F _grub_mkfont -o filenames ${__grub_mkfont_program} +unset __grub_mkfont_program + + +# +# grub-mkrescue +# +_grub_mkrescue () { + local cur prev last + + COMPREPLY=() + cur=`_get_cword` + prev=${COMP_WORDS[COMP_CWORD-1]} + last=$(__grub_get_last_option) + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + case "$last" in + --modules) + __grub_list_modules + return + ;; + esac + + # Default complete with a filename + _filedir + fi +} +__grub_mkrescue_program=$( echo grub-mkrescue | sed "@program_transform_name@" ) +have ${__grub_mkrescue_program} && \ + complete -F _grub_mkrescue -o filenames ${__grub_mkrescue_program} +unset __grub_mkrescue_program + + +# +# grub-mkimage +# +_grub_mkimage () { + local cur prev split=false + + COMPREPLY=() + cur=`_get_cword` + prev=${COMP_WORDS[COMP_CWORD-1]} + + _split_longopt && split=true + + case "$prev" in + -d|--directory|-p|--prefix) + _filedir -d + return + ;; + -O|--format) + # Get available format from help + local prog=${COMP_WORDS[0]} + __grubcomp "$(LC_ALL=C $prog --help | \ + awk -F ":" '/available formats/ { print $2 }' | \ + sed 's/, / /g')" + return + ;; + esac + + $split && return 0 + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + # Default complete with a filename + _filedir + fi +} +__grub_mkimage_program=$( echo grub-mkimage | sed "@program_transform_name@" ) +have ${__grub_mkimage_program} && \ + complete -F _grub_mkimage -o filenames ${__grub_mkimage_program} +unset __grub_mkimage_program + + +# +# grub-mkpasswd-pbkdf2 +# +_grub_mkpasswd-pbkdf2 () { + local cur + + COMPREPLY=() + cur=`_get_cword` + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + # Default complete with a filename + _filedir + fi +} +__grub_mkpasswd_pbkdf2_program=$( echo grub-mkpasswd-pbkdf2 | sed "@program_transform_name@" ) +have ${__grub_mkpasswd_pbkdf2_program} && \ + complete -F _grub_mkpasswd-pbkdf2 -o filenames ${__grub_mkpasswd_pbkdf2_program} +unset __grub_mkpasswd_pbkdf2_program + + +# +# grub-probe +# +_grub_probe () { + local cur prev split=false + + COMPREPLY=() + cur=`_get_cword` + prev=${COMP_WORDS[COMP_CWORD-1]} + + _split_longopt && split=true + + case "$prev" in + -t|--target) + # Get target type from help + local prog=${COMP_WORDS[0]} + __grubcomp "$(LC_ALL=C $prog --help | \ + awk -F "[()]" '/--target=/ { print $2 }' | \ + sed 's/|/ /g')" + return + ;; + esac + + $split && return 0 + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + # Default complete with a filename + _filedir + fi +} +__grub_probe_program=$( echo grub-probe | sed "@program_transform_name@" ) +have ${__grub_probe_program} && \ + complete -F _grub_probe -o filenames ${__grub_probe_program} +unset __grub_probe_program + + +# +# grub-script-check +# +_grub_script-check () { + local cur + + COMPREPLY=() + cur=`_get_cword` + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + # Default complete with a filename + _filedir + fi +} +__grub_script_check_program=$( echo grub-script-check | sed "@program_transform_name@" ) +have ${__grub_script_check_program} && \ + complete -F _grub_script-check -o filenames ${__grub_script_check_program} + + +# Local variables: +# mode: shell-script +# sh-basic-offset: 4 +# sh-indent-comment: t +# indent-tabs-mode: nil +# End: +# ex: ts=4 sw=4 et filetype=sh diff --git a/util/grub-fstest.c b/util/grub-fstest.c index 3935ce08b..eb7981d3a 100644 --- a/util/grub-fstest.c +++ b/util/grub-fstest.c @@ -259,13 +259,11 @@ fstest (char **images, int num_disks, int cmd, int n, char **args) { char *host_file; char *loop_name; - char *argv[3]; int i; - argv[0] = "-p"; - for (i = 0; i < num_disks; i++) { + char *argv[2]; loop_name = grub_xasprintf ("loop%d", i); if (!loop_name) grub_util_error (grub_errmsg); @@ -274,10 +272,10 @@ fstest (char **images, int num_disks, int cmd, int n, char **args) if (!host_file) grub_util_error (grub_errmsg); - argv[1] = loop_name; - argv[2] = host_file; + argv[0] = loop_name; + argv[1] = host_file; - if (execute_command ("loopback", 3, argv)) + if (execute_command ("loopback", 2, argv)) grub_util_error ("loopback command fails"); grub_free (loop_name); @@ -312,15 +310,16 @@ fstest (char **images, int num_disks, int cmd, int n, char **args) execute_command ("blocklist", n, args); grub_printf ("\n"); } - - argv[0] = "-d"; - + for (i = 0; i < num_disks; i++) { + char *argv[2]; + loop_name = grub_xasprintf ("loop%d", i); if (!loop_name) grub_util_error (grub_errmsg); + argv[0] = "-d"; argv[1] = loop_name; execute_command ("loopback", 2, argv); diff --git a/util/grub-install.in b/util/grub-install.in index e6521f069..955bf0257 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -24,6 +24,7 @@ exec_prefix=@exec_prefix@ sbindir=@sbindir@ bindir=@bindir@ libdir=@libdir@ +sysconfdir=@sysconfdir@ PACKAGE_NAME=@PACKAGE_NAME@ PACKAGE_TARNAME=@PACKAGE_TARNAME@ PACKAGE_VERSION=@PACKAGE_VERSION@ @@ -40,8 +41,10 @@ grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}` grub_probe=${sbindir}/`echo grub-probe | sed ${transform}` grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}` +grub_mkrelpath=${bindir}/`echo grub-mkrelpath | sed ${transform}` rootdir= -grub_prefix=`echo /boot/grub | sed ${transform}` +bootdir= +grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'` modules= install_device= @@ -51,9 +54,27 @@ recheck=no debug=no debug_image= +update_nvram=yes + +ofpathname=`which ofpathname` +nvsetenv=`which nvsetenv` +efibootmgr=`which efibootmgr 2>/dev/null || true` +removable=no +efi_quiet= + +# Get GRUB_DISTRIBUTOR. +if test -f ${sysconfdir}/default/grub ; then + . ${sysconfdir}/default/grub +fi + +bootloader_id="$(echo "$GRUB_DISTRIBUTOR" | tr '[A-Z]' '[a-z]' | cut -d' ' -f1)" +if test -z "$bootloader_id"; then + bootloader_id=grub +fi + if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then disk_module=biosdisk -elif [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then +elif [ "${platform}" = "ieee1275" ] || [ "${platform}" = "efi" ] ; then disk_module= else disk_module=ata @@ -62,17 +83,27 @@ fi # Usage: usage # Print the usage. usage () { +if [ "${target_cpu}-${platform}" = "i386-pc" ] \ + || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ]; then cat <. EOF @@ -134,21 +173,37 @@ do --font=*) ;; +# Accept for compatibility --root-directory) rootdir=`argument $option "$@"`; shift;; --root-directory=*) rootdir=`echo "$option" | sed 's/--root-directory=//'` ;; + --boot-directory) + bootdir=`argument $option "$@"`; shift;; + --boot-directory=*) + bootdir=`echo "$option" | sed 's/--boot-directory=//'` ;; + --grub-setup) grub_setup=`argument $option "$@"`; shift;; --grub-setup=*) grub_setup=`echo "$option" | sed 's/--grub-setup=//'` ;; + --bootloader-id) + bootloader_id=`argument $option "$@"`; shift;; + --bootloader_id=*) + bootloader_id=`echo "$option" | sed 's/--bootloader_id=//'` ;; + --grub-mkimage) grub_mkimage=`argument $option "$@"`; shift;; --grub-mkimage=*) grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;; + --grub-mkrelpath) + grub_mkrelpath=`argument $option "$@"`; shift;; + --grub-mkimage=*) + grub_mkrelpath=`echo "$option" | sed 's/--grub-mkrelpath=//'` ;; + --grub-mkdevicemap) grub_mkdevicemap=`argument $option "$@"`; shift;; --grub-mkdevicemap=*) @@ -163,6 +218,8 @@ do no_floppy="--no-floppy" ;; --recheck) recheck=yes ;; + --removable) + removable=yes ;; --disk-module) if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then @@ -173,6 +230,9 @@ do disk_module=`echo "$option" | sed 's/--disk-module=//'` fi ;; + --no-nvram) + update_nvram=no ;; + # This is an undocumented feature... --debug) debug=yes ;; @@ -202,7 +262,8 @@ done # for make_system_path_relative_to_its_root() . ${libdir}/grub/grub-mkconfig_lib -if test "x$install_device" = x && test "${target_cpu}-${platform}" != "mips-yeeloong"; then +if test "x$install_device" = x && ([ "${target_cpu}-${platform}" = "i386-pc" ] \ + || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ]); then echo "install_device not specified." 1>&2 usage exit 1 @@ -213,25 +274,21 @@ setup_verbose= if test $debug = yes; then set -x setup_verbose="--verbose" + efi_quiet=-q fi -# Initialize these directories here, since ROOTDIR was initialized. -case "$host_os" in -netbsd* | openbsd*) - # Because /boot is used for the boot block in NetBSD and OpenBSD, use /grub - # instead of /boot/grub. - grub_prefix=`echo /grub | sed ${transform}` - bootdir=${rootdir} - ;; -*) - # Use /boot/grub by default. - bootdir=${rootdir}/boot - ;; -esac +if [ -z "$bootdir" ]; then + # Default bootdir if bootdir not initialized. + bootdir=/@bootdirname@ -grubdir=${bootdir}/`echo grub | sed ${transform}` + if [ -n "$rootdir" ] ; then + # Initialize bootdir if rootdir was initialized. + bootdir=${rootdir}/@bootdirname@ + fi +fi + +grubdir=`echo "${bootdir}/@grubdirname@" | sed 's,//*,/,g'` device_map=${grubdir}/device.map - grub_probe="${grub_probe} --device-map=${device_map}" # Check if GRUB is installed. @@ -261,6 +318,87 @@ else exit 1 fi +if [ x"$platform" = xefi ]; then + # Find the EFI System Partition. + efidir= + if test -d ${bootdir}/efi; then + install_device=`$grub_mkdevicemap --device-map=/dev/stdout | $grub_probe --target=device --device-map=/dev/stdin ${bootdir}/efi` + # Is it a mount point? + if test "x$install_device" != "x`$grub_mkdevicemap --device-map=/dev/stdout | $grub_probe --target=device --device-map=/dev/stdin ${bootdir}`"; then + efidir=${bootdir}/efi + fi + elif test -n "$rootdir" && test "x$rootdir" != "x/"; then + # The EFI System Partition may have been given directly using + # --root-directory. + install_device=`$grub_mkdevicemap --device-map=/dev/stdout | $grub_probe --target=device --device-map=/dev/stdin ${rootdir}` + # Is it a mount point? + if test "x$install_device" != "x`$grub_mkdevicemap --device-map=/dev/stdout | $grub_probe --target=device --device-map=/dev/stdin ${rootdir}/..`"; then + efidir=${rootdir} + fi + fi + + if test -n "$efidir"; then + efi_fs=`$grub_probe --target=fs --device-map=${device_map} ${efidir}` + if test "x$efi_fs" = xfat; then :; else + echo "${efidir} doesn't look like an EFI partition." 1>&2 + efidir= + fi + fi + + if test -n "$efidir"; then + # The EFI specification requires that an EFI System Partition must + # contain an "EFI" subdirectory, and that OS loaders are stored in + # subdirectories below EFI. Vendors are expected to pick names that do + # not collide with other vendors. To minimise collisions, we use the + # name of our distributor if possible. + efi_distributor="$bootloader_id" + if test $removable = yes; then + # The specification makes stricter requirements of removable + # devices, in order that only one image can be automatically loaded + # from them. The image must always reside under /EFI/BOOT, and it + # must have a specific file name depending on the architecture. + efi_distributor=BOOT + case "$target_cpu" in + i386) + efi_file=BOOTIA32.EFI ;; + x86-64) + efi_file=BOOTX64.EFI ;; + # GRUB does not yet support these architectures, but they're defined + # by the specification so we include them here to ease future + # expansion. + ia64) + efi_file=BOOTIA64.EFI ;; + esac + else + # It is convenient for each architecture to have a different + # efi_file, so that different versions can be installed in parallel. + case "$target_cpu" in + i386) + efi_file=grubia32.efi ;; + x86-64) + efi_file=grubx64.efi ;; + # GRUB does not yet support these architectures, but they're defined + # by the specification so we include them here to ease future + # expansion. + ia64) + efi_file=grubia64.efi ;; + *) + efi_file=grub.efi ;; + esac + # TODO: We should also use efibootmgr, if available, to add a Boot + # entry for ourselves. + fi + efidir="$efidir/EFI/$efi_distributor" + mkdir -p "$efidir" || exit 1 + else + # We don't know what's going on. Fall back to traditional + # (non-specification-compliant) behaviour. + efidir="$grubdir" + efi_distributor= + efi_file=grub.efi + fi +fi + # Create the GRUB directory if it is not present. mkdir -p "$grubdir" || exit 1 @@ -369,6 +507,7 @@ if [ "x${devabstraction_module}" = "x" ] ; then grub_drive="`$grub_probe --target=drive --device ${grub_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`" if [ "$disk_module" = ata ] ; then # generic method (used on coreboot and ata mod) @@ -391,28 +530,113 @@ if [ "x${devabstraction_module}" = "x" ] ; then echo 'set prefix=($root)'"${relative_grubdir}" >> ${grubdir}/load.cfg config_opt="-c ${grubdir}/load.cfg " modules="$modules search_fs_uuid" + elif [ "x$platform" = xefi ] || [ "x$platform" = xpc ]; then + # we need to hardcode the partition number in the core image's prefix. + prefix_drive="(,$grub_partition)" fi else prefix_drive=`$grub_probe --target=drive --device ${grub_device}` || exit 1 fi case "${target_cpu}-${platform}" in - i386-pc) mkimage_target=i386-pc ;; sparc64-ieee1275) mkimage_target=sparc64-ieee1275-raw ;; mips-yeeloong) mkimage_target=mipsel-yeeloong-elf ;; - *) mkimage_target=i386-coreboot; + *) mkimage_target="${target_cpu}-${platform}" ;; esac -if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then - $grub_mkimage ${config_opt} -O ${mkimage_target} --output=${grubdir}/core.img --prefix=${prefix_drive}${relative_grubdir} $modules || exit 1 +case "${target_cpu}-${platform}" in + i386-efi | x86_64-efi) imgext=efi ;; + mips-yeeloong | i386-coreboot | i386-multiboot | i386-ieee1275 \ + | powerpc-ieee1275) imgext=elf ;; + *) imgext=img ;; +esac + +$grub_mkimage ${config_opt} -d ${pkglibdir} -O ${mkimage_target} --output=${grubdir}/core.${imgext} --prefix=${prefix_drive}${relative_grubdir} $modules || exit 1 + +# Backward-compatibility kludges +if [ "${target_cpu}-${platform}" = "mips-yeeloong" ]; then + cp ${grubdir}/core.${imgext} /boot/grub.elf +elif [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${platform}" = "powerpc-ieee1275" ]; then + cp ${grubdir}/core.${imgext} /boot/grub/grub +elif [ "${target_cpu}-${platform}" = "i386-efi" ] || [ "${target_cpu}-${platform}" = "x86_64-efi" ]; then + $grub_mkimage ${config_opt} -d ${pkglibdir} -O ${mkimage_target} --output=${grubdir}/grub.efi --prefix="" $modules || exit 1 +fi + + +# Perform the platform-dependent install +if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then # Now perform the installation. - $grub_setup ${setup_verbose} ${setup_force} --directory=${grubdir} --device-map=${device_map} \ - ${install_device} || exit 1 -elif [ "${target_cpu}-${platform}" = "mips-yeeloong" ] ; then - $grub_mkimage ${config_opt} -d ${pkglibdir} -O ${mkimage_target} --output=/boot/grub.elf --prefix=${prefix_drive}${relative_grubdir} $modules || exit 1 -else - $grub_mkimage -O ${mkimage_target} ${config_opt} -d ${pkglibdir} --output=/boot/multiboot.img --prefix=${prefix_drive}${relative_grubdir} $modules || exit 1 + $grub_setup ${setup_verbose} ${setup_force} --directory=${grubdir} \ + --device-map=${device_map} ${install_device} || exit 1 +elif [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${platform}" = "powerpc-ieee1275" ]; then + if [ x"$update_nvram" = xyes ]; then + set $ofpathname dummy + if test -f "$1"; then + : + else + echo "$1: Not found." 1>&2 + exit 1 + fi + set $nvsetenv dummy + if test -f "$1"; then + : + else + echo "$1: Not found." 1>&2 + exit 1 + fi + # Get the Open Firmware device tree path translation. + dev=`echo $grub_device | sed -e 's/\/dev\///' -e 's/[0-9]\+//'` + partno=`echo $grub_device | sed -e 's/.*[^0-9]\([0-9]\+\)$/\1/'` + ofpath=`$ofpathname $dev` || { + echo "Couldn't find Open Firmware device tree path for $dev." + echo "You will have to set boot-device manually." + exit 1 + } + + # Point boot-device at the new grub install + boot_device="$ofpath:$partno,"`grub-mkrelpath ${grubdir}/core.${imgext} | sed 's,/,\\\\,g'` + "$nvsetenv" boot-device "$boot_device" || { + echo "$nvsetenv failed." + echo "You will have to set boot-device manually. At the Open Firmware prompt, type:" + echo " setenv boot-device $boot_device" + exit 1 + } + fi +elif [ x"$platform" = xefi ]; then + cp ${grubdir}/core.${imgext} ${efidir}/${efi_file} + + # Try to make this image bootable using the EFI Boot Manager, if available. + if test "$removable" = no && test -n "$efi_distributor" && \ + test -n "$efibootmgr"; then + # On Linux, we need the efivars kernel modules. + case "$host_os" in + linux*) + modprobe -q efivars 2>/dev/null || true ;; + esac + + # Delete old entries from the same distributor. + for bootnum in `efibootmgr | grep '^Boot[0-9]' | \ + fgrep -i " $efi_distributor" | cut -b5-8`; do + efibootmgr $efi_quiet -b "$bootnum" -B + done + + # Add a new entry for the image we just created. efibootmgr needs to be + # given the disk device and partition number separately, so we have to + # fiddle about with grub-probe to get hold of this reasonably reliably. + # Use fresh device map text to avoid any problems with stale data, since + # all we need here is a one-to-one mapping. + clean_devmap="$($grub_mkdevicemap --device-map=/dev/stdout)" + efidir_drive="$(echo "$clean_devmap" | $grub_probe --target=drive --device-map=/dev/stdin "$efidir")" + if test -z "$efidir_drive"; then + echo "Can't find GRUB drive for $efidir; unable to create EFI Boot Manager entry." >&2 + else + efidir_disk="$(echo "$clean_devmap" | grep "^$(echo "$efidir_drive" | sed 's/,[^)]*//')" | cut -f2)" + efidir_part="$(echo "$efidir_drive" | sed 's/^([^,]*,[^0-9]*//; s/[^0-9].*//')" + efibootmgr $efi_quiet -c -d "$efidir_disk" -p "$efidir_part" -w \ + -L "$GRUB_DISTRIBUTOR" -l "\\EFI\\$efi_distributor\\$efi_file" + fi + fi fi echo "Installation finished. No error reported." diff --git a/util/grub-kbdcomp.in b/util/grub-kbdcomp.in new file mode 100644 index 000000000..87b24bcdf --- /dev/null +++ b/util/grub-kbdcomp.in @@ -0,0 +1,6 @@ +#!/bin/sh + +grub_mklayout=${bindir}/`echo grub-mklayout | sed ${transform}` + +ckbcomp "$@" | $grub_mklayout -o "$1".gkb + diff --git a/util/grub-menulst2cfg.c b/util/grub-menulst2cfg.c new file mode 100644 index 000000000..512239e89 --- /dev/null +++ b/util/grub-menulst2cfg.c @@ -0,0 +1,120 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include + +int +main (int argc, char **argv) +{ + FILE *in, *out; + char *entryname = NULL; + char *buf = NULL; + size_t bufsize = 0; + char *suffix = xstrdup (""); + int suffixlen = 0; + + if (argc >= 2 && argv[1][0] == '-') + { + fprintf (stdout, "Usage: %s [INFILE [OUTFILE]]\n", argv[0]); + return 0; + } + + if (argc >= 2) + { + in = fopen (argv[1], "r"); + if (!in) + { + fprintf (stderr, "Couldn't open %s for reading: %s\n", + argv[1], strerror (errno)); + return 1; + } + } + else + in = stdin; + + if (argc >= 3) + { + out = fopen (argv[2], "w"); + if (!out) + { + if (in != stdin) + fclose (in); + fprintf (stderr, "Couldn't open %s for writing: %s\n", + argv[2], strerror (errno)); + return 1; + } + } + else + out = stdout; + + while (1) + { + char *parsed; + + if (getline (&buf, &bufsize, in) < 0) + break; + + { + char *oldname = NULL; + char *newsuffix; + + oldname = entryname; + parsed = grub_legacy_parse (buf, &entryname, &newsuffix); + if (newsuffix) + { + suffixlen += strlen (newsuffix); + suffix = xrealloc (suffix, suffixlen + 1); + strcat (suffix, newsuffix); + } + if (oldname != entryname && oldname) + fprintf (out, "}\n\n"); + if (oldname != entryname) + { + char *escaped = grub_legacy_escape (entryname, strlen (entryname)); + fprintf (out, "menuentry \'%s\' {\n", escaped); + free (escaped); + free (oldname); + } + } + + if (parsed) + fprintf (out, "%s%s", entryname ? " " : "", parsed); + free (parsed); + parsed = NULL; + } + + if (entryname) + fprintf (out, "}\n\n"); + + fwrite (suffix, 1, suffixlen, out); + + free (buf); + free (suffix); + free (entryname); + + if (in != stdin) + fclose (in); + if (out != stdout) + fclose (out); + + return 0; +} diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in index 3233043c8..145143a4b 100644 --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in @@ -38,6 +38,8 @@ self=`basename $0` grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}` grub_probe=${sbindir}/`echo grub-probe | sed ${transform}` +GRUB_PREFIX=`echo '/@bootdirname@/@grubdirname@' | sed "s,//*,/,g"` + # Usage: usage # Print the usage. usage () { @@ -93,18 +95,6 @@ done . ${libdir}/grub/grub-mkconfig_lib -case "$host_os" in -netbsd* | openbsd*) - # Because /boot is used for the boot block in NetBSD and OpenBSD, use /grub - # instead of /boot/grub. - GRUB_PREFIX=`echo /grub | sed ${transform}` - ;; -*) - # Use /boot/grub by default. - GRUB_PREFIX=`echo /boot/grub | sed ${transform}` - ;; -esac - if [ "x$EUID" = "x" ] ; then EUID=`id -u` fi @@ -158,7 +148,7 @@ GRUB_DEVICE_BOOT_UUID="`${grub_probe} --device ${GRUB_DEVICE_BOOT} --target=fs_u # Filesystem for the device containing our userland. Used for stuff like # choosing Hurd filesystem module. -GRUB_FS="`${grub_probe} --target=fs / 2> /dev/null || echo unknown`" +GRUB_FS="`${grub_probe} --device ${GRUB_DEVICE} --target=fs 2> /dev/null || echo unknown`" if test -f ${sysconfdir}/default/grub ; then . ${sysconfdir}/default/grub @@ -200,7 +190,7 @@ for x in ${GRUB_TERMINAL_OUTPUT}; do exit 1 fi else - for dir in ${pkgdatadir} /boot/grub /usr/share/grub ; do + for dir in ${pkgdatadir} ${GRUB_PREFIX} /usr/share/grub ; do for basename in unicode unifont ascii; do path="${dir}/${basename}.pf2" if is_path_readable_by_grub ${path} > /dev/null ; then @@ -255,6 +245,7 @@ export GRUB_DEFAULT \ GRUB_HIDDEN_TIMEOUT_BUTTON \ GRUB_TIMEOUT_BUTTON \ GRUB_BUTTON_CMOS_ADDRESS \ + GRUB_BUTTON_CMOS_CLEAN \ GRUB_DISTRIBUTOR \ GRUB_CMDLINE_LINUX \ GRUB_CMDLINE_LINUX_DEFAULT \ diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in index 9a77d1bdf..41359975e 100644 --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in @@ -119,7 +119,7 @@ prepare_grub_to_access_device () # otherwise set root as per value in device.map. echo "set root='`${grub_probe} --device ${device} --target=drive`'" if fs_uuid="`${grub_probe} --device ${device} --target=fs_uuid 2> /dev/null`" ; then - echo "search --no-floppy --fs-uuid --set ${fs_uuid}" + echo "search --no-floppy --fs-uuid --set=root ${fs_uuid}" fi } diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c index 4a257e329..ce51f2fbc 100644 --- a/util/grub-mkimagexx.c +++ b/util/grub-mkimagexx.c @@ -555,7 +555,7 @@ SUFFIX (locate_sections) (Elf_Shdr *sections, Elf_Half section_entsize, i++, s = (Elf_Shdr *) ((char *) s + section_entsize)) if (SUFFIX (is_text_section) (s, image_target)) { - Elf_Word align = grub_host_to_target32 (s->sh_addralign); + Elf_Word align = grub_host_to_target_addr (s->sh_addralign); const char *name = strtab + grub_host_to_target32 (s->sh_name); if (align) current_address = ALIGN_UP (current_address + image_target->vaddr_offset, @@ -577,7 +577,7 @@ SUFFIX (locate_sections) (Elf_Shdr *sections, Elf_Half section_entsize, i++, s = (Elf_Shdr *) ((char *) s + section_entsize)) if (SUFFIX (is_data_section) (s, image_target)) { - Elf_Word align = grub_host_to_target32 (s->sh_addralign); + Elf_Word align = grub_host_to_target_addr (s->sh_addralign); const char *name = strtab + grub_host_to_target32 (s->sh_name); if (align) @@ -641,7 +641,7 @@ SUFFIX (load_image) (const char *kernel_path, grub_size_t *exec_size, /* Relocate sections then symbols in the virtual address space. */ s = (Elf_Shdr *) ((char *) sections + grub_host_to_target16 (e->e_shstrndx) * section_entsize); - strtab = (char *) e + grub_host_to_target32 (s->sh_offset); + strtab = (char *) e + grub_host_to_target_addr (s->sh_offset); section_addresses = SUFFIX (locate_sections) (sections, section_entsize, num_sections, strtab, @@ -662,7 +662,7 @@ SUFFIX (load_image) (const char *kernel_path, grub_size_t *exec_size, i++, s = (Elf_Shdr *) ((char *) s + section_entsize)) if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS) { - Elf_Word align = grub_host_to_target32 (s->sh_addralign); + Elf_Word align = grub_host_to_target_addr (s->sh_addralign); const char *name = strtab + grub_host_to_target32 (s->sh_name); if (align) diff --git a/util/grub-mklayout.c b/util/grub-mklayout.c new file mode 100644 index 000000000..ac59981c7 --- /dev/null +++ b/util/grub-mklayout.c @@ -0,0 +1,498 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "progname.h" + +#define CKBCOMP "ckbcomp" + +static struct option options[] = { + {"output", required_argument, 0, 'o'}, + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'V'}, + {"verbose", no_argument, 0, 'v'}, + {0, 0, 0, 0} +}; + +struct console_grub_equivalence +{ + char *layout; + grub_uint32_t grub; +}; + +static struct console_grub_equivalence console_grub_equivalences_shift[] = { + {"KP_0", '0'}, + {"KP_1", '1'}, + {"KP_2", '2'}, + {"KP_3", '3'}, + {"KP_4", '4'}, + {"KP_5", '5'}, + {"KP_6", '6'}, + {"KP_7", '7'}, + {"KP_8", '8'}, + {"KP_9", '9'}, + {"KP_Period", '.'}, +}; + +static struct console_grub_equivalence console_grub_equivalences_unshift[] = { + {"KP_0", GRUB_TERM_KEY_INSERT}, + {"KP_1", GRUB_TERM_KEY_END}, + {"KP_2", GRUB_TERM_KEY_DOWN}, + {"KP_3", GRUB_TERM_KEY_NPAGE}, + {"KP_4", GRUB_TERM_KEY_LEFT}, + {"KP_5", GRUB_TERM_KEY_CENTER}, + {"KP_6", GRUB_TERM_KEY_RIGHT}, + {"KP_7", GRUB_TERM_KEY_HOME}, + {"KP_8", GRUB_TERM_KEY_UP}, + {"KP_9", GRUB_TERM_KEY_PPAGE}, + {"KP_Period", GRUB_TERM_KEY_DC}, +}; + +static struct console_grub_equivalence console_grub_equivalences_common[] = { + {"Escape", GRUB_TERM_ESC}, + {"Tab", GRUB_TERM_TAB}, + {"Delete", GRUB_TERM_BACKSPACE}, + + {"KP_Enter", '\n'}, + {"Return", '\n'}, + + {"KP_Multiply", '*'}, + {"KP_Subtract", '-'}, + {"KP_Add", '+'}, + {"KP_Divide", '/'}, + + {"F1", GRUB_TERM_KEY_F1}, + {"F2", GRUB_TERM_KEY_F2}, + {"F3", GRUB_TERM_KEY_F3}, + {"F4", GRUB_TERM_KEY_F4}, + {"F5", GRUB_TERM_KEY_F5}, + {"F6", GRUB_TERM_KEY_F6}, + {"F7", GRUB_TERM_KEY_F7}, + {"F8", GRUB_TERM_KEY_F8}, + {"F9", GRUB_TERM_KEY_F9}, + {"F10", GRUB_TERM_KEY_F10}, + {"F11", GRUB_TERM_KEY_F11}, + {"F12", GRUB_TERM_KEY_F12}, + {"F13", GRUB_TERM_KEY_F1 | GRUB_TERM_SHIFT}, + {"F14", GRUB_TERM_KEY_F2 | GRUB_TERM_SHIFT}, + {"F15", GRUB_TERM_KEY_F3 | GRUB_TERM_SHIFT}, + {"F16", GRUB_TERM_KEY_F4 | GRUB_TERM_SHIFT}, + {"F17", GRUB_TERM_KEY_F5 | GRUB_TERM_SHIFT}, + {"F18", GRUB_TERM_KEY_F6 | GRUB_TERM_SHIFT}, + {"F19", GRUB_TERM_KEY_F7 | GRUB_TERM_SHIFT}, + {"F20", GRUB_TERM_KEY_F8 | GRUB_TERM_SHIFT}, + {"F21", GRUB_TERM_KEY_F9 | GRUB_TERM_SHIFT}, + {"F22", GRUB_TERM_KEY_F10 | GRUB_TERM_SHIFT}, + {"F23", GRUB_TERM_KEY_F11 | GRUB_TERM_SHIFT}, + {"F24", GRUB_TERM_KEY_F12 | GRUB_TERM_SHIFT}, + {"Console_13", GRUB_TERM_KEY_F1 | GRUB_TERM_ALT}, + {"Console_14", GRUB_TERM_KEY_F2 | GRUB_TERM_ALT}, + {"Console_15", GRUB_TERM_KEY_F3 | GRUB_TERM_ALT}, + {"Console_16", GRUB_TERM_KEY_F4 | GRUB_TERM_ALT}, + {"Console_17", GRUB_TERM_KEY_F5 | GRUB_TERM_ALT}, + {"Console_18", GRUB_TERM_KEY_F6 | GRUB_TERM_ALT}, + {"Console_19", GRUB_TERM_KEY_F7 | GRUB_TERM_ALT}, + {"Console_20", GRUB_TERM_KEY_F8 | GRUB_TERM_ALT}, + {"Console_21", GRUB_TERM_KEY_F9 | GRUB_TERM_ALT}, + {"Console_22", GRUB_TERM_KEY_F10 | GRUB_TERM_ALT}, + {"Console_23", GRUB_TERM_KEY_F11 | GRUB_TERM_ALT}, + {"Console_24", GRUB_TERM_KEY_F12 | GRUB_TERM_ALT}, + {"Console_25", GRUB_TERM_KEY_F1 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_26", GRUB_TERM_KEY_F2 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_27", GRUB_TERM_KEY_F3 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_28", GRUB_TERM_KEY_F4 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_29", GRUB_TERM_KEY_F5 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_30", GRUB_TERM_KEY_F6 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_31", GRUB_TERM_KEY_F7 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_32", GRUB_TERM_KEY_F8 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_33", GRUB_TERM_KEY_F9 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_34", GRUB_TERM_KEY_F10 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_35", GRUB_TERM_KEY_F11 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_36", GRUB_TERM_KEY_F12 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + + {"Insert", GRUB_TERM_KEY_INSERT}, + {"Down", GRUB_TERM_KEY_DOWN}, + {"Up", GRUB_TERM_KEY_UP}, + {"Home", GRUB_TERM_KEY_HOME}, + {"End", GRUB_TERM_KEY_END}, + {"Right", GRUB_TERM_KEY_RIGHT}, + {"Left", GRUB_TERM_KEY_LEFT}, + {"Next", GRUB_TERM_KEY_NPAGE}, + {"Prior", GRUB_TERM_KEY_PPAGE}, + {"Remove", GRUB_TERM_KEY_DC}, + {"VoidSymbol", 0}, + + /* "Undead" keys since no dead key support in GRUB. */ + {"dead_acute", '\''}, + {"dead_circumflex", '^'}, + {"dead_grave", '`'}, + {"dead_tilde", '~'}, + {"dead_diaeresis", '"'}, + + /* Following ones don't provide any useful symbols for shell. */ + {"dead_cedilla", 0}, + {"dead_ogonek", 0}, + {"dead_caron", 0}, + {"dead_breve", 0}, + {"dead_doubleacute", 0}, + + /* Unused in GRUB. */ + {"Pause", 0}, + {"Scroll_Forward", 0}, + {"Scroll_Backward", 0}, + {"Hex_0", 0}, + {"Hex_1", 0}, + {"Hex_2", 0}, + {"Hex_3", 0}, + {"Hex_4", 0}, + {"Hex_5", 0}, + {"Hex_6", 0}, + {"Hex_7", 0}, + {"Hex_8", 0}, + {"Hex_9", 0}, + {"Hex_A", 0}, + {"Hex_B", 0}, + {"Hex_C", 0}, + {"Hex_D", 0}, + {"Hex_E", 0}, + {"Hex_F", 0}, + {"Scroll_Lock", 0}, + {"Show_Memory", 0}, + {"Show_Registers", 0}, + {"Control_backslash", 0}, + {"Compose", 0}, + + {NULL, '\0'} +}; + +static grub_uint8_t linux_to_usb_map[128] = { + /* 0x00 */ 0 /* Unused */, GRUB_KEYBOARD_KEY_ESCAPE, + /* 0x02 */ GRUB_KEYBOARD_KEY_1, GRUB_KEYBOARD_KEY_2, + /* 0x04 */ GRUB_KEYBOARD_KEY_3, GRUB_KEYBOARD_KEY_4, + /* 0x06 */ GRUB_KEYBOARD_KEY_5, GRUB_KEYBOARD_KEY_6, + /* 0x08 */ GRUB_KEYBOARD_KEY_7, GRUB_KEYBOARD_KEY_8, + /* 0x0a */ GRUB_KEYBOARD_KEY_9, GRUB_KEYBOARD_KEY_0, + /* 0x0c */ GRUB_KEYBOARD_KEY_DASH, GRUB_KEYBOARD_KEY_EQUAL, + /* 0x0e */ GRUB_KEYBOARD_KEY_BACKSPACE, GRUB_KEYBOARD_KEY_TAB, + /* 0x10 */ GRUB_KEYBOARD_KEY_Q, GRUB_KEYBOARD_KEY_W, + /* 0x12 */ GRUB_KEYBOARD_KEY_E, GRUB_KEYBOARD_KEY_R, + /* 0x14 */ GRUB_KEYBOARD_KEY_T, GRUB_KEYBOARD_KEY_Y, + /* 0x16 */ GRUB_KEYBOARD_KEY_U, GRUB_KEYBOARD_KEY_I, + /* 0x18 */ GRUB_KEYBOARD_KEY_O, GRUB_KEYBOARD_KEY_P, + /* 0x1a */ GRUB_KEYBOARD_KEY_LBRACKET, GRUB_KEYBOARD_KEY_RBRACKET, + /* 0x1c */ GRUB_KEYBOARD_KEY_ENTER, GRUB_KEYBOARD_KEY_LEFT_CTRL, + /* 0x1e */ GRUB_KEYBOARD_KEY_A, GRUB_KEYBOARD_KEY_S, + /* 0x20 */ GRUB_KEYBOARD_KEY_D, GRUB_KEYBOARD_KEY_F, + /* 0x22 */ GRUB_KEYBOARD_KEY_G, GRUB_KEYBOARD_KEY_H, + /* 0x24 */ GRUB_KEYBOARD_KEY_J, GRUB_KEYBOARD_KEY_K, + /* 0x26 */ GRUB_KEYBOARD_KEY_L, GRUB_KEYBOARD_KEY_SEMICOLON, + /* 0x28 */ GRUB_KEYBOARD_KEY_DQUOTE, GRUB_KEYBOARD_KEY_RQUOTE, + /* 0x2a */ GRUB_KEYBOARD_KEY_LEFT_SHIFT, GRUB_KEYBOARD_KEY_BACKSLASH, + /* 0x2c */ GRUB_KEYBOARD_KEY_Z, GRUB_KEYBOARD_KEY_X, + /* 0x2e */ GRUB_KEYBOARD_KEY_C, GRUB_KEYBOARD_KEY_V, + /* 0x30 */ GRUB_KEYBOARD_KEY_B, GRUB_KEYBOARD_KEY_N, + /* 0x32 */ GRUB_KEYBOARD_KEY_M, GRUB_KEYBOARD_KEY_COMMA, + /* 0x34 */ GRUB_KEYBOARD_KEY_DOT, GRUB_KEYBOARD_KEY_SLASH, + /* 0x36 */ GRUB_KEYBOARD_KEY_RIGHT_SHIFT, GRUB_KEYBOARD_KEY_NUMMUL, + /* 0x38 */ GRUB_KEYBOARD_KEY_LEFT_ALT, GRUB_KEYBOARD_KEY_SPACE, + /* 0x3a */ GRUB_KEYBOARD_KEY_CAPS_LOCK, GRUB_KEYBOARD_KEY_F1, + /* 0x3c */ GRUB_KEYBOARD_KEY_F2, GRUB_KEYBOARD_KEY_F3, + /* 0x3e */ GRUB_KEYBOARD_KEY_F4, GRUB_KEYBOARD_KEY_F5, + /* 0x40 */ GRUB_KEYBOARD_KEY_F6, GRUB_KEYBOARD_KEY_F7, + /* 0x42 */ GRUB_KEYBOARD_KEY_F8, GRUB_KEYBOARD_KEY_F9, + /* 0x44 */ GRUB_KEYBOARD_KEY_F10, GRUB_KEYBOARD_KEY_NUM_LOCK, + /* 0x46 */ GRUB_KEYBOARD_KEY_SCROLL_LOCK, GRUB_KEYBOARD_KEY_NUM7, + /* 0x48 */ GRUB_KEYBOARD_KEY_NUM8, GRUB_KEYBOARD_KEY_NUM9, + /* 0x4a */ GRUB_KEYBOARD_KEY_NUMMINUS, GRUB_KEYBOARD_KEY_NUM4, + /* 0x4c */ GRUB_KEYBOARD_KEY_NUM5, GRUB_KEYBOARD_KEY_NUM6, + /* 0x4e */ GRUB_KEYBOARD_KEY_NUMPLUS, GRUB_KEYBOARD_KEY_NUM1, + /* 0x50 */ GRUB_KEYBOARD_KEY_NUM2, GRUB_KEYBOARD_KEY_NUM3, + /* 0x52 */ GRUB_KEYBOARD_KEY_NUMDOT, GRUB_KEYBOARD_KEY_NUMDOT, + /* 0x54 */ 0, 0, + /* 0x56 */ GRUB_KEYBOARD_KEY_102ND, GRUB_KEYBOARD_KEY_F11, + /* 0x58 */ GRUB_KEYBOARD_KEY_F12, 0, + /* 0x5a */ 0, 0, + /* 0x5c */ 0, 0, + /* 0x5e */ 0, 0, + /* 0x60 */ GRUB_KEYBOARD_KEY_NUMENTER, GRUB_KEYBOARD_KEY_RIGHT_CTRL, + /* 0x62 */ GRUB_KEYBOARD_KEY_NUMSLASH, 0, + /* 0x64 */ GRUB_KEYBOARD_KEY_RIGHT_ALT, 0, + /* 0x66 */ GRUB_KEYBOARD_KEY_HOME, GRUB_KEYBOARD_KEY_UP, + /* 0x68 */ GRUB_KEYBOARD_KEY_PPAGE, GRUB_KEYBOARD_KEY_LEFT, + /* 0x6a */ GRUB_KEYBOARD_KEY_RIGHT, GRUB_KEYBOARD_KEY_END, + /* 0x6c */ GRUB_KEYBOARD_KEY_DOWN, GRUB_KEYBOARD_KEY_NPAGE, + /* 0x6e */ GRUB_KEYBOARD_KEY_INSERT, GRUB_KEYBOARD_KEY_DELETE +}; + +static void +usage (int status) +{ + if (status) + fprintf (stderr, "Try `%s --help' for more information.\n", program_name); + else + printf ("\ +Usage: %s [OPTIONS] LAYOUT\n\ + -o, --output set output base name file. Default is LAYOUT.gkb\n\ + -h, --help display this message and exit.\n\ + -V, --version print version information and exit.\n\ + -v, --verbose print verbose messages.\n\ +\n\ +Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT); + + exit (status); +} + +static void +add_special_keys (struct grub_keyboard_layout *layout) +{ + (void) layout; +} + +static unsigned +lookup (char *code, int shift) +{ + int i; + struct console_grub_equivalence *pr; + + if (shift) + pr = console_grub_equivalences_shift; + else + pr = console_grub_equivalences_unshift; + + for (i = 0; pr[i].layout != NULL; i++) + if (strcmp (code, pr[i].layout) == 0) + return pr[i].grub; + + for (i = 0; console_grub_equivalences_common[i].layout != NULL; i++) + if (strcmp (code, console_grub_equivalences_common[i].layout) == 0) + return console_grub_equivalences_common[i].grub; + + fprintf (stderr, "Unknown key %s\n", code); + + return '\0'; +} + +static unsigned int +get_grub_code (char *layout_code, int shift) +{ + unsigned int code; + + if (strncmp (layout_code, "U+", sizeof ("U+") - 1) == 0) + sscanf (layout_code, "U+%x", &code); + else if (strncmp (layout_code, "+U+", sizeof ("+U+") - 1) == 0) + sscanf (layout_code, "+U+%x", &code); + else + code = lookup (layout_code, shift); + return code; +} + +static void +write_file (FILE *out, struct grub_keyboard_layout *layout) +{ + grub_uint32_t version; + unsigned i; + + version = grub_cpu_to_le32 (GRUB_KEYBOARD_LAYOUTS_VERSION); + + for (i = 0; i < ARRAY_SIZE (layout->keyboard_map); i++) + layout->keyboard_map[i] = grub_cpu_to_le32(layout->keyboard_map[i]); + + for (i = 0; i < ARRAY_SIZE (layout->keyboard_map_shift); i++) + layout->keyboard_map_shift[i] + = grub_cpu_to_le32(layout->keyboard_map_shift[i]); + + for (i = 0; i < ARRAY_SIZE (layout->keyboard_map_l3); i++) + layout->keyboard_map_l3[i] + = grub_cpu_to_le32(layout->keyboard_map_l3[i]); + + for (i = 0; i < ARRAY_SIZE (layout->keyboard_map_shift_l3); i++) + layout->keyboard_map_shift_l3[i] + = grub_cpu_to_le32(layout->keyboard_map_shift_l3[i]); + + fwrite (GRUB_KEYBOARD_LAYOUTS_FILEMAGIC, 1, + GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE, out); + fwrite (&version, sizeof (version), 1, out); + fwrite (layout, 1, sizeof (*layout), out); +} + +static void +write_keymaps (FILE *in, FILE *out) +{ + struct grub_keyboard_layout layout; + char line[2048]; + int ok; + + memset (&layout, 0, sizeof (layout)); + + /* Process the ckbcomp output and prepare the layouts. */ + ok = 0; + while (fgets (line, sizeof (line), in)) + { + if (strncmp (line, "keycode", sizeof ("keycode") - 1) == 0) + { + unsigned keycode_linux; + unsigned keycode_usb; + char normal[64]; + char shift[64]; + char normalalt[64]; + char shiftalt[64]; + + sscanf (line, "keycode %u = %60s %60s %60s %60s", &keycode_linux, + normal, shift, normalalt, shiftalt); + + /* Not used. */ + if (keycode_linux == 0x77 /* Pause */ + /* Some obscure keys */ + || keycode_linux == 0x63 || keycode_linux == 0x7d + || keycode_linux == 0x7e) + continue; + + /* Not remappable. */ + if (keycode_linux == 0x1d /* Left CTRL */ + || keycode_linux == 0x61 /* Right CTRL */ + || keycode_linux == 0x2a /* Left Shift. */ + || keycode_linux == 0x36 /* Right Shift. */ + || keycode_linux == 0x38 /* Left ALT. */ + || keycode_linux == 0x64 /* Right ALT. */ + || keycode_linux == 0x3a /* CapsLock. */ + || keycode_linux == 0x45 /* NumLock. */ + || keycode_linux == 0x46 /* ScrollLock. */) + continue; + + keycode_usb = linux_to_usb_map[keycode_linux]; + if (keycode_usb == 0 + || keycode_usb >= GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE) + { + fprintf (stderr, "Unknown keycode 0x%02x\n", keycode_linux); + continue; + } + if (keycode_usb < GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE) + { + layout.keyboard_map[keycode_usb] = get_grub_code (normal, 0); + layout.keyboard_map_shift[keycode_usb] = get_grub_code (shift, 1); + layout.keyboard_map_l3[keycode_usb] + = get_grub_code (normalalt, 0); + layout.keyboard_map_shift_l3[keycode_usb] + = get_grub_code (shiftalt, 1); + ok = 1; + } + } + } + + if (ok == 0) + { + fprintf (stderr, "ERROR: no keycodes found. Check output of %s.\n", + CKBCOMP); + exit (1); + } + + add_special_keys (&layout); + + write_file (out, &layout); +} + +int +main (int argc, char *argv[]) +{ + int verbosity; + char *infile_name = NULL; + char *outfile_name = NULL; + FILE *in, *out; + + set_program_name (argv[0]); + + verbosity = 0; + + /* Check for options. */ + while (1) + { + int c = getopt_long (argc, argv, "o:i:hVv", options, 0); + + if (c == -1) + break; + else + switch (c) + { + case 'h': + usage (0); + break; + + case 'i': + infile_name = optarg; + break; + + case 'o': + outfile_name = optarg; + break; + + case 'V': + printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, + PACKAGE_VERSION); + return 0; + + case 'v': + verbosity++; + break; + + default: + usage (1); + break; + } + } + + if (infile_name) + in = fopen (infile_name, "r"); + else + in = stdin; + + if (!in) + grub_util_error ("Couldn't open input file: %s\n", strerror (errno)); + + if (outfile_name) + out = fopen (outfile_name, "wb"); + else + out = stdout; + + if (!out) + { + if (in != stdin) + fclose (in); + grub_util_error ("Couldn't open output file: %s\n", strerror (errno)); + } + + write_keymaps (in, out); + + if (in != stdin) + fclose (in); + + if (out != stdout) + fclose (out); + + return 0; +} diff --git a/util/grub-mknetdir.in b/util/grub-mknetdir.in new file mode 100644 index 000000000..b353e98b9 --- /dev/null +++ b/util/grub-mknetdir.in @@ -0,0 +1,230 @@ +#! /bin/sh + +# Install GRUB on your drive. +# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc. +# +# GRUB is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# GRUB is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GRUB. If not, see . + +# Initialize some variables. +transform="@program_transform_name@" + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +sbindir=@sbindir@ +bindir=@bindir@ +libdir=@libdir@ +PACKAGE_NAME=@PACKAGE_NAME@ +PACKAGE_TARNAME=@PACKAGE_TARNAME@ +PACKAGE_VERSION=@PACKAGE_VERSION@ +target_cpu=@target_cpu@ +platform=@platform@ +host_os=@host_os@ +pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}` +localedir=@datadir@/locale +native_platform=@platform@ +pkglib_DATA="moddep.lst command.lst fs.lst partmap.lst parttool.lst handler.lst video.lst crypto.lst terminal.lst" + +self=`basename $0` + +grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` +rootdir=/srv/tftp +grub_prefix=`echo /boot/grub | sed ${transform}` +modules= + +install_device= +no_floppy= +recheck=no +debug=no +debug_image= +subdir=`echo /boot/grub | sed ${transform}` +pc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-pc + +# Usage: usage +# Print the usage. +usage () { + cat <. +EOF +} + +argument () { + opt=$1 + shift + + if test $# -eq 0; then + echo "$0: option requires an argument -- '$opt'" 1>&2 + exit 1 + fi + echo $1 +} + +# Check the arguments. +while test $# -gt 0 +do + option=$1 + shift + + case "$option" in + -h | --help) + usage + exit 0 ;; + -v | --version) + echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" + exit 0 ;; + + --modules) + modules=`argument $option "$@"`; shift;; + --modules=*) + modules=`echo "$option" | sed 's/--modules=//'` ;; + + --net-directory) + rootdir=`argument $option "$@"`; shift;; + --net-directory=*) + rootdir=`echo "$option" | sed 's/--net-directory=//'` ;; + + --subdir) + subdir=`argument $option "$@"`; shift;; + --subdir=*) + subdir=`echo "$option" | sed 's/--subdir=//'` ;; + + --grub-mkimage) + grub_mkimage=`argument $option "$@"`; shift;; + --grub-mkimage=*) + grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;; + + # This is an undocumented feature... + --debug) + debug=yes ;; + --debug-image) + debug_image=`argument $option "$@"`; shift;; + --debug-image=*) + debug_image=`echo "$option" | sed 's/--debug-image=//'` ;; + + # Intentionally undocumented + --override-directory) + override_dir=`argument $option "$@"` + shift + PATH=${override_dir}:$PATH + export PATH + ;; + --override-directory=*) + override_dir=`echo "${option}/" | sed 's/--override-directory=//'` + PATH=${override_dir}:$PATH + export PATH + ;; + + -*) + echo "Unrecognized option \`$option'" 1>&2 + usage + exit 1 + ;; + *) + if test "x$install_device" != x; then + echo "More than one install_devices?" 1>&2 + usage + exit 1 + fi + install_device="${option}" ;; + esac +done + +set $grub_mkimage dummy +if test -f "$1"; then + : +else + echo "$1: Not found." 1>&2 + exit 1 +fi + +# Create the GRUB directory if it is not present. +mkdir -p "${rootdir}/${subdir}" || exit 1 + +process_input_dir () +{ + input_dir="$1" + platform="$2" + grubdir="${rootdir}/${subdir}/${platform}" + config_opt= + mkdir -p "$grubdir" || exit 1 + + for file in ${grubdir}/*.mod ${grubdir}/*.lst ${grubdir}/*.img ${grubdir}/efiemu??.o; do + if test -f $file && [ "`basename $file`" != menu.lst ]; then + rm -f $file || exit 1 + fi + done + for file in ${input_dir}/*.mod; do + if test -f "$file"; then + cp -f "$file" "$grubdir/" + fi + done + for file in ${pkglib_DATA}; do + if test -f "${input_dir}/${file}"; then + cp -f "${input_dir}/${file}" "$grubdir/" + fi + done + + mkdir -p "$grubdir/locale" + for file in ${input_dir}/po/*.mo; do + if test -f "$file"; then + cp -f "$file" "$grubdir/locale/" + fi + done + + rm -f ${grubdir}/load.cfg + + if [ "x${debug_image}" != x ]; then + echo "set debug='${debug_image}'" >> ${grubdir}/load.cfg + config_opt="-c ${grubdir}/load.cfg " + fi + + case "${platform}" in + i386-pc) mkimage_target=i386-pc-pxe; + netmodules="pxe"; + prefix="(pxe)/${subdir}/${platform}"; + ext=0 ;; + *) echo Unsupported platform ${platform}; + exit 1;; + esac + + cat << EOF > ${grubdir}/grub.cfg +source ${subdir}/grub.cfg +EOF + + $grub_mkimage ${config_opt} -d "${input_dir}" -O ${mkimage_target} --output=${grubdir}/core.$ext --prefix=$prefix $modules $netmodules || exit 1 + echo "Netboot directory for ${platform} created. Configure your DHCP server to point to ${subdir}/${platform}/core.$ext" +} + +if [ "${override_dir}" = "" ] ; then + if test -e "${pc_dir}" ; then + process_input_dir ${pc_dir} i386-pc + fi +else + process_input_dir ${override_dir} ${target_cpu}-${native_platform} +fi + + +# Bye. +exit 0 diff --git a/util/grub-probe.c b/util/grub-probe.c index f02d98589..9f8a443c8 100644 --- a/util/grub-probe.c +++ b/util/grub-probe.c @@ -226,49 +226,16 @@ probe (const char *path, char *device_name) if (print == PRINT_FS) { - if (path) - { - struct stat st; - - stat (path, &st); - - if (S_ISREG (st.st_mode)) - { - /* Regular file. Verify that we can read it properly. */ - - grub_file_t file; - char *rel_path; - grub_util_info ("reading %s via OS facilities", path); - filebuf_via_sys = grub_util_read_image (path); - - rel_path = grub_make_system_path_relative_to_its_root (path); - grub_path = xasprintf ("(%s)%s", drive_name, rel_path); - free (rel_path); - grub_util_info ("reading %s via GRUB facilities", grub_path); - grub_file_filter_disable_compression (); - file = grub_file_open (grub_path); - if (! file) - grub_util_error ("cannot open %s via GRUB facilities", grub_path); - filebuf_via_grub = xmalloc (file->size); - grub_file_read (file, filebuf_via_grub, file->size); - - grub_util_info ("comparing"); - - if (memcmp (filebuf_via_grub, filebuf_via_sys, file->size)) - grub_util_error ("files differ"); - } - } - printf ("%s\n", fs->name); } - - if (print == PRINT_FS_UUID) + else if (print == PRINT_FS_UUID) { char *uuid; if (! fs->uuid) grub_util_error ("%s does not support UUIDs", fs->name); - fs->uuid (dev, &uuid); + if (fs->uuid (dev, &uuid) != GRUB_ERR_NONE) + grub_util_error ("%s", grub_errmsg); printf ("%s\n", uuid); } @@ -278,7 +245,8 @@ probe (const char *path, char *device_name) if (! fs->label) grub_util_error ("%s does not support labels", fs->name); - fs->label (dev, &label); + if (fs->label (dev, &label) != GRUB_ERR_NONE) + grub_util_error ("%s", grub_errmsg); printf ("%s\n", label); } diff --git a/util/grub-reboot.in b/util/grub-reboot.in index e7a41f68f..929cf5202 100644 --- a/util/grub-reboot.in +++ b/util/grub-reboot.in @@ -29,6 +29,8 @@ self=`basename $0` grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}` rootdir= +bootdir= +grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'` # Usage: usage # Print the usage. @@ -39,8 +41,8 @@ Set the default boot entry for GRUB, for the next boot only. -h, --help print this message and exit -v, --version print the version information and exit - --root-directory=DIR expect GRUB images under the directory DIR - instead of the root directory + --boot-directory=DIR expect GRUB images under the directory DIR/@grubdirname@ + instead of the $grubdir directory ENTRY is a number or a menu item title. @@ -73,11 +75,17 @@ do echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" exit 0 ;; +# Accept for compatibility --root-directory) rootdir=`argument $option "$@"`; shift ;; --root-directory=*) rootdir=`echo "$option" | sed 's/--root-directory=//'` ;; + --boot-directory) + bootdir=`argument $option "$@"`; shift;; + --boot-directory=*) + bootdir=`echo "$option" | sed 's/--boot-directory=//'` ;; + -*) echo "Unrecognized option \`$option'" 1>&2 usage @@ -99,21 +107,17 @@ if test "x$entry" = x; then exit 1 fi -# Initialize these directories here, since ROOTDIR was initialized. -case "$host_os" in -netbsd* | openbsd*) - # Because /boot is used for the boot block in NetBSD and OpenBSD, use /grub - # instead of /boot/grub. - grub_prefix=`echo /grub | sed ${transform}` - bootdir=${rootdir} - ;; -*) - # Use /boot/grub by default. - bootdir=${rootdir}/boot - ;; -esac +if [ -z "$bootdir" ]; then + # Default bootdir if bootdir not initialized. + bootdir=/@bootdirname@ -grubdir=${bootdir}/`echo grub | sed ${transform}` + if [ -n "$rootdir" ] ; then + # Initialize bootdir if rootdir was initialized. + bootdir=${rootdir}/@bootdirname@ + fi +fi + +grubdir=`echo "${bootdir}/@grubdirname@" | sed 's,//*,/,g'` prev_saved_entry=`$grub_editenv ${grubdir}/grubenv list | sed -n 's/^saved_entry=//p'` if [ "$prev_saved_entry" ]; then diff --git a/util/grub-set-default.in b/util/grub-set-default.in index 389c504c7..b09727de2 100644 --- a/util/grub-set-default.in +++ b/util/grub-set-default.in @@ -29,6 +29,8 @@ self=`basename $0` grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}` rootdir= +bootdir= +grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'` # Usage: usage # Print the usage. @@ -39,8 +41,8 @@ Set the default boot entry for GRUB. -h, --help print this message and exit -v, --version print the version information and exit - --root-directory=DIR expect GRUB images under the directory DIR - instead of the root directory + --boot-directory=DIR expect GRUB images under the directory DIR/@grubdirname@ + instead of the $grubdir directory ENTRY is a number or a menu item title. @@ -73,11 +75,17 @@ do echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" exit 0 ;; +# Accept for compatibility --root-directory) rootdir=`argument $option "$@"`; shift ;; --root-directory=*) rootdir=`echo "$option" | sed 's/--root-directory=//'` ;; + --boot-directory) + bootdir=`argument $option "$@"`; shift;; + --boot-directory=*) + bootdir=`echo "$option" | sed 's/--boot-directory=//'` ;; + -*) echo "Unrecognized option \`$option'" 1>&2 usage @@ -99,21 +107,17 @@ if test "x$entry" = x; then exit 1 fi -# Initialize these directories here, since ROOTDIR was initialized. -case "$host_os" in -netbsd* | openbsd*) - # Because /boot is used for the boot block in NetBSD and OpenBSD, use /grub - # instead of /boot/grub. - grub_prefix=`echo /grub | sed ${transform}` - bootdir=${rootdir} - ;; -*) - # Use /boot/grub by default. - bootdir=${rootdir}/boot - ;; -esac +if [ -z "$bootdir" ]; then + # Default bootdir if bootdir not initialized. + bootdir=/@bootdirname@ -grubdir=${bootdir}/`echo grub | sed ${transform}` + if [ -n "$rootdir" ] ; then + # Initialize bootdir if rootdir was initialized. + bootdir=${rootdir}/@bootdirname@ + fi +fi + +grubdir=`echo "${bootdir}/@grubdirname@" | sed 's,//*,/,g'` $grub_editenv ${grubdir}/grubenv unset prev_saved_entry $grub_editenv ${grubdir}/grubenv set saved_entry="$entry" diff --git a/util/i386/pc/grub-setup.c b/util/grub-setup.c similarity index 56% rename from util/i386/pc/grub-setup.c rename to util/grub-setup.c index ff5aeda40..1bf0d958d 100644 --- a/util/i386/pc/grub-setup.c +++ b/util/grub-setup.c @@ -26,8 +26,6 @@ #include #include #include -#include -#include #include #include #include @@ -36,9 +34,9 @@ #include #include #include -#include - -static const grub_gpt_part_type_t grub_gpt_partition_type_bios_boot = GRUB_GPT_PARTITION_TYPE_BIOS_BOOT; +#ifdef GRUB_MACHINE_IEEE1275 +#include +#endif #include #include @@ -48,96 +46,165 @@ static const grub_gpt_part_type_t grub_gpt_partition_type_bios_boot = GRUB_GPT_P #include #include #include +#include #include "progname.h" #define _GNU_SOURCE 1 #include +/* On SPARC this program fills in various fields inside of the 'boot' and 'core' + * image files. + * + * The 'boot' image needs to know the OBP path name of the root + * device. It also needs to know the initial block number of + * 'core' (which is 'diskboot' concatenated with 'kernel' and + * all the modules, this is created by grub-mkimage). This resulting + * 'boot' image is 512 bytes in size and is placed in the second block + * of a partition. + * + * The initial 'diskboot' block acts as a loader for the actual GRUB + * kernel. It contains the loading code and then a block list. + * + * The block list of 'core' starts at the end of the 'diskboot' image + * and works it's way backwards towards the end of the code of 'diskboot'. + * + * We patch up the images with the necessary values and write out the + * result. + */ + #define DEFAULT_BOOT_FILE "boot.img" #define DEFAULT_CORE_FILE "core.img" +#ifdef GRUB_MACHINE_SPARC64 +#define grub_target_to_host16(x) grub_be_to_cpu16(x) +#define grub_target_to_host32(x) grub_be_to_cpu32(x) +#define grub_target_to_host64(x) grub_be_to_cpu64(x) +#define grub_host_to_target16(x) grub_cpu_to_be16(x) +#define grub_host_to_target32(x) grub_cpu_to_be32(x) +#define grub_host_to_target64(x) grub_cpu_to_be64(x) +#elif defined (GRUB_MACHINE_PCBIOS) #define grub_target_to_host16(x) grub_le_to_cpu16(x) #define grub_target_to_host32(x) grub_le_to_cpu32(x) #define grub_target_to_host64(x) grub_le_to_cpu64(x) #define grub_host_to_target16(x) grub_cpu_to_le16(x) #define grub_host_to_target32(x) grub_cpu_to_le32(x) #define grub_host_to_target64(x) grub_cpu_to_le64(x) +#else +#error Complete this +#endif + +static void +write_rootdev (char *core_img, grub_device_t root_dev, + char *boot_img, grub_uint64_t first_sector) +{ +#ifdef GRUB_MACHINE_PCBIOS + { + grub_int32_t *install_dos_part, *install_bsd_part; + grub_int32_t dos_part, bsd_part; + grub_uint8_t *boot_drive; + grub_disk_addr_t *kernel_sector; + boot_drive = (grub_uint8_t *) (boot_img + GRUB_BOOT_MACHINE_BOOT_DRIVE); + kernel_sector = (grub_disk_addr_t *) (boot_img + + GRUB_BOOT_MACHINE_KERNEL_SECTOR); + + + install_dos_part = (grub_int32_t *) (core_img + GRUB_DISK_SECTOR_SIZE + + GRUB_KERNEL_MACHINE_INSTALL_DOS_PART); + install_bsd_part = (grub_int32_t *) (core_img + GRUB_DISK_SECTOR_SIZE + + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART); + + /* If we hardcoded drive as part of prefix, we don't want to + override the current setting. */ + if (*install_dos_part != -2) + { + /* Embed information about the installed location. */ + if (root_dev->disk->partition) + { + if (root_dev->disk->partition->parent) + { + if (root_dev->disk->partition->parent->parent) + grub_util_error ("Installing on doubly nested partitions is " + "not supported"); + dos_part = root_dev->disk->partition->parent->number; + bsd_part = root_dev->disk->partition->number; + } + else + { + dos_part = root_dev->disk->partition->number; + bsd_part = -1; + } + } + else + dos_part = bsd_part = -1; + } + else + { + dos_part = grub_le_to_cpu32 (*install_dos_part); + bsd_part = grub_le_to_cpu32 (*install_bsd_part); + } + + grub_util_info ("dos partition is %d, bsd partition is %d", + dos_part, bsd_part); + + *install_dos_part = grub_cpu_to_le32 (dos_part); + *install_bsd_part = grub_cpu_to_le32 (bsd_part); + + /* FIXME: can this be skipped? */ + *boot_drive = 0xFF; + + *kernel_sector = grub_cpu_to_le64 (first_sector); + } +#endif +#ifdef GRUB_MACHINE_IEEE1275 + { + grub_disk_addr_t *kernel_byte; + kernel_byte = (grub_disk_addr_t *) (boot_img + + GRUB_BOOT_AOUT_HEADER_SIZE + + GRUB_BOOT_MACHINE_KERNEL_BYTE); + *kernel_byte = grub_cpu_to_be64 (first_sector << GRUB_DISK_SECTOR_BITS); + } +#endif +} + +#ifdef GRUB_MACHINE_IEEE1275 +#define BOOT_SECTOR 1 +#else +#define BOOT_SECTOR 0 +#endif static void setup (const char *dir, const char *boot_file, const char *core_file, - const char *root, const char *dest, int must_embed, int force, int fs_probe) + const char *root, const char *dest, int must_embed, int force, + int fs_probe) { char *boot_path, *core_path, *core_path_dev, *core_path_dev_full; char *boot_img, *core_img; size_t boot_size, core_size; grub_uint16_t core_sectors; grub_device_t root_dev, dest_dev; - const char *dest_partmap; - int multiple_partmaps; - grub_uint8_t *boot_drive; - grub_disk_addr_t *kernel_sector; - grub_uint16_t *boot_drive_check; struct grub_boot_blocklist *first_block, *block; - grub_int32_t *install_dos_part, *install_bsd_part; - grub_int32_t dos_part, bsd_part; - char *install_prefix; - char *prefix = NULL; char *tmp_img; int i; grub_disk_addr_t first_sector; +#ifdef GRUB_MACHINE_PCBIOS grub_uint16_t current_segment = GRUB_BOOT_MACHINE_KERNEL_SEG + (GRUB_DISK_SECTOR_SIZE >> 4); +#endif grub_uint16_t last_length = GRUB_DISK_SECTOR_SIZE; grub_file_t file; FILE *fp; - struct { grub_uint64_t start; grub_uint64_t end; } embed_region; - embed_region.start = embed_region.end = ~0UL; - auto void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, unsigned offset, - unsigned length); - auto void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, unsigned offset, - unsigned length); + auto void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, + unsigned offset, + unsigned length); + auto void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, + unsigned offset, + unsigned length); - auto int NESTED_FUNC_ATTR find_usable_region_msdos (grub_disk_t disk, - const grub_partition_t p); - int NESTED_FUNC_ATTR find_usable_region_msdos (grub_disk_t disk __attribute__ ((unused)), - const grub_partition_t p) - { - /* There's always an embed region, and it starts right after the MBR. */ - embed_region.start = 1; - - if (embed_region.end > grub_partition_get_start (p)) - embed_region.end = grub_partition_get_start (p); - - return 0; - } - - auto int NESTED_FUNC_ATTR find_usable_region_gpt (grub_disk_t disk, - const grub_partition_t p); - int NESTED_FUNC_ATTR find_usable_region_gpt (grub_disk_t disk __attribute__ ((unused)), - const grub_partition_t p) - { - struct grub_gpt_partentry gptdata; - - disk->partition = p->parent; - if (grub_disk_read (disk, p->offset, p->index, - sizeof (gptdata), &gptdata)) - return 0; - - /* If there's an embed region, it is in a dedicated partition. */ - if (! memcmp (&gptdata.type, &grub_gpt_partition_type_bios_boot, 16)) - { - embed_region.start = grub_partition_get_start (p); - embed_region.end = grub_partition_get_start (p) + grub_partition_get_len (p); - - return 1; - } - return 0; - } - - void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, unsigned offset, - unsigned length) + void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, + unsigned offset, + unsigned length) { grub_util_info ("the first sector is <%llu,%u,%u>", sector, offset, length); @@ -148,26 +215,28 @@ setup (const char *dir, first_sector = sector; } - void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, unsigned offset, - unsigned length) + void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, + unsigned offset, + unsigned length) { struct grub_boot_blocklist *prev = block + 1; - grub_util_info ("saving <%llu,%u,%u> with the segment 0x%x", - sector, offset, length, (unsigned) current_segment); + grub_util_info ("saving <%llu,%u,%u>", sector, offset, length); if (offset != 0 || last_length != GRUB_DISK_SECTOR_SIZE) grub_util_error (_("non-sector-aligned data is found in the core file")); if (block != first_block - && (grub_le_to_cpu64 (prev->start) - + grub_le_to_cpu16 (prev->len)) == sector) - prev->len = grub_cpu_to_le16 (grub_le_to_cpu16 (prev->len) + 1); + && (grub_target_to_host64 (prev->start) + + grub_target_to_host16 (prev->len)) == sector) + prev->len = grub_host_to_target16 (grub_target_to_host16 (prev->len) + 1); else { - block->start = grub_cpu_to_le64 (sector); - block->len = grub_cpu_to_le16 (1); - block->segment = grub_cpu_to_le16 (current_segment); + block->start = grub_host_to_target64 (sector); + block->len = grub_host_to_target16 (1); +#ifdef GRUB_MACHINE_PCBIOS + block->segment = grub_host_to_target16 (current_segment); +#endif block--; if (block->len) @@ -175,7 +244,9 @@ setup (const char *dir, } last_length = length; +#ifdef GRUB_MACHINE_PCBIOS current_segment += GRUB_DISK_SECTOR_SIZE >> 4; +#endif } /* Read the boot image by the OS service. */ @@ -187,21 +258,16 @@ setup (const char *dir, boot_img = grub_util_read_image (boot_path); free (boot_path); - /* Set the addresses of variables in the boot image. */ - boot_drive = (grub_uint8_t *) (boot_img + GRUB_BOOT_MACHINE_BOOT_DRIVE); - kernel_sector = (grub_disk_addr_t *) (boot_img - + GRUB_BOOT_MACHINE_KERNEL_SECTOR); - boot_drive_check = (grub_uint16_t *) (boot_img - + GRUB_BOOT_MACHINE_DRIVE_CHECK); - core_path = grub_util_get_path (dir, core_file); core_size = grub_util_get_image_size (core_path); core_sectors = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS); if (core_size < GRUB_DISK_SECTOR_SIZE) grub_util_error (_("the size of `%s' is too small"), core_path); - else if (core_size > 0xFFFF * GRUB_DISK_SECTOR_SIZE) +#ifdef GRUB_MACHINE_PCBIOS + if (core_size > 0xFFFF * GRUB_DISK_SECTOR_SIZE) grub_util_error (_("the size of `%s' is too large"), core_path); +#endif core_img = grub_util_read_image (core_path); @@ -209,19 +275,15 @@ setup (const char *dir, first_block = (struct grub_boot_blocklist *) (core_img + GRUB_DISK_SECTOR_SIZE - sizeof (*block)); - - install_dos_part = (grub_int32_t *) (core_img + GRUB_DISK_SECTOR_SIZE - + GRUB_KERNEL_MACHINE_INSTALL_DOS_PART); - install_bsd_part = (grub_int32_t *) (core_img + GRUB_DISK_SECTOR_SIZE - + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART); - install_prefix = (char *) (core_img + GRUB_DISK_SECTOR_SIZE + - GRUB_KERNEL_MACHINE_PREFIX); + 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); @@ -230,197 +292,171 @@ setup (const char *dir, if (grub_env_set ("root", root) != GRUB_ERR_NONE) grub_util_error ("%s", grub_errmsg); +#ifdef GRUB_MACHINE_PCBIOS /* Read the original sector from the disk. */ tmp_img = xmalloc (GRUB_DISK_SECTOR_SIZE); if (grub_disk_read (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, tmp_img)) grub_util_error ("%s", grub_errmsg); +#endif - if (dest_dev->disk->partition && fs_probe) +#ifdef GRUB_MACHINE_PCBIOS + { + grub_uint16_t *boot_drive_check; + boot_drive_check = (grub_uint16_t *) (boot_img + + GRUB_BOOT_MACHINE_DRIVE_CHECK); + /* Copy the possible DOS BPB. */ + memcpy (boot_img + GRUB_BOOT_MACHINE_BPB_START, + tmp_img + GRUB_BOOT_MACHINE_BPB_START, + GRUB_BOOT_MACHINE_BPB_END - GRUB_BOOT_MACHINE_BPB_START); + + /* If DEST_DRIVE is a hard disk, enable the workaround, which is + for buggy BIOSes which don't pass boot drive correctly. Instead, + they pass 0x00 or 0x01 even when booted from 0x80. */ + if (!grub_util_biosdisk_is_floppy (dest_dev->disk)) + /* Replace the jmp (2 bytes) with double nop's. */ + *boot_drive_check = 0x9090; + } +#endif + + /* Clean out the blocklists. */ + block = first_block; + while (block->len) { - grub_fs_t fs; - fs = grub_fs_probe (dest_dev); - if (! fs) - grub_util_error (_("unable to identify a filesystem in %s; safety check can't be performed"), - dest_dev->disk->name); + grub_memset (block, 0, sizeof (block)); - if (! fs->reserved_first_sector) - grub_util_error (_("%s appears to contain a %s filesystem which isn't known to " - "reserve space for DOS-style boot. Installing GRUB there could " - "result in FILESYSTEM DESTRUCTION if valuable data is overwritten " - "by grub-setup (--skip-fs-probe disables this " - "check, use at your own risk)"), dest_dev->disk->name, fs->name); + block--; + + if ((char *) block <= core_img) + grub_util_error ("No terminator in the core image"); } - /* Copy the possible DOS BPB. */ - memcpy (boot_img + GRUB_BOOT_MACHINE_BPB_START, - tmp_img + GRUB_BOOT_MACHINE_BPB_START, - GRUB_BOOT_MACHINE_BPB_END - GRUB_BOOT_MACHINE_BPB_START); +#ifdef GRUB_MACHINE_PCBIOS + { + grub_partition_map_t dest_partmap = NULL; + grub_partition_t container = dest_dev->disk->partition; + int multiple_partmaps = 0; + grub_err_t err; + grub_disk_addr_t sectors[core_sectors]; + int i; + grub_fs_t fs; - /* Copy the possible partition table. */ - if (dest_dev->disk->has_partitions) - memcpy (boot_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC, - tmp_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC, - GRUB_BOOT_MACHINE_PART_END - GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC); - - free (tmp_img); - - /* If DEST_DRIVE is a hard disk, enable the workaround, which is - for buggy BIOSes which don't pass boot drive correctly. Instead, - they pass 0x00 or 0x01 even when booted from 0x80. */ - if (dest_dev->disk->id & 0x80) - /* Replace the jmp (2 bytes) with double nop's. */ - *boot_drive_check = 0x9090; - - /* If we hardcoded drive as part of prefix, we don't want to - override the current setting. */ - if (*install_dos_part != -2) + /* Unlike root_dev, with dest_dev we're interested in the partition map even + if dest_dev itself is a whole disk. */ + auto int NESTED_FUNC_ATTR identify_partmap (grub_disk_t disk, + const grub_partition_t p); + int NESTED_FUNC_ATTR identify_partmap (grub_disk_t disk __attribute__ ((unused)), + const grub_partition_t p) { - /* Embed information about the installed location. */ - if (root_dev->disk->partition) - { - if (root_dev->disk->partition->parent) - { - if (root_dev->disk->partition->parent->parent) - grub_util_error ("Installing on doubly nested partitions is " - "not supported"); - dos_part = root_dev->disk->partition->parent->number; - bsd_part = root_dev->disk->partition->number; - } - else - { - dos_part = root_dev->disk->partition->number; - bsd_part = -1; - } - - if (install_prefix[0] != '(') - { - char *root_part_name; - - root_part_name = - grub_partition_get_name (root_dev->disk->partition); - prefix = xasprintf ("(,%s)%s", root_part_name, install_prefix); - free (root_part_name); - } - } - else - dos_part = bsd_part = -1; - } - else - { - dos_part = grub_le_to_cpu32 (*install_dos_part); - bsd_part = grub_le_to_cpu32 (*install_bsd_part); - } - - grub_util_info ("dos partition is %d, bsd partition is %d", - dos_part, bsd_part); - - if (! dest_dev->disk->has_partitions) - { - grub_util_warn (_("Attempting to install GRUB to a partitionless disk. This is a BAD idea.")); - goto unable_to_embed; - } - - if (dest_dev->disk->partition) - { - grub_util_warn (_("Attempting to install GRUB to a partition instead of the MBR. This is a BAD idea.")); - goto unable_to_embed; - } - - /* Unlike root_dev, with dest_dev we're interested in the partition map even - if dest_dev itself is a whole disk. */ - auto int NESTED_FUNC_ATTR identify_partmap (grub_disk_t disk, - const grub_partition_t p); - int NESTED_FUNC_ATTR identify_partmap (grub_disk_t disk __attribute__ ((unused)), - const grub_partition_t p) - { - if (p->parent) + if (p->parent != container) return 0; if (dest_partmap == NULL) - dest_partmap = p->partmap->name; - else if (strcmp (dest_partmap, p->partmap->name) != 0) { - multiple_partmaps = 1; - return 1; + dest_partmap = p->partmap; + return 0; } - return 0; - } - dest_partmap = 0; - multiple_partmaps = 0; - grub_partition_iterate (dest_dev->disk, identify_partmap); - - if (! dest_partmap) - { - grub_util_warn (_("Attempting to install GRUB to a partitionless disk. This is a BAD idea.")); - goto unable_to_embed; - } - if (multiple_partmaps) - { - grub_util_warn (_("Attempting to install GRUB to a disk with multiple partition labels. This is not supported yet.")); - goto unable_to_embed; + if (dest_partmap == p->partmap) + return 0; + multiple_partmaps = 1; + return 1; } - if (strcmp (dest_partmap, "msdos") == 0) - grub_partition_iterate (dest_dev->disk, find_usable_region_msdos); - else if (strcmp (dest_partmap, "gpt") == 0) - grub_partition_iterate (dest_dev->disk, find_usable_region_gpt); - else - grub_util_error (_("No DOS-style partitions found")); + grub_partition_iterate (dest_dev->disk, identify_partmap); - if (embed_region.end <= embed_region.start) - { - if (! strcmp (dest_partmap, "msdos")) - grub_util_warn (_("This msdos-style partition label has no post-MBR gap; embedding won't be possible!")); - else - grub_util_warn (_("This GPT partition label has no BIOS Boot Partition; embedding won't be possible!")); - goto unable_to_embed; - } + fs = grub_fs_probe (dest_dev); + if (!fs) + grub_errno = GRUB_ERR_NONE; - if ((unsigned long) core_sectors > embed_region.end - embed_region.start) - { - if (core_sectors > 62) - grub_util_warn (_("Your core.img is unusually large. It won't fit in the embedding area.")); - else /* embed_region.end - embed_region.start < 62 */ - grub_util_warn (_("Your embedding area is unusually small. core.img won't fit in it.")); - goto unable_to_embed; - } +#ifdef GRUB_MACHINE_PCBIOS + if (fs_probe) + { + if (!fs && !dest_partmap) + grub_util_error (_("unable to identify a filesystem in %s; safety check can't be performed"), + dest_dev->disk->name); + if (fs && !fs->reserved_first_sector) + grub_util_error (_("%s appears to contain a %s filesystem which isn't known to " + "reserve space for DOS-style boot. Installing GRUB there could " + "result in FILESYSTEM DESTRUCTION if valuable data is overwritten " + "by grub-setup (--skip-fs-probe disables this " + "check, use at your own risk)"), dest_dev->disk->name, fs->name); + if (dest_partmap && strcmp (dest_partmap->name, "msdos") != 0 + && strcmp (dest_partmap->name, "gpt") != 0 + && strcmp (dest_partmap->name, "bsd") != 0 + && strcmp (dest_partmap->name, "netbsd") != 0 + && strcmp (dest_partmap->name, "openbsd") != 0 + && strcmp (dest_partmap->name, "sunpc") != 0) + grub_util_error (_("%s appears to contain a %s partition map which isn't known to " + "reserve space for DOS-style boot. Installing GRUB there could " + "result in FILESYSTEM DESTRUCTION if valuable data is overwritten " + "by grub-setup (--skip-fs-probe disables this " + "check, use at your own risk)"), dest_dev->disk->name, dest_partmap->name); + } +#endif - grub_util_info ("the core image will be embedded at sector 0x%llx", embed_region.start); + if (! dest_partmap) + { + grub_util_warn (_("Attempting to install GRUB to a partitionless disk. This is a BAD idea.")); + goto unable_to_embed; + } + if (multiple_partmaps || fs) + { + grub_util_warn (_("Attempting to install GRUB to a disk with multiple partition labels or both partition label and filesystem. This is not supported yet.")); + goto unable_to_embed; + } - *install_dos_part = grub_cpu_to_le32 (dos_part); - *install_bsd_part = grub_cpu_to_le32 (bsd_part); - if (prefix) - strcpy (install_prefix, prefix); + /* Copy the partition table. */ + if (dest_partmap) + memcpy (boot_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC, + tmp_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC, + GRUB_BOOT_MACHINE_PART_END - GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC); - /* The first blocklist contains the whole sectors. */ - first_block->start = grub_cpu_to_le64 (embed_region.start + 1); + free (tmp_img); + + if (!dest_partmap->embed) + { + grub_util_warn ("Partition style '%s' doesn't support embeding", + dest_partmap->name); + goto unable_to_embed; + } - /* These are filled elsewhere. Verify them just in case. */ - assert (first_block->len == grub_host_to_target16 (core_sectors - 1)); - assert (first_block->segment == grub_host_to_target16 (GRUB_BOOT_MACHINE_KERNEL_SEG - + (GRUB_DISK_SECTOR_SIZE >> 4))); + err = dest_partmap->embed (dest_dev->disk, core_sectors, + GRUB_EMBED_PCBIOS, sectors); + + if (err) + { + grub_util_warn ("%s", grub_errmsg); + grub_errno = GRUB_ERR_NONE; + goto unable_to_embed; + } - /* Make sure that the second blocklist is a terminator. */ - block = first_block - 1; - block->start = 0; - block->len = 0; - block->segment = 0; + save_first_sector (sectors[0] + grub_partition_get_start (container), + 0, GRUB_DISK_SECTOR_SIZE); - /* Write the core image onto the disk. */ - if (grub_disk_write (dest_dev->disk, embed_region.start, 0, core_size, core_img)) - grub_util_error ("%s", grub_errmsg); + block = first_block; + for (i = 1; i < core_sectors; i++) + save_blocklists (sectors[i] + grub_partition_get_start (container), + 0, GRUB_DISK_SECTOR_SIZE); - /* FIXME: can this be skipped? */ - *boot_drive = 0xFF; + write_rootdev (core_img, root_dev, boot_img, first_sector); - *kernel_sector = grub_cpu_to_le64 (embed_region.start); + /* Make sure that the second blocklist is a terminator. */ + block = first_block - 1; + block->start = 0; + block->len = 0; + block->segment = 0; - /* Write the boot image onto the disk. */ - if (grub_disk_write (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, - boot_img)) - grub_util_error ("%s", grub_errmsg); + /* Write the core image onto the disk. */ + for (i = 0; i < core_sectors; i++) + grub_disk_write (dest_dev->disk, sectors[i], 0, + (core_size - i * GRUB_DISK_SECTOR_SIZE + < GRUB_DISK_SECTOR_SIZE) ? core_size + - i * GRUB_DISK_SECTOR_SIZE + : GRUB_DISK_SECTOR_SIZE, + core_img + i * GRUB_DISK_SECTOR_SIZE); - goto finish; + goto finish; + } +#endif unable_to_embed: @@ -434,6 +470,9 @@ unable_to_embed: if (! force) grub_util_error (_("if you really want blocklists, use --force")); + /* The core image must be put on a filesystem unfortunately. */ + grub_util_info ("will leave the core image on the filesystem"); + /* Make sure that GRUB reads the identical image as the OS. */ tmp_img = xmalloc (core_size); core_path_dev_full = grub_util_get_path (dir, core_file); @@ -516,7 +555,9 @@ unable_to_embed: { block->start = 0; block->len = 0; +#ifdef GRUB_MACHINE_PCBIOS block->segment = 0; +#endif block--; @@ -541,20 +582,39 @@ unable_to_embed: != (grub_ssize_t) core_size - GRUB_DISK_SECTOR_SIZE) grub_util_error (_("failed to read the rest sectors of the core image")); +#ifdef GRUB_MACHINE_IEEE1275 + { + char *boot_devpath; + boot_devpath = (char *) (boot_img + + GRUB_BOOT_AOUT_HEADER_SIZE + + GRUB_BOOT_MACHINE_BOOT_DEVPATH); + if (file->device->disk->id != dest_dev->disk->id) + { + const char *dest_ofpath; + dest_ofpath + = grub_util_devname_to_ofpath (grub_util_biosdisk_get_osdev (file->device->disk)); + grub_util_info ("dest_ofpath is `%s'", dest_ofpath); + strncpy (boot_devpath, dest_ofpath, GRUB_BOOT_MACHINE_BOOT_DEVPATH_END + - GRUB_BOOT_MACHINE_BOOT_DEVPATH - 1); + boot_devpath[GRUB_BOOT_MACHINE_BOOT_DEVPATH_END + - GRUB_BOOT_MACHINE_BOOT_DEVPATH - 1] = 0; + } + else + { + grub_util_info ("non cross-disk install"); + memset (boot_devpath, 0, GRUB_BOOT_MACHINE_BOOT_DEVPATH_END + - GRUB_BOOT_MACHINE_BOOT_DEVPATH); + } + grub_util_info ("boot device path %s", boot_devpath); + } +#endif + grub_file_close (file); free (core_path_dev); free (tmp_img); - *kernel_sector = grub_cpu_to_le64 (first_sector); - - /* FIXME: can this be skipped? */ - *boot_drive = 0xFF; - - *install_dos_part = grub_cpu_to_le32 (dos_part); - *install_bsd_part = grub_cpu_to_le32 (bsd_part); - if (prefix) - strcpy (install_prefix, prefix); + write_rootdev (core_img, root_dev, boot_img, first_sector); /* Write the first two sectors of the core image onto the disk. */ grub_util_info ("opening the core image `%s'", core_path); @@ -565,16 +625,17 @@ unable_to_embed: grub_util_write_image (core_img, GRUB_DISK_SECTOR_SIZE * 2, fp); fclose (fp); + finish: + /* Write the boot image onto the disk. */ - if (grub_disk_write (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, boot_img)) + if (grub_disk_write (dest_dev->disk, BOOT_SECTOR, + 0, GRUB_DISK_SECTOR_SIZE, boot_img)) grub_util_error ("%s", grub_errmsg); - finish: /* Sync is a Good Thing. */ sync (); - free (prefix); free (core_path); free (core_img); free (boot_img); @@ -646,14 +707,18 @@ get_device_name (char *dev) int main (int argc, char *argv[]) { - char *boot_file = 0; - char *core_file = 0; - char *dir = 0; - char *dev_map = 0; - char *root_dev = 0; - char *dest_dev; + char *boot_file = NULL; + char *core_file = NULL; + char *dir = NULL; + char *dev_map = NULL; + char *root_dev = NULL; + char *dest_dev = NULL; int must_embed = 0, force = 0, fs_probe = 1; +#ifdef GRUB_MACHINE_IEEE1275 + force = 1; +#endif + set_program_name (argv[0]); grub_util_init_nls (); @@ -768,10 +833,15 @@ main (int argc, char *argv[]) fprintf (stderr, _("Invalid device `%s'.\n"), argv[optind]); usage (1); } + grub_util_info ("transformed OS device `%s' into GRUB device `%s'", + argv[optind], dest_dev); } else - /* For simplicity. */ - dest_dev = xstrdup (dest_dev); + { + /* For simplicity. */ + dest_dev = xstrdup (dest_dev); + grub_util_info ("Using `%s' as GRUB device", dest_dev); + } if (root_dev) { @@ -786,13 +856,18 @@ main (int argc, char *argv[]) } else { - root_dev = grub_util_get_grub_dev (grub_guess_root_device (dir ? : DEFAULT_DIRECTORY)); + char *root_device = grub_guess_root_device (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, + dir ? : DEFAULT_DIRECTORY); } #ifdef __linux__ @@ -824,7 +899,7 @@ main (int argc, char *argv[]) } else #endif - /* Do the real work. */ + /* Do the real work. */ setup (dir ? : DEFAULT_DIRECTORY, boot_file ? : DEFAULT_BOOT_FILE, core_file ? : DEFAULT_CORE_FILE, diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in index 2f39650e9..9ed3fc3a1 100644 --- a/util/grub.d/00_header.in +++ b/util/grub.d/00_header.in @@ -247,6 +247,12 @@ else make_timeout "${GRUB_HIDDEN_TIMEOUT}" "${GRUB_TIMEOUT}" fi +if [ "x$GRUB_BUTTON_CMOS_ADDRESS" != "x" ] && [ "x$GRUB_BUTTON_CMOS_CLEAN" = "xyes" ]; then + cat <. - -# Initialize some variables. -transform="@program_transform_name@" - -prefix=@prefix@ -exec_prefix=@exec_prefix@ -sbindir=@sbindir@ -bindir=@bindir@ -libdir=@libdir@ -PACKAGE_NAME=@PACKAGE_NAME@ -PACKAGE_TARNAME=@PACKAGE_TARNAME@ -PACKAGE_VERSION=@PACKAGE_VERSION@ -target_cpu=@target_cpu@ -platform=@platform@ -host_os=@host_os@ -pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}` -localedir=@datadir@/locale - -self=`basename $0` - -grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` -grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}` -grub_probe=${sbindir}/`echo grub-probe | sed ${transform}` -grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}` -rootdir= -grub_prefix=`echo /boot/grub | sed ${transform}` -modules= - -no_floppy= -force_lba= -recheck=no -debug=no - -# Usage: usage -# Print the usage. -usage () { - cat <. -EOF -} - -argument () { - opt=$1 - shift - - if test $# -eq 0; then - echo "$0: option requires an argument -- '$opt'" 1>&2 - exit 1 - fi - echo $1 -} - -# Check the arguments. -while test $# -gt 0 -do - option=$1 - shift - - case "$option" in - -h | --help) - usage - exit 0 ;; - -v | --version) - echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" - exit 0 ;; - - --modules) - modules=`argument $option "$@"`; shift ;; - --modules=*) - modules=`echo "$option" | sed 's/--modules=//'` ;; - - --root-directory) - rootdir=`argument $option "$@"`; shift ;; - --root-directory=*) - rootdir=`echo "$option" | sed 's/--root-directory=//'` ;; - - --grub-mkimage) - grub_mkimage=`argument $option "$@"`; shift ;; - --grub-mkimage=*) - grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;; - - --grub-mkdevicemap) - grub_mkdevicemap=`argument $option "$@"`; shift ;; - --grub-mkdevicemap=*) - grub_mkdevicemap=`echo "$option" | sed 's/--grub-mkdevicemap=//'` ;; - - --grub-probe) - grub_probe=`argument $option "$@"`; shift ;; - --grub-probe=*) - grub_probe=`echo "$option" | sed 's/--grub-probe=//'` ;; - - --no-floppy) - no_floppy="--no-floppy" ;; - --recheck) - recheck=yes ;; - # This is an undocumented feature... - --debug) - debug=yes ;; - *) - echo "Unrecognized option \`$option'" 1>&2 - usage - exit 1 - ;; - esac -done - -# If the debugging feature is enabled, print commands. -if test $debug = yes; then - set -x -fi - -# Initialize these directories here, since ROOTDIR was initialized. -case "$host_os" in -netbsd* | openbsd*) - # Because /boot is used for the boot block in NetBSD and OpenBSD, use /grub - # instead of /boot/grub. - grub_prefix=`echo /grub | sed ${transform}` - bootdir=${rootdir} - ;; -*) - # Use /boot/grub by default. - bootdir=${rootdir}/boot - ;; -esac - -grubdir=${bootdir}/`echo grub | sed ${transform}` -device_map=${grubdir}/device.map - -# Check if GRUB is installed. -set $grub_mkimage dummy -if test -f "$1"; then - : -else - echo "$1: Not found." 1>&2 - exit 1 -fi - -set $grub_mkdevicemap dummy -if test -f "$1"; then - : -else - echo "$1: Not found." 1>&2 - exit 1 -fi - -# Create the GRUB directory if it is not present. -mkdir -p "$grubdir" || exit 1 - -# If --recheck is specified, remove the device map, if present. -if test $recheck = yes; then - rm -f $device_map -fi - -# Create the device map file if it is not present. -if test -f "$device_map"; then - : -else - # Create a safe temporary file. - test -n "$mklog" && log_file=`$mklog` - - $grub_mkdevicemap --device-map=$device_map $no_floppy || exit 1 -fi - -# Make sure that there is no duplicated entry. -tmp=`sed -n '/^([fh]d[0-9]*)/s/\(^(.*)\).*/\1/p' $device_map \ - | sort | uniq -d | sed -n 1p` -if test -n "$tmp"; then - echo "The drive $tmp is defined multiple times in the device map $device_map" 1>&2 - exit 1 -fi - -# Copy the GRUB images to the GRUB directory. -for file in ${grubdir}/*.mod ${grubdir}/*.lst; do - if test -f $file && [ "`basename $file`" != menu.lst ]; then - rm -f $file || exit 1 - fi -done -for file in ${pkglibdir}/*.mod ${pkglibdir}/*.lst; do - cp -f $file ${grubdir} || exit 1 -done - -# Copy gettext files -mkdir -p ${grubdir}/locale/ -for dir in ${localedir}/*; do - if test -f "$dir/LC_MESSAGES/grub.mo"; then - cp -f "$dir/LC_MESSAGES/grub.mo" "${grubdir}/locale/${dir##*/}.mo" - fi -done - -if ! test -f ${grubdir}/grubenv; then - $grub_editenv ${grubdir}/grubenv create -fi - -# Create the core image. First, auto-detect the filesystem module. -fs_module=`$grub_probe --target=fs --device-map=${device_map} ${grubdir}` -if test "x$fs_module" = xfat; then :; else - echo "${grubdir} doesn't look like an EFI partition." 1>&2 - exit 1 -fi - -# Then the partition map module. In order to support partition-less media, -# this command is allowed to fail (--target=fs already grants us that the -# filesystem will be accessible). -partmap_module= -for x in `$grub_probe --target=partmap --device-map=${device_map} ${grubdir} 2> /dev/null`; do - partmap_module="$partmap_module part_$x"; -done - -# Device abstraction module, if any (lvm, raid). -devabstraction_module=`$grub_probe --target=abstraction --device-map=${device_map} ${grubdir}` - -# The order in this list is critical. Be careful when modifying it. -modules="$modules $fs_module $partmap_module $devabstraction_module" - -$grub_mkimage -p "" -O ${target_cpu}-efi --output=${grubdir}/grub.efi $modules || exit 1 - -# Prompt the user to check if the device map is correct. -echo "Installation finished. No error reported." -echo "This is the contents of the device map $device_map." -echo "Check if this is correct or not. If any of the lines is incorrect," -echo "fix it and re-run the script \`$self'." -echo - -cat $device_map - -# Bye. -exit 0 diff --git a/util/ieee1275/grub-install.in b/util/ieee1275/grub-install.in deleted file mode 100644 index 98de5f348..000000000 --- a/util/ieee1275/grub-install.in +++ /dev/null @@ -1,273 +0,0 @@ -#! /bin/sh - -# Install GRUB on your drive. -# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008 Free Software Foundation, Inc. -# -# GRUB is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# GRUB is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GRUB. If not, see . - -# This script uses `ofpathname', which is downloadable from -# http://ppc64-utils.ozlabs.org . - -# Initialize some variables. -transform="@program_transform_name@" - -prefix=@prefix@ -exec_prefix=@exec_prefix@ -sbindir=@sbindir@ -bindir=@bindir@ -libdir=@libdir@ -PACKAGE_NAME=@PACKAGE_NAME@ -PACKAGE_TARNAME=@PACKAGE_TARNAME@ -PACKAGE_VERSION=@PACKAGE_VERSION@ -target_cpu=@target_cpu@ -platform=@platform@ -pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}` - -self=`basename $0` - -grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` -grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}` -grub_probe=${sbindir}/`echo grub-probe | sed ${transform}` -grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}` -rootdir= -grub_prefix=`echo /boot/grub | sed ${transform}` -modules= - -install_device= -debug=no -update_nvram=yes - -ofpathname=`which ofpathname` -nvsetenv=`which nvsetenv` - -# Usage: usage -# Print the usage. -usage () { - cat <. -EOF -} - -argument () { - opt=$1 - shift - - if test $# -eq 0; then - echo "$0: option requires an argument -- '$opt'" 1>&2 - exit 1 - fi - echo $1 -} - -# Check the arguments. -while test $# -gt 0 -do - option=$1 - shift - - case "$option" in - -h | --help) - usage - exit 0 ;; - -v | --version) - echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" - exit 0 ;; - - --modules) - modules=`argument $option "$@"`; shift ;; - --modules=*) - modules=`echo "$option" | sed 's/--modules=//'` ;; - - --root-directory) - rootdir=`argument $option "$@"`; shift ;; - --root-directory=*) - rootdir=`echo "$option" | sed 's/--root-directory=//'` ;; - - --grub-mkdevicemap) - grub_mkdevicemap=`argument $option "$@"`; shift ;; - --grub-mkdevicemap=*) - grub_mkdevicemap=`echo "$option" | sed 's/--grub-mkdevicemap=//'` ;; - - --grub-mkimage) - grub_mkimage=`argument $option "$@"`; shift ;; - --grub-mkimage=*) - grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;; - - --grub-probe) - grub_probe=`argument $option "$@"`; shift ;; - --grub-probe=*) - grub_probe=`echo "$option" | sed 's/--grub-probe=//'` ;; - - --no-nvram) - update_nvram=no ;; - # This is an undocumented feature... - --debug) - debug=yes ;; - -*) - echo "Unrecognized option \`$option'" 1>&2 - usage - exit 1 - ;; - *) - if test "x$install_device" != x; then - echo "More than one install_devices?" 1>&2 - usage - exit 1 - fi - install_device="${option}" ;; - esac -done - -# If the debugging feature is enabled, print commands. -if test $debug = yes; then - set -x -fi - -# Initialize these directories here, since ROOTDIR was initialized. -bootdir=${rootdir}/boot -grubdir=${bootdir}/`echo grub | sed ${transform}` -device_map=${grubdir}/device.map - -set $grub_mkimage dummy -if test -f "$1"; then - : -else - echo "$1: Not found." 1>&2 - exit 1 -fi - -# Find the partition at the right mount point. -install_device=`$grub_mkdevicemap --device-map=/dev/stdout | $grub_probe --target=device --device-map=/dev/stdin ${grubdir}` - -if test "x$install_device" = "x`$grub_mkdevicemap --device-map=/dev/stdout | $grub_probe --target=device --device-map=/dev/stdin ${bootdir}`"; then - echo "$grubdir must be a mount point." - exit 1 -fi -# XXX warn on firmware-unreadable filesystems? - -# Create the GRUB directory if it is not present. -mkdir -p "$grubdir" || exit 1 - -# Create the device map file if it is not present. -if test -f "$device_map"; then - : -else - # Create a safe temporary file. - test -n "$mklog" && log_file=`$mklog` - - $grub_mkdevicemap --device-map=$device_map $no_floppy || exit 1 -fi - -# Copy the GRUB images to the GRUB directory. -for file in ${grubdir}/*.mod ${grubdir}/*.lst ; do - if test -f $file; then - rm -f $file || exit 1 - fi -done -for file in ${pkglibdir}/*.mod ${pkglibdir}/*.lst ; do - cp -f $file ${grubdir} || exit 1 -done - -if ! test -f ${grubdir}/grubenv; then - $grub_editenv ${grubdir}/grubenv create -fi - -# Create the core image. First, auto-detect the filesystem module. -fs_module=`$grub_probe --target=fs --device-map=${device_map} ${grubdir}` -if test "x$fs_module" = x -a "x$modules" = x; then - echo "Auto-detection of a filesystem module failed." 1>&2 - echo "Please specify the module with the option \`--modules' explicitly." 1>&2 - exit 1 -fi - -# Then the partition map module. In order to support partition-less media, -# this command is allowed to fail (--target=fs already grants us that the -# filesystem will be accessible). -partmap_module= -for x in `$grub_probe --target=partmap --device-map=${device_map} ${grubdir} 2> /dev/null`; do - partmap_module="$partmap_module part_$x"; -done - -# Device abstraction module, if any (lvm, raid). -devabstraction_module=`$grub_probe --target=abstraction --device-map=${device_map} ${grubdir}` - -modules="$modules $fs_module $partmap_module $devabstraction_module" - -# Now perform the installation. -"$grub_mkimage" -O ${target_cpu}-ieee1275 --directory=${pkglibdir} --output=${grubdir}/grub $modules || exit 1 - -if test $update_nvram = yes; then - set $ofpathname dummy - if test -f "$1"; then - : - else - echo "$1: Not found." 1>&2 - exit 1 - fi - - set $nvsetenv dummy - if test -f "$1"; then - : - else - echo "$1: Not found." 1>&2 - exit 1 - fi - - # Get the Open Firmware device tree path translation. - dev=`echo $install_device | sed -e 's/\/dev\///' -e 's/[0-9]\+//'` - partno=`echo $install_device | sed -e 's/.*[^0-9]\([0-9]\+\)$/\1/'` - ofpath=`$ofpathname $dev` || { - echo "Couldn't find Open Firmware device tree path for $dev." - echo "You will have to set boot-device manually." - exit 1 - } - - # Point boot-device at the new grub install - boot_device="$ofpath:$partno,\\grub" - "$nvsetenv" boot-device "$boot_device" || { - echo "$nvsetenv failed." - echo "You will have to set boot-device manually. At the Open Firmware prompt, type:" - echo " setenv boot-device $boot_device" - exit 1 - } -fi - -# Prompt the user to check if the device map is correct. -echo "Installation finished. No error reported." -echo "This is the contents of the device map $device_map." -echo "Check if this is correct or not. If any of the lines is incorrect," -echo "fix it and re-run the script \`$self'." -echo - -cat $device_map - -# Bye. -exit 0 diff --git a/util/raid.c b/util/raid.c index edf865aa7..dac19a935 100644 --- a/util/raid.c +++ b/util/raid.c @@ -22,40 +22,19 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include #include -static char * -grub_util_getdiskname (int major, int minor) -{ - char *name = xmalloc (15); - - if (major == LOOP_MAJOR) - sprintf (name, "/dev/loop%d", minor); - else if (major == IDE0_MAJOR) - sprintf (name, "/dev/hd%c", 'a' + minor / 64); - else if (major == IDE1_MAJOR) - sprintf (name, "/dev/hd%c", 'c' + minor / 64); - else if (major == IDE2_MAJOR) - sprintf (name, "/dev/hd%c", 'e' + minor / 64); - else if (major == IDE3_MAJOR) - sprintf (name, "/dev/hd%c", 'g' + minor / 64); - else if (major == SCSI_DISK0_MAJOR) - sprintf (name, "/dev/sd%c", 'a' + minor / 16); - else - grub_util_error ("unknown device number: %d, %d", major, minor); - - return name; -} - char ** grub_util_raid_getmembers (char *name) { @@ -100,7 +79,8 @@ grub_util_raid_getmembers (char *name) if (disk.state & (1 << MD_DISK_ACTIVE)) { - devicelist[j] = grub_util_getdiskname (disk.major, disk.minor); + devicelist[j] = grub_find_device (NULL, + makedev (disk.major, disk.minor)); j++; } } diff --git a/util/sparc64/ieee1275/grub-setup.c b/util/sparc64/ieee1275/grub-setup.c deleted file mode 100644 index 1b1a80911..000000000 --- a/util/sparc64/ieee1275/grub-setup.c +++ /dev/null @@ -1,644 +0,0 @@ -/* grub-setup.c - make GRUB usable */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GRUB. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#define _GNU_SOURCE 1 -#include - -#include "progname.h" - -/* This program fills in various fields inside of the 'boot' and 'core' - * image files. - * - * The 'boot' image needs to know the OBP path name of the root - * device. It also needs to know the initial block number of - * 'core' (which is 'diskboot' concatenated with 'kernel' and - * all the modules, this is created by grub-mkimage). This resulting - * 'boot' image is 512 bytes in size and is placed in the second block - * of a partition. - * - * The initial 'diskboot' block acts as a loader for the actual GRUB - * kernel. It contains the loading code and then a block list. - * - * The block list of 'core' starts at the end of the 'diskboot' image - * and works it's way backwards towards the end of the code of 'diskboot'. - * - * We patch up the images with the necessary values and write out the - * result. - */ - -#define DEFAULT_BOOT_FILE "boot.img" -#define DEFAULT_CORE_FILE "core.img" - -#define grub_target_to_host16(x) grub_be_to_cpu16(x) -#define grub_target_to_host32(x) grub_be_to_cpu32(x) -#define grub_target_to_host64(x) grub_be_to_cpu64(x) -#define grub_host_to_target16(x) grub_cpu_to_be16(x) -#define grub_host_to_target32(x) grub_cpu_to_be32(x) -#define grub_host_to_target64(x) grub_cpu_to_be64(x) - -/* This is the blocklist used in the diskboot image. */ -struct boot_blocklist -{ - grub_uint64_t start; - grub_uint32_t len; -} __attribute__ ((packed)); - -static void -setup (const char *prefix, const char *dir, - const char *boot_file, const char *core_file, - const char *root, const char *dest) -{ - char *boot_path, *core_path; - char *boot_img, *core_img; - size_t boot_size, core_size; - grub_uint16_t core_sectors; - grub_device_t root_dev, dest_dev; - char *boot_devpath; - grub_disk_addr_t *kernel_byte; - struct boot_blocklist *first_block, *block; - char *tmp_img; - int i; - grub_disk_addr_t first_sector; - grub_uint16_t last_length = GRUB_DISK_SECTOR_SIZE; - grub_file_t file; - FILE *fp; - struct { grub_uint64_t start; grub_uint64_t end; } embed_region; - embed_region.start = embed_region.end = ~0UL; - - auto void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, - unsigned int offset, - unsigned int length); - auto void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, - unsigned int offset, - unsigned int length); - - void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, - unsigned int offset, - unsigned int length) - { - grub_util_info ("first sector is <%llu,%u,%u>", sector, offset, length); - - if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE) - grub_util_error ("the first sector of the core file " - "is not sector-aligned"); - - first_sector = sector; - } - - void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, - unsigned int offset, - unsigned int length) - { - struct boot_blocklist *prev = block + 1; - - grub_util_info ("saving <%llu,%u,%u>", sector, offset, length); - - if (offset != 0 || last_length != GRUB_DISK_SECTOR_SIZE) - grub_util_error ("non-sector-aligned data is found in the core file"); - - if (block != first_block - && (grub_be_to_cpu64 (prev->start) - + grub_be_to_cpu16 (prev->len)) == sector) - prev->len = grub_cpu_to_be16 (grub_be_to_cpu16 (prev->len) + 1); - else - { - block->start = grub_cpu_to_be64 (sector); - block->len = grub_cpu_to_be16 (1); - - block--; - if (block->len) - grub_util_error ("the sectors of the core file are too fragmented"); - } - - last_length = length; - } - - /* Read the boot image by the OS service. */ - boot_path = grub_util_get_path (dir, boot_file); - boot_size = grub_util_get_image_size (boot_path); - if (boot_size != GRUB_DISK_SECTOR_SIZE) - grub_util_error ("the size of `%s' is not %d", - boot_path, GRUB_DISK_SECTOR_SIZE); - boot_img = grub_util_read_image (boot_path); - free (boot_path); - - /* Set the addresses of variables in the boot image. */ - boot_devpath = (char *) (boot_img - + GRUB_BOOT_AOUT_HEADER_SIZE - + GRUB_BOOT_MACHINE_BOOT_DEVPATH); - kernel_byte = (grub_disk_addr_t *) (boot_img - + GRUB_BOOT_AOUT_HEADER_SIZE - + GRUB_BOOT_MACHINE_KERNEL_BYTE); - - core_path = grub_util_get_path (dir, core_file); - core_size = grub_util_get_image_size (core_path); - core_sectors = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) - >> GRUB_DISK_SECTOR_BITS); - if (core_size < GRUB_DISK_SECTOR_SIZE) - grub_util_error ("the size of `%s' is too small", core_path); - - core_img = grub_util_read_image (core_path); - free (core_path); - - /* Have FIRST_BLOCK to point to the first blocklist. */ - first_block = (struct boot_blocklist *) (core_img - + GRUB_DISK_SECTOR_SIZE - - sizeof (*block)); - - grub_util_info ("root is `%s', dest is `%s'", root, dest); - - /* Open the root device and the destination device. */ - grub_util_info ("Opening root"); - root_dev = grub_device_open (root); - if (! root_dev) - grub_util_error ("%s", grub_errmsg); - - grub_util_info ("Opening dest"); - dest_dev = grub_device_open (dest); - if (! dest_dev) - grub_util_error ("%s", grub_errmsg); - - grub_util_info ("setting the root device to `%s'", root); - if (grub_env_set ("root", root) != GRUB_ERR_NONE) - grub_util_error ("%s", grub_errmsg); - - /* The core image must be put on a filesystem unfortunately. */ - grub_util_info ("will leave the core image on the filesystem"); - - /* Make sure that GRUB reads the identical image as the OS. */ - tmp_img = xmalloc (core_size); - core_path = grub_util_get_path (prefix, core_file); - - /* It is a Good Thing to sync two times. */ - sync (); - sync (); - -#define MAX_TRIES 5 - - for (i = 0; i < MAX_TRIES; i++) - { - grub_util_info ("attempting to read the core image `%s' from GRUB%s", - core_path, (i == 0) ? "" : " again"); - - grub_disk_cache_invalidate_all (); - - grub_file_filter_disable_compression (); - file = grub_file_open (core_path); - if (file) - { - if (grub_file_size (file) != core_size) - grub_util_info ("succeeded in opening the core image but the size is different (%d != %d)", - (int) grub_file_size (file), (int) core_size); - else if (grub_file_read (file, tmp_img, core_size) - != (grub_ssize_t) core_size) - grub_util_info ("succeeded in opening the core image but cannot read %d bytes", - (int) core_size); - else if (memcmp (core_img, tmp_img, core_size) != 0) - { -#if 0 - FILE *dump; - FILE *dump2; - - dump = fopen ("dump.img", "wb"); - if (dump) - { - fwrite (tmp_img, 1, core_size, dump); - fclose (dump); - } - - dump2 = fopen ("dump2.img", "wb"); - if (dump2) - { - fwrite (core_img, 1, core_size, dump2); - fclose (dump2); - } - -#endif - grub_util_info ("succeeded in opening the core image but the data is different"); - } - else - { - grub_file_close (file); - break; - } - - grub_file_close (file); - } - else - grub_util_info ("couldn't open the core image"); - - if (grub_errno) - grub_util_info ("error message = %s", grub_errmsg); - - grub_errno = GRUB_ERR_NONE; - sync (); - sleep (1); - } - - if (i == MAX_TRIES) - grub_util_error ("cannot read `%s' correctly", core_path); - - /* Clean out the blocklists. */ - block = first_block; - while (block->len) - { - block->start = 0; - block->len = 0; - - block--; - - if ((char *) block <= core_img) - grub_util_error ("no terminator in the core image"); - } - - /* Now read the core image to determine where the sectors are. */ - grub_file_filter_disable_compression (); - file = grub_file_open (core_path); - if (! file) - grub_util_error ("%s", grub_errmsg); - - file->read_hook = save_first_sector; - if (grub_file_read (file, tmp_img, GRUB_DISK_SECTOR_SIZE) - != GRUB_DISK_SECTOR_SIZE) - grub_util_error ("failed to read the first sector of the core image"); - - block = first_block; - file->read_hook = save_blocklists; - if (grub_file_read (file, tmp_img, core_size - GRUB_DISK_SECTOR_SIZE) - != (grub_ssize_t) core_size - GRUB_DISK_SECTOR_SIZE) - grub_util_error ("failed to read the rest sectors of the core image"); - - if (file->device->disk->id != dest_dev->disk->id) - { - const char *dest_ofpath; - dest_ofpath - = grub_util_devname_to_ofpath (grub_util_biosdisk_get_osdev (file->device->disk)); - grub_util_info ("dest_ofpath is `%s'", dest_ofpath); - strncpy (boot_devpath, dest_ofpath, GRUB_BOOT_MACHINE_BOOT_DEVPATH_END - - GRUB_BOOT_MACHINE_BOOT_DEVPATH - 1); - boot_devpath[GRUB_BOOT_MACHINE_BOOT_DEVPATH_END - - GRUB_BOOT_MACHINE_BOOT_DEVPATH - 1] = 0; - } - else - { - grub_util_info ("non cross-disk install"); - memset (boot_devpath, 0, GRUB_BOOT_MACHINE_BOOT_DEVPATH_END - - GRUB_BOOT_MACHINE_BOOT_DEVPATH); - } - - grub_file_close (file); - - free (core_path); - free (tmp_img); - - *kernel_byte = grub_cpu_to_be64 (first_sector << GRUB_DISK_SECTOR_BITS); - - grub_util_info ("boot device path %s, prefix is %s, dest is %s", - boot_devpath, prefix, dest); - - /* Write the first two sectors of the core image onto the disk. */ - core_path = grub_util_get_path (dir, core_file); - grub_util_info ("opening the core image `%s'", core_path); - fp = fopen (core_path, "r+b"); - if (! fp) - grub_util_error ("cannot open `%s'", core_path); - - grub_util_write_image (core_img, GRUB_DISK_SECTOR_SIZE, fp); - fclose (fp); - free (core_path); - - /* Write the boot image onto the disk. */ - if (grub_disk_write (dest_dev->disk, 1, 0, GRUB_DISK_SECTOR_SIZE, boot_img)) - grub_util_error ("%s", grub_errmsg); - - /* Sync is a Good Thing. */ - sync (); - - free (core_img); - free (boot_img); - grub_device_close (dest_dev); - grub_device_close (root_dev); -} - -static struct option options[] = - { - {"boot-image", required_argument, 0, 'b'}, - {"core-image", required_argument, 0, 'c'}, - {"directory", required_argument, 0, 'd'}, - {"device-map", required_argument, 0, 'm'}, - {"root-device", required_argument, 0, 'r'}, - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'V'}, - {"verbose", no_argument, 0, 'v'}, - {0, 0, 0, 0} - }; - -static void -usage (int status) -{ - if (status) - fprintf (stderr, "Try `%s --help' for more information.\n", program_name); - else - printf ("\ -Usage: %s [OPTION]... DEVICE\n\ -\n\ -Set up images to boot from DEVICE.\n\ -DEVICE must be a GRUB device (e.g. `(hd0,1)').\n\ -\n\ -You should not normally run %s directly. Use grub-install instead.\n\ -\n\ - -b, --boot-image=FILE use FILE as the boot image [default=%s]\n\ - -c, --core-image=FILE use FILE as the core image [default=%s]\n\ - -d, --directory=DIR use GRUB files in the directory DIR [default=%s]\n\ - -m, --device-map=FILE use FILE as the device map [default=%s]\n\ - -r, --root-device=DEV use DEV as the root device [default=guessed]\n\ - -h, --help display this message and exit\n\ - -V, --version print version information and exit\n\ - -v, --verbose print verbose messages\n\ -\n\ -Report bugs to <%s>.\n\ -", program_name, program_name, - DEFAULT_BOOT_FILE, DEFAULT_CORE_FILE, DEFAULT_DIRECTORY, - DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT); - - exit (status); -} - -struct grub_setup_info -{ - char *boot_file; - char *core_file; - char *dir; - char *dev_map; - char *root_dev; - char *prefix; - char *dest_dev; -}; - -static void -init_info (struct grub_setup_info *gp) -{ - gp->boot_file = NULL; - gp->core_file = NULL; - gp->dir = NULL; - gp->dev_map = NULL; - gp->root_dev = NULL; - gp->prefix = NULL; - gp->dest_dev = NULL; -} - -static int -parse_options (struct grub_setup_info *gp, int argc, char *argv[]) -{ - while (1) - { - int c = getopt_long (argc, argv, "b:c:d:m:r:hVv", options, 0); - - if (c == -1) - break; - else - switch (c) - { - case 'b': - if (gp->boot_file) - free (gp->boot_file); - - gp->boot_file = xstrdup (optarg); - break; - - case 'c': - if (gp->core_file) - free (gp->core_file); - - gp->core_file = xstrdup (optarg); - break; - - case 'd': - if (gp->dir) - free (gp->dir); - - gp->dir = xstrdup (optarg); - break; - - case 'm': - if (gp->dev_map) - free (gp->dev_map); - - gp->dev_map = xstrdup (optarg); - break; - - case 'r': - if (gp->root_dev) - free (gp->root_dev); - - gp->root_dev = xstrdup (optarg); - break; - - case 'h': - usage (0); - break; - - case 'V': - printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); - return 0; - - case 'v': - verbosity++; - break; - - default: - usage (1); - break; - } - } - - if (verbosity > 1) - grub_env_set ("debug", "all"); - - if (optind >= argc) - { - fprintf (stderr, "No device is specified.\n"); - usage (1); - } - - if (optind + 1 != argc) - { - fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind + 1]); - usage (1); - } - return 1; -} - -static char * -get_device_name (char *dev) -{ - size_t len = strlen (dev); - - if (dev[0] != '(' || dev[len - 1] != ')') - return 0; - - dev[len - 1] = '\0'; - return dev + 1; -} - -static void -find_dest_dev (struct grub_setup_info *gp, char *argv[]) -{ - gp->dest_dev = get_device_name (argv[optind]); - if (! gp->dest_dev) - { - /* Possibly, the user specified an OS device file. */ - gp->dest_dev = grub_util_get_grub_dev (argv[optind]); - if (! gp->dest_dev) - { - fprintf (stderr, "Invalid device `%s'.\n", argv[optind]); - usage (1); - } - grub_util_info ("transformed OS device `%s' into GRUB device `%s'", - argv[optind], gp->dest_dev); - } - else - { - /* For simplicity. */ - gp->dest_dev = xstrdup (gp->dest_dev); - grub_util_info ("Using `%s' as GRUB device", gp->dest_dev); - } -} - -static void -check_root_dev (struct grub_setup_info *gp) -{ - if (gp->root_dev) - { - char *tmp = get_device_name (gp->root_dev); - - if (! tmp) - grub_util_error ("invalid root device `%s'", gp->root_dev); - - tmp = xstrdup (tmp); - free (gp->root_dev); - gp->root_dev = tmp; - } - else - { - char *dir = gp->dir ? gp->dir : DEFAULT_DIRECTORY; - char *root_device = grub_guess_root_device (dir); - - gp->root_dev = grub_util_get_grub_dev (root_device); - if (! gp->root_dev) - { - grub_util_info ("guessing the root device failed, because of `%s'", - grub_errmsg); - grub_util_error ("cannot guess the root device. " - "Specify the option `--root-device'"); - } - grub_util_info ("guessed root device `%s' and root_dev `%s' from " - "dir `%s'", root_device, gp->root_dev, dir); - } -} - -static void -free_memory (struct grub_setup_info *gp) -{ - free (gp->boot_file); - free (gp->core_file); - free (gp->dir); - free (gp->dev_map); - free (gp->root_dev); - free (gp->prefix); - free (gp->dest_dev); -} - -int -main (int argc, char *argv[]) -{ - struct grub_setup_info ginfo; - - set_program_name (argv[0]); - - grub_util_init_nls (); - - init_info (&ginfo); - if (!parse_options (&ginfo, argc, argv)) - return 0; - - /* Initialize the emulated biosdisk driver. */ - grub_util_biosdisk_init (ginfo.dev_map ? ginfo.dev_map : DEFAULT_DEVICE_MAP); - - /* Initialize all modules. */ - grub_init_all (); - - grub_lvm_fini (); - grub_mdraid_fini (); - grub_raid_fini (); - grub_raid_init (); - grub_mdraid_init (); - grub_lvm_init (); - - find_dest_dev (&ginfo, argv); - - ginfo.prefix = grub_make_system_path_relative_to_its_root (ginfo.dir ? - : DEFAULT_DIRECTORY); - - check_root_dev (&ginfo); - - /* Do the real work. */ - setup (ginfo.prefix, - ginfo.dir ? ginfo.dir : DEFAULT_DIRECTORY, - ginfo.boot_file ? ginfo.boot_file : DEFAULT_BOOT_FILE, - ginfo.core_file ? ginfo.core_file : DEFAULT_CORE_FILE, - ginfo.root_dev, ginfo.dest_dev); - - /* Free resources. */ - grub_fini_all (); - - free_memory (&ginfo); - - return 0; -}