diff --git a/.bzrignore b/.bzrignore index 46e8637b6..c124c9280 100644 --- a/.bzrignore +++ b/.bzrignore @@ -2,7 +2,10 @@ 10_* 30_os-prober 40_custom +41_custom aclocal.m4 +ascii.bitmaps +ascii.h autom4te.cache build_env.mk .bzrignore @@ -48,6 +51,8 @@ grub_script_check_init.c grub_script_check_init.h grub_script.tab.c grub_script.tab.h +grub_script.yy.c +grub_script.yy.h grub-set-default grub-setup grub_setup_init.c diff --git a/ChangeLog b/ChangeLog index 5072a6026..bccc55dea 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,966 @@ +2010-06-28 Vladimir Serbinenko + + Use normal parser for menu entries. + Reported by: Thomas Frauendorfer + + * include/grub/parser.h (grub_parser_execute): Don't export. + * normal/menu.c (grub_menu_execute_entry_real): New function. + (grub_menu_execute_entry): Use grub_menu_execute_entry_real. + +2010-06-28 Colin Watson + + * docs/grub.texi (Embedded configuration): New section (replacing + old "Preset Menu" stub). + (Images): New section. + (configfile): Note that any menu entries defined in `file' are shown + immediately. + +2010-06-28 Josh Triplett + + * mmap/i386/pc/mmap_helper.S: Set CF on return. + +2010-06-28 Colin Watson + + * util/grub-install.in: Add --debug-image= option. + +2010-06-28 Colin Watson + + Change grub-mkdevicemap to emit /dev/disk/by-id/ names where + possible on Linux. + + * util/deviceiter.c (check_device): Rename to ... + (check_device_readable_unique): ... this. Update all callers. + Maintain and check a list of which devices (by canonicalized name) + have already been seen. + (clear_seen_devices): New function. + (compare_file_names) [__linux__]: New function. + (grub_util_iterate_devices): Clear the list of seen devices on exit + and (just in case) on entry. + (grub_util_iterate_devices) [__linux__]: Iterate over non-partition + devices in /dev/disk/by-id/, in sorted order. Remove DM-RAID + seen-devices list, superseded by general code in check_device. + +2010-06-28 Colin Watson + + * commands/cat.c (options): New variable. + (grub_cmd_cat): Parse options. If the --dos option is given, print + DOS-style "\r\n" line endings as simple newlines (Debian bug + #586358). + (GRUB_MOD_INIT): Use extcmd. + (GRUB_MOD_FINI): Likewise. + * docs/grub.texi (cat): Document --dos. + +2010-06-28 Vladimir Serbinenko + + XEN with Linux grub-mkconfig support. + + * conf/common.rmk (grub-mkconfig_SCRIPTS) [linux]: Add 20_linux_xen. + * util/grub-mkconfig.in: Export GRUB_CMDLINE_XEN and + GRUB_CMDLINE_XEN_DEFAULT. + * util/grub.d/20_linux_xen.in: New file. + +2010-06-28 Vladimir Serbinenko + + Initialise VGA video on qemu ourselves. + + * boot/i386/qemu/boot.S: Don't call 0xc000. + * conf/i386-qemu.rmk (kern/i386/qemu/init.c_DEPENDENCIES): New variable. + (kernel_img_SOURCES): Add kern/i386/qemu/init.c and bus/pci.c. + (kernel_img_HEADERS): Add pci.h. + * conf/i386.rmk (pkglib_MODULES) [qemu]: Remove pci.mod. + * configure.ac: Force unifont on qemu and yeeloong. + * include/grub/i386/qemu/kernel.h (grub_qemu_init_cirrus): New proto. + (grub_vga_palette_write): Use correct register. + * kern/i386/coreboot/init.c (grub_machine_init) [GRUB_MACHINE_QEMU]: + Call grub_qemu_init_cirrus. + * kern/i386/qemu/init.c: New file. + * term/i386/pc/vga_text.c (inc_y): Never read outside the screen. + + * commands/videotest.c (grub_cmd_videotest): Handle double buffering. + +2010-06-26 Pavel Roskin + + * util/grub.d/10_linux.in: Add support for initrd images on Fedora + 13. + +2010-06-26 Colin Watson + + * docs/grub.texi (Simple configuration): Explain that + GRUB_DISABLE_LINUX_RECOVERY and GRUB_DISABLE_NETBSD_RECOVERY must be + set to `true' to disable their respective recovery entries, not + merely set. + +2010-06-26 Colin Watson + + Make the `source' command slightly faster. + + * normal/main.c (grub_normal_execute): Don't re-read list files when + nested. + +2010-06-23 Colin Watson + + * loader/i386/multiboot_mbi.c (retrieve_video_parameters): Set red + field position and mask size to red fields from mode_info, not + green. + * loader/multiboot_mbi2.c (retrieve_video_parameters): Likewise. + Remove redundant tag->common.framebuffer_type assignment. + Reported by: Seth Goldberg. + +2010-06-23 Colin Watson + + Sync up other versions of the Linux loader with Robert Millan's + change of 2010-01-09, "Make loader output a bit more user-friendly". + + * loader/i386/efi/linux.c (grub_linux_boot): Move debug info to + grub_dprintf(). + (grub_cmd_linux): Likewise. + (grub_cmd_initrd): Likewise. + * loader/i386/ieee1275/linux.c (grub_cmd_linux): Likewise. + * loader/i386/pc/linux.c (grub_cmd_linux): Likewise. + +2010-06-21 Colin Watson + + * kern/efi/mm.c (grub_efi_mm_init): Handle systems with memory maps + larger than MEMORY_MAP_SIZE. + +2010-06-21 BVK Chaitanya + + Fix parallel build. + + * conf/common.rmk: Add grub_script.tab.h as a grub-script-check + dependency. + * script/parser.y: #include grub_script.tab.h header. + +2010-06-20 Vladimir Serbinenko + + Support >3GiB and <16MiB RAM in i386-qemu. + + * kern/i386/qemu/mmap.c (QEMU_CMOS_MEMSIZE2_HIGH): New const. + (QEMU_CMOS_MEMSIZE2_LOW): Likewise. + (grub_lower_mem): Removed. + (grub_upper_mem): Likewise. + (mem_size): Made static. + (above_4g): New variable. + (grub_machine_mmap_init): Detect small mem_size and above_4g. + (grub_machine_mmap_iterate): Order in ascending order and add above_4g + support. + +2010-06-20 Vladimir Serbinenko + + Cirrus 5446 and Bochs video cards support. + + * conf/i386.rmk (pkglib_MODULES): Add video_cirrus.mod and + video_bochs.mod + (video_cirrus_mod_SOURCES): New variable. + (video_cirrus_mod_CFLAGS): Likewise. + (video_cirrus_mod_LDFLAGS): Likewise. + (video_bochs_mod_SOURCES): Likewise. + (video_bochs_mod_CFLAGS): Likewise. + (video_bochs_mod_LDFLAGS): Likewise. + * include/grub/vga.h: New file. + * include/grub/video_fb.h (grub_video_fb_doublebuf_blit_init): Removed. + (grub_video_fb_set_page_t): New type. + (grub_video_fb_setup): New prototype. + (grub_video_fb_swap_buffers): Likewise. + (grub_video_fb_get_info_and_fini): Likewise. + * term/i386/pc/vga_text.c (CRTC_ADDR_PORT): Moved to include/grub/vga.h. + (CRTC_DATA_PORT): Likewise. + (CRTC_CURSOR): Likewise. + (CRTC_CURSOR_ADDR_HIGH): Likewise. + (CRTC_CURSOR_ADDR_LOW): Likewise. + (CRTC_CURSOR_DISABLE): Likewise. + (update_cursor): Use grub_vga_cr_write. + (grub_vga_text_setcursor): Likewise. + * video/bochs.c: New file. + * video/fb/video_fb.c (render_target): Moved into framebuffer variable. + (palette): Likewise. + (palette_size): Likewise. + (framebuffer): New variable. + (grub_video_fb_init): Use 'framebuffer'. + (grub_video_fb_fini): Likewise. + (grub_video_fb_get_info): Likewise. + (grub_video_fb_get_palette): Likewise. + (grub_video_fb_set_palette): Likewise. + (grub_video_fb_set_viewport): Likewise. + (grub_video_fb_get_viewport): Likewise. + (grub_video_fb_map_color): Likewise. + (grub_video_fb_map_rgb): Likewise. + (grub_video_fb_map_rgba): Likewise. + (grub_video_fb_unmap_color): Likewise. + (grub_video_fb_unmap_color_int): Likewise. + (grub_video_fb_fill_rect): Likewise. + (grub_video_fb_blit_bitmap): Likewise. + (grub_video_fb_blit_render_target): Likewise. + (grub_video_fb_scroll): Likewise. + (grub_video_fb_create_render_target): Likewise. + (grub_video_fb_doublebuf_blit_init): Likewise. + (grub_video_fb_set_active_render_target): Handle doublebuffering. + (doublebuf_pageflipping_update_screen): New function. + (doublebuf_pageflipping_init): Likewise. + (grub_video_fb_setup): Likewise. + (grub_video_fb_swap_buffers): Likewise. + (grub_video_fb_get_info_and_fini): Likewise. + * video/i386/pc/vbe.c (framebuffer): Remove all doublebuffering fields. + All users updated. + (doublebuf_pageflipping_commit): Restructured into ... + (doublebuf_pageflipping_set_page): ... this. + (doublebuf_pageflipping_update_screen): Removed. + (doublebuf_pageflipping_init): Likewise. + (double_buffering_init): Likewise. + (grub_video_vbe_setup): Use grub_video_fb_setup. + (grub_video_vbe_swap_buffers): Removed. + (grub_video_vbe_set_active_render_target): Likewise. + (grub_video_vbe_get_active_render_target): Likewise. + (grub_video_vbe_get_info_and_fini): Use grub_video_fb_get_info_and_fini. + (grub_video_vbe_adapter): Use grub_video_fb_swap_buffers, + grub_video_fb_set_active_render_target and + grub_video_fb_get_active_render_target. + * video/i386/pc/vga.c (SEQUENCER_ADDR_PORT): Move to include/grub/vga.h. + (SEQUENCER_DATA_PORT): Likewise. + (MAP_MASK_REGISTER): Likewise. + (CRTC_ADDR_PORT): Likewise. + (CRTC_DATA_PORT): Likewise. + (START_ADDR_HIGH_REGISTER): Likewise. + (START_ADDR_LOW_REGISTER): Likewise. + (GRAPHICS_ADDR_PORT): Likewise. + (GRAPHICS_DATA_PORT): Likewise. + (READ_MAP_REGISTER): Likewise. + (INPUT_STATUS1_REGISTER): Likewise. + (INPUT_STATUS1_VERTR_BIT): Likewise. + (get_map_mask): Use grub_vga_sr_read. + (set_map_mask): Use grub_vga_sr_write. + (set_read_map): Use grub_vga_gr_write. + (set_start_address): Use grub_vga_cr_write. + * video/sm712.c (framebuffer): Remove leftover fields. + +2010-06-20 Colin Watson + + * util/grub-mkconfig.in: Capitalise and export GRUB_PREFIX. Stop + setting GRUB_VIDEO_BACKEND. Make it available as a user override + instead. Replace the gfxterm backend check with a check that + ${GRUB_PREFIX}/video.lst is non-empty. + * util/grub.d/00_header.in: Use GRUB_PREFIX rather than computing it + again. + (load_video): New generated function. Call it before loading + gfxterm rather than loading ${GRUB_VIDEO_BACKEND}. + * util/grub.d/10_linux.in (linux_entry): Call load_video. + * util/grub.d/30_os-prober.in (osx_entry): Likewise. + * docs/grub.texi (Simple configuration): Document + GRUB_VIDEO_BACKEND. + +2010-06-20 Vladimir Serbinenko + + Use video functions in linux and xnu loaders. + + * conf/i386-pc.rmk (xnu_mod_SOURCES): Remove loader/i386/pc/xnu.c. + * conf/x86-efi.rmk (xnu_mod_SOURCES): Remove loader/i386/efi/xnu.c. + * include/grub/i386/xnu.h (grub_xnu_set_video): Removed. + * loader/i386/efi/linux.c (grub_linux_setup_video): Copied from + loader/i386/pc/linux.c. + (grub_linux_boot): Resynced with loader/i386/pc/linux.c. + (find_line_len): Removed. + (find_framebuf): Likewise. + (grub_cmd_linux): Declare grub_linux_boot as possibly returning. + * loader/i386/efi/xnu.c: Removed. + * loader/i386/pc/xnu.c: Moved from here... + * loader/i386/xnu.c: ...here. + + Enable priorities in video drivers. + + * include/grub/video.h (grub_video_adapter_prio_t): New type. + (grub_video_adapter): New field prio. + (grub_video_register): Respect prio when inserting. + * video/efi_gop.c (grub_video_gop_adapter): Add prio. + * video/efi_uga.c (grub_video_uga_adapter): Likewise. + * video/emu/sdl.c (grub_video_sdl_adapter): Likewise. + * video/i386/pc/vbe.c (grub_video_vbe_adapter): Likewise. + * video/i386/pc/vga.c (grub_video_vga_adapter): Likewise. + * video/ieee1275.c (grub_video_ieee1275_adapter): Likewise. + * video/sm712.c (grub_video_sm712_adapter): Likewise. + + Fix SDL driver ID. + + * include/grub/video.h (grub_video_driver_id_t): New value + GRUB_VIDEO_DRIVER_SDL. + * video/emu/sdl.c (grub_video_sdl_adapter): Add id. + +2010-06-17 Colin Watson + + * util/i386/pc/grub-setup.c (usage): Pass an extra `program_name' + argument to printf. + * util/sparc64/ieee1275/grub-setup.c (usage): Likewise. + +2010-06-17 Colin Watson + + * util/i386/pc/grub-setup.c (usage): Fix syntax error. + * util/sparc64/ieee1275/grub-setup.c (usage): Likewise. + +2010-06-17 Colin Watson + + * util/i386/pc/grub-setup.c (usage): Warn against running grub-setup + directly, and recommend grub-install instead. + * util/sparc64/ieee1275/grub-setup.c (usage): Likewise. + +2010-06-17 Colin Watson + + Fix i386-pc prefix handling with nested partitions (Debian bug + #585068). Note that the case where the core image is booted using + multiboot and relocated from its original location still requires + more work. + + * kern/i386/pc/init.c (make_install_device): If the prefix starts + with "(,", fill the boot drive in between those two characters, but + expect that a full partition specification including partition map + names will follow. + * util/i386/pc/grub-setup.c (setup): Unless an explicit prefix was + specified, write a prefix without the drive name but including a + full partition specification. + +2010-06-16 Colin Watson + + * util/grub-mkconfig.in: Ignore non-option arguments, for + compatibility with older versions (before 2010-06-12) which did the + same. In particular, this makes it easier to ship an update-grub + wrapper which is compatible with that used with GRUB Legacy (Debian + bug #586056). + +2010-06-14 Grégoire Sutre + + * Makefile.in (install-local): Use $$file.h2m instead of $$dest.h2m + for manual page generation. + +2010-06-14 Grégoire Sutre + + * po/POTFILES: Remove leftover commands/handler.c. + +2010-06-14 Colin Watson + + * util/grub-mkconfig.in: Remove vestige of old argument parsing that + left this script non-functional. + +2010-06-14 Colin Watson + + * docs/man/grub-emu.h2m: New file. + +2010-06-13 Colin Watson + + * docs/grub.texi (Commands): Document reduced command set in rescue + mode. + (cpuid): New section. + +2010-06-13 Grégoire Sutre + + * kern/emu/hostdisk.c (grub_util_biosdisk_get_grub_dev): Use the + new partition naming style. + * util/grub-install.in: Adapt sed subtitutions in grub-probe calls. + +2010-06-12 BVK Chaitanya + + Add "-o grub.iso" like cmdline options support. + + * util/grub-install.in: Improve cmdline option parsing. + * util/grub-mkconfig.in: Likewise. + * util/grub-mkrescue.in: Likewise. + * util/grub-reboot.in: Likewise. + * util/grub-set-default.in: Likewise. + * util/i386/efi/grub-install.in: Likewise. + * util/ieee1275/grub-install.in: Likewise. + * util/powerpc/ieee1275/grub-mkrescue.in: Likewise. + +2010-06-12 Colin Watson + + * .bzrignore: Ignore 41_custom. + +2010-06-12 Thomas Schmitt + + * util/grub-mkrescue.in: Pass unrecognized options to xorriso. + +2010-06-12 Colin Watson + + Avoid false positives in fs.lst, partmap.lst, and video.lst due to + prototype declarations. + + * genmk.rb (PModule::rule): Define GRUB_LST_GENERATOR when + generating fs, partmap, and video lists. + * include/grub/fs.h (grub_fs_register): Omit prototype if + GRUB_LST_GENERATOR is defined. + * include/grub/partition.h (grub_partition_map_register): Likewise. + * include/grub/video.h (grub_video_register): Likewise. + +2010-06-12 Javier Martín + + * include/grub/types.h: Check for GRUB_CPU_SIZEOF_LONG when appropriate. + +2010-06-12 Thomas Schmitt + + * util/grub-mkrescue.in: Support --xorriso argument. + +2010-06-12 Vladimir Serbinenko + + * util/grub-mkrescue.in: Use -graft-points instead of -pathspecs. + Suggested by: Thomas Schmitt. + +2010-06-12 Vladimir Serbinenko + + * util/grub-mkrescue.in: Add --sort-weight arguments to xorriso. + Suggested by: Thomas Schmitt. + +2010-06-12 Vladimir Serbinenko + + custom.cfg support. + + * conf/common.rmk (grub-mkconfig_SCRIPTS): Add 41_custom. + * util/grub.d/41_custom.in: New file. + +2010-06-12 Colin Watson + + * util/grub-mkrescue.in (make_image): Remove sh module, which has + been merged back into normal. + +2010-06-11 Colin Watson + + * include/grub/efi/uga_draw.h (GRUB_EFI_UGA_GLT_MAX): Rename to ... + (GRUB_EFI_UGA_BLT_MAX): ... this (typo fix). + +2010-06-11 Colin Watson + + * Makefile.in (install-local): Include $(srcdir)/docs/man/$$dest.h2m + when generating manual pages. + * docs/man/grub-bin2h.h2m: New file. + * docs/man/grub-editenv.h2m: New file. + * docs/man/grub-fstest.h2m: New file. + * docs/man/grub-install.h2m: New file. + * docs/man/grub-macho2img.h2m: New file. + * docs/man/grub-mkconfig.h2m: New file. + * docs/man/grub-mkdevicemap.h2m: New file. + * docs/man/grub-mkfont.h2m: New file. + * docs/man/grub-mkimage.h2m: New file. + * docs/man/grub-mkpasswd-pbkdf2.h2m: New file. + * docs/man/grub-mkrelpath.h2m: New file. + * docs/man/grub-mkrescue.h2m: New file. + * docs/man/grub-ofpathname.h2m: New file. + * docs/man/grub-pe2elf.h2m: New file. + * docs/man/grub-probe.h2m: New file. + * docs/man/grub-reboot.h2m: New file. + * docs/man/grub-script-check.h2m: New file. + * docs/man/grub-set-default.h2m: New file. + * docs/man/grub-setup.h2m: New file. + +2010-06-10 Vladimir Serbinenko + + Use FOR_* macros instead of *_iterate whenever possible. + + * commands/handler.c: Removed. + * commands/help.c (grub_cmd_help): Use FOR_COMMANDS. + * commands/minicmd.c (grub_mini_cmd_lsmod): Use FOR_DL_MODULES. + * conf/any-emu.rmk (kernel_img_SOURCES): Remove kern/handler.c. + * conf/common.rmk (script/lexer.c_DEPENDENCIES): Add grub_script.yy.h. + (grub_probe_SOURCES): Remove kern/parser.c. + (util/grub-script-check.c_DEPENDENCIES): Removed. + (grub_script_check_SOURCES): Remove kern/handler.c, kern/parser.c + and grub_script_check_init.c. + (grub_script_check_init.lst): Removed. + (grub_script_check_init.h): Likewise. + (grub_script_check_init.c): Likewise. + (pkglib_MODULES): Remove handler.mod and sh.mod. + (handler_mod_SOURCES): Removed. + (handler_mod_CFLAGS): Likewise. + (handler_mod_LDFLAGS): Likewise. + (normal_mod_SOURCES): Remove normal/handler.c. + Add script/main.c, script/script.c, script/execute.c, + script/function.c, script/lexer.c, grub_script.tab.c + and grub_script.yy.c. + * conf/i386-coreboot.rmk (kernel_img_SOURCES): Remove kern/handler.c. + * conf/i386-ieee1275.rmk (kernel_img_SOURCES): Likewise. + * conf/i386-pc.rmk (kernel_img_SOURCES): Likewise. + (grub_setup_SOURCES): Remove kern/parser.c. + * conf/i386-qemu.rmk (kernel_img_SOURCES): Remove kern/handler.c. + * conf/mips-qemu-mips.rmk (kernel_img_SOURCES): Likewise. + * conf/mips-yeeloong.rmk (kernel_img_SOURCES): Likewise. + * conf/powerpc-ieee1275.rmk (kernel_img_SOURCES): Likewise. + * conf/sparc64-ieee1275.rmk (kernel_img_SOURCES): Likewise. + (grub_setup_SOURCES): Remove kern/parser.c. + * conf/x86-efi.rmk (kernel_img_SOURCES): Remove kern/handler.c. + * gettext/gettext.c (grub_gettext_delete_list): Don't use grub_list_pop. + * include/grub/command.h (grub_command_iterate): Removed. + (FOR_COMMANDS): New macro. + * include/grub/dl.h (grub_dl): New member next. + (grub_dl_iterate): Removed. + (grub_dl_head): New variable declaration. + (FOR_DL_MODULES): New macro. + * include/grub/fs.h: Include list.h. + (grub_fs): Make next first element. + (grub_fs_list): New variable declaration. + (grub_fs_register): Make inline. + (grub_fs_unregister): Likewise. + (grub_fs_iterate): Removed. + (FOR_FILESYSTEMS): New macro. + * include/grub/handler.h: Removed. + * include/grub/list.h (grub_list_hook_t): Removed. + (grub_list_test_t): Likewise. + (grub_list_pop): Likewise. + (grub_list_iterate): Likewise. + (grub_list_insert): Likewise. + (FOR_LIST_ELEMENTS): New macro. + * include/grub/parser.h (grub_parser_class): Removed. + (grub_parser_register): Likewise. + (grub_parser_unregister): Likewise. + (grub_parser_get_current): Likewise. + (grub_parser_set_current): Likewise. + (grub_register_rescue_parser): Likewise. + (grub_rescue_parse_line): New function. + * include/grub/partition.h (FOR_PARTITION_MAPS): Use FOR_LIST_ELEMENTS. + * include/grub/script_sh.h (grub_script_function_list): New variable + declaration. + (FOR_SCRIPT_FUNCTIONS): New macro. + (grub_script_function_iterate): Removed. + (grub_normal_parse_line): New prototype. + * include/grub/term.h (FOR_ACTIVE_TERM_INPUTS): Use FOR_LIST_ELEMENTS. + (FOR_DISABLED_TERM_INPUTS): Likewise. + (FOR_ACTIVE_TERM_OUTPUTS): Likewise. + (FOR_DISABLED_TERM_OUTPUTS): Likewise. + * include/grub/video.h (grub_video_adapter): Move 'next' to first + element. + (grub_video_register): Inline. + (grub_video_unregister): Likewise. + (grub_video_adapter_list): New variable declaration. + (grub_video_iterate): Removed. + (FOR_VIDEO_ADAPTERS): New macro. + * kern/dl.c (grub_dl_list): Removed. All users updated. + (grub_dl_iterate): Removed. + * kern/fs.c (grub_fs_list): Make global. + (grub_fs_register): Removed. + (grub_fs_unregister): Likewise. + (grub_fs_iterate): Likewise. + * kern/handler.c: Removed. + * kern/list.c (grub_list_pop): Removed. + (grub_list_iterate): Likewise. + (grub_list_insert): Likewise. + (grub_named_list_find): Use FOR_LIST_ELEMENTS. + (grub_prio_list_insert): Don't use grub_list_insert. + * kern/main.c (grub_register_rescue_parser): Don't call + grub_register_rescue_parser. + * kern/parser.c (grub_parser_class): Removed. + (grub_parser_execute): Use grub_rescue_parse_line. + * kern/rescue_parser.c (grub_rescue_parse_line): Make global. + (grub_rescue_parser): Removed. + (grub_register_rescue_parser): Likewise. + * kern/rescue_reader.c (grub_rescue_run): Use grub_rescue_parse_line. + * normal/auth.c (is_authenticated): Use FOR_LIST_ELEMENTS. + (grub_auth_check_authentication): Likewise. + * normal/completion.c (iterate_command): Removed. + (grub_normal_do_completion): Use FOR_COMMANDS. + * normal/handler.c: Removed. + * normal/main.c (read_config_file): Remove parser changing. + (grub_normal_execute): Don't call read_handler_list. + (grub_normal_read_line_real): Statically allocate prompt. + (grub_cmdline_run): Use grub_normal_parse_line. + (GRUB_MOD_FINI): Don't call free_handler_list. + * normal/menu_entry.c (run): Likewise. + * script/function.c (grub_script_function_list): Make global. + (grub_script_function_iterate): Removed. + * script/main.c (grub_normal_parse_line): Make global. + (grub_sh_parser): Removed. + (GRUB_MOD_INIT): Likewise. + (GRUB_MOD_FINI): Likewise. + * tests/lib/functional_test.c (grub_functional_test): Use + FOR_LIST_ELEMENTS. + * tests/lib/test.c (free_failures): Don't use grub_list_pop. + (grub_test_run): Use FOR_LIST_ELEMENTS. + * tests/lib/unit_test.c (main): Likewise. + * util/deviceiter.c (grub_util_iterate_devices): Don't use + grub_list_pop. + * util/grub-fstest.c (grub_term_input_class): Removed. + (grub_term_output_class): Likewise. + * util/grub-probe.c: Likewise. + * util/i386/pc/grub-setup.c: Likewise. + * util/sparc64/ieee1275/grub-setup.c: Likewise. + * util/grub-script-check.c (main): Don't call grub_init_all and + grub_fini_all. + * video/video.c (grub_video_adapter_list): Make global. + (grub_video_register): Removed. + (grub_video_unregister): Likewise. + (grub_video_iterate): Likewise. + +2010-06-09 Vladimir Serbinenko + + * docs/grub.texi (Vendor power-on button): Add Asus EeePC 1005PE as + reported by Henrique Ferreiro. + +2010-06-09 Robert Millan + + * util/grub.d/10_linux.in: Prefer compressed images over non-compressed + ones, when both are available. + +2010-06-08 Grégoire Sutre + + Make --version uniform and avoid hard-coded program name. + + * util/grub-mkimage.c (main): Use `program_name' instead of + hard-coded string. + * util/i386/pc/grub-setup.c (main): Likewise. + * util/sparc64/ieee1275/grub-setup.c (parse_options): Likewise. + * util/grub-install.in: Save the basename of $0 in $self, and use the + latter in informational messages. Use the same format for --version + as the binary programs. + * util/grub-mkconfig.in: Likewise. + * util/grub-mkrescue.in: Likewise. + * util/grub-reboot.in: Likewise. + * util/grub-set-default.in: Likewise. + * util/i386/efi/grub-install.in: Likewise. + * util/ieee1275/grub-install.in: Likewise. + * util/powerpc/ieee1275/grub-mkrescue.in: Likewise. + +2010-06-08 Grégoire Sutre + + * util/i386/pc/grub-setup.c (setup): Use absolute offsets for start of + embedding area. Use <= instead of == when checking for non-emptiness. + +2010-06-08 Grégoire Sutre + + * configure.ac: Add `.' to the directories searched for unifont. + +2010-06-08 Colin Watson + + * .bzrignore: Add ascii.bitmaps, ascii.h, grub_script.yy.c, and + grub_script.yy.h. + +2010-06-08 Colin Watson + + * docs/grub.texi (History): Expand to cover GRUB 2. + (Serial terminal): Refer to `terminal_input' and `terminal_output' + commands, not `terminal'. + (serial): Likewise. + (terminal_input): New section. + (terminal_output): New section. + (uppermem): New section (stub). + (Obtaining and Building GRUB): Refer to Bazaar, not Subversion. + +2010-06-08 Colin Watson + + * docs/grub.texi (Security): Menu entries are unrestricted by + default, not restricted to superusers as I had previously thought. + Reword to account for this. + +2010-06-07 Colin Watson + + * kern/emu/misc.c (device_mapper_null_log): New function. + (grub_device_mapper_supported): New function. + * include/grub/emu/misc.h (grub_device_mapper_supported): Add + prototype. + * kern/emu/hostdisk.c (find_partition_start): Check whether + device-mapper is supported before trying to use it. + * util/deviceiter.c (grub_util_iterate_devices): Likewise. + +2010-06-07 Colin Watson + + * docs/grub.texi (Naming convention): Use GRUB 2 syntax. + (File name syntax): Likewise. + (help): --all is no longer supported in GRUB 2. Be more precise + about pattern matching. + +2010-06-07 Colin Watson + + * normal/completion.c (grub_normal_do_completion): When completing + arguments to "set" and the current word contains an equals sign, + skip to after the equals sign before starting completion. + +2010-06-07 Colin Watson + + * fs/i386/pc/pxe.c (grub_pxe_open): Fix parsing of gateway_ip. + +2010-06-07 Colin Watson + + * docs/grub.texi (Network): New section. + (Device syntax): The network device is called `(pxe)' in GRUB 2, not + `(nd)' as in GRUB Legacy. + (pxe_unload): New section. + +2010-06-07 Colin Watson + + * docs/grub.texi (Troubleshooting): `echo' is not usually available + in the rescue shell, so recommend using `set' instead. Thanks, + Jordan Uggla. + +2010-06-07 Colin Watson + + * docs/grub.texi (Filesystem): Refer to `search' instead of `find'. + (password): New section. + (password_pbkdf2): New section. + (search): New section. + (Security): New section. + (Troubleshooting): New section, currently very incomplete. + (Invoking grub-mkpasswd-pbkdf2): New section. + (Internals): New section, currently very incomplete. + +2010-06-07 Colin Watson + + * util/grub.d/00_header.in: Add some more quoting (of + "${prev_saved_entry}" and "${boot_once}") needed to make savedefault + work again. + Reported by: Mario 'BitKoenig' Holbe (Debian bug #584812). + +2010-06-07 Colin Watson + + * util/grub-mkpasswd-pbkdf2.c (main): Rename top-level `c' variable + to `count', fixing variable shadowing that broke the -c option. + +2010-06-05 Colin Watson + + * util/grub.d/00_header.in: Quote values assigned to `saved_entry', + in case they contain spaces. + +2010-06-04 Colin Watson + + * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Prepend + "part_" to partmap module names, in line with grub-install. + Reported by: Jindřich Makovička (Debian bug #584426). + +2010-06-04 Colin Watson + + * util/grub-mkimage.c: Make target-related error messages slightly + more helpful; -O talks about "format". Explicitly point to the use + of -O if no target is specified. + Reported by: Didier Raboud (Debian bug #584415). + +2010-06-03 Colin Watson + + * INSTALL: Document several build requirements for optional features + (libdevmapper, ncurses, libusb, SDL, FreeType, GNU Unifont). + +2010-06-02 Grégoire Sutre + + * kern/emu/hostdisk.c (convert_system_partition_to_system_disk) + [__NetBSD__]: Handle all device names matching /dev/r[a-z]+[0-9][a-z]. + (find_partition_start) [__NetBSD__]: Correct error messages for NetBSD. + +2010-06-02 Colin Watson + + * docs/grub.texi (Simple configuration): Fix copy-and-paste typo. + Thanks to Jordan Uggla for spotting this. + +2010-06-02 Aleš Nesrsta + + Finally make USB usable. + + * bus/usb/ohci.c (grub_ohci_reg_t): Add missing values. + (GRUB_OHCI_RHUB_PORT_POWER_MASK): New macro. + (GRUB_OHCI_RHUB_PORT_ALL_POWERED): Likewise. + (GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_MASK): Likewise. + (GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_SHIFT): Likewise. + (GRUB_OHCI_REG_FRAME_INTERVAL_FI_SHIFT): Likewise. + (GRUB_OHCI_FSMPS): Likewise. + (GRUB_OHCI_PERIODIC_START): Likewise. + (GRUB_OHCI_FRAME_INTERVAL): Likewise. + (GRUB_OHCI_SET_PORT_ENABLE): Likewise. + (GRUB_OHCI_CLEAR_PORT_ENABLE): Likewise. + (GRUB_OHCI_SET_PORT_RESET): Likewise. + (GRUB_OHCI_SET_PORT_RESET_STATUS_CHANGE): Likewise. + * bus/usb/ohci.c (grub_ohci_pci_iter): Various important fixups. + (grub_ohci_transaction): Likewise. + (grub_ohci_transfer): Improve condition detection algorithms. + Handle toggle property. Program the transactions correctly. + Improve error handling. Various important fixups. + (grub_ohci_portstatus): Put register writes in right order. + * bus/usb/uhci.c (grub_free_queue): Compute last_trans. + (grub_uhci_transfer): Don't show "failed" message on success. + * bus/usb/usb.c (grub_usb_set_configuration): Zero-fill whole "toggle" + array. + (grub_usb_device_initialize): Read first 8 bytes of descriptor to + determine its size. + * bus/usb/usbtrans.c (grub_usb_control_msg): Use descdev.maxsize0 even + before initialization is completed. Use IN direction for empty + transfers. Use last_trans and compute toggle. + * include/grub/usbtrans.h (grub_usb_transfer): New field last_trans. + (GRUB_USB_FEATURE_ENDP_HALT): Correct the value. + (GRUB_USB_FEATURE_DEV_REMOTE_WU): Likewise. + (GRUB_USB_FEATURE_TEST_MODE): Likewise. + * include/grub/usb.h (grub_usb_err_t): New value GRUB_USB_ERR_UNRECOVERABLE. + (grub_usb_device): Increase toggle to 256. + (grub_usbms_subclass_t): New values GRUB_USBMS_SUBCLASS_RBC, + GRUB_USBMS_SUBCLASS_MMC2, GRUB_USBMS_SUBCLASS_UFI and + GRUB_USBMS_SUBCLASS_SFF8070. + * include/grub/scsicmd.h (grub_scsi_test_unit_ready): New structure. + (grub_scsi_inquiry): New member page and alloc_length. + (grub_scsi_request_sense): New structure. + (grub_scsi_request_sense_data): Likewise. + (grub_scsi_read_capacity): New fields logical_block_addr, PMI and + control. + * disk/scsi.c (grub_scsi_request_sense): New function. + (grub_scsi_test_unit_ready): Likewise. + (grub_scsi_inquiry): Fill new fields. + (grub_scsi_read_capacity): Likewise. + (grub_scsi_read10): Add request sense at the end. + (grub_scsi_read12): Likewise. + (grub_scsi_write10): Likewise. + (grub_scsi_write12): Likewise. + (grub_scsi_open): Add Test Unit Ready. + * disk/usbms.c (grub_usbms_finddevs): Check configcnt. + Support additional subclasses. Con't clear halt yet. Activate the + proper config. Calculate LUNs correctly. + (grub_usbms_transfer): Various important fixups. + +2010-06-02 Vladimir Serbinenko + + * bus/pci.c (grub_pci_iterate) [GRUB_MACHINE_MIPS_YEELOONG]: Skip ghosts. + * bus/usb/ohci.c (grub_ohci_portstatus): Handle R/WC correctly. + (grub_ohci_fini_hw): New function. + (grub_ohci_restore_hw): Likewise. + (GRUB_MOD_INIT(ohci)): Register preboot hook. + (GRUB_MOD_FINI(ohci)): Shutdown OHCI. + * term/usb_keyboard.c: Remove include of grub/machine/console.h. + +2010-06-02 Vladimir Serbinenko + + Dedicated DMA allocations. + + * bus/pci.c (grub_memalign_dma32): New function + (grub_dma_free): Likewise. + (grub_dma_get_virt): Likewise. + (grub_dma_get_phys): Likewise. + * bus/usb/ohci.c (grub_ohci): New members hcca_addr and hcca_chunk. + (grub_ohci_pci_iter): Use dma32_alloc. + (grub_ohci_transfer): Likewise. + * bus/usb/usbtrans.c (grub_usb_control_msg): Likewise. + (grub_usb_bulk_readwrite): Likewise. + * include/grub/pci.h: Add declarations. + +2010-06-02 Vladimir Serbinenko + + CS5536 support. + + * bus/cs5536.c: New file. + * bus/usb/ohci.c (grub_ohci_pci_iter): Check for CS5536. + * conf/i386.rmk (pkglib_MODULES): Add cs5536.mod. + (cs5536_mod_SOURCES): New variable. + (cs5536_mod_CFLAGS): Likewise. + (cs5536_mod_LDFLAGS): Likewise. + * conf/mips-yeeloong.rmk (kernel_img_HEADERS): Add cs5536.h and + machine/pci.h. + (kernel_img_SOURCES): Add bus/cs5536.c. + (pkglib_MODULES): Add usb.mod, usbtest.mod, ohci.mod, usbms.mod and + usb_keyboard.mod. + (usb_mod_SOURCES): New variable. + (usb_mod_CFLAGS): New variable. + (usb_mod_LDFLAGS): New variable. + (usbtest_mod_SOURCES): New variable. + (usbtest_mod_CFLAGS): New variable. + (usbtest_mod_LDFLAGS): New variable. + (ohci_mod_SOURCES): New variable. + (ohci_mod_CFLAGS): New variable. + (ohci_mod_LDFLAGS): New variable. + (usbms_mod_SOURCES): New variable. + (usbms_mod_CFLAGS): New variable. + (usbms_mod_LDFLAGS): New variable. + (usb_keyboard_mod_SOURCES): New variable. + (usb_keyboard_mod_CFLAGS): New variable. + (usb_keyboard_mod_LDFLAGS): New variable. + * include/grub/smbus.h: New file. + * include/grub/cs5536.h: New file. + +2010-06-02 Colin Watson + + * util/grub.d/00_header.in: Add safety check to make sure that + ${locale_dir} exists before trying to probe it. + +2010-06-02 Colin Watson + + * docs/grub.texi (SCO UnixWare): Remove, at Vladimir's request and + per the GNU Coding Standards; this is now too obscure to be worth + documenting. + (QNX): Likewise. + (chainloader): Remove cross-reference to `SCO UnixWare'. + +2010-06-02 Colin Watson + + * docs/grub.texi (Chain-loading): New section. + (DOS/Windows): New section, borrowed from GRUB Legacy with details + adjusted for GRUB 2. + (SCO UnixWare): Likewise. + (QNX): Likewise. + (chainloader): Add reference to `Block list syntax'. + (drivemap): New section. + (parttool): New section. + +2010-06-02 Colin Watson + + * docs/grub.texi (GNU GRUB manual): Remove reference to `Invoking + the grub shell'. + (Installation): Add reference to `Making a GRUB bootable CD-ROM'. + (Installing GRUB using grub-install): Remove reference to the grub + shell; mention `grub-mkimage' and `grub-setup' instead. + (Invoking grub-install): Likewise. + (Interface): Add reference to `Menu entry editor'. + (serial): Remove `--device' option. + +2010-06-02 Colin Watson + + * docs/grub.texi (Configuration): New section, documenting + configuration file generation using grub-mkconfig. I've left a slot + for documenting the full shell scripting format but have not yet + started on writing that up. + (Invoking grub-mkconfig): New section. + +2010-06-02 Colin Watson + + * docs/grub.texi (direntry): Remove grub-terminfo reference. + (GNU GRUB manual): Likewise. + (General commands): Update description of `terminfo' for GRUB 2. + +2010-06-02 Colin Watson + + * commands/gptsync.c (grub_cmd_gptsync): Fix typos. + (GRUB_MOD_INIT): Fix capitalisation. + * docs/grub.texi (Command-line and menu entry commands): Document + gettext and gptsync commands. + +2010-06-02 Colin Watson + + * conf/any-emu.rmk (kernel_img_SOURCES) [!x86]: Include + kern/$(target_cpu)/cache.S even if TARGET_NO_MODULES = yes. + +2010-06-01 Colin Watson + + Add btrfs probing support, currently only in the single-device case. + + * kern/emu/getroot.c (find_root_device_from_mountinfo): New + function. + (grub_guess_root_device): Call find_root_device_from_mountinfo + before looking in /dev. + +2010-05-31 Vladimir Serbinenko + + * disk/i386/pc/biosdisk.c (grub_biosdisk_open): Use + GRUB_DISK_SIZE_UNKNOWN. + * disk/ieee1275/ofdisk.c (grub_ofdisk_open): Likewise. + +2010-05-31 Jiro SEKIBA + + * include/grub/disk.h (GRUB_DISK_SIZE_UNKNOWN): New macro. + * fs/nilfs.c: Support 2nd super block in case 1st one is accidently + corrupted or not synced properly. + +2010-05-31 Vladimir Serbinenko + + * normal/main.c (grub_normal_add_menu_entry): Avoid going out of args. + Reported by: Seth Goldberg. + +2010-05-31 Vladimir Serbinenko + + * loader/multiboot_mbi2.c (grub_multiboot_make_mbi): Fix incorrect + addition of dest. + Reported by: Seth Goldberg. + +2010-05-31 Vladimir Serbinenko + + * commands/setpci.c (grub_setpci_iter): Fix an incorrect function check. + Reported by: Seth Goldberg. + +2010-05-31 Vladimir Serbinenko + + * loader/multiboot_elfxx.c (grub_multiboot_load_elfXX) [__mips]: Check + 64-bit address as signed on MIPS. + 2010-05-28 Colin Watson * configure.ac: AC_PROG_LEX sets LEX to ":" if lex is missing, not diff --git a/INSTALL b/INSTALL index 7186d20db..44a442253 100644 --- a/INSTALL +++ b/INSTALL @@ -19,6 +19,21 @@ configuring the GRUB. * Flex 2.5.35 or later * Other standard GNU/Unix tools +On GNU/Linux, you also need: + +* libdevmapper (recommended) + +To build grub-emu, you need: + +* ncurses +* libusb (recommended) +* SDL (recommended) + +To build GRUB's graphical terminal (gfxterm), you need: + +* FreeType 2 or later +* GNU Unifont + If you use a development snapshot or want to hack on GRUB you may need the following. diff --git a/Makefile.in b/Makefile.in index 75388e3c8..b9b7f3d08 100644 --- a/Makefile.in +++ b/Makefile.in @@ -323,26 +323,26 @@ install-local: all if test -f "$$file"; then dir=; else dir="$(srcdir)/"; fi; \ dest="`echo $$file | sed 's,.*/,,' | sed '$(transform)'`"; \ $(INSTALL_PROGRAM) $$dir$$file $(DESTDIR)$(bindir)/$$dest; \ - $(HELP2MAN) --section=1 -o $(DESTDIR)$(mandir)/man1/$$dest.1 $(builddir)/$$file; \ + $(HELP2MAN) --section=1 -i $(srcdir)/docs/man/$$file.h2m -o $(DESTDIR)$(mandir)/man1/$$dest.1 $(builddir)/$$file; \ done $(SHELL) $(mkinstalldirs) $(DESTDIR)$(sbindir) $(DESTDIR)$(mandir)/man8 @list='$(sbin_UTILITIES)'; for file in $$list; do \ if test -f "$$file"; then dir=; else dir="$(srcdir)/"; fi; \ dest="`echo $$file | sed 's,.*/,,' | sed '$(transform)'`"; \ $(INSTALL_PROGRAM) $$dir$$file $(DESTDIR)$(sbindir)/$$dest; \ - $(HELP2MAN) --section=8 -o $(DESTDIR)$(mandir)/man8/$$dest.8 $(builddir)/$$file; \ + $(HELP2MAN) --section=8 -i $(srcdir)/docs/man/$$file.h2m -o $(DESTDIR)$(mandir)/man8/$$dest.8 $(builddir)/$$file; \ done @list='$(bin_SCRIPTS)'; for file in $$list; do \ if test -f "$$file"; then dir=; else dir="$(srcdir)/"; fi; \ dest="`echo $$file | sed 's,.*/,,' | sed '$(transform)'`"; \ $(INSTALL_SCRIPT) $$dir$$file $(DESTDIR)$(bindir)/$$dest; \ - $(HELP2MAN) --section=1 -o $(DESTDIR)$(mandir)/man1/$$dest.1 $(builddir)/$$file; \ + $(HELP2MAN) --section=1 -i $(srcdir)/docs/man/$$file.h2m -o $(DESTDIR)$(mandir)/man1/$$dest.1 $(builddir)/$$file; \ done @list='$(sbin_SCRIPTS)'; for file in $$list; do \ if test -f "$$file"; then dir=; else dir="$(srcdir)/"; fi; \ dest="`echo $$file | sed 's,.*/,,' | sed '$(transform)'`"; \ $(INSTALL_SCRIPT) $$dir$$file $(DESTDIR)$(sbindir)/$$dest; \ - $(HELP2MAN) --section=8 -o $(DESTDIR)$(mandir)/man8/$$dest.8 $(builddir)/$$file; \ + $(HELP2MAN) --section=8 -i $(srcdir)/docs/man/$$file.h2m -o $(DESTDIR)$(mandir)/man8/$$dest.8 $(builddir)/$$file; \ done $(SHELL) $(mkinstalldirs) $(DESTDIR)$(sysconfdir)/grub.d @list='$(grub-mkconfig_SCRIPTS)'; for file in $$list; do \ diff --git a/boot/i386/qemu/boot.S b/boot/i386/qemu/boot.S index a84bd77a8..fe14f0f06 100644 --- a/boot/i386/qemu/boot.S +++ b/boot/i386/qemu/boot.S @@ -36,9 +36,6 @@ VARIABLE(grub_core_entry_addr) .long 0 1: - /* Process VGA rom. */ - call $0xc000, $0x3 - /* Set up %ds, %ss, and %es. */ xorw %ax, %ax movw %ax, %ds diff --git a/bus/pci.c b/bus/pci.c index 3e2126962..bf14a8653 100644 --- a/bus/pci.c +++ b/bus/pci.c @@ -21,7 +21,8 @@ #include #include -#if GRUB_TARGET_SIZEOF_VOID_P == 4 +/* FIXME: correctly support 64-bit architectures. */ +/* #if GRUB_TARGET_SIZEOF_VOID_P == 4 */ struct grub_pci_dma_chunk * grub_memalign_dma32 (grub_size_t align, grub_size_t size) { @@ -33,7 +34,7 @@ grub_dma_free (struct grub_pci_dma_chunk *ch) { grub_free (ch); } -#endif +/* #endif */ #ifdef GRUB_MACHINE_MIPS_YEELOONG volatile void * @@ -58,7 +59,7 @@ grub_dma_get_virt (struct grub_pci_dma_chunk *ch) grub_uint32_t grub_dma_get_phys (struct grub_pci_dma_chunk *ch) { - return (grub_uint32_t) ch; + return (grub_uint32_t) (grub_addr_t) ch; } #endif diff --git a/bus/usb/ohci.c b/bus/usb/ohci.c index 6c564ebdb..47cca7ce4 100644 --- a/bus/usb/ohci.c +++ b/bus/usb/ohci.c @@ -116,6 +116,11 @@ typedef enum #define GRUB_OHCI_PERIODIC_START 0x257f #define GRUB_OHCI_FRAME_INTERVAL 0x2edf +#define GRUB_OHCI_SET_PORT_ENABLE (1 << 1) +#define GRUB_OHCI_CLEAR_PORT_ENABLE (1 << 0) +#define GRUB_OHCI_SET_PORT_RESET (1 << 4) +#define GRUB_OHCI_SET_PORT_RESET_STATUS_CHANGE (1 << 20) + static grub_uint32_t grub_ohci_readreg32 (struct grub_ohci *o, grub_ohci_reg_t reg) { @@ -280,7 +285,7 @@ grub_ohci_pci_iter (grub_pci_device_t dev, /* Misc. pre-sets. */ o->hcca->donehead = 0; - grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1)); /* Clears WDH */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, 0x7f); /* Clears everything */ grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD, 0); grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLCURR, 0); grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, 0); @@ -333,10 +338,8 @@ grub_ohci_pci_iter (grub_pci_device_t dev, return 0; fail: -#ifndef GRUB_MACHINE_MIPS_YEELOONG if (o) - grub_free ((void *) o->hcca); -#endif + grub_dma_free (o->hcca_chunk); grub_free (o); return 0; @@ -395,8 +398,10 @@ grub_ohci_transaction (grub_ohci_td_t td, break; } +#if 0 /* Always generate interrupt */ /* Generate no interrupts. */ token |= 7 << 21; +#endif /* Set the token. */ token |= toggle << 24; @@ -443,9 +448,12 @@ grub_ohci_transfer (grub_usb_controller_t dev, grub_uint32_t status; grub_uint32_t control; grub_usb_err_t err; - int i, j; + int i; grub_uint64_t maxtime; int err_timeout = 0; + int err_unrec = 0; + grub_uint32_t intstatus; + grub_uint32_t tderr_addr = 0; /* Allocate an Endpoint Descriptor. */ ed_chunk = grub_memalign_dma32 (256, sizeof (*ed)); @@ -478,11 +486,13 @@ grub_ohci_transfer (grub_usb_controller_t dev, + (i + 1) * sizeof (td_list[0])); } +#if 0 /* Better will be enable interrupt on all TDs. */ /* The last-1 TD token we should change to enable interrupt when TD finishes. * As OHCI interrupts are disabled, it does only setting of WDH bit in * HcInterruptStatus register - and that is what we want to safely detect * normal end of all transactions. */ td_list[transfer->transcnt - 1].token &= ~(7 << 21); +#endif td_list[transfer->transcnt].token = 0; td_list[transfer->transcnt].buffer = 0; @@ -550,9 +560,14 @@ grub_ohci_transfer (grub_usb_controller_t dev, grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, ed_addr); grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKCURR, 0); +#define GRUB_OHCI_REG_CONTROL_BULK_ENABLE (1 << 5) +#define GRUB_OHCI_REG_CONTROL_CONTROL_ENABLE (1 << 4) + /* Enable the Bulk list. */ control = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL); - control |= 1 << 5; + control |= GRUB_OHCI_REG_CONTROL_BULK_ENABLE; + control &= ~GRUB_OHCI_REG_CONTROL_CONTROL_ENABLE; + grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, control); /* Set BulkListFilled. */ @@ -565,12 +580,15 @@ grub_ohci_transfer (grub_usb_controller_t dev, case GRUB_USB_TRANSACTION_TYPE_CONTROL: { + grub_dprintf ("ohci", "add to control list\n"); + /* Set ControlList Head and Current */ grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD, ed_addr); grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLCURR, 0); /* Enable the Control list. */ - control |= 1 << 4; + control |= GRUB_OHCI_REG_CONTROL_CONTROL_ENABLE; + control &= ~GRUB_OHCI_REG_CONTROL_BULK_ENABLE; grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, control); /* Set ControlListFilled. */ @@ -581,9 +599,11 @@ grub_ohci_transfer (grub_usb_controller_t dev, } grub_dprintf ("ohci", "wait for completion\n"); - grub_dprintf ("ohci", "control=0x%02x status=0x%02x\n", + grub_dprintf ("ohci", "begin: control=0x%02x status=0x%02x\n", grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL), grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS)); + grub_dprintf ("ohci","intstatus=0x%02x\n", + grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS)); /* Safety measure to avoid a hang. */ maxtime = grub_get_time_ms () + 1000; @@ -591,30 +611,34 @@ grub_ohci_transfer (grub_usb_controller_t dev, /* Wait until the transfer is completed or STALLs. */ do { - grub_cpu_idle (); + /* Check transfer status */ + intstatus = grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); + if ((intstatus & 0x2) != 0) + { + grub_dprintf ("ohci", "Current HccaDoneHead=0x%08x\n", + o->hcca->donehead); + /* Remember last successful TD */ + tderr_addr = grub_le_to_cpu32 (o->hcca->donehead) & ~0xf; + /* Reset DoneHead */ + o->hcca->donehead = 0; + grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1)); + /* if TD is last, finish */ + if (tderr_addr == td_list_addr + + sizeof (td_list[0]) * (transfer->transcnt - 1)) + break; + continue; + } + + if ((intstatus & 0x10) != 0) + { /* Unrecoverable error - only reset can help...! */ + err_unrec = 1; + break; + } /* Detected a HALT. */ if (grub_le_to_cpu32 (ed->td_head) & 1) break; - - if ((grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS) & 0x2) != 0) - { - if ((grub_le_to_cpu32 (o->hcca->donehead) & ~0xf) - == td_list_addr + (transfer->transcnt - 1) * sizeof (td_list[0])) - break; - /* Done Head can be updated on some another place if ED is halted. */ - if (grub_le_to_cpu32 (ed->td_head) & 1) - break; - - /* If there is not HALT in ED, it is not correct, so debug it, reset - * donehead and WDH and continue waiting. */ - grub_dprintf ("ohci", "Incorrect HccaDoneHead=0x%08x\n", - o->hcca->donehead); - o->hcca->donehead = 0; - grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1)); - continue; - } /* Timeout ? */ if (grub_get_time_ms () > maxtime) { @@ -627,32 +651,83 @@ grub_ohci_transfer (grub_usb_controller_t dev, if ((ed->td_head & ~0xf) == (ed->td_tail & ~0xf)) break; + + grub_cpu_idle (); } while (1); + grub_dprintf ("ohci", "end: control=0x%02x status=0x%02x\n", + grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL), + grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS)); + grub_dprintf ("ohci", "intstatus=0x%02x\n", + grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS)); + + if (!tderr_addr) + { + /* It means that something wrong happened, + * it could be: + * - timeout and no TD processed + * - some or unrecoverable error and no TD processed + * - something unexpected... :-( */ + /* Try look into DONEHEAD reg., but there should be also zero */ + grub_dprintf("ohci", "HCCA DoneHead is zero, something is bad!\n"); + tderr_addr = grub_ohci_readreg32 (o, GRUB_OHCI_REG_DONEHEAD) & ~0xf; + } + + /* Remember last processed transaction (TD) - it is necessary for + * proper setting of toggle bit in next transaction. */ + transfer->last_trans = ((tderr_addr - td_list_addr) / sizeof (*td_list)); + grub_dprintf("ohci", "tderr_addr=0x%x, td_list_addr=0x%x,\n", + tderr_addr, td_list_addr); + + if ((ed->td_head & ~0xf) == (ed->td_tail & ~0xf)) + transfer->last_trans = transfer->transcnt - 1; + + /* Check correct value in last_trans */ + /* It could happen if timeout happens and no TD was retired */ + if (transfer->last_trans >= transfer->transcnt || !tderr_addr) + { + grub_dprintf("ohci", "tderr==0 or out of TDs range!\n"); + grub_dprintf("ohci", "last_trans=%d, transcnt=%d\n", + transfer->last_trans, transfer->transcnt); + + /* We should set something valid... */ + transfer->last_trans = -1; /* Probably no TD done */ + tderr_addr = td_list_addr; + } + + /* In case of timeout do not detect error from TD */ if (err_timeout) { err = GRUB_ERR_TIMEOUT; - grub_dprintf("ohci", "Timeout, target=%08x, head=%08x\n\t\ttail=%08x, next=%08x\n", - grub_le_to_cpu32(ed->target), - grub_le_to_cpu32(ed->td_head), - grub_le_to_cpu32(ed->td_tail), - grub_le_to_cpu32(ed->next_ed)); + grub_dprintf("ohci", "Timeout, target=%08x, head=%08x\n", + grub_le_to_cpu32(ed->target), + grub_le_to_cpu32(ed->td_head)); + grub_dprintf("ohci", "tail=%08x, next=%08x\n", + grub_le_to_cpu32(ed->td_tail), + grub_le_to_cpu32(ed->next_ed)); + } + /* In case of unrecoverable error do not detect error from TD */ + else if (err_unrec) + { + err = GRUB_USB_ERR_UNRECOVERABLE; + grub_dprintf("ohci", + "Unrecoverable error, target=%08x, head=%08x\n", + grub_le_to_cpu32(ed->target), + grub_le_to_cpu32(ed->td_head)); + grub_dprintf("ohci", "tail=%08x, next=%08x\n", + grub_le_to_cpu32(ed->td_tail), + grub_le_to_cpu32(ed->next_ed)); } else if (grub_le_to_cpu32 (ed->td_head) & 1) { - grub_uint32_t td_err_addr; grub_uint8_t errcode; grub_ohci_td_t tderr = NULL; - td_err_addr = (grub_ohci_readreg32 (o, GRUB_OHCI_REG_DONEHEAD) & ~0xf); - if (td_err_addr == 0) - /* If DONEHEAD==0 it means that correct address is in HCCA. - * It should be always now! */ - td_err_addr = (grub_le_to_cpu32 (o->hcca->donehead) & ~0xf); + transfer->last_trans--; tderr = (grub_ohci_td_t) ((char *) td_list - + (td_err_addr - td_list_addr)); + + (tderr_addr - td_list_addr)); errcode = grub_le_to_cpu32 (tderr->token) >> 28; grub_dprintf ("ohci", "OHCI errcode=0x%02x\n", errcode); @@ -701,17 +776,17 @@ grub_ohci_transfer (grub_usb_controller_t dev, case 8: /* XXX: Data overrun error. */ err = GRUB_USB_ERR_DATA; - j = ((grub_uint32_t)tderr - (grub_uint32_t)td_list) / sizeof (*td_list); - grub_dprintf ("ohci", "Overrun, failed TD address: %p, index: %d\n", tderr, j); + grub_dprintf ("ohci", "Overrun, failed TD address: %p, index: %d\n", + tderr, transfer->last_trans); break; case 9: /* XXX: Data underrun error. */ err = GRUB_USB_ERR_DATA; + grub_dprintf ("ohci", "Underrun, failed TD address: %p, index: %d\n", + tderr, transfer->last_trans); grub_dprintf ("ohci", "Underrun, number of not transferred bytes: %d\n", 1 + grub_le_to_cpu32 (tderr->buffer_end) - grub_le_to_cpu32 (tderr->buffer)); - j = ((grub_uint32_t)tderr - (grub_uint32_t)td_list) / sizeof (*td_list); - grub_dprintf ("ohci", "Underrun, failed TD address: %p, index: %d\n", tderr, j); break; case 10: @@ -763,7 +838,8 @@ grub_ohci_transfer (grub_usb_controller_t dev, /* SF bit reset. (SF bit indicates Start Of Frame (SOF) packet) */ grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1<<2)); /* Wait for new SOF */ - while ((grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS) & 0x4) == 0); + while (((grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS) & 0x4) == 0) + && !err_unrec); /* Now it should be safe to change CONTROL and BULK lists. */ /* Important cleaning. */ @@ -773,7 +849,29 @@ grub_ohci_transfer (grub_usb_controller_t dev, grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLCURR, 0); grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, 0); grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKCURR, 0); - + + if (err_unrec) + { + /* Do OHCI reset in case of unrecoverable error - maybe we will need + * do more - re-enumerate bus etc. (?) */ + + /* Suspend the OHCI by issuing a reset. */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, 1); /* XXX: Magic. */ + grub_millisleep (1); + grub_dprintf ("ohci", "Unrecoverable error - OHCI reset\n"); + + /* Misc. resets. */ + o->hcca->donehead = 0; + grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, 0x7f); /* Clears everything */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD, 0); + grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLCURR, 0); + grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, 0); + grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKCURR, 0); + + /* Enable the OHCI. */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, (2 << 6)); + } + grub_dprintf ("ohci", "OHCI finished, freeing, err=0x%02x\n", err); grub_dma_free (td_list_chunk); @@ -782,11 +880,6 @@ grub_ohci_transfer (grub_usb_controller_t dev, return err; } -#define GRUB_OHCI_SET_PORT_ENABLE (1 << 1) -#define GRUB_OHCI_CLEAR_PORT_ENABLE (1 << 0) -#define GRUB_OHCI_SET_PORT_RESET (1 << 4) -#define GRUB_OHCI_SET_PORT_RESET_STATUS_CHANGE (1 << 20) - static grub_err_t grub_ohci_portstatus (grub_usb_controller_t dev, unsigned int port, unsigned int enable) @@ -869,7 +962,10 @@ grub_ohci_fini_hw (int noreturn __attribute__ ((unused))) grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, 0); grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKCURR, 0); grub_ohci_writereg32 (o, GRUB_OHCI_REG_DONEHEAD, 0); + grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, 0); + grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, 1); } + grub_millisleep (10); return GRUB_ERR_NONE; } diff --git a/bus/usb/uhci.c b/bus/usb/uhci.c index eb533c926..1510f98e8 100644 --- a/bus/usb/uhci.c +++ b/bus/usb/uhci.c @@ -332,13 +332,20 @@ grub_free_td (struct grub_uhci *u, grub_uhci_td_t td) } static void -grub_free_queue (struct grub_uhci *u, grub_uhci_td_t td) +grub_free_queue (struct grub_uhci *u, grub_uhci_td_t td, + grub_usb_transfer_t transfer) { - /* Free the TDs in this queue. */ - while (td) + int i; /* Index of TD in transfer */ + + /* Free the TDs in this queue and set last_trans. */ + for (i=0; td; i++) { grub_uhci_td_t tdprev; + /* Check state of TD and possibly set last_trans */ + if (transfer && (td->linkptr & 1)) + transfer->last_trans = i; + /* Unlink the queue. */ tdprev = td; td = (grub_uhci_td_t) td->linkptr2; @@ -461,7 +468,7 @@ grub_uhci_transfer (grub_usb_controller_t dev, td_prev->linkptr = 1; if (td_first) - grub_free_queue (u, td_first); + grub_free_queue (u, td_first, NULL); return GRUB_USB_ERR_INTERNAL; } @@ -560,7 +567,7 @@ grub_uhci_transfer (grub_usb_controller_t dev, /* Place the QH back in the free list and deallocate the associated TDs. */ qh->elinkptr = 1; - grub_free_queue (u, td_first); + grub_free_queue (u, td_first, transfer); return err; } @@ -609,7 +616,7 @@ grub_uhci_portstatus (grub_usb_controller_t dev, grub_uhci_writereg16 (u, reg, enable << 9); /* Wait for the reset to complete. XXX: How long exactly? */ - grub_millisleep (10); + grub_millisleep (50); /* For root hub should be nominaly 50ms */ status = grub_uhci_readreg16 (u, reg); grub_uhci_writereg16 (u, reg, status & ~(1 << 9)); grub_dprintf ("uhci", "reset completed\n"); diff --git a/bus/usb/usb.c b/bus/usb/usb.c index 7df148333..c872e9276 100644 --- a/bus/usb/usb.c +++ b/bus/usb/usb.c @@ -105,10 +105,7 @@ grub_usb_clear_halt (grub_usb_device_t dev, int endpoint) grub_usb_err_t grub_usb_set_configuration (grub_usb_device_t dev, int configuration) { - int i; - - for (i = 0; i < 256; i++) - dev->toggle[i] = 0; + grub_memset (dev->toggle, 0, sizeof (dev->toggle)); return grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT | GRUB_USB_REQTYPE_STANDARD diff --git a/bus/usb/usbtrans.c b/bus/usb/usbtrans.c index 0bf5ee6de..e1b9097e6 100644 --- a/bus/usb/usbtrans.c +++ b/bus/usb/usbtrans.c @@ -76,7 +76,7 @@ grub_usb_control_msg (grub_usb_device_t dev, setupdata_addr = grub_dma_get_phys (setupdata_chunk); /* Determine the maximum packet size. */ - if (dev->initialized && dev->descdev.maxsize0) + if (dev->descdev.maxsize0) max = dev->descdev.maxsize0; else max = 64; @@ -213,6 +213,7 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, transfer->type = GRUB_USB_TRANSACTION_TYPE_BULK; transfer->max = max; transfer->dev = dev; + transfer->last_trans = -1; /* Reset index of last processed transaction (TD) */ /* Allocate an array of transfer data structures. */ transfer->transactions = grub_malloc (transfer->transcnt @@ -240,6 +241,13 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, } err = dev->controller.dev->transfer (&dev->controller, transfer); + /* We must remember proper toggle value even if some transactions + * were not processed - correct value should be inversion of last + * processed transaction (TD). */ + if (transfer->last_trans >= 0) + toggle = transfer->transactions[transfer->last_trans].toggle ? 0 : 1; + else + toggle = dev->toggle[endpoint]; /* Nothing done, take original */ grub_dprintf ("usb", "toggle=%d\n", toggle); dev->toggle[endpoint] = toggle; diff --git a/commands/cat.c b/commands/cat.c index 3bdafc4c6..4c0e19bc2 100644 --- a/commands/cat.c +++ b/commands/cat.c @@ -23,19 +23,28 @@ #include #include #include -#include +#include #include -static grub_err_t -grub_cmd_cat (grub_command_t cmd __attribute__ ((unused)), - int argc, char **args) +static const struct grub_arg_option options[] = + { + {"dos", -1, 0, N_("Accept DOS-style CR/NL line endings."), 0, 0}, + {0, 0, 0, 0, 0, 0} + }; +static grub_err_t +grub_cmd_cat (grub_extcmd_t cmd, int argc, char **args) { + struct grub_arg_list *state = cmd->state; + int dos = 0; grub_file_t file; char buf[GRUB_DISK_SECTOR_SIZE]; grub_ssize_t size; int key = 0; + if (state[0].set) + dos = 1; + if (argc != 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); @@ -54,6 +63,11 @@ grub_cmd_cat (grub_command_t cmd __attribute__ ((unused)), if ((grub_isprint (c) || grub_isspace (c)) && c != '\r') grub_putchar (c); + else if (dos && c == '\r' && buf[i + 1] == '\n') + { + grub_putchar ('\n'); + i++; + } else { grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT); @@ -74,15 +88,16 @@ grub_cmd_cat (grub_command_t cmd __attribute__ ((unused)), return 0; } -static grub_command_t cmd; +static grub_extcmd_t cmd; GRUB_MOD_INIT(cat) { - cmd = grub_register_command_p1 ("cat", grub_cmd_cat, - N_("FILE"), N_("Show the contents of a file.")); + cmd = grub_register_extcmd ("cat", grub_cmd_cat, GRUB_COMMAND_FLAG_BOTH, + N_("FILE"), N_("Show the contents of a file."), + options); } GRUB_MOD_FINI(cat) { - grub_unregister_command (cmd); + grub_unregister_extcmd (cmd); } diff --git a/commands/gptsync.c b/commands/gptsync.c index d217b5d5c..6364c13f7 100644 --- a/commands/gptsync.c +++ b/commands/gptsync.c @@ -138,8 +138,8 @@ grub_cmd_gptsync (grub_command_t cmd __attribute__ ((unused)), { grub_device_close (dev); return grub_error (GRUB_ERR_OUT_OF_RANGE, - "only partitions resding in the first 2TB " - "can be presen in hybrid MBR"); + "only partitions residing in the first 2TB " + "can be present in hybrid MBR"); } @@ -243,8 +243,8 @@ GRUB_MOD_INIT(gptsync) cmd = grub_register_command ("gptsync", grub_cmd_gptsync, N_("DEVICE [PARTITION[+/-[TYPE]]] ..."), N_("Fill hybrid MBR of GPT drive DEVICE. " - "specified partitions will be a part " - "of hybrid mbr. Up to 3 partitions are " + "Specified partitions will be a part " + "of hybrid MBR. Up to 3 partitions are " "allowed. TYPE is an MBR type. " "+ means that partition is active. " "Only one partition can be active.")); diff --git a/commands/handler.c b/commands/handler.c deleted file mode 100644 index f9270972b..000000000 --- a/commands/handler.c +++ /dev/null @@ -1,101 +0,0 @@ -/* handler.c - commands to list or select handlers */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2009 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GRUB. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include - -static grub_err_t -grub_cmd_handler (struct grub_command *cmd __attribute__ ((unused)), - int argc, char **args) -{ - void *curr_item = 0; - grub_handler_class_t head; - - auto int list_item (grub_named_list_t item); - int list_item (grub_named_list_t item) - { - if (item == curr_item) - grub_putchar ('*'); - - grub_printf ("%s\n", item->name); - - return 0; - } - - head = grub_handler_class_list; - 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; - - class_name = args[0]; - argc--; - args++; - - class = grub_named_list_find (GRUB_AS_NAMED_LIST (head), class_name); - if (! class) - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "class not found"); - - if (argc == 0) - { - curr_item = class->cur_handler; - grub_list_iterate (GRUB_AS_LIST (class->handler_list), - (grub_list_hook_t) list_item); - } - else - { - grub_handler_t handler; - - handler = - grub_named_list_find (GRUB_AS_NAMED_LIST (class->handler_list), - args[0]); - - if (! handler) - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "handler not found"); - - grub_handler_set_current (class, handler); - } - } - - return 0; -} - -static grub_command_t cmd_handler; - -GRUB_MOD_INIT(handler) -{ - cmd_handler = - grub_register_command ("handler", grub_cmd_handler, - N_("[class [handler]]"), - N_("List or select a handler.")); -} - -GRUB_MOD_FINI(handler) -{ - grub_unregister_command (cmd_handler); -} diff --git a/commands/help.c b/commands/help.c index c2aad03b2..ecf77fa4c 100644 --- a/commands/help.c +++ b/commands/help.c @@ -33,94 +33,87 @@ grub_cmd_help (grub_extcmd_t ext __attribute__ ((unused)), int argc, int cnt = 0; char *currarg; - auto int print_command_info (grub_command_t cmd); - auto int print_command_help (grub_command_t cmd); - - int print_command_info (grub_command_t cmd) - { - 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; - grub_uint32_t *unicode_command_help; - grub_uint32_t *unicode_last_position; - - command_help = grub_xasprintf ("%s %s", cmd->name, summary_translated); - if (!command_help) - return 1; - - grub_utf8_to_ucs4_alloc (command_help, &unicode_command_help, - &unicode_last_position); - - FOR_ACTIVE_TERM_OUTPUTS(term) - { - unsigned stringwidth; - grub_uint32_t *unicode_last_screen_position; - - unicode_last_screen_position = unicode_command_help; - - 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); - } - return 0; - } - - int print_command_help (grub_command_t cmd) - { - if (cmd->prio & GRUB_PRIO_LIST_FLAG_ACTIVE) - { - if (! grub_strncmp (cmd->name, currarg, grub_strlen (currarg))) - { - if (cnt++ > 0) - grub_printf ("\n\n"); - - if (cmd->flags & GRUB_COMMAND_FLAG_EXTCMD) - grub_arg_show_help ((grub_extcmd_t) cmd->data); - else - grub_printf ("%s %s %s\n%s\n", _("Usage:"), cmd->name, _(cmd->summary), - _(cmd->description)); - } - } - return 0; - } - if (argc == 0) { - grub_command_iterate (print_command_info); + grub_command_t cmd; + FOR_COMMANDS(cmd) + { + 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; + grub_uint32_t *unicode_command_help; + grub_uint32_t *unicode_last_position; + + command_help = grub_xasprintf ("%s %s", cmd->name, summary_translated); + if (!command_help) + break; + + grub_utf8_to_ucs4_alloc (command_help, &unicode_command_help, + &unicode_last_position); + + FOR_ACTIVE_TERM_OUTPUTS(term) + { + unsigned stringwidth; + grub_uint32_t *unicode_last_screen_position; + + unicode_last_screen_position = unicode_command_help; + + 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); + } + } if (!(cnt % 2)) grub_printf ("\n"); } else { int i; + grub_command_t cmd; for (i = 0; i < argc; i++) { currarg = args[i]; - grub_command_iterate (print_command_help); + FOR_COMMANDS(cmd) + { + if (cmd->prio & GRUB_PRIO_LIST_FLAG_ACTIVE) + { + if (! grub_strncmp (cmd->name, currarg, grub_strlen (currarg))) + { + if (cnt++ > 0) + grub_printf ("\n\n"); + + if (cmd->flags & GRUB_COMMAND_FLAG_EXTCMD) + grub_arg_show_help ((grub_extcmd_t) cmd->data); + else + grub_printf ("%s %s %s\n%s\b", _("Usage:"), cmd->name, _(cmd->summary), + _(cmd->description)); + } + } + } } } diff --git a/commands/minicmd.c b/commands/minicmd.c index 4ea9efead..92d262caf 100644 --- a/commands/minicmd.c +++ b/commands/minicmd.c @@ -301,27 +301,23 @@ grub_mini_cmd_lsmod (struct grub_command *cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), char *argv[] __attribute__ ((unused))) { - auto int print_module (grub_dl_t mod); - - int print_module (grub_dl_t mod) - { - grub_dl_dep_t dep; - - grub_printf ("%s\t%d\t\t", mod->name, mod->ref_count); - for (dep = mod->dep; dep; dep = dep->next) - { - if (dep != mod->dep) - grub_putchar (','); - - grub_printf ("%s", dep->mod->name); - } - grub_putchar ('\n'); - - return 0; - } + grub_dl_t mod; grub_printf ("Name\tRef Count\tDependencies\n"); - grub_dl_iterate (print_module); + FOR_DL_MODULES (mod) + { + grub_dl_dep_t dep; + + grub_printf ("%s\t%d\t\t", mod->name, mod->ref_count); + for (dep = mod->dep; dep; dep = dep->next) + { + if (dep != mod->dep) + grub_putchar (','); + + grub_printf ("%s", dep->mod->name); + } + grub_putchar ('\n'); + } return 0; } diff --git a/commands/setpci.c b/commands/setpci.c index fbc7c214e..aa09f5bbb 100644 --- a/commands/setpci.c +++ b/commands/setpci.c @@ -96,7 +96,7 @@ grub_setpci_iter (grub_pci_device_t dev, grub_pci_id_t pciid) if (check_device && grub_pci_get_device (dev) != device) return 0; - if (check_function && grub_pci_get_function (dev) != device) + if (check_function && grub_pci_get_function (dev) != function) return 0; addr = grub_pci_make_address (dev, regaddr); diff --git a/commands/usbtest.c b/commands/usbtest.c index 7d1f85cfd..191c4e4df 100644 --- a/commands/usbtest.c +++ b/commands/usbtest.c @@ -148,8 +148,6 @@ usb_iterate (grub_usb_device_t dev) grub_printf ("%s speed device\n", usb_devspeed[dev->speed]); - return 0; - for (i = 0; i < descdev->configcnt; i++) { struct grub_usb_desc_config *config; diff --git a/commands/videotest.c b/commands/videotest.c index 390811a71..f6a786e79 100644 --- a/commands/videotest.c +++ b/commands/videotest.c @@ -38,15 +38,8 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), unsigned int width; unsigned int height; int i; - grub_font_t sansbig; - grub_font_t sans; - grub_font_t sanssmall; - grub_font_t fixed; - struct grub_font_glyph *glyph; struct grub_video_render_target *text_layer; grub_video_color_t palette[16]; - const char *str; - int texty; err = grub_video_set_mode ("auto", GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0); if (err) @@ -54,102 +47,115 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), grub_video_get_viewport (&x, &y, &width, &height); - grub_video_create_render_target (&text_layer, width, height, - GRUB_VIDEO_MODE_TYPE_RGB - | GRUB_VIDEO_MODE_TYPE_ALPHA); + { + const char *str; + int texty; + grub_font_t sansbig; + grub_font_t sans; + grub_font_t sanssmall; + grub_font_t fixed; + struct grub_font_glyph *glyph; - grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); + grub_video_create_render_target (&text_layer, width, height, + GRUB_VIDEO_MODE_TYPE_RGB + | GRUB_VIDEO_MODE_TYPE_ALPHA); - color = grub_video_map_rgb (0, 0, 0); - grub_video_fill_rect (color, 0, 0, width, height); + grub_video_set_active_render_target (text_layer); - color = grub_video_map_rgb (255, 0, 0); - grub_video_fill_rect (color, 0, 0, 100, 100); + color = grub_video_map_rgb (0, 255, 255); + sansbig = grub_font_get ("Unknown Regular 16"); + sans = grub_font_get ("Unknown Regular 16"); + sanssmall = grub_font_get ("Unknown Regular 16"); + fixed = grub_font_get ("Fixed 20"); + if (! sansbig || ! sans || ! sanssmall || ! fixed) + return grub_error (GRUB_ERR_BAD_FONT, "no font loaded"); - color = grub_video_map_rgb (0, 255, 255); - grub_video_fill_rect (color, 100, 100, 100, 100); + glyph = grub_font_get_glyph (fixed, '*'); + grub_font_draw_glyph (glyph, color, 200 ,0); - sansbig = grub_font_get ("Unknown Regular 16"); - sans = grub_font_get ("Unknown Regular 16"); - sanssmall = grub_font_get ("Unknown Regular 16"); - fixed = grub_font_get ("Fixed 20"); - if (! sansbig || ! sans || ! sanssmall || ! fixed) - return grub_error (GRUB_ERR_BAD_FONT, "no font loaded"); + color = grub_video_map_rgb (255, 255, 255); - glyph = grub_font_get_glyph (fixed, '*'); - grub_font_draw_glyph (glyph, color, 200 ,0); + texty = 32; + grub_font_draw_string ("The quick brown fox jumped over the lazy dog.", + sans, color, 16, texty); + texty += grub_font_get_descent (sans) + grub_font_get_leading (sans); - grub_video_set_viewport (x + 150, y + 150, - width - 150 * 2, height - 150 * 2); - color = grub_video_map_rgb (77, 33, 77); - grub_video_fill_rect (color, 0, 0, width, height); + texty += grub_font_get_ascent (fixed); + grub_font_draw_string ("The quick brown fox jumped over the lazy dog.", + fixed, color, 16, texty); + texty += grub_font_get_descent (fixed) + grub_font_get_leading (fixed); - grub_video_set_active_render_target (text_layer); - - color = grub_video_map_rgb (255, 255, 255); - - texty = 32; - grub_font_draw_string ("The quick brown fox jumped over the lazy dog.", - sans, color, 16, texty); - texty += grub_font_get_descent (sans) + grub_font_get_leading (sans); - - texty += grub_font_get_ascent (fixed); - grub_font_draw_string ("The quick brown fox jumped over the lazy dog.", - fixed, color, 16, texty); - texty += grub_font_get_descent (fixed) + grub_font_get_leading (fixed); - - /* To convert Unicode characters into UTF-8 for this test, the following - command is useful: + /* To convert Unicode characters into UTF-8 for this test, the following + command is useful: echo -ne '\x00\x00\x26\x3A' | iconv -f UTF-32BE -t UTF-8 | od -t x1 - This converts the Unicode character U+263A to UTF-8. */ + This converts the Unicode character U+263A to UTF-8. */ - /* Characters used: - Code point Description UTF-8 encoding - ----------- ------------------------------ -------------- - U+263A unfilled smiley face E2 98 BA - U+00A1 inverted exclamation point C2 A1 - U+00A3 British pound currency symbol C2 A3 - U+03C4 Greek tau CF 84 - U+00E4 lowercase letter a with umlaut C3 A4 - U+2124 set 'Z' symbol (integers) E2 84 A4 - U+2287 subset symbol E2 8A 87 - U+211D set 'R' symbol (real numbers) E2 84 9D */ + /* Characters used: + Code point Description UTF-8 encoding + ----------- ------------------------------ -------------- + U+263A unfilled smiley face E2 98 BA + U+00A1 inverted exclamation point C2 A1 + U+00A3 British pound currency symbol C2 A3 + U+03C4 Greek tau CF 84 + U+00E4 lowercase letter a with umlaut C3 A4 + U+2124 set 'Z' symbol (integers) E2 84 A4 + U+2287 subset symbol E2 8A 87 + U+211D set 'R' symbol (real numbers) E2 84 9D */ - str = - "Unicode test: happy\xE2\x98\xBA \xC2\xA3 5.00" - " \xC2\xA1\xCF\x84\xC3\xA4u! " - " \xE2\x84\xA4\xE2\x8A\x87\xE2\x84\x9D"; - color = grub_video_map_rgb (128, 128, 255); + str = + "Unicode test: happy\xE2\x98\xBA \xC2\xA3 5.00" + " \xC2\xA1\xCF\x84\xC3\xA4u! " + " \xE2\x84\xA4\xE2\x8A\x87\xE2\x84\x9D"; + color = grub_video_map_rgb (128, 128, 255); - /* All characters in the string exist in the 'Fixed 20' (10x20) font. */ - texty += grub_font_get_ascent(fixed); - grub_font_draw_string (str, fixed, color, 16, texty); - texty += grub_font_get_descent (fixed) + grub_font_get_leading (fixed); + /* All characters in the string exist in the 'Fixed 20' (10x20) font. */ + texty += grub_font_get_ascent(fixed); + grub_font_draw_string (str, fixed, color, 16, texty); + texty += grub_font_get_descent (fixed) + grub_font_get_leading (fixed); - texty += grub_font_get_ascent(sansbig); - grub_font_draw_string (str, sansbig, color, 16, texty); - texty += grub_font_get_descent (sansbig) + grub_font_get_leading (sansbig); + texty += grub_font_get_ascent(sansbig); + grub_font_draw_string (str, sansbig, color, 16, texty); + texty += grub_font_get_descent (sansbig) + grub_font_get_leading (sansbig); - texty += grub_font_get_ascent(sans); - grub_font_draw_string (str, sans, color, 16, texty); - texty += grub_font_get_descent (sans) + grub_font_get_leading (sans); + texty += grub_font_get_ascent(sans); + grub_font_draw_string (str, sans, color, 16, texty); + texty += grub_font_get_descent (sans) + grub_font_get_leading (sans); - texty += grub_font_get_ascent(sanssmall); - grub_font_draw_string (str, sanssmall, color, 16, texty); - texty += (grub_font_get_descent (sanssmall) - + grub_font_get_leading (sanssmall)); + texty += grub_font_get_ascent(sanssmall); + grub_font_draw_string (str, sanssmall, color, 16, texty); + texty += (grub_font_get_descent (sanssmall) + + grub_font_get_leading (sanssmall)); - glyph = grub_font_get_glyph (fixed, '*'); + glyph = grub_font_get_glyph (fixed, '*'); - for (i = 0; i < 16; i++) - { - color = grub_video_map_color (i); - palette[i] = color; - grub_font_draw_glyph (glyph, color, 16 + i * 16, 220); - } + for (i = 0; i < 16; i++) + { + color = grub_video_map_color (i); + palette[i] = color; + grub_font_draw_glyph (glyph, color, 16 + i * 16, 220); + } + } grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); + for (i = 0; i < 2; i++) + { + color = grub_video_map_rgb (0, 0, 0); + grub_video_fill_rect (color, 0, 0, width, height); + + color = grub_video_map_rgb (255, 0, 0); + grub_video_fill_rect (color, 0, 0, 100, 100); + + color = grub_video_map_rgb (0, 255, 255); + grub_video_fill_rect (color, 100, 100, 100, 100); + + grub_video_set_viewport (x + 150, y + 150, + width - 150 * 2, height - 150 * 2); + color = grub_video_map_rgb (77, 33, 77); + grub_video_fill_rect (color, 0, 0, width, height); + grub_video_swap_buffers (); + } + for (i = 0; i < 5; i++) { color = grub_video_map_rgb (i, 33, 77); diff --git a/conf/any-emu.rmk b/conf/any-emu.rmk index 000996172..958da2bee 100644 --- a/conf/any-emu.rmk +++ b/conf/any-emu.rmk @@ -3,7 +3,7 @@ kernel_img_RELOCATABLE = yes pkglib_PROGRAMS = kernel.img kernel_img_SOURCES = kern/device.c kern/disk.c kern/dl.c kern/env.c \ - kern/err.c kern/list.c kern/handler.c kern/command.c \ + kern/err.c kern/list.c kern/command.c \ kern/corecmd.c kern/file.c kern/fs.c kern/main.c kern/misc.c \ kern/parser.c kern/partition.c kern/term.c \ kern/rescue_reader.c kern/rescue_parser.c \ @@ -20,14 +20,14 @@ TARGET_NO_STRIP = yes ifneq ($(TARGET_NO_MODULES), yes) kernel_img_SOURCES += symlist.c kern/$(target_cpu)/dl.c +else +kernel_img_SOURCES += grub_emu_init.c +endif ifneq ($(target_cpu), i386) ifneq ($(target_cpu), x86_64) kernel_img_SOURCES += kern/$(target_cpu)/cache.S endif endif -else -kernel_img_SOURCES += grub_emu_init.c -endif # For halt.mod. pkglib_MODULES += halt.mod diff --git a/conf/common.rmk b/conf/common.rmk index beee25be9..c98060a29 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -1,7 +1,7 @@ # -*- makefile -*- # Used by various components. These rules need to precede them. -script/lexer.c_DEPENDENCIES = grub_script.tab.h +script/lexer.c_DEPENDENCIES = grub_script.tab.h grub_script.yy.h sbin_UTILITIES += grub-mkdevicemap grub_mkdevicemap_SOURCES = gnulib/progname.c util/grub-mkdevicemap.c \ @@ -27,7 +27,7 @@ util/grub-probe.c_DEPENDENCIES = grub_probe_init.h grub_probe_SOURCES = gnulib/progname.c util/grub-probe.c \ kern/emu/hostdisk.c util/misc.c kern/emu/misc.c kern/emu/getroot.c kern/emu/mm.c \ kern/device.c kern/disk.c kern/err.c kern/misc.c \ - kern/parser.c kern/partition.c kern/file.c kern/list.c \ + kern/partition.c kern/file.c kern/list.c \ \ fs/affs.c fs/cpio.c fs/fat.c fs/ext2.c fs/hfs.c \ fs/hfsplus.c fs/iso9660.c fs/udf.c fs/jfs.c fs/minix.c \ @@ -88,21 +88,21 @@ DISTCLEANFILES += grub_script.yy.c grub_script.yy.h # For grub-script-check. bin_UTILITIES += grub-script-check -util/grub-script-check.c_DEPENDENCIES = grub_script_check_init.h grub_script_check_SOURCES = gnulib/progname.c gnulib/getdelim.c gnulib/getline.c \ util/grub-script-check.c util/misc.c kern/emu/misc.c kern/emu/mm.c \ script/main.c script/script.c script/function.c script/lexer.c \ - kern/handler.c kern/err.c kern/parser.c kern/list.c \ - kern/misc.c kern/env.c grub_script_check_init.c grub_script.tab.c \ + kern/err.c kern/list.c \ + kern/misc.c kern/env.c grub_script.tab.c \ grub_script.yy.c grub_script_check_CFLAGS = $(GNULIB_UTIL_CFLAGS) +grub_script_check_DEPENDENCIES = grub_script.tab.h MOSTLYCLEANFILES += symlist.c kernel_syms.lst DEFSYMFILES += kernel_syms.lst kernel_img_HEADERS += boot.h cache.h device.h disk.h dl.h elf.h elfload.h \ env.h err.h file.h fs.h kernel.h loader.h misc.h mm.h net.h parser.h \ partition.h msdos_partition.h reader.h symbol.h term.h time.h types.h \ - list.h handler.h command.h i18n.h env_private.h libgcc.h + list.h command.h i18n.h env_private.h libgcc.h ifneq ($(platform), emu) kernel_img_HEADERS += machine/memory.h machine/loader.h @@ -119,19 +119,6 @@ grub_script.tab.c grub_script.tab.h: script/parser.y $(YACC) -d -p grub_script_yy -b grub_script $(srcdir)/script/parser.y DISTCLEANFILES += grub_script.tab.c grub_script.tab.h -# For grub-script-check. -grub_script_check_init.lst: geninit.sh $(filter-out grub_script_check_init.c,$(grub_script_check_SOURCES)) - rm -f $@; grep GRUB_MOD_INIT $(filter %.c,$^) /dev/null > $@ -DISTCLEANFILES += grub_script_check_init.lst - -grub_script_check_init.h: grub_script_check_init.lst $(filter-out grub_script_check_init.c,$(grub_script_check_SOURCES)) geninitheader.sh - rm -f $@; sh $(srcdir)/geninitheader.sh $< > $@ -DISTCLEANFILES += grub_script_check_init.h - -grub_script_check_init.c: grub_script_check_init.lst $(filter-out grub_script_check_init.c,$(grub_script_check_SOURCES)) geninit.sh - rm -f $@; sh $(srcdir)/geninit.sh $< $(filter %.c,$^) > $@ -DISTCLEANFILES += grub_script_check_init.c - # For grub-probe. grub_probe_init.lst: geninit.sh $(filter-out grub_probe_init.c,$(grub_probe_SOURCES)) rm -f $@; grep GRUB_MOD_INIT $(filter %.c,$^) /dev/null > $@ @@ -215,10 +202,13 @@ CLEANFILES += grub-gettext_lib %: util/grub.d/%.in config.status ./config.status --file=$@:$< chmod +x $@ -grub-mkconfig_SCRIPTS = 00_header 30_os-prober 40_custom +grub-mkconfig_SCRIPTS = 00_header 30_os-prober 40_custom 41_custom ifneq (, $(host_kernel)) grub-mkconfig_SCRIPTS += 10_$(host_kernel) endif +ifeq (linux, $(host_kernel)) +grub-mkconfig_SCRIPTS += 20_linux_xen +endif CLEANFILES += $(grub-mkconfig_SCRIPTS) @@ -448,12 +438,12 @@ scsi_mod_CFLAGS = $(COMMON_CFLAGS) scsi_mod_LDFLAGS = $(COMMON_LDFLAGS) # Commands. -pkglib_MODULES += minicmd.mod extcmd.mod hello.mod handler.mod \ +pkglib_MODULES += minicmd.mod extcmd.mod hello.mod \ ls.mod cmp.mod cat.mod help.mod search.mod loopback.mod \ configfile.mod echo.mod \ terminfo.mod test.mod blocklist.mod hexdump.mod \ read.mod sleep.mod loadenv.mod crc.mod parttool.mod \ - msdospart.mod memrw.mod normal.mod sh.mod \ + msdospart.mod memrw.mod normal.mod \ gptsync.mod true.mod probe.mod password.mod \ keystatus.mod @@ -514,11 +504,6 @@ msdospart_mod_SOURCES = parttool/msdospart.c msdospart_mod_CFLAGS = $(COMMON_CFLAGS) msdospart_mod_LDFLAGS = $(COMMON_LDFLAGS) -# For handler.mod. -handler_mod_SOURCES = commands/handler.c -handler_mod_CFLAGS = $(COMMON_CFLAGS) -handler_mod_LDFLAGS = $(COMMON_LDFLAGS) - # For ls.mod. ls_mod_SOURCES = commands/ls.c ls_mod_CFLAGS = $(COMMON_CFLAGS) @@ -638,18 +623,14 @@ keystatus_mod_LDFLAGS = $(COMMON_LDFLAGS) # For normal.mod. normal_mod_SOURCES = normal/main.c normal/cmdline.c normal/dyncmd.c \ - normal/auth.c normal/autofs.c normal/handler.c \ + normal/auth.c normal/autofs.c \ normal/color.c normal/completion.c normal/datetime.c normal/menu.c \ normal/menu_entry.c normal/menu_text.c \ - normal/misc.c normal/crypto.c normal/term.c normal/context.c -normal_mod_CFLAGS = $(COMMON_CFLAGS) -normal_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For sh.mod. -sh_mod_SOURCES = script/main.c script/script.c script/execute.c \ + normal/misc.c normal/crypto.c normal/term.c normal/context.c \ + script/main.c script/script.c script/execute.c \ script/function.c script/lexer.c grub_script.tab.c grub_script.yy.c -sh_mod_CFLAGS = $(COMMON_CFLAGS) $(POSIX_CFLAGS) -Wno-error -sh_mod_LDFLAGS = $(COMMON_LDFLAGS) +normal_mod_CFLAGS = $(COMMON_CFLAGS) $(POSIX_CFLAGS) -Wno-error +normal_mod_LDFLAGS = $(COMMON_LDFLAGS) ifneq (, $(FONT_SOURCE)) font/font.c_DEPENDENCIES = ascii.h diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk index f6a375624..259f4e162 100644 --- a/conf/i386-coreboot.rmk +++ b/conf/i386-coreboot.rmk @@ -14,7 +14,7 @@ kernel_img_SOURCES = kern/i386/coreboot/startup.S \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ kern/misc.c kern/mm.c kern/term.c \ kern/rescue_parser.c kern/rescue_reader.c \ - kern/time.c kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ + kern/time.c kern/list.c kern/command.c kern/corecmd.c \ kern/$(target_cpu)/dl.c kern/parser.c kern/partition.c \ kern/i386/tsc.c kern/i386/pit.c \ kern/generic/rtc_get_time_ms.c \ diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk index 05ba38a65..7fb45003c 100644 --- a/conf/i386-ieee1275.rmk +++ b/conf/i386-ieee1275.rmk @@ -18,7 +18,7 @@ kernel_img_SOURCES = kern/i386/ieee1275/startup.S \ kern/rescue_parser.c kern/rescue_reader.c \ kern/$(target_cpu)/dl.c kern/parser.c kern/partition.c \ kern/env.c \ - kern/time.c kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ + kern/time.c kern/list.c kern/command.c kern/corecmd.c \ kern/generic/millisleep.c \ kern/ieee1275/ieee1275.c \ term/ieee1275/ofconsole.c \ diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index fa8394b52..96058e807 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -43,7 +43,7 @@ kernel_img_SOURCES = kern/i386/pc/startup.S \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ kern/misc.c kern/mm.c kern/term.c \ kern/rescue_parser.c kern/rescue_reader.c \ - kern/time.c kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ + kern/time.c kern/list.c kern/command.c kern/corecmd.c \ kern/$(target_cpu)/dl.c kern/i386/pc/init.c kern/i386/pc/mmap.c \ kern/parser.c kern/partition.c \ kern/i386/tsc.c kern/i386/pit.c \ @@ -66,7 +66,7 @@ util/i386/pc/grub-setup.c_DEPENDENCIES = grub_setup_init.h grub_setup_SOURCES = gnulib/progname.c util/i386/pc/grub-setup.c \ util/misc.c kern/emu/misc.c kern/emu/getroot.c \ kern/emu/hostdisk.c kern/device.c kern/disk.c kern/err.c \ - kern/misc.c kern/parser.c kern/partition.c kern/file.c \ + kern/misc.c kern/partition.c kern/file.c \ kern/emu/mm.c kern/fs.c kern/env.c kern/list.c fs/fshelp.c \ \ fs/affs.c fs/cpio.c fs/ext2.c fs/fat.c fs/hfs.c \ @@ -147,7 +147,7 @@ linux_mod_CFLAGS = $(COMMON_CFLAGS) linux_mod_LDFLAGS = $(COMMON_LDFLAGS) pkglib_MODULES += xnu.mod -xnu_mod_SOURCES = loader/xnu_resume.c loader/i386/xnu.c loader/i386/pc/xnu.c \ +xnu_mod_SOURCES = loader/xnu_resume.c loader/i386/xnu.c \ loader/macho32.c loader/macho64.c loader/macho.c loader/xnu.c xnu_mod_CFLAGS = $(COMMON_CFLAGS) xnu_mod_LDFLAGS = $(COMMON_LDFLAGS) diff --git a/conf/i386-qemu.rmk b/conf/i386-qemu.rmk index ff263245d..adb5f7f0f 100644 --- a/conf/i386-qemu.rmk +++ b/conf/i386-qemu.rmk @@ -13,24 +13,28 @@ boot_img_ASFLAGS = $(COMMON_ASFLAGS) -DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_M boot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)$(GRUB_BOOT_MACHINE_LINK_ADDR) boot_img_FORMAT = binary +kern/i386/qemu/init.c_DEPENDENCIES = ascii.h + pkglib_PROGRAMS += kernel.img kernel_img_SOURCES = kern/i386/qemu/startup.S \ kern/i386/misc.S \ kern/i386/coreboot/init.c \ + kern/i386/qemu/init.c \ kern/i386/qemu/mmap.c \ kern/i386/halt.c \ kern/main.c kern/device.c \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ kern/misc.c kern/mm.c kern/term.c \ kern/rescue_parser.c kern/rescue_reader.c \ - kern/time.c kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ + kern/time.c kern/list.c kern/command.c kern/corecmd.c \ kern/$(target_cpu)/dl.c kern/parser.c kern/partition.c \ kern/i386/tsc.c kern/i386/pit.c \ kern/generic/rtc_get_time_ms.c \ kern/generic/millisleep.c \ kern/env.c \ - term/i386/pc/vga_text.c term/i386/vga_common.c \ + term/i386/pc/vga_text.c term/i386/vga_common.c bus/pci.c \ symlist.c +kernel_img_HEADERS += pci.h kernel_img_CFLAGS = $(COMMON_CFLAGS) -DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR) kernel_img_ASFLAGS = $(COMMON_ASFLAGS) -DGRUB_KERNEL_MACHINE_LINK_ADDR=$(GRUB_KERNEL_MACHINE_LINK_ADDR) kernel_img_LDFLAGS += $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)$(GRUB_KERNEL_MACHINE_LINK_ADDR) diff --git a/conf/i386.rmk b/conf/i386.rmk index 73e818f9e..b1df584a6 100644 --- a/conf/i386.rmk +++ b/conf/i386.rmk @@ -15,6 +15,16 @@ vga_text_mod_SOURCES = term/i386/pc/vga_text.c term/i386/vga_common.c vga_text_mod_CFLAGS = $(COMMON_CFLAGS) vga_text_mod_LDFLAGS = $(COMMON_LDFLAGS) +pkglib_MODULES += video_cirrus.mod +video_cirrus_mod_SOURCES = video/cirrus.c +video_cirrus_mod_CFLAGS = $(COMMON_CFLAGS) +video_cirrus_mod_LDFLAGS = $(COMMON_LDFLAGS) + +pkglib_MODULES += video_bochs.mod +video_bochs_mod_SOURCES = video/bochs.c +video_bochs_mod_CFLAGS = $(COMMON_CFLAGS) +video_bochs_mod_LDFLAGS = $(COMMON_LDFLAGS) + pkglib_MODULES += relocator.mod relocator_mod_SOURCES = lib/i386/relocator.c lib/i386/relocator_asm.S lib/i386/relocator_backward.S relocator_mod_CFLAGS = $(COMMON_CFLAGS) @@ -50,11 +60,14 @@ serial_mod_SOURCES = term/serial.c serial_mod_CFLAGS = $(COMMON_CFLAGS) serial_mod_LDFLAGS = $(COMMON_LDFLAGS) +# On qemu it's compiled in +ifneq ($(platform), qemu) # For pci.mod pkglib_MODULES += pci.mod pci_mod_SOURCES = bus/pci.c pci_mod_CFLAGS = $(COMMON_CFLAGS) pci_mod_LDFLAGS = $(COMMON_LDFLAGS) +endif # For cs5536.mod pkglib_MODULES += cs5536.mod diff --git a/conf/mips-qemu-mips.rmk b/conf/mips-qemu-mips.rmk index 0d81bbe8b..be2b9f555 100644 --- a/conf/mips-qemu-mips.rmk +++ b/conf/mips-qemu-mips.rmk @@ -12,7 +12,7 @@ kernel_img_SOURCES = kern/$(target_cpu)/startup.S \ kern/disk.c kern/dl.c kern/err.c kern/file.c kern/fs.c \ kern/misc.c kern/mm.c kern/term.c \ kern/rescue_parser.c kern/rescue_reader.c \ - kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ + kern/list.c kern/command.c kern/corecmd.c \ kern/parser.c kern/partition.c kern/env.c kern/$(target_cpu)/dl.c \ kern/generic/millisleep.c kern/generic/rtc_get_time_ms.c kern/time.c \ symlist.c kern/$(target_cpu)/cache.S diff --git a/conf/mips-yeeloong.rmk b/conf/mips-yeeloong.rmk index 6e8444495..deb6dd33f 100644 --- a/conf/mips-yeeloong.rmk +++ b/conf/mips-yeeloong.rmk @@ -16,7 +16,7 @@ kernel_img_SOURCES = kern/$(target_cpu)/startup.S \ kern/disk.c kern/dl.c kern/err.c kern/file.c kern/fs.c \ kern/misc.c kern/mm.c kern/term.c \ kern/rescue_parser.c kern/rescue_reader.c \ - kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ + kern/list.c kern/command.c kern/corecmd.c \ kern/parser.c kern/partition.c kern/env.c kern/$(target_cpu)/dl.c \ kern/generic/millisleep.c kern/generic/rtc_get_time_ms.c kern/time.c \ kern/$(target_cpu)/cache.S \ diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk index d5968ac8e..be95b30ba 100644 --- a/conf/powerpc-ieee1275.rmk +++ b/conf/powerpc-ieee1275.rmk @@ -13,7 +13,7 @@ kernel_img_SOURCES = kern/powerpc/ieee1275/startup.S kern/ieee1275/cmain.c \ kern/disk.c kern/dl.c kern/err.c kern/file.c kern/fs.c \ kern/misc.c kern/mm.c kern/term.c \ kern/rescue_parser.c kern/rescue_reader.c \ - kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ + kern/list.c kern/command.c kern/corecmd.c \ kern/ieee1275/init.c \ kern/ieee1275/mmap.c \ term/ieee1275/ofconsole.c \ diff --git a/conf/sparc64-ieee1275.rmk b/conf/sparc64-ieee1275.rmk index 0aac67104..2314f6477 100644 --- a/conf/sparc64-ieee1275.rmk +++ b/conf/sparc64-ieee1275.rmk @@ -26,7 +26,7 @@ kernel_img_SOURCES = kern/sparc64/ieee1275/crt0.S kern/ieee1275/cmain.c \ kern/disk.c kern/dl.c kern/err.c kern/file.c kern/fs.c \ kern/misc.c kern/mm.c kern/term.c \ kern/rescue_parser.c kern/rescue_reader.c \ - kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ + kern/list.c kern/command.c kern/corecmd.c \ kern/sparc64/ieee1275/ieee1275.c \ kern/sparc64/ieee1275/init.c \ kern/ieee1275/mmap.c \ @@ -48,7 +48,7 @@ util/sparc64/ieee1275/grub-setup.c_DEPENDENCIES = grub_setup_init.h grub_setup_SOURCES = util/sparc64/ieee1275/grub-setup.c \ util/ieee1275/ofpath.c util/misc.c kern/emu/hostdisk.c \ kern/emu/misc.c kern/emu/getroot.c kern/emu/mm.c kern/device.c \ - kern/disk.c kern/err.c kern/misc.c kern/parser.c \ + kern/disk.c kern/err.c kern/misc.c \ kern/partition.c kern/file.c kern/fs.c kern/env.c kern/list.c \ fs/fshelp.c \ \ diff --git a/conf/x86-efi.rmk b/conf/x86-efi.rmk index 1011a3e64..f9f07684e 100644 --- a/conf/x86-efi.rmk +++ b/conf/x86-efi.rmk @@ -25,7 +25,7 @@ kernel_img_SOURCES = kern/$(target_cpu)/efi/startup.S kern/main.c kern/device.c kern/$(target_cpu)/dl.c kern/i386/efi/init.c kern/parser.c kern/partition.c \ kern/env.c symlist.c kern/efi/efi.c kern/efi/init.c kern/efi/mm.c \ term/efi/console.c disk/efi/efidisk.c \ - kern/time.c kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ + kern/time.c kern/list.c kern/command.c kern/corecmd.c \ kern/i386/tsc.c kern/i386/pit.c \ kern/generic/rtc_get_time_ms.c \ kern/generic/millisleep.c @@ -102,7 +102,7 @@ efi_gop_mod_CFLAGS = $(COMMON_CFLAGS) efi_gop_mod_LDFLAGS = $(COMMON_LDFLAGS) pkglib_MODULES += xnu.mod -xnu_mod_SOURCES = loader/xnu_resume.c loader/i386/xnu.c loader/i386/efi/xnu.c \ +xnu_mod_SOURCES = loader/xnu_resume.c loader/i386/xnu.c \ loader/macho32.c loader/macho64.c loader/macho.c loader/xnu.c xnu_mod_CFLAGS = $(COMMON_CFLAGS) xnu_mod_LDFLAGS = $(COMMON_LDFLAGS) diff --git a/configure.ac b/configure.ac index 31b179d46..e5840118c 100644 --- a/configure.ac +++ b/configure.ac @@ -179,13 +179,23 @@ if test "x$YACC" = x; then AC_MSG_ERROR([bison is not found]) fi -for file in /usr/src/unifont.bdf /usr/share/fonts/X11/misc/unifont.pcf.gz /usr/share/fonts/unifont/unifont.pcf.gz; do - if test -e $file ; then - AC_SUBST([FONT_SOURCE], [$file]) - break - fi +FONT_SOURCE= + +for ext in pcf pcf.gz bdf bdf.gz ttf ttf.gz; do + for dir in . /usr/src /usr/share/fonts/X11/misc /usr/share/fonts/unifont; do + if test -f "$dir/unifont.$ext"; then + FONT_SOURCE="$dir/unifont.$ext" + break 2 + fi + done done +if test "x$FONT_SOURCE" == x && ( test "x$platform" = xqemu || test "x$platform" = xyeeloong ); then + AC_MSG_ERROR([qemu and yeeloong ports need unifont]) +fi + +AC_SUBST([FONT_SOURCE]) + AC_PROG_INSTALL AC_PROG_AWK AC_PROG_LEX diff --git a/disk/i386/pc/biosdisk.c b/disk/i386/pc/biosdisk.c index 94d0e3708..f82f91ff0 100644 --- a/disk/i386/pc/biosdisk.c +++ b/disk/i386/pc/biosdisk.c @@ -120,7 +120,8 @@ grub_biosdisk_open (const char *name, grub_disk_t disk) { data->flags = GRUB_BIOSDISK_FLAG_LBA | GRUB_BIOSDISK_FLAG_CDROM; data->sectors = 32; - total_sectors = GRUB_ULONG_MAX; /* TODO: get the correct size. */ + /* TODO: get the correct size. */ + total_sectors = GRUB_DISK_SIZE_UNKNOWN; } else if (drive & 0x80) { diff --git a/disk/ieee1275/ofdisk.c b/disk/ieee1275/ofdisk.c index e5a4a67fa..d0d9e894f 100644 --- a/disk/ieee1275/ofdisk.c +++ b/disk/ieee1275/ofdisk.c @@ -204,7 +204,7 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) /* XXX: There is no property to read the number of blocks. There should be a property `#blocks', but it is not there. Perhaps it is possible to use seek for this. */ - disk->total_sectors = 0xFFFFFFFFUL; + disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN; disk->id = (unsigned long) op; diff --git a/disk/scsi.c b/disk/scsi.c index e8bfb6a3f..5d3e50966 100644 --- a/disk/scsi.c +++ b/disk/scsi.c @@ -421,7 +421,7 @@ grub_scsi_open (const char *name, grub_disk_t disk) /* According to USB MS tests specification, issue Test Unit Ready * until OK */ - maxtime = grub_get_time_ms () + 1000; + maxtime = grub_get_time_ms () + 5000; /* It is safer value */ do { /* Timeout is necessary - for example in case when we have @@ -460,7 +460,7 @@ grub_scsi_open (const char *name, grub_disk_t disk) grub_dprintf ("scsi", "blocks=%u, blocksize=%u\n", scsi->size, scsi->blocksize); grub_dprintf ("scsi", "Disk total 512 sectors = %llu\n", - disk->total_sectors); + (unsigned long long) disk->total_sectors); return GRUB_ERR_NONE; } @@ -519,6 +519,37 @@ grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector, /* XXX: Never reached. */ return GRUB_ERR_NONE; + +#if 0 /* Workaround - it works - but very slowly, from some reason + * unknown to me (specially on OHCI). Do not use it. */ + /* Split transfer requests to device sector size because */ + /* some devices are not able to transfer more than 512-1024 bytes */ + grub_err_t err = GRUB_ERR_NONE; + + for ( ; size; size--) + { + /* Depending on the type, select a read function. */ + switch (scsi->devtype) + { + case grub_scsi_devtype_direct: + err = grub_scsi_read10 (disk, sector, 1, buf); + break; + + case grub_scsi_devtype_cdrom: + err = grub_scsi_read12 (disk, sector, 1, buf); + break; + + default: /* This should not happen */ + return GRUB_ERR_READ_ERROR; + } + if (err) + return err; + sector++; + buf += scsi->blocksize; + } + + return err; +#endif } static grub_err_t diff --git a/disk/usbms.c b/disk/usbms.c index 7b719fb84..a49b30e7e 100644 --- a/disk/usbms.c +++ b/disk/usbms.c @@ -253,6 +253,7 @@ grub_usbms_transfer (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, struct grub_usbms_csw status; static grub_uint32_t tag = 0; grub_usb_err_t err = GRUB_USB_ERR_NONE; + grub_usb_err_t errCSW = GRUB_USB_ERR_NONE; int retrycnt = 3 + 1; grub_size_t i; @@ -290,9 +291,8 @@ grub_usbms_transfer (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, { if (err == GRUB_USB_ERR_STALL) { - grub_usb_clear_halt (dev->dev, dev->in->endp_addr); grub_usb_clear_halt (dev->dev, dev->out->endp_addr); - goto retry; + goto CheckCSW; } return grub_error (GRUB_ERR_IO, "USB Mass Storage request failed"); } @@ -302,7 +302,12 @@ grub_usbms_transfer (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, { err = grub_usb_bulk_read (dev->dev, dev->in->endp_addr, size, buf); grub_dprintf ("usb", "read: %d %d\n", err, GRUB_USB_ERR_STALL); - if (err) goto CheckCSW; + if (err) + { + if (err == GRUB_USB_ERR_STALL) + grub_usb_clear_halt (dev->dev, dev->in->endp_addr); + goto CheckCSW; + } /* Debug print of received data. */ grub_dprintf ("usb", "buf:\n"); if (size <= 64) @@ -316,6 +321,12 @@ grub_usbms_transfer (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, err = grub_usb_bulk_write (dev->dev, dev->out->endp_addr, size, buf); grub_dprintf ("usb", "write: %d %d\n", err, GRUB_USB_ERR_STALL); grub_dprintf ("usb", "buf:\n"); + if (err) + { + if (err == GRUB_USB_ERR_STALL) + grub_usb_clear_halt (dev->dev, dev->out->endp_addr); + goto CheckCSW; + } /* Debug print of sent data. */ if (size <= 256) for (i=0; idev, dev->in->endp_addr, + errCSW = grub_usb_bulk_read (dev->dev, dev->in->endp_addr, sizeof (status), (char *) &status); - if (err) + if (errCSW) { grub_usb_clear_halt (dev->dev, dev->in->endp_addr); - err = grub_usb_bulk_read (dev->dev, dev->in->endp_addr, + errCSW = grub_usb_bulk_read (dev->dev, dev->in->endp_addr, sizeof (status), (char *) &status); - if (err) + if (errCSW) { /* Bulk-only reset device. */ + grub_dprintf ("usb", "Bulk-only reset device - errCSW\n"); grub_usbms_reset (dev->dev, dev->interface); grub_usb_clear_halt (dev->dev, dev->in->endp_addr); grub_usb_clear_halt (dev->dev, dev->out->endp_addr); @@ -347,9 +359,11 @@ CheckCSW: status.signature, status.tag, status.residue); grub_dprintf ("usb", "CSW: status=0x%02x\n", status.status); - /* If phase error, do bulk-only reset device. */ - if (status.status == 2) - { + /* If phase error or not valid signature, do bulk-only reset device. */ + if ((status.status == 2) || + (status.signature != grub_cpu_to_le32(0x53425355))) + { /* Bulk-only reset device. */ + grub_dprintf ("usb", "Bulk-only reset device - bad status\n"); grub_usbms_reset (dev->dev, dev->interface); grub_usb_clear_halt (dev->dev, dev->in->endp_addr); grub_usb_clear_halt (dev->dev, dev->out->endp_addr); @@ -357,9 +371,13 @@ CheckCSW: goto retry; } - if (status.status) + /* If "command failed" status or data transfer failed -> error */ + if ((status.status || err) && !read_write) return grub_error (GRUB_ERR_READ_ERROR, "error communication with USB Mass Storage device"); + else if ((status.status || err) && read_write) + return grub_error (GRUB_ERR_WRITE_ERROR, + "error communication with USB Mass Storage device"); return GRUB_ERR_NONE; } diff --git a/docs/grub.texi b/docs/grub.texi index bcc05c1f8..a7750992c 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -20,7 +20,7 @@ This manual is for GNU GRUB (version @value{VERSION}, @value{UPDATED}). -Copyright @copyright{} 1999,2000,2001,2002,2004,2006,2008,2009 Free Software Foundation, Inc. +Copyright @copyright{} 1999,2000,2001,2002,2004,2006,2008,2009,2010 Free Software Foundation, Inc. @quotation Permission is granted to copy, distribute and/or modify this document @@ -34,9 +34,8 @@ Invariant Sections. @direntry * GRUB: (grub). The GRand Unified Bootloader * grub-install: (grub)Invoking grub-install. Install GRUB on your drive -* grub-terminfo: (grub)Invoking grub-terminfo. Generate a terminfo - command from a - terminfo name +* grub-mkconfig: (grub)Invoking grub-mkconfig. Generate GRUB configuration +* grub-mkpasswd-pbkdf2: (grub)Invoking grub-mkpasswd-pbkdf2. @end direntry @setchapternewpage odd @@ -81,15 +80,16 @@ This edition documents version @value{VERSION}. * Network:: Downloading OS images from a network * Serial terminal:: Using GRUB via a serial line * Vendor power-on keys:: Changing GRUB behaviour on vendor power-on keys -* Preset Menu:: Embedding a configuration file into GRUB * Images:: GRUB image files * Filesystem:: Filesystem syntax and semantics * Interface:: The menu and the command-line * Commands:: The list of available builtin commands +* Security:: Authentication and authorisation * Troubleshooting:: Error messages produced by GRUB -* Invoking the grub shell:: How to use the grub shell * Invoking grub-install:: How to use the GRUB installer -* Invoking grub-terminfo:: How to generate a terminfo command +* Invoking grub-mkconfig:: Generate a GRUB configuration file +* Invoking grub-mkpasswd-pbkdf2:: + Generate GRUB password hashes * Obtaining and Building GRUB:: How to obtain and build GRUB * Reporting bugs:: Where you should send a bug report * Future:: Some future plans on GRUB @@ -173,6 +173,22 @@ official GNU package, and opened its development by making the latest sources available via anonymous CVS. @xref{Obtaining and Building GRUB}, for more information. +Over the next few years, GRUB was extended to meet many needs, but it +quickly became clear that its design was not keeping up with the extensions +being made to it, and we reached the point where it was very difficult to +make any further changes without breaking existing features. Around 2002, +Yoshinori K. Okuji started work on PUPA (Preliminary Universal Programming +Architecture for GNU GRUB), aiming to rewrite the core of GRUB to make it +cleaner, safer, more robust, and more powerful. PUPA was eventually renamed +to GRUB 2, and the original version of GRUB was renamed to GRUB Legacy. +Small amounts of maintenance continued to be done on GRUB Legacy, but the +last release (0.97) was made in 2005 and at the time of writing it seems +unlikely that there will be another. + +By around 2007, GNU/Linux distributions started to use GRUB 2 to limited +extents, and by the end of 2009 multiple major distributions were installing +it by default. + @node Features @section GRUB features @@ -389,14 +405,14 @@ GRUB searches for the first @sc{pc} slice which has a BSD @samp{a} partition. Of course, to actually access the disks or partitions with GRUB, you -need to use the device specification in a command, like @samp{root -(fd0)} or @samp{unhide (hd0,3)}. To help you find out which number -specifies a partition you want, the GRUB command-line +need to use the device specification in a command, like @samp{set +root=(fd0)} or @samp{parttool (hd0,3) hidden-}. To help you find out +which number specifies a partition you want, the GRUB command-line (@pxref{Command-line interface}) options have argument completion. This means that, for example, you only need to type @example -root ( +set root=( @end example followed by a @key{TAB}, and GRUB will display the list of drives, @@ -453,6 +469,7 @@ the @dfn{boot directory}. @menu * Installing GRUB using grub-install:: +* Making a GRUB bootable CD-ROM:: @end menu @@ -532,11 +549,11 @@ quite careful. If the output is wrong, it is unlikely that your computer will be able to boot with no problem. Note that @command{grub-install} is actually just a shell script and the -real task is done by the grub shell @command{grub} (@pxref{Invoking the -grub shell}). Therefore, you may run @command{grub} directly to install -GRUB, without using @command{grub-install}. Don't do that, however, -unless you are very familiar with the internals of GRUB. Installing a -boot loader on a running OS may be extremely dangerous. +real task is done by @command{grub-mkimage} and @command{grub-setup}. +Therefore, you may run those commands directly to install GRUB, without +using @command{grub-install}. Don't do that, however, unless you are very +familiar with the internals of GRUB. Installing a boot loader on a running +OS may be extremely dangerous. @node Making a GRUB bootable CD-ROM @@ -649,6 +666,35 @@ use more complicated instructions. @xref{DOS/Windows}, for more information. +@node Chain-loading +@subsection Chain-loading an OS + +Operating systems that do not support Multiboot and do not have specific +support in GRUB (specific support is available for Linux, FreeBSD, NetBSD +and OpenBSD) must be chain-loaded, which involves loading another boot +loader and jumping to it in real mode. + +The @command{chainloader} command (@pxref{chainloader}) is used to set this +up. It is normally also necessary to load some GRUB modules and set the +appropriate root device. Putting this together, we get something like this, +for a Windows system on the first partition of the first hard disk: + +@verbatim +menuentry "Windows" { + insmod chain + insmod ntfs + set root=(hd0,1) + chainloader +1 +} +@end verbatim +@c FIXME: document UUIDs. + +On systems with multiple hard disks, an additional workaround may be +required. @xref{DOS/Windows}. + +Chain-loading is only supported on PC BIOS and EFI platforms. + + @node OS-specific notes @section Some caveats on OS-specific issues @@ -657,6 +703,7 @@ Here, we describe some caveats on several operating systems. @menu * GNU/Hurd:: * GNU/Linux:: +* DOS/Windows:: @end menu @@ -698,6 +745,400 @@ the size, run the command @command{uppermem} @emph{before} loading the kernel. @xref{uppermem}, for more information. +@node DOS/Windows +@subsection DOS/Windows + +GRUB cannot boot DOS or Windows directly, so you must chain-load them +(@pxref{Chain-loading}). However, their boot loaders have some critical +deficiencies, so it may not work to just chain-load them. To overcome +the problems, GRUB provides you with two helper functions. + +If you have installed DOS (or Windows) on a non-first hard disk, you +have to use the disk swapping technique, because that OS cannot boot +from any disks but the first one. The workaround used in GRUB is the +command @command{drivemap} (@pxref{drivemap}), like this: + +@example +drivemap -s (hd0) (hd1) +@end example + +This performs a @dfn{virtual} swap between your first and second hard +drive. + +@strong{Caution:} This is effective only if DOS (or Windows) uses BIOS +to access the swapped disks. If that OS uses a special driver for the +disks, this probably won't work. + +Another problem arises if you installed more than one set of DOS/Windows +onto one disk, because they could be confused if there are more than one +primary partitions for DOS/Windows. Certainly you should avoid doing +this, but there is a solution if you do want to do so. Use the partition +hiding/unhiding technique. + +If GRUB @dfn{hides} a DOS (or Windows) partition (@pxref{parttool}), DOS (or +Windows) will ignore the partition. If GRUB @dfn{unhides} a DOS (or Windows) +partition, DOS (or Windows) will detect the partition. Thus, if you have +installed DOS (or Windows) on the first and the second partition of the +first hard disk, and you want to boot the copy on the first partition, do +the following: + +@example +@group +parttool (hd0,1) hidden- +parttool (hd0,2) hidden+ +set root=(hd0,1) +chainloader +1 +parttool @verb{'${root}'} boot+ +boot +@end group +@end example + + +@node Configuration +@chapter Writing your own configuration file + +GRUB is configured using @file{grub.cfg}, usually located under +@file{/boot/grub}. This file is quite flexible, but most users will not +need to write the whole thing by hand. + +@menu +* Simple configuration:: Recommended for most users +* Shell-like scripting:: For power users and developers +* Embedded configuration:: Embedding a configuration file into GRUB +@end menu + + +@node Simple configuration +@section Simple configuration handling + +The program @command{grub-mkconfig} (@pxref{Invoking grub-mkconfig}) +generates @file{grub.cfg} files suitable for most cases. It is suitable for +use when upgrading a distribution, and will discover available kernels and +attempt to generate menu entries for them. + +The file @file{/etc/default/grub} controls the operation of +@command{grub-mkconfig}. It is sourced by a shell script, and so must be +valid POSIX shell input; normally, it will just be a sequence of +@samp{KEY=value} lines, but if the value contains spaces or other special +characters then it must be quoted. For example: + +@example +GRUB_TERMINAL_INPUT="console serial" +@end example + +Valid keys in @file{/etc/default/grub} are as follows: + +@table @samp +@item GRUB_DEFAULT +The default menu entry. This may be a number, in which case it identifies +the Nth entry in the generated menu counted from zero, or the full name of a +menu entry, or the special string @samp{saved}. Using the full name may be +useful if you want to set a menu entry as the default even though there may +be a variable number of entries before it. + +If you set this to @samp{saved}, then the default menu entry will be that +saved by @samp{GRUB_SAVEDEFAULT}, @command{grub-set-default}, or +@command{grub-reboot}. + +The default is @samp{0}. + +@item GRUB_SAVEDEFAULT +If this option is set to @samp{true}, then, when an entry is selected, save +it as a new default entry for use by future runs of GRUB. This is only +useful if @samp{GRUB_DEFAULT=saved}; it is a separate option because +@samp{GRUB_DEFAULT=saved} is useful without this option, in conjunction with +@command{grub-set-default} or @command{grub-reboot}. Unset by default. + +@item GRUB_TIMEOUT +Boot the default entry this many seconds after the menu is displayed, unless +a key is pressed. The default is @samp{5}. Set to @samp{0} to boot +immediately without displaying the menu, or to @samp{-1} to wait +indefinitely. + +@item GRUB_HIDDEN_TIMEOUT +Wait this many seconds for a key to be pressed before displaying the menu. +If no key is pressed during that time, boot immediately. Unset by default. + +@item GRUB_HIDDEN_TIMEOUT_QUIET +In conjunction with @samp{GRUB_HIDDEN_TIMEOUT}, set this to @samp{true} to +suppress the verbose countdown while waiting for a key to be pressed before +displaying the menu. Unset by default. + +@item GRUB_DEFAULT_BUTTON +@itemx GRUB_TIMEOUT_BUTTON +@itemx GRUB_HIDDEN_TIMEOUT_BUTTON +@itemx GRUB_BUTTON_CMOS_ADDRESS +Variants of the corresponding variables without the @samp{_BUTTON} suffix, +used to support vendor-specific power buttons. @xref{Vendor power-on keys}. + +@item GRUB_DISTRIBUTOR +Set by distributors of GRUB to their identifying name. This is used to +generate more informative menu entry titles. + +@item GRUB_TERMINAL_INPUT +Select the terminal input device. You may select multiple devices here, +separated by spaces. + +Valid terminal input names depend on the platform, but may include +@samp{console} (PC BIOS and EFI consoles), @samp{serial} (serial terminal), +@samp{ofconsole} (Open Firmware console), @samp{at_keyboard} (PC AT +keyboard, mainly useful with Coreboot), or @samp{usb_keyboard} (USB keyboard +using the HID Boot Protocol, for cases where the firmware does not handle +this). + +The default is to use the platform's native terminal input. + +@item GRUB_TERMINAL_OUTPUT +Select the terminal output device. You may select multiple devices here, +separated by spaces. + +Valid terminal output names depend on the platform, but may include +@samp{console} (PC BIOS and EFI consoles), @samp{serial} (serial terminal), +@samp{gfxterm} (graphics-mode output), @samp{ofconsole} (Open Firmware +console), or @samp{vga_text} (VGA text output, mainly useful with Coreboot). + +The default is to use the platform's native terminal output. + +@item GRUB_TERMINAL +If this option is set, it overrides both @samp{GRUB_TERMINAL_INPUT} and +@samp{GRUB_TERMINAL_OUTPUT} to the same value. + +@item GRUB_SERIAL_COMMAND +A command to configure the serial port when using the serial console. +@xref{serial}. Defaults to @samp{serial}. + +@item GRUB_CMDLINE_LINUX +Command-line arguments to add to menu entries for the Linux kernel. + +@item GRUB_CMDLINE_LINUX_DEFAULT +Unless @samp{GRUB_DISABLE_LINUX_RECOVERY} is set to @samp{true}, two menu +entries will be generated for each Linux kernel: one default entry and one +entry for recovery mode. This option lists command-line arguments to add +only to the default menu entry, after those listed in +@samp{GRUB_CMDLINE_LINUX}. + +@item GRUB_CMDLINE_NETBSD +@itemx GRUB_CMDLINE_NETBSD_DEFAULT +As @samp{GRUB_CMDLINE_LINUX} and @samp{GRUB_CMDLINE_LINUX_DEFAULT}, but for +NetBSD. + +@item GRUB_DISABLE_LINUX_UUID +Normally, @command{grub-mkconfig} will generate menu entries that use +universally-unique identifiers (UUIDs) to identify the root filesystem to +the Linux kernel, using a @samp{root=UUID=...} kernel parameter. This is +usually more reliable, but in some cases it may not be appropriate. To +disable the use of UUIDs, set this option to @samp{true}. + +@item GRUB_DISABLE_LINUX_RECOVERY +If this option is set to @samp{true}, disable the generation of recovery +mode menu entries for Linux. + +@item GRUB_DISABLE_NETBSD_RECOVERY +If this option is set to @samp{true}, disable the generation of recovery +mode menu entries for NetBSD. + +@item GRUB_VIDEO_BACKEND +If graphical video support is required, either because the @samp{gfxterm} +graphical terminal is in use or because @samp{GRUB_GFXPAYLOAD_LINUX} is set, +then @command{grub-mkconfig} will normally load all available GRUB video +drivers and use the one most appropriate for your hardware. If you need to +override this for some reason, then you can set this option. + +After @command{grub-install} has been run, the available video drivers are +listed in @file{/boot/grub/video.lst}. + +@item GRUB_GFXMODE +Set the resolution used on the @samp{gfxterm} graphical terminal. Note that +you can only use modes which your graphics card supports via VESA BIOS +Extensions (VBE), so for example native LCD panel resolutions may not be +available. The default is @samp{640x480}. + +@item GRUB_BACKGROUND +Set a background image for use with the @samp{gfxterm} graphical terminal. +The value of this option must be a file readable by GRUB at boot time, and +it must end with @file{.png}, @file{.tga}, @file{.jpg}, or @file{.jpeg}. +The image will be scaled if necessary to fit the screen. + +@item GRUB_THEME +Set a theme for use with the @samp{gfxterm} graphical terminal. +@xref{Themes}. + +@item GRUB_GFXPAYLOAD_LINUX +Set to @samp{text} to force the Linux kernel to boot in normal text mode, +@samp{keep} to preserve the graphics mode set using @samp{GRUB_GFXMODE}, +@samp{@var{width}x@var{height}}[@samp{x@var{depth}}] to set a particular +graphics mode, or a sequence of these separated by commas or semicolons to +try several modes in sequence. + +Depending on your kernel, your distribution, your graphics card, and the +phase of the moon, note that using this option may cause GNU/Linux to suffer +from various display problems, particularly during the early part of the +boot sequence. If you have problems, simply unset this option and GRUB will +tell Linux to boot in normal text mode. + +@item GRUB_DISABLE_OS_PROBER +Normally, @command{grub-mkconfig} will try to use the external +@command{os-prober} program, if installed, to discover other operating +systems installed on the same system and generate appropriate menu entries +for them. Set this option to @samp{true} to disable this. + +@item GRUB_INIT_TUNE +Play a tune on the speaker when GRUB starts. This is particularly useful +for users unable to see the screen. The value of this option is passed +directly to @ref{play}. +@end table + +For more detailed customisation of @command{grub-mkconfig}'s output, you may +edit the scripts in @file{/etc/grub.d} directly. +@file{/etc/grub.d/40_custom} is particularly useful for adding entire custom +menu entries; simply type the menu entries you want to add at the end of +that file, making sure to leave at least the first two lines intact. + + +@node Shell-like scripting +@section Writing full configuration files directly + + +@node Embedded configuration +@section Embedding a configuration file into GRUB + +GRUB supports embedding a configuration file directly into the core image, +so that it is loaded before entering normal mode. This is useful, for +example, when it is not straightforward to find the real configuration file, +or when you need to debug problems with loading that file. +@command{grub-install} uses this feature when it is not using BIOS disk +functions or when installing to a different disk from the one containing +@file{/boot/grub}, in which case it needs to use the @command{search} +command (@pxref{search}) to find @file{/boot/grub}. + +To embed a configuration file, use the @option{-c} option to +@command{grub-mkimage}. The file is copied into the core image, so it may +reside anywhere on the file system, and may be removed after running +@command{grub-mkimage}. + +After the embedded configuration file (if any) is executed, GRUB will load +the @samp{normal} module, which will then read the real configuration file +from @file{$prefix/grub.cfg}. By this point, the @code{root} variable will +also have been set to the root device name. For example, @code{prefix} +might be set to @samp{(hd0,1)/boot/grub}, and @code{root} might be set to +@samp{hd0,1}. Thus, in most cases, the embedded configuration file only +needs to set the @code{prefix} and @code{root} variables, and then drop +through to GRUB's normal processing. A typical example of this might look +like this: + +@example +@group +search.fs_uuid 01234567-89ab-cdef-0123-456789abcdef root +set prefix=($root)/boot/grub +@end group +@end example + +(The @samp{search_fs_uuid} module must be included in the core image for this +example to work.) + +In more complex cases, it may be useful to read other configuration files +directly from the embedded configuration file. This allows such things as +reading files not called @file{grub.cfg}, or reading files from a directory +other than that where GRUB's loadable modules are installed. To do this, +include the @samp{configfile} and @samp{normal} modules in the core image, +and embed a configuration file that uses the @command{configfile} command to +load another file. The following example of this also requires the +@command{echo}, @command{search_label}, and @command{test} modules to be +included in the core image: + +@example +@group +search.fs_label grub root +if [ -e /boot/grub/example/test1.cfg ]; then + set prefix=($root)/boot/grub + configfile /boot/grub/example/test1.cfg +else + if [ -e /boot/grub/example/test2.cfg ]; then + set prefix=($root)/boot/grub + configfile /boot/grub/example/test2.cfg + else + echo "Could not find an example configuration file!" + fi +fi +@end group +@end example + +The embedded configuration file may not contain menu entries directly, but +may only read them from elsewhere using @command{configfile}. + + +@node Network +@chapter Booting GRUB from the network + +The following instructions only work on PC BIOS systems where the Preboot +eXecution Environment (PXE) is available. + +To generate a PXE boot image, run: + +@example +@group +grub-mkimage --format=i386-pc --output=core.img --prefix='(pxe)/boot/grub' pxe pxecmd +cat /boot/grub/pxeboot.img core.img >grub.pxe +@end group +@end example + +Copy @file{grub.pxe}, @file{/boot/grub/*.mod}, and @file{/boot/grub/*.lst} +to the PXE (TFTP) server, ensuring that @file{*.mod} and @file{*.lst} are +accessible via the @file{/boot/grub/} path from the TFTP server root. Set +the DHCP server configuration to offer @file{grub.pxe} as the boot file (the +@samp{filename} option in ISC dhcpd). + +After GRUB has started, files on the TFTP server will be accessible via the +@samp{(pxe)} device. + +The server and gateway IP address can be controlled by changing the +@samp{(pxe)} device name to @samp{(pxe:@var{server-ip})} or +@samp{(pxe:@var{server-ip}:@var{gateway-ip})}. Note that this should be +changed both in the prefix and in any references to the device name in the +configuration file. + +GRUB provides several environment variables which may be used to inspect or +change the behaviour of the PXE device: + +@table @samp +@item net_pxe_ip +The IP address of this machine. Read-only. + +@item net_pxe_mac +The network interface's MAC address. Read-only. + +@item net_pxe_hostname +The client host name provided by DHCP. Read-only. + +@item net_pxe_domain +The client domain name provided by DHCP. Read-only. + +@item net_pxe_rootpath +The path to the client's root disk provided by DHCP. Read-only. + +@item net_pxe_extensionspath +The path to additional DHCP vendor extensions provided by DHCP. Read-only. + +@item net_pxe_boot_file +The boot file name provided by DHCP. Read-only. + +@item net_pxe_dhcp_server_name +The name of the DHCP server responsible for these boot parameters. +Read-only. + +@item net_pxe_blksize +The PXE transfer block size. Read-write, defaults to 512. + +@item pxe_default_server +The default PXE server. Read-write, although setting this is only useful +before opening a PXE device. + +@item pxe_default_gateway +The default gateway to use when contacting the PXE server. Read-write, +although setting this is only useful before opening a PXE device. +@end table + + @node Serial terminal @chapter Using GRUB via a serial line @@ -734,7 +1175,8 @@ you want to use COM2, you must specify @samp{--unit=1} instead. This command accepts many other options, so please refer to @ref{serial}, for more details. -The command @command{terminal} (@pxref{terminal}) chooses which type of +The commands @command{terminal_input} (@pxref{terminal_input}) and +@command{terminal_output} (@pxref{terminal_output} choose which type of terminal you want to use. In the case above, the terminal will be a serial terminal, but you can also pass @code{console} to the command, as @samp{terminal serial console}. In this case, a terminal in which @@ -748,6 +1190,7 @@ implements few VT100 escape sequences. If you specify this option then GRUB provides you with an alternative menu interface, because the normal menu requires several fancy features of your terminal. + @node Vendor power-on keys @chapter Using GRUB with vendor power-on keys Some laptop vendor provide an additional power-on button which boots another OS. @@ -762,10 +1205,148 @@ Values known to GRUB team are: @table @key @item Dell XPS M1530 85:3 +@item Asus EeePC 1005PE +84:1 (unconfirmed) @end table To take full advantage of this function install GRUB into MBR. + +@node Images +@chapter GRUB image files + +@c FIXME: parts of this section are specific to PC BIOS right now. + +GRUB consists of several images: a variety of bootstrap images for starting +GRUB in various ways, a kernel image, and a set of modules which are +combined with the kernel image to form a core image. Here is a short +overview of them. + +@table @file +@item boot.img +On PC BIOS systems, this image is the first part of GRUB to start. It is +written to a master boot record (MBR) or to the boot sector of a partition. +Because a PC boot sector is 512 bytes, the size of this image is exactly 512 +bytes. + +The sole function of @file{boot.img} is to read the first sector of the core +image from a local disk and jump to it. Because of the size restriction, +@file{boot.img} cannot understand any file system structure, so +@command{grub-setup} hardcodes the location of the first sector of the core +image into @file{boot.img} when installing GRUB. + +@item diskboot.img +This image is used as the first sector of the core image when booting from a +hard disk. It reads the rest of the core image into memory and starts the +kernel. Since file system handling is not yet available, it encodes the +location of the core image using a block list format. + +@item cdboot.img +This image is used as the first sector of the core image when booting from a +CD-ROM drive. It performs a similar function to @file{diskboot.img}. + +@item pxeboot.img +This image is used as the start of the core image when booting from the +network using PXE. @xref{Network}. + +@item lnxboot.img +This image may be placed at the start of the core image in order to make +GRUB look enough like a Linux kernel that it can be booted by LILO using an +@samp{image=} section. + +@item kernel.img +This image contains GRUB's basic run-time facilities: frameworks for device +and file handling, environment variables, the rescue mode command-line +parser, and so on. It is rarely used directly, but is built into all core +images. + +@item core.img +This is the core image of GRUB. It is built dynamically from the kernel +image and an arbitrary list of modules by the @command{grub-mkimage} +program. Usually, it contains enough modules to access @file{/boot/grub}, +and loads everything else (including menu handling, the ability to load +target operating systems, and so on) from the file system at run-time. The +modular design allows the core image to be kept small, since the areas of +disk where it must be installed are often as small as 32KB. + +On PC systems using the traditional MBR partition table format, the core +image is usually installed in the "MBR gap" between the master boot record +and the first partition, or sometimes it is installed in a file system and +read directly from that. The latter is not recommended because GRUB needs +to encode the location of all the core image sectors in @file{diskboot.img}, +and if the file system ever moves the core image around (as it is entitled +to do) then GRUB must be reinstalled; it also means that GRUB will not be +able to reliably find the core image if it resides on a different disk than +the one to which @file{boot.img} was installed. + +On PC systems using the more recent GUID Partition Table (GPT) format, the +core image should be installed to a BIOS Boot Partition. This may be +created by GNU Parted using a command such as the following: + +@example +# @kbd{parted /dev/@var{disk} set @var{partition-number} bios_grub on} +@end example + +@strong{Caution:} Be very careful which partition you select! When GRUB +finds a BIOS Boot Partition during installation, it will automatically +overwrite part of it. Make sure that the partition does not contain any +other data. + +@item *.mod +Everything else in GRUB resides in dynamically loadable modules. These are +often loaded automatically, or built into the core image if they are +essential, but may also be loaded manually using the @command{insmod} +command (@pxref{insmod}). +@end table + +@heading For GRUB Legacy users + +GRUB 2 has a different design from GRUB Legacy, and so correspondences with +the images it used cannot be exact. Nevertheless, GRUB Legacy users often +ask questions in the terms they are familiar with, and so here is a brief +guide to how GRUB 2's images relate to that. + +@table @file +@item stage1 +Stage 1 from GRUB Legacy was very similar to @file{boot.img} in GRUB 2, and +they serve the same function. + +@item *_stage1_5 +In GRUB Legacy, Stage 1.5's function was to include enough filesystem code +to allow the much larger Stage 2 to be read from an ordinary filesystem. In +this respect, its function was similar to @file{core.img} in GRUB 2. +However, @file{core.img} is much more capable than Stage 1.5 was; since it +offers a rescue shell, it is sometimes possible to recover manually in the +event that it is unable to load any other modules, for example if partition +numbers have changed. @file{core.img} is built in a more flexible way, +allowing GRUB 2 to support reading modules from advanced disk types such as +LVM and RAID. + +GRUB Legacy could run with only Stage 1 and Stage 2 in some limited +configurations, while GRUB 2 requires @file{core.img} and cannot work +without it. + +@item stage2 +GRUB 2 has no single Stage 2 image. Instead, it loads modules from +@file{/boot/grub} at run-time. + +@item stage2_eltorito +In GRUB 2, images for booting from CD-ROM drives are now constructed using +@file{cdboot.img} and @file{core.img}, making sure that the core image +contains the @samp{iso9660} module. It is usually best to use the +@command{grub-mkrescue} program for this. + +@item nbgrub +There is as yet no equivalent for @file{nbgrub} in GRUB 2; it was used by +Etherboot and some other network boot loaders. + +@item pxegrub +In GRUB 2, images for PXE network booting are now constructed using +@file{pxeboot.img} and @file{core.img}, making sure that the core image +contains the @samp{pxe} and @samp{pxecmd} modules. @xref{Network}. +@end table + + @node Filesystem @chapter Filesystem syntax and semantics @@ -773,8 +1354,8 @@ GRUB uses a special syntax for specifying disk drives which can be accessed by BIOS. Because of BIOS limitations, GRUB cannot distinguish between IDE, ESDI, SCSI, or others. You must know yourself which BIOS device is equivalent to which OS device. Normally, that will be clear if -you see the files in a device or use the command @command{find} -(@pxref{find}). +you see the files in a device or use the command @command{search} +(@pxref{search}). @menu * Device syntax:: How to specify devices @@ -822,7 +1403,7 @@ MBR when installing GRUB), while the syntax @samp{(hd0,1)} represents using the first partition of the disk (or the boot sector of the partition when installing GRUB). -If you enabled the network support, the special drive, @samp{(nd)}, is +If you enabled the network support, the special drive @samp{(pxe)} is also available. Before using the network drive, you must initialize the network. @xref{Network}, for more information. @@ -842,8 +1423,8 @@ example is @samp{(hd0,1)/boot/grub/grub.cfg}. This means the file @file{/boot/grub/grub.cfg} in the first partition of the first hard disk. If you omit the device name in an absolute file name, GRUB uses GRUB's @dfn{root device} implicitly. So if you set the root device to, -say, @samp{(hd1,1)} by the command @command{root} (@pxref{root}), then -@code{/boot/kernel} is the same as @code{(hd1,1)/boot/kernel}. +say, @samp{(hd1,1)} by the command @samp{set root=(hd1,1)} (@pxref{set}), +then @code{/boot/kernel} is the same as @code{(hd1,1)/boot/kernel}. @node Block list syntax @@ -884,6 +1465,7 @@ the command-line interface. @menu * Command-line interface:: The flexible command-line interface * Menu interface:: The simple menu interface +* Menu entry editor:: Editing a menu entry @end menu @@ -1014,6 +1596,10 @@ the global section of the configuration file (or ``menu''); most of them can be entered on the command-line and can be used either anywhere in the menu or specifically in the menu entries. +In rescue mode, only the @command{insmod} (@pxref{insmod}), @command{ls} +(@pxref{ls}), @command{set} (@pxref{set}), and @command{unset} +(@pxref{unset}) commands are normally available. + @menu * Menu-specific commands:: * General commands:: @@ -1076,14 +1662,16 @@ Commands usable anywhere in the menu and in the command-line. @menu * serial:: Set up a serial device -* terminfo:: Define escape sequences for a terminal +* terminal_input:: Manage input terminals +* terminal_output:: Manage output terminals +* terminfo:: Define terminal type @end menu @node serial @subsection serial -@deffn Command serial [@option{--unit=unit}] [@option{--port=port}] [@option{--speed=speed}] [@option{--word=word}] [@option{--parity=parity}] [@option{--stop=stop}] [@option{--device=dev}] +@deffn Command serial [@option{--unit=unit}] [@option{--port=port}] [@option{--speed=speed}] [@option{--word=word}] [@option{--parity=parity}] [@option{--stop=stop}] Initialize a serial device. @var{unit} is a number in the range 0-3 specifying which serial port to use; default is 0, which corresponds to the port often called COM1. @var{port} is the I/O port where the UART @@ -1092,31 +1680,68 @@ is to be found; if specified it takes precedence over @var{unit}. @var{stop} are the number of data bits and stop bits. Data bits must be in the range 5-8 and stop bits must be 1 or 2. Default is 8 data bits and one stop bit. @var{parity} is one of @samp{no}, @samp{odd}, -@samp{even} and defaults to @samp{no}. The option @option{--device} -can only be used in the grub shell and is used to specify the -tty device to be used in the host operating system (@pxref{Invoking the -grub shell}). +@samp{even} and defaults to @samp{no}. The serial port is not used as a communication channel unless the -@command{terminal} command is used (@pxref{terminal}). +@command{terminal_input} or @command{terminal_output} command is used +(@pxref{terminal_input}, @pxref{terminal_output}). This command is only available if GRUB is compiled with serial support. See also @ref{Serial terminal}. @end deffn +@node terminal_input +@subsection terminal_input + +@deffn Command terminal_input [@option{--append}|@option{--remove}] @ + [terminal1] [terminal2] @dots{} +List or select an input terminal. + +With no arguments, list the active and available input terminals. + +With @option{--append}, add the named terminals to the list of active input +terminals; any of these may be used to provide input to GRUB. + +With @option{--remove}, remove the named terminals from the active list. + +With no options but a list of terminal names, make only the listed terminal +names active. +@end deffn + + +@node terminal_output +@subsection terminal_output + +@deffn Command terminal_output [@option{--append}|@option{--remove}] @ + [terminal1] [terminal2] @dots{} +List or select an output terminal. + +With no arguments, list the active and available output terminals. + +With @option{--append}, add the named terminals to the list of active output +terminals; all of these will receive output from GRUB. + +With @option{--remove}, remove the named terminals from the active list. + +With no options but a list of terminal names, make only the listed terminal +names active. +@end deffn + + @node terminfo @subsection terminfo -@deffn Command terminfo @option{--name=name} @option{--cursor-address=seq} [@option{--clear-screen=seq}] [@option{--enter-standout-mode=seq}] [@option{--exit-standout-mode=seq}] -Define the capabilities of your terminal. Use this command to define -escape sequences, if it is not vt100-compatible. You may use @samp{\e} -for @key{ESC} and @samp{^X} for a control character. +@deffn Command terminfo [term] +Define the capabilities of your terminal by giving the name of an entry in +the terminfo database, which should correspond roughly to a @samp{TERM} +environment variable in Unix. -You can use the utility @command{grub-terminfo} to generate -appropriate arguments to this command. @xref{Invoking grub-terminfo}. +At the moment, only @samp{vt100} is supported in GRUB 2. If you need other +terminal types, please contact us to discuss the best way to include support +for these in GRUB. -If no option is specified, the current settings are printed. +If no option is specified, the current terminal type is printed. @end deffn @@ -1135,19 +1760,29 @@ you forget a command, you can run the command @command{help} * chainloader:: Chain-load another boot loader * cmp:: Compare two files * configfile:: Load a configuration file +* cpuid:: Check for CPU features * crc:: Calculate CRC32 checksums * date:: Display or set current date and time +* drivemap:: Map a drive to another * echo:: Display a line of text * export:: Export an environment variable +* gettext:: Translate a string +* gptsync:: Fill an MBR based on GPT entries * halt:: Shut down your computer * help:: Show help messages * insmod:: Insert a module * keystatus:: Check key modifier status * ls:: List devices or files +* parttool:: Modify partition table entries +* password:: Set a clear-text password +* password_pbkdf2:: Set a hashed password * play:: Play a tune +* pxe_unload:: Unload the PXE environment * reboot:: Reboot your computer +* search:: Search devices by file, label, or UUID * set:: Set an environment variable * unset:: Unset an environment variable +* uppermem:: Set the upper memory size @end menu @@ -1194,13 +1829,19 @@ a menu entry). @node cat @subsection cat -@deffn Command cat file +@deffn Command cat [@option{--dos}] file Display the contents of the file @var{file}. This command may be useful to remind you of your OS's root partition: @example grub> @kbd{cat /etc/fstab} @end example + +If the @option{--dos} option is used, then carriage return / new line pairs +will be displayed as a simple new line. Otherwise, the carriage return will +be displayed as a control character (@samp{}) to make it easier to see +when boot problems are caused by a file formatted using DOS-style line +endings. @end deffn @@ -1209,11 +1850,11 @@ grub> @kbd{cat /etc/fstab} @deffn Command chainloader [@option{--force}] file Load @var{file} as a chain-loader. Like any other file loaded by the -filesystem code, it can use the blocklist notation to grab the first -sector of the current partition with @samp{+1}. If you specify the -option @option{--force}, then load @var{file} forcibly, whether it has a -correct signature or not. This is required when you want to load a -defective boot loader, such as SCO UnixWare 7.1 (@pxref{SCO UnixWare}). +filesystem code, it can use the blocklist notation (@pxref{Block list +syntax}) to grab the first sector of the current partition with @samp{+1}. +If you specify the option @option{--force}, then load @var{file} forcibly, +whether it has a correct signature or not. This is required when you want to +load a defective boot loader, such as SCO UnixWare 7.1. @end deffn @@ -1243,7 +1884,22 @@ If they are completely identical, nothing will be printed. @subsection configfile @deffn Command configfile file -Load @var{file} as a configuration file. +Load @var{file} as a configuration file. If @var{file} defines any menu +entries, then show a menu containing them immediately. +@end deffn + + +@node cpuid +@subsection cpuid + +@deffn Command cpuid [-l] +Check for CPU features. This command is only available on x86 systems. + +With the @option{-l} option, return true if the CPU supports long mode +(64-bit). + +If invoked without options, this command currently behaves as if it had been +invoked with @option{-l}. This may change in the future. @end deffn @@ -1268,6 +1924,32 @@ hour, minute, and second unchanged. @end deffn +@node drivemap +@subsection drivemap + +@deffn Command drivemap @option{-l}|@option{-r}|[@option{-s}] @ + from_drive to_drive +Without options, map the drive @var{from_drive} to the drive @var{to_drive}. +This is necessary when you chain-load some operating systems, such as DOS, +if such an OS resides at a non-first drive. For convenience, any partition +suffix on the drive is ignored, so you can safely use @verb{'${root}'} as a +drive specification. + +With the @option{-s} option, perform the reverse mapping as well, swapping +the two drives. + +With the @option{-l} option, list the current mappings. + +With the @option{-r} option, reset all mappings to the default values. + +For example: + +@example +drivemap -s (hd0) (hd1) +@end example +@end deffn + + @node echo @subsection echo @@ -1320,6 +2002,38 @@ to subsidiary configuration files loaded using @command{configfile}. @end deffn +@node gettext +@subsection gettext + +@deffn Command gettext string +Translate @var{string} into the current language. + +The current language code is stored in the @samp{lang} variable in GRUB's +environment. Translation files in MO format are read from +@samp{locale_dir}, usually @file{/boot/grub/locale}. +@end deffn + + +@node gptsync +@subsection gptsync + +@deffn Command gptsync device [partition[+/-[type]]] @dots{} +Disks using the GUID Partition Table (GPT) also have a legacy Master Boot +Record (MBR) partition table for compatibility with the BIOS and with older +operating systems. The legacy MBR can only represent a limited subset of +GPT partition entries. + +This command populates the legacy MBR with the specified @var{partition} +entries on @var{device}. Up to three partitions may be used. + +@var{type} is an MBR partition type code; prefix with @samp{0x} if you want +to enter this in hexadecimal. The separator between @var{partition} and +@var{type} may be @samp{+} to make the partition active, or @samp{-} to make +it inactive; only one partition may be active. If both the separator and +type are omitted, then the partition will be inactive. +@end deffn + + @node halt @subsection halt @@ -1333,15 +2047,13 @@ is shut down using APM. @node help @subsection help -@deffn Command help @option{--all} [pattern @dots{}] +@deffn Command help [pattern @dots{}] Display helpful information about builtin commands. If you do not -specify @var{pattern}, this command shows short descriptions of most of -available commands. If you specify the option @option{--all} to this -command, short descriptions of rarely used commands (such as -@ref{testload}) are displayed as well. +specify @var{pattern}, this command shows short descriptions of all +available commands. If you specify any @var{patterns}, it displays longer information -about each of the commands which match those @var{patterns}. +about each of the commands whose names begin with those @var{patterns}. @end deffn @@ -1383,6 +2095,60 @@ name syntax}), then list the contents of that directory. @end deffn +@node parttool +@subsection parttool + +@deffn Command parttool partition commands +Make various modifications to partition table entries. + +Each @var{command} is either a boolean option, in which case it must be +followed with @samp{+} or @samp{-} (with no intervening space) to enable or +disable that option, or else it takes a value in the form +@samp{@var{command}=@var{value}}. + +Currently, @command{parttool} is only useful on DOS partition tables (also +known as Master Boot Record, or MBR). On these partition tables, the +following commands are available: + +@table @asis +@item @samp{boot} (boolean) +When enabled, this makes the selected partition be the active (bootable) +partition on its disk, clearing the active flag on all other partitions. +This command is limited to @emph{primary} partitions. + +@item @samp{type} (value) +Change the type of an existing partition. The value must be a number in the +range 0-0xFF (prefix with @samp{0x} to enter it in hexadecimal). + +@item @samp{hidden} (boolean) +When enabled, this hides the selected partition by setting the @dfn{hidden} +bit in its partition type code; when disabled, unhides the selected +partition by clearing this bit. This is useful only when booting DOS or +Wwindows and multiple primary FAT partitions exist in one disk. See also +@ref{DOS/Windows}. +@end table +@end deffn + + +@node password +@subsection password + +@deffn Command password user clear-password +Define a user named @var{user} with password @var{clear-password}. +@xref{Security}. +@end deffn + + +@node password_pbkdf2 +@subsection password_pbkdf2 + +@deffn Command password_pbkdf2 user hashed-password +Define a user named @var{user} with password hash @var{hashed-password}. +Use @command{grub-mkpasswd-pbkdf2} (@pxref{Invoking grub-mkpasswd-pbkdf2}) +to generate password hashes. @xref{Security}. +@end deffn + + @node play @subsection play @@ -1402,6 +2168,16 @@ a rest. @end deffn +@node pxe_unload +@subsection pxe_unload + +@deffn Command pxe_unload +Unload the PXE environment (@pxref{Network}). + +This command is only available on PC BIOS systems. +@end deffn + + @node reboot @subsection reboot @@ -1410,6 +2186,29 @@ Reboot the computer. @end deffn +@node search +@subsection search + +@deffn Command search @ + [@option{--file}|@option{--label}|@option{--fs-uuid}] @ + [@option{--set} var] [@option{--no-floppy}] name +Search devices by file (@option{-f}, @option{--file}), filesystem label +(@option{-l}, @option{--label}), or filesystem UUID (@option{-u}, +@option{--fs-uuid}). + +If the @option{--set} option is used, the first device found is set as the +value of environment variable @var{var}. The default variable is +@samp{root}. + +The @option{--no-floppy} option prevents searching floppy devices, which can +be slow. + +The @samp{search.file}, @samp{search.fs_label}, and @samp{search.fs_uuid} +commands are aliases for @samp{search --file}, @samp{search --label}, and +@samp{search --fs-uuid} respectively. +@end deffn + + @node set @subsection set @@ -1427,12 +2226,155 @@ Unset the environment variable @var{envvar}. @end deffn +@node uppermem +@subsection uppermem + +This command is not yet implemented for GRUB 2, although it is planned. + + +@node Security +@chapter Authentication and authorisation + +By default, the boot loader interface is accessible to anyone with physical +access to the console: anyone can select and edit any menu entry, and anyone +can get direct access to a GRUB shell prompt. For most systems, this is +reasonable since anyone with direct physical access has a variety of other +ways to gain full access, and requiring authentication at the boot loader +level would only serve to make it difficult to recover broken systems. + +However, in some environments, such as kiosks, it may be appropriate to lock +down the boot loader to require authentication before performing certain +operations. + +The @samp{password} (@pxref{password}) and @samp{password_pbkdf2} +(@pxref{password_pbkdf2}) commands can be used to define users, each of +which has an associated password. @samp{password} sets the password in +plain text, requiring @file{grub.cfg} to be secure; @samp{password_pbkdf2} +sets the password hashed using the Password-Based Key Derivation Function +(RFC 2898), requiring the use of @command{grub-mkpasswd-pbkdf2} +(@pxref{Invoking grub-mkpasswd-pbkdf2}) to generate password hashes. + +In order to enable authentication support, the @samp{superusers} environment +variable must be set to a list of usernames, separated by any of spaces, +commas, semicolons, pipes, or ampersands. Superusers are permitted to use +the GRUB command line, edit menu entries, and execute any menu entry. If +@samp{superusers} is set, then use of the command line is automatically +restricted to superusers. + +Other users may be given access to specific menu entries by giving a list of +usernames (as above) using the @option{--users} option to the +@samp{menuentry} command (@pxref{menuentry}). If the @option{--users} +option is not used for a menu entry, then that entry is unrestricted. + +Putting this together, a typical @file{grub.cfg} fragment might look like +this: + +@example +@group +set superusers="root" +password_pbkdf2 root grub.pbkdf2.sha512.10000.biglongstring +password user1 insecure + +menuentry "May be run by any user" @{ + set root=(hd0,1) + linux /vmlinuz +@} + +menuentry "Superusers only" --users "" @{ + set root=(hd0,1) + linux /vmlinuz single +@} + +menuentry "May be run by user1 or a superuser" --users user1 @{ + set root=(hd0,2) + chainloader +1 +@} +@end group +@end example + +The @command{grub-mkconfig} program does not yet have built-in support for +generating configuration files with authentication. You can use +@file{/etc/grub.d/40_custom} to add simple superuser authentication, by +adding @kbd{set superusers=} and @kbd{password} or @kbd{password_pbkdf2} +commands. + + +@node Troubleshooting +@chapter Error messages produced by GRUB + +@menu +* GRUB only offers a rescue shell:: +@end menu + + +@node GRUB only offers a rescue shell +@section GRUB only offers a rescue shell + +GRUB's normal start-up procedure involves setting the @samp{prefix} +environment variable to a value set in the core image by +@command{grub-install}, setting the @samp{root} variable to match, loading +the @samp{normal} module from the prefix, and running the @samp{normal} +command. This command is responsible for reading +@file{/boot/grub/grub.cfg}, running the menu, and doing all the useful +things GRUB is supposed to do. + +If, instead, you only get a rescue shell, this usually means that GRUB +failed to load the @samp{normal} module for some reason. It may be possible +to work around this temporarily: for instance, if the reason for the failure +is that @samp{prefix} is wrong (perhaps it refers to the wrong device, or +perhaps the path to @file{/boot/grub} was not correctly made relative to the +device), then you can correct this and enter normal mode manually: + +@example +@group +# Inspect the current prefix (and other preset variables): +set +# Set to the correct value, which might be something like this: +set prefix=(hd0,1)/grub +set root=(hd0,1) +insmod normal +normal +@end group +@end example + +However, any problem that leaves you in the rescue shell probably means that +GRUB was not correctly installed. It may be more useful to try to reinstall +it properly using @kbd{grub-install @var{device}} (@pxref{Invoking +grub-install}). When doing this, there are a few things to remember: + +@itemize @bullet{} +@item +Drive ordering in your operating system may not be the same as the boot +drive ordering used by your firmware. Do not assume that your first hard +drive (e.g. @samp{/dev/sda}) is the one that your firmware will boot from. + +@item +At least on BIOS systems, if you tell @command{grub-install} to install GRUB +to a partition but GRUB has already been installed in the master boot +record, then the GRUB installation in the partition will be ignored. + +@item +If possible, it is generally best to avoid installing GRUB to a partition +(unless it is a special partition for the use of GRUB alone, such as the +BIOS Boot Partition used on GPT). Doing this means that GRUB may stop being +able to read its core image due to a file system moving blocks around, such +as while defragmenting, running checks, or even during normal operation. +Installing to the whole disk device is normally more robust. + +@item +Check that GRUB actually knows how to read from the device and file system +containing @file{/boot/grub}. It will not be able to read from encrypted +devices, nor from file systems for which support has not yet been added to +GRUB. +@end itemize + + @node Invoking grub-install @chapter Invoking grub-install -The program @command{grub-install} installs GRUB on your drive using the -grub shell (@pxref{Invoking the grub shell}). You must specify the -device name on which you want to install GRUB, like this: +The program @command{grub-install} installs GRUB on your drive using +@command{grub-mkimage} and (on some platforms) @command{grub-setup}. You +must specify the device name on which you want to install GRUB, like this: @example grub-install @var{install_device} @@ -1468,6 +2410,60 @@ into/from your computer. @end table +@node Invoking grub-mkconfig +@chapter Invoking grub-mkconfig + +The program @command{grub-mkconfig} generates a configuration file for GRUB +(@pxref{Simple configuration}). + +@example +grub-mkconfig -o /boot/grub/grub.cfg +@end example + +@command{grub-mkconfig} accepts the following options: + +@table @option +@item --help +Print a summary of the command-line options and exit. + +@item --version +Print the version number of GRUB and exit. + +@item -o @var{file} +@itemx --output=@var{file} +Send the generated configuration file to @var{file}. The default is to send +it to standard output. +@end table + + +@node Invoking grub-mkpasswd-pbkdf2 +@chapter Invoking grub-mkpasswd-pbkdf2 + +The program @command{grub-mkpasswd-pbkdf2} generates password hashes for +GRUB (@pxref{Security}). + +@example +grub-mkpasswd-pbkdf2 +@end example + +@command{grub-mkpasswd-pbkdf2} accepts the following options: + +@table @option +@item -c @var{number} +@itemx --iteration-count=@var{number} +Number of iterations of the underlying pseudo-random function. Defaults to +10000. + +@item -l @var{number} +@itemx --buflen=@var{number} +Length of the generated hash. Defaults to 64. + +@item -s @var{number} +@itemx --salt=@var{number} +Length of the salt. Defaults to 64. +@end table + + @node Obtaining and Building GRUB @appendix How to obtain and build GRUB @@ -1505,8 +2501,9 @@ just do: @end group @end example -Also, the latest version is available from the SVN. See -@uref{http://savannah.gnu.org/svn/?group=grub} for more information. +Also, the latest version is available using Bazaar. See +@uref{http://www.gnu.org/software/grub/grub-download.en.html} for more +information. @node Reporting bugs @appendix Reporting bugs @@ -1586,6 +2583,113 @@ a look at @uref{http://www.gnu.org/software/grub/grub.html, the homepage}. +@node Internals +@appendix Hacking GRUB + +@menu +* Getting the source code:: +* Finding your way around:: +@end menu + + +@node Getting the source code +@section Getting the source code + +GRUB is maintained using the @uref{http://bazaar-vcs.org/, Bazaar revision +control system}. To fetch the primary development branch: + +@example +bzr get http://bzr.savannah.gnu.org/r/grub/trunk/grub +@end example + +The GRUB developers maintain several other branches with work in progress. +Of these, the most interesting is the experimental branch, which is a +staging area for new code which we expect to eventually merge into trunk but +which is not yet ready: + +@example +bzr get http://bzr.savannah.gnu.org/r/grub/branches/experimental +@end example + +Once you have used @kbd{bzr get} to fetch an initial copy of a branch, you +can use @kbd{bzr pull} to keep it up to date. If you have modified your +local version, you may need to resolve conflicts when pulling. + + +@node Finding your way around +@section Finding your way around + +Here is a brief map of the GRUB code base. + +GRUB uses Autoconf, but not (yet) Automake. The top-level build rules are +in @file{configure.ac}, @file{Makefile.in}, and @file{conf/*.rmk}. Each +@file{conf/*.rmk} file represents a particular target configuration, and is +processed into GNU Make rules by @file{genmk.rb} (which you only need to +look at if you are extending the build system). If you are adding a new +module which follows an existing pattern, such as a new command or a new +filesystem implementation, it is usually easiest to grep @file{conf/*.rmk} +for an existing example of that pattern to find out where it should be +added. + +Low-level boot code, such as the MBR implementation on PC BIOS systems, is +in the @file{boot/} directory. + +The GRUB kernel is in @file{kern/}. This contains core facilities such as +the device, disk, and file frameworks, environment variable handling, list +processing, and so on. The kernel should contain enough to get up to a +rescue prompt. Header files for kernel facilities, among others, are in +@file{include/}. + +Terminal implementations are in @file{term/}. + +Disk access code is spread across @file{disk/} (for accessing the disk +devices themselves), @file{partmap/} (for interpreting partition table +data), and @file{fs/} (for accessing filesystems). Note that, with the odd +specialised exception, GRUB only contains code to @emph{read} from +filesystems and tries to avoid containing any code to @emph{write} to +filesystems; this lets us confidently assure users that GRUB cannot be +responsible for filesystem corruption. + +PCI and USB bus handling is in @file{bus/}. + +Video handling code is in @file{video/}. The graphical menu system uses +this heavily, but is in a separate directory, @file{gfxmenu/}. + +Most commands are implemented by files in @file{commands/}, with the +following exceptions: + +@itemize +@item +A few core commands live in @file{kern/corecmd.c}. + +@item +Commands related to normal mode live under @file{normal/}. + +@item +Commands that load and boot kernels live under @file{loader/}. + +@item +The @samp{loopback} command is really a disk device, and so lives in +@file{disk/loopback.c}. + +@item +The @samp{gettext} command lives under @file{gettext/}. + +@item +The @samp{loadfont} and @samp{lsfonts} commands live under @file{font/}. + +@item +The @samp{serial}, @samp{terminfo}, and @samp{background_image} commands +live under @file{term/}. + +@item +The @samp{efiemu_*} commands live under @file{efiemu/}. +@end itemize + +There are a few other special-purpose exceptions; grep for them if they +matter to you. + + @node Copying This Manual @appendix Copying This Manual diff --git a/docs/man/grub-bin2h.h2m b/docs/man/grub-bin2h.h2m new file mode 100644 index 000000000..ef463f3d1 --- /dev/null +++ b/docs/man/grub-bin2h.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-bin2h \- convert a binary file to a C header diff --git a/docs/man/grub-editenv.h2m b/docs/man/grub-editenv.h2m new file mode 100644 index 000000000..efbd79070 --- /dev/null +++ b/docs/man/grub-editenv.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-editenv \- edit GRUB environment block diff --git a/docs/man/grub-emu.h2m b/docs/man/grub-emu.h2m new file mode 100644 index 000000000..09a1f88c1 --- /dev/null +++ b/docs/man/grub-emu.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-emu \- GRUB emulator diff --git a/docs/man/grub-fstest.h2m b/docs/man/grub-fstest.h2m new file mode 100644 index 000000000..be39429b5 --- /dev/null +++ b/docs/man/grub-fstest.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-fstest \- debug tool for GRUB filesystem drivers diff --git a/docs/man/grub-install.h2m b/docs/man/grub-install.h2m new file mode 100644 index 000000000..65252155c --- /dev/null +++ b/docs/man/grub-install.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-install \- install GRUB to a device diff --git a/docs/man/grub-macho2img.h2m b/docs/man/grub-macho2img.h2m new file mode 100644 index 000000000..412bf926a --- /dev/null +++ b/docs/man/grub-macho2img.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-macho2img \- convert Mach-O to raw image diff --git a/docs/man/grub-mkconfig.h2m b/docs/man/grub-mkconfig.h2m new file mode 100644 index 000000000..b0d33ec61 --- /dev/null +++ b/docs/man/grub-mkconfig.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-mkconfig \- generate a GRUB configuration file diff --git a/docs/man/grub-mkdevicemap.h2m b/docs/man/grub-mkdevicemap.h2m new file mode 100644 index 000000000..8ab34ac86 --- /dev/null +++ b/docs/man/grub-mkdevicemap.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-mkdevicemap \- generate a GRUB device map file automatically diff --git a/docs/man/grub-mkfont.h2m b/docs/man/grub-mkfont.h2m new file mode 100644 index 000000000..d8580186f --- /dev/null +++ b/docs/man/grub-mkfont.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-mkfont \- make GRUB font files diff --git a/docs/man/grub-mkimage.h2m b/docs/man/grub-mkimage.h2m new file mode 100644 index 000000000..71f270940 --- /dev/null +++ b/docs/man/grub-mkimage.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-mkimage \- make a bootable image of GRUB diff --git a/docs/man/grub-mkpasswd-pbkdf2.h2m b/docs/man/grub-mkpasswd-pbkdf2.h2m new file mode 100644 index 000000000..5b2b2ef7f --- /dev/null +++ b/docs/man/grub-mkpasswd-pbkdf2.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-mkpasswd-pbkdf2 \- generate hashed password for GRUB diff --git a/docs/man/grub-mkrelpath.h2m b/docs/man/grub-mkrelpath.h2m new file mode 100644 index 000000000..ccc0880fa --- /dev/null +++ b/docs/man/grub-mkrelpath.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-mkrelpath \- make a system path relative to its root diff --git a/docs/man/grub-mkrescue.h2m b/docs/man/grub-mkrescue.h2m new file mode 100644 index 000000000..5e92e0d99 --- /dev/null +++ b/docs/man/grub-mkrescue.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-mkrescue \- make a GRUB rescue image diff --git a/docs/man/grub-ofpathname.h2m b/docs/man/grub-ofpathname.h2m new file mode 100644 index 000000000..f07158cb3 --- /dev/null +++ b/docs/man/grub-ofpathname.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-ofpathname \- find OpenBOOT path for a device diff --git a/docs/man/grub-pe2elf.h2m b/docs/man/grub-pe2elf.h2m new file mode 100644 index 000000000..3fdb88b43 --- /dev/null +++ b/docs/man/grub-pe2elf.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-pe2elf \- convert PE image to ELF diff --git a/docs/man/grub-probe.h2m b/docs/man/grub-probe.h2m new file mode 100644 index 000000000..817ba8ef6 --- /dev/null +++ b/docs/man/grub-probe.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-probe \- probe device information for GRUB diff --git a/docs/man/grub-reboot.h2m b/docs/man/grub-reboot.h2m new file mode 100644 index 000000000..957e4b797 --- /dev/null +++ b/docs/man/grub-reboot.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-reboot \- set the default boot entry for GRUB, for the next boot only diff --git a/docs/man/grub-script-check.h2m b/docs/man/grub-script-check.h2m new file mode 100644 index 000000000..39c0a3ef6 --- /dev/null +++ b/docs/man/grub-script-check.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-script-check \- check grub.cfg for syntax errors diff --git a/docs/man/grub-set-default.h2m b/docs/man/grub-set-default.h2m new file mode 100644 index 000000000..3ac13d7ed --- /dev/null +++ b/docs/man/grub-set-default.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-set-default \- set the default boot entry for GRUB diff --git a/docs/man/grub-setup.h2m b/docs/man/grub-setup.h2m new file mode 100644 index 000000000..e70e465a4 --- /dev/null +++ b/docs/man/grub-setup.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-setup \- set up a device to boot using GRUB diff --git a/fs/i386/pc/pxe.c b/fs/i386/pc/pxe.c index 82d8ee583..e4d481a8e 100644 --- a/fs/i386/pc/pxe.c +++ b/fs/i386/pc/pxe.c @@ -114,7 +114,7 @@ grub_pxe_open (const char *name, grub_disk_t disk) return err; if (*ptr == ':') { - err = parse_ip (ptr + 1, &(data->server_ip), 0); + err = parse_ip (ptr + 1, &(data->gateway_ip), 0); if (err) return err; } diff --git a/fs/nilfs2.c b/fs/nilfs2.c index 7e0415d12..5d32f5f88 100644 --- a/fs/nilfs2.c +++ b/fs/nilfs2.c @@ -49,6 +49,13 @@ #define NILFS_BTREE_LEVEL_NODE_MIN (NILFS_BTREE_LEVEL_DATA + 1) #define NILFS_BTREE_LEVEL_MAX 14 +/* nilfs 1st super block posission from beginning of the partition + in 512 block size */ +#define NILFS_1ST_SUPER_BLOCK 2 +/* nilfs 2nd super block posission from end of the partition + in 512 block size */ +#define NILFS_2ND_SUPER_BLOCK 8 + struct grub_nilfs2_inode { grub_uint64_t i_blocks; @@ -703,6 +710,52 @@ grub_nilfs2_valid_sb (struct grub_nilfs2_super_block *sbp) return 1; } +static grub_err_t +grub_nilfs2_load_sb (struct grub_nilfs2_data *data) +{ + grub_disk_t disk = data->disk; + struct grub_nilfs2_super_block sb2; + grub_uint64_t partition_size; + int valid[2]; + int swp = 0; + + /* Read first super block. */ + grub_disk_read (disk, NILFS_1ST_SUPER_BLOCK, 0, + sizeof (struct grub_nilfs2_super_block), &data->sblock); + /* Make sure if 1st super block is valid. */ + valid[0] = grub_nilfs2_valid_sb (&data->sblock); + + partition_size = grub_disk_get_size (disk); + if (partition_size != GRUB_DISK_SIZE_UNKNOWN) + { + /* Read second super block. */ + grub_disk_read (disk, partition_size - NILFS_2ND_SUPER_BLOCK, 0, + sizeof (struct grub_nilfs2_super_block), &sb2); + /* Make sure if 2nd super block is valid. */ + valid[1] = grub_nilfs2_valid_sb (&sb2); + } + else + /* 2nd super block may not exist, so it's invalid. */ + valid[1] = 0; + + + + if (!valid[0] && !valid[1]) + return grub_error (GRUB_ERR_BAD_FS, "not a nilfs2 filesystem"); + + swp = valid[1] && (!valid[0] || + grub_le_to_cpu64 (data->sblock.s_last_cno) < + grub_le_to_cpu64 (sb2.s_last_cno)); + + /* swap if first super block is invalid or older than second one. */ + if (swp) + grub_memcpy (&data->sblock, &sb2, + sizeof (struct grub_nilfs2_super_block)); + + grub_errno = GRUB_ERR_NONE; + return grub_errno; +} + static struct grub_nilfs2_data * grub_nilfs2_mount (grub_disk_t disk) { @@ -717,19 +770,13 @@ grub_nilfs2_mount (grub_disk_t disk) if (!data) return 0; + data->disk = disk; + /* Read the superblock. */ - grub_disk_read (disk, 1 * 2, 0, sizeof (struct grub_nilfs2_super_block), - &data->sblock); + grub_nilfs2_load_sb (data); if (grub_errno) goto fail; - /* Make sure this is an nilfs2 filesystem. */ - if (!grub_nilfs2_valid_sb (&data->sblock)) - { - grub_error (GRUB_ERR_BAD_FS, "not a nilfs2 filesystem"); - goto fail; - } - nilfs2_block_count = (1 << LOG2_NILFS2_BLOCK_SIZE (data)); /* Read the last segment summary. */ @@ -748,8 +795,6 @@ grub_nilfs2_mount (grub_disk_t disk) if (grub_errno) goto fail; - data->disk = disk; - grub_nilfs2_read_last_checkpoint (data, &last_checkpoint); if (grub_errno) diff --git a/genmk.rb b/genmk.rb index e62dbd4f6..01b969ecf 100644 --- a/genmk.rb +++ b/genmk.rb @@ -228,7 +228,7 @@ VIDEOFILES += #{video} #{fs}: #{src} $(#{src}_DEPENDENCIES) genfslist.sh set -e; \ - $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \ + $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} -DGRUB_LST_GENERATOR $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \ | sh $(srcdir)/genfslist.sh #{symbolic_name} > $@ || (rm -f $@; exit 1) #{parttool}: #{src} $(#{src}_DEPENDENCIES) genparttoollist.sh @@ -238,7 +238,7 @@ VIDEOFILES += #{video} #{partmap}: #{src} $(#{src}_DEPENDENCIES) genpartmaplist.sh set -e; \ - $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \ + $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} -DGRUB_LST_GENERATOR $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \ | sh $(srcdir)/genpartmaplist.sh #{symbolic_name} > $@ || (rm -f $@; exit 1) #{handler}: #{src} $(#{src}_DEPENDENCIES) genhandlerlist.sh @@ -253,7 +253,7 @@ VIDEOFILES += #{video} #{video}: #{src} $(#{src}_DEPENDENCIES) genvideolist.sh set -e; \ - $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \ + $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} -DGRUB_LST_GENERATOR $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \ | sh $(srcdir)/genvideolist.sh #{symbolic_name} > $@ || (rm -f $@; exit 1) " diff --git a/gettext/gettext.c b/gettext/gettext.c index 0aa8decbd..bc7d42824 100644 --- a/gettext/gettext.c +++ b/gettext/gettext.c @@ -309,14 +309,10 @@ grub_gettext_init_ext (const char *lang) static void grub_gettext_delete_list (void) { - struct grub_gettext_msg *item; - - while ((item = - grub_list_pop (GRUB_AS_LIST_P (&grub_gettext_msg_list))) != 0) + while (grub_gettext_msg_list) { - char *original = (char *) ((struct grub_gettext_msg *) item)->name; - grub_free (original); - + grub_free ((char *) grub_gettext_msg_list->name); + grub_gettext_msg_list = grub_gettext_msg_list->next; /* Don't delete the translated message because could be in use. */ } } diff --git a/include/grub/command.h b/include/grub/command.h index 6e9942b60..6bd3d07c9 100644 --- a/include/grub/command.h +++ b/include/grub/command.h @@ -115,12 +115,7 @@ grub_command_execute (const char *name, int argc, char **argv) return (cmd) ? cmd->func (cmd, argc, argv) : GRUB_ERR_FILE_NOT_FOUND; } -static inline int -grub_command_iterate (int (*func) (grub_command_t)) -{ - return grub_list_iterate (GRUB_AS_LIST (grub_command_list), - (grub_list_hook_t) func); -} +#define FOR_COMMANDS(var) FOR_LIST_ELEMENTS((var), grub_command_list) void grub_register_core_commands (void); diff --git a/include/grub/disk.h b/include/grub/disk.h index e60b1f3de..e7f807e0e 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -138,6 +138,9 @@ typedef struct grub_disk_memberlist *grub_disk_memberlist_t; #define GRUB_DISK_CACHE_SIZE 8 #define GRUB_DISK_CACHE_BITS 3 +/* Return value of grub_disk_get_size() in case disk size is unknown. */ +#define GRUB_DISK_SIZE_UNKNOWN 0xffffffffffffffffULL + /* This is called from the memory manager. */ void grub_disk_cache_invalidate_all (void); diff --git a/include/grub/dl.h b/include/grub/dl.h index cf5da7fd5..351cca64d 100644 --- a/include/grub/dl.h +++ b/include/grub/dl.h @@ -82,6 +82,7 @@ struct grub_dl Elf_Sym *symtab; void (*init) (struct grub_dl *mod); void (*fini) (void); + struct grub_dl *next; }; typedef struct grub_dl *grub_dl_t; @@ -98,7 +99,10 @@ void grub_dl_unload_all (void); #endif int EXPORT_FUNC(grub_dl_ref) (grub_dl_t mod); int EXPORT_FUNC(grub_dl_unref) (grub_dl_t mod); -void EXPORT_FUNC(grub_dl_iterate) (int (*hook) (grub_dl_t mod)); +extern grub_dl_t EXPORT_VAR(grub_dl_head); + +#define FOR_DL_MODULES(var) FOR_LIST_ELEMENTS ((var), (grub_dl_head)) + grub_dl_t EXPORT_FUNC(grub_dl_get) (const char *name); grub_err_t grub_dl_register_symbol (const char *name, void *addr, grub_dl_t mod); diff --git a/include/grub/efi/uga_draw.h b/include/grub/efi/uga_draw.h index 93504307c..a31f2672e 100644 --- a/include/grub/efi/uga_draw.h +++ b/include/grub/efi/uga_draw.h @@ -32,7 +32,7 @@ enum grub_efi_uga_blt_operation GRUB_EFI_UGA_VIDEO_TO_BLT, GRUB_EFI_UGA_BLT_TO_VIDEO, GRUB_EFI_UGA_VIDEO_TO_VIDEO, - GRUB_EFI_UGA_GLT_MAX + GRUB_EFI_UGA_BLT_MAX }; struct grub_efi_uga_pixel diff --git a/include/grub/emu/misc.h b/include/grub/emu/misc.h index 0e6ace0e8..f34cd4287 100644 --- a/include/grub/emu/misc.h +++ b/include/grub/emu/misc.h @@ -48,4 +48,8 @@ int EXPORT_FUNC(asprintf) (char **buf, const char *fmt, ...); char * EXPORT_FUNC(xasprintf) (const char *fmt, ...); extern char * canonicalize_file_name (const char *path); +#ifdef HAVE_DEVICE_MAPPER +int grub_device_mapper_supported (void); +#endif + #endif /* GRUB_EMU_MISC_H */ diff --git a/include/grub/fs.h b/include/grub/fs.h index 45f515768..994eb8080 100644 --- a/include/grub/fs.h +++ b/include/grub/fs.h @@ -24,6 +24,8 @@ #include #include +#include + /* Forward declaration is required, because of mutual reference. */ struct grub_file; @@ -38,6 +40,9 @@ struct grub_dirhook_info /* Filesystem descriptor. */ struct grub_fs { + /* The next filesystem. */ + struct grub_fs *next; + /* My name. */ const char *name; @@ -72,9 +77,6 @@ struct grub_fs /* Whether this filesystem reserves first sector for DOS-style boot. */ int reserved_first_sector; #endif - - /* The next filesystem. */ - struct grub_fs *next; }; typedef struct grub_fs *grub_fs_t; @@ -87,10 +89,24 @@ extern struct grub_fs grub_fs_blocklist; the linked list GRUB_FS_LIST through the function grub_fs_register. */ typedef int (*grub_fs_autoload_hook_t) (void); extern grub_fs_autoload_hook_t EXPORT_VAR(grub_fs_autoload_hook); +extern grub_fs_t EXPORT_VAR (grub_fs_list); + +#ifndef GRUB_LST_GENERATOR +static inline void +grub_fs_register (grub_fs_t fs) +{ + grub_list_push (GRUB_AS_LIST_P (&grub_fs_list), GRUB_AS_LIST (fs)); +} +#endif + +static inline void +grub_fs_unregister (grub_fs_t fs) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_fs_list), GRUB_AS_LIST (fs)); +} + +#define FOR_FILESYSTEMS(var) FOR_LIST_ELEMENTS((var), (grub_fs_list)) -void EXPORT_FUNC(grub_fs_register) (grub_fs_t fs); -void EXPORT_FUNC(grub_fs_unregister) (grub_fs_t fs); -void EXPORT_FUNC(grub_fs_iterate) (int (*hook) (const grub_fs_t fs)); grub_fs_t EXPORT_FUNC(grub_fs_probe) (grub_device_t device); #endif /* ! GRUB_FS_HEADER */ diff --git a/include/grub/handler.h b/include/grub/handler.h deleted file mode 100644 index 77dd7d9c1..000000000 --- a/include/grub/handler.h +++ /dev/null @@ -1,60 +0,0 @@ -/* handler.h - header for grub handler */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2009 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GRUB. If not, see . - */ - -#ifndef GRUB_HANDLER_HEADER -#define GRUB_HANDLER_HEADER 1 - -#include -#include - -struct grub_handler -{ - struct grub_handler *next; - const char *name; - grub_err_t (*init) (void); - grub_err_t (*fini) (void); -}; -typedef struct grub_handler *grub_handler_t; - -struct grub_handler_class -{ - struct grub_handler_class *next; - const char *name; - grub_handler_t handler_list; - grub_handler_t cur_handler; -}; -typedef struct grub_handler_class *grub_handler_class_t; - -extern grub_handler_class_t EXPORT_VAR(grub_handler_class_list); - -void EXPORT_FUNC(grub_handler_register) (grub_handler_class_t class, - grub_handler_t handler); -void EXPORT_FUNC(grub_handler_unregister) (grub_handler_class_t class, - grub_handler_t handler); -grub_err_t EXPORT_FUNC(grub_handler_set_current) (grub_handler_class_t class, - grub_handler_t handler); - -#define GRUB_AS_HANDLER(ptr) \ - ((GRUB_FIELD_MATCH (ptr, grub_handler_t, next) && \ - GRUB_FIELD_MATCH (ptr, grub_handler_t, name) && \ - GRUB_FIELD_MATCH (ptr, grub_handler_t, init) && \ - GRUB_FIELD_MATCH (ptr, grub_handler_t, fini)) ? \ - (grub_handler_t) ptr : grub_bad_type_cast ()) - -#endif /* ! GRUB_HANDLER_HEADER */ diff --git a/include/grub/i386/qemu/kernel.h b/include/grub/i386/qemu/kernel.h index 0aa2b3d09..df06e6731 100644 --- a/include/grub/i386/qemu/kernel.h +++ b/include/grub/i386/qemu/kernel.h @@ -34,6 +34,8 @@ extern grub_int32_t grub_kernel_image_size; /* The total size of module images following the kernel. */ extern grub_int32_t grub_total_module_size; +void grub_qemu_init_cirrus (void); + #endif /* ! ASM_FILE */ #endif /* ! GRUB_KERNEL_MACHINE_HEADER */ diff --git a/include/grub/i386/xnu.h b/include/grub/i386/xnu.h index 3be2c3bcc..2fa2639c1 100644 --- a/include/grub/i386/xnu.h +++ b/include/grub/i386/xnu.h @@ -114,8 +114,6 @@ extern grub_uint32_t grub_xnu_stack; extern grub_uint32_t grub_xnu_arg1; extern char grub_xnu_cmdline[1024]; grub_err_t grub_xnu_boot (void); -grub_err_t grub_xnu_set_video (struct grub_xnu_boot_params *bootparams_relloc); -grub_err_t -grub_cpu_xnu_fill_devicetree (void); +grub_err_t grub_cpu_xnu_fill_devicetree (void); extern grub_uint32_t grub_xnu_heap_will_be_at; #endif diff --git a/include/grub/list.h b/include/grub/list.h index 5559158dc..75353010c 100644 --- a/include/grub/list.h +++ b/include/grub/list.h @@ -30,15 +30,10 @@ struct grub_list }; typedef struct grub_list *grub_list_t; -typedef int (*grub_list_hook_t) (grub_list_t item); -typedef int (*grub_list_test_t) (grub_list_t new_item, grub_list_t item); - void EXPORT_FUNC(grub_list_push) (grub_list_t *head, grub_list_t item); -void * EXPORT_FUNC(grub_list_pop) (grub_list_t *head); void EXPORT_FUNC(grub_list_remove) (grub_list_t *head, grub_list_t item); -int EXPORT_FUNC(grub_list_iterate) (grub_list_t head, grub_list_hook_t hook); -void EXPORT_FUNC(grub_list_insert) (grub_list_t *head, grub_list_t item, - grub_list_test_t test); + +#define FOR_LIST_ELEMENTS(var, list) for ((var) = (list); (var); (var) = (var)->next) static inline void * grub_bad_type_cast_real (int line, const char *file) diff --git a/include/grub/parser.h b/include/grub/parser.h index 17f0c4303..de4da05ad 100644 --- a/include/grub/parser.h +++ b/include/grub/parser.h @@ -22,7 +22,6 @@ #include #include -#include #include /* All the states for the command line. */ @@ -84,36 +83,9 @@ struct grub_parser }; typedef struct grub_parser *grub_parser_t; -extern struct grub_handler_class EXPORT_VAR(grub_parser_class); -grub_err_t EXPORT_FUNC(grub_parser_execute) (char *source); +grub_err_t grub_parser_execute (char *source); -static inline void -grub_parser_register (const char *name __attribute__ ((unused)), - /* `name' is ignored here, but used by genhandlerlist.sh. */ - grub_parser_t parser) -{ - grub_handler_register (&grub_parser_class, GRUB_AS_HANDLER (parser)); -} - -static inline void -grub_parser_unregister (grub_parser_t parser) -{ - grub_handler_unregister (&grub_parser_class, GRUB_AS_HANDLER (parser)); -} - -static inline grub_parser_t -grub_parser_get_current (void) -{ - return (grub_parser_t) grub_parser_class.cur_handler; -} - -static inline grub_err_t -grub_parser_set_current (grub_parser_t parser) -{ - return grub_handler_set_current (&grub_parser_class, - GRUB_AS_HANDLER (parser)); -} - -void grub_register_rescue_parser (void); +grub_err_t +grub_rescue_parse_line (char *line, grub_reader_getline_t getline); #endif /* ! GRUB_PARSER_HEADER */ diff --git a/include/grub/partition.h b/include/grub/partition.h index 80a9c15f0..a23e94e07 100644 --- a/include/grub/partition.h +++ b/include/grub/partition.h @@ -77,12 +77,14 @@ char *EXPORT_FUNC(grub_partition_get_name) (const grub_partition_t partition); extern grub_partition_map_t EXPORT_VAR(grub_partition_map_list); +#ifndef GRUB_LST_GENERATOR static inline void grub_partition_map_register (grub_partition_map_t partmap) { grub_list_push (GRUB_AS_LIST_P (&grub_partition_map_list), GRUB_AS_LIST (partmap)); } +#endif static inline void grub_partition_map_unregister (grub_partition_map_t partmap) @@ -91,7 +93,7 @@ grub_partition_map_unregister (grub_partition_map_t partmap) GRUB_AS_LIST (partmap)); } -#define FOR_PARTITION_MAPS(var) for (var = grub_partition_map_list; var; var = var->next) +#define FOR_PARTITION_MAPS(var) FOR_LIST_ELEMENTS((var), (grub_partition_map_list)) static inline grub_disk_addr_t diff --git a/include/grub/script_sh.h b/include/grub/script_sh.h index b55b6a806..7d6129243 100644 --- a/include/grub/script_sh.h +++ b/include/grub/script_sh.h @@ -335,15 +335,22 @@ struct grub_script_function }; typedef struct grub_script_function *grub_script_function_t; +extern grub_script_function_t grub_script_function_list; + +#define FOR_SCRIPT_FUNCTIONS(var) for((var) = grub_script_function_list; \ + (var); (var) = (var)->next) + grub_script_function_t grub_script_function_create (struct grub_script_arg *functionname, struct grub_script *cmd); void grub_script_function_remove (const char *name); grub_script_function_t grub_script_function_find (char *functionname); -int grub_script_function_iterate (int (*iterate) (grub_script_function_t)); int grub_script_function_call (grub_script_function_t func, int argc, char **args); char ** grub_script_execute_arglist_to_argv (struct grub_script_arglist *arglist, int *count); +grub_err_t +grub_normal_parse_line (char *line, grub_reader_getline_t getline); + #endif /* ! GRUB_NORMAL_PARSER_HEADER */ diff --git a/include/grub/scsicmd.h b/include/grub/scsicmd.h index f9a7cb200..9cc5afe72 100644 --- a/include/grub/scsicmd.h +++ b/include/grub/scsicmd.h @@ -147,14 +147,14 @@ struct grub_scsi_write12 typedef enum { - grub_scsi_cmd_inquiry = 0x12, grub_scsi_cmd_test_unit_ready = 0x00, + grub_scsi_cmd_request_sense = 0x03, + grub_scsi_cmd_inquiry = 0x12, grub_scsi_cmd_read_capacity = 0x25, grub_scsi_cmd_read10 = 0x28, grub_scsi_cmd_write10 = 0x2a, grub_scsi_cmd_read12 = 0xa8, grub_scsi_cmd_write12 = 0xaa, - grub_scsi_cmd_request_sense = 0x03 } grub_scsi_cmd_t; typedef enum diff --git a/include/grub/term.h b/include/grub/term.h index 9500e1c99..971a8db32 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -38,7 +38,7 @@ #include #include #include -#include +#include /* These are used to represent the various color states we use. */ typedef enum @@ -262,10 +262,10 @@ grub_term_unregister_output (grub_term_output_t term) GRUB_AS_LIST (term)); } -#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) +#define FOR_ACTIVE_TERM_INPUTS(var) FOR_LIST_ELEMENTS((var), (grub_term_inputs)) +#define FOR_DISABLED_TERM_INPUTS(var) FOR_LIST_ELEMENTS((var), (grub_term_inputs_disabled)) +#define FOR_ACTIVE_TERM_OUTPUTS(var) FOR_LIST_ELEMENTS((var), (grub_term_outputs)) +#define FOR_DISABLED_TERM_OUTPUTS(var) FOR_LIST_ELEMENTS((var), (grub_term_outputs_disabled)) void EXPORT_FUNC(grub_putchar) (int c); void EXPORT_FUNC(grub_putcode) (grub_uint32_t code, diff --git a/include/grub/types.h b/include/grub/types.h index 6e9461f1d..a9e8adfd6 100644 --- a/include/grub/types.h +++ b/include/grub/types.h @@ -60,7 +60,7 @@ typedef signed char grub_int8_t; typedef short grub_int16_t; typedef int grub_int32_t; -#if GRUB_CPU_SIZEOF_VOID_P == 8 +#if GRUB_CPU_SIZEOF_LONG == 8 typedef long grub_int64_t; #else typedef long long grub_int64_t; @@ -69,7 +69,7 @@ typedef long long grub_int64_t; typedef unsigned char grub_uint8_t; typedef unsigned short grub_uint16_t; typedef unsigned grub_uint32_t; -#if GRUB_CPU_SIZEOF_VOID_P == 8 +#if GRUB_CPU_SIZEOF_LONG == 8 typedef unsigned long grub_uint64_t; #else typedef unsigned long long grub_uint64_t; @@ -98,7 +98,7 @@ typedef grub_uint32_t grub_size_t; typedef grub_int32_t grub_ssize_t; #endif -#if GRUB_CPU_SIZEOF_VOID_P == 8 +#if GRUB_CPU_SIZEOF_LONG == 8 # define GRUB_ULONG_MAX 18446744073709551615UL # define GRUB_LONG_MAX 9223372036854775807L # define GRUB_LONG_MIN (-9223372036854775807L - 1) diff --git a/include/grub/usb.h b/include/grub/usb.h index cbbc39303..64dc78d61 100644 --- a/include/grub/usb.h +++ b/include/grub/usb.h @@ -35,7 +35,8 @@ typedef enum GRUB_USB_ERR_NAK, GRUB_USB_ERR_BABBLE, GRUB_USB_ERR_TIMEOUT, - GRUB_USB_ERR_BITSTUFF + GRUB_USB_ERR_BITSTUFF, + GRUB_USB_ERR_UNRECOVERABLE } grub_usb_err_t; typedef enum diff --git a/include/grub/usbtrans.h b/include/grub/usbtrans.h index cd818e1fc..40fc0dd5f 100644 --- a/include/grub/usbtrans.h +++ b/include/grub/usbtrans.h @@ -58,6 +58,9 @@ struct grub_usb_transfer struct grub_usb_device *dev; struct grub_usb_transaction *transactions; + + int last_trans; + /* Index of last processed transaction in OHCI/UHCI driver. */ }; typedef struct grub_usb_transfer *grub_usb_transfer_t; diff --git a/include/grub/vga.h b/include/grub/vga.h new file mode 100644 index 000000000..d4a1523a7 --- /dev/null +++ b/include/grub/vga.h @@ -0,0 +1,195 @@ +/* + * 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_VGA_HEADER +#define GRUB_VGA_HEADER 1 + +enum + { + GRUB_VGA_IO_ARX = 0x3c0, + GRUB_VGA_IO_SR_INDEX = 0x3c4, + GRUB_VGA_IO_SR_DATA = 0x3c5, + GRUB_VGA_IO_PIXEL_MASK = 0x3c6, + GRUB_VGA_IO_PALLETTE_READ_INDEX = 0x3c7, + GRUB_VGA_IO_PALLETTE_WRITE_INDEX = 0x3c8, + GRUB_VGA_IO_PALLETTE_DATA = 0x3c9, + GRUB_VGA_IO_GR_INDEX = 0x3ce, + GRUB_VGA_IO_GR_DATA = 0x3cf, + GRUB_VGA_IO_CR_INDEX = 0x3d4, + GRUB_VGA_IO_CR_DATA = 0x3d5, + GRUB_VGA_IO_INPUT_STATUS1_REGISTER = 0x3da + }; + +#define GRUB_VGA_IO_INPUT_STATUS1_VERTR_BIT 0x08 + +enum + { + GRUB_VGA_CR_WIDTH = 0x01, + GRUB_VGA_CR_OVERFLOW = 0x07, + GRUB_VGA_CR_CELL_HEIGHT = 0x09, + GRUB_VGA_CR_CURSOR_START = 0x0a, + GRUB_VGA_CR_CURSOR_END = 0x0b, + GRUB_VGA_CR_START_ADDR_HIGH_REGISTER = 0x0c, + GRUB_VGA_CR_START_ADDR_LOW_REGISTER = 0x0d, + GRUB_VGA_CR_CURSOR_ADDR_HIGH = 0x0e, + GRUB_VGA_CR_CURSOR_ADDR_LOW = 0x0f, + GRUB_VGA_CR_VSYNC_END = 0x11, + GRUB_VGA_CR_HEIGHT = 0x12, + GRUB_VGA_CR_PITCH = 0x13, + GRUB_VGA_CR_MODE = 0x17, + GRUB_VGA_CR_LINE_COMPARE = 0x18, + }; + +#define GRUB_VGA_CR_WIDTH_DIVISOR 8 +#define GRUB_VGA_CR_OVERFLOW_HEIGHT1_SHIFT 7 +#define GRUB_VGA_CR_OVERFLOW_HEIGHT1_MASK 0x02 +#define GRUB_VGA_CR_OVERFLOW_HEIGHT2_SHIFT 3 +#define GRUB_VGA_CR_OVERFLOW_HEIGHT2_MASK 0xc0 +#define GRUB_VGA_CR_OVERFLOW_LINE_COMPARE_SHIFT 4 +#define GRUB_VGA_CR_OVERFLOW_LINE_COMPARE_MASK 0x10 + +#define GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_MASK 0x40 +#define GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_SHIFT 3 + +enum + { + GRUB_VGA_CR_CURSOR_START_DISABLE = (1 << 5) + }; + +#define GRUB_VGA_CR_PITCH_DIVISOR 8 + +enum + { + GRUB_VGA_CR_MODE_NO_CGA = 0x01, + GRUB_VGA_CR_MODE_NO_HERCULES = 0x02, + GRUB_VGA_CR_MODE_BYTE_MODE = 0x40, + GRUB_VGA_CR_MODE_TIMING_ENABLE = 0x80 + }; + +enum + { + GRUB_VGA_SR_CLOCKING_MODE = 1, + GRUB_VGA_SR_MAP_MASK_REGISTER = 2, + GRUB_VGA_SR_MEMORY_MODE = 4, + }; + +enum + { + GRUB_VGA_SR_CLOCKING_MODE_8_DOT_CLOCK = 1 + }; + +enum + { + GRUB_VGA_SR_MEMORY_MODE_NORMAL = 0, + GRUB_VGA_SR_MEMORY_MODE_CHAIN4 = 8 + }; + +enum + { + GRUB_VGA_GR_DATA_ROTATE = 3, + GRUB_VGA_GR_READ_MAP_REGISTER = 4, + GRUB_VGA_GR_MODE = 5, + GRUB_VGA_GR_GR6 = 6, + GRUB_VGA_GR_BITMASK = 8, + GRUB_VGA_GR_MAX + }; + +enum + { + GRUB_VGA_TEXT_TEXT_PLANE = 0, + GRUB_VGA_TEXT_ATTR_PLANE = 1, + GRUB_VGA_TEXT_FONT_PLANE = 2 + }; + +enum + { + GRUB_VGA_GR_GR6_GRAPHICS_MODE = 1, + GRUB_VGA_GR_GR6_MMAP_CGA = (3 << 2) + }; + +enum + { + GRUB_VGA_GR_MODE_READ_MODE1 = 0x08, + GRUB_VGA_GR_MODE_ODD_EVEN = 0x10, + GRUB_VGA_GR_MODE_256_COLOR = 0x40 + }; + +static inline void +grub_vga_gr_write (grub_uint8_t val, grub_uint8_t addr) +{ + grub_outb (addr, GRUB_VGA_IO_GR_INDEX); + grub_outb (val, GRUB_VGA_IO_GR_DATA); +} + +static inline grub_uint8_t +grub_vga_gr_read (grub_uint8_t addr) +{ + grub_outb (addr, GRUB_VGA_IO_GR_INDEX); + return grub_inb (GRUB_VGA_IO_GR_DATA); +} + +static inline void +grub_vga_cr_write (grub_uint8_t val, grub_uint8_t addr) +{ + grub_outb (addr, GRUB_VGA_IO_CR_INDEX); + grub_outb (val, GRUB_VGA_IO_CR_DATA); +} + +static inline grub_uint8_t +grub_vga_cr_read (grub_uint8_t addr) +{ + grub_outb (addr, GRUB_VGA_IO_CR_INDEX); + return grub_inb (GRUB_VGA_IO_CR_DATA); +} + +static inline void +grub_vga_sr_write (grub_uint8_t val, grub_uint8_t addr) +{ + grub_outb (addr, GRUB_VGA_IO_SR_INDEX); + grub_outb (val, GRUB_VGA_IO_SR_DATA); +} + +static inline grub_uint8_t +grub_vga_sr_read (grub_uint8_t addr) +{ + grub_outb (addr, GRUB_VGA_IO_SR_INDEX); + return grub_inb (GRUB_VGA_IO_SR_DATA); +} + +static inline void +grub_vga_palette_read (grub_uint8_t addr, grub_uint8_t *r, grub_uint8_t *g, + grub_uint8_t *b) +{ + grub_outb (addr, GRUB_VGA_IO_PALLETTE_READ_INDEX); + *r = grub_inb (GRUB_VGA_IO_PALLETTE_DATA); + *g = grub_inb (GRUB_VGA_IO_PALLETTE_DATA); + *b = grub_inb (GRUB_VGA_IO_PALLETTE_DATA); +} + +static inline void +grub_vga_palette_write (grub_uint8_t addr, grub_uint8_t r, grub_uint8_t g, + grub_uint8_t b) +{ + grub_outb (addr, GRUB_VGA_IO_PALLETTE_WRITE_INDEX); + grub_outb (r, GRUB_VGA_IO_PALLETTE_DATA); + grub_outb (g, GRUB_VGA_IO_PALLETTE_DATA); + grub_outb (b, GRUB_VGA_IO_PALLETTE_DATA); +} + + +#endif diff --git a/include/grub/video.h b/include/grub/video.h index 5fd7e0c47..63f2b02cf 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -21,6 +21,7 @@ #include #include +#include /* Video color in hardware dependent format. Users should not assume any specific coding format. */ @@ -182,15 +183,32 @@ typedef enum grub_video_driver_id GRUB_VIDEO_DRIVER_EFI_UGA, GRUB_VIDEO_DRIVER_EFI_GOP, GRUB_VIDEO_DRIVER_SM712, - GRUB_VIDEO_DRIVER_VGA + GRUB_VIDEO_DRIVER_VGA, + GRUB_VIDEO_DRIVER_CIRRUS, + GRUB_VIDEO_DRIVER_BOCHS, + GRUB_VIDEO_DRIVER_SDL } grub_video_driver_id_t; +typedef enum grub_video_adapter_prio + { + GRUB_VIDEO_ADAPTER_PRIO_FALLBACK = 60, + GRUB_VIDEO_ADAPTER_PRIO_FIRMWARE_DIRTY = 70, + GRUB_VIDEO_ADAPTER_PRIO_FIRMWARE = 80, + GRUB_VIDEO_ADAPTER_PRIO_NATIVE = 100 + } grub_video_adapter_prio_t; + + struct grub_video_adapter { + /* The next video adapter. */ + struct grub_video_adapter *next; + /* The video adapter name. */ const char *name; grub_video_driver_id_t id; + grub_video_adapter_prio_t prio; + /* Initialize the video adapter. */ grub_err_t (*init) (void); @@ -255,15 +273,33 @@ struct grub_video_adapter grub_err_t (*set_active_render_target) (struct grub_video_render_target *target); grub_err_t (*get_active_render_target) (struct grub_video_render_target **target); - - /* The next video adapter. */ - struct grub_video_adapter *next; }; typedef struct grub_video_adapter *grub_video_adapter_t; -void EXPORT_FUNC (grub_video_register) (grub_video_adapter_t adapter); -void grub_video_unregister (grub_video_adapter_t adapter); -void grub_video_iterate (int (*hook) (grub_video_adapter_t adapter)); +extern grub_video_adapter_t EXPORT_VAR(grub_video_adapter_list); + +#ifndef GRUB_LST_GENERATOR +/* Register video driver. */ +static inline void +grub_video_register (grub_video_adapter_t adapter) +{ + grub_video_adapter_t *p; + for (p = &grub_video_adapter_list; *p && (*p)->prio > adapter->prio; + p = &((*p)->next)); + adapter->next = *p; + *p = adapter; +} +#endif + +/* Unregister video driver. */ +static inline void +grub_video_unregister (grub_video_adapter_t adapter) +{ + grub_list_remove (GRUB_AS_LIST_P (&grub_video_adapter_list), + GRUB_AS_LIST (adapter)); +} + +#define FOR_VIDEO_ADAPTERS(var) FOR_LIST_ELEMENTS((var), (grub_video_adapter_list)) grub_err_t EXPORT_FUNC (grub_video_restore) (void); diff --git a/include/grub/video_fb.h b/include/grub/video_fb.h index 3046a597b..6816f6f60 100644 --- a/include/grub/video_fb.h +++ b/include/grub/video_fb.h @@ -89,8 +89,8 @@ grub_video_fb_blit_bitmap (struct grub_video_bitmap *bitmap, grub_err_t grub_video_fb_blit_render_target (struct grub_video_fbrender_target *source, - enum grub_video_blit_operators oper, - int x, int y, int offset_x, int offset_y, + enum grub_video_blit_operators oper, + int x, int y, int offset_x, int offset_y, unsigned int width, unsigned int height); grub_err_t @@ -119,11 +119,18 @@ typedef grub_err_t (*grub_video_fb_doublebuf_update_screen_t) (struct grub_video_fbrender_target *front, struct grub_video_fbrender_target *back); +typedef grub_err_t (*grub_video_fb_set_page_t) (int page); + grub_err_t -grub_video_fb_doublebuf_blit_init (struct grub_video_fbrender_target **front, - struct grub_video_fbrender_target **back, - grub_video_fb_doublebuf_update_screen_t *update_screen, - struct grub_video_mode_info mode_info, - void *framebuf); +grub_video_fb_setup (unsigned int mode_type, unsigned int mode_mask, + struct grub_video_mode_info *mode_info, + volatile void *page0_ptr, + grub_video_fb_set_page_t set_page_in, + volatile void *page1_ptr); +grub_err_t +grub_video_fb_swap_buffers (void); +grub_err_t +grub_video_fb_get_info_and_fini (struct grub_video_mode_info *mode_info, + void **framebuf); #endif /* ! GRUB_VIDEO_FB_HEADER */ diff --git a/kern/dl.c b/kern/dl.c index c6a038cfa..09849f174 100644 --- a/kern/dl.c +++ b/kern/dl.c @@ -39,31 +39,17 @@ -struct grub_dl_list -{ - struct grub_dl_list *next; - grub_dl_t mod; -}; -typedef struct grub_dl_list *grub_dl_list_t; - -static grub_dl_list_t grub_dl_head; +grub_dl_t grub_dl_head = 0; static grub_err_t grub_dl_add (grub_dl_t mod) { - grub_dl_list_t l; - if (grub_dl_get (mod->name)) return grub_error (GRUB_ERR_BAD_MODULE, "`%s' is already loaded", mod->name); - l = (grub_dl_list_t) grub_malloc (sizeof (*l)); - if (! l) - return grub_errno; - - l->mod = mod; - l->next = grub_dl_head; - grub_dl_head = l; + mod->next = grub_dl_head; + grub_dl_head = mod; return GRUB_ERR_NONE; } @@ -71,13 +57,12 @@ grub_dl_add (grub_dl_t mod) static void grub_dl_remove (grub_dl_t mod) { - grub_dl_list_t *p, q; + grub_dl_t *p, q; for (p = &grub_dl_head, q = *p; q; p = &q->next, q = *p) - if (q->mod == mod) + if (q == mod) { *p = q->next; - grub_free (q); return; } } @@ -85,25 +70,15 @@ grub_dl_remove (grub_dl_t mod) grub_dl_t grub_dl_get (const char *name) { - grub_dl_list_t l; + grub_dl_t l; for (l = grub_dl_head; l; l = l->next) - if (grub_strcmp (name, l->mod->name) == 0) - return l->mod; + if (grub_strcmp (name, l->name) == 0) + return l; return 0; } -void -grub_dl_iterate (int (*hook) (grub_dl_t mod)) -{ - grub_dl_list_t l; - - for (l = grub_dl_head; l; l = l->next) - if (hook (l->mod)) - break; -} - struct grub_symbol @@ -694,11 +669,11 @@ grub_dl_unload_unneeded (void) { /* Because grub_dl_remove modifies the list of modules, this implementation is tricky. */ - grub_dl_list_t p = grub_dl_head; + grub_dl_t p = grub_dl_head; while (p) { - if (grub_dl_unload (p->mod)) + if (grub_dl_unload (p)) { p = grub_dl_head; continue; @@ -714,13 +689,13 @@ grub_dl_unload_all (void) { while (grub_dl_head) { - grub_dl_list_t p; + grub_dl_t p; grub_dl_unload_unneeded (); /* Force to decrement the ref count. This will purge pre-loaded modules and manually inserted modules. */ for (p = grub_dl_head; p; p = p->next) - p->mod->ref_count--; + p->ref_count--; } } diff --git a/kern/efi/mm.c b/kern/efi/mm.c index ceb8fc9ba..2abd6325d 100644 --- a/kern/efi/mm.c +++ b/kern/efi/mm.c @@ -346,6 +346,7 @@ grub_efi_mm_init (void) grub_efi_uintn_t desc_size; grub_efi_uint64_t total_pages; grub_efi_uint64_t required_pages; + int mm_status; /* First of all, allocate pages to maintain allocations. */ allocated_pages @@ -361,16 +362,32 @@ grub_efi_mm_init (void) if (! memory_map) grub_fatal ("cannot allocate memory"); - filtered_memory_map = NEXT_MEMORY_DESCRIPTOR (memory_map, MEMORY_MAP_SIZE); - /* Obtain descriptors for available memory. */ map_size = MEMORY_MAP_SIZE; - if (grub_efi_get_memory_map (&map_size, memory_map, 0, &desc_size, 0) < 0) + mm_status = grub_efi_get_memory_map (&map_size, memory_map, 0, &desc_size, 0); + + if (mm_status == 0) + { + grub_efi_free_pages + ((grub_efi_physical_address_t) ((grub_addr_t) memory_map), + 2 * BYTES_TO_PAGES (MEMORY_MAP_SIZE)); + + memory_map = grub_efi_allocate_pages (0, 2 * BYTES_TO_PAGES (map_size)); + if (! memory_map) + grub_fatal ("cannot allocate memory"); + + mm_status = grub_efi_get_memory_map (&map_size, memory_map, 0, + &desc_size, 0); + } + + if (mm_status < 0) grub_fatal ("cannot get memory map"); memory_map_end = NEXT_MEMORY_DESCRIPTOR (memory_map, map_size); + filtered_memory_map = memory_map_end; + filtered_memory_map_end = filter_memory_map (memory_map, filtered_memory_map, desc_size, memory_map_end); diff --git a/kern/emu/getroot.c b/kern/emu/getroot.c index e62abe089..fa74c384b 100644 --- a/kern/emu/getroot.c +++ b/kern/emu/getroot.c @@ -80,6 +80,86 @@ xgetcwd (void) return path; } +#ifdef __linux__ + +/* Statting something on a btrfs filesystem always returns a virtual device + major/minor pair rather than the real underlying device, because btrfs + can span multiple underlying devices (and even if it's currently only + using a single device it can be dynamically extended onto another). We + can't deal with the multiple-device case yet, but in the meantime, we can + at least cope with the single-device case by scanning + /proc/self/mountinfo. */ +static char * +find_root_device_from_mountinfo (const char *dir) +{ + FILE *fp; + char *buf = NULL; + size_t len = 0; + char *ret = NULL; + + fp = fopen ("/proc/self/mountinfo", "r"); + if (! fp) + return NULL; /* fall through to other methods */ + + while (getline (&buf, &len, fp) > 0) + { + int mnt_id, parent_mnt_id; + unsigned int major, minor; + char enc_root[PATH_MAX], enc_path[PATH_MAX]; + int count; + size_t enc_path_len; + const char *sep; + char fstype[PATH_MAX], device[PATH_MAX]; + struct stat st; + + if (sscanf (buf, "%d %d %u:%u %s %s%n", + &mnt_id, &parent_mnt_id, &major, &minor, enc_root, enc_path, + &count) < 6) + continue; + + if (strcmp (enc_root, "/") != 0) + continue; /* only a subtree is mounted */ + + enc_path_len = strlen (enc_path); + if (strncmp (dir, enc_path, enc_path_len) != 0 || + (dir[enc_path_len] && dir[enc_path_len] != '/')) + continue; + + /* This is a parent of the requested directory. /proc/self/mountinfo + is in mount order, so it must be the closest parent we've + encountered so far. If it's virtual, return its device node; + otherwise, carry on to try to find something closer. */ + + free (ret); + ret = NULL; + + if (major != 0) + continue; /* not a virtual device */ + + sep = strstr (buf + count, " - "); + if (!sep) + continue; + + sep += sizeof (" - ") - 1; + if (sscanf (sep, "%s %s", fstype, device) != 2) + continue; + + if (stat (device, &st) < 0) + continue; + + if (!S_ISBLK (st.st_mode)) + continue; /* not a block device */ + + ret = strdup (device); + } + + free (buf); + fclose (fp); + return ret; +} + +#endif /* __linux__ */ + #ifdef __MINGW32__ static char * @@ -366,6 +446,12 @@ grub_guess_root_device (const char *dir) #else /* !__GNU__ */ struct stat st; +#ifdef __linux__ + os_dev = find_root_device_from_mountinfo (dir); + if (os_dev) + return os_dev; +#endif /* __linux__ */ + if (stat (dir, &st) < 0) grub_util_error ("cannot stat `%s'", dir); diff --git a/kern/emu/hostdisk.c b/kern/emu/hostdisk.c index ae2f7d9ad..bc37e9949 100644 --- a/kern/emu/hostdisk.c +++ b/kern/emu/hostdisk.c @@ -342,7 +342,7 @@ find_partition_start (const char *dev) # endif /* !defined(__NetBSD__) */ # ifdef HAVE_DEVICE_MAPPER - if (device_is_mapped (dev)) { + if (grub_device_mapper_supported () && device_is_mapped (dev)) { struct dm_task *task = NULL; grub_uint64_t start, length; char *target_type, *params, *space; @@ -413,7 +413,11 @@ devmapper_fail: if (fd == -1) { grub_error (GRUB_ERR_BAD_DEVICE, +# if !defined(__NetBSD__) "cannot open `%s' while attempting to get disk geometry", dev); +# else /* defined(__NetBSD__) */ + "cannot open `%s' while attempting to get disk label", dev); +# endif /* !defined(__NetBSD__) */ return 0; } @@ -425,7 +429,11 @@ devmapper_fail: # endif /* !defined(__NetBSD__) */ { grub_error (GRUB_ERR_BAD_DEVICE, +# if !defined(__NetBSD__) "cannot get disk geometry of `%s'", dev); +# else /* defined(__NetBSD__) */ + "cannot get disk label of `%s'", dev); +# endif /* !defined(__NetBSD__) */ close (fd); return 0; } @@ -984,6 +992,11 @@ grub_util_biosdisk_fini (void) grub_disk_dev_unregister (&grub_util_biosdisk_dev); } +/* + * Note: we do not use the new partition naming scheme as dos_part does not + * necessarily correspond to an msdos partition. See e.g. the FreeBSD code + * in function grub_util_biosdisk_get_grub_dev. + */ static char * make_device_name (int drive, int dos_part, int bsd_part) { @@ -1256,22 +1269,28 @@ devmapper_out: return path; #elif defined(__NetBSD__) - /* NetBSD uses "/dev/r[wsc]d[0-9]+[a-z]". */ + /* NetBSD uses "/dev/r[a-z]+[0-9][a-z]". */ char *path = xstrdup (os_dev); - if (strncmp ("/dev/rwd", path, 8) == 0 || - strncmp ("/dev/rsd", path, 8) == 0 || - strncmp ("/dev/rcd", path, 8) == 0) + if (strncmp ("/dev/r", path, sizeof("/dev/r") - 1) == 0 && + (path[sizeof("/dev/r") - 1] >= 'a' && path[sizeof("/dev/r") - 1] <= 'z') && + strncmp ("fd", path + sizeof("/dev/r") - 1, sizeof("fd") - 1) != 0) /* not a floppy device name */ { - char *q; - q = path + strlen(path) - 1; /* last character */ - if (grub_isalpha(*q) && grub_isdigit(*(q-1))) - { - int rawpart = -1; + char *p; + for (p = path + sizeof("/dev/r"); *p >= 'a' && *p <= 'z'; p++); + if (grub_isdigit(*p)) + { + p++; + if ((*p >= 'a' && *p <= 'z') && (*(p+1) == '\0')) + { + /* path matches the required regular expression and + p points to its last character. */ + int rawpart = -1; # ifdef HAVE_GETRAWPARTITION - rawpart = getrawpartition(); + rawpart = getrawpartition(); # endif /* HAVE_GETRAWPARTITION */ - if (rawpart >= 0) - *q = 'a' + rawpart; + if (rawpart >= 0) + *p = 'a' + rawpart; + } } } return path; @@ -1386,11 +1405,9 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev) For NetBSD, proceed as for Linux, except that the start sector is obtained from the disk label. */ { - char *name; + char *name, *partname; grub_disk_t disk; grub_disk_addr_t start; - int dos_part = -1; - int bsd_part = -1; auto int find_partition (grub_disk_t dsk, const grub_partition_t partition); @@ -1405,17 +1422,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev) if (start == part_start) { - if (partition->parent) - { - dos_part = partition->parent->number; - bsd_part = partition->number; - } - else - { - dos_part = partition->number; - bsd_part = -1; - } - + partname = grub_partition_get_name (partition); return 1; } @@ -1429,8 +1436,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev) return name; # else /* defined(__NetBSD__) */ /* Since os_dev and convert_system_partition_to_system_disk (os_dev) are - * different, we know that os_dev is of the form /dev/r[wsc]d[0-9]+[a-z] - * and in particular it cannot be a floppy device. */ + * different, we know that os_dev cannot be a floppy device. */ # endif /* !defined(__NetBSD__) */ start = find_partition_start (os_dev); @@ -1452,6 +1458,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev) if (! disk) return 0; + partname = NULL; grub_partition_iterate (disk, find_partition); if (grub_errno != GRUB_ERR_NONE) { @@ -1459,7 +1466,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev) return 0; } - if (dos_part < 0) + if (partname == NULL) { grub_disk_close (disk); grub_error (GRUB_ERR_BAD_DEVICE, @@ -1467,7 +1474,9 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev) return 0; } - return make_device_name (drive, dos_part, bsd_part); + name = grub_xasprintf ("%s,%s", disk->name, partname); + free (partname); + return name; } #elif defined(__GNU__) @@ -1512,7 +1521,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev) for (p = os_dev + 5; *p; ++p) if (grub_isdigit(*p)) { - p = strchr (p, 's'); + p = strchr (p, 's'); /* msdos or apple (or ... ?) partition map */ if (p) { p++; diff --git a/kern/emu/misc.c b/kern/emu/misc.c index 9437169e0..38395fca8 100644 --- a/kern/emu/misc.c +++ b/kern/emu/misc.c @@ -22,6 +22,10 @@ #include #include +#ifdef HAVE_DEVICE_MAPPER +# include +#endif + int verbosity; void @@ -311,3 +315,38 @@ grub_make_system_path_relative_to_its_root (const char *path) return buf3; } + +#ifdef HAVE_DEVICE_MAPPER +static void device_mapper_null_log (int level __attribute__ ((unused)), + const char *file __attribute__ ((unused)), + int line __attribute__ ((unused)), + int dm_errno __attribute__ ((unused)), + const char *f __attribute__ ((unused)), + ...) +{ +} + +int +grub_device_mapper_supported (void) +{ + static int supported = -1; + + if (supported == -1) + { + struct dm_task *dmt; + + /* Suppress annoying log messages. */ + dm_log_with_errno_init (&device_mapper_null_log); + + dmt = dm_task_create (DM_DEVICE_VERSION); + supported = (dmt != NULL); + if (dmt) + dm_task_destroy (dmt); + + /* Restore the original logger. */ + dm_log_with_errno_init (NULL); + } + + return supported; +} +#endif /* HAVE_DEVICE_MAPPER */ diff --git a/kern/fs.c b/kern/fs.c index 0c456377f..cf800f4cc 100644 --- a/kern/fs.c +++ b/kern/fs.c @@ -27,40 +27,10 @@ #include #include -static grub_fs_t grub_fs_list; +grub_fs_t grub_fs_list = 0; grub_fs_autoload_hook_t grub_fs_autoload_hook = 0; -void -grub_fs_register (grub_fs_t fs) -{ - fs->next = grub_fs_list; - grub_fs_list = fs; -} - -void -grub_fs_unregister (grub_fs_t fs) -{ - grub_fs_t *p, q; - - for (p = &grub_fs_list, q = *p; q; p = &(q->next), q = q->next) - if (q == fs) - { - *p = q->next; - break; - } -} - -void -grub_fs_iterate (int (*hook) (const grub_fs_t fs)) -{ - grub_fs_t p; - - for (p = grub_fs_list; p; p = p->next) - if (hook (p)) - break; -} - grub_fs_t grub_fs_probe (grub_device_t device) { diff --git a/kern/handler.c b/kern/handler.c deleted file mode 100644 index 2bf85313c..000000000 --- a/kern/handler.c +++ /dev/null @@ -1,64 +0,0 @@ -/* handler.c - grub handler function */ -/* - * 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 - -grub_handler_class_t grub_handler_class_list; - -void -grub_handler_register (grub_handler_class_t class, grub_handler_t handler) -{ - int first_handler = (class->handler_list == 0); - - grub_list_push (GRUB_AS_LIST_P (&class->handler_list), - GRUB_AS_LIST (handler)); - - if (first_handler) - { - grub_list_push (GRUB_AS_LIST_P (&grub_handler_class_list), - GRUB_AS_LIST (class)); - grub_handler_set_current (class, handler); - } -} - -void -grub_handler_unregister (grub_handler_class_t class, grub_handler_t handler) -{ - grub_list_remove (GRUB_AS_LIST_P (&class->handler_list), - GRUB_AS_LIST (handler)); - - if (class->handler_list == 0) - grub_list_remove (GRUB_AS_LIST_P (&grub_handler_class_list), - GRUB_AS_LIST (class)); -} - -grub_err_t -grub_handler_set_current (grub_handler_class_t class, grub_handler_t handler) -{ - if (class->cur_handler && class->cur_handler->fini) - if ((class->cur_handler->fini) () != GRUB_ERR_NONE) - return grub_errno; - - if (handler->init) - if ((handler->init) () != GRUB_ERR_NONE) - return grub_errno; - - class->cur_handler = handler; - return GRUB_ERR_NONE; -} diff --git a/kern/i386/coreboot/init.c b/kern/i386/coreboot/init.c index 8defc9589..0afbfd3af 100644 --- a/kern/i386/coreboot/init.c +++ b/kern/i386/coreboot/init.c @@ -71,6 +71,9 @@ grub_exit (void) void grub_machine_init (void) { +#ifdef GRUB_MACHINE_QEMU + grub_qemu_init_cirrus (); +#endif /* Initialize the console as early as possible. */ grub_vga_text_init (); diff --git a/kern/i386/pc/init.c b/kern/i386/pc/init.c index d81b1e117..8cbc757b2 100644 --- a/kern/i386/pc/init.c +++ b/kern/i386/pc/init.c @@ -83,6 +83,14 @@ make_install_device (void) grub_snprintf (ptr, sizeof (dev) - (ptr - dev), ")%s", grub_prefix); grub_strcpy (grub_prefix, dev); } + else if (grub_prefix[1] == ',' || grub_prefix[1] == ')') + { + /* We have a prefix, but still need to fill in the boot drive. */ + grub_snprintf (dev, sizeof (dev), + "(%cd%u%s", (grub_boot_drive & 0x80) ? 'h' : 'f', + grub_boot_drive & 0x7f, grub_prefix + 1); + grub_strcpy (grub_prefix, dev); + } return grub_prefix; } diff --git a/kern/i386/qemu/init.c b/kern/i386/qemu/init.c new file mode 100644 index 000000000..ff4c7b62f --- /dev/null +++ b/kern/i386/qemu/init.c @@ -0,0 +1,152 @@ +/* + * 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 struct {grub_uint8_t r, g, b, a; } colors[] = + { + // {R, G, B, A} + {0x00, 0x00, 0x00, 0xFF}, // 0 = black + {0x00, 0x00, 0xA8, 0xFF}, // 1 = blue + {0x00, 0xA8, 0x00, 0xFF}, // 2 = green + {0x00, 0xA8, 0xA8, 0xFF}, // 3 = cyan + {0xA8, 0x00, 0x00, 0xFF}, // 4 = red + {0xA8, 0x00, 0xA8, 0xFF}, // 5 = magenta + {0xA8, 0x54, 0x00, 0xFF}, // 6 = brown + {0xA8, 0xA8, 0xA8, 0xFF}, // 7 = light gray + + {0x54, 0x54, 0x54, 0xFF}, // 8 = dark gray + {0x54, 0x54, 0xFE, 0xFF}, // 9 = bright blue + {0x54, 0xFE, 0x54, 0xFF}, // 10 = bright green + {0x54, 0xFE, 0xFE, 0xFF}, // 11 = bright cyan + {0xFE, 0x54, 0x54, 0xFF}, // 12 = bright red + {0xFE, 0x54, 0xFE, 0xFF}, // 13 = bright magenta + {0xFE, 0xFE, 0x54, 0xFF}, // 14 = yellow + {0xFE, 0xFE, 0xFE, 0xFF} // 15 = white + }; + +#include + +static void +load_font (void) +{ + unsigned i; + + grub_vga_gr_write (0 << 2, GRUB_VGA_GR_GR6); + + grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_NORMAL, GRUB_VGA_SR_MEMORY_MODE); + grub_vga_sr_write (1 << GRUB_VGA_TEXT_FONT_PLANE, + GRUB_VGA_SR_MAP_MASK_REGISTER); + + grub_vga_gr_write (0, GRUB_VGA_GR_DATA_ROTATE); + grub_vga_gr_write (0, GRUB_VGA_GR_MODE); + grub_vga_gr_write (0xff, GRUB_VGA_GR_BITMASK); + + for (i = 0; i < 128; i++) + grub_memcpy ((void *) (0xa0000 + 32 * i), ascii_bitmaps + 16 * (0x7f - i), 16); +} + +static void +load_palette (void) +{ + unsigned i; + for (i = 0; i < 16; i++) + { + grub_outb (i, GRUB_VGA_IO_ARX); + grub_outb (i, GRUB_VGA_IO_ARX); + } + + for (i = 0; i < ARRAY_SIZE (colors); i++) + grub_vga_palette_write (i, colors[i].r, colors[i].g, colors[i].b); +} + +void +grub_qemu_init_cirrus (void) +{ + auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid); + int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused))) + { + grub_pci_address_t addr; + grub_uint32_t class; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); + class = grub_pci_read (addr); + + if (((class >> 16) & 0xffff) != 0x0300) + return 0; + + /* FIXME: chooose addresses dynamically. */ + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); + grub_pci_write (addr, 0xf0000000 | GRUB_PCI_ADDR_MEM_PREFETCH + | GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32); + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG1); + grub_pci_write (addr, 0xf2000000 + | GRUB_PCI_ADDR_SPACE_MEMORY | GRUB_PCI_ADDR_MEM_TYPE_32); + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_COMMAND); + grub_pci_write (addr, GRUB_PCI_COMMAND_MEM_ENABLED + | GRUB_PCI_COMMAND_IO_ENABLED); + + return 1; + } + + grub_pci_iterate (find_card); + + grub_outb (1, 0x3c2); + + load_font (); + + grub_vga_gr_write (GRUB_VGA_GR_GR6_MMAP_CGA, GRUB_VGA_GR_GR6); + grub_vga_gr_write (GRUB_VGA_GR_MODE_ODD_EVEN, GRUB_VGA_GR_MODE); + + grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_NORMAL, GRUB_VGA_SR_MEMORY_MODE); + + grub_vga_sr_write ((1 << GRUB_VGA_TEXT_TEXT_PLANE) + | (1 << GRUB_VGA_TEXT_ATTR_PLANE), + GRUB_VGA_SR_MAP_MASK_REGISTER); + + grub_vga_cr_write (15, GRUB_VGA_CR_CELL_HEIGHT); + grub_vga_cr_write (79, GRUB_VGA_CR_WIDTH); + grub_vga_cr_write (40, GRUB_VGA_CR_PITCH); + + int vert = 25 * 16; + grub_vga_cr_write (vert & 0xff, GRUB_VGA_CR_HEIGHT); + grub_vga_cr_write (((vert >> GRUB_VGA_CR_OVERFLOW_HEIGHT1_SHIFT) + & GRUB_VGA_CR_OVERFLOW_HEIGHT1_MASK) + | ((vert >> GRUB_VGA_CR_OVERFLOW_HEIGHT2_SHIFT) + & GRUB_VGA_CR_OVERFLOW_HEIGHT2_MASK), + GRUB_VGA_CR_OVERFLOW); + + load_palette (); + + grub_outb (0x10, 0x3c0); + grub_outb (0, 0x3c1); + grub_outb (0x14, 0x3c0); + grub_outb (0, 0x3c1); + + grub_vga_sr_write (GRUB_VGA_SR_CLOCKING_MODE_8_DOT_CLOCK, + GRUB_VGA_SR_CLOCKING_MODE); + + grub_vga_cr_write (14, GRUB_VGA_CR_CURSOR_START); + grub_vga_cr_write (15, GRUB_VGA_CR_CURSOR_END); + + grub_outb (0x20, 0x3c0); +} diff --git a/kern/i386/qemu/mmap.c b/kern/i386/qemu/mmap.c index c7fc4f45e..f2a998e78 100644 --- a/kern/i386/qemu/mmap.c +++ b/kern/i386/qemu/mmap.c @@ -27,21 +27,37 @@ #define QEMU_CMOS_MEMSIZE_HIGH 0x35 #define QEMU_CMOS_MEMSIZE_LOW 0x34 +#define QEMU_CMOS_MEMSIZE2_HIGH 0x31 +#define QEMU_CMOS_MEMSIZE2_LOW 0x30 + #define min(a,b) ((a) > (b) ? (b) : (a)) extern char _start[]; extern char _end[]; -grub_size_t grub_lower_mem, grub_upper_mem; -grub_uint64_t mem_size; +static grub_uint64_t mem_size, above_4g; void grub_machine_mmap_init () { - mem_size = grub_cmos_read (QEMU_CMOS_MEMSIZE_HIGH) << 24 | grub_cmos_read (QEMU_CMOS_MEMSIZE_LOW) << 16; + mem_size = ((grub_uint64_t) grub_cmos_read (QEMU_CMOS_MEMSIZE_HIGH)) << 24 + | ((grub_uint64_t) grub_cmos_read (QEMU_CMOS_MEMSIZE_LOW)) << 16; + if (mem_size > 0) + { + /* Don't ask... */ + mem_size += (16 * 1024 * 1024); + } + else + { + mem_size + = ((((grub_uint64_t) grub_cmos_read (QEMU_CMOS_MEMSIZE2_HIGH)) << 18) + | ((grub_uint64_t) (grub_cmos_read (QEMU_CMOS_MEMSIZE2_LOW)) << 10)) + + 1024 * 1024; + } - /* Don't ask... */ - mem_size += (16 * 1024 * 1024); + above_4g = (((grub_uint64_t) grub_cmos_read (0x5b)) << 16) + | (((grub_uint64_t) grub_cmos_read (0x5c)) << 24) + | (((grub_uint64_t) grub_cmos_read (0x5d)) << 32); } grub_err_t @@ -57,6 +73,12 @@ grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uin GRUB_MACHINE_MEMORY_RESERVED)) return 1; + /* Everything else is free. */ + if (hook (0x100000, + min (mem_size, (grub_uint32_t) -GRUB_BOOT_MACHINE_SIZE) - 0x100000, + GRUB_MACHINE_MEMORY_AVAILABLE)) + return 1; + /* Protect boot.img, which contains the gdt. It is mapped at the top of memory (it is also mapped below 0x100000, but we already reserved that area). */ if (hook ((grub_uint32_t) -GRUB_BOOT_MACHINE_SIZE, @@ -64,10 +86,8 @@ grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uin GRUB_MACHINE_MEMORY_RESERVED)) return 1; - /* Everything else is free. */ - if (hook (0x100000, - min (mem_size, (grub_uint32_t) -GRUB_BOOT_MACHINE_SIZE) - 0x100000, - GRUB_MACHINE_MEMORY_AVAILABLE)) + if (above_4g != 0 && hook (0x100000000ULL, above_4g, + GRUB_MACHINE_MEMORY_AVAILABLE)) return 1; return 0; diff --git a/kern/list.c b/kern/list.c index 379b0d886..33c334166 100644 --- a/kern/list.c +++ b/kern/list.c @@ -28,18 +28,6 @@ grub_list_push (grub_list_t *head, grub_list_t item) *head = item; } -void * -grub_list_pop (grub_list_t *head) -{ - grub_list_t item; - - item = *head; - if (item) - *head = item->next; - - return item; -} - void grub_list_remove (grub_list_t *head, grub_list_t item) { @@ -53,51 +41,16 @@ grub_list_remove (grub_list_t *head, grub_list_t item) } } -int -grub_list_iterate (grub_list_t head, grub_list_hook_t hook) -{ - grub_list_t p; - - for (p = head; p; p = p->next) - if (hook (p)) - return 1; - - return 0; -} - -void -grub_list_insert (grub_list_t *head, grub_list_t item, - grub_list_test_t test) -{ - grub_list_t *p, q; - - for (p = head, q = *p; q; p = &(q->next), q = q->next) - if (test (item, q)) - break; - - *p = item; - item->next = q; -} - void * grub_named_list_find (grub_named_list_t head, const char *name) { - grub_named_list_t result = NULL; + grub_named_list_t item; - auto int list_find (grub_named_list_t item); - int list_find (grub_named_list_t item) - { - if (! grub_strcmp (item->name, name)) - { - result = item; - return 1; - } + FOR_LIST_ELEMENTS (item, head) + if (grub_strcmp (item->name, name) == 0) + return item; - return 0; - } - - grub_list_iterate (GRUB_AS_LIST (head), (grub_list_hook_t) list_find); - return result; + return NULL; } void @@ -105,27 +58,30 @@ grub_prio_list_insert (grub_prio_list_t *head, grub_prio_list_t nitem) { int inactive = 0; - auto int test (grub_prio_list_t new_item, grub_prio_list_t item); - int test (grub_prio_list_t new_item, grub_prio_list_t item) + grub_prio_list_t *p, q; + + for (p = head, q = *p; q; p = &(q->next), q = q->next) { int r; - r = grub_strcmp (new_item->name, item->name); - if (r) - return (r < 0); + r = grub_strcmp (nitem->name, q->name); + if (r < 0) + break; + if (r > 0) + continue; - if (new_item->prio >= (item->prio & GRUB_PRIO_LIST_PRIO_MASK)) + if (nitem->prio >= (q->prio & GRUB_PRIO_LIST_PRIO_MASK)) { - item->prio &= ~GRUB_PRIO_LIST_FLAG_ACTIVE; - return 1; + q->prio &= ~GRUB_PRIO_LIST_FLAG_ACTIVE; + break; } inactive = 1; - return 0; } - grub_list_insert (GRUB_AS_LIST_P (head), GRUB_AS_LIST (nitem), - (grub_list_test_t) test); + *p = nitem; + nitem->next = q; + if (! inactive) nitem->prio |= GRUB_PRIO_LIST_FLAG_ACTIVE; } diff --git a/kern/main.c b/kern/main.c index 1fdf4ab07..8b6c8a180 100644 --- a/kern/main.c +++ b/kern/main.c @@ -191,7 +191,6 @@ grub_main (void) grub_set_root_dev (); grub_register_core_commands (); - grub_register_rescue_parser (); grub_load_config (); grub_load_normal_mode (); diff --git a/kern/parser.c b/kern/parser.c index 07597a1a8..6370a7b3a 100644 --- a/kern/parser.c +++ b/kern/parser.c @@ -230,10 +230,6 @@ grub_parser_split_cmdline (const char *cmdline, grub_reader_getline_t getline, return 0; } -struct grub_handler_class grub_parser_class = { - .name = "parser" -}; - grub_err_t grub_parser_execute (char *source) { @@ -261,11 +257,9 @@ grub_parser_execute (char *source) while (source) { char *line; - grub_parser_t parser; getline (&line, 0); - parser = grub_parser_get_current (); - parser->parse_line (line, getline); + grub_rescue_parse_line (line, getline); grub_free (line); } diff --git a/kern/rescue_parser.c b/kern/rescue_parser.c index d3725e739..9c85ba6bd 100644 --- a/kern/rescue_parser.c +++ b/kern/rescue_parser.c @@ -24,7 +24,7 @@ #include #include -static grub_err_t +grub_err_t grub_rescue_parse_line (char *line, grub_reader_getline_t getline) { char *name; @@ -74,15 +74,3 @@ grub_rescue_parse_line (char *line, grub_reader_getline_t getline) return grub_errno; } - -static struct grub_parser grub_rescue_parser = - { - .name = "rescue", - .parse_line = grub_rescue_parse_line - }; - -void -grub_register_rescue_parser (void) -{ - grub_parser_register ("rescue", &grub_rescue_parser); -} diff --git a/kern/rescue_reader.c b/kern/rescue_reader.c index f573cf41f..2f053aaea 100644 --- a/kern/rescue_reader.c +++ b/kern/rescue_reader.c @@ -86,7 +86,7 @@ grub_rescue_run (void) if (! line || line[0] == '\0') continue; - grub_parser_get_current ()->parse_line (line, grub_rescue_read_line); + grub_rescue_parse_line (line, grub_rescue_read_line); grub_free (line); } } diff --git a/loader/i386/efi/linux.c b/loader/i386/efi/linux.c index a6db22e22..d37feb983 100644 --- a/loader/i386/efi/linux.c +++ b/loader/i386/efi/linux.c @@ -29,10 +29,11 @@ #include #include #include -#include -#include #include #include +#include +#include +#include #include #define GRUB_LINUX_CL_OFFSET 0x1000 @@ -286,6 +287,67 @@ grub_e820_add_region (struct grub_e820_mmap *e820_map, int *e820_num, } } +static grub_err_t +grub_linux_setup_video (struct linux_kernel_params *params) +{ + struct grub_video_mode_info mode_info; + void *framebuffer; + grub_err_t err; + + err = grub_video_get_info_and_fini (&mode_info, &framebuffer); + + if (err) + return err; + + params->lfb_width = mode_info.width; + params->lfb_height = mode_info.height; + params->lfb_depth = mode_info.bpp; + params->lfb_line_len = mode_info.pitch; + + params->lfb_base = (grub_size_t) framebuffer; + params->lfb_size = ALIGN_UP (params->lfb_line_len * params->lfb_height, + 65536); + + params->red_mask_size = mode_info.red_mask_size; + params->red_field_pos = mode_info.red_field_pos; + params->green_mask_size = mode_info.green_mask_size; + params->green_field_pos = mode_info.green_field_pos; + params->blue_mask_size = mode_info.blue_mask_size; + params->blue_field_pos = mode_info.blue_field_pos; + params->reserved_mask_size = mode_info.reserved_mask_size; + params->reserved_field_pos = mode_info.reserved_field_pos; + + params->have_vga = GRUB_VIDEO_LINUX_TYPE_SIMPLE; + +#ifdef GRUB_MACHINE_PCBIOS + /* VESA packed modes may come with zeroed mask sizes, which need + to be set here according to DAC Palette width. If we don't, + this results in Linux displaying a black screen. */ + if (mode_info.bpp <= 8) + { + struct grub_vbe_info_block controller_info; + int status; + int width = 8; + + status = grub_vbe_bios_get_controller_info (&controller_info); + + if (status == GRUB_VBE_STATUS_OK && + (controller_info.capabilities & GRUB_VBE_CAPABILITY_DACWIDTH)) + status = grub_vbe_bios_set_dac_palette_width (&width); + + if (status != GRUB_VBE_STATUS_OK) + /* 6 is default after mode reset. */ + width = 6; + + params->red_mask_size = params->green_mask_size + = params->blue_mask_size = width; + params->reserved_mask_size = 0; + } +#endif + + return 0; +} + #ifdef __x86_64__ extern grub_uint8_t grub_linux_trampoline_start[]; extern grub_uint8_t grub_linux_trampoline_end[]; @@ -300,6 +362,9 @@ grub_linux_boot (void) grub_efi_uintn_t desc_size; grub_efi_uint32_t desc_version; int e820_num; + const char *modevar; + char *tmp; + grub_err_t err; params = real_mode_mem; @@ -353,6 +418,35 @@ grub_linux_boot (void) grub_mmap_iterate (hook); params->mmap_size = e820_num; + grub_dprintf ("linux", "Trampoline at %p. code32=%x, real_mode_mem=%p\n", + ((char *) prot_mode_mem + (prot_mode_pages << 12)), + (unsigned) params->code32_start, real_mode_mem); + + modevar = grub_env_get ("gfxpayload"); + + /* Now all graphical modes are acceptable. + May change in future if we have modes without framebuffer. */ + if (modevar && *modevar != 0) + { + tmp = grub_xasprintf ("%s;auto", modevar); + if (! tmp) + return grub_errno; + err = grub_video_set_mode (tmp, GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0); + grub_free (tmp); + } + else + err = grub_video_set_mode ("auto", GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0); + + if (!err) + err = grub_linux_setup_video (params); + + if (err) + { + grub_print_error (); + grub_printf ("Booting however\n"); + grub_errno = GRUB_ERR_NONE; + } + mmap_size = find_mmap_size (); if (grub_efi_get_memory_map (&mmap_size, mmap_buf, &map_key, &desc_size, &desc_version) <= 0) @@ -425,174 +519,6 @@ grub_linux_unload (void) return GRUB_ERR_NONE; } -static grub_efi_guid_t uga_draw_guid = GRUB_EFI_UGA_DRAW_GUID; - - -#define RGB_MASK 0xffffff -#define RGB_MAGIC 0x121314 -#define LINE_MIN 800 -#define LINE_MAX 4096 -#define FBTEST_STEP (0x10000 >> 2) -#define FBTEST_COUNT 8 - -static int -find_line_len (grub_uint32_t *fb_base, grub_uint32_t *line_len) -{ - grub_uint32_t *base = (grub_uint32_t *) (grub_target_addr_t) *fb_base; - int i; - - for (i = 0; i < FBTEST_COUNT; i++, base += FBTEST_STEP) - { - if ((*base & RGB_MASK) == RGB_MAGIC) - { - int j; - - for (j = LINE_MIN; j <= LINE_MAX; j++) - { - if ((base[j] & RGB_MASK) == RGB_MAGIC) - { - *fb_base = (grub_uint32_t) (grub_target_addr_t) base; - *line_len = j << 2; - - return 1; - } - } - - break; - } - } - - return 0; -} - -static int -find_framebuf (grub_uint32_t *fb_base, grub_uint32_t *line_len) -{ - int found = 0; - - auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, - grub_pci_id_t pciid); - - int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, - grub_pci_id_t pciid) - { - grub_pci_address_t addr; - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); - if (grub_pci_read (addr) >> 24 == 0x3) - { - int i; - - grub_printf ("Display controller: %d:%d.%d\nDevice id: %x\n", - grub_pci_get_bus (dev), grub_pci_get_device (dev), - grub_pci_get_function (dev), pciid); - addr += 8; - for (i = 0; i < 6; i++, addr += 4) - { - grub_uint32_t old_bar1, old_bar2, type; - grub_uint64_t base64; - - old_bar1 = grub_pci_read (addr); - if ((! old_bar1) || (old_bar1 & GRUB_PCI_ADDR_SPACE_IO)) - continue; - - type = old_bar1 & GRUB_PCI_ADDR_MEM_TYPE_MASK; - if (type == GRUB_PCI_ADDR_MEM_TYPE_64) - { - if (i == 5) - break; - - old_bar2 = grub_pci_read (addr + 4); - } - else - old_bar2 = 0; - - base64 = old_bar2; - base64 <<= 32; - base64 |= (old_bar1 & GRUB_PCI_ADDR_MEM_MASK); - - grub_printf ("%s(%d): 0x%llx\n", - ((old_bar1 & GRUB_PCI_ADDR_MEM_PREFETCH) ? - "VMEM" : "MMIO"), i, - (unsigned long long) base64); - - if ((old_bar1 & GRUB_PCI_ADDR_MEM_PREFETCH) && (! found)) - { - *fb_base = base64; - if (find_line_len (fb_base, line_len)) - found++; - } - - if (type == GRUB_PCI_ADDR_MEM_TYPE_64) - { - i++; - addr += 4; - } - } - } - - return found; - } - - grub_pci_iterate (find_card); - return found; -} - -static int -grub_linux_setup_video (struct linux_kernel_params *params) -{ - grub_efi_uga_draw_protocol_t *c; - grub_uint32_t width, height, depth, rate, pixel, fb_base, line_len; - int ret; - - c = grub_efi_locate_protocol (&uga_draw_guid, 0); - if (! c) - return 1; - - if (efi_call_5 (c->get_mode, c, &width, &height, &depth, &rate)) - return 1; - - grub_printf ("Video mode: %ux%u-%u@%u\n", width, height, depth, rate); - - grub_efi_set_text_mode (0); - pixel = RGB_MAGIC; - efi_call_10 (c->blt, c, (struct grub_efi_uga_pixel *) &pixel, - GRUB_EFI_UGA_VIDEO_FILL, 0, 0, 0, 0, 1, height, 0); - ret = find_framebuf (&fb_base, &line_len); - grub_efi_set_text_mode (1); - - if (! ret) - { - grub_printf ("Can\'t find frame buffer address\n"); - return 1; - } - - grub_printf ("Frame buffer base: 0x%x\n", fb_base); - grub_printf ("Video line length: %d\n", line_len); - - params->lfb_width = width; - params->lfb_height = height; - params->lfb_depth = depth; - params->lfb_line_len = line_len; - - params->lfb_base = fb_base; - params->lfb_size = ALIGN_UP (line_len * params->lfb_height, 65536); - - params->red_mask_size = 8; - params->red_field_pos = 16; - params->green_mask_size = 8; - params->green_field_pos = 8; - params->blue_mask_size = 8; - params->blue_field_pos = 0; - params->reserved_mask_size = 8; - params->reserved_field_pos = 24; - - params->have_vga = GRUB_VIDEO_LINUX_TYPE_VESA; - params->vid_mode = 0x338; /* 1024x768x32 */ - - return 0; -} - static grub_err_t grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), int argc, char *argv[]) @@ -806,10 +732,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), grub_file_seek (file, real_size + GRUB_DISK_SECTOR_SIZE); /* XXX there is no way to know if the kernel really supports EFI. */ - grub_printf (" [Linux-bzImage, setup=0x%x, size=0x%x]\n", - (unsigned) real_size, (unsigned) prot_size); - - grub_linux_setup_video (params); + grub_dprintf ("linux", "bzImage, setup=0x%x, size=0x%x\n", + (unsigned) real_size, (unsigned) prot_size); /* Detect explicitly specified memory size, if any. */ linux_mem_size = 0; @@ -876,7 +800,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), if (grub_errno == GRUB_ERR_NONE) { - grub_loader_set (grub_linux_boot, grub_linux_unload, 1); + grub_loader_set (grub_linux_boot, grub_linux_unload, 0); loaded = 1; } @@ -989,8 +913,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; diff --git a/loader/i386/efi/xnu.c b/loader/i386/efi/xnu.c deleted file mode 100644 index e80f7f3dd..000000000 --- a/loader/i386/efi/xnu.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2009 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GRUB. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* Setup video for xnu. Big parts are copied from linux.c. */ - -static grub_efi_guid_t uga_draw_guid = GRUB_EFI_UGA_DRAW_GUID; - -#define RGB_MASK 0xffffff -#define RGB_MAGIC 0x121314 -#define LINE_MIN 800 -#define LINE_MAX 4096 -#define FBTEST_STEP (0x10000 >> 2) -#define FBTEST_COUNT 8 - -static int -find_line_len (grub_uint32_t *fb_base, grub_uint32_t *line_len) -{ - grub_uint32_t *base = (grub_uint32_t *) (grub_target_addr_t) *fb_base; - int i; - - for (i = 0; i < FBTEST_COUNT; i++, base += FBTEST_STEP) - { - if ((*base & RGB_MASK) == RGB_MAGIC) - { - int j; - - for (j = LINE_MIN; j <= LINE_MAX; j++) - { - if ((base[j] & RGB_MASK) == RGB_MAGIC) - { - *fb_base = (grub_uint32_t) (grub_target_addr_t) base; - *line_len = j << 2; - - return 1; - } - } - - break; - } - } - - return 0; -} - -static int -find_framebuf (grub_uint32_t *fb_base, grub_uint32_t *line_len) -{ - int found = 0; - - auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, - grub_pci_id_t pciid); - - int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, - grub_pci_id_t pciid) - { - grub_pci_address_t addr; - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); - if (grub_pci_read (addr) >> 24 == 0x3) - { - int i; - - grub_printf ("Display controller: %d:%d.%d\nDevice id: %x\n", - grub_pci_get_bus (dev), grub_pci_get_device (dev), - grub_pci_get_function (dev), pciid); - addr += 8; - for (i = 0; i < 6; i++, addr += 4) - { - grub_uint32_t old_bar1, old_bar2, type; - grub_uint64_t base64; - - old_bar1 = grub_pci_read (addr); - if ((! old_bar1) || (old_bar1 & GRUB_PCI_ADDR_SPACE_IO)) - continue; - - type = old_bar1 & GRUB_PCI_ADDR_MEM_TYPE_MASK; - if (type == GRUB_PCI_ADDR_MEM_TYPE_64) - { - if (i == 5) - break; - - old_bar2 = grub_pci_read (addr + 4); - } - else - old_bar2 = 0; - - base64 = old_bar2; - base64 <<= 32; - base64 |= (old_bar1 & GRUB_PCI_ADDR_MEM_MASK); - - grub_printf ("%s(%d): 0x%llx\n", - ((old_bar1 & GRUB_PCI_ADDR_MEM_PREFETCH) ? - "VMEM" : "MMIO"), i, - (unsigned long long) base64); - - if ((old_bar1 & GRUB_PCI_ADDR_MEM_PREFETCH) && (! found)) - { - *fb_base = base64; - if (find_line_len (fb_base, line_len)) - found++; - } - - if (type == GRUB_PCI_ADDR_MEM_TYPE_64) - { - i++; - addr += 4; - } - } - } - - return found; - } - - grub_pci_iterate (find_card); - return found; -} - -grub_err_t -grub_xnu_set_video (struct grub_xnu_boot_params *params) -{ - grub_efi_uga_draw_protocol_t *c; - grub_uint32_t width, height, depth, rate, pixel, fb_base, line_len; - int ret; - - c = grub_efi_locate_protocol (&uga_draw_guid, 0); - if (! c) - return grub_error (GRUB_ERR_IO, "couldn't find UGADraw"); - - if (efi_call_5 (c->get_mode, c, &width, &height, &depth, &rate)) - return grub_error (GRUB_ERR_IO, "couldn't retrieve video mode"); - - grub_printf ("Video mode: %ux%u-%u@%u\n", width, height, depth, rate); - - grub_efi_set_text_mode (0); - pixel = RGB_MAGIC; - efi_call_10 (c->blt, c, (struct grub_efi_uga_pixel *) &pixel, - GRUB_EFI_UGA_VIDEO_FILL, 0, 0, 0, 0, 1, height, 0); - ret = find_framebuf (&fb_base, &line_len); - grub_efi_set_text_mode (1); - - if (! ret) - return grub_error (GRUB_ERR_IO, "can\'t find frame buffer address"); - - grub_printf ("Frame buffer base: 0x%x\n", fb_base); - grub_printf ("Video line length: %d\n", line_len); - - params->lfb_width = width; - params->lfb_height = height; - params->lfb_depth = depth; - params->lfb_line_len = line_len; - params->lfb_mode = GRUB_XNU_VIDEO_TEXT_IN_VIDEO; - params->lfb_base = fb_base; - return GRUB_ERR_NONE; -} diff --git a/loader/i386/ieee1275/linux.c b/loader/i386/ieee1275/linux.c index 8780804fd..9f7556ffa 100644 --- a/loader/i386/ieee1275/linux.c +++ b/loader/i386/ieee1275/linux.c @@ -205,8 +205,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), real_size = setup_sects << GRUB_DISK_SECTOR_BITS; prot_size = grub_file_size (file) - real_size - GRUB_DISK_SECTOR_SIZE; - grub_printf (" [Linux-%s, setup=0x%x, size=0x%x]\n", - "bzImage", real_size, prot_size); + grub_dprintf ("linux", "Linux-%s, setup=0x%x, size=0x%x\n", + "bzImage", real_size, prot_size); grub_file_seek (file, real_size + GRUB_DISK_SECTOR_SIZE); if (grub_errno) diff --git a/loader/i386/multiboot_mbi.c b/loader/i386/multiboot_mbi.c index 3d974f04e..d984e4e4e 100644 --- a/loader/i386/multiboot_mbi.c +++ b/loader/i386/multiboot_mbi.c @@ -295,8 +295,8 @@ retrieve_video_parameters (struct multiboot_info *mbi, 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_red_field_position = mode_info.red_field_pos; + mbi->framebuffer_red_mask_size = mode_info.red_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; diff --git a/loader/i386/pc/linux.c b/loader/i386/pc/linux.c index 0fa9abc12..04bc66661 100644 --- a/loader/i386/pc/linux.c +++ b/loader/i386/pc/linux.c @@ -182,8 +182,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), goto fail; } - grub_printf (" [Linux-%s, setup=0x%x, size=0x%x]\n", - grub_linux_is_bzimage ? "bzImage" : "zImage", real_size, prot_size); + grub_dprintf ("linux", "Linux-%s, setup=0x%x, size=0x%x\n", + grub_linux_is_bzimage ? "bzImage" : "zImage", + real_size, prot_size); for (i = 1; i < argc; i++) if (grub_memcmp (argv[i], "vga=", 4) == 0) diff --git a/loader/i386/pc/xnu.c b/loader/i386/pc/xnu.c deleted file mode 100644 index 39a595d9b..000000000 --- a/loader/i386/pc/xnu.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2009 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GRUB. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include - -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#define max(a,b) (((a) > (b)) ? (a) : (b)) - -#define DEFAULT_VIDEO_MODE "auto" - -/* Setup video for xnu. */ -grub_err_t -grub_xnu_set_video (struct grub_xnu_boot_params *params) -{ - struct grub_video_mode_info mode_info; - int ret; - char *tmp; - const char *modevar; - void *framebuffer; - grub_err_t err; - struct grub_video_bitmap *bitmap = NULL; - - modevar = grub_env_get ("gfxpayload"); - /* Consider only graphical 32-bit deep modes. */ - if (! modevar || *modevar == 0) - 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_xasprintf ("%s;" DEFAULT_VIDEO_MODE, modevar); - if (! tmp) - return grub_errno; - 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); - } - - if (err) - return err; - - ret = grub_video_get_info (&mode_info); - if (ret) - return grub_error (GRUB_ERR_IO, "couldn't retrieve video parameters"); - - if (grub_xnu_bitmap) - { - if (grub_xnu_bitmap_mode == GRUB_XNU_BITMAP_STRETCH) - err = grub_video_bitmap_create_scaled (&bitmap, - mode_info.width, - mode_info.height, - grub_xnu_bitmap, - GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST); - else - bitmap = grub_xnu_bitmap; - } - - if (bitmap) - { - int x, y; - - x = mode_info.width - bitmap->mode_info.width; - x /= 2; - y = mode_info.height - bitmap->mode_info.height; - y /= 2; - err = grub_video_blit_bitmap (bitmap, - GRUB_VIDEO_BLIT_REPLACE, - x > 0 ? x : 0, - y > 0 ? y : 0, - x < 0 ? -x : 0, - y < 0 ? -y : 0, - min (bitmap->mode_info.width, - mode_info.width), - min (bitmap->mode_info.height, - mode_info.height)); - } - if (err) - { - grub_print_error (); - grub_errno = GRUB_ERR_NONE; - bitmap = 0; - } - - ret = grub_video_get_info_and_fini (&mode_info, &framebuffer); - if (ret) - return grub_error (GRUB_ERR_IO, "couldn't retrieve video parameters"); - - params->lfb_width = mode_info.width; - params->lfb_height = mode_info.height; - params->lfb_depth = mode_info.bpp; - params->lfb_line_len = mode_info.pitch; - - params->lfb_base = PTR_TO_UINT32 (framebuffer); - params->lfb_mode = bitmap ? GRUB_XNU_VIDEO_SPLASH - : GRUB_XNU_VIDEO_TEXT_IN_VIDEO; - - return GRUB_ERR_NONE; -} - diff --git a/loader/i386/xnu.c b/loader/i386/xnu.c index 8000579d0..5f18d744b 100644 --- a/loader/i386/xnu.c +++ b/loader/i386/xnu.c @@ -33,6 +33,12 @@ #include #include #include +#include + +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#define max(a,b) (((a) > (b)) ? (a) : (b)) + +#define DEFAULT_VIDEO_MODE "auto" char grub_xnu_cmdline[1024]; grub_uint32_t grub_xnu_heap_will_be_at; @@ -838,6 +844,98 @@ grub_xnu_boot_resume (void) state); } +/* Setup video for xnu. */ +static grub_err_t +grub_xnu_set_video (struct grub_xnu_boot_params *params) +{ + struct grub_video_mode_info mode_info; + int ret; + char *tmp; + const char *modevar; + void *framebuffer; + grub_err_t err; + struct grub_video_bitmap *bitmap = NULL; + + modevar = grub_env_get ("gfxpayload"); + /* Consider only graphical 32-bit deep modes. */ + if (! modevar || *modevar == 0) + 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_xasprintf ("%s;" DEFAULT_VIDEO_MODE, modevar); + if (! tmp) + return grub_errno; + 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); + } + + if (err) + return err; + + ret = grub_video_get_info (&mode_info); + if (ret) + return grub_error (GRUB_ERR_IO, "couldn't retrieve video parameters"); + + if (grub_xnu_bitmap) + { + if (grub_xnu_bitmap_mode == GRUB_XNU_BITMAP_STRETCH) + err = grub_video_bitmap_create_scaled (&bitmap, + mode_info.width, + mode_info.height, + grub_xnu_bitmap, + GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST); + else + bitmap = grub_xnu_bitmap; + } + + if (bitmap) + { + int x, y; + + x = mode_info.width - bitmap->mode_info.width; + x /= 2; + y = mode_info.height - bitmap->mode_info.height; + y /= 2; + err = grub_video_blit_bitmap (bitmap, + GRUB_VIDEO_BLIT_REPLACE, + x > 0 ? x : 0, + y > 0 ? y : 0, + x < 0 ? -x : 0, + y < 0 ? -y : 0, + min (bitmap->mode_info.width, + mode_info.width), + min (bitmap->mode_info.height, + mode_info.height)); + } + if (err) + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + bitmap = 0; + } + + ret = grub_video_get_info_and_fini (&mode_info, &framebuffer); + if (ret) + return grub_error (GRUB_ERR_IO, "couldn't retrieve video parameters"); + + params->lfb_width = mode_info.width; + params->lfb_height = mode_info.height; + params->lfb_depth = mode_info.bpp; + params->lfb_line_len = mode_info.pitch; + + params->lfb_base = PTR_TO_UINT32 (framebuffer); + params->lfb_mode = bitmap ? GRUB_XNU_VIDEO_SPLASH + : GRUB_XNU_VIDEO_TEXT_IN_VIDEO; + + return GRUB_ERR_NONE; +} + /* Boot xnu. */ grub_err_t grub_xnu_boot (void) diff --git a/loader/multiboot_elfxx.c b/loader/multiboot_elfxx.c index 92a52d3a8..78b7c542c 100644 --- a/loader/multiboot_elfxx.c +++ b/loader/multiboot_elfxx.c @@ -74,7 +74,11 @@ CONCAT(grub_multiboot_load_elf, XX) (grub_file_t file, void *buffer) if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > MULTIBOOT_SEARCH) return grub_error (GRUB_ERR_BAD_OS, "program header at a too high offset"); -#ifdef MULTIBOOT_LOAD_ELF64 +#if defined (MULTIBOOT_LOAD_ELF64) && defined (__mips) + /* We still in 32-bit mode. */ + if (ehdr->e_entry < 0xffffffff80000000ULL) + return grub_error (GRUB_ERR_BAD_OS, "invalid entry point for ELF64"); +#else /* We still in 32-bit mode. */ if (ehdr->e_entry > 0xffffffff) return grub_error (GRUB_ERR_BAD_OS, "invalid entry point for ELF64"); diff --git a/loader/multiboot_mbi2.c b/loader/multiboot_mbi2.c index 7e9cebe49..3ad6a6c4a 100644 --- a/loader/multiboot_mbi2.c +++ b/loader/multiboot_mbi2.c @@ -441,9 +441,8 @@ retrieve_video_parameters (grub_uint8_t **ptrorig) else { tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_RGB; - tag->common.framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_RGB; - tag->framebuffer_red_field_position = mode_info.green_field_pos; - tag->framebuffer_red_mask_size = mode_info.green_mask_size; + tag->framebuffer_red_field_position = mode_info.red_field_pos; + tag->framebuffer_red_mask_size = mode_info.red_mask_size; tag->framebuffer_green_field_position = mode_info.green_field_pos; tag->framebuffer_green_mask_size = mode_info.green_mask_size; tag->framebuffer_blue_field_position = mode_info.blue_field_pos; @@ -496,7 +495,7 @@ grub_multiboot_make_mbi (void *orig, grub_uint32_t dest, grub_off_t buf_off, = (struct multiboot_tag_module *) ptrorig; tag->type = MULTIBOOT_TAG_TYPE_MODULE; tag->size = sizeof (struct multiboot_tag_module) + cur->cmdline_size; - tag->mod_start = dest + cur->start; + tag->mod_start = cur->start; tag->mod_end = tag->mod_start + cur->size; grub_memcpy (tag->cmdline, cur->cmdline, cur->cmdline_size); ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); diff --git a/mmap/i386/pc/mmap_helper.S b/mmap/i386/pc/mmap_helper.S index 743954574..3302a9a15 100644 --- a/mmap/i386/pc/mmap_helper.S +++ b/mmap/i386/pc/mmap_helper.S @@ -59,7 +59,7 @@ LOCAL (e801): movw %bx, %dx pop %ds clc - iret + jmp LOCAL (iret_cf) LOCAL (h88): popf @@ -69,7 +69,7 @@ LOCAL (h88): movw DS (LOCAL (kbin16mb)), %ax pop %ds clc - iret + jmp LOCAL (iret_cf) LOCAL (e820): popf @@ -101,12 +101,18 @@ LOCAL (noclean): mov $0x534d4150, %eax pop %ds clc - iret + jmp LOCAL (iret_cf) LOCAL (errexit): mov $0x534d4150, %eax pop %ds - stc xor %bx, %bx + stc + +LOCAL (iret_cf): + push %bp + mov %sp, %bp + setc 6(%bp) + pop %bp iret VARIABLE(grub_machine_mmaphook_mmap_num) diff --git a/normal/auth.c b/normal/auth.c index 156b84c37..15acfb128 100644 --- a/normal/auth.c +++ b/normal/auth.c @@ -133,25 +133,24 @@ static int is_authenticated (const char *userlist) { const char *superusers; - - auto int hook (grub_list_t item); - int hook (grub_list_t item) - { - const char *name; - if (!((struct grub_auth_user *) item)->authenticated) - return 0; - name = ((struct grub_auth_user *) item)->name; - - return (userlist && grub_strword (userlist, name)) - || grub_strword (superusers, name); - } + struct grub_auth_user *user; superusers = grub_env_get ("superusers"); if (!superusers) return 1; - return grub_list_iterate (GRUB_AS_LIST (users), hook); + FOR_LIST_ELEMENTS (user, users) + { + if (!(user->authenticated)) + continue; + + if ((userlist && grub_strword (userlist, user->name)) + || grub_strword (superusers, user->name)) + return 1; + } + + return 0; } static int @@ -205,22 +204,7 @@ grub_auth_check_authentication (const char *userlist) grub_err_t err; static unsigned long punishment_delay = 1; char entered[GRUB_AUTH_MAX_PASSLEN]; - - auto int hook (grub_list_t item); - int hook (grub_list_t item) - { - if (grub_strcmp (login, ((struct grub_auth_user *) item)->name) == 0) - cur = (struct grub_auth_user *) item; - return 0; - } - - auto int hook_any (grub_list_t item); - int hook_any (grub_list_t item) - { - if (((struct grub_auth_user *) item)->callback) - cur = (struct grub_auth_user *) item; - return 0; - } + struct grub_auth_user *user; grub_memset (login, 0, sizeof (login)); @@ -240,7 +224,11 @@ grub_auth_check_authentication (const char *userlist) if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN)) goto access_denied; - grub_list_iterate (GRUB_AS_LIST (users), hook); + FOR_LIST_ELEMENTS (user, users) + { + if (grub_strcmp (login, user->name) == 0) + cur = user; + } if (!cur || ! cur->callback) goto access_denied; diff --git a/normal/completion.c b/normal/completion.c index 13e8f7a6b..40a645fb4 100644 --- a/normal/completion.c +++ b/normal/completion.c @@ -176,21 +176,6 @@ iterate_dev (const char *devname) return 0; } -static int -iterate_command (grub_command_t cmd) -{ - if (cmd->prio & GRUB_PRIO_LIST_FLAG_ACTIVE) - { - if (cmd->flags & GRUB_COMMAND_FLAG_CMDLINE) - { - if (add_completion (cmd->name, " ", GRUB_COMPLETION_TYPE_COMMAND)) - return 1; - } - } - - return 0; -} - /* Complete a device. */ static int complete_device (void) @@ -414,6 +399,14 @@ grub_normal_do_completion (char *buf, int *restore, else current_word = argv[argc - 1]; + if (argc > 1 && ! grub_strcmp (argv[0], "set")) + { + char *equals = grub_strchr (current_word, '='); + if (equals) + /* Complete the value of the variable. */ + current_word = equals + 1; + } + /* Determine the state the command line is in, depending on the state, it can be determined how to complete. */ cmdline_state = get_state (buf); @@ -421,8 +414,18 @@ grub_normal_do_completion (char *buf, int *restore, if (argc == 1 || argc == 0) { /* Complete a command. */ - if (grub_command_iterate (iterate_command)) - goto fail; + grub_command_t cmd; + FOR_COMMANDS(cmd) + { + if (cmd->prio & GRUB_PRIO_LIST_FLAG_ACTIVE) + { + if (cmd->flags & GRUB_COMMAND_FLAG_CMDLINE) + { + if (add_completion (cmd->name, " ", GRUB_COMPLETION_TYPE_COMMAND)) + goto fail; + } + } + } } else if (*current_word == '-') { diff --git a/normal/handler.c b/normal/handler.c deleted file mode 100644 index 686626929..000000000 --- a/normal/handler.c +++ /dev/null @@ -1,231 +0,0 @@ -/* handler.c - support handler loading */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2009 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GRUB. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -struct grub_handler_list -{ - struct grub_handler_list *next; - char *name; - grub_command_t cmd; -}; - -static grub_list_t handler_list; - -static grub_err_t -grub_handler_cmd (struct grub_command *cmd, - int argc __attribute__ ((unused)), - char **args __attribute__ ((unused))) -{ - char *p; - grub_handler_class_t class; - grub_handler_t handler; - - p = grub_strchr (cmd->name, '.'); - if (! p) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid command name"); - - if (cmd->data) - { - if (! grub_dl_get (cmd->data)) - { - grub_dl_t mod; - - mod = grub_dl_load (cmd->data); - if (mod) - grub_dl_ref (mod); - else - return grub_errno; - } - grub_free (cmd->data); - cmd->data = 0; - } - - *p = 0; - class = grub_named_list_find (GRUB_AS_NAMED_LIST (grub_handler_class_list), - cmd->name); - *p = '.'; - - if (! class) - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "class not found"); - - - handler = grub_named_list_find (GRUB_AS_NAMED_LIST (class->handler_list), - p + 1); - if (! handler) - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "handler not found"); - - grub_handler_set_current (class, handler); - - return 0; -} - -static void -insert_handler (char *name, char *module) -{ - struct grub_handler_list *item; - char *data; - - if (grub_command_find (name)) - return; - - item = grub_malloc (sizeof (*item)); - if (! item) - return; - - item->name = grub_strdup (name); - if (! item->name) - { - grub_free (item); - return; - } - - if (module) - { - data = grub_strdup (module); - if (! data) - { - grub_free (item->name); - grub_free (item); - return; - } - } - else - data = 0; - - item->cmd = grub_register_command (item->name, grub_handler_cmd, 0, - "Set active handler."); - if (! item->cmd) - { - grub_free (data); - grub_free (item->name); - grub_free (item); - return; - } - - item->cmd->data = data; - grub_list_push (&handler_list, GRUB_AS_LIST (item)); -} - -/* Read the file handler.lst for auto-loading. */ -void -read_handler_list (void) -{ - const char *prefix; - static int first_time = 1; - const char *class_name; - - auto int iterate_handler (grub_handler_t handler); - int iterate_handler (grub_handler_t handler) - { - char name[grub_strlen (class_name) + grub_strlen (handler->name) + 2]; - - grub_strcpy (name, class_name); - grub_strcat (name, "."); - grub_strcat (name, handler->name); - - insert_handler (name, 0); - - return 0; - } - - auto int iterate_class (grub_handler_class_t class); - int iterate_class (grub_handler_class_t class) - { - class_name = class->name; - grub_list_iterate (GRUB_AS_LIST (class->handler_list), - (grub_list_hook_t) iterate_handler); - - return 0; - } - - /* Make sure that this function does not get executed twice. */ - if (! first_time) - return; - first_time = 0; - - prefix = grub_env_get ("prefix"); - if (prefix) - { - char *filename; - - filename = grub_xasprintf ("%s/handler.lst", prefix); - if (filename) - { - grub_file_t file; - - file = grub_file_open (filename); - if (file) - { - char *buf = NULL; - for (;; grub_free (buf)) - { - char *p; - - buf = grub_file_getline (file); - - if (! buf) - break; - - if (! grub_isgraph (buf[0])) - continue; - - p = grub_strchr (buf, ':'); - if (! p) - continue; - - *p = '\0'; - while (*++p == ' ') - ; - - insert_handler (buf, p); - } - grub_file_close (file); - } - grub_free (filename); - } - } - - grub_list_iterate (GRUB_AS_LIST (grub_handler_class_list), - (grub_list_hook_t) iterate_class); - - /* Ignore errors. */ - grub_errno = GRUB_ERR_NONE; -} - -void -free_handler_list (void) -{ - struct grub_handler_list *item; - - while ((item = grub_list_pop (&handler_list)) != 0) - { - grub_free (item->cmd->data); - grub_unregister_command (item->cmd); - grub_free (item->name); - grub_free (item); - } -} diff --git a/normal/main.c b/normal/main.c index 4ed17e82c..7275b6367 100644 --- a/normal/main.c +++ b/normal/main.c @@ -31,6 +31,7 @@ #include #include #include +#include #define GRUB_DEFAULT_HISTORY_SIZE 50 @@ -204,7 +205,7 @@ grub_normal_add_menu_entry (int argc, const char **args, for (i = 0; i < argc; i++) { /* Capture arguments. */ - if (grub_strncmp ("--", args[i], 2) == 0) + if (grub_strncmp ("--", args[i], 2) == 0 && i + 1 < argc) { const char *arg = &args[i][2]; @@ -347,7 +348,6 @@ static grub_menu_t read_config_file (const char *config) { grub_file_t file; - grub_parser_t old_parser = 0; auto grub_err_t getline (char **line, int cont); grub_err_t getline (char **line, int cont __attribute__ ((unused))) @@ -361,36 +361,7 @@ read_config_file (const char *config) return grub_errno; if (buf[0] == '#') - { - if (buf[1] == '!') - { - grub_parser_t parser; - grub_named_list_t list; - - buf += 2; - while (grub_isspace (*buf)) - buf++; - - if (! old_parser) - old_parser = grub_parser_get_current (); - - list = GRUB_AS_NAMED_LIST (grub_parser_class.handler_list); - parser = grub_named_list_find (list, buf); - if (parser) - grub_parser_set_current (parser); - else - { - char cmd_name[8 + grub_strlen (buf)]; - - /* Perhaps it's not loaded yet, try the autoload - command. */ - grub_strcpy (cmd_name, "parser."); - grub_strcat (cmd_name, buf); - grub_command_execute (cmd_name, 0, 0); - } - } - grub_free (*line); - } + grub_free (*line); else break; } @@ -426,15 +397,12 @@ read_config_file (const char *config) if ((getline (&line, 0)) || (! line)) break; - grub_parser_get_current ()->parse_line (line, getline); + grub_normal_parse_line (line, getline); grub_free (line); } grub_file_close (file); - if (old_parser) - grub_parser_set_current (old_parser); - return newmenu; } @@ -496,12 +464,15 @@ void grub_normal_execute (const char *config, int nested, int batch) { grub_menu_t menu = 0; - const char *prefix = grub_env_get ("prefix"); + const char *prefix; - read_lists (prefix); - read_handler_list (); - grub_register_variable_hook ("prefix", NULL, read_lists_hook); - grub_command_execute ("parser.grub", 0, 0); + if (! nested) + { + prefix = grub_env_get ("prefix"); + read_lists (prefix); + grub_register_variable_hook ("prefix", NULL, read_lists_hook); + grub_command_execute ("parser.grub", 0, 0); + } if (config) { @@ -605,17 +576,15 @@ grub_normal_reader_init (int nested) 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; + const char *prompt; if (cont) - prompt = grub_xasprintf (">"); + prompt = ">"; else - prompt = grub_xasprintf ("%s>", parser->name); + prompt = "grub>"; if (!prompt) return grub_errno; @@ -629,14 +598,11 @@ grub_normal_read_line_real (char **line, int cont, int nested) if (cont || nested) { grub_free (*line); - grub_free (prompt); *line = 0; return grub_errno; } } - grub_free (prompt); - return 0; } @@ -677,7 +643,7 @@ grub_cmdline_run (int nested) if (! line) break; - grub_parser_get_current ()->parse_line (line, grub_normal_read_line); + grub_normal_parse_line (line, grub_normal_read_line); grub_free (line); } } @@ -725,5 +691,4 @@ GRUB_MOD_FINI(normal) grub_set_history (0); 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 09c5fd1eb..f98cfed66 100644 --- a/normal/menu.c +++ b/normal/menu.c @@ -29,6 +29,7 @@ #include #include #include +#include /* Time to delay after displaying an error message about a default/fallback entry failing to boot. */ @@ -141,6 +142,44 @@ get_and_remove_first_entry_number (const char *name) return entry; } +static void +grub_menu_execute_entry_real (grub_menu_entry_t entry) +{ + const char *source; + + auto grub_err_t getline (char **line, int cont); + grub_err_t getline (char **line, int cont __attribute__ ((unused))) + { + const char *p; + + if (!source) + { + *line = 0; + return 0; + } + + p = grub_strchr (source, '\n'); + + if (p) + *line = grub_strndup (source, p - source); + else + *line = grub_strdup (source); + source = p ? p + 1 : 0; + return 0; + } + + source = entry->sourcecode; + + while (source) + { + char *line; + + getline (&line, 0); + grub_normal_parse_line (line, getline); + grub_free (line); + } +} + /* Run a menu entry. */ void grub_menu_execute_entry(grub_menu_entry_t entry) @@ -159,7 +198,7 @@ grub_menu_execute_entry(grub_menu_entry_t entry) grub_env_set ("chosen", entry->title); - grub_parser_execute ((char *) entry->sourcecode); + grub_menu_execute_entry_real (entry); if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ()) /* Implicit execution of boot, only if something is loaded. */ diff --git a/normal/menu_entry.c b/normal/menu_entry.c index 644fe90fd..c23d67d70 100644 --- a/normal/menu_entry.c +++ b/normal/menu_entry.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -1189,7 +1190,7 @@ run (struct screen *screen) while (currline < screen->num_lines) { editor_getline (&nextline, 0); - if (grub_parser_get_current ()->parse_line (nextline, editor_getline)) + if (grub_normal_parse_line (nextline, editor_getline)) break; } diff --git a/po/POTFILES b/po/POTFILES index d2c579edb..cfa1e33cb 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -12,7 +12,6 @@ commands/efi/fixvideo.c commands/efi/loadbios.c commands/gptsync.c commands/halt.c -commands/handler.c commands/hdparm.c commands/help.c commands/hexdump.c diff --git a/script/function.c b/script/function.c index ded470c4e..810c65233 100644 --- a/script/function.c +++ b/script/function.c @@ -21,7 +21,7 @@ #include #include -static grub_script_function_t grub_script_function_list; +grub_script_function_t grub_script_function_list; grub_script_function_t grub_script_function_create (struct grub_script_arg *functionname_arg, @@ -104,18 +104,6 @@ grub_script_function_find (char *functionname) return func; } -int -grub_script_function_iterate (int (*iterate) (grub_script_function_t)) -{ - grub_script_function_t func; - - for (func = grub_script_function_list; func; func = func->next) - if (iterate (func)) - return 1; - - return 0; -} - int grub_script_function_call (grub_script_function_t func, int argc __attribute__((unused)), diff --git a/script/main.c b/script/main.c index b5159dc7d..752a8cd8a 100644 --- a/script/main.c +++ b/script/main.c @@ -20,7 +20,7 @@ #include #include -static grub_err_t +grub_err_t grub_normal_parse_line (char *line, grub_reader_getline_t getline) { struct grub_script *parsed_script; @@ -39,19 +39,3 @@ grub_normal_parse_line (char *line, grub_reader_getline_t getline) return grub_errno; } - -static struct grub_parser grub_sh_parser = - { - .name = "grub", - .parse_line = grub_normal_parse_line - }; - -GRUB_MOD_INIT(sh) -{ - grub_parser_register ("grub", &grub_sh_parser); -} - -GRUB_MOD_FINI(sh) -{ - grub_parser_unregister (&grub_sh_parser); -} diff --git a/script/parser.y b/script/parser.y index b5815ea8d..e85ba624d 100644 --- a/script/parser.y +++ b/script/parser.y @@ -26,6 +26,7 @@ #define YYLTYPE_IS_TRIVIAL 0 #define YYENABLE_NLS 0 +#include "grub_script.tab.h" %} %union { @@ -126,6 +127,7 @@ word: GRUB_PARSER_TOKEN_NAME { $$ = grub_script_add_arglist (state, 0, $1); } statement: command { $$ = $1; } | function { $$ = 0; } | menuentry { $$ = $1; } +; argument : "case" { $$ = grub_script_add_arglist (state, 0, $1); } | "do" { $$ = grub_script_add_arglist (state, 0, $1); } diff --git a/term/i386/pc/vga_text.c b/term/i386/pc/vga_text.c index f954cab43..717a7576e 100644 --- a/term/i386/pc/vga_text.c +++ b/term/i386/pc/vga_text.c @@ -20,6 +20,7 @@ #include #include #include +#include #define COLS 80 #define ROWS 25 @@ -28,15 +29,6 @@ static int grub_curr_x, grub_curr_y; #define VGA_TEXT_SCREEN 0xb8000 -#define CRTC_ADDR_PORT 0x3D4 -#define CRTC_DATA_PORT 0x3D5 - -#define CRTC_CURSOR 0x0a -#define CRTC_CURSOR_ADDR_HIGH 0x0e -#define CRTC_CURSOR_ADDR_LOW 0x0f - -#define CRTC_CURSOR_DISABLE (1 << 5) - static void screen_write_char (int x, int y, short c) { @@ -53,10 +45,8 @@ static void update_cursor (void) { unsigned int pos = grub_curr_y * COLS + grub_curr_x; - grub_outb (CRTC_CURSOR_ADDR_HIGH, CRTC_ADDR_PORT); - grub_outb (pos >> 8, CRTC_DATA_PORT); - grub_outb (CRTC_CURSOR_ADDR_LOW, CRTC_ADDR_PORT); - grub_outb (pos & 0xFF, CRTC_DATA_PORT); + grub_vga_cr_write (pos >> 8, GRUB_VGA_CR_CURSOR_ADDR_HIGH); + grub_vga_cr_write (pos & 0xFF, GRUB_VGA_CR_CURSOR_ADDR_LOW); } static void @@ -68,9 +58,11 @@ inc_y (void) else { int x, y; - for (y = 0; y < ROWS; y++) + for (y = 0; y < ROWS - 1; y++) for (x = 0; x < COLS; x++) screen_write_char (x, y, screen_read_char (x, y + 1)); + for (x = 0; x < COLS; x++) + screen_write_char (x, ROWS - 1, ' ' | (grub_console_cur_color << 8)); } } @@ -134,12 +126,13 @@ static void grub_vga_text_setcursor (int on) { grub_uint8_t old; - grub_outb (CRTC_CURSOR, CRTC_ADDR_PORT); - old = grub_inb (CRTC_DATA_PORT); + old = grub_vga_cr_read (GRUB_VGA_CR_CURSOR_START); if (on) - grub_outb (old & ~CRTC_CURSOR_DISABLE, CRTC_DATA_PORT); + grub_vga_cr_write (old & ~GRUB_VGA_CR_CURSOR_START_DISABLE, + GRUB_VGA_CR_CURSOR_START); else - grub_outb (old | CRTC_CURSOR_DISABLE, CRTC_DATA_PORT); + grub_vga_cr_write (old | GRUB_VGA_CR_CURSOR_START_DISABLE, + GRUB_VGA_CR_CURSOR_START); } static grub_err_t diff --git a/tests/lib/functional_test.c b/tests/lib/functional_test.c index 8ff08cf8a..6aafe4dbb 100644 --- a/tests/lib/functional_test.c +++ b/tests/lib/functional_test.c @@ -26,15 +26,10 @@ 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_test_t test; - grub_list_iterate (GRUB_AS_LIST (grub_test_list), - (grub_list_hook_t) run_test); + FOR_LIST_ELEMENTS (test, grub_test_list) + grub_test_run (test); return GRUB_ERR_NONE; } diff --git a/tests/lib/test.c b/tests/lib/test.c index b5c054370..06d78b7d7 100644 --- a/tests/lib/test.c +++ b/tests/lib/test.c @@ -66,8 +66,10 @@ free_failures (void) { grub_test_failure_t item; - while ((item = grub_list_pop (GRUB_AS_LIST_P (&failure_list))) != 0) + while (failure_list) { + item = failure_list; + failure_list = item->next; if (item->message) grub_free (item->message); @@ -134,23 +136,17 @@ grub_test_unregister (const char *name) 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; - } + grub_test_failure_t failure; test->main (); grub_printf ("%s:\n", test->name); - grub_list_iterate (GRUB_AS_LIST (failure_list), - (grub_list_hook_t) print_failure); + FOR_LIST_ELEMENTS (failure, failure_list) + grub_printf (" %s:%s:%u: %s\n", + (failure->file ? : ""), + (failure->funp ? : ""), + failure->line, (failure->message ? : "")); + if (!failure_list) grub_printf ("%s: PASS\n", test->name); else diff --git a/tests/lib/unit_test.c b/tests/lib/unit_test.c index e461150de..e8b97b1f4 100644 --- a/tests/lib/unit_test.c +++ b/tests/lib/unit_test.c @@ -34,16 +34,12 @@ main (int argc __attribute__ ((unused)), 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_test_t test; grub_unit_test_init (); - grub_list_iterate (GRUB_AS_LIST (grub_test_list), - (grub_list_hook_t) run_test); + FOR_LIST_ELEMENTS (test, grub_test_list) + status = grub_test_run (test) ? : status; + grub_unit_test_fini (); exit (status); diff --git a/util/deviceiter.c b/util/deviceiter.c index 03813bc7d..e3a0ab76d 100644 --- a/util/deviceiter.c +++ b/util/deviceiter.c @@ -28,11 +28,13 @@ #include #include #include +#include #include #include #include #include +#include #ifdef __linux__ # if !defined(__GLIBC__) || \ @@ -344,18 +346,37 @@ get_xvd_disk_name (char *name, int unit) } #endif -/* Check if DEVICE can be read. If an error occurs, return zero, - otherwise return non-zero. */ -static int -check_device (const char *device) +static struct seen_device { + struct seen_device *next; + const char *name; +} *seen; + +/* Check if DEVICE can be read. Skip any DEVICE that we have already seen. + If an error occurs, return zero, otherwise return non-zero. */ +static int +check_device_readable_unique (const char *device) +{ + char *real_device; char buf[512]; FILE *fp; + struct seen_device *seen_elt; /* If DEVICE is empty, just return error. */ if (*device == 0) return 0; + /* Have we seen this device already? */ + real_device = canonicalize_file_name (device); + if (! real_device) + return 0; + if (grub_named_list_find (GRUB_AS_NAMED_LIST (seen), real_device)) + { + grub_dprintf ("deviceiter", "Already seen %s (%s)\n", + device, real_device); + goto fail; + } + fp = fopen (device, "r"); if (! fp) { @@ -378,7 +399,7 @@ check_device (const char *device) break; } /* Error opening the device. */ - return 0; + goto fail; } /* Make sure CD-ROMs don't get assigned a BIOS disk number @@ -386,7 +407,7 @@ check_device (const char *device) #ifdef __linux__ # ifdef CDROM_GET_CAPABILITY if (ioctl (fileno (fp), CDROM_GET_CAPABILITY, 0) >= 0) - return 0; + goto fail; # else /* ! CDROM_GET_CAPABILITY */ /* Check if DEVICE is a CD-ROM drive by the HDIO_GETGEO ioctl. */ { @@ -394,14 +415,14 @@ check_device (const char *device) struct stat st; if (fstat (fileno (fp), &st)) - return 0; + goto fail; /* If it is a block device and isn't a floppy, check if HDIO_GETGEO succeeds. */ if (S_ISBLK (st.st_mode) && MAJOR (st.st_rdev) != FLOPPY_MAJOR && ioctl (fileno (fp), HDIO_GETGEO, &hdg)) - return 0; + goto fail; } # endif /* ! CDROM_GET_CAPABILITY */ #endif /* __linux__ */ @@ -409,7 +430,7 @@ check_device (const char *device) #if defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) # ifdef CDIOCCLRDEBUG if (ioctl (fileno (fp), CDIOCCLRDEBUG, 0) >= 0) - return 0; + goto fail; # endif /* CDIOCCLRDEBUG */ #endif /* __FreeBSD_kernel__ || __NetBSD__ || __OpenBSD__ */ @@ -417,21 +438,43 @@ check_device (const char *device) if (fread (buf, 1, 512, fp) != 512) { fclose (fp); - return 0; + goto fail; } + /* Remember that we've seen this device. */ + seen_elt = xmalloc (sizeof (*seen_elt)); + seen_elt->name = real_device; /* steal memory */ + grub_list_push (GRUB_AS_LIST_P (&seen), GRUB_AS_LIST (seen_elt)); + fclose (fp); return 1; + +fail: + free (real_device); + return 0; +} + +static void +clear_seen_devices (void) +{ + while (seen) + { + struct seen_device *seen_elt = seen; + seen = seen->next; + free (seen_elt); + } + seen = NULL; } #ifdef __linux__ -# ifdef HAVE_DEVICE_MAPPER -struct dmraid_seen +/* Like strcmp, but doesn't require a cast for use as a qsort comparator. */ +static int +compare_file_names (const void *a, const void *b) { - struct dmraid_seen *next; - const char *name; -}; -# endif /* HAVE_DEVICE_MAPPER */ + const char *left = *(const char **) a; + const char *right = *(const char **) b; + return strcmp (left, right); +} #endif /* __linux__ */ void @@ -440,6 +483,8 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int), { int i; + clear_seen_devices (); + /* Floppies. */ for (i = 0; i < floppy_disks; i++) { @@ -449,13 +494,63 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int), get_floppy_disk_name (name, i); if (stat (name, &st) < 0) break; - /* In floppies, write the map, whether check_device succeeds - or not, because the user just may not insert floppies. */ + /* In floppies, write the map, whether check_device_readable_unique + succeeds or not, because the user just may not insert floppies. */ if (hook (name, 1)) - return; + goto out; } #ifdef __linux__ + { + DIR *dir = opendir ("/dev/disk/by-id"); + + if (dir) + { + struct dirent *entry; + char **names; + size_t names_len = 0, names_max = 1024, i; + + names = xmalloc (names_max * sizeof (*names)); + + /* Dump all the directory entries into names, resizing if + necessary. */ + for (entry = readdir (dir); entry; entry = readdir (dir)) + { + /* Skip partition entries. */ + if (strstr (entry->d_name, "-part")) + continue; + if (names_len >= names_max) + { + names_max *= 2; + names = xrealloc (names, names_max * sizeof (*names)); + } + names[names_len++] = xasprintf (entry->d_name); + } + + /* /dev/disk/by-id/ usually has a few alternative identifications of + devices (e.g. ATA vs. SATA). check_device_readable_unique will + ensure that we only get one for any given disk, but sort the list + so that the choice of which one we get is stable. */ + qsort (names, names_len, sizeof (*names), &compare_file_names); + + closedir (dir); + + /* Now add all the devices in sorted order. */ + for (i = 0; i < names_len; ++i) + { + char *path = xasprintf ("/dev/disk/by-id/%s", names[i]); + if (check_device_readable_unique (path)) + { + if (hook (path, 0)) + goto out; + } + free (path); + free (names[i]); + } + free (names); + } + } + if (have_devfs ()) { i = 0; @@ -475,10 +570,10 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int), { strcat (name, "/disc"); if (hook (name, 0)) - return; + goto out; } } - return; + goto out; } #endif /* __linux__ */ @@ -488,10 +583,10 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int), char name[16]; get_ide_disk_name (name, i); - if (check_device (name)) + if (check_device_readable_unique (name)) { if (hook (name, 0)) - return; + goto out; } } @@ -502,10 +597,10 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int), char name[16]; get_virtio_disk_name (name, i); - if (check_device (name)) + if (check_device_readable_unique (name)) { if (hook (name, 0)) - return; + goto out; } } @@ -515,10 +610,10 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int), char name[20]; get_ataraid_disk_name (name, i); - if (check_device (name)) + if (check_device_readable_unique (name)) { if (hook (name, 0)) - return; + goto out; } } @@ -528,10 +623,10 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int), char name[16]; get_xvd_disk_name (name, i); - if (check_device (name)) + if (check_device_readable_unique (name)) { if (hook (name, 0)) - return; + goto out; } } #endif /* __linux__ */ @@ -542,10 +637,10 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int), char name[16]; get_scsi_disk_name (name, i); - if (check_device (name)) + if (check_device_readable_unique (name)) { if (hook (name, 0)) - return; + goto out; } } @@ -565,10 +660,10 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int), char name[24]; get_dac960_disk_name (name, controller, drive); - if (check_device (name)) + if (check_device_readable_unique (name)) { if (hook (name, 0)) - return; + goto out; } } } @@ -586,10 +681,10 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int), char name[24]; get_acceleraid_disk_name (name, controller, drive); - if (check_device (name)) + if (check_device_readable_unique (name)) { if (hook (name, 0)) - return; + goto out; } } } @@ -607,10 +702,10 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int), char name[24]; get_cciss_disk_name (name, controller, drive); - if (check_device (name)) + if (check_device_readable_unique (name)) { if (hook (name, 0)) - return; + goto out; } } } @@ -628,10 +723,10 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int), char name[24]; get_ida_disk_name (name, controller, drive); - if (check_device (name)) + if (check_device_readable_unique (name)) { if (hook (name, 0)) - return; + goto out; } } } @@ -646,10 +741,10 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int), char name[24]; get_i2o_disk_name (name, unit); - if (check_device (name)) + if (check_device_readable_unique (name)) { if (hook (name, 0)) - return; + goto out; } } } @@ -660,10 +755,10 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int), char name[16]; get_mmc_disk_name (name, i); - if (check_device (name)) + if (check_device_readable_unique (name)) { if (hook (name, 0)) - return; + goto out; } } @@ -676,113 +771,91 @@ grub_util_iterate_devices (int NESTED_FUNC_ATTR (*hook) (const char *, int), } /* DM-RAID. */ - { - struct dm_tree *tree = NULL; - struct dm_task *task = NULL; - struct dm_names *names = NULL; - unsigned int next = 0; - void *top_handle, *second_handle; - struct dm_tree_node *root, *top, *second; - struct dmraid_seen *seen = NULL; + if (grub_device_mapper_supported ()) + { + struct dm_tree *tree = NULL; + struct dm_task *task = NULL; + struct dm_names *names = NULL; + unsigned int next = 0; + void *top_handle, *second_handle; + struct dm_tree_node *root, *top, *second; - /* Build DM tree for all devices. */ - tree = dm_tree_create (); - dmraid_check (tree, "dm_tree_create failed\n"); - task = dm_task_create (DM_DEVICE_LIST); - dmraid_check (task, "dm_task_create failed\n"); - dmraid_check (dm_task_run (task), "dm_task_run failed\n"); - names = dm_task_get_names (task); - dmraid_check (names, "dm_task_get_names failed\n"); - dmraid_check (names->dev, "No DM devices found\n"); - do - { - names = (void *) names + next; - dmraid_check (dm_tree_add_dev (tree, MAJOR (names->dev), - MINOR (names->dev)), - "dm_tree_add_dev (%s) failed\n", names->name); - next = names->next; - } - while (next); + /* Build DM tree for all devices. */ + tree = dm_tree_create (); + dmraid_check (tree, "dm_tree_create failed\n"); + task = dm_task_create (DM_DEVICE_LIST); + dmraid_check (task, "dm_task_create failed\n"); + dmraid_check (dm_task_run (task), "dm_task_run failed\n"); + names = dm_task_get_names (task); + dmraid_check (names, "dm_task_get_names failed\n"); + dmraid_check (names->dev, "No DM devices found\n"); + do + { + names = (void *) names + next; + dmraid_check (dm_tree_add_dev (tree, MAJOR (names->dev), + MINOR (names->dev)), + "dm_tree_add_dev (%s) failed\n", names->name); + next = names->next; + } + while (next); - /* Walk the second-level children of the inverted tree; that is, devices - which are directly composed of non-DM devices such as hard disks. - This class includes all DM-RAID disks and excludes all DM-RAID - partitions. */ - root = dm_tree_find_node (tree, 0, 0); - top_handle = NULL; - top = dm_tree_next_child (&top_handle, root, 1); - while (top) - { - second_handle = NULL; - second = dm_tree_next_child (&second_handle, top, 1); - while (second) - { - const char *node_name, *node_uuid; - char *name; - struct dmraid_seen *seen_elt; + /* Walk the second-level children of the inverted tree; that is, devices + which are directly composed of non-DM devices such as hard disks. + This class includes all DM-RAID disks and excludes all DM-RAID + partitions. */ + root = dm_tree_find_node (tree, 0, 0); + top_handle = NULL; + top = dm_tree_next_child (&top_handle, root, 1); + while (top) + { + second_handle = NULL; + second = dm_tree_next_child (&second_handle, top, 1); + while (second) + { + const char *node_name, *node_uuid; + char *name; - node_name = dm_tree_node_get_name (second); - dmraid_check (node_name, "dm_tree_node_get_name failed\n"); - node_uuid = dm_tree_node_get_uuid (second); - dmraid_check (node_uuid, "dm_tree_node_get_uuid failed\n"); - if (strncmp (node_uuid, "DMRAID-", 7) != 0) - { - grub_dprintf ("deviceiter", "%s is not DM-RAID\n", node_name); - goto dmraid_next_child; - } + node_name = dm_tree_node_get_name (second); + dmraid_check (node_name, "dm_tree_node_get_name failed\n"); + node_uuid = dm_tree_node_get_uuid (second); + dmraid_check (node_uuid, "dm_tree_node_get_uuid failed\n"); + if (strncmp (node_uuid, "DMRAID-", 7) != 0) + { + grub_dprintf ("deviceiter", "%s is not DM-RAID\n", node_name); + goto dmraid_next_child; + } - /* Have we already seen this node? There are typically very few - DM-RAID disks, so a list should be fast enough. */ - if (grub_named_list_find (GRUB_AS_NAMED_LIST (seen), node_name)) - { - grub_dprintf ("deviceiter", "Already seen DM device %s\n", - node_name); - goto dmraid_next_child; - } - - name = xasprintf ("/dev/mapper/%s", node_name); - if (check_device (name)) - { - if (hook (name, 0)) - { - free (name); - while (seen) - { - struct dmraid_seen *seen_elt = - grub_list_pop (GRUB_AS_LIST_P (&seen)); - free (seen_elt); - } - if (task) - dm_task_destroy (task); - if (tree) - dm_tree_free (tree); - return; - } - } - free (name); - - seen_elt = xmalloc (sizeof *seen_elt); - seen_elt->name = node_name; - grub_list_push (GRUB_AS_LIST_P (&seen), GRUB_AS_LIST (seen_elt)); + name = xasprintf ("/dev/mapper/%s", node_name); + if (check_device_readable_unique (name)) + { + if (hook (name, 0)) + { + free (name); + if (task) + dm_task_destroy (task); + if (tree) + dm_tree_free (tree); + goto out; + } + } + free (name); dmraid_next_child: - second = dm_tree_next_child (&second_handle, top, 1); - } - top = dm_tree_next_child (&top_handle, root, 1); - } + second = dm_tree_next_child (&second_handle, top, 1); + } + top = dm_tree_next_child (&top_handle, root, 1); + } dmraid_end: - while (seen) - { - struct dmraid_seen *seen_elt = grub_list_pop (GRUB_AS_LIST_P (&seen)); - free (seen_elt); - } - if (task) - dm_task_destroy (task); - if (tree) - dm_tree_free (tree); - } + if (task) + dm_task_destroy (task); + if (tree) + dm_tree_free (tree); + } # endif /* HAVE_DEVICE_MAPPER */ #endif /* __linux__ */ + +out: + clear_seen_devices (); } diff --git a/util/grub-editenv.c b/util/grub-editenv.c index f21042c97..4ea97bded 100644 --- a/util/grub-editenv.c +++ b/util/grub-editenv.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include diff --git a/util/grub-fstest.c b/util/grub-fstest.c index c03c43451..f7e1eb2dd 100644 --- a/util/grub-fstest.c +++ b/util/grub-fstest.c @@ -55,9 +55,6 @@ grub_getkey (void) return -1; } -struct grub_handler_class grub_term_input_class; -struct grub_handler_class grub_term_output_class; - void grub_refresh (void) { diff --git a/util/grub-install.in b/util/grub-install.in index 0db216fd5..4a5b5a1c3 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -34,6 +34,8 @@ font=@datadir@/@PACKAGE_TARNAME@/ascii.pf2 pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}` localedir=@datadir@/locale +self=`basename $0` + grub_setup=${sbindir}/`echo grub-setup | sed ${transform}` grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}` @@ -48,6 +50,7 @@ no_floppy= force_lba= recheck=no debug=no +debug_image= if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then disk_module=biosdisk @@ -61,7 +64,7 @@ fi # Print the usage. usage () { cat <. EOF } +argument () { + opt=$1 + shift + + if test $# -eq 0; then + echo "$0: option requires an argument -- '$opt'" 1>&2 + exit 1 + fi + echo $1 +} + # Check the arguments. -for option in "$@"; do +while test $# -gt 0 +do + option=$1 + shift + case "$option" in -h | --help) usage exit 0 ;; -v | --version) - echo "grub-install (GNU GRUB ${PACKAGE_VERSION})" + echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" exit 0 ;; + + --modules) + modules=`argument $option "$@"`; shift;; --modules=*) modules=`echo "$option" | sed 's/--modules=//'` ;; + + --font) + font=`argument $option "$@"`; shift;; --font=*) font=`echo "$option" | sed 's/--font=//'` ;; + + --root-directory) + rootdir=`argument $option "$@"`; shift;; --root-directory=*) rootdir=`echo "$option" | sed 's/--root-directory=//'` ;; + + --grub-setup) + grub_setup=`argument $option "$@"`; shift;; --grub-setup=*) grub_setup=`echo "$option" | sed 's/--grub-setup=//'` ;; + + --grub-mkimage) + grub_mkimage=`argument $option "$@"`; shift;; --grub-mkimage=*) grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;; + + --grub-mkdevicemap) + grub_mkdevicemap=`argument $option "$@"`; shift;; --grub-mkdevicemap=*) grub_mkdevicemap=`echo "$option" | sed 's/--grub-mkdevicemap=//'` ;; + + --grub-probe) + grub_probe=`argument $option "$@"`; shift;; --grub-probe=*) grub_probe=`echo "$option" | sed 's/--grub-probe=//'` ;; + --no-floppy) no_floppy="--no-floppy" ;; --recheck) recheck=yes ;; + + --disk-module) + if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then + disk_module=`argument $option "$@"`; shift; + fi ;; --disk-module=*) if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then disk_module=`echo "$option" | sed 's/--disk-module=//'` fi ;; + # This is an undocumented feature... --debug) debug=yes ;; + --debug-image) + debug_image=`argument $option "$@"`; shift;; + --debug-image=*) + debug_image=`echo "$option" | sed 's/--debug-image=//'` ;; + -f | --force) setup_force="--force" ;; + -*) echo "Unrecognized option \`$option'" 1>&2 usage @@ -303,6 +355,13 @@ fi prefix_drive= config_opt= +rm -f ${grubdir}/load.cfg + +if [ "x${debug_image}" != x ]; then + echo "set debug='${debug_image}'" >> ${grubdir}/load.cfg + config_opt="-c ${grubdir}/load.cfg " +fi + if [ "x${devabstraction_module}" = "x" ] ; then if [ x"${install_device}" != x ]; then if echo "${install_device}" | grep -qx "(.*)" ; then @@ -310,12 +369,12 @@ if [ "x${devabstraction_module}" = "x" ] ; then else install_drive="`$grub_probe --target=drive --device ${install_device}`" || exit 1 fi - install_drive="`echo ${install_drive} | sed -e s/,[0-9]*[a-z]*//g`" + install_drive="`echo ${install_drive} | sed -e s/,[a-z0-9,]*//g`" fi grub_drive="`$grub_probe --target=drive --device ${grub_device}`" || exit 1 # Strip partition number - grub_drive="`echo ${grub_drive} | sed -e s/,[0-9]*[a-z]*//g`" + grub_drive="`echo ${grub_drive} | sed -e s/,[a-z0-9,]*//g`" if [ "$disk_module" = ata ] ; then # generic method (used on coreboot and ata mod) uuid="`$grub_probe --target=fs_uuid --device ${grub_device}`" @@ -323,7 +382,7 @@ if [ "x${devabstraction_module}" = "x" ] ; then echo "UUID needed with ata mod, but the filesystem containing ${grubdir} does not support UUIDs." 1>&2 exit 1 fi - echo "search.fs_uuid ${uuid} root " > ${grubdir}/load.cfg + echo "search.fs_uuid ${uuid} root " >> ${grubdir}/load.cfg echo 'set prefix=($root)'"${relative_grubdir}" >> ${grubdir}/load.cfg config_opt="-c ${grubdir}/load.cfg " modules="$modules search_fs_uuid" @@ -333,7 +392,7 @@ if [ "x${devabstraction_module}" = "x" ] ; then echo "You attempted a cross-disk install, but the filesystem containing ${grubdir} does not support UUIDs." 1>&2 exit 1 fi - echo "search.fs_uuid ${uuid} root " > ${grubdir}/load.cfg + echo "search.fs_uuid ${uuid} root " >> ${grubdir}/load.cfg echo 'set prefix=($root)'"${relative_grubdir}" >> ${grubdir}/load.cfg config_opt="-c ${grubdir}/load.cfg " modules="$modules search_fs_uuid" diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in index 0095e1ce8..5548da4da 100644 --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in @@ -23,7 +23,8 @@ exec_prefix=@exec_prefix@ sbindir=@sbindir@ libdir=@libdir@ sysconfdir=@sysconfdir@ -package_version=@PACKAGE_VERSION@ +PACKAGE_NAME=@PACKAGE_NAME@ +PACKAGE_VERSION=@PACKAGE_VERSION@ host_os=@host_os@ datarootdir=@datarootdir@ datadir=@datadir@ @@ -31,6 +32,8 @@ pkgdatadir=${datadir}/`echo @PACKAGE_TARNAME@ | sed "${transform}"` grub_cfg="" grub_mkconfig_dir=${sysconfdir}/grub.d +self=`basename $0` + grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}` grub_probe=${sbindir}/`echo grub-probe | sed ${transform}` @@ -38,7 +41,7 @@ grub_probe=${sbindir}/`echo grub-probe | sed ${transform}` # Print the usage. usage () { cat <. EOF } +argument () { + opt=$1 + shift + + if test $# -eq 0; then + echo "$0: option requires an argument -- '$opt'" 1>&2 + exit 1 + fi + echo $1 +} + # Check the arguments. -next_grub_cfg=false -for option in "$@"; do - if $next_grub_cfg; then - grub_cfg=$option - next_grub_cfg=false - continue - fi +while test $# -gt 0 +do + option=$1 + shift + case "$option" in -h | --help) usage exit 0 ;; -v | --version) - echo "$0 (GNU GRUB ${package_version})" + echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" exit 0 ;; - -o) - next_grub_cfg=: - ;; + -o | --output) + grub_cfg=`argument $option "$@"`; shift;; --output=*) grub_cfg=`echo "$option" | sed 's/--output=//'` ;; @@ -75,13 +86,9 @@ for option in "$@"; do usage exit 1 ;; + # Explicitly ignore non-option arguments, for compatibility. esac done -if $next_grub_cfg; then - echo "Missing argument to \`-o'" 1>&2 - usage - exit 1 -fi . ${libdir}/grub/grub-mkconfig_lib @@ -89,11 +96,11 @@ 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}` + GRUB_PREFIX=`echo /grub | sed ${transform}` ;; *) # Use /boot/grub by default. - grub_prefix=`echo /boot/grub | sed ${transform}` + GRUB_PREFIX=`echo /boot/grub | sed ${transform}` ;; esac @@ -113,7 +120,7 @@ if [ "$EUID" != 0 ] ; then done ;; esac if [ $root != t ] ; then - echo "$0: You must run this as root" >&2 + echo "$self: You must run this as root" >&2 exit 1 fi fi @@ -134,9 +141,9 @@ else exit 1 fi -mkdir -p ${grub_prefix} +mkdir -p ${GRUB_PREFIX} -if test -e ${grub_prefix}/device.map ; then : ; else +if test -e ${GRUB_PREFIX}/device.map ; then : ; else ${grub_mkdevicemap} fi @@ -171,17 +178,14 @@ fi for x in ${GRUB_TERMINAL_OUTPUT}; do if [ "x${x}" = "xgfxterm" ]; then # If this platform supports gfxterm, try to use it. - if ! test -e ${grub_prefix}/gfxterm.mod ; then + if ! test -e ${GRUB_PREFIX}/gfxterm.mod ; then if [ "x$termoutdefault" != "x1" ]; then echo "gfxterm isn't available on your platform" >&2 ; exit 1 fi GRUB_TERMINAL_OUTPUT= break; fi - # FIXME: this should do something smarter than just loading first - # video backend. - GRUB_VIDEO_BACKEND=$(head -n 1 ${grub_prefix}/video.lst || true) - if [ -z "${GRUB_VIDEO_BACKEND}" ] ; then + if [ ! -s "${GRUB_PREFIX}/video.lst" ] ; then if [ "x$termoutdefault" != "x1" ]; then echo "No suitable backend could be found for gfxterm." >&2 ; exit 1 fi @@ -239,7 +243,7 @@ export GRUB_DEVICE \ GRUB_FS \ GRUB_FONT_PATH \ GRUB_PRELOAD_MODULES \ - GRUB_VIDEO_BACKEND + GRUB_PREFIX # These are optional, user-defined variables. export GRUB_DEFAULT \ @@ -253,6 +257,8 @@ export GRUB_DEFAULT \ GRUB_DISTRIBUTOR \ GRUB_CMDLINE_LINUX \ GRUB_CMDLINE_LINUX_DEFAULT \ + GRUB_CMDLINE_XEN \ + GRUB_CMDLINE_XEN_DEFAULT \ GRUB_CMDLINE_NETBSD \ GRUB_CMDLINE_NETBSD_DEFAULT \ GRUB_TERMINAL_INPUT \ @@ -261,6 +267,7 @@ export GRUB_DEFAULT \ GRUB_DISABLE_LINUX_UUID \ GRUB_DISABLE_LINUX_RECOVERY \ GRUB_DISABLE_NETBSD_RECOVERY \ + GRUB_VIDEO_BACKEND \ GRUB_GFXMODE \ GRUB_BACKGROUND \ GRUB_THEME \ @@ -284,7 +291,7 @@ cat << EOF # # DO NOT EDIT THIS FILE # -# It is automatically generated by $0 using templates +# It is automatically generated by $self using templates # from ${grub_mkconfig_dir} and settings from ${sysconfdir}/default/grub # EOF diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in index 7ec8cb5be..14ea1842f 100644 --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in @@ -107,7 +107,7 @@ prepare_grub_to_access_device () partmap="`${grub_probe} --device ${device} --target=partmap`" for module in ${partmap} ; do - echo "insmod ${module}" + echo "insmod part_${module}" done fs="`${grub_probe} --device ${device} --target=fs`" diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index dc9dcc208..c89eddc32 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -1301,7 +1301,7 @@ main (int argc, char *argv[]) image_target = &image_targets[i]; if (!image_target) { - printf ("unknown target %s\n", optarg); + printf ("unknown target format %s\n", optarg); usage (1); } break; @@ -1355,7 +1355,7 @@ main (int argc, char *argv[]) break; case 'V': - printf ("grub-mkimage (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION); + printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); return 0; case 'v': @@ -1370,7 +1370,7 @@ main (int argc, char *argv[]) if (!image_target) { - printf ("Target not specified.\n"); + printf ("Target format not specified (use the -O option).\n"); usage (1); } diff --git a/util/grub-mkpasswd-pbkdf2.c b/util/grub-mkpasswd-pbkdf2.c index a00b1e990..944c6c46a 100644 --- a/util/grub-mkpasswd-pbkdf2.c +++ b/util/grub-mkpasswd-pbkdf2.c @@ -112,7 +112,7 @@ hexify (char *hex, grub_uint8_t *bin, grub_size_t n) int main (int argc, char *argv[]) { - unsigned int c = 10000, buflen = 64, saltlen = 64; + unsigned int count = 10000, buflen = 64, saltlen = 64; char *pass1, *pass2; char *bufhex, *salthex; gcry_err_code_t gcry_err; @@ -137,7 +137,7 @@ main (int argc, char *argv[]) switch (c) { case 'c': - c = strtoul (optarg, NULL, 0); + count = strtoul (optarg, NULL, 0); break; case 'l': @@ -307,7 +307,7 @@ main (int argc, char *argv[]) gcry_err = grub_crypto_pbkdf2 (GRUB_MD_SHA512, (grub_uint8_t *) pass1, strlen (pass1), salt, saltlen, - c, buf, buflen); + count, buf, buflen); memset (pass1, 0, strlen (pass1)); free (pass1); @@ -327,7 +327,8 @@ main (int argc, char *argv[]) hexify (bufhex, buf, buflen); hexify (salthex, salt, saltlen); - printf ("Your PBKDF2 is grub.pbkdf2.sha512.%d.%s.%s\n", c, salthex, bufhex); + printf ("Your PBKDF2 is grub.pbkdf2.sha512.%d.%s.%s\n", + count, salthex, bufhex); memset (buf, 0, buflen); memset (bufhex, 0, 2 * buflen); free (buf); diff --git a/util/grub-mkrescue.in b/util/grub-mkrescue.in index 99b10de7b..36cce31ec 100644 --- a/util/grub-mkrescue.in +++ b/util/grub-mkrescue.in @@ -30,6 +30,8 @@ target_cpu=@target_cpu@ native_platform=@platform@ pkglib_DATA="@pkglib_DATA@" +self=`basename $0` + multiboot_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-multiboot coreboot_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-coreboot qemu_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-qemu @@ -40,56 +42,97 @@ rom_directory= override_dir= grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` +xorriso=xorriso + # Usage: usage # Print the usage. usage () { cat <. +Mail xorriso support requests to . EOF } +argument () { + opt=$1 + shift + + if test $# -eq 0; then + echo "$0: option requires an argument -- '$opt'" 1>&2 + exit 1 + fi + echo $1 +} + # Check the arguments. -for option in "$@"; do +while test $# -gt 0 +do + option=$1 + shift + case "$option" in -h | --help) usage exit 0 ;; -v | --version) - echo "$0 (GNU GRUB ${PACKAGE_VERSION})" + echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" exit 0 ;; + + --modules) + modules=`argument $option "$@"`; shift ;; --modules=*) modules=`echo "$option" | sed 's/--modules=//'` ;; + + -o | --output) + output_image=`argument $option "$@"`; shift ;; --output=*) output_image=`echo "$option" | sed 's/--output=//'` ;; + + --rom-directory) + rom_directory=`argument $option "$@"`; shift ;; --rom-directory=*) rom_directory=`echo "$option" | sed 's/--rom-directory=//'` ;; + # Intentionally undocumented + --override-directory) + override_dir=`argument $option "$@"` + shift + PATH=${override_dir}:$PATH + export PATH + ;; --override-directory=*) override_dir=`echo "${option}/" | sed 's/--override-directory=//'` PATH=${override_dir}:$PATH export PATH ;; + + --grub-mkimage) + grub_mkimage=`argument $option "$@"`; shift ;; --grub-mkimage=*) grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;; - -*) - echo "Unrecognized option \`$option'" 1>&2 - usage - exit 1 - ;; + + --xorriso) + xorriso=`argument $option "$@"`; shift ;; + --xorriso=*) + xorriso=`echo "${option}/" | sed 's/--xorriso=//'` ;; + *) - source="${source} ${option}" ;; + source="${source} ${option} $@"; break ;; esac done @@ -171,7 +214,7 @@ EOF tar -C ${memdisk_dir} -cf ${memdisk_img} boot rm -rf ${memdisk_dir} $grub_mkimage -O ${platform} -d "${source_directory}" -m "${memdisk_img}" -o "$3" --prefix='(memdisk)/boot/grub' \ - search iso9660 configfile normal sh memdisk tar $4 + search iso9660 configfile normal memdisk tar $4 rm -rf ${memdisk_img} } @@ -267,7 +310,7 @@ if [ -e "${iso9660_dir}/boot/coreboot.elf" ] && [ -d "${rom_directory}" ]; then fi # build iso image -xorriso -pathspecs on -as mkisofs ${grub_mkisofs_arguments} --protective-msdos-label -o ${output_image} -r ${iso9660_dir} ${source} +"${xorriso}" -as mkisofs -graft-points ${grub_mkisofs_arguments} --protective-msdos-label -o ${output_image} -r ${iso9660_dir} --sort-weight 0 / --sort-weight 1 /boot ${source} rm -rf ${iso9660_dir} rm -f ${embed_img} diff --git a/util/grub-probe.c b/util/grub-probe.c index 1f956efb7..493148bd0 100644 --- a/util/grub-probe.c +++ b/util/grub-probe.c @@ -71,9 +71,6 @@ grub_getkey (void) return -1; } -struct grub_handler_class grub_term_input_class; -struct grub_handler_class grub_term_output_class; - void grub_refresh (void) { diff --git a/util/grub-reboot.in b/util/grub-reboot.in index 20f2b10bc..e7a41f68f 100644 --- a/util/grub-reboot.in +++ b/util/grub-reboot.in @@ -22,6 +22,10 @@ transform="@program_transform_name@" prefix=@prefix@ exec_prefix=@exec_prefix@ bindir=@bindir@ +PACKAGE_NAME=@PACKAGE_NAME@ +PACKAGE_VERSION=@PACKAGE_VERSION@ + +self=`basename $0` grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}` rootdir= @@ -30,7 +34,7 @@ rootdir= # Print the usage. usage () { cat <. EOF } +argument () { + opt=$1 + shift + + if test $# -eq 0; then + echo "$0: option requires an argument -- '$opt'" 1>&2 + exit 1 + fi + echo $1 +} + # Check the arguments. -for option in "$@"; do +while test $# -gt 0 +do + option=$1 + shift + case "$option" in -h | --help) usage exit 0 ;; -v | --version) - echo "grub-reboot (GNU GRUB ${PACKAGE_VERSION})" + echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" exit 0 ;; + + --root-directory) + rootdir=`argument $option "$@"`; shift ;; --root-directory=*) rootdir=`echo "$option" | sed 's/--root-directory=//'` ;; + -*) echo "Unrecognized option \`$option'" 1>&2 usage diff --git a/util/grub-script-check.c b/util/grub-script-check.c index e69f787f5..77213c109 100644 --- a/util/grub-script-check.c +++ b/util/grub-script-check.c @@ -26,8 +26,6 @@ #include #include -#include - #define _GNU_SOURCE 1 #include @@ -239,9 +237,6 @@ main (int argc, char *argv[]) } } - /* Initialize all modules. */ - grub_init_all (); - do { input = 0; @@ -260,8 +255,6 @@ main (int argc, char *argv[]) grub_free (input); } while (script != 0); - /* Free resources. */ - grub_fini_all (); if (file) fclose (file); return (found_input && script == 0); diff --git a/util/grub-set-default.in b/util/grub-set-default.in index 4d7c10e8e..389c504c7 100644 --- a/util/grub-set-default.in +++ b/util/grub-set-default.in @@ -22,6 +22,10 @@ transform="@program_transform_name@" prefix=@prefix@ exec_prefix=@exec_prefix@ bindir=@bindir@ +PACKAGE_NAME=@PACKAGE_NAME@ +PACKAGE_VERSION=@PACKAGE_VERSION@ + +self=`basename $0` grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}` rootdir= @@ -30,7 +34,7 @@ rootdir= # Print the usage. usage () { cat <. EOF } +argument () { + opt=$1 + shift + + if test $# -eq 0; then + echo "$0: option requires an argument -- '$opt'" 1>&2 + exit 1 + fi + echo $1 +} + # Check the arguments. -for option in "$@"; do +while test $# -gt 0 +do + option=$1 + shift + case "$option" in -h | --help) usage exit 0 ;; -v | --version) - echo "grub-set-default (GNU GRUB ${PACKAGE_VERSION})" + echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" exit 0 ;; + + --root-directory) + rootdir=`argument $option "$@"`; shift ;; --root-directory=*) rootdir=`echo "$option" | sed 's/--root-directory=//'` ;; + -*) echo "Unrecognized option \`$option'" 1>&2 usage diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in index df8f5dfaa..8040a7c9b 100644 --- a/util/grub.d/00_header.in +++ b/util/grub.d/00_header.in @@ -21,8 +21,7 @@ transform="@program_transform_name@" prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ -grub_prefix=`echo /boot/grub | sed ${transform}` -locale_dir=`echo /boot/grub/locale | sed ${transform}` +locale_dir=`echo ${GRUB_PREFIX}/locale | sed ${transform}` grub_lang=`echo $LANG | cut -d _ -f 1` . ${libdir}/grub/grub-mkconfig_lib @@ -61,8 +60,8 @@ set default="${GRUB_DEFAULT}" EOF fi cat <&2 ; exit 1 fi @@ -107,8 +124,8 @@ if [ "x$gfxterm" = x1 ]; then cat << EOF if loadfont `make_system_path_relative_to_its_root "${GRUB_FONT_PATH}"` ; then set gfxmode=${GRUB_GFXMODE} + load_video insmod gfxterm - insmod ${GRUB_VIDEO_BACKEND} EOF if [ "x$GRUB_THEME" != x ] && [ -f "$GRUB_THEME" ] \ && is_path_readable_by_grub "$GRUB_THEME"; then @@ -195,7 +212,7 @@ EOF esac # Gettext variables and module -if [ "x${LANG}" != "xC" ] ; then +if [ "x${LANG}" != "xC" ] && [ -d "${locale_dir}" ] ; then prepare_grub_to_access_device $(${grub_probe} --target=device ${locale_dir}) cat << EOF set locale_dir=(\$root)$(make_system_path_relative_to_its_root ${locale_dir}) diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in index 802d59f51..9e1450f51 100644 --- a/util/grub.d/10_linux.in +++ b/util/grub.d/10_linux.in @@ -66,6 +66,9 @@ linux_entry () # Use ELILO's generic "efifb" when it's known to be available. # FIXME: We need an interface to select vesafb in case efifb can't be used. if [ "x$GRUB_GFXPAYLOAD_LINUX" = x ]; then + cat << EOF + load_video +EOF if grep -qx "CONFIG_FB_EFI=y" /boot/config-${version} 2> /dev/null \ && grep -qx "CONFIG_VT_HW_CONSOLE_BINDING=y" /boot/config-${version} 2> /dev/null; then cat << EOF @@ -97,7 +100,7 @@ EOF EOF } -list=`for i in /boot/vmlinu[xz]-* /vmlinu[xz]-* ; do +list=`for i in /boot/vmlinu[zx]-* /vmlinu[zx]-* ; do if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi done` prepare_boot_cache= @@ -114,8 +117,9 @@ while [ "x$list" != "x" ] ; do initrd= for i in "initrd.img-${version}" "initrd-${version}.img" \ - "initrd-${version}" "initrd.img-${alt_version}" \ - "initrd-${alt_version}.img" "initrd-${alt_version}"; do + "initrd-${version}" "initramfs-${version}.img" \ + "initrd.img-${alt_version}" "initrd-${alt_version}.img" \ + "initrd-${alt_version}" "initramfs-${alt_version}.img"; do if test -e "${dirname}/${i}" ; then initrd="$i" break diff --git a/util/grub.d/20_linux_xen.in b/util/grub.d/20_linux_xen.in new file mode 100644 index 000000000..9a0136a76 --- /dev/null +++ b/util/grub.d/20_linux_xen.in @@ -0,0 +1,141 @@ +#! /bin/sh -e + +# grub-mkconfig helper script. +# Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc. +# +# GRUB is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# GRUB is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GRUB. If not, see . + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +bindir=@bindir@ +libdir=@libdir@ +. ${libdir}/grub/grub-mkconfig_lib + +export TEXTDOMAIN=@PACKAGE@ +export TEXTDOMAINDIR=@localedir@ + +CLASS="--class gnu-linux --class gnu --class os --class xen" + +if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then + OS=GNU/Linux +else + OS="${GRUB_DISTRIBUTOR} GNU/Linux" + CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr '[A-Z]' '[a-z]' | cut -d' ' -f1) ${CLASS}" +fi + +# loop-AES arranges things so that /dev/loop/X can be our root device, but +# the initrds that Linux uses don't like that. +case ${GRUB_DEVICE} in + /dev/loop/*|/dev/loop[0-9]) + GRUB_DEVICE=`losetup ${GRUB_DEVICE} | sed -e "s/^[^(]*(\([^)]\+\)).*/\1/"` + ;; +esac + +if [ "x${GRUB_DEVICE_UUID}" = "x" ] || [ "x${GRUB_DISABLE_LINUX_UUID}" = "xtrue" ] \ + || ! test -e "/dev/disk/by-uuid/${GRUB_DEVICE_UUID}" ; then + LINUX_ROOT_DEVICE=${GRUB_DEVICE} +else + LINUX_ROOT_DEVICE=UUID=${GRUB_DEVICE_UUID} +fi + +linux_entry () +{ + os="$1" + version="$2" + xen_version="$3" + recovery="$4" + args="$5" + xen_args="$6" + if ${recovery} ; then + title="$(gettext_quoted "%s, with Linux %s and XEN %s (recovery mode)")" + else + title="$(gettext_quoted "%s, with Linux %s and XEN %s")" + fi + printf "menuentry '${title}' ${CLASS} {\n" "${os}" "${version}" "${xen_version}" + save_default_entry | sed -e "s/^/\t/" + + if [ -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_quoted "Loading Linux %s ...")" ${version})' + multiboot ${rel_xen_dirname}/${xen_basename} placeholder ${xen_args} + module ${rel_dirname}/${basename} placeholder root=${linux_root_device_thisversion} ro ${args} +EOF + if test -n "${initrd}" ; then + cat << EOF + echo '$(gettext_quoted "Loading initial ramdisk ...")' + module ${rel_dirname}/${initrd} +EOF + fi + cat << EOF +} +EOF +} + +linux_list=`for i in /boot/vmlinu[xz]-* /vmlinu[xz]-* ; do + basename=$(basename $i) + version=$(echo $basename | sed -e "s,^[^0-9]*-,,g") + if grub_file_is_not_garbage "$i" && grep -qx "CONFIG_XEN_DOM0=y" /boot/config-${version} 2> /dev/null ; then echo -n "$i " ; fi + done` +xen_list=`for i in /boot/xen*; do + if grub_file_is_not_garbage "$i" ; then echo -n "$i " ; fi + done` +prepare_boot_cache= + +while [ "x${xen_list}" != "x" ] ; do + list="${linux_list}" + current_xen=`version_find_latest $xen_list` + xen_basename=`basename ${current_xen}` + xen_dirname=`dirname ${current_xen}` + rel_xen_dirname=`make_system_path_relative_to_its_root $xen_dirname` + xen_version=`echo $xen_basename | sed -e "s,.gz$,,g;s,^xen-,,g"` + while [ "x$list" != "x" ] ; do + linux=`version_find_latest $list` + echo "Found linux image: $linux" >&2 + basename=`basename $linux` + dirname=`dirname $linux` + rel_dirname=`make_system_path_relative_to_its_root $dirname` + version=`echo $basename | sed -e "s,^[^0-9]*-,,g"` + alt_version=`echo $version | sed -e "s,\.old$,,g"` + linux_root_device_thisversion="${LINUX_ROOT_DEVICE}" + + initrd= + for i in "initrd.img-${version}" "initrd-${version}.img" \ + "initrd-${version}" "initrd.img-${alt_version}" \ + "initrd-${alt_version}.img" "initrd-${alt_version}"; do + if test -e "${dirname}/${i}" ; then + initrd="$i" + break + fi + done + if test -n "${initrd}" ; then + echo "Found initrd image: ${dirname}/${initrd}" >&2 + else + # "UUID=" magic is parsed by initrds. Since there's no initrd, it can't work here. + linux_root_device_thisversion=${GRUB_DEVICE} + fi + + linux_entry "${OS}" "${version}" "${xen_version}" false \ + "${GRUB_CMDLINE_LINUX} ${GRUB_CMDLINE_LINUX_DEFAULT}" "${GRUB_CMDLINE_XEN} ${GRUB_CMDLINE_XEN_DEFAULT}" + if [ "x${GRUB_DISABLE_LINUX_RECOVERY}" != "xtrue" ]; then + linux_entry "${OS}" "${version}" "${xen_version}" true \ + "single ${GRUB_CMDLINE_LINUX}" "${GRUB_CMDLINE_XEN}" + fi + + list=`echo $list | tr ' ' '\n' | grep -vx $linux | tr '\n' ' '` + done + xen_list=`echo $xen_list | tr ' ' '\n' | grep -vx $current_xen | tr '\n' ' '` +done diff --git a/util/grub.d/30_os-prober.in b/util/grub.d/30_os-prober.in index edef37e66..90e2e3d92 100644 --- a/util/grub.d/30_os-prober.in +++ b/util/grub.d/30_os-prober.in @@ -44,7 +44,7 @@ EOF save_default_entry | sed -e "s/^/\t/" prepare_grub_to_access_device ${DEVICE} | sed -e "s/^/\t/" cat << EOF - insmod ${GRUB_VIDEO_BACKEND} + load_video set do_resume=0 if [ /var/vm/sleepimage -nt10 / ]; then if xnu_resume /var/vm/sleepimage; then diff --git a/util/grub.d/41_custom.in b/util/grub.d/41_custom.in new file mode 100644 index 000000000..64d691c55 --- /dev/null +++ b/util/grub.d/41_custom.in @@ -0,0 +1,7 @@ +#!/bin/sh +cat <. EOF } +argument () { + opt=$1 + shift + + if test $# -eq 0; then + echo "$0: option requires an argument -- '$opt'" 1>&2 + exit 1 + fi + echo $1 +} + # Check the arguments. -for option in "$@"; do +while test $# -gt 0 +do + option=$1 + shift + case "$option" in -h | --help) usage exit 0 ;; -v | --version) - echo "grub-install (GNU GRUB ${PACKAGE_VERSION})" + echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" exit 0 ;; + + --modules) + modules=`argument $option "$@"`; shift ;; --modules=*) modules=`echo "$option" | sed 's/--modules=//'` ;; + + --root-directory) + rootdir=`argument $option "$@"`; shift ;; --root-directory=*) rootdir=`echo "$option" | sed 's/--root-directory=//'` ;; + + --grub-mkimage) + grub_mkimage=`argument $option "$@"`; shift ;; --grub-mkimage=*) grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;; + + --grub-mkdevicemap) + grub_mkdevicemap=`argument $option "$@"`; shift ;; --grub-mkdevicemap=*) grub_mkdevicemap=`echo "$option" | sed 's/--grub-mkdevicemap=//'` ;; + + --grub-probe) + grub_probe=`argument $option "$@"`; shift ;; --grub-probe=*) grub_probe=`echo "$option" | sed 's/--grub-probe=//'` ;; + --no-floppy) no_floppy="--no-floppy" ;; --recheck) @@ -219,7 +252,7 @@ $grub_mkimage -O ${target_cpu}-efi --output=${grubdir}/grub.efi $modules || exit echo "Installation finished. No error reported." echo "This is the contents of the device map $device_map." echo "Check if this is correct or not. If any of the lines is incorrect," -echo "fix it and re-run the script \`grub-install'." +echo "fix it and re-run the script \`$self'." echo cat $device_map diff --git a/util/i386/pc/grub-setup.c b/util/i386/pc/grub-setup.c index 6e6b2e878..32f1f90e4 100644 --- a/util/i386/pc/grub-setup.c +++ b/util/i386/pc/grub-setup.c @@ -76,9 +76,6 @@ grub_getkey (void) return -1; } -struct grub_handler_class grub_term_input_class; -struct grub_handler_class grub_term_output_class; - void grub_refresh (void) { @@ -102,6 +99,7 @@ setup (const char *dir, struct grub_boot_blocklist *first_block, *block; grub_int32_t *install_dos_part, *install_bsd_part; grub_int32_t dos_part, bsd_part; + char *prefix; char *tmp_img; int i; grub_disk_addr_t first_sector; @@ -126,8 +124,8 @@ setup (const char *dir, /* There's always an embed region, and it starts right after the MBR. */ embed_region.start = 1; - if (embed_region.end > p->start) - embed_region.end = p->start; + if (embed_region.end > grub_partition_get_start (p)) + embed_region.end = grub_partition_get_start (p); return 0; } @@ -147,8 +145,8 @@ setup (const char *dir, /* If there's an embed region, it is in a dedicated partition. */ if (! memcmp (&gptdata.type, &grub_gpt_partition_type_bios_boot, 16)) { - embed_region.start = p->start; - embed_region.end = p->start + p->len; + embed_region.start = grub_partition_get_start (p); + embed_region.end = grub_partition_get_start (p) + grub_partition_get_len (p); return 1; } @@ -233,6 +231,8 @@ setup (const char *dir, + GRUB_KERNEL_MACHINE_INSTALL_DOS_PART); install_bsd_part = (grub_int32_t *) (core_img + GRUB_DISK_SECTOR_SIZE + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART); + prefix = (char *) (core_img + GRUB_DISK_SECTOR_SIZE + + GRUB_KERNEL_MACHINE_PREFIX); /* Open the root device and the destination device. */ root_dev = grub_device_open (root); @@ -308,6 +308,18 @@ setup (const char *dir, dos_part = root_dev->disk->partition->number; bsd_part = -1; } + + if (prefix[0] != '(') + { + char *root_part_name, *new_prefix; + + root_part_name = + grub_partition_get_name (root_dev->disk->partition); + new_prefix = xasprintf ("(,%s)%s", root_part_name, prefix); + strcpy (prefix, new_prefix); + free (new_prefix); + free (root_part_name); + } } else dos_part = bsd_part = -1; @@ -361,7 +373,7 @@ setup (const char *dir, else grub_util_error (_("No DOS-style partitions found")); - if (embed_region.end == embed_region.start) + if (embed_region.end <= embed_region.start) { if (! strcmp (dest_partmap, "msdos")) grub_util_warn (_("This msdos-style partition label has no post-MBR gap; embedding won't be possible!")); @@ -596,6 +608,8 @@ Usage: %s [OPTION]... DEVICE\n\ \n\ Set up images to boot from DEVICE.\n\ DEVICE must be a GRUB device (e.g. `(hd0,1)').\n\ +\n\ +You should not normally run %s directly. Use grub-install instead.\n\ \n\ -b, --boot-image=FILE use FILE as the boot image [default=%s]\n\ -c, --core-image=FILE use FILE as the core image [default=%s]\n\ @@ -610,7 +624,7 @@ DEVICE must be a GRUB device (e.g. `(hd0,1)').\n\ \n\ Report bugs to <%s>.\n\ "), - program_name, + program_name, program_name, DEFAULT_BOOT_FILE, DEFAULT_CORE_FILE, DEFAULT_DIRECTORY, DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT); @@ -702,7 +716,7 @@ main (int argc, char *argv[]) break; case 'V': - printf ("grub-setup (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION); + printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); return 0; case 'v': diff --git a/util/ieee1275/grub-install.in b/util/ieee1275/grub-install.in index 4d00cc217..98fd5d65a 100644 --- a/util/ieee1275/grub-install.in +++ b/util/ieee1275/grub-install.in @@ -34,6 +34,8 @@ target_cpu=@target_cpu@ platform=@platform@ pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}` +self=`basename $0` + grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}` grub_probe=${sbindir}/`echo grub-probe | sed ${transform}` @@ -53,7 +55,7 @@ nvsetenv=`which nvsetenv` # Print the usage. usage () { cat <. EOF } +argument () { + opt=$1 + shift + + if test $# -eq 0; then + echo "$0: option requires an argument -- '$opt'" 1>&2 + exit 1 + fi + echo $1 +} + # Check the arguments. -for option in "$@"; do +while test $# -gt 0 +do + option=$1 + shift + case "$option" in -h | --help) usage exit 0 ;; -v | --version) - echo "grub-install (GNU GRUB ${PACKAGE_VERSION})" + echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" exit 0 ;; + + --modules) + modules=`argument $option "$@"`; shift ;; --modules=*) modules=`echo "$option" | sed 's/--modules=//'` ;; + + --root-directory) + rootdir=`argument $option "$@"`; shift ;; --root-directory=*) rootdir=`echo "$option" | sed 's/--root-directory=//'` ;; + + --grub-mkdevicemap) + grub_mkdevicemap=`argument $option "$@"`; shift ;; --grub-mkdevicemap=*) grub_mkdevicemap=`echo "$option" | sed 's/--grub-mkdevicemap=//'` ;; + + --grub-mkimage) + grub_mkimage=`argument $option "$@"`; shift ;; --grub-mkimage=*) grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;; + + --grub-probe) + grub_probe=`argument $option "$@"`; shift ;; --grub-probe=*) grub_probe=`echo "$option" | sed 's/--grub-probe=//'` ;; + --no-nvram) update_nvram=no ;; # This is an undocumented feature... @@ -231,7 +264,7 @@ fi echo "Installation finished. No error reported." echo "This is the contents of the device map $device_map." echo "Check if this is correct or not. If any of the lines is incorrect," -echo "fix it and re-run the script \`grub-install'." +echo "fix it and re-run the script \`$self'." echo cat $device_map diff --git a/util/powerpc/ieee1275/grub-mkrescue.in b/util/powerpc/ieee1275/grub-mkrescue.in index 16658505b..4ef26f616 100644 --- a/util/powerpc/ieee1275/grub-mkrescue.in +++ b/util/powerpc/ieee1275/grub-mkrescue.in @@ -30,13 +30,15 @@ target_cpu=@target_cpu@ platform=@platform@ pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}` +self=`basename $0` + grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` # Usage: usage # Print the usage. usage () { cat <. EOF } +argument () { + opt=$1 + shift + + if test $# -eq 0; then + echo "$0: option requires an argument -- '$opt'" 1>&2 + exit 1 + fi + echo $1 +} + input_dir=${pkglibdir} # Check the arguments. -for option in "$@"; do +while test $# -gt 0 +do + option=$1 + shift + case "$option" in -h | --help) usage exit 0 ;; -v | --version) - echo "grub-mkrescue (GNU GRUB ${PACKAGE_VERSION})" + echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" exit 0 ;; + + --modules) + modules=`argument $option "$@"`; shift ;; --modules=*) modules=`echo "$option" | sed 's/--modules=//'` ;; + + --pkglibdir) + input_dir=`argument $option "$@"`; shift ;; --pkglibdir=*) input_dir=`echo "$option" | sed 's/--pkglibdir=//'` ;; + + --grub-mkimage) + grub_mkimage=`argument $option "$@"`; shift ;; --grub-mkimage=*) grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;; + -*) echo "Unrecognized option \`$option'" 1>&2 usage diff --git a/util/sparc64/ieee1275/grub-setup.c b/util/sparc64/ieee1275/grub-setup.c index 8a2d30ba1..e53542263 100644 --- a/util/sparc64/ieee1275/grub-setup.c +++ b/util/sparc64/ieee1275/grub-setup.c @@ -102,9 +102,6 @@ grub_getkey (void) return -1; } -struct grub_handler_class grub_term_input_class; -struct grub_handler_class grub_term_output_class; - void grub_refresh (void) { @@ -410,6 +407,8 @@ Usage: %s [OPTION]... DEVICE\n\ \n\ Set up images to boot from DEVICE.\n\ DEVICE must be a GRUB device (e.g. `(hd0,1)').\n\ +\n\ +You should not normally run %s directly. Use grub-install instead.\n\ \n\ -b, --boot-image=FILE use FILE as the boot image [default=%s]\n\ -c, --core-image=FILE use FILE as the core image [default=%s]\n\ @@ -421,7 +420,7 @@ DEVICE must be a GRUB device (e.g. `(hd0,1)').\n\ -v, --verbose print verbose messages\n\ \n\ Report bugs to <%s>.\n\ -", program_name, +", program_name, program_name, DEFAULT_BOOT_FILE, DEFAULT_CORE_FILE, DEFAULT_DIRECTORY, DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT); @@ -503,7 +502,7 @@ parse_options (struct grub_setup_info *gp, int argc, char *argv[]) break; case 'V': - printf ("grub-setup (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION); + printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); return 0; case 'v': diff --git a/video/bochs.c b/video/bochs.c new file mode 100644 index 000000000..5def0985b --- /dev/null +++ b/video/bochs.c @@ -0,0 +1,423 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#define grub_video_render_target grub_video_fbrender_target + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct +{ + struct grub_video_mode_info mode_info; + + grub_uint8_t *ptr; + int mapped; + grub_uint32_t base; + grub_pci_device_t dev; +} framebuffer; + +#define BOCHS_APERTURE_SIZE 0x800000 +#define BOCHS_MAX_WIDTH 1600 +#define BOCHS_MAX_HEIGHT 1200 +#define BOCHS_WIDTH_ALIGN 8 + +enum + { + BOCHS_VBE_INDEX = 0x1ce, + BOCHS_VBE_DATA = 0x1cf, + }; + +enum + { + BOCHS_VBE_WIDTH = 1, + BOCHS_VBE_HEIGHT = 2, + BOCHS_VBE_BPP = 3, + BOCHS_VBE_ENABLE = 4, + BOCHS_VBE_Y_OFFSET = 9, + BOCHS_VBE_MAX + }; + +static void +vbe_write (grub_uint16_t val, grub_uint16_t addr) +{ + grub_outw (addr, BOCHS_VBE_INDEX); + grub_outw (val, BOCHS_VBE_DATA); +} + +static grub_uint16_t +vbe_read (grub_uint16_t addr) +{ + grub_outw (addr, BOCHS_VBE_INDEX); + return grub_inw (BOCHS_VBE_DATA); +} + +struct saved_state +{ + grub_uint8_t cr[256]; + grub_uint8_t gr[256]; + grub_uint8_t sr[256]; + grub_uint8_t r[256]; + grub_uint8_t g[256]; + grub_uint8_t b[256]; + grub_uint8_t vbe[BOCHS_VBE_MAX]; + int vbe_enable; + /* We need to preserve VGA font and VGA text. */ + grub_uint8_t vram[32 * 4 * 256]; +}; + +static struct saved_state initial_state; +static int state_saved = 0; + +static void +save_state (struct saved_state *st) +{ + unsigned i; + + for (i = 0; i < ARRAY_SIZE (st->cr); i++) + st->cr[i] = grub_vga_cr_read (i); + for (i = 0; i < ARRAY_SIZE (st->gr); i++) + st->gr[i] = grub_vga_gr_read (i); + for (i = 0; i < ARRAY_SIZE (st->sr); i++) + st->sr[i] = grub_vga_sr_read (i); + + for (i = 0; i < 256; i++) + grub_vga_palette_read (i, st->r + i, st->g + i, st->b + i); + + st->vbe_enable = vbe_read (BOCHS_VBE_ENABLE) & 1; + if (st->vbe_enable) + for (i = 0; i < ARRAY_SIZE (st->vbe); i++) + st->vbe[i] = vbe_read (i); + + grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_CHAIN4, GRUB_VGA_SR_MEMORY_MODE); + grub_memcpy (st->vram, framebuffer.ptr, sizeof (st->vram)); + grub_vga_sr_write (st->sr[GRUB_VGA_SR_MEMORY_MODE], GRUB_VGA_SR_MEMORY_MODE); +} + +static void +restore_state (struct saved_state *st) +{ + unsigned i; + + if (st->vbe_enable) + for (i = 0; i < ARRAY_SIZE (st->vbe); i++) + vbe_write (st->vbe[i], i); + else + vbe_write (0, BOCHS_VBE_ENABLE); + + grub_vga_cr_write (0, 0x11); + for (i = 0; i < ARRAY_SIZE (st->cr); i++) + grub_vga_cr_write (st->cr[i], i); + for (i = 0; i < ARRAY_SIZE (st->sr); i++) + grub_vga_sr_write (st->sr[i], i); + for (i = 0; i < ARRAY_SIZE (st->gr); i++) + grub_vga_gr_write (st->gr[i], i); + + for (i = 0; i < 256; i++) + grub_vga_palette_write (i, st->r[i], st->g[i], st->b[i]); + + grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_CHAIN4, GRUB_VGA_SR_MEMORY_MODE); + grub_memcpy (framebuffer.ptr, st->vram, sizeof (st->vram)); + grub_vga_sr_write (st->sr[GRUB_VGA_SR_MEMORY_MODE], GRUB_VGA_SR_MEMORY_MODE); +} + +static grub_err_t +grub_video_bochs_video_init (void) +{ + /* Reset frame buffer. */ + grub_memset (&framebuffer, 0, sizeof(framebuffer)); + + return grub_video_fb_init (); +} + +static grub_err_t +grub_video_bochs_video_fini (void) +{ + if (framebuffer.mapped) + grub_pci_device_unmap_range (framebuffer.dev, framebuffer.ptr, + BOCHS_APERTURE_SIZE); + + if (state_saved) + { + restore_state (&initial_state); + state_saved = 0; + } + + return grub_video_fb_fini (); +} + +static grub_err_t +doublebuf_pageflipping_set_page (int page) +{ + int start = framebuffer.mode_info.height * page; + + vbe_write (start, BOCHS_VBE_Y_OFFSET); + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_video_bochs_set_palette (unsigned int start, unsigned int count, + struct grub_video_palette_data *palette_data) +{ + if (framebuffer.mode_info.mode_type == GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) + { + unsigned i; + if (start >= 0x100) + return GRUB_ERR_NONE; + if (start + count >= 0x100) + count = 0x100 - start; + + for (i = 0; i < count; i++) + grub_vga_palette_write (start + i, palette_data[i].r, palette_data[i].g, + palette_data[i].b); + } + + /* Then set color to emulated palette. */ + return grub_video_fb_set_palette (start, count, palette_data); +} + +static grub_err_t +grub_video_bochs_setup (unsigned int width, unsigned int height, + unsigned int mode_type, unsigned int mode_mask) +{ + int depth; + grub_err_t err; + int found = 0; + int pitch, bytes_per_pixel; + grub_size_t page_size; /* The size of a page in bytes. */ + + auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused))); + int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid) + { + grub_pci_address_t addr; + grub_uint32_t class; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); + class = grub_pci_read (addr); + + if (((class >> 16) & 0xffff) != 0x0300 || pciid != 0x11111234) + return 0; + + found = 1; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); + framebuffer.base = grub_pci_read (addr) & GRUB_PCI_ADDR_MEM_MASK; + framebuffer.dev = dev; + + return 1; + } + + /* Decode depth from mode_type. If it is zero, then autodetect. */ + depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK) + >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS; + + if (width == 0 || height == 0) + { + width = 800; + height = 600; + } + + if (width > BOCHS_MAX_WIDTH) + return grub_error (GRUB_ERR_IO, "width must be at most", + BOCHS_MAX_WIDTH); + + if (height > BOCHS_MAX_HEIGHT) + return grub_error (GRUB_ERR_IO, "height must be at most", + BOCHS_MAX_HEIGHT); + + if (width & (BOCHS_WIDTH_ALIGN - 1)) + return grub_error (GRUB_ERR_IO, "width must be a multiple of %d", + BOCHS_WIDTH_ALIGN); + + if (depth == 0 + && !grub_video_check_mode_flag (mode_type, mode_mask, + GRUB_VIDEO_MODE_TYPE_INDEX_COLOR, 0)) + depth = 24; + + if (depth == 0) + depth = 8; + + if (depth != 32 && depth != 24 && depth != 16 && depth != 15 && depth != 8 + && depth != 4) + return grub_error (GRUB_ERR_IO, "only 32, 24, 16, 15 and 8-bpp are" + " supported by bochs video"); + + if (depth == 4) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "4-bpp isn't cupported"); + + bytes_per_pixel = (depth + 7) / 8; + if (depth == 4) + pitch = width / 2; + else + pitch = width * bytes_per_pixel; + + page_size = pitch * height; + + if (page_size > BOCHS_APERTURE_SIZE) + return grub_error (GRUB_ERR_IO, "Not enough video memory for this mode"); + + grub_pci_iterate (find_card); + if (!found) + return grub_error (GRUB_ERR_IO, "Couldn't find graphics card"); + + if (found && framebuffer.base == 0) + { + /* FIXME: change framebuffer base */ + return grub_error (GRUB_ERR_IO, "PCI BAR not set"); + } + + /* We can safely discard volatile attribute. */ + framebuffer.ptr = (void *) grub_pci_device_map_range (framebuffer.dev, + framebuffer.base, + BOCHS_APERTURE_SIZE); + framebuffer.mapped = 1; + + if (!state_saved) + { + save_state (&initial_state); + state_saved = 1; + } + + { + vbe_write (0, BOCHS_VBE_ENABLE); + + vbe_write (width, BOCHS_VBE_WIDTH); + vbe_write (height, BOCHS_VBE_HEIGHT); + vbe_write (depth, BOCHS_VBE_BPP); + + vbe_write (1, BOCHS_VBE_ENABLE); + doublebuf_pageflipping_set_page (0); + } + + /* Fill mode info details. */ + framebuffer.mode_info.width = width; + framebuffer.mode_info.height = height; + framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB; + framebuffer.mode_info.bpp = depth; + framebuffer.mode_info.bytes_per_pixel = bytes_per_pixel; + framebuffer.mode_info.pitch = pitch; + framebuffer.mode_info.number_of_colors = 256; + framebuffer.mode_info.reserved_mask_size = 0; + framebuffer.mode_info.reserved_field_pos = 0; + + switch (depth) + { + case 4: + case 8: + framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; + break; + case 16: + framebuffer.mode_info.red_mask_size = 5; + framebuffer.mode_info.red_field_pos = 11; + framebuffer.mode_info.green_mask_size = 6; + framebuffer.mode_info.green_field_pos = 5; + framebuffer.mode_info.blue_mask_size = 5; + framebuffer.mode_info.blue_field_pos = 0; + break; + + case 15: + framebuffer.mode_info.red_mask_size = 5; + framebuffer.mode_info.red_field_pos = 10; + framebuffer.mode_info.green_mask_size = 5; + framebuffer.mode_info.green_field_pos = 5; + framebuffer.mode_info.blue_mask_size = 5; + framebuffer.mode_info.blue_field_pos = 0; + break; + + case 32: + framebuffer.mode_info.reserved_mask_size = 8; + framebuffer.mode_info.reserved_field_pos = 24; + + case 24: + framebuffer.mode_info.red_mask_size = 8; + framebuffer.mode_info.red_field_pos = 16; + framebuffer.mode_info.green_mask_size = 8; + framebuffer.mode_info.green_field_pos = 8; + framebuffer.mode_info.blue_mask_size = 8; + framebuffer.mode_info.blue_field_pos = 0; + break; + } + + framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info); + + if (BOCHS_APERTURE_SIZE >= 2 * page_size) + err = grub_video_fb_setup (mode_type, mode_mask, + &framebuffer.mode_info, + framebuffer.ptr, + doublebuf_pageflipping_set_page, + framebuffer.ptr + page_size); + else + err = grub_video_fb_setup (mode_type, mode_mask, + &framebuffer.mode_info, + framebuffer.ptr, 0, 0); + + + /* Copy default palette to initialize emulated palette. */ + err = grub_video_bochs_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, + grub_video_fbstd_colors); + return err; +} + +static struct grub_video_adapter grub_video_bochs_adapter = + { + .name = "Bochs PCI Video Driver", + .id = GRUB_VIDEO_DRIVER_BOCHS, + + .prio = GRUB_VIDEO_ADAPTER_PRIO_NATIVE, + + .init = grub_video_bochs_video_init, + .fini = grub_video_bochs_video_fini, + .setup = grub_video_bochs_setup, + .get_info = grub_video_fb_get_info, + .get_info_and_fini = grub_video_fb_get_info_and_fini, + .set_palette = grub_video_bochs_set_palette, + .get_palette = grub_video_fb_get_palette, + .set_viewport = grub_video_fb_set_viewport, + .get_viewport = grub_video_fb_get_viewport, + .map_color = grub_video_fb_map_color, + .map_rgb = grub_video_fb_map_rgb, + .map_rgba = grub_video_fb_map_rgba, + .unmap_color = grub_video_fb_unmap_color, + .fill_rect = grub_video_fb_fill_rect, + .blit_bitmap = grub_video_fb_blit_bitmap, + .blit_render_target = grub_video_fb_blit_render_target, + .scroll = grub_video_fb_scroll, + .swap_buffers = grub_video_fb_swap_buffers, + .create_render_target = grub_video_fb_create_render_target, + .delete_render_target = grub_video_fb_delete_render_target, + .set_active_render_target = grub_video_fb_set_active_render_target, + .get_active_render_target = grub_video_fb_get_active_render_target, + + .next = 0 + }; + +GRUB_MOD_INIT(video_bochs) +{ + grub_video_register (&grub_video_bochs_adapter); +} + +GRUB_MOD_FINI(video_bochs) +{ + grub_video_unregister (&grub_video_bochs_adapter); +} diff --git a/video/cirrus.c b/video/cirrus.c new file mode 100644 index 000000000..ccbab9d15 --- /dev/null +++ b/video/cirrus.c @@ -0,0 +1,520 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#define grub_video_render_target grub_video_fbrender_target + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct +{ + struct grub_video_mode_info mode_info; + grub_size_t page_size; /* The size of a page in bytes. */ + + grub_uint8_t *ptr; + int mapped; + grub_uint32_t base; + grub_pci_device_t dev; +} framebuffer; + +#define CIRRUS_APERTURE_SIZE 0x1000000 + +#define CIRRUS_MAX_WIDTH 0x800 +#define CIRRUS_MAX_HEIGHT 0x800 +#define CIRRUS_MAX_PITCH (0x1ff * GRUB_VGA_CR_PITCH_DIVISOR) + +enum + { + CIRRUS_CR_EXTENDED_DISPLAY = 0x1b, + CIRRUS_CR_EXTENDED_OVERLAY = 0x1d, + CIRRUS_CR_MAX + }; + +#define CIRRUS_CR_EXTENDED_DISPLAY_PITCH_MASK 0x10 +#define CIRRUS_CR_EXTENDED_DISPLAY_PITCH_SHIFT 4 +#define CIRRUS_CR_EXTENDED_DISPLAY_START_MASK1 0x1 +#define CIRRUS_CR_EXTENDED_DISPLAY_START_SHIFT1 16 +#define CIRRUS_CR_EXTENDED_DISPLAY_START_MASK2 0xc +#define CIRRUS_CR_EXTENDED_DISPLAY_START_SHIFT2 15 + +#define CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_MASK 0x80 +#define CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_SHIFT 12 + +enum + { + CIRRUS_SR_EXTENDED_MODE = 7, + CIRRUS_SR_MAX + }; + +#define CIRRUS_SR_EXTENDED_MODE_LFB_ENABLE 0xf0 +#define CIRRUS_SR_EXTENDED_MODE_ENABLE_EXT 0x01 +#define CIRRUS_SR_EXTENDED_MODE_8BPP 0x00 +#define CIRRUS_SR_EXTENDED_MODE_16BPP 0x06 +#define CIRRUS_SR_EXTENDED_MODE_24BPP 0x04 +#define CIRRUS_SR_EXTENDED_MODE_32BPP 0x08 + +#define CIRRUS_HIDDEN_DAC_ENABLE_EXT 0x80 +#define CIRRUS_HIDDEN_DAC_ENABLE_ALL 0x40 +#define CIRRUS_HIDDEN_DAC_8BPP 0 +#define CIRRUS_HIDDEN_DAC_15BPP (CIRRUS_HIDDEN_DAC_ENABLE_EXT \ + | CIRRUS_HIDDEN_DAC_ENABLE_ALL | 0) +#define CIRRUS_HIDDEN_DAC_16BPP (CIRRUS_HIDDEN_DAC_ENABLE_EXT \ + | CIRRUS_HIDDEN_DAC_ENABLE_ALL | 1) +#define CIRRUS_HIDDEN_DAC_888COLOR (CIRRUS_HIDDEN_DAC_ENABLE_EXT \ + | CIRRUS_HIDDEN_DAC_ENABLE_ALL | 5) + +static void +write_hidden_dac (grub_uint8_t data) +{ + grub_inb (GRUB_VGA_IO_PALLETTE_WRITE_INDEX); + grub_inb (GRUB_VGA_IO_PIXEL_MASK); + grub_inb (GRUB_VGA_IO_PIXEL_MASK); + grub_inb (GRUB_VGA_IO_PIXEL_MASK); + grub_inb (GRUB_VGA_IO_PIXEL_MASK); + grub_outb (data, GRUB_VGA_IO_PIXEL_MASK); +} + +static grub_uint8_t +read_hidden_dac (void) +{ + grub_inb (GRUB_VGA_IO_PALLETTE_WRITE_INDEX); + grub_inb (GRUB_VGA_IO_PIXEL_MASK); + grub_inb (GRUB_VGA_IO_PIXEL_MASK); + grub_inb (GRUB_VGA_IO_PIXEL_MASK); + grub_inb (GRUB_VGA_IO_PIXEL_MASK); + return grub_inb (GRUB_VGA_IO_PIXEL_MASK); +} + +struct saved_state +{ + grub_uint8_t cr[CIRRUS_CR_MAX]; + grub_uint8_t gr[GRUB_VGA_GR_MAX]; + grub_uint8_t sr[CIRRUS_SR_MAX]; + grub_uint8_t hidden_dac; + /* We need to preserve VGA font and VGA text. */ + grub_uint8_t vram[32 * 4 * 256]; + grub_uint8_t r[256]; + grub_uint8_t g[256]; + grub_uint8_t b[256]; +}; + +static struct saved_state initial_state; +static int state_saved = 0; + +static void +save_state (struct saved_state *st) +{ + unsigned i; + for (i = 0; i < ARRAY_SIZE (st->cr); i++) + st->cr[i] = grub_vga_cr_read (i); + for (i = 0; i < ARRAY_SIZE (st->sr); i++) + st->sr[i] = grub_vga_sr_read (i); + for (i = 0; i < ARRAY_SIZE (st->gr); i++) + st->gr[i] = grub_vga_gr_read (i); + for (i = 0; i < 256; i++) + grub_vga_palette_read (i, st->r + i, st->g + i, st->b + i); + + st->hidden_dac = read_hidden_dac (); + grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_CHAIN4, GRUB_VGA_SR_MEMORY_MODE); + grub_memcpy (st->vram, framebuffer.ptr, sizeof (st->vram)); +} + +static void +restore_state (struct saved_state *st) +{ + unsigned i; + grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_CHAIN4, GRUB_VGA_SR_MEMORY_MODE); + grub_memcpy (framebuffer.ptr, st->vram, sizeof (st->vram)); + for (i = 0; i < ARRAY_SIZE (st->cr); i++) + grub_vga_cr_write (st->cr[i], i); + for (i = 0; i < ARRAY_SIZE (st->sr); i++) + grub_vga_sr_write (st->sr[i], i); + for (i = 0; i < ARRAY_SIZE (st->gr); i++) + grub_vga_gr_write (st->gr[i], i); + for (i = 0; i < 256; i++) + grub_vga_palette_write (i, st->r[i], st->g[i], st->b[i]); + + write_hidden_dac (st->hidden_dac); +} + +static grub_err_t +grub_video_cirrus_video_init (void) +{ + /* Reset frame buffer. */ + grub_memset (&framebuffer, 0, sizeof(framebuffer)); + + return grub_video_fb_init (); +} + +static grub_err_t +grub_video_cirrus_video_fini (void) +{ + if (framebuffer.mapped) + grub_pci_device_unmap_range (framebuffer.dev, framebuffer.ptr, + CIRRUS_APERTURE_SIZE); + + if (state_saved) + { + restore_state (&initial_state); + state_saved = 0; + } + + return grub_video_fb_fini (); +} + +static grub_err_t +doublebuf_pageflipping_set_page (int page) +{ + int start = framebuffer.page_size * page / 4; + grub_uint8_t cr_ext, cr_overlay; + + grub_vga_cr_write (start & 0xff, GRUB_VGA_CR_START_ADDR_LOW_REGISTER); + grub_vga_cr_write ((start & 0xff00) >> 8, + GRUB_VGA_CR_START_ADDR_HIGH_REGISTER); + + cr_ext = grub_vga_cr_read (CIRRUS_CR_EXTENDED_DISPLAY); + cr_ext &= ~(CIRRUS_CR_EXTENDED_DISPLAY_START_MASK1 + | CIRRUS_CR_EXTENDED_DISPLAY_START_MASK2); + cr_ext |= ((start >> CIRRUS_CR_EXTENDED_DISPLAY_START_SHIFT1) + & CIRRUS_CR_EXTENDED_DISPLAY_START_MASK1); + cr_ext |= ((start >> CIRRUS_CR_EXTENDED_DISPLAY_START_SHIFT2) + & CIRRUS_CR_EXTENDED_DISPLAY_START_MASK2); + grub_vga_cr_write (cr_ext, CIRRUS_CR_EXTENDED_DISPLAY); + + cr_overlay = grub_vga_cr_read (CIRRUS_CR_EXTENDED_OVERLAY); + cr_overlay &= ~(CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_MASK); + cr_overlay |= ((start >> CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_SHIFT) + & CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_MASK); + grub_vga_cr_write (cr_overlay, CIRRUS_CR_EXTENDED_OVERLAY); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_video_cirrus_set_palette (unsigned int start, unsigned int count, + struct grub_video_palette_data *palette_data) +{ + if (framebuffer.mode_info.mode_type == GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) + { + unsigned i; + if (start >= 0x100) + return GRUB_ERR_NONE; + if (start + count >= 0x100) + count = 0x100 - start; + + for (i = 0; i < count; i++) + grub_vga_palette_write (start + i, palette_data[i].r, palette_data[i].g, + palette_data[i].b); + } + + /* Then set color to emulated palette. */ + return grub_video_fb_set_palette (start, count, palette_data); +} + +static grub_err_t +grub_video_cirrus_setup (unsigned int width, unsigned int height, + unsigned int mode_type, unsigned int mode_mask) +{ + int depth; + grub_err_t err; + int found = 0; + int pitch, bytes_per_pixel; + + auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused))); + int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid) + { + grub_pci_address_t addr; + grub_uint32_t class; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); + class = grub_pci_read (addr); + + if (((class >> 16) & 0xffff) != 0x0300 || pciid != 0x00b81013) + return 0; + + found = 1; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); + framebuffer.base = grub_pci_read (addr) & GRUB_PCI_ADDR_MEM_MASK; + framebuffer.dev = dev; + + return 1; + } + + /* Decode depth from mode_type. If it is zero, then autodetect. */ + depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK) + >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS; + + if (width == 0 || height == 0) + { + width = 800; + height = 600; + } + + if (width & (GRUB_VGA_CR_WIDTH_DIVISOR - 1)) + return grub_error (GRUB_ERR_IO, + "screen width must be a multiple of %d", + GRUB_VGA_CR_WIDTH_DIVISOR); + + if (width > CIRRUS_MAX_WIDTH) + return grub_error (GRUB_ERR_IO, + "screen width must be at most %d", CIRRUS_MAX_WIDTH); + + if (height > CIRRUS_MAX_HEIGHT) + return grub_error (GRUB_ERR_IO, + "screen height must be at most %d", CIRRUS_MAX_HEIGHT); + + if (depth == 0 + && !grub_video_check_mode_flag (mode_type, mode_mask, + GRUB_VIDEO_MODE_TYPE_INDEX_COLOR, 0)) + depth = 24; + + if (depth == 0) + depth = 8; + + if (depth != 32 && depth != 24 && depth != 16 && depth != 15 && depth != 8) + return grub_error (GRUB_ERR_IO, "only 32, 24, 16, 15 and 8-bit bpp are" + " supported by cirrus video"); + + bytes_per_pixel = (depth + 7) / 8; + pitch = width * bytes_per_pixel; + + if (pitch > CIRRUS_MAX_PITCH) + return grub_error (GRUB_ERR_IO, + "screen width must be at most %d at bitdepth %d", + CIRRUS_MAX_PITCH / bytes_per_pixel, depth); + + framebuffer.page_size = pitch * height; + + if (framebuffer.page_size > CIRRUS_APERTURE_SIZE) + return grub_error (GRUB_ERR_IO, "Not enough video memory for this mode"); + + grub_pci_iterate (find_card); + if (!found) + return grub_error (GRUB_ERR_IO, "Couldn't find graphics card"); + + if (found && framebuffer.base == 0) + { + /* FIXME: change framebuffer base */ + return grub_error (GRUB_ERR_IO, "PCI BAR not set"); + } + + /* We can safely discard volatile attribute. */ + framebuffer.ptr = (void *) grub_pci_device_map_range (framebuffer.dev, + framebuffer.base, + CIRRUS_APERTURE_SIZE); + framebuffer.mapped = 1; + + if (!state_saved) + { + save_state (&initial_state); + state_saved = 1; + } + + { + int pitch_reg, overflow_reg = 0, line_compare = 0x3ff; + grub_uint8_t sr_ext = 0, hidden_dac = 0; + + pitch_reg = pitch / GRUB_VGA_CR_PITCH_DIVISOR; + + grub_vga_gr_write (GRUB_VGA_GR_MODE_256_COLOR | GRUB_VGA_GR_MODE_READ_MODE1, + GRUB_VGA_GR_MODE); + grub_vga_gr_write (GRUB_VGA_GR_GR6_GRAPHICS_MODE, GRUB_VGA_GR_GR6); + + grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_NORMAL, GRUB_VGA_SR_MEMORY_MODE); + + /* Disable CR0-7 write protection. */ + grub_vga_cr_write (0, GRUB_VGA_CR_VSYNC_END); + + grub_vga_cr_write (width / GRUB_VGA_CR_WIDTH_DIVISOR - 1, + GRUB_VGA_CR_WIDTH); + grub_vga_cr_write ((height - 1) & 0xff, GRUB_VGA_CR_HEIGHT); + overflow_reg |= (((height - 1) >> GRUB_VGA_CR_OVERFLOW_HEIGHT1_SHIFT) & + GRUB_VGA_CR_OVERFLOW_HEIGHT1_MASK) + | (((height - 1) >> GRUB_VGA_CR_OVERFLOW_HEIGHT2_SHIFT) & + GRUB_VGA_CR_OVERFLOW_HEIGHT2_MASK); + + grub_vga_cr_write (pitch_reg & 0xff, GRUB_VGA_CR_PITCH); + + grub_vga_cr_write (line_compare & 0xff, GRUB_VGA_CR_LINE_COMPARE); + overflow_reg |= (line_compare >> GRUB_VGA_CR_OVERFLOW_LINE_COMPARE_SHIFT) + & GRUB_VGA_CR_OVERFLOW_LINE_COMPARE_MASK; + + grub_vga_cr_write (overflow_reg, GRUB_VGA_CR_OVERFLOW); + + grub_vga_cr_write ((pitch_reg >> CIRRUS_CR_EXTENDED_DISPLAY_PITCH_SHIFT) + & CIRRUS_CR_EXTENDED_DISPLAY_PITCH_MASK, + CIRRUS_CR_EXTENDED_DISPLAY); + + grub_vga_cr_write ((line_compare >> GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_SHIFT) + & GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_MASK, GRUB_VGA_CR_CELL_HEIGHT); + + grub_vga_cr_write (GRUB_VGA_CR_MODE_TIMING_ENABLE + | GRUB_VGA_CR_MODE_BYTE_MODE + | GRUB_VGA_CR_MODE_NO_HERCULES | GRUB_VGA_CR_MODE_NO_CGA, + GRUB_VGA_CR_MODE); + + doublebuf_pageflipping_set_page (0); + + sr_ext = CIRRUS_SR_EXTENDED_MODE_LFB_ENABLE + | CIRRUS_SR_EXTENDED_MODE_ENABLE_EXT; + switch (depth) + { + /* FIXME: support 8-bit grayscale and 8-bit RGB. */ + case 32: + hidden_dac = CIRRUS_HIDDEN_DAC_888COLOR; + sr_ext |= CIRRUS_SR_EXTENDED_MODE_32BPP; + break; + case 24: + hidden_dac = CIRRUS_HIDDEN_DAC_888COLOR; + sr_ext |= CIRRUS_SR_EXTENDED_MODE_24BPP; + break; + case 16: + hidden_dac = CIRRUS_HIDDEN_DAC_16BPP; + sr_ext |= CIRRUS_SR_EXTENDED_MODE_16BPP; + break; + case 15: + hidden_dac = CIRRUS_HIDDEN_DAC_15BPP; + sr_ext |= CIRRUS_SR_EXTENDED_MODE_16BPP; + break; + case 8: + hidden_dac = CIRRUS_HIDDEN_DAC_8BPP; + sr_ext |= CIRRUS_SR_EXTENDED_MODE_8BPP; + break; + } + grub_vga_sr_write (sr_ext, CIRRUS_SR_EXTENDED_MODE); + write_hidden_dac (hidden_dac); + } + + /* Fill mode info details. */ + framebuffer.mode_info.width = width; + framebuffer.mode_info.height = height; + framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB; + framebuffer.mode_info.bpp = depth; + framebuffer.mode_info.bytes_per_pixel = bytes_per_pixel; + framebuffer.mode_info.pitch = pitch; + framebuffer.mode_info.number_of_colors = 256; + framebuffer.mode_info.reserved_mask_size = 0; + framebuffer.mode_info.reserved_field_pos = 0; + + switch (depth) + { + case 8: + framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; + break; + case 16: + framebuffer.mode_info.red_mask_size = 5; + framebuffer.mode_info.red_field_pos = 11; + framebuffer.mode_info.green_mask_size = 6; + framebuffer.mode_info.green_field_pos = 5; + framebuffer.mode_info.blue_mask_size = 5; + framebuffer.mode_info.blue_field_pos = 0; + break; + + case 15: + framebuffer.mode_info.red_mask_size = 5; + framebuffer.mode_info.red_field_pos = 10; + framebuffer.mode_info.green_mask_size = 5; + framebuffer.mode_info.green_field_pos = 5; + framebuffer.mode_info.blue_mask_size = 5; + framebuffer.mode_info.blue_field_pos = 0; + break; + + case 32: + framebuffer.mode_info.reserved_mask_size = 8; + framebuffer.mode_info.reserved_field_pos = 24; + + case 24: + framebuffer.mode_info.red_mask_size = 8; + framebuffer.mode_info.red_field_pos = 16; + framebuffer.mode_info.green_mask_size = 8; + framebuffer.mode_info.green_field_pos = 8; + framebuffer.mode_info.blue_mask_size = 8; + framebuffer.mode_info.blue_field_pos = 0; + break; + } + + framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info); + + if (CIRRUS_APERTURE_SIZE >= 2 * framebuffer.page_size) + err = grub_video_fb_setup (mode_type, mode_mask, + &framebuffer.mode_info, + framebuffer.ptr, + doublebuf_pageflipping_set_page, + framebuffer.ptr + framebuffer.page_size); + else + err = grub_video_fb_setup (mode_type, mode_mask, + &framebuffer.mode_info, + framebuffer.ptr, 0, 0); + + + /* Copy default palette to initialize emulated palette. */ + err = grub_video_cirrus_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, + grub_video_fbstd_colors); + return err; +} + +static struct grub_video_adapter grub_video_cirrus_adapter = + { + .name = "Cirrus CLGD 5446 PCI Video Driver", + .id = GRUB_VIDEO_DRIVER_CIRRUS, + + .prio = GRUB_VIDEO_ADAPTER_PRIO_NATIVE, + + .init = grub_video_cirrus_video_init, + .fini = grub_video_cirrus_video_fini, + .setup = grub_video_cirrus_setup, + .get_info = grub_video_fb_get_info, + .get_info_and_fini = grub_video_fb_get_info_and_fini, + .set_palette = grub_video_cirrus_set_palette, + .get_palette = grub_video_fb_get_palette, + .set_viewport = grub_video_fb_set_viewport, + .get_viewport = grub_video_fb_get_viewport, + .map_color = grub_video_fb_map_color, + .map_rgb = grub_video_fb_map_rgb, + .map_rgba = grub_video_fb_map_rgba, + .unmap_color = grub_video_fb_unmap_color, + .fill_rect = grub_video_fb_fill_rect, + .blit_bitmap = grub_video_fb_blit_bitmap, + .blit_render_target = grub_video_fb_blit_render_target, + .scroll = grub_video_fb_scroll, + .swap_buffers = grub_video_fb_swap_buffers, + .create_render_target = grub_video_fb_create_render_target, + .delete_render_target = grub_video_fb_delete_render_target, + .set_active_render_target = grub_video_fb_set_active_render_target, + .get_active_render_target = grub_video_fb_get_active_render_target, + + .next = 0 + }; + +GRUB_MOD_INIT(video_cirrus) +{ + grub_video_register (&grub_video_cirrus_adapter); +} + +GRUB_MOD_FINI(video_cirrus) +{ + grub_video_unregister (&grub_video_cirrus_adapter); +} diff --git a/video/efi_gop.c b/video/efi_gop.c index 86a2881f8..4e79b8521 100644 --- a/video/efi_gop.c +++ b/video/efi_gop.c @@ -355,6 +355,8 @@ static struct grub_video_adapter grub_video_gop_adapter = .name = "EFI GOP driver", .id = GRUB_VIDEO_DRIVER_EFI_GOP, + .prio = GRUB_VIDEO_ADAPTER_PRIO_FIRMWARE, + .init = grub_video_gop_init, .fini = grub_video_gop_fini, .setup = grub_video_gop_setup, diff --git a/video/efi_uga.c b/video/efi_uga.c index eb4e6b42e..6352d4342 100644 --- a/video/efi_uga.c +++ b/video/efi_uga.c @@ -302,6 +302,8 @@ static struct grub_video_adapter grub_video_uga_adapter = .name = "EFI UGA driver", .id = GRUB_VIDEO_DRIVER_EFI_UGA, + .prio = GRUB_VIDEO_ADAPTER_PRIO_FIRMWARE_DIRTY, + .init = grub_video_uga_init, .fini = grub_video_uga_fini, .setup = grub_video_uga_setup, diff --git a/video/emu/sdl.c b/video/emu/sdl.c index d261db6b0..d66b8b0c0 100644 --- a/video/emu/sdl.c +++ b/video/emu/sdl.c @@ -200,6 +200,9 @@ grub_video_sdl_set_active_render_target (struct grub_video_render_target *target static struct grub_video_adapter grub_video_sdl_adapter = { .name = "SDL Video Driver", + .id = GRUB_VIDEO_DRIVER_SDL, + + .prio = GRUB_VIDEO_ADAPTER_PRIO_FIRMWARE, .init = grub_video_sdl_init, .fini = grub_video_sdl_fini, diff --git a/video/fb/video_fb.c b/video/fb/video_fb.c index 9c5577bb9..69626be5c 100644 --- a/video/fb/video_fb.c +++ b/video/fb/video_fb.c @@ -25,9 +25,20 @@ #include #include -static struct grub_video_fbrender_target *render_target; -struct grub_video_palette_data *palette; -static unsigned int palette_size; +static struct +{ + struct grub_video_fbrender_target *render_target; + struct grub_video_fbrender_target *front_target; + struct grub_video_fbrender_target *back_target; + struct grub_video_palette_data *palette; + unsigned int palette_size; + /* For page flipping strategy. */ + int displayed_page; /* The page # that is the front buffer. */ + int render_page; /* The page # that is the back buffer. */ + grub_video_fb_set_page_t set_page; + char *offscreen_buffer; + grub_video_fb_doublebuf_update_screen_t update_screen; +} framebuffer; /* Specify "standard" VGA palette, some video cards may need this and this will also be used when using RGB modes. */ @@ -56,10 +67,13 @@ struct grub_video_palette_data grub_video_fbstd_colors[GRUB_VIDEO_FBSTD_NUMCOLOR grub_err_t grub_video_fb_init (void) { - grub_free (palette); - render_target = 0; - palette = 0; - palette_size = 0; + grub_free (framebuffer.palette); + framebuffer.render_target = 0; + framebuffer.front_target = 0; + framebuffer.back_target = 0; + framebuffer.palette = 0; + framebuffer.palette_size = 0; + framebuffer.set_page = 0; return GRUB_ERR_NONE; } @@ -68,10 +82,15 @@ grub_video_fb_fini (void) { /* TODO: destroy render targets. */ - grub_free (palette); - render_target = 0; - palette = 0; - palette_size = 0; + grub_free (framebuffer.offscreen_buffer); + grub_free (framebuffer.palette); + framebuffer.render_target = 0; + framebuffer.front_target = 0; + framebuffer.back_target = 0; + framebuffer.palette = 0; + framebuffer.palette_size = 0; + framebuffer.set_page = 0; + framebuffer.offscreen_buffer = 0; return GRUB_ERR_NONE; } @@ -79,7 +98,7 @@ grub_err_t grub_video_fb_get_info (struct grub_video_mode_info *mode_info) { /* Copy mode info from active render target. */ - grub_memcpy (mode_info, &render_target->mode_info, + grub_memcpy (mode_info, &framebuffer.render_target->mode_info, sizeof (struct grub_video_mode_info)); return GRUB_ERR_NONE; @@ -92,8 +111,8 @@ grub_video_fb_get_palette (unsigned int start, unsigned int count, unsigned int i; /* Assume that we know everything from index color palette. */ - for (i = 0; (i < count) && ((i + start) < palette_size); i++) - palette_data[i] = palette[start + i]; + for (i = 0; (i < count) && ((i + start) < framebuffer.palette_size); i++) + palette_data[i] = framebuffer.palette[start + i]; return GRUB_ERR_NONE; } @@ -103,18 +122,20 @@ grub_video_fb_set_palette (unsigned int start, unsigned int count, struct grub_video_palette_data *palette_data) { unsigned i; - if (start + count > palette_size) + if (start + count > framebuffer.palette_size) { - palette_size = start + count; - palette = grub_realloc (palette, sizeof (palette[0]) * palette_size); - if (!palette) + framebuffer.palette_size = start + count; + framebuffer.palette = grub_realloc (framebuffer.palette, + sizeof (framebuffer.palette[0]) + * framebuffer.palette_size); + if (!framebuffer.palette) { grub_video_fb_fini (); return grub_errno; } } - for (i = 0; (i < count) && ((i + start) < palette_size); i++) - palette[start + i] = palette_data[i]; + for (i = 0; (i < count) && ((i + start) < framebuffer.palette_size); i++) + framebuffer.palette[start + i] = palette_data[i]; return GRUB_ERR_NONE; } @@ -124,28 +145,28 @@ grub_video_fb_set_viewport (unsigned int x, unsigned int y, { /* Make sure viewport is withing screen dimensions. If viewport was set to be out of the region, mark its size as zero. */ - if (x > render_target->mode_info.width) + if (x > framebuffer.render_target->mode_info.width) { x = 0; width = 0; } - if (y > render_target->mode_info.height) + if (y > framebuffer.render_target->mode_info.height) { y = 0; height = 0; } - if (x + width > render_target->mode_info.width) - width = render_target->mode_info.width - x; + if (x + width > framebuffer.render_target->mode_info.width) + width = framebuffer.render_target->mode_info.width - x; - if (y + height > render_target->mode_info.height) - height = render_target->mode_info.height - y; + if (y + height > framebuffer.render_target->mode_info.height) + height = framebuffer.render_target->mode_info.height - y; - render_target->viewport.x = x; - render_target->viewport.y = y; - render_target->viewport.width = width; - render_target->viewport.height = height; + framebuffer.render_target->viewport.x = x; + framebuffer.render_target->viewport.y = y; + framebuffer.render_target->viewport.width = width; + framebuffer.render_target->viewport.height = height; return GRUB_ERR_NONE; } @@ -154,10 +175,10 @@ grub_err_t grub_video_fb_get_viewport (unsigned int *x, unsigned int *y, unsigned int *width, unsigned int *height) { - if (x) *x = render_target->viewport.x; - if (y) *y = render_target->viewport.y; - if (width) *width = render_target->viewport.width; - if (height) *height = render_target->viewport.height; + if (x) *x = framebuffer.render_target->viewport.x; + if (y) *y = framebuffer.render_target->viewport.y; + if (width) *width = framebuffer.render_target->viewport.width; + if (height) *height = framebuffer.render_target->viewport.height; return GRUB_ERR_NONE; } @@ -168,18 +189,18 @@ grub_video_fb_map_color (grub_uint32_t color_name) { /* TODO: implement color theme mapping code. */ - if (color_name < palette_size) + if (color_name < framebuffer.palette_size) { - if ((render_target->mode_info.mode_type + if ((framebuffer.render_target->mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0) return color_name; else { grub_video_color_t color; - color = grub_video_fb_map_rgb (palette[color_name].r, - palette[color_name].g, - palette[color_name].b); + color = grub_video_fb_map_rgb (framebuffer.palette[color_name].r, + framebuffer.palette[color_name].g, + framebuffer.palette[color_name].b); return color; } @@ -193,7 +214,7 @@ grub_video_color_t grub_video_fb_map_rgb (grub_uint8_t red, grub_uint8_t green, grub_uint8_t blue) { - if ((render_target->mode_info.mode_type + if ((framebuffer.render_target->mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0) { int minindex = 0; @@ -203,13 +224,13 @@ grub_video_fb_map_rgb (grub_uint8_t red, grub_uint8_t green, unsigned i; /* Find best matching color. */ - for (i = 0; i < palette_size; i++) + for (i = 0; i < framebuffer.palette_size; i++) { - val = palette[i].r - red; + val = framebuffer.palette[i].r - red; tmp = val * val; - val = palette[i].g - green; + val = framebuffer.palette[i].g - green; tmp += val * val; - val = palette[i].b - blue; + val = framebuffer.palette[i].b - blue; tmp += val * val; if (i == 0) @@ -226,12 +247,12 @@ grub_video_fb_map_rgb (grub_uint8_t red, grub_uint8_t green, return minindex; } - else if ((render_target->mode_info.mode_type + else if ((framebuffer.render_target->mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) != 0) { - if (red == render_target->mode_info.fg_red - && green == render_target->mode_info.fg_green - && blue == render_target->mode_info.fg_blue) + if (red == framebuffer.render_target->mode_info.fg_red + && green == framebuffer.render_target->mode_info.fg_green + && blue == framebuffer.render_target->mode_info.fg_blue) return 1; else return 0; @@ -241,15 +262,15 @@ grub_video_fb_map_rgb (grub_uint8_t red, grub_uint8_t green, grub_uint32_t value; grub_uint8_t alpha = 255; /* Opaque color. */ - red >>= 8 - render_target->mode_info.red_mask_size; - green >>= 8 - render_target->mode_info.green_mask_size; - blue >>= 8 - render_target->mode_info.blue_mask_size; - alpha >>= 8 - render_target->mode_info.reserved_mask_size; + red >>= 8 - framebuffer.render_target->mode_info.red_mask_size; + green >>= 8 - framebuffer.render_target->mode_info.green_mask_size; + blue >>= 8 - framebuffer.render_target->mode_info.blue_mask_size; + alpha >>= 8 - framebuffer.render_target->mode_info.reserved_mask_size; - value = red << render_target->mode_info.red_field_pos; - value |= green << render_target->mode_info.green_field_pos; - value |= blue << render_target->mode_info.blue_field_pos; - value |= alpha << render_target->mode_info.reserved_field_pos; + value = red << framebuffer.render_target->mode_info.red_field_pos; + value |= green << framebuffer.render_target->mode_info.green_field_pos; + value |= blue << framebuffer.render_target->mode_info.blue_field_pos; + value |= alpha << framebuffer.render_target->mode_info.reserved_field_pos; return value; } @@ -261,18 +282,18 @@ grub_video_color_t grub_video_fb_map_rgba (grub_uint8_t red, grub_uint8_t green, grub_uint8_t blue, grub_uint8_t alpha) { - if ((render_target->mode_info.mode_type + if ((framebuffer.render_target->mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0) /* No alpha available in index color modes, just use same value as in only RGB modes. */ return grub_video_fb_map_rgb (red, green, blue); - else if ((render_target->mode_info.mode_type + else if ((framebuffer.render_target->mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) != 0) { - if (red == render_target->mode_info.fg_red - && green == render_target->mode_info.fg_green - && blue == render_target->mode_info.fg_blue - && alpha == render_target->mode_info.fg_alpha) + if (red == framebuffer.render_target->mode_info.fg_red + && green == framebuffer.render_target->mode_info.fg_green + && blue == framebuffer.render_target->mode_info.fg_blue + && alpha == framebuffer.render_target->mode_info.fg_alpha) return 1; else return 0; @@ -281,15 +302,15 @@ grub_video_fb_map_rgba (grub_uint8_t red, grub_uint8_t green, { grub_uint32_t value; - red >>= 8 - render_target->mode_info.red_mask_size; - green >>= 8 - render_target->mode_info.green_mask_size; - blue >>= 8 - render_target->mode_info.blue_mask_size; - alpha >>= 8 - render_target->mode_info.reserved_mask_size; + red >>= 8 - framebuffer.render_target->mode_info.red_mask_size; + green >>= 8 - framebuffer.render_target->mode_info.green_mask_size; + blue >>= 8 - framebuffer.render_target->mode_info.blue_mask_size; + alpha >>= 8 - framebuffer.render_target->mode_info.reserved_mask_size; - value = red << render_target->mode_info.red_field_pos; - value |= green << render_target->mode_info.green_field_pos; - value |= blue << render_target->mode_info.blue_field_pos; - value |= alpha << render_target->mode_info.reserved_field_pos; + value = red << framebuffer.render_target->mode_info.red_field_pos; + value |= green << framebuffer.render_target->mode_info.green_field_pos; + value |= blue << framebuffer.render_target->mode_info.blue_field_pos; + value |= alpha << framebuffer.render_target->mode_info.reserved_field_pos; return value; } @@ -303,8 +324,8 @@ grub_video_fb_unmap_color (grub_video_color_t color, { struct grub_video_fbblit_info target_info; - target_info.mode_info = &render_target->mode_info; - target_info.data = render_target->data; + target_info.mode_info = &framebuffer.render_target->mode_info; + target_info.data = framebuffer.render_target->data; grub_video_fb_unmap_color_int (&target_info, color, red, green, blue, alpha); @@ -334,10 +355,10 @@ grub_video_fb_unmap_color_int (struct grub_video_fbblit_info * source, return; } - *red = palette[color].r; - *green = palette[color].g; - *blue = palette[color].b; - *alpha = palette[color].a; + *red = framebuffer.palette[color].r; + *green = framebuffer.palette[color].g; + *blue = framebuffer.palette[color].b; + *alpha = framebuffer.palette[color].a; return; } else if ((mode_info->mode_type @@ -406,9 +427,9 @@ grub_video_fb_fill_rect (grub_video_color_t color, int x, int y, struct grub_video_fbblit_info target; /* Make sure there is something to do. */ - if ((x >= (int)render_target->viewport.width) || (x + (int)width < 0)) + if ((x >= (int)framebuffer.render_target->viewport.width) || (x + (int)width < 0)) return GRUB_ERR_NONE; - if ((y >= (int)render_target->viewport.height) || (y + (int)height < 0)) + if ((y >= (int)framebuffer.render_target->viewport.height) || (y + (int)height < 0)) return GRUB_ERR_NONE; /* Do not allow drawing out of viewport. */ @@ -423,18 +444,18 @@ grub_video_fb_fill_rect (grub_video_color_t color, int x, int y, y = 0; } - if ((x + width) > render_target->viewport.width) - width = render_target->viewport.width - x; - if ((y + height) > render_target->viewport.height) - height = render_target->viewport.height - y; + if ((x + width) > framebuffer.render_target->viewport.width) + width = framebuffer.render_target->viewport.width - x; + if ((y + height) > framebuffer.render_target->viewport.height) + height = framebuffer.render_target->viewport.height - y; /* Add viewport offset. */ - x += render_target->viewport.x; - y += render_target->viewport.y; + x += framebuffer.render_target->viewport.x; + y += framebuffer.render_target->viewport.y; /* Use fbblit_info to encapsulate rendering. */ - target.mode_info = &render_target->mode_info; - target.data = render_target->data; + target.mode_info = &framebuffer.render_target->mode_info; + target.data = framebuffer.render_target->data; /* Try to figure out more optimized version. Note that color is already mapped to target format so we can make assumptions based on that. */ @@ -761,9 +782,9 @@ grub_video_fb_blit_bitmap (struct grub_video_bitmap *bitmap, /* Make sure there is something to do. */ if ((width == 0) || (height == 0)) return GRUB_ERR_NONE; - if ((x >= (int)render_target->viewport.width) || (x + (int)width < 0)) + if ((x >= (int)framebuffer.render_target->viewport.width) || (x + (int)width < 0)) return GRUB_ERR_NONE; - if ((y >= (int)render_target->viewport.height) || (y + (int)height < 0)) + if ((y >= (int)framebuffer.render_target->viewport.height) || (y + (int)height < 0)) return GRUB_ERR_NONE; if ((x + (int)bitmap->mode_info.width) < 0) return GRUB_ERR_NONE; @@ -806,10 +827,10 @@ grub_video_fb_blit_bitmap (struct grub_video_bitmap *bitmap, } /* Do not allow drawing out of viewport. */ - if ((x + width) > render_target->viewport.width) - width = render_target->viewport.width - x; - if ((y + height) > render_target->viewport.height) - height = render_target->viewport.height - y; + if ((x + width) > framebuffer.render_target->viewport.width) + width = framebuffer.render_target->viewport.width - x; + if ((y + height) > framebuffer.render_target->viewport.height) + height = framebuffer.render_target->viewport.height - y; if ((offset_x + width) > bitmap->mode_info.width) width = bitmap->mode_info.width - offset_x; @@ -824,14 +845,14 @@ grub_video_fb_blit_bitmap (struct grub_video_bitmap *bitmap, height = bitmap->mode_info.height; /* Add viewport offset. */ - x += render_target->viewport.x; - y += render_target->viewport.y; + x += framebuffer.render_target->viewport.x; + y += framebuffer.render_target->viewport.y; /* Use fbblit_info to encapsulate rendering. */ source.mode_info = &bitmap->mode_info; source.data = bitmap->data; - target.mode_info = &render_target->mode_info; - target.data = render_target->data; + target.mode_info = &framebuffer.render_target->mode_info; + target.data = framebuffer.render_target->data; /* Do actual blitting. */ common_blitter (&target, &source, oper, x, y, width, height, @@ -852,9 +873,9 @@ grub_video_fb_blit_render_target (struct grub_video_fbrender_target *source, /* Make sure there is something to do. */ if ((width == 0) || (height == 0)) return GRUB_ERR_NONE; - if ((x >= (int)render_target->viewport.width) || (x + (int)width < 0)) + if ((x >= (int)framebuffer.render_target->viewport.width) || (x + (int)width < 0)) return GRUB_ERR_NONE; - if ((y >= (int)render_target->viewport.height) || (y + (int)height < 0)) + if ((y >= (int)framebuffer.render_target->viewport.height) || (y + (int)height < 0)) return GRUB_ERR_NONE; if ((x + (int)source->mode_info.width) < 0) return GRUB_ERR_NONE; @@ -897,10 +918,10 @@ grub_video_fb_blit_render_target (struct grub_video_fbrender_target *source, } /* Do not allow drawing out of viewport. */ - if ((x + width) > render_target->viewport.width) - width = render_target->viewport.width - x; - if ((y + height) > render_target->viewport.height) - height = render_target->viewport.height - y; + if ((x + width) > framebuffer.render_target->viewport.width) + width = framebuffer.render_target->viewport.width - x; + if ((y + height) > framebuffer.render_target->viewport.height) + height = framebuffer.render_target->viewport.height - y; if ((offset_x + width) > source->mode_info.width) width = source->mode_info.width - offset_x; @@ -915,14 +936,14 @@ grub_video_fb_blit_render_target (struct grub_video_fbrender_target *source, height = source->mode_info.height; /* Add viewport offset. */ - x += render_target->viewport.x; - y += render_target->viewport.y; + x += framebuffer.render_target->viewport.x; + y += framebuffer.render_target->viewport.y; /* Use fbblit_info to encapsulate rendering. */ source_info.mode_info = &source->mode_info; source_info.data = source->data; - target_info.mode_info = &render_target->mode_info; - target_info.data = render_target->data; + target_info.mode_info = &framebuffer.render_target->mode_info; + target_info.data = framebuffer.render_target->data; /* Do actual blitting. */ common_blitter (&target_info, &source_info, oper, x, y, width, height, @@ -945,42 +966,42 @@ grub_video_fb_scroll (grub_video_color_t color, int dx, int dy) if ((dx == 0) && (dy == 0)) return GRUB_ERR_NONE; - width = render_target->viewport.width - grub_abs (dx); - height = render_target->viewport.height - grub_abs (dy); + width = framebuffer.render_target->viewport.width - grub_abs (dx); + height = framebuffer.render_target->viewport.height - grub_abs (dy); if (dx < 0) { - src_x = render_target->viewport.x - dx; - dst_x = render_target->viewport.x; + src_x = framebuffer.render_target->viewport.x - dx; + dst_x = framebuffer.render_target->viewport.x; } else { - src_x = render_target->viewport.x; - dst_x = render_target->viewport.x + dx; + src_x = framebuffer.render_target->viewport.x; + dst_x = framebuffer.render_target->viewport.x + dx; } if (dy < 0) { - src_y = render_target->viewport.y - dy; - dst_y = render_target->viewport.y; + src_y = framebuffer.render_target->viewport.y - dy; + dst_y = framebuffer.render_target->viewport.y; } else { - src_y = render_target->viewport.y; - dst_y = render_target->viewport.y + dy; + src_y = framebuffer.render_target->viewport.y; + dst_y = framebuffer.render_target->viewport.y + dy; } /* 2. Check if there is need to copy data. */ - if ((grub_abs (dx) < render_target->viewport.width) - && (grub_abs (dy) < render_target->viewport.height)) + if ((grub_abs (dx) < framebuffer.render_target->viewport.width) + && (grub_abs (dy) < framebuffer.render_target->viewport.height)) { /* 3. Move data in render target. */ struct grub_video_fbblit_info target; int i, j; int linedelta, linelen; - target.mode_info = &render_target->mode_info; - target.data = render_target->data; + target.mode_info = &framebuffer.render_target->mode_info; + target.data = framebuffer.render_target->data; linedelta = target.mode_info->pitch - width * target.mode_info->bytes_per_pixel; @@ -1063,27 +1084,27 @@ grub_video_fb_scroll (grub_video_color_t color, int dx, int dy) /* 4a. Fill top & bottom parts. */ if (dy > 0) - grub_video_fb_fill_rect (color, 0, 0, render_target->viewport.width, dy); + grub_video_fb_fill_rect (color, 0, 0, framebuffer.render_target->viewport.width, dy); else if (dy < 0) { - if (render_target->viewport.height < grub_abs (dy)) - dy = -render_target->viewport.height; + if (framebuffer.render_target->viewport.height < grub_abs (dy)) + dy = -framebuffer.render_target->viewport.height; - grub_video_fb_fill_rect (color, 0, render_target->viewport.height + dy, - render_target->viewport.width, -dy); + grub_video_fb_fill_rect (color, 0, framebuffer.render_target->viewport.height + dy, + framebuffer.render_target->viewport.width, -dy); } /* 4b. Fill left & right parts. */ if (dx > 0) grub_video_fb_fill_rect (color, 0, 0, - dx, render_target->viewport.height); + dx, framebuffer.render_target->viewport.height); else if (dx < 0) { - if (render_target->viewport.width < grub_abs (dx)) - dx = -render_target->viewport.width; + if (framebuffer.render_target->viewport.width < grub_abs (dx)) + dx = -framebuffer.render_target->viewport.width; - grub_video_fb_fill_rect (color, render_target->viewport.width + dx, 0, - -dx, render_target->viewport.height); + grub_video_fb_fill_rect (color, framebuffer.render_target->viewport.width + dx, 0, + -dx, framebuffer.render_target->viewport.height); } return GRUB_ERR_NONE; @@ -1130,7 +1151,7 @@ grub_video_fb_create_render_target (struct grub_video_fbrender_target **result, target->mode_info.bpp = 32; target->mode_info.bytes_per_pixel = 4; target->mode_info.pitch = target->mode_info.bytes_per_pixel * width; - target->mode_info.number_of_colors = palette_size; /* Emulated palette. */ + target->mode_info.number_of_colors = framebuffer.palette_size; /* Emulated palette. */ target->mode_info.red_mask_size = 8; target->mode_info.red_field_pos = 0; target->mode_info.green_mask_size = 8; @@ -1221,11 +1242,15 @@ grub_video_fb_delete_render_target (struct grub_video_fbrender_target *target) grub_err_t grub_video_fb_set_active_render_target (struct grub_video_fbrender_target *target) { + if (target == (struct grub_video_fbrender_target *) + GRUB_VIDEO_RENDER_TARGET_DISPLAY) + target = framebuffer.back_target; + if (! target->data) return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid render target given"); - render_target = target; + framebuffer.render_target = target; return GRUB_ERR_NONE; } @@ -1233,7 +1258,10 @@ grub_video_fb_set_active_render_target (struct grub_video_fbrender_target *targe grub_err_t grub_video_fb_get_active_render_target (struct grub_video_fbrender_target **target) { - *target = render_target; + *target = framebuffer.render_target; + + if (*target == framebuffer.back_target) + *target = (struct grub_video_fbrender_target *) GRUB_VIDEO_RENDER_TARGET_DISPLAY; return GRUB_ERR_NONE; } @@ -1247,24 +1275,22 @@ doublebuf_blit_update_screen (struct grub_video_fbrender_target *front, return GRUB_ERR_NONE; } -grub_err_t +static grub_err_t grub_video_fb_doublebuf_blit_init (struct grub_video_fbrender_target **front, struct grub_video_fbrender_target **back, - grub_video_fb_doublebuf_update_screen_t *update_screen, struct grub_video_mode_info mode_info, void *framebuf) { grub_err_t err; int page_size = mode_info.pitch * mode_info.height; - void *offscreen_buffer; err = grub_video_fb_create_render_target_from_pointer (front, &mode_info, framebuf); if (err) return err; - offscreen_buffer = grub_malloc (page_size); - if (! offscreen_buffer) + framebuffer.offscreen_buffer = grub_malloc (page_size); + if (! framebuffer.offscreen_buffer) { grub_video_fb_delete_render_target (*front); *front = 0; @@ -1272,18 +1298,216 @@ grub_video_fb_doublebuf_blit_init (struct grub_video_fbrender_target **front, } err = grub_video_fb_create_render_target_from_pointer (back, &mode_info, - offscreen_buffer); + framebuffer.offscreen_buffer); if (err) { grub_video_fb_delete_render_target (*front); - grub_free (offscreen_buffer); + grub_free (framebuffer.offscreen_buffer); + framebuffer.offscreen_buffer = 0; *front = 0; return grub_errno; } (*back)->is_allocated = 1; - *update_screen = doublebuf_blit_update_screen; + framebuffer.update_screen = doublebuf_blit_update_screen; + + return GRUB_ERR_NONE; +} + +static grub_err_t +doublebuf_pageflipping_update_screen (struct grub_video_fbrender_target *front + __attribute__ ((unused)), + struct grub_video_fbrender_target *back + __attribute__ ((unused))) +{ + int new_displayed_page; + struct grub_video_fbrender_target *target; + grub_err_t err; + + /* Swap the page numbers in the framebuffer struct. */ + new_displayed_page = framebuffer.render_page; + framebuffer.render_page = framebuffer.displayed_page; + framebuffer.displayed_page = new_displayed_page; + + err = framebuffer.set_page (framebuffer.displayed_page); + if (err) + { + /* Restore previous state. */ + framebuffer.render_page = framebuffer.displayed_page; + framebuffer.displayed_page = new_displayed_page; + return err; + } + + target = framebuffer.back_target; + framebuffer.back_target = framebuffer.front_target; + framebuffer.front_target = target; + + if (framebuffer.front_target->mode_info.mode_type + & GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP) + grub_memcpy (framebuffer.back_target->data, framebuffer.front_target->data, + framebuffer.back_target->mode_info.pitch + * framebuffer.back_target->mode_info.height); + + err = grub_video_fb_get_active_render_target (&target); + if (err) + return err; + + if (framebuffer.render_target == framebuffer.back_target) + framebuffer.render_target = framebuffer.front_target; + else if (framebuffer.render_target == framebuffer.front_target) + framebuffer.render_target = framebuffer.back_target; + + return err; +} + +static grub_err_t +doublebuf_pageflipping_init (struct grub_video_mode_info *mode_info, + volatile void *page0_ptr, + grub_video_fb_set_page_t set_page_in, + volatile void *page1_ptr) +{ + grub_err_t err; + + framebuffer.displayed_page = 0; + framebuffer.render_page = 1; + + framebuffer.update_screen = doublebuf_pageflipping_update_screen; + + err = grub_video_fb_create_render_target_from_pointer (&framebuffer.front_target, + mode_info, + (void *) page0_ptr); + if (err) + return err; + + err = grub_video_fb_create_render_target_from_pointer (&framebuffer.back_target, + mode_info, + (void *) page1_ptr); + if (err) + { + grub_video_fb_delete_render_target (framebuffer.front_target); + return err; + } + + /* Set the framebuffer memory data pointer and display the right page. */ + err = set_page_in (framebuffer.displayed_page); + if (err) + { + grub_video_fb_delete_render_target (framebuffer.front_target); + grub_video_fb_delete_render_target (framebuffer.back_target); + return err; + } + framebuffer.set_page = set_page_in; + + return GRUB_ERR_NONE; +} + +/* Select the best double buffering mode available. */ +grub_err_t +grub_video_fb_setup (unsigned int mode_type, unsigned int mode_mask, + struct grub_video_mode_info *mode_info, + volatile void *page0_ptr, + grub_video_fb_set_page_t set_page_in, + volatile void *page1_ptr) +{ + grub_err_t err; + int updating_swap_needed; + + updating_swap_needed + = grub_video_check_mode_flag (mode_type, mode_mask, + GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP, 0); + + /* Do double buffering only if it's either requested or efficient. */ + if (set_page_in && grub_video_check_mode_flag (mode_type, mode_mask, + GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED, + !updating_swap_needed)) + { + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED; + if (updating_swap_needed) + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP; + + err = doublebuf_pageflipping_init (mode_info, page0_ptr, + set_page_in, + page1_ptr); + if (!err) + { + framebuffer.render_target = framebuffer.back_target; + return GRUB_ERR_NONE; + } + + mode_info->mode_type &= ~(GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED + | GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP); + + grub_errno = GRUB_ERR_NONE; + } + + if (grub_video_check_mode_flag (mode_type, mode_mask, + GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED, + 0)) + { + mode_info->mode_type |= (GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED + | GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP); + + err = grub_video_fb_doublebuf_blit_init (&framebuffer.front_target, + &framebuffer.back_target, + *mode_info, + (void *) page0_ptr); + + if (!err) + { + framebuffer.render_target = framebuffer.back_target; + return GRUB_ERR_NONE; + } + + mode_info->mode_type &= ~(GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED + | GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP); + + grub_errno = GRUB_ERR_NONE; + } + + /* Fall back to no double buffering. */ + err = grub_video_fb_create_render_target_from_pointer (&framebuffer.front_target, + mode_info, + (void *) page0_ptr); + + if (err) + return err; + + framebuffer.back_target = framebuffer.front_target; + framebuffer.update_screen = 0; + + mode_info->mode_type &= ~GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED; + + framebuffer.render_target = framebuffer.back_target; + + return GRUB_ERR_NONE; +} + + +grub_err_t +grub_video_fb_swap_buffers (void) +{ + grub_err_t err; + if (!framebuffer.update_screen) + return GRUB_ERR_NONE; + + err = framebuffer.update_screen (framebuffer.front_target, + framebuffer.back_target); + if (err) + return err; + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_video_fb_get_info_and_fini (struct grub_video_mode_info *mode_info, + void **framebuf) +{ + grub_memcpy (mode_info, &(framebuffer.front_target->mode_info), + sizeof (*mode_info)); + *framebuf = framebuffer.front_target->data; + + grub_video_fb_fini (); return GRUB_ERR_NONE; } diff --git a/video/i386/pc/vbe.c b/video/i386/pc/vbe.c index 72b8f1831..7581c48b1 100644 --- a/video/i386/pc/vbe.c +++ b/video/i386/pc/vbe.c @@ -40,25 +40,12 @@ static grub_uint32_t last_set_mode = 3; static struct { struct grub_video_mode_info mode_info; - struct grub_video_render_target *front_target; - struct grub_video_render_target *back_target; unsigned int bytes_per_scan_line; unsigned int bytes_per_pixel; grub_uint32_t active_vbe_mode; grub_uint8_t *ptr; int index_color_mode; - - char *offscreen_buffer; - - grub_size_t page_size; /* The size of a page in bytes. */ - - /* For page flipping strategy. */ - int displayed_page; /* The page # that is the front buffer. */ - int render_page; /* The page # that is the back buffer. */ - - /* Virtual functions. */ - grub_video_fb_doublebuf_update_screen_t update_screen; } framebuffer; static grub_uint32_t initial_vbe_mode; @@ -377,7 +364,6 @@ grub_video_vbe_fini (void) vbe_mode_list = NULL; err = grub_video_fb_fini (); - grub_free (framebuffer.offscreen_buffer); return err; } @@ -387,11 +373,11 @@ grub_video_vbe_fini (void) respectively. */ static grub_err_t -doublebuf_pageflipping_commit (void) +doublebuf_pageflipping_set_page (int page) { /* Tell the video adapter to display the new front page. */ int display_start_line - = framebuffer.mode_info.height * framebuffer.displayed_page; + = framebuffer.mode_info.height * page; grub_vbe_status_t vbe_err = grub_vbe_bios_set_display_start (0, display_start_line); @@ -402,164 +388,6 @@ doublebuf_pageflipping_commit (void) return 0; } -static grub_err_t -doublebuf_pageflipping_update_screen (struct grub_video_fbrender_target *front - __attribute__ ((unused)), - struct grub_video_fbrender_target *back - __attribute__ ((unused))) -{ - int new_displayed_page; - struct grub_video_fbrender_target *target; - grub_err_t err; - - /* Swap the page numbers in the framebuffer struct. */ - new_displayed_page = framebuffer.render_page; - framebuffer.render_page = framebuffer.displayed_page; - framebuffer.displayed_page = new_displayed_page; - - err = doublebuf_pageflipping_commit (); - if (err) - { - /* Restore previous state. */ - framebuffer.render_page = framebuffer.displayed_page; - framebuffer.displayed_page = new_displayed_page; - return err; - } - - if (framebuffer.mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP) - grub_memcpy (framebuffer.ptr + framebuffer.render_page - * framebuffer.page_size, framebuffer.ptr - + framebuffer.displayed_page * framebuffer.page_size, - framebuffer.page_size); - - target = framebuffer.back_target; - framebuffer.back_target = framebuffer.front_target; - framebuffer.front_target = target; - - err = grub_video_fb_get_active_render_target (&target); - if (err) - return err; - - if (target == framebuffer.back_target) - err = grub_video_fb_set_active_render_target (framebuffer.front_target); - else if (target == framebuffer.front_target) - err = grub_video_fb_set_active_render_target (framebuffer.back_target); - - return err; -} - -static grub_err_t -doublebuf_pageflipping_init (void) -{ - /* Get video RAM size in bytes. */ - grub_size_t vram_size = controller_info.total_memory << 16; - grub_err_t err; - - framebuffer.page_size = - framebuffer.mode_info.pitch * framebuffer.mode_info.height; - - if (2 * framebuffer.page_size > vram_size) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, - "Not enough video memory for double buffering."); - - framebuffer.displayed_page = 0; - framebuffer.render_page = 1; - - framebuffer.update_screen = doublebuf_pageflipping_update_screen; - - err = grub_video_fb_create_render_target_from_pointer (&framebuffer.front_target, &framebuffer.mode_info, framebuffer.ptr); - if (err) - return err; - - err = grub_video_fb_create_render_target_from_pointer (&framebuffer.back_target, &framebuffer.mode_info, framebuffer.ptr + framebuffer.page_size); - if (err) - { - grub_video_fb_delete_render_target (framebuffer.front_target); - return err; - } - - /* Set the framebuffer memory data pointer and display the right page. */ - err = doublebuf_pageflipping_commit (); - if (err) - { - grub_video_fb_delete_render_target (framebuffer.front_target); - grub_video_fb_delete_render_target (framebuffer.back_target); - return err; - } - - return GRUB_ERR_NONE; -} - -/* Select the best double buffering mode available. */ -static grub_err_t -double_buffering_init (unsigned int mode_type, unsigned int mode_mask) -{ - grub_err_t err; - int updating_swap_needed; - - updating_swap_needed - = grub_video_check_mode_flag (mode_type, mode_mask, - GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP, 0); - - /* Do double buffering only if it's either requested or efficient. */ - if (grub_video_check_mode_flag (mode_type, mode_mask, - GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED, - !updating_swap_needed)) - { - framebuffer.mode_info.mode_type |= GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED; - if (updating_swap_needed) - framebuffer.mode_info.mode_type |= GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP; - err = doublebuf_pageflipping_init (); - if (!err) - return GRUB_ERR_NONE; - - framebuffer.mode_info.mode_type - &= ~(GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED - | GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP); - - grub_errno = GRUB_ERR_NONE; - } - - if (grub_video_check_mode_flag (mode_type, mode_mask, - GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED, - 0)) - { - framebuffer.mode_info.mode_type - |= (GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED - | GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP); - - err = grub_video_fb_doublebuf_blit_init (&framebuffer.front_target, - &framebuffer.back_target, - &framebuffer.update_screen, - framebuffer.mode_info, - framebuffer.ptr); - - if (!err) - return GRUB_ERR_NONE; - - framebuffer.mode_info.mode_type - &= ~(GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED - | GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP); - - grub_errno = GRUB_ERR_NONE; - } - - /* Fall back to no double buffering. */ - err = grub_video_fb_create_render_target_from_pointer (&framebuffer.front_target, &framebuffer.mode_info, framebuffer.ptr); - - if (err) - return err; - - framebuffer.back_target = framebuffer.front_target; - framebuffer.update_screen = 0; - - framebuffer.mode_info.mode_type &= ~GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED; - - return GRUB_ERR_NONE; -} - - - static grub_err_t grub_video_vbe_setup (unsigned int width, unsigned int height, unsigned int mode_type, unsigned int mode_mask) @@ -684,15 +512,24 @@ grub_video_vbe_setup (unsigned int width, unsigned int height, framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info); - /* Set up double buffering and targets. */ - err = double_buffering_init (mode_type, mode_mask); - if (err) - return err; + { + /* Get video RAM size in bytes. */ + grub_size_t vram_size = controller_info.total_memory << 16; + grub_size_t page_size; /* The size of a page in bytes. */ - err = grub_video_fb_set_active_render_target (framebuffer.back_target); + page_size = framebuffer.mode_info.pitch * framebuffer.mode_info.height; - if (err) - return err; + if (vram_size >= 2 * page_size) + err = grub_video_fb_setup (mode_type, mode_mask, + &framebuffer.mode_info, + framebuffer.ptr, + doublebuf_pageflipping_set_page, + framebuffer.ptr + page_size); + else + err = grub_video_fb_setup (mode_type, mode_mask, + &framebuffer.mode_info, + framebuffer.ptr, 0, 0); + } /* Copy default palette to initialize emulated palette. */ err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, @@ -723,59 +560,13 @@ grub_video_vbe_set_palette (unsigned int start, unsigned int count, return grub_video_fb_set_palette (start, count, palette_data); } -static grub_err_t -grub_video_vbe_swap_buffers (void) -{ - grub_err_t err; - if (!framebuffer.update_screen) - return GRUB_ERR_NONE; - - err = framebuffer.update_screen (framebuffer.front_target, - framebuffer.back_target); - if (err) - return err; - - return GRUB_ERR_NONE; -} - -static grub_err_t -grub_video_vbe_set_active_render_target (struct grub_video_render_target *target) -{ - if (target == GRUB_VIDEO_RENDER_TARGET_DISPLAY) - target = framebuffer.back_target; - - return grub_video_fb_set_active_render_target (target); -} - -static grub_err_t -grub_video_vbe_get_active_render_target (struct grub_video_render_target **target) -{ - grub_err_t err; - err = grub_video_fb_get_active_render_target (target); - if (err) - return err; - - if (*target == framebuffer.back_target) - *target = GRUB_VIDEO_RENDER_TARGET_DISPLAY; - - return GRUB_ERR_NONE; -} - static grub_err_t grub_video_vbe_get_info_and_fini (struct grub_video_mode_info *mode_info, void **framebuf) { - grub_memcpy (mode_info, &(framebuffer.mode_info), sizeof (*mode_info)); - *framebuf = (char *) framebuffer.ptr - + framebuffer.displayed_page * framebuffer.page_size; - grub_free (vbe_mode_list); vbe_mode_list = NULL; - - grub_video_fb_fini (); - grub_free (framebuffer.offscreen_buffer); - - return GRUB_ERR_NONE; + return grub_video_fb_get_info_and_fini (mode_info, framebuf); } static struct grub_video_adapter grub_video_vbe_adapter = @@ -783,6 +574,8 @@ static struct grub_video_adapter grub_video_vbe_adapter = .name = "VESA BIOS Extension Video Driver", .id = GRUB_VIDEO_DRIVER_VBE, + .prio = GRUB_VIDEO_ADAPTER_PRIO_FIRMWARE, + .init = grub_video_vbe_init, .fini = grub_video_vbe_fini, .setup = grub_video_vbe_setup, @@ -800,11 +593,11 @@ static struct grub_video_adapter grub_video_vbe_adapter = .blit_bitmap = grub_video_fb_blit_bitmap, .blit_render_target = grub_video_fb_blit_render_target, .scroll = grub_video_fb_scroll, - .swap_buffers = grub_video_vbe_swap_buffers, + .swap_buffers = grub_video_fb_swap_buffers, .create_render_target = grub_video_fb_create_render_target, .delete_render_target = grub_video_fb_delete_render_target, - .set_active_render_target = grub_video_vbe_set_active_render_target, - .get_active_render_target = grub_video_vbe_get_active_render_target, + .set_active_render_target = grub_video_fb_set_active_render_target, + .get_active_render_target = grub_video_fb_get_active_render_target, .next = 0 }; diff --git a/video/i386/pc/vga.c b/video/i386/pc/vga.c index 222a71272..3fbb18bb0 100644 --- a/video/i386/pc/vga.c +++ b/video/i386/pc/vga.c @@ -27,6 +27,7 @@ #include #include #include +#include #define VGA_WIDTH 640 #define VGA_HEIGHT 350 @@ -45,58 +46,26 @@ static struct int back_page; } framebuffer; -#define SEQUENCER_ADDR_PORT 0x3C4 -#define SEQUENCER_DATA_PORT 0x3C5 -#define MAP_MASK_REGISTER 0x02 - -#define CRTC_ADDR_PORT 0x3D4 -#define CRTC_DATA_PORT 0x3D5 -#define START_ADDR_HIGH_REGISTER 0x0C -#define START_ADDR_LOW_REGISTER 0x0D - -#define GRAPHICS_ADDR_PORT 0x3CE -#define GRAPHICS_DATA_PORT 0x3CF -#define READ_MAP_REGISTER 0x04 - -#define INPUT_STATUS1_REGISTER 0x3DA -#define INPUT_STATUS1_VERTR_BIT 0x08 - static inline void wait_vretrace (void) { /* Wait until there is a vertical retrace. */ - while (! (grub_inb (INPUT_STATUS1_REGISTER) & INPUT_STATUS1_VERTR_BIT)); + while (! (grub_inb (GRUB_VGA_IO_INPUT_STATUS1_REGISTER) + & GRUB_VGA_IO_INPUT_STATUS1_VERTR_BIT)); } /* Get Map Mask Register. */ static unsigned char get_map_mask (void) { - unsigned char old_addr; - unsigned char old_data; - - old_addr = grub_inb (SEQUENCER_ADDR_PORT); - grub_outb (MAP_MASK_REGISTER, SEQUENCER_ADDR_PORT); - - old_data = grub_inb (SEQUENCER_DATA_PORT); - - grub_outb (old_addr, SEQUENCER_ADDR_PORT); - - return old_data; + return grub_vga_sr_read (GRUB_VGA_SR_MAP_MASK_REGISTER); } /* Set Map Mask Register. */ static void set_map_mask (unsigned char mask) { - unsigned char old_addr; - - old_addr = grub_inb (SEQUENCER_ADDR_PORT); - grub_outb (MAP_MASK_REGISTER, SEQUENCER_ADDR_PORT); - - grub_outb (mask, SEQUENCER_DATA_PORT); - - grub_outb (old_addr, SEQUENCER_ADDR_PORT); + grub_vga_sr_write (mask, GRUB_VGA_SR_MAP_MASK_REGISTER); } #if 0 @@ -104,14 +73,7 @@ set_map_mask (unsigned char mask) static void set_read_map (unsigned char map) { - unsigned char old_addr; - - old_addr = grub_inb (GRAPHICS_ADDR_PORT); - - grub_outb (READ_MAP_REGISTER, GRAPHICS_ADDR_PORT); - grub_outb (map, GRAPHICS_DATA_PORT); - - grub_outb (old_addr, GRAPHICS_ADDR_PORT); + grub_vga_gr_write (map, GRUB_VGA_GR_READ_MAP_REGISTER); } #endif @@ -119,17 +81,8 @@ set_read_map (unsigned char map) static void set_start_address (unsigned int start) { - unsigned char old_addr; - - old_addr = grub_inb (CRTC_ADDR_PORT); - - grub_outb (START_ADDR_LOW_REGISTER, CRTC_ADDR_PORT); - grub_outb (start & 0xFF, CRTC_DATA_PORT); - - grub_outb (START_ADDR_HIGH_REGISTER, CRTC_ADDR_PORT); - grub_outb (start >> 8, CRTC_DATA_PORT); - - grub_outb (old_addr, CRTC_ADDR_PORT); + grub_vga_cr_write (start & 0xFF, GRUB_VGA_CR_START_ADDR_LOW_REGISTER); + grub_vga_cr_write (start >> 8, GRUB_VGA_CR_START_ADDR_HIGH_REGISTER); } static int setup = 0; @@ -375,6 +328,8 @@ static struct grub_video_adapter grub_video_vga_adapter = .name = "VGA Video Driver", .id = GRUB_VIDEO_DRIVER_VGA, + .prio = GRUB_VIDEO_ADAPTER_PRIO_FALLBACK, + .init = grub_video_vga_init, .fini = grub_video_vga_fini, .setup = grub_video_vga_setup, diff --git a/video/ieee1275.c b/video/ieee1275.c index 5c6bc1594..9c9477c2b 100644 --- a/video/ieee1275.c +++ b/video/ieee1275.c @@ -254,6 +254,8 @@ static struct grub_video_adapter grub_video_ieee1275_adapter = { .name = "IEEE1275 video driver", + .prio = GRUB_VIDEO_ADAPTER_PRIO_FIRMWARE, + .init = grub_video_ieee1275_init, .fini = grub_video_ieee1275_fini, .setup = grub_video_ieee1275_setup, diff --git a/video/sm712.c b/video/sm712.c index cee9831bb..a58032c42 100644 --- a/video/sm712.c +++ b/video/sm712.c @@ -36,10 +36,7 @@ static struct struct grub_video_mode_info mode_info; struct grub_video_render_target *render_target; - unsigned int bytes_per_scan_line; - unsigned int bytes_per_pixel; grub_uint8_t *ptr; - int index_color_mode; int mapped; grub_uint32_t base; grub_pci_device_t dev; @@ -198,19 +195,6 @@ grub_video_sm712_setup (unsigned int width, unsigned int height, return err; } -static grub_err_t -grub_video_sm712_set_palette (unsigned int start, unsigned int count, - struct grub_video_palette_data *palette_data) -{ - if (framebuffer.index_color_mode) - { - /* TODO: Implement setting indexed color mode palette to hardware. */ - } - - /* Then set color to emulated palette. */ - return grub_video_fb_set_palette (start, count, palette_data); -} - static grub_err_t grub_video_sm712_swap_buffers (void) { @@ -245,12 +229,14 @@ static struct grub_video_adapter grub_video_sm712_adapter = .name = "SM712 Video Driver", .id = GRUB_VIDEO_DRIVER_SM712, + .prio = GRUB_VIDEO_ADAPTER_PRIO_NATIVE, + .init = grub_video_sm712_video_init, .fini = grub_video_sm712_video_fini, .setup = grub_video_sm712_setup, .get_info = grub_video_fb_get_info, .get_info_and_fini = grub_video_sm712_get_info_and_fini, - .set_palette = grub_video_sm712_set_palette, + .set_palette = grub_video_fb_set_palette, .get_palette = grub_video_fb_get_palette, .set_viewport = grub_video_fb_set_viewport, .get_viewport = grub_video_fb_get_viewport, diff --git a/video/video.c b/video/video.c index 42418f980..7a1a446e4 100644 --- a/video/video.c +++ b/video/video.c @@ -23,44 +23,11 @@ #include /* The list of video adapters registered to system. */ -static grub_video_adapter_t grub_video_adapter_list; +grub_video_adapter_t grub_video_adapter_list = NULL; /* Active video adapter. */ static grub_video_adapter_t grub_video_adapter_active; -/* Register video driver. */ -void -grub_video_register (grub_video_adapter_t adapter) -{ - adapter->next = grub_video_adapter_list; - grub_video_adapter_list = adapter; -} - -/* Unregister video driver. */ -void -grub_video_unregister (grub_video_adapter_t adapter) -{ - grub_video_adapter_t *p, q; - - for (p = &grub_video_adapter_list, q = *p; q; p = &(q->next), q = q->next) - if (q == adapter) - { - *p = q->next; - break; - } -} - -/* Iterate thru all registered video drivers. */ -void -grub_video_iterate (int (*hook) (grub_video_adapter_t adapter)) -{ - grub_video_adapter_t p; - - for (p = grub_video_adapter_list; p; p = p->next) - if (hook (p)) - break; -} - /* Restore back to initial mode (where applicable). */ grub_err_t grub_video_restore (void)