diff --git a/ChangeLog b/ChangeLog index e91e87536..a53cf9279 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,552 @@ +2010-01-18 Robert Millan + + * include/grub/i386/linux.h (GRUB_VIDEO_TYPE_TEXT): Rename to ... + (GRUB_VIDEO_LINUX_TYPE_TEXT): ... this. Update all users. + (GRUB_VIDEO_TYPE_VLFB): Rename to ... + (GRUB_VIDEO_LINUX_TYPE_VESA): ... this. Update all users. + (GRUB_VIDEO_TYPE_EFI): Rename to ... + (GRUB_VIDEO_LINUX_TYPE_SIMPLE): ... this. Update all users. + +2010-01-17 Robert Millan + + * include/grub/test.h: Add license header. + * tests/example_functional_test.c: Likewise. + * tests/example_unit_test.c: Likewise. + * tests/lib/functional_test.c: Likewise. + * tests/lib/test.c: Likewise. + * tests/lib/unit_test.c: Likewise. + +2010-01-17 Vladimir Serbinenko + + Use flag-based instead of hook-based video mode selection and "auto" + keyword. + + * include/grub/video.h (grub_video_adapter): Changed 'setup' member. + (grub_video_set_mode): Changed prototype. All users updated. + (grub_video_check_mode_flag): New inline function. + * video/video.c (parse_modespec): New function. + (grub_video_set_mode): Parse flags and keywords. + +2010-01-17 Carles Pina i Estany + + * util/misc.c (grub_util_info): Fix the order of the parameters in a + fprintf call. + +2010-01-16 Grégoire Sutre + + * genmk.rb (class SCRIPT): Replace option -i of sed by a pipe. + +2010-01-16 Carles Pina i Estany + + * util/grub-editenv.c (usage): Use `program_name' instead of hardcoded + string. + * util/grub-emu.c (usage): Likewise. + * util/grub-mkpasswd-pbkdf2.c (usage): Likewise. + * util/i386/efi/grub-mkimage.c (usage): Likewise. + * util/i386/pc/grub-mkimage.c (usage): Likewise. + * util/i386/pc/grub-setup.c (usage): Likewise. + +2010-01-16 Carles Pina i Estany + + * util/misc.c (grub_util_warn): Gettextizze, print full stop after + the message. + (grub_util_info): Likewise. + (grub_util_error): Likewise. + * util/elf/grub-mkimage.c: Fix capitalisation, quotes, full stops + and/or new lines in `grub_util_warna', `grub_util_info', + `grub_util_error' calls. + * util/getroot.c: Likewise. + * util/grub-editenv.c: Likewise. + * util/grub-emu.c: Likewise. + * util/grub-fstest.c: Likewise. + * util/grub-mkdevicemap.c: Likewise. + * util/grub-mkfont.c: Likewise. + * util/grub-mkpasswd-pbkdf2.c: Likewise. + * util/grub-mkrelpath.c: Likewise. + * util/grub-pe2elf.c: Likewise. + * util/grub-probe.c: Likewise. + * util/hostdisk.c: Likewise. + * util/i386/efi/grub-mkimage.c: Likewise. + * util/i386/pc/grub-mkimage.c: Likewise. + * util/i386/pc/grub-setup.c: Likewise. + * util/ieee1275/ofpath.c: Likewise. + * util/mkisofs/eltorito.c: Likewise. + * util/mkisofs/rock.c: Likewise. + * util/mkisofs/write.c: Likewise. + * util/raid.c: Likewise. + * util/sparc64/ieee1275/grub-mkimage.c: Likewise. + * util/sparc64/ieee1275/grub-setup.c: Likewise. + +2010-01-15 Vladimir Serbinenko + + Enable multiboot on non-pc. + + * conf/i386-coreboot.rmk, conf/i386-pc.rmk (pkglib_MODULES): Move + multiboot.mod and multiboot2.mod to ... + * conf/i386.rmk (pkglib_MODULES): ... here. + * conf/i386-coreboot.rmk, conf/i386-pc.rmk (multiboot_mod_SOURCES): + Moved to ... + * conf/i386.rmk (multiboot_mod_SOURCES): .. here. + * conf/i386-coreboot.rmk, conf/i386-pc.rmk (multiboot_mod_CFLAGS): + Moved to ... + * conf/i386.rmk (multiboot_mod_CFLAGS): .. here. + * conf/i386-coreboot.rmk, conf/i386-pc.rmk (multiboot_mod_ASFLAGS): + Moved to ... + * conf/i386.rmk (multiboot_mod_ASFLAGS): .. here. + * conf/i386-coreboot.rmk, conf/i386-pc.rmk (multiboot_mod_LDFLAGS): + Moved to ... + * conf/i386.rmk (multiboot_mod_LDFLAGS): .. here. + * conf/x86_64-efi.rmk (pkglib_MODULES): Remove ata.mod and + relocator.mod. + (ata_mod_SOURCES): Removed. + (ata_mod_CFLAGS): Likewise. + (ata_mod_LDFLAGS): Likewise. + (relocator_mod_SOURCES): Removed. + (relocator_mod_CFLAGS): Likewise. + (relocator_mod_ASFLAGS): Likewise. + (relocator_mod_LDFLAGS): Likewise. + Include i386.mk. + * include/grub/x86_64/multiboot.h: New file. + * loader/i386/multiboot.c (grub_multiboot_boot) [GRUB_MACHINE_EFI]: + Terminate EFI. + +2010-01-15 Vladimir Serbinenko + + Video multiboot support. + + * include/grub/multiboot.h (grub_multiboot_set_accepts_video): + New prototype. + * include/multiboot.h: Resynced with multiboot specification. + * include/multiboot2.h: Likewise. + * loader/i386/multiboot.c (UNSUPPORTED_FLAGS): Support video flags. + (grub_multiboot): Parse MULTIBOOT_VIDEO_MODE fields. + * loader/i386/multiboot_mbi.c (DEFAULT_VIDEO_MODE): New constant. + (HAS_VGA_TEXT): Likewise. + (accepts_video): New variable. + (grub_multiboot_set_accepts_video): New function. + (grub_multiboot_get_mbi_size): Account for video structures. + (set_video_mode): New function. + (retrieve_video_parameters): Likewise. + (grub_multiboot_make_mbi): Fill video fields. + +2010-01-15 Vladimir Serbinenko + + Video driver ids. + + * include/grub/video.h (grub_video_driver_id): New type. + (grub_video_adapter): New member 'id'. All users updated. + (grub_video_get_driver_id): New proto. + * video/video.c (grub_video_get_driver_id): New function. + +2010-01-14 Carles Pina i Estany + + * util/grub.d/30_os-prober.in: Use `set var=val' rather than plain + `var=val'. + +2010-01-14 Carles Pina i Estany + + * normal/cmdline.c (print_completion): Gettextizze. + +2001-01-14 Carles Pina i Estany + + * loader/i386/pc/chainloader.c: Include `'. + +2010-01-14 Carles Pina i Estany + + * gettext/gettext.c (grub_gettext_translate): Push and pop + grub_errno. + (grub_gettext_delete_list): Change comment style. + * kern/err.c (grub_error): Gettextizze. + (grub_fatal): Gettextizze. + +2010-01-14 Robert Millan + + * include/grub/i386/loader.h (grub_linux16_boot): Renamed to ... + (grub_linux16_real_boot): ... this. + * kern/i386/loader.S: Likewise. + * loader/i386/pc/linux.c: Include `' and `'. + (grub_linux16_boot): New function. Switches to text mode and calls + grub_linux16_real_boot(). + + * loader/i386/bsd.c: Include `'. + (grub_freebsd_boot, grub_openbsd_boot, grub_netbsd_boot): Switch to + text mode before calling grub_unix_real_boot(). + + * loader/i386/multiboot.c: Include `'. + (grub_multiboot_boot): Switch to text mode before calling + grub_relocator32_boot(). + + * loader/i386/pc/chainloader.c: Include `'. + (grub_chainloader_boot): Switch to text mode before calling + grub_chainloader_real_boot(). + +2010-01-05 Jordan Uggla +2010-01-05 Colin Watson + + * util/grub-reboot.in: Make sure prev_saved_entry always gets a + non-empty value. + +2010-01-05 Jordan Uggla +2010-01-05 Colin Watson + + * util/grub.d/00_header.in: Define a "savedefault" function for use + in menu entries. + * util/grub-mkconfig_lib.in (save_default_entry): Use it. + +2010-01-05 Jordan Uggla +2010-01-05 Colin Watson + + * util/grub-mkconfig_lib.in (save_default_entry): Only set + saved_entry if boot_once is unset. + * util/grub.d/00_header.in: Set boot_once to "true" if there was a + previous saved entry (i.e. grub-reboot). + +2009-12-08 Colin Watson + + * util/grub.d/30_os-prober.in: Call save_default_entry for hurd. + +2009-12-08 Colin Watson + + * util/grub.d/00_header.in: Use `set var=val' rather than plain + `var=val'. + * util/grub-mkconfig_lib.in (save_default_entry): Likewise. + +2009-12-08 Colin Watson + + * util/grub-reboot.in: Fix --version output. + * util/grub-set-default.in: Likewise. + +2009-12-08 Colin Watson + + * util/grub.d/00_header.in: Silently ignore zero-sized environment + blocks. + +2009-12-08 Colin Watson + + * util/grub.d/00_header.in: Quote the value assigned to `default', + in case it contains spaces. + +2009-12-08 Colin Watson + + * util/grub.d/30_os-prober.in: Fix merge error that moved a + `save_default_entry' call from the macosx case to the linux case. + +2009-10-25 Vladimir Serbinenko +2009-10-25 Colin Watson + + * normal/menu.c (grub_menu_execute_entry): Save selected entry title + in `chosen' environment variable. + * normal/menu_text.c (get_entry_number): Check if the variable + matches the title of a menu entry. + (run_menu): Pass menu to get_entry_number. + + * util/grub-reboot.in: New file. + * util/grub-set-default.in: New file. + * conf/common.rmk (grub-reboot): New utility. + (grub-set-default): New utility. + + * util/grub-mkconfig_lib.in (save_default_entry): New function. + * util/grub.d/00_header.in: If GRUB_DEFAULT is `saved', set + default to `${saved_entry}'. If `${prev_saved_entry}' is non-empty, + move it to `saved_entry' for the next boot. Load environment on + initialisation. + * util/grub.d/10_kfreebsd.in: Call save_default_entry. + * util/grub.d/10_hurd.in: Likewise. + * util/grub.d/10_linux.in (linux_entry): Likewise. + * util/grub.d/10_windows.in: Likewise. + * util/grub.d/30_os-prober.in: Likewise. + + * util/grub-install.in: Create environment block. + * util/i386/efi/grub-install.in: Likewise. + * util/ieee1275/grub-install.in: Likewise. + * util/sparc64/ieee1275/grub-install.in: Likewise. + +2010-01-14 BVK Chaitanya + + Unit testing framework for GRUB. + + * Makefile.in: Test framework build rules for 'make check'. + * conf/tests.rmk: Build rules for individual tests and framework. + + * include/grub/test.h: Header file for whitebox tests. + * tests/lib/functional_test.c: Framework support for whitebox + functional tests. + * tests/lib/test.c: Common whitebox testing code for unit and + functional tests. + * tests/lib/unit_test.c: Framework support for whitebox unit + tests. + + * tests/util/grub-shell-tester.in: Support utility for grub-script + tests. + * tests/util/grub-shell.in: Utility to execute grub-script + commands in a Qemu instance. + + * tests/example_functional_test.c: Example whitebox functional + test. + * tests/example_grub_script_test.in: Example grub-script test. + * tests/example_scripted_test.in: Example scripted test. + * tests/example_unit_test.c: Example whitebox unit test. + +2010-01-14 Vladimir Serbinenko + + * conf/i386-coreboot.rmk (multiboot_mod_SOURCES): + Add loader/i386/multiboot_mbi.c. + (multiboot2_mod_SOURCES): Likewise. + * conf/i386-pc.rmk (multiboot_mod_SOURCES): Likewise. + (multiboot2_mod_SOURCES): Likewise. + * include/grub/multiboot.h (grub_multiboot_get_mbi_size): New proto. + (grub_multiboot_make_mbi): Likewise. + (grub_multiboot_free_mbi): Likewise. + (grub_multiboot_init_mbi): Likewise. + (grub_multiboot_add_module): Likewise. + (grub_multiboot_set_bootdev): Likewise. + * loader/i386/multiboot.c (mbi): Removed. + (mbi_dest): Likewise. + (alloc_mbi): New variable. + (grub_multiboot_payload_size): Removed. All users updated. + (grub_multiboot_pure_size): New variable. + (grub_multiboot_boot): Use grub_multiboot_make_mbi. + (grub_multiboot_unload): Use grub_multiboot_free_mbi. + (grub_get_multiboot_mmap_len): Moved to loader/i386/multiboot_mbi.c. + (grub_fill_multiboot_mmap): Likewise. + (grub_multiboot_get_bootdev): Likewise. + (grub_multiboot): Use multiboot_mbi functions. + * loader/i386/multiboot_mbi.c: New file. + +2010-01-13 Vladimir Serbinenko + + * kern/efi/init.c (grub_efi_fini): Don't call grub_efi_mm_fini as + it would result in module crash. + +2010-01-13 Vladimir Serbinenko + + * term/ieee1275/ofconsole.c (grub_ofconsole_putchar): Handle '\r'. + (grub_ofconsole_getwh): Split to ... + (grub_ofconsole_getwh): ... this. + (grub_ofconsole_dimensions): ...and this. + (grub_ofconsole_init_output): Call grub_ofconsole_dimensions. + +2010-01-13 Robert Millan + + * util/mkisofs/rock.c (generate_rock_ridge_attributes): Fix a typo. + +2010-01-12 Vladimir Serbinenko + + * loader/i386/pc/multiboot2.c: Removed stalled file. + +2010-01-12 Vladimir Serbinenko + + * util/grub-mkpasswd-pbkdf2.c (main): Use grub_util_init_nls. + Reported by: Grégoire Sutre + +2010-01-11 Robert Millan + + * util/misc.c (canonicalize_file_name): New function. + (make_system_path_relative_to_its_root): Use canonicalize_file_name() + instead of realpath(). + +2010-01-11 Colin Watson + + * util/grub-install.in (usage): Clarify meaning of --root-directory, + and make it clearer that it's optional. Based on confusion + witnessed on IRC. + +2010-01-10 Vladimir Serbinenko + + * term/i386/pc/vga_text.c (inc_y): Fix off-by-one error which resulted + in premature implicit newline. + +2010-01-10 Vladimir Serbinenko + + * normal/cmdline.c (grub_cmdline_get): Fix off-by-one error + which resulted in garbled command line at the end of screen. + +2010-01-10 Robert Millan + + * loader/i386/ieee1275/linux.c (grub_linux_boot): Rework video position + initialization with similar approach as with other Linux loaders. + +2010-01-10 Robert Millan + + Fix i386-ieee1275 build. + + * loader/i386/ieee1275/linux.c (grub_linux_boot): Use grub_term_width() + and grub_term_height() for video_{width,height} initialization. + +2010-01-10 Robert Millan + + Fix grub-emu build. + + * conf/any-emu.rmk (grub_emu_SOURCES): Remove `kern/reader.c'. + +2010-01-07 Vladimir Serbinenko +2010-01-09 Robert Millan + + Support for multiple terminals. + + * Makefile.in (pkglib_DATA): terminal.lst. + (terminal.lst): New target. + * commands/handler.c (grub_cmd_handler): Don't handle terminals. + (GRUB_MOD_INIT(handler)): Likewise. + (GRUB_MOD_FINI(handler)): Likewise. + * commands/help.c (grub_cmd_help): Handle multiple terminals. + * commands/keystatus.c (grub_cmd_keystatus): Likewise. + * commands/sleep.c (do_print): Use grub_term_restore_pos. + (grub_cmd_sleep): Use grub_term_save_pos. + * commands/terminal.c: New file. + * conf/any-emu.rmk (grub_emu_SOURCES): Add normal/term.c + commands/terminal.c and lib/charset.c. + * conf/common.rmk (normal_mod_SOURCES): Add normal/term.c. + (pkglib_MODULES): Add terminal.mod. + (terminal_mod_SOURCES): New variable. + (terminal_mod_CFLAGS): Likewise. + (terminal_mod_LDFLAGS): Likewise. + * genhandlerlist.sh: Don't handle terminals. + * genmk.rb: Generate terminal-*.lst. + * genterminallist.sh: New file. + * include/grub/charset.h (grub_ucs4_to_utf8_alloc): New proto. + (grub_is_valid_utf8): Likewise. + (grub_utf8_to_ucs4_alloc): Likewise. + * include/grub/menu_viewer.h (grub_menu_viewer): Rewritten. + (grub_menu_register_viewer): Changed argument. + (grub_menu_try_text): New proto. + (grub_gfxmenu_try_hook): New declaration. + * include/grub/normal.h (grub_normal_exit_level): New declaration. + (grub_menu_init_page): Additional argument term. + (grub_normal_init_page): Likewise. + (grub_cmdline_get): Arguments simplified. + (grub_utf8_to_ucs4_alloc): Removed. + (grub_print_ucs4): Additional argument term. + (grub_getstringwidth): Likewise. + (grub_print_message_indented): Likewise. + (grub_menu_text_register_instances): New proto. + (grub_show_menu): Likewise. + (read_terminal_list): Likewise. + (grub_set_more): Likewise. + * include/grub/parser.h: Include handler.h. + * include/grub/reader.h: Rewritten. + * include/grub/term.h (GRUB_TERM_NEED_INIT): Removed. + (GRUB_TERM_WIDTH): Changed to function. + (GRUB_TERM_HEIGHT): Likewise. + (GRUB_TERM_BORDER_WIDTH): Likewise. + (GRUB_TERM_BORDER_HEIGHT): Likewise. + (GRUB_TERM_NUM_ENTRIES): Likewise. + (GRUB_TERM_ENTRY_WIDTH): Likewise. + (GRUB_TERM_CURSOR_X): Likewise. + (grub_term_input_class): Likewise. + (grub_term_output_class): Likewise. + (grub_term_outputs_disabled): New declaration. + (grub_term_inputs_disabled): Likewise. + (grub_term_outputs): Likewise. + (grub_term_inputs): Likewise. + (grub_term_register_input): Rewritten. + (grub_term_register_output): Likewise. + (grub_term_unregister_input): Likewise. + (grub_term_unregister_output): Likewise. + (FOR_ACTIVE_TERM_INPUTS): New macro. + (FOR_DISABLED_TERM_INPUTS): Likewise. + (FOR_ACTIVE_TERM_OUTPUTS): Likewise. + (FOR_DISABLED_TERM_OUTPUTS): Likewise. + * include/grub/terminfo.h: Add oterm argument to all protypes. + * kern/main.c (grub_main): Don't call grub_register_rescue_reader. + Use grub_rescue_run. + * kern/misc.c (grub_utf8_to_ucs4): Put '?' for invalid characters. + All users updated. + * kern/reader.c: Removed. All users updated. + * kern/rescue_reader.c (grub_rescue_init): Removed. + (grub_rescue_reader): Likewise. + (grub_register_rescue_reader): Likewise. + (grub_rescue_run): New function based on kern/reader.c. + * kern/term.c: Adapted for multiterm. + * lib/charset.c (grub_ucs4_to_utf8_alloc): New function. + (grub_is_valid_utf8): Likewise. + (grub_utf8_to_ucs4_alloc): Moved from normal/menu_text.c. + * loader/i386/efi/linux.c (grub_cmd_linux): Retrieve parameters of + right terminal. + * loader/i386/linux.c (grub_linux_boot): Likewise. + * normal/auth.c (grub_username_get): New function. + (grub_auth_check_authentication): Use grub_username_get. + * normal/cmdline.c: Changed to UCS4. Adapted for multiterm. + * normal/color.c: Adapt for multiterm. + * normal/main.c (read_config_file): Don't use grub_reader_loop. + (grub_normal_init_page): Additional argument term. + (read_lists): Call read_terminal_lists. + (grub_enter_normal_mode): Call grub_cmdline_run. + Handle grub_normal_exit_level. + (grub_cmd_normal): Make reentrant. + (grub_cmd_normal_exit): New function. + (grub_normal_reader_init): Additional argument nested. Handle multiterm. + * normal/menu.c: Adapt for multiterm. + * normal/menu_entry.c: Likewise. + * normal/menu_text.c: Likewise. + * normal/menu_viewer.c: Removed. All users updated. + * normal/term.c: New file. + * util/console.c: Change order of includes to workaround a bug in + ncurses headers. + * term/terminfo.c: New argument oterm on all exported functions. + All users updated. + * util/grub-editenv.c (grub_term_input_class): Removed. + (grub_term_output_class): Likewise. + +2010-01-09 Robert Millan + + Make loader output a bit more user-friendly. + + * util/grub.d/10_hurd.in: Print message indicating that GNU Mach + is being loaded. Likewise for the Hurd. + + * util/grub.d/10_kfreebsd.in (kfreebsd_entry): Print message indicating + that kernel of FreeBSD ${version} is being loaded. + + * loader/i386/linux.c (grub_cmd_linux): Move debug info to + grub_dprintf(). + (grub_cmd_initrd): Likewise. + * util/grub.d/10_linux.in (linux_entry): Print message indicating + that Linux ${version} is being loaded. Likewise for initrd. + +2010-01-09 Carles Pina i Estany + + * gettext/gettext.c (GRUB_MOD_INIT): Gettextizze. + +2010-01-08 Carles Pina i Estany + + * loader/efi/appleloader.c: Include `'. + (GRUB_MOD_INIT): Gettextizze. + * loader/efi/chainloader.c: Include `'. + (GRUB_MOD_INIT): Gettextizze. + * loader/i386/efi/linux.c: Include `'. + (grub_cmd_linux): Capitalise Linux. + (GRUB_MOD_INIT): Gettextizze. + * loader/i386/ieee1275/linux.c: Include `'. + (grub_cmd_linux): Capitalise Linux. + (GRUB_MOD_INIT): Gettextizze. + * loader/i386/linux.c: Include `'. + (grub_cmd_linux): Capitalise Linux. + (GRUB_MOD_INIT): Gettextizze. + * loader/i386/pc/chainloader.c: Include `'. + (GRUB_MOD_INIT): Gettextizze. + * loader/i386/pc/linux.c: Include `'. + (grub_cmd_linux): Capitalise Linux. + (GRUB_MOD_INIT): Gettextizze. + * loader/i386/xnu.c: Include `'. + (grub_cpu_xnu_init): Gettextizze. + * loader/multiboot_loader.c: Include `'. + (GRUB_MOD_INIT): Gettextizze. + * loader/powerpc/ieee1275/linux.c: Include `'. + (GRUB_MOD_INIT): Gettextizze. + * loader/sparc64/ieee1275/linux.c: Include `'. + (grub_linux_load64): Capitalise Linux. + (GRUB_MOD_INIT): Gettextizze. + * loader/xnu.c: Include `'. + (GRUB_MOD_INIT): Gettextizze. + * po/POTFILES: Add `loader/efi/appleloader.c', + `loader/efi/chainloader.c', `loader/i386/efi/linux.c', + `loader/i386/ieee1275/linux.c', `loader/i386/linux.c', + `loader/i386/pc/chainloader.c', `loader/i386/pc/linux.c', + `loader/i386/xnu.c', `loader/multiboot_loader.c', + `loader/powerpc/ieee1275/linux.c', `loader/sparc64/ieee1275/linux.c' + and `loader/xnu.c'. + 2010-01-08 Robert Millan * src/mkisofs.c: Remove `ifdef linux' portability kludge. diff --git a/Makefile.in b/Makefile.in index ffa8716ed..e1067b985 100644 --- a/Makefile.in +++ b/Makefile.in @@ -167,6 +167,8 @@ ifeq ($(platform), emu) include $(srcdir)/conf/any-emu.mk else include $(srcdir)/conf/$(target_cpu)-$(platform).mk +# For tests. +include $(srcdir)/conf/tests.mk # For external modules. -include $(wildcard $(GRUB_CONTRIB)/*/conf/common.mk) endif @@ -174,7 +176,7 @@ endif ### General targets. CLEANFILES += $(pkglib_DATA) $(pkgdata_DATA) po/*.mo -pkglib_DATA += moddep.lst command.lst fs.lst partmap.lst parttool.lst handler.lst video.lst crypto.lst +pkglib_DATA += moddep.lst command.lst fs.lst partmap.lst parttool.lst handler.lst video.lst crypto.lst terminal.lst moddep.lst: $(DEFSYMFILES) $(UNDSYMFILES) genmoddep.awk cat $(DEFSYMFILES) /dev/null \ | $(AWK) -f $(srcdir)/genmoddep.awk $(UNDSYMFILES) > $@ \ @@ -192,6 +194,9 @@ partmap.lst: $(PARTMAPFILES) handler.lst: $(HANDLERFILES) cat $^ /dev/null | sort > $@ +terminal.lst: $(TERMINALFILES) + cat $^ /dev/null | sort > $@ + parttool.lst: $(PARTTOOLFILES) cat $^ /dev/null | sort | uniq > $@ @@ -458,7 +463,26 @@ distcheck: dist @echo "$(distdir).tar.gz is ready for distribution" | \ sed 'h;s/./=/g;p;x;p;x' -check: +check: all $(UNIT_TESTS) $(FUNCTIONAL_TESTS) $(SCRIPTED_TESTS) + @list="$(UNIT_TESTS)"; \ + for file in $$list; do \ + $(builddir)/$$file; \ + done + @list="$(FUNCTIONAL_TESTS)"; \ + for file in $$list; do \ + mod=`basename $$file .mod`; \ + echo "insmod functional_test; insmod $$mod; functional_test" \ + | $(builddir)/grub-shell; \ + done + @list="$(SCRIPTED_TESTS)"; \ + for file in $$list; do \ + echo "$$file:"; \ + if $(builddir)/$$file; then \ + echo "$$file: PASS"; \ + else \ + echo "$$file: FAIL"; \ + fi; \ + done .SUFFIX: .SUFFIX: .c .o .S .d diff --git a/commands/handler.c b/commands/handler.c index 7316db304..f9270972b 100644 --- a/commands/handler.c +++ b/commands/handler.c @@ -26,10 +26,9 @@ #include static grub_err_t -grub_cmd_handler (struct grub_command *cmd, +grub_cmd_handler (struct grub_command *cmd __attribute__ ((unused)), int argc, char **args) { - char *class_name; void *curr_item = 0; grub_handler_class_t head; @@ -44,23 +43,19 @@ grub_cmd_handler (struct grub_command *cmd, return 0; } - class_name = (grub_strcmp (cmd->name, "handler")) ? (char *) cmd->name : 0; - head = grub_handler_class_list; - if ((argc == 0) && (class_name == 0)) + if (argc == 0) { grub_list_iterate (GRUB_AS_LIST (head), (grub_list_hook_t) list_item); } else { + char *class_name; grub_handler_class_t class; - if (class_name == 0) - { - class_name = args[0]; - argc--; - args++; - } + class_name = args[0]; + argc--; + args++; class = grub_named_list_find (GRUB_AS_NAMED_LIST (head), class_name); if (! class) @@ -90,7 +85,7 @@ grub_cmd_handler (struct grub_command *cmd, return 0; } -static grub_command_t cmd_handler, cmd_terminal_input, cmd_terminal_output; +static grub_command_t cmd_handler; GRUB_MOD_INIT(handler) { @@ -98,19 +93,9 @@ GRUB_MOD_INIT(handler) grub_register_command ("handler", grub_cmd_handler, N_("[class [handler]]"), N_("List or select a handler.")); - cmd_terminal_input = - grub_register_command ("terminal_input", grub_cmd_handler, - N_("[handler]"), - N_("List or select an input terminal.")); - cmd_terminal_output = - grub_register_command ("terminal_output", grub_cmd_handler, - N_("[handler]"), - N_("List or select an output terminal.")); } GRUB_MOD_FINI(handler) { grub_unregister_command (cmd_handler); - grub_unregister_command (cmd_terminal_input); - grub_unregister_command (cmd_terminal_output); } diff --git a/commands/help.c b/commands/help.c index 7edc23563..9234a3697 100644 --- a/commands/help.c +++ b/commands/help.c @@ -24,6 +24,7 @@ #include #include #include +#include static grub_err_t grub_cmd_help (grub_extcmd_t ext __attribute__ ((unused)), int argc, @@ -40,12 +41,11 @@ grub_cmd_help (grub_extcmd_t ext __attribute__ ((unused)), int argc, if ((cmd->prio & GRUB_PRIO_LIST_FLAG_ACTIVE) && (cmd->flags & GRUB_COMMAND_FLAG_CMDLINE)) { + struct grub_term_output *term; + const char *summary_translated = _(cmd->summary); char *command_help; - int stringwidth; grub_uint32_t *unicode_command_help; grub_uint32_t *unicode_last_position; - grub_uint32_t *unicode_last_screen_position; - const char *summary_translated = _(cmd->summary); command_help = grub_malloc (grub_strlen (cmd->name) + sizeof (" ") - 1 + @@ -55,28 +55,34 @@ grub_cmd_help (grub_extcmd_t ext __attribute__ ((unused)), int argc, grub_utf8_to_ucs4_alloc (command_help, &unicode_command_help, &unicode_last_position); - - unicode_last_screen_position = unicode_command_help; - stringwidth = 0; + FOR_ACTIVE_TERM_OUTPUTS(term) + { + unsigned stringwidth; + grub_uint32_t *unicode_last_screen_position; - while (unicode_last_screen_position < unicode_last_position && - stringwidth < ((GRUB_TERM_WIDTH / 2) - 2)) - { - stringwidth += grub_getcharwidth (*unicode_last_screen_position); - unicode_last_screen_position++; - } + unicode_last_screen_position = unicode_command_help; - grub_print_ucs4 (unicode_command_help, unicode_last_screen_position); - - if ((cnt++) % 2) - { - grub_putchar ('\n'); - } - else - { - grub_print_spaces (GRUB_TERM_WIDTH / 2 - stringwidth); - } + stringwidth = 0; + + while (unicode_last_screen_position < unicode_last_position && + stringwidth < ((grub_term_width (term) / 2) - 2)) + { + stringwidth + += grub_term_getcharwidth (term, + *unicode_last_screen_position); + unicode_last_screen_position++; + } + + grub_print_ucs4 (unicode_command_help, + unicode_last_screen_position, term); + if (!(cnt % 2)) + grub_print_spaces (term, grub_term_width (term) / 2 + - stringwidth); + } + if (cnt % 2) + grub_printf ("\n"); + cnt++; grub_free (command_help); grub_free (unicode_command_help); @@ -104,7 +110,11 @@ grub_cmd_help (grub_extcmd_t ext __attribute__ ((unused)), int argc, } if (argc == 0) - grub_command_iterate (print_command_info); + { + grub_command_iterate (print_command_info); + if (!(cnt % 2)) + grub_printf ("\n"); + } else { int i; diff --git a/commands/keystatus.c b/commands/keystatus.c index a0a429284..838792889 100644 --- a/commands/keystatus.c +++ b/commands/keystatus.c @@ -49,13 +49,24 @@ grub_cmd_keystatus (grub_extcmd_t cmd, if (state[2].set) expect_mods |= GRUB_TERM_STATUS_ALT; + grub_dprintf ("keystatus", "expect_mods: %d\n", expect_mods); + /* Without arguments, just check whether getkeystatus is supported at all. */ - if (!grub_cur_term_input->getkeystatus) - return grub_error (GRUB_ERR_TEST_FAILURE, "false"); - grub_dprintf ("keystatus", "expect_mods: %d\n", expect_mods); - if (!expect_mods) - return 0; + if (expect_mods == 0) + { + grub_term_input_t term; + int nterms = 0; + + FOR_ACTIVE_TERM_INPUTS (term) + if (!term->getkeystatus) + return grub_error (GRUB_ERR_TEST_FAILURE, "false"); + else + nterms++; + if (!nterms) + return grub_error (GRUB_ERR_TEST_FAILURE, "false"); + return 0; + } mods = grub_getkeystatus (); grub_dprintf ("keystatus", "mods: %d\n", mods); diff --git a/commands/sleep.c b/commands/sleep.c index a2caad89a..012181fa2 100644 --- a/commands/sleep.c +++ b/commands/sleep.c @@ -33,12 +33,12 @@ static const struct grub_arg_option options[] = {0, 0, 0, 0, 0, 0} }; -static grub_uint8_t x, y; +static grub_uint16_t *pos; static void do_print (int n) { - grub_gotoxy (x, y); + grub_term_restore_pos (pos); /* NOTE: Do not remove the trailing space characters. They are required to clear the line. */ grub_printf ("%d ", n); @@ -64,7 +64,6 @@ static grub_err_t grub_cmd_sleep (grub_extcmd_t cmd, int argc, char **args) { struct grub_arg_list *state = cmd->state; - grub_uint16_t xy; int n; if (argc != 1) @@ -78,9 +77,7 @@ grub_cmd_sleep (grub_extcmd_t cmd, int argc, char **args) return 0; } - xy = grub_getxy (); - x = xy >> 8; - y = xy & 0xff; + pos = grub_term_save_pos (); for (; n; n--) { diff --git a/commands/terminal.c b/commands/terminal.c new file mode 100644 index 000000000..b30f43130 --- /dev/null +++ b/commands/terminal.c @@ -0,0 +1,364 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +struct grub_term_autoload *grub_term_input_autoload = NULL; +struct grub_term_autoload *grub_term_output_autoload = NULL; + +static grub_err_t +grub_cmd_terminal_input (grub_command_t cmd __attribute__ ((unused)), + int argc, char **args) +{ + int i; + grub_term_input_t term; + struct grub_term_autoload *aut; + + if (argc == 0) + { + grub_puts_ (N_ ("Active input terminals:")); + FOR_ACTIVE_TERM_INPUTS(term) + grub_printf ("%s ", term->name); + grub_printf ("\n"); + grub_puts_ (N_ ("Available input terminals:")); + FOR_DISABLED_TERM_INPUTS(term) + grub_printf ("%s ", term->name); + /* This is quadratic but we don't expect mode than 30 terminal + modules ever. */ + for (aut = grub_term_input_autoload; aut; aut = aut->next) + { + FOR_DISABLED_TERM_INPUTS(term) + if (grub_strcmp (term->name, aut->name) == 0) + break; + if (!term) + FOR_ACTIVE_TERM_INPUTS(term) + if (grub_strcmp (term->name, aut->name) == 0) + break; + if (!term) + grub_printf ("%s ", aut->name); + } + grub_printf ("\n"); + return GRUB_ERR_NONE; + } + i = 0; + + if (grub_strcmp (args[0], "--append") == 0 + || grub_strcmp (args[0], "--remove") == 0) + i++; + + if (i == argc) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_ ("no terminal specified")); + + for (; i < argc; i++) + { + int again = 0; + while (1) + { + FOR_DISABLED_TERM_INPUTS(term) + if (grub_strcmp (args[i], term->name) == 0) + break; + if (term == 0) + FOR_ACTIVE_TERM_INPUTS(term) + if (grub_strcmp (args[i], term->name) == 0) + break; + if (term) + break; + if (again) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminal '%s'\n", + args[i]); + for (aut = grub_term_input_autoload; aut; aut = aut->next) + if (grub_strcmp (args[i], aut->name) == 0) + { + grub_dl_t mod; + mod = grub_dl_load (aut->modname); + if (mod) + grub_dl_ref (mod); + grub_errno = GRUB_ERR_NONE; + break; + } + if (!aut) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminal '%s'\n", + args[i]); + again = 1; + } + } + + if (grub_strcmp (args[0], "--append") == 0) + { + for (i = 1; i < argc; i++) + { + FOR_DISABLED_TERM_INPUTS(term) + if (grub_strcmp (args[i], term->name) == 0) + break; + if (term) + { + grub_list_remove (GRUB_AS_LIST_P (&(grub_term_inputs_disabled)), + GRUB_AS_LIST (term)); + if (term->init) + term->init (); + grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs), + GRUB_AS_LIST (term)); + } + } + return GRUB_ERR_NONE; + } + + if (grub_strcmp (args[0], "--remove") == 0) + { + for (i = 1; i < argc; i++) + { + FOR_ACTIVE_TERM_INPUTS(term) + if (grub_strcmp (args[i], term->name) == 0) + break; + if (term) + { + if (!term->next && term == grub_term_inputs) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "can't remove the last terminal"); + grub_list_remove (GRUB_AS_LIST_P (&(grub_term_inputs)), + GRUB_AS_LIST (term)); + if (term->fini) + term->fini (); + grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs_disabled), + GRUB_AS_LIST (term)); + } + } + return GRUB_ERR_NONE; + } + for (i = 0; i < argc; i++) + { + FOR_DISABLED_TERM_INPUTS(term) + if (grub_strcmp (args[i], term->name) == 0) + break; + if (term) + { + grub_list_remove (GRUB_AS_LIST_P (&(grub_term_inputs_disabled)), + GRUB_AS_LIST (term)); + if (term->init) + term->init (); + grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs), + GRUB_AS_LIST (term)); + } + } + + FOR_ACTIVE_TERM_INPUTS(term) + { + for (i = 0; i < argc; i++) + if (grub_strcmp (args[i], term->name) == 0) + break; + if (i == argc) + { + if (!term->next && term == grub_term_inputs) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "can't remove the last terminal"); + grub_list_remove (GRUB_AS_LIST_P (&(grub_term_inputs)), + GRUB_AS_LIST (term)); + if (term->fini) + term->fini (); + grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs_disabled), + GRUB_AS_LIST (term)); + } + } + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_terminal_output (grub_command_t cmd __attribute__ ((unused)), + int argc, char **args) +{ + int i; + grub_term_output_t term; + struct grub_term_autoload *aut; + + if (argc == 0) + { + grub_puts_ (N_ ("Active output terminals:")); + FOR_ACTIVE_TERM_OUTPUTS(term) + grub_printf ("%s ", term->name); + grub_printf ("\n"); + grub_puts_ (N_ ("Available output terminals:")); + FOR_DISABLED_TERM_OUTPUTS(term) + grub_printf ("%s ", term->name); + /* This is quadratic but we don't expect mode than 30 terminal + modules ever. */ + for (aut = grub_term_output_autoload; aut; aut = aut->next) + { + FOR_DISABLED_TERM_OUTPUTS(term) + if (grub_strcmp (term->name, aut->name) == 0) + break; + if (!term) + FOR_ACTIVE_TERM_OUTPUTS(term) + if (grub_strcmp (term->name, aut->name) == 0) + break; + if (!term) + grub_printf ("%s ", aut->name); + } + grub_printf ("\n"); + return GRUB_ERR_NONE; + } + i = 0; + + if (grub_strcmp (args[0], "--append") == 0 + || grub_strcmp (args[0], "--remove") == 0) + i++; + + if (i == argc) + return grub_error (GRUB_ERR_BAD_ARGUMENT, N_ ("no terminal specified")); + + for (; i < argc; i++) + { + int again = 0; + while (1) + { + FOR_DISABLED_TERM_OUTPUTS(term) + if (grub_strcmp (args[i], term->name) == 0) + break; + if (term == 0) + FOR_ACTIVE_TERM_OUTPUTS(term) + if (grub_strcmp (args[i], term->name) == 0) + break; + if (term) + break; + if (again) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminal '%s'\n", + args[i]); + for (aut = grub_term_output_autoload; aut; aut = aut->next) + if (grub_strcmp (args[i], aut->name) == 0) + { + grub_dl_t mod; + mod = grub_dl_load (aut->modname); + if (mod) + grub_dl_ref (mod); + grub_errno = GRUB_ERR_NONE; + break; + } + if (!aut) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminal '%s'\n", + args[i]); + again = 1; + } + } + + if (grub_strcmp (args[0], "--append") == 0) + { + for (i = 1; i < argc; i++) + { + FOR_DISABLED_TERM_OUTPUTS(term) + if (grub_strcmp (args[i], term->name) == 0) + break; + if (term) + { + grub_list_remove (GRUB_AS_LIST_P (&(grub_term_outputs_disabled)), + GRUB_AS_LIST (term)); + if (term->init) + term->init (); + grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs), + GRUB_AS_LIST (term)); + } + } + return GRUB_ERR_NONE; + } + + if (grub_strcmp (args[0], "--remove") == 0) + { + for (i = 1; i < argc; i++) + { + FOR_ACTIVE_TERM_OUTPUTS(term) + if (grub_strcmp (args[i], term->name) == 0) + break; + if (term) + { + if (!term->next && term == grub_term_outputs) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "can't remove the last terminal"); + grub_list_remove (GRUB_AS_LIST_P (&(grub_term_outputs)), + GRUB_AS_LIST (term)); + if (term->fini) + term->fini (); + grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs_disabled), + GRUB_AS_LIST (term)); + } + } + return GRUB_ERR_NONE; + } + + for (i = 0; i < argc; i++) + { + FOR_DISABLED_TERM_OUTPUTS(term) + if (grub_strcmp (args[i], term->name) == 0) + break; + if (term) + { + grub_list_remove (GRUB_AS_LIST_P (&(grub_term_outputs_disabled)), + GRUB_AS_LIST (term)); + if (term->init) + term->init (); + grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs), + GRUB_AS_LIST (term)); + } + } + + FOR_ACTIVE_TERM_OUTPUTS(term) + { + for (i = 0; i < argc; i++) + if (grub_strcmp (args[i], term->name) == 0) + break; + if (i == argc) + { + if (!term->next && term == grub_term_outputs) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "can't remove the last terminal"); + grub_list_remove (GRUB_AS_LIST_P (&(grub_term_outputs)), + GRUB_AS_LIST (term)); + if (term->fini) + term->fini (); + grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs_disabled), + GRUB_AS_LIST (term)); + } + } + + return GRUB_ERR_NONE; +} + +static grub_command_t cmd_terminal_input, cmd_terminal_output; + +GRUB_MOD_INIT(terminal) +{ + cmd_terminal_input = + grub_register_command ("terminal_input", grub_cmd_terminal_input, + "[--append|--remove] " + "[TERMINAL1] [TERMINAL2] ...", + "List or select an input terminal."); + cmd_terminal_output = + grub_register_command ("terminal_output", grub_cmd_terminal_output, + "[--append|--remove] " + "[TERMINAL1] [TERMINAL2] ...", + "List or select an output terminal."); +} + +GRUB_MOD_FINI(terminal) +{ + grub_unregister_command (cmd_terminal_input); + grub_unregister_command (cmd_terminal_output); +} diff --git a/commands/videotest.c b/commands/videotest.c index 850639bd9..1730a2031 100644 --- a/commands/videotest.c +++ b/commands/videotest.c @@ -31,9 +31,7 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - if (grub_video_set_mode ("1024x768;800x600;640x480", 0) != GRUB_ERR_NONE) - return grub_errno; - + grub_err_t err; grub_video_color_t color; unsigned int x; unsigned int y; @@ -50,6 +48,10 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), const char *str; int texty; + err = grub_video_set_mode ("auto", GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0); + if (err) + return err; + grub_video_get_viewport (&x, &y, &width, &height); grub_video_create_render_target (&text_layer, width, height, @@ -153,12 +155,13 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); - for (i = 0; i < 255; i++) + for (i = 0; i < 5; i++) { color = grub_video_map_rgb (i, 33, 77); grub_video_fill_rect (color, 0, 0, width, height); grub_video_blit_render_target (text_layer, GRUB_VIDEO_BLIT_BLEND, 0, 0, 0, 0, width, height); + grub_video_swap_buffers (); } grub_getkey (); diff --git a/conf/any-emu.rmk b/conf/any-emu.rmk index 82eef8270..cee9e8338 100644 --- a/conf/any-emu.rmk +++ b/conf/any-emu.rmk @@ -23,13 +23,14 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c \ kern/err.c kern/list.c kern/handler.c \ kern/command.c kern/corecmd.c commands/extcmd.c kern/file.c \ kern/fs.c commands/boot.c kern/main.c kern/misc.c kern/parser.c \ - kern/partition.c kern/reader.c kern/term.c \ + kern/partition.c kern/term.c \ kern/rescue_reader.c kern/rescue_parser.c \ lib/arg.c normal/cmdline.c normal/datetime.c normal/misc.c \ normal/handler.c normal/auth.c lib/crypto.c normal/autofs.c \ normal/completion.c normal/main.c normal/color.c \ - normal/menu.c normal/menu_entry.c normal/menu_viewer.c \ - normal/menu_text.c normal/crypto.c \ + normal/menu.c normal/menu_entry.c \ + normal/menu_text.c normal/crypto.c normal/term.c \ + commands/terminal.c lib/charset.c \ script/main.c script/execute.c script/function.c \ script/lexer.c script/script.c grub_script.tab.c \ partmap/amiga.c partmap/apple.c partmap/msdos.c partmap/sun.c \ diff --git a/conf/common.rmk b/conf/common.rmk index 83464d3dd..ffcdf045c 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -206,6 +206,20 @@ CLEANFILES += $(grub-mkconfig_SCRIPTS) grub-mkconfig_DATA += util/grub.d/README +# For grub-set-default. +grub-set-default: util/grub-set-default.in config.status + ./config.status --file=$@:$< + chmod +x $@ +sbin_SCRIPTS += grub-set-default +CLEANFILES += grub-set-default + +# For grub-reboot. +grub-reboot: util/grub-reboot.in config.status + ./config.status --file=$@:$< + chmod +x $@ +sbin_SCRIPTS += grub-reboot +CLEANFILES += grub-reboot + # Filing systems. pkglib_MODULES += fshelp.mod fat.mod ufs1.mod ufs2.mod ext2.mod ntfs.mod \ ntfscomp.mod minix.mod hfs.mod jfs.mod iso9660.mod xfs.mod \ @@ -570,8 +584,8 @@ keystatus_mod_LDFLAGS = $(COMMON_LDFLAGS) normal_mod_SOURCES = normal/main.c normal/cmdline.c normal/dyncmd.c \ normal/auth.c normal/autofs.c normal/handler.c \ normal/color.c normal/completion.c normal/datetime.c normal/menu.c \ - normal/menu_entry.c normal/menu_text.c normal/menu_viewer.c \ - normal/misc.c normal/crypto.c + normal/menu_entry.c normal/menu_text.c \ + normal/misc.c normal/crypto.c normal/term.c normal_mod_CFLAGS = $(COMMON_CFLAGS) normal_mod_LDFLAGS = $(COMMON_LDFLAGS) @@ -672,6 +686,11 @@ charset_mod_SOURCES = lib/charset.c charset_mod_CFLAGS = $(COMMON_CFLAGS) charset_mod_LDFLAGS = $(COMMON_LDFLAGS) +pkglib_MODULES += terminal.mod +terminal_mod_SOURCES = commands/terminal.c +terminal_mod_CFLAGS = $(COMMON_CFLAGS) +terminal_mod_LDFLAGS = $(COMMON_LDFLAGS) + pkglib_MODULES += crypto.mod crypto_mod_SOURCES = lib/crypto.c crypto_mod_CFLAGS = $(COMMON_CFLAGS) diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk index 797b29daf..57fb3350c 100644 --- a/conf/i386-coreboot.rmk +++ b/conf/i386-coreboot.rmk @@ -21,7 +21,7 @@ kernel_img_SOURCES = kern/i386/coreboot/startup.S \ kern/i386/halt.c \ kern/main.c kern/device.c \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ - kern/misc.c kern/mm.c kern/reader.c kern/term.c \ + kern/misc.c kern/mm.c kern/term.c \ kern/rescue_parser.c kern/rescue_reader.c \ kern/time.c kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ kern/$(target_cpu)/dl.c kern/parser.c kern/partition.c \ @@ -65,7 +65,7 @@ kernel_img_SOURCES = kern/i386/qemu/startup.S \ kern/i386/halt.c \ kern/main.c kern/device.c \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ - kern/misc.c kern/mm.c kern/reader.c kern/term.c \ + kern/misc.c kern/mm.c kern/term.c \ kern/rescue_parser.c kern/rescue_reader.c \ kern/time.c kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ kern/$(target_cpu)/dl.c kern/parser.c kern/partition.c \ @@ -140,20 +140,6 @@ serial_mod_SOURCES = term/i386/pc/serial.c serial_mod_CFLAGS = $(COMMON_CFLAGS) serial_mod_LDFLAGS = $(COMMON_LDFLAGS) -pkglib_MODULES += multiboot.mod -multiboot_mod_SOURCES = loader/i386/multiboot.c \ - loader/multiboot_loader.c -multiboot_mod_CFLAGS = $(COMMON_CFLAGS) -multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS) -multiboot_mod_ASFLAGS = $(COMMON_ASFLAGS) - -pkglib_MODULES += multiboot2.mod -multiboot2_mod_SOURCES = loader/i386/multiboot.c \ - loader/multiboot_loader.c -multiboot2_mod_CFLAGS = $(COMMON_CFLAGS) -DGRUB_USE_MULTIBOOT2 -multiboot2_mod_LDFLAGS = $(COMMON_LDFLAGS) -multiboot2_mod_ASFLAGS = $(COMMON_ASFLAGS) - # For aout.mod. aout_mod_SOURCES = loader/aout.c aout_mod_CFLAGS = $(COMMON_CFLAGS) diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk index 3a219e71b..f3281a1bc 100644 --- a/conf/i386-efi.rmk +++ b/conf/i386-efi.rmk @@ -39,7 +39,7 @@ pkglib_MODULES = kernel.img chain.mod appleldr.mod \ kernel_img_EXPORTS = no kernel_img_SOURCES = kern/i386/efi/startup.S kern/main.c kern/device.c \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ - kern/misc.c kern/mm.c kern/reader.c kern/term.c \ + kern/misc.c kern/mm.c kern/term.c \ kern/rescue_parser.c kern/rescue_reader.c \ kern/$(target_cpu)/dl.c kern/i386/efi/init.c kern/parser.c kern/partition.c \ kern/env.c symlist.c kern/efi/efi.c kern/efi/init.c kern/efi/mm.c \ diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk index 2a90fd2be..5c3a5aaf6 100644 --- a/conf/i386-ieee1275.rmk +++ b/conf/i386-ieee1275.rmk @@ -19,7 +19,7 @@ kernel_img_SOURCES = kern/i386/ieee1275/startup.S \ kern/ieee1275/cmain.c kern/ieee1275/openfw.c \ kern/main.c kern/device.c \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ - kern/misc.c kern/mm.c kern/reader.c kern/term.c \ + kern/misc.c kern/mm.c kern/term.c \ kern/rescue_parser.c kern/rescue_reader.c \ kern/$(target_cpu)/dl.c kern/parser.c kern/partition.c \ kern/env.c \ diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index e02ee4665..a89203dea 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -48,7 +48,7 @@ kernel_img_SOURCES = kern/i386/pc/startup.S \ kern/i386/misc.S \ kern/main.c kern/device.c \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ - kern/misc.c kern/mm.c kern/reader.c kern/term.c \ + kern/misc.c kern/mm.c kern/term.c \ kern/rescue_parser.c kern/rescue_reader.c \ kern/time.c kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ kern/$(target_cpu)/dl.c kern/i386/pc/init.c kern/i386/pc/mmap.c \ @@ -201,20 +201,6 @@ serial_mod_SOURCES = term/i386/pc/serial.c serial_mod_CFLAGS = $(COMMON_CFLAGS) serial_mod_LDFLAGS = $(COMMON_LDFLAGS) -pkglib_MODULES += multiboot.mod -multiboot_mod_SOURCES = loader/i386/multiboot.c \ - loader/multiboot_loader.c -multiboot_mod_CFLAGS = $(COMMON_CFLAGS) -multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS) -multiboot_mod_ASFLAGS = $(COMMON_ASFLAGS) - -pkglib_MODULES += multiboot2.mod -multiboot2_mod_SOURCES = loader/i386/multiboot.c \ - loader/multiboot_loader.c -multiboot2_mod_CFLAGS = $(COMMON_CFLAGS) -DGRUB_USE_MULTIBOOT2 -multiboot2_mod_LDFLAGS = $(COMMON_LDFLAGS) -multiboot2_mod_ASFLAGS = $(COMMON_ASFLAGS) - # For vbe.mod. vbe_mod_SOURCES = video/i386/pc/vbe.c vbe_mod_CFLAGS = $(COMMON_CFLAGS) diff --git a/conf/i386.rmk b/conf/i386.rmk index c3f036d0f..7ef337c61 100644 --- a/conf/i386.rmk +++ b/conf/i386.rmk @@ -25,3 +25,19 @@ pkglib_MODULES += ata.mod ata_mod_SOURCES = disk/ata.c ata_mod_CFLAGS = $(COMMON_CFLAGS) ata_mod_LDFLAGS = $(COMMON_LDFLAGS) + +pkglib_MODULES += multiboot.mod +multiboot_mod_SOURCES = loader/i386/multiboot.c \ + loader/i386/multiboot_mbi.c \ + loader/multiboot_loader.c +multiboot_mod_CFLAGS = $(COMMON_CFLAGS) +multiboot_mod_LDFLAGS = $(COMMON_LDFLAGS) +multiboot_mod_ASFLAGS = $(COMMON_ASFLAGS) + +pkglib_MODULES += multiboot2.mod +multiboot2_mod_SOURCES = loader/i386/multiboot.c \ + loader/i386/multiboot_mbi.c \ + loader/multiboot_loader.c +multiboot2_mod_CFLAGS = $(COMMON_CFLAGS) -DGRUB_USE_MULTIBOOT2 +multiboot2_mod_LDFLAGS = $(COMMON_LDFLAGS) +multiboot2_mod_ASFLAGS = $(COMMON_ASFLAGS) diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk index 000434f33..854ad50b7 100644 --- a/conf/powerpc-ieee1275.rmk +++ b/conf/powerpc-ieee1275.rmk @@ -31,7 +31,7 @@ pkglib_PROGRAMS = kernel.img kernel_img_SOURCES = kern/powerpc/ieee1275/startup.S kern/ieee1275/cmain.c \ kern/ieee1275/ieee1275.c kern/main.c kern/device.c \ kern/disk.c kern/dl.c kern/err.c kern/file.c kern/fs.c \ - kern/misc.c kern/mm.c kern/reader.c kern/term.c \ + kern/misc.c kern/mm.c kern/term.c \ kern/rescue_parser.c kern/rescue_reader.c \ kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ kern/ieee1275/init.c \ diff --git a/conf/sparc64-ieee1275.rmk b/conf/sparc64-ieee1275.rmk index 9d020a84f..4ba098619 100644 --- a/conf/sparc64-ieee1275.rmk +++ b/conf/sparc64-ieee1275.rmk @@ -35,7 +35,7 @@ kernel_img_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \ kernel_img_SOURCES = kern/sparc64/ieee1275/crt0.S kern/ieee1275/cmain.c \ kern/ieee1275/ieee1275.c kern/main.c kern/device.c \ kern/disk.c kern/dl.c kern/err.c kern/file.c kern/fs.c \ - kern/misc.c kern/mm.c kern/reader.c kern/term.c \ + kern/misc.c kern/mm.c kern/term.c \ kern/rescue_parser.c kern/rescue_reader.c \ kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ kern/sparc64/ieee1275/ieee1275.c \ diff --git a/conf/tests.rmk b/conf/tests.rmk new file mode 100644 index 000000000..18b23ff5a --- /dev/null +++ b/conf/tests.rmk @@ -0,0 +1,50 @@ +# -*- makefile -*- + +# For grub-shell +grub-shell: tests/util/grub-shell.in config.status + ./config.status --file=$@:$< + chmod +x $@ +check_SCRIPTS += grub-shell +CLEANFILES += grub-shell + +# For grub-shell-tester +grub-shell-tester: tests/util/grub-shell-tester.in config.status + ./config.status --file=$@:$< + chmod +x $@ +check_SCRIPTS += grub-shell-tester +CLEANFILES += grub-shell-tester + +pkglib_MODULES += functional_test.mod +functional_test_mod_SOURCES = tests/lib/functional_test.c tests/lib/test.c +functional_test_mod_CFLAGS = $(COMMON_CFLAGS) +functional_test_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# Rules for unit tests +check_UTILITIES += example_unit_test +example_unit_test_SOURCES = tests/example_unit_test.c kern/list.c kern/misc.c tests/lib/test.c tests/lib/unit_test.c +example_unit_test_CFLAGS = -Wno-format + +# Rules for functional tests +pkglib_MODULES += example_functional_test.mod +example_functional_test_mod_SOURCES = tests/example_functional_test.c +example_functional_test_mod_CFLAGS = -Wno-format $(COMMON_CFLAGS) +example_functional_test_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# Rules for scripted tests +check_SCRIPTS += example_scripted_test +example_scripted_test_SOURCES = tests/example_scripted_test.in + +check_SCRIPTS += example_grub_script_test +example_grub_script_test_SOURCES = tests/example_grub_script_test.in + + +# List of tests to execute on "make check" +SCRIPTED_TESTS = example_scripted_test +SCRIPTED_TESTS += example_grub_script_test +UNIT_TESTS = example_unit_test +FUNCTIONAL_TESTS = example_functional_test.mod + +# dependencies between tests and testing-tools +$(SCRIPTED_TESTS): grub-shell grub-shell-tester +$(FUNCTIONAL_TESTS): functional_test.mod + diff --git a/conf/x86_64-efi.rmk b/conf/x86_64-efi.rmk index a82b35222..122700711 100644 --- a/conf/x86_64-efi.rmk +++ b/conf/x86_64-efi.rmk @@ -32,14 +32,14 @@ grub_install_SOURCES = util/i386/efi/grub-install.in pkglib_MODULES = kernel.img chain.mod appleldr.mod \ halt.mod reboot.mod linux.mod pci.mod lspci.mod \ datetime.mod date.mod datehook.mod loadbios.mod \ - fixvideo.mod mmap.mod acpi.mod ata.mod + fixvideo.mod mmap.mod acpi.mod # For kernel.img. kernel_img_EXPORTS = no kernel_img_SOURCES = kern/x86_64/efi/startup.S kern/x86_64/efi/callwrap.S \ kern/main.c kern/device.c \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ - kern/misc.c kern/mm.c kern/reader.c kern/term.c \ + kern/misc.c kern/mm.c kern/term.c \ kern/rescue_parser.c kern/rescue_reader.c \ kern/$(target_cpu)/dl.c kern/i386/efi/init.c kern/parser.c kern/partition.c \ kern/env.c symlist.c kern/efi/efi.c kern/efi/init.c kern/efi/mm.c \ @@ -77,11 +77,6 @@ acpi_mod_SOURCES = commands/acpi.c commands/efi/acpi.c acpi_mod_CFLAGS = $(COMMON_CFLAGS) acpi_mod_LDFLAGS = $(COMMON_LDFLAGS) -# For ata.mod -ata_mod_SOURCES = disk/ata.c -ata_mod_CFLAGS = $(COMMON_CFLAGS) -ata_mod_LDFLAGS = $(COMMON_LDFLAGS) - # For mmap.mod. mmap_mod_SOURCES = mmap/mmap.c mmap/i386/uppermem.c mmap/i386/mmap.c \ mmap/efi/mmap.c @@ -166,10 +161,5 @@ xnu_mod_CFLAGS = $(COMMON_CFLAGS) xnu_mod_LDFLAGS = $(COMMON_LDFLAGS) xnu_mod_ASFLAGS = $(COMMON_ASFLAGS) -pkglib_MODULES += relocator.mod -relocator_mod_SOURCES = lib/i386/relocator.c lib/i386/relocator_asm.S lib/i386/relocator_backward.S -relocator_mod_CFLAGS = $(COMMON_CFLAGS) -relocator_mod_ASFLAGS = $(COMMON_ASFLAGS) -relocator_mod_LDFLAGS = $(COMMON_LDFLAGS) - +include $(srcdir)/conf/i386.mk include $(srcdir)/conf/common.mk diff --git a/genhandlerlist.sh b/genhandlerlist.sh index 6446a98ff..e4cb0d9de 100644 --- a/genhandlerlist.sh +++ b/genhandlerlist.sh @@ -16,8 +16,4 @@ module=$1 grep -v "^#" | sed -n \ - -e "/grub_parser_register *( *\"/{s/.*( *\"\([^\"]*\)\".*/parser.\1: $module/;p;}" \ - -e "/grub_reader_register *( *\"/{s/.*( *\"\([^\"]*\)\".*/reader.\1: $module/;p;}" \ - -e "/grub_term_register_input *( *\"/{s/.*( *\"\([^\"]*\)\".*/terminal_input.\1: $module/;p;}" \ - -e "/grub_term_register_output *( *\"/{s/.*( *\"\([^\"]*\)\".*/terminal_output.\1: $module/;p;}" \ - -e "/grub_menu_viewer_register *( *\"/{s/.*( *\"\([^\"]*\)\".*/menu_viewer.\1: $module/;p;}" + -e "/grub_parser_register *( *\"/{s/.*( *\"\([^\"]*\)\".*/parser.\1: $module/;p;}" diff --git a/genmk.rb b/genmk.rb index b1cce3831..afd1582aa 100644 --- a/genmk.rb +++ b/genmk.rb @@ -192,6 +192,7 @@ endif fs = 'fs-' + obj.suffix('lst') partmap = 'partmap-' + obj.suffix('lst') handler = 'handler-' + obj.suffix('lst') + terminal = 'terminal-' + obj.suffix('lst') parttool = 'parttool-' + obj.suffix('lst') video = 'video-' + obj.suffix('lst') dep = deps[i] @@ -213,6 +214,7 @@ FSFILES += #{fs} PARTTOOLFILES += #{parttool} PARTMAPFILES += #{partmap} HANDLERFILES += #{handler} +TERMINALFILES += #{terminal} VIDEOFILES += #{video} #{command}: #{src} $(#{src}_DEPENDENCIES) gencmdlist.sh @@ -240,6 +242,11 @@ VIDEOFILES += #{video} $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \ | sh $(srcdir)/genhandlerlist.sh #{symbolic_name} > $@ || (rm -f $@; exit 1) +#{terminal}: #{src} $(#{src}_DEPENDENCIES) genterminallist.sh + set -e; \ + $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \ + | sh $(srcdir)/genterminallist.sh #{symbolic_name} > $@ || (rm -f $@; exit 1) + #{video}: #{src} $(#{src}_DEPENDENCIES) genvideolist.sh set -e; \ $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \ @@ -363,8 +370,7 @@ class Script "CLEANFILES += #{@name} #{@name}: #{src} $(#{src}_DEPENDENCIES) config.status - ./config.status --file=#{name}:#{src} - sed -i -e 's,@pkglib_DATA@,$(pkglib_DATA),g' $@ + ./config.status --file=-:#{src} | sed -e 's,@pkglib_DATA@,$(pkglib_DATA),g' > $@ chmod +x $@ " diff --git a/genterminallist.sh b/genterminallist.sh new file mode 100644 index 000000000..60f5b9105 --- /dev/null +++ b/genterminallist.sh @@ -0,0 +1,20 @@ +#! /bin/sh +# +# Copyright (C) 2009,2010 Free Software Foundation, Inc. +# +# This script is free software; the author +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# Read source code from stdin and detect command names. + +module=$1 + +grep -v "^#" | sed -n \ + -e "/grub_term_register_input *( *\"/{s/.*( *\"\([^\"]*\)\".*/i\1: $module/;p;}" \ + -e "/grub_term_register_output *( *\"/{s/.*( *\"\([^\"]*\)\".*/o\1: $module/;p;}" \ diff --git a/gettext/gettext.c b/gettext/gettext.c index 165feb332..83497b7f6 100644 --- a/gettext/gettext.c +++ b/gettext/gettext.c @@ -148,14 +148,24 @@ grub_gettext_translate (const char *orig) struct grub_gettext_msg *cur; + /* Make sure we can use grub_gettext_translate for error messages. Push + active error message to error stack and reset error message. */ + grub_error_push (); + cur = grub_named_list_find (GRUB_AS_NAMED_LIST (grub_gettext_msg_list), orig); if (cur) - return cur->translated; + { + grub_error_pop (); + return cur->translated; + } if (fd_mo == 0) - return orig; + { + grub_error_pop (); + return orig; + } min = 0; max = grub_gettext_max; @@ -205,6 +215,7 @@ grub_gettext_translate (const char *orig) grub_errno = GRUB_ERR_NONE; } + grub_error_pop (); return ret; } @@ -308,7 +319,7 @@ grub_gettext_delete_list (void) char *original = (char *) ((struct grub_gettext_msg *) item)->name; grub_free (original); - // Don't delete the translated message because could be in use. + /* Don't delete the translated message because could be in use. */ } } @@ -347,8 +358,8 @@ GRUB_MOD_INIT (gettext) grub_gettext_init_ext (lang); grub_register_command_p1 ("gettext", grub_cmd_translate, - "STRING", - "Translates the string with the current settings."); + N_("STRING"), + N_("Translates the string with the current settings.")); /* Reload .mo file information if lang changes. */ grub_register_variable_hook ("lang", NULL, grub_gettext_env_write_lang); diff --git a/include/grub/charset.h b/include/grub/charset.h index f85862f8b..fc050da24 100644 --- a/include/grub/charset.h +++ b/include/grub/charset.h @@ -109,4 +109,13 @@ grub_utf16_to_utf8 (grub_uint8_t *dest, grub_uint16_t *src, return dest; } +/* Convert UCS-4 to UTF-8. */ +char *grub_ucs4_to_utf8_alloc (grub_uint32_t *src, grub_size_t size); + +int +grub_is_valid_utf8 (const grub_uint8_t *src, grub_size_t srcsize); + +int grub_utf8_to_ucs4_alloc (const char *msg, grub_uint32_t **unicode_msg, + grub_uint32_t **last_position); + #endif diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h index 8a5a84da3..f02a722d6 100644 --- a/include/grub/i386/linux.h +++ b/include/grub/i386/linux.h @@ -79,9 +79,9 @@ struct grub_e820_mmap grub_uint32_t type; } __attribute__((packed)); -#define GRUB_VIDEO_TYPE_TEXT 0x01 -#define GRUB_VIDEO_TYPE_VLFB 0x23 /* VESA VGA in graphic mode */ -#define GRUB_VIDEO_TYPE_EFI 0x70 +#define GRUB_VIDEO_LINUX_TYPE_TEXT 0x01 +#define GRUB_VIDEO_LINUX_TYPE_VESA 0x23 /* VESA VGA in graphic mode. */ +#define GRUB_VIDEO_LINUX_TYPE_SIMPLE 0x70 /* Linear framebuffer without any additional functions. */ /* For the Linux/i386 boot protocol version 2.03. */ struct linux_kernel_header diff --git a/include/grub/i386/loader.h b/include/grub/i386/loader.h index 0df5f757f..05954b6db 100644 --- a/include/grub/i386/loader.h +++ b/include/grub/i386/loader.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2003,2004,2007,2008,2009 Free Software Foundation, Inc. + * Copyright (C) 2002,2003,2004,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 @@ -31,7 +31,7 @@ extern grub_uint32_t EXPORT_VAR(grub_linux_prot_size); extern char *EXPORT_VAR(grub_linux_tmp_addr); extern char *EXPORT_VAR(grub_linux_real_addr); extern grub_int32_t EXPORT_VAR(grub_linux_is_bzimage); -grub_err_t EXPORT_FUNC(grub_linux16_boot) (void); +grub_err_t EXPORT_FUNC(grub_linux16_real_boot) (void); #endif #endif /* ! GRUB_LOADER_CPU_HEADER */ diff --git a/include/grub/menu_viewer.h b/include/grub/menu_viewer.h index 725c97548..c6513c4e8 100644 --- a/include/grub/menu_viewer.h +++ b/include/grub/menu_viewer.h @@ -24,20 +24,25 @@ #include #include #include +#include struct grub_menu_viewer { - /* The menu viewer name. */ - const char *name; - - grub_err_t (*show_menu) (grub_menu_t menu, int nested); - struct grub_menu_viewer *next; + void *data; + void (*set_chosen_entry) (int entry, void *data); + void (*print_timeout) (int timeout, void *data); + void (*clear_timeout) (void *data); + void (*fini) (void *fini); }; -typedef struct grub_menu_viewer *grub_menu_viewer_t; -void grub_menu_viewer_register (grub_menu_viewer_t viewer); +void grub_menu_register_viewer (struct grub_menu_viewer *viewer); -grub_err_t grub_menu_viewer_show_menu (grub_menu_t menu, int nested); +grub_err_t +grub_menu_try_text (struct grub_term_output *term, + int entry, grub_menu_t menu, int nested); + +extern grub_err_t (*grub_gfxmenu_try_hook) (int entry, grub_menu_t menu, + int nested); #endif /* GRUB_MENU_VIEWER_HEADER */ diff --git a/include/grub/misc.h b/include/grub/misc.h index c5eb953e2..48eb1fcdd 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -199,11 +199,11 @@ int EXPORT_FUNC(grub_sprintf) (char *str, const char *fmt, ...) __attribute__ (( int EXPORT_FUNC(grub_vsprintf) (char *str, const char *fmt, va_list args); void EXPORT_FUNC(grub_exit) (void) __attribute__ ((noreturn)); void EXPORT_FUNC(grub_abort) (void) __attribute__ ((noreturn)); -grub_ssize_t EXPORT_FUNC(grub_utf8_to_ucs4) (grub_uint32_t *dest, - grub_size_t destsize, - const grub_uint8_t *src, - grub_size_t srcsize, - const grub_uint8_t **srcend); +grub_size_t EXPORT_FUNC(grub_utf8_to_ucs4) (grub_uint32_t *dest, + grub_size_t destsize, + const grub_uint8_t *src, + grub_size_t srcsize, + const grub_uint8_t **srcend); grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n, grub_uint32_t d, grub_uint32_t *r); diff --git a/include/grub/multiboot.h b/include/grub/multiboot.h index 041ee1f18..665292e33 100644 --- a/include/grub/multiboot.h +++ b/include/grub/multiboot.h @@ -29,7 +29,22 @@ #include #endif +#include +#include + void grub_multiboot (int argc, char *argv[]); void grub_module (int argc, char *argv[]); +void grub_multiboot_set_accepts_video (int val); + +grub_size_t grub_multiboot_get_mbi_size (void); +grub_err_t grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, + grub_off_t buf_off, grub_size_t bufsize); +void grub_multiboot_free_mbi (void); +grub_err_t grub_multiboot_init_mbi (int argc, char *argv[]); +grub_err_t grub_multiboot_add_module (grub_addr_t start, grub_size_t size, + int argc, char *argv[]); +void grub_multiboot_set_bootdev (void); + + #endif /* ! GRUB_MULTIBOOT_HEADER */ diff --git a/include/grub/normal.h b/include/grub/normal.h index 66b427bcb..58b2c7966 100644 --- a/include/grub/normal.h +++ b/include/grub/normal.h @@ -20,6 +20,7 @@ #ifndef GRUB_NORMAL_HEADER #define GRUB_NORMAL_HEADER 1 +#include #include #include #include @@ -45,21 +46,21 @@ enum grub_completion_type typedef enum grub_completion_type grub_completion_type_t; extern struct grub_menu_viewer grub_normal_text_menu_viewer; - +extern int grub_normal_exit_level; /* Defined in `main.c'. */ void grub_enter_normal_mode (const char *config); void grub_normal_execute (const char *config, int nested, int batch); -void grub_normal_init_page (void); -void grub_menu_init_page (int nested, int edit); +void grub_menu_init_page (int nested, int edit, + struct grub_term_output *term); +void grub_normal_init_page (struct grub_term_output *term); grub_err_t grub_normal_add_menu_entry (int argc, const char **args, const char *sourcecode); char *grub_file_getline (grub_file_t file); void grub_cmdline_run (int nested); /* Defined in `cmdline.c'. */ -int grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len, - int echo_char, int readline, int history); +char *grub_cmdline_get (const char *prompt); grub_err_t grub_set_history (int newsize); /* Defined in `completion.c'. */ @@ -76,14 +77,19 @@ void grub_parse_color_name_pair (grub_uint8_t *ret, const char *name); /* Defined in `menu_text.c'. */ void grub_wait_after_message (void); -int grub_utf8_to_ucs4_alloc (const char *msg, grub_uint32_t **unicode_msg, - grub_uint32_t **last_position); void grub_print_ucs4 (const grub_uint32_t * str, - const grub_uint32_t * last_position); + const grub_uint32_t * last_position, + struct grub_term_output *term); grub_ssize_t grub_getstringwidth (grub_uint32_t * str, - const grub_uint32_t * last_position); + const grub_uint32_t * last_position, + struct grub_term_output *term); void grub_print_message_indented (const char *msg, int margin_left, - int margin_right); + int margin_right, + struct grub_term_output *term); +void +grub_menu_text_register_instances (int entry, grub_menu_t menu, int nested); +grub_err_t +grub_show_menu (grub_menu_t menu, int nested); /* Defined in `handler.c'. */ void read_handler_list (void); @@ -97,6 +103,9 @@ void read_fs_list (void); void read_crypto_list (void); +void read_terminal_list (void); + +void grub_set_more (int onoff); #ifdef GRUB_UTIL void grub_normal_init (void); diff --git a/include/grub/parser.h b/include/grub/parser.h index 41f768bba..17f0c4303 100644 --- a/include/grub/parser.h +++ b/include/grub/parser.h @@ -22,6 +22,7 @@ #include #include +#include #include /* All the states for the command line. */ diff --git a/include/grub/reader.h b/include/grub/reader.h index c7e67bf5e..fd72a3252 100644 --- a/include/grub/reader.h +++ b/include/grub/reader.h @@ -20,60 +20,10 @@ #ifndef GRUB_READER_HEADER #define GRUB_READER_HEADER 1 -#include #include -#include typedef grub_err_t (*grub_reader_getline_t) (char **, int); -struct grub_reader -{ - /* The next reader. */ - struct grub_parser *next; - - /* The reader name. */ - const char *name; - - /* Initialize the reader. */ - grub_err_t (*init) (void); - - /* Clean up the reader. */ - grub_err_t (*fini) (void); - - grub_reader_getline_t read_line; -}; -typedef struct grub_reader *grub_reader_t; - -extern struct grub_handler_class EXPORT_VAR(grub_reader_class); - -grub_err_t EXPORT_FUNC(grub_reader_loop) (grub_reader_getline_t getline); - -static inline void -grub_reader_register (const char *name __attribute__ ((unused)), - grub_reader_t reader) -{ - grub_handler_register (&grub_reader_class, GRUB_AS_HANDLER (reader)); -} - -static inline void -grub_reader_unregister (grub_reader_t reader) -{ - grub_handler_unregister (&grub_reader_class, GRUB_AS_HANDLER (reader)); -} - -static inline grub_reader_t -grub_reader_get_current (void) -{ - return (grub_reader_t) grub_reader_class.cur_handler; -} - -static inline grub_err_t -grub_reader_set_current (grub_reader_t reader) -{ - return grub_handler_set_current (&grub_reader_class, - GRUB_AS_HANDLER (reader)); -} - -void grub_register_rescue_reader (void); +void grub_rescue_run (void); #endif /* ! GRUB_READER_HEADER */ diff --git a/include/grub/term.h b/include/grub/term.h index ec158353d..3d644b848 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2003,2005,2007,2008,2009 Free Software Foundation, Inc. + * Copyright (C) 2002,2003,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 @@ -68,8 +68,6 @@ grub_term_color_state; #define GRUB_TERM_NO_EDIT (1 << 1) /* Set when the terminal cannot do fancy things. */ #define GRUB_TERM_DUMB (1 << 2) -/* Set when the terminal needs to be initialized. */ -#define GRUB_TERM_NEED_INIT (1 << 16) /* Bitmasks for modifier keys returned by grub_getkeystatus. */ @@ -93,10 +91,6 @@ grub_term_color_state; /* Menu-related geometrical constants. */ -/* FIXME: Ugly way to get them form terminal. */ -#define GRUB_TERM_WIDTH ((grub_getwh()&0xFF00)>>8) -#define GRUB_TERM_HEIGHT (grub_getwh()&0xFF) - /* The number of lines of "GRUB version..." at the top. */ #define GRUB_TERM_INFO_HEIGHT 1 @@ -113,37 +107,12 @@ grub_term_color_state; /* The X position of the left border. */ #define GRUB_TERM_LEFT_BORDER_X GRUB_TERM_MARGIN -/* The width of the border. */ -#define GRUB_TERM_BORDER_WIDTH (GRUB_TERM_WIDTH \ - - GRUB_TERM_MARGIN * 3 \ - - GRUB_TERM_SCROLL_WIDTH) - /* The number of lines of messages at the bottom. */ #define GRUB_TERM_MESSAGE_HEIGHT 8 -/* The height of the border. */ -#define GRUB_TERM_BORDER_HEIGHT (GRUB_TERM_HEIGHT \ - - GRUB_TERM_TOP_BORDER_Y \ - - GRUB_TERM_MESSAGE_HEIGHT) - -/* The number of entries shown at a time. */ -#define GRUB_TERM_NUM_ENTRIES (GRUB_TERM_BORDER_HEIGHT - 2) - /* The Y position of the first entry. */ #define GRUB_TERM_FIRST_ENTRY_Y (GRUB_TERM_TOP_BORDER_Y + 1) -/* The max column number of an entry. The last "-1" is for a - continuation marker. */ -#define GRUB_TERM_ENTRY_WIDTH (GRUB_TERM_BORDER_WIDTH - 2 \ - - GRUB_TERM_MARGIN * 2 - 1) - -/* The standard X position of the cursor. */ -#define GRUB_TERM_CURSOR_X (GRUB_TERM_LEFT_BORDER_X \ - + GRUB_TERM_BORDER_WIDTH \ - - GRUB_TERM_MARGIN \ - - 1) - - struct grub_term_input { /* The next terminal. */ @@ -224,86 +193,222 @@ struct grub_term_output }; typedef struct grub_term_output *grub_term_output_t; -extern struct grub_handler_class EXPORT_VAR(grub_term_input_class); -extern struct grub_handler_class EXPORT_VAR(grub_term_output_class); +extern struct grub_term_output *EXPORT_VAR(grub_term_outputs_disabled); +extern struct grub_term_input *EXPORT_VAR(grub_term_inputs_disabled); +extern struct grub_term_output *EXPORT_VAR(grub_term_outputs); +extern struct grub_term_input *EXPORT_VAR(grub_term_inputs); static inline void grub_term_register_input (const char *name __attribute__ ((unused)), grub_term_input_t term) { - grub_handler_register (&grub_term_input_class, GRUB_AS_HANDLER (term)); + if (grub_term_inputs) + grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs_disabled), + GRUB_AS_LIST (term)); + else + { + /* If this is the first terminal, enable automatically. */ + if (term->init) + term->init (); + grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs), GRUB_AS_LIST (term)); + } } static inline void grub_term_register_output (const char *name __attribute__ ((unused)), grub_term_output_t term) { - grub_handler_register (&grub_term_output_class, GRUB_AS_HANDLER (term)); + if (grub_term_outputs) + grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs_disabled), + GRUB_AS_LIST (term)); + else + { + /* If this is the first terminal, enable automatically. */ + if (term->init) + term->init (); + grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs), + GRUB_AS_LIST (term)); + } } static inline void grub_term_unregister_input (grub_term_input_t term) { - grub_handler_unregister (&grub_term_input_class, GRUB_AS_HANDLER (term)); + grub_list_remove (GRUB_AS_LIST_P (&grub_term_inputs), GRUB_AS_LIST (term)); + grub_list_remove (GRUB_AS_LIST_P (&grub_term_inputs_disabled), + GRUB_AS_LIST (term)); } static inline void grub_term_unregister_output (grub_term_output_t term) { - grub_handler_unregister (&grub_term_output_class, GRUB_AS_HANDLER (term)); + grub_list_remove (GRUB_AS_LIST_P (&grub_term_outputs), GRUB_AS_LIST (term)); + grub_list_remove (GRUB_AS_LIST_P (&(grub_term_outputs_disabled)), + GRUB_AS_LIST (term)); } -static inline grub_err_t -grub_term_set_current_input (grub_term_input_t term) -{ - return grub_handler_set_current (&grub_term_input_class, - GRUB_AS_HANDLER (term)); -} - -static inline grub_err_t -grub_term_set_current_output (grub_term_output_t term) -{ - return grub_handler_set_current (&grub_term_output_class, - GRUB_AS_HANDLER (term)); -} - -static inline grub_term_input_t -grub_term_get_current_input (void) -{ - return (grub_term_input_t) grub_term_input_class.cur_handler; -} - -static inline grub_term_output_t -grub_term_get_current_output (void) -{ - return (grub_term_output_t) grub_term_output_class.cur_handler; -} +#define FOR_ACTIVE_TERM_INPUTS(var) for (var = grub_term_inputs; var; var = var->next) +#define FOR_DISABLED_TERM_INPUTS(var) for (var = grub_term_inputs_disabled; var; var = var->next) +#define FOR_ACTIVE_TERM_OUTPUTS(var) for (var = grub_term_outputs; var; var = var->next) +#define FOR_DISABLED_TERM_OUTPUTS(var) for (var = grub_term_outputs_disabled; var; var = var->next) void EXPORT_FUNC(grub_putchar) (int c); -void EXPORT_FUNC(grub_putcode) (grub_uint32_t code); -grub_ssize_t EXPORT_FUNC(grub_getcharwidth) (grub_uint32_t code); +void EXPORT_FUNC(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); -grub_uint16_t EXPORT_FUNC(grub_getwh) (void); -grub_uint16_t EXPORT_FUNC(grub_getxy) (void); -void EXPORT_FUNC(grub_gotoxy) (grub_uint8_t x, grub_uint8_t y); void EXPORT_FUNC(grub_cls) (void); void EXPORT_FUNC(grub_setcolorstate) (grub_term_color_state state); -void EXPORT_FUNC(grub_setcolor) (grub_uint8_t normal_color, - grub_uint8_t highlight_color); -void EXPORT_FUNC(grub_getcolor) (grub_uint8_t *normal_color, - grub_uint8_t *highlight_color); -int EXPORT_FUNC(grub_setcursor) (int on); -int EXPORT_FUNC(grub_getcursor) (void); void EXPORT_FUNC(grub_refresh) (void); -void EXPORT_FUNC(grub_set_more) (int onoff); +void grub_puts_terminal (const char *str, struct grub_term_output *term); +grub_uint16_t *grub_term_save_pos (void); +void grub_term_restore_pos (grub_uint16_t *pos); + +static inline unsigned grub_term_width (struct grub_term_output *term) +{ + return ((term->getwh()&0xFF00)>>8); +} + +static inline unsigned grub_term_height (struct grub_term_output *term) +{ + return (term->getwh()&0xFF); +} + +/* The width of the border. */ +static inline unsigned +grub_term_border_width (struct grub_term_output *term) +{ + return grub_term_width (term) - GRUB_TERM_MARGIN * 3 - GRUB_TERM_SCROLL_WIDTH; +} + +/* The max column number of an entry. The last "-1" is for a + continuation marker. */ +static inline int +grub_term_entry_width (struct grub_term_output *term) +{ + return grub_term_border_width (term) - 2 - GRUB_TERM_MARGIN * 2 - 1; +} + +/* The height of the border. */ + +static inline unsigned +grub_term_border_height (struct grub_term_output *term) +{ + return grub_term_height (term) - GRUB_TERM_TOP_BORDER_Y + - GRUB_TERM_MESSAGE_HEIGHT; +} + +/* The number of entries shown at a time. */ +static inline int +grub_term_num_entries (struct grub_term_output *term) +{ + return grub_term_border_height (term) - 2; +} + +static inline int +grub_term_cursor_x (struct grub_term_output *term) +{ + return (GRUB_TERM_LEFT_BORDER_X + grub_term_border_width (term) + - GRUB_TERM_MARGIN - 1); +} + +static inline grub_uint16_t +grub_term_getxy (struct grub_term_output *term) +{ + return term->getxy (); +} static inline void -grub_print_spaces (int number_spaces) +grub_term_refresh (struct grub_term_output *term) +{ + if (term->refresh) + term->refresh (); +} + +static inline void +grub_term_gotoxy (struct grub_term_output *term, grub_uint8_t x, grub_uint8_t y) +{ + term->gotoxy (x, y); +} + +static inline void +grub_term_setcolorstate (struct grub_term_output *term, + grub_term_color_state state) +{ + if (term->setcolorstate) + term->setcolorstate (state); +} + + /* Set the normal color and the highlight color. The format of each + color is VGA's. */ +static inline void +grub_term_setcolor (struct grub_term_output *term, + grub_uint8_t normal_color, grub_uint8_t highlight_color) +{ + if (term->setcolor) + term->setcolor (normal_color, highlight_color); +} + +/* Turn on/off the cursor. */ +static inline void +grub_term_setcursor (struct grub_term_output *term, int on) +{ + if (term->setcursor) + term->setcursor (on); +} + +static inline void +grub_term_cls (struct grub_term_output *term) +{ + if (term->cls) + (term->cls) (); + else + { + grub_putcode ('\n', term); + grub_term_refresh (term); + } +} + +static inline grub_ssize_t +grub_term_getcharwidth (struct grub_term_output *term, grub_uint32_t c) +{ + if (term->getcharwidth) + return term->getcharwidth (c); + else + return 1; +} + +static inline void +grub_term_getcolor (struct grub_term_output *term, + grub_uint8_t *normal_color, grub_uint8_t *highlight_color) +{ + if (term->getcolor) + term->getcolor (normal_color, highlight_color); + else + { + *normal_color = 0x07; + *highlight_color = 0x07; + } +} + +extern void (*EXPORT_VAR (grub_newline_hook)) (void); + +struct grub_term_autoload +{ + struct grub_term_autoload *next; + char *name; + char *modname; +}; + +extern struct grub_term_autoload *grub_term_input_autoload; +extern struct grub_term_autoload *grub_term_output_autoload; + +static inline void +grub_print_spaces (struct grub_term_output *term, int number_spaces) { while (--number_spaces >= 0) - grub_putchar (' '); + grub_putcode (' ', term); } diff --git a/include/grub/terminfo.h b/include/grub/terminfo.h index 1ea741e04..e3a2c170a 100644 --- a/include/grub/terminfo.h +++ b/include/grub/terminfo.h @@ -21,15 +21,17 @@ #include #include +#include char *grub_terminfo_get_current (void); grub_err_t grub_terminfo_set_current (const char *); -void grub_terminfo_gotoxy (grub_uint8_t x, grub_uint8_t y); -void grub_terminfo_cls (void); -void grub_terminfo_reverse_video_on (void); -void grub_terminfo_reverse_video_off (void); -void grub_terminfo_cursor_on (void); -void grub_terminfo_cursor_off (void); +void grub_terminfo_gotoxy (grub_uint8_t x, grub_uint8_t y, + grub_term_output_t oterm); +void grub_terminfo_cls (grub_term_output_t oterm); +void grub_terminfo_reverse_video_on (grub_term_output_t oterm); +void grub_terminfo_reverse_video_off (grub_term_output_t oterm); +void grub_terminfo_cursor_on (grub_term_output_t oterm); +void grub_terminfo_cursor_off (grub_term_output_t oterm); #endif /* ! GRUB_TERMINFO_HEADER */ diff --git a/include/grub/test.h b/include/grub/test.h new file mode 100644 index 000000000..a7d3a2399 --- /dev/null +++ b/include/grub/test.h @@ -0,0 +1,85 @@ +/* + * 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_TEST_HEADER +#define GRUB_TEST_HEADER + +#include +#include +#include +#include +#include + +struct grub_test +{ + /* The next test. */ + struct grub_test *next; + + /* The test name. */ + char *name; + + /* The test main function. */ + void (*main) (void); +}; +typedef struct grub_test *grub_test_t; + +extern grub_test_t grub_test_list; + +void grub_test_register (const char *name, void (*test) (void)); +void grub_test_unregister (const char *name); + +/* Execute a test and print results. */ +int grub_test_run (grub_test_t test); + +/* Test `cond' for nonzero; log failure otherwise. */ +void grub_test_nonzero (int cond, const char *file, + const char *func, grub_uint32_t line, + const char *fmt, ...) + __attribute__ ((format (printf, 5, 6))); + +/* Macro to fill in location details and an optional error message. */ +#define grub_test_assert(cond, ...) \ + grub_test_nonzero(cond, __FILE__, __FUNCTION__, __LINE__, \ + ## __VA_ARGS__, \ + "assert failed: %s", #cond) + +/* Macro to define a unit test. */ +#define GRUB_UNIT_TEST(name, funp) \ + void grub_unit_test_init (void) \ + { \ + grub_test_register (name, funp); \ + } \ + \ + void grub_unit_test_fini (void) \ + { \ + grub_test_unregister (name); \ + } + +/* Macro to define a functional test. */ +#define GRUB_FUNCTIONAL_TEST(name, funp) \ + GRUB_MOD_INIT(functional_test_##funp) \ + { \ + grub_test_register (name, funp); \ + } \ + \ + GRUB_MOD_FINI(functional_test_##funp) \ + { \ + grub_test_unregister (name); \ + } + +#endif /* ! GRUB_TEST_HEADER */ diff --git a/include/grub/video.h b/include/grub/video.h index 4145db465..fb0151878 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -159,10 +159,19 @@ struct grub_video_palette_data grub_uint8_t a; /* Reserved bits value (0-255). */ }; +typedef enum grub_video_driver_id + { + GRUB_VIDEO_DRIVER_NONE, + GRUB_VIDEO_DRIVER_VBE, + GRUB_VIDEO_DRIVER_EFI_UGA, + GRUB_VIDEO_DRIVER_EFI_GOP + } grub_video_driver_id_t; + struct grub_video_adapter { /* The video adapter name. */ const char *name; + grub_video_driver_id_t id; /* Initialize the video adapter. */ grub_err_t (*init) (void); @@ -171,7 +180,7 @@ 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_type, unsigned int mode_mask); grub_err_t (*get_info) (struct grub_video_mode_info *mode_info); @@ -307,7 +316,17 @@ grub_err_t grub_video_set_active_render_target (struct grub_video_render_target grub_err_t grub_video_get_active_render_target (struct grub_video_render_target **target); grub_err_t grub_video_set_mode (const char *modestring, - int NESTED_FUNC_ATTR (*hook) (grub_video_adapter_t p, - struct grub_video_mode_info *mode_info)); + unsigned int modemask, + unsigned int modevalue); + +static inline int +grub_video_check_mode_flag (unsigned int flags, unsigned int mask, + unsigned int flag, int def) +{ + return (flag & mask) ? !! (flags & flag) : def; +} + +grub_video_driver_id_t +grub_video_get_driver_id (void); #endif /* ! GRUB_VIDEO_HEADER */ diff --git a/include/grub/x86_64/multiboot.h b/include/grub/x86_64/multiboot.h new file mode 100644 index 000000000..957c7a5ad --- /dev/null +++ b/include/grub/x86_64/multiboot.h @@ -0,0 +1 @@ +#include diff --git a/include/multiboot.h b/include/multiboot.h index da7afd9b3..57c154c98 100644 --- a/include/multiboot.h +++ b/include/multiboot.h @@ -85,10 +85,12 @@ #define MULTIBOOT_INFO_APM_TABLE 0x00000400 /* Is there video information? */ -#define MULTIBOOT_INFO_VIDEO_INFO 0x00000800 +#define MULTIBOOT_INFO_VBE_INFO 0x00000800 +#define MULTIBOOT_INFO_FRAMEBUFFER_INFO 0x00001000 #ifndef ASM_FILE +typedef unsigned char multiboot_uint8_t; typedef unsigned short multiboot_uint16_t; typedef unsigned int multiboot_uint32_t; typedef unsigned long long multiboot_uint64_t; @@ -187,9 +189,43 @@ struct multiboot_info multiboot_uint16_t vbe_interface_seg; multiboot_uint16_t vbe_interface_off; multiboot_uint16_t vbe_interface_len; + + multiboot_uint64_t framebuffer_addr; + multiboot_uint32_t framebuffer_pitch; + multiboot_uint32_t framebuffer_width; + multiboot_uint32_t framebuffer_height; + multiboot_uint8_t framebuffer_bpp; +#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0 +#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1 +#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2 + multiboot_uint8_t framebuffer_type; + union + { + struct + { + multiboot_uint32_t framebuffer_palette_addr; + multiboot_uint16_t framebuffer_palette_num_colors; + }; + struct + { + multiboot_uint8_t framebuffer_red_field_position; + multiboot_uint8_t framebuffer_red_mask_size; + multiboot_uint8_t framebuffer_green_field_position; + multiboot_uint8_t framebuffer_green_mask_size; + multiboot_uint8_t framebuffer_blue_field_position; + multiboot_uint8_t framebuffer_blue_mask_size; + }; + }; }; typedef struct multiboot_info multiboot_info_t; +struct multiboot_color +{ + multiboot_uint8_t red; + multiboot_uint8_t green; + multiboot_uint8_t blue; +}; + struct multiboot_mmap_entry { multiboot_uint32_t size; diff --git a/include/multiboot2.h b/include/multiboot2.h index 0488849d7..a241a70ad 100644 --- a/include/multiboot2.h +++ b/include/multiboot2.h @@ -85,10 +85,12 @@ #define MULTIBOOT_INFO_APM_TABLE 0x00000400 /* Is there video information? */ -#define MULTIBOOT_INFO_VIDEO_INFO 0x00000800 +#define MULTIBOOT_INFO_VBE_INFO 0x00000800 +#define MULTIBOOT_INFO_FRAMEBUFFER_INFO 0x00001000 #ifndef ASM_FILE +typedef unsigned char multiboot_uint8_t; typedef unsigned short multiboot_uint16_t; typedef unsigned int multiboot_uint32_t; typedef unsigned long long multiboot_uint64_t; @@ -187,9 +189,43 @@ struct multiboot_info multiboot_uint16_t vbe_interface_seg; multiboot_uint16_t vbe_interface_off; multiboot_uint16_t vbe_interface_len; + + multiboot_uint64_t framebuffer_addr; + multiboot_uint32_t framebuffer_pitch; + multiboot_uint32_t framebuffer_width; + multiboot_uint32_t framebuffer_height; + multiboot_uint8_t framebuffer_bpp; +#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0 +#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1 +#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2 + multiboot_uint8_t framebuffer_type; + union + { + struct + { + multiboot_uint32_t framebuffer_palette_addr; + multiboot_uint16_t framebuffer_palette_num_colors; + }; + struct + { + multiboot_uint8_t framebuffer_red_field_position; + multiboot_uint8_t framebuffer_red_mask_size; + multiboot_uint8_t framebuffer_green_field_position; + multiboot_uint8_t framebuffer_green_mask_size; + multiboot_uint8_t framebuffer_blue_field_position; + multiboot_uint8_t framebuffer_blue_mask_size; + }; + }; }; typedef struct multiboot_info multiboot_info_t; +struct multiboot_color +{ + multiboot_uint8_t red; + multiboot_uint8_t green; + multiboot_uint8_t blue; +}; + struct multiboot_mmap_entry { multiboot_uint32_t size; diff --git a/kern/efi/init.c b/kern/efi/init.c index f9ba03852..8862eb2f9 100644 --- a/kern/efi/init.c +++ b/kern/efi/init.c @@ -82,6 +82,5 @@ void grub_efi_fini (void) { grub_efidisk_fini (); - grub_efi_mm_fini (); grub_console_fini (); } diff --git a/kern/err.c b/kern/err.c index 02d7d879f..1a881db25 100644 --- a/kern/err.c +++ b/kern/err.c @@ -45,7 +45,7 @@ grub_error (grub_err_t n, const char *fmt, ...) grub_errno = n; va_start (ap, fmt); - grub_vsprintf (grub_errmsg, fmt, ap); + grub_vsprintf (grub_errmsg, _(fmt), ap); va_end (ap); return n; @@ -57,7 +57,7 @@ grub_fatal (const char *fmt, ...) va_list ap; va_start (ap, fmt); - grub_vprintf (fmt, ap); + grub_vprintf (_(fmt), ap); va_end (ap); grub_abort (); diff --git a/kern/i386/loader.S b/kern/i386/loader.S index 3e9c71327..ed57c43ca 100644 --- a/kern/i386/loader.S +++ b/kern/i386/loader.S @@ -59,7 +59,7 @@ VARIABLE(grub_linux_real_addr) VARIABLE(grub_linux_is_bzimage) .long 0 -FUNCTION(grub_linux16_boot) +FUNCTION(grub_linux16_real_boot) /* Must be done before zImage copy. */ call EXT_C(grub_dl_unload_all) diff --git a/kern/main.c b/kern/main.c index b3b33e93b..7250c73e0 100644 --- a/kern/main.c +++ b/kern/main.c @@ -169,9 +169,8 @@ grub_main (void) grub_register_core_commands (); grub_register_rescue_parser (); - grub_register_rescue_reader (); grub_load_config (); grub_load_normal_mode (); - grub_reader_loop (0); + grub_rescue_run (); } diff --git a/kern/misc.c b/kern/misc.c index 63007510e..3a2cf9ed9 100644 --- a/kern/misc.c +++ b/kern/misc.c @@ -892,10 +892,10 @@ grub_sprintf (char *str, const char *fmt, ...) /* Convert a (possibly null-terminated) UTF-8 string of at most SRCSIZE bytes (if SRCSIZE is -1, it is ignored) in length to a UCS-4 string. Return the number of characters converted. DEST must be able to hold - at least DESTSIZE characters. If an invalid sequence is found, return -1. + at least DESTSIZE characters. If SRCEND is not NULL, then *SRCEND is set to the next byte after the last byte used in SRC. */ -grub_ssize_t +grub_size_t grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize, const grub_uint8_t *src, grub_size_t srcsize, const grub_uint8_t **srcend) @@ -917,7 +917,8 @@ grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize, if ((c & 0xc0) != 0x80) { /* invalid */ - return -1; + code = '?'; + count = 0; } else { @@ -959,7 +960,11 @@ grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize, code = c & 0x01; } else - return -1; + { + /* invalid */ + code = '?'; + count = 0; + } } if (count == 0) @@ -978,15 +983,14 @@ grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize, void grub_abort (void) { - if (grub_term_get_current_output ()) + grub_printf ("\nAborted."); + +#ifndef GRUB_UTIL + if (grub_term_inputs) +#endif { - grub_printf ("\nAborted."); - - if (grub_term_get_current_input ()) - { - grub_printf (" Press any key to exit."); - grub_getkey (); - } + grub_printf (" Press any key to exit."); + grub_getkey (); } grub_exit (); diff --git a/kern/reader.c b/kern/reader.c deleted file mode 100644 index 271a90f5a..000000000 --- a/kern/reader.c +++ /dev/null @@ -1,49 +0,0 @@ -/* reader.c - reader support */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2009 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GRUB. If not, see . - */ - -#include -#include -#include -#include - -struct grub_handler_class grub_reader_class = - { - .name = "reader" - }; - -grub_err_t -grub_reader_loop (grub_reader_getline_t getline) -{ - while (1) - { - char *line; - grub_reader_getline_t func; - - /* Print an error, if any. */ - grub_print_error (); - grub_errno = GRUB_ERR_NONE; - - func = (getline) ? : grub_reader_get_current ()->read_line; - if ((func (&line, 0)) || (! line)) - return grub_errno; - - grub_parser_get_current ()->parse_line (line, func); - grub_free (line); - } -} diff --git a/kern/rescue_reader.c b/kern/rescue_reader.c index 2a06f3fc2..732124b1a 100644 --- a/kern/rescue_reader.c +++ b/kern/rescue_reader.c @@ -19,20 +19,15 @@ #include #include +#include #include #include +#include #define GRUB_RESCUE_BUF_SIZE 256 static char linebuf[GRUB_RESCUE_BUF_SIZE]; -static grub_err_t -grub_rescue_init (void) -{ - grub_printf ("Entering rescue mode...\n"); - return 0; -} - /* Prompt to input a command and read the line. */ static grub_err_t grub_rescue_read_line (char **line, int cont) @@ -74,15 +69,24 @@ grub_rescue_read_line (char **line, int cont) return 0; } -static struct grub_reader grub_rescue_reader = - { - .name = "rescue", - .init = grub_rescue_init, - .read_line = grub_rescue_read_line - }; - void -grub_register_rescue_reader (void) +grub_rescue_run (void) { - grub_reader_register ("rescue", &grub_rescue_reader); + grub_printf ("Entering rescue mode...\n"); + + while (1) + { + char *line; + + /* Print an error, if any. */ + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + + grub_rescue_read_line (&line, 0); + if (! line) + continue; + + grub_parser_get_current ()->parse_line (line, grub_rescue_read_line); + grub_free (line); + } } diff --git a/kern/term.c b/kern/term.c index 94d5a9e1d..50fbbf302 100644 --- a/kern/term.c +++ b/kern/term.c @@ -21,79 +21,33 @@ #include #include #include +#include -/* The amount of lines counted by the pager. */ -static int grub_more_lines; +struct grub_term_output *grub_term_outputs_disabled; +struct grub_term_input *grub_term_inputs_disabled; +struct grub_term_output *grub_term_outputs; +struct grub_term_input *grub_term_inputs; -/* If the more pager is active. */ -static int grub_more; - -/* The current cursor state. */ -static int cursor_state = 1; - -struct grub_handler_class grub_term_input_class = - { - .name = "terminal_input" - }; - -struct grub_handler_class grub_term_output_class = - { - .name = "terminal_output" - }; - -#define grub_cur_term_input grub_term_get_current_input () -#define grub_cur_term_output grub_term_get_current_output () +void (*grub_newline_hook) (void) = NULL; /* Put a Unicode character. */ void -grub_putcode (grub_uint32_t code) +grub_putcode (grub_uint32_t code, struct grub_term_output *term) { - int height = grub_getwh () & 255; - - if (code == '\t' && grub_cur_term_output->getxy) + if (code == '\t' && term->getxy) { int n; - n = 8 - ((grub_getxy () >> 8) & 7); + n = 8 - ((term->getxy () >> 8) & 7); while (n--) - grub_putcode (' '); + grub_putcode (' ', term); return; } - (grub_cur_term_output->putchar) (code); - + (term->putchar) (code); if (code == '\n') - { - grub_putcode ('\r'); - - grub_more_lines++; - - if (grub_more && grub_more_lines == height - 1) - { - char key; - int pos = grub_getxy (); - - /* Show --MORE-- on the lower left side of the screen. */ - grub_gotoxy (1, height - 1); - grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT); - grub_printf ("--MORE--"); - grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); - - key = grub_getkey (); - - /* Remove the message. */ - grub_gotoxy (1, height - 1); - grub_printf (" "); - grub_gotoxy (pos >> 8, pos & 0xFF); - - /* Scroll one lines or an entire page, depending on the key. */ - if (key == '\r' || key =='\n') - grub_more_lines--; - else - grub_more_lines = 0; - } - } + (term->putchar) ('\r'); } /* Put a character. C is one byte of a UTF-8 stream. @@ -104,136 +58,101 @@ grub_putchar (int c) static grub_size_t size = 0; static grub_uint8_t buf[6]; grub_uint32_t code; - grub_ssize_t ret; + grub_size_t ret; buf[size++] = c; ret = grub_utf8_to_ucs4 (&code, 1, buf, size, 0); - if (ret > 0) + if (ret != 0) { + struct grub_term_output *term; size = 0; - grub_putcode (code); + FOR_ACTIVE_TERM_OUTPUTS(term) + grub_putcode (code, term); + if (code == '\n' && grub_newline_hook) + grub_newline_hook (); } - else if (ret < 0) - { - size = 0; - grub_putcode ('?'); - } -} - -/* Return the number of columns occupied by the character code CODE. */ -grub_ssize_t -grub_getcharwidth (grub_uint32_t code) -{ - return (grub_cur_term_output->getcharwidth) (code); } int grub_getkey (void) { - return (grub_cur_term_input->getkey) (); + grub_term_input_t term; + + while (1) + { + FOR_ACTIVE_TERM_INPUTS(term) + { + int key = term->checkkey (); + if (key != -1) + return term->getkey (); + } + + grub_cpu_idle (); + } } int grub_checkkey (void) { - return (grub_cur_term_input->checkkey) (); + grub_term_input_t term; + + FOR_ACTIVE_TERM_INPUTS(term) + { + int key = term->checkkey (); + if (key != -1) + return key; + } + + return -1; } int grub_getkeystatus (void) { - if (grub_cur_term_input->getkeystatus) - return (grub_cur_term_input->getkeystatus) (); - else - return 0; -} + int status = 0; + grub_term_input_t term; -grub_uint16_t -grub_getxy (void) -{ - return (grub_cur_term_output->getxy) (); -} + FOR_ACTIVE_TERM_INPUTS(term) + { + if (term->getkeystatus) + status |= term->getkeystatus (); + } -grub_uint16_t -grub_getwh (void) -{ - return (grub_cur_term_output->getwh) (); -} - -void -grub_gotoxy (grub_uint8_t x, grub_uint8_t y) -{ - (grub_cur_term_output->gotoxy) (x, y); + return status; } void grub_cls (void) { - if ((grub_cur_term_output->flags & GRUB_TERM_DUMB) || (grub_env_get ("debug"))) - { - grub_putchar ('\n'); - grub_refresh (); - } - else - (grub_cur_term_output->cls) (); + struct grub_term_output *term; + + FOR_ACTIVE_TERM_OUTPUTS(term) + { + if ((term->flags & GRUB_TERM_DUMB) || (grub_env_get ("debug"))) + { + grub_putcode ('\n', term); + grub_term_refresh (term); + } + else + (term->cls) (); + } } void grub_setcolorstate (grub_term_color_state state) { - if (grub_cur_term_output->setcolorstate) - (grub_cur_term_output->setcolorstate) (state); -} - -void -grub_setcolor (grub_uint8_t normal_color, grub_uint8_t highlight_color) -{ - if (grub_cur_term_output->setcolor) - (grub_cur_term_output->setcolor) (normal_color, highlight_color); -} - -void -grub_getcolor (grub_uint8_t *normal_color, grub_uint8_t *highlight_color) -{ - if (grub_cur_term_output->getcolor) - (grub_cur_term_output->getcolor) (normal_color, highlight_color); -} - -int -grub_setcursor (int on) -{ - int ret = cursor_state; - - if (grub_cur_term_output->setcursor) - { - (grub_cur_term_output->setcursor) (on); - cursor_state = on; - } - - return ret; -} - -int -grub_getcursor (void) -{ - return cursor_state; + struct grub_term_output *term; + + FOR_ACTIVE_TERM_OUTPUTS(term) + grub_term_setcolorstate (term, state); } void grub_refresh (void) { - if (grub_cur_term_output->refresh) - (grub_cur_term_output->refresh) (); -} + struct grub_term_output *term; -void -grub_set_more (int onoff) -{ - if (onoff == 1) - grub_more++; - else - grub_more--; - - grub_more_lines = 0; + FOR_ACTIVE_TERM_OUTPUTS(term) + grub_term_refresh (term); } diff --git a/lib/charset.c b/lib/charset.c index 8bc5b9149..f2e1b036d 100644 --- a/lib/charset.c +++ b/lib/charset.c @@ -24,6 +24,8 @@ last byte used in SRC. */ #include +#include +#include grub_ssize_t grub_utf8_to_utf16 (grub_uint16_t *dest, grub_size_t destsize, @@ -114,3 +116,154 @@ grub_utf8_to_utf16 (grub_uint16_t *dest, grub_size_t destsize, *srcend = src; return p - dest; } + +/* Convert UCS-4 to UTF-8. */ +char * +grub_ucs4_to_utf8_alloc (grub_uint32_t *src, grub_size_t size) +{ + grub_size_t remaining; + grub_uint32_t *ptr; + grub_size_t cnt = 0; + grub_uint8_t *ret, *dest; + + remaining = size; + ptr = src; + while (remaining--) + { + grub_uint32_t code = *ptr++; + + if (code <= 0x007F) + cnt++; + else if (code <= 0x07FF) + cnt += 2; + else if ((code >= 0xDC00 && code <= 0xDFFF) + || (code >= 0xD800 && code <= 0xDBFF)) + /* No surrogates in UCS-4... */ + cnt++; + else + cnt += 3; + } + cnt++; + + ret = grub_malloc (cnt); + if (!ret) + return 0; + + dest = ret; + remaining = size; + ptr = src; + while (remaining--) + { + grub_uint32_t code = *ptr++; + + if (code <= 0x007F) + *dest++ = code; + else if (code <= 0x07FF) + { + *dest++ = (code >> 6) | 0xC0; + *dest++ = (code & 0x3F) | 0x80; + } + else if ((code >= 0xDC00 && code <= 0xDFFF) + || (code >= 0xD800 && code <= 0xDBFF)) + { + /* No surrogates in UCS-4... */ + *dest++ = '?'; + } + else + { + *dest++ = (code >> 12) | 0xE0; + *dest++ = ((code >> 6) & 0x3F) | 0x80; + *dest++ = (code & 0x3F) | 0x80; + } + } + *dest = 0; + + return (char *) ret; +} + +int +grub_is_valid_utf8 (const grub_uint8_t *src, grub_size_t srcsize) +{ + grub_uint32_t code = 0; + int count = 0; + + while (srcsize) + { + grub_uint32_t c = *src++; + if (srcsize != (grub_size_t)-1) + srcsize--; + if (count) + { + if ((c & 0xc0) != 0x80) + { + /* invalid */ + return 0; + } + else + { + code <<= 6; + code |= (c & 0x3f); + count--; + } + } + else + { + if (c == 0) + break; + + if ((c & 0x80) == 0x00) + code = c; + else if ((c & 0xe0) == 0xc0) + { + count = 1; + code = c & 0x1f; + } + else if ((c & 0xf0) == 0xe0) + { + count = 2; + code = c & 0x0f; + } + else if ((c & 0xf8) == 0xf0) + { + count = 3; + code = c & 0x07; + } + else if ((c & 0xfc) == 0xf8) + { + count = 4; + code = c & 0x03; + } + else if ((c & 0xfe) == 0xfc) + { + count = 5; + code = c & 0x01; + } + else + return 0; + } + } + + return 1; +} + +int +grub_utf8_to_ucs4_alloc (const char *msg, grub_uint32_t **unicode_msg, + grub_uint32_t **last_position) +{ + grub_size_t msg_len = grub_strlen (msg); + + *unicode_msg = grub_malloc (grub_strlen (msg) * sizeof (grub_uint32_t)); + + if (!*unicode_msg) + { + grub_printf ("utf8_to_ucs4 ERROR1: %s", msg); + return -1; + } + + msg_len = grub_utf8_to_ucs4 (*unicode_msg, msg_len, + (grub_uint8_t *) msg, -1, 0); + + *last_position = *unicode_msg + msg_len; + + return msg_len; +} diff --git a/loader/efi/appleloader.c b/loader/efi/appleloader.c index 114a0a506..dc42683a6 100644 --- a/loader/efi/appleloader.c +++ b/loader/efi/appleloader.c @@ -25,6 +25,7 @@ #include #include #include +#include static grub_dl_t my_mod; @@ -321,7 +322,7 @@ static grub_command_t cmd; GRUB_MOD_INIT(appleloader) { cmd = grub_register_command ("appleloader", grub_cmd_appleloader, - "[OPTS]", "Boot legacy system."); + "[OPTS]", N_("Boot legacy system.")); my_mod = mod; } diff --git a/loader/efi/chainloader.c b/loader/efi/chainloader.c index 559c3f52a..a095ad931 100644 --- a/loader/efi/chainloader.c +++ b/loader/efi/chainloader.c @@ -33,6 +33,7 @@ #include #include #include +#include static grub_dl_t my_mod; @@ -336,7 +337,7 @@ static grub_command_t cmd; GRUB_MOD_INIT(chainloader) { cmd = grub_register_command ("chainloader", grub_cmd_chainloader, - 0, "Load another boot loader."); + 0, N_("Load another boot loader.")); my_mod = mod; } diff --git a/loader/i386/bsd.c b/loader/i386/bsd.c index 0785a3fc1..c5d213a06 100644 --- a/loader/i386/bsd.c +++ b/loader/i386/bsd.c @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2008, 2009 Free Software Foundation, Inc. + * Copyright (C) 2008,2009,2010 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -35,7 +35,7 @@ #include #include #include - +#include #ifdef GRUB_MACHINE_PCBIOS #include #endif @@ -509,6 +509,8 @@ grub_freebsd_boot (void) bi.bi_kernend = kern_end; + grub_video_set_mode ("text", 0, 0); + if (is_64bit) { grub_uint32_t *gdt; @@ -617,6 +619,8 @@ grub_openbsd_boot (void) pa->ba_type = OPENBSD_BOOTARG_END; pa++; + grub_video_set_mode ("text", 0, 0); + grub_unix_real_boot (entry, bootflags, openbsd_root, OPENBSD_BOOTARG_APIVER, 0, (grub_uint32_t) (grub_mmap_get_upper () >> 10), (grub_uint32_t) (grub_mmap_get_lower () >> 10), @@ -713,6 +717,8 @@ grub_netbsd_boot (void) bootinfo->bi_data[0] = mmap; } + grub_video_set_mode ("text", 0, 0); + grub_unix_real_boot (entry, bootflags, 0, bootinfo, 0, (grub_uint32_t) (grub_mmap_get_upper () >> 10), (grub_uint32_t) (grub_mmap_get_lower () >> 10)); diff --git a/loader/i386/efi/linux.c b/loader/i386/efi/linux.c index 1c256e377..2e26f3929 100644 --- a/loader/i386/efi/linux.c +++ b/loader/i386/efi/linux.c @@ -33,6 +33,7 @@ #include #include #include +#include #define GRUB_LINUX_CL_OFFSET 0x1000 #define GRUB_LINUX_CL_END_OFFSET 0x2000 @@ -586,7 +587,7 @@ grub_linux_setup_video (struct linux_kernel_params *params) params->reserved_mask_size = 8; params->reserved_field_pos = 24; - params->have_vga = GRUB_VIDEO_TYPE_VLFB; + params->have_vga = GRUB_VIDEO_LINUX_TYPE_VESA; params->vid_mode = 0x338; /* 1024x768x32 */ return 0; @@ -619,7 +620,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) { - grub_error (GRUB_ERR_READ_ERROR, "cannot read the linux header"); + grub_error (GRUB_ERR_READ_ERROR, "cannot read the Linux header"); goto fail; } @@ -693,13 +694,32 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), params->ext_mem = ((32 * 0x100000) >> 10); params->alt_mem = ((32 * 0x100000) >> 10); - params->video_cursor_x = grub_getxy () >> 8; - params->video_cursor_y = grub_getxy () & 0xff; + { + grub_term_output_t term; + int found = 0; + FOR_ACTIVE_TERM_OUTPUTS(term) + if (grub_strcmp (term->name, "vga_text") == 0 + || grub_strcmp (term->name, "console") == 0) + { + grub_uint16_t pos = grub_term_getxy (term); + params->video_cursor_x = pos >> 8; + params->video_cursor_y = pos & 0xff; + params->video_width = grub_term_width (term); + params->video_height = grub_term_height (term); + found = 1; + break; + } + if (!found) + { + params->video_cursor_x = 0; + params->video_cursor_y = 0; + params->video_width = 80; + params->video_height = 25; + } + } params->video_page = 0; /* ??? */ params->video_mode = grub_efi_system_table->con_out->mode->mode; - params->video_width = (grub_getwh () >> 8); params->video_ega_bx = 0; - params->video_height = (grub_getwh () & 0xff); params->have_vga = 0; params->font_size = 16; /* XXX */ @@ -832,7 +852,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), else if (grub_memcmp (argv[i], "video=efifb", 11) == 0) { if (params->have_vga) - params->have_vga = GRUB_VIDEO_TYPE_EFI; + params->have_vga = GRUB_VIDEO_LINUX_TYPE_SIMPLE; } /* Specify the boot file. */ @@ -989,9 +1009,9 @@ static grub_command_t cmd_linux, cmd_initrd; GRUB_MOD_INIT(linux) { cmd_linux = grub_register_command ("linux", grub_cmd_linux, - 0, "Load Linux."); + 0, N_("Load Linux.")); cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, - 0, "Load initrd."); + 0, N_("Load initrd.")); my_mod = mod; } diff --git a/loader/i386/ieee1275/linux.c b/loader/i386/ieee1275/linux.c index e8a6f1a52..8780804fd 100644 --- a/loader/i386/ieee1275/linux.c +++ b/loader/i386/ieee1275/linux.c @@ -1,7 +1,7 @@ /* linux.c - boot Linux zImage or bzImage */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2009,2010 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -32,6 +32,7 @@ #include #include #include +#include #define GRUB_OFW_LINUX_PARAMS_ADDR 0x90000 #define GRUB_OFW_LINUX_KERNEL_ADDR 0x100000 @@ -109,8 +110,29 @@ grub_linux_boot (void) params->cl_magic = GRUB_LINUX_CL_MAGIC; params->cl_offset = GRUB_OFW_LINUX_CL_OFFSET; - params->video_width = (grub_getwh () >> 8); - params->video_height = (grub_getwh () & 0xff); + { + grub_term_output_t term; + int found = 0; + FOR_ACTIVE_TERM_OUTPUTS(term) + if (grub_strcmp (term->name, "ofconsole") == 0) + { + grub_uint16_t pos = grub_term_getxy (term); + params->video_cursor_x = pos >> 8; + params->video_cursor_y = pos & 0xff; + params->video_width = grub_term_width (term); + params->video_height = grub_term_height (term); + found = 1; + break; + } + if (!found) + { + params->video_cursor_x = 0; + params->video_cursor_y = 0; + params->video_width = 80; + params->video_height = 25; + } + } + params->font_size = 16; params->ofw_signature = GRUB_LINUX_OFW_SIGNATURE; @@ -165,7 +187,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) { - grub_error (GRUB_ERR_READ_ERROR, "cannot read the linux header"); + grub_error (GRUB_ERR_READ_ERROR, "cannot read the Linux header"); goto fail; } @@ -276,9 +298,9 @@ static grub_command_t cmd_linux, cmd_initrd; GRUB_MOD_INIT(linux) { cmd_linux = grub_register_command ("linux", grub_cmd_linux, - 0, "Load Linux."); + 0, N_("Load Linux.")); cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, - 0, "Load initrd."); + 0, N_("Load initrd.")); my_mod = mod; } diff --git a/loader/i386/linux.c b/loader/i386/linux.c index 899216783..a81e84135 100644 --- a/loader/i386/linux.c +++ b/loader/i386/linux.c @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2006,2007,2008,2009 Free Software Foundation, Inc. + * Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,6 +33,8 @@ #include #include #include +#include +#include #define GRUB_LINUX_CL_OFFSET 0x1000 #define GRUB_LINUX_CL_END_OFFSET 0x2000 @@ -522,11 +524,11 @@ grub_linux_boot (void) if (! tmp) return grub_errno; grub_sprintf (tmp, "%s;text", modevar); - err = grub_video_set_mode (tmp, 0); + err = grub_video_set_mode (tmp, 0, 0); grub_free (tmp); } else - err = grub_video_set_mode ("text", 0); + err = grub_video_set_mode ("text", 0, 0); if (err) { @@ -536,19 +538,34 @@ grub_linux_boot (void) } if (! grub_linux_setup_video (params)) - params->have_vga = GRUB_VIDEO_TYPE_VLFB; + params->have_vga = GRUB_VIDEO_LINUX_TYPE_VESA; else { - params->have_vga = GRUB_VIDEO_TYPE_TEXT; + params->have_vga = GRUB_VIDEO_LINUX_TYPE_TEXT; params->video_width = 80; params->video_height = 25; } /* Initialize these last, because terminal position could be affected by printfs above. */ - if (params->have_vga == GRUB_VIDEO_TYPE_TEXT) + if (params->have_vga == GRUB_VIDEO_LINUX_TYPE_TEXT) { - params->video_cursor_x = grub_getxy () >> 8; - params->video_cursor_y = grub_getxy () & 0xff; + grub_term_output_t term; + int found = 0; + FOR_ACTIVE_TERM_OUTPUTS(term) + if (grub_strcmp (term->name, "vga_text") == 0 + || grub_strcmp (term->name, "console") == 0) + { + grub_uint16_t pos = grub_term_getxy (term); + params->video_cursor_x = pos >> 8; + params->video_cursor_y = pos & 0xff; + found = 1; + break; + } + if (!found) + { + params->video_cursor_x = 0; + params->video_cursor_y = 0; + } } #ifdef __x86_64__ @@ -613,7 +630,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) { - grub_error (GRUB_ERR_READ_ERROR, "cannot read the linux header"); + grub_error (GRUB_ERR_READ_ERROR, "cannot read the Linux header"); goto fail; } @@ -712,8 +729,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), grub_file_seek (file, real_size + GRUB_DISK_SECTOR_SIZE); - grub_printf (" [Linux-bzImage, setup=0x%x, size=0x%x]\n", - (unsigned) real_size, (unsigned) prot_size); + grub_dprintf ("linux", "bzImage, setup=0x%x, size=0x%x\n", + (unsigned) real_size, (unsigned) prot_size); /* Look for memory size and video mode specified on the command line. */ linux_mem_size = 0; @@ -963,8 +980,8 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), goto fail; } - grub_printf (" [Initrd, addr=0x%x, size=0x%x]\n", - (unsigned) addr, (unsigned) size); + grub_dprintf ("linux", "Initrd, addr=0x%x, size=0x%x\n", + (unsigned) addr, (unsigned) size); lh->ramdisk_image = addr; lh->ramdisk_size = size; @@ -982,9 +999,9 @@ static grub_command_t cmd_linux, cmd_initrd; GRUB_MOD_INIT(linux) { cmd_linux = grub_register_command ("linux", grub_cmd_linux, - 0, "Load Linux."); + 0, N_("Load Linux.")); cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, - 0, "Load initrd."); + 0, N_("Load initrd.")); my_mod = mod; } diff --git a/loader/i386/multiboot.c b/loader/i386/multiboot.c index f4869594e..d06f18692 100644 --- a/loader/i386/multiboot.c +++ b/loader/i386/multiboot.c @@ -1,7 +1,7 @@ /* multiboot.c - boot a multiboot OS image. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2009,2010 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,13 +28,11 @@ */ /* The bits in the required part of flags field we don't support. */ -#define UNSUPPORTED_FLAGS 0x0000fffc +#define UNSUPPORTED_FLAGS 0x0000fff8 #include #include #include -#include -#include #include #include #include @@ -45,31 +43,29 @@ #include #include #include -#ifdef GRUB_MACHINE_PCBIOS -#include -#include -#include -#include -#endif #include +#include + +#ifdef GRUB_MACHINE_EFI +#include +#endif extern grub_dl_t my_mod; -static struct multiboot_info *mbi, *mbi_dest; - -static grub_size_t code_size; +static grub_size_t code_size, alloc_mbi; char *grub_multiboot_payload_orig; grub_addr_t grub_multiboot_payload_dest; -grub_size_t grub_multiboot_payload_size; +grub_size_t grub_multiboot_pure_size; grub_uint32_t grub_multiboot_payload_eip; static grub_err_t grub_multiboot_boot (void) { + grub_size_t mbi_size; + grub_err_t err; struct grub_relocator32_state state = { .eax = MULTIBOOT_BOOTLOADER_MAGIC, - .ebx = PTR_TO_UINT32 (mbi_dest), .ecx = 0, .edx = 0, .eip = grub_multiboot_payload_eip, @@ -78,6 +74,29 @@ grub_multiboot_boot (void) .esp = 0x7ff00 }; + mbi_size = grub_multiboot_get_mbi_size (); + if (alloc_mbi < mbi_size) + { + grub_multiboot_payload_orig + = grub_relocator32_realloc (grub_multiboot_payload_orig, + grub_multiboot_pure_size + mbi_size); + if (!grub_multiboot_payload_orig) + return grub_errno; + alloc_mbi = mbi_size; + } + + state.ebx = grub_multiboot_payload_dest + grub_multiboot_pure_size; + err = grub_multiboot_make_mbi (grub_multiboot_payload_orig, + grub_multiboot_payload_dest, + grub_multiboot_pure_size, mbi_size); + if (err) + return err; + +#ifdef GRUB_MACHINE_EFI + if (! grub_efi_finish_boot_services ()) + grub_fatal ("cannot exit boot services"); +#endif + grub_relocator32_boot (grub_multiboot_payload_orig, grub_multiboot_payload_dest, state); @@ -89,69 +108,18 @@ grub_multiboot_boot (void) static grub_err_t grub_multiboot_unload (void) { - if (mbi) - { - unsigned int i; - for (i = 0; i < mbi->mods_count; i++) - { - grub_free ((void *) - ((struct multiboot_mod_list *) mbi->mods_addr)[i].mod_start); - grub_free ((void *) - ((struct multiboot_mod_list *) mbi->mods_addr)[i].cmdline); - } - grub_free ((void *) mbi->mods_addr); - } + grub_multiboot_free_mbi (); + grub_relocator32_free (grub_multiboot_payload_orig); - mbi = NULL; + alloc_mbi = 0; + grub_multiboot_payload_orig = NULL; grub_dl_unref (my_mod); return GRUB_ERR_NONE; } -/* Return the length of the Multiboot mmap that will be needed to allocate - our platform's map. */ -static grub_uint32_t -grub_get_multiboot_mmap_len (void) -{ - grub_size_t count = 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 __attribute__ ((unused)), - grub_uint64_t size __attribute__ ((unused)), - grub_uint32_t type __attribute__ ((unused))) - { - count++; - return 0; - } - - grub_mmap_iterate (hook); - - return count * sizeof (struct multiboot_mmap_entry); -} - -/* Fill previously allocated Multiboot mmap. */ -static void -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) - { - mmap_entry->addr = addr; - mmap_entry->len = size; - mmap_entry->type = type; - mmap_entry->size = sizeof (struct multiboot_mmap_entry) - sizeof (mmap_entry->size); - mmap_entry++; - - return 0; - } - - grub_mmap_iterate (hook); -} - #define MULTIBOOT_LOAD_ELF64 #include "multiboot_elfxx.c" #undef MULTIBOOT_LOAD_ELF64 @@ -172,58 +140,13 @@ grub_multiboot_load_elf (grub_file_t file, void *buffer) return grub_error (GRUB_ERR_UNKNOWN_OS, "unknown ELF class"); } -static int -grub_multiboot_get_bootdev (grub_uint32_t *bootdev) -{ -#ifdef GRUB_MACHINE_PCBIOS - char *p; - grub_uint32_t biosdev, slice = ~0, part = ~0; - grub_device_t dev; - - biosdev = grub_get_root_biosnumber (); - - dev = grub_device_open (0); - if (dev && dev->disk && dev->disk->partition) - { - - p = dev->disk->partition->partmap->get_name (dev->disk->partition); - if (p) - { - if ((p[0] >= '0') && (p[0] <= '9')) - { - slice = grub_strtoul (p, &p, 0) - 1; - - if ((p) && (p[0] == ',')) - p++; - } - - if ((p[0] >= 'a') && (p[0] <= 'z')) - part = p[0] - 'a'; - } - } - if (dev) - grub_device_close (dev); - - *bootdev = ((biosdev & 0xff) << 24) | ((slice & 0xff) << 16) - | ((part & 0xff) << 8) | 0xff; - return (biosdev != ~0UL); -#else - *bootdev = 0xffffffff; - return 0; -#endif -} - void grub_multiboot (int argc, char *argv[]) { grub_file_t file = 0; - char buffer[MULTIBOOT_SEARCH], *cmdline = 0, *p; + char buffer[MULTIBOOT_SEARCH]; struct multiboot_header *header; - grub_ssize_t len, cmdline_length, boot_loader_name_length; - grub_uint32_t mmap_length; - int i; - int cmdline_argc; - char **cmdline_argv; + grub_ssize_t len; grub_loader_unset (); @@ -274,31 +197,8 @@ grub_multiboot (int argc, char *argv[]) grub_relocator32_free (grub_multiboot_payload_orig); grub_multiboot_payload_orig = NULL; - mmap_length = grub_get_multiboot_mmap_len (); - - /* Figure out cmdline length. */ /* Skip filename. */ - cmdline_argc = argc - 1; - cmdline_argv = argv + 1; - - for (i = 0, cmdline_length = 0; i < cmdline_argc; i++) - cmdline_length += grub_strlen (cmdline_argv[i]) + 1; - - if (cmdline_length == 0) - cmdline_length = 1; - - boot_loader_name_length = sizeof(PACKAGE_STRING); - -#define cmdline_addr(x) ((void *) ((x) + code_size)) -#define boot_loader_name_addr(x) \ - ((void *) ((x) + code_size + cmdline_length)) -#define mbi_addr(x) ((void *) ((x) + code_size + cmdline_length + boot_loader_name_length)) -#define mmap_addr(x) ((void *) ((x) + code_size + cmdline_length + boot_loader_name_length + sizeof (struct multiboot_info))) - - grub_multiboot_payload_size = cmdline_length - /* boot_loader_name_length might need to grow for mbi,etc to be aligned (see below) */ - + boot_loader_name_length + 3 - + sizeof (struct multiboot_info) + mmap_length; + grub_multiboot_init_mbi (argc - 1, argv + 1); if (header->flags & MULTIBOOT_AOUT_KLUDGE) { @@ -313,10 +213,12 @@ grub_multiboot (int argc, char *argv[]) code_size = load_size; grub_multiboot_payload_dest = header->load_addr; - grub_multiboot_payload_size += code_size; + grub_multiboot_pure_size += code_size; + /* Allocate a bit more to avoid relocations in most cases. */ + alloc_mbi = grub_multiboot_get_mbi_size () + 65536; grub_multiboot_payload_orig - = grub_relocator32_alloc (grub_multiboot_payload_size); + = grub_relocator32_alloc (grub_multiboot_pure_size + alloc_mbi); if (! grub_multiboot_payload_orig) goto fail; @@ -338,53 +240,37 @@ grub_multiboot (int argc, char *argv[]) else if (grub_multiboot_load_elf (file, buffer) != GRUB_ERR_NONE) goto fail; - /* This provides alignment for the MBI, the memory map and the backward relocator. */ - boot_loader_name_length += (0x04 - ((unsigned long) mbi_addr (grub_multiboot_payload_dest) & 0x03)); - - mbi = mbi_addr (grub_multiboot_payload_orig); - mbi_dest = mbi_addr (grub_multiboot_payload_dest); - grub_memset (mbi, 0, sizeof (struct multiboot_info)); - mbi->mmap_length = mmap_length; - - grub_fill_multiboot_mmap (mmap_addr (grub_multiboot_payload_orig)); - - /* FIXME: grub_uint32_t will break for addresses above 4 GiB, but is mandated - by the spec. Is there something we can do about it? */ - mbi->mmap_addr = (grub_uint32_t) mmap_addr (grub_multiboot_payload_dest); - mbi->flags |= MULTIBOOT_INFO_MEM_MAP; - - /* Convert from bytes to kilobytes. */ - mbi->mem_lower = grub_mmap_get_lower () / 1024; - mbi->mem_upper = grub_mmap_get_upper () / 1024; - mbi->flags |= MULTIBOOT_INFO_MEMORY; - - cmdline = p = cmdline_addr (grub_multiboot_payload_orig); - if (! cmdline) - goto fail; - - for (i = 0; i < cmdline_argc; i++) + if (header->flags & MULTIBOOT_VIDEO_MODE) { - p = grub_stpcpy (p, cmdline_argv[i]); - *(p++) = ' '; + switch (header->mode_type) + { + case 1: + grub_env_set ("gfxpayload", "text"); + break; + + case 0: + { + char buf[sizeof ("XXXXXXXXXXxXXXXXXXXXXxXXXXXXXXXX,XXXXXXXXXXxXXXXXXXXXX,auto")]; + if (header->depth && header->width && header->height) + grub_sprintf (buf, "%dx%dx%d,%dx%d,auto", header->width, + header->height, header->depth, header->width, + header->height); + else if (header->width && header->height) + grub_sprintf (buf, "%dx%d,auto", header->width, header->height); + else + grub_sprintf (buf, "auto"); + + grub_env_set ("gfxpayload", buf); + break; + } + } } - /* Remove the space after the last word. */ - if (p != cmdline) - p--; - *p = 0; + grub_multiboot_set_accepts_video (!!(header->flags & MULTIBOOT_VIDEO_MODE)); - mbi->flags |= MULTIBOOT_INFO_CMDLINE; - mbi->cmdline = (grub_uint32_t) cmdline_addr (grub_multiboot_payload_dest); + grub_multiboot_set_bootdev (); - - grub_strcpy (boot_loader_name_addr (grub_multiboot_payload_orig), PACKAGE_STRING); - mbi->flags |= MULTIBOOT_INFO_BOOT_LOADER_NAME; - mbi->boot_loader_name = (grub_uint32_t) boot_loader_name_addr (grub_multiboot_payload_dest); - - if (grub_multiboot_get_bootdev (&mbi->boot_device)) - mbi->flags |= MULTIBOOT_INFO_BOOTDEV; - - grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 1); + grub_loader_set (grub_multiboot_boot, grub_multiboot_unload, 0); fail: if (file) @@ -392,22 +278,18 @@ grub_multiboot (int argc, char *argv[]) if (grub_errno != GRUB_ERR_NONE) { - grub_free (cmdline); - grub_free (mbi); + grub_relocator32_free (grub_multiboot_payload_orig); grub_dl_unref (my_mod); } } - void grub_module (int argc, char *argv[]) { grub_file_t file = 0; - grub_ssize_t size, len = 0; - char *module = 0, *cmdline = 0, *p; - int i; - int cmdline_argc; - char **cmdline_argv; + grub_ssize_t size; + char *module = 0; + grub_err_t err; if (argc == 0) { @@ -415,7 +297,7 @@ grub_module (int argc, char *argv[]) goto fail; } - if (!mbi) + if (!grub_multiboot_payload_orig) { grub_error (GRUB_ERR_BAD_ARGUMENT, "you need to load the multiboot kernel first"); @@ -431,73 +313,19 @@ grub_module (int argc, char *argv[]) if (! module) goto fail; + err = grub_multiboot_add_module ((grub_addr_t) module, size, + argc - 1, argv + 1); + if (err) + goto fail; + if (grub_file_read (file, module, size) != size) { grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file"); goto fail; } - /* Skip module name. */ - cmdline_argc = argc - 1; - cmdline_argv = argv + 1; - - for (i = 0; i < cmdline_argc; i++) - len += grub_strlen (cmdline_argv[i]) + 1; - - if (len == 0) - len = 1; - - cmdline = p = grub_malloc (len); - if (! cmdline) - goto fail; - - for (i = 0; i < cmdline_argc; i++) - { - p = grub_stpcpy (p, cmdline_argv[i]); - *(p++) = ' '; - } - - /* Remove the space after the last word. */ - if (p != cmdline) - p--; - *p = '\0'; - - if (mbi->flags & MULTIBOOT_INFO_MODS) - { - struct multiboot_mod_list *modlist = (struct multiboot_mod_list *) mbi->mods_addr; - - modlist = grub_realloc (modlist, (mbi->mods_count + 1) - * sizeof (struct multiboot_mod_list)); - if (! modlist) - goto fail; - mbi->mods_addr = (grub_uint32_t) modlist; - modlist += mbi->mods_count; - modlist->mod_start = (grub_uint32_t) module; - modlist->mod_end = (grub_uint32_t) module + size; - modlist->cmdline = (grub_uint32_t) cmdline; - modlist->pad = 0; - mbi->mods_count++; - } - else - { - struct multiboot_mod_list *modlist = grub_zalloc (sizeof (struct multiboot_mod_list)); - if (! modlist) - goto fail; - modlist->mod_start = (grub_uint32_t) module; - modlist->mod_end = (grub_uint32_t) module + size; - modlist->cmdline = (grub_uint32_t) cmdline; - mbi->mods_count = 1; - mbi->mods_addr = (grub_uint32_t) modlist; - mbi->flags |= MULTIBOOT_INFO_MODS; - } - fail: if (file) grub_file_close (file); - - if (grub_errno != GRUB_ERR_NONE) - { - grub_free (module); - grub_free (cmdline); - } } + diff --git a/loader/i386/multiboot_elfxx.c b/loader/i386/multiboot_elfxx.c index 80db25144..2e35183a4 100644 --- a/loader/i386/multiboot_elfxx.c +++ b/loader/i386/multiboot_elfxx.c @@ -100,10 +100,11 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, void *buffer) code_size = (phdr(highest_segment)->p_paddr + phdr(highest_segment)->p_memsz) - phdr(lowest_segment)->p_paddr; grub_multiboot_payload_dest = phdr(lowest_segment)->p_paddr; - grub_multiboot_payload_size += code_size; + grub_multiboot_pure_size += code_size; + alloc_mbi = grub_multiboot_get_mbi_size (); grub_multiboot_payload_orig - = grub_relocator32_alloc (grub_multiboot_payload_size); + = grub_relocator32_alloc (grub_multiboot_pure_size + alloc_mbi + 65536); if (!grub_multiboot_payload_orig) return grub_errno; diff --git a/loader/i386/multiboot_mbi.c b/loader/i386/multiboot_mbi.c new file mode 100644 index 000000000..58bb68323 --- /dev/null +++ b/loader/i386/multiboot_mbi.c @@ -0,0 +1,463 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#ifdef GRUB_MACHINE_PCBIOS +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU) +#include +#define DEFAULT_VIDEO_MODE "text" +#define HAS_VGA_TEXT 1 +#else +#define DEFAULT_VIDEO_MODE "auto" +#define HAS_VGA_TEXT 0 +#endif + +struct module +{ + struct module *next; + grub_addr_t start; + grub_size_t size; + char *cmdline; + int cmdline_size; +}; + +struct module *modules, *modules_last; +static grub_size_t cmdline_size; +static grub_size_t total_modcmd; +static unsigned modcnt; +static char *cmdline = NULL; +static grub_uint32_t bootdev; +static int bootdev_set; +static int accepts_video; + +void +grub_multiboot_set_accepts_video (int val) +{ + accepts_video = val; +} + +/* Return the length of the Multiboot mmap that will be needed to allocate + our platform's map. */ +static grub_uint32_t +grub_get_multiboot_mmap_len (void) +{ + grub_size_t count = 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 __attribute__ ((unused)), + grub_uint64_t size __attribute__ ((unused)), + grub_uint32_t type __attribute__ ((unused))) + { + count++; + return 0; + } + + grub_mmap_iterate (hook); + + return count * sizeof (struct multiboot_mmap_entry); +} + +grub_size_t +grub_multiboot_get_mbi_size (void) +{ + return sizeof (struct multiboot_info) + ALIGN_UP (cmdline_size, 4) + + modcnt * sizeof (struct multiboot_mod_list) + total_modcmd + + ALIGN_UP (sizeof(PACKAGE_STRING), 4) + grub_get_multiboot_mmap_len () + + 256 * sizeof (struct multiboot_color); +} + +/* Fill previously allocated Multiboot mmap. */ +static void +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) + { + mmap_entry->addr = addr; + mmap_entry->len = size; + switch (type) + { + case GRUB_MACHINE_MEMORY_AVAILABLE: + mmap_entry->type = MULTIBOOT_MEMORY_AVAILABLE; + break; + + default: + mmap_entry->type = MULTIBOOT_MEMORY_RESERVED; + break; + } + mmap_entry->size = sizeof (struct multiboot_mmap_entry) - sizeof (mmap_entry->size); + mmap_entry++; + + return 0; + } + + grub_mmap_iterate (hook); +} + +static grub_err_t +set_video_mode (void) +{ + grub_err_t err; + const char *modevar; + + if (accepts_video || !HAS_VGA_TEXT) + { + modevar = grub_env_get ("gfxpayload"); + if (! modevar || *modevar == 0) + err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0, 0); + else + { + char *tmp; + tmp = grub_malloc (grub_strlen (modevar) + + sizeof (DEFAULT_VIDEO_MODE) + 1); + if (! tmp) + return grub_errno; + grub_sprintf (tmp, "%s;" DEFAULT_VIDEO_MODE, modevar); + err = grub_video_set_mode (tmp, 0, 0); + grub_free (tmp); + } + } + else + err = grub_video_set_mode ("text", 0, 0); + + return err; +} + +static grub_err_t +retrieve_video_parameters (struct multiboot_info *mbi, + grub_uint8_t *ptrorig, grub_uint32_t ptrdest) +{ + grub_err_t err; + struct grub_video_mode_info mode_info; + void *framebuffer; + grub_video_driver_id_t driv_id; + struct grub_video_palette_data palette[256]; + + err = set_video_mode (); + if (err) + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + } + + grub_video_get_palette (0, ARRAY_SIZE (palette), palette); + + driv_id = grub_video_get_driver_id (); + if (driv_id == GRUB_VIDEO_DRIVER_NONE) + return GRUB_ERR_NONE; + + err = grub_video_get_info_and_fini (&mode_info, &framebuffer); + if (err) + return err; + + mbi->framebuffer_addr = (grub_addr_t) framebuffer; + mbi->framebuffer_pitch = mode_info.pitch; + + mbi->framebuffer_width = mode_info.width; + mbi->framebuffer_height = mode_info.height; + + mbi->framebuffer_bpp = mode_info.bpp; + + if (mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) + { + struct multiboot_color *mb_palette; + unsigned i; + mbi->framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED; + mbi->framebuffer_palette_addr = ptrdest; + mbi->framebuffer_palette_num_colors = mode_info.number_of_colors; + if (mbi->framebuffer_palette_num_colors > ARRAY_SIZE (palette)) + mbi->framebuffer_palette_num_colors = ARRAY_SIZE (palette); + mb_palette = (struct multiboot_color *) ptrorig; + for (i = 0; i < mbi->framebuffer_palette_num_colors; i++) + { + mb_palette[i].red = palette[i].r; + mb_palette[i].green = palette[i].g; + mb_palette[i].blue = palette[i].b; + } + ptrorig += mbi->framebuffer_palette_num_colors + * sizeof (struct multiboot_color); + ptrdest += mbi->framebuffer_palette_num_colors + * sizeof (struct multiboot_color); + } + else + { + mbi->framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_RGB; + mbi->framebuffer_red_field_position = mode_info.green_field_pos; + mbi->framebuffer_red_mask_size = mode_info.green_mask_size; + mbi->framebuffer_green_field_position = mode_info.green_field_pos; + mbi->framebuffer_green_mask_size = mode_info.green_mask_size; + mbi->framebuffer_blue_field_position = mode_info.blue_field_pos; + mbi->framebuffer_blue_mask_size = mode_info.blue_mask_size; + } + + mbi->flags |= MULTIBOOT_INFO_FRAMEBUFFER_INFO; + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_off, + grub_size_t bufsize) +{ + grub_uint8_t *ptrorig = (grub_uint8_t *) orig + buf_off; + grub_uint32_t ptrdest = dest + buf_off; + struct multiboot_info *mbi; + struct multiboot_mod_list *modlist; + unsigned i; + struct module *cur; + grub_size_t mmap_size; + grub_err_t err; + + if (bufsize < grub_multiboot_get_mbi_size ()) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, "mbi buffer is too small"); + + mbi = (struct multiboot_info *) ptrorig; + ptrorig += sizeof (*mbi); + ptrdest += sizeof (*mbi); + grub_memset (mbi, 0, sizeof (*mbi)); + + grub_memcpy (ptrorig, cmdline, cmdline_size); + mbi->flags |= MULTIBOOT_INFO_CMDLINE; + mbi->cmdline = ptrdest; + ptrorig += ALIGN_UP (cmdline_size, 4); + ptrdest += ALIGN_UP (cmdline_size, 4); + + grub_memcpy (ptrorig, PACKAGE_STRING, sizeof(PACKAGE_STRING)); + mbi->flags |= MULTIBOOT_INFO_BOOT_LOADER_NAME; + mbi->boot_loader_name = ptrdest; + ptrorig += ALIGN_UP (sizeof(PACKAGE_STRING), 4); + ptrdest += ALIGN_UP (sizeof(PACKAGE_STRING), 4); + + if (modcnt) + { + mbi->flags |= MULTIBOOT_INFO_MODS; + mbi->mods_addr = ptrdest; + mbi->mods_count = modcnt; + modlist = (struct multiboot_mod_list *) ptrorig; + ptrorig += modcnt * sizeof (struct multiboot_mod_list); + ptrdest += modcnt * sizeof (struct multiboot_mod_list); + + for (i = 0, cur = modules; i < modcnt; i++, cur = cur->next) + { + modlist[i].mod_start = cur->start; + modlist[i].mod_end = modlist[i].mod_start + cur->size; + modlist[i].cmdline = ptrdest; + grub_memcpy (ptrorig, cur->cmdline, cur->cmdline_size); + ptrorig += ALIGN_UP (cur->cmdline_size, 4); + ptrdest += ALIGN_UP (cur->cmdline_size, 4); + } + } + else + { + mbi->mods_addr = 0; + mbi->mods_count = 0; + } + + mmap_size = grub_get_multiboot_mmap_len (); + grub_fill_multiboot_mmap ((struct multiboot_mmap_entry *) ptrorig); + mbi->mmap_length = mmap_size; + mbi->mmap_addr = ptrdest; + mbi->flags |= MULTIBOOT_INFO_MEM_MAP; + ptrorig += mmap_size; + ptrdest += mmap_size; + + /* Convert from bytes to kilobytes. */ + mbi->mem_lower = grub_mmap_get_lower () / 1024; + mbi->mem_upper = grub_mmap_get_upper () / 1024; + mbi->flags |= MULTIBOOT_INFO_MEMORY; + + if (bootdev_set) + { + mbi->boot_device = bootdev; + mbi->flags |= MULTIBOOT_INFO_BOOTDEV; + } + + err = retrieve_video_parameters (mbi, ptrorig, ptrdest); + if (err) + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + } + + return GRUB_ERR_NONE; +} + +void +grub_multiboot_free_mbi (void) +{ + struct module *cur, *next; + + cmdline_size = 0; + total_modcmd = 0; + modcnt = 0; + grub_free (cmdline); + cmdline = NULL; + bootdev_set = 0; + + for (cur = modules; cur; cur = next) + { + next = cur->next; + grub_free (cur->cmdline); + grub_free (cur); + } + modules = NULL; + modules_last = NULL; +} + +grub_err_t +grub_multiboot_init_mbi (int argc, char *argv[]) +{ + grub_ssize_t len = 0; + char *p; + int i; + + grub_multiboot_free_mbi (); + + for (i = 0; i < argc; i++) + len += grub_strlen (argv[i]) + 1; + if (len == 0) + len = 1; + + cmdline = p = grub_malloc (len); + if (! cmdline) + return grub_errno; + cmdline_size = len; + + for (i = 0; i < argc; i++) + { + p = grub_stpcpy (p, argv[i]); + *(p++) = ' '; + } + + /* Remove the space after the last word. */ + if (p != cmdline) + p--; + *p = '\0'; + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_multiboot_add_module (grub_addr_t start, grub_size_t size, + int argc, char *argv[]) +{ + struct module *newmod; + char *p; + grub_ssize_t len = 0; + int i; + + newmod = grub_malloc (sizeof (*newmod)); + if (!newmod) + return grub_errno; + newmod->start = start; + newmod->size = size; + + for (i = 0; i < argc; i++) + len += grub_strlen (argv[i]) + 1; + + if (len == 0) + len = 1; + + newmod->cmdline = p = grub_malloc (len); + if (! newmod->cmdline) + { + grub_free (newmod); + return grub_errno; + } + newmod->cmdline_size = len; + total_modcmd += ALIGN_UP (len, 4); + + for (i = 0; i < argc; i++) + { + p = grub_stpcpy (p, argv[i]); + *(p++) = ' '; + } + + /* Remove the space after the last word. */ + if (p != newmod->cmdline) + p--; + *p = '\0'; + + if (modules_last) + modules_last->next = newmod; + else + { + modules = newmod; + modules_last->next = NULL; + } + modules_last = newmod; + + modcnt++; + + return GRUB_ERR_NONE; +} + +void +grub_multiboot_set_bootdev (void) +{ + char *p; + grub_uint32_t biosdev, slice = ~0, part = ~0; + grub_device_t dev; + +#ifdef GRUB_MACHINE_PCBIOS + biosdev = grub_get_root_biosnumber (); +#else + biosdev = 0xffffffff; +#endif + + dev = grub_device_open (0); + if (dev && dev->disk && dev->disk->partition) + { + + p = dev->disk->partition->partmap->get_name (dev->disk->partition); + if (p) + { + if ((p[0] >= '0') && (p[0] <= '9')) + { + slice = grub_strtoul (p, &p, 0) - 1; + + if ((p) && (p[0] == ',')) + p++; + } + + if ((p[0] >= 'a') && (p[0] <= 'z')) + part = p[0] - 'a'; + } + } + if (dev) + grub_device_close (dev); + + bootdev = ((biosdev & 0xff) << 24) | ((slice & 0xff) << 16) + | ((part & 0xff) << 8) | 0xff; + bootdev_set = 1; +} diff --git a/loader/i386/pc/chainloader.c b/loader/i386/pc/chainloader.c index a153d80a9..fbc356895 100644 --- a/loader/i386/pc/chainloader.c +++ b/loader/i386/pc/chainloader.c @@ -1,7 +1,7 @@ /* chainloader.c - boot another boot loader */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2004,2007,2009 Free Software Foundation, Inc. + * Copyright (C) 2002,2004,2007,2009,2010 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -32,6 +32,9 @@ #include #include #include +#include +#include +#include static grub_dl_t my_mod; static int boot_drive; @@ -40,6 +43,7 @@ static void *boot_part_addr; static grub_err_t grub_chainloader_boot (void) { + grub_video_set_mode ("text", 0, 0); grub_chainloader_real_boot (boot_drive, boot_part_addr); /* Never reach here. */ @@ -146,7 +150,7 @@ static grub_command_t cmd; GRUB_MOD_INIT(chainloader) { cmd = grub_register_command ("chainloader", grub_cmd_chainloader, - 0, "Load another boot loader."); + 0, N_("Load another boot loader.")); my_mod = mod; } diff --git a/loader/i386/pc/linux.c b/loader/i386/pc/linux.c index 77b7966bf..0fa9abc12 100644 --- a/loader/i386/pc/linux.c +++ b/loader/i386/pc/linux.c @@ -1,7 +1,7 @@ /* linux.c - boot Linux zImage or bzImage */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2009 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2007,2008,2009,2010 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,6 +30,9 @@ #include #include #include +#include +#include +#include #define GRUB_LINUX_CL_OFFSET 0x9000 #define GRUB_LINUX_CL_END_OFFSET 0x90FF @@ -47,6 +50,16 @@ grub_linux_unload (void) return GRUB_ERR_NONE; } +static grub_err_t +grub_linux16_boot (void) +{ + grub_video_set_mode ("text", 0, 0); + grub_linux16_real_boot (); + + /* Not reached. */ + return GRUB_ERR_NONE; +} + static grub_err_t grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) @@ -81,7 +94,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), if (grub_file_read (file, &lh, sizeof (lh)) != sizeof (lh)) { - grub_error (GRUB_ERR_READ_ERROR, "cannot read the linux header"); + grub_error (GRUB_ERR_READ_ERROR, "cannot read the Linux header"); goto fail; } @@ -383,10 +396,10 @@ GRUB_MOD_INIT(linux16) { cmd_linux = grub_register_command ("linux16", grub_cmd_linux, - 0, "Load Linux."); + 0, N_("Load Linux.")); cmd_initrd = grub_register_command ("initrd16", grub_cmd_initrd, - 0, "Load initrd."); + 0, N_("Load initrd.")); my_mod = mod; } diff --git a/loader/i386/pc/multiboot2.c b/loader/i386/pc/multiboot2.c deleted file mode 100644 index 005c8a823..000000000 --- a/loader/i386/pc/multiboot2.c +++ /dev/null @@ -1,122 +0,0 @@ -/* multiboot2.c - boot a multiboot 2 OS image. */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2007,2008,2009 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GRUB. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -grub_err_t -grub_mb2_arch_elf32_hook (Elf32_Phdr *phdr, - grub_addr_t *addr __attribute__ ((unused)), - int *do_load) -{ - Elf32_Addr paddr = phdr->p_paddr; - - if (phdr->p_type != PT_LOAD) - { - *do_load = 0; - return 0; - } - *do_load = 1; - - if ((paddr < grub_os_area_addr) - || (paddr + phdr->p_memsz > grub_os_area_addr + grub_os_area_size)) - return grub_error(GRUB_ERR_OUT_OF_RANGE,"address 0x%x is out of range", - paddr); - - return GRUB_ERR_NONE; -} - -grub_err_t -grub_mb2_arch_elf64_hook (Elf64_Phdr *phdr, - grub_addr_t *addr __attribute__ ((unused)), - int *do_load) -{ - Elf64_Addr paddr = phdr->p_paddr; - - if (phdr->p_type != PT_LOAD) - { - *do_load = 0; - return 0; - } - *do_load = 1; - - if ((paddr < grub_os_area_addr) - || (paddr + phdr->p_memsz > grub_os_area_addr + grub_os_area_size)) - return grub_error (GRUB_ERR_OUT_OF_RANGE, "address 0x%x is out of range", - paddr); - - return GRUB_ERR_NONE; -} - -grub_err_t -grub_mb2_arch_module_alloc (grub_size_t size, grub_addr_t *addr) -{ - grub_addr_t modaddr; - - modaddr = (grub_addr_t) grub_memalign (MULTIBOOT2_MOD_ALIGN, size); - if (! modaddr) - return grub_errno; - - *addr = modaddr; - return GRUB_ERR_NONE; -} - -grub_err_t -grub_mb2_arch_module_free (grub_addr_t addr, - grub_size_t size __attribute__ ((unused))) -{ - grub_free((void *) addr); - return GRUB_ERR_NONE; -} - -void -grub_mb2_arch_boot (grub_addr_t entry, void *tags) -{ - grub_multiboot2_real_boot (entry, tags); -} - -void -grub_mb2_arch_unload (struct multiboot2_tag_header *tags) -{ - struct multiboot2_tag_header *tag; - - /* Free all module memory in the tag list. */ - for_each_tag (tag, tags) - { - if (tag->key == MULTIBOOT2_TAG_MODULE) - { - struct multiboot2_tag_module *module = - (struct multiboot2_tag_module *) tag; - grub_free((void *) module->addr); - } - } -} - -grub_err_t -grub_mb2_tags_arch_create (void) -{ - /* XXX Create boot device et al. */ - return GRUB_ERR_NONE; -} diff --git a/loader/i386/pc/xnu.c b/loader/i386/pc/xnu.c index ebb176bb4..839d0ad44 100644 --- a/loader/i386/pc/xnu.c +++ b/loader/i386/pc/xnu.c @@ -26,16 +26,7 @@ #define min(a,b) (((a) < (b)) ? (a) : (b)) #define max(a,b) (((a) > (b)) ? (a) : (b)) -#define DEFAULT_VIDEO_MODE "1024x768x32,800x600x32,640x480x32" - -static int NESTED_FUNC_ATTR video_hook (grub_video_adapter_t p __attribute__ ((unused)), - struct grub_video_mode_info *info) -{ - if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT) - return 0; - - return 1; -} +#define DEFAULT_VIDEO_MODE "auto" /* Setup video for xnu. */ grub_err_t @@ -48,8 +39,12 @@ grub_xnu_set_video (struct grub_xnu_boot_params *params) grub_err_t err; modevar = grub_env_get ("gfxpayload"); + /* Consider only graphical 32-bit deep modes. */ if (! modevar || *modevar == 0) - err = grub_video_set_mode (DEFAULT_VIDEO_MODE, video_hook); + err = grub_video_set_mode (DEFAULT_VIDEO_MODE, + GRUB_VIDEO_MODE_TYPE_PURE_TEXT + | GRUB_VIDEO_MODE_TYPE_DEPTH_MASK, + 32 << GRUB_VIDEO_MODE_TYPE_DEPTH_POS); else { tmp = grub_malloc (grub_strlen (modevar) @@ -58,7 +53,10 @@ grub_xnu_set_video (struct grub_xnu_boot_params *params) return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't allocate temporary storag"); grub_sprintf (tmp, "%s;" DEFAULT_VIDEO_MODE, modevar); - err = grub_video_set_mode (tmp, video_hook); + err = grub_video_set_mode (tmp, + GRUB_VIDEO_MODE_TYPE_PURE_TEXT + | GRUB_VIDEO_MODE_TYPE_DEPTH_MASK, + 32 << GRUB_VIDEO_MODE_TYPE_DEPTH_POS); grub_free (tmp); } diff --git a/loader/i386/xnu.c b/loader/i386/xnu.c index f71e2c306..23a8a6f7b 100644 --- a/loader/i386/xnu.c +++ b/loader/i386/xnu.c @@ -32,6 +32,7 @@ #include #include #include +#include char grub_xnu_cmdline[1024]; grub_uint32_t grub_xnu_heap_will_be_at; @@ -1026,7 +1027,7 @@ grub_cpu_xnu_init (void) { cmd_devprop_load = grub_register_command ("xnu_devprop_load", grub_cmd_devprop_load, - 0, "Load device-properties dump."); + 0, N_("Load device-properties dump.")); } void diff --git a/loader/multiboot_loader.c b/loader/multiboot_loader.c index 790f14d9a..6d042fa81 100644 --- a/loader/multiboot_loader.c +++ b/loader/multiboot_loader.c @@ -26,6 +26,7 @@ #include #include #include +#include grub_dl_t my_mod; @@ -129,15 +130,15 @@ GRUB_MOD_INIT(multiboot) cmd_multiboot = #ifdef GRUB_USE_MULTIBOOT2 grub_register_command ("multiboot2", grub_cmd_multiboot_loader, - 0, "Load a multiboot 2 kernel."); + 0, N_("Load a multiboot 2 kernel.")); #else grub_register_command ("multiboot", grub_cmd_multiboot_loader, - 0, "Load a multiboot kernel."); + 0, N_("Load a multiboot kernel.")); #endif cmd_module = grub_register_command ("module", grub_cmd_module_loader, - 0, "Load a multiboot module."); + 0, N_("Load a multiboot module.")); my_mod = mod; } diff --git a/loader/powerpc/ieee1275/linux.c b/loader/powerpc/ieee1275/linux.c index 085f5c026..39ba2ad0a 100644 --- a/loader/powerpc/ieee1275/linux.c +++ b/loader/powerpc/ieee1275/linux.c @@ -26,6 +26,7 @@ #include #include #include +#include #define ELF32_LOADMASK (0xc0000000UL) #define ELF64_LOADMASK (0xc000000000000000ULL) @@ -349,9 +350,9 @@ static grub_command_t cmd_linux, cmd_initrd; GRUB_MOD_INIT(linux) { cmd_linux = grub_register_command ("linux", grub_cmd_linux, - 0, "Load Linux."); + 0, N_("Load Linux.")); cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, - 0, "Load initrd."); + 0, N_("Load initrd.")); my_mod = mod; } diff --git a/loader/sparc64/ieee1275/linux.c b/loader/sparc64/ieee1275/linux.c index 6ffad202e..4d5723c19 100644 --- a/loader/sparc64/ieee1275/linux.c +++ b/loader/sparc64/ieee1275/linux.c @@ -27,6 +27,7 @@ #include #include #include +#include static grub_dl_t my_mod; @@ -263,7 +264,7 @@ grub_linux_load64 (grub_elf_t elf) return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't map physical memory"); - grub_dprintf ("loader", "Loading linux at vaddr 0x%lx, paddr 0x%lx, size 0x%lx\n", + grub_dprintf ("loader", "Loading Linux at vaddr 0x%lx, paddr 0x%lx, size 0x%lx\n", linux_addr, paddr, linux_size); linux_paddr = paddr; @@ -516,9 +517,9 @@ GRUB_MOD_INIT(linux) fetch_translations (); cmd_linux = grub_register_command ("linux", grub_cmd_linux, - 0, "Load Linux."); + 0, N_("Load Linux.")); cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, - 0, "Load initrd."); + 0, N_("Load initrd.")); my_mod = mod; } diff --git a/loader/xnu.c b/loader/xnu.c index f3ae3888a..c3dcee3ed 100644 --- a/loader/xnu.c +++ b/loader/xnu.c @@ -32,6 +32,7 @@ #include #include #include +#include struct grub_xnu_devtree_key *grub_xnu_devtree_root = 0; static int driverspackagenum = 0; @@ -1404,25 +1405,25 @@ static grub_command_t cmd_kextdir, cmd_ramdisk, cmd_resume, cmd_splash; GRUB_MOD_INIT(xnu) { cmd_kernel = grub_register_command ("xnu_kernel", grub_cmd_xnu_kernel, 0, - "Load XNU image."); + N_("Load XNU image.")); cmd_kernel64 = grub_register_command ("xnu_kernel64", grub_cmd_xnu_kernel64, - 0, "Load 64-bit XNU image."); + 0, N_("Load 64-bit XNU image.")); cmd_mkext = grub_register_command ("xnu_mkext", grub_cmd_xnu_mkext, 0, - "Load XNU extension package."); + N_("Load XNU extension package.")); cmd_kext = grub_register_command ("xnu_kext", grub_cmd_xnu_kext, 0, - "Load XNU extension."); + N_("Load XNU extension.")); cmd_kextdir = grub_register_command ("xnu_kextdir", grub_cmd_xnu_kextdir, - "DIRECTORY [OSBundleRequired]", - "Load XNU extension directory."); + N_("DIRECTORY [OSBundleRequired]"), + N_("Load XNU extension directory.")); cmd_ramdisk = grub_register_command ("xnu_ramdisk", grub_cmd_xnu_ramdisk, 0, - "Load XNU ramdisk. " - "It will be seen as md0."); + N_("Load XNU ramdisk. " + "It will be seen as md0.")); cmd_splash = grub_register_command ("xnu_splash", grub_cmd_xnu_splash, 0, - "Load a splash image for XNU."); + N_("Load a splash image for XNU.")); #ifndef GRUB_UTIL cmd_resume = grub_register_command ("xnu_resume", grub_cmd_xnu_resume, - 0, "Load XNU hibernate image."); + 0, N_("Load XNU hibernate image.")); #endif grub_cpu_xnu_init (); diff --git a/normal/auth.c b/normal/auth.c index 240a77aee..156b84c37 100644 --- a/normal/auth.c +++ b/normal/auth.c @@ -154,6 +154,49 @@ is_authenticated (const char *userlist) return grub_list_iterate (GRUB_AS_LIST (users), hook); } +static int +grub_username_get (char buf[], unsigned buf_size) +{ + unsigned cur_len = 0; + int key; + + while (1) + { + key = GRUB_TERM_ASCII_CHAR (grub_getkey ()); + if (key == '\n' || key == '\r') + break; + + if (key == '\e') + { + cur_len = 0; + break; + } + + if (key == '\b') + { + cur_len--; + grub_printf ("\b"); + continue; + } + + if (!grub_isprint (key)) + continue; + + if (cur_len + 2 < buf_size) + { + buf[cur_len++] = key; + grub_putchar (key); + } + } + + grub_memset (buf + cur_len, 0, buf_size - cur_len); + + grub_putchar ('\n'); + grub_refresh (); + + return (key != '\e'); +} + grub_err_t grub_auth_check_authentication (const char *userlist) { @@ -187,11 +230,12 @@ grub_auth_check_authentication (const char *userlist) return GRUB_ERR_NONE; } - if (!grub_cmdline_get (N_("Enter username:"), login, sizeof (login) - 1, - 0, 0, 0)) + grub_puts_ (N_("Enter username: ")); + + if (!grub_username_get (login, sizeof (login) - 1)) goto access_denied; - grub_printf ("Enter password: "); + grub_puts_ (N_("Enter password: ")); if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN)) goto access_denied; diff --git a/normal/cmdline.c b/normal/cmdline.c index 19b83951a..bcffffeab 100644 --- a/normal/cmdline.c +++ b/normal/cmdline.c @@ -27,11 +27,12 @@ #include #include #include +#include -static char *kill_buf; +static grub_uint32_t *kill_buf; static int hist_size; -static char **hist_lines = 0; +static grub_uint32_t **hist_lines = 0; static int hist_pos = 0; static int hist_end = 0; static int hist_used = 0; @@ -39,8 +40,8 @@ static int hist_used = 0; grub_err_t grub_set_history (int newsize) { - char **old_hist_lines = hist_lines; - hist_lines = grub_malloc (sizeof (char *) * newsize); + grub_uint32_t **old_hist_lines = hist_lines; + hist_lines = grub_malloc (sizeof (grub_uint32_t *) * newsize); /* Copy the old lines into the new buffer. */ if (old_hist_lines) @@ -67,16 +68,16 @@ grub_set_history (int newsize) if (hist_pos < hist_end) grub_memmove (hist_lines, old_hist_lines + hist_pos, - (hist_end - hist_pos) * sizeof (char *)); + (hist_end - hist_pos) * sizeof (grub_uint32_t *)); else if (hist_used) { /* Copy the older part. */ grub_memmove (hist_lines, old_hist_lines + hist_pos, - (hist_size - hist_pos) * sizeof (char *)); + (hist_size - hist_pos) * sizeof (grub_uint32_t *)); /* Copy the newer part. */ grub_memmove (hist_lines + hist_size - hist_pos, old_hist_lines, - hist_end * sizeof (char *)); + hist_end * sizeof (grub_uint32_t *)); } } @@ -90,17 +91,43 @@ grub_set_history (int newsize) /* Get the entry POS from the history where `0' is the newest entry. */ -static char * +static grub_uint32_t * grub_history_get (int pos) { pos = (hist_pos + pos) % hist_size; return hist_lines[pos]; } +static grub_size_t +strlen_ucs4 (const grub_uint32_t *s) +{ + const grub_uint32_t *p = s; + + while (*p) + p++; + + return p - s; +} + +/* Replace the history entry on position POS with the string S. */ +static void +grub_history_set (int pos, grub_uint32_t *s, grub_size_t len) +{ + grub_free (hist_lines[pos]); + hist_lines[pos] = grub_malloc ((len + 1) * sizeof (grub_uint32_t)); + if (!hist_lines[pos]) + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + return ; + } + grub_memcpy (hist_lines[pos], s, len * sizeof (grub_uint32_t)); + hist_lines[pos][len] = 0; +} /* Insert a new history line S on the top of the history. */ static void -grub_history_add (char *s) +grub_history_add (grub_uint32_t *s, grub_size_t len) { /* Remove the oldest entry in the history to make room for a new entry. */ @@ -121,16 +148,15 @@ grub_history_add (char *s) hist_pos = hist_size + hist_pos; /* Insert into history. */ - hist_lines[hist_pos] = grub_strdup (s); + hist_lines[hist_pos] = NULL; + grub_history_set (hist_pos, s, len); } /* Replace the history entry on position POS with the string S. */ static void -grub_history_replace (int pos, char *s) +grub_history_replace (int pos, grub_uint32_t *s, grub_size_t len) { - pos = (hist_pos + pos) % hist_size; - grub_free (hist_lines[pos]); - hist_lines[pos] = grub_strdup (s); + grub_history_set ((hist_pos + pos) % hist_size, s, len); } /* A completion hook to print items. */ @@ -140,31 +166,30 @@ print_completion (const char *item, grub_completion_type_t type, int count) if (count == 0) { /* If this is the first time, print a label. */ - const char *what; - + + grub_puts (""); switch (type) { case GRUB_COMPLETION_TYPE_COMMAND: - what = "commands"; + grub_puts_ (N_("Possible commands are:")); break; case GRUB_COMPLETION_TYPE_DEVICE: - what = "devices"; + grub_puts_ (N_("Possible devices are:")); break; case GRUB_COMPLETION_TYPE_FILE: - what = "files"; + grub_puts_ (N_("Possible files are:")); break; case GRUB_COMPLETION_TYPE_PARTITION: - what = "partitions"; + grub_puts_ (N_("Possible partitions are:")); break; case GRUB_COMPLETION_TYPE_ARGUMENT: - what = "arguments"; + grub_puts_ (N_("Possible arguments are:")); break; default: - what = "things"; + grub_puts_ (N_("Possible things are:")); break; } - - grub_printf ("\nPossible %s are:\n", what); + grub_puts (""); } if (type == GRUB_COMPLETION_TYPE_PARTITION) @@ -176,75 +201,112 @@ print_completion (const char *item, grub_completion_type_t type, int count) grub_printf (" %s", item); } -/* Get a command-line. If ECHO_CHAR is not zero, echo it instead of input - characters. If READLINE is non-zero, readline-like key bindings are - available. If ESC is pushed, return zero, otherwise return non-zero. */ -/* FIXME: The dumb interface is not supported yet. */ -int -grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len, - int echo_char, int readline, int history) +struct cmdline_term +{ + unsigned xpos, ypos, ystart, width, height; + struct grub_term_output *term; +}; + +/* Get a command-line. If ESC is pushed, return zero, + otherwise return command line. */ +/* FIXME: The dumb interface is not supported yet. */ +char * +grub_cmdline_get (const char *prompt) { - unsigned xpos, ypos, ystart; grub_size_t lpos, llen; grub_size_t plen; - char buf[max_len]; + grub_uint32_t *buf; + grub_size_t max_len = 256; int key; int histpos = 0; - auto void cl_insert (const char *str); + auto void cl_insert (const grub_uint32_t *str); auto void cl_delete (unsigned len); - auto void cl_print (int pos, int c); - auto void cl_set_pos (void); + auto inline void __attribute__ ((always_inline)) cl_print (struct cmdline_term *cl_term, int pos, + grub_uint32_t c); + auto void cl_set_pos (struct cmdline_term *cl_term); + auto void cl_print_all (int pos, grub_uint32_t c); + auto void cl_set_pos_all (void); + auto void init_clterm (struct cmdline_term *cl_term_cur); + auto void init_clterm_all (void); const char *prompt_translated = _(prompt); + struct cmdline_term *cl_terms; + char *ret; + unsigned nterms; - void cl_set_pos (void) + void cl_set_pos (struct cmdline_term *cl_term) + { + cl_term->xpos = (plen + lpos) % (cl_term->width - 1); + cl_term->ypos = cl_term->ystart + (plen + lpos) / (cl_term->width - 1); + grub_term_gotoxy (cl_term->term, cl_term->xpos, cl_term->ypos); + } + + void cl_set_pos_all () + { + unsigned i; + for (i = 0; i < nterms; i++) + cl_set_pos (&cl_terms[i]); + } + + inline void __attribute__ ((always_inline)) cl_print (struct cmdline_term *cl_term, int pos, grub_uint32_t c) { - xpos = (plen + lpos) % 79; - ypos = ystart + (plen + lpos) / 79; - grub_gotoxy (xpos, ypos); + grub_uint32_t *p; - grub_refresh (); - } - - void cl_print (int pos, int c) - { - char *p; - - for (p = buf + pos; *p; p++) + for (p = buf + pos; p < buf + llen; p++) { - if (xpos++ > 78) - { - grub_putchar ('\n'); - - xpos = 1; - if (ypos == (unsigned) (grub_getxy () & 0xFF)) - ystart--; - else - ypos++; - } - if (c) - grub_putchar (c); + grub_putcode (c, cl_term->term); else - grub_putchar (*p); + grub_putcode (*p, cl_term->term); + cl_term->xpos++; + if (cl_term->xpos >= cl_term->width - 1) + { + cl_term->xpos = 0; + if (cl_term->ypos >= (unsigned) (cl_term->height - 1)) + cl_term->ystart--; + else + cl_term->ypos++; + grub_putcode ('\n', cl_term->term); + } } } - void cl_insert (const char *str) + void cl_print_all (int pos, grub_uint32_t c) + { + unsigned i; + for (i = 0; i < nterms; i++) + cl_print (&cl_terms[i], pos, c); + } + + void cl_insert (const grub_uint32_t *str) { - grub_size_t len = grub_strlen (str); + grub_size_t len = strlen_ucs4 (str); + + if (len + llen >= max_len) + { + grub_uint32_t *nbuf; + max_len *= 2; + nbuf = grub_realloc (buf, sizeof (grub_uint32_t) * max_len); + if (nbuf) + buf = nbuf; + else + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + max_len /= 2; + } + } if (len + llen < max_len) { - grub_memmove (buf + lpos + len, buf + lpos, llen - lpos + 1); - grub_memmove (buf + lpos, str, len); + grub_memmove (buf + lpos + len, buf + lpos, + (llen - lpos + 1) * sizeof (grub_uint32_t)); + grub_memmove (buf + lpos, str, len * sizeof (grub_uint32_t)); llen += len; lpos += len; - cl_print (lpos - len, echo_char); - cl_set_pos (); + cl_print_all (lpos - len, 0); + cl_set_pos_all (); } - - grub_refresh (); } void cl_delete (unsigned len) @@ -254,182 +316,254 @@ grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len, grub_size_t saved_lpos = lpos; lpos = llen - len; - cl_set_pos (); - cl_print (lpos, ' '); + cl_set_pos_all (); + cl_print_all (lpos, ' '); lpos = saved_lpos; - cl_set_pos (); + cl_set_pos_all (); - grub_memmove (buf + lpos, buf + lpos + len, llen - lpos + 1); + grub_memmove (buf + lpos, buf + lpos + len, + sizeof (grub_uint32_t) * (llen - lpos + 1)); llen -= len; - cl_print (lpos, echo_char); - cl_set_pos (); + cl_print_all (lpos, 0); + cl_set_pos_all (); } - - grub_refresh (); } + void init_clterm (struct cmdline_term *cl_term_cur) + { + cl_term_cur->xpos = plen; + cl_term_cur->ypos = (grub_term_getxy (cl_term_cur->term) & 0xFF); + cl_term_cur->ystart = cl_term_cur->ypos; + cl_term_cur->width = grub_term_width (cl_term_cur->term); + cl_term_cur->height = grub_term_height (cl_term_cur->term); + } + + void init_clterm_all (void) + { + unsigned i; + for (i = 0; i < nterms; i++) + init_clterm (&cl_terms[i]); + } + + buf = grub_malloc (max_len * sizeof (grub_uint32_t)); + if (!buf) + return 0; + plen = grub_strlen (prompt_translated) + sizeof (" ") - 1; lpos = llen = 0; buf[0] = '\0'; - if ((grub_getxy () >> 8) != 0) - grub_putchar ('\n'); + { + grub_term_output_t term; + FOR_ACTIVE_TERM_OUTPUTS(term) + if ((grub_term_getxy (term) >> 8) != 0) + grub_putcode ('\n', term); + } grub_printf ("%s ", prompt_translated); - xpos = plen; - ystart = ypos = (grub_getxy () & 0xFF); + { + struct cmdline_term *cl_term_cur; + struct grub_term_output *cur; + nterms = 0; + FOR_ACTIVE_TERM_OUTPUTS(cur) + nterms++; - cl_insert (cmdline); + cl_terms = grub_malloc (sizeof (cl_terms[0]) * nterms); + if (!cl_terms) + return 0; + cl_term_cur = cl_terms; + FOR_ACTIVE_TERM_OUTPUTS(cur) + { + cl_term_cur->term = cur; + init_clterm (cl_term_cur); + cl_term_cur++; + } + } - if (history && hist_used == 0) - grub_history_add (buf); + if (hist_used == 0) + grub_history_add (buf, llen); while ((key = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != '\n' && key != '\r') { - if (readline) - { - switch (key) - { - case 1: /* Ctrl-a */ - lpos = 0; - cl_set_pos (); - break; - - case 2: /* Ctrl-b */ - if (lpos > 0) - { - lpos--; - cl_set_pos (); - } - break; - - case 5: /* Ctrl-e */ - lpos = llen; - cl_set_pos (); - break; - - case 6: /* Ctrl-f */ - if (lpos < llen) - { - lpos++; - cl_set_pos (); - } - break; - - case 9: /* Ctrl-i or TAB */ - { - char *insert; - int restore; - - /* Backup the next character and make it 0 so it will - be easy to use string functions. */ - char backup = buf[lpos]; - buf[lpos] = '\0'; - - - insert = grub_normal_do_completion (buf, &restore, - print_completion); - /* Restore the original string. */ - buf[lpos] = backup; - - if (restore) - { - /* Restore the prompt. */ - grub_printf ("\n%s %s", prompt_translated, buf); - xpos = plen; - ystart = ypos = (grub_getxy () & 0xFF); - } - - if (insert) - { - cl_insert (insert); - grub_free (insert); - } - } - break; - - case 11: /* Ctrl-k */ - if (lpos < llen) - { - if (kill_buf) - grub_free (kill_buf); - - kill_buf = grub_strdup (buf + lpos); - grub_errno = GRUB_ERR_NONE; - - cl_delete (llen - lpos); - } - break; - - case 14: /* Ctrl-n */ - { - char *hist; - - lpos = 0; - - if (histpos > 0) - { - grub_history_replace (histpos, buf); - histpos--; - } - - cl_delete (llen); - hist = grub_history_get (histpos); - cl_insert (hist); - - break; - } - case 16: /* Ctrl-p */ - { - char *hist; - - lpos = 0; - - if (histpos < hist_used - 1) - { - grub_history_replace (histpos, buf); - histpos++; - } - - cl_delete (llen); - hist = grub_history_get (histpos); - - cl_insert (hist); - } - break; - - case 21: /* Ctrl-u */ - if (lpos > 0) - { - grub_size_t n = lpos; - - if (kill_buf) - grub_free (kill_buf); - - kill_buf = grub_malloc (n + 1); - grub_errno = GRUB_ERR_NONE; - if (kill_buf) - { - grub_memcpy (kill_buf, buf, n); - kill_buf[n] = '\0'; - } - - lpos = 0; - cl_set_pos (); - cl_delete (n); - } - break; - - case 25: /* Ctrl-y */ - if (kill_buf) - cl_insert (kill_buf); - break; - } - } - switch (key) { + case 1: /* Ctrl-a */ + lpos = 0; + cl_set_pos_all (); + break; + + case 2: /* Ctrl-b */ + if (lpos > 0) + { + lpos--; + cl_set_pos_all (); + } + break; + + case 5: /* Ctrl-e */ + lpos = llen; + cl_set_pos_all (); + break; + + case 6: /* Ctrl-f */ + if (lpos < llen) + { + lpos++; + cl_set_pos_all (); + } + break; + + case 9: /* Ctrl-i or TAB */ + { + int restore; + char *insertu8; + char *bufu8; + + buf[lpos] = '\0'; + + bufu8 = grub_ucs4_to_utf8_alloc (buf, lpos); + if (!bufu8) + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + break; + } + + insertu8 = grub_normal_do_completion (bufu8, &restore, + print_completion); + grub_free (bufu8); + + if (restore) + { + /* Restore the prompt. */ + grub_printf ("\n%s ", prompt_translated); + init_clterm_all (); + cl_print_all (0, 0); + } + + if (insertu8) + { + grub_size_t insertlen; + grub_ssize_t t; + grub_uint32_t *insert; + + insertlen = grub_strlen (insertu8); + insert = grub_malloc ((insertlen + 1) * sizeof (grub_uint32_t)); + if (!insert) + { + grub_free (insertu8); + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + break; + } + t = grub_utf8_to_ucs4 (insert, insertlen, + (grub_uint8_t *) insertu8, + insertlen, 0); + if (t > 0) + { + insert[t] = 0; + cl_insert (insert); + } + + grub_free (insertu8); + grub_free (insert); + } + } + break; + + case 11: /* Ctrl-k */ + if (lpos < llen) + { + if (kill_buf) + grub_free (kill_buf); + + kill_buf = grub_malloc ((llen - lpos + 1) + * sizeof (grub_uint32_t)); + if (grub_errno) + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + } + else + { + grub_memcpy (kill_buf, buf + lpos, + (llen - lpos + 1) * sizeof (grub_uint32_t)); + kill_buf[llen - lpos] = 0; + } + + cl_delete (llen - lpos); + } + break; + + case 14: /* Ctrl-n */ + { + grub_uint32_t *hist; + + lpos = 0; + + if (histpos > 0) + { + grub_history_replace (histpos, buf, llen); + histpos--; + } + + cl_delete (llen); + hist = grub_history_get (histpos); + cl_insert (hist); + + break; + } + case 16: /* Ctrl-p */ + { + grub_uint32_t *hist; + + lpos = 0; + + if (histpos < hist_used - 1) + { + grub_history_replace (histpos, buf, llen); + histpos++; + } + + cl_delete (llen); + hist = grub_history_get (histpos); + + cl_insert (hist); + } + break; + + case 21: /* Ctrl-u */ + if (lpos > 0) + { + grub_size_t n = lpos; + + if (kill_buf) + grub_free (kill_buf); + + kill_buf = grub_malloc (n + 1); + if (grub_errno) + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + } + if (kill_buf) + { + grub_memcpy (kill_buf, buf, n); + kill_buf[n] = '\0'; + } + + lpos = 0; + cl_set_pos_all (); + cl_delete (n); + } + break; + + case 25: /* Ctrl-y */ + if (kill_buf) + cl_insert (kill_buf); + break; + case '\e': return 0; @@ -437,7 +571,7 @@ grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len, if (lpos > 0) { lpos--; - cl_set_pos (); + cl_set_pos_all (); } else break; @@ -451,7 +585,7 @@ grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len, default: if (grub_isprint (key)) { - char str[2]; + grub_uint32_t str[2]; str[0] = key; str[1] = '\0'; @@ -459,28 +593,26 @@ grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len, } break; } + grub_refresh (); } grub_putchar ('\n'); grub_refresh (); - /* If ECHO_CHAR is NUL, remove leading spaces. */ + /* Remove leading spaces. */ lpos = 0; - if (! echo_char) - while (buf[lpos] == ' ') - lpos++; + while (buf[lpos] == ' ') + lpos++; - if (history) + histpos = 0; + if (strlen_ucs4 (buf) > 0) { - histpos = 0; - if (grub_strlen (buf) > 0) - { - grub_history_replace (histpos, buf); - grub_history_add (""); - } + grub_uint32_t empty[] = { 0 }; + grub_history_replace (histpos, buf, llen); + grub_history_add (empty, 0); } - grub_memcpy (cmdline, buf + lpos, llen - lpos + 1); - - return 1; + ret = grub_ucs4_to_utf8_alloc (buf + lpos, llen - lpos + 1); + grub_free (buf); + return ret; } diff --git a/normal/color.c b/normal/color.c index 0b9868d3b..bae082911 100644 --- a/normal/color.c +++ b/normal/color.c @@ -103,23 +103,31 @@ free_and_return: grub_free (fg_name); } +static grub_uint8_t color_normal, color_highlight; + +static void +set_colors (void) +{ + struct grub_term_output *term; + + FOR_ACTIVE_TERM_OUTPUTS(term) + { + /* Reloads terminal `normal' and `highlight' colors. */ + grub_term_setcolor (term, color_normal, color_highlight); + + /* Propagates `normal' color to terminal current color. */ + grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL); + } +} + /* Replace default `normal' colors with the ones specified by user (if any). */ char * grub_env_write_color_normal (struct grub_env_var *var __attribute__ ((unused)), const char *val) { - grub_uint8_t color_normal, color_highlight; - - /* Use old settings in case grub_parse_color_name_pair() has no effect. */ - grub_getcolor (&color_normal, &color_highlight); - grub_parse_color_name_pair (&color_normal, val); - /* Reloads terminal `normal' and `highlight' colors. */ - grub_setcolor (color_normal, color_highlight); - - /* Propagates `normal' color to terminal current color. */ - grub_setcolorstate (GRUB_TERM_COLOR_NORMAL); + set_colors (); return grub_strdup (val); } @@ -129,21 +137,9 @@ char * grub_env_write_color_highlight (struct grub_env_var *var __attribute__ ((unused)), const char *val) { - grub_uint8_t color_normal, color_highlight; - - /* Use old settings in case grub_parse_color_name_pair() has no effect. */ - grub_getcolor (&color_normal, &color_highlight); - grub_parse_color_name_pair (&color_highlight, val); - /* Reloads terminal `normal' and `highlight' colors. */ - grub_setcolor (color_normal, color_highlight); - - /* Propagates `normal' color to terminal current color. - Note: Using GRUB_TERM_COLOR_NORMAL here rather than - GRUB_TERM_COLOR_HIGHLIGHT is intentional. We don't want to switch - to highlight state just because color was reloaded. */ - grub_setcolorstate (GRUB_TERM_COLOR_NORMAL); + set_colors (); return grub_strdup (val); } diff --git a/normal/main.c b/normal/main.c index 84162c08a..7a5e3ee8e 100644 --- a/normal/main.c +++ b/normal/main.c @@ -30,9 +30,13 @@ #include #include #include +#include #define GRUB_DEFAULT_HISTORY_SIZE 50 +static int nested_level = 0; +int grub_normal_exit_level = 0; + /* Read a line from the file FILE. */ char * grub_file_getline (grub_file_t file) @@ -372,7 +376,21 @@ read_config_file (const char *config) if (! file) return 0; - grub_reader_loop (getline); + while (1) + { + char *line; + + /* Print an error, if any. */ + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + + if ((getline (&line, 0)) || (! line)) + break; + + grub_parser_get_current ()->parse_line (line, getline); + grub_free (line); + } + grub_file_close (file); if (old_parser) @@ -383,7 +401,7 @@ read_config_file (const char *config) /* Initialize the screen. */ void -grub_normal_init_page (void) +grub_normal_init_page (struct grub_term_output *term) { int msg_len; int posx; @@ -391,14 +409,13 @@ grub_normal_init_page (void) char *msg_formatted = grub_malloc (grub_strlen(msg) + grub_strlen(PACKAGE_VERSION)); - - grub_cls (); - - grub_sprintf (msg_formatted, msg, PACKAGE_VERSION); - grub_uint32_t *unicode_msg; grub_uint32_t *last_position; + grub_term_cls (term); + + grub_sprintf (msg_formatted, msg, PACKAGE_VERSION); + msg_len = grub_utf8_to_ucs4_alloc (msg_formatted, &unicode_msg, &last_position); @@ -407,17 +424,15 @@ grub_normal_init_page (void) return; } - posx = grub_getstringwidth (unicode_msg, last_position); - posx = (GRUB_TERM_WIDTH - posx) / 2; - grub_gotoxy (posx, 1); + posx = grub_getstringwidth (unicode_msg, last_position, term); + posx = (grub_term_width (term) - posx) / 2; + grub_term_gotoxy (term, posx, 1); - grub_print_ucs4 (unicode_msg, last_position); + grub_print_ucs4 (unicode_msg, last_position, term); grub_printf("\n\n"); grub_free (unicode_msg); } -static int reader_nested; - static char * read_lists (struct grub_env_var *var __attribute__ ((unused)), const char *val) @@ -425,6 +440,7 @@ read_lists (struct grub_env_var *var __attribute__ ((unused)), read_command_list (); read_fs_list (); read_crypto_list (); + read_terminal_list (); return val ? grub_strdup (val) : NULL; } @@ -440,8 +456,6 @@ grub_normal_execute (const char *config, int nested, int batch) grub_register_variable_hook ("prefix", NULL, read_lists); grub_command_execute ("parser.grub", 0, 0); - reader_nested = nested; - if (config) { menu = read_config_file (config); @@ -454,7 +468,7 @@ grub_normal_execute (const char *config, int nested, int batch) { if (menu && menu->size) { - grub_menu_viewer_show_menu (menu, nested); + grub_show_menu (menu, nested); if (nested) free_menu (menu); } @@ -465,21 +479,24 @@ grub_normal_execute (const char *config, int nested, int batch) void grub_enter_normal_mode (const char *config) { + nested_level++; grub_normal_execute (config, 0, 0); + grub_cmdline_run (0); + nested_level--; + if (grub_normal_exit_level) + grub_normal_exit_level--; } /* Enter normal mode from rescue mode. */ static grub_err_t -grub_cmd_normal (struct grub_command *cmd, +grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), int argc, char *argv[]) { - grub_unregister_command (cmd); - if (argc == 0) { /* Guess the config filename. It is necessary to make CONFIG static, so that it won't get broken by longjmp. */ - static char *config; + char *config; const char *prefix; prefix = grub_env_get ("prefix"); @@ -503,10 +520,82 @@ quit: return 0; } +/* Exit from normal mode to rescue mode. */ +static grub_err_t +grub_cmd_normal_exit (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char *argv[] __attribute__ ((unused))) +{ + if (nested_level <= grub_normal_exit_level) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "not in normal environment"); + grub_normal_exit_level++; + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_normal_reader_init (int nested) +{ + struct grub_term_output *term; + const char *msg = _("Minimal BASH-like line editing is supported. For " + "the first word, TAB lists possible command completions. Anywhere " + "else TAB lists possible device or file completions. %s"); + const char *msg_esc = _("ESC at any time exits."); + char *msg_formatted = grub_malloc (sizeof (char) * (grub_strlen (msg) + + grub_strlen(msg_esc) + 1)); + + grub_sprintf (msg_formatted, msg, nested ? msg_esc : ""); + + FOR_ACTIVE_TERM_OUTPUTS(term) + { + grub_normal_init_page (term); + grub_term_setcursor (term, 1); + + grub_print_message_indented (msg_formatted, 3, STANDARD_MARGIN, term); + grub_puts ("\n"); + } + grub_free (msg_formatted); + + return 0; +} + + +static grub_err_t +grub_normal_read_line_real (char **line, int cont, int nested) +{ + grub_parser_t parser = grub_parser_get_current (); + char prompt[sizeof(">") + grub_strlen (parser->name)]; + + if (cont) + grub_sprintf (prompt, ">"); + else + grub_sprintf (prompt, "%s>", parser->name); + + while (1) + { + *line = grub_cmdline_get (prompt); + if (*line) + break; + + if (cont || nested) + { + grub_free (*line); + *line = 0; + return grub_errno; + } + } + + return 0; +} + +static grub_err_t +grub_normal_read_line (char **line, int cont) +{ + return grub_normal_read_line_real (line, cont, 0); +} + void grub_cmdline_run (int nested) { - grub_reader_t reader; grub_err_t err = GRUB_ERR_NONE; err = grub_auth_check_authentication (NULL); @@ -518,72 +607,28 @@ grub_cmdline_run (int nested) return; } - reader = grub_reader_get_current (); - - reader_nested = nested; - if (reader->init) - reader->init (); - grub_reader_loop (0); -} - -static grub_err_t -grub_normal_reader_init (void) -{ - grub_normal_init_page (); - grub_setcursor (1); - - const char *msg = _("Minimal BASH-like line editing is supported. For " - "the first word, TAB lists possible command completions. Anywhere " - "else TAB lists possible device or file completions. %s"); - - const char *msg_esc = _("ESC at any time exits."); - - char *msg_formatted = grub_malloc (sizeof (char) * (grub_strlen (msg) + - grub_strlen(msg_esc) + 1)); - - grub_sprintf (msg_formatted, msg, reader_nested ? msg_esc : ""); - grub_print_message_indented (msg_formatted, 3, STANDARD_MARGIN); - grub_puts ("\n"); - - grub_free (msg_formatted); - - return 0; -} - -static char cmdline[GRUB_MAX_CMDLINE]; - -static grub_err_t -grub_normal_read_line (char **line, int cont) -{ - grub_parser_t parser = grub_parser_get_current (); - char prompt[sizeof(">") + grub_strlen (parser->name)]; - - grub_sprintf (prompt, "%s>", parser->name); + grub_normal_reader_init (nested); while (1) { - cmdline[0] = 0; - if (grub_cmdline_get (prompt, cmdline, sizeof (cmdline), 0, 1, 1)) + char *line; + + if (grub_normal_exit_level) break; - if ((reader_nested) || (cont)) - { - *line = 0; - return grub_errno; - } + /* Print an error, if any. */ + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + + grub_normal_read_line_real (&line, 0, nested); + if (! line) + break; + + grub_parser_get_current ()->parse_line (line, grub_normal_read_line); + grub_free (line); } - - *line = grub_strdup (cmdline); - return 0; } -static struct grub_reader grub_normal_reader = - { - .name = "normal", - .init = grub_normal_reader_init, - .read_line = grub_normal_read_line - }; - static char * grub_env_write_pager (struct grub_env_var *var __attribute__ ((unused)), const char *val) @@ -598,17 +643,15 @@ GRUB_MOD_INIT(normal) if (mod) grub_dl_ref (mod); - grub_menu_viewer_register (&grub_normal_text_menu_viewer); - grub_set_history (GRUB_DEFAULT_HISTORY_SIZE); - grub_reader_register ("normal", &grub_normal_reader); - grub_reader_set_current (&grub_normal_reader); grub_register_variable_hook ("pager", 0, grub_env_write_pager); /* Register a command "normal" for the rescue mode. */ - grub_register_command_prio ("normal", grub_cmd_normal, - 0, "Enter normal mode.", 0); + grub_register_command ("normal", grub_cmd_normal, + 0, "Enter normal mode."); + grub_register_command ("normal_exit", grub_cmd_normal_exit, + 0, "Exit from normal mode."); /* Reload terminal colors when these variables are written to. */ grub_register_variable_hook ("color_normal", NULL, grub_env_write_color_normal); @@ -622,7 +665,6 @@ GRUB_MOD_INIT(normal) GRUB_MOD_FINI(normal) { grub_set_history (0); - grub_reader_unregister (&grub_normal_reader); grub_register_variable_hook ("pager", 0, 0); grub_fs_autoload_hook = 0; free_handler_list (); diff --git a/normal/menu.c b/normal/menu.c index 8ee7d1c22..17730eff3 100644 --- a/normal/menu.c +++ b/normal/menu.c @@ -27,6 +27,26 @@ #include #include #include +#include +#include + +/* Time to delay after displaying an error message about a default/fallback + entry failing to boot. */ +#define DEFAULT_ENTRY_ERROR_DELAY_MS 2500 + +grub_err_t (*grub_gfxmenu_try_hook) (int entry, grub_menu_t menu, + int nested) = NULL; + +/* Wait until the user pushes any key so that the user + can see what happened. */ +void +grub_wait_after_message (void) +{ + grub_putchar ('\n'); + grub_printf_ (N_("Press any key to continue...")); + (void) grub_getkey (); + grub_putchar ('\n'); +} /* Get a menu entry by its index in the entry list. */ grub_menu_entry_t @@ -137,6 +157,8 @@ grub_menu_execute_entry(grub_menu_entry_t entry) return; } + grub_env_set ("chosen", entry->title); + grub_parser_execute ((char *) entry->sourcecode); if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ()) @@ -178,3 +200,400 @@ grub_menu_execute_with_fallback (grub_menu_t menu, callback->notify_failure (callback_data); } + +static struct grub_menu_viewer *viewers; + +static void +menu_set_chosen_entry (int entry) +{ + struct grub_menu_viewer *cur; + for (cur = viewers; cur; cur = cur->next) + cur->set_chosen_entry (entry, cur->data); +} + +static void +menu_print_timeout (int timeout) +{ + struct grub_menu_viewer *cur; + for (cur = viewers; cur; cur = cur->next) + cur->print_timeout (timeout, cur->data); +} + +static void +menu_fini (void) +{ + struct grub_menu_viewer *cur, *next; + for (cur = viewers; cur; cur = next) + { + next = cur->next; + cur->fini (cur->data); + grub_free (cur); + } + viewers = NULL; +} + +static void +menu_init (int entry, grub_menu_t menu, int nested) +{ + struct grub_term_output *term; + + FOR_ACTIVE_TERM_OUTPUTS(term) + { + grub_err_t err; + + if (grub_gfxmenu_try_hook && grub_strcmp (term->name, "gfxterm") == 0) + { + err = grub_gfxmenu_try_hook (entry, menu, nested); + if(!err) + continue; + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + } + + err = grub_menu_try_text (term, entry, menu, nested); + if(!err) + continue; + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + } +} + +static void +clear_timeout (void) +{ + struct grub_menu_viewer *cur; + for (cur = viewers; cur; cur = cur->next) + cur->clear_timeout (cur->data); +} + +void +grub_menu_register_viewer (struct grub_menu_viewer *viewer) +{ + viewer->next = viewers; + viewers = viewer; +} + +/* Get the entry number from the variable NAME. */ +static int +get_entry_number (grub_menu_t menu, const char *name) +{ + char *val; + int entry; + + val = grub_env_get (name); + if (! val) + return -1; + + grub_error_push (); + + entry = (int) grub_strtoul (val, 0, 0); + + if (grub_errno == GRUB_ERR_BAD_NUMBER) + { + /* See if the variable matches the title of a menu entry. */ + grub_menu_entry_t e = menu->entry_list; + int i; + + grub_errno = GRUB_ERR_NONE; + + for (i = 0; e; i++) + { + if (grub_strcmp (e->title, val) == 0) + { + entry = i; + break; + } + e = e->next; + } + + if (! e) + entry = -1; + } + + if (grub_errno != GRUB_ERR_NONE) + { + grub_errno = GRUB_ERR_NONE; + entry = -1; + } + + grub_error_pop (); + + return entry; +} + +#define GRUB_MENU_PAGE_SIZE 10 + +/* Show the menu and handle menu entry selection. Returns the menu entry + index that should be executed or -1 if no entry should be executed (e.g., + Esc pressed to exit a sub-menu or switching menu viewers). + If the return value is not -1, then *AUTO_BOOT is nonzero iff the menu + entry to be executed is a result of an automatic default selection because + of the timeout. */ +static int +run_menu (grub_menu_t menu, int nested, int *auto_boot) +{ + grub_uint64_t saved_time; + int default_entry, current_entry; + int timeout; + + default_entry = get_entry_number (menu, "default"); + + /* If DEFAULT_ENTRY is not within the menu entries, fall back to + the first entry. */ + if (default_entry < 0 || default_entry >= menu->size) + default_entry = 0; + + /* If timeout is 0, drawing is pointless (and ugly). */ + if (grub_menu_get_timeout () == 0) + { + *auto_boot = 1; + return default_entry; + } + + current_entry = default_entry; + + /* Initialize the time. */ + saved_time = grub_get_time_ms (); + + refresh: + menu_init (current_entry, menu, nested); + + timeout = grub_menu_get_timeout (); + + if (timeout > 0) + menu_print_timeout (timeout); + + while (1) + { + int c; + timeout = grub_menu_get_timeout (); + + if (grub_normal_exit_level) + return -1; + + if (timeout > 0) + { + grub_uint64_t current_time; + + current_time = grub_get_time_ms (); + if (current_time - saved_time >= 1000) + { + timeout--; + grub_menu_set_timeout (timeout); + saved_time = current_time; + menu_print_timeout (timeout); + } + } + + if (timeout == 0) + { + grub_env_unset ("timeout"); + *auto_boot = 1; + menu_fini (); + return default_entry; + } + + if (grub_checkkey () >= 0 || timeout < 0) + { + c = GRUB_TERM_ASCII_CHAR (grub_getkey ()); + + if (timeout >= 0) + { + grub_env_unset ("timeout"); + grub_env_unset ("fallback"); + clear_timeout (); + } + + switch (c) + { + case GRUB_TERM_HOME: + current_entry = 0; + menu_set_chosen_entry (current_entry); + break; + + case GRUB_TERM_END: + current_entry = menu->size - 1; + menu_set_chosen_entry (current_entry); + break; + + case GRUB_TERM_UP: + case '^': + if (current_entry > 0) + current_entry--; + menu_set_chosen_entry (current_entry); + break; + + case GRUB_TERM_DOWN: + case 'v': + if (current_entry < menu->size - 1) + current_entry++; + menu_set_chosen_entry (current_entry); + break; + + case GRUB_TERM_PPAGE: + if (current_entry < GRUB_MENU_PAGE_SIZE) + current_entry = 0; + else + current_entry -= GRUB_MENU_PAGE_SIZE; + menu_set_chosen_entry (current_entry); + break; + + case GRUB_TERM_NPAGE: + if (current_entry + GRUB_MENU_PAGE_SIZE < menu->size) + current_entry += GRUB_MENU_PAGE_SIZE; + else + current_entry = menu->size - 1; + menu_set_chosen_entry (current_entry); + break; + + case '\n': + case '\r': + case 6: + menu_fini (); + *auto_boot = 0; + return current_entry; + + case '\e': + if (nested) + { + menu_fini (); + return -1; + } + break; + + case 'c': + menu_fini (); + grub_cmdline_run (1); + goto refresh; + + case 'e': + menu_fini (); + { + grub_menu_entry_t e = grub_menu_get_entry (menu, current_entry); + if (e) + grub_menu_entry_run (e); + } + goto refresh; + + default: + break; + } + } + } + + /* Never reach here. */ + return -1; +} + +/* Callback invoked immediately before a menu entry is executed. */ +static void +notify_booting (grub_menu_entry_t entry, + void *userdata __attribute__((unused))) +{ + grub_printf (" "); + grub_printf_ (N_("Booting \'%s\'"), entry->title); + grub_printf ("\n\n"); +} + +/* Callback invoked when a default menu entry executed because of a timeout + has failed and an attempt will be made to execute the next fallback + entry, ENTRY. */ +static void +notify_fallback (grub_menu_entry_t entry, + void *userdata __attribute__((unused))) +{ + grub_printf ("\n "); + grub_printf_ (N_("Falling back to \'%s\'"), entry->title); + grub_printf ("\n\n"); + grub_millisleep (DEFAULT_ENTRY_ERROR_DELAY_MS); +} + +/* Callback invoked when a menu entry has failed and there is no remaining + fallback entry to attempt. */ +static void +notify_execution_failure (void *userdata __attribute__((unused))) +{ + if (grub_errno != GRUB_ERR_NONE) + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + } + grub_printf ("\n "); + grub_printf_ (N_("Failed to boot default entries.\n")); + grub_wait_after_message (); +} + +/* Callbacks used by the text menu to provide user feedback when menu entries + are executed. */ +static struct grub_menu_execute_callback execution_callback = +{ + .notify_booting = notify_booting, + .notify_fallback = notify_fallback, + .notify_failure = notify_execution_failure +}; + +static grub_err_t +show_menu (grub_menu_t menu, int nested) +{ + while (1) + { + int boot_entry; + grub_menu_entry_t e; + int auto_boot; + + boot_entry = run_menu (menu, nested, &auto_boot); + if (boot_entry < 0) + break; + + e = grub_menu_get_entry (menu, boot_entry); + if (! e) + continue; /* Menu is empty. */ + + grub_cls (); + + if (auto_boot) + { + grub_menu_execute_with_fallback (menu, e, &execution_callback, 0); + } + else + { + grub_errno = GRUB_ERR_NONE; + grub_menu_execute_entry (e); + if (grub_errno != GRUB_ERR_NONE) + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + grub_wait_after_message (); + } + } + } + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_show_menu (grub_menu_t menu, int nested) +{ + grub_err_t err1, err2; + + while (1) + { + err1 = show_menu (menu, nested); + grub_print_error (); + + if (grub_normal_exit_level) + break; + + err2 = grub_auth_check_authentication (NULL); + if (err2) + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + continue; + } + + break; + } + + return err1; +} diff --git a/normal/menu_entry.c b/normal/menu_entry.c index 1b26be1fd..644fe90fd 100644 --- a/normal/menu_entry.c +++ b/normal/menu_entry.c @@ -43,6 +43,15 @@ struct line int max_len; }; +struct per_term_screen +{ + struct grub_term_output *term; + /* The X coordinate. */ + int x; + /* The Y coordinate. */ + int y; +}; + struct screen { /* The array of lines. */ @@ -55,18 +64,18 @@ struct screen int real_column; /* The current line. */ int line; - /* The X coordinate. */ - int x; - /* The Y coordinate. */ - int y; /* The kill buffer. */ char *killed_text; /* The flag of a completion window. */ int completion_shown; + + struct per_term_screen *terms; + unsigned nterms; }; /* Used for storing completion items temporarily. */ static struct line completion_buffer; +static int completion_type; /* Initialize a line. */ static int @@ -98,77 +107,95 @@ ensure_space (struct line *linep, int extra) /* Return the number of lines occupied by this line on the screen. */ static int -get_logical_num_lines (struct line *linep) +get_logical_num_lines (struct line *linep, struct per_term_screen *term_screen) { - return (linep->len / GRUB_TERM_ENTRY_WIDTH) + 1; + return (linep->len / grub_term_entry_width (term_screen->term)) + 1; } /* Print a line. */ static void -print_line (struct line *linep, int offset, int start, int y) +print_line (struct line *linep, int offset, int start, int y, + struct per_term_screen *term_screen) { - int i; - char *p; + grub_term_gotoxy (term_screen->term, + GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + start + 1, + y + GRUB_TERM_FIRST_ENTRY_Y); - grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + start + 1, - y + GRUB_TERM_FIRST_ENTRY_Y); - - for (p = linep->buf + offset + start, i = start; - i < GRUB_TERM_ENTRY_WIDTH && offset + i < linep->len; - p++, i++) - grub_putchar (*p); - - for (; i < GRUB_TERM_ENTRY_WIDTH; i++) - grub_putchar (' '); - - if (linep->len >= offset + GRUB_TERM_ENTRY_WIDTH) - grub_putchar ('\\'); + if (linep->len >= offset + grub_term_entry_width (term_screen->term)) + { + char *p, c; + p = linep->buf + offset + grub_term_entry_width (term_screen->term); + c = *p; + *p = 0; + grub_puts_terminal (linep->buf + offset + start, term_screen->term); + *p = c; + grub_putcode ('\\', term_screen->term); + } else - grub_putchar (' '); + { + int i; + char *p, c; + + p = linep->buf + linep->len; + c = *p; + *p = 0; + grub_puts_terminal (linep->buf + offset + start, term_screen->term); + *p = c; + + for (i = 0; + i <= grub_term_entry_width (term_screen->term) - linep->len + offset; + i++) + grub_putcode (' ', term_screen->term); + } } /* Print an empty line. */ static void -print_empty_line (int y) +print_empty_line (int y, struct per_term_screen *term_screen) { int i; - grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1, - y + GRUB_TERM_FIRST_ENTRY_Y); + grub_term_gotoxy (term_screen->term, + GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1, + y + GRUB_TERM_FIRST_ENTRY_Y); - for (i = 0; i < GRUB_TERM_ENTRY_WIDTH + 1; i++) - grub_putchar (' '); + for (i = 0; i < grub_term_entry_width (term_screen->term) + 1; i++) + grub_putcode (' ', term_screen->term); } /* Print an up arrow. */ static void -print_up (int flag) +print_up (int flag, struct per_term_screen *term_screen) { - grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH, - GRUB_TERM_FIRST_ENTRY_Y); + grub_term_gotoxy (term_screen->term, GRUB_TERM_LEFT_BORDER_X + + grub_term_entry_width (term_screen->term), + GRUB_TERM_FIRST_ENTRY_Y); if (flag) - grub_putcode (GRUB_TERM_DISP_UP); + grub_putcode (GRUB_TERM_DISP_UP, term_screen->term); else - grub_putchar (' '); + grub_putcode (' ', term_screen->term); } /* Print a down arrow. */ static void -print_down (int flag) +print_down (int flag, struct per_term_screen *term_screen) { - grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH, - GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES); + grub_term_gotoxy (term_screen->term, GRUB_TERM_LEFT_BORDER_X + + grub_term_border_width (term_screen->term), + GRUB_TERM_TOP_BORDER_Y + + grub_term_num_entries (term_screen->term)); if (flag) - grub_putcode (GRUB_TERM_DISP_DOWN); + grub_putcode (GRUB_TERM_DISP_DOWN, term_screen->term); else - grub_putchar (' '); + grub_putcode (' ', term_screen->term); } /* Draw the lines of the screen SCREEN. */ static void -update_screen (struct screen *screen, int region_start, int region_column, +update_screen (struct screen *screen, struct per_term_screen *term_screen, + int region_start, int region_column, int up, int down, enum update_mode mode) { int up_flag = 0; @@ -178,12 +205,13 @@ update_screen (struct screen *screen, int region_start, int region_column, struct line *linep; /* Check if scrolling is necessary. */ - if (screen->y < 0 || screen->y >= GRUB_TERM_NUM_ENTRIES) + if (term_screen->y < 0 || term_screen->y + >= grub_term_num_entries (term_screen->term)) { - if (screen->y < 0) - screen->y = 0; + if (term_screen->y < 0) + term_screen->y = 0; else - screen->y = GRUB_TERM_NUM_ENTRIES - 1; + term_screen->y = grub_term_num_entries (term_screen->term) - 1; region_start = 0; region_column = 0; @@ -196,14 +224,15 @@ update_screen (struct screen *screen, int region_start, int region_column, { /* Draw lines. This code is tricky, because this must calculate logical positions. */ - y = screen->y - screen->column / GRUB_TERM_ENTRY_WIDTH; + y = term_screen->y - screen->column + / grub_term_entry_width (term_screen->term); i = screen->line; linep = screen->lines + i; while (y > 0) { i--; linep--; - y -= get_logical_num_lines (linep); + y -= get_logical_num_lines (linep, term_screen); } if (y < 0 || i > 0) @@ -214,8 +243,9 @@ update_screen (struct screen *screen, int region_start, int region_column, int column; for (column = 0; - column <= linep->len && y < GRUB_TERM_NUM_ENTRIES; - column += GRUB_TERM_ENTRY_WIDTH, y++) + column <= linep->len + && y < grub_term_num_entries (term_screen->term); + column += grub_term_entry_width (term_screen->term), y++) { if (y < 0) continue; @@ -223,16 +253,19 @@ update_screen (struct screen *screen, int region_start, int region_column, if (i == region_start) { if (region_column >= column - && region_column < column + GRUB_TERM_ENTRY_WIDTH) - print_line (linep, column, region_column - column, y); + && region_column + < (column + + grub_term_entry_width (term_screen->term))) + print_line (linep, column, region_column - column, y, + term_screen); else if (region_column < column) - print_line (linep, column, 0, y); + print_line (linep, column, 0, y, term_screen); } else if (i > region_start && mode == ALL_LINES) - print_line (linep, column, 0, y); + print_line (linep, column, 0, y, term_screen); } - if (y == GRUB_TERM_NUM_ENTRIES) + if (y == grub_term_num_entries (term_screen->term)) { if (column <= linep->len || i + 1 < screen->num_lines) down_flag = 1; @@ -242,35 +275,53 @@ update_screen (struct screen *screen, int region_start, int region_column, i++; if (mode == ALL_LINES && i == screen->num_lines) - for (; y < GRUB_TERM_NUM_ENTRIES; y++) - print_empty_line (y); + for (; y < grub_term_num_entries (term_screen->term); y++) + print_empty_line (y, term_screen); } - while (y < GRUB_TERM_NUM_ENTRIES); + while (y < grub_term_num_entries (term_screen->term)); /* Draw up and down arrows. */ if (up) - print_up (up_flag); + print_up (up_flag, term_screen); if (down) - print_down (down_flag); + print_down (down_flag, term_screen); } /* Place the cursor. */ - grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1 + screen->x, - GRUB_TERM_FIRST_ENTRY_Y + screen->y); + grub_term_gotoxy (term_screen->term, + GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1 + + term_screen->x, + GRUB_TERM_FIRST_ENTRY_Y + term_screen->y); - grub_refresh (); + grub_term_refresh (term_screen->term); +} + +static void +update_screen_all (struct screen *screen, + int region_start, int region_column, + int up, int down, enum update_mode mode) +{ + unsigned i; + for (i = 0; i < screen->nterms; i++) + update_screen (screen, &screen->terms[i], region_start, region_column, + up, down, mode); } -/* Insert the string S into the screen SCREEN. This updates the cursor - position and redraw the screen. Return zero if fails. */ static int insert_string (struct screen *screen, char *s, int update) { int region_start = screen->num_lines; int region_column = 0; - int down = 0; - enum update_mode mode = NO_LINE; + int down[screen->nterms]; + enum update_mode mode[screen->nterms]; + unsigned i; + + for (i = 0; i < screen->nterms; i++) + { + down[i] = 0; + mode[i] = NO_LINE; + } while (*s) { @@ -319,15 +370,20 @@ insert_string (struct screen *screen, char *s, int update) region_column = screen->column; } - mode = ALL_LINES; - down = 1; /* XXX not optimal. */ + for (i = 0; i < screen->nterms; i++) + { + mode[i] = ALL_LINES; + down[i] = 1; /* XXX not optimal. */ + } /* Move the cursor. */ screen->column = screen->real_column = 0; screen->line++; - screen->x = 0; - screen->y++; - + for (i = 0; i < screen->nterms; i++) + { + screen->terms[i].x = 0; + screen->terms[i].y++; + } s++; } else @@ -336,7 +392,7 @@ insert_string (struct screen *screen, char *s, int update) char *p; struct line *current_linep; int size; - int orig_num, new_num; + int orig_num[screen->nterms], new_num[screen->nterms]; /* Find a string delimited by LF. */ p = grub_strchr (s, '\n'); @@ -355,9 +411,13 @@ insert_string (struct screen *screen, char *s, int update) grub_memmove (current_linep->buf + screen->column, s, size); - orig_num = get_logical_num_lines (current_linep); + for (i = 0; i < screen->nterms; i++) + orig_num[i] = get_logical_num_lines (current_linep, + &screen->terms[i]); current_linep->len += size; - new_num = get_logical_num_lines (current_linep); + for (i = 0; i < screen->nterms; i++) + new_num[i] = get_logical_num_lines (current_linep, + &screen->terms[i]); /* Update the dirty region. */ if (region_start > screen->line) @@ -366,27 +426,34 @@ insert_string (struct screen *screen, char *s, int update) region_column = screen->column; } - if (orig_num != new_num) - { - mode = ALL_LINES; - down = 1; /* XXX not optimal. */ - } - else if (mode != ALL_LINES) - mode = SINGLE_LINE; + for (i = 0; i < screen->nterms; i++) + if (orig_num[i] != new_num[i]) + { + mode[i] = ALL_LINES; + down[i] = 1; /* XXX not optimal. */ + } + else if (mode[i] != ALL_LINES) + mode[i] = SINGLE_LINE; /* Move the cursor. */ screen->column += size; screen->real_column = screen->column; - screen->x += size; - screen->y += screen->x / GRUB_TERM_ENTRY_WIDTH; - screen->x %= GRUB_TERM_ENTRY_WIDTH; - + for (i = 0; i < screen->nterms; i++) + { + screen->terms[i].x += size; + screen->terms[i].y += screen->terms[i].x + / grub_term_entry_width (screen->terms[i].term); + screen->terms[i].x + %= grub_term_entry_width (screen->terms[i].term); + } s = p; } } if (update) - update_screen (screen, region_start, region_column, 0, down, mode); + for (i = 0; i < screen->nterms; i++) + update_screen (screen, &screen->terms[i], + region_start, region_column, 0, down[i], mode[i]); return 1; } @@ -408,6 +475,7 @@ destroy_screen (struct screen *screen) grub_free (screen->killed_text); grub_free (screen->lines); + grub_free (screen->terms); grub_free (screen); } @@ -416,6 +484,7 @@ static struct screen * make_screen (grub_menu_entry_t entry) { struct screen *screen; + unsigned i; /* Initialize the screen. */ screen = grub_zalloc (sizeof (*screen)); @@ -437,8 +506,11 @@ make_screen (grub_menu_entry_t entry) screen->column = 0; screen->real_column = 0; screen->line = 0; - screen->x = 0; - screen->y = 0; + for (i = 0; i < screen->nterms; i++) + { + screen->terms[i].x = 0; + screen->terms[i].y = 0; + } return screen; @@ -451,44 +523,58 @@ static int forward_char (struct screen *screen, int update) { struct line *linep; + unsigned i; linep = screen->lines + screen->line; if (screen->column < linep->len) { screen->column++; - screen->x++; - if (screen->x == GRUB_TERM_ENTRY_WIDTH) + for (i = 0; i < screen->nterms; i++) { - screen->x = 0; - screen->y++; + screen->terms[i].x++; + if (screen->terms[i].x + == grub_term_entry_width (screen->terms[i].term)) + { + screen->terms[i].x = 0; + screen->terms[i].y++; + } } } else if (screen->num_lines > screen->line + 1) { screen->column = 0; screen->line++; - screen->x = 0; - screen->y++; + for (i = 0; i < screen->nterms; i++) + { + screen->terms[i].x = 0; + screen->terms[i].y++; + } } screen->real_column = screen->column; if (update) - update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE); + update_screen_all (screen, screen->num_lines, 0, 0, 0, NO_LINE); return 1; } static int backward_char (struct screen *screen, int update) { + unsigned i; + if (screen->column > 0) { screen->column--; - screen->x--; - if (screen->x == -1) + for (i = 0; i < screen->nterms; i++) { - screen->x = GRUB_TERM_ENTRY_WIDTH - 1; - screen->y--; + screen->terms[i].x--; + if (screen->terms[i].x == -1) + { + screen->terms[i].x + = grub_term_entry_width (screen->terms[i].term) - 1; + screen->terms[i].y--; + } } } else if (screen->line > 0) @@ -498,14 +584,18 @@ backward_char (struct screen *screen, int update) screen->line--; linep = screen->lines + screen->line; screen->column = linep->len; - screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH; - screen->y--; + for (i = 0; i < screen->nterms; i++) + { + screen->terms[i].x = screen->column + % grub_term_entry_width (screen->terms[i].term); + screen->terms[i].y--; + } } screen->real_column = screen->column; if (update) - update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE); + update_screen_all (screen, screen->num_lines, 0, 0, 0, NO_LINE); return 1; } @@ -513,14 +603,16 @@ backward_char (struct screen *screen, int update) static int previous_line (struct screen *screen, int update) { + unsigned i; + if (screen->line > 0) { struct line *linep; - int dy; + int col; /* How many physical lines from the current position to the first physical line? */ - dy = screen->column / GRUB_TERM_ENTRY_WIDTH; + col = screen->column; screen->line--; @@ -530,23 +622,35 @@ previous_line (struct screen *screen, int update) else screen->column = screen->real_column; - /* How many physical lines from the current position - to the last physical line? */ - dy += (linep->len / GRUB_TERM_ENTRY_WIDTH - - screen->column / GRUB_TERM_ENTRY_WIDTH); + for (i = 0; i < screen->nterms; i++) + { + int dy; + dy = col / grub_term_entry_width (screen->terms[i].term); - screen->y -= dy + 1; - screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH; + /* How many physical lines from the current position + to the last physical line? */ + dy += (linep->len / grub_term_entry_width (screen->terms[i].term) + - screen->column + / grub_term_entry_width (screen->terms[i].term)); + + screen->terms[i].y -= dy + 1; + screen->terms[i].x + = screen->column % grub_term_entry_width (screen->terms[i].term); + } } else { - screen->y -= screen->column / GRUB_TERM_ENTRY_WIDTH; + for (i = 0; i < screen->nterms; i++) + { + screen->terms[i].y + -= screen->column / grub_term_entry_width (screen->terms[i].term); + screen->terms[i].x = 0; + } screen->column = 0; - screen->x = 0; } if (update) - update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE); + update_screen_all (screen, screen->num_lines, 0, 0, 0, NO_LINE); return 1; } @@ -554,16 +658,18 @@ previous_line (struct screen *screen, int update) static int next_line (struct screen *screen, int update) { + unsigned i; + if (screen->line < screen->num_lines - 1) { struct line *linep; - int dy; + int l1, c1; /* How many physical lines from the current position to the last physical line? */ linep = screen->lines + screen->line; - dy = (linep->len / GRUB_TERM_ENTRY_WIDTH - - screen->column / GRUB_TERM_ENTRY_WIDTH); + l1 = linep->len; + c1 = screen->column; screen->line++; @@ -573,26 +679,40 @@ next_line (struct screen *screen, int update) else screen->column = screen->real_column; - /* How many physical lines from the current position - to the first physical line? */ - dy += screen->column / GRUB_TERM_ENTRY_WIDTH; - - screen->y += dy + 1; - screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH; + for (i = 0; i < screen->nterms; i++) + { + int dy; + dy = l1 / grub_term_entry_width (screen->terms[i].term) + - c1 / grub_term_entry_width (screen->terms[i].term); + /* How many physical lines from the current position + to the first physical line? */ + dy += screen->column / grub_term_entry_width (screen->terms[i].term); + screen->terms[i].y += dy + 1; + screen->terms[i].x = screen->column + % grub_term_entry_width (screen->terms[i].term); + } } else { struct line *linep; - + int l, s; + linep = screen->lines + screen->line; - screen->y += (linep->len / GRUB_TERM_ENTRY_WIDTH - - screen->column / GRUB_TERM_ENTRY_WIDTH); + l = linep->len; + s = screen->column; screen->column = linep->len; - screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH; + for (i = 0; i < screen->nterms; i++) + { + screen->terms[i].y + += (l / grub_term_entry_width (screen->terms[i].term) + - s / grub_term_entry_width (screen->terms[i].term)); + screen->terms[i].x + = screen->column % grub_term_entry_width (screen->terms[i].term); + } } if (update) - update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE); + update_screen_all (screen, screen->num_lines, 0, 0, 0, NO_LINE); return 1; } @@ -600,12 +720,19 @@ next_line (struct screen *screen, int update) static int beginning_of_line (struct screen *screen, int update) { - screen->y -= screen->column / GRUB_TERM_ENTRY_WIDTH; + unsigned i; + int col; + + col = screen->column; screen->column = screen->real_column = 0; - screen->x = 0; + for (i = 0; i < screen->nterms; i++) + { + screen->terms[i].x = 0; + screen->terms[i].y -= col / grub_term_entry_width (screen->terms[i].term); + } if (update) - update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE); + update_screen_all (screen, screen->num_lines, 0, 0, 0, NO_LINE); return 1; } @@ -614,15 +741,23 @@ static int end_of_line (struct screen *screen, int update) { struct line *linep; + unsigned i; + int col; linep = screen->lines + screen->line; - screen->y += (linep->len / GRUB_TERM_ENTRY_WIDTH - - screen->column / GRUB_TERM_ENTRY_WIDTH); + col = screen->column; screen->column = screen->real_column = linep->len; - screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH; + for (i = 0; i < screen->nterms; i++) + { + screen->terms[i].y + += (linep->len / grub_term_entry_width (screen->terms->term) + - col / grub_term_entry_width (screen->terms->term)); + screen->terms[i].x + = screen->column % grub_term_entry_width (screen->terms->term); + } if (update) - update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE); + update_screen_all (screen, screen->num_lines, 0, 0, 0, NO_LINE); return 1; } @@ -631,32 +766,41 @@ static int delete_char (struct screen *screen, int update) { struct line *linep; - enum update_mode mode = NO_LINE; int start = screen->num_lines; int column = 0; - int down = 0; linep = screen->lines + screen->line; if (linep->len > screen->column) { - int orig_num, new_num; + int orig_num[screen->nterms], new_num; + unsigned i; - orig_num = get_logical_num_lines (linep); + for (i = 0; i < screen->nterms; i++) + orig_num[i] = get_logical_num_lines (linep, &screen->terms[i]); grub_memmove (linep->buf + screen->column, linep->buf + screen->column + 1, linep->len - screen->column - 1); linep->len--; - new_num = get_logical_num_lines (linep); - - if (orig_num != new_num) - mode = ALL_LINES; - else - mode = SINGLE_LINE; - start = screen->line; column = screen->column; + + screen->real_column = screen->column; + + if (update) + { + for (i = 0; i < screen->nterms; i++) + { + new_num = get_logical_num_lines (linep, &screen->terms[i]); + if (orig_num[i] != new_num) + update_screen (screen, &screen->terms[i], + start, column, 0, 0, ALL_LINES); + else + update_screen (screen, &screen->terms[i], + start, column, 0, 0, SINGLE_LINE); + } + } } else if (screen->num_lines > screen->line + 1) { @@ -676,17 +820,14 @@ delete_char (struct screen *screen, int update) * sizeof (struct line)); screen->num_lines--; - mode = ALL_LINES; start = screen->line; column = screen->column; - down = 1; + + screen->real_column = screen->column; + if (update) + update_screen_all (screen, start, column, 0, 1, ALL_LINES); } - screen->real_column = screen->column; - - if (update) - update_screen (screen, start, column, 0, down, mode); - return 1; } @@ -731,9 +872,8 @@ kill_line (struct screen *screen, int continuous, int update) if (size > 0) { - enum update_mode mode = SINGLE_LINE; - int down = 0; - int orig_num, new_num; + int orig_num[screen->nterms], new_num; + unsigned i; p = grub_realloc (p, offset + size + 1); if (! p) @@ -744,18 +884,23 @@ kill_line (struct screen *screen, int continuous, int update) screen->killed_text = p; - orig_num = get_logical_num_lines (linep); + for (i = 0; i < screen->nterms; i++) + orig_num[i] = get_logical_num_lines (linep, &screen->terms[i]); linep->len = screen->column; - new_num = get_logical_num_lines (linep); - - if (orig_num != new_num) - { - mode = ALL_LINES; - down = 1; - } if (update) - update_screen (screen, screen->line, screen->column, 0, down, mode); + { + new_num = get_logical_num_lines (linep, &screen->terms[i]); + for (i = 0; i < screen->nterms; i++) + { + if (orig_num[i] != new_num) + update_screen (screen, &screen->terms[i], + screen->line, screen->column, 0, 1, ALL_LINES); + else + update_screen (screen, &screen->terms[i], + screen->line, screen->column, 0, 0, SINGLE_LINE); + } + } } else if (screen->line + 1 < screen->num_lines) { @@ -786,7 +931,11 @@ yank (struct screen *screen, int update) static int open_line (struct screen *screen, int update) { - int saved_y = screen->y; + int saved_y[screen->nterms]; + unsigned i; + + for (i = 0; i < screen->nterms; i++) + saved_y[i] = screen->terms[i].y; if (! insert_string (screen, "\n", 0)) return 0; @@ -794,52 +943,23 @@ open_line (struct screen *screen, int update) if (! backward_char (screen, 0)) return 0; - screen->y = saved_y; + for (i = 0; i < screen->nterms; i++) + screen->terms[i].y = saved_y[i]; if (update) - update_screen (screen, screen->line, screen->column, 0, 1, ALL_LINES); + update_screen_all (screen, screen->line, screen->column, 0, 1, ALL_LINES); return 1; } /* A completion hook to print items. */ static void -store_completion (const char *item, grub_completion_type_t type, int count) +store_completion (const char *item, grub_completion_type_t type, + int count __attribute__ ((unused))) { char *p; - if (count == 0) - { - /* If this is the first time, print a label. */ - const char *what; - - switch (type) - { - case GRUB_COMPLETION_TYPE_COMMAND: - what = N_("commands"); - break; - case GRUB_COMPLETION_TYPE_DEVICE: - what = N_("devices"); - break; - case GRUB_COMPLETION_TYPE_FILE: - what = N_("files"); - break; - case GRUB_COMPLETION_TYPE_PARTITION: - what = N_("partitions"); - break; - case GRUB_COMPLETION_TYPE_ARGUMENT: - what = N_("arguments"); - break; - default: - what = N_("things"); - break; - } - - grub_gotoxy (0, GRUB_TERM_HEIGHT - 3); - grub_printf (" "); - grub_printf_ (N_("Possible %s are:"), _(what)); - grub_printf ("\n "); - } + completion_type = type; /* Make sure that the completion buffer has enough room. */ if (completion_buffer.max_len < (completion_buffer.len @@ -873,21 +993,21 @@ store_completion (const char *item, grub_completion_type_t type, int count) static int complete (struct screen *screen, int continuous, int update) { - grub_uint16_t pos; char saved_char; struct line *linep; int restore; char *insert; static int count = -1; + unsigned i; + grub_uint32_t *ucs4; + grub_size_t buflen; + grub_ssize_t ucs4len; if (continuous) count++; else count = 0; - pos = grub_getxy (); - grub_gotoxy (0, GRUB_TERM_HEIGHT - 3); - completion_buffer.buf = 0; completion_buffer.len = 0; completion_buffer.max_len = 0; @@ -900,35 +1020,86 @@ complete (struct screen *screen, int continuous, int update) linep->buf[screen->column] = saved_char; - if (restore) + buflen = grub_strlen (completion_buffer.buf); + ucs4 = grub_malloc (sizeof (grub_uint32_t) * (buflen + 1)); + + if (!ucs4) { - char *p = completion_buffer.buf; - - screen->completion_shown = 1; - - if (p) - { - int num_sections = ((completion_buffer.len + GRUB_TERM_WIDTH - 8 - 1) - / (GRUB_TERM_WIDTH - 8)); - char *endp; - - p += (count % num_sections) * (GRUB_TERM_WIDTH - 8); - endp = p + (GRUB_TERM_WIDTH - 8); - - if (p != completion_buffer.buf) - grub_putcode (GRUB_TERM_DISP_LEFT); - else - grub_putchar (' '); - - while (*p && p < endp) - grub_putchar (*p++); - - if (*p) - grub_putcode (GRUB_TERM_DISP_RIGHT); - } + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + return 1; } - grub_gotoxy (pos >> 8, pos & 0xFF); + ucs4len = grub_utf8_to_ucs4 (ucs4, buflen, + (grub_uint8_t *) completion_buffer.buf, + buflen, 0); + ucs4[ucs4len] = 0; + + if (restore) + for (i = 0; i < screen->nterms; i++) + { + int num_sections = ((completion_buffer.len + + grub_term_width (screen->terms[i].term) - 8 - 1) + / (grub_term_width (screen->terms[i].term) - 8)); + grub_uint32_t *endp; + grub_uint16_t pos; + grub_uint32_t *p = ucs4; + + pos = grub_term_getxy (screen->terms[i].term); + grub_term_gotoxy (screen->terms[i].term, 0, + grub_term_height (screen->terms[i].term) - 3); + + screen->completion_shown = 1; + + grub_term_gotoxy (screen->terms[i].term, 0, + grub_term_height (screen->terms[i].term) - 3); + grub_puts_terminal (" ", screen->terms[i].term); + switch (completion_type) + { + case GRUB_COMPLETION_TYPE_COMMAND: + grub_puts_terminal (_("Possible commands are:"), + screen->terms[i].term); + break; + case GRUB_COMPLETION_TYPE_DEVICE: + grub_puts_terminal (_("Possible devices are:"), + screen->terms[i].term); + break; + case GRUB_COMPLETION_TYPE_FILE: + grub_puts_terminal (_("Possible files are:"), + screen->terms[i].term); + break; + case GRUB_COMPLETION_TYPE_PARTITION: + grub_puts_terminal (_("Possible partitions are:"), + screen->terms[i].term); + break; + case GRUB_COMPLETION_TYPE_ARGUMENT: + grub_puts_terminal (_("Possible arguments are:"), + screen->terms[i].term); + break; + default: + grub_puts_terminal (_("Possible things are:"), + screen->terms[i].term); + break; + } + + grub_puts_terminal ("\n ", screen->terms[i].term); + + p += (count % num_sections) + * (grub_term_width (screen->terms[i].term) - 8); + endp = p + (grub_term_width (screen->terms[i].term) - 8); + + if (p != ucs4) + grub_putcode (GRUB_TERM_DISP_LEFT, screen->terms[i].term); + else + grub_putcode (' ', screen->terms[i].term); + + while (*p && p < endp) + grub_putcode (*p++, screen->terms[i].term); + + if (*p) + grub_putcode (GRUB_TERM_DISP_RIGHT, screen->terms[i].term); + grub_term_gotoxy (screen->terms[i].term, pos >> 8, pos & 0xFF); + } if (insert) { @@ -945,23 +1116,33 @@ complete (struct screen *screen, int continuous, int update) /* Clear displayed completions. */ static void -clear_completions (void) +clear_completions (struct per_term_screen *term_screen) { grub_uint16_t pos; - int i, j; + unsigned i, j; - pos = grub_getxy (); - grub_gotoxy (0, GRUB_TERM_HEIGHT - 3); + pos = grub_term_getxy (term_screen->term); + grub_term_gotoxy (term_screen->term, 0, + grub_term_height (term_screen->term) - 3); for (i = 0; i < 2; i++) { - for (j = 0; j < GRUB_TERM_WIDTH - 1; j++) - grub_putchar (' '); - grub_putchar ('\n'); + for (j = 0; j < grub_term_width (term_screen->term) - 1; j++) + grub_putcode (' ', term_screen->term); + grub_putcode ('\n', term_screen->term); } - grub_gotoxy (pos >> 8, pos & 0xFF); - grub_refresh (); + grub_term_gotoxy (term_screen->term, pos >> 8, pos & 0xFF); + grub_term_refresh (term_screen->term); +} + +static void +clear_completions_all (struct screen *screen) +{ + unsigned i; + + for (i = 0; i < screen->nterms; i++) + clear_completions (&screen->terms[i]); } /* Execute the command list in the screen SCREEN. */ @@ -1033,6 +1214,8 @@ grub_menu_entry_run (grub_menu_entry_t entry) struct screen *screen; int prev_c; grub_err_t err = GRUB_ERR_NONE; + unsigned i; + grub_term_output_t term; err = grub_auth_check_authentication (NULL); @@ -1047,11 +1230,34 @@ grub_menu_entry_run (grub_menu_entry_t entry) if (! screen) return; + screen->terms = NULL; + refresh: + grub_free (screen->terms); + screen->nterms = 0; + FOR_ACTIVE_TERM_OUTPUTS(term) + screen->nterms++; + screen->terms = grub_malloc (screen->nterms * sizeof (screen->terms[0])); + if (!screen->terms) + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + return; + } + i = 0; + FOR_ACTIVE_TERM_OUTPUTS(term) + { + screen->terms[i].term = term; + screen->terms[i].x = 0; + screen->terms[i].y = 0; + i++; + } /* Draw the screen. */ - grub_menu_init_page (0, 1); - update_screen (screen, 0, 0, 1, 1, ALL_LINES); - grub_setcursor (1); + for (i = 0; i < screen->nterms; i++) + grub_menu_init_page (0, 1, screen->terms[i].term); + update_screen_all (screen, 0, 0, 1, 1, ALL_LINES); + for (i = 0; i < screen->nterms; i++) + grub_term_setcursor (screen->terms[i].term, 1); prev_c = '\0'; while (1) @@ -1060,10 +1266,16 @@ grub_menu_entry_run (grub_menu_entry_t entry) if (screen->completion_shown) { - clear_completions (); + clear_completions_all (screen); screen->completion_shown = 0; } + if (grub_normal_exit_level) + { + destroy_screen (screen); + return; + } + switch (c) { case 16: /* C-p */ diff --git a/normal/menu_text.c b/normal/menu_text.c index 8ab67a35c..cab1d22f8 100644 --- a/normal/menu_text.c +++ b/normal/menu_text.c @@ -26,88 +26,66 @@ #include #include #include - -/* Time to delay after displaying an error message about a default/fallback - entry failing to boot. */ -#define DEFAULT_ENTRY_ERROR_DELAY_MS 2500 +#include static grub_uint8_t grub_color_menu_normal; static grub_uint8_t grub_color_menu_highlight; -/* Wait until the user pushes any key so that the user - can see what happened. */ -void -grub_wait_after_message (void) +struct menu_viewer_data { - grub_putchar ('\n'); - grub_printf_ (N_("Press any key to continue...")); - (void) grub_getkey (); - grub_putchar ('\n'); + int first, offset; + grub_menu_t menu; + struct grub_term_output *term; +}; + +static void +print_spaces (int number_spaces, struct grub_term_output *term) +{ + int i; + for (i = 0; i < number_spaces; i++) + grub_putcode (' ', term); } void grub_print_ucs4 (const grub_uint32_t * str, - const grub_uint32_t * last_position) + const grub_uint32_t * last_position, + struct grub_term_output *term) { while (str < last_position) { - grub_putcode (*str); + grub_putcode (*str, term); str++; } } -int -grub_utf8_to_ucs4_alloc (const char *msg, grub_uint32_t **unicode_msg, - grub_uint32_t **last_position) -{ - grub_ssize_t msg_len = grub_strlen (msg); - - *unicode_msg = grub_malloc (grub_strlen (msg) * sizeof (grub_uint32_t)); - - if (!*unicode_msg) - { - grub_printf ("utf8_to_ucs4 ERROR1: %s", msg); - return -1; - } - - msg_len = grub_utf8_to_ucs4 (*unicode_msg, msg_len, - (grub_uint8_t *) msg, -1, 0); - - *last_position = *unicode_msg + msg_len; - - if (msg_len < 0) - { - grub_printf ("utf8_to_ucs4 ERROR2: %s", msg); - grub_free (*unicode_msg); - } - return msg_len; -} - grub_ssize_t -grub_getstringwidth (grub_uint32_t * str, const grub_uint32_t * last_position) +grub_getstringwidth (grub_uint32_t * str, const grub_uint32_t * last_position, + struct grub_term_output *term) { grub_ssize_t width = 0; while (str < last_position) { - width += grub_getcharwidth (*str); + width += grub_term_getcharwidth (term, *str); str++; } return width; } void -grub_print_message_indented (const char *msg, int margin_left, int margin_right) +grub_print_message_indented (const char *msg, int margin_left, int margin_right, + struct grub_term_output *term) { int line_len; - line_len = GRUB_TERM_WIDTH - grub_getcharwidth ('m') * - (margin_left + margin_right); grub_uint32_t *unicode_msg; grub_uint32_t *last_position; int msg_len; + line_len = grub_term_width (term) - grub_term_getcharwidth (term, 'm') * + (margin_left + margin_right); + msg_len = grub_utf8_to_ucs4_alloc (msg, &unicode_msg, &last_position); if (msg_len < 0) @@ -124,11 +102,12 @@ grub_print_message_indented (const char *msg, int margin_left, int margin_right) while (current_position < last_position) { if (! first_loop) - grub_putchar ('\n'); + grub_putcode ('\n', term); next_new_line = (grub_uint32_t *) last_position; - while (grub_getstringwidth (current_position, next_new_line) > line_len + while (grub_getstringwidth (current_position, next_new_line,term) + > line_len || (next_new_line != last_position && *next_new_line != ' ' && next_new_line > current_position)) { @@ -141,8 +120,8 @@ grub_print_message_indented (const char *msg, int margin_left, int margin_right) (grub_uint32_t *) last_position : next_new_line + line_len; } - grub_print_spaces (margin_left); - grub_print_ucs4 (current_position, next_new_line); + print_spaces (margin_left, term); + grub_print_ucs4 (current_position, next_new_line, term); next_new_line++; current_position = next_new_line; @@ -153,52 +132,54 @@ grub_print_message_indented (const char *msg, int margin_left, int margin_right) static void -draw_border (void) +draw_border (struct grub_term_output *term) { unsigned i; - grub_setcolorstate (GRUB_TERM_COLOR_NORMAL); + grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL); - grub_gotoxy (GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y); - grub_putcode (GRUB_TERM_DISP_UL); - for (i = 0; i < (unsigned) GRUB_TERM_BORDER_WIDTH - 2; i++) - grub_putcode (GRUB_TERM_DISP_HLINE); - grub_putcode (GRUB_TERM_DISP_UR); + grub_term_gotoxy (term, GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y); + grub_putcode (GRUB_TERM_DISP_UL, term); + for (i = 0; i < (unsigned) grub_term_border_width (term) - 2; i++) + grub_putcode (GRUB_TERM_DISP_HLINE, term); + grub_putcode (GRUB_TERM_DISP_UR, term); - for (i = 0; i < (unsigned) GRUB_TERM_NUM_ENTRIES; i++) + for (i = 0; i < (unsigned) grub_term_num_entries (term); i++) { - grub_gotoxy (GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y + i + 1); - grub_putcode (GRUB_TERM_DISP_VLINE); - grub_gotoxy (GRUB_TERM_MARGIN + GRUB_TERM_BORDER_WIDTH - 1, - GRUB_TERM_TOP_BORDER_Y + i + 1); - grub_putcode (GRUB_TERM_DISP_VLINE); + grub_term_gotoxy (term, GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y + i + 1); + grub_putcode (GRUB_TERM_DISP_VLINE, term); + grub_term_gotoxy (term, GRUB_TERM_MARGIN + grub_term_border_width (term) + - 1, + GRUB_TERM_TOP_BORDER_Y + i + 1); + grub_putcode (GRUB_TERM_DISP_VLINE, term); } - grub_gotoxy (GRUB_TERM_MARGIN, - GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES + 1); - grub_putcode (GRUB_TERM_DISP_LL); - for (i = 0; i < (unsigned) GRUB_TERM_BORDER_WIDTH - 2; i++) - grub_putcode (GRUB_TERM_DISP_HLINE); - grub_putcode (GRUB_TERM_DISP_LR); + grub_term_gotoxy (term, GRUB_TERM_MARGIN, + GRUB_TERM_TOP_BORDER_Y + grub_term_num_entries (term) + 1); + grub_putcode (GRUB_TERM_DISP_LL, term); + for (i = 0; i < (unsigned) grub_term_border_width (term) - 2; i++) + grub_putcode (GRUB_TERM_DISP_HLINE, term); + grub_putcode (GRUB_TERM_DISP_LR, term); - grub_setcolorstate (GRUB_TERM_COLOR_NORMAL); + grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL); - grub_gotoxy (GRUB_TERM_MARGIN, - (GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES - + GRUB_TERM_MARGIN + 1)); + grub_term_gotoxy (term, GRUB_TERM_MARGIN, + (GRUB_TERM_TOP_BORDER_Y + grub_term_num_entries (term) + + GRUB_TERM_MARGIN + 1)); } static void -print_message (int nested, int edit) +print_message (int nested, int edit, struct grub_term_output *term) { - grub_setcolorstate (GRUB_TERM_COLOR_NORMAL); + grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL); if (edit) { - grub_putchar ('\n'); + grub_putcode ('\n', term); grub_print_message_indented (_("Minimum Emacs-like screen editing is \ supported. TAB lists completions. Press Ctrl-x to boot, Ctrl-c for a \ -command-line or ESC to return menu."), STANDARD_MARGIN, STANDARD_MARGIN); +command-line or ESC to return menu."), STANDARD_MARGIN, STANDARD_MARGIN, + term); } else { @@ -210,23 +191,33 @@ entry is highlighted.\n"); grub_sprintf (msg_translated, msg, (grub_uint32_t) GRUB_TERM_DISP_UP, (grub_uint32_t) GRUB_TERM_DISP_DOWN); grub_putchar ('\n'); - grub_print_message_indented (msg_translated, STANDARD_MARGIN, STANDARD_MARGIN); + grub_print_message_indented (msg_translated, STANDARD_MARGIN, + STANDARD_MARGIN, term); grub_free (msg_translated); - grub_print_message_indented (_("Press enter to execute the selected \ -entry, \'e\' to edit the commands before booting or \'c\' for a command-line.\n"), STANDARD_MARGIN, STANDARD_MARGIN); - if (nested) - { - grub_printf ("\n "); - grub_printf_ (N_("ESC to return previous menu.")); - } + { + grub_print_message_indented + (_("Press enter to boot the selected OS, " + "\'e\' to edit the commands before booting " + "or \'c\' for a command-line. ESC to return previous menu.\n"), + STANDARD_MARGIN, STANDARD_MARGIN, term); + } + else + { + grub_print_message_indented + (_("Press enter to boot the selected OS, " + "\'e\' to edit the commands before booting " + "or \'c\' for a command-line.\n"), + STANDARD_MARGIN, STANDARD_MARGIN, term); + } } } static void -print_entry (int y, int highlight, grub_menu_entry_t entry) +print_entry (int y, int highlight, grub_menu_entry_t entry, + struct grub_term_output *term) { int x; const char *title; @@ -252,482 +243,245 @@ print_entry (int y, int highlight, grub_menu_entry_t entry) return; } - grub_getcolor (&old_color_normal, &old_color_highlight); - grub_setcolor (grub_color_menu_normal, grub_color_menu_highlight); - grub_setcolorstate (highlight - ? GRUB_TERM_COLOR_HIGHLIGHT - : GRUB_TERM_COLOR_NORMAL); + grub_term_getcolor (term, &old_color_normal, &old_color_highlight); + grub_term_setcolor (term, grub_color_menu_normal, grub_color_menu_highlight); + grub_term_setcolorstate (term, highlight + ? GRUB_TERM_COLOR_HIGHLIGHT + : GRUB_TERM_COLOR_NORMAL); - grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN, y); + grub_term_gotoxy (term, GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN, y); for (x = GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1, i = 0; - x < GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH - GRUB_TERM_MARGIN; + x < (int) (GRUB_TERM_LEFT_BORDER_X + grub_term_border_width (term) + - GRUB_TERM_MARGIN); i++) { if (i < len - && x <= (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH - - GRUB_TERM_MARGIN - 1)) + && x <= (int) (GRUB_TERM_LEFT_BORDER_X + grub_term_border_width (term) + - GRUB_TERM_MARGIN - 1)) { grub_ssize_t width; - width = grub_getcharwidth (unicode_title[i]); + width = grub_term_getcharwidth (term, unicode_title[i]); - if (x + width > (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH - - GRUB_TERM_MARGIN - 1)) - grub_putcode (GRUB_TERM_DISP_RIGHT); + if (x + width > (int) (GRUB_TERM_LEFT_BORDER_X + + grub_term_border_width (term) + - GRUB_TERM_MARGIN - 1)) + grub_putcode (GRUB_TERM_DISP_RIGHT, term); else - grub_putcode (unicode_title[i]); + grub_putcode (unicode_title[i], term); x += width; } else { - grub_putchar (' '); + grub_putcode (' ', term); x++; } } - grub_setcolorstate (GRUB_TERM_COLOR_NORMAL); - grub_putchar (' '); + grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL); + grub_putcode (' ', term); - grub_gotoxy (GRUB_TERM_CURSOR_X, y); + grub_term_gotoxy (term, grub_term_cursor_x (term), y); - grub_setcolor (old_color_normal, old_color_highlight); - grub_setcolorstate (GRUB_TERM_COLOR_NORMAL); + grub_term_setcolor (term, old_color_normal, old_color_highlight); + grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL); grub_free (unicode_title); } static void -print_entries (grub_menu_t menu, int first, int offset) +print_entries (grub_menu_t menu, int first, int offset, + struct grub_term_output *term) { grub_menu_entry_t e; int i; - grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH, - GRUB_TERM_FIRST_ENTRY_Y); + grub_term_gotoxy (term, + GRUB_TERM_LEFT_BORDER_X + grub_term_border_width (term), + GRUB_TERM_FIRST_ENTRY_Y); if (first) - grub_putcode (GRUB_TERM_DISP_UP); + grub_putcode (GRUB_TERM_DISP_UP, term); else - grub_putchar (' '); + grub_putcode (' ', term); e = grub_menu_get_entry (menu, first); - for (i = 0; i < GRUB_TERM_NUM_ENTRIES; i++) + for (i = 0; i < grub_term_num_entries (term); i++) { - print_entry (GRUB_TERM_FIRST_ENTRY_Y + i, offset == i, e); + print_entry (GRUB_TERM_FIRST_ENTRY_Y + i, offset == i, e, term); if (e) e = e->next; } - grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH, - GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES); + grub_term_gotoxy (term, GRUB_TERM_LEFT_BORDER_X + + grub_term_border_width (term), + GRUB_TERM_TOP_BORDER_Y + grub_term_num_entries (term)); if (e) - grub_putcode (GRUB_TERM_DISP_DOWN); + grub_putcode (GRUB_TERM_DISP_DOWN, term); else - grub_putchar (' '); + grub_putcode (' ', term); - grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset); + grub_term_gotoxy (term, grub_term_cursor_x (term), + GRUB_TERM_FIRST_ENTRY_Y + offset); } /* Initialize the screen. If NESTED is non-zero, assume that this menu is run from another menu or a command-line. If EDIT is non-zero, show a message for the menu entry editor. */ void -grub_menu_init_page (int nested, int edit) +grub_menu_init_page (int nested, int edit, + struct grub_term_output *term) { grub_uint8_t old_color_normal, old_color_highlight; - grub_getcolor (&old_color_normal, &old_color_highlight); + grub_term_getcolor (term, &old_color_normal, &old_color_highlight); /* By default, use the same colors for the menu. */ grub_color_menu_normal = old_color_normal; grub_color_menu_highlight = old_color_highlight; /* Then give user a chance to replace them. */ - grub_parse_color_name_pair (&grub_color_menu_normal, grub_env_get ("menu_color_normal")); - grub_parse_color_name_pair (&grub_color_menu_highlight, grub_env_get ("menu_color_highlight")); + grub_parse_color_name_pair (&grub_color_menu_normal, + grub_env_get ("menu_color_normal")); + grub_parse_color_name_pair (&grub_color_menu_highlight, + grub_env_get ("menu_color_highlight")); - grub_normal_init_page (); - grub_setcolor (grub_color_menu_normal, grub_color_menu_highlight); - draw_border (); - grub_setcolor (old_color_normal, old_color_highlight); - print_message (nested, edit); -} - -/* Get the entry number from the variable NAME. */ -static int -get_entry_number (const char *name) -{ - char *val; - int entry; - - val = grub_env_get (name); - if (! val) - return -1; - - grub_error_push (); - - entry = (int) grub_strtoul (val, 0, 0); - - if (grub_errno != GRUB_ERR_NONE) - { - grub_errno = GRUB_ERR_NONE; - entry = -1; - } - - grub_error_pop (); - - return entry; + grub_normal_init_page (term); + grub_term_setcolor (term, grub_color_menu_normal, grub_color_menu_highlight); + draw_border (term); + grub_term_setcolor (term, old_color_normal, old_color_highlight); + print_message (nested, edit, term); } static void -print_timeout (int timeout, int offset) +menu_text_print_timeout (int timeout, void *dataptr) { const char *msg = _("The highlighted entry will be executed automatically in %ds."); - - grub_gotoxy (0, GRUB_TERM_HEIGHT - 3); - - char *msg_translated = - grub_malloc (sizeof (char) * grub_strlen (msg) + 5); - - grub_sprintf (msg_translated, msg, timeout); - grub_print_message_indented (msg_translated, 3, 0); - + struct menu_viewer_data *data = dataptr; + char *msg_translated; int posx; - posx = grub_getxy() >> 8; - grub_print_spaces (GRUB_TERM_WIDTH - posx - 1); - grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset); - grub_refresh (); -} + grub_term_gotoxy (data->term, 0, grub_term_height (data->term) - 3); -/* Show the menu and handle menu entry selection. Returns the menu entry - index that should be executed or -1 if no entry should be executed (e.g., - Esc pressed to exit a sub-menu or switching menu viewers). - If the return value is not -1, then *AUTO_BOOT is nonzero iff the menu - entry to be executed is a result of an automatic default selection because - of the timeout. */ -static int -run_menu (grub_menu_t menu, int nested, int *auto_boot) -{ - int first, offset; - grub_uint64_t saved_time; - int default_entry; - int timeout; - - first = 0; - - default_entry = get_entry_number ("default"); - - /* If DEFAULT_ENTRY is not within the menu entries, fall back to - the first entry. */ - if (default_entry < 0 || default_entry >= menu->size) - default_entry = 0; - - /* If timeout is 0, drawing is pointless (and ugly). */ - if (grub_menu_get_timeout () == 0) - { - *auto_boot = 1; - return default_entry; - } - - offset = default_entry; - if (offset > GRUB_TERM_NUM_ENTRIES - 1) - { - first = offset - (GRUB_TERM_NUM_ENTRIES - 1); - offset = GRUB_TERM_NUM_ENTRIES - 1; - } - - /* Initialize the time. */ - saved_time = grub_get_time_ms (); - - refresh: - grub_setcursor (0); - grub_menu_init_page (nested, 0); - print_entries (menu, first, offset); - grub_refresh (); - - timeout = grub_menu_get_timeout (); - - if (timeout > 0) - print_timeout (timeout, offset); - - while (1) - { - int c; - timeout = grub_menu_get_timeout (); - - if (timeout > 0) - { - grub_uint64_t current_time; - - current_time = grub_get_time_ms (); - if (current_time - saved_time >= 1000) - { - timeout--; - grub_menu_set_timeout (timeout); - saved_time = current_time; - print_timeout (timeout, offset); - } - } - - if (timeout == 0) - { - grub_env_unset ("timeout"); - *auto_boot = 1; - return default_entry; - } - - if (grub_checkkey () >= 0 || timeout < 0) - { - c = GRUB_TERM_ASCII_CHAR (grub_getkey ()); - - if (timeout >= 0) - { - grub_gotoxy (0, GRUB_TERM_HEIGHT - 3); - grub_print_spaces (GRUB_TERM_WIDTH - 1); - - grub_env_unset ("timeout"); - grub_env_unset ("fallback"); - grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset); - } - - switch (c) - { - case GRUB_TERM_HOME: - first = 0; - offset = 0; - print_entries (menu, first, offset); - break; - - case GRUB_TERM_END: - offset = menu->size - 1; - if (offset > GRUB_TERM_NUM_ENTRIES - 1) - { - first = offset - (GRUB_TERM_NUM_ENTRIES - 1); - offset = GRUB_TERM_NUM_ENTRIES - 1; - } - print_entries (menu, first, offset); - break; - - case GRUB_TERM_UP: - case '^': - if (offset > 0) - { - print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 0, - grub_menu_get_entry (menu, first + offset)); - offset--; - print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 1, - grub_menu_get_entry (menu, first + offset)); - } - else if (first > 0) - { - first--; - print_entries (menu, first, offset); - } - break; - - case GRUB_TERM_DOWN: - case 'v': - if (menu->size > first + offset + 1) - { - if (offset < GRUB_TERM_NUM_ENTRIES - 1) - { - print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 0, - grub_menu_get_entry (menu, first + offset)); - offset++; - print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 1, - grub_menu_get_entry (menu, first + offset)); - } - else - { - first++; - print_entries (menu, first, offset); - } - } - break; - - case GRUB_TERM_PPAGE: - if (first == 0) - { - offset = 0; - } - else - { - first -= GRUB_TERM_NUM_ENTRIES; - - if (first < 0) - { - offset += first; - first = 0; - } - } - print_entries (menu, first, offset); - break; - - case GRUB_TERM_NPAGE: - if (offset == 0) - { - offset += GRUB_TERM_NUM_ENTRIES - 1; - if (first + offset >= menu->size) - { - offset = menu->size - first - 1; - } - } - else - { - first += GRUB_TERM_NUM_ENTRIES; - - if (first + offset >= menu->size) - { - first -= GRUB_TERM_NUM_ENTRIES; - offset += GRUB_TERM_NUM_ENTRIES; - - if (offset > menu->size - 1 || - offset > GRUB_TERM_NUM_ENTRIES - 1) - { - offset = menu->size - first - 1; - } - if (offset > GRUB_TERM_NUM_ENTRIES) - { - first += offset - GRUB_TERM_NUM_ENTRIES + 1; - offset = GRUB_TERM_NUM_ENTRIES - 1; - } - } - } - print_entries (menu, first, offset); - break; - - case '\n': - case '\r': - case 6: - grub_setcursor (1); - *auto_boot = 0; - return first + offset; - - case '\e': - if (nested) - { - grub_setcursor (1); - return -1; - } - break; - - case 'c': - grub_cmdline_run (1); - goto refresh; - - case 'e': - { - grub_menu_entry_t e = grub_menu_get_entry (menu, first + offset); - if (e) - grub_menu_entry_run (e); - } - goto refresh; - - default: - break; - } - - grub_refresh (); - } - } - - /* Never reach here. */ - return -1; -} - -/* Callback invoked immediately before a menu entry is executed. */ -static void -notify_booting (grub_menu_entry_t entry, - void *userdata __attribute__((unused))) -{ - grub_printf (" "); - grub_printf_ (N_("Booting \'%s\'"), entry->title); - grub_printf ("\n\n"); -} - -/* Callback invoked when a default menu entry executed because of a timeout - has failed and an attempt will be made to execute the next fallback - entry, ENTRY. */ -static void -notify_fallback (grub_menu_entry_t entry, - void *userdata __attribute__((unused))) -{ - grub_printf ("\n "); - grub_printf_ (N_("Falling back to \'%s\'"), entry->title); - grub_printf ("\n\n"); - grub_millisleep (DEFAULT_ENTRY_ERROR_DELAY_MS); -} - -/* Callback invoked when a menu entry has failed and there is no remaining - fallback entry to attempt. */ -static void -notify_execution_failure (void *userdata __attribute__((unused))) -{ - if (grub_errno != GRUB_ERR_NONE) + msg_translated = grub_malloc (sizeof (char) * grub_strlen (msg) + 5); + if (!msg_translated) { grub_print_error (); grub_errno = GRUB_ERR_NONE; + return; } - grub_printf ("\n "); - grub_printf_ (N_("Failed to boot default entries.\n")); - grub_wait_after_message (); + + grub_sprintf (msg_translated, msg, timeout); + grub_print_message_indented (msg_translated, 3, 0, data->term); + + posx = grub_term_getxy (data->term) >> 8; + print_spaces (grub_term_width (data->term) - posx - 1, data->term); + + grub_term_gotoxy (data->term, + grub_term_cursor_x (data->term), + GRUB_TERM_FIRST_ENTRY_Y + data->offset); + grub_term_refresh (data->term); } -/* Callbacks used by the text menu to provide user feedback when menu entries - are executed. */ -static struct grub_menu_execute_callback execution_callback = +static void +menu_text_set_chosen_entry (int entry, void *dataptr) { - .notify_booting = notify_booting, - .notify_fallback = notify_fallback, - .notify_failure = notify_execution_failure -}; + struct menu_viewer_data *data = dataptr; + int oldoffset = data->offset; + int complete_redraw = 0; -static grub_err_t -show_text_menu (grub_menu_t menu, int nested) -{ - while (1) + data->offset = entry - data->first; + if (data->offset > grub_term_num_entries (data->term) - 1) { - int boot_entry; - grub_menu_entry_t e; - int auto_boot; - - boot_entry = run_menu (menu, nested, &auto_boot); - if (boot_entry < 0) - break; - - e = grub_menu_get_entry (menu, boot_entry); - if (! e) - continue; /* Menu is empty. */ - - grub_cls (); - grub_setcursor (1); - - if (auto_boot) - { - grub_menu_execute_with_fallback (menu, e, &execution_callback, 0); - } - else - { - grub_errno = GRUB_ERR_NONE; - grub_menu_execute_entry (e); - if (grub_errno != GRUB_ERR_NONE) - { - grub_print_error (); - grub_errno = GRUB_ERR_NONE; - grub_wait_after_message (); - } - } + data->first = entry - (grub_term_num_entries (data->term) - 1); + data->offset = grub_term_num_entries (data->term) - 1; + complete_redraw = 1; } + if (data->offset < 0) + { + data->offset = 0; + data->first = entry; + complete_redraw = 1; + } + if (complete_redraw) + print_entries (data->menu, data->first, data->offset, data->term); + else + { + print_entry (GRUB_TERM_FIRST_ENTRY_Y + oldoffset, 0, + grub_menu_get_entry (data->menu, data->first + oldoffset), + data->term); + print_entry (GRUB_TERM_FIRST_ENTRY_Y + data->offset, 1, + grub_menu_get_entry (data->menu, data->first + data->offset), + data->term); + } + grub_term_refresh (data->term); +} + +static void +menu_text_fini (void *dataptr) +{ + struct menu_viewer_data *data = dataptr; + + grub_term_setcursor (data->term, 1); + grub_term_cls (data->term); + +} + +static void +menu_text_clear_timeout (void *dataptr) +{ + struct menu_viewer_data *data = dataptr; + + grub_term_gotoxy (data->term, 0, grub_term_height (data->term) - 3); + print_spaces (grub_term_width (data->term) - 1, data->term); + grub_term_gotoxy (data->term, grub_term_cursor_x (data->term), + GRUB_TERM_FIRST_ENTRY_Y + data->offset); + grub_term_refresh (data->term); +} + +grub_err_t +grub_menu_try_text (struct grub_term_output *term, + int entry, grub_menu_t menu, int nested) +{ + struct menu_viewer_data *data; + struct grub_menu_viewer *instance; + + instance = grub_zalloc (sizeof (*instance)); + if (!instance) + return grub_errno; + + data = grub_zalloc (sizeof (*data)); + if (!data) + { + grub_free (instance); + return grub_errno; + } + + data->term = term; + instance->data = data; + instance->set_chosen_entry = menu_text_set_chosen_entry; + instance->print_timeout = menu_text_print_timeout; + instance->clear_timeout = menu_text_clear_timeout; + instance->fini = menu_text_fini; + + data->menu = menu; + + data->offset = entry; + data->first = 0; + if (data->offset > grub_term_num_entries (data->term) - 1) + { + data->first = data->offset - (grub_term_num_entries (data->term) - 1); + data->offset = grub_term_num_entries (data->term) - 1; + } + + grub_term_setcursor (data->term, 0); + grub_menu_init_page (nested, 0, data->term); + print_entries (menu, data->first, data->offset, data->term); + grub_term_refresh (data->term); + grub_menu_register_viewer (instance); return GRUB_ERR_NONE; } - -struct grub_menu_viewer grub_normal_text_menu_viewer = -{ - .name = "text", - .show_menu = show_text_menu -}; diff --git a/normal/menu_viewer.c b/normal/menu_viewer.c deleted file mode 100644 index f870ccd53..000000000 --- a/normal/menu_viewer.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2009 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GRUB. If not, see . - */ - -#include -#include -#include -#include -#include -#include - -/* The list of menu viewers. */ -static grub_menu_viewer_t menu_viewer_list; - -void -grub_menu_viewer_register (grub_menu_viewer_t viewer) -{ - viewer->next = menu_viewer_list; - menu_viewer_list = viewer; -} - -static grub_menu_viewer_t get_current_menu_viewer (void) -{ - const char *selected_name = grub_env_get ("menuviewer"); - - /* If none selected, pick the last registered one. */ - if (selected_name == 0) - return menu_viewer_list; - - grub_menu_viewer_t cur; - for (cur = menu_viewer_list; cur; cur = cur->next) - { - if (grub_strcmp (cur->name, selected_name) == 0) - return cur; - } - - /* Fall back to the first entry (or null). */ - return menu_viewer_list; -} - -grub_err_t -grub_menu_viewer_show_menu (grub_menu_t menu, int nested) -{ - grub_menu_viewer_t cur = get_current_menu_viewer (); - grub_err_t err1, err2; - if (!cur) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "no menu viewer available"); - - while (1) - { - err1 = cur->show_menu (menu, nested); - grub_print_error (); - - err2 = grub_auth_check_authentication (NULL); - if (err2) - { - grub_print_error (); - grub_errno = GRUB_ERR_NONE; - continue; - } - - break; - } - - return err1; -} - diff --git a/normal/term.c b/normal/term.c new file mode 100644 index 000000000..667d27ee9 --- /dev/null +++ b/normal/term.c @@ -0,0 +1,252 @@ +/* + * 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 + +/* The amount of lines counted by the pager. */ +static unsigned grub_more_lines; + +/* If the more pager is active. */ +static int grub_more; + +static void +process_newline (void) +{ + struct grub_term_output *cur; + unsigned height = -1; + + FOR_ACTIVE_TERM_OUTPUTS(cur) + if (grub_term_height (cur) < height) + height = grub_term_height (cur); + grub_more_lines++; + + if (grub_more && grub_more_lines >= height - 1) + { + char key; + grub_uint16_t *pos; + + pos = grub_term_save_pos (); + + grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT); + grub_printf ("--MORE--"); + grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); + + key = grub_getkey (); + + /* Remove the message. */ + grub_term_restore_pos (pos); + grub_printf (" "); + grub_term_restore_pos (pos); + + /* Scroll one lines or an entire page, depending on the key. */ + if (key == '\r' || key =='\n') + grub_more_lines = height - 2; + else + grub_more_lines = 0; + } +} + +void +grub_set_more (int onoff) +{ + if (onoff == 1) + grub_more++; + else + grub_more--; + + grub_more_lines = 0; + grub_newline_hook = process_newline; +} + +void +grub_puts_terminal (const char *str, struct grub_term_output *term) +{ + grub_uint32_t code; + grub_ssize_t ret; + const grub_uint8_t *ptr = (const grub_uint8_t *) str; + const grub_uint8_t *end; + end = (const grub_uint8_t *) (str + grub_strlen (str)); + + while (*ptr) + { + ret = grub_utf8_to_ucs4 (&code, 1, ptr, end - ptr, &ptr); + grub_putcode (code, term); + } +} + +grub_uint16_t * +grub_term_save_pos (void) +{ + struct grub_term_output *cur; + unsigned cnt = 0; + grub_uint16_t *ret, *ptr; + + FOR_ACTIVE_TERM_OUTPUTS(cur) + cnt++; + + ret = grub_malloc (cnt * sizeof (ret[0])); + if (!ret) + return NULL; + + ptr = ret; + FOR_ACTIVE_TERM_OUTPUTS(cur) + *ptr++ = grub_term_getxy (cur); + + return ret; +} + +void +grub_term_restore_pos (grub_uint16_t *pos) +{ + struct grub_term_output *cur; + grub_uint16_t *ptr = pos; + + if (!pos) + return; + + FOR_ACTIVE_TERM_OUTPUTS(cur) + { + grub_term_gotoxy (cur, (*ptr & 0xff00) >> 8, *ptr & 0xff); + ptr++; + } +} + +static void +grub_terminal_autoload_free (void) +{ + struct grub_term_autoload *cur, *next; + unsigned i; + for (i = 0; i < 2; i++) + for (cur = i ? grub_term_input_autoload : grub_term_output_autoload; + cur; cur = next) + { + next = cur->next; + grub_free (cur->name); + grub_free (cur->modname); + grub_free (cur); + } + grub_term_input_autoload = NULL; + grub_term_output_autoload = NULL; +} + + +/* Read the file terminal.lst for auto-loading. */ +void +read_terminal_list (void) +{ + const char *prefix; + char *filename; + grub_file_t file; + char *buf = NULL; + + prefix = grub_env_get ("prefix"); + if (!prefix) + { + grub_errno = GRUB_ERR_NONE; + return; + } + + filename = grub_malloc (grub_strlen (prefix) + sizeof ("/terminal.lst")); + if (!filename) + { + grub_errno = GRUB_ERR_NONE; + return; + } + + grub_sprintf (filename, "%s/terminal.lst", prefix); + file = grub_file_open (filename); + if (!file) + { + grub_errno = GRUB_ERR_NONE; + return; + } + + /* Override previous terminal.lst. */ + grub_terminal_autoload_free (); + + for (;; grub_free (buf)) + { + char *p, *name; + struct grub_term_autoload *cur; + struct grub_term_autoload **target = NULL; + + buf = grub_file_getline (file); + + if (! buf) + break; + + switch (buf[0]) + { + case 'i': + target = &grub_term_input_autoload; + break; + + case 'o': + target = &grub_term_output_autoload; + break; + } + if (!target) + continue; + + name = buf + 1; + + p = grub_strchr (name, ':'); + if (! p) + continue; + + *p = '\0'; + while (*++p == ' ') + ; + + cur = grub_malloc (sizeof (*cur)); + if (!cur) + { + grub_errno = GRUB_ERR_NONE; + continue; + } + + cur->name = grub_strdup (name); + if (! name) + { + grub_errno = GRUB_ERR_NONE; + grub_free (cur); + continue; + } + + cur->modname = grub_strdup (p); + if (! cur->modname) + { + grub_errno = GRUB_ERR_NONE; + grub_free (cur); + grub_free (cur->name); + continue; + } + cur->next = *target; + *target = cur; + } + + grub_file_close (file); + + grub_errno = GRUB_ERR_NONE; +} diff --git a/po/POTFILES b/po/POTFILES index c4ae9d562..32927256c 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -53,7 +53,19 @@ hello/hello.c lib/arg.c +loader/efi/appleloader.c +loader/efi/chainloader.c loader/i386/bsd.c +loader/i386/efi/linux.c +loader/i386/ieee1275/linux.c +loader/i386/linux.c +loader/i386/pc/chainloader.c +loader/i386/pc/linux.c +loader/i386/xnu.c +loader/multiboot_loader.c +loader/powerpc/ieee1275/linux.c +loader/sparc64/ieee1275/linux.c +loader/xnu.c normal/auth.c normal/color.c diff --git a/term/efi/console.c b/term/efi/console.c index f3845089c..264770cae 100644 --- a/term/efi/console.c +++ b/term/efi/console.c @@ -351,8 +351,7 @@ static struct grub_term_output grub_console_term_output = .setcolorstate = grub_console_setcolorstate, .setcolor = grub_console_setcolor, .getcolor = grub_console_getcolor, - .setcursor = grub_console_setcursor, - .flags = 0, + .setcursor = grub_console_setcursor }; void diff --git a/term/gfxterm.c b/term/gfxterm.c index fa19a5d85..f493f882c 100644 --- a/term/gfxterm.c +++ b/term/gfxterm.c @@ -27,7 +27,7 @@ #include #include -#define DEFAULT_VIDEO_MODE "1024x768,800x600,640x480" +#define DEFAULT_VIDEO_MODE "auto" #define DEFAULT_BORDER_WIDTH 10 #define DEFAULT_STANDARD_COLOR 0x07 @@ -244,12 +244,6 @@ grub_virtual_screen_setup (unsigned int x, unsigned int y, return grub_errno; } -static int NESTED_FUNC_ATTR video_hook (grub_video_adapter_t p __attribute__ ((unused)), - struct grub_video_mode_info *info) -{ - return ! (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT); -} - static grub_err_t grub_gfxterm_init (void) { @@ -269,13 +263,15 @@ grub_gfxterm_init (void) /* Parse gfxmode environment variable if set. */ modevar = grub_env_get ("gfxmode"); if (! modevar || *modevar == 0) - err = grub_video_set_mode (DEFAULT_VIDEO_MODE, video_hook); + err = grub_video_set_mode (DEFAULT_VIDEO_MODE, + GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0); else { tmp = grub_malloc (grub_strlen (modevar) + sizeof (DEFAULT_VIDEO_MODE) + 1); grub_sprintf (tmp, "%s;" DEFAULT_VIDEO_MODE, modevar); - err = grub_video_set_mode (tmp, video_hook); + err = grub_video_set_mode (tmp, + GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0); grub_free (tmp); } diff --git a/term/i386/pc/console.c b/term/i386/pc/console.c index 66475d456..43cfe2f2a 100644 --- a/term/i386/pc/console.c +++ b/term/i386/pc/console.c @@ -65,8 +65,7 @@ static struct grub_term_output grub_console_term_output = .setcolorstate = grub_console_setcolorstate, .setcolor = grub_console_setcolor, .getcolor = grub_console_getcolor, - .setcursor = grub_console_setcursor, - .flags = 0, + .setcursor = grub_console_setcursor }; void @@ -79,10 +78,6 @@ grub_console_init (void) void grub_console_fini (void) { - /* This is to make sure the console is restored to text mode before - we boot. */ - grub_term_set_current_output (&grub_console_term_output); - grub_term_unregister_input (&grub_console_term_input); grub_term_unregister_output (&grub_console_term_output); } diff --git a/term/i386/pc/serial.c b/term/i386/pc/serial.c index 0f4749eae..8d09f6211 100644 --- a/term/i386/pc/serial.c +++ b/term/i386/pc/serial.c @@ -31,6 +31,7 @@ #define TEXT_WIDTH 80 #define TEXT_HEIGHT 25 +static struct grub_term_output grub_serial_term_output; static unsigned int xpos, ypos; static unsigned int keep_track = 1; static unsigned int registered = 0; @@ -414,7 +415,7 @@ grub_serial_gotoxy (grub_uint8_t x, grub_uint8_t y) else { keep_track = 0; - grub_terminfo_gotoxy (x, y); + grub_terminfo_gotoxy (x, y, &grub_serial_term_output); keep_track = 1; xpos = x; @@ -426,7 +427,7 @@ static void grub_serial_cls (void) { keep_track = 0; - grub_terminfo_cls (); + grub_terminfo_cls (&grub_serial_term_output); keep_track = 1; xpos = ypos = 0; @@ -440,10 +441,10 @@ grub_serial_setcolorstate (const grub_term_color_state state) { case GRUB_TERM_COLOR_STANDARD: case GRUB_TERM_COLOR_NORMAL: - grub_terminfo_reverse_video_off (); + grub_terminfo_reverse_video_off (&grub_serial_term_output); break; case GRUB_TERM_COLOR_HIGHLIGHT: - grub_terminfo_reverse_video_on (); + grub_terminfo_reverse_video_on (&grub_serial_term_output); break; default: break; @@ -455,9 +456,9 @@ static void grub_serial_setcursor (const int on) { if (on) - grub_terminfo_cursor_on (); + grub_terminfo_cursor_on (&grub_serial_term_output); else - grub_terminfo_cursor_off (); + grub_terminfo_cursor_off (&grub_serial_term_output); } static struct grub_term_input grub_serial_term_input = diff --git a/term/i386/pc/vga_text.c b/term/i386/pc/vga_text.c index 170f74de8..f954cab43 100644 --- a/term/i386/pc/vga_text.c +++ b/term/i386/pc/vga_text.c @@ -77,7 +77,7 @@ inc_y (void) static void inc_x (void) { - if (grub_curr_x >= COLS - 2) + if (grub_curr_x >= COLS - 1) inc_y (); else grub_curr_x++; diff --git a/term/ieee1275/ofconsole.c b/term/ieee1275/ofconsole.c index fbed9eca1..a9834e23e 100644 --- a/term/ieee1275/ofconsole.c +++ b/term/ieee1275/ofconsole.c @@ -83,12 +83,17 @@ grub_ofconsole_putchar (grub_uint32_t c) grub_curr_y++; grub_curr_x = 0; } + else if (c == '\r') + { + grub_curr_x = 0; + } else { grub_curr_x++; - if (grub_curr_x > grub_ofconsole_width) + if (grub_curr_x >= grub_ofconsole_width) { - grub_putcode ('\n'); + grub_ofconsole_putchar ('\n'); + grub_ofconsole_putchar ('\r'); grub_curr_x++; } } @@ -234,16 +239,13 @@ grub_ofconsole_getxy (void) return ((grub_curr_x - 1) << 8) | grub_curr_y; } -static grub_uint16_t -grub_ofconsole_getwh (void) +static void +grub_ofconsole_dimensions (void) { grub_ieee1275_ihandle_t options; char *val; grub_ssize_t lval; - if (grub_ofconsole_width && grub_ofconsole_height) - return (grub_ofconsole_width << 8) | grub_ofconsole_height; - if (! grub_ieee1275_finddevice ("/options", &options) && options != (grub_ieee1275_ihandle_t) -1) { @@ -280,7 +282,11 @@ grub_ofconsole_getwh (void) grub_ofconsole_width = 80; if (! grub_ofconsole_height) grub_ofconsole_height = 24; +} +static grub_uint16_t +grub_ofconsole_getwh (void) +{ return (grub_ofconsole_width << 8) | grub_ofconsole_height; } @@ -319,7 +325,7 @@ grub_ofconsole_cls (void) * ANSI escape sequence. Using video console, Apple Open Firmware (version * 3.1.1) only recognizes the literal ^L. So use both. */ grub_ofconsole_writeesc (" \e[2J"); - grub_gotoxy (0, 0); + grub_ofconsole_gotoxy (0, 0); } static void @@ -379,6 +385,8 @@ grub_ofconsole_init_output (void) grub_ofconsole_setcolorstate (GRUB_TERM_COLOR_NORMAL); } + grub_ofconsole_dimensions (); + return 0; } @@ -414,8 +422,7 @@ static struct grub_term_output grub_ofconsole_term_output = .setcolor = grub_ofconsole_setcolor, .getcolor = grub_ofconsole_getcolor, .setcursor = grub_ofconsole_setcursor, - .refresh = grub_ofconsole_refresh, - .flags = 0, + .refresh = grub_ofconsole_refresh }; void diff --git a/term/terminfo.c b/term/terminfo.c index fc22fe850..9a5979b1c 100644 --- a/term/terminfo.c +++ b/term/terminfo.c @@ -108,52 +108,52 @@ grub_terminfo_set_current (const char *str) /* Wrapper for grub_putchar to write strings. */ static void -putstr (const char *str) +putstr (const char *str, grub_term_output_t oterm) { while (*str) - grub_putchar (*str++); + grub_putcode (*str++, oterm); } /* Move the cursor to the given position starting with "0". */ void -grub_terminfo_gotoxy (grub_uint8_t x, grub_uint8_t y) +grub_terminfo_gotoxy (grub_uint8_t x, grub_uint8_t y, grub_term_output_t oterm) { - putstr (grub_terminfo_tparm (term.gotoxy, y, x)); + putstr (grub_terminfo_tparm (term.gotoxy, y, x), oterm); } /* Clear the screen. */ void -grub_terminfo_cls (void) +grub_terminfo_cls (grub_term_output_t oterm) { - putstr (grub_terminfo_tparm (term.cls)); + putstr (grub_terminfo_tparm (term.cls), oterm); } /* Set reverse video mode on. */ void -grub_terminfo_reverse_video_on (void) +grub_terminfo_reverse_video_on (grub_term_output_t oterm) { - putstr (grub_terminfo_tparm (term.reverse_video_on)); + putstr (grub_terminfo_tparm (term.reverse_video_on), oterm); } /* Set reverse video mode off. */ void -grub_terminfo_reverse_video_off (void) +grub_terminfo_reverse_video_off (grub_term_output_t oterm) { - putstr (grub_terminfo_tparm (term.reverse_video_off)); + putstr (grub_terminfo_tparm (term.reverse_video_off), oterm); } /* Show cursor. */ void -grub_terminfo_cursor_on (void) +grub_terminfo_cursor_on (grub_term_output_t oterm) { - putstr (grub_terminfo_tparm (term.cursor_on)); + putstr (grub_terminfo_tparm (term.cursor_on), oterm); } /* Hide cursor. */ void -grub_terminfo_cursor_off (void) +grub_terminfo_cursor_off (grub_term_output_t oterm) { - putstr (grub_terminfo_tparm (term.cursor_off)); + putstr (grub_terminfo_tparm (term.cursor_off), oterm); } /* GRUB Command. */ diff --git a/tests/example_functional_test.c b/tests/example_functional_test.c new file mode 100644 index 000000000..f43c0f1ce --- /dev/null +++ b/tests/example_functional_test.c @@ -0,0 +1,35 @@ +/* + * 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 . + */ + +/* All tests need to include test.h for GRUB testing framework. */ +#include + +/* Functional test main method. */ +static void +example_test (void) +{ + /* Check if 1st argument is true and report with default error message. */ + grub_test_assert (1 == 1); + + /* Check if 1st argument is true and report with custom error message. */ + grub_test_assert (2 == 2, "2 equal 2 expected"); + grub_test_assert (2 == 3, "2 is not equal to %d", 3); +} + +/* Register example_test method as a functional test. */ +GRUB_FUNCTIONAL_TEST ("example_functional_test", example_test); diff --git a/tests/example_grub_script_test.in b/tests/example_grub_script_test.in new file mode 100644 index 000000000..93a90a18e --- /dev/null +++ b/tests/example_grub_script_test.in @@ -0,0 +1,3 @@ +#! @builddir@/grub-shell-tester --modules=echo + +echo "hello world" diff --git a/tests/example_scripted_test.in b/tests/example_scripted_test.in new file mode 100644 index 000000000..9ac0424c0 --- /dev/null +++ b/tests/example_scripted_test.in @@ -0,0 +1,3 @@ +#!/bin/sh -e + +true diff --git a/tests/example_unit_test.c b/tests/example_unit_test.c new file mode 100644 index 000000000..4999f1412 --- /dev/null +++ b/tests/example_unit_test.c @@ -0,0 +1,38 @@ +/* + * 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 . + */ + +/* Unit tests are normal programs, so they can include C library. */ +#include + +/* All tests need to include test.h for GRUB testing framework. */ +#include + +/* Unit test main method. */ +static void +example_test (void) +{ + /* Check if 1st argument is true and report with default error message. */ + grub_test_assert (1 == 1); + + /* Check if 1st argument is true and report with custom error message. */ + grub_test_assert (2 == 2, "2 equal 2 expected"); + grub_test_assert (2 == 3, "2 is not equal to %d", 3); +} + +/* Register example_test method as a unit test. */ +GRUB_UNIT_TEST ("example_unit_test", example_test); diff --git a/tests/lib/functional_test.c b/tests/lib/functional_test.c new file mode 100644 index 000000000..8ff08cf8a --- /dev/null +++ b/tests/lib/functional_test.c @@ -0,0 +1,53 @@ +/* + * 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 + +static grub_err_t +grub_functional_test (struct grub_extcmd *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + auto int run_test (grub_test_t test); + int run_test (grub_test_t test) + { + grub_test_run (test); + return 0; + } + + grub_list_iterate (GRUB_AS_LIST (grub_test_list), + (grub_list_hook_t) run_test); + return GRUB_ERR_NONE; +} + +static grub_extcmd_t cmd; + +GRUB_MOD_INIT (functional_test) +{ + cmd = grub_register_extcmd ("functional_test", grub_functional_test, + GRUB_COMMAND_FLAG_CMDLINE, 0, + "Run all functional tests.", 0); +} + +GRUB_MOD_FINI (functional_test) +{ + grub_unregister_extcmd (cmd); +} diff --git a/tests/lib/test.c b/tests/lib/test.c new file mode 100644 index 000000000..cd0799f56 --- /dev/null +++ b/tests/lib/test.c @@ -0,0 +1,164 @@ +/* + * 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 + +struct grub_test_failure +{ + /* The next failure. */ + struct grub_test_failure *next; + + /* The test source file name. */ + char *file; + + /* The test function name. */ + char *funp; + + /* The test call line number. */ + grub_uint32_t line; + + /* The test failure message. */ + char *message; +}; +typedef struct grub_test_failure *grub_test_failure_t; + +grub_test_t grub_test_list; +static grub_test_failure_t failure_list; + +static void +add_failure (const char *file, + const char *funp, + grub_uint32_t line, const char *fmt, va_list args) +{ + char buf[1024]; + grub_test_failure_t failure; + + failure = (grub_test_failure_t) grub_malloc (sizeof (*failure)); + if (!failure) + return; + + grub_vsprintf (buf, fmt, args); + + failure->file = grub_strdup (file ? : ""); + failure->funp = grub_strdup (funp ? : ""); + failure->line = line; + failure->message = grub_strdup (buf); + + grub_list_push (GRUB_AS_LIST_P (&failure_list), GRUB_AS_LIST (failure)); +} + +static void +free_failures (void) +{ + grub_test_failure_t item; + + while ((item = grub_list_pop (GRUB_AS_LIST_P (&failure_list))) != 0) + { + if (item->message) + grub_free (item->message); + + if (item->funp) + grub_free (item->funp); + + if (item->file) + grub_free (item->file); + + grub_free (item); + } + failure_list = 0; +} + +void +grub_test_nonzero (int cond, + const char *file, + const char *funp, grub_uint32_t line, const char *fmt, ...) +{ + va_list ap; + + if (cond) + return; + + va_start (ap, fmt); + add_failure (file, funp, line, fmt, ap); + va_end (ap); +} + +void +grub_test_register (const char *name, void (*test_main) (void)) +{ + grub_test_t test; + + test = (grub_test_t) grub_malloc (sizeof (*test)); + if (!test) + return; + + test->name = grub_strdup (name); + test->main = test_main; + + grub_list_push (GRUB_AS_LIST_P (&grub_test_list), GRUB_AS_LIST (test)); +} + +void +grub_test_unregister (const char *name) +{ + grub_test_t test; + + test = (grub_test_t) grub_named_list_find + (GRUB_AS_NAMED_LIST (grub_test_list), name); + + if (test) + { + grub_list_remove (GRUB_AS_LIST_P (&grub_test_list), GRUB_AS_LIST (test)); + + if (test->name) + grub_free (test->name); + + grub_free (test); + } +} + +int +grub_test_run (grub_test_t test) +{ + auto int print_failure (grub_test_failure_t item); + int print_failure (grub_test_failure_t item) + { + grub_test_failure_t failure = (grub_test_failure_t) item; + + grub_printf (" %s:%s:%u: %s\n", + (failure->file ? : ""), + (failure->funp ? : ""), + failure->line, (failure->message ? : "")); + return 0; + } + + test->main (); + + grub_printf ("%s:\n", test->name); + grub_list_iterate (GRUB_AS_LIST (failure_list), + (grub_list_hook_t) print_failure); + if (!failure_list) + grub_printf ("%s: PASS\n", test->name); + else + grub_printf ("%s: FAIL\n", test->name); + + free_failures (); + return GRUB_ERR_NONE; +} diff --git a/tests/lib/unit_test.c b/tests/lib/unit_test.c new file mode 100644 index 000000000..e461150de --- /dev/null +++ b/tests/lib/unit_test.c @@ -0,0 +1,109 @@ +/* + * 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 + +int +main (int argc __attribute__ ((unused)), + char *argv[] __attribute__ ((unused))) +{ + int status = 0; + + extern void grub_unit_test_init (void); + extern void grub_unit_test_fini (void); + + auto int run_test (grub_test_t test); + int run_test (grub_test_t test) + { + status = grub_test_run (test) ? : status; + return 0; + } + + grub_unit_test_init (); + grub_list_iterate (GRUB_AS_LIST (grub_test_list), + (grub_list_hook_t) run_test); + grub_unit_test_fini (); + + exit (status); +} + +/* Other misc. functions necessary for successful linking. */ + +void +grub_free (void *ptr) +{ + free (ptr); +} + +char * +grub_env_get (const char *name __attribute__ ((unused))) +{ + return NULL; +} + +grub_err_t +grub_error (grub_err_t n, const char *fmt, ...) +{ + va_list ap; + + va_start (ap, fmt); + vfprintf (stderr, fmt, ap); + va_end (ap); + + return n; +} + +void * +grub_malloc (grub_size_t size) +{ + return malloc (size); +} + +void +grub_refresh (void) +{ + fflush (stdout); +} + +void +grub_putchar (int c) +{ + putchar (c); +} + +int +grub_getkey (void) +{ + return -1; +} + +void +grub_exit (void) +{ + exit (1); +} + +struct grub_handler_class grub_term_input_class; +struct grub_handler_class grub_term_output_class; diff --git a/tests/util/grub-shell-tester.in b/tests/util/grub-shell-tester.in new file mode 100644 index 000000000..6ed4ebcac --- /dev/null +++ b/tests/util/grub-shell-tester.in @@ -0,0 +1,109 @@ +#! /bin/bash -e + +# Compares GRUB script output with BASH output. +# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc. +# +# GRUB is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# GRUB is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU 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@ +bindir=@bindir@ +libdir=@libdir@ +builddir=@builddir@ +PACKAGE_NAME=@PACKAGE_NAME@ +PACKAGE_TARNAME=@PACKAGE_TARNAME@ +PACKAGE_VERSION=@PACKAGE_VERSION@ +target_cpu=@target_cpu@ + +# Force build directory components +PATH=${builddir}:$PATH +export PATH + +# Usage: usage +# Print the usage. +usage () { + cat <. +EOF +} + +# Check the arguments. +for option in "$@"; do + case "$option" in + -h | --help) + usage + exit 0 ;; + -v | --version) + echo "$0 (GNU GRUB ${PACKAGE_VERSION})" + exit 0 ;; + --modules=*) + ms=`echo "$option" | sed -e 's/--modules=//'` + modules="$modules,$ms" ;; + --qemu-opts=*) + qs=`echo "$option" | sed -e 's/--qemu-opts=//'` + qemuopts="$qemuopts $qs" ;; + -*) + echo "Unrecognized option \`$option'" 1>&2 + usage + exit 1 + ;; + *) + if [ "x${source}" != x ] ; then + echo "too many parameters at the end" 1>&2 + usage + exit 1 + fi + source="${option}" ;; + esac +done + +if [ "x${source}" = x ] ; then + tmpfile=`mktemp` + while read; do + echo $REPLY >> ${tmpfile} + done + source=${tmpfile} +fi + +outfile1=`mktemp` +@builddir@/grub-shell --qemu-opts="${qemuopts}" --modules=${modules} ${source} >${outfile1} + +outfile2=`mktemp` +bash ${source} >${outfile2} + +if ! diff -q ${outfile1} ${outfile2} >/dev/null +then + echo "${source}: GRUB and BASH outputs did not match (see diff -u ${outfile1} ${outfile2})" + status=1 +else + rm -f ${outfile1} ${outfile2} +fi + +exit $status + + diff --git a/tests/util/grub-shell.in b/tests/util/grub-shell.in new file mode 100644 index 000000000..e6fef8313 --- /dev/null +++ b/tests/util/grub-shell.in @@ -0,0 +1,145 @@ +#! /bin/bash -e + +# Run GRUB script in a Qemu instance +# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc. +# +# GRUB is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# GRUB is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU 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@ +bindir=@bindir@ +libdir=@libdir@ +builddir=@builddir@ +PACKAGE_NAME=@PACKAGE_NAME@ +PACKAGE_TARNAME=@PACKAGE_TARNAME@ +PACKAGE_VERSION=@PACKAGE_VERSION@ +target_cpu=@target_cpu@ + +# Force build directory components +PATH=${builddir}:$PATH +export PATH + +# Usage: usage +# Print the usage. +usage () { + cat <. +EOF +} + +# Check the arguments. +for option in "$@"; do + case "$option" in + -h | --help) + usage + exit 0 ;; + -v | --version) + echo "$0 (GNU GRUB ${PACKAGE_VERSION})" + exit 0 ;; + --modules=*) + ms=`echo "$option" | sed -e 's/--modules=//' -e 's/,/ /g'` + modules="$modules $ms" ;; + --qemu-opts=*) + qs=`echo "$option" | sed -e 's/--qemu-opts=//'` + qemuopts="$qemuopts $qs" ;; + --boot=*) + dev=`echo "$option" | sed -e 's/--boot=//'` + if [ "$dev" = "fd" ] ; then bootdev=a; + elif [ "$dev" = "hd" ] ; then bootdev=c; + elif [ "$dev" = "cd" ] ; then bootdev=d; + else + echo "Unrecognized boot method \`$dev'" 1>&2 + usage + exit 1 + fi ;; + -*) + echo "Unrecognized option \`$option'" 1>&2 + usage + exit 1 ;; + *) + if [ "x${source}" != x ] ; then + echo "too many parameters at the end" 1>&2 + usage + exit 1 + fi + source="${option}" ;; + esac +done + +if [ "x${source}" = x ] ; then + tmpfile=`mktemp` + while read; do + echo $REPLY >> ${tmpfile} + done + source=${tmpfile} +fi + +if [ "x${bootdev}" = x ] ; then + bootdev=c # default is boot as disk image +fi + +cfgfile=`mktemp` +cat <${cfgfile} +grubshell=yes +insmod serial +serial +terminal_input serial +terminal_output serial +EOF + +for mod in ${modules} +do + echo "insmod ${mod}" >> ${cfgfile} +done + +cat <>${cfgfile} +source /boot/grub/testcase.cfg +halt +EOF + +isofile=`mktemp` +grub-mkrescue --output=${isofile} --override-directory=${builddir} \ + /boot/grub/grub.cfg=${cfgfile} /boot/grub/testcase.cfg=${source} \ + >/dev/null 2>&1 + +hdafile=`mktemp` +cp ${isofile} ${hdafile} + +fdafile=`mktemp` +cp ${isofile} ${fdafile} + +outfile=`mktemp` +qemu-system-i386 ${qemuopts} -nographic -serial stdio -hda ${hdafile} -fda ${fdafile} -cdrom ${isofile} -boot ${bootdev} | tr -d "\r" >${outfile} + +cat $outfile + +rm -f ${tmpfile} ${outfile} ${cfgfile} ${isofile} ${hdafile} ${fdafile} +exit 0 + + diff --git a/util/console.c b/util/console.c index 9d8bb1a63..382fd7f89 100644 --- a/util/console.c +++ b/util/console.c @@ -19,14 +19,6 @@ #include -#if defined(HAVE_NCURSES_CURSES_H) -# include -#elif defined(HAVE_NCURSES_H) -# include -#elif defined(HAVE_CURSES_H) -# include -#endif - /* For compatibility. */ #ifndef A_NORMAL # define A_NORMAL 0 @@ -39,6 +31,14 @@ #include #include +#if defined(HAVE_NCURSES_CURSES_H) +# include +#elif defined(HAVE_NCURSES_H) +# include +#elif defined(HAVE_CURSES_H) +# include +#endif + static int grub_console_attr = A_NORMAL; grub_uint8_t grub_console_cur_color = 7; @@ -367,8 +367,7 @@ static struct grub_term_output grub_ncurses_term_output = .setcolor = grub_ncurses_setcolor, .getcolor = grub_ncurses_getcolor, .setcursor = grub_ncurses_setcursor, - .refresh = grub_ncurses_refresh, - .flags = 0, + .refresh = grub_ncurses_refresh }; void @@ -376,8 +375,6 @@ grub_console_init (void) { grub_term_register_output ("console", &grub_ncurses_term_output); grub_term_register_input ("console", &grub_ncurses_term_input); - grub_term_set_current_output (&grub_ncurses_term_output); - grub_term_set_current_input (&grub_ncurses_term_input); } void diff --git a/util/elf/grub-mkimage.c b/util/elf/grub-mkimage.c index 6ba8b1ae2..c0736b83f 100644 --- a/util/elf/grub-mkimage.c +++ b/util/elf/grub-mkimage.c @@ -328,7 +328,7 @@ static void usage (int status) { if (status) - fprintf (stderr, "Try ``%s --help'' for more information.\n", program_name); + fprintf (stderr, "Try `%s --help' for more information.\n", program_name); else printf ("\ Usage: %s -o FILE [OPTION]... [MODULES]\n\ diff --git a/util/getroot.c b/util/getroot.c index 22ad7e967..6357c8a26 100644 --- a/util/getroot.c +++ b/util/getroot.c @@ -115,14 +115,14 @@ grub_get_prefix (const char *dir) saved_cwd = xgetcwd (); if (chdir (dir) < 0) - grub_util_error ("Cannot change directory to `%s'", dir); + grub_util_error ("cannot change directory to `%s'", dir); abs_dir = xgetcwd (); strip_extra_slashes (abs_dir); prev_dir = xstrdup (abs_dir); if (stat (".", &prev_st) < 0) - grub_util_error ("Cannot stat `%s'", dir); + grub_util_error ("cannot stat `%s'", dir); if (! S_ISDIR (prev_st.st_mode)) grub_util_error ("`%s' is not a directory", dir); @@ -130,13 +130,13 @@ grub_get_prefix (const char *dir) while (1) { if (chdir ("..") < 0) - grub_util_error ("Cannot change directory to the parent"); + grub_util_error ("cannot change directory to the parent"); if (stat (".", &st) < 0) - grub_util_error ("Cannot stat current directory"); + grub_util_error ("cannot stat current directory"); if (! S_ISDIR (st.st_mode)) - grub_util_error ("Current directory is not a directory???"); + grub_util_error ("current directory is not a directory???"); if (prev_st.st_dev != st.st_dev || prev_st.st_ino == st.st_ino) break; @@ -153,7 +153,7 @@ grub_get_prefix (const char *dir) strip_extra_slashes (prefix); if (chdir (saved_cwd) < 0) - grub_util_error ("Cannot change directory to `%s'", dir); + grub_util_error ("cannot change directory to `%s'", dir); #ifdef __CYGWIN__ if (st.st_dev != (DEV_CYGDRIVE_MAJOR << 16)) @@ -236,7 +236,7 @@ find_root_device (const char *dir, dev_t dev) if (res) { if (chdir (saved_cwd) < 0) - grub_util_error ("Cannot restore the original directory"); + grub_util_error ("cannot restore the original directory"); free (saved_cwd); closedir (dp); @@ -279,7 +279,7 @@ find_root_device (const char *dir, dev_t dev) continue; if (chdir (saved_cwd) < 0) - grub_util_error ("Cannot restore the original directory"); + grub_util_error ("cannot restore the original directory"); free (saved_cwd); closedir (dp); @@ -288,7 +288,7 @@ find_root_device (const char *dir, dev_t dev) } if (chdir (saved_cwd) < 0) - grub_util_error ("Cannot restore the original directory"); + grub_util_error ("cannot restore the original directory"); free (saved_cwd); closedir (dp); @@ -445,7 +445,7 @@ grub_guess_root_device (const char *dir) struct stat st; if (stat (dir, &st) < 0) - grub_util_error ("Cannot stat `%s'", dir); + grub_util_error ("cannot stat `%s'", dir); #ifdef __CYGWIN__ /* Cygwin specific function. */ @@ -591,7 +591,7 @@ grub_util_get_grub_dev (const char *os_dev) free (p); } else - grub_util_error ("Unknown kind of RAID device `%s'", os_dev); + grub_util_error ("unknown kind of RAID device `%s'", os_dev); break; @@ -608,7 +608,7 @@ grub_util_check_block_device (const char *blk_dev) struct stat st; if (stat (blk_dev, &st) < 0) - grub_util_error ("Cannot stat `%s'", blk_dev); + grub_util_error ("cannot stat `%s'", blk_dev); if (S_ISBLK (st.st_mode)) return (blk_dev); @@ -622,7 +622,7 @@ grub_util_check_char_device (const char *blk_dev) struct stat st; if (stat (blk_dev, &st) < 0) - grub_util_error ("Cannot stat `%s'", blk_dev); + grub_util_error ("cannot stat `%s'", blk_dev); if (S_ISCHR (st.st_mode)) return (blk_dev); diff --git a/util/grub-editenv.c b/util/grub-editenv.c index b6b731549..f21042c97 100644 --- a/util/grub-editenv.c +++ b/util/grub-editenv.c @@ -46,9 +46,6 @@ grub_refresh (void) fflush (stdout); } -struct grub_handler_class grub_term_input_class; -struct grub_handler_class grub_term_output_class; - int grub_getkey (void) { @@ -72,10 +69,10 @@ static void usage (int status) { if (status) - fprintf (stderr, "Try ``grub-editenv --help'' for more information.\n"); + fprintf (stderr, "Try `%s --help' for more information.\n", program_name); else printf ("\ -Usage: grub-editenv [OPTIONS] [FILENAME] COMMAND\n\ +Usage: %s [OPTIONS] [FILENAME] COMMAND\n\ \n\ Tool to edit environment block.\n\ \nCommands:\n\ @@ -91,7 +88,7 @@ Tool to edit environment block.\n\ If not given explicitly, FILENAME defaults to %s.\n\ \n\ Report bugs to <%s>.\n", -DEFAULT_DIRECTORY "/" GRUB_ENVBLK_DEFCFG, PACKAGE_BUGREPORT); +program_name, DEFAULT_DIRECTORY "/" GRUB_ENVBLK_DEFCFG, PACKAGE_BUGREPORT); exit (status); } diff --git a/util/grub-emu.c b/util/grub-emu.c index 3f2acaaec..21fc6fa09 100644 --- a/util/grub-emu.c +++ b/util/grub-emu.c @@ -129,10 +129,10 @@ usage (int status) { if (status) fprintf (stderr, - "Try ``grub-emu --help'' for more information.\n"); + "Try `%s --help' for more information.\n", program_name); else printf ( - "Usage: grub-emu [OPTION]...\n" + "Usage: %s [OPTION]...\n" "\n" "GRUB emulator.\n" "\n" @@ -144,7 +144,7 @@ usage (int status) " -h, --help display this message and exit\n" " -V, --version print version information and exit\n" "\n" - "Report bugs to <%s>.\n", DEFAULT_DEVICE_MAP, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT); + "Report bugs to <%s>.\n", program_name, DEFAULT_DEVICE_MAP, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT); return status; } @@ -220,14 +220,14 @@ main (int argc, char *argv[]) { char *device_name = grub_guess_root_device (dir); if (! device_name) - grub_util_error ("cannot find a device for %s.\n", dir); + grub_util_error ("cannot find a device for %s", dir); root_dev = grub_util_get_grub_dev (device_name); 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_error ("cannot guess the root device. Specify the option `--root-device'"); } } diff --git a/util/grub-fstest.c b/util/grub-fstest.c index 586dda0f9..4470cbfa5 100644 --- a/util/grub-fstest.c +++ b/util/grub-fstest.c @@ -71,7 +71,7 @@ execute_command (char *name, int n, char **args) cmd = grub_command_find (name); if (! cmd) - grub_util_error ("Can\'t find command %s", name); + grub_util_error ("can\'t find command %s", name); return (cmd->func) (cmd, n, args); } @@ -100,9 +100,9 @@ read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len)) dev = grub_device_open (0); if ((! dev) || (! dev->disk)) - grub_util_error ("Can\'t open device."); + grub_util_error ("can\'t open device"); - grub_util_info ("total sectors : %lld.", + grub_util_info ("total sectors : %lld", (unsigned long long) dev->disk->total_sectors); if (! leng) @@ -115,7 +115,7 @@ read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len)) len = (leng > BUF_SIZE) ? BUF_SIZE : leng; if (grub_disk_read (dev->disk, 0, skip, len, buf)) - grub_util_error ("Disk read fails at offset %lld, length %d.", + grub_util_error ("disk read fails at offset %lld, length %d", skip, len); if (hook (skip, buf, len)) @@ -132,15 +132,15 @@ read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len)) file = grub_file_open (pathname); if (!file) { - grub_util_error ("cannot open file %s.", pathname); + grub_util_error ("cannot open file %s", pathname); return; } - grub_util_info ("file size : %lld.", (unsigned long long) file->size); + grub_util_info ("file size : %lld", (unsigned long long) file->size); if (skip > file->size) { - grub_util_error ("invalid skip value %lld.", (unsigned long long) skip); + grub_util_error ("invalid skip value %lld", (unsigned long long) skip); return; } @@ -158,7 +158,7 @@ read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len)) sz = grub_file_read (file, buf, (len > BUF_SIZE) ? BUF_SIZE : len); if (sz < 0) { - grub_util_error ("read error at offset %llu.", ofs); + grub_util_error ("read error at offset %llu", ofs); break; } @@ -184,7 +184,7 @@ cmd_cp (char *src, char *dest) if ((int) fwrite (buf, 1, len, ff) != len) { - grub_util_error ("write error."); + grub_util_error ("write error"); return 1; } @@ -194,7 +194,7 @@ cmd_cp (char *src, char *dest) ff = fopen (dest, "wb"); if (ff == NULL) { - grub_util_error ("open error."); + grub_util_error ("open error"); return; } read_file (src, cp_hook); @@ -212,7 +212,7 @@ cmd_cmp (char *src, char *dest) { if ((int) fread (buf_1, 1, len, ff) != len) { - grub_util_error ("read error at offset %llu.", ofs); + grub_util_error ("read error at offset %llu", ofs); return 1; } @@ -223,7 +223,7 @@ cmd_cmp (char *src, char *dest) for (i = 0; i < len; i++, ofs++) if (buf_1[i] != buf[i]) { - grub_util_error ("compare fail at offset %llu.", ofs); + grub_util_error ("compare fail at offset %llu", ofs); return 1; } } @@ -233,12 +233,12 @@ cmd_cmp (char *src, char *dest) ff = fopen (dest, "rb"); if (ff == NULL) { - grub_util_error ("open error."); + grub_util_error ("open error"); return; } if ((skip) && (fseeko (ff, skip, SEEK_SET))) - grub_util_error ("seek error."); + grub_util_error ("seek error"); read_file (src, cmp_hook); fclose (ff); @@ -286,13 +286,13 @@ fstest (char **images, int num_disks, int cmd, int n, char **args) for (i = 0; i < num_disks; i++) { if (grub_strlen (images[i]) + 7 > sizeof (host_file)) - grub_util_error ("Pathname %s too long.", images[i]); + grub_util_error ("pathname %s too long", images[i]); grub_sprintf (loop_name, "loop%d", i); grub_sprintf (host_file, "(host)%s", images[i]); if (execute_command ("loopback", 3, argv)) - grub_util_error ("loopback command fails."); + grub_util_error ("loopback command fails"); } grub_lvm_fini (); @@ -349,7 +349,7 @@ static void usage (int status) { if (status) - fprintf (stderr, "Try ``%s --help'' for more information.\n", program_name); + fprintf (stderr, "Try `%s --help' for more information.\n", program_name); else printf ("\ Usage: %s [OPTION]... IMAGE_PATH COMMANDS\n\ diff --git a/util/grub-install.in b/util/grub-install.in index 1fcfb1aca..4d814b085 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -40,6 +40,7 @@ else fi 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= @@ -87,9 +88,11 @@ fi INSTALL_DEVICE can be a GRUB device name or a system device filename. -grub-install copies GRUB images into the DIR/boot directory specified by ---root-directory, and uses grub-setup to install grub into the boot -sector. +grub-install copies GRUB images into /boot/grub (or /grub on NetBSD and +OpenBSD), and uses grub-setup to install grub into the boot sector. + +If the --root-directory option is used, then grub-install will copy +images into the operating system installation rooted at that directory. Report bugs to . EOF @@ -261,6 +264,10 @@ done # Write device to a variable so we don't have to traverse /dev every time. grub_device=`$grub_probe --target=device ${grubdir}` +if ! test -f ${grubdir}/grubenv; then + $grub_editenv ${grubdir}/grubenv create +fi + # Create the core image. First, auto-detect the filesystem module. fs_module=`$grub_probe --target=fs --device ${grub_device}` if test "x$fs_module" = x -a "x$modules" = x; then diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in index bd4b3e2c8..fc24c7b70 100644 --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in @@ -94,6 +94,15 @@ convert_system_path_to_grub_path () echo ${drive}${relative_path} } +save_default_entry () +{ + if [ "x${GRUB_DEFAULT}" = "xsaved" ] ; then + cat << EOF +savedefault +EOF + fi +} + prepare_grub_to_access_device () { device=$1 diff --git a/util/grub-mkdevicemap.c b/util/grub-mkdevicemap.c index b4febbb8d..c68482af1 100644 --- a/util/grub-mkdevicemap.c +++ b/util/grub-mkdevicemap.c @@ -84,7 +84,7 @@ usage (int status) { if (status) fprintf (stderr, - "Try ``%s --help'' for more information.\n", program_name); + "Try `%s --help' for more information.\n", program_name); else printf ("\ Usage: %s [OPTION]...\n\ diff --git a/util/grub-mkfont.c b/util/grub-mkfont.c index 3d1c6faac..fcd35afd4 100644 --- a/util/grub-mkfont.c +++ b/util/grub-mkfont.c @@ -96,7 +96,7 @@ static void usage (int status) { if (status) - fprintf (stderr, "Try ``%s --help'' for more information.\n", program_name); + fprintf (stderr, "Try `%s --help' for more information.\n", program_name); else printf ("\ Usage: %s [OPTIONS] FONT_FILES\n\ @@ -347,7 +347,7 @@ write_font (struct grub_font_info *font_info, char *output_file) file = fopen (output_file, "wb"); if (! file) - grub_util_error ("Can\'t write to file %s.", output_file); + grub_util_error ("can\'t write to file %s.", output_file); offset = 0; @@ -546,7 +546,7 @@ main (int argc, char *argv[]) a = strtoul (p, &p, 0); if (*p != '-') - grub_util_error ("Invalid font range"); + grub_util_error ("invalid font range"); b = strtoul (p + 1, &p, 0); if ((font_info.num_range & (GRUB_FONT_RANGE_BLOCK - 1)) == 0) font_info.ranges = xrealloc (font_info.ranges, @@ -561,7 +561,7 @@ main (int argc, char *argv[]) if (*p) { if (*p != ',') - grub_util_error ("Invalid font range"); + grub_util_error ("invalid font range"); else p++; } @@ -598,7 +598,7 @@ main (int argc, char *argv[]) } if (! output_file) - grub_util_error ("No output file is specified."); + grub_util_error ("no output file is specified"); if (FT_Init_FreeType (&ft_lib)) grub_util_error ("FT_Init_FreeType fails"); @@ -610,7 +610,7 @@ main (int argc, char *argv[]) if (FT_New_Face (ft_lib, argv[optind], font_index, &ft_face)) { - grub_util_info ("Can't open file %s, index %d\n", argv[optind], + grub_util_info ("can't open file %s, index %d", argv[optind], font_index); continue; } diff --git a/util/grub-mkpasswd-pbkdf2.c b/util/grub-mkpasswd-pbkdf2.c index 2f7c5efaa..82437fdca 100644 --- a/util/grub-mkpasswd-pbkdf2.c +++ b/util/grub-mkpasswd-pbkdf2.c @@ -74,16 +74,16 @@ static void usage (int status) { if (status) - fprintf (stderr, "Try ``grub-scrypt --help'' for more information.\n"); + fprintf (stderr, "Try `%s --help' for more information.\n", program_name); else printf ("\ -Usage: grub-scrypt [OPTIONS]\n\ +Usage: %s [OPTIONS]\n\ \nOptions:\n\ -c number, --iteration-count=number Number of PBKDF2 iterations\n\ -l number, --buflen=number Length of generated hash\n\ -s number, --salt=number Length of salt\n\ \n\ -Report bugs to <%s>.\n", PACKAGE_BUGREPORT); +Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT); exit (status); } @@ -123,9 +123,8 @@ main (int argc, char *argv[]) int tty_changed; set_program_name (argv[0]); - setlocale (LC_ALL, ""); - bindtextdomain (PACKAGE, LOCALEDIR); - textdomain (PACKAGE); + + grub_util_init_nls (); /* Check for options. */ while (1) @@ -166,12 +165,12 @@ main (int argc, char *argv[]) bufhex = malloc (buflen * 2 + 1); if (!bufhex) - grub_util_error ("Out of memory"); + grub_util_error ("out of memory"); buf = malloc (buflen); if (!buf) { free (bufhex); - grub_util_error ("Out of memory"); + grub_util_error ("out of memory"); } salt = malloc (saltlen); @@ -179,7 +178,7 @@ main (int argc, char *argv[]) { free (bufhex); free (buf); - grub_util_error ("Out of memory"); + grub_util_error ("out of memory"); } salthex = malloc (saltlen * 2 + 1); if (!salthex) @@ -187,7 +186,7 @@ main (int argc, char *argv[]) free (salt); free (bufhex); free (buf); - grub_util_error ("Out of memory"); + grub_util_error ("out of memory"); } /* Disable echoing. Based on glibc. */ @@ -226,7 +225,7 @@ main (int argc, char *argv[]) /* Restore the original setting. */ if (tty_changed) (void) tcsetattr (fileno (in), TCSAFLUSH, &s); - grub_util_error ("Failure to read password"); + grub_util_error ("failure to read password"); } if (nr >= 1 && pass1[nr-1] == '\n') pass1[nr-1] = 0; @@ -250,7 +249,7 @@ main (int argc, char *argv[]) free (bufhex); free (salthex); free (salt); - grub_util_error ("Failure to read password"); + grub_util_error ("failure to read password"); } if (nr >= 1 && pass2[nr-1] == '\n') pass2[nr-1] = 0; @@ -265,7 +264,7 @@ main (int argc, char *argv[]) free (bufhex); free (salthex); free (salt); - grub_util_error ("Passwords don't match"); + grub_util_error ("passwords don't match"); } memset (pass2, 0, strlen (pass2)); free (pass2); @@ -287,7 +286,7 @@ main (int argc, char *argv[]) free (salthex); free (salt); fclose (f); - grub_util_error ("Couldn't retrieve random data for salt"); + grub_util_error ("couldn't retrieve random data for salt"); } rd = fread (salt, 1, saltlen, f); if (rd != saltlen) @@ -300,7 +299,7 @@ main (int argc, char *argv[]) free (salthex); free (salt); fclose (f); - grub_util_error ("Couldn't retrieve random data for salt"); + grub_util_error ("couldn't retrieve random data for salt"); } fclose (f); } @@ -322,7 +321,7 @@ main (int argc, char *argv[]) memset (salthex, 0, 2 * saltlen); free (salt); free (salthex); - grub_util_error ("Cryptographic error number %d", gcry_err); + grub_util_error ("cryptographic error number %d", gcry_err); } hexify (bufhex, buf, buflen); diff --git a/util/grub-mkrelpath.c b/util/grub-mkrelpath.c index 62e400814..327f0c866 100644 --- a/util/grub-mkrelpath.c +++ b/util/grub-mkrelpath.c @@ -34,7 +34,7 @@ static void usage (int status) { if (status) - fprintf (stderr, "Try ``%s --help'' for more information.\n", program_name); + fprintf (stderr, "Try `%s --help' for more information.\n", program_name); else printf ("\ Usage: %s [OPTIONS] PATH\n\ diff --git a/util/grub-pe2elf.c b/util/grub-pe2elf.c index fb370d9ec..488ad9b23 100644 --- a/util/grub-pe2elf.c +++ b/util/grub-pe2elf.c @@ -40,7 +40,7 @@ static void usage (int status) { if (status) - fprintf (stderr, "Try ``%s --help'' for more information.\n", program_name); + fprintf (stderr, "Try `%s --help' for more information.\n", program_name); else printf ("\ Usage: %s [OPTIONS] input [output]\n\ @@ -182,7 +182,7 @@ write_section_data (FILE* fp, char *image, char name[5 + strlen (pe_shdr->name)]; if (num_sections >= MAX_SECTIONS) - grub_util_error ("Too many sections"); + grub_util_error ("too many sections"); sprintf (name, ".rel%s", pe_shdr->name); @@ -230,14 +230,14 @@ write_reloc_section (FILE* fp, char *image, if ((pe_rel->symtab_index >= pe_chdr->num_symbols) || (symtab_map[pe_rel->symtab_index] == -1)) - grub_util_error ("Invalid symbol"); + grub_util_error ("invalid symbol"); if (pe_rel->type == GRUB_PE32_REL_I386_DIR32) type = R_386_32; else if (pe_rel->type == GRUB_PE32_REL_I386_REL32) type = R_386_PC32; else - grub_util_error ("Unknown pe relocation type %d\n", pe_rel->type); + grub_util_error ("unknown pe relocation type %d\n", pe_rel->type); ofs = pe_rel->offset - pe_sec->virtual_address; addr = (grub_uint32_t *)(image + pe_sec->raw_data_offset + ofs); @@ -248,14 +248,14 @@ write_reloc_section (FILE* fp, char *image, code = image[pe_sec->raw_data_offset + ofs - 1]; if (((code != 0xe8) && (code != 0xe9)) || (*addr)) - grub_util_error ("Invalid relocation (%x %x)", code, *addr); + grub_util_error ("invalid relocation (%x %x)", code, *addr); modified = 1; if (symtab[symtab_map[pe_rel->symtab_index]].st_shndx) { if (symtab[symtab_map[pe_rel->symtab_index]].st_shndx != shdr[i].sh_info) - grub_util_error ("Cross section call is not allowed"); + grub_util_error ("cross section call is not allowed"); *addr = (symtab[symtab_map[pe_rel->symtab_index]].st_value - ofs - 4); @@ -440,7 +440,7 @@ convert_pe (FILE* fp, char *image) pe_chdr = (struct grub_pe32_coff_header *) image; if (grub_le_to_cpu16 (pe_chdr->machine) != GRUB_PE32_MACHINE_I386) - grub_util_error ("Invalid coff image"); + grub_util_error ("invalid coff image"); strtab = xmalloc (STRTAB_BLOCK); strtab_max = STRTAB_BLOCK; diff --git a/util/grub-probe.c b/util/grub-probe.c index 4ba8a98e5..879098542 100644 --- a/util/grub-probe.c +++ b/util/grub-probe.c @@ -84,7 +84,7 @@ probe_partmap (grub_disk_t disk) { if (disk->partition == NULL) { - grub_util_info ("No partition map found for %s", disk->name); + grub_util_info ("no partition map found for %s", disk->name); return; } @@ -113,17 +113,17 @@ probe (const char *path, char *device_name) { #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) if (! grub_util_check_char_device (device_name)) - grub_util_error ("%s is not a character device.\n", device_name); + grub_util_error ("%s is not a character device", device_name); #else if (! grub_util_check_block_device (device_name)) - grub_util_error ("%s is not a block device.\n", device_name); + grub_util_error ("%s is not a block device", device_name); #endif } else device_name = grub_guess_root_device (path); if (! device_name) - grub_util_error ("cannot find a device for %s (is /dev mounted?).\n", path); + grub_util_error ("cannot find a device for %s (is /dev mounted?)", path); if (print == PRINT_DEVICE) { @@ -133,7 +133,7 @@ probe (const char *path, char *device_name) drive_name = grub_util_get_grub_dev (device_name); if (! drive_name) - grub_util_error ("Cannot find a GRUB drive for %s. Check your device.map.\n", device_name); + grub_util_error ("cannot find a GRUB drive for %s. Check your device.map", device_name); if (print == PRINT_DRIVE) { @@ -309,7 +309,7 @@ usage (int status) { if (status) fprintf (stderr, - "Try ``%s --help'' for more information.\n", program_name); + "Try `%s --help' for more information.\n", program_name); else printf ("\ Usage: %s [OPTION]... [PATH|DEVICE]\n\ diff --git a/util/grub-reboot.in b/util/grub-reboot.in new file mode 100644 index 000000000..20f2b10bc --- /dev/null +++ b/util/grub-reboot.in @@ -0,0 +1,108 @@ +#! /bin/sh +# +# Set a default boot entry for GRUB, for the next boot only. +# Copyright (C) 2004,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 . + +# Initialize some variables. +transform="@program_transform_name@" + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +bindir=@bindir@ + +grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}` +rootdir= + +# Usage: usage +# Print the usage. +usage () { + cat <. +EOF +} + +# Check the arguments. +for option in "$@"; do + case "$option" in + -h | --help) + usage + exit 0 ;; + -v | --version) + echo "grub-reboot (GNU GRUB ${PACKAGE_VERSION})" + exit 0 ;; + --root-directory=*) + rootdir=`echo "$option" | sed 's/--root-directory=//'` ;; + -*) + echo "Unrecognized option \`$option'" 1>&2 + usage + exit 1 + ;; + *) + if test "x$entry" != x; then + echo "More than one entry?" 1>&2 + usage + exit 1 + fi + entry="${option}" ;; + esac +done + +if test "x$entry" = x; then + echo "entry not specified." 1>&2 + usage + 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 + +grubdir=${bootdir}/`echo grub | sed ${transform}` + +prev_saved_entry=`$grub_editenv ${grubdir}/grubenv list | sed -n 's/^saved_entry=//p'` +if [ "$prev_saved_entry" ]; then + $grub_editenv ${grubdir}/grubenv set prev_saved_entry="$prev_saved_entry" +else + # We need some non-empty value for prev_saved_entry so that GRUB will + # recognise that grub-reboot has been used and restore the previous + # saved entry. "0" is the same as an empty value, i.e. the first menu + # entry. + $grub_editenv ${grubdir}/grubenv set prev_saved_entry=0 +fi +$grub_editenv ${grubdir}/grubenv set saved_entry="$entry" + +# Bye. +exit 0 diff --git a/util/grub-script-check.c b/util/grub-script-check.c index 3136c6530..bfb44c511 100644 --- a/util/grub-script-check.c +++ b/util/grub-script-check.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -56,9 +57,6 @@ grub_refresh (void) fflush (stdout); } -struct grub_handler_class grub_term_input_class; -struct grub_handler_class grub_term_output_class; - char * grub_script_execute_argument_to_string (struct grub_script_arg *arg __attribute__ ((unused))) { @@ -173,9 +171,7 @@ main (int argc, char *argv[]) } set_program_name (argv[0]); - setlocale (LC_ALL, ""); - bindtextdomain (PACKAGE, LOCALEDIR); - textdomain (PACKAGE); + grub_util_init_nls (); /* Check for options. */ while (1) @@ -208,7 +204,7 @@ main (int argc, char *argv[]) /* Obtain ARGUMENT. */ if (optind >= argc) { - file = 0; // read from stdin + file = 0; /* read from stdin */ } else if (optind + 1 != argc) { diff --git a/util/grub-set-default.in b/util/grub-set-default.in new file mode 100644 index 000000000..4d7c10e8e --- /dev/null +++ b/util/grub-set-default.in @@ -0,0 +1,99 @@ +#! /bin/sh +# +# Set a default boot entry for GRUB. +# Copyright (C) 2004,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 . + +# Initialize some variables. +transform="@program_transform_name@" + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +bindir=@bindir@ + +grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}` +rootdir= + +# Usage: usage +# Print the usage. +usage () { + cat <. +EOF +} + +# Check the arguments. +for option in "$@"; do + case "$option" in + -h | --help) + usage + exit 0 ;; + -v | --version) + echo "grub-set-default (GNU GRUB ${PACKAGE_VERSION})" + exit 0 ;; + --root-directory=*) + rootdir=`echo "$option" | sed 's/--root-directory=//'` ;; + -*) + echo "Unrecognized option \`$option'" 1>&2 + usage + exit 1 + ;; + *) + if test "x$entry" != x; then + echo "More than one entry?" 1>&2 + usage + exit 1 + fi + entry="${option}" ;; + esac +done + +if test "x$entry" = x; then + echo "entry not specified." 1>&2 + usage + 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 + +grubdir=${bootdir}/`echo grub | sed ${transform}` + +$grub_editenv ${grubdir}/grubenv unset prev_saved_entry +$grub_editenv ${grubdir}/grubenv set saved_entry="$entry" + +# Bye. +exit 0 diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in index feeb69b70..0048ebed1 100644 --- a/util/grub.d/00_header.in +++ b/util/grub.d/00_header.in @@ -34,11 +34,29 @@ for i in ${GRUB_PRELOAD_MODULES} ; do done if [ "x${GRUB_DEFAULT}" = "x" ] ; then GRUB_DEFAULT=0 ; fi +if [ "x${GRUB_DEFAULT}" = "xsaved" ] ; then GRUB_DEFAULT='${saved_entry}' ; fi if [ "x${GRUB_TIMEOUT}" = "x" ] ; then GRUB_TIMEOUT=5 ; fi if [ "x${GRUB_GFXMODE}" = "x" ] ; then GRUB_GFXMODE=640x480 ; fi cat << EOF -set default=${GRUB_DEFAULT} +if [ -s \$prefix/grubenv ]; then + load_env +fi +set default="${GRUB_DEFAULT}" +if [ \${prev_saved_entry} ]; then + set saved_entry=\${prev_saved_entry} + save_env saved_entry + set prev_saved_entry= + save_env prev_saved_entry + set boot_once=true +fi + +function savedefault { + if [ -z \${boot_once} ]; then + saved_entry=\${chosen} + save_env saved_entry + fi +} EOF case ${GRUB_TERMINAL_INPUT}:${GRUB_TERMINAL_OUTPUT} in diff --git a/util/grub.d/10_hurd.in b/util/grub.d/10_hurd.in index 19fd8ec27..65a9a70b1 100644 --- a/util/grub.d/10_hurd.in +++ b/util/grub.d/10_hurd.in @@ -1,7 +1,7 @@ #! /bin/sh -e # grub-mkconfig helper script. -# Copyright (C) 2006,2007,2008,2009 Free Software Foundation, Inc. +# Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc. # # GRUB is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -73,16 +73,19 @@ menuentry "${OS}" { EOF prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/" cat << EOF - multiboot ${kernel} root=device:${GRUB_DEVICE#/dev/} + echo $(gettext "Loading GNU Mach ...") + multiboot ${kernel} root=device:${GRUB_DEVICE#/dev/} EOF +save_default_entry | sed -e "s/^/\t/" prepare_grub_to_access_device ${GRUB_DEVICE} | sed -e "s/^/\t/" cat << EOF - module /hurd/${hurd_fs}.static ${hurd_fs} --readonly \\ + echo $(gettext "Loading the Hurd ...") + module /hurd/${hurd_fs}.static ${hurd_fs} --readonly \\ --multiboot-command-line='\${kernel-command-line}' \\ --host-priv-port='\${host-port}' \\ --device-master-port='\${device-port}' \\ --exec-server-task='\${exec-task}' -T typed '\${root}' \\ '\$(task-create)' '\$(task-resume)' - module /lib/ld.so.1 exec /hurd/exec '\$(exec-task=task-create)' + module /lib/ld.so.1 exec /hurd/exec '\$(exec-task=task-create)' } EOF diff --git a/util/grub.d/10_kfreebsd.in b/util/grub.d/10_kfreebsd.in index 1329bba1f..b84b90a33 100644 --- a/util/grub.d/10_kfreebsd.in +++ b/util/grub.d/10_kfreebsd.in @@ -1,7 +1,7 @@ #! /bin/sh -e # grub-mkconfig helper script. -# Copyright (C) 2006,2007,2008,2009 Free Software Foundation, Inc. +# Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc. # # GRUB is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -39,17 +39,19 @@ kfreebsd_entry () args="$4" # not used yet title="$(gettext "%s, with kFreeBSD %s")" printf "menuentry \"${title}\" {\n" "${os}" "${version}" + save_default_entry | sed -e "s/^/\t/" if [ -z "${prepare_boot_cache}" ]; then prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")" fi printf '%s\n' "${prepare_boot_cache}" cat << EOF - kfreebsd ${rel_dirname}/${basename} + echo $(printf "$(gettext "Loading kernel of FreeBSD %s ...")" ${version}) + kfreebsd ${rel_dirname}/${basename} EOF if test -n "${devices}" ; then cat << EOF - kfreebsd_loadenv ${devices_rel_dirname}/${devices_basename} + kfreebsd_loadenv ${devices_rel_dirname}/${devices_basename} EOF fi diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in index 5fea5338e..3ecf454e2 100644 --- a/util/grub.d/10_linux.in +++ b/util/grub.d/10_linux.in @@ -1,7 +1,7 @@ #! /bin/sh -e # grub-mkconfig helper script. -# Copyright (C) 2006,2007,2008,2009 Free Software Foundation, Inc. +# Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc. # # GRUB is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -59,15 +59,18 @@ linux_entry () title="$(gettext "%s, with Linux %s")" fi printf "menuentry \"${title}\" {\n" "${os}" "${version}" + save_default_entry | sed -e "s/^/\t/" if [ -z "${prepare_boot_cache}" ]; then prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")" fi printf '%s\n' "${prepare_boot_cache}" cat << EOF + echo $(printf "$(gettext "Loading Linux %s ...")" ${version}) linux ${rel_dirname}/${basename} root=${linux_root_device_thisversion} ro ${args} EOF if test -n "${initrd}" ; then cat << EOF + echo $(gettext "Loading initial ramdisk ...") initrd ${rel_dirname}/${initrd} EOF fi diff --git a/util/grub.d/10_windows.in b/util/grub.d/10_windows.in index 055258e29..35dd4a4cc 100644 --- a/util/grub.d/10_windows.in +++ b/util/grub.d/10_windows.in @@ -73,6 +73,7 @@ for dir in $dirlist ; do menuentry "$OS" { EOF + save_default_entry | sed -e 's,^,\t,' prepare_grub_to_access_device "$dev" | sed 's,^,\t,' cat << EOF diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in index 38c96f9f8..edef37e66 100644 --- a/util/grub.d/30_os-prober.in +++ b/util/grub.d/30_os-prober.in @@ -41,13 +41,14 @@ osx_entry() { cat << EOF menuentry "${LONGNAME} (${2}-bit) (on ${DEVICE})" { EOF + save_default_entry | sed -e "s/^/\t/" prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/" cat << EOF insmod ${GRUB_VIDEO_BACKEND} - do_resume=0 + set do_resume=0 if [ /var/vm/sleepimage -nt10 / ]; then if xnu_resume /var/vm/sleepimage; then - do_resume=1 + set do_resume=1 fi fi if [ \$do_resume == 0 ]; then @@ -105,6 +106,7 @@ for OS in ${OSPROBED} ; do cat << EOF menuentry "${LONGNAME} (on ${DEVICE})" { EOF + save_default_entry | sed -e "s/^/\t/" prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/" case ${LONGNAME} in @@ -146,6 +148,7 @@ EOF cat << EOF menuentry "${LLABEL} (on ${DEVICE})" { EOF + save_default_entry | sed -e "s/^/\t/" if [ -z "${prepare_boot_cache}" ]; then prepare_boot_cache="$(prepare_grub_to_access_device ${LBOOT} | sed -e "s/^/\t/")" fi @@ -172,6 +175,7 @@ EOF cat << EOF menuentry "${LONGNAME} (on ${DEVICE})" { EOF + save_default_entry | sed -e "s/^/\t/" prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/" grub_device="`${grub_probe} --device ${DEVICE} --target=drive`" mach_device="`echo "${grub_device}" | tr -d '()' | tr , s`" diff --git a/util/hostdisk.c b/util/hostdisk.c index c94f4237e..603445801 100644 --- a/util/hostdisk.c +++ b/util/hostdisk.c @@ -568,7 +568,7 @@ read_device_map (const char *dev_map) fp = fopen (dev_map, "r"); if (! fp) { - grub_util_info (_("Cannot open `%s'"), dev_map); + grub_util_info (_("cannot open `%s'"), dev_map); return; } @@ -639,7 +639,7 @@ read_device_map (const char *dev_map) 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); + grub_util_error ("cannot get the real path of `%s'", p); #else map[drive].device = xstrdup (p); #endif diff --git a/util/i386/efi/grub-install.in b/util/i386/efi/grub-install.in index e0e0f2717..caa7be7e4 100644 --- a/util/i386/efi/grub-install.in +++ b/util/i386/efi/grub-install.in @@ -35,6 +35,7 @@ pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${t 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= @@ -179,6 +180,10 @@ 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" = xfat; then :; else diff --git a/util/i386/efi/grub-mkimage.c b/util/i386/efi/grub-mkimage.c index 7f5141531..f8c0f152e 100644 --- a/util/i386/efi/grub-mkimage.c +++ b/util/i386/efi/grub-mkimage.c @@ -778,7 +778,7 @@ make_reloc_section (FILE *out, Elf_Addr current_address, Elf_Ehdr *e, if ((ELF_R_TYPE (info) == R_X86_64_32) || (ELF_R_TYPE (info) == R_X86_64_32S)) { - grub_util_error ("Can\'t add fixup entry for R_X86_64_32(S)"); + grub_util_error ("can\'t add fixup entry for R_X86_64_32(S)"); } else if (ELF_R_TYPE (info) == R_X86_64_64) { @@ -1029,10 +1029,10 @@ static void usage (int status) { if (status) - fprintf (stderr, "Try ``grub-mkimage --help'' for more information.\n"); + fprintf (stderr, "Try `%s --help' for more information.\n", program_name); else printf ("\ -Usage: grub-mkimage -o FILE [OPTION]... [MODULES]\n\ +Usage: %s -o FILE [OPTION]... [MODULES]\n\ \n\ Make a bootable image of GRUB.\n\ \n\ @@ -1044,7 +1044,7 @@ Make a bootable image of GRUB.\n\ -v, --verbose print verbose messages\n\ \n\ Report bugs to <%s>.\n\ -", GRUB_LIBDIR, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT); +", program_name, GRUB_LIBDIR, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT); exit (status); } diff --git a/util/i386/pc/grub-mkimage.c b/util/i386/pc/grub-mkimage.c index ebf1bc7ff..16b2c6619 100644 --- a/util/i386/pc/grub-mkimage.c +++ b/util/i386/pc/grub-mkimage.c @@ -289,7 +289,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], #ifdef GRUB_MACHINE_PCBIOS if (GRUB_KERNEL_MACHINE_LINK_ADDR + core_size > GRUB_MEMORY_MACHINE_UPPER) - grub_util_error (_("Core image is too big (%p > %p)\n"), + grub_util_error (_("core image is too big (%p > %p)"), GRUB_KERNEL_MACHINE_LINK_ADDR + core_size, GRUB_MEMORY_MACHINE_UPPER); #endif @@ -326,10 +326,10 @@ static void usage (int status) { if (status) - fprintf (stderr, _("Try ``%s --help'' for more information.\n"), program_name); + fprintf (stderr, _("Try `%s --help' for more information.\n"), program_name); else printf (_("\ -Usage: grub-mkimage [OPTION]... [MODULES]\n\ +Usage: %s [OPTION]... [MODULES]\n\ \n\ Make a bootable image of GRUB.\n\ \n\ @@ -343,7 +343,7 @@ Make a bootable image of GRUB.\n\ -v, --verbose print verbose messages\n\ \n\ Report bugs to <%s>.\n\ -"), GRUB_LIBDIR, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT); +"), program_name, GRUB_LIBDIR, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT); exit (status); } diff --git a/util/i386/pc/grub-setup.c b/util/i386/pc/grub-setup.c index 909a521eb..4e2517ef2 100644 --- a/util/i386/pc/grub-setup.c +++ b/util/i386/pc/grub-setup.c @@ -156,7 +156,7 @@ setup (const char *dir, sector, offset, length); if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("The first sector of the core file is not sector-aligned")); + grub_util_error (_("the first sector of the core file is not sector-aligned")); first_sector = sector; } @@ -170,7 +170,7 @@ setup (const char *dir, sector, offset, length, (unsigned) current_segment); if (offset != 0 || last_length != GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("Non-sector-aligned data is found in the core file")); + grub_util_error (_("non-sector-aligned data is found in the core file")); if (block != first_block && (grub_le_to_cpu64 (prev->start) @@ -184,7 +184,7 @@ setup (const char *dir, block--; if (block->len) - grub_util_error (_("The sectors of the core file are too fragmented")); + grub_util_error (_("the sectors of the core file are too fragmented")); } last_length = length; @@ -195,7 +195,7 @@ setup (const char *dir, boot_path = grub_util_get_path (dir, boot_file); boot_size = grub_util_get_image_size (boot_path); if (boot_size != GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("The size of `%s' is not %u"), + grub_util_error (_("the size of `%s' is not %u"), boot_path, GRUB_DISK_SECTOR_SIZE); boot_img = grub_util_read_image (boot_path); free (boot_path); @@ -212,9 +212,9 @@ setup (const char *dir, 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); + grub_util_error (_("the size of `%s' is too small"), core_path); else if (core_size > 0xFFFF * GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("The size of `%s' is too large"), core_path); + grub_util_error (_("the size of `%s' is too large"), core_path); core_img = grub_util_read_image (core_path); @@ -251,7 +251,7 @@ setup (const char *dir, 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"), + grub_util_error (_("unable to identify a filesystem in %s; safety check can't be performed"), dest_dev->disk->name); if (! fs->reserved_first_sector) @@ -304,7 +304,7 @@ setup (const char *dir, bsd_part = -1; } else - grub_util_error (_("No DOS-style partitions found")); + grub_util_error (_("no DOS-style partitions found")); } else dos_part = bsd_part = -1; @@ -413,14 +413,14 @@ setup (const char *dir, unable_to_embed: if (must_embed) - grub_util_error (_("Embedding is not possible, but this is required when " - "the root device is on a RAID array or LVM volume.")); + grub_util_error (_("embedding is not possible, but this is required when " + "the root device is on a RAID array or LVM volume")); grub_util_warn (_("Embedding is not possible. GRUB can only be installed in this " "setup by using blocklists. However, blocklists are UNRELIABLE and " "its use is discouraged.")); if (! force) - grub_util_error (_("If you really want blocklists, use --force.")); + grub_util_error (_("if you really want blocklists, use --force")); /* Make sure that GRUB reads the identical image as the OS. */ tmp_img = xmalloc (core_size); @@ -495,7 +495,7 @@ unable_to_embed: } if (i == MAX_TRIES) - grub_util_error (_("Cannot read `%s' correctly"), core_path_dev); + grub_util_error (_("cannot read `%s' correctly"), core_path_dev); /* Clean out the blocklists. */ block = first_block; @@ -508,7 +508,7 @@ unable_to_embed: block--; if ((char *) block <= core_img) - grub_util_error (_("No terminator in the core image")); + grub_util_error (_("no terminator in the core image")); } /* Now read the core image to determine where the sectors are. */ @@ -519,13 +519,13 @@ unable_to_embed: file->read_hook = save_first_sector; if (grub_file_read (file, tmp_img, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("Failed to read the first sector of the core image")); + grub_util_error (_("failed to read the first sector of the core image")); block = first_block; file->read_hook = save_blocklists; if (grub_file_read (file, tmp_img, core_size - GRUB_DISK_SECTOR_SIZE) != (grub_ssize_t) core_size - GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("Failed to read the rest sectors of the core image")); + grub_util_error (_("failed to read the rest sectors of the core image")); grub_file_close (file); @@ -544,7 +544,7 @@ unable_to_embed: grub_util_info ("opening the core image `%s'", core_path); fp = fopen (core_path, "r+b"); if (! fp) - grub_util_error (_("Cannot open `%s'"), core_path); + grub_util_error (_("cannot open `%s'"), core_path); grub_util_write_image (core_img, GRUB_DISK_SECTOR_SIZE * 2, fp); fclose (fp); @@ -584,13 +584,13 @@ static void usage (int status) { if (status) - fprintf (stderr, _("Try ``%s --help'' for more information.\n"), program_name); + fprintf (stderr, _("Try `%s --help' for more information.\n"), program_name); else printf (_("\ -Usage: grub-setup [OPTION]... DEVICE\n\ +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\ +DEVICE must be a GRUB device (e.g. `(hd0,1)').\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\ @@ -605,6 +605,7 @@ DEVICE must be a GRUB device (e.g. ``(hd0,1)'').\n\ \n\ Report bugs to <%s>.\n\ "), + program_name, DEFAULT_BOOT_FILE, DEFAULT_CORE_FILE, DEFAULT_DIRECTORY, DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT); @@ -751,7 +752,7 @@ main (int argc, char *argv[]) char *tmp = get_device_name (root_dev); if (! tmp) - grub_util_error (_("Invalid root device `%s'"), root_dev); + grub_util_error (_("invalid root device `%s'"), root_dev); tmp = xstrdup (tmp); free (root_dev); @@ -764,7 +765,7 @@ main (int argc, char *argv[]) { 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_error (_("cannot guess the root device. Specify the option `--root-device'")); } } diff --git a/util/ieee1275/grub-install.in b/util/ieee1275/grub-install.in index 710ed125b..9a26b0dca 100644 --- a/util/ieee1275/grub-install.in +++ b/util/ieee1275/grub-install.in @@ -37,6 +37,7 @@ pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${t grub_mkimage=${bindir}/`echo grub-mkelfimage | 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= @@ -163,6 +164,10 @@ 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 diff --git a/util/ieee1275/ofpath.c b/util/ieee1275/ofpath.c index e90488fc3..79a0e8be5 100644 --- a/util/ieee1275/ofpath.c +++ b/util/ieee1275/ofpath.c @@ -131,12 +131,12 @@ block_device_get_sysfs_path_and_link(const char *devicenode, snprintf(sysfs_path, sysfs_path_len, "/sys/block/%s", devicenode); if (!realpath (sysfs_path, rpath)) - grub_util_error ("Cannot get the real path of `%s'", sysfs_path); + grub_util_error ("cannot get the real path of `%s'", sysfs_path); strcat(rpath, "/device"); if (!realpath (rpath, sysfs_path)) - grub_util_error ("Cannot get the real path of `%s'", rpath); + grub_util_error ("cannot get the real path of `%s'", rpath); free (rpath); } @@ -247,12 +247,12 @@ vendor_is_ATA(const char *path) snprintf(buf, PATH_MAX, "%s/vendor", path); fd = open(buf, O_RDONLY); if (fd < 0) - grub_util_error ("Cannot open 'vendor' node of `%s'", path); + grub_util_error ("cannot open 'vendor' node of `%s'", path); memset(buf, 0, PATH_MAX); err = read(fd, buf, PATH_MAX); if (err < 0) - grub_util_error ("Cannot read 'vendor' node of `%s'", path); + grub_util_error ("cannot read 'vendor' node of `%s'", path); close(fd); @@ -288,7 +288,7 @@ check_sas (char *sysfs_path, int *tgt) fd = open(path, O_RDONLY); if (fd < 0) - grub_util_error("Cannot open SAS PHY ID '%s'\n", path); + grub_util_error("cannot open SAS PHY ID `%s'\n", path); memset (phy, 0, sizeof (phy)); read (fd, phy, sizeof (phy)); @@ -375,7 +375,7 @@ grub_util_devname_to_ofpath (char *devname) name_buf = xmalloc (PATH_MAX); name_buf = realpath (devname, name_buf); if (! name_buf) - grub_util_error ("Cannot get the real path of `%s'", devname); + grub_util_error ("cannot get the real path of `%s'", devname); device = get_basename (devname); devnode = strip_trailing_digits (devname); diff --git a/util/misc.c b/util/misc.c index d8aa041be..0b682c445 100644 --- a/util/misc.c +++ b/util/misc.c @@ -60,11 +60,12 @@ grub_util_warn (const char *fmt, ...) { va_list ap; - fprintf (stderr, "%s: warn: ", program_name); + fprintf (stderr, _("%s: warn:"), program_name); + fprintf (stderr, " "); va_start (ap, fmt); vfprintf (stderr, fmt, ap); va_end (ap); - fputc ('\n', stderr); + fprintf (stderr, ".\n"); fflush (stderr); } @@ -75,11 +76,12 @@ grub_util_info (const char *fmt, ...) { va_list ap; - fprintf (stderr, "%s: info: ", program_name); + fprintf (stderr, _("%s: info:"), program_name); + fprintf (stderr, " "); va_start (ap, fmt); vfprintf (stderr, fmt, ap); va_end (ap); - fputc ('\n', stderr); + fprintf (stderr, ".\n"); fflush (stderr); } } @@ -89,11 +91,12 @@ grub_util_error (const char *fmt, ...) { va_list ap; - fprintf (stderr, "%s: error: ", program_name); + fprintf (stderr, _("%s: error:"), program_name); + fprintf (stderr, " "); va_start (ap, fmt); vfprintf (stderr, fmt, ap); va_end (ap); - fputc ('\n', stderr); + fprintf (stderr, ".\n"); exit (1); } @@ -479,6 +482,19 @@ fail: #endif /* __MINGW32__ */ +char * +canonicalize_file_name (const char *path) +{ + char *ret; +#ifdef PATH_MAX + ret = xmalloc (PATH_MAX); + (void) realpath (path, ret); +#else + ret = realpath (path, NULL); +#endif + return ret; +} + /* This function never prints trailing slashes (so that its output can be appended a slash unconditionally). */ char * @@ -491,15 +507,11 @@ make_system_path_relative_to_its_root (const char *path) size_t len; /* canonicalize. */ - p = realpath (path, NULL); + p = canonicalize_file_name (path); if (p == NULL) - { - if (errno != EINVAL) - grub_util_error ("failed to get realpath of %s", path); - else - grub_util_error ("realpath not supporting (path, NULL)"); - } + grub_util_error ("failed to get canonical path of %s", path); + len = strlen (p) + 1; buf = strdup (p); free (p); diff --git a/util/mkisofs/eltorito.c b/util/mkisofs/eltorito.c index a134dfc48..1d2a715e0 100644 --- a/util/mkisofs/eltorito.c +++ b/util/mkisofs/eltorito.c @@ -288,7 +288,7 @@ void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc) struct eltorito_boot_info bi_table; bootimage = fopen (de->whole_name, "r+b"); if (bootimage == NULL) - error (1, errno, _("Error opening boot image file '%s' for update"), + error (1, errno, _("Error opening boot image file `%s' for update"), de->whole_name); /* Compute checksum of boot image, sans 64 bytes */ total_len = 0; @@ -296,7 +296,7 @@ void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc) while ((len = fread (csum_buffer, 1, SECTOR_SIZE, bootimage)) > 0) { if (total_len & 3) - error (1, 0, _("Odd alignment at non-end-of-file in boot image '%s'"), + error (1, 0, _("Odd alignment at non-end-of-file in boot image `%s'"), de->whole_name); if (total_len < 64) memset (csum_buffer, 0, 64 - total_len); @@ -308,7 +308,7 @@ void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc) } if (total_len != de->size) - error (1, 0, _("Boot image file '%s' changed unexpectedly"), + error (1, 0, _("Boot image file `%s' changed unexpectedly"), de->whole_name); /* End of file, set position to byte 8 */ fseeko (bootimage, (off_t) 8, SEEK_SET); diff --git a/util/mkisofs/rock.c b/util/mkisofs/rock.c index a4cc27fa9..a7a39f774 100644 --- a/util/mkisofs/rock.c +++ b/util/mkisofs/rock.c @@ -5,7 +5,7 @@ Copyright 1993 Yggdrasil Computing, Incorporated - Copyright (C) 2009 Free Software Foundation, Inc. + Copyright (C) 2009,2010 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -306,7 +306,7 @@ int deep_opt; * the symbolic link won't fit into one SL System Use Field * print an error message and continue with splited one */ - fprintf(stderr, _("symbolic link ``%s'' to long for one SL System Use Field, splitting"), cpnt); + fprintf (stderr, _("symbolic link `%s' too long for one SL System Use Field, splitting"), cpnt); } if(MAYBE_ADD_CE_ENTRY(SL_SIZE + sl_bytes)) add_CE_entry(); } diff --git a/util/mkisofs/write.c b/util/mkisofs/write.c index 5447229c8..e1cdd213e 100644 --- a/util/mkisofs/write.c +++ b/util/mkisofs/write.c @@ -158,7 +158,7 @@ void FDECL4(xfwrite, void *, buffer, uint64_t, count, uint64_t, size, FILE *, fi sprintf(nbuf, "%s_%02d", outfile, idx++); file = freopen(nbuf, "wb", file); if (file == NULL) - error (1, errno, _("Cannot open '%s'"), nbuf); + error (1, errno, _("Cannot open `%s'"), nbuf); } while(count) diff --git a/util/raid.c b/util/raid.c index 83a0ee6e2..ec3ecd26e 100644 --- a/util/raid.c +++ b/util/raid.c @@ -50,7 +50,7 @@ grub_util_getdiskname (int major, int minor) 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); + grub_util_error ("unknown device number: %d, %d", major, minor); return name; } @@ -72,7 +72,7 @@ grub_util_raid_getmembers (char *name) fd = open (devname, O_RDONLY); if (fd == -1) - grub_util_error ("Can't open %s: %s", devname, strerror (errno)); + grub_util_error ("can't open %s: %s", devname, strerror (errno)); free (devname); @@ -81,7 +81,7 @@ grub_util_raid_getmembers (char *name) grub_util_error ("ioctl RAID_VERSION error: %s", strerror (errno)); if (version.major != 0 || version.minor != 90) - grub_util_error ("Unsupported RAID version: %d.%d", + grub_util_error ("unsupported RAID version: %d.%d", version.major, version.minor); ret = ioctl (fd, GET_ARRAY_INFO, &info); diff --git a/util/sparc64/ieee1275/grub-mkimage.c b/util/sparc64/ieee1275/grub-mkimage.c index 96ddfe3d7..6907b8d8a 100644 --- a/util/sparc64/ieee1275/grub-mkimage.c +++ b/util/sparc64/ieee1275/grub-mkimage.c @@ -191,7 +191,7 @@ static void usage (int status) { if (status) - fprintf (stderr, "Try ``%s --help'' for more information.\n", program_name); + fprintf (stderr, "Try `%s --help' for more information.\n", program_name); else printf ("\ Usage: %s [OPTION]... [MODULES]\n\ diff --git a/util/sparc64/ieee1275/grub-setup.c b/util/sparc64/ieee1275/grub-setup.c index 9d8e67562..c39ea853f 100644 --- a/util/sparc64/ieee1275/grub-setup.c +++ b/util/sparc64/ieee1275/grub-setup.c @@ -161,7 +161,7 @@ setup (const char *prefix, const char *dir, 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 " + grub_util_error ("the first sector of the core file " "is not sector-aligned"); first_sector = sector; @@ -176,7 +176,7 @@ setup (const char *prefix, const char *dir, 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"); + grub_util_error ("non-sector-aligned data is found in the core file"); if (block != first_block && (grub_be_to_cpu64 (prev->start) @@ -189,7 +189,7 @@ setup (const char *prefix, const char *dir, block--; if (block->len) - grub_util_error ("The sectors of the core file are too fragmented"); + grub_util_error ("the sectors of the core file are too fragmented"); } last_length = length; @@ -201,7 +201,7 @@ setup (const char *prefix, const char *dir, 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", + 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); @@ -219,7 +219,7 @@ setup (const char *prefix, const char *dir, 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); + grub_util_error ("the size of `%s' is too small", core_path); core_img = grub_util_read_image (core_path); free (core_path); @@ -229,7 +229,7 @@ setup (const char *prefix, const char *dir, + GRUB_DISK_SECTOR_SIZE - sizeof (*block)); - grub_util_info ("root is '%s', dest is '%s', and dest_ofpath is '%s'", + grub_util_info ("root is `%s', dest is `%s', and dest_ofpath is `%s'", root, dest, dest_ofpath); /* Open the root device and the destination device. */ @@ -320,7 +320,7 @@ setup (const char *prefix, const char *dir, } if (i == MAX_TRIES) - grub_util_error ("Cannot read `%s' correctly", core_path); + grub_util_error ("cannot read `%s' correctly", core_path); /* Clean out the blocklists. */ block = first_block; @@ -332,7 +332,7 @@ setup (const char *prefix, const char *dir, block--; if ((char *) block <= core_img) - grub_util_error ("No terminator in the core image"); + grub_util_error ("no terminator in the core image"); } /* Now read the core image to determine where the sectors are. */ @@ -343,13 +343,13 @@ setup (const char *prefix, const char *dir, file->read_hook = save_first_sector; if (grub_file_read (file, tmp_img, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE) - grub_util_error ("Failed to read the first sector of the core image"); + grub_util_error ("failed to read the first sector of the core image"); block = first_block; file->read_hook = save_blocklists; if (grub_file_read (file, tmp_img, core_size - GRUB_DISK_SECTOR_SIZE) != (grub_ssize_t) core_size - GRUB_DISK_SECTOR_SIZE) - grub_util_error ("Failed to read the rest sectors of the core image"); + grub_util_error ("failed to read the rest sectors of the core image"); grub_file_close (file); @@ -368,7 +368,7 @@ setup (const char *prefix, const char *dir, grub_util_info ("opening the core image `%s'", core_path); fp = fopen (core_path, "r+b"); if (! fp) - grub_util_error ("Cannot open `%s'", core_path); + grub_util_error ("cannot open `%s'", core_path); grub_util_write_image (core_img, GRUB_DISK_SECTOR_SIZE, fp); fclose (fp); @@ -404,13 +404,13 @@ static void usage (int status) { if (status) - fprintf (stderr, "Try ``%s --help'' for more information.\n", program_name); + 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\ +DEVICE must be a GRUB device (e.g. `(hd0,1)').\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\ @@ -559,14 +559,14 @@ find_dest_dev (struct grub_setup_info *gp, char *argv[]) fprintf (stderr, "Invalid device `%s'.\n", argv[optind]); usage (1); } - grub_util_info ("transformed OS device '%s' into GRUB device '%s'", + 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); + grub_util_info ("Using `%s' as GRUB device", gp->dest_dev); } } @@ -578,7 +578,7 @@ check_root_dev (struct grub_setup_info *gp) char *tmp = get_device_name (gp->root_dev); if (! tmp) - grub_util_error ("Invalid root device `%s'", gp->root_dev); + grub_util_error ("invalid root device `%s'", gp->root_dev); tmp = xstrdup (tmp); free (gp->root_dev); @@ -594,11 +594,11 @@ check_root_dev (struct grub_setup_info *gp) { 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_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); + grub_util_info ("guessed root device `%s' and root_dev `%s' from " + "dir `%s'", root_device, gp->root_dev, dir); } } diff --git a/video/efi_gop.c b/video/efi_gop.c index 30863c1ed..86a2881f8 100644 --- a/video/efi_gop.c +++ b/video/efi_gop.c @@ -185,7 +185,7 @@ grub_video_gop_fill_mode_info (struct grub_efi_gop_mode_info *in, static grub_err_t grub_video_gop_setup (unsigned int width, unsigned int height, - unsigned int mode_type) + unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused))) { unsigned int depth; struct grub_efi_gop_mode_info *info = NULL; @@ -353,6 +353,7 @@ grub_video_gop_get_info_and_fini (struct grub_video_mode_info *mode_info, static struct grub_video_adapter grub_video_gop_adapter = { .name = "EFI GOP driver", + .id = GRUB_VIDEO_DRIVER_EFI_GOP, .init = grub_video_gop_init, .fini = grub_video_gop_fini, diff --git a/video/efi_uga.c b/video/efi_uga.c index 12ca35cde..e86837b06 100644 --- a/video/efi_uga.c +++ b/video/efi_uga.c @@ -198,7 +198,7 @@ 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_type, unsigned int mode_mask __attribute__ ((unused))) { unsigned int depth; int found = 0; @@ -300,6 +300,7 @@ grub_video_uga_get_info_and_fini (struct grub_video_mode_info *mode_info, static struct grub_video_adapter grub_video_uga_adapter = { .name = "EFI UGA driver", + .id = GRUB_VIDEO_DRIVER_EFI_UGA, .init = grub_video_uga_init, .fini = grub_video_uga_fini, diff --git a/video/i386/pc/vbe.c b/video/i386/pc/vbe.c index 17d9b3282..34745b474 100644 --- a/video/i386/pc/vbe.c +++ b/video/i386/pc/vbe.c @@ -369,7 +369,7 @@ grub_video_vbe_fini (void) static grub_err_t grub_video_vbe_setup (unsigned int width, unsigned int height, - unsigned int mode_type) + unsigned int mode_type, unsigned int mode_mask) { grub_uint16_t *p; struct grub_vbe_mode_info_block vbe_mode_info; @@ -415,32 +415,40 @@ grub_video_vbe_setup (unsigned int width, unsigned int height, /* Not compatible memory model. */ continue; - if ((vbe_mode_info.x_resolution != width) - || (vbe_mode_info.y_resolution != height)) + if (((vbe_mode_info.x_resolution != width) + || (vbe_mode_info.y_resolution != height)) && width != 0 && height != 0) /* Non matching resolution. */ continue; /* Check if user requested RGB or index color mode. */ - if ((mode_type & GRUB_VIDEO_MODE_TYPE_COLOR_MASK) != 0) + if ((mode_mask & GRUB_VIDEO_MODE_TYPE_COLOR_MASK) != 0) { - if (((mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0) - && (vbe_mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL)) - /* Requested only index color modes. */ - continue; + unsigned my_mode_type = 0; - if (((mode_type & GRUB_VIDEO_MODE_TYPE_RGB) != 0) - && (vbe_mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR)) - /* Requested only RGB modes. */ - continue; + if (vbe_mode_info.memory_model == GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL) + my_mode_type |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; + + if (vbe_mode_info.memory_model == GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR) + my_mode_type |= GRUB_VIDEO_MODE_TYPE_RGB; + + if ((my_mode_type & mode_mask + & (GRUB_VIDEO_MODE_TYPE_RGB | GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)) + != (mode_type & mode_mask + & (GRUB_VIDEO_MODE_TYPE_RGB + | GRUB_VIDEO_MODE_TYPE_INDEX_COLOR))) + continue; } /* If there is a request for specific depth, ignore others. */ if ((depth != 0) && (vbe_mode_info.bits_per_pixel != depth)) continue; - /* Select mode with most number of bits per pixel. */ + /* Select mode with most of "volume" (size of framebuffer in bits). */ if (best_vbe_mode != 0) - if (vbe_mode_info.bits_per_pixel < best_vbe_mode_info.bits_per_pixel) + if ((grub_uint64_t) vbe_mode_info.bits_per_pixel + * vbe_mode_info.x_resolution * vbe_mode_info.y_resolution + < (grub_uint64_t) best_vbe_mode_info.bits_per_pixel + * best_vbe_mode_info.x_resolution * best_vbe_mode_info.y_resolution) continue; /* Save so far best mode information for later use. */ @@ -557,6 +565,7 @@ grub_video_vbe_get_info_and_fini (struct grub_video_mode_info *mode_info, static struct grub_video_adapter grub_video_vbe_adapter = { .name = "VESA BIOS Extension Video Driver", + .id = GRUB_VIDEO_DRIVER_VBE, .init = grub_video_vbe_init, .fini = grub_video_vbe_fini, diff --git a/video/video.c b/video/video.c index 682bebcbf..f6b1aad9e 100644 --- a/video/video.c +++ b/video/video.c @@ -93,6 +93,14 @@ grub_video_get_info (struct grub_video_mode_info *mode_info) return grub_video_adapter_active->get_info (mode_info); } +grub_video_driver_id_t +grub_video_get_driver_id (void) +{ + if (! grub_video_adapter_active) + return GRUB_VIDEO_DRIVER_NONE; + return grub_video_adapter_active->id; +} + /* Get information about active video mode. */ grub_err_t grub_video_get_info_and_fini (struct grub_video_mode_info *mode_info, @@ -399,21 +407,81 @@ grub_video_get_active_render_target (struct grub_video_render_target **target) return grub_video_adapter_active->get_active_render_target (target); } +/* Parse x[x]*/ +static grub_err_t +parse_modespec (const char *current_mode, int *width, int *height, int *depth) +{ + const char *value; + const char *param = current_mode; + + *width = *height = *depth = -1; + + if (grub_strcmp (param, "auto") == 0) + { + *width = *height = 0; + return GRUB_ERR_NONE; + } + + /* Find width value. */ + value = param; + param = grub_strchr(param, 'x'); + if (param == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "Invalid mode: %s\n", + current_mode); + + param++; + + *width = grub_strtoul (value, 0, 0); + if (grub_errno != GRUB_ERR_NONE) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "Invalid mode: %s\n", + current_mode); + + /* Find height value. */ + value = param; + param = grub_strchr(param, 'x'); + if (param == NULL) + { + *height = grub_strtoul (value, 0, 0); + if (grub_errno != GRUB_ERR_NONE) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "Invalid mode: %s\n", + current_mode); + } + else + { + /* We have optional color depth value. */ + param++; + + *height = grub_strtoul (value, 0, 0); + if (grub_errno != GRUB_ERR_NONE) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "Invalid mode: %s\n", + current_mode); + + /* Convert color depth value. */ + value = param; + *depth = grub_strtoul (value, 0, 0); + if (grub_errno != GRUB_ERR_NONE) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "Invalid mode: %s\n", + current_mode); + } + return GRUB_ERR_NONE; +} + grub_err_t grub_video_set_mode (const char *modestring, - int NESTED_FUNC_ATTR (*hook) (grub_video_adapter_t p, - struct grub_video_mode_info *mode_info)) + unsigned int modemask, + unsigned int modevalue) { char *tmp; char *next_mode; char *current_mode; - char *param; - char *value; char *modevar; - int width = -1; - int height = -1; - int depth = -1; - int flags = 0; + + modevalue &= modemask; /* Take copy of env.var. as we don't want to modify that. */ modevar = grub_strdup (modestring); @@ -429,26 +497,26 @@ grub_video_set_mode (const char *modestring, || grub_memcmp (next_mode, "keep,", sizeof ("keep,") - 1) == 0 || grub_memcmp (next_mode, "keep;", sizeof ("keep;") - 1) == 0) { - struct grub_video_mode_info mode_info; int suitable = 1; grub_err_t err; - grub_memset (&mode_info, 0, sizeof (mode_info)); - if (grub_video_adapter_active) { + struct grub_video_mode_info mode_info; + grub_memset (&mode_info, 0, sizeof (mode_info)); err = grub_video_get_info (&mode_info); if (err) { suitable = 0; grub_errno = GRUB_ERR_NONE; } + if ((mode_info.mode_type & modemask) != modevalue) + suitable = 0; } - else - mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_PURE_TEXT; + else if (((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modemask) != 0) + && ((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modevalue) == 0)) + suitable = 0; - if (suitable && hook) - suitable = hook (grub_video_adapter_active, &mode_info); if (suitable) { grub_free (modevar); @@ -482,15 +550,16 @@ grub_video_set_mode (const char *modestring, /* Loop until all modes has been tested out. */ while (next_mode != NULL) { + int width = -1; + int height = -1; + int depth = -1; + grub_err_t err; + unsigned int flags = modevalue; + unsigned int flagmask = modemask; + /* Use last next_mode as current mode. */ tmp = next_mode; - /* Reset video mode settings. */ - width = -1; - height = -1; - depth = -1; - flags = 0; - /* Save position of next mode and separate modes. */ for (; *next_mode; next_mode++) if (*next_mode == ',' || *next_mode == ';') @@ -509,19 +578,16 @@ grub_video_set_mode (const char *modestring, /* Initialize token holders. */ current_mode = tmp; - param = tmp; - value = NULL; /* XXX: we assume that we're in pure text mode if no video mode is initialized. Is it always true? */ - if (grub_strcmp (param, "text") == 0) + if (grub_strcmp (current_mode, "text") == 0) { struct grub_video_mode_info mode_info; grub_memset (&mode_info, 0, sizeof (mode_info)); - mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_PURE_TEXT; - - if (! hook || hook (0, &mode_info)) + if (((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modemask) == 0) + || ((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modevalue) != 0)) { /* Valid mode found from adapter, and it has been activated. Specify it as active adapter. */ @@ -534,121 +600,31 @@ grub_video_set_mode (const char *modestring, } } - /* Parse x[x]*/ - - /* Find width value. */ - value = param; - param = grub_strchr(param, 'x'); - if (param == NULL) + err = parse_modespec (current_mode, &width, &height, &depth); + if (err) { - grub_err_t rc; - - /* First setup error message. */ - rc = grub_error (GRUB_ERR_BAD_ARGUMENT, - "invalid mode: %s", - current_mode); - /* Free memory before returning. */ grub_free (modevar); - return rc; - } - - *param = 0; - param++; - - width = grub_strtoul (value, 0, 0); - if (grub_errno != GRUB_ERR_NONE) - { - grub_err_t rc; - - /* First setup error message. */ - rc = grub_error (GRUB_ERR_BAD_ARGUMENT, - "invalid mode: %s", - current_mode); - - /* Free memory before returning. */ - grub_free (modevar); - - return rc; - } - - /* Find height value. */ - value = param; - param = grub_strchr(param, 'x'); - if (param == NULL) - { - height = grub_strtoul (value, 0, 0); - if (grub_errno != GRUB_ERR_NONE) - { - grub_err_t rc; - - /* First setup error message. */ - rc = grub_error (GRUB_ERR_BAD_ARGUMENT, - "invalid mode: %s", - current_mode); - - /* Free memory before returning. */ - grub_free (modevar); - - return rc; - } - } - else - { - /* We have optional color depth value. */ - *param = 0; - param++; - - height = grub_strtoul (value, 0, 0); - if (grub_errno != GRUB_ERR_NONE) - { - grub_err_t rc; - - /* First setup error message. */ - rc = grub_error (GRUB_ERR_BAD_ARGUMENT, - "invalid mode: %s", - current_mode); - - /* Free memory before returning. */ - grub_free (modevar); - - return rc; - } - - /* Convert color depth value. */ - value = param; - depth = grub_strtoul (value, 0, 0); - if (grub_errno != GRUB_ERR_NONE) - { - grub_err_t rc; - - /* First setup error message. */ - rc = grub_error (GRUB_ERR_BAD_ARGUMENT, - "invalid mode: %s", - current_mode); - - /* Free memory before returning. */ - grub_free (modevar); - - return rc; - } + return err; } /* Try out video mode. */ - /* If we have 8 or less bits, then assume that it is indexed color mode. */ - if ((depth <= 8) && (depth != -1)) - flags |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; + /* If user requested specific depth check if this depth is supported. */ + if (depth != -1 && (flagmask & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK) + && + (((flags & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK) + != ((depth << GRUB_VIDEO_MODE_TYPE_DEPTH_POS) + & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK)))) + continue; - /* We have more than 8 bits, then assume that it is RGB color mode. */ - if (depth > 8) - flags |= GRUB_VIDEO_MODE_TYPE_RGB; - - /* If user requested specific depth, forward that information to driver. */ if (depth != -1) - flags |= (depth << GRUB_VIDEO_MODE_TYPE_DEPTH_POS) - & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK; + { + flags |= (depth << GRUB_VIDEO_MODE_TYPE_DEPTH_POS) + & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK; + flagmask |= GRUB_VIDEO_MODE_TYPE_DEPTH_MASK; + } /* Try to initialize requested mode. Ignore any errors. */ grub_video_adapter_t p; @@ -656,7 +632,6 @@ grub_video_set_mode (const char *modestring, /* Loop thru all possible video adapter trying to find requested mode. */ for (p = grub_video_adapter_list; p; p = p->next) { - grub_err_t err; struct grub_video_mode_info mode_info; grub_memset (&mode_info, 0, sizeof (mode_info)); @@ -670,7 +645,7 @@ grub_video_set_mode (const char *modestring, } /* Try to initialize video mode. */ - err = p->setup (width, height, flags); + err = p->setup (width, height, flags, flagmask); if (err != GRUB_ERR_NONE) { p->fini (); @@ -686,7 +661,15 @@ grub_video_set_mode (const char *modestring, continue; } - if (hook && ! hook (p, &mode_info)) + flags = mode_info.mode_type & ~GRUB_VIDEO_MODE_TYPE_DEPTH_MASK; + flags |= (mode_info.bpp << GRUB_VIDEO_MODE_TYPE_DEPTH_POS) + & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK; + + /* Check that mode is suitable for upper layer. */ + if ((flags & GRUB_VIDEO_MODE_TYPE_PURE_TEXT) + ? (((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modemask) != 0) + && ((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modevalue) == 0)) + : ((flags & modemask) != modevalue)) { p->fini (); grub_errno = GRUB_ERR_NONE;