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 4e0f35c1d..5509a9f05 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,995 @@ +2010-06-21 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-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 + to the empty string. + +2010-05-28 BVK Chaitanya + + Fix grub-emu issues on NetBSD, with gcc 4.1.3. + + * conf/any-emu.rmk: Remove unnecessary COMMON_CFLAGS. + * include/grub/emu/misc.h (canonicalize_file_name): New Prototype. + * kern/misc.c (__enable_execute_stack): Disable on + GRUB_MACHINE_EMU. + +2010-05-28 Colin Watson + + Make grub-probe work with symbolic links under /dev/mapper as well + as with real block devices. The Linux world seems to be (at best) + in transition here, and GRUB shouldn't get caught in the middle. + + * kern/emu/getroot.c (find_root_device): Follow symbolic links under + /dev/mapper. + +2010-05-27 Colin Watson + + * util/grub-script-check.c (main): Ensure defined behaviour on empty + input files (in which case exit zero). + +2010-05-27 Colin Watson + + * kern/emu/misc.c (canonicalize_file_name): realpath can still + return NULL for various reasons even if it has a maximum-length + buffer: for example, there might be a symlink loop, or the path + might exceed PATH_MAX. If this happens, return NULL. + +2010-05-27 Robert Millan + + * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Insert + partmap module to handle cross-partmap setups. + Reported by Orestes Mas. Gràcies! + +2010-05-27 Colin Watson + + * util/grub-mkrescue.in: Initialise override_dir rather than + assuming that it's unset or empty in the environment. + +2010-05-26 Grégoire Sutre + + * kern/emu/hostdisk.c (find_partition_start) [__NetBSD__]: Renamed + variable index into p_index to suppress a warning with -Wshadow. + +2010-05-25 BVK Chaitanya + + * INSTALL: Added flex >= 2.5.35 requirement. + +2010-05-23 Vladimir Serbinenko + + * commands/usbtest.c (grub_usb_get_string): Properly support UTF-16. + +2010-05-23 Vladimir Serbinenko + + cmostest support. + + * commands/i386/cmostest.c: New file. + * conf/i386-coreboot.rmk (pkglib_MODULES): Add cmostest.mod. + (cmostest_mod_SOURCES): New variable. + (cmostest_mod_CFLAGS): Likewise. + (cmostest_mod_LDFLAGS): Likewise. + * conf/i386-pc.rmk: Likewise. + * docs/grub.texi (Vendor power-on keys): New section. + * util/grub-mkconfig.in: export GRUB_DEFAULT_BUTTON, + GRUB_HIDDEN_TIMEOUT_BUTTON, GRUB_TIMEOUT_BUTTON + and GRUB_BUTTON_CMOS_ADDRESS. + * util/grub.d/00_header.in: Handle powering-on by separate button. + +2010-05-23 Vladimir Serbinenko + + * gfxmenu/gui_list.c (draw_menu): Don't add scrollbar width to padding. + Removed drawing_scrollbar argument. All users updated + Fixes #29792. + Reported by Jo Shields + +2010-05-23 Vladimir Serbinenko + + * gfxmenu/view.c (grub_gfxmenu_draw_terminal_box): Apply only to current + buffer since gfxterm handles double repaint. + +2010-05-23 Vladimir Serbinenko + + * gfxmenu/gfxmenu.c (grub_gfxmenu_try): Change viewport on both buffers. + * term/gfxterm.c (real_scroll): Likewise. + +2010-05-21 Vladimir Serbinenko + + * kern/i386/pc/mmap.c (grub_machine_mmap_iterate): Zero-fill entry + before calling BIOS. + +2010-05-21 Vladimir Serbinenko + + * include/grub/i18n.h: Always enable grub_gettext. + +2010-05-21 Vladimir Serbinenko + + * kern/i386/pc/init.c (make_install_device): Fix a leftover usage of old + partition naming style. + +2010-05-21 Colin Watson + + * util/grub-mkconfig.in: Fix handling of -o so that it works when + not the first option. + +2010-05-20 Colin Watson + + * util/grub-mkrelpath.c (usage): Remove excess apostrophe. + +2010-05-20 Colin Watson + + * util/misc.c: Move inclusion of to ... + * kern/emu/misc.c: ... here. Needed for canonicalize_file_name. + +2010-05-20 Grégoire Sutre + + * kern/emu/hostdisk.c (grub_util_biosdisk_get_grub_dev) [__NetBSD__]: + Fix merge error in NetBSD code. + (find_partition_start) [__NetBSD__]: Likewise. + +2010-05-19 BVK Chaitanya + + Fix grub-mkrescue usage unit testing. + + * tests/util/grub-shell.in: Use --grub-mkimage with grub-mkrescue. + +2010-05-18 Christian Franke + + * util/grub.d/10_windows.in: Use path names instead of + drive letters to prevent warning from Cygwin 1.7. + Add drivemap command to menuentry if needed. + +2010-05-18 Justus Winter <4winter@informatik.uni-hamburg.de> + + * util/grub.d/10_hurd.in: Include all gnumach* kernels, not only + gnumach and gnumach.gz. + 2010-05-18 Vladimir Serbinenko * include/grub/i18n.h (gettext): Inline instead of using #define. diff --git a/INSTALL b/INSTALL index 0dd408bcc..44a442253 100644 --- a/INSTALL +++ b/INSTALL @@ -16,8 +16,24 @@ configuring the GRUB. * GNU Bison 2.3 or later * GNU gettext 0.17 or later * GNU binutils 2.9.1.0.23 or later +* 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/cs5536.c b/bus/cs5536.c new file mode 100644 index 000000000..61b0646b4 --- /dev/null +++ b/bus/cs5536.c @@ -0,0 +1,215 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include + +int +grub_cs5536_find (grub_pci_device_t *devp) +{ + int found = 0; + auto int NESTED_FUNC_ATTR hook (grub_pci_device_t dev, + grub_pci_id_t pciid); + + int NESTED_FUNC_ATTR hook (grub_pci_device_t dev, + grub_pci_id_t pciid) + { + if (pciid == GRUB_CS5536_PCIID) + { + *devp = dev; + found = 1; + return 1; + } + return 0; + } + + grub_pci_iterate (hook); + + return found; +} + +grub_uint64_t +grub_cs5536_read_msr (grub_pci_device_t dev, grub_uint32_t addr) +{ + grub_uint64_t ret = 0; + grub_pci_write (grub_pci_make_address (dev, GRUB_CS5536_MSR_MAILBOX_ADDR), + addr); + ret = (grub_uint64_t) + grub_pci_read (grub_pci_make_address (dev, GRUB_CS5536_MSR_MAILBOX_DATA0)); + ret |= (((grub_uint64_t) + grub_pci_read (grub_pci_make_address (dev, + GRUB_CS5536_MSR_MAILBOX_DATA1))) + << 32); + return ret; +} + +void +grub_cs5536_write_msr (grub_pci_device_t dev, grub_uint32_t addr, + grub_uint64_t val) +{ + grub_pci_write (grub_pci_make_address (dev, GRUB_CS5536_MSR_MAILBOX_ADDR), + addr); + grub_pci_write (grub_pci_make_address (dev, GRUB_CS5536_MSR_MAILBOX_DATA0), + val & 0xffffffff); + grub_pci_write (grub_pci_make_address (dev, GRUB_CS5536_MSR_MAILBOX_DATA1), + val >> 32); +} + +grub_err_t +grub_cs5536_smbus_wait (grub_port_t smbbase) +{ + grub_uint64_t start = grub_get_time_ms (); + while (1) + { + grub_uint8_t status; + status = grub_inb (smbbase + GRUB_CS5536_SMB_REG_STATUS); + if (status & GRUB_CS5536_SMB_REG_STATUS_SDAST) + return GRUB_ERR_NONE; + if (status & GRUB_CS5536_SMB_REG_STATUS_BER) + return grub_error (GRUB_ERR_IO, "SM bus error"); + if (status & GRUB_CS5536_SMB_REG_STATUS_NACK) + return grub_error (GRUB_ERR_IO, "NACK received"); + if (grub_get_time_ms () > start + 40) + return grub_error (GRUB_ERR_IO, "SM stalled"); + } + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_cs5536_read_spd_byte (grub_port_t smbbase, grub_uint8_t dev, + grub_uint8_t addr, grub_uint8_t *res) +{ + grub_err_t err; + + /* Send START. */ + grub_outb (grub_inb (smbbase + GRUB_CS5536_SMB_REG_CTRL1) + | GRUB_CS5536_SMB_REG_CTRL1_START, + smbbase + GRUB_CS5536_SMB_REG_CTRL1); + + /* Send device address. */ + err = grub_cs5536_smbus_wait (smbbase); + if (err) + return err; + grub_outb (dev << 1, smbbase + GRUB_CS5536_SMB_REG_DATA); + + /* Send ACK. */ + err = grub_cs5536_smbus_wait (smbbase); + if (err) + return err; + grub_outb (grub_inb (smbbase + GRUB_CS5536_SMB_REG_CTRL1) + | GRUB_CS5536_SMB_REG_CTRL1_ACK, + smbbase + GRUB_CS5536_SMB_REG_CTRL1); + + /* Send byte address. */ + grub_outb (addr, smbbase + GRUB_CS5536_SMB_REG_DATA); + + /* Send START. */ + err = grub_cs5536_smbus_wait (smbbase); + if (err) + return err; + grub_outb (grub_inb (smbbase + GRUB_CS5536_SMB_REG_CTRL1) + | GRUB_CS5536_SMB_REG_CTRL1_START, + smbbase + GRUB_CS5536_SMB_REG_CTRL1); + + /* Send device address. */ + err = grub_cs5536_smbus_wait (smbbase); + if (err) + return err; + grub_outb ((dev << 1) | 1, smbbase + GRUB_CS5536_SMB_REG_DATA); + + /* Send STOP. */ + err = grub_cs5536_smbus_wait (smbbase); + if (err) + return err; + grub_outb (grub_inb (smbbase + GRUB_CS5536_SMB_REG_CTRL1) + | GRUB_CS5536_SMB_REG_CTRL1_STOP, + smbbase + GRUB_CS5536_SMB_REG_CTRL1); + + err = grub_cs5536_smbus_wait (smbbase); + if (err) + return err; + *res = grub_inb (smbbase + GRUB_CS5536_SMB_REG_DATA); + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_cs5536_init_smbus (grub_pci_device_t dev, grub_uint16_t divisor, + grub_port_t *smbbase) +{ + grub_uint64_t smbbar; + + smbbar = grub_cs5536_read_msr (dev, GRUB_CS5536_MSR_SMB_BAR); + + /* FIXME */ + if (!(smbbar & GRUB_CS5536_LBAR_ENABLE)) + return grub_error(GRUB_ERR_IO, "SMB controller not enabled\n"); + *smbbase = (smbbar & GRUB_CS5536_LBAR_ADDR_MASK) + GRUB_MACHINE_PCI_IO_BASE; + + if (divisor < 8) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid divisor"); + + /* Disable SMB. */ + grub_outb (0, *smbbase + GRUB_CS5536_SMB_REG_CTRL2); + + /* Disable interrupts. */ + grub_outb (0, *smbbase + GRUB_CS5536_SMB_REG_CTRL1); + + /* Set as master. */ + grub_outb (GRUB_CS5536_SMB_REG_ADDR_MASTER, + *smbbase + GRUB_CS5536_SMB_REG_ADDR); + + /* Launch. */ + grub_outb (((divisor >> 7) & 0xff), *smbbase + GRUB_CS5536_SMB_REG_CTRL3); + grub_outb (((divisor << 1) & 0xfe) | GRUB_CS5536_SMB_REG_CTRL2_ENABLE, + *smbbase + GRUB_CS5536_SMB_REG_CTRL2); + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_cs5536_read_spd (grub_port_t smbbase, grub_uint8_t dev, + struct grub_smbus_spd *res) +{ + grub_err_t err; + grub_size_t size; + grub_uint8_t b; + grub_size_t ptr; + + err = grub_cs5536_read_spd_byte (smbbase, dev, 0, &b); + if (err) + return err; + if (b == 0) + return grub_error (GRUB_ERR_IO, "no SPD found"); + size = b; + + ((grub_uint8_t *) res)[0] = b; + for (ptr = 1; ptr < size; ptr++) + { + err = grub_cs5536_read_spd_byte (smbbase, dev, ptr, + &((grub_uint8_t *) res)[ptr]); + if (err) + return err; + } + return GRUB_ERR_NONE; +} + diff --git a/bus/pci.c b/bus/pci.c index a08e53446..bf14a8653 100644 --- a/bus/pci.c +++ b/bus/pci.c @@ -19,6 +19,50 @@ #include #include +#include + +/* 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) +{ + return grub_memalign (align, size); +} + +void +grub_dma_free (struct grub_pci_dma_chunk *ch) +{ + grub_free (ch); +} +/* #endif */ + +#ifdef GRUB_MACHINE_MIPS_YEELOONG +volatile void * +grub_dma_get_virt (struct grub_pci_dma_chunk *ch) +{ + return (void *) ((((grub_uint32_t) ch) & 0x1fffffff) | 0xa0000000); +} + +grub_uint32_t +grub_dma_get_phys (struct grub_pci_dma_chunk *ch) +{ + return (((grub_uint32_t) ch) & 0x1fffffff) | 0x80000000; +} +#else + +volatile void * +grub_dma_get_virt (struct grub_pci_dma_chunk *ch) +{ + return (void *) ch; +} + +grub_uint32_t +grub_dma_get_phys (struct grub_pci_dma_chunk *ch) +{ + return (grub_uint32_t) (grub_addr_t) ch; +} + +#endif grub_pci_address_t grub_pci_make_address (grub_pci_device_t dev, int reg) @@ -48,6 +92,16 @@ grub_pci_iterate (grub_pci_iteratefunc_t hook) if (id >> 16 == 0xFFFF) continue; +#ifdef GRUB_MACHINE_MIPS_YEELOONG + /* Skip ghosts. */ + if (id == GRUB_YEELOONG_OHCI_PCIID + && dev.function == GRUB_YEELOONG_OHCI_GHOST_FUNCTION) + continue; + if (id == GRUB_YEELOONG_EHCI_PCIID + && dev.function == GRUB_YEELOONG_EHCI_GHOST_FUNCTION) + continue; +#endif + if (hook (dev, id)) return; diff --git a/bus/usb/ohci.c b/bus/usb/ohci.c index 6d185bc7f..956a27292 100644 --- a/bus/usb/ohci.c +++ b/bus/usb/ohci.c @@ -24,8 +24,10 @@ #include #include #include -#include +#include #include +#include +#include struct grub_ohci_hcca { @@ -63,13 +65,15 @@ struct grub_ohci_td grub_uint32_t buffer_end; } __attribute__((packed)); -typedef struct grub_ohci_td *grub_ohci_td_t; -typedef struct grub_ohci_ed *grub_ohci_ed_t; +typedef volatile struct grub_ohci_td *grub_ohci_td_t; +typedef volatile struct grub_ohci_ed *grub_ohci_ed_t; struct grub_ohci { volatile grub_uint32_t *iobase; volatile struct grub_ohci_hcca *hcca; + grub_uint32_t hcca_addr; + struct grub_pci_dma_chunk *hcca_chunk; struct grub_ohci *next; }; @@ -91,10 +95,32 @@ typedef enum GRUB_OHCI_REG_BULKCURR, GRUB_OHCI_REG_DONEHEAD, GRUB_OHCI_REG_FRAME_INTERVAL, + GRUB_OHCI_REG_PERIODIC_START = 16, GRUB_OHCI_REG_RHUBA = 18, - GRUB_OHCI_REG_RHUBPORT = 21 + GRUB_OHCI_REG_RHUBPORT = 21, + GRUB_OHCI_REG_LEGACY_CONTROL = 0x100, + GRUB_OHCI_REG_LEGACY_INPUT = 0x104, + GRUB_OHCI_REG_LEGACY_OUTPUT = 0x108, + GRUB_OHCI_REG_LEGACY_STATUS = 0x10c } grub_ohci_reg_t; +#define GRUB_OHCI_RHUB_PORT_POWER_MASK 0x300 +#define GRUB_OHCI_RHUB_PORT_ALL_POWERED 0x200 + +#define GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_MASK 0x8fff0000 +#define GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_SHIFT 16 +#define GRUB_OHCI_REG_FRAME_INTERVAL_FI_SHIFT 0 + +/* XXX: Is this choice of timings sane? */ +#define GRUB_OHCI_FSMPS 0x2778 +#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) { @@ -114,51 +140,81 @@ grub_ohci_writereg32 (struct grub_ohci *o, controller. If this is the case, initialize it. */ static int NESTED_FUNC_ATTR grub_ohci_pci_iter (grub_pci_device_t dev, - grub_pci_id_t pciid __attribute__((unused))) + grub_pci_id_t pciid) { - grub_uint32_t class_code; - grub_uint32_t class; - grub_uint32_t subclass; grub_uint32_t interf; grub_uint32_t base; grub_pci_address_t addr; struct grub_ohci *o; grub_uint32_t revision; - grub_uint32_t frame_interval; - - addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); - class_code = grub_pci_read (addr) >> 8; - - interf = class_code & 0xFF; - subclass = (class_code >> 8) & 0xFF; - class = class_code >> 16; - - /* If this is not an OHCI controller, just return. */ - if (class != 0x0c || subclass != 0x03 || interf != 0x10) - return 0; + int cs5536; /* Determine IO base address. */ - addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); - base = grub_pci_read (addr); + grub_dprintf ("ohci", "pciid = %x\n", pciid); + + if (pciid == GRUB_CS5536_PCIID) + { + grub_uint64_t basereg; + + cs5536 = 1; + basereg = grub_cs5536_read_msr (dev, GRUB_CS5536_MSR_USB_OHCI_BASE); + if (!(basereg & GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE)) + { + /* Shouldn't happen. */ + grub_dprintf ("ohci", "No OHCI address is assigned\n"); + return 0; + } + base = (basereg & GRUB_CS5536_MSR_USB_BASE_ADDR_MASK); + basereg |= GRUB_CS5536_MSR_USB_BASE_BUS_MASTER; + basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_ENABLED; + basereg &= ~GRUB_CS5536_MSR_USB_BASE_PME_STATUS; + grub_cs5536_write_msr (dev, GRUB_CS5536_MSR_USB_OHCI_BASE, basereg); + } + else + { + grub_uint32_t class_code; + grub_uint32_t class; + grub_uint32_t subclass; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); + class_code = grub_pci_read (addr) >> 8; + + interf = class_code & 0xFF; + subclass = (class_code >> 8) & 0xFF; + class = class_code >> 16; + + /* If this is not an OHCI controller, just return. */ + if (class != 0x0c || subclass != 0x03 || interf != 0x10) + return 0; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); + base = grub_pci_read (addr); #if 0 - /* Stop if there is no IO space base address defined. */ - if (! (base & 1)) - return 0; + /* Stop if there is no IO space base address defined. */ + if (! (base & 1)) + return 0; #endif + grub_dprintf ("ohci", "class=0x%02x 0x%02x interface 0x%02x\n", + class, subclass, interf); + } + /* Allocate memory for the controller and register it. */ o = grub_malloc (sizeof (*o)); if (! o) return 1; - o->iobase = (grub_uint32_t *) base; + o->iobase = grub_pci_device_map_range (dev, base, 0x800); + + grub_dprintf ("ohci", "base=%p\n", o->iobase); /* Reserve memory for the HCCA. */ - o->hcca = (struct grub_ohci_hcca *) grub_memalign (256, 256); - - grub_dprintf ("ohci", "class=0x%02x 0x%02x interface 0x%02x base=%p\n", - class, subclass, interf, o->iobase); + o->hcca_chunk = grub_memalign_dma32 (256, 256); + if (! o->hcca_chunk) + return 1; + o->hcca = grub_dma_get_virt (o->hcca_chunk); + o->hcca_addr = grub_dma_get_phys (o->hcca_chunk); /* Check if the OHCI revision is actually 1.0 as supported. */ revision = grub_ohci_readreg32 (o, GRUB_OHCI_REG_REVISION); @@ -166,27 +222,116 @@ grub_ohci_pci_iter (grub_pci_device_t dev, if ((revision & 0xFF) != 0x10) goto fail; - /* Backup the frame interval register. */ - frame_interval = grub_ohci_readreg32 (o, GRUB_OHCI_REG_FRAME_INTERVAL); + + { + grub_uint32_t control; + /* Check SMM/BIOS ownership of OHCI (SMM = USB Legacy Support driver for BIOS) */ + control = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL); + if ((control & 0x100) != 0) + { + unsigned i; + grub_dprintf("ohci", "OHCI is owned by SMM\n"); + /* Do change of ownership */ + /* Ownership change request */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, (1<<3)); /* XXX: Magic. */ + /* Waiting for SMM deactivation */ + for (i=0; i < 10; i++) + { + if ((grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL) & 0x100) == 0) + { + grub_dprintf("ohci", "Ownership changed normally.\n"); + break; + } + grub_millisleep (100); + } + if (i >= 10) + { + grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, + grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL) & ~0x100); + grub_dprintf("ohci", "Ownership changing timeout, change forced !\n"); + } + } + else if (((control & 0x100) == 0) && + ((control & 0xc0) != 0)) /* Not owned by SMM nor reset */ + { + grub_dprintf("ohci", "OHCI is owned by BIOS\n"); + /* Do change of ownership - not implemented yet... */ + /* In fact we probably need to do nothing ...? */ + } + else + { + grub_dprintf("ohci", "OHCI is not owned by SMM nor BIOS\n"); + /* We can setup OHCI. */ + } + } /* Suspend the OHCI by issuing a reset. */ grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, 1); /* XXX: Magic. */ grub_millisleep (1); grub_dprintf ("ohci", "OHCI reset\n"); - /* Restore the frame interval register. */ - grub_ohci_writereg32 (o, GRUB_OHCI_REG_FRAME_INTERVAL, frame_interval); + grub_ohci_writereg32 (o, GRUB_OHCI_REG_FRAME_INTERVAL, + (GRUB_OHCI_FSMPS + << GRUB_OHCI_REG_FRAME_INTERVAL_FSMPS_SHIFT) + | (GRUB_OHCI_FRAME_INTERVAL + << GRUB_OHCI_REG_FRAME_INTERVAL_FI_SHIFT)); + + grub_ohci_writereg32 (o, GRUB_OHCI_REG_PERIODIC_START, + GRUB_OHCI_PERIODIC_START); /* Setup the HCCA. */ - grub_ohci_writereg32 (o, GRUB_OHCI_REG_HCCA, (grub_uint32_t) o->hcca); + o->hcca->donehead = 0; + grub_ohci_writereg32 (o, GRUB_OHCI_REG_HCCA, o->hcca_addr); grub_dprintf ("ohci", "OHCI HCCA\n"); + /* Misc. pre-sets. */ + 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); + + /* Check OHCI Legacy Support */ + if ((revision & 0x100) != 0) + { + grub_dprintf ("ohci", "Legacy Support registers detected\n"); + grub_dprintf ("ohci", "Current state of legacy control reg.: 0x%04x\n", + grub_ohci_readreg32 (o, GRUB_OHCI_REG_LEGACY_CONTROL)); + grub_ohci_writereg32 (o, GRUB_OHCI_REG_LEGACY_CONTROL, + (grub_ohci_readreg32 (o, GRUB_OHCI_REG_LEGACY_CONTROL)) & ~1); + grub_dprintf ("ohci", "OHCI Legacy Support disabled.\n"); + } + /* Enable the OHCI. */ grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, (2 << 6)); grub_dprintf ("ohci", "OHCI enable: 0x%02x\n", (grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL) >> 6) & 3); + /* Power on all ports */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBA, + (grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBA) + & ~GRUB_OHCI_RHUB_PORT_POWER_MASK) + | GRUB_OHCI_RHUB_PORT_ALL_POWERED); + /* Wait for stable power (100ms) and stable attachment (100ms) */ + /* I.e. minimum wait time should be probably 200ms. */ + /* We assume that device is attached when ohci is loaded. */ + /* Some devices take long time to power-on or indicate attach. */ + /* Here is some experimental value which should probably mostly work. */ + /* Cameras with manual USB mode selection and maybe some other similar + * devices will not work in some cases - they are repowered during + * ownership change and then they are starting slowly and mostly they + * are wanting select proper mode again... + * The same situation can be on computers where BIOS not set-up OHCI + * to be at least powered USB bus (maybe it is Yeelong case...?) + * Possible workaround could be for example some prompt + * for user with confirmation of proper USB device connection. + * Another workaround - "rmmod usbms", "rmmod ohci", proper start + * and configuration of USB device and then "insmod ohci" + * and "insmod usbms". */ + grub_millisleep (500); + /* Link to ohci now that initialisation is successful. */ o->next = ohci; ohci = o; @@ -195,10 +340,10 @@ grub_ohci_pci_iter (grub_pci_device_t dev, fail: if (o) - grub_free ((void *) o->hcca); + grub_dma_free (o->hcca_chunk); grub_free (o); - return 1; + return 0; } @@ -229,7 +374,7 @@ grub_ohci_iterate (int (*hook) (grub_usb_controller_t dev)) static void grub_ohci_transaction (grub_ohci_td_t td, grub_transfer_type_t type, unsigned int toggle, - grub_size_t size, char *data) + grub_size_t size, grub_uint32_t data) { grub_uint32_t token; grub_uint32_t buffer; @@ -254,20 +399,38 @@ 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; token |= 1 << 25; - buffer = (grub_uint32_t) data; + /* Set "Not accessed" error code */ + token |= 15 << 28; + + buffer = data; buffer_end = buffer + size - 1; + /* Set correct buffer values in TD if zero transfer occurs */ + if (size) + { + buffer = (grub_uint32_t) data; + buffer_end = buffer + size - 1; + td->buffer = grub_cpu_to_le32 (buffer); + td->buffer_end = grub_cpu_to_le32 (buffer_end); + } + else + { + td->buffer = 0; + td->buffer_end = 0; + } + + /* Set the rest of TD */ td->token = grub_cpu_to_le32 (token); - td->buffer = grub_cpu_to_le32 (buffer); td->next_td = 0; - td->buffer_end = grub_cpu_to_le32 (buffer_end); } static grub_usb_err_t @@ -276,7 +439,10 @@ grub_ohci_transfer (grub_usb_controller_t dev, { struct grub_ohci *o = (struct grub_ohci *) dev->data; grub_ohci_ed_t ed; + grub_uint32_t ed_addr; + struct grub_pci_dma_chunk *ed_chunk, *td_list_chunk; grub_ohci_td_t td_list; + grub_uint32_t td_list_addr; grub_uint32_t target; grub_uint32_t td_tail; grub_uint32_t td_head; @@ -284,20 +450,30 @@ grub_ohci_transfer (grub_usb_controller_t dev, grub_uint32_t control; grub_usb_err_t err; 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 = grub_memalign (16, sizeof (*ed)); - if (! ed) + ed_chunk = grub_memalign_dma32 (256, sizeof (*ed)); + if (! ed_chunk) return GRUB_USB_ERR_INTERNAL; + ed = grub_dma_get_virt (ed_chunk); + ed_addr = grub_dma_get_phys (ed_chunk); - td_list = grub_memalign (16, sizeof (*td_list) * (transfer->transcnt + 1)); - if (! td_list) + td_list_chunk = grub_memalign_dma32 (256, sizeof (*td_list) + * (transfer->transcnt + 1)); + if (! td_list_chunk) { - grub_free ((void *) ed); + grub_dma_free (ed_chunk); return GRUB_USB_ERR_INTERNAL; } + td_list = grub_dma_get_virt (td_list_chunk); + td_list_addr = grub_dma_get_phys (td_list_chunk); - grub_dprintf ("ohci", "alloc=%p\n", td_list); + grub_dprintf ("ohci", "alloc=%p/0x%x\n", td_list, td_list_addr); /* Setup all Transfer Descriptors. */ for (i = 0; i < transfer->transcnt; i++) @@ -307,16 +483,31 @@ grub_ohci_transfer (grub_usb_controller_t dev, grub_ohci_transaction (&td_list[i], tr->pid, tr->toggle, tr->size, tr->data); - td_list[i].next_td = grub_cpu_to_le32 (&td_list[i + 1]); + td_list[i].next_td = grub_cpu_to_le32 (td_list_addr + + (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; + td_list[transfer->transcnt].buffer_end = 0; + td_list[transfer->transcnt].next_td = + (grub_uint32_t) &td_list[transfer->transcnt]; + /* Setup the Endpoint Descriptor. */ /* Set the device address. */ target = transfer->devaddr; - /* Set the endpoint. */ - target |= transfer->endpoint << 7; + /* Set the endpoint. It should be masked, we need 4 bits only. */ + target |= (transfer->endpoint & 15) << 7; /* Set the device speed. */ target |= (transfer->dev->speed == GRUB_USB_SPEED_LOW) << 13; @@ -324,9 +515,9 @@ grub_ohci_transfer (grub_usb_controller_t dev, /* Set the maximum packet size. */ target |= transfer->max << 16; - td_head = (grub_uint32_t) td_list; + td_head = td_list_addr; - td_tail = (grub_uint32_t) &td_list[transfer->transcnt]; + td_tail = td_list_addr + transfer->transcnt * sizeof (*td_list); ed->target = grub_cpu_to_le32 (target); ed->td_head = grub_cpu_to_le32 (td_head); @@ -335,6 +526,30 @@ grub_ohci_transfer (grub_usb_controller_t dev, grub_dprintf ("ohci", "program OHCI\n"); + /* Disable the Control and Bulk lists. */ + control = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL); + control &= ~(3 << 4); + grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, control); + + /* Clear BulkListFilled and ControlListFilled. */ + status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS); + status &= ~(3 << 1); + grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, status); + + /* Now we should wait for start of next frame. Because we are not using + * interrupt, we reset SF bit and wait when it goes to 1. */ + /* SF bit reset. (SF bit indicates Start Of Frame (SOF) packet) */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1<<2)); + /* Wait for new SOF */ + while ((grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS) & 0x4) == 0); + /* Now it should be safe to change CONTROL and BULK lists. */ + + /* This we do for safety's sake - it should be done in previous call + * of grub_ohci_transfer and nobody should change it in meantime... + * It should be done before start of control or bulk OHCI list. */ + o->hcca->donehead = 0; + grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1)); /* Clears WDH */ + /* Program the OHCI to actually transfer. */ switch (transfer->type) { @@ -342,24 +557,22 @@ grub_ohci_transfer (grub_usb_controller_t dev, { grub_dprintf ("ohci", "add to bulk list\n"); - status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS); - control = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL); + /* Set BulkList Head and Current */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, ed_addr); + grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKCURR, 0); - /* Disable the Control and Bulk lists. */ - control &= ~(3 << 4); - grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, control); - - /* Clear BulkListFilled. */ - status &= ~(1 << 2); - grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, status); - - grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, (grub_uint32_t) ed); +#define GRUB_OHCI_REG_CONTROL_BULK_ENABLE (1 << 5) +#define GRUB_OHCI_REG_CONTROL_CONTROL_ENABLE (1 << 4) /* Enable the Bulk list. */ - control |= 1 << 5; + control = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL); + 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. */ + status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS); status |= 1 << 2; grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, status); @@ -369,24 +582,14 @@ grub_ohci_transfer (grub_usb_controller_t dev, case GRUB_USB_TRANSACTION_TYPE_CONTROL: { grub_dprintf ("ohci", "add to control list\n"); - status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS); - control = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL); - /* Disable the Control and Bulk lists. */ - control &= ~(3 << 4); - grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, control); - - /* Clear ControlListFilled. */ - status &= ~(1 << 1); - grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, status); - - grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD, - (grub_uint32_t) ed); - grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD+1, - (grub_uint32_t) ed); + /* 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. */ @@ -397,37 +600,138 @@ 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; + /* Wait until the transfer is completed or STALLs. */ - while ((ed->td_head & ~0xf) != (ed->td_tail & ~0xf)) + 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; + } - grub_dprintf ("ohci", "head=0x%02x tail=0x%02x\n", ed->td_head, ed->td_tail); + if ((intstatus & 0x10) != 0) + { /* Unrecoverable error - only reset can help...! */ + err_unrec = 1; + break; + } - /* Detected a STALL. */ - if (ed->td_head & 1) + /* Detected a HALT. */ + if (grub_le_to_cpu32 (ed->td_head) & 1) + break; + + /* Timeout ? */ + if (grub_get_time_ms () > maxtime) + { + /* Disable the Control and Bulk lists. */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, + grub_ohci_readreg32 (o, GRUB_OHCI_REG_CONTROL) & ~(3 << 4)); + err_timeout = 1; + break; + } + + if ((ed->td_head & ~0xf) == (ed->td_tail & ~0xf)) break; + + grub_cpu_idle (); } + while (1); - grub_dprintf ("ohci", "complete\n"); + 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 (ed->td_head & 1) */ -/* err = GRUB_USB_ERR_STALL; */ -/* else if (ed->td */ + 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; - if (ed->td_head & 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", + 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_uint8_t errcode; - grub_ohci_td_t tderr; + grub_ohci_td_t tderr = NULL; - tderr = (grub_ohci_td_t) grub_ohci_readreg32 (o, - GRUB_OHCI_REG_DONEHEAD); - errcode = tderr->token >> 28; + transfer->last_trans--; + + tderr = (grub_ohci_td_t) ((char *) td_list + + (tderr_addr - td_list_addr)); + + errcode = grub_le_to_cpu32 (tderr->token) >> 28; + grub_dprintf ("ohci", "OHCI errcode=0x%02x\n", errcode); switch (errcode) { @@ -473,11 +777,17 @@ grub_ohci_transfer (grub_usb_controller_t dev, case 8: /* XXX: Data overrun error. */ err = GRUB_USB_ERR_DATA; + 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)); break; case 10: @@ -515,12 +825,58 @@ grub_ohci_transfer (grub_usb_controller_t dev, /* Clear BulkListFilled and ControlListFilled. */ status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS); - status &= ~((1 << 2) | (1 << 3)); + status &= ~(3 << 1); grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, status); + + /* Set ED to be skipped - for safety */ + ed->target |= grub_cpu_to_le32 (1 << 14); + + /* Now we should wait for start of next frame. + * It is necessary because we will invalidate pointer to ED and it + * can be on OHCI active till SOF! + * Because we are not using interrupt, we reset SF bit and wait when + * it goes to 1. */ + /* 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) + && !err_unrec); + /* Now it should be safe to change CONTROL and BULK lists. */ + + /* Important cleaning. */ + o->hcca->donehead = 0; + grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1)); /* Clears WDH */ + 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); - /* XXX */ - grub_free (td_list); - grub_free (ed); + 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); + grub_dma_free (ed_chunk); return err; } @@ -530,28 +886,30 @@ grub_ohci_portstatus (grub_usb_controller_t dev, unsigned int port, unsigned int enable) { struct grub_ohci *o = (struct grub_ohci *) dev->data; - grub_uint32_t status; - /* Reset the port. */ - status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port); - status |= (1 << 4); /* XXX: Magic. */ - grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, status); - grub_millisleep (100); + grub_dprintf ("ohci", "begin of portstatus=0x%02x\n", + grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port)); - /* End the reset signaling. */ - status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port); - status |= (1 << 20); /* XXX: Magic. */ - grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, status); + grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, + GRUB_OHCI_SET_PORT_RESET); + grub_millisleep (50); /* For root hub should be nominaly 50ms */ + + /* End the reset signaling. */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, + GRUB_OHCI_SET_PORT_RESET_STATUS_CHANGE); grub_millisleep (10); - /* Enable the port. */ - status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port); - status |= (enable << 1); /* XXX: Magic. */ - grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, status); - - status = grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port); - grub_dprintf ("ohci", "portstatus=0x%02x\n", status); + if (enable) + grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, + GRUB_OHCI_SET_PORT_ENABLE); + else + grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, + GRUB_OHCI_CLEAR_PORT_ENABLE); + grub_millisleep (10); + grub_dprintf ("ohci", "end of portstatus=0x%02x\n", + grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port)); + return GRUB_ERR_NONE; } @@ -587,6 +945,42 @@ grub_ohci_hubports (grub_usb_controller_t dev) return portinfo & 0xFF; } +static grub_err_t +grub_ohci_fini_hw (int noreturn __attribute__ ((unused))) +{ + struct grub_ohci *o; + + for (o = ohci; o; o = o->next) + { + int i, nports = grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBA) & 0xff; + for (i = 0; i < nports; i++) + grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + i, + GRUB_OHCI_CLEAR_PORT_ENABLE); + + grub_ohci_writereg32 (o, GRUB_OHCI_REG_HCCA, 0); + 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); + 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; +} + +static grub_err_t +grub_ohci_restore_hw (void) +{ + struct grub_ohci *o; + + for (o = ohci; o; o = o->next) + grub_ohci_writereg32 (o, GRUB_OHCI_REG_HCCA, o->hcca_addr); + + return GRUB_ERR_NONE; +} static struct grub_usb_controller_dev usb_controller = @@ -603,9 +997,12 @@ GRUB_MOD_INIT(ohci) { grub_ohci_inithw (); grub_usb_controller_dev_register (&usb_controller); + grub_loader_register_preboot_hook (grub_ohci_fini_hw, grub_ohci_restore_hw, + GRUB_LOADER_PREBOOT_HOOK_PRIO_DISK); } GRUB_MOD_FINI(ohci) { + grub_ohci_fini_hw (0); grub_usb_controller_dev_unregister (&usb_controller); } diff --git a/bus/usb/uhci.c b/bus/usb/uhci.c index 947f2367b..1510f98e8 100644 --- a/bus/usb/uhci.c +++ b/bus/usb/uhci.c @@ -174,14 +174,15 @@ grub_uhci_pci_iter (grub_pci_device_t dev, return 1; u->iobase = base & GRUB_UHCI_IOMASK; - grub_dprintf ("uhci", "class=0x%02x 0x%02x interface 0x%02x base=0x%x\n", - class, subclass, interf, u->iobase); /* Reserve a page for the frame list. */ u->framelist = grub_memalign (4096, 4096); if (! u->framelist) goto fail; + grub_dprintf ("uhci", "class=0x%02x 0x%02x interface 0x%02x base=0x%x framelist=%p\n", + class, subclass, interf, u->iobase, u->framelist); + /* The framelist pointer of UHCI is only 32 bits, make sure this code works on on 64 bits architectures. */ #if GRUB_CPU_SIZEOF_VOID_P == 8 @@ -221,6 +222,9 @@ grub_uhci_pci_iter (grub_pci_device_t dev, } #endif + grub_dprintf ("uhci", "QH=%p, TD=%p\n", + u->qh, u->td); + /* Link all Transfer Descriptors in a list of available Transfer Descriptors. */ for (i = 0; i < 256; i++) @@ -328,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; @@ -380,7 +391,7 @@ static grub_uhci_td_t grub_uhci_transaction (struct grub_uhci *u, unsigned int endp, grub_transfer_type_t type, unsigned int addr, unsigned int toggle, grub_size_t size, - char *data) + grub_uint32_t data) { grub_uhci_td_t td; static const unsigned int tf[] = { 0x69, 0xE1, 0x2D }; @@ -398,7 +409,7 @@ grub_uhci_transaction (struct grub_uhci *u, unsigned int endp, } grub_dprintf ("uhci", - "transaction: endp=%d, type=%d, addr=%d, toggle=%d, size=%d data=%p td=%p\n", + "transaction: endp=%d, type=%d, addr=%d, toggle=%d, size=%d data=0x%x td=%p\n", endp, type, addr, toggle, size, data, td); /* Don't point to any TD, just terminate. */ @@ -418,7 +429,7 @@ grub_uhci_transaction (struct grub_uhci *u, unsigned int endp, td->token = ((size << 21) | (toggle << 19) | (endp << 15) | (addr << 8) | tf[type]); - td->buffer = (grub_uint32_t) data; + td->buffer = data; return td; } @@ -441,6 +452,8 @@ grub_uhci_transfer (grub_usb_controller_t dev, if (! qh) return grub_errno; + grub_dprintf ("uhci", "transfer, iobase:%08x\n", u->iobase); + for (i = 0; i < transfer->transcnt; i++) { grub_usb_transaction_t tr = &transfer->transactions[i]; @@ -455,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; } @@ -548,12 +561,13 @@ grub_uhci_transfer (grub_usb_controller_t dev, fail: - grub_dprintf ("uhci", "transaction failed\n"); + if (err != GRUB_USB_ERR_NONE) + grub_dprintf ("uhci", "transaction failed\n"); /* 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; } @@ -583,6 +597,8 @@ grub_uhci_portstatus (grub_usb_controller_t dev, unsigned int status; grub_uint64_t endtime; + grub_dprintf ("uhci", "portstatus, iobase:%08x\n", u->iobase); + grub_dprintf ("uhci", "enable=%d port=%d\n", enable, port); if (port == 0) @@ -600,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"); @@ -631,6 +647,8 @@ grub_uhci_detect_dev (grub_usb_controller_t dev, int port) int reg; unsigned int status; + grub_dprintf ("uhci", "detect_dev, iobase:%08x\n", u->iobase); + if (port == 0) reg = GRUB_UHCI_REG_PORTSC1; else if (port == 1) diff --git a/bus/usb/usb.c b/bus/usb/usb.c index 8289185da..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 < 16; 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 @@ -163,6 +160,16 @@ grub_usb_device_initialize (grub_usb_device_t dev) grub_usb_err_t err; int i; + /* First we have to read first 8 bytes only and determine + * max. size of packet */ + dev->descdev.maxsize0 = 0; /* invalidating, for safety only, can be removed if it is sure it is zero here */ + err = grub_usb_get_descriptor (dev, GRUB_USB_DESCRIPTOR_DEVICE, + 0, 8, (char *) &dev->descdev); + if (err) + return err; + + /* Now we have valid value in dev->descdev.maxsize0, + * so we can read whole device descriptor */ err = grub_usb_get_descriptor (dev, GRUB_USB_DESCRIPTOR_DEVICE, 0, sizeof (struct grub_usb_desc_device), (char *) &dev->descdev); diff --git a/bus/usb/usbtrans.c b/bus/usb/usbtrans.c index 09e7af83e..e1b9097e6 100644 --- a/bus/usb/usbtrans.c +++ b/bus/usb/usbtrans.c @@ -18,6 +18,7 @@ */ #include +#include #include #include #include @@ -29,30 +30,59 @@ grub_usb_control_msg (grub_usb_device_t dev, grub_uint8_t request, grub_uint16_t value, grub_uint16_t index, - grub_size_t size, char *data) + grub_size_t size0, char *data_in) { int i; grub_usb_transfer_t transfer; int datablocks; - struct grub_usb_packet_setup setupdata; + volatile struct grub_usb_packet_setup *setupdata; + grub_uint32_t setupdata_addr; grub_usb_err_t err; unsigned int max; + struct grub_pci_dma_chunk *data_chunk, *setupdata_chunk; + volatile char *data; + grub_uint32_t data_addr; + grub_size_t size = size0; + + /* FIXME: avoid allocation any kind of buffer in a first place. */ + data_chunk = grub_memalign_dma32 (128, size ? : 16); + if (!data_chunk) + return GRUB_USB_ERR_INTERNAL; + data = grub_dma_get_virt (data_chunk); + data_addr = grub_dma_get_phys (data_chunk); + grub_memcpy ((char *) data, data_in, size); grub_dprintf ("usb", "control: reqtype=0x%02x req=0x%02x val=0x%02x idx=0x%02x size=%d\n", reqtype, request, value, index, size); /* Create a transfer. */ - transfer = grub_malloc (sizeof (struct grub_usb_transfer)); + transfer = grub_malloc (sizeof (*transfer)); if (! transfer) - return grub_errno; + { + grub_dma_free (data_chunk); + return grub_errno; + } + + setupdata_chunk = grub_memalign_dma32 (32, sizeof (*setupdata)); + if (! setupdata_chunk) + { + grub_free (transfer); + grub_dma_free (data_chunk); + return grub_errno; + } + + setupdata = grub_dma_get_virt (setupdata_chunk); + setupdata_addr = grub_dma_get_phys (setupdata_chunk); /* Determine the maximum packet size. */ - if (dev->initialized) + if (dev->descdev.maxsize0) max = dev->descdev.maxsize0; else max = 64; + grub_dprintf ("usb", "transfer = %p, dev = %p\n", transfer, dev); + datablocks = (size + max - 1) / max; /* XXX: Discriminate between different types of control @@ -71,18 +101,20 @@ grub_usb_control_msg (grub_usb_device_t dev, if (! transfer->transactions) { grub_free (transfer); + grub_dma_free (setupdata_chunk); + grub_dma_free (data_chunk); return grub_errno; } /* Build a Setup packet. XXX: Endianness. */ - setupdata.reqtype = reqtype; - setupdata.request = request; - setupdata.value = value; - setupdata.index = index; - setupdata.length = size; - transfer->transactions[0].size = sizeof (setupdata); + setupdata->reqtype = reqtype; + setupdata->request = request; + setupdata->value = value; + setupdata->index = index; + setupdata->length = size; + transfer->transactions[0].size = sizeof (*setupdata); transfer->transactions[0].pid = GRUB_USB_TRANSFER_TYPE_SETUP; - transfer->transactions[0].data = (char *) &setupdata; + transfer->transactions[0].data = setupdata_addr; transfer->transactions[0].toggle = 0; /* Now the data... XXX: Is this the right way to transfer control @@ -99,14 +131,14 @@ grub_usb_control_msg (grub_usb_device_t dev, tr->pid = GRUB_USB_TRANSFER_TYPE_IN; else tr->pid = GRUB_USB_TRANSFER_TYPE_OUT; - tr->data = &data[i * max]; + tr->data = data_addr + i * max; size -= max; } /* End with an empty OUT transaction. */ transfer->transactions[datablocks + 1].size = 0; - transfer->transactions[datablocks + 1].data = NULL; - if (reqtype & 128) + transfer->transactions[datablocks + 1].data = 0; + if ((reqtype & 128) && datablocks) transfer->transactions[datablocks + 1].pid = GRUB_USB_TRANSFER_TYPE_OUT; else transfer->transactions[datablocks + 1].pid = GRUB_USB_TRANSFER_TYPE_IN; @@ -116,14 +148,19 @@ grub_usb_control_msg (grub_usb_device_t dev, err = dev->controller.dev->transfer (&dev->controller, transfer); grub_free (transfer->transactions); + grub_free (transfer); + grub_dma_free (data_chunk); + grub_dma_free (setupdata_chunk); + + grub_memcpy (data_in, (char *) data, size0); return err; } static grub_usb_err_t grub_usb_bulk_readwrite (grub_usb_device_t dev, - int endpoint, grub_size_t size, char *data, + int endpoint, grub_size_t size0, char *data_in, grub_transfer_type_t type) { int i; @@ -132,6 +169,19 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, unsigned int max; grub_usb_err_t err; int toggle = dev->toggle[endpoint]; + volatile char *data; + grub_uint32_t data_addr; + struct grub_pci_dma_chunk *data_chunk; + grub_size_t size = size0; + + /* FIXME: avoid allocation any kind of buffer in a first place. */ + data_chunk = grub_memalign_dma32 (128, size); + if (!data_chunk) + return GRUB_USB_ERR_INTERNAL; + data = grub_dma_get_virt (data_chunk); + data_addr = grub_dma_get_phys (data_chunk); + if (type == GRUB_USB_TRANSFER_TYPE_OUT) + grub_memcpy ((char *) data, data_in, size); /* Use the maximum packet size given in the endpoint descriptor. */ if (dev->initialized) @@ -150,16 +200,20 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, /* Create a transfer. */ transfer = grub_malloc (sizeof (struct grub_usb_transfer)); if (! transfer) - return grub_errno; + { + grub_dma_free (data_chunk); + return grub_errno; + } datablocks = ((size + max - 1) / max); transfer->transcnt = datablocks; transfer->size = size - 1; - transfer->endpoint = endpoint; + transfer->endpoint = endpoint & 15; transfer->devaddr = dev->addr; 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 @@ -167,6 +221,7 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, if (! transfer->transactions) { grub_free (transfer); + grub_dma_free (data_chunk); return grub_errno; } @@ -181,16 +236,27 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, tr->toggle = toggle; toggle = toggle ? 0 : 1; tr->pid = type; - tr->data = &data[i * max]; + tr->data = data_addr + i * max; size -= tr->size; } 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; grub_free (transfer->transactions); grub_free (transfer); + grub_dma_free (data_chunk); + + if (type == GRUB_USB_TRANSFER_TYPE_IN) + grub_memcpy (data_in, (char *) data, size0); return err; } 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/i386/cmostest.c b/commands/i386/cmostest.c new file mode 100644 index 000000000..36c35e6c4 --- /dev/null +++ b/commands/i386/cmostest.c @@ -0,0 +1,59 @@ +/* + * 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 + +static grub_err_t +grub_cmd_cmostest (struct grub_command *cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + int byte, bit; + char *rest; + + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Address required."); + + byte = grub_strtoul (argv[0], &rest, 0); + if (*rest != ':') + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Address required."); + + bit = grub_strtoul (rest + 1, 0, 0); + + if (grub_cmos_read (byte) & (1 << bit)) + return GRUB_ERR_NONE; + + return grub_error (GRUB_ERR_TEST_FAILURE, "false"); +} + +static grub_command_t cmd; + + +GRUB_MOD_INIT(cmostest) +{ + cmd = grub_register_command ("cmostest", grub_cmd_cmostest, + "cmostest BYTE:BIT", + "Test bit at BYTE:BIT in CMOS."); +} + +GRUB_MOD_FINI(cmostest) +{ + grub_unregister_command (cmd); +} 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 b884a93f1..191c4e4df 100644 --- a/commands/usbtest.c +++ b/commands/usbtest.c @@ -83,15 +83,24 @@ grub_usb_get_string (grub_usb_device_t dev, grub_uint8_t index, int langid, 0x06, (3 << 8) | index, langid, descstr.length, (char *) descstrp); - *string = grub_malloc (descstr.length / 2); + if (descstrp->length == 0) + { + grub_free (descstrp); + *string = grub_strdup (""); + if (! *string) + return GRUB_USB_ERR_INTERNAL; + return GRUB_USB_ERR_NONE; + } + + *string = grub_malloc (descstr.length * 2 + 1); if (! *string) { grub_free (descstrp); return GRUB_USB_ERR_INTERNAL; } - grub_utf16_to_utf8 ((grub_uint8_t *) *string, descstrp->str, descstrp->length / 2 - 1); - (*string)[descstr.length / 2 - 1] = '\0'; + *grub_utf16_to_utf8 ((grub_uint8_t *) *string, descstrp->str, + descstrp->length / 2 - 1) = 0; grub_free (descstrp); return GRUB_USB_ERR_NONE; 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 3f0df06aa..958da2bee 100644 --- a/conf/any-emu.rmk +++ b/conf/any-emu.rmk @@ -1,11 +1,9 @@ # -*- makefile -*- -COMMON_CFLAGS += -nostdinc -isystem $(shell $(TARGET_CC) -print-file-name=include) - 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 \ @@ -22,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 ee5152553..9a572288d 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,12 +88,11 @@ 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) MOSTLYCLEANFILES += symlist.c kernel_syms.lst @@ -102,7 +101,7 @@ 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 mm_private.h + list.h command.h i18n.h env_private.h libgcc.h mm_private.h ifneq ($(platform), emu) kernel_img_HEADERS += machine/memory.h @@ -119,19 +118,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,7 +201,7 @@ 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 @@ -448,12 +434,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 +500,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 +619,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 821431cbb..7486aa618 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 \ @@ -52,6 +52,12 @@ datetime_mod_SOURCES = lib/cmos_datetime.c datetime_mod_CFLAGS = $(COMMON_CFLAGS) datetime_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For cmostest.mod +pkglib_MODULES += cmostest.mod +cmostest_mod_SOURCES = commands/i386/cmostest.c +cmostest_mod_CFLAGS = $(COMMON_CFLAGS) +cmostest_mod_LDFLAGS = $(COMMON_LDFLAGS) + pkglib_MODULES += efiemu.mod efiemu_mod_SOURCES = efiemu/main.c efiemu/i386/loadcore32.c \ efiemu/i386/loadcore64.c efiemu/i386/pc/cfgtables.c \ diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk index b12022780..aefcc7bf8 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 e1927c0b0..91b0cb041 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 \ @@ -224,6 +224,12 @@ hdparm_mod_SOURCES = commands/hdparm.c lib/hexdump.c hdparm_mod_CFLAGS = $(COMMON_CFLAGS) hdparm_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For cmostest.mod +pkglib_MODULES += cmostest.mod +cmostest_mod_SOURCES = commands/i386/cmostest.c +cmostest_mod_CFLAGS = $(COMMON_CFLAGS) +cmostest_mod_LDFLAGS = $(COMMON_LDFLAGS) + BOOTTARGET=cd QEMU32=qemu-system-i386 diff --git a/conf/i386-qemu.rmk b/conf/i386-qemu.rmk index 5ec3c7eea..209eb2e5b 100644 --- a/conf/i386-qemu.rmk +++ b/conf/i386-qemu.rmk @@ -13,25 +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 += i386/pit.h +kernel_img_HEADERS += pci.h i386/pit.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 bca07c8e5..6fa12402a 100644 --- a/conf/i386.rmk +++ b/conf/i386.rmk @@ -17,6 +17,16 @@ vga_text_mod_CFLAGS = $(COMMON_CFLAGS) vga_text_mod_LDFLAGS = $(COMMON_LDFLAGS) endif +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 ifeq ($(platform), ieee1275) relocator_mod_SOURCES = lib/relocator.c lib/i386/relocator32.S \ @@ -87,11 +97,20 @@ 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 +cs5536_mod_SOURCES = bus/cs5536.c +cs5536_mod_CFLAGS = $(COMMON_CFLAGS) +cs5536_mod_LDFLAGS = $(COMMON_LDFLAGS) # For lspci.mod pkglib_MODULES += lspci.mod diff --git a/conf/mips-qemu-mips.rmk b/conf/mips-qemu-mips.rmk index 2f80ab2e3..b7eb513e7 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 5ce8ede9d..337bc41aa 100644 --- a/conf/mips-yeeloong.rmk +++ b/conf/mips-yeeloong.rmk @@ -4,7 +4,8 @@ target_machine=yeeloong COMMON_CFLAGS += -march=mips3 COMMON_ASFLAGS += -march=mips3 -kernel_img_HEADERS += pci.h bitmap.h video.h gfxterm.h font.h bitmap_scale.h bufio.h +kernel_img_HEADERS += pci.h bitmap.h video.h gfxterm.h font.h \ + bitmap_scale.h bufio.h cs5536.h machine/pci.h include $(srcdir)/conf/mips.mk @@ -15,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 \ @@ -26,6 +27,7 @@ kernel_img_SOURCES = kern/$(target_cpu)/startup.S \ video/fb/fbfill.c video/fb/fbutil.c video/bitmap.c \ video/bitmap_scale.c video/sm712.c bus/pci.c bus/bonito.c \ term/gfxterm.c commands/extcmd.c lib/arg.c \ + bus/cs5536.c \ symlist.c kernel_img_CFLAGS = $(COMMON_CFLAGS) -DUSE_ASCII_FAILBACK kernel_img_ASFLAGS = $(COMMON_ASFLAGS) @@ -69,5 +71,35 @@ linux_mod_CFLAGS = $(COMMON_CFLAGS) linux_mod_ASFLAGS = $(COMMON_ASFLAGS) linux_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For usb.mod +pkglib_MODULES += usb.mod +usb_mod_SOURCES = bus/usb/usb.c bus/usb/usbtrans.c bus/usb/usbhub.c +usb_mod_CFLAGS = $(COMMON_CFLAGS) +usb_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For usbtest.mod +pkglib_MODULES += usbtest.mod +usbtest_mod_SOURCES = commands/usbtest.c +usbtest_mod_CFLAGS = $(COMMON_CFLAGS) +usbtest_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For ohci.mod +pkglib_MODULES += ohci.mod +ohci_mod_SOURCES = bus/usb/ohci.c +ohci_mod_CFLAGS = $(COMMON_CFLAGS) +ohci_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For usbms.mod +pkglib_MODULES += usbms.mod +usbms_mod_SOURCES = disk/usbms.c +usbms_mod_CFLAGS = $(COMMON_CFLAGS) +usbms_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For usb_keyboard.mod +pkglib_MODULES += usb_keyboard.mod +usb_keyboard_mod_SOURCES = term/usb_keyboard.c +usb_keyboard_mod_CFLAGS = $(COMMON_CFLAGS) +usb_keyboard_mod_LDFLAGS = $(COMMON_LDFLAGS) + sbin_SCRIPTS += grub-install grub_install_SOURCES = util/grub-install.in diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk index 86ec85bfc..226d7baf8 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 7bc0eeea0..c81a026fe 100644 --- a/conf/x86-efi.rmk +++ b/conf/x86-efi.rmk @@ -24,7 +24,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 diff --git a/configure.ac b/configure.ac index 535804672..6fe1faf26 100644 --- a/configure.ac +++ b/configure.ac @@ -179,20 +179,30 @@ 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 AC_PROG_MAKE_SET AC_PROG_MKDIR_P -if test "x$LEX" = x; then +if test "x$LEX" = "x:"; then AC_MSG_ERROR([flex is not found]) else version=`$LEX --version | $AWK '{ split($NF,x,"."); print x[[1]]*10000+x[[2]]*100+x[[3]]; }'` 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 eba237287..5d3e50966 100644 --- a/disk/scsi.c +++ b/disk/scsi.c @@ -25,6 +25,7 @@ #include #include #include +#include static grub_scsi_dev_t grub_scsi_dev_list; @@ -50,7 +51,62 @@ grub_scsi_dev_unregister (grub_scsi_dev_t dev) } -/* Determine the the device is removable and the type of the device +/* Check result of previous operation. */ +static grub_err_t +grub_scsi_request_sense (grub_scsi_t scsi) +{ + struct grub_scsi_request_sense rs; + struct grub_scsi_request_sense_data rsd; + grub_err_t err; + + rs.opcode = grub_scsi_cmd_request_sense; + rs.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT; + rs.reserved1 = 0; + rs.reserved2 = 0; + rs.alloc_length = 0x12; /* XXX: Hardcoded for now */ + rs.control = 0; + grub_memset (rs.pad, 0, sizeof(rs.pad)); + + err = scsi->dev->read (scsi, sizeof (rs), (char *) &rs, + sizeof (rsd), (char *) &rsd); + if (err) + return err; + + return GRUB_ERR_NONE; +} +/* Self commenting... */ +static grub_err_t +grub_scsi_test_unit_ready (grub_scsi_t scsi) +{ + struct grub_scsi_test_unit_ready tur; + grub_err_t err; + grub_err_t err_sense; + + tur.opcode = grub_scsi_cmd_test_unit_ready; + tur.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT; + tur.reserved1 = 0; + tur.reserved2 = 0; + tur.reserved3 = 0; + tur.control = 0; + grub_memset (tur.pad, 0, sizeof(tur.pad)); + + err = scsi->dev->read (scsi, sizeof (tur), (char *) &tur, + 0, NULL); + + /* Each SCSI command should be followed by Request Sense. + If not so, many devices STALLs or definitely freezes. */ + err_sense = grub_scsi_request_sense (scsi); + if (err_sense != GRUB_ERR_NONE) + grub_errno = err; + /* err_sense is ignored for now and Request Sense Data also... */ + + if (err) + return err; + + return GRUB_ERR_NONE; +} + +/* Determine if the device is removable and the type of the device SCSI. */ static grub_err_t grub_scsi_inquiry (grub_scsi_t scsi) @@ -58,15 +114,26 @@ grub_scsi_inquiry (grub_scsi_t scsi) struct grub_scsi_inquiry iq; struct grub_scsi_inquiry_data iqd; grub_err_t err; + grub_err_t err_sense; iq.opcode = grub_scsi_cmd_inquiry; iq.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT; + iq.page = 0; iq.reserved = 0; iq.alloc_length = 0x24; /* XXX: Hardcoded for now */ - iq.reserved2 = 0; + iq.control = 0; + grub_memset (iq.pad, 0, sizeof(iq.pad)); err = scsi->dev->read (scsi, sizeof (iq), (char *) &iq, sizeof (iqd), (char *) &iqd); + + /* Each SCSI command should be followed by Request Sense. + If not so, many devices STALLs or definitely freezes. */ + err_sense = grub_scsi_request_sense (scsi); + if (err_sense != GRUB_ERR_NONE) + grub_errno = err; + /* err_sense is ignored for now and Request Sense Data also... */ + if (err) return err; @@ -83,13 +150,27 @@ grub_scsi_read_capacity (grub_scsi_t scsi) struct grub_scsi_read_capacity rc; struct grub_scsi_read_capacity_data rcd; grub_err_t err; + grub_err_t err_sense; rc.opcode = grub_scsi_cmd_read_capacity; rc.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT; - grub_memset (rc.reserved, 0, sizeof (rc.reserved)); - + rc.logical_block_addr = 0; + rc.reserved1 = 0; + rc.reserved2 = 0; + rc.PMI = 0; + rc.control = 0; + rc.pad = 0; + err = scsi->dev->read (scsi, sizeof (rc), (char *) &rc, sizeof (rcd), (char *) &rcd); + + /* Each SCSI command should be followed by Request Sense. + If not so, many devices STALLs or definitely freezes. */ + err_sense = grub_scsi_request_sense (scsi); + if (err_sense != GRUB_ERR_NONE) + grub_errno = err; +/* err_sense is ignored for now and Request Sense Data also... */ + if (err) return err; @@ -107,6 +188,8 @@ grub_scsi_read10 (grub_disk_t disk, grub_disk_addr_t sector, { grub_scsi_t scsi; struct grub_scsi_read10 rd; + grub_err_t err; + grub_err_t err_sense; scsi = disk->data; @@ -118,7 +201,16 @@ grub_scsi_read10 (grub_disk_t disk, grub_disk_addr_t sector, rd.reserved2 = 0; rd.pad = 0; - return scsi->dev->read (scsi, sizeof (rd), (char *) &rd, size * scsi->blocksize, buf); + err = scsi->dev->read (scsi, sizeof (rd), (char *) &rd, size * scsi->blocksize, buf); + + /* Each SCSI command should be followed by Request Sense. + If not so, many devices STALLs or definitely freezes. */ + err_sense = grub_scsi_request_sense (scsi); + if (err_sense != GRUB_ERR_NONE) + grub_errno = err; + /* err_sense is ignored for now and Request Sense Data also... */ + + return err; } /* Send a SCSI request for DISK: read SIZE sectors starting with @@ -129,6 +221,8 @@ grub_scsi_read12 (grub_disk_t disk, grub_disk_addr_t sector, { grub_scsi_t scsi; struct grub_scsi_read12 rd; + grub_err_t err; + grub_err_t err_sense; scsi = disk->data; @@ -139,7 +233,16 @@ grub_scsi_read12 (grub_disk_t disk, grub_disk_addr_t sector, rd.reserved = 0; rd.control = 0; - return scsi->dev->read (scsi, sizeof (rd), (char *) &rd, size * scsi->blocksize, buf); + err = scsi->dev->read (scsi, sizeof (rd), (char *) &rd, size * scsi->blocksize, buf); + + /* Each SCSI command should be followed by Request Sense. + If not so, many devices STALLs or definitely freezes. */ + err_sense = grub_scsi_request_sense (scsi); + if (err_sense != GRUB_ERR_NONE) + grub_errno = err; + /* err_sense is ignored for now and Request Sense Data also... */ + + return err; } #if 0 @@ -151,6 +254,8 @@ grub_scsi_write10 (grub_disk_t disk, grub_disk_addr_t sector, { grub_scsi_t scsi; struct grub_scsi_write10 wr; + grub_err_t err; + grub_err_t err_sense; scsi = disk->data; @@ -162,7 +267,16 @@ grub_scsi_write10 (grub_disk_t disk, grub_disk_addr_t sector, wr.reserved2 = 0; wr.pad = 0; - return scsi->dev->write (scsi, sizeof (wr), (char *) &wr, size * scsi->blocksize, buf); + err = scsi->dev->write (scsi, sizeof (wr), (char *) &wr, size * scsi->blocksize, buf); + + /* Each SCSI command should be followed by Request Sense. + If not so, many devices STALLs or definitely freezes. */ + err_sense = grub_scsi_request_sense (scsi); + if (err_sense != GRUB_ERR_NONE) + grub_errno = err; + /* err_sense is ignored for now and Request Sense Data also... */ + + return err; } /* Send a SCSI request for DISK: write the data stored in BUF to SIZE @@ -172,7 +286,9 @@ grub_scsi_write12 (grub_disk_t disk, grub_disk_addr_t sector, grub_size_t size, char *buf) { grub_scsi_t scsi; - struct grub_scsi_write10 wr; + struct grub_scsi_write12 wr; + grub_err_t err; + grub_err_t err_sense; scsi = disk->data; @@ -181,9 +297,18 @@ grub_scsi_write12 (grub_disk_t disk, grub_disk_addr_t sector, wr.lba = grub_cpu_to_be32 (sector); wr.size = grub_cpu_to_be32 (size); wr.reserved = 0; - wr.pad = 0; + wr.control = 0; - return scsi->dev->write (scsi, sizeof (wr), (char *) &wr, size * scsi->blocksize, buf); + err = scsi->dev->write (scsi, sizeof (wr), (char *) &wr, size * scsi->blocksize, buf); + + /* Each SCSI command should be followed by Request Sense. + If not so, many devices STALLs or definitely freezes. */ + err_sense = grub_scsi_request_sense (scsi); + if (err_sense != GRUB_ERR_NONE) + grub_errno = err; + /* err_sense is ignored for now and Request Sense Data also... */ + + return err; } #endif @@ -235,6 +360,7 @@ grub_scsi_open (const char *name, grub_disk_t disk) grub_err_t err; int len; int lun; + grub_uint64_t maxtime; scsi = grub_malloc (sizeof (*scsi)); if (! scsi) @@ -292,6 +418,31 @@ grub_scsi_open (const char *name, grub_disk_t disk) else disk->has_partitions = 1; + + /* According to USB MS tests specification, issue Test Unit Ready + * until OK */ + maxtime = grub_get_time_ms () + 5000; /* It is safer value */ + do + { + /* Timeout is necessary - for example in case when we have + * universal card reader with more LUNs and we have only + * one card inserted (or none), so only one LUN (or none) + * will be ready - and we want not to hang... */ + if (grub_get_time_ms () > maxtime) + { + err = GRUB_ERR_READ_ERROR; + grub_free (scsi); + grub_dprintf ("scsi", "LUN is not ready - timeout\n"); + return err; + } + err = grub_scsi_test_unit_ready (scsi); + } + while (err == GRUB_ERR_READ_ERROR); + /* Reset grub_errno ! + * It is set to some error code in loop before... */ + grub_errno = GRUB_ERR_NONE; + + /* Read capacity of media */ err = grub_scsi_read_capacity (scsi); if (err) { @@ -302,12 +453,14 @@ grub_scsi_open (const char *name, grub_disk_t disk) /* SCSI blocks can be something else than 512, although GRUB wants 512 byte blocks. */ - disk->total_sectors = ((scsi->size * scsi->blocksize) - << GRUB_DISK_SECTOR_BITS); + disk->total_sectors = ((grub_uint64_t)scsi->size + * (grub_uint64_t)scsi->blocksize) + >> GRUB_DISK_SECTOR_BITS; - grub_dprintf ("scsi", "capacity=%llu, blksize=%d\n", - (unsigned long long) disk->total_sectors, - scsi->blocksize); + grub_dprintf ("scsi", "blocks=%u, blocksize=%u\n", + scsi->size, scsi->blocksize); + grub_dprintf ("scsi", "Disk total 512 sectors = %llu\n", + (unsigned long long) disk->total_sectors); return GRUB_ERR_NONE; } @@ -366,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 8554b224f..a49b30e7e 100644 --- a/disk/usbms.c +++ b/disk/usbms.c @@ -84,7 +84,8 @@ grub_usbms_finddevs (void) struct grub_usb_desc_device *descdev = &usbdev->descdev; int i; - if (descdev->class != 0 || descdev->subclass || descdev->protocol != 0) + if (descdev->class != 0 || descdev->subclass || descdev->protocol != 0 + || descdev->configcnt == 0) return 0; /* XXX: Just check configuration 0 for now. */ @@ -93,19 +94,31 @@ grub_usbms_finddevs (void) struct grub_usbms_dev *usbms; struct grub_usb_desc_if *interf; int j; - grub_uint8_t luns; + grub_uint8_t luns = 0; + + grub_dprintf ("usbms", "alive\n"); interf = usbdev->config[0].interf[i].descif; /* If this is not a USB Mass Storage device with a supported protocol, just skip it. */ + grub_dprintf ("usbms", "iterate: interf=%d, class=%d, subclass=%d, protocol=%d\n", + i, interf->class, interf->subclass, interf->protocol); + if (interf->class != GRUB_USB_CLASS_MASS_STORAGE - || interf->subclass != GRUB_USBMS_SUBCLASS_BULK + || ( interf->subclass != GRUB_USBMS_SUBCLASS_BULK && + /* Experimental support of RBC, MMC-2, UFI, SFF-8070i devices */ + interf->subclass != GRUB_USBMS_SUBCLASS_RBC && + interf->subclass != GRUB_USBMS_SUBCLASS_MMC2 && + interf->subclass != GRUB_USBMS_SUBCLASS_UFI && + interf->subclass != GRUB_USBMS_SUBCLASS_SFF8070 ) || interf->protocol != GRUB_USBMS_PROTOCOL_BULK) { continue; } + grub_dprintf ("usbms", "alive\n"); + devcnt++; usbms = grub_zalloc (sizeof (struct grub_usbms_dev)); if (! usbms) @@ -114,6 +127,8 @@ grub_usbms_finddevs (void) usbms->dev = usbdev; usbms->interface = i; + grub_dprintf ("usbms", "alive\n"); + /* Iterate over all endpoints of this interface, at least a IN and OUT bulk endpoint are required. */ for (j = 0; j < interf->endpointcnt; j++) @@ -125,14 +140,16 @@ grub_usbms_finddevs (void) { /* Bulk IN endpoint. */ usbms->in = endp; - grub_usb_clear_halt (usbdev, endp->endp_addr & 128); + /* Clear Halt is not possible yet! */ + /* grub_usb_clear_halt (usbdev, endp->endp_addr); */ usbms->in_maxsz = endp->maxpacket; } else if (!(endp->endp_addr & 128) && (endp->attrib & 3) == 2) { /* Bulk OUT endpoint. */ usbms->out = endp; - grub_usb_clear_halt (usbdev, endp->endp_addr & 128); + /* Clear Halt is not possible yet! */ + /* grub_usb_clear_halt (usbdev, endp->endp_addr); */ usbms->out_maxsz = endp->maxpacket; } } @@ -143,51 +160,63 @@ grub_usbms_finddevs (void) return 0; } + grub_dprintf ("usbms", "alive\n"); + + /* XXX: Activate the first configuration. */ + grub_usb_set_configuration (usbdev, 1); + /* Query the amount of LUNs. */ err = grub_usb_control_msg (usbdev, 0xA1, 254, 0, i, 1, (char *) &luns); + if (err) { /* In case of a stall, clear the stall. */ if (err == GRUB_USB_ERR_STALL) { - grub_usb_clear_halt (usbdev, usbms->in->endp_addr & 3); - grub_usb_clear_halt (usbdev, usbms->out->endp_addr & 3); + grub_usb_clear_halt (usbdev, usbms->in->endp_addr); + grub_usb_clear_halt (usbdev, usbms->out->endp_addr); } - /* Just set the amount of LUNs to one. */ grub_errno = GRUB_ERR_NONE; usbms->luns = 1; } else - usbms->luns = luns; + /* luns = 0 means one LUN with ID 0 present ! */ + /* We get from device not number of LUNs but highest + * LUN number. LUNs are numbered from 0, + * i.e. number of LUNs is luns+1 ! */ + usbms->luns = luns + 1; - /* XXX: Check the magic values, does this really make - sense? */ - grub_usb_control_msg (usbdev, (1 << 6) | 1, 255, - 0, i, 0, 0); - - /* XXX: To make Qemu work? */ - if (usbms->luns == 0) - usbms->luns = 1; + grub_dprintf ("usbms", "alive\n"); usbms->next = grub_usbms_dev_list; grub_usbms_dev_list = usbms; - /* XXX: Activate the first configuration. */ - grub_usb_set_configuration (usbdev, 1); - +#if 0 /* All this part should be probably deleted. + * This make trouble on some devices if they are not in + * Phase Error state - and there they should be not in such state... + * Bulk only mass storage reset procedure should be used only + * on place and in time when it is really necessary. */ + /* Reset recovery procedure */ /* Bulk-Only Mass Storage Reset, after the reset commands will be accepted. */ grub_usbms_reset (usbdev, i); + grub_usb_clear_halt (usbdev, usbms->in->endp_addr); + grub_usb_clear_halt (usbdev, usbms->out->endp_addr); +#endif return 0; } + grub_dprintf ("usbms", "alive\n"); return 0; } + grub_dprintf ("usbms", "alive\n"); grub_usb_iterate (usb_iterate); + grub_dprintf ("usbms", "alive\n"); + } @@ -224,7 +253,9 @@ 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; retry: retrycnt--; @@ -237,73 +268,102 @@ grub_usbms_transfer (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, cbw.tag = tag++; cbw.transfer_length = grub_cpu_to_le32 (size); cbw.flags = (!read_write) << GRUB_USBMS_DIRECTION_BIT; - cbw.lun = scsi->lun << GRUB_SCSI_LUN_SHIFT; + cbw.lun = scsi->lun; /* In USB MS CBW are LUN bits on another place than in SCSI CDB, both should be set correctly. */ cbw.length = cmdsize; grub_memcpy (cbw.cbwcb, cmd, cmdsize); + + /* Debug print of CBW content. */ + grub_dprintf ("usb", "CBW: sign=0x%08x tag=0x%08x len=0x%08x\n", + cbw.signature, cbw.tag, cbw.transfer_length); + grub_dprintf ("usb", "CBW: flags=0x%02x lun=0x%02x CB_len=0x%02x\n", + cbw.flags, cbw.lun, cbw.length); + grub_dprintf ("usb", "CBW: cmd:\n %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + cbw.cbwcb[ 0], cbw.cbwcb[ 1], cbw.cbwcb[ 2], cbw.cbwcb[ 3], + cbw.cbwcb[ 4], cbw.cbwcb[ 5], cbw.cbwcb[ 6], cbw.cbwcb[ 7], + cbw.cbwcb[ 8], cbw.cbwcb[ 9], cbw.cbwcb[10], cbw.cbwcb[11], + cbw.cbwcb[12], cbw.cbwcb[13], cbw.cbwcb[14], cbw.cbwcb[15]); - /* Write the request. */ - err = grub_usb_bulk_write (dev->dev, dev->out->endp_addr & 15, + /* Write the request. + * XXX: Error recovery is maybe still not fully correct. */ + err = grub_usb_bulk_write (dev->dev, dev->out->endp_addr, sizeof (cbw), (char *) &cbw); if (err) { if (err == GRUB_USB_ERR_STALL) { 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"); } - /* Read/write the data. */ - if (read_write == 0) + /* Read/write the data, (maybe) according to specification. */ + if (size && (read_write == 0)) { - err = grub_usb_bulk_read (dev->dev, dev->in->endp_addr & 15, size, buf); - grub_dprintf ("usb", "read: %d %d\n", err, GRUB_USB_ERR_STALL); + 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) - { - if (err == GRUB_USB_ERR_STALL) - { - grub_usb_clear_halt (dev->dev, dev->in->endp_addr); - goto retry; - } - return grub_error (GRUB_ERR_READ_ERROR, - "can't read from USB Mass Storage device"); - } + { + 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) + for (i=0; idev, dev->in->endp_addr & 15, size, buf); + 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 retry; - } - return grub_error (GRUB_ERR_WRITE_ERROR, - "can't write to USB Mass Storage device"); - } + { + 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 & 15, - sizeof (status), (char *) &status); - if (err) + /* Read the status - (maybe) according to specification. */ +CheckCSW: + errCSW = grub_usb_bulk_read (dev->dev, dev->in->endp_addr, + sizeof (status), (char *) &status); + if (errCSW) { - if (err == GRUB_USB_ERR_STALL) - { - grub_usb_clear_halt (dev->dev, dev->in->endp_addr); + grub_usb_clear_halt (dev->dev, dev->in->endp_addr); + errCSW = grub_usb_bulk_read (dev->dev, dev->in->endp_addr, + sizeof (status), (char *) &status); + 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); goto retry; - } - return grub_error (GRUB_ERR_READ_ERROR, - "can't read status from USB Mass Storage device"); + } } - /* XXX: Magic and check this code. */ - if (status.status == 2) - { - /* XXX: Phase error, reset device. */ + /* Debug print of CSW content. */ + grub_dprintf ("usb", "CSW: sign=0x%08x tag=0x%08x resid=0x%08x\n", + status.signature, status.tag, status.residue); + grub_dprintf ("usb", "CSW: status=0x%02x\n", status.status); + + /* 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); @@ -311,9 +371,13 @@ grub_usbms_transfer (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd, 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 704f8b2a3..822849777 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 @@ -80,15 +79,18 @@ This edition documents version @value{VERSION}. * Configuration:: Writing your own configuration file * 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 @@ -172,6 +174,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 @@ -388,14 +406,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, @@ -452,6 +470,7 @@ the @dfn{boot directory}. @menu * Installing GRUB using grub-install:: +* Making a GRUB bootable CD-ROM:: @end menu @@ -531,11 +550,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 @@ -648,6 +667,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 @@ -656,6 +704,7 @@ Here, we describe some caveats on several operating systems. @menu * GNU/Hurd:: * GNU/Linux:: +* DOS/Windows:: @end menu @@ -697,6 +746,328 @@ 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 +@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, 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 +Disable the generation of recovery mode menu entries for Linux. + +@item GRUB_DISABLE_NETBSD_RECOVERY +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 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 @@ -733,7 +1104,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 @@ -747,6 +1119,25 @@ 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. +GRUB supports such buttons with GRUB_TIMEOUT_BUTTON, GRUB_DEFAULT_BUTTON, +GRUB_HIDDEN_TIMEOUT_BUTTON and GRUB_BUTTON_CMOS_ADDRESS variables in +default/grub. GRUB_TIMEOUT_BUTTON, GRUB_DEFAULT_BUTTON and +GRUB_HIDDEN_TIMEOUT_BUTTON are used instead of corresponding variables without +_BUTTON suffix when powered using special button. +GRUB_BUTTON_CMOS_ADDRESS is vendor specific and partially model-specific. +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 Filesystem @chapter Filesystem syntax and semantics @@ -755,8 +1146,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 @@ -804,7 +1195,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. @@ -824,8 +1215,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 @@ -866,6 +1257,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 @@ -996,6 +1388,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:: @@ -1058,14 +1454,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 @@ -1074,31 +1472,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 @@ -1117,19 +1552,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 @@ -1191,11 +1636,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 @@ -1229,6 +1674,20 @@ Load @var{file} as a configuration file. @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 + + @node crc @subsection crc @@ -1250,6 +1709,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 @@ -1302,6 +1787,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 @@ -1315,15 +1832,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 @@ -1365,6 +1880,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 @@ -1384,6 +1953,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 @@ -1392,6 +1971,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 @@ -1409,12 +2011,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} @@ -1450,6 +2195,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 @@ -1487,8 +2286,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 @@ -1568,6 +2368,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/gfxmenu/gfxmenu.c b/gfxmenu/gfxmenu.c index a2e765156..1acab9ca7 100644 --- a/gfxmenu/gfxmenu.c +++ b/gfxmenu/gfxmenu.c @@ -110,6 +110,13 @@ grub_gfxmenu_try (int entry, grub_menu_t menu, int nested) view->nested = nested; view->first_timeout = -1; + grub_video_set_viewport (0, 0, mode_info.width, mode_info.height); + if (view->double_repaint) + { + grub_video_swap_buffers (); + grub_video_set_viewport (0, 0, mode_info.width, mode_info.height); + } + grub_gfxmenu_view_draw (view); instance->data = view; diff --git a/gfxmenu/gui_list.c b/gfxmenu/gui_list.c index 0d771413f..8583a214e 100644 --- a/gfxmenu/gui_list.c +++ b/gfxmenu/gui_list.c @@ -210,8 +210,7 @@ draw_scrollbar (list_impl_t self, /* Draw the list of items. */ static void -draw_menu (list_impl_t self, int width, int drawing_scrollbar, - int num_shown_items) +draw_menu (list_impl_t self, int width, int num_shown_items) { if (! self->menu_box || ! self->selected_item_box) return; @@ -226,8 +225,6 @@ draw_menu (list_impl_t self, int width, int drawing_scrollbar, make_selected_item_visible (self); - int scrollbar_h_space = drawing_scrollbar ? self->scrollbar_width : 0; - grub_gfxmenu_box_t selbox = self->selected_item_box; int sel_leftpad = selbox->get_left_pad (selbox); int item_top = boxpad; @@ -244,12 +241,8 @@ draw_menu (list_impl_t self, int width, int drawing_scrollbar, if (is_selected) { int sel_toppad = selbox->get_top_pad (selbox); - selbox->set_content_size (selbox, - (width - 2 * boxpad - - scrollbar_h_space), - item_height); - selbox->draw (selbox, - item_left - sel_leftpad, + selbox->set_content_size (selbox, (width - 2 * boxpad), item_height); + selbox->draw (selbox, item_left - sel_leftpad, item_top - sel_toppad); } @@ -320,7 +313,7 @@ list_paint (void *vself, const grub_video_rect_t *region) box->draw (box, 0, 0); grub_gui_set_viewport (&content_rect, &vpsave2); - draw_menu (self, content_rect.width, drawing_scrollbar, num_shown_items); + draw_menu (self, content_rect.width, num_shown_items); grub_gui_restore_viewport (&vpsave2); if (drawing_scrollbar) diff --git a/gfxmenu/view.c b/gfxmenu/view.c index 9a5671cdd..518c3ba53 100644 --- a/gfxmenu/view.c +++ b/gfxmenu/view.c @@ -357,11 +357,6 @@ grub_gfxmenu_draw_terminal_box (void) term_box->draw (term_box, term_rect.x - term_box->get_left_pad (term_box), term_rect.y - term_box->get_top_pad (term_box)); - grub_video_swap_buffers (); - if (term_view->double_repaint) - term_box->draw (term_box, - term_rect.x - term_box->get_left_pad (term_box), - term_rect.y - term_box->get_top_pad (term_box)); } static void 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/cs5536.h b/include/grub/cs5536.h new file mode 100644 index 000000000..cd17e11fc --- /dev/null +++ b/include/grub/cs5536.h @@ -0,0 +1,190 @@ +/* + * 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_CS5536_HEADER +#define GRUB_CS5536_HEADER 1 + +#ifndef ASM_FILE +#include +#include +#include +#endif + +#define GRUB_CS5536_PCIID 0x208f1022 +#define GRUB_CS5536_MSR_MAILBOX_ADDR 0xf4 +#define GRUB_CS5536_MSR_MAILBOX_DATA0 0xf8 +#define GRUB_CS5536_MSR_MAILBOX_DATA1 0xfc +#define GRUB_CS5536_MSR_IRQ_MAP_BAR 0x80000008 +#define GRUB_CS5536_MSR_SMB_BAR 0x8000000b + +#define GRUB_CS5536_SMBUS_REGS_SIZE 8 +#define GRUB_CS5536_GPIO_REGS_SIZE 256 +#define GRUB_CS5536_MFGPT_REGS_SIZE 64 +#define GRUB_CS5536_IRQ_MAP_REGS_SIZE 32 +#define GRUB_CS5536_PM_REGS_SIZE 128 +#define GRUB_CS5536_ACPI_REGS_SIZE 32 + +#define GRUB_CS5536_USB_OPTION_REGS_SIZE 0x1c +#define GRUB_CS5536_USB_OPTION_REG_UOCMUX 1 +#define GRUB_CS5536_USB_OPTION_REG_UOCMUX_PMUX_MASK 0x03 +#define GRUB_CS5536_USB_OPTION_REG_UOCMUX_PMUX_HC 0x02 + +#define GRUB_CS5536_DESTINATION_GLIU 0 +#define GRUB_CS5536_DESTINATION_GLPCI_SB 1 +#define GRUB_CS5536_DESTINATION_USB 2 +#define GRUB_CS5536_DESTINATION_IDE 3 +#define GRUB_CS5536_DESTINATION_DD 4 +#define GRUB_CS5536_DESTINATION_ACC 5 +#define GRUB_CS5536_DESTINATION_GLCP 7 + +#define GRUB_CS5536_P2D_DEST_SHIFT 61 +#define GRUB_CS5536_P2D_LOG_ALIGN 12 +#define GRUB_CS5536_P2D_ALIGN (1 << GRUB_CS5536_P2D_LOG_ALIGN) +#define GRUB_CS5536_P2D_BASE_SHIFT 20 +#define GRUB_CS5536_P2D_MASK_SHIFT 0 + +#define GRUB_CS5536_MSR_GL_IOD_START 0x000100e0 +#define GRUB_CS5536_IOD_DEST_SHIFT 61 +#define GRUB_CS5536_IOD_BASE_SHIFT 20 +#define GRUB_CS5536_IOD_MASK_SHIFT 0 +#define GRUB_CS5536_IOD_ADDR_MASK 0xfffff + +#define GRUB_CS5536_MSR_GPIO_BAR 0x8000000c +#define GRUB_CS5536_MSR_MFGPT_BAR 0x8000000d +#define GRUB_CS5536_MSR_ACPI_BAR 0x8000000e +#define GRUB_CS5536_MSR_PM_BAR 0x8000000f +#define GRUB_CS5536_MSR_DIVIL_LEG_IO 0x80000014 +#define GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE0 0x00000001 +#define GRUB_CS5536_MSR_DIVIL_LEG_IO_RTC_ENABLE1 0x00000002 +#define GRUB_CS5536_MSR_DIVIL_LEG_IO_MODE_X86 0x10000000 +#define GRUB_CS5536_MSR_DIVIL_LEG_IO_F_REMAP 0x04000000 +#define GRUB_CS5536_MSR_DIVIL_IRQ_MAPPER_PRIMARY_MASK 0x80000024 +#define GRUB_CS5536_MSR_DIVIL_IRQ_MAPPER_LPC_MASK 0x80000025 +#define GRUB_CS5536_DIVIL_LPC_INTERRUPTS 0x1002 +#define GRUB_CS5536_MSR_DIVIL_LPC_SERIAL_IRQ_CONTROL 0x8000004e +#define GRUB_CS5536_MSR_DIVIL_LPC_SERIAL_IRQ_CONTROL_ENABLE 0x80 + +#define GRUB_CS5536_MSR_USB_OHCI_BASE 0x40000008 +#define GRUB_CS5536_MSR_USB_EHCI_BASE 0x40000009 +#define GRUB_CS5536_MSR_USB_CONTROLLER_BASE 0x4000000a +#define GRUB_CS5536_MSR_USB_OPTION_CONTROLLER_BASE 0x4000000b +#define GRUB_CS5536_MSR_USB_BASE_ADDR_MASK 0x00ffffff00ULL +#define GRUB_CS5536_MSR_USB_BASE_BUS_MASTER 0x0400000000ULL +#define GRUB_CS5536_MSR_USB_BASE_MEMORY_ENABLE 0x0200000000ULL +#define GRUB_CS5536_MSR_USB_BASE_PME_ENABLED 0x0800000000ULL +#define GRUB_CS5536_MSR_USB_BASE_PME_STATUS 0x1000000000ULL +#define GRUB_CS5536_MSR_USB_EHCI_BASE_FLDJ_SHIFT 40 + +#define GRUB_CS5536_MSR_IDE_IO_BAR 0x60000008 +#define GRUB_CS5536_MSR_IDE_IO_BAR_UNITS 1 +#define GRUB_CS5536_MSR_IDE_IO_BAR_ADDR_MASK 0xfffffff0 +#define GRUB_CS5536_MSR_IDE_CFG 0x60000010 +#define GRUB_CS5536_MSR_IDE_CFG_CHANNEL_ENABLE 2 +#define GRUB_CS5536_MSR_IDE_TIMING 0x60000012 +#define GRUB_CS5536_MSR_IDE_TIMING_PIO0 0x98 +#define GRUB_CS5536_MSR_IDE_TIMING_DRIVE0_SHIFT 24 +#define GRUB_CS5536_MSR_IDE_TIMING_DRIVE1_SHIFT 16 +#define GRUB_CS5536_MSR_IDE_CAS_TIMING 0x60000013 +#define GRUB_CS5536_MSR_IDE_CAS_TIMING_CMD_PIO0 0x99 +#define GRUB_CS5536_MSR_IDE_CAS_TIMING_CMD_SHIFT 24 +#define GRUB_CS5536_MSR_IDE_CAS_TIMING_DRIVE0_SHIFT 6 +#define GRUB_CS5536_MSR_IDE_CAS_TIMING_DRIVE1_SHIFT 4 +#define GRUB_CS5536_MSR_IDE_CAS_TIMING_PIO0 2 + +#define GRUB_CS5536_MSR_GL_PCI_CTRL 0x00000010 +#define GRUB_CS5536_MSR_GL_PCI_CTRL_MEMORY_ENABLE 1 +#define GRUB_CS5536_MSR_GL_PCI_CTRL_IO_ENABLE 2 +#define GRUB_CS5536_MSR_GL_PCI_CTRL_LATENCY_SHIFT 35 +#define GRUB_CS5536_MSR_GL_PCI_CTRL_OUT_THR_SHIFT 60 +#define GRUB_CS5536_MSR_GL_PCI_CTRL_IN_THR_SHIFT 56 + +#define GRUB_CS5536_MSR_GL_REGIONS_START 0x00000020 +#define GRUB_CS5536_MSR_GL_REGIONS_NUM 16 +#define GRUB_CS5536_MSR_GL_REGION_ENABLE 1 +#define GRUB_CS5536_MSR_GL_REGION_IO 0x100000000ULL +#define GRUB_CS5536_MSR_GL_REGION_BASE_MASK 0xfffff000ULL +#define GRUB_CS5536_MSR_GL_REGION_IO_BASE_SHIFT 12 +#define GRUB_CS5536_MSR_GL_REGION_TOP_MASK 0xfffff00000000000ULL +#define GRUB_CS5536_MSR_GL_REGION_IO_TOP_SHIFT 44 + +#define GRUB_CS5536_MSR_GL_P2D_START 0x00010020 + +#define GRUB_CS5536_SMB_REG_DATA 0x0 +#define GRUB_CS5536_SMB_REG_STATUS 0x1 +#define GRUB_CS5536_SMB_REG_STATUS_SDAST (1 << 6) +#define GRUB_CS5536_SMB_REG_STATUS_BER (1 << 5) +#define GRUB_CS5536_SMB_REG_STATUS_NACK (1 << 4) +#define GRUB_CS5536_SMB_REG_CTRL1 0x3 +#define GRUB_CS5536_SMB_REG_CTRL1_START 0x01 +#define GRUB_CS5536_SMB_REG_CTRL1_STOP 0x02 +#define GRUB_CS5536_SMB_REG_CTRL1_ACK 0x10 +#define GRUB_CS5536_SMB_REG_ADDR 0x4 +#define GRUB_CS5536_SMB_REG_ADDR_MASTER 0x0 +#define GRUB_CS5536_SMB_REG_CTRL2 0x5 +#define GRUB_CS5536_SMB_REG_CTRL2_ENABLE 0x1 +#define GRUB_CS5536_SMB_REG_CTRL3 0x6 + +#ifdef ASM_FILE +#define GRUB_ULL(x) x +#else +#define GRUB_ULL(x) x ## ULL +#endif + +#define GRUB_CS5536_LBAR_ADDR_MASK GRUB_ULL (0x000000000000fff8) +#define GRUB_CS5536_LBAR_ENABLE GRUB_ULL (0x0000000100000000) +#define GRUB_CS5536_LBAR_MASK_MASK GRUB_ULL (0x0000f00000000000) +#define GRUB_CS5536_LBAR_TURN_ON (GRUB_CS5536_LBAR_ENABLE | GRUB_CS5536_LBAR_MASK_MASK) + +/* PMON-compatible LBARs. */ +#define GRUB_CS5536_LBAR_GPIO 0xb000 +#define GRUB_CS5536_LBAR_ACC 0xb200 +#define GRUB_CS5536_LBAR_PM 0xb280 +#define GRUB_CS5536_LBAR_MFGPT 0xb300 +#define GRUB_CS5536_LBAR_ACPI 0xb340 +#define GRUB_CS5536_LBAR_IRQ_MAP 0xb360 +#define GRUB_CS5536_LBAR_IDE 0xb380 +#define GRUB_CS5536_LBAR_SMBUS 0xb390 + +#define GRUB_GPIO_SMBUS_PINS ((1 << 14) | (1 << 15)) +#define GRUB_GPIO_REG_OUT_EN 0x4 +#define GRUB_GPIO_REG_OUT_AUX1 0x10 +#define GRUB_GPIO_REG_IN_EN 0x20 +#define GRUB_GPIO_REG_IN_AUX1 0x34 + +#ifndef ASM_FILE +int EXPORT_FUNC (grub_cs5536_find) (grub_pci_device_t *devp); + +grub_uint64_t EXPORT_FUNC (grub_cs5536_read_msr) (grub_pci_device_t dev, + grub_uint32_t addr); +void EXPORT_FUNC (grub_cs5536_write_msr) (grub_pci_device_t dev, + grub_uint32_t addr, + grub_uint64_t val); +grub_err_t grub_cs5536_read_spd_byte (grub_port_t smbbase, grub_uint8_t dev, + grub_uint8_t addr, grub_uint8_t *res); +grub_err_t EXPORT_FUNC (grub_cs5536_read_spd) (grub_port_t smbbase, + grub_uint8_t dev, + struct grub_smbus_spd *res); +grub_err_t grub_cs5536_smbus_wait (grub_port_t smbbase); +grub_err_t EXPORT_FUNC (grub_cs5536_init_smbus) (grub_pci_device_t dev, + grub_uint16_t divisor, + grub_port_t *smbbase); + +void grub_cs5536_init_geode (grub_pci_device_t dev); +#endif + +#endif 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 e037e6be7..f34cd4287 100644 --- a/include/grub/emu/misc.h +++ b/include/grub/emu/misc.h @@ -46,5 +46,10 @@ int EXPORT_FUNC(asprintf) (char **buf, const char *fmt, ...); #endif 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/i18n.h b/include/grub/i18n.h index 57ca1c45b..a91d73346 100644 --- a/include/grub/i18n.h +++ b/include/grub/i18n.h @@ -22,10 +22,10 @@ #include #include -extern const char *(*EXPORT_VAR(grub_gettext)) (const char *s); - /* NLS can be disabled through the configure --disable-nls option. */ -#if (defined(ENABLE_NLS) && ENABLE_NLS) +#if (defined(ENABLE_NLS) && ENABLE_NLS) || !defined (GRUB_UTIL) + +extern const char *(*EXPORT_VAR(grub_gettext)) (const char *s); # ifdef GRUB_UTIL @@ -41,19 +41,11 @@ extern const char *(*EXPORT_VAR(grub_gettext)) (const char *s); for invalid uses of the value returned from these functions. On pre-ANSI systems without 'const', the config.h file is supposed to contain "#define const". */ -# ifdef GRUB_UTIL static inline const char * __attribute__ ((always_inline)) gettext (const char *str) { return str; } -# else -static inline const char * __attribute__ ((always_inline)) -grub_gettext (const char *str) -{ - return str; -} -# endif /* GRUB_UTIL */ #endif /* (defined(ENABLE_NLS) && ENABLE_NLS) */ diff --git a/include/grub/i386/pci.h b/include/grub/i386/pci.h index bab42adb6..795dec58b 100644 --- a/include/grub/i386/pci.h +++ b/include/grub/i386/pci.h @@ -80,7 +80,7 @@ grub_pci_device_map_range (grub_pci_device_t dev __attribute__ ((unused)), static inline void grub_pci_device_unmap_range (grub_pci_device_t dev __attribute__ ((unused)), - void *mem __attribute__ ((unused)), + volatile void *mem __attribute__ ((unused)), grub_size_t size __attribute__ ((unused))) { } 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/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/mips/yeeloong/pci.h b/include/grub/mips/yeeloong/pci.h index c7bd31d4f..199bac048 100644 --- a/include/grub/mips/yeeloong/pci.h +++ b/include/grub/mips/yeeloong/pci.h @@ -19,16 +19,30 @@ #ifndef GRUB_MACHINE_PCI_H #define GRUB_MACHINE_PCI_H 1 +#ifndef ASM_FILE #include #include +#endif + +#define GRUB_YEELOONG_OHCI_PCIID 0x00351033 +#define GRUB_YEELOONG_EHCI_PCIID 0x00e01033 +#define GRUB_YEELOONG_OHCI_GHOST_FUNCTION 4 +#define GRUB_YEELOONG_EHCI_GHOST_FUNCTION 5 #define GRUB_PCI_NUM_BUS 1 #define GRUB_PCI_NUM_DEVICES 16 -#define GRUB_MACHINE_PCI_IO_BASE 0xbfd00000 -#define GRUB_MACHINE_PCI_CONFSPACE 0xbfe80000 -#define GRUB_MACHINE_PCI_CONF_CTRL_REG (*(volatile grub_uint32_t *) 0xbfe00118) +#define GRUB_MACHINE_PCI_IO_BASE 0xbfd00000 +#define GRUB_MACHINE_PCI_CONFSPACE 0xbfe80000 +#define GRUB_MACHINE_PCI_CONTROLLER_HEADER 0xbfe00000 + +#define GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR 0xbfe00118 + +#ifndef ASM_FILE +#define GRUB_MACHINE_PCI_CONF_CTRL_REG (*(volatile grub_uint32_t *) \ + GRUB_MACHINE_PCI_CONF_CTRL_REG_ADDR) #define GRUB_MACHINE_PCI_IO_CTRL_REG (*(volatile grub_uint32_t *) 0xbfe00110) +#endif #define GRUB_MACHINE_PCI_WIN_MASK_SIZE 6 #define GRUB_MACHINE_PCI_WIN_MASK ((1 << GRUB_MACHINE_PCI_WIN_MASK_SIZE) - 1) @@ -46,6 +60,7 @@ #define GRUB_MACHINE_PCI_WIN2_ADDR 0xb4000000 #define GRUB_MACHINE_PCI_WIN3_ADDR 0xb8000000 +#ifndef ASM_FILE static inline grub_uint32_t grub_pci_read (grub_pci_address_t addr) { @@ -95,11 +110,12 @@ grub_pci_write_byte (grub_pci_address_t addr, grub_uint8_t data) } volatile void * -grub_pci_device_map_range (grub_pci_device_t dev __attribute__ ((unused)), - grub_addr_t base, grub_size_t size); +EXPORT_FUNC (grub_pci_device_map_range) (grub_pci_device_t dev, + grub_addr_t base, grub_size_t size); void -grub_pci_device_unmap_range (grub_pci_device_t dev __attribute__ ((unused)), - volatile void *mem, - grub_size_t size __attribute__ ((unused))); +EXPORT_FUNC (grub_pci_device_unmap_range) (grub_pci_device_t dev, + volatile void *mem, + grub_size_t size); +#endif #endif /* GRUB_MACHINE_PCI_H */ diff --git a/include/grub/parser.h b/include/grub/parser.h index 17f0c4303..064f73fcb 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); -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/pci.h b/include/grub/pci.h index 89bd1034a..e6d6488f0 100644 --- a/include/grub/pci.h +++ b/include/grub/pci.h @@ -19,8 +19,10 @@ #ifndef GRUB_PCI_H #define GRUB_PCI_H 1 +#ifndef ASM_FILE #include #include +#endif #define GRUB_PCI_ADDR_SPACE_MASK 0x01 #define GRUB_PCI_ADDR_SPACE_MEMORY 0x00 @@ -66,6 +68,20 @@ #define GRUB_PCI_REG_MIN_GNT 0x3e #define GRUB_PCI_REG_MAX_LAT 0x3f +#define GRUB_PCI_COMMAND_IO_ENABLED 0x0001 +#define GRUB_PCI_COMMAND_MEM_ENABLED 0x0002 +#define GRUB_PCI_COMMAND_BUS_MASTER 0x0004 +#define GRUB_PCI_COMMAND_PARITY_ERROR 0x0040 +#define GRUB_PCI_COMMAND_SERR_ENABLE 0x0100 + +#define GRUB_PCI_STATUS_CAPABILITIES 0x0010 +#define GRUB_PCI_STATUS_66MHZ_CAPABLE 0x0020 +#define GRUB_PCI_STATUS_FAST_B2B_CAPABLE 0x0080 + +#define GRUB_PCI_STATUS_DEVSEL_TIMING_SHIFT 9 +#define GRUB_PCI_STATUS_DEVSEL_TIMING_MASK 0x0600 + +#ifndef ASM_FILE typedef grub_uint32_t grub_pci_id_t; #ifdef GRUB_MACHINE_EMU @@ -107,4 +123,14 @@ grub_pci_address_t EXPORT_FUNC(grub_pci_make_address) (grub_pci_device_t dev, void EXPORT_FUNC(grub_pci_iterate) (grub_pci_iteratefunc_t hook); +struct grub_pci_dma_chunk; + +struct grub_pci_dma_chunk *EXPORT_FUNC(grub_memalign_dma32) (grub_size_t align, + grub_size_t size); +void EXPORT_FUNC(grub_dma_free) (struct grub_pci_dma_chunk *ch); +volatile void *EXPORT_FUNC(grub_dma_get_virt) (struct grub_pci_dma_chunk *ch); +grub_uint32_t EXPORT_FUNC(grub_dma_get_phys) (struct grub_pci_dma_chunk *ch); + +#endif + #endif /* GRUB_PCI_H */ 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 40f237a17..9cc5afe72 100644 --- a/include/grub/scsicmd.h +++ b/include/grub/scsicmd.h @@ -25,14 +25,26 @@ #define GRUB_SCSI_REMOVABLE_BIT 7 #define GRUB_SCSI_LUN_SHIFT 5 +struct grub_scsi_test_unit_ready +{ + grub_uint8_t opcode; + grub_uint8_t lun; /* 7-5 LUN, 4-0 reserved */ + grub_uint8_t reserved1; + grub_uint8_t reserved2; + grub_uint8_t reserved3; + grub_uint8_t control; + grub_uint8_t pad[6]; /* To be ATAPI compatible */ +} __attribute__((packed)); + struct grub_scsi_inquiry { grub_uint8_t opcode; - grub_uint8_t lun; - grub_uint16_t reserved; - grub_uint16_t alloc_length; - grub_uint8_t reserved2; - grub_uint8_t pad[5]; + grub_uint8_t lun; /* 7-5 LUN, 4-1 reserved, 0 EVPD */ + grub_uint8_t page; /* page code if EVPD=1 */ + grub_uint8_t reserved; + grub_uint8_t alloc_length; + grub_uint8_t control; + grub_uint8_t pad[6]; /* To be ATAPI compatible */ } __attribute__((packed)); struct grub_scsi_inquiry_data @@ -47,12 +59,42 @@ struct grub_scsi_inquiry_data char prodrev[4]; } __attribute__((packed)); +struct grub_scsi_request_sense +{ + grub_uint8_t opcode; + grub_uint8_t lun; /* 7-5 LUN, 4-0 reserved */ + grub_uint8_t reserved1; + grub_uint8_t reserved2; + grub_uint8_t alloc_length; + grub_uint8_t control; + grub_uint8_t pad[6]; /* To be ATAPI compatible */ +} __attribute__((packed)); + +struct grub_scsi_request_sense_data +{ + grub_uint8_t error_code; /* 7 Valid, 6-0 Err. code */ + grub_uint8_t segment_number; + grub_uint8_t sense_key; /*7 FileMark, 6 EndOfMedia, 5 ILI, 4-0 sense key */ + grub_uint32_t information; + grub_uint8_t additional_sense_length; + grub_uint32_t cmd_specific_info; + grub_uint8_t additional_sense_code; + grub_uint8_t additional_sense_code_qualifier; + grub_uint8_t field_replaceable_unit_code; + grub_uint8_t sense_key_specific[3]; + /* there can be additional sense field */ +} __attribute__((packed)); + struct grub_scsi_read_capacity { grub_uint8_t opcode; - grub_uint8_t lun; - grub_uint8_t reserved[8]; - grub_uint8_t pad[2]; + grub_uint8_t lun; /* 7-5 LUN, 4-1 reserved, 0 reserved */ + grub_uint32_t logical_block_addr; /* only if PMI=1 */ + grub_uint8_t reserved1; + grub_uint8_t reserved2; + grub_uint8_t PMI; + grub_uint8_t control; + grub_uint16_t pad; /* To be ATAPI compatible */ } __attribute__((packed)); struct grub_scsi_read_capacity_data @@ -105,12 +147,14 @@ struct grub_scsi_write12 typedef enum { + grub_scsi_cmd_test_unit_ready = 0x00, + grub_scsi_cmd_request_sense = 0x03, grub_scsi_cmd_inquiry = 0x12, grub_scsi_cmd_read_capacity = 0x25, grub_scsi_cmd_read10 = 0x28, grub_scsi_cmd_write10 = 0x2a, grub_scsi_cmd_read12 = 0xa8, - grub_scsi_cmd_write12 = 0xaa + grub_scsi_cmd_write12 = 0xaa, } grub_scsi_cmd_t; typedef enum diff --git a/include/grub/smbus.h b/include/grub/smbus.h new file mode 100644 index 000000000..0b8e6718f --- /dev/null +++ b/include/grub/smbus.h @@ -0,0 +1,70 @@ +/* + * 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_SMBUS_HEADER +#define GRUB_SMBUS_HEADER 1 + +#define GRUB_SMB_RAM_START_ADDR 0x50 +#define GRUB_SMB_RAM_NUM_MAX 0x08 + +#define GRUB_SMBUS_SPD_MEMORY_TYPE_ADDR 2 +#define GRUB_SMBUS_SPD_MEMORY_TYPE_DDR2 8 +#define GRUB_SMBUS_SPD_MEMORY_NUM_BANKS_ADDR 17 +#define GRUB_SMBUS_SPD_MEMORY_NUM_ROWS_ADDR 3 +#define GRUB_SMBUS_SPD_MEMORY_NUM_COLUMNS_ADDR 4 +#define GRUB_SMBUS_SPD_MEMORY_NUM_OF_RANKS_ADDR 5 +#define GRUB_SMBUS_SPD_MEMORY_NUM_OF_RANKS_MASK 0x7 +#define GRUB_SMBUS_SPD_MEMORY_CAS_LATENCY_ADDR 18 +#define GRUB_SMBUS_SPD_MEMORY_CAS_LATENCY_MIN_VALUE 5 +#define GRUB_SMBUS_SPD_MEMORY_TRAS_ADDR 30 +#define GRUB_SMBUS_SPD_MEMORY_TRTP_ADDR 38 + +#ifndef ASM_FILE + +struct grub_smbus_spd +{ + grub_uint8_t written_size; + grub_uint8_t log_total_flash_size; + grub_uint8_t memory_type; + union + { + grub_uint8_t unknown[253]; + struct { + grub_uint8_t num_rows; + grub_uint8_t num_columns; + grub_uint8_t num_of_ranks; + grub_uint8_t unused1[12]; + grub_uint8_t num_of_banks; + grub_uint8_t unused2[2]; + grub_uint8_t cas_latency; + grub_uint8_t unused3[9]; + grub_uint8_t rank_capacity; + grub_uint8_t unused4[1]; + grub_uint8_t tras; + grub_uint8_t unused5[7]; + grub_uint8_t trtp; + grub_uint8_t unused6[31]; + grub_uint8_t part_number[18]; + grub_uint8_t unused7[165]; + } ddr2; + }; +}; + +#endif + +#endif diff --git a/include/grub/term.h b/include/grub/term.h index 143aabe1e..4a05909da 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 @@ -245,10 +245,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 dc90e7879..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 @@ -156,7 +157,7 @@ struct grub_usb_device int initialized; /* Data toggle values (used for bulk transfers only). */ - int toggle[16]; + int toggle[256]; /* Device-specific data. */ void *data; @@ -184,7 +185,12 @@ typedef enum typedef enum { - GRUB_USBMS_SUBCLASS_BULK = 0x06 + GRUB_USBMS_SUBCLASS_BULK = 0x06, + /* Experimental support for non-pure SCSI devices */ + GRUB_USBMS_SUBCLASS_RBC = 0x01, + GRUB_USBMS_SUBCLASS_MMC2 = 0x02, + GRUB_USBMS_SUBCLASS_UFI = 0x04, + GRUB_USBMS_SUBCLASS_SFF8070 = 0x05 } grub_usbms_subclass_t; typedef enum diff --git a/include/grub/usbtrans.h b/include/grub/usbtrans.h index 7e4a9d7ee..40fc0dd5f 100644 --- a/include/grub/usbtrans.h +++ b/include/grub/usbtrans.h @@ -37,7 +37,7 @@ struct grub_usb_transaction int size; int toggle; grub_transfer_type_t pid; - char *data; + grub_uint32_t data; }; typedef struct grub_usb_transaction *grub_usb_transaction_t; @@ -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; @@ -86,9 +89,9 @@ typedef struct grub_usb_transfer *grub_usb_transfer_t; #define GRUB_USB_REQ_HUB_GET_PORT_STATUS 0x00 -#define GRUB_USB_FEATURE_ENDP_HALT 0x01 -#define GRUB_USB_FEATURE_DEV_REMOTE_WU 0x02 -#define GRUB_USB_FEATURE_TEST_MODE 0x04 +#define GRUB_USB_FEATURE_ENDP_HALT 0x00 +#define GRUB_USB_FEATURE_DEV_REMOTE_WU 0x01 +#define GRUB_USB_FEATURE_TEST_MODE 0x02 #define GRUB_USB_HUB_STATUS_CONNECTED (1 << 0) #define GRUB_USB_HUB_STATUS_LOWSPEED (1 << 9) 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/emu/getroot.c b/kern/emu/getroot.c index 6875044da..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 * @@ -126,9 +206,20 @@ find_root_device (const char *dir, dev_t dev) /* Ignore any error. */ continue; - if (S_ISLNK (st.st_mode)) - /* Don't follow symbolic links. */ + if (S_ISLNK (st.st_mode)) { +#ifdef __linux__ + if (strcmp (dir, "mapper") == 0) { + /* Follow symbolic links under /dev/mapper/; the canonical name + may be something like /dev/dm-0, but the names under + /dev/mapper/ are more human-readable and so we prefer them if + we can get them. */ + if (stat (ent->d_name, &st) < 0) + continue; + } else +#endif /* __linux__ */ + /* Don't follow other symbolic links. */ continue; + } if (S_ISDIR (st.st_mode)) { @@ -355,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 0ab25ec7d..bc37e9949 100644 --- a/kern/emu/hostdisk.c +++ b/kern/emu/hostdisk.c @@ -338,11 +338,11 @@ find_partition_start (const char *dev) struct hd_geometry hdg; # else /* defined(__NetBSD__) */ struct disklabel label; - int index; + int p_index; # 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; @@ -412,7 +412,12 @@ devmapper_fail: fd = open (dev, O_RDONLY); if (fd == -1) { - grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s' while attempting to get disk geometry", dev); + 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; } @@ -424,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; } @@ -434,18 +443,15 @@ devmapper_fail: # if !defined(__NetBSD__) return hdg.start; # else /* defined(__NetBSD__) */ - /* Since dev and convert_system_partition_to_system_disk (dev) are - * different, we know that dev is of the form /dev/r[wsc]d[0-9]+[a-z] - * and in particular it cannot be a floppy device. */ - index = dev[strlen(dev) - 1] - 'a'; + p_index = dev[strlen(dev) - 1] - 'a'; - if (index >= label.d_npartitions) + if (p_index >= label.d_npartitions) { grub_error (GRUB_ERR_BAD_DEVICE, "no disk label entry for `%s'", dev); return 0; } - return (grub_disk_addr_t) label.d_partitions[index].p_offset; + return (grub_disk_addr_t) label.d_partitions[p_index].p_offset; # endif /* !defined(__NetBSD__) */ } #endif /* __linux__ || __CYGWIN__ */ @@ -986,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) { @@ -1258,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; @@ -1388,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); @@ -1407,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; } @@ -1431,9 +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. */ - index = os_dev[strlen(os_dev) - 1] - 'a'; + * different, we know that os_dev cannot be a floppy device. */ # endif /* !defined(__NetBSD__) */ start = find_partition_start (os_dev); @@ -1455,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) { @@ -1462,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, @@ -1470,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__) @@ -1515,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 54c808a47..38395fca8 100644 --- a/kern/emu/misc.c +++ b/kern/emu/misc.c @@ -9,6 +9,9 @@ #include #include #include +#ifdef HAVE_LIMITS_H +#include +#endif #include #include @@ -19,6 +22,10 @@ #include #include +#ifdef HAVE_DEVICE_MAPPER +# include +#endif + int verbosity; void @@ -182,7 +189,8 @@ canonicalize_file_name (const char *path) char *ret; #ifdef PATH_MAX ret = xmalloc (PATH_MAX); - (void) realpath (path, ret); + if (!realpath (path, ret)) + return NULL; #else ret = realpath (path, NULL); #endif @@ -307,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 d1b94496c..7ee809c79 100644 --- a/kern/i386/coreboot/init.c +++ b/kern/i386/coreboot/init.c @@ -68,6 +68,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 ac859c245..3e8819464 100644 --- a/kern/i386/pc/init.c +++ b/kern/i386/pc/init.c @@ -72,14 +72,22 @@ make_install_device (void) ptr += grub_strlen (ptr); if (grub_install_bsd_part >= 0) - grub_snprintf (ptr, sizeof (dev) - (ptr - dev), ",%c", - grub_install_bsd_part + 'a'); + grub_snprintf (ptr, sizeof (dev) - (ptr - dev), ",%u", + grub_install_bsd_part + 1); ptr += grub_strlen (ptr); } 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/pc/mmap.c b/kern/i386/pc/mmap.c index 52d8fd597..72a6b3539 100644 --- a/kern/i386/pc/mmap.c +++ b/kern/i386/pc/mmap.c @@ -20,6 +20,7 @@ #include #include #include +#include grub_err_t grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)) @@ -28,6 +29,8 @@ grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uin struct grub_machine_mmap_entry *entry = (struct grub_machine_mmap_entry *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; + grub_memset (entry, 0, sizeof (entry)); + /* Check if grub_get_mmap_entry works. */ cont = grub_get_mmap_entry (entry, 0); @@ -43,6 +46,8 @@ grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uin if (! cont) break; + grub_memset (entry, 0, sizeof (entry)); + cont = grub_get_mmap_entry (entry, cont); } while (entry->size); 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 dfdb99b74..0242da1ca 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 @@ -62,6 +78,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, @@ -69,10 +91,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/misc.c b/kern/misc.c index ccc01d43f..2ba34f235 100644 --- a/kern/misc.c +++ b/kern/misc.c @@ -1058,7 +1058,7 @@ grub_abort (void) void abort (void) __attribute__ ((alias ("grub_abort"))); #endif -#if defined(NEED_ENABLE_EXECUTE_STACK) && !defined(GRUB_UTIL) +#if defined(NEED_ENABLE_EXECUTE_STACK) && !defined(GRUB_UTIL) && !defined(GRUB_MACHINE_EMU) /* Some gcc versions generate a call to this function in trampolines for nested functions. */ void __enable_execute_stack (void *addr __attribute__ ((unused))) @@ -1075,3 +1075,4 @@ void __deregister_frame_info (void) { } #endif + 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/xnu.c b/loader/i386/xnu.c index d110293e0..643a895e8 100644 --- a/loader/i386/xnu.c +++ b/loader/i386/xnu.c @@ -896,6 +896,18 @@ grub_xnu_set_video (struct grub_xnu_boot_params *params) bitmap = grub_xnu_bitmap; } + if (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; @@ -914,13 +926,12 @@ grub_xnu_set_video (struct grub_xnu_boot_params *params) mode_info.width), min (bitmap->mode_info.height, mode_info.height)); - if (err) - { - grub_print_error (); - grub_errno = GRUB_ERR_NONE; - grub_xnu_bitmap = 0; - } - err = GRUB_ERR_NONE; + } + if (err) + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + bitmap = 0; } ret = grub_video_get_info_and_fini (&mode_info, &framebuffer); @@ -933,7 +944,7 @@ grub_xnu_set_video (struct grub_xnu_boot_params *params) params->lfb_line_len = mode_info.pitch; params->lfb_base = PTR_TO_UINT32 (framebuffer); - params->lfb_mode = bitmap ? GRUB_XNU_VIDEO_SPLASH + params->lfb_mode = bitmap ? GRUB_XNU_VIDEO_SPLASH : GRUB_XNU_VIDEO_TEXT_IN_VIDEO; return GRUB_ERR_NONE; diff --git a/loader/multiboot_elfxx.c b/loader/multiboot_elfxx.c index 880e93ce5..7d08eda2a 100644 --- a/loader/multiboot_elfxx.c +++ b/loader/multiboot_elfxx.c @@ -72,7 +72,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/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..fdd3c558c 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; } @@ -499,7 +467,6 @@ grub_normal_execute (const char *config, int nested, int batch) const char *prefix = grub_env_get ("prefix"); read_lists (prefix); - read_handler_list (); grub_register_variable_hook ("prefix", NULL, read_lists_hook); grub_command_execute ("parser.grub", 0, 0); @@ -605,17 +572,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 +594,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 +639,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 +687,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_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/term/gfxterm.c b/term/gfxterm.c index ecfe4ff3b..c57d0f0fa 100644 --- a/term/gfxterm.c +++ b/term/gfxterm.c @@ -707,12 +707,6 @@ real_scroll (void) draw_cursor (0); grub_video_set_active_render_target (render_target); - /* Save viewport and set it to our window. */ - grub_video_get_viewport ((unsigned *) &saved_view.x, - (unsigned *) &saved_view.y, - (unsigned *) &saved_view.width, - (unsigned *) &saved_view.height); - grub_video_set_viewport (window.x, window.y, window.width, window.height); i = window.double_repaint ? 2 : 1; @@ -720,6 +714,15 @@ real_scroll (void) while (i--) { + /* Save viewport and set it to our window. */ + grub_video_get_viewport ((unsigned *) &saved_view.x, + (unsigned *) &saved_view.y, + (unsigned *) &saved_view.width, + (unsigned *) &saved_view.height); + + grub_video_set_viewport (window.x, window.y, window.width, + window.height); + /* Clear new border area. */ grub_video_fill_rect (color, virtual_screen.offset_x, @@ -735,6 +738,10 @@ real_scroll (void) grub_video_scroll (color, 0, -virtual_screen.normal_char_height * virtual_screen.total_scroll); + /* Restore saved viewport. */ + grub_video_set_viewport (saved_view.x, saved_view.y, + saved_view.width, saved_view.height); + if (i) grub_video_swap_buffers (); } @@ -746,9 +753,6 @@ real_scroll (void) grub_video_scroll (color, 0, -virtual_screen.normal_char_height * virtual_screen.total_scroll); - /* Restore saved viewport. */ - grub_video_set_viewport (saved_view.x, saved_view.y, - saved_view.width, saved_view.height); grub_video_set_active_render_target (render_target); } 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/term/usb_keyboard.c b/term/usb_keyboard.c index 5d76c5e02..69d5709b6 100644 --- a/term/usb_keyboard.c +++ b/term/usb_keyboard.c @@ -18,7 +18,6 @@ */ #include -#include #include #include #include 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..c3bc508dd 100644 --- a/util/deviceiter.c +++ b/util/deviceiter.c @@ -33,6 +33,7 @@ #include #include #include +#include #ifdef __linux__ # if !defined(__GLIBC__) || \ @@ -676,112 +677,114 @@ 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; + struct dmraid_seen *seen = NULL; - /* 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; + struct dmraid_seen *seen_elt; - 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; - } + /* 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); + name = xasprintf ("/dev/mapper/%s", node_name); + if (check_device (name)) + { + if (hook (name, 0)) + { + free (name); + while (seen) + { + struct dmraid_seen *seen_elt = seen; + seen = seen->next; + 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)); + seen_elt = xmalloc (sizeof *seen_elt); + seen_elt->name = node_name; + grub_list_push (GRUB_AS_LIST_P (&seen), GRUB_AS_LIST (seen_elt)); 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); - } + while (seen) + { + struct dmraid_seen *seen_elt = seen; + seen = seen->next; + free (seen_elt); + } + if (task) + dm_task_destroy (task); + if (tree) + dm_tree_free (tree); + } # endif /* HAVE_DEVICE_MAPPER */ #endif /* __linux__ */ } 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..c7e087dd0 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}` @@ -61,7 +63,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 ;; -f | --force) setup_force="--force" ;; + -*) echo "Unrecognized option \`$option'" 1>&2 usage @@ -310,12 +356,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}`" diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in index 85212f8fc..fb475af6a 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. -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 ;; - -o) - shift - grub_cfg=$1 - ;; + -o | --output) + grub_cfg=`argument $option "$@"`; shift;; --output=*) grub_cfg=`echo "$option" | sed 's/--output=//'` ;; @@ -70,6 +86,7 @@ for option in "$@"; do usage exit 1 ;; + # Explicitly ignore non-option arguments, for compatibility. esac done @@ -79,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 @@ -103,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 @@ -124,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 @@ -161,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 @@ -229,13 +243,17 @@ 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 \ GRUB_HIDDEN_TIMEOUT \ GRUB_HIDDEN_TIMEOUT_QUIET \ GRUB_TIMEOUT \ + GRUB_DEFAULT_BUTTON \ + GRUB_HIDDEN_TIMEOUT_BUTTON \ + GRUB_TIMEOUT_BUTTON \ + GRUB_BUTTON_CMOS_ADDRESS \ GRUB_DISTRIBUTOR \ GRUB_CMDLINE_LINUX \ GRUB_CMDLINE_LINUX_DEFAULT \ @@ -247,6 +265,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 \ @@ -270,7 +289,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 f4674b257..14ea1842f 100644 --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in @@ -105,6 +105,11 @@ prepare_grub_to_access_device () echo "insmod ${module}" done + partmap="`${grub_probe} --device ${device} --target=partmap`" + for module in ${partmap} ; do + echo "insmod part_${module}" + done + fs="`${grub_probe} --device ${device} --target=fs`" for module in ${fs} ; do echo "insmod ${module}" diff --git a/util/grub-mkimage.c b/util/grub-mkimage.c index 6366a9803..7b03c2fd0 100644 --- a/util/grub-mkimage.c +++ b/util/grub-mkimage.c @@ -1253,7 +1253,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; @@ -1307,7 +1307,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': @@ -1322,7 +1322,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-mkrelpath.c b/util/grub-mkrelpath.c index e771bd873..eccb49cdc 100644 --- a/util/grub-mkrelpath.c +++ b/util/grub-mkrelpath.c @@ -41,7 +41,7 @@ usage (int status) printf ("\ Usage: %s [OPTIONS] PATH\n\ \n\ -Make a system path relative to it's root.\n\ +Make a system path relative to its root.\n\ \n\ Options:\n\ -h, --help display this message and exit\n\ diff --git a/util/grub-mkrescue.in b/util/grub-mkrescue.in index 7e7253006..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 @@ -37,58 +39,100 @@ pc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-pc efi32_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-efi efi64_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/x86_64-efi 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 @@ -170,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} } @@ -266,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 dc732aa01..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 @@ -145,7 +143,8 @@ main (int argc, char *argv[]) char *input; FILE *file = 0; int verbose = 0; - struct grub_script *script; + int found_input = 0; + struct grub_script *script = NULL; auto grub_err_t get_config_line (char **line, int cont); grub_err_t get_config_line (char **line, int cont __attribute__ ((unused))) @@ -238,15 +237,13 @@ main (int argc, char *argv[]) } } - /* Initialize all modules. */ - grub_init_all (); - do { input = 0; get_config_line(&input, 0); if (! input) break; + found_input = 1; script = grub_script_parse (input, get_config_line); if (script) @@ -258,9 +255,7 @@ main (int argc, char *argv[]) grub_free (input); } while (script != 0); - /* Free resources. */ - grub_fini_all (); if (file) fclose (file); - return (script == 0); + 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 d181fdffc..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 @@ -38,13 +37,31 @@ if [ "x${GRUB_DEFAULT}" = "xsaved" ] ; then GRUB_DEFAULT='${saved_entry}' ; fi if [ "x${GRUB_TIMEOUT}" = "x" ] ; then GRUB_TIMEOUT=5 ; fi if [ "x${GRUB_GFXMODE}" = "x" ] ; then GRUB_GFXMODE=640x480 ; fi +if [ "x${GRUB_DEFAULT_BUTTON}" = "x" ] ; then GRUB_DEFAULT_BUTTON="$GRUB_DEFAULT" ; fi +if [ "x${GRUB_DEFAULT_BUTTON}" = "xsaved" ] ; then GRUB_DEFAULT_BUTTON='${saved_entry}' ; fi +if [ "x${GRUB_TIMEOUT_BUTTON}" = "x" ] ; then GRUB_TIMEOUT_BUTTON="$GRUB_TIMEOUT" ; fi + cat << EOF if [ -s \$prefix/grubenv ]; then load_env fi +EOF +if [ "x$GRUB_BUTTON_CMOS_ADDRESS" != "x" ]; then + cat <&2 ; exit 1 fi @@ -89,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 @@ -177,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}) @@ -186,21 +221,36 @@ insmod gettext EOF fi -if [ "x${GRUB_HIDDEN_TIMEOUT}" != "x" ] ; then - if [ "x${GRUB_HIDDEN_TIMEOUT_QUIET}" = "xtrue" ] ; then - verbose= - else - verbose=" --verbose" - fi - cat << EOF -if sleep$verbose --interruptible ${GRUB_HIDDEN_TIMEOUT} ; then - set timeout=${GRUB_TIMEOUT} +make_timeout () +{ + if [ "x${1}" != "x" ] ; then + if [ "x${GRUB_HIDDEN_TIMEOUT_QUIET}" = "xtrue" ] ; then + verbose= + else + verbose=" --verbose" + fi + cat << EOF +if sleep$verbose --interruptible ${1} ; then + set timeout=${2} fi EOF -else - cat << EOF -set timeout=${GRUB_TIMEOUT} + else + cat << EOF +set timeout=${2} EOF + fi +} + +if [ "x$GRUB_BUTTON_CMOS_ADDRESS" != "x" ]; then + cat <&2 - kernel=${rel_dirname}/${basename} + kernels="${kernels} ${rel_dirname}/${basename}" at_least_one=true fi done @@ -71,17 +71,22 @@ if ${all_of_them} && test -e /lib/ld.so.1 ; then : ; else exit 1 fi -cat << EOF -menuentry "${OS}" ${CLASS} { +for kernel in ${kernels} +do + kernel_base="`basename "${kernel}"`" + KERNEL="using ${kernel_base}" + + cat << EOF +menuentry "${OS} ${KERNEL}" ${CLASS} { EOF -prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/" -cat << EOF + prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/" + cat << EOF echo '$(gettext_quoted "Loading GNU Mach ...")' multiboot ${kernel} root=device:${GRUB_DEVICE#/dev/} EOF -save_default_entry | sed -e "s/^/\t/" -prepare_grub_to_access_device ${GRUB_DEVICE} | sed -e "s/^/\t/" -cat << EOF + save_default_entry | sed -e "s/^/\t/" + prepare_grub_to_access_device ${GRUB_DEVICE} | sed -e "s/^/\t/" + cat << EOF echo '$(gettext_quoted "Loading the Hurd ...")' module /hurd/${hurd_fs}.static ${hurd_fs} --readonly \\ --multiboot-command-line='\${kernel-command-line}' \\ @@ -93,17 +98,17 @@ cat << EOF } EOF -cat << EOF -menuentry "${OS} (recovery mode)" { + cat << EOF +menuentry "${OS} ${KERNEL} (recovery mode)" ${CLASS} { EOF -prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/" -cat << EOF + prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/" + cat << EOF echo '$(gettext_quoted "Loading GNU Mach ...")' multiboot ${kernel} root=device:${GRUB_DEVICE#/dev/} -s EOF -save_default_entry | sed -e "s/^/\t/" -prepare_grub_to_access_device ${GRUB_DEVICE} | sed -e "s/^/\t/" -cat << EOF + save_default_entry | sed -e "s/^/\t/" + prepare_grub_to_access_device ${GRUB_DEVICE} | sed -e "s/^/\t/" + cat << EOF echo '$(gettext_quoted "Loading the Hurd ...")' module /hurd/${hurd_fs}.static ${hurd_fs} \\ --multiboot-command-line='\${kernel-command-line}' \\ @@ -114,3 +119,5 @@ cat << EOF module /lib/ld.so.1 exec /hurd/exec '\$(exec-task=task-create)' } EOF + +done diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in index 802d59f51..4b5ddb9d8 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= diff --git a/util/grub.d/10_windows.in b/util/grub.d/10_windows.in index 35dd4a4cc..7d221eac9 100644 --- a/util/grub.d/10_windows.in +++ b/util/grub.d/10_windows.in @@ -1,7 +1,7 @@ #! /bin/sh -e # grub-mkconfig helper script. -# Copyright (C) 2008 Free Software Foundation, Inc. +# Copyright (C) 2008,2009,2010 Free Software Foundation, Inc. # # GRUB is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -28,8 +28,8 @@ esac # Try C: even if current system is on other partition. case "$SYSTEMDRIVE" in - [Cc]:) dirlist="C:" ;; - [D-Zd-z]:) dirlist="C: $SYSTEMDRIVE" ;; + [Cc]:) drives="C:" ;; + [D-Zd-z]:) drives="C: $SYSTEMDRIVE" ;; *) exit 0 ;; esac @@ -51,7 +51,13 @@ get_os_name_from_boot_ini () } -for dir in $dirlist ; do +for drv in $drives ; do + + # Convert to Cygwin path. + dir=`cygpath "$drv"` + test -n "$dir" || continue + + needmap= # Check for Vista bootmgr. if [ -f "$dir"/bootmgr -a -f "$dir"/boot/bcd ] ; then @@ -60,6 +66,7 @@ for dir in $dirlist ; do # Check for NTLDR. elif [ -f "$dir"/ntldr -a -f "$dir"/ntdetect.com -a -f "$dir"/boot.ini ] ; then OS=`get_os_name_from_boot_ini "$dir"/boot.ini` || OS="Windows NT/2000/XP loader" + needmap=t else continue @@ -68,14 +75,16 @@ for dir in $dirlist ; do # Get boot /dev/ice. dev=`${grub_probe} -t device "$dir" 2>/dev/null` || continue - echo "Found $OS on $dir ($dev)" >&2 + echo "Found $OS on $drv ($dev)" >&2 cat << EOF menuentry "$OS" { EOF save_default_entry | sed -e 's,^,\t,' prepare_grub_to_access_device "$dev" | sed 's,^,\t,' - + test -z "$needmap" || 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/misc.c b/util/misc.c index 46e5c6093..91bc25a55 100644 --- a/util/misc.c +++ b/util/misc.c @@ -30,9 +30,6 @@ #include #include #include -#ifdef HAVE_LIMITS_H -#include -#endif #include #include 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 33861beef..44bfd74c3 100644 --- a/video/sm712.c +++ b/video/sm712.c @@ -32,10 +32,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; @@ -193,6 +190,8 @@ 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, 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)