diff --git a/ChangeLog b/ChangeLog index 3acc543d4..56f19acde 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,1579 @@ +2010-03-06 Vladimir Serbinenko + + * NEWS: Put the date of 1.98 release. + +2010-03-06 Vladimir Serbinenko + + * configure.ac: Update CPPFLAGS and not CFLAGS when checking for + ft2build.h. + +2010-03-06 Vladimir Serbinenko + + * normal/cmdline.c (grub_cmdline_get): Fix gabled line after + completition in the middle of string. + +2010-03-06 Vladimir Serbinenko + + * util/grub-mkrescue.in: Use mktemp with explicit template. + +2010-03-06 Vladimir Serbinenko + + * loader/i386/bsd.c (grub_bsd_get_device): Fix a memory leak. + +2010-03-06 Vladimir Serbinenko + + * loader/i386/multiboot_mbi.c (grub_multiboot_set_bootdev): Free the + right pointer. + +2010-03-05 Vladimir Serbinenko + + Fix FreeBSD compilation. + + * Makefile.in (TARGET_CPPFLAGS): Remove -nostdinc -isystem. + * configure.ac: Add -nostdinc -isystem to TARGET_CPPFLAGS if it works. + +2010-03-05 Vladimir Serbinenko + + * util/import_gcry.py: Add autogenerated files to MAINTAINER_CLEANFILES. + +2010-03-04 Vladimir Serbinenko + + * gettext/gettext.c (grub_gettext_init_ext): Fix a memory leak. + +2010-03-04 Vladimir Serbinenko + + * disk/scsi.c (grub_scsi_iterate): Fix a memory leak. + +2010-03-04 Robert Millan + + Support relative image path in theme file. + + * gfxmenu/gui_image.c (grub_gui_image): New member theme_dir. + (image_set_property): Handle theme_dir and relative path. + +2010-03-04 Vladimir Serbinenko + + * configure.ac: Alias amd64 to x86_64. + +2010-03-04 Vladimir Serbinenko + + * NEWS: mention multiboot on EFI. + +2010-03-04 Vladimir Serbinenko + + * kern/main.c (grub_load_modules): Handle errors from init functions of + embeded modules. + +2010-03-04 Vladimir Serbinenko + + * normal/autofs.c (autoload_fs_module): Handle errors. + +2010-03-04 Vladimir Serbinenko + + Disable linux.mod on qemu-mips since it's not functional and leads + to compilation failure. + + * conf/mips.rmk (pkglib_MODULES): Remove linux.mod. + * conf/mips-yeeloong.rmk (pkglib_MODULES): Add linux.mod. + * conf/mips.rmk (linux_mod_SOURCES): Move from here ... + * conf/mips-yeeloong.rmk (linux_mod_SOURCES): ... here + * conf/mips.rmk (linux_mod_CFLAGS): Move from here ... + * conf/mips-yeeloong.rmk (linux_mod_CFLAGS): ... here + * conf/mips.rmk (linux_mod_ASFLAGS): Move from here ... + * conf/mips-yeeloong.rmk (linux_mod_ASFLAGS): ... here + * conf/mips.rmk (linux_mod_LDFLAGS): Move from here ... + * conf/mips-yeeloong.rmk (linux_mod_LDFLAGS): ... here + Reported by: BVK Chaitanya + +2010-03-04 Jordan Uggla + + * INSTALL: Add gettext as a dependency and add qemu to a new section + "Prerequisites for make-check". + +2010-03-04 Christian Franke + + * util/grub-pe2elf.c: Add missing include "progname.h". + +2010-03-04 Vladimir Serbinenko + + * normal/crypto.c (read_crypto_list): Fix a typo. + Reported by: Seth Goldberg. + +2010-03-04 Vladimir Serbinenko + + * Makefile.in (DISTCLEANFILES): Add stamp-h1. + Reported by: Seth Goldberg. + +2010-03-04 Vladimir Serbinenko + + * Makefile.in (CLEANFILES) [FONT_SOURCE && grub_mkfont]: Add + ascii.bitmaps. + +2010-03-04 Vladimir Serbinenko + + * genmk.rb: Remove terminal*.lst in make clean. + Reported by: Seth Goldberg. + +2010-03-04 Vladimir Serbinenko + + * util/i386/efi/grub-install.in: Copy gettext files. + +2010-03-01 Vladimir Serbinenko + + * fs/ext2.c (grub_ext2_read_block): Fix an integer overflow. + +2010-03-01 Vladimir Serbinenko + + Wait for user entry basing on presence of output rather than on errors. + + * include/grub/normal.h (grub_normal_get_line_counter): New proto. + (grub_install_newline_hook): Likewise. + * normal/main.c (GRUB_MOD_INIT): Call grub_install_newline_hook. + * normal/menu.c (show_menu): Check line_counter to determine presence + of output. + * normal/term.c (grub_normal_line_counter): New variable. + (grub_normal_get_line_counter): New function. + (grub_install_newline_hook): Likewise. + +2010-03-01 Vladimir Serbinenko + + * commands/cat.c (grub_cmd_cat): Propagate grub_gzfile_open error. + +2010-03-01 Vladimir Serbinenko + + * configure.ac: Update version to 1.98. + +2010-02-26 Vladimir Serbinenko + + * util/grub.d/10_linux.in (linux_entry): Don't default to + gfxpayload=keep if Linux doesn't support video handover. + +2010-02-25 Vladimir Serbinenko + + Don't compile video modules on yeeloong since video subsystem is part + of kernel. + + * conf/common.rmk (pkglib_MODULES) [yeeloong]: Remove video.mod, + video_fb.mod, bitmap.mod, font.mod, gfxterm.mod and bufio.mod + * conf/mips-yeeloong.rmk (kernel_img_HEADERS): Add bitmap.h, + video.h, gfxterm.h, font.h, bitmap_scale.h and bufio.h. + * conf/mips.rmk (kernel_img_HEADERS): Add values instead of overwriting. + * include/grub/bitmap.h: Add EXPORT_FUNC and EXPORT_VAR. + * include/grub/bitmap_scale.h: Likewise. + * include/grub/bufio.h: Likewise. + * include/grub/font.h: Likewise. + * include/grub/gfxterm.h: Likewise. + * include/grub/video.h: Likewise. + * include/grub/vbe.h: Don't include video_fb.h. + * video/i386/pc/vbe.c: Include video_fb.h. + * commands/i386/pc/vbetest.c: Include video.h. + +2010-02-25 Jordan Uggla + + * util/grub-mkconfig.in (GRUB_SAVEDEFAULT): Export new variable. + * util/grub-mkconfig_lib.in (save_default_entry): Only save a new + default entry if GRUB_SAVEDEFAULT=true. This allows using + GRUB_DEFAULT=saved on its own to let grub-reboot work, without + saving a new default on every boot. + +2010-02-24 Vladimir Serbinenko + + * normal/crypto.c (read_crypto_list): Fix a memory leak. + * normal/term.c (read_terminal_list): Likewise. + * normal/main.c (grub_normal_init_page): Likewise. + (grub_normal_read_line_real): Likewise. + +2010-02-24 Vladimir Serbinenko + + * loader/i386/multiboot_mbi.c (grub_multiboot_set_bootdev): Fix a + memory leak. + Reported by: Seth Goldberg. + +2010-02-24 Joey Korkames + + * term/ieee1275/ofconsole.c (grub_ofconsole_readkey): Remove + duplicate declaration of `start'. + +2010-02-20 Vladimir Serbinenko + + * fs/iso9660.c (grub_iso9660_iterate_dir): Strip version from joliet + filename. + Reported by: Georgy Buranov + +2010-02-20 Carles Pina i Estany + + * util/grub-mkrawimage.c (usage): Change string formatting to + improve gettext. + +2010-02-20 Manoel Rebelo Abranches + + * term/ieee1275/ofconsole.c (grub_ofconsole_readkey): Add delete and + backspace keys. + +2010-02-20 Vladimir Serbinenko + + * video/fb/video_fb.c (grub_video_fb_scroll): Fix a pixel size bug. + Reported by: Michael Suchanek. + +2010-02-18 Samuel Thibault + + * util/grub-mkconfig.in: Export GRUB_INIT_TUNE. + * util/grub.d/00_header.in: Handle GRUB_INIT_TUNE. + +2010-02-16 Vladimir Serbinenko + + Remove any reference to non-free fonts. + + * commands/videotest.c (grub_cmd_videotest): Use unifont by default. + * docs/gfxmenu-theme-example.txt: Removed. It's both outdated and + uses non-free components. + * font/font.c (grub_font_get_name): Remove example name. + * gfxmenu/gui_label.c (grub_gui_label_new): Use unifont by default. + * gfxmenu/gui_list.c (grub_gui_list_new): Likewise. + * gfxmenu/gui_progress_bar.c (grub_gui_progress_bar_new): Likewise. + * gfxmenu/view.c (grub_gfxmenu_view_new): Likewise. + +2010-02-16 Georgy Buranov + + * disk/efi/efidisk.c (grub_efidisk_get_device_name): Fix a typo. + +2010-02-15 Vladimir Serbinenko + + * term/serial.c (serial_get_divisor) [GRUB_MACHINE_MIPS_YEELOONG]: + Double divisor. + (serial_hw_init) [GRUB_MACHINE_MIPS_YEELOONG]: Don't enable advanced + features. + (GRUB_MOD_INIT) [GRUB_MACHINE_MIPS_YEELOONG]: Default to 115200. + +2010-02-15 Vladimir Serbinenko + + * gensymlist.sh.in: Use TARGET_CC instead of CC. + +2010-02-14 Samuel Thibault + + * commands/i386/pc/play.c (GRUB_MOD_INIT(play)): Fix help. + * docs/grub.texi (Command-line and menu entry commands): Document play + command. + +2010-02-14 Samuel Thibault + + * commands/i386/pc/play.c (grub_cmd_play): If grub_file_open fails, + parse arguments as inline tempo and notes. Move code for playing notes + to... + (play): ... new function. + +2010-02-14 Samuel Thibault + + * commands/i386/pc/play.c (T_REST, T_FINE, struct note, beep_on): Use + grub_uint16_t instead of short. + (grub_cmd_play): Use grub_uint32_t instead of int, convert data from + disk from little endian to cpu endianness. + +2010-02-07 Samuel Thibault + + * commands/i386/pc/play.c (BASE_TEMPO): Set to 60 * + GRUB_TICKS_PER_SECOND instead of 120. + +2010-02-14 Vladimir Serbinenko + + * term/ieee1275/ofconsole.c (grub_ofconsole_readkey): Wait for possible + escape sequence after \e. + +2010-02-14 Vladimir Serbinenko + + * term/ieee1275/ofconsole.c (grub_ofconsole_putchar): Don't output + non-ASCII characters. + +2010-02-14 Vladimir Serbinenko + + * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Enclose + set root in single quotes to prevent \, from being unescaped. + +2010-02-14 Vladimir Serbinenko + + Prevent unknown commands from stopping menuentry execution. + + * script/execute.c (grub_script_execute_cmdline): Print error after + unknown command. + +2010-02-14 Vladimir Serbinenko + + * fs/i386/pc/pxe.c (GRUB_MOD_INIT): Fix typo. + Reported by: Pavel Pisa. + +2010-02-13 Vladimir Serbinenko + + * io/gzio.c (grub_gzio_open): Use grub_zalloc. + +2010-02-13 Vladimir Serbinenko + + Merge grub_ieee1275_map_physical into grub_map and rename to + grub_ieee1275_map + + * include/grub/ieee1275/ieee1275.h (grub_ieee1275_map): New proto. + * include/grub/sparc64/ieee1275/ieee1275.h (grub_ieee1275_map_physical): + Remove. + * kern/ieee1275/openfw.c (grub_map): Rename to ... + (grub_ieee1275_map): ... this. All users updated. Add phys_lo when + necessary. + * kern/sparc64/ieee1275/ieee1275.c (grub_ieee1275_map_physical): Remove. + +2010-02-13 Vladimir Serbinenko + + * disk/ieee1275/ofdisk.c (grub_ofdisk_open): Check device type before + opening and not after. + +2010-02-13 Vladimir Serbinenko + + * term/ieee1275/ofconsole.c (grub_ofconsole_readkey): Macroify + constants. + +2010-02-13 Vladimir Serbinenko + + * loader/sparc64/ieee1275/linux.c (align_addr): Remove. + (alloc_phys): Use ALIGN_UP instead of align_addr. + +2010-02-13 Vladimir Serbinenko + + * loader/sparc64/ieee1275/linux.c (alloc_phys): Correct bounds checking. + +2010-02-13 Vladimir Serbinenko + + * kern/sparc64/ieee1275/crt0.S (codestart): Move modules backwards. + +2010-02-13 Vladimir Serbinenko + + * disk/ieee1275/ofdisk.c (grub_ofdisk_read): Remove excessively + verbose dprintf. + +2010-02-13 Vladimir Serbinenko + + Fix over-4GiB seek on sparc64. + + * include/grub/ieee1275/ieee1275.h (grub_ieee1275_seek): + Replace pos_i and pos_lo with pos. All users updated. + * include/grub/powerpc/ieee1275/ieee1275.h (GRUB_IEEE1275_CELL_SIZEOF): + New constant. + * include/grub/sparc64/ieee1275/ieee1275.h (GRUB_IEEE1275_CELL_SIZEOF): + Likewise. + * kern/ieee1275/ieee1275.c (grub_ieee1275_seek): Split pos into pos_hi + and pos_lo. + +2010-02-13 Vladimir Serbinenko + + * util/grub-mkrawimage.c (main): Call set_program_name. + +2010-02-13 Vladimir Serbinenko + + Properly align 64-bit targets. + + * util/grub-mkrawimage.c (ALIGN_ADDR): New macro. + (generate_image): Use ALIGN_ADDR. + +2010-02-13 Vladimir Serbinenko + + Properly create cross-endian images. + + * include/grub/types.h (grub_host_to_target_addr): New macro + * util/grub-mkrawimage.c (generate_image): Add missing host_to_target. + +2010-02-13 Vladimir Serbinenko + + * util/grub-mkrawimage.c (generate_image): Add forgotten ALIGN_UP. + +2010-02-10 Vladimir Serbinenko + + Pass SIMPLE framebuffer size in bytes and not 64K blocks. + + * loader/i386/efi/linux.c (grub_linux_setup_video): Don't divide by 64K. + * loader/i386/linux.c (grub_linux_setup_video): Likewise. + (grub_linux_boot): Divide by 64K when on VESA. + +2010-02-10 Vladimir Serbinenko + + Support GRUB_GFXPAYLOAD_LINUX. + + * util/grub-mkconfig.in: Export GRUB_GFXPAYLOAD_LINUX. + * util/grub.d/10_linux.in (linux_entry): Handle GRUB_GFXPAYLOAD_LINUX. + +2010-02-10 Vladimir Serbinenko + + * script/execute.c (grub_script_execute_cmdline): Use grub_print_error + to show messages instead of discarding them. + Process errors after executing command and not before. Keep old method + too as precaution. + +2010-02-09 Vladimir Serbinenko + + * configure.ac: Check for ft2build.h. + +2010-02-07 Vladimir Serbinenko + + * kern/ieee1275/openfw.c (grub_halt): Try executing "poweroff". + +2010-02-07 Vladimir Serbinenko + + * genkernsyms.sh.in: Use TARGET_CC. + +2010-02-07 Colin Watson + + * NEWS: Update. + +2010-02-07 Vladimir Serbinenko + + * include/grub/multiboot2.h: Remove leftover file. + * include/grub/normal.h [GRUB_UTIL]: Remove leftover declarations. + * include/grub/partition.h [GRUB_UTIL]: Likewise. + +2010-02-07 Yves Blusseau + + * gnulib/getdelim.c: add missing header (type ssize_t must be defined). + +2010-02-07 Vladimir Serbinenko + + Fix warnings in grub-emu when compiling with maximum warning options. + + * util/grub-emu.c (ENABLE_RELOCATABLE): New definition. + (grub_arch_modules_addr): Return 0 and not NULL. + * util/misc.c (ENABLE_RELOCATABLE): New definition. + (xstrdup): Use newstr instead of dup. + * util/hostdisk.c (grub_util_biosdisk_get_grub_dev): Rename one instance + of disk to dsk to avoid shadowing. + (find_free_slot): Fix prototype. + * util/getroot.c (grub_util_is_dmraid): Make static. + * include/grub/time.h (grub_get_rtc) [GRUB_MACHINE_EMU || GRUB_UTIL]: + Add missing prototype. + * util/sdl.c (grub_video_sdl_set_viewport): Remove. + +2010-02-07 Vladimir Serbinenko + + * loader/i386/linux.c (grub_linux_setup_video): Handle error + appropriately. + +2010-02-07 Vladimir Serbinenko + + * fs/reiserfs.c (grub_reiserfs_read): Use #if 0 instead of commenting + code out. + +2010-02-07 Vladimir Serbinenko + + * include/grub/cache.h (grub_arch_sync_caches) [i386 || x86_64]: Inline. + * kern/i386/coreboot/init.c (grub_arch_sync_caches): Remove. + * kern/i386/efi/init.c (grub_arch_sync_caches): Likewise. + * kern/i386/ieee1275/init.c (grub_arch_sync_caches): Likewise. + * kern/i386/pc/init.c (grub_arch_sync_caches): Likewise. + * util/misc.c (grub_arch_sync_caches) [i386 || x86_64]: Likewise. + +2010-02-07 Vladimir Serbinenko + + * include/grub/err.h (grub_err_printf): Don't export. + +2010-02-07 Vladimir Serbinenko + + * include/grub/dl.h (grub_dl_register_symbol): Don't export. + +2010-02-07 Vladimir Serbinenko + + * include/grub/i18n.h (grub_gettext_dummy): Removed. + * kern/misc.c (grub_gettext_dummy): Make static. + +2010-02-06 Vladimir Serbinenko + + * kern/misc.c (grub_utf8_to_ucs4): Don't eat valid characters preceeded + by non-valid ones. + * kern/term.c (grub_putchar): Likewise. + +2010-02-06 Vladimir Serbinenko + + * partmap/sun.c (sun_partition_map_iterate): Restructure flow to fix + buggy hook call and memory leak. + +2010-02-06 Vladimir Serbinenko + + * commands/ls.c (grub_ls_list_files): Free pathname on exit. + +2010-02-06 Vladimir Serbinenko + + * fs/fat.c (grub_fat_iterate_dir): Free unibuf at exit. + +2010-02-06 Vladimir Serbinenko + + * loader/i386/pc/xnu.c (grub_xnu_set_video): Add const qualifier to + modevar. + Return grub_errno on allocation error. + +2010-02-06 Vladimir Serbinenko + + * disk/ieee1275/ofdisk.c (grub_ofdisk_read): Correct error handling. + +2010-02-06 Yves Blusseau + + * conf/common.rmk (grub_script_check_SOURCES): add missing dependencies. + (grub_mkpasswd_pbkdf2_SOURCES): Likewise. + +2010-02-06 Vladimir Serbinenko + + * fs/i386/pc/pxe.c (grub_pxefs_dir): Return with failure on + non-pxe disk. + (grub_pxefs_open): Likewise. + +2010-02-06 Robert Millan + + * util/grub.d/10_hurd.in: Add --class information to menuentries. + * util/grub.d/10_kfreebsd.in: Likewise. + * util/grub.d/10_linux.in: Likewise. + +2010-02-06 Colin D Bennett + + * conf/common.rmk (pkglib_MODULES): Add gfxmenu.mod. + (gfxmenu_mod_SOURCES): New variable. + (gfxmenu_mod_CFLAGS): Likewise. + (gfxmenu_mod_LDFLAGS): Likewise. + * include/grub/term.h (grub_term_set_current_output): Declare + argument as const. + * docs/gfxmenu-theme-example.txt: New file. + * gfxmenu/gfxmenu.c: Likewise. + * gfxmenu/gui_box.c: Likewise. + * gfxmenu/gui_canvas.c: Likewise. + * gfxmenu/gui_circular_progress.c: Likewise. + * gfxmenu/gui_image.c: Likewise. + * gfxmenu/gui_label.c: Likewise. + * gfxmenu/gui_list.c: Likewise. + * gfxmenu/gui_progress_bar.c: Likewise. + * gfxmenu/gui_string_util.c: Likewise. + * gfxmenu/gui_util.c: Likewise. + * gfxmenu/icon_manager.c: Likewise. + * gfxmenu/model.c: Likewise. + * gfxmenu/named_colors.c: Likewise. + * gfxmenu/theme_loader.c: Likewise. + * gfxmenu/view.c: Likewise. + * gfxmenu/widget-box.c: Likewise. + * include/grub/gfxmenu_model.h: Likewise. + * include/grub/gfxmenu_view.h: Likewise. + * include/grub/gfxwidgets.h: Likewise. + * include/grub/gui.h: Likewise. + * include/grub/gui_string_util.h: Likewise. + * include/grub/icon_manager.h: Likewise. + +2010-02-06 Vladimir Serbinenko + + Agglomerate scrolling in gfxterm. + + * term/gfxterm.c (grub_virtual_screen): New member 'total_screen'. + (grub_virtual_screen_setup): Initialise 'total_screen'. + (write_char): Split to ... + (paint_char): ... this ... + (write_char): ... and this. + (paint_char): Handle delayed scrolling. + (draw_cursor): Likewise. + (scroll_up): Split to ... + (real_scroll): ... this ... + (scroll_up): ... and this. + (real_scroll): Handle multi-line scroll and draw below-the-bottom + characters. + (grub_gfxterm_refresh): Call real_scroll. + +2010-02-06 Colin D Bennett + + * include/grub/misc.h (grub_iscntrl): New inline function. + (grub_isalnum): Likewise. + (grub_strtol): Likewise. + +2010-02-06 Colin D Bennett + + * normal/menu_text.c (get_entry_number): Move from here ... + * normal/menu.c (get_entry_number): ... moved here. + * include/grub/menu.h (grub_menu_get_default_entry_index): + New prototype. + * normal/menu.c (grub_menu_get_default_entry_index): New function. + * normal/menu_text.c (run_menu): Use grub_menu_get_default_entry_index. + * include/grub/menu_viewer.h (grub_menu_viewer_init): New prototype. + (grub_menu_viewer_should_return): Likewise. + * normal/main.c (GRUB_MOD_INIT (normal)): Call grub_menu_viewer_init. + * normal/menu_text.c (run_menu): Enable menu switching. + * normal/menu_viewer.c (should_return): New variable. + (menu_viewer_changed): Likewise. + (grub_menu_viewer_show_menu): Handle menu viewer changes. + (grub_menu_viewer_should_return): New function. + (menuviewer_write_hook): Likewise. + (grub_menu_viewer_init): Likewise. + +2010-02-06 Colin D Bennet +2010-02-06 Vladimir Serbinenko + + Support for gfxterm in a window. + + * include/grub/gfxterm.h: New file. + * include/grub/video.h (struct grub_video_rect): New declaration. + (grub_video_rect_t): Likewise. + * term/gfxterm.c (struct grub_gfxterm_window): New type. + (refcount): New variable. + (render_target): Likewise. + (window): Likewise. + (repaint_callback): Likewise. + (grub_virtual_screen_setup): Use 'render_target'. + (init_window): New function. + (grub_gfxterm_init_window): Likewise. + (grub_gfxterm_init): Check reference counter. + Use init_window. + (destroy_window): New function. + (grub_gfxterm_destroy_window): Likewise. + (grub_gfxterm_fini): Check reference counter. + Use destroy_window. + (redraw_screen_rect): Restore viewport. + Use 'render_target' and 'window'. + Call 'repaint_callback'. + (write_char): Use 'render_target'. + (draw_cursor): Likewise. + (scroll_up): Restore viewport. + Use 'render_target' and 'window'. + Call 'repaint_callback'. + (grub_gfxterm_cls): Likewise. + (grub_gfxterm_refresh): Use 'window'. + (grub_gfxterm_set_repaint_callback): New function. + (grub_gfxterm_background_image_cmd): Use 'window'. + (grub_gfxterm_get_term): New function. + (GRUB_MOD_INIT(term_gfxterm)): Set 'refcount' to 0. + +2010-02-06 Colin D Bennett + + Bitmap scaling support. + + * conf/common.rmk (pkglib_MODULES): Add bitmap_scale.mod. + (bitmap_scale_mod_SOURCES): New variable. + (bitmap_scale_mod_CFLAGS): Likewise. + (bitmap_scale_mod_LDFLAGS): Likewise. + * include/grub/bitmap_scale.h: New file. + * term/gfxterm.c (BACKGROUND_CMD_ARGINDEX_MODE): New definiton. + (background_image_cmd_options): New variable. + (grub_gfxterm_background_image_cmd): Support bitmap stretching. + (cmd): Rename and change type to ... + (background_image_cmd_handle): ... this. All users updated. + (GRUB_MOD_INIT(term_gfxterm)): Make background_image extended command. + * video/bitmap_scale.c: New file. + +2010-02-06 Vladimir Serbinenko + + SDL support. + + * Makefile.in (LIBSDL): New variable. + (enable_grub_emu_sdl): Likewise. + * conf/i386-pc.rmk (grub_emu_SOURCES): Add video files. + (grub_emu_SOURCES) [enable_grub_emu_sdl]: Add util/sdl.c. + (grub_emu_LDFLAGS) [enable_grub_emu_sdl]: Add $(LIBSDL). + * configure.ac: Detect SDL availability and add --enable-grub-emu-sdl + * util/sdl.c: New file. + +2010-02-06 Colin D Bennett +2010-02-06 Vladimir Serbinenko + + Double buffering support. + + * commands/i386/pc/videotest.c (grub_cmd_videotest): Swap doublebuffers. + * include/grub/video.h: Update comment. + * include/grub/video_fb.h (grub_video_fb_doublebuf_update_screen_t): + New type. + (grub_video_fb_doublebuf_blit_init): New prototype. + * term/gfxterm.c (scroll_up): Support double buffering. + (grub_gfxterm_refresh): Likewise. + * video/fb/video_fb.c (doublebuf_blit_update_screen): New function. + (grub_video_fb_doublebuf_blit_init): Likewise. + * video/i386/pc/vbe.c (framebuffer): Remove 'render_target'. Add + 'front_target', 'back_target', 'offscreen_buffer', 'page_size', + 'displayed_page', 'render_page' and 'update_screen'. + (grub_video_vbe_fini): Free offscreen buffer. + (doublebuf_pageflipping_commit): New function. + (doublebuf_pageflipping_update_screen): Likewise. + (doublebuf_pageflipping_init): Likewise. + (double_buffering_init): Likewise. + (grub_video_vbe_setup): Enable doublebuffering. + (grub_video_vbe_swap_buffers): Implement. + (grub_video_vbe_set_active_render_target): Handle double buffering. + (grub_video_vbe_get_active_render_target): Likewise. + (grub_video_vbe_get_info_and_fini): Likewise. Free offscreen_buffer. + (grub_video_vbe_adapter): Use grub_video_vbe_get_active_render_target. + (grub_video_vbe_enable_double_buffering): Likewise. + (grub_video_vbe_swap_buffers): Use update_screen. + (grub_video_set_mode): Use double buffering. + +2010-02-06 Robert Millan + + * maintainance/gentrigtables.py: Remove. + * lib/trig.c: Likewise. + + * gentrigtables.c: New file. C rewrite of gentrigtables.py. + + * conf/common.rmk (trig_mod_SOURCES): Replace `lib/trig.c' with + `trigtables.c'. + (trigtables.c): New rule. + (gentrigtables): Likewise. + (DISTCLEANFILES): Add `trigtables.c' and `gentrigtables'. + +2010-02-06 Robert Millan + + * maintainance/gentrigtables.py: Avoid duplicate hardcoding of + integer constants. + +2010-02-06 Colin D Bennet + + Trigonometry support. + + * include/grub/trig.h: New file. + * lib/trig.c: Likewise. + * maintainance/gentrigtables.py: Likewise. + * conf/common.rmk (pkglib_MODULES): Add trig.mod. + (trig_mod_SOURCES): New variable. + (trig_mod_CFLAGS): Likewise. + (trig_mod_LDFLAGS): Likewise. + +2010-02-06 Vladimir Serbinenko + + * kern/ieee1275/openfw.c (grub_ieee1275_encode_devname): Support whole + disk devices. + +2010-02-06 Vladimir Serbinenko + + * kern/ieee1275/openfw.c (grub_devalias_iterate): Stop iterating on + error. + +2010-02-03 Vladimir Serbinenko + + * util/hostdisk.c (open_device): Don't use partition device when reading + before the partition. + (grub_util_biosdisk_read): Don't read from partition and before the + partition in single operation. + (grub_util_biosdisk_write): Don't write to partition and before the + partition in single operation. + +2010-02-03 Torsten Landschoff + + * kern/disk.c (grub_disk_read): Fix offset computation when reading + last sectors. + +2010-02-03 Vladimir Serbinenko + + * disk/i386/pc/biosdisk.c (grub_biosdisk_read): Handle non-2048 aligned + CDROM reads. + (grub_biosdisk_write): Refuse to write to CDROM. + +2010-01-31 Vladimir Serbinenko + + * disk/ieee1275/ofdisk.c (grub_ofdisk_iterate): Fix off-by-one error. + +2010-01-31 Vladimir Serbinenko + + * font/font.c (find_glyph): Check that bmp_idx is available before + using it. + (grub_font_get_string_width): Never call grub_font_get_glyph_internal + with (font == NULL). + +2010-01-28 Christian Schmitt + + * util/ieee1275/grub-install.in: Fix nvsetenv arguments. + +2010-01-28 BVK Chaitanya + + * include/grub/script_sh.h (sourcecode): Add const qualifier. + * util/grub-script-check.c (getline): Fix empty lines case. + +2010-01-28 Robert Millan + + * Makefile.in (check): Exit with fail status when one of the tests + fails. + * tests/example_functional_test.c (example_test): Fix reversed assert. + * tests/example_unit_test.c (example_test): Likewise. + +2010-01-28 Colin Watson + + * util/grub.d/10_linux.in: This script does not use any of the + contents of gettext.sh, only the external command `gettext', so stop + sourcing it. (Moreover, gettext.sh isn't necessarily installed in + the same prefix as GRUB.) + * util/grub.d/10_kfreebsd.in: Likewise. + +2010-01-27 Vladimir Serbinenko + + * normal/cmdline.c (grub_cmdline_get): Fix completion in the middle + of the line. + +2010-01-27 Vladimir Serbinenko + + * kern/disk.c (grub_disk_read): Fix offset computation when reading + last sectors. + +2010-01-27 Vladimir Serbinenko + + * commands/hashsum.c (hash_file): Avoid possible stack overflow by + having a 4KiB and not 32KiB buffer size. + +2010-01-27 Robert Millan + + * util/hostfs.c: Include `'. + (grub_hostfs_read): Handle errors from fseeko() and fread(). + +2010-01-27 Robert Millan + + * kern/disk.c (grub_disk_read): Fix bug that would cause infinite + loop when using read hooks on files whose size isn't sector-aligned. + +2010-01-27 Robert Millan + + Remove unused parameter. + + * fs/iso9660.c (struct grub_iso9660_data): Remove `length' parameter. + (grub_iso9660_open): Remove initialization of `data->length'. + +2010-01-27 Robert Millan + + * util/grub-fstest.c (fstest): Rewrite allocation, fixing a few + memleak conditions. + +2010-01-27 Carles Pina i Estany + + * util/lvm.c: New macro LVM_DEV_MAPPER_STRING. + (grub_util_lvm_isvolume): Use LVM_DEV_MAPPER_STRING. + +2010-01-26 Carles Pina i Estany + + * util/bin2h.c (usage): Fix warning (space after backslash). + +2010-01-26 Carles Pina i Estany + + * font/font.c: Include `grub/fontformat.h. + Remove font file format constants. + (grub_font_load): Use the new macros. + * include/grub/fontformat.h: New file. + * util/grub-mkfont.c: Include `grub/fontformat.c'. + (write_font_pf2): Use the new macros. + +2010-01-26 Robert Millan + + * util/bin2h.c (usage): Make --help actually explain what `grub-bin2h' + does. + +2010-01-26 Robert Millan + + * include/grub/i386/pc/boot.h (GRUB_BOOT_MACHINE_PXE_DL): New macro. + + * boot/i386/pc/pxeboot.S: Include `'. + (_start): Macroify `0x7F'. + + * kern/i386/pc/init.c: Include `'. + (make_install_device): Use "(pxe)" as fallback prefix when booting + via PXE. + +2010-01-26 Vladimir Serbinenko + + * configure.ac: Reset LIBS after check for libgcc symbols. + +2010-01-25 Colin Watson + + * util/hostdisk.c (open_device): Add trailing newline to debug + message. + +2010-01-25 Grégoire Sutre + + * configure.ac: Check for `limits.h'. + * util/misc.c: Include `' (for PATH_MAX). + +2010-01-24 Robert Millan + + * loader/mips/linux.c (grub_cmd_linux, grub_cmd_initrd): Don't + capitalize error strings. + +2010-01-24 Samuel Thibault + + * util/grub.d/10_hurd.in: Add a recovery mode. + +2010-01-23 Vladimir Serbinenko + + * configure.ac: Check for libgcc symbols with -nostdlib. + +2010-01-23 BVK Chaitanya + + * acinclude.m4: Quote underquoted AC_DEFUN parameters. + +2010-01-22 Vladimir Serbinenko + + * term/ieee1275/ofconsole.c (grub_ofconsole_setcolorstate): Allocate on + stack since heap may be unavailable at that point. + (grub_ofconsole_gotoxy): Likewise. + +2010-01-22 Vladimir Serbinenko + + * configure.ac: Check for _restgpr_14_x. + * include/grub/powerpc/libgcc.h [HAVE__RESTGPR_14_X]: Add _restgpr_*_x + and _savegpr_* prototypes. + +2010-01-22 Robert Millan + + Use generic grub_reboot() for i386-efi. + + * kern/efi/efi.c [__i386__] (grub_reboot): Remove. + * kern/i386/efi/startup.S: Include `"../realmode.S"'. + * kern/i386/realmode.S: Include `'. + +2010-01-22 Vladimir Serbinenko + + * kern/ieee1275/init.c (grub_machine_set_prefix): Don't check for + presence of "prefix" variable as it breaks when normal.mod is + embedded. + +2010-01-21 Vladimir Serbinenko + + * term/ieee1275/ofconsole.c (grub_ofconsole_dimensions): Allocate on + stack since heap is unavailable at that point. + +2010-01-21 Vladimir Serbinenko + + * include/grub/i386/bsd.h (FREEBSD_N_BIOS_GEOM): Removed. + (grub_freebsd_bootinfo): Rewritten. + * loader/i386/bsd.c (grub_freebsd_boot): Use new grub_freebsd_bootinfo. + +2010-01-21 Vladimir Serbinenko + + * util/misc.c (make_system_path_relative_to_its_root): Fix typo. + +2010-01-21 Robert Millan + + * po/POTFILES: Remove mkisofs-related files. They have their own TLP + domain now. + +2010-01-20 Felix Zielcke + + * util/misc.c (make_system_path_relative_to_its_root): Change the work + around for handling "/" to the correct fix. Fix a memory leak. Use + xstrdup instead of strdup. + +2010-01-20 Vladimir Serbinenko + + * conf/mips.rmk (kernel_img_HEADERS): Add env_private.h + +2010-01-20 Vladimir Serbinenko + + Optimise glyph lookup by Basic Multilingual Plane lookup array. + + * font/font.c (struct grub_font): New member 'bmp_idx'. + (font_init): Initialise 'bmp_idx'. + (load_font_index): Fill 'bmp_idx'. + (find_glyph): Make inline. Use bmp_idx for BMP characters. + +2010-01-20 Vladimir Serbinenko + + * video/fb/video_fb.c (grub_video_fb_scroll): Optimise by avoiding + unnecessary calls. + +2010-01-20 Vladimir Serbinenko + + Move context handling out of the kernel. + + * conf/any-emu.rmk (grub_emu_SOURCES): Add normal/context.c. + * conf/common.rmk (normal_mod_SOURCES): Add normal/context.c. + * conf/i386-coreboot.rmk (kernel_img_HEADERS): Add env_private.h. + * conf/i386-efi.rmk: Likewise. + * conf/i386-ieee1275.rmk: Likewise. + * conf/i386-pc.rmk: Likewise. + * conf/powerpc-ieee1275.rmk: Likewise. + * conf/sparc64-ieee1275.rmk: Likewise. + * conf/x86_64-efi.rmk: Likewise. + * include/grub/env.h: Include grub/menu.h. + (grub_env_var_type): Removed. + (grub_env_var): Replaced field 'type' with 'global'. + (grub_env_find): New prototype. + (grub_env_context_open): Remove EXPORT_FUNC. + (grub_env_context_close): Likewise. + (grub_env_export): Likewise. + (grub_env_set_data_slot): Removed. + (grub_env_get_data_slot): Likewise. + (grub_env_unset_data_slot): Likewise. + (grub_env_unset_menu): New prototype. + (grub_env_set_menu): Likewise. + (grub_env_get_menu): Likewise. + * include/grub/env_private.h: New file. + * include/grub/normal.h (grub_context_init): New prototype. + (grub_context_fini): Likewise. + * kern/corecmd.c (grub_core_cmd_export): Moved from here ... + * normal/context.c (grub_cmd_export): ... to here. + * kern/env.c: Include env_private.h. + (HASHSZ): Moved to include/grub/env_private.h. + (grub_env_context): Likewise. + (grub_env_sorted_var): Likewise. + (current_context): Renamed from this ... + (grub_current_context): ...to this. 'static' removed. All users updated. + (grub_env_find): Removed 'static'. + (grub_env_context_open): Moved to normal/context.c. + (grub_env_context_close): Likewise. + (grub_env_export): Likewise. + (mangle_data_slot_name): Removed. + (grub_env_set_data_slot): Likewise. + (grub_env_get_data_slot): Likewise. + (grub_env_unset_data_slot): Likewise. + * kern/main.c (grub_set_root_dev): Don't export root. + It will be done later. + (grub_main): Don't export prefix. + It will be done later. + * normal/context.c: New file. + * normal/main.c (free_menu): Use grub_env_unset_menu. + (grub_normal_add_menu_entry): Use grub_env_get_menu. + (read_config_file): Use grub_env_get_menu and grub_env_set_menu. + (GRUB_MOD_INIT(normal)): Call grub_context_init. + (GRUB_MOD_FINI(normal)): Call grub_context_fini. + +2010-01-20 Vladimir Serbinenko + + setpci support. + + * commands/setpci.c: New file. + * conf/i386.rmk (pkglib_MODULES): Add setpci.mod. + (setpci_mod_SOURCES): New variable. + (setpci_mod_CFLAGS): Likewise. + (setpci_mod_LDFLAGS): Likewise. + +2010-01-20 Vladimir Serbinenko + + Byte-addressable PCI configuration space. + + * bus/pci.c (grub_pci_make_address): Use byte address instead of + dword address. + (grub_pci_iterate): Use macroses GRUB_PCI_REG_PCI_ID and + GRUB_PCI_REG_CACHELINE. + * bus/usb/ohci.c (grub_ohci_pci_iter): Use macroses + GRUB_PCI_REG_CLASS and GRUB_PCI_REG_ADDRESS_REG0. + * bus/usb/uhci.c (grub_ohci_pci_iter): Use macroses + GRUB_PCI_REG_CLASS and GRUB_PCI_REG_ADDRESS_REG4. + * commands/efi/fixvideo.c (scan_card): Use macros GRUB_PCI_REG_CLASS. + * commands/efi/loadbios.c (enable_rom_area): Pass byte-address to + grub_pci_make_address. + (lock_rom_area): Likewise. + * commands/lspci.c (grub_lspci_iter): Use macroses + GRUB_PCI_REG_CLASS and GRUB_PCI_REG_ADDRESSES. Handle byte-addressing + of grub_pci_make_address. + * disk/ata.c (grub_ata_pciinit): Likewise. + * include/grub/pci.h (GRUB_PCI_REG_PCI_ID): New macro. + (GRUB_PCI_REG_VENDOR): Likewise. + (GRUB_PCI_REG_DEVICE): Likewise. + (GRUB_PCI_REG_COMMAND): Likewise. + (GRUB_PCI_REG_STATUS): Likewise. + (GRUB_PCI_REG_REVISION): Likewise. + (GRUB_PCI_REG_CLASS): Likewise. + (GRUB_PCI_REG_CACHELINE): Likewise. + (GRUB_PCI_REG_LAT_TIMER): Likewise. + (GRUB_PCI_REG_HEADER_TYPE): Likewise. + (GRUB_PCI_REG_BIST): Likewise. + (GRUB_PCI_REG_ADDRESSES): Likewise. + (GRUB_PCI_REG_ADDRESS_REG): Likewise. + (GRUB_PCI_REG_ADDRESS_REG): Likewise. + (GRUB_PCI_REG_ADDRESS_REG): Likewise. + (GRUB_PCI_REG_ADDRESS_REG): Likewise. + (GRUB_PCI_REG_ADDRESS_REG): Likewise. + (GRUB_PCI_REG_ADDRESS_REG): Likewise. + (GRUB_PCI_REG_CIS_POINTER): Likewise. + (GRUB_PCI_REG_SUBVENDOR): Likewise. + (GRUB_PCI_REG_SUBSYSTEM): Likewise. + (GRUB_PCI_REG_ROM_ADDRESS): Likewise. + (GRUB_PCI_REG_CAP_POINTER): Likewise. + (GRUB_PCI_REG_IRQ_LINE): Likewise. + (GRUB_PCI_REG_IRQ_PIN): Likewise. + (GRUB_PCI_REG_MIN_GNT): Likewise. + (GRUB_PCI_REG_MAX_LAT): Likewise. + * loader/i386/efi/linux.c (find_framebuf): Use GRUB_PCI_REG_CLASS. + * loader/i386/efi/xnu.c (find_framebuf): Likewise. + * video/efi_uga.c (find_framebuf): Likewise. + * video/sm712.c (grub_video_sm712_setup): Likewise. + * util/pci.c (grub_pci_make_address): Use byte-addressed configuration + space. + +2010-01-20 Robert Millan + + * util/grub.d/10_linux.in (linux_entry): Set gfxpayload=keep when it + can be reliably determined to be supported. + +2010-01-20 Robert Millan + + * loader/i386/linux.c (grub_cmd_linux): If `vga=' was used, write down + that VESA is supported. + (grub_linux_boot): Use generic framebuffer unless VESA is known to be + supported. + +2010-01-20 Vladimir Serbinenko + + * conf/common.rmk (font/font.c_DEPENDENCIES): Condition on FONT_SOURCE. + +2010-01-20 Robert Millan + + * util/misc.c (make_system_path_relative_to_its_root): Work around + special-casing of "/", as previous incarnation of this routine did. + +2010-01-20 Vladimir Serbinenko + + Fix any-emu compilation. + + * conf/any-emu.rmk (bin_UTILITIES): Add grub-bin2h. + * grub_bin2h_SOURCES: New variable. + +2010-01-20 Robert Millan + + * util/grub.d/00_header.in: Fix stupid mistake from last commit. + +2010-01-20 Robert Millan + + * util/grub.d/00_header.in: Fix handling of locale_dir. + +2010-01-20 Vladimir Serbinenko + + * configure.ac: Add /usr/share/fonts/unifont/unifont.pcf.gz + as possible unifont location (Gentoo). + Reported by: Alexander Brüning + +2010-01-20 Vladimir Serbinenko + + Don't try to generate lists for kernel.img. + + * conf/i386-efi.rmk (pkglib_PROGRAMS): New variable. + (pkglib_MODULES): Remove kernel.img. + (kernel_img_EXPORTS): Removed. + (kernel_img_RELOCATABLE): New variable. + * conf/x86_64-efi.rmk: Likewise. + * genmk.rb: Remove *_EXPORTS support and add *_RELOCATABLE support. + +2010-01-20 Vladimir Serbinenko + + * include/grub/misc.h (grub_sprintf): Removed. All users switched to + grub_xasprintf or grub_snprintf. + (grub_vsprintf): Likewise. + (grub_snprintf): New proto. + (grub_vsnprintf): Likewise. + (grub_xasprintf): Likewise. + (grub_xvasprintf): Likewise. + * kern/misc.c (grub_vprintf): Use grub_vsnprintf_real. + (grub_sprintf): Removed. + (grub_vsnprintf): New function. + (grub_snprintf): Likewise. + (grub_xvasprintf): Likewise. + (grub_xasprintf): Likewise. + (grub_vsprintf): Renamed to ... + (grub_vsnprintf_real): ...this. New argument max_len. + +2010-01-20 BVK Chaitanya + + * include/grub/script_sh.h (sourcecode): Remove const qualifier to + fix grub-script-check warning. + +2010-01-20 Vladimir Serbinenko + + * include/grub/font.h (grub_font_load): Fix prototype. + +2010-01-20 Vladimir Serbinenko + + * conf/mips.rmk (kernel_img_HEADERS) [yeeloong]: Add pci.h. + +2010-01-20 Vladimir Serbinenko + + * include/grub/x86_64/at_keyboard.h: New file. + +2010-01-20 Vladimir Serbinenko + + * loader/mips/linux.c: Include missing grub/i18n.h. + +2009-12-20 Robert Millan + + * normal/menu.c (notify_execution_failure): Clarify error message. + +2009-12-20 Robert Millan + + * commands/loadenv.c (check_blocklists): Use `grub_err_t' as + return value (and revert all return statements). Update users. + +2010-01-20 Dan Merillat + + * kern/device.c (grub_device_iterate): Allocate new part_ent + structure based on sizeof (*p) rather than sizeof (p->next), to + account for structure padding. + + * util/grub-probe.c (probe_raid_level): Return -1 immediately if + disk is NULL, which might happen for LVM physical volumes with no + LVM signature. + +2009-12-20 Robert Millan + + * loader/mips/linux.c (grub_cmd_initrd) + (GRUB_MOD_INIT(linux)): Adjust and gettextize a few strings. + +2009-12-20 Robert Millan + + * kern/mips/yeeloong/init.c (grub_video_sm712_init) + (grub_video_video_init, grub_video_bitmap_init) + (grub_font_manager_init, grub_term_gfxterm_init) + (grub_at_keyboard_init): New extern declarations. + (grub_machine_init): Initialize gfxterm and at_keyboard. + + * kern/main.c (grub_main): Revert grub_printf delay kludge. + + * util/grub-install.in: Revert embed of `at_keyboard.mod' and + `gfxterm.mod' into core image. + + * conf/mips.rmk (pkglib_IMAGES, kernel_img_SOURCES) + (kernel_img_CFLAGS, kernel_img_ASFLAGS, kernel_img_LDFLAGS) + (kernel_img_FORMAT): Copy to ... + + * conf/mips-qemu-mips.rmk (pkglib_IMAGES, kernel_img_SOURCES) + (kernel_img_CFLAGS, kernel_img_ASFLAGS, kernel_img_LDFLAGS) + (kernel_img_FORMAT): ... here, and ... + + * conf/mips-yeeloong.rmk (pkglib_IMAGES, kernel_img_SOURCES) + (kernel_img_CFLAGS, kernel_img_ASFLAGS, kernel_img_LDFLAGS) + (kernel_img_FORMAT): ... here. + + (kernel_img_SOURCES): Add files necessary for output (gfxterm) + and input (at_keyboard) terminals in kernel. + (kernel_img_CFLAGS): Add `-DUSE_ASCII_FAILBACK'. + + (pkglib_MODULES): Remove `pci.mod'. + (pci_mod_SOURCES, pci_mod_CFLAGS, pci_mod_LDFLAGS) + (sm712_mod_SOURCES, sm712_mod_CFLAGS, sm712_mod_LDFLAGS) + (at_keyboard_mod_SOURCES, at_keyboard_mod_CFLAGS) + (at_keyboard_mod_LDFLAGS): Remove variables. + +2010-01-11 Felix Zielcke + + * po/POTFILES: Replace `term/i386/pc/serial.c' with `term/serial.c'. + +2009-12-10 Robert Millan + + * include/grub/mips/libgcc.h: Only export symbols for functions + that libgcc provides. + +2009-12-02 Vladimir Serbinenko + + MIPS support. + + * bus/bonito.c: New file. + * bus/pci.c (grub_pci_iterate): Use GRUB_PCI_NUM_BUS and + GRUB_PCI_NUM_DEVICES. + * term/i386/pc/serial.c: Move to ... + * term/serial.c: ... here. All users updated. + * util/i386/pc/grub-mkimage.c: Move to ... + * util/grub-mkrawimage.c: ... here. All users updated. + * term/i386/pc/at_keyboard.c: Move to ... + * term/at_keyboard.c: ... here. All users updated. + * conf/mips-qemu-mips.rmk: New file. + * conf/mips-yeeloong.rmk: Likewise. + * conf/mips.rmk: Likewise. + * configure.ac: New platforms mipsel-yeeloong, mips-qemu-mips and + mipsel-qemu-mips. + * disk/ata.c (grub_ata_device_initialize): Add GRUB_MACHINE_PCI_IO_BASE + to port addresses. + (grub_ata_pciinit): Support CS5536. + * font/font.c (grub_font_load): Use grub_file_t instead of filename. + * font/font_cmd.c (loadfont_command): Open file before passing it to + grub_font_load. + (pseudo_file_read): New function. + (pseudo_file_close): Likewise. + (pseudo_fs): New structure. + (load_font_module): New function. + (GRUB_MOD_INIT(font_manager)): Load embedded font. + * fs/cpio.c (grub_cpio_open): Handle partial matches correctly. + * genmk.rb: Strip .rel.dyn, .reginfo, .note and .comment. + * genmoddep.awk: Ignore __gnu_local_gp. It's defined by linker. + * include/grub/i386/at_keyboard.h: Split into ... + * include/grub/at_keyboard.h: ... this ... + * include/grub/i386/at_keyboard.h: ... and this. + * include/grub/dl.h (grub_arch_dl_init_linker) [_mips && !GRUB_UTIL]: + New prototype. + * include/grub/elfload.h (grub_elf32_size): New parameter. All users + updated. + (grub_elf64_size): Likewise. + * include/grub/font.h (grub_font_load): Use grub_file_t instead of + filename. + * include/grub/i386/io.h (grub_port_t): New type. All users updated. + * include/grub/i386/coreboot/serial.h: Rewritten. + * include/grub/i386/ieee1275/serial.h: Include + grub/i386/coreboot/serial.h instead of grub/i386/pc/serial.h. + * include/grub/i386/pc/serial.h: Moved from here ... + * include/grub/serial.h: ... to here. All users updated. + * include/grub/i386/pci.h (GRUB_MACHINE_PCI_IO_BASE): New definition. + (GRUB_PCI_NUM_BUS): Likewise. + (GRUB_PCI_NUM_DEVICES): Likewise. + (grub_pci_device_map_range): Add missing volatile keyword. + * include/grub/kernel.h (OBJ_TYPE_FONT): New enum value. + * include/grub/mips/at_keyboard.h: New file. + * include/grub/mips/cache.h: Likewise. + * include/grub/mips/io.h: Likewise. + * include/grub/mips/kernel.h: Likewise. + * include/grub/mips/libgcc.h: Likewise. + * include/grub/mips/pci.h: Likewise. + * include/grub/mips/qemu-mips/boot.h: Likewise. + * include/grub/mips/qemu-mips/kernel.h: Likewise. + * include/grub/mips/qemu-mips/loader.h: Likewise. + * include/grub/mips/qemu-mips/memory.h: Likewise. + * include/grub/mips/qemu-mips/serial.h: Likewise. + * include/grub/mips/qemu-mips/time.h: Likewise. + * include/grub/mips/relocator.h: Likewise. + * include/grub/mips/time.h: Likewise. + * include/grub/mips/types.h: Likewise. + * include/grub/mips/yeeloong/at_keyboard.h: Likewise. + * include/grub/mips/yeeloong/boot.h: Likewise. + * include/grub/mips/yeeloong/kernel.h: Likewise. + * include/grub/mips/yeeloong/loader.h: Likewise. + * include/grub/mips/yeeloong/memory.h: Likewise. + * include/grub/mips/yeeloong/pci.h: Likewise. + * include/grub/mips/yeeloong/serial.h: Likewise. + * include/grub/mips/yeeloong/time.h: Likewise. + * kern/dl.c (grub_dl_resolve_symbols): Handle STT_OBJECT correctly. + * kern/elf.c (grub_elf32_size): New parameter. All users + updated. + (grub_elf64_size): Likewise. + * kern/main.c (grub_main): Call grub_arch_dl_init_linker if necessary. + Load modules before saying "Welcome to GRUB!". + Call grub_refresh after saying "Welcome to GRUB!". + * kern/mips/cache.S: New file. + * kern/mips/cache_flush.S: Likewise. + * kern/mips/dl.c: Likewise. + * kern/mips/init.c: Likewise. + * kern/mips/qemu-mips/init.c: Likewise. + * kern/mips/startup.S: Likewise. + * kern/mips/yeeloong/init.c: Likewise. + * kern/term.c (grub_putcode): Handle NULL terminal. + (grub_getcharwidth): Likewise. + (grub_getkey): Likewise. + (grub_checkkey): Likewise. + (grub_getkeystatus): Likewise. + (grub_getxy): Likewise. + (grub_getwh): Likewise. + (grub_gotoxy): Likewise. + (grub_cls): Likewise. + (grub_setcolorstate): Likewise. + (grub_setcolor): Likewise. + (grub_getcolor): Likewise. + (grub_refresh): Likewise. + * lib/mips/relocator.c (JUMP_SIZEOF): Fix incorrect value. + (write_jump): Add hatch nop. + * lib/mips/relocator_asm.S: Use kern/mips/cache_flush.S. + * lib/mips/setjmp.S: New file. + * loader/mips/linux.c: Likewise. + * term/i386/pc/at_keyboard.c: Move from here ... + * term/at_keyboard.c: ... to here. + * term/i386/pc/serial.c: Moved from here ... + * term/serial.c: ... to here. All users updated. + (TEXT_HEIGHT): Set to 24 to fit linux terminal. + (serial_hw_io_addr): Use GRUB_MACHINE_SERIAL_PORTS. + (serial_translate_key_sequence): Avoid deadlock. + (grub_serial_getkey): Handle backspace. + (grub_serial_putchar): Fix newline handling. + * util/i386/pc/grub-mkimage.c: Move from here ... + * util/grub-mkrawimage.c: ... to here. All users updated. + (generate_image): New parameters 'font_path' and 'format'. + Support embedding font. + Use grub_host_to_target* instead of grub_cpu_to_le*. + (generate_image) [GRUB_MACHINE_MIPS]: Support ELF encapsulation. + (options) [GRUB_PLATFORM_IMAGE_DEFAULT]: New option "--format". + (options): New option "--font". + (usage): Likewise. + (main) [GRUB_PLATFORM_IMAGE_DEFAULT]: Handle "--format". + (main): Handle "--font". + * term/gfxterm.c (grub_virtual_screen): New member bg_color_display. + (grub_virtual_screen_setup): Set bg_color_display. + (redraw_screen_rect): Use bg_color_display instead of incorrect + bg_color. + (grub_gfxterm_cls): Likewise. + * util/elf/grub-mkimage.c (load_modules): New parameter 'config_path'. + Support embedding config file. + (add_segments): Likewise. + (options): New option "--config". + (main): Handle "--config". + * video/sm712.c: New file. + +2010-01-18 Robert Millan + + Fix parallel builds. + + * conf/common.rmk (font/font.c_DEPENDENCIES): New variable (makes + font.c depend on ascii.h). + +2010-01-12 Carles Pina i Estany + + * Makefile.in (DUSE_ASCII_FAILBACK): New macro. + +2010-01-11 Carles Pina i Estany + + * font/font.c (GENERATE_ASCII): Change the name to USE_ASCII_FAILBACK. + By default: disabled. + * Makefile.in (ascii.h): Remove the non-needed grub/bin2h size + parameter. + +2010-01-10 Carles Pina i Estany + + * font/font.c: Update copyright years. + * util/grub-mkfont.c (write_font_ascii_bitmap): Change comment format. + +2010-01-10 Carles Pina i Estany + + * font/font.c: Include `ascii.h'. + (ASCII_BITMAP_SIZE): New macro. + (ascii_font_glyph): Define. + (ascii_glyph_lookup): New function. + (grub_font_get_string_width): Change comment. If glyph not found, use + ascii_glyph_lookup. + (grub_font_get_glyph_with_fallback): If glyph not available returns + ascii_glyph_lookup. + * util/grub-mkfont.c (file_formats): New enum. + (options): Add `ascii-bitmaps' new option. + (usage): Add `asii-bitmaps' new option. + (write_font_ascii_bitmap): New function. + (write_font): Rename to ... + (write_font_p2): ... this. Remove print_glyphs call. + (main): Use file_format. Implement code for ranges if ascii-bitmaps is + used. Call print_glyphs. + * Makefile.in (pkgdata_DATA): Add `ascii.h'. + +2010-01-14 Robert Millan + + * conf/common.rmk (bin_UTILITIES): Add `grub-bin2h'. + (grub_bin2h_SOURCES): New variable. + * util/bin2h.c: New file. + +2010-01-20 Vladimir Serbinenko + + * include/multiboot.h: Resynced with spec. + * include/multiboot2.h: Likewise. + * loader/i386/multiboot_mbi.c (grub_fill_multiboot_mmap): Handle + GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE and GRUB_MACHINE_MEMORY_NVS. + +2010-01-18 Robert Millan + + * include/grub/term.h (grub_term_register_input, + grub_term_register_output): Check return of terminal init() + routines, and abort if errors are raised. + + * commands/terminal.c: Update copyright year. + +2010-01-18 Robert Millan + + * commands/terminal.c (grub_cmd_terminal_input) + (grub_cmd_terminal_output): Check return of terminal init() + routines, and abort if errors are raised. + +2010-01-18 Vladimir Serbinenko + + * include/grub/i386/bsd.h: Fix include pathes. + +2010-01-18 Vladimir Serbinenko + + Add missing *BSD copyright headers. + + * include/grub/aout.h: Add BSD licence. + * include/grub/i386/bsd.h: Parts under different licences moved to ... + * include/grub/i386/freebsd_linker.h: ... here, + * include/grub/i386/freebsd_reboot.h: ... here, + * include/grub/i386/netbsd_bootinfo.h: ... here, + * include/grub/i386/netbsd_reboot.h: ... here, + * include/grub/i386/openbsd_bootarg.h: ... here, + * include/grub/i386/openbsd_reboot.h: ... and here. Added appropriate + licence to each file. + +2010-01-18 Robert Millan + + * acinclude.m4: Remove `nop' assembly instruction; it's not + implemented by all architectures. + +2010-01-18 Robert Millan + + * loader/i386/efi/linux.c (grub_cmd_linux): Stop pretending we're + ELILO. This is no longer necessary. + +2010-01-18 BVK Chaitanya + + Added new tool, grub-scrit-check to verify grub.cfg syntax. + + * util/grub-script-check.c: grub-script-check tool. + * conf/common.rmk: Make rules for grub-script-check. + +2010-01-18 Robert Millan + + Fix annoying UI bug in rescue mode. Thanks to Tristan Gingold for + spotting it back in 2008. Shame on me for forgetting he did. + + * kern/rescue_reader.c (grub_rescue_run): Skip zero-length lines. + +2010-01-18 Robert Millan + + * include/grub/i386/linux.h (GRUB_VIDEO_TYPE_TEXT): Rename to ... + (GRUB_VIDEO_LINUX_TYPE_TEXT): ... this. Update all users. + (GRUB_VIDEO_TYPE_VLFB): Rename to ... + (GRUB_VIDEO_LINUX_TYPE_VESA): ... this. Update all users. + (GRUB_VIDEO_TYPE_EFI): Rename to ... + (GRUB_VIDEO_LINUX_TYPE_SIMPLE): ... this. Update all users. + +2010-01-17 Robert Millan + + * include/grub/test.h: Add license header. + * tests/example_functional_test.c: Likewise. + * tests/example_unit_test.c: Likewise. + * tests/lib/functional_test.c: Likewise. + * tests/lib/test.c: Likewise. + * tests/lib/unit_test.c: Likewise. + +2010-01-17 Vladimir Serbinenko + + Use flag-based instead of hook-based video mode selection and "auto" + keyword. + + * include/grub/video.h (grub_video_adapter): Changed 'setup' member. + (grub_video_set_mode): Changed prototype. All users updated. + (grub_video_check_mode_flag): New inline function. + * video/video.c (parse_modespec): New function. + (grub_video_set_mode): Parse flags and keywords. + +2010-01-17 Carles Pina i Estany + + * util/misc.c (grub_util_info): Fix the order of the parameters in a + fprintf call. + +2010-01-16 Grégoire Sutre + + * genmk.rb (class SCRIPT): Replace option -i of sed by a pipe. + +2010-01-16 Carles Pina i Estany + + * util/grub-editenv.c (usage): Use `program_name' instead of hardcoded + string. + * util/grub-emu.c (usage): Likewise. + * util/grub-mkpasswd-pbkdf2.c (usage): Likewise. + * util/i386/efi/grub-mkimage.c (usage): Likewise. + * util/i386/pc/grub-mkimage.c (usage): Likewise. + * util/i386/pc/grub-setup.c (usage): Likewise. + +2010-01-16 Carles Pina i Estany + + * util/misc.c (grub_util_warn): Gettextizze, print full stop after + the message. + (grub_util_info): Likewise. + (grub_util_error): Likewise. + * util/elf/grub-mkimage.c: Fix capitalisation, quotes, full stops + and/or new lines in `grub_util_warna', `grub_util_info', + `grub_util_error' calls. + * util/getroot.c: Likewise. + * util/grub-editenv.c: Likewise. + * util/grub-emu.c: Likewise. + * util/grub-fstest.c: Likewise. + * util/grub-mkdevicemap.c: Likewise. + * util/grub-mkfont.c: Likewise. + * util/grub-mkpasswd-pbkdf2.c: Likewise. + * util/grub-mkrelpath.c: Likewise. + * util/grub-pe2elf.c: Likewise. + * util/grub-probe.c: Likewise. + * util/hostdisk.c: Likewise. + * util/i386/efi/grub-mkimage.c: Likewise. + * util/i386/pc/grub-mkimage.c: Likewise. + * util/i386/pc/grub-setup.c: Likewise. + * util/ieee1275/ofpath.c: Likewise. + * util/mkisofs/eltorito.c: Likewise. + * util/mkisofs/rock.c: Likewise. + * util/mkisofs/write.c: Likewise. + * util/raid.c: Likewise. + * util/sparc64/ieee1275/grub-mkimage.c: Likewise. + * util/sparc64/ieee1275/grub-setup.c: Likewise. + 2010-01-15 Vladimir Serbinenko Enable multiboot on non-pc. @@ -23135,7 +24711,7 @@ * genmk.rb (PModule#rule): Make sure to get only symbol names from the output of nm. - Reported by Robert Millan . + Reported by Robert Millan . 2003-09-25 Yoshinori K. Okuji diff --git a/INSTALL b/INSTALL index cfade2026..0dd408bcc 100644 --- a/INSTALL +++ b/INSTALL @@ -14,6 +14,7 @@ configuring the GRUB. * GCC 4.1.3 or later * GNU Make * GNU Bison 2.3 or later +* GNU gettext 0.17 or later * GNU binutils 2.9.1.0.23 or later * Other standard GNU/Unix tools @@ -25,6 +26,10 @@ need the following. * Autoconf 2.60 or later * Automake 1.10.1 or later +Prerequisites for make-check: + +* qemu, specifically the binary 'qemu-system-i386' + Configuring the GRUB ==================== diff --git a/Makefile.in b/Makefile.in index e1067b985..47584cdde 100644 --- a/Makefile.in +++ b/Makefile.in @@ -89,7 +89,7 @@ TARGET_ASFLAGS = @TARGET_ASFLAGS@ TARGET_MODULE_FORMAT = @TARGET_MODULE_FORMAT@ TARGET_APPLE_CC = @TARGET_APPLE_CC@ OBJCONV = @OBJCONV@ -TARGET_CPPFLAGS = @TARGET_CPPFLAGS@ -nostdinc -isystem $(shell $(TARGET_CC) -print-file-name=include) -I$(srcdir)/include -I$(builddir) -I$(builddir)/include \ +TARGET_CPPFLAGS = @TARGET_CPPFLAGS@ -I$(srcdir)/include -I$(builddir) -I$(builddir)/include \ -Wall -W TARGET_LDFLAGS = @TARGET_LDFLAGS@ TARGET_IMG_LDSCRIPT = @TARGET_IMG_LDSCRIPT@ @@ -114,12 +114,14 @@ endif AWK = @AWK@ LIBCURSES = @LIBCURSES@ LIBUSB = @LIBUSB@ +LIBSDL = @LIBSDL@ LIBPCIACCESS = @LIBPCIACCESS@ YACC = @YACC@ FONT_SOURCE = @FONT_SOURCE@ # Options. enable_grub_emu_usb = @enable_grub_emu_usb@ +enable_grub_emu_sdl = @enable_grub_emu_sdl@ enable_grub_emu_pci = @enable_grub_emu_pci@ enable_grub_fstest = @enable_grub_fstest@ enable_grub_pe2elf = @enable_grub_pe2elf@ @@ -145,7 +147,7 @@ INFOS = $(info_INFOS) CLEANFILES = MOSTLYCLEANFILES = DISTCLEANFILES = config.status config.cache config.log config.h \ - Makefile stamp-h include/grub/cpu include/grub/machine \ + Makefile stamp-h stamp-h1 include/grub/cpu include/grub/machine \ gensymlist.sh genkernsyms.sh build_env.mk \ docs/grub.info docs/version.texi docs/stamp-vti @@ -236,7 +238,8 @@ else ifeq ($(enable_grub_mkfont),yes) -pkgdata_DATA += unicode.pf2 ascii.pf2 +pkgdata_DATA += unicode.pf2 ascii.pf2 ascii.h +CLEANFILES += ascii.bitmaps # Arrows and lines are needed to draw the menu, so we always include them UNICODE_ARROWS=0x2190-0x2193 @@ -247,6 +250,14 @@ unicode.pf2: $(FONT_SOURCE) grub-mkfont ascii.pf2: $(FONT_SOURCE) grub-mkfont $(builddir)/grub-mkfont -o $@ $(FONT_SOURCE) -r 0x0-0x7f,$(UNICODE_ARROWS),$(UNICODE_LINES) + +ascii.bitmaps: $(FONT_SOURCE) grub-mkfont + $(builddir)/grub-mkfont --ascii-bitmaps -o $@ $(FONT_SOURCE) + +ascii.h: ascii.bitmaps grub-bin2h + $(builddir)/grub-bin2h ascii_bitmaps < $< > $@ + +TARGET_CFLAGS += -DUSE_ASCII_FAILBACK=1 endif endif @@ -465,23 +476,21 @@ distcheck: dist check: all $(UNIT_TESTS) $(FUNCTIONAL_TESTS) $(SCRIPTED_TESTS) @list="$(UNIT_TESTS)"; \ + set -e; \ for file in $$list; do \ $(builddir)/$$file; \ done @list="$(FUNCTIONAL_TESTS)"; \ + set -e; \ for file in $$list; do \ mod=`basename $$file .mod`; \ echo "insmod functional_test; insmod $$mod; functional_test" \ | $(builddir)/grub-shell; \ done @list="$(SCRIPTED_TESTS)"; \ + set -e; \ for file in $$list; do \ - echo "$$file:"; \ - if $(builddir)/$$file; then \ - echo "$$file: PASS"; \ - else \ - echo "$$file: FAIL"; \ - fi; \ + $(builddir)/$$file; \ done .SUFFIX: diff --git a/NEWS b/NEWS index cc725fd3b..1e3334f18 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,21 @@ -New in 1.98: +New in 1.98 - 2010-03-06: + +* Multiboot on EFI support. + +* Graphical menu support. + +* MIPS support. + +* Saved default menu entry support, with new utilities `grub-reboot' and + `grub-set-default'. + +* Unit testing framework. + +* Support for multiple terminals. + +* Encrypted password support, with a new utility `grub-mkpasswd-pbkdf2'. + +* `grub-mkfloppy' removed; use `grub-mkrescue' to create floppy images. * Add grub-probe support for GNU/Hurd. diff --git a/acinclude.m4 b/acinclude.m4 index 6f9baf18f..692404e20 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -14,11 +14,11 @@ $2 dnl Check whether target compiler is working -AC_DEFUN(grub_PROG_TARGET_CC, +AC_DEFUN([grub_PROG_TARGET_CC], [AC_MSG_CHECKING([whether target compiler is working]) AC_CACHE_VAL(grub_cv_prog_target_cc, [AC_LINK_IFELSE([AC_LANG_PROGRAM([[ -asm (".globl start; start: nop"); +asm (".globl start; start:"); int main (void); ]], [[]])], [grub_cv_prog_target_cc=yes], @@ -36,7 +36,7 @@ dnl grub_ASM_USCORE checks if C symbols get an underscore after dnl compiling to assembler. dnl Written by Pavel Roskin. Based on grub_ASM_EXT_C written by dnl Erich Boleyn and modified by Yoshinori K. Okuji. -AC_DEFUN(grub_ASM_USCORE, +AC_DEFUN([grub_ASM_USCORE], [AC_REQUIRE([AC_PROG_CC]) AC_MSG_CHECKING([if C symbols get an underscore after compilation]) AC_CACHE_VAL(grub_cv_asm_uscore, @@ -75,7 +75,7 @@ AC_MSG_RESULT([$grub_cv_asm_uscore]) dnl Some versions of `objcopy -O binary' vary their output depending dnl on the link address. -AC_DEFUN(grub_PROG_OBJCOPY_ABSOLUTE, +AC_DEFUN([grub_PROG_OBJCOPY_ABSOLUTE], [AC_MSG_CHECKING([whether ${OBJCOPY} works for absolute addresses]) AC_CACHE_VAL(grub_cv_prog_objcopy_absolute, [cat > conftest.c <<\EOF @@ -119,7 +119,7 @@ fi dnl Supply --build-id=none to ld if building modules. dnl This suppresses warnings from ld on some systems -AC_DEFUN(grub_PROG_LD_BUILD_ID_NONE, +AC_DEFUN([grub_PROG_LD_BUILD_ID_NONE], [AC_MSG_CHECKING([whether linker accepts --build-id=none]) AC_CACHE_VAL(grub_cv_prog_ld_build_id_none, [save_LDFLAGS="$LDFLAGS" @@ -150,7 +150,7 @@ dnl dnl We only support the newer versions, because the old versions cause dnl major pain, by requiring manual assembly to get 16-bit instructions into dnl asm files. -AC_DEFUN(grub_I386_ASM_ADDR32, +AC_DEFUN([grub_I386_ASM_ADDR32], [AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([grub_I386_ASM_PREFIX_REQUIREMENT]) AC_MSG_CHECKING([for .code16 addr32 assembler support]) @@ -178,7 +178,7 @@ AC_MSG_RESULT([$grub_cv_i386_asm_addr32])]) dnl check if our compiler is apple cc dnl because it requires numerous workarounds -AC_DEFUN(grub_apple_cc, +AC_DEFUN([grub_apple_cc], [AC_REQUIRE([AC_PROG_CC]) AC_MSG_CHECKING([whether our compiler is apple cc]) AC_CACHE_VAL(grub_cv_apple_cc, @@ -193,7 +193,7 @@ AC_MSG_RESULT([$grub_cv_apple_cc])]) dnl check if our target compiler is apple cc dnl because it requires numerous workarounds -AC_DEFUN(grub_apple_target_cc, +AC_DEFUN([grub_apple_target_cc], [AC_REQUIRE([AC_PROG_CC]) AC_MSG_CHECKING([whether our target compiler is apple cc]) AC_CACHE_VAL(grub_cv_apple_target_cc, @@ -210,7 +210,7 @@ AC_MSG_RESULT([$grub_cv_apple_target_cc])]) dnl Later versions of GAS requires that addr32 and data32 prefixes dnl appear in the same lines as the instructions they modify, while dnl earlier versions requires that they appear in separate lines. -AC_DEFUN(grub_I386_ASM_PREFIX_REQUIREMENT, +AC_DEFUN([grub_I386_ASM_PREFIX_REQUIREMENT], [AC_REQUIRE([AC_PROG_CC]) AC_MSG_CHECKING(dnl [whether addr32 must be in the same line as the instruction]) @@ -246,7 +246,7 @@ AC_MSG_RESULT([$grub_cv_i386_asm_prefix_requirement])]) dnl Older versions of GAS require that absolute indirect calls/jumps are dnl not prefixed with `*', while later versions warn if not prefixed. -AC_DEFUN(grub_I386_ASM_ABSOLUTE_WITHOUT_ASTERISK, +AC_DEFUN([grub_I386_ASM_ABSOLUTE_WITHOUT_ASTERISK], [AC_REQUIRE([AC_PROG_CC]) AC_MSG_CHECKING(dnl [whether an absolute indirect call/jump must not be prefixed with an asterisk]) @@ -276,7 +276,7 @@ AC_MSG_RESULT([$grub_cv_i386_asm_absolute_without_asterisk])]) dnl Check what symbol is defined as a bss start symbol. dnl Written by Michael Hohmoth and Yoshinori K. Okuji. -AC_DEFUN(grub_CHECK_BSS_START_SYMBOL, +AC_DEFUN([grub_CHECK_BSS_START_SYMBOL], [AC_REQUIRE([AC_PROG_CC]) AC_MSG_CHECKING([if __bss_start is defined by the compiler]) AC_CACHE_VAL(grub_cv_check_uscore_uscore_bss_start_symbol, @@ -320,7 +320,7 @@ fi dnl Check what symbol is defined as an end symbol. dnl Written by Yoshinori K. Okuji. -AC_DEFUN(grub_CHECK_END_SYMBOL, +AC_DEFUN([grub_CHECK_END_SYMBOL], [AC_REQUIRE([AC_PROG_CC]) AC_MSG_CHECKING([if end is defined by the compiler]) AC_CACHE_VAL(grub_cv_check_end_symbol, @@ -352,7 +352,7 @@ fi ]) dnl Check if the C compiler generates calls to `__enable_execute_stack()'. -AC_DEFUN(grub_CHECK_ENABLE_EXECUTE_STACK,[ +AC_DEFUN([grub_CHECK_ENABLE_EXECUTE_STACK],[ AC_MSG_CHECKING([whether `$CC' generates calls to `__enable_execute_stack()']) AC_LANG_CONFTEST([[ void f (int (*p) (void)); @@ -379,7 +379,7 @@ rm -f conftest* dnl Check if the C compiler supports `-fstack-protector'. -AC_DEFUN(grub_CHECK_STACK_PROTECTOR,[ +AC_DEFUN([grub_CHECK_STACK_PROTECTOR],[ [# Smashing stack protector. ssp_possible=yes] AC_MSG_CHECKING([whether `$CC' accepts `-fstack-protector']) @@ -398,7 +398,7 @@ else ]) dnl Check if the C compiler supports `-mstack-arg-probe' (Cygwin). -AC_DEFUN(grub_CHECK_STACK_ARG_PROBE,[ +AC_DEFUN([grub_CHECK_STACK_ARG_PROBE],[ [# Smashing stack arg probe. sap_possible=yes] AC_MSG_CHECKING([whether `$CC' accepts `-mstack-arg-probe']) @@ -414,7 +414,7 @@ else ]) dnl Check if ln can handle directories properly (mingw). -AC_DEFUN(grub_CHECK_LINK_DIR,[ +AC_DEFUN([grub_CHECK_LINK_DIR],[ AC_MSG_CHECKING([whether ln can handle directories properly]) [mkdir testdir 2>/dev/null case $srcdir in @@ -432,7 +432,7 @@ rm -rf testdir] ]) dnl Check if the C compiler supports `-fPIE'. -AC_DEFUN(grub_CHECK_PIE,[ +AC_DEFUN([grub_CHECK_PIE],[ [# Position independent executable. pie_possible=yes] AC_MSG_CHECKING([whether `$CC' has `-fPIE' as default]) diff --git a/boot/i386/pc/pxeboot.S b/boot/i386/pc/pxeboot.S index 28c90e29b..446bfc781 100644 --- a/boot/i386/pc/pxeboot.S +++ b/boot/i386/pc/pxeboot.S @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2000,2005,2007,2008,2009 Free Software Foundation, Inc. + * Copyright (C) 2000,2005,2007,2008,2009,2010 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,6 +16,8 @@ * along with GRUB. If not, see . */ +#include + .file "pxeboot.S" .text @@ -28,7 +30,7 @@ _start: start: /* Use drive number 0x7F for PXE */ - movb $0x7F, %dl + movb $GRUB_BOOT_MACHINE_PXE_DL, %dl /* Jump to the real world */ ljmp $0, $0x8200 diff --git a/bus/bonito.c b/bus/bonito.c new file mode 100644 index 000000000..3f794c45a --- /dev/null +++ b/bus/bonito.c @@ -0,0 +1,90 @@ +/* bonito.c - PCI bonito interface. */ +/* + * 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 + +static grub_uint32_t base_win[GRUB_MACHINE_PCI_NUM_WIN]; +static const grub_size_t sizes_win[GRUB_MACHINE_PCI_NUM_WIN] = + {GRUB_MACHINE_PCI_WIN1_SIZE, GRUB_MACHINE_PCI_WIN_SIZE, + GRUB_MACHINE_PCI_WIN_SIZE}; +/* Usage counters. */ +static int usage_win[GRUB_MACHINE_PCI_NUM_WIN]; +static grub_addr_t addr_win[GRUB_MACHINE_PCI_NUM_WIN] = + {GRUB_MACHINE_PCI_WIN1_ADDR, GRUB_MACHINE_PCI_WIN2_ADDR, + GRUB_MACHINE_PCI_WIN3_ADDR}; + +static inline void +write_bases (void) +{ + int i; + grub_uint32_t reg = 0; + for (i = 0; i < GRUB_MACHINE_PCI_NUM_WIN; i++) + reg |= (((base_win[i] >> GRUB_MACHINE_PCI_WIN_SHIFT) + & GRUB_MACHINE_PCI_WIN_MASK) + >> (i * GRUB_MACHINE_PCI_WIN_MASK_SIZE)); + GRUB_MACHINE_PCI_IO_CTRL_REG = reg; +} + +volatile void * +grub_pci_device_map_range (grub_pci_device_t dev __attribute__ ((unused)), + grub_addr_t base, grub_size_t size) +{ + int i; + grub_addr_t newbase; + + /* First try already used registers. */ + for (i = 0; i < GRUB_MACHINE_PCI_NUM_WIN; i++) + if (usage_win[i] && base_win[i] <= base + && base_win[i] + sizes_win[i] > base + size) + { + usage_win[i]++; + return (void *) + (addr_win[i] | (base & GRUB_MACHINE_PCI_WIN_OFFSET_MASK)); + } + /* Map new register. */ + newbase = base & ~GRUB_MACHINE_PCI_WIN_OFFSET_MASK; + for (i = 0; i < GRUB_MACHINE_PCI_NUM_WIN; i++) + if (!usage_win[i] && newbase <= base + && newbase + sizes_win[i] > base + size) + { + usage_win[i]++; + base_win[i] = newbase; + write_bases (); + return (void *) + (addr_win[i] | (base & GRUB_MACHINE_PCI_WIN_OFFSET_MASK)); + } + grub_fatal ("Out of PCI windows."); +} + +void +grub_pci_device_unmap_range (grub_pci_device_t dev __attribute__ ((unused)), + volatile void *mem __attribute__ ((unused)), + grub_size_t size __attribute__ ((unused))) +{ + int i; + for (i = 0; i < GRUB_MACHINE_PCI_NUM_WIN; i++) + if (usage_win[i] && addr_win[i] + == (((grub_addr_t) mem) & ~GRUB_MACHINE_PCI_WIN_OFFSET_MASK)) + { + usage_win[i]--; + return; + } + grub_fatal ("Tried to unmap not mapped region"); +} diff --git a/bus/pci.c b/bus/pci.c index 65d848a18..a08e53446 100644 --- a/bus/pci.c +++ b/bus/pci.c @@ -24,7 +24,7 @@ grub_pci_address_t grub_pci_make_address (grub_pci_device_t dev, int reg) { return (1 << 31) | (dev.bus << 16) | (dev.device << 11) - | (dev.function << 8) | (reg << 2); + | (dev.function << 8) | reg; } void @@ -35,13 +35,13 @@ grub_pci_iterate (grub_pci_iteratefunc_t hook) grub_pci_id_t id; grub_uint32_t hdr; - for (dev.bus = 0; dev.bus < 256; dev.bus++) + for (dev.bus = 0; dev.bus < GRUB_PCI_NUM_BUS; dev.bus++) { - for (dev.device = 0; dev.device < 32; dev.device++) + for (dev.device = 0; dev.device < GRUB_PCI_NUM_DEVICES; dev.device++) { for (dev.function = 0; dev.function < 8; dev.function++) { - addr = grub_pci_make_address (dev, 0); + addr = grub_pci_make_address (dev, GRUB_PCI_REG_PCI_ID); id = grub_pci_read (addr); /* Check if there is a device present. */ @@ -54,7 +54,7 @@ grub_pci_iterate (grub_pci_iteratefunc_t hook) /* Probe only func = 0 if the device if not multifunction */ if (dev.function == 0) { - addr = grub_pci_make_address (dev, 3); + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CACHELINE); hdr = grub_pci_read (addr); if (!(hdr & 0x800000)) break; diff --git a/bus/usb/ohci.c b/bus/usb/ohci.c index 5fe9c9507..6d185bc7f 100644 --- a/bus/usb/ohci.c +++ b/bus/usb/ohci.c @@ -126,7 +126,7 @@ grub_ohci_pci_iter (grub_pci_device_t dev, grub_uint32_t revision; grub_uint32_t frame_interval; - addr = grub_pci_make_address (dev, 2); + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); class_code = grub_pci_read (addr) >> 8; interf = class_code & 0xFF; @@ -138,7 +138,7 @@ grub_ohci_pci_iter (grub_pci_device_t dev, return 0; /* Determine IO base address. */ - addr = grub_pci_make_address (dev, 4); + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); base = grub_pci_read (addr); #if 0 diff --git a/bus/usb/uhci.c b/bus/usb/uhci.c index e83fccc1d..947f2367b 100644 --- a/bus/usb/uhci.c +++ b/bus/usb/uhci.c @@ -150,7 +150,7 @@ grub_uhci_pci_iter (grub_pci_device_t dev, struct grub_uhci *u; int i; - addr = grub_pci_make_address (dev, 2); + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); class_code = grub_pci_read (addr) >> 8; interf = class_code & 0xFF; @@ -162,7 +162,7 @@ grub_uhci_pci_iter (grub_pci_device_t dev, return 0; /* Determine IO base address. */ - addr = grub_pci_make_address (dev, 8); + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG4); base = grub_pci_read (addr); /* Stop if there is no IO space base address defined. */ if (! (base & 1)) diff --git a/commands/cat.c b/commands/cat.c index 844034777..3bdafc4c6 100644 --- a/commands/cat.c +++ b/commands/cat.c @@ -41,7 +41,7 @@ grub_cmd_cat (grub_command_t cmd __attribute__ ((unused)), file = grub_gzfile_open (args[0], 1); if (! file) - return 0; + return grub_errno; while ((size = grub_file_read (file, buf, sizeof (buf))) > 0 && key != GRUB_TERM_ESC) diff --git a/commands/efi/fixvideo.c b/commands/efi/fixvideo.c index 0f821b7a2..6430be5e3 100644 --- a/commands/efi/fixvideo.c +++ b/commands/efi/fixvideo.c @@ -43,7 +43,7 @@ scan_card (grub_pci_device_t dev, grub_pci_id_t pciid) { grub_pci_address_t addr; - addr = grub_pci_make_address (dev, 2); + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); if (grub_pci_read_byte (addr + 3) == 0x3) { struct grub_video_patch *p = video_patches; diff --git a/commands/efi/loadbios.c b/commands/efi/loadbios.c index 653327d6c..8c7c25abd 100644 --- a/commands/efi/loadbios.c +++ b/commands/efi/loadbios.c @@ -51,7 +51,8 @@ enable_rom_area (void) return 0; } - addr = grub_pci_make_address (dev, 36); + /* FIXME: should be macroified. */ + addr = grub_pci_make_address (dev, 144); grub_pci_write_byte (addr++, 0x30); grub_pci_write_byte (addr++, 0x33); grub_pci_write_byte (addr++, 0x33); @@ -77,7 +78,8 @@ lock_rom_area (void) grub_pci_address_t addr; grub_pci_device_t dev = { .bus = 0, .device = 0, .function = 0}; - addr = grub_pci_make_address (dev, 36); + /* FIXME: should be macroified. */ + addr = grub_pci_make_address (dev, 144); grub_pci_write_byte (addr++, 0x10); grub_pci_write_byte (addr++, 0x11); grub_pci_write_byte (addr++, 0x11); diff --git a/commands/hashsum.c b/commands/hashsum.c index 60e17447b..951479fa7 100644 --- a/commands/hashsum.c +++ b/commands/hashsum.c @@ -57,7 +57,7 @@ static grub_err_t hash_file (grub_file_t file, const gcry_md_spec_t *hash, void *result) { grub_uint8_t context[hash->contextsize]; - char *readbuf[4096]; + grub_uint8_t readbuf[4096]; grub_memset (context, 0, sizeof (context)); hash->init (context); @@ -111,11 +111,9 @@ check_list (const gcry_md_spec_t *hash, const char *hashfilename, { char *filename; - filename = grub_malloc (grub_strlen (prefix) - + grub_strlen (p) + 2); + filename = grub_xasprintf ("%s/%s", prefix, p); if (!filename) return grub_errno; - grub_sprintf (filename, "%s/%s", prefix, p); file = grub_file_open (filename); grub_free (filename); } diff --git a/commands/help.c b/commands/help.c index 9234a3697..1181c3bfb 100644 --- a/commands/help.c +++ b/commands/help.c @@ -46,12 +46,10 @@ grub_cmd_help (grub_extcmd_t ext __attribute__ ((unused)), int argc, char *command_help; grub_uint32_t *unicode_command_help; grub_uint32_t *unicode_last_position; - - command_help = grub_malloc (grub_strlen (cmd->name) + - sizeof (" ") - 1 + - grub_strlen (summary_translated)); - grub_sprintf(command_help, "%s %s", cmd->name, summary_translated); + 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); diff --git a/commands/i386/pc/play.c b/commands/i386/pc/play.c index 1151dddf4..44d98a1f0 100644 --- a/commands/i386/pc/play.c +++ b/commands/i386/pc/play.c @@ -29,7 +29,7 @@ #include #include -#define BASE_TEMPO 120 +#define BASE_TEMPO (60 * GRUB_TICKS_PER_SECOND) /* The speaker port. */ #define SPEAKER 0x61 @@ -101,13 +101,13 @@ #define PIT_CTRL_COUNT_BINARY 0x00 /* 16-bit binary counter. */ #define PIT_CTRL_COUNT_BCD 0x01 /* 4-decade BCD counter. */ -#define T_REST ((short) 0) -#define T_FINE ((short) -1) +#define T_REST ((grub_uint16_t) 0) +#define T_FINE ((grub_uint16_t) -1) struct note { - short pitch; - short duration; + grub_uint16_t pitch; + grub_uint16_t duration; }; static void @@ -120,7 +120,7 @@ beep_off (void) } static void -beep_on (short pitch) +beep_on (grub_uint16_t pitch) { unsigned char status; unsigned int counter; @@ -143,60 +143,111 @@ beep_on (short pitch) grub_outb (status | SPEAKER_TMR2 | SPEAKER_DATA, SPEAKER); } +/* Returns whether playing should continue. */ +static int +play (unsigned tempo, struct note *note) +{ + unsigned int to; + + if (note->pitch == T_FINE || grub_checkkey () >= 0) + return 1; + + grub_dprintf ("play", "pitch = %d, duration = %d\n", note->pitch, + note->duration); + + switch (note->pitch) + { + case T_REST: + beep_off (); + break; + + default: + beep_on (note->pitch); + break; + } + + to = grub_get_rtc () + BASE_TEMPO * note->duration / tempo; + while (((unsigned int) grub_get_rtc () <= to) && (grub_checkkey () < 0)) + ; + + return 0; +} + static grub_err_t grub_cmd_play (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) { grub_file_t file; - struct note buf; - int tempo; - unsigned int to; - if (argc != 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); + if (argc < 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name or tempo and notes required"); file = grub_file_open (args[0]); - if (! file) - return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); - - if (grub_file_read (file, &tempo, sizeof(tempo)) != sizeof(tempo)) + if (file) { - grub_file_close (file); - return grub_error (GRUB_ERR_FILE_READ_ERROR, - "file doesn't even contains a full tempo record"); - } + struct note buf; + grub_uint32_t tempo; - grub_dprintf ("play","tempo = %d\n", tempo); - - while (grub_file_read (file, &buf, - sizeof (struct note)) == sizeof (struct note) - && buf.pitch != T_FINE && grub_checkkey () < 0) - { - - grub_dprintf ("play", "pitch = %d, duration = %d\n", buf.pitch, - buf.duration); - - switch (buf.pitch) + if (grub_file_read (file, &tempo, sizeof (tempo)) != sizeof (tempo)) { - case T_REST: - beep_off (); - break; + grub_file_close (file); + return grub_error (GRUB_ERR_FILE_READ_ERROR, + "file doesn't even contains a full tempo record"); + } - default: - beep_on (buf.pitch); + tempo = grub_le_to_cpu32 (tempo); + grub_dprintf ("play","tempo = %d\n", tempo); + + while (grub_file_read (file, &buf, + sizeof (struct note)) == sizeof (struct note)) + { + buf.pitch = grub_le_to_cpu16 (buf.pitch); + buf.duration = grub_le_to_cpu16 (buf.duration); + + if (play (tempo, &buf)) break; } - to = grub_get_rtc () + BASE_TEMPO * buf.duration / tempo; - while (((unsigned int) grub_get_rtc () <= to) && (grub_checkkey () < 0)) - ; + grub_file_close (file); + } + else + { + char *end; + unsigned tempo; + struct note note; + int i; + tempo = grub_strtoul (args[0], &end, 0); + + if (*end) + /* Was not a number either, assume it was supposed to be a file name. */ + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found"); + + grub_dprintf ("play","tempo = %d\n", tempo); + + for (i = 1; i + 1 < argc; i += 2) + { + note.pitch = grub_strtoul (args[i], &end, 0); + if (*end) + { + grub_error (GRUB_ERR_BAD_NUMBER, "bogus pitch number"); + break; + } + + note.duration = grub_strtoul (args[i + 1], &end, 0); + if (*end) + { + grub_error (GRUB_ERR_BAD_NUMBER, "bogus duration number"); + break; + } + + if (play (tempo, ¬e)) + break; + } } beep_off (); - grub_file_close (file); - while (grub_checkkey () > 0) grub_getkey (); @@ -208,7 +259,8 @@ static grub_command_t cmd; GRUB_MOD_INIT(play) { cmd = grub_register_command ("play", grub_cmd_play, - N_("FILE"), N_("Play a tune.")); + N_("FILE | TEMPO [PITCH1 DURATION1] [PITCH2 DURATION2] ... "), + N_("Play a tune.")); } GRUB_MOD_FINI(play) diff --git a/commands/i386/pc/vbetest.c b/commands/i386/pc/vbetest.c index d97323087..d2921c09d 100644 --- a/commands/i386/pc/vbetest.c +++ b/commands/i386/pc/vbetest.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include diff --git a/commands/loadenv.c b/commands/loadenv.c index 910392614..51b88cbc9 100644 --- a/commands/loadenv.c +++ b/commands/loadenv.c @@ -1,7 +1,7 @@ /* loadenv.c - command to load/save environment variable. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2008,2009 Free Software Foundation, Inc. + * Copyright (C) 2008,2009,2010 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -196,7 +196,7 @@ free_blocklists (struct blocklist *p) } } -static int +static grub_err_t check_blocklists (grub_envblk_t envblk, struct blocklist *blocklists, grub_file_t file) { @@ -219,8 +219,7 @@ check_blocklists (grub_envblk_t envblk, struct blocklist *blocklists, { /* This might be actually valid, but it is unbelievable that any filesystem makes such a silly allocation. */ - grub_error (GRUB_ERR_BAD_FS, "malformed file"); - return 0; + return grub_error (GRUB_ERR_BAD_FS, "malformed file"); } } @@ -230,8 +229,7 @@ check_blocklists (grub_envblk_t envblk, struct blocklist *blocklists, if (total_length != grub_file_size (file)) { /* Maybe sparse, unallocated sectors. No way in GRUB. */ - grub_error (GRUB_ERR_BAD_FILE_TYPE, "sparse file not allowed"); - return 0; + return grub_error (GRUB_ERR_BAD_FILE_TYPE, "sparse file not allowed"); } /* One more sanity check. Re-read all sectors by blocklists, and compare @@ -249,16 +247,13 @@ check_blocklists (grub_envblk_t envblk, struct blocklist *blocklists, if (grub_disk_read (disk, p->sector - part_start, p->offset, p->length, blockbuf)) - return 0; + return grub_errno; if (grub_memcmp (buf + index, blockbuf, p->length) != 0) - { - grub_error (GRUB_ERR_FILE_READ_ERROR, "invalid blocklist"); - return 0; - } + return grub_error (GRUB_ERR_FILE_READ_ERROR, "invalid blocklist"); } - return 1; + return GRUB_ERR_NONE; } static int @@ -347,7 +342,7 @@ grub_cmd_save_env (grub_extcmd_t cmd, int argc, char **args) if (! envblk) goto fail; - if (! check_blocklists (envblk, head, file)) + if (check_blocklists (envblk, head, file)) goto fail; while (argc) diff --git a/commands/ls.c b/commands/ls.c index 57409c4f6..eb1049617 100644 --- a/commands/ls.c +++ b/commands/ls.c @@ -87,19 +87,21 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human) int print_files_long (const char *filename, const struct grub_dirhook_info *info) { - char pathname[grub_strlen (dirname) + grub_strlen (filename) + 1]; - if ((! all) && (filename[0] == '.')) return 0; if (! info->dir) { grub_file_t file; + char *pathname; if (dirname[grub_strlen (dirname) - 1] == '/') - grub_sprintf (pathname, "%s%s", dirname, filename); + pathname = grub_xasprintf ("%s%s", dirname, filename); else - grub_sprintf (pathname, "%s/%s", dirname, filename); + pathname = grub_xasprintf ("%s/%s", dirname, filename); + + if (!pathname) + return 1; /* XXX: For ext2fs symlinks are detected as files while they should be reported as directories. */ @@ -107,6 +109,7 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human) if (! file) { grub_errno = 0; + grub_free (pathname); return 0; } @@ -131,8 +134,9 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human) grub_uint32_t whole, fraction; whole = grub_divmod64 (fsize, 100, &fraction); - grub_sprintf (buf, "%u.%02u%c", whole, fraction, - grub_human_sizes[units]); + grub_snprintf (buf, sizeof (buf), + "%u.%02u%c", whole, fraction, + grub_human_sizes[units]); grub_printf ("%-12s", buf); } else @@ -140,6 +144,7 @@ grub_ls_list_files (char *dirname, int longlist, int all, int human) } grub_file_close (file); + grub_free (pathname); } else grub_printf ("%-12s", "DIR"); diff --git a/commands/lspci.c b/commands/lspci.c index c2abd8736..a69bb35ad 100644 --- a/commands/lspci.c +++ b/commands/lspci.c @@ -135,7 +135,7 @@ grub_lspci_iter (grub_pci_device_t dev, grub_pci_id_t pciid) grub_printf ("%02x:%02x.%x %04x:%04x", grub_pci_get_bus (dev), grub_pci_get_device (dev), grub_pci_get_function (dev), pciid & 0xFFFF, pciid >> 16); - addr = grub_pci_make_address (dev, 2); + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); class = grub_pci_read (addr); /* Lookup the class name, if there isn't a specific one, @@ -156,22 +156,24 @@ grub_lspci_iter (grub_pci_device_t dev, grub_pci_id_t pciid) if (iospace) { - reg = 4; - while (reg < 10) + reg = GRUB_PCI_REG_ADDRESSES; + while (reg < GRUB_PCI_REG_CIS_POINTER) { grub_uint64_t space; addr = grub_pci_make_address (dev, reg); space = grub_pci_read (addr); - reg++; - + reg += sizeof (grub_uint32_t); + if (space == 0) continue; switch (space & GRUB_PCI_ADDR_SPACE_MASK) { case GRUB_PCI_ADDR_SPACE_IO: - grub_printf ("\tIO space %d at 0x%llx\n", (reg - 1) - 4, + grub_printf ("\tIO space %d at 0x%llx\n", + (unsigned) ((reg - GRUB_PCI_REG_ADDRESSES) + / sizeof (grub_uint32_t)) - 1, (unsigned long long) (space & GRUB_PCI_ADDR_IO_MASK)); break; @@ -181,9 +183,11 @@ grub_lspci_iter (grub_pci_device_t dev, grub_pci_id_t pciid) { addr = grub_pci_make_address (dev, reg); space |= ((grub_uint64_t) grub_pci_read (addr)) << 32; - reg++; + reg += sizeof (grub_uint32_t); grub_printf ("\t64-bit memory space %d at 0x%016llx [%s]\n", - (reg - 2) - 4, (unsigned long long) + (unsigned) ((reg - GRUB_PCI_REG_ADDRESSES) + / sizeof (grub_uint32_t)) - 2, + (unsigned long long) (space & GRUB_PCI_ADDR_MEM_MASK), space & GRUB_PCI_ADDR_MEM_PREFETCH ? "prefetchable" : "non-prefetchable"); @@ -191,7 +195,9 @@ grub_lspci_iter (grub_pci_device_t dev, grub_pci_id_t pciid) } else grub_printf ("\t32-bit memory space %d at 0x%016llx [%s]\n", - (reg - 1) - 4, (unsigned long long) + (unsigned) ((reg - GRUB_PCI_REG_ADDRESSES) + / sizeof (grub_uint32_t)) - 1, + (unsigned long long) (space & GRUB_PCI_ADDR_MEM_MASK), space & GRUB_PCI_ADDR_MEM_PREFETCH ? "prefetchable" : "non-prefetchable"); diff --git a/commands/memrw.c b/commands/memrw.c index d0908a237..6a4d43be2 100644 --- a/commands/memrw.c +++ b/commands/memrw.c @@ -62,7 +62,7 @@ grub_cmd_read (grub_extcmd_t cmd, int argc, char **argv) if (cmd->state[0].set) { - grub_sprintf (buf, "%x", value); + grub_snprintf (buf, sizeof (buf), "%x", value); grub_env_set (cmd->state[0].arg, buf); } else diff --git a/commands/minicmd.c b/commands/minicmd.c index 72e855faf..4ea9efead 100644 --- a/commands/minicmd.c +++ b/commands/minicmd.c @@ -316,7 +316,6 @@ grub_mini_cmd_lsmod (struct grub_command *cmd __attribute__ ((unused)), grub_printf ("%s", dep->mod->name); } grub_putchar ('\n'); - grub_refresh (); return 0; } diff --git a/commands/parttool.c b/commands/parttool.c index 3f69d5525..5ad6133ca 100644 --- a/commands/parttool.c +++ b/commands/parttool.c @@ -183,12 +183,11 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)), { char *filename; - filename = grub_malloc (grub_strlen (prefix) + sizeof ("/parttool.lst")); + filename = grub_xasprintf ("%s/parttool.lst", prefix); if (filename) { grub_file_t file; - grub_sprintf (filename, "%s/parttool.lst", prefix); file = grub_file_open (filename); if (file) { diff --git a/commands/search.c b/commands/search.c index ec736de3c..afb2e98e8 100644 --- a/commands/search.c +++ b/commands/search.c @@ -33,7 +33,6 @@ void FUNC_NAME (const char *key, const char *var, int no_floppy) { int count = 0; - char *buf = NULL; grub_fs_autoload_hook_t saved_autoload; auto int iterate_device (const char *name); @@ -48,24 +47,20 @@ FUNC_NAME (const char *key, const char *var, int no_floppy) #ifdef DO_SEARCH_FILE { - grub_size_t len; - char *p; + char *buf; grub_file_t file; - len = grub_strlen (name) + 2 + grub_strlen (key) + 1; - p = grub_realloc (buf, len); - if (! p) + buf = grub_xasprintf ("(%s)%s", name, key); + if (! buf) return 1; - buf = p; - grub_sprintf (buf, "(%s)%s", name, key); - file = grub_file_open (buf); if (file) { found = 1; grub_file_close (file); } + grub_free (buf); } #else { @@ -135,8 +130,6 @@ FUNC_NAME (const char *key, const char *var, int no_floppy) else grub_device_iterate (iterate_device); - grub_free (buf); - if (grub_errno == GRUB_ERR_NONE && count == 0) grub_error (GRUB_ERR_FILE_NOT_FOUND, "no such device: %s", key); } diff --git a/commands/setpci.c b/commands/setpci.c new file mode 100644 index 000000000..f780547a2 --- /dev/null +++ b/commands/setpci.c @@ -0,0 +1,340 @@ +/* lspci.c - List PCI devices. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008, 2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +struct pci_register +{ + const char *name; + grub_uint16_t addr; + unsigned size; +}; + +struct pci_register pci_registers[] = + { + {"VENDOR_ID", GRUB_PCI_REG_VENDOR , 2}, + {"DEVICE_ID", GRUB_PCI_REG_DEVICE , 2}, + {"COMMAND", GRUB_PCI_REG_COMMAND , 2}, + {"STATUS", GRUB_PCI_REG_STATUS , 2}, + {"REVISION", GRUB_PCI_REG_REVISION , 1}, + {"CLASS_PROG", GRUB_PCI_REG_CLASS + 1 , 1}, + {"CLASS_DEVICE", GRUB_PCI_REG_CLASS + 2 , 2}, + {"CACHE_LINE_SIZE", GRUB_PCI_REG_CACHELINE , 1}, + {"LATENCY_TIMER", GRUB_PCI_REG_LAT_TIMER , 1}, + {"HEADER_TYPE", GRUB_PCI_REG_HEADER_TYPE , 1}, + {"BIST", GRUB_PCI_REG_BIST , 1}, + {"BASE_ADDRESS_0", GRUB_PCI_REG_ADDRESS_REG0, 4}, + {"BASE_ADDRESS_1", GRUB_PCI_REG_ADDRESS_REG1, 4}, + {"BASE_ADDRESS_2", GRUB_PCI_REG_ADDRESS_REG2, 4}, + {"BASE_ADDRESS_3", GRUB_PCI_REG_ADDRESS_REG3, 4}, + {"BASE_ADDRESS_4", GRUB_PCI_REG_ADDRESS_REG4, 4}, + {"BASE_ADDRESS_5", GRUB_PCI_REG_ADDRESS_REG5, 4}, + {"CARDBUS_CIS", GRUB_PCI_REG_CIS_POINTER , 4}, + {"SUBVENDOR_ID", GRUB_PCI_REG_SUBVENDOR , 2}, + {"SUBSYSTEM_ID", GRUB_PCI_REG_SUBSYSTEM , 2}, + {"ROM_ADDRESS", GRUB_PCI_REG_ROM_ADDRESS , 4}, + {"CAP_POINTER", GRUB_PCI_REG_CAP_POINTER , 1}, + {"INTERRUPT_LINE", GRUB_PCI_REG_IRQ_LINE , 1}, + {"INTERRUPT_PIN", GRUB_PCI_REG_IRQ_PIN , 1}, + {"MIN_GNT", GRUB_PCI_REG_MIN_GNT , 1}, + {"MAX_LAT", GRUB_PCI_REG_MIN_GNT , 1}, + }; + +static const struct grub_arg_option options[] = + { + {0, 'd', 0, "Select device by vendor and device IDs.", + "[vendor]:[device]", ARG_TYPE_STRING}, + {0, 's', 0, "Select device by its position on the bus.", + "[bus]:[slot][.func]", ARG_TYPE_STRING}, + {0, 'v', 0, "Save read value into variable VARNAME.", + "VARNAME", ARG_TYPE_STRING}, + {0, 0, 0, 0, 0, 0} + }; + +static grub_uint32_t pciid_check_mask, pciid_check_value; +static int bus, device, function; +static int check_bus, check_device, check_function; +static grub_uint32_t write_mask, regwrite; +static int regsize; +static grub_uint16_t regaddr; +static const char *varname; + +static int NESTED_FUNC_ATTR +grub_setpci_iter (grub_pci_device_t dev, grub_pci_id_t pciid) +{ + grub_uint32_t regval = 0; + grub_pci_address_t addr; + + if ((pciid & pciid_check_mask) != pciid_check_value) + return 0; + + if (check_bus && grub_pci_get_bus (dev) != bus) + return 0; + + if (check_device && grub_pci_get_device (dev) != device) + return 0; + + if (check_function && grub_pci_get_function (dev) != device) + return 0; + + addr = grub_pci_make_address (dev, regaddr); + + switch (regsize) + { + case 1: + regval = grub_pci_read_byte (addr); + break; + + case 2: + regval = grub_pci_read_word (addr); + break; + + case 4: + regval = grub_pci_read (addr); + break; + } + + if (varname) + { + char buf[sizeof ("XXXXXXXX")]; + grub_snprintf (buf, sizeof (buf), "%x", regval); + grub_env_set (varname, buf); + return 1; + } + + if (!write_mask) + { + grub_printf ("Register %x of %d:%d.%d is %x\n", regaddr, + grub_pci_get_bus (dev), + grub_pci_get_device (dev), + grub_pci_get_function (dev), + regval); + return 0; + } + + regval = (regval & ~write_mask) | regwrite; + + switch (regsize) + { + case 1: + grub_pci_write_byte (addr, regval); + break; + + case 2: + grub_pci_write_word (addr, regval); + break; + + case 4: + grub_pci_write (addr, regval); + break; + } + + return 0; +} + +static grub_err_t +grub_cmd_setpci (grub_extcmd_t cmd, int argc, char **argv) +{ + const char *ptr; + unsigned i; + + pciid_check_value = 0; + pciid_check_mask = 0; + + if (cmd->state[0].set) + { + ptr = cmd->state[0].arg; + pciid_check_value |= (grub_strtoul (ptr, (char **) &ptr, 16) & 0xffff); + if (grub_errno == GRUB_ERR_BAD_NUMBER) + { + grub_errno = GRUB_ERR_NONE; + ptr = cmd->state[0].arg; + } + else + pciid_check_mask |= 0xffff; + if (grub_errno) + return grub_errno; + if (*ptr != ':') + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Colon expected."); + ptr++; + pciid_check_value |= (grub_strtoul (ptr, (char **) &ptr, 16) & 0xffff) + << 16; + if (grub_errno == GRUB_ERR_BAD_NUMBER) + grub_errno = GRUB_ERR_NONE; + else + pciid_check_mask |= 0xffff0000; + } + + pciid_check_value &= pciid_check_mask; + + check_bus = check_device = check_function = 0; + + if (cmd->state[1].set) + { + const char *optr; + + ptr = cmd->state[1].arg; + optr = ptr; + bus = grub_strtoul (ptr, (char **) &ptr, 16); + if (grub_errno == GRUB_ERR_BAD_NUMBER) + { + grub_errno = GRUB_ERR_NONE; + ptr = optr; + } + else + check_bus = 1; + if (grub_errno) + return grub_errno; + if (*ptr != ':') + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Colon expected."); + ptr++; + optr = ptr; + device = grub_strtoul (ptr, (char **) &ptr, 16); + if (grub_errno == GRUB_ERR_BAD_NUMBER) + { + grub_errno = GRUB_ERR_NONE; + ptr = optr; + } + else + check_device = 1; + if (*ptr == '.') + { + ptr++; + function = grub_strtoul (ptr, (char **) &ptr, 16); + if (grub_errno) + return grub_errno; + check_function = 1; + } + } + + if (cmd->state[2].set) + varname = cmd->state[2].arg; + else + varname = NULL; + + write_mask = 0; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Command expected."); + + if (argc > 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Only one command is supported."); + + ptr = argv[0]; + + for (i = 0; i < ARRAY_SIZE (pci_registers); i++) + { + if (grub_strncmp (ptr, pci_registers[i].name, + grub_strlen (pci_registers[i].name)) == 0) + break; + } + if (i == ARRAY_SIZE (pci_registers)) + { + regsize = 0; + regaddr = grub_strtoul (ptr, (char **) &ptr, 16); + if (grub_errno) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unknown register"); + } + else + { + regaddr = pci_registers[i].addr; + regsize = pci_registers[i].size; + ptr += grub_strlen (pci_registers[i].name); + } + + if (grub_errno) + return grub_errno; + + if (*ptr == '+') + { + ptr++; + regaddr += grub_strtoul (ptr, (char **) &ptr, 16); + if (grub_errno) + return grub_errno; + } + + if (grub_memcmp (ptr, ".L", sizeof (".L") - 1) == 0 + || grub_memcmp (ptr, ".l", sizeof (".l") - 1) == 0) + { + regsize = 4; + ptr += sizeof (".l") - 1; + } + else if (grub_memcmp (ptr, ".W", sizeof (".W") - 1) == 0 + || grub_memcmp (ptr, ".w", sizeof (".w") - 1) == 0) + { + regsize = 2; + ptr += sizeof (".w") - 1; + } + else if (grub_memcmp (ptr, ".B", sizeof (".B") - 1) == 0 + || grub_memcmp (ptr, ".b", sizeof (".b") - 1) == 0) + { + regsize = 1; + ptr += sizeof (".b") - 1; + } + + if (!regsize) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "Unknown register size."); + + write_mask = 0; + if (*ptr == '=') + { + ptr++; + regwrite = grub_strtoul (ptr, (char **) &ptr, 16); + if (grub_errno) + return grub_errno; + write_mask = 0xffffffff; + if (*ptr == ':') + { + ptr++; + write_mask = grub_strtoul (ptr, (char **) &ptr, 16); + if (grub_errno) + return grub_errno; + write_mask = 0xffffffff; + } + regwrite &= write_mask; + } + + if (write_mask && varname) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "Option -v isn't valid for writes."); + + grub_pci_iterate (grub_setpci_iter); + return GRUB_ERR_NONE; +} + +static grub_extcmd_t cmd; + +GRUB_MOD_INIT(setpci) +{ + cmd = grub_register_extcmd ("setpci", grub_cmd_setpci, GRUB_COMMAND_FLAG_BOTH, + "setpci [-s POSITION] [-d DEVICE] [-v VAR] " + "[REGISTER][=VALUE[:MASK]]", + "Manipulate PCI devices.", options); +} + +GRUB_MOD_FINI(setpci) +{ + grub_unregister_extcmd (cmd); +} diff --git a/commands/terminal.c b/commands/terminal.c index b30f43130..e725123b8 100644 --- a/commands/terminal.c +++ b/commands/terminal.c @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2009 Free Software Foundation, Inc. + * Copyright (C) 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 @@ -112,10 +112,11 @@ grub_cmd_terminal_input (grub_command_t cmd __attribute__ ((unused)), break; if (term) { + if (term->init && term->init () != GRUB_ERR_NONE) + return grub_errno; + grub_list_remove (GRUB_AS_LIST_P (&(grub_term_inputs_disabled)), GRUB_AS_LIST (term)); - if (term->init) - term->init (); grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs), GRUB_AS_LIST (term)); } @@ -152,10 +153,11 @@ grub_cmd_terminal_input (grub_command_t cmd __attribute__ ((unused)), break; if (term) { + if (term->init && term->init () != GRUB_ERR_NONE) + return grub_errno; + grub_list_remove (GRUB_AS_LIST_P (&(grub_term_inputs_disabled)), GRUB_AS_LIST (term)); - if (term->init) - term->init (); grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs), GRUB_AS_LIST (term)); } @@ -269,10 +271,11 @@ grub_cmd_terminal_output (grub_command_t cmd __attribute__ ((unused)), break; if (term) { + if (term->init && term->init () != GRUB_ERR_NONE) + return grub_errno; + grub_list_remove (GRUB_AS_LIST_P (&(grub_term_outputs_disabled)), GRUB_AS_LIST (term)); - if (term->init) - term->init (); grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs), GRUB_AS_LIST (term)); } @@ -310,10 +313,11 @@ grub_cmd_terminal_output (grub_command_t cmd __attribute__ ((unused)), break; if (term) { + if (term->init && term->init () != GRUB_ERR_NONE) + return grub_errno; + grub_list_remove (GRUB_AS_LIST_P (&(grub_term_outputs_disabled)), GRUB_AS_LIST (term)); - if (term->init) - term->init (); grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs), GRUB_AS_LIST (term)); } diff --git a/commands/videotest.c b/commands/videotest.c index 850639bd9..390811a71 100644 --- a/commands/videotest.c +++ b/commands/videotest.c @@ -31,9 +31,7 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - if (grub_video_set_mode ("1024x768;800x600;640x480", 0) != GRUB_ERR_NONE) - return grub_errno; - + grub_err_t err; grub_video_color_t color; unsigned int x; unsigned int y; @@ -50,6 +48,10 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), const char *str; int texty; + err = grub_video_set_mode ("auto", GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0); + if (err) + return err; + grub_video_get_viewport (&x, &y, &width, &height); grub_video_create_render_target (&text_layer, width, height, @@ -67,9 +69,9 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), color = grub_video_map_rgb (0, 255, 255); grub_video_fill_rect (color, 100, 100, 100, 100); - sansbig = grub_font_get ("Helvetica Bold 24"); - sans = grub_font_get ("Helvetica Bold 14"); - sanssmall = grub_font_get ("Helvetica 8"); + 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"); @@ -124,11 +126,6 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), grub_font_draw_string (str, fixed, color, 16, texty); texty += grub_font_get_descent (fixed) + grub_font_get_leading (fixed); - /* Some character don't exist in the Helvetica font, so the font engine - will fall back to using glyphs from another font that does contain them. - TODO The font engine should be smart about selecting a replacement font - and prioritize fonts with similar sizes. */ - 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); @@ -153,12 +150,13 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); - for (i = 0; i < 255; i++) + for (i = 0; i < 5; i++) { color = grub_video_map_rgb (i, 33, 77); grub_video_fill_rect (color, 0, 0, width, height); grub_video_blit_render_target (text_layer, GRUB_VIDEO_BLIT_BLEND, 0, 0, 0, 0, width, height); + grub_video_swap_buffers (); } grub_getkey (); diff --git a/commands/xnu_uuid.c b/commands/xnu_uuid.c index b6f2b2604..382d3196b 100644 --- a/commands/xnu_uuid.c +++ b/commands/xnu_uuid.c @@ -61,7 +61,7 @@ grub_cmd_xnu_uuid (grub_command_t cmd __attribute__ ((unused)), GRUB_MD_MD5->final (&ctx); xnu_uuid = GRUB_MD_MD5->read (&ctx); - grub_sprintf (uuid_string, + grub_snprintf (uuid_string, sizeof (uuid_string), "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", (unsigned int) xnu_uuid[0], (unsigned int) xnu_uuid[1], (unsigned int) xnu_uuid[2], (unsigned int) xnu_uuid[3], diff --git a/conf/any-emu.rmk b/conf/any-emu.rmk index cee9e8338..ff0d69c41 100644 --- a/conf/any-emu.rmk +++ b/conf/any-emu.rmk @@ -30,7 +30,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c \ normal/completion.c normal/main.c normal/color.c \ normal/menu.c normal/menu_entry.c \ normal/menu_text.c normal/crypto.c normal/term.c \ - commands/terminal.c lib/charset.c \ + commands/terminal.c normal/context.c lib/charset.c \ script/main.c script/execute.c script/function.c \ script/lexer.c script/script.c grub_script.tab.c \ partmap/amiga.c partmap/apple.c partmap/msdos.c partmap/sun.c \ @@ -42,6 +42,20 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c \ fs/ufs.c fs/ufs2.c fs/xfs.c fs/afs.c fs/afs_be.c \ fs/befs.c fs/befs_be.c fs/tar.c \ \ + video/video.c video/fb/video_fb.c video/fb/fbblit.c \ + video/fb/fbfill.c video/fb/fbutil.c commands/videotest.c \ + video/bitmap.c video/bitmap_scale.c video/readers/tga.c \ + video/readers/jpeg.c video/readers/png.c font/font_cmd.c \ + font/font.c term/gfxterm.c io/bufio.c \ + \ + gfxmenu/gfxmenu.c gfxmenu/model.c gfxmenu/view.c \ + gfxmenu/icon_manager.c gfxmenu/theme_loader.c \ + gfxmenu/widget-box.c gfxmenu/gui_canvas.c \ + gfxmenu/gui_circular_progress.c gfxmenu/gui_box.c \ + gfxmenu/gui_label.c gfxmenu/gui_list.c gfxmenu/gui_image.c \ + gfxmenu/gui_progress_bar.c gfxmenu/gui_util.c \ + gfxmenu/gui_string_util.c gfxmenu/named_colors.c trigtables.c \ + \ util/console.c util/hostfs.c util/grub-emu.c util/misc.c \ util/hostdisk.c util/getroot.c \ \ @@ -65,6 +79,11 @@ grub_emu_SOURCES += disk/usbms.c util/usb.c bus/usb/usb.c \ grub_emu_LDFLAGS += $(LIBCURSES) $(LIBUSB) endif +ifeq ($(enable_grub_emu_sdl), yes) +grub_emu_SOURCES += util/sdl.c +grub_emu_LDFLAGS += $(LIBSDL) +endif + ifeq ($(enable_grub_emu_pci), yes) grub_emu_SOURCES += util/pci.c commands/lspci.c grub_emu_LDFLAGS += $(LIBPCIACCESS) @@ -87,6 +106,13 @@ DISTCLEANFILES += grub_emu_init.c # FIXME: this could be shared with common.rmk +trigtables.c: gentrigtables + ./gentrigtables > $@ +DISTCLEANFILES += trigtables.c +gentrigtables: gentrigtables.c + $(CC) -o $@ $^ $(CPPFLAGS) -lm +DISTCLEANFILES += gentrigtables + # For grub-mkfont. ifeq ($(enable_grub_mkfont), yes) bin_UTILITIES += grub-mkfont @@ -98,3 +124,6 @@ endif 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 + +bin_UTILITIES += grub-bin2h +grub_bin2h_SOURCES = gnulib/progname.c util/bin2h.c diff --git a/conf/common.rmk b/conf/common.rmk index 31b62892b..7effa8af3 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -88,11 +88,36 @@ endif bin_UTILITIES += grub-mkrelpath grub_mkrelpath_SOURCES = gnulib/progname.c util/grub-mkrelpath.c util/misc.c +bin_UTILITIES += grub-bin2h +grub_bin2h_SOURCES = gnulib/progname.c util/bin2h.c + +# 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 \ + 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 + # For the parser. 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 > $@ @@ -427,6 +452,28 @@ hello_mod_SOURCES = hello/hello.c hello_mod_CFLAGS = $(COMMON_CFLAGS) hello_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For gfxmenu.mod. +pkglib_MODULES += gfxmenu.mod +gfxmenu_mod_SOURCES = \ + gfxmenu/gfxmenu.c \ + gfxmenu/model.c \ + gfxmenu/view.c \ + gfxmenu/icon_manager.c \ + gfxmenu/theme_loader.c \ + gfxmenu/widget-box.c \ + gfxmenu/gui_canvas.c \ + gfxmenu/gui_circular_progress.c \ + gfxmenu/gui_box.c \ + gfxmenu/gui_label.c \ + gfxmenu/gui_list.c \ + gfxmenu/gui_image.c \ + gfxmenu/gui_progress_bar.c \ + gfxmenu/gui_util.c \ + gfxmenu/gui_string_util.c \ + gfxmenu/named_colors.c +gfxmenu_mod_CFLAGS = $(COMMON_CFLAGS) +gfxmenu_mod_LDFLAGS = $(COMMON_LDFLAGS) + # For parttool.mod. parttool_mod_SOURCES = commands/parttool.c parttool_mod_CFLAGS = $(COMMON_CFLAGS) @@ -564,7 +611,7 @@ normal_mod_SOURCES = normal/main.c normal/cmdline.c normal/dyncmd.c \ normal/auth.c normal/autofs.c normal/handler.c \ normal/color.c normal/completion.c normal/datetime.c normal/menu.c \ normal/menu_entry.c normal/menu_text.c \ - normal/misc.c normal/crypto.c normal/term.c + normal/misc.c normal/crypto.c normal/term.c normal/context.c normal_mod_CFLAGS = $(COMMON_CFLAGS) normal_mod_LDFLAGS = $(COMMON_LDFLAGS) @@ -574,57 +621,78 @@ sh_mod_SOURCES = script/main.c script/script.c script/execute.c \ sh_mod_CFLAGS = $(COMMON_CFLAGS) sh_mod_LDFLAGS = $(COMMON_LDFLAGS) +ifneq (, $(FONT_SOURCE)) +font/font.c_DEPENDENCIES = ascii.h +endif + # Common Video Subsystem specific modules. -pkglib_MODULES += video.mod videotest.mod bitmap.mod tga.mod jpeg.mod \ - png.mod font.mod gfxterm.mod video_fb.mod +# On Yeeloong it's part of kernel +ifneq ($(platform), yeeloong) # For video.mod. +pkglib_MODULES += video.mod video_mod_SOURCES = video/video.c video_mod_CFLAGS = $(COMMON_CFLAGS) video_mod_LDFLAGS = $(COMMON_LDFLAGS) +pkglib_MODULES += video_fb.mod video_fb_mod_SOURCES = video/fb/video_fb.c video/fb/fbblit.c \ video/fb/fbfill.c video/fb/fbutil.c video_fb_mod_CFLAGS = $(COMMON_CFLAGS) video_fb_mod_LDFLAGS = $(COMMON_LDFLAGS) -# For videotest.mod. -videotest_mod_SOURCES = commands/videotest.c -videotest_mod_CFLAGS = $(COMMON_CFLAGS) -videotest_mod_LDFLAGS = $(COMMON_LDFLAGS) - # For bitmap.mod +pkglib_MODULES += bitmap.mod bitmap_mod_SOURCES = video/bitmap.c bitmap_mod_CFLAGS = $(COMMON_CFLAGS) bitmap_mod_LDFLAGS = $(COMMON_LDFLAGS) -# For tga.mod -tga_mod_SOURCES = video/readers/tga.c -tga_mod_CFLAGS = $(COMMON_CFLAGS) -tga_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For bitmap_scale.mod +pkglib_MODULES += bitmap_scale.mod +bitmap_scale_mod_SOURCES = video/bitmap_scale.c +bitmap_scale_mod_CFLAGS = $(COMMON_CFLAGS) +bitmap_scale_mod_LDFLAGS = $(COMMON_LDFLAGS) -# For jpeg.mod. -jpeg_mod_SOURCES = video/readers/jpeg.c -jpeg_mod_CFLAGS = $(COMMON_CFLAGS) -jpeg_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For png.mod. -png_mod_SOURCES = video/readers/png.c -png_mod_CFLAGS = $(COMMON_CFLAGS) -png_mod_LDFLAGS = $(COMMON_LDFLAGS) - -# For font.mod. +pkglib_MODULES += font.mod font_mod_SOURCES = font/font_cmd.c font/font.c font_mod_CFLAGS = $(COMMON_CFLAGS) font_mod_LDFLAGS = $(COMMON_LDFLAGS) # For gfxterm.mod. +pkglib_MODULES += gfxterm.mod gfxterm_mod_SOURCES = term/gfxterm.c gfxterm_mod_CFLAGS = $(COMMON_CFLAGS) gfxterm_mod_LDFLAGS = $(COMMON_LDFLAGS) +endif + +# For videotest.mod. +pkglib_MODULES += videotest.mod +videotest_mod_SOURCES = commands/videotest.c +videotest_mod_CFLAGS = $(COMMON_CFLAGS) +videotest_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For tga.mod +pkglib_MODULES += tga.mod +tga_mod_SOURCES = video/readers/tga.c +tga_mod_CFLAGS = $(COMMON_CFLAGS) +tga_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For jpeg.mod. +pkglib_MODULES += jpeg.mod +jpeg_mod_SOURCES = video/readers/jpeg.c +jpeg_mod_CFLAGS = $(COMMON_CFLAGS) +jpeg_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For png.mod. +pkglib_MODULES += png.mod +png_mod_SOURCES = video/readers/png.c +png_mod_CFLAGS = $(COMMON_CFLAGS) +png_mod_LDFLAGS = $(COMMON_LDFLAGS) + + # Misc. -pkglib_MODULES += gzio.mod bufio.mod elf.mod +pkglib_MODULES += gzio.mod elf.mod # For elf.mod. elf_mod_SOURCES = kern/elf.c @@ -636,10 +704,14 @@ gzio_mod_SOURCES = io/gzio.c gzio_mod_CFLAGS = $(COMMON_CFLAGS) gzio_mod_LDFLAGS = $(COMMON_LDFLAGS) +# On Yeeloong it's part of kernel +ifneq ($(platform), yeeloong) # For bufio.mod. +pkglib_MODULES += bufio.mod bufio_mod_SOURCES = io/bufio.c bufio_mod_CFLAGS = $(COMMON_CFLAGS) bufio_mod_LDFLAGS = $(COMMON_LDFLAGS) +endif # For gettext.mod. pkglib_MODULES += gettext.mod @@ -655,6 +727,18 @@ xnu_uuid_mod_SOURCES = commands/xnu_uuid.c xnu_uuid_mod_CFLAGS = $(COMMON_CFLAGS) xnu_uuid_mod_LDFLAGS = $(COMMON_LDFLAGS) +pkglib_MODULES += trig.mod +trig_mod_SOURCES = trigtables.c +trig_mod_CFLAGS = $(COMMON_CFLAGS) +trig_mod_LDFLAGS = $(COMMON_LDFLAGS) + +trigtables.c: gentrigtables + ./gentrigtables > $@ +DISTCLEANFILES += trigtables.c +gentrigtables: gentrigtables.c + $(CC) -o $@ $^ $(CPPFLAGS) -lm +DISTCLEANFILES += gentrigtables + pkglib_MODULES += setjmp.mod setjmp_mod_SOURCES = lib/$(target_cpu)/setjmp.S setjmp_mod_ASFLAGS = $(COMMON_ASFLAGS) @@ -692,7 +776,7 @@ password_pbkdf2_mod_CFLAGS = $(COMMON_CFLAGS) password_pbkdf2_mod_LDFLAGS = $(COMMON_LDFLAGS) bin_UTILITIES += grub-mkpasswd-pbkdf2 -grub_mkpasswd_pbkdf2_SOURCES = gnulib/progname.c util/grub-mkpasswd-pbkdf2.c lib/crypto.c lib/libgcrypt-grub/cipher/sha512.c lib/pbkdf2.c util/misc.c kern/err.c +grub_mkpasswd_pbkdf2_SOURCES = gnulib/progname.c gnulib/getdelim.c gnulib/getline.c util/grub-mkpasswd-pbkdf2.c lib/crypto.c lib/libgcrypt-grub/cipher/sha512.c lib/pbkdf2.c util/misc.c kern/err.c grub_mkpasswd_pbkdf2_CFLAGS += -Wno-missing-field-initializers -Wno-error -I$(srcdir)/lib/libgcrypt_wrap -DGRUB_MKPASSWD=1 include $(srcdir)/conf/gcry.mk diff --git a/conf/i386-coreboot.rmk b/conf/i386-coreboot.rmk index 57fb3350c..9563c0b2b 100644 --- a/conf/i386-coreboot.rmk +++ b/conf/i386-coreboot.rmk @@ -35,7 +35,8 @@ 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 \ machine/boot.h machine/console.h machine/init.h \ - machine/memory.h machine/loader.h list.h handler.h command.h i18n.h + machine/memory.h machine/loader.h list.h handler.h command.h i18n.h \ + env_private.h kernel_img_CFLAGS = $(COMMON_CFLAGS) kernel_img_ASFLAGS = $(COMMON_ASFLAGS) kernel_img_LDFLAGS = $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,$(GRUB_KERNEL_MACHINE_LINK_ADDR),-Bstatic @@ -53,9 +54,11 @@ boot_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)$(GRUB_BOOT_MACHINE_LI boot_img_FORMAT = binary bin_UTILITIES += grub-mkimage -grub_mkimage_SOURCES = util/i386/pc/grub-mkimage.c util/misc.c \ +grub_mkimage_SOURCES = util/grub-mkrawimage.c util/misc.c \ util/resolve.c gnulib/progname.c grub_mkimage_CFLAGS = -DGRUB_KERNEL_MACHINE_LINK_ADDR=$(GRUB_KERNEL_MACHINE_LINK_ADDR) +util/grub-mkrawimage.c_DEPENDENCIES = Makefile + pkglib_IMAGES += kernel.img kernel_img_SOURCES = kern/i386/qemu/startup.S \ @@ -79,7 +82,8 @@ 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 \ machine/boot.h machine/console.h machine/init.h \ - machine/memory.h machine/loader.h list.h handler.h command.h i18n.h + machine/memory.h machine/loader.h list.h handler.h command.h i18n.h \ + env_private.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) @@ -136,7 +140,7 @@ halt_mod_CFLAGS = $(COMMON_CFLAGS) halt_mod_LDFLAGS = $(COMMON_LDFLAGS) # For serial.mod. -serial_mod_SOURCES = term/i386/pc/serial.c +serial_mod_SOURCES = term/serial.c serial_mod_CFLAGS = $(COMMON_CFLAGS) serial_mod_LDFLAGS = $(COMMON_LDFLAGS) @@ -173,7 +177,7 @@ lspci_mod_CFLAGS = $(COMMON_CFLAGS) lspci_mod_LDFLAGS = $(COMMON_LDFLAGS) # For datetime.mod -datetime_mod_SOURCES = lib/i386/datetime.c +datetime_mod_SOURCES = lib/cmos_datetime.c datetime_mod_CFLAGS = $(COMMON_CFLAGS) datetime_mod_LDFLAGS = $(COMMON_LDFLAGS) diff --git a/conf/i386-efi.rmk b/conf/i386-efi.rmk index f3281a1bc..c03abb429 100644 --- a/conf/i386-efi.rmk +++ b/conf/i386-efi.rmk @@ -30,13 +30,14 @@ sbin_SCRIPTS = grub-install grub_install_SOURCES = util/i386/efi/grub-install.in # Modules. -pkglib_MODULES = kernel.img chain.mod appleldr.mod \ +pkglib_PROGRAMS = kernel.img +pkglib_MODULES = chain.mod appleldr.mod \ linux.mod halt.mod reboot.mod pci.mod lspci.mod \ datetime.mod date.mod datehook.mod loadbios.mod \ fixvideo.mod mmap.mod acpi.mod # For kernel.img. -kernel_img_EXPORTS = no +kernel_img_RELOCATABLE = yes kernel_img_SOURCES = kern/i386/efi/startup.S kern/main.c kern/device.c \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ kern/misc.c kern/mm.c kern/term.c \ @@ -51,7 +52,8 @@ kernel_img_SOURCES = kern/i386/efi/startup.S kern/main.c kern/device.c \ 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 \ - efi/efi.h efi/time.h efi/disk.h i386/pit.h list.h handler.h command.h i18n.h + efi/efi.h efi/time.h efi/disk.h i386/pit.h list.h handler.h command.h \ + i18n.h env_private.h kernel_img_CFLAGS = $(COMMON_CFLAGS) kernel_img_ASFLAGS = $(COMMON_ASFLAGS) kernel_img_LDFLAGS = $(COMMON_LDFLAGS) diff --git a/conf/i386-ieee1275.rmk b/conf/i386-ieee1275.rmk index 5c3a5aaf6..e19f6e9a1 100644 --- a/conf/i386-ieee1275.rmk +++ b/conf/i386-ieee1275.rmk @@ -33,7 +33,7 @@ kernel_img_HEADERS = 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 \ ieee1275/ieee1275.h machine/kernel.h machine/loader.h machine/memory.h \ - list.h handler.h command.h i18n.h + list.h handler.h command.h i18n.h env_private.h kernel_img_CFLAGS = $(COMMON_CFLAGS) kernel_img_ASFLAGS = $(COMMON_ASFLAGS) kernel_img_LDFLAGS = $(COMMON_LDFLAGS) -Wl,-N,-S,-Ttext,0x10000,-Bstatic @@ -92,7 +92,7 @@ halt_mod_CFLAGS = $(COMMON_CFLAGS) halt_mod_LDFLAGS = $(COMMON_LDFLAGS) # For serial.mod. -serial_mod_SOURCES = term/i386/pc/serial.c +serial_mod_SOURCES = term/serial.c serial_mod_CFLAGS = $(COMMON_CFLAGS) serial_mod_LDFLAGS = $(COMMON_LDFLAGS) @@ -122,7 +122,7 @@ lspci_mod_CFLAGS = $(COMMON_CFLAGS) lspci_mod_LDFLAGS = $(COMMON_LDFLAGS) # For datetime.mod -datetime_mod_SOURCES = lib/i386/datetime.c +datetime_mod_SOURCES = lib/cmos_datetime.c datetime_mod_CFLAGS = $(COMMON_CFLAGS) datetime_mod_LDFLAGS = $(COMMON_LDFLAGS) diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index a89203dea..580bfea0a 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -64,7 +64,8 @@ kernel_img_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \ partition.h msdos_partition.h reader.h symbol.h term.h time.h types.h \ machine/biosdisk.h machine/boot.h machine/console.h machine/init.h \ machine/memory.h machine/loader.h machine/vga.h machine/vbe.h \ - machine/kernel.h machine/pxe.h i386/pit.h list.h handler.h command.h i18n.h + machine/kernel.h machine/pxe.h i386/pit.h list.h handler.h command.h \ + i18n.h env_private.h kernel_img_CFLAGS = $(COMMON_CFLAGS) $(TARGET_IMG_CFLAGS) kernel_img_ASFLAGS = $(COMMON_ASFLAGS) kernel_img_LDFLAGS = $(COMMON_LDFLAGS) $(TARGET_IMG_LDFLAGS)$(GRUB_KERNEL_MACHINE_LINK_ADDR) $(COMMON_CFLAGS) @@ -84,10 +85,10 @@ bin_UTILITIES = grub-mkimage sbin_UTILITIES = grub-setup # For grub-mkimage. -grub_mkimage_SOURCES = gnulib/progname.c util/i386/pc/grub-mkimage.c util/misc.c \ +grub_mkimage_SOURCES = gnulib/progname.c util/grub-mkrawimage.c util/misc.c \ util/resolve.c lib/LzmaEnc.c lib/LzFind.c grub_mkimage_CFLAGS = -DGRUB_KERNEL_MACHINE_LINK_ADDR=$(GRUB_KERNEL_MACHINE_LINK_ADDR) -util/i386/pc/grub-mkimage.c_DEPENDENCIES = Makefile +util/grub-mkrawimage.c_DEPENDENCIES = Makefile # For grub-setup. util/i386/pc/grub-setup.c_DEPENDENCIES = grub_setup_init.h @@ -197,7 +198,7 @@ halt_mod_CFLAGS = $(COMMON_CFLAGS) halt_mod_LDFLAGS = $(COMMON_LDFLAGS) # For serial.mod. -serial_mod_SOURCES = term/i386/pc/serial.c +serial_mod_SOURCES = term/serial.c serial_mod_CFLAGS = $(COMMON_CFLAGS) serial_mod_LDFLAGS = $(COMMON_LDFLAGS) @@ -293,7 +294,7 @@ pxecmd_mod_CFLAGS = $(COMMON_CFLAGS) pxecmd_mod_LDFLAGS = $(COMMON_LDFLAGS) # For datetime.mod -datetime_mod_SOURCES = lib/i386/datetime.c +datetime_mod_SOURCES = lib/cmos_datetime.c datetime_mod_CFLAGS = $(COMMON_CFLAGS) datetime_mod_LDFLAGS = $(COMMON_LDFLAGS) diff --git a/conf/i386.rmk b/conf/i386.rmk index 064ee3ab4..e5bd27265 100644 --- a/conf/i386.rmk +++ b/conf/i386.rmk @@ -6,7 +6,7 @@ cpuid_mod_CFLAGS = $(COMMON_CFLAGS) cpuid_mod_LDFLAGS = $(COMMON_LDFLAGS) pkglib_MODULES += at_keyboard.mod -at_keyboard_mod_SOURCES = term/i386/pc/at_keyboard.c +at_keyboard_mod_SOURCES = term/at_keyboard.c at_keyboard_mod_CFLAGS = $(COMMON_CFLAGS) at_keyboard_mod_LDFLAGS = $(COMMON_LDFLAGS) @@ -26,6 +26,12 @@ ata_mod_SOURCES = disk/ata.c ata_mod_CFLAGS = $(COMMON_CFLAGS) ata_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For setpci.mod +pkglib_MODULES += setpci.mod +setpci_mod_SOURCES = commands/setpci.c +setpci_mod_CFLAGS = $(COMMON_CFLAGS) +setpci_mod_LDFLAGS = $(COMMON_LDFLAGS) + pkglib_MODULES += multiboot.mod multiboot_mod_SOURCES = loader/i386/multiboot.c \ loader/i386/multiboot_mbi.c \ diff --git a/conf/mips-qemu-mips.rmk b/conf/mips-qemu-mips.rmk new file mode 100644 index 000000000..e06370122 --- /dev/null +++ b/conf/mips-qemu-mips.rmk @@ -0,0 +1,23 @@ +# -*- makefile -*- +LINK_BASE = 0x80010000 +target_machine=qemu-mips +COMMON_CFLAGS += -march=mips3 +COMMON_ASFLAGS += -march=mips3 +include $(srcdir)/conf/mips.mk + +pkglib_IMAGES = kernel.img +kernel_img_SOURCES = kern/$(target_cpu)/startup.S \ + kern/main.c kern/device.c kern/$(target_cpu)/init.c \ + kern/$(target_cpu)/$(target_machine)/init.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/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 +kernel_img_CFLAGS = $(COMMON_CFLAGS) +kernel_img_ASFLAGS = $(COMMON_ASFLAGS) +kernel_img_LDFLAGS = $(COMMON_LDFLAGS) -static-libgcc -lgcc \ + -Wl,-N,-S,-Ttext,$(LINK_BASE),-Bstatic +kernel_img_FORMAT = binary diff --git a/conf/mips-yeeloong.rmk b/conf/mips-yeeloong.rmk new file mode 100644 index 000000000..9977f7881 --- /dev/null +++ b/conf/mips-yeeloong.rmk @@ -0,0 +1,87 @@ +# -*- makefile -*- +LINK_BASE = 0x80200000 +target_machine=yeeloong +COMMON_CFLAGS += -march=mips3 +COMMON_ASFLAGS += -march=mips3 + +kernel_img_HEADERS += bitmap.h video.h gfxterm.h font.h bitmap_scale.h bufio.h + +include $(srcdir)/conf/mips.mk + +pkglib_IMAGES = kernel.img +kernel_img_SOURCES = kern/$(target_cpu)/startup.S \ + kern/main.c kern/device.c kern/$(target_cpu)/init.c \ + kern/$(target_cpu)/$(target_machine)/init.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/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 \ + \ + term/at_keyboard.c \ + font/font_cmd.c font/font.c io/bufio.c \ + video/video.c video/fb/video_fb.c video/fb/fbblit.c \ + 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 \ + symlist.c +kernel_img_CFLAGS = $(COMMON_CFLAGS) -DUSE_ASCII_FAILBACK +kernel_img_ASFLAGS = $(COMMON_ASFLAGS) +kernel_img_LDFLAGS = $(COMMON_LDFLAGS) -static-libgcc -lgcc \ + -Wl,-N,-S,-Ttext,$(LINK_BASE),-Bstatic +kernel_img_FORMAT = binary + +# For ata.mod. +pkglib_MODULES += ata.mod +ata_mod_SOURCES = disk/ata.c +ata_mod_CFLAGS = $(COMMON_CFLAGS) +ata_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For lspci.mod +pkglib_MODULES += lspci.mod +lspci_mod_SOURCES = commands/lspci.c +lspci_mod_CFLAGS = $(COMMON_CFLAGS) +lspci_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For ata_pthru.mod. +pkglib_MODULES += ata_pthru.mod +ata_pthru_mod_SOURCES = disk/ata_pthru.c +ata_pthru_mod_CFLAGS = $(COMMON_CFLAGS) +ata_pthru_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For mmap.mod. +pkglib_MODULES += mmap.mod +mmap_mod_SOURCES = mmap/mmap.c mmap/mips/yeeloong/uppermem.c +mmap_mod_CFLAGS = $(COMMON_CFLAGS) +mmap_mod_LDFLAGS = $(COMMON_LDFLAGS) +mmap_mod_ASFLAGS = $(COMMON_ASFLAGS) + +# For datetime.mod +pkglib_MODULES += datetime.mod +datetime_mod_SOURCES = lib/cmos_datetime.c +datetime_mod_CFLAGS = $(COMMON_CFLAGS) +datetime_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For date.mod +pkglib_MODULES += date.mod +date_mod_SOURCES = commands/date.c +date_mod_CFLAGS = $(COMMON_CFLAGS) +date_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For datehook.mod +pkglib_MODULES += datehook.mod +datehook_mod_SOURCES = hook/datehook.c +datehook_mod_CFLAGS = $(COMMON_CFLAGS) +datehook_mod_LDFLAGS = $(COMMON_LDFLAGS) + +pkglib_MODULES += linux.mod +linux_mod_SOURCES = loader/$(target_cpu)/linux.c +linux_mod_CFLAGS = $(COMMON_CFLAGS) +linux_mod_ASFLAGS = $(COMMON_ASFLAGS) +linux_mod_LDFLAGS = $(COMMON_LDFLAGS) + +sbin_SCRIPTS += grub-install +grub_install_SOURCES = util/grub-install.in + diff --git a/conf/mips.rmk b/conf/mips.rmk new file mode 100644 index 000000000..536d35cac --- /dev/null +++ b/conf/mips.rmk @@ -0,0 +1,76 @@ + +# -*- makefile -*- + +COMMON_ASFLAGS += -nostdinc +COMMON_CFLAGS += -ffreestanding -mexplicit-relocs -mflush-func=grub_cpu_flush_cache +COMMON_LDFLAGS += -nostdlib + +# Used by various components. These rules need to precede them. +script/lexer.c_DEPENDENCIES = grub_script.tab.h + +# Images. + +MOSTLYCLEANFILES += symlist.c kernel_syms.lst +DEFSYMFILES += kernel_syms.lst + +kernel_img_HEADERS += boot.h cache.h device.h disk.h dl.h elf.h elfload.h \ + env.h err.h file.h fs.h kernel.h misc.h mm.h net.h parser.h reader.h \ + symbol.h term.h time.h types.h loader.h partition.h \ + msdos_partition.h machine/kernel.h handler.h list.h \ + command.h machine/memory.h cpu/libgcc.h cpu/cache.h i18n.h env_private.h + +ifeq ($(platform), yeeloong) +kernel_img_HEADERS += pci.h +endif + +symlist.c: $(addprefix include/grub/,$(kernel_img_HEADERS)) config.h gensymlist.sh + /bin/sh gensymlist.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1) + +kernel_syms.lst: $(addprefix include/grub/,$(kernel_img_HEADERS)) config.h genkernsyms.sh + /bin/sh genkernsyms.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1) + +# Scripts. +sbin_SCRIPTS = +bin_SCRIPTS = + +# For grub-mkimage. +bin_UTILITIES += grub-mkimage +grub_mkimage_SOURCES = gnulib/progname.c util/grub-mkrawimage.c util/misc.c \ + util/resolve.c lib/LzmaEnc.c lib/LzFind.c +grub_mkimage_CFLAGS = -DGRUB_KERNEL_MACHINE_LINK_ADDR=$(LINK_BASE) +util/grub-mkrawimage.c_DEPENDENCIES = Makefile + +# Modules. +pkglib_MODULES = memdisk.mod \ + lsmmap.mod + +# For boot.mod. +pkglib_MODULES += boot.mod +boot_mod_SOURCES = commands/boot.c lib/i386/pc/biosnum.c +boot_mod_CFLAGS = $(COMMON_CFLAGS) +boot_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For memdisk.mod. +memdisk_mod_SOURCES = disk/memdisk.c +memdisk_mod_CFLAGS = $(COMMON_CFLAGS) +memdisk_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For lsmmap.mod +lsmmap_mod_SOURCES = commands/lsmmap.c +lsmmap_mod_CFLAGS = $(COMMON_CFLAGS) +lsmmap_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For serial.mod. +pkglib_MODULES += serial.mod +serial_mod_SOURCES = term/serial.c +serial_mod_CFLAGS = $(COMMON_CFLAGS) +serial_mod_LDFLAGS = $(COMMON_LDFLAGS) + +# For relocator.mod. +pkglib_MODULES += relocator.mod +relocator_mod_SOURCES = lib/$(target_cpu)/relocator.c lib/$(target_cpu)/relocator_asm.S +relocator_mod_CFLAGS = $(COMMON_CFLAGS) +relocator_mod_ASFLAGS = $(COMMON_ASFLAGS) +relocator_mod_LDFLAGS = $(COMMON_LDFLAGS) + +include $(srcdir)/conf/common.mk diff --git a/conf/powerpc-ieee1275.rmk b/conf/powerpc-ieee1275.rmk index 854ad50b7..23bd2d620 100644 --- a/conf/powerpc-ieee1275.rmk +++ b/conf/powerpc-ieee1275.rmk @@ -17,7 +17,7 @@ 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 misc.h mm.h net.h parser.h reader.h \ symbol.h term.h time.h types.h powerpc/libgcc.h loader.h partition.h \ msdos_partition.h ieee1275/ieee1275.h machine/kernel.h handler.h list.h \ - command.h i18n.h + command.h i18n.h env_private.h symlist.c: $(addprefix include/grub/,$(kernel_img_HEADERS)) config.h gensymlist.sh /bin/sh gensymlist.sh $(filter %.h,$^) > $@ || (rm -f $@; exit 1) diff --git a/conf/sparc64-ieee1275.rmk b/conf/sparc64-ieee1275.rmk index 4ba098619..befc7dce5 100644 --- a/conf/sparc64-ieee1275.rmk +++ b/conf/sparc64-ieee1275.rmk @@ -31,7 +31,7 @@ kernel_img_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \ partition.h msdos_partition.h reader.h symbol.h term.h time.h types.h \ list.h handler.h command.h i18n.h \ sparc64/libgcc.h ieee1275/ieee1275.h machine/kernel.h \ - sparc64/ieee1275/ieee1275.h + sparc64/ieee1275/ieee1275.h env_private.h kernel_img_SOURCES = kern/sparc64/ieee1275/crt0.S kern/ieee1275/cmain.c \ kern/ieee1275/ieee1275.c kern/main.c kern/device.c \ kern/disk.c kern/dl.c kern/err.c kern/file.c kern/fs.c \ diff --git a/conf/x86_64-efi.rmk b/conf/x86_64-efi.rmk index 122700711..d5c3c24cb 100644 --- a/conf/x86_64-efi.rmk +++ b/conf/x86_64-efi.rmk @@ -29,13 +29,14 @@ sbin_SCRIPTS = grub-install grub_install_SOURCES = util/i386/efi/grub-install.in # Modules. -pkglib_MODULES = kernel.img chain.mod appleldr.mod \ +pkglib_PROGRAMS = kernel.img +pkglib_MODULES = chain.mod appleldr.mod \ halt.mod reboot.mod linux.mod pci.mod lspci.mod \ datetime.mod date.mod datehook.mod loadbios.mod \ fixvideo.mod mmap.mod acpi.mod # For kernel.img. -kernel_img_EXPORTS = no +kernel_img_RELOCATABLE = yes kernel_img_SOURCES = kern/x86_64/efi/startup.S kern/x86_64/efi/callwrap.S \ kern/main.c kern/device.c \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ @@ -51,7 +52,7 @@ 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 \ efi/efi.h efi/time.h efi/disk.h machine/loader.h i386/pit.h list.h \ - handler.h command.h i18n.h + handler.h command.h i18n.h env_private.h kernel_img_CFLAGS = $(COMMON_CFLAGS) kernel_img_ASFLAGS = $(COMMON_ASFLAGS) kernel_img_LDFLAGS = $(COMMON_LDFLAGS) diff --git a/configure.ac b/configure.ac index 4b5b5dd5a..6deac6c6d 100644 --- a/configure.ac +++ b/configure.ac @@ -31,7 +31,7 @@ dnl (such as TARGET_CC, TARGET_CFLAGS, etc.) are used for the target dnl type. -AC_INIT([GRUB],[1.97],[bug-grub@gnu.org]) +AC_INIT([GRUB],[1.98],[bug-grub@gnu.org]) AM_INIT_AUTOMAKE() AC_PREREQ(2.60) AC_CONFIG_SRCDIR([include/grub/dl.h]) @@ -51,7 +51,18 @@ fi case "$target_cpu" in i[[3456]]86) target_cpu=i386 ;; + amd64) target_cpu=x86_64 ;; sparc) target_cpu=sparc64 ;; + mipsel|mips64el) + target_cpu=mips; + TARGET_CFLAGS="$TARGET_CFLAGS -DGRUB_CPU_MIPSEL=1"; + CFLAGS="$CFLAGS -DGRUB_CPU_MIPSEL=1"; + ;; + mips|mips64) + target_cpu=mips; + TARGET_CFLAGS="$TARGET_CFLAGS -DGRUB_CPU_MIPS=1"; + CFLAGS="$CFLAGS -DGRUB_CPU_MIPS=1"; + ;; esac # Specify the platform (such as firmware). @@ -69,6 +80,7 @@ if test "x$with_platform" = x; then powerpc-*) platform=ieee1275 ;; powerpc64-*) platform=ieee1275 ;; sparc64-*) platform=ieee1275 ;; + mips-*) platform=yeeloong ;; *) AC_MSG_ERROR([unsupported CPU: "$target_cpu"]) ;; esac else @@ -95,6 +107,8 @@ case "$target_cpu"-"$platform" in i386-qemu) ;; powerpc-ieee1275) ;; sparc64-ieee1275) ;; + mips-qemu-mips) ;; + mips-yeeloong) ;; *-emu) ;; *) AC_MSG_ERROR([platform "$platform" is not supported for target CPU "$target_cpu"]) ;; esac @@ -125,6 +139,8 @@ case "$platform" in qemu) machine_CFLAGS="-DGRUB_MACHINE_QEMU=1" ;; pc) machine_CFLAGS="-DGRUB_MACHINE_PCBIOS=1" ;; emu) machine_CFLAGS="-DGRUB_MACHINE_EMU=1" ;; + yeeloong) machine_CFLAGS="-DGRUB_MACHINE_MIPS_YEELOONG=1 -DGRUB_MACHINE_MIPS=1 -DGRUB_MACHINE_MIPS_BONITO=1" ;; + qemu-mips) machine_CFLAGS="-DGRUB_MACHINE_MIPS_QEMU_MIPS=1 -DGRUB_MACHINE_MIPS=1 -DGRUB_MACHINE_MIPS_BONITO=1" ;; esac CFLAGS="$CFLAGS $machine_CFLAGS" TARGET_ASFLAGS="$TARGET_ASFLAGS $machine_CFLAGS" @@ -153,7 +169,7 @@ 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 ; do +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 @@ -206,7 +222,7 @@ AC_HEADER_MAJOR AC_HEADER_DIRENT AC_CHECK_FUNCS(memmove sbrk strdup lstat getuid getgid) AC_CHECK_HEADERS(sys/mkdev.h sys/sysmacros.h malloc.h termios.h sys/types.h) -AC_CHECK_HEADERS(unistd.h string.h strings.h sys/stat.h sys/fcntl.h) +AC_CHECK_HEADERS(unistd.h string.h strings.h sys/stat.h sys/fcntl.h limits.h) # # Check for target programs. @@ -423,18 +439,26 @@ AC_SUBST(TARGET_ASFLAGS) AC_SUBST(TARGET_CPPFLAGS) AC_SUBST(TARGET_LDFLAGS) -# Check for libgcc symbols (must be performed before we add -nostdlib to LDFLAGS) -AC_CHECK_FUNCS(__bswapsi2 __bswapdi2 __ashldi3 __ashrdi3 __lshrdi3 __trampoline_setup __ucmpdi2) - # Set them to their new values for the tests below. CC="$TARGET_CC" +if test "x$TARGET_APPLE_CC" = x1 ; then +CFLAGS="$TARGET_CFLAGS -nostdlib -Wno-error" +else +CFLAGS="$TARGET_CFLAGS -nostdlib -Wl,--defsym,___main=0x8100 -Wl,--defsym,abort=main -Wno-error" +fi +CPPFLAGS="$TARGET_CPPFLAGS" +LDFLAGS="$TARGET_LDFLAGS" +LIBS=-lgcc + +# Check for libgcc symbols +AC_CHECK_FUNCS(__bswapsi2 __bswapdi2 __ashldi3 __ashrdi3 __lshrdi3 __trampoline_setup __ucmpdi2 _restgpr_14_x) + if test "x$TARGET_APPLE_CC" = x1 ; then CFLAGS="$TARGET_CFLAGS -nostdlib" else CFLAGS="$TARGET_CFLAGS -nostdlib -Wl,--defsym,___main=0x8100" fi -CPPFLAGS="$TARGET_CPPFLAGS" -LDFLAGS="$TARGET_LDFLAGS" +LIBS="" # Defined in aclocal.m4. grub_PROG_TARGET_CC @@ -493,6 +517,19 @@ enable_efiemu=no fi AC_SUBST([enable_efiemu]) +AC_CACHE_CHECK([whether -nostdinc -isystem works], [grub_cv_cc_isystem], [ + SAVED_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$TARGET_CPPFLAGS -nostdinc -isystem `$TARGET_CC -print-file-name=include`" + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include +int va_arg_func (int fixed, va_list args);]], [[]])], + [grub_cv_cc_isystem=yes], + [grub_cv_cc_isystem=no]) + CPPFLAGS="$SAVED_CPPFLAGS" +]) + +if test x"$grub_cv_cc_isystem" = xyes ; then + TARGET_CPPFLAGS="$TARGET_CPPFLAGS -nostdinc -isystem `$TARGET_CC -print-file-name=include`" +fi # Restore the flags. CC="$tmp_CC" @@ -516,6 +553,10 @@ AC_ARG_ENABLE([grub-emu-usb], [AS_HELP_STRING([--enable-grub-emu-usb], [build and install the `grub-emu' debugging utility with USB support (default=guessed)])]) +AC_ARG_ENABLE([grub-emu-sdl], + [AS_HELP_STRING([--enable-grub-emu-sdl], + [build and install the `grub-emu' debugging utility with SDL support (default=guessed)])]) + AC_ARG_ENABLE([grub-emu-pci], [AS_HELP_STRING([--enable-grub-emu-pci], [build and install the `grub-emu' debugging utility with PCI support (potentially dangerous) (default=no)])]) @@ -566,6 +607,31 @@ else enable_grub_emu_usb=no fi +if test x"$enable_grub_emu_sdl" = xno ; then + grub_emu_sdl_excuse="explicitely disabled" +fi +[if [ x"$grub_emu_sdl_excuse" = x ]; then + # Check for libSDL libraries.] +AC_CHECK_LIB([SDL], [SDL_Init], [LIBSDL="-lSDL"], + [grub_emu_sdl_excuse=["libSDL libraries are required to build \`grub-emu' with SDL support"]]) + AC_SUBST([LIBSDL]) +[fi] + +[if [ x"$grub_emu_sdl_excuse" = x ]; then + # Check for headers.] + AC_CHECK_HEADERS([SDL/SDL.h], [], + [grub_emu_sdl_excuse=["libSDL header file is required to build \`grub-emu' with SDL support"]]) +[fi] + +if test x"enable_grub_emu_sdl" = xyes && test x"$grub_emu_sdl_excuse" != x ; then + AC_MSG_ERROR([SDL support for grub-emu was explicitely requested but can't be compiled]) +fi +if test x"$grub_emu_sdl_excuse" = x ; then +enable_grub_emu_sdl=yes +else +enable_grub_emu_sdl=no +fi + if test x"$enable_grub_emu_pci" != xyes ; then grub_emu_pci_excuse="not enabled" fi @@ -589,9 +655,11 @@ fi if test x"$grub_emu_pci_excuse" = x ; then enable_grub_emu_pci=yes else + enable_grub_emu_pci=no fi +AC_SUBST([enable_grub_emu_sdl]) AC_SUBST([enable_grub_emu_usb]) AC_SUBST([enable_grub_emu_pci]) fi @@ -625,6 +693,16 @@ if test x"$grub_mkfont_excuse" = x ; then freetype_cflags=`freetype-config --cflags` freetype_libs=`freetype-config --libs` fi + +if test x"$grub_mkfont_excuse" = x ; then + # Check for freetype libraries. + SAVED_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $freetype_cflags" + AC_CHECK_HEADERS([ft2build.h], [], + [grub_mkfont_excuse=["need freetype2 headers"]]) + CPPFLAGS="$SAVED_CPPFLAGS" +fi + if test x"$enable_grub_mkfont" = xyes && test x"$grub_mkfont_excuse" != x ; then AC_MSG_ERROR([grub-mkfont was explicitly requested but can't be compiled]) fi @@ -668,6 +746,11 @@ echo USB support for grub-emu: Yes else echo USB support for grub-emu: No "($grub_emu_usb_excuse)" fi +if [ x"$grub_emu_sdl_excuse" = x ]; then +echo SDL support for grub-emu: Yes +else +echo SDL support for grub-emu: No "($grub_emu_sdl_excuse)" +fi if [ x"$grub_emu_pci_excuse" = x ]; then echo PCI support for grub-emu: Yes else diff --git a/disk/ata.c b/disk/ata.c index 864ae9488..687ed9378 100644 --- a/disk/ata.c +++ b/disk/ata.c @@ -26,8 +26,8 @@ #include /* At the moment, only two IDE ports are supported. */ -static const int grub_ata_ioaddress[] = { 0x1f0, 0x170 }; -static const int grub_ata_ioaddress2[] = { 0x3f6, 0x376 }; +static const grub_port_t grub_ata_ioaddress[] = { 0x1f0, 0x170 }; +static const grub_port_t grub_ata_ioaddress2[] = { 0x3f6, 0x376 }; static struct grub_ata_device *grub_ata_devices; @@ -347,8 +347,8 @@ grub_ata_device_initialize (int port, int device, int addr, int addr2) /* Setup the device information. */ dev->port = port; dev->device = device; - dev->ioaddress = addr; - dev->ioaddress2 = addr2; + dev->ioaddress = addr + GRUB_MACHINE_PCI_IO_BASE; + dev->ioaddress2 = addr2 + GRUB_MACHINE_PCI_IO_BASE; dev->next = NULL; grub_ata_regset (dev, GRUB_ATA_REG_DISK, dev->device << 4); @@ -389,7 +389,7 @@ grub_ata_device_initialize (int port, int device, int addr, int addr2) static int NESTED_FUNC_ATTR grub_ata_pciinit (grub_pci_device_t dev, - grub_pci_id_t pciid __attribute__((unused))) + grub_pci_id_t pciid) { static int compat_use[2] = { 0 }; grub_pci_address_t addr; @@ -400,19 +400,34 @@ grub_ata_pciinit (grub_pci_device_t dev, int regb; int i; static int controller = 0; + int cs5536 = 0; + int nports = 2; /* Read class. */ - addr = grub_pci_make_address (dev, 2); + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); class = grub_pci_read (addr); + /* AMD CS5536 Southbridge. */ + if (pciid == 0x208f1022) + { + cs5536 = 1; + nports = 1; + } + /* Check if this class ID matches that of a PCI IDE Controller. */ - if (class >> 16 != 0x0101) + if (!cs5536 && (class >> 16 != 0x0101)) return 0; - for (i = 0; i < 2; i++) + for (i = 0; i < nports; i++) { /* Set to 0 when the channel operated in compatibility mode. */ - int compat = (class >> (8 + 2 * i)) & 1; + int compat; + + /* We don't support non-compatibility mode for CS5536. */ + if (cs5536) + compat = 0; + else + compat = (class >> (8 + 2 * i)) & 1; rega = 0; regb = 0; @@ -429,9 +444,12 @@ grub_ata_pciinit (grub_pci_device_t dev, { /* Read the BARs, which either contain a mmapped IO address or the IO port address. */ - addr = grub_pci_make_address (dev, 4 + 2 * i); + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESSES + + sizeof (grub_uint64_t) * i); bar1 = grub_pci_read (addr); - addr = grub_pci_make_address (dev, 5 + 2 * i); + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESSES + + sizeof (grub_uint64_t) * i + + sizeof (grub_uint32_t)); bar2 = grub_pci_read (addr); /* Check if the BARs describe an IO region. */ @@ -485,7 +503,6 @@ grub_ata_initialize (void) return 0; } - static void grub_ata_setlba (struct grub_ata_device *dev, grub_disk_addr_t sector, grub_size_t size) @@ -648,12 +665,14 @@ grub_ata_iterate (int (*hook) (const char *name)) for (dev = grub_ata_devices; dev; dev = dev->next) { - char devname[5]; - grub_sprintf (devname, "ata%d", dev->port * 2 + dev->device); + char devname[10]; if (dev->atapi) continue; + grub_snprintf (devname, sizeof (devname), + "ata%d", dev->port * 2 + dev->device); + if (hook (devname)) return 1; } @@ -668,8 +687,9 @@ grub_ata_open (const char *name, grub_disk_t disk) for (dev = grub_ata_devices; dev; dev = dev->next) { - char devname[5]; - grub_sprintf (devname, "ata%d", dev->port * 2 + dev->device); + char devname[10]; + grub_snprintf (devname, sizeof (devname), + "ata%d", dev->port * 2 + dev->device); if (grub_strcmp (name, devname) == 0) break; } @@ -735,8 +755,9 @@ grub_atapi_iterate (int (*hook) (const char *name, int luns)) for (dev = grub_ata_devices; dev; dev = dev->next) { - char devname[7]; - grub_sprintf (devname, "ata%d", dev->port * 2 + dev->device); + char devname[10]; + grub_snprintf (devname, sizeof (devname), + "ata%d", dev->port * 2 + dev->device); if (! dev->atapi) continue; @@ -808,8 +829,9 @@ grub_atapi_open (const char *name, struct grub_scsi *scsi) for (dev = grub_ata_devices; dev; dev = dev->next) { - char devname[7]; - grub_sprintf (devname, "ata%d", dev->port * 2 + dev->device); + char devname[10]; + grub_snprintf (devname, sizeof (devname), + "ata%d", dev->port * 2 + dev->device); if (!grub_strcmp (devname, name)) { diff --git a/disk/efi/efidisk.c b/disk/efi/efidisk.c index de848594a..f9c6f3153 100644 --- a/disk/efi/efidisk.c +++ b/disk/efi/efidisk.c @@ -440,7 +440,7 @@ grub_efidisk_iterate (int (*hook) (const char *name)) for (d = fd_devices, count = 0; d; d = d->next, count++) { - grub_sprintf (buf, "fd%d", count); + grub_snprintf (buf, sizeof (buf), "fd%d", count); grub_dprintf ("efidisk", "iterating %s\n", buf); if (hook (buf)) return 1; @@ -448,7 +448,7 @@ grub_efidisk_iterate (int (*hook) (const char *name)) for (d = hd_devices, count = 0; d; d = d->next, count++) { - grub_sprintf (buf, "hd%d", count); + grub_snprintf (buf, sizeof (buf), "hd%d", count); grub_dprintf ("efidisk", "iterating %s\n", buf); if (hook (buf)) return 1; @@ -456,7 +456,7 @@ grub_efidisk_iterate (int (*hook) (const char *name)) for (d = cd_devices, count = 0; d; d = d->next, count++) { - grub_sprintf (buf, "cd%d", count); + grub_snprintf (buf, sizeof (buf), "cd%d", count); grub_dprintf ("efidisk", "iterating %s\n", buf); if (hook (buf)) return 1; @@ -805,18 +805,10 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) return 0; } - device_name = grub_malloc (grub_strlen (parent->name) + 1 - + grub_strlen (partition_name) + 1); - if (! device_name) - { - grub_free (partition_name); - grub_disk_close (parent); - return 0; - } - - grub_sprintf (device_name, "%s,%s", parent->name, partition_name); + device_name = grub_xasprintf ("%s,%s", parent->name, partition_name); grub_free (partition_name); grub_disk_close (parent); + return device_name; } else @@ -833,7 +825,7 @@ grub_efidisk_get_device_name (grub_efi_handle_t *handle) if (! disk) return 1; - if (disk->id == GRUB_DISK_DEVICE_EFIDISK_ID) + if (disk->dev->id == GRUB_DISK_DEVICE_EFIDISK_ID) { struct grub_efidisk_data *d; diff --git a/disk/i386/pc/biosdisk.c b/disk/i386/pc/biosdisk.c index 5f04ecc1e..94d0e3708 100644 --- a/disk/i386/pc/biosdisk.c +++ b/disk/i386/pc/biosdisk.c @@ -56,7 +56,8 @@ grub_biosdisk_call_hook (int (*hook) (const char *name), int drive) { char name[10]; - grub_sprintf (name, (drive & 0x80) ? "hd%d" : "fd%d", drive & (~0x80)); + grub_snprintf (name, sizeof (name), + (drive & 0x80) ? "hd%d" : "fd%d", drive & (~0x80)); return hook (name); } @@ -306,8 +307,17 @@ grub_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector, while (size) { grub_size_t len; + grub_size_t cdoff = 0; len = get_safe_sectors (sector, data->sectors); + + if (data->flags & GRUB_BIOSDISK_FLAG_CDROM) + { + cdoff = (sector & 3) << GRUB_DISK_SECTOR_BITS; + len = ALIGN_UP (sector + len, 4) - (sector & ~3); + sector &= ~3; + } + if (len > size) len = size; @@ -315,7 +325,7 @@ grub_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector, GRUB_MEMORY_MACHINE_SCRATCH_SEG)) return grub_errno; - grub_memcpy (buf, (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR, + grub_memcpy (buf, (void *) (GRUB_MEMORY_MACHINE_SCRATCH_ADDR + cdoff), len << GRUB_DISK_SECTOR_BITS); buf += len << GRUB_DISK_SECTOR_BITS; sector += len; @@ -331,6 +341,9 @@ grub_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector, { struct grub_biosdisk_data *data = disk->data; + if (data->flags & GRUB_BIOSDISK_FLAG_CDROM) + return grub_error (GRUB_ERR_IO, "can't write to CDROM"); + while (size) { grub_size_t len; diff --git a/disk/ieee1275/ofdisk.c b/disk/ieee1275/ofdisk.c index c8c4d1a4e..e5a4a67fa 100644 --- a/disk/ieee1275/ofdisk.c +++ b/disk/ieee1275/ofdisk.c @@ -118,7 +118,7 @@ grub_ofdisk_iterate (int (*hook) (const char *name)) static char * compute_dev_path (const char *name) { - char *devpath = grub_malloc (grub_strlen (name) + 2); + char *devpath = grub_malloc (grub_strlen (name) + 3); char *p, c; if (!devpath) @@ -172,16 +172,6 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) grub_dprintf ("disk", "Opening `%s'.\n", op->devpath); - grub_ieee1275_open (op->devpath, &dev_ihandle); - if (! dev_ihandle) - { - grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); - goto fail; - } - - grub_dprintf ("disk", "Opened `%s' as handle %p.\n", op->devpath, - (void *) (unsigned long) dev_ihandle); - if (grub_ieee1275_finddevice (op->devpath, &dev)) { grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read device properties"); @@ -201,6 +191,16 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) goto fail; } + grub_ieee1275_open (op->devpath, &dev_ihandle); + if (! dev_ihandle) + { + grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); + goto fail; + } + + grub_dprintf ("disk", "Opened `%s' as handle %p.\n", op->devpath, + (void *) (unsigned long) dev_ihandle); + /* 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. */ @@ -234,21 +234,17 @@ grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector, grub_ssize_t status, actual; unsigned long long pos; - grub_dprintf ("disk", - "Reading handle %p: sector 0x%llx, size 0x%lx, buf %p.\n", - (void *) disk->data, (long long) sector, (long) size, buf); - pos = sector * 512UL; grub_ieee1275_seek ((grub_ieee1275_ihandle_t) (unsigned long) disk->data, - (int) (pos >> 32), (int) pos & 0xFFFFFFFFUL, &status); + pos, &status); if (status < 0) return grub_error (GRUB_ERR_READ_ERROR, "seek error, can't seek block %llu", (long long) sector); grub_ieee1275_read ((grub_ieee1275_ihandle_t) (unsigned long) disk->data, buf, size * 512UL, &actual); - if (actual != actual) + if (actual != (grub_ssize_t) (size * 512UL)) return grub_error (GRUB_ERR_READ_ERROR, "read error on block: %llu", (long long) sector); diff --git a/disk/raid.c b/disk/raid.c index 5d2793a07..2d544afdc 100644 --- a/disk/raid.c +++ b/disk/raid.c @@ -556,7 +556,7 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array, } } - array->name = grub_malloc (13); + array->name = grub_xasprintf ("md%d", array->number); if (! array->name) { grub_free (array->uuid); @@ -565,8 +565,6 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array, return grub_errno; } - grub_sprintf (array->name, "md%d", array->number); - grub_dprintf ("raid", "Found array %s (%s)\n", array->name, scanner_name); diff --git a/disk/scsi.c b/disk/scsi.c index 2a5e934f0..eba237287 100644 --- a/disk/scsi.c +++ b/disk/scsi.c @@ -197,7 +197,6 @@ grub_scsi_iterate (int (*hook) (const char *name)) int scsi_iterate (const char *name, int luns) { - char sname[40]; int i; /* In case of a single LUN, just return `usbX'. */ @@ -208,8 +207,14 @@ grub_scsi_iterate (int (*hook) (const char *name)) distinguish it. */ for (i = 0; i < luns; i++) { - grub_sprintf (sname, "%s%c", name, 'a' + i); - if (hook (sname)) + char *sname; + int ret; + sname = grub_xasprintf ("%s%c", name, 'a' + i); + if (!sname) + return 1; + ret = hook (sname); + grub_free (sname); + if (ret) return 1; } return 0; diff --git a/disk/usbms.c b/disk/usbms.c index 51e886520..8554b224f 100644 --- a/disk/usbms.c +++ b/disk/usbms.c @@ -200,11 +200,15 @@ grub_usbms_iterate (int (*hook) (const char *name, int luns)) for (p = grub_usbms_dev_list; p; p = p->next) { - char devname[20]; - grub_sprintf (devname, "usb%d", cnt); + char *devname; + devname = grub_xasprintf ("usb%d", cnt); if (hook (devname, p->luns)) - return 1; + { + grub_free (devname); + return 1; + } + grub_free (devname); cnt++; } diff --git a/docs/grub.texi b/docs/grub.texi index 4fa44462e..f8a9bc414 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -1126,6 +1126,7 @@ you forget a command, you can run the command @command{help} * insmod:: Insert a module * keystatus:: Check key modifier status * ls:: List devices or files +* play:: Play a tune * reboot:: Reboot your computer * set:: Set an environment variable * unset:: Unset an environment variable @@ -1364,6 +1365,24 @@ name syntax}), then list the contents of that directory. @end deffn +@node play +@subsection play + +@deffn Command play file | tempo [pitch1 duration1] [pitch2 duration2] ... +Plays a tune + +If the argument is a file name (@pxref{File name syntax}), play the tune +recorded in it. The file format is first the tempo as an unsigned 32bit +little-endian number, then pairs of unsigned 16bit little-endian numbers for +pitch and duration pairs. + +If the arguments are a series of numbers, play the inline tune. + +The tempo is the base for all note durations. 60 gives a 1-second base, 120 +gives a half-second base, etc. Pitches are Hz. +@end deffn + + @node reboot @subsection reboot diff --git a/efiemu/main.c b/efiemu/main.c index a3cfdb5b5..9480bfc4d 100644 --- a/efiemu/main.c +++ b/efiemu/main.c @@ -255,12 +255,11 @@ grub_efiemu_autocore (void) suffix = grub_efiemu_get_default_core_name (); - filename = grub_malloc (grub_strlen (prefix) + grub_strlen (suffix) + 2); + filename = grub_xasprintf ("%s/%s", prefix, suffix); if (! filename) return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't allocate temporary space"); - grub_sprintf (filename, "%s/%s", prefix, suffix); err = grub_efiemu_load_file (filename); grub_free (filename); diff --git a/font/font.c b/font/font.c index 44827a9a1..1b3dc6387 100644 --- a/font/font.c +++ b/font/font.c @@ -1,7 +1,7 @@ /* font.c - Font API and font file loader. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2003,2005,2006,2007,2008,2009 Free Software Foundation, Inc. + * Copyright (C) 2003,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 @@ -26,6 +26,11 @@ #include #include #include +#include + +#ifdef USE_ASCII_FAILBACK +#include "ascii.h" +#endif #ifndef FONT_DEBUG #define FONT_DEBUG 0 @@ -43,6 +48,7 @@ struct char_index_entry #define FONT_WEIGHT_NORMAL 100 #define FONT_WEIGHT_BOLD 200 +#define ASCII_BITMAP_SIZE 16 struct grub_font { @@ -58,6 +64,7 @@ struct grub_font short leading; grub_uint32_t num_chars; struct char_index_entry *char_index; + grub_uint16_t *bmp_idx; }; /* Definition of font registry. */ @@ -83,19 +90,6 @@ struct font_file_section int eof; }; -/* Font file format constants. */ -static const char pff2_magic[4] = { 'P', 'F', 'F', '2' }; -static const char section_names_file[4] = { 'F', 'I', 'L', 'E' }; -static const char section_names_font_name[4] = { 'N', 'A', 'M', 'E' }; -static const char section_names_point_size[4] = { 'P', 'T', 'S', 'Z' }; -static const char section_names_weight[4] = { 'W', 'E', 'I', 'G' }; -static const char section_names_max_char_width[4] = { 'M', 'A', 'X', 'W' }; -static const char section_names_max_char_height[4] = { 'M', 'A', 'X', 'H' }; -static const char section_names_ascent[4] = { 'A', 'S', 'C', 'E' }; -static const char section_names_descent[4] = { 'D', 'E', 'S', 'C' }; -static const char section_names_char_index[4] = { 'C', 'H', 'I', 'X' }; -static const char section_names_data[4] = { 'D', 'A', 'T', 'A' }; - /* Replace unknown glyphs with a rounded question mark. */ static grub_uint8_t unknown_glyph_bitmap[] = { @@ -129,6 +123,48 @@ static struct grub_font null_font; /* Flag to ensure module is initialized only once. */ static grub_uint8_t font_loader_initialized; +#ifdef USE_ASCII_FAILBACK +static struct grub_font_glyph *ascii_font_glyph[0x80]; +#endif + +static struct grub_font_glyph * +ascii_glyph_lookup (grub_uint32_t code) +{ +#ifdef USE_ASCII_FAILBACK + static int ascii_failback_initialized = 0; + + if (code >= 0x80) + return unknown_glyph; + + if (ascii_failback_initialized == 0) + { + int current; + for (current = 0; current < 0x80; current++) + { + ascii_font_glyph[current] = grub_malloc(sizeof(struct grub_font_glyph) + + ASCII_BITMAP_SIZE); + + ascii_font_glyph[current]->width = 8; + ascii_font_glyph[current]->height = 16; + ascii_font_glyph[current]->offset_x = 0; + ascii_font_glyph[current]->offset_y = -2; + ascii_font_glyph[current]->device_width = 8; + + grub_memcpy (ascii_font_glyph[current]->bitmap, + &ascii_bitmaps[(0x7f - current) * ASCII_BITMAP_SIZE], + ASCII_BITMAP_SIZE); + } + + ascii_failback_initialized = 1; + } + + return ascii_font_glyph[code]; +#else + (void) code; + return unknown_glyph; +#endif +} + void grub_font_loader_init (void) { @@ -180,6 +216,7 @@ font_init (grub_font_t font) font->descent = 0; font->num_chars = 0; font->char_index = 0; + font->bmp_idx = 0; } /* Open the next section in the file. @@ -273,6 +310,14 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct * sizeof (struct char_index_entry)); if (! font->char_index) return 1; + font->bmp_idx = grub_malloc (0x10000 * sizeof (grub_uint16_t)); + if (! font->bmp_idx) + { + grub_free (font->char_index); + return 1; + } + grub_memset (font->bmp_idx, 0xff, 0x10000 * sizeof (grub_uint16_t)); + #if FONT_DEBUG >= 2 grub_printf("num_chars=%d)\n", font->num_chars); @@ -299,6 +344,9 @@ load_font_index (grub_file_t file, grub_uint32_t sect_length, struct return 1; } + if (entry->code < 0x10000) + font->bmp_idx[entry->code] = i; + last_code = entry->code; /* Read storage flags byte. */ @@ -400,7 +448,8 @@ grub_font_load (const char *filename) #if FONT_DEBUG >= 3 grub_printf("opened FILE section\n"); #endif - if (grub_memcmp (section.name, section_names_file, 4) != 0) + if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_FILE, + sizeof(FONT_FORMAT_SECTION_NAMES_FILE) - 1) != 0) { grub_error (GRUB_ERR_BAD_FONT, "font file format error: 1st section must be FILE"); @@ -429,7 +478,7 @@ grub_font_load (const char *filename) grub_printf("read magic ok\n"); #endif - if (grub_memcmp (magic, pff2_magic, 4) != 0) + if (grub_memcmp (magic, FONT_FORMAT_PFF2_MAGIC, 4) != 0) { grub_error (GRUB_ERR_BAD_FONT, "invalid font magic %x %x %x %x", magic[0], magic[1], magic[2], magic[3]); @@ -469,18 +518,22 @@ grub_font_load (const char *filename) section.name[2], section.name[3]); #endif - if (grub_memcmp (section.name, section_names_font_name, 4) == 0) + if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_FONT_NAME, + sizeof(FONT_FORMAT_SECTION_NAMES_FONT_NAME) - 1) == 0) { font->name = read_section_as_string (§ion); if (!font->name) goto fail; } - else if (grub_memcmp (section.name, section_names_point_size, 4) == 0) + else if (grub_memcmp (section.name, + FONT_FORMAT_SECTION_NAMES_POINT_SIZE, + sizeof(FONT_FORMAT_SECTION_NAMES_POINT_SIZE) - 1) == 0) { if (read_section_as_short (§ion, &font->point_size) != 0) goto fail; } - else if (grub_memcmp (section.name, section_names_weight, 4) == 0) + else if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_WEIGHT, + sizeof(FONT_FORMAT_SECTION_NAMES_WEIGHT) - 1) == 0) { char *wt; wt = read_section_as_string (§ion); @@ -493,32 +546,42 @@ grub_font_load (const char *filename) font->weight = FONT_WEIGHT_BOLD; grub_free (wt); } - else if (grub_memcmp (section.name, section_names_max_char_width, 4) == 0) + else if (grub_memcmp (section.name, + FONT_FORMAT_SECTION_NAMES_MAX_CHAR_WIDTH, + sizeof(FONT_FORMAT_SECTION_NAMES_MAX_CHAR_WIDTH) - 1) == 0) { if (read_section_as_short (§ion, &font->max_char_width) != 0) goto fail; } - else if (grub_memcmp (section.name, section_names_max_char_height, 4) == 0) + else if (grub_memcmp (section.name, + FONT_FORMAT_SECTION_NAMES_MAX_CHAR_HEIGHT, + sizeof(FONT_FORMAT_SECTION_NAMES_MAX_CHAR_HEIGHT) - 1) == 0) { if (read_section_as_short (§ion, &font->max_char_height) != 0) goto fail; } - else if (grub_memcmp (section.name, section_names_ascent, 4) == 0) + else if (grub_memcmp (section.name, + FONT_FORMAT_SECTION_NAMES_ASCENT, + sizeof(FONT_FORMAT_SECTION_NAMES_ASCENT) - 1) == 0) { if (read_section_as_short (§ion, &font->ascent) != 0) goto fail; } - else if (grub_memcmp (section.name, section_names_descent, 4) == 0) + else if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_DESCENT, + sizeof(FONT_FORMAT_SECTION_NAMES_DESCENT) - 1) == 0) { if (read_section_as_short (§ion, &font->descent) != 0) goto fail; } - else if (grub_memcmp (section.name, section_names_char_index, 4) == 0) + else if (grub_memcmp (section.name, + FONT_FORMAT_SECTION_NAMES_CHAR_INDEX, + sizeof(FONT_FORMAT_SECTION_NAMES_CHAR_INDEX) - 1) == 0) { if (load_font_index (file, section.length, font) != 0) goto fail; } - else if (grub_memcmp (section.name, section_names_data, 4) == 0) + else if (grub_memcmp (section.name, FONT_FORMAT_SECTION_NAMES_DATA, + sizeof(FONT_FORMAT_SECTION_NAMES_DATA) - 1) == 0) { /* When the DATA section marker is reached, we stop reading. */ break; @@ -594,7 +657,7 @@ read_be_int16 (grub_file_t file, grub_int16_t * value) /* Return a pointer to the character index entry for the glyph corresponding to the codepoint CODE in the font FONT. If not found, return zero. */ -static struct char_index_entry * +static inline struct char_index_entry * find_glyph (const grub_font_t font, grub_uint32_t code) { struct char_index_entry *table; @@ -602,8 +665,17 @@ find_glyph (const grub_font_t font, grub_uint32_t code) grub_size_t hi; grub_size_t mid; - /* Do a binary search in `char_index', which is ordered by code point. */ table = font->char_index; + + /* Use BMP index if possible. */ + if (code < 0x10000 && font->bmp_idx) + { + if (font->bmp_idx[code] == 0xffff) + return 0; + return &table[font->bmp_idx[code]]; + } + + /* Do a binary search in `char_index', which is ordered by code point. */ lo = 0; hi = font->num_chars - 1; @@ -790,7 +862,7 @@ grub_font_get (const char *font_name) return &null_font; } -/* Get the full name of the font. For instance, "Helvetica Bold 12". */ +/* Get the full name of the font. */ const char * grub_font_get_name (grub_font_t font) { @@ -865,15 +937,18 @@ grub_font_get_string_width (grub_font_t font, const char *str) } /* Get the glyph for FONT corresponding to the Unicode code point CODE. - Returns a pointer to an glyph indicating there is no glyph available - if CODE does not exist in the font. The glyphs are cached once loaded. */ + Returns the ASCII glyph for the code if no other fonts are available. + The glyphs are cached once loaded. */ struct grub_font_glyph * grub_font_get_glyph (grub_font_t font, grub_uint32_t code) { - struct grub_font_glyph *glyph; - glyph = grub_font_get_glyph_internal (font, code); + struct grub_font_glyph *glyph = 0; + if (font) + glyph = grub_font_get_glyph_internal (font, code); if (glyph == 0) - glyph = unknown_glyph; + { + glyph = ascii_glyph_lookup (code); + } return glyph; } @@ -968,8 +1043,8 @@ grub_font_get_glyph_with_fallback (grub_font_t font, grub_uint32_t code) if (best_glyph) return best_glyph; else - /* Glyph not available in any font. Return unknown glyph. */ - return unknown_glyph; + /* Glyph not available in any font. Return ASCII failback. */ + return ascii_glyph_lookup (code); } diff --git a/fs/cpio.c b/fs/cpio.c index 17c37975d..c087b4f90 100644 --- a/fs/cpio.c +++ b/fs/cpio.c @@ -280,8 +280,10 @@ grub_cpio_open (grub_file_t file, const char *name) /* Compare NAME and FN by hand in order to cope with duplicate slashes. */ - i = 1; + i = 0; j = 0; + while (name[i] == '/') + i++; while (1) { if (name[i] != fn[j]) @@ -290,13 +292,16 @@ grub_cpio_open (grub_file_t file, const char *name) if (name[i] == '\0') break; - if (name[i] == '/' && name[i+1] == '/') + while (name[i] == '/' && name[i+1] == '/') i++; i++; j++; } + if (name[i] != fn[j]) + goto no_match; + file->data = data; file->size = data->size; grub_free (fn); diff --git a/fs/ext2.c b/fs/ext2.c index 58be3e6fc..f2fec828a 100644 --- a/fs/ext2.c +++ b/fs/ext2.c @@ -436,7 +436,8 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) grub_uint32_t indir[blksz / 4]; if (grub_disk_read (data->disk, - grub_le_to_cpu32 (inode->blocks.indir_block) + ((grub_disk_addr_t) + grub_le_to_cpu32 (inode->blocks.indir_block)) << log2_blksz, 0, blksz, indir)) return grub_errno; @@ -452,13 +453,15 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock) grub_uint32_t indir[blksz / 4]; if (grub_disk_read (data->disk, - grub_le_to_cpu32 (inode->blocks.double_indir_block) + ((grub_disk_addr_t) + grub_le_to_cpu32 (inode->blocks.double_indir_block)) << log2_blksz, 0, blksz, indir)) return grub_errno; if (grub_disk_read (data->disk, - grub_le_to_cpu32 (indir[rblock / perblock]) + ((grub_disk_addr_t) + grub_le_to_cpu32 (indir[rblock / perblock])) << log2_blksz, 0, blksz, indir)) return grub_errno; @@ -875,12 +878,15 @@ grub_ext2_uuid (grub_device_t device, char **uuid) data = grub_ext2_mount (disk); if (data) { - *uuid = grub_malloc (40 + sizeof ('\0')); - grub_sprintf (*uuid, "%04x%04x-%04x-%04x-%04x-%04x%04x%04x", - grub_be_to_cpu16 (data->sblock.uuid[0]), grub_be_to_cpu16 (data->sblock.uuid[1]), - grub_be_to_cpu16 (data->sblock.uuid[2]), grub_be_to_cpu16 (data->sblock.uuid[3]), - grub_be_to_cpu16 (data->sblock.uuid[4]), grub_be_to_cpu16 (data->sblock.uuid[5]), - grub_be_to_cpu16 (data->sblock.uuid[6]), grub_be_to_cpu16 (data->sblock.uuid[7])); + *uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x", + grub_be_to_cpu16 (data->sblock.uuid[0]), + grub_be_to_cpu16 (data->sblock.uuid[1]), + grub_be_to_cpu16 (data->sblock.uuid[2]), + grub_be_to_cpu16 (data->sblock.uuid[3]), + grub_be_to_cpu16 (data->sblock.uuid[4]), + grub_be_to_cpu16 (data->sblock.uuid[5]), + grub_be_to_cpu16 (data->sblock.uuid[6]), + grub_be_to_cpu16 (data->sblock.uuid[7])); } else *uuid = NULL; diff --git a/fs/fat.c b/fs/fat.c index 8a0fc0292..89050943c 100644 --- a/fs/fat.c +++ b/fs/fat.c @@ -592,6 +592,7 @@ grub_fat_iterate_dir (grub_disk_t disk, struct grub_fat_data *data, } grub_free (filename); + grub_free (unibuf); return grub_errno; } @@ -833,9 +834,9 @@ grub_fat_uuid (grub_device_t device, char **uuid) data = grub_fat_mount (disk); if (data) { - *uuid = grub_malloc (sizeof ("xxxx-xxxx")); - grub_sprintf (*uuid, "%04x-%04x", (grub_uint16_t) (data->uuid >> 16), - (grub_uint16_t) data->uuid); + *uuid = grub_xasprintf ("%04x-%04x", + (grub_uint16_t) (data->uuid >> 16), + (grub_uint16_t) data->uuid); } else *uuid = NULL; diff --git a/fs/hfs.c b/fs/hfs.c index f7dc2484f..cef856326 100644 --- a/fs/hfs.c +++ b/fs/hfs.c @@ -1082,10 +1082,9 @@ grub_hfs_uuid (grub_device_t device, char **uuid) data = grub_hfs_mount (device->disk); if (data && data->sblock.num_serial != 0) { - *uuid = grub_malloc (16 + sizeof ('\0')); - grub_sprintf (*uuid, "%016llx", - (unsigned long long) - grub_be_to_cpu64 (data->sblock.num_serial)); + *uuid = grub_xasprintf ("%016llx", + (unsigned long long) + grub_be_to_cpu64 (data->sblock.num_serial)); } else *uuid = NULL; diff --git a/fs/hfsplus.c b/fs/hfsplus.c index 9310b6502..bcb8e9584 100644 --- a/fs/hfsplus.c +++ b/fs/hfsplus.c @@ -995,10 +995,9 @@ grub_hfsplus_uuid (grub_device_t device, char **uuid) data = grub_hfsplus_mount (disk); if (data) { - *uuid = grub_malloc (16 + sizeof ('\0')); - grub_sprintf (*uuid, "%016llx", - (unsigned long long) - grub_be_to_cpu64 (data->volheader.num_serial)); + *uuid = grub_xasprintf ("%016llx", + (unsigned long long) + grub_be_to_cpu64 (data->volheader.num_serial)); } else *uuid = NULL; diff --git a/fs/i386/pc/pxe.c b/fs/i386/pc/pxe.c index 03385b3e3..82d8ee583 100644 --- a/fs/i386/pc/pxe.c +++ b/fs/i386/pc/pxe.c @@ -173,12 +173,15 @@ static struct grub_disk_dev grub_pxe_dev = }; static grub_err_t -grub_pxefs_dir (grub_device_t device __attribute__ ((unused)), +grub_pxefs_dir (grub_device_t device, const char *path __attribute__ ((unused)), int (*hook) (const char *filename, const struct grub_dirhook_info *info) __attribute__ ((unused))) { + if (device->disk->dev->id != GRUB_DISK_DEVICE_PXE_ID) + return grub_error (GRUB_ERR_IO, "not a pxe disk"); + return GRUB_ERR_NONE; } @@ -194,6 +197,9 @@ grub_pxefs_open (struct grub_file *file, const char *name) struct grub_pxe_disk_data *disk_data = file->device->disk->data; grub_file_t file_int, bufio; + if (file->device->disk->dev->id != GRUB_DISK_DEVICE_PXE_ID) + return grub_error (GRUB_ERR_IO, "not a pxe disk"); + if (curr_file != 0) { grub_pxe_call (GRUB_PXENV_TFTP_CLOSE, &c.c2); @@ -356,7 +362,8 @@ set_mac_env (grub_uint8_t *mac_addr, grub_size_t mac_len) for (i = 0; i < mac_len; i++) { - grub_sprintf (ptr, "%02x:", mac_addr[i] & 0xff); + grub_snprintf (ptr, sizeof (buf) - (ptr - buf), + "%02x:", mac_addr[i] & 0xff); ptr += (sizeof ("XX:") - 1); } if (mac_len) @@ -483,8 +490,8 @@ set_ip_env (char *varname, grub_uint32_t ip) { char buf[sizeof ("XXX.XXX.XXX.XXX")]; - grub_sprintf (buf, "%d.%d.%d.%d", (ip & 0xff), - (ip >> 8) & 0xff, (ip >> 16) & 0xff, (ip >> 24) & 0xff); + grub_snprintf (buf, sizeof (buf), "%d.%d.%d.%d", (ip & 0xff), + (ip >> 8) & 0xff, (ip >> 16) & 0xff, (ip >> 24) & 0xff); grub_env_set (varname, buf); } @@ -500,15 +507,13 @@ write_ip_env (grub_uint32_t *ip, const char *val) return 0; /* Normalize the IP. */ - buf = grub_malloc (sizeof ("XXX.XXX.XXX.XXX")); + buf = grub_xasprintf ("%d.%d.%d.%d", (newip & 0xff), (newip >> 8) & 0xff, + (newip >> 16) & 0xff, (newip >> 24) & 0xff); if (!buf) return 0; *ip = newip; - grub_sprintf (buf, "%d.%d.%d.%d", (newip & 0xff), (newip >> 8) & 0xff, - (newip >> 16) & 0xff, (newip >> 24) & 0xff); - return buf; } @@ -544,11 +549,10 @@ grub_env_write_pxe_blocksize (struct grub_env_var *var __attribute__ ((unused)), else if (size > GRUB_PXE_MAX_BLKSIZE) size = GRUB_PXE_MAX_BLKSIZE; - buf = grub_malloc (sizeof ("XXXXXX XXXXXX")); + buf = grub_xasprintf ("%d", size); if (!buf) return 0; - grub_sprintf (buf, "%d", size); grub_pxe_blksize = size; return buf; @@ -562,25 +566,23 @@ GRUB_MOD_INIT(pxe) { char *buf; - buf = grub_malloc (sizeof ("XXXXXX XXXXXX")); + buf = grub_xasprintf ("%d", grub_pxe_blksize); if (buf) - { - grub_sprintf (buf, "%d", grub_pxe_blksize); - grub_env_set ("net_pxe_blksize", buf); - } + grub_env_set ("pxe_blksize", buf); + grub_free (buf); set_ip_env ("pxe_default_server", grub_pxe_default_server_ip); set_ip_env ("pxe_default_gateway", grub_pxe_default_gateway_ip); set_ip_env ("net_pxe_ip", grub_pxe_your_ip); - grub_register_variable_hook ("net_pxe_default_server", 0, + grub_register_variable_hook ("pxe_default_server", 0, grub_env_write_pxe_default_server); - grub_register_variable_hook ("net_pxe_default_gateway", 0, + grub_register_variable_hook ("pxe_default_gateway", 0, grub_env_write_pxe_default_gateway); /* XXX: Is it possible to change IP in PXE? */ grub_register_variable_hook ("net_pxe_ip", 0, grub_env_write_readonly); - grub_register_variable_hook ("net_pxe_blksize", 0, + grub_register_variable_hook ("pxe_blksize", 0, grub_env_write_pxe_blocksize); grub_disk_dev_register (&grub_pxe_dev); grub_fs_register (&grub_pxefs_fs); diff --git a/fs/iso9660.c b/fs/iso9660.c index 1ab98be3f..6dc465f25 100644 --- a/fs/iso9660.c +++ b/fs/iso9660.c @@ -136,7 +136,6 @@ struct grub_iso9660_data struct grub_iso9660_primary_voldesc voldesc; grub_disk_t disk; unsigned int first_sector; - unsigned int length; int rockridge; int susp_skip; int joliet; @@ -630,12 +629,16 @@ grub_iso9660_iterate_dir (grub_fshelp_node_t dir, if (dir->data->joliet) { - char *oldname; + char *oldname, *semicolon; oldname = filename; filename = grub_iso9660_convert_string ((grub_uint16_t *) oldname, dirent.namelen >> 1); + semicolon = grub_strrchr (filename, ';'); + if (semicolon) + *semicolon = '\0'; + if (filename_alloc) grub_free (oldname); @@ -744,7 +747,6 @@ grub_iso9660_open (struct grub_file *file, const char *name) goto fail; data->first_sector = foundnode->blk; - data->length = foundnode->size; file->data = data; file->size = foundnode->size; @@ -840,16 +842,23 @@ grub_iso9660_uuid (grub_device_t device, char **uuid) } else { - *uuid = grub_malloc (sizeof ("YYYY-MM-DD-HH-mm-ss-hh")); - grub_sprintf (*uuid, "%c%c%c%c-%c%c-%c%c-%c%c-%c%c-%c%c-%c%c", - data->voldesc.modified.year[0], data->voldesc.modified.year[1], - data->voldesc.modified.year[2], data->voldesc.modified.year[3], - data->voldesc.modified.month[0], data->voldesc.modified.month[1], - data->voldesc.modified.day[0], data->voldesc.modified.day[1], - data->voldesc.modified.hour[0], data->voldesc.modified.hour[1], - data->voldesc.modified.minute[0], data->voldesc.modified.minute[1], - data->voldesc.modified.second[0], data->voldesc.modified.second[1], - data->voldesc.modified.hundredth[0], data->voldesc.modified.hundredth[1]); + *uuid = grub_xasprintf ("%c%c%c%c-%c%c-%c%c-%c%c-%c%c-%c%c-%c%c", + data->voldesc.modified.year[0], + data->voldesc.modified.year[1], + data->voldesc.modified.year[2], + data->voldesc.modified.year[3], + data->voldesc.modified.month[0], + data->voldesc.modified.month[1], + data->voldesc.modified.day[0], + data->voldesc.modified.day[1], + data->voldesc.modified.hour[0], + data->voldesc.modified.hour[1], + data->voldesc.modified.minute[0], + data->voldesc.modified.minute[1], + data->voldesc.modified.second[0], + data->voldesc.modified.second[1], + data->voldesc.modified.hundredth[0], + data->voldesc.modified.hundredth[1]); } } else diff --git a/fs/jfs.c b/fs/jfs.c index dc5eaed67..c9839a22f 100644 --- a/fs/jfs.c +++ b/fs/jfs.c @@ -842,17 +842,16 @@ grub_jfs_uuid (grub_device_t device, char **uuid) data = grub_jfs_mount (disk); if (data) { - *uuid = grub_malloc (40 + sizeof ('\0')); - - grub_sprintf (*uuid, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", - data->sblock.uuid[0], data->sblock.uuid[1], - data->sblock.uuid[2], data->sblock.uuid[3], - data->sblock.uuid[4], data->sblock.uuid[5], - data->sblock.uuid[6], data->sblock.uuid[7], - data->sblock.uuid[8], data->sblock.uuid[9], - data->sblock.uuid[10], data->sblock.uuid[11], - data->sblock.uuid[12], data->sblock.uuid[13], - data->sblock.uuid[14], data->sblock.uuid[15]); + *uuid = grub_xasprintf ("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-" + "%02x%02x%02x%02x%02x%02x", + data->sblock.uuid[0], data->sblock.uuid[1], + data->sblock.uuid[2], data->sblock.uuid[3], + data->sblock.uuid[4], data->sblock.uuid[5], + data->sblock.uuid[6], data->sblock.uuid[7], + data->sblock.uuid[8], data->sblock.uuid[9], + data->sblock.uuid[10], data->sblock.uuid[11], + data->sblock.uuid[12], data->sblock.uuid[13], + data->sblock.uuid[14], data->sblock.uuid[15]); } else *uuid = NULL; diff --git a/fs/ntfs.c b/fs/ntfs.c index c1b4b2fe1..dd041e23a 100644 --- a/fs/ntfs.c +++ b/fs/ntfs.c @@ -1072,8 +1072,7 @@ grub_ntfs_uuid (grub_device_t device, char **uuid) data = grub_ntfs_mount (disk); if (data) { - *uuid = grub_malloc (16 + sizeof ('\0')); - grub_sprintf (*uuid, "%016llx", (unsigned long long) data->uuid); + *uuid = grub_xasprintf ("%016llx", (unsigned long long) data->uuid); } else *uuid = NULL; diff --git a/fs/reiserfs.c b/fs/reiserfs.c index a8ba75910..c3db52f60 100644 --- a/fs/reiserfs.c +++ b/fs/reiserfs.c @@ -1189,7 +1189,8 @@ grub_reiserfs_read (grub_file_t file, char *buf, grub_size_t len) (unsigned long long) (current_position - initial_position), (unsigned long) len); return current_position - initial_position; -/* + +#if 0 switch (found.type) { case GRUB_REISERFS_DIRECT: @@ -1232,7 +1233,8 @@ grub_reiserfs_read (grub_file_t file, char *buf, grub_size_t len) goto fail; } - return read_length;*/ + return read_length; +#endif fail: grub_free (indirect_block_ptr); @@ -1335,12 +1337,15 @@ grub_reiserfs_uuid (grub_device_t device, char **uuid) data = grub_reiserfs_mount (disk); if (data) { - *uuid = grub_malloc (sizeof ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")); - grub_sprintf (*uuid, "%04x%04x-%04x-%04x-%04x-%04x%04x%04x", - grub_be_to_cpu16 (data->superblock.uuid[0]), grub_be_to_cpu16 (data->superblock.uuid[1]), - grub_be_to_cpu16 (data->superblock.uuid[2]), grub_be_to_cpu16 (data->superblock.uuid[3]), - grub_be_to_cpu16 (data->superblock.uuid[4]), grub_be_to_cpu16 (data->superblock.uuid[5]), - grub_be_to_cpu16 (data->superblock.uuid[6]), grub_be_to_cpu16 (data->superblock.uuid[7])); + *uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x", + grub_be_to_cpu16 (data->superblock.uuid[0]), + grub_be_to_cpu16 (data->superblock.uuid[1]), + grub_be_to_cpu16 (data->superblock.uuid[2]), + grub_be_to_cpu16 (data->superblock.uuid[3]), + grub_be_to_cpu16 (data->superblock.uuid[4]), + grub_be_to_cpu16 (data->superblock.uuid[5]), + grub_be_to_cpu16 (data->superblock.uuid[6]), + grub_be_to_cpu16 (data->superblock.uuid[7])); } else *uuid = NULL; diff --git a/fs/ufs.c b/fs/ufs.c index 9f3743d8b..40cf068e6 100644 --- a/fs/ufs.c +++ b/fs/ufs.c @@ -732,12 +732,9 @@ grub_ufs_uuid (grub_device_t device, char **uuid) data = grub_ufs_mount (disk); if (data && (data->sblock.uuidhi != 0 || data->sblock.uuidlow != 0)) - { - *uuid = grub_malloc (16 + sizeof ('\0')); - grub_sprintf (*uuid, "%08x%08x", - (unsigned) grub_le_to_cpu32 (data->sblock.uuidhi), - (unsigned) grub_le_to_cpu32 (data->sblock.uuidlow)); - } + *uuid = grub_xasprintf ("%08x%08x", + (unsigned) grub_le_to_cpu32 (data->sblock.uuidhi), + (unsigned) grub_le_to_cpu32 (data->sblock.uuidlow)); else *uuid = NULL; diff --git a/fs/xfs.c b/fs/xfs.c index 8b512de37..9dffe31d1 100644 --- a/fs/xfs.c +++ b/fs/xfs.c @@ -777,12 +777,15 @@ grub_xfs_uuid (grub_device_t device, char **uuid) data = grub_xfs_mount (disk); if (data) { - *uuid = grub_malloc (sizeof ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")); - grub_sprintf (*uuid, "%04x%04x-%04x-%04x-%04x-%04x%04x%04x", - grub_be_to_cpu16 (data->sblock.uuid[0]), grub_be_to_cpu16 (data->sblock.uuid[1]), - grub_be_to_cpu16 (data->sblock.uuid[2]), grub_be_to_cpu16 (data->sblock.uuid[3]), - grub_be_to_cpu16 (data->sblock.uuid[4]), grub_be_to_cpu16 (data->sblock.uuid[5]), - grub_be_to_cpu16 (data->sblock.uuid[6]), grub_be_to_cpu16 (data->sblock.uuid[7])); + *uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x", + grub_be_to_cpu16 (data->sblock.uuid[0]), + grub_be_to_cpu16 (data->sblock.uuid[1]), + grub_be_to_cpu16 (data->sblock.uuid[2]), + grub_be_to_cpu16 (data->sblock.uuid[3]), + grub_be_to_cpu16 (data->sblock.uuid[4]), + grub_be_to_cpu16 (data->sblock.uuid[5]), + grub_be_to_cpu16 (data->sblock.uuid[6]), + grub_be_to_cpu16 (data->sblock.uuid[7])); } else *uuid = NULL; diff --git a/genkernsyms.sh.in b/genkernsyms.sh.in index b2f3f7af9..c5c63b2d5 100644 --- a/genkernsyms.sh.in +++ b/genkernsyms.sh.in @@ -14,7 +14,7 @@ ### The configure script will replace these variables. : ${srcdir=@srcdir@} -: ${CC=@CC@} +: ${CC=@TARGET_CC@} u= grep "^#define HAVE_ASM_USCORE" config.h >/dev/null 2>&1 && u="_" diff --git a/genmk.rb b/genmk.rb index 810a2f1be..efea16412 100644 --- a/genmk.rb +++ b/genmk.rb @@ -68,7 +68,7 @@ MOSTLYCLEAN_IMAGE_TARGETS += mostlyclean-image-#{@name}.#{@rule_count} ifneq ($(TARGET_APPLE_CC),1) #{@name}: #{exe} - $(OBJCOPY) -O $(#{prefix}_FORMAT) --strip-unneeded -R .note -R .comment -R .note.gnu.build-id $< $@ + $(OBJCOPY) -O $(#{prefix}_FORMAT) --strip-unneeded -R .note -R .comment -R .note.gnu.build-id -R .reginfo -R .rel.dyn $< $@ else ifneq (#{exe},kernel.exec) #{@name}: #{exe} ./grub-macho2img @@ -132,13 +132,11 @@ clean-module-#{@name}.#{@rule_count}: CLEAN_MODULE_TARGETS += clean-module-#{@name}.#{@rule_count} -ifneq ($(#{prefix}_EXPORTS),no) clean-module-#{@name}-symbol.#{@rule_count}: rm -f #{defsym} CLEAN_MODULE_TARGETS += clean-module-#{@name}-symbol.#{@rule_count} DEFSYMFILES += #{defsym} -endif mostlyclean-module-#{@name}.#{@rule_count}: rm -f #{deps_str} @@ -170,7 +168,6 @@ endif #{mod_src}: $(builddir)/moddep.lst $(srcdir)/genmodsrc.sh sh $(srcdir)/genmodsrc.sh '#{mod_name}' $< > $@ || (rm -f $@; exit 1) -ifneq ($(#{prefix}_EXPORTS),no) ifneq ($(TARGET_APPLE_CC),1) #{defsym}: #{pre_obj} $(NM) -g --defined-only -P -p $< | sed 's/^\\([^ ]*\\).*/\\1 #{mod_name}/' > $@ @@ -178,7 +175,6 @@ else #{defsym}: #{pre_obj} $(NM) -g -P -p $< | grep -E '^[a-zA-Z0-9_]* [TDS]' | sed 's/^\\([^ ]*\\).*/\\1 #{mod_name}/' > $@ endif -endif #{undsym}: #{pre_obj} echo '#{mod_name}' > $@ @@ -205,7 +201,7 @@ endif -include #{dep} clean-module-#{extra_target}.#{@rule_count}: - rm -f #{command} #{fs} #{partmap} #{handler} #{parttool} #{video} + rm -f #{command} #{fs} #{partmap} #{handler} #{parttool} #{video} #{terminal} CLEAN_MODULE_TARGETS += clean-module-#{extra_target}.#{@rule_count} @@ -331,8 +327,15 @@ class Program "CLEANFILES += #{@name} #{objs_str} MOSTLYCLEANFILES += #{deps_str} +ifeq ($(#{prefix}_RELOCATABLE),yes) +#{@name}: $(#{prefix}_DEPENDENCIES) #{objs_str} + $(TARGET_CC) -Wl,-r,-d -o $@ #{objs_str} $(TARGET_LDFLAGS) $(#{prefix}_LDFLAGS) + $(STRIP) --strip-unneeded -K start -R .note -R .comment $@ +else #{@name}: $(#{prefix}_DEPENDENCIES) #{objs_str} $(TARGET_CC) -o $@ #{objs_str} $(TARGET_LDFLAGS) $(#{prefix}_LDFLAGS) + $(STRIP) -R .rel.dyn -R .reginfo -R .note -R .comment $@ +endif " + objs.collect_with_index do |obj, i| src = sources[i] @@ -344,6 +347,7 @@ MOSTLYCLEANFILES += #{deps_str} "#{obj}: #{src} $(#{src}_DEPENDENCIES) $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -MD -c -o $@ $< + -include #{dep} " @@ -370,8 +374,7 @@ class Script "CLEANFILES += #{@name} #{@name}: #{src} $(#{src}_DEPENDENCIES) config.status - ./config.status --file=#{name}:#{src} - sed -i -e 's,@pkglib_DATA@,$(pkglib_DATA),g' $@ + ./config.status --file=-:#{src} | sed -e 's,@pkglib_DATA@,$(pkglib_DATA),g' > $@ chmod +x $@ " diff --git a/genmoddep.awk b/genmoddep.awk index f7f085e99..19ac80c71 100644 --- a/genmoddep.awk +++ b/genmoddep.awk @@ -29,7 +29,7 @@ FNR == 1 { if ($1 in symtab) { modtab[module] = modtab[module] " " symtab[$1]; } - else { + else if ($1 != "__gnu_local_gp") { printf "%s in %s is not defined\n", $1, module >"/dev/stderr"; error++; exit; diff --git a/gensymlist.sh.in b/gensymlist.sh.in index 27fc5e61a..7cd3b48e3 100644 --- a/gensymlist.sh.in +++ b/gensymlist.sh.in @@ -14,7 +14,7 @@ ### The configure script will replace these variables. : ${srcdir=@srcdir@} -: ${CC=@CC@} +: ${CC=@TARGET_CC@} cat <. + */ + +#define _GNU_SOURCE 1 + +#include +#include +#include + +int +main () +{ + int i; + + printf ("#include \n"); + +#define TAB(op) \ + printf ("grub_int16_t grub_trig_" #op "tab[] =\n{"); \ + for (i = 0; i < GRUB_TRIG_ANGLE_MAX; i++) \ + { \ + double x = i * 2 * M_PI / GRUB_TRIG_ANGLE_MAX; \ + if (i % 10 == 0) \ + printf ("\n "); \ + printf ("%d,", (int) (round (op (x) * GRUB_TRIG_FRACTION_SCALE))); \ + } \ + printf ("\n};\n") + + TAB(sin); + TAB(cos); + + return 0; +} diff --git a/gettext/gettext.c b/gettext/gettext.c index 83497b7f6..0aa8decbd 100644 --- a/gettext/gettext.c +++ b/gettext/gettext.c @@ -279,21 +279,19 @@ grub_gettext_init_ext (const char *lang) /* mo_file e.g.: /boot/grub/locale/ca.mo */ - mo_file = - grub_malloc (grub_strlen (locale_dir) + grub_strlen ("/") + - grub_strlen (lang) + grub_strlen (".mo") + 1); - - /* Warning: if changing some paths in the below line, change the grub_malloc - contents below. */ - - grub_sprintf (mo_file, "%s/%s.mo", locale_dir, lang); + mo_file = grub_xasprintf ("%s/%s.mo", locale_dir, lang); + if (!mo_file) + return; fd_mo = grub_mofile_open (mo_file); /* Will try adding .gz as well. */ if (fd_mo == NULL) { - grub_sprintf (mo_file, "%s.gz", mo_file); + grub_free (mo_file); + mo_file = grub_xasprintf ("%s.gz", mo_file); + if (!mo_file) + return; fd_mo = grub_mofile_open (mo_file); } diff --git a/gfxmenu/gfxmenu.c b/gfxmenu/gfxmenu.c new file mode 100644 index 000000000..a2e765156 --- /dev/null +++ b/gfxmenu/gfxmenu.c @@ -0,0 +1,144 @@ +/* gfxmenu.c - Graphical menu interface controller. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +grub_gfxmenu_view_t cached_view; + +static void +grub_gfxmenu_viewer_fini (void *data __attribute__ ((unused))) +{ +} + +/* FIXME: Previously 't' changed to text menu is it necessary? */ +static grub_err_t +grub_gfxmenu_try (int entry, grub_menu_t menu, int nested) +{ + grub_gfxmenu_view_t view = NULL; + const char *theme_path; + struct grub_menu_viewer *instance; + grub_err_t err; + struct grub_video_mode_info mode_info; + + theme_path = grub_env_get ("theme"); + if (! theme_path) + { + grub_error_push (); + grub_gfxterm_fullscreen (); + grub_error_pop (); + return grub_error (GRUB_ERR_FILE_NOT_FOUND, "no theme specified"); + } + + instance = grub_zalloc (sizeof (*instance)); + if (!instance) + { + grub_error_push (); + grub_gfxterm_fullscreen (); + grub_error_pop (); + return grub_errno; + } + + err = grub_video_get_info (&mode_info); + if (err) + { + grub_error_push (); + grub_gfxterm_fullscreen (); + grub_error_pop (); + return err; + } + + if (!cached_view || grub_strcmp (cached_view->theme_path, theme_path) != 0 + || cached_view->screen.width != mode_info.width + || cached_view->screen.height != mode_info.height) + { + grub_free (cached_view); + /* Create the view. */ + cached_view = grub_gfxmenu_view_new (theme_path, mode_info.width, + mode_info.height); + } + + if (! cached_view) + { + grub_free (instance); + grub_error_push (); + grub_gfxterm_fullscreen (); + grub_error_pop (); + return grub_errno; + } + + view = cached_view; + + view->double_repaint = (mode_info.mode_type + & GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED) + && !(mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP); + view->selected = entry; + view->menu = menu; + view->nested = nested; + view->first_timeout = -1; + + grub_gfxmenu_view_draw (view); + + instance->data = view; + instance->set_chosen_entry = grub_gfxmenu_set_chosen_entry; + instance->fini = grub_gfxmenu_viewer_fini; + instance->print_timeout = grub_gfxmenu_print_timeout; + instance->clear_timeout = grub_gfxmenu_clear_timeout; + + grub_menu_register_viewer (instance); + + return GRUB_ERR_NONE; +} + +GRUB_MOD_INIT (gfxmenu) +{ + struct grub_term_output *term; + + FOR_ACTIVE_TERM_OUTPUTS(term) + if (grub_gfxmenu_try_hook && grub_strcmp (term->name, "gfxterm") == 0) + { + grub_gfxterm_fullscreen (); + break; + } + + grub_gfxmenu_try_hook = grub_gfxmenu_try; +} + +GRUB_MOD_FINI (gfxmenu) +{ + grub_gfxmenu_view_destroy (cached_view); + grub_gfxmenu_try_hook = NULL; +} diff --git a/gfxmenu/gui_box.c b/gfxmenu/gui_box.c new file mode 100644 index 000000000..38b15f96d --- /dev/null +++ b/gfxmenu/gui_box.c @@ -0,0 +1,412 @@ +/* gui_box.c - GUI container that stack components. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include + +struct component_node +{ + grub_gui_component_t component; + struct component_node *next; + struct component_node *prev; +}; + +typedef struct grub_gui_box *grub_gui_box_t; + +typedef void (*layout_func_t) (grub_gui_box_t self, int modify_layout, + unsigned *minimal_width, + unsigned *minimal_height); + +struct grub_gui_box +{ + struct grub_gui_container container; + + grub_gui_container_t parent; + grub_video_rect_t bounds; + char *id; + + /* Doubly linked list of components with dummy head & tail nodes. */ + struct component_node chead; + struct component_node ctail; + + /* The layout function: differs for vertical and horizontal boxes. */ + layout_func_t layout_func; +}; + +static void +box_destroy (void *vself) +{ + grub_gui_box_t self = vself; + struct component_node *cur; + struct component_node *next; + for (cur = self->chead.next; cur != &self->ctail; cur = next) + { + /* Copy the 'next' pointer, since we need it for the next iteration, + and we're going to free the memory it is stored in. */ + next = cur->next; + /* Destroy the child component. */ + cur->component->ops->destroy (cur->component); + /* Free the linked list node. */ + grub_free (cur); + } + grub_free (self); +} + +static const char * +box_get_id (void *vself) +{ + grub_gui_box_t self = vself; + return self->id; +} + +static int +box_is_instance (void *vself __attribute__((unused)), const char *type) +{ + return (grub_strcmp (type, "component") == 0 + || grub_strcmp (type, "container") == 0); +} + +static void +layout_horizontally (grub_gui_box_t self, int modify_layout, + unsigned *min_width, unsigned *min_height) +{ + /* Start at the left (chead) and set the x coordinates as we go right. */ + /* All components have their width set to the box's width. */ + + struct component_node *cur; + unsigned w = 0, mwfrac = 0, h = 0, x = 0; + grub_fixed_signed_t wfrac = 0; + int bogus_frac = 0; + + for (cur = self->chead.next; cur != &self->ctail; cur = cur->next) + { + grub_gui_component_t c = cur->component; + unsigned mw = 0, mh = 0; + + if (c->ops->get_minimal_size) + c->ops->get_minimal_size (c, &mw, &mh); + + if (c->h > (signed) h) + h = c->h; + if (mh > h) + h = mh; + wfrac += c->wfrac; + w += c->w; + if (mw - c->w > 0) + mwfrac += mw - c->w; + } + if (wfrac > GRUB_FIXED_1 || (w > 0 && wfrac == GRUB_FIXED_1)) + bogus_frac = 1; + + if (min_width) + { + if (wfrac < GRUB_FIXED_1) + *min_width = grub_fixed_sfs_divide (w, GRUB_FIXED_1 - wfrac); + else + *min_width = w; + if (*min_width < w + mwfrac) + *min_width = w + mwfrac; + } + if (min_height) + *min_height = h; + + if (!modify_layout) + return; + + for (cur = self->chead.next; cur != &self->ctail; cur = cur->next) + { + grub_video_rect_t r; + grub_gui_component_t c = cur->component; + unsigned mw = 0, mh = 0; + + r.x = x; + r.y = 0; + r.height = h; + + if (c->ops->get_minimal_size) + c->ops->get_minimal_size (c, &mw, &mh); + + r.width = c->w; + if (!bogus_frac) + r.width += grub_fixed_sfs_multiply (self->bounds.width, c->wfrac); + + if (r.width < mw) + r.width = mw; + + c->ops->set_bounds (c, &r); + + x += r.width; + } +} + +static void +layout_vertically (grub_gui_box_t self, int modify_layout, + unsigned *min_width, unsigned *min_height) +{ + /* Start at the top (chead) and set the y coordinates as we go rdown. */ + /* All components have their height set to the box's height. */ + + struct component_node *cur; + unsigned h = 0, mhfrac = 0, w = 0, y = 0; + grub_fixed_signed_t hfrac = 0; + int bogus_frac = 0; + + for (cur = self->chead.next; cur != &self->ctail; cur = cur->next) + { + grub_gui_component_t c = cur->component; + unsigned mw = 0, mh = 0; + + if (c->ops->get_minimal_size) + c->ops->get_minimal_size (c, &mw, &mh); + + if (c->w > (signed) w) + w = c->w; + if (mw > w) + w = mw; + hfrac += c->hfrac; + h += c->h; + if (mh - c->h > 0) + mhfrac += mh - c->h; + } + if (hfrac > GRUB_FIXED_1 || (h > 0 && hfrac == GRUB_FIXED_1)) + bogus_frac = 1; + + if (min_height) + { + if (hfrac < GRUB_FIXED_1) + *min_height = grub_fixed_sfs_divide (h, GRUB_FIXED_1 - hfrac); + else + *min_height = h; + if (*min_height < h + mhfrac) + *min_height = h + mhfrac; + } + if (min_width) + *min_width = w; + + if (!modify_layout) + return; + + for (cur = self->chead.next; cur != &self->ctail; cur = cur->next) + { + grub_video_rect_t r; + grub_gui_component_t c = cur->component; + unsigned mw = 0, mh = 0; + + r.x = 0; + r.y = y; + r.width = w; + + if (c->ops->get_minimal_size) + c->ops->get_minimal_size (c, &mw, &mh); + + r.height = c->h; + if (!bogus_frac) + r.height += grub_fixed_sfs_multiply (self->bounds.height, c->hfrac); + + if (r.height < mh) + r.height = mh; + + c->ops->set_bounds (c, &r); + + y += r.height; + } +} + +static void +box_paint (void *vself, const grub_video_rect_t *region) +{ + grub_gui_box_t self = vself; + struct component_node *cur; + grub_video_rect_t vpsave; + + grub_gui_set_viewport (&self->bounds, &vpsave); + for (cur = self->chead.next; cur != &self->ctail; cur = cur->next) + { + grub_gui_component_t comp = cur->component; + comp->ops->paint (comp, region); + } + grub_gui_restore_viewport (&vpsave); +} + +static void +box_set_parent (void *vself, grub_gui_container_t parent) +{ + grub_gui_box_t self = vself; + self->parent = parent; +} + +static grub_gui_container_t +box_get_parent (void *vself) +{ + grub_gui_box_t self = vself; + return self->parent; +} + +static void +box_set_bounds (void *vself, const grub_video_rect_t *bounds) +{ + grub_gui_box_t self = vself; + self->bounds = *bounds; + self->layout_func (self, 1, 0, 0); /* Relayout the children. */ +} + +static void +box_get_bounds (void *vself, grub_video_rect_t *bounds) +{ + grub_gui_box_t self = vself; + *bounds = self->bounds; +} + +/* The box's preferred size is based on the preferred sizes + of its children. */ +static void +box_get_minimal_size (void *vself, unsigned *width, unsigned *height) +{ + grub_gui_box_t self = vself; + self->layout_func (self, 0, width, height); /* Just calculate the size. */ +} + +static grub_err_t +box_set_property (void *vself, const char *name, const char *value) +{ + grub_gui_box_t self = vself; + if (grub_strcmp (name, "id") == 0) + { + grub_free (self->id); + if (value) + { + self->id = grub_strdup (value); + if (! self->id) + return grub_errno; + } + else + self->id = 0; + } + + return grub_errno; +} + +static void +box_add (void *vself, grub_gui_component_t comp) +{ + grub_gui_box_t self = vself; + struct component_node *node; + node = grub_malloc (sizeof (*node)); + if (! node) + return; /* Note: probably should handle the error. */ + node->component = comp; + /* Insert the node before the tail. */ + node->prev = self->ctail.prev; + node->prev->next = node; + node->next = &self->ctail; + node->next->prev = node; + + comp->ops->set_parent (comp, (grub_gui_container_t) self); + self->layout_func (self, 1, 0, 0); /* Relayout the children. */ +} + +static void +box_remove (void *vself, grub_gui_component_t comp) +{ + grub_gui_box_t self = vself; + struct component_node *cur; + for (cur = self->chead.next; cur != &self->ctail; cur = cur->next) + { + if (cur->component == comp) + { + /* Unlink 'cur' from the list. */ + cur->prev->next = cur->next; + cur->next->prev = cur->prev; + /* Free the node's memory (but don't destroy the component). */ + grub_free (cur); + /* Must not loop again, since 'cur' would be dereferenced! */ + return; + } + } +} + +static void +box_iterate_children (void *vself, + grub_gui_component_callback cb, void *userdata) +{ + grub_gui_box_t self = vself; + struct component_node *cur; + for (cur = self->chead.next; cur != &self->ctail; cur = cur->next) + cb (cur->component, userdata); +} + +static struct grub_gui_component_ops box_comp_ops = + { + .destroy = box_destroy, + .get_id = box_get_id, + .is_instance = box_is_instance, + .paint = box_paint, + .set_parent = box_set_parent, + .get_parent = box_get_parent, + .set_bounds = box_set_bounds, + .get_bounds = box_get_bounds, + .get_minimal_size = box_get_minimal_size, + .set_property = box_set_property + }; + +static struct grub_gui_container_ops box_ops = +{ + .add = box_add, + .remove = box_remove, + .iterate_children = box_iterate_children +}; + +/* Box constructor. Specify the appropriate layout function to create + a horizontal or vertical stacking box. */ +static grub_gui_box_t +box_new (layout_func_t layout_func) +{ + grub_gui_box_t box; + box = grub_zalloc (sizeof (*box)); + if (! box) + return 0; + box->container.ops = &box_ops; + box->container.component.ops = &box_comp_ops; + box->chead.next = &box->ctail; + box->ctail.prev = &box->chead; + box->layout_func = layout_func; + return box; +} + +/* Create a new container that stacks its child components horizontally, + from left to right. Each child get a width corresponding to its + preferred width. The height of each child is set the maximum of the + preferred heights of all children. */ +grub_gui_container_t +grub_gui_hbox_new (void) +{ + return (grub_gui_container_t) box_new (layout_horizontally); +} + +/* Create a new container that stacks its child components verticallyj, + from top to bottom. Each child get a height corresponding to its + preferred height. The width of each child is set the maximum of the + preferred widths of all children. */ +grub_gui_container_t +grub_gui_vbox_new (void) +{ + return (grub_gui_container_t) box_new (layout_vertically); +} diff --git a/gfxmenu/gui_canvas.c b/gfxmenu/gui_canvas.c new file mode 100644 index 000000000..b3919c2d3 --- /dev/null +++ b/gfxmenu/gui_canvas.c @@ -0,0 +1,267 @@ +/* gui_canvas.c - GUI container allowing manually placed components. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include + +/* TODO Add layering so that components can be properly overlaid. */ + +struct component_node +{ + grub_gui_component_t component; + struct component_node *next; +}; + +struct grub_gui_canvas +{ + struct grub_gui_container container; + + grub_gui_container_t parent; + grub_video_rect_t bounds; + char *id; + /* Component list (dummy head node). */ + struct component_node components; +}; + +typedef struct grub_gui_canvas *grub_gui_canvas_t; + +static void +canvas_destroy (void *vself) +{ + grub_gui_canvas_t self = vself; + struct component_node *cur; + struct component_node *next; + for (cur = self->components.next; cur; cur = next) + { + /* Copy the 'next' pointer, since we need it for the next iteration, + and we're going to free the memory it is stored in. */ + next = cur->next; + /* Destroy the child component. */ + cur->component->ops->destroy (cur->component); + /* Free the linked list node. */ + grub_free (cur); + } + grub_free (self); +} + +static const char * +canvas_get_id (void *vself) +{ + grub_gui_canvas_t self = vself; + return self->id; +} + +static int +canvas_is_instance (void *vself __attribute__((unused)), const char *type) +{ + return (grub_strcmp (type, "component") == 0 + || grub_strcmp (type, "container") == 0); +} + +static void +canvas_paint (void *vself, const grub_video_rect_t *region) +{ + grub_gui_canvas_t self = vself; + struct component_node *cur; + grub_video_rect_t vpsave; + + grub_gui_set_viewport (&self->bounds, &vpsave); + for (cur = self->components.next; cur; cur = cur->next) + { + grub_video_rect_t r; + grub_gui_component_t comp; + signed x, y, w, h; + + comp = cur->component; + + w = grub_fixed_sfs_multiply (self->bounds.width, comp->wfrac) + comp->w; + h = grub_fixed_sfs_multiply (self->bounds.height, comp->hfrac) + comp->h; + x = grub_fixed_sfs_multiply (self->bounds.width, comp->xfrac) + comp->x; + y = grub_fixed_sfs_multiply (self->bounds.height, comp->yfrac) + comp->y; + + if (comp->ops->get_minimal_size) + { + unsigned mw; + unsigned mh; + comp->ops->get_minimal_size (comp, &mw, &mh); + if (w < (signed) mw) + w = mw; + if (h < (signed) mh) + h = mh; + } + + /* Sanity checks. */ + if (w <= 0) + w = 32; + if (h <= 0) + h = 32; + + if (x >= (signed) self->bounds.width) + x = self->bounds.width - 32; + if (y >= (signed) self->bounds.height) + y = self->bounds.height - 32; + + if (x < 0) + x = 0; + if (y < 0) + y = 0; + + if (x + w >= (signed) self->bounds.width) + w = self->bounds.width - x; + if (y + h >= (signed) self->bounds.height) + h = self->bounds.height - y; + + r.x = x; + r.y = y; + r.width = w; + r.height = h; + comp->ops->set_bounds (comp, &r); + + /* Paint the child. */ + if (grub_video_have_common_points (region, &r)) + comp->ops->paint (comp, region); + } + grub_gui_restore_viewport (&vpsave); +} + +static void +canvas_set_parent (void *vself, grub_gui_container_t parent) +{ + grub_gui_canvas_t self = vself; + self->parent = parent; +} + +static grub_gui_container_t +canvas_get_parent (void *vself) +{ + grub_gui_canvas_t self = vself; + return self->parent; +} + +static void +canvas_set_bounds (void *vself, const grub_video_rect_t *bounds) +{ + grub_gui_canvas_t self = vself; + self->bounds = *bounds; +} + +static void +canvas_get_bounds (void *vself, grub_video_rect_t *bounds) +{ + grub_gui_canvas_t self = vself; + *bounds = self->bounds; +} + +static grub_err_t +canvas_set_property (void *vself, const char *name, const char *value) +{ + grub_gui_canvas_t self = vself; + if (grub_strcmp (name, "id") == 0) + { + grub_free (self->id); + if (value) + { + self->id = grub_strdup (value); + if (! self->id) + return grub_errno; + } + else + self->id = 0; + } + return grub_errno; +} + +static void +canvas_add (void *vself, grub_gui_component_t comp) +{ + grub_gui_canvas_t self = vself; + struct component_node *node; + node = grub_malloc (sizeof (*node)); + if (! node) + return; /* Note: probably should handle the error. */ + node->component = comp; + node->next = self->components.next; + self->components.next = node; + comp->ops->set_parent (comp, (grub_gui_container_t) self); +} + +static void +canvas_remove (void *vself, grub_gui_component_t comp) +{ + grub_gui_canvas_t self = vself; + struct component_node *cur; + struct component_node *prev; + prev = &self->components; + for (cur = self->components.next; cur; prev = cur, cur = cur->next) + { + if (cur->component == comp) + { + /* Unlink 'cur' from the list. */ + prev->next = cur->next; + /* Free the node's memory (but don't destroy the component). */ + grub_free (cur); + /* Must not loop again, since 'cur' would be dereferenced! */ + return; + } + } +} + +static void +canvas_iterate_children (void *vself, + grub_gui_component_callback cb, void *userdata) +{ + grub_gui_canvas_t self = vself; + struct component_node *cur; + for (cur = self->components.next; cur; cur = cur->next) + cb (cur->component, userdata); +} + +static struct grub_gui_component_ops canvas_comp_ops = +{ + .destroy = canvas_destroy, + .get_id = canvas_get_id, + .is_instance = canvas_is_instance, + .paint = canvas_paint, + .set_parent = canvas_set_parent, + .get_parent = canvas_get_parent, + .set_bounds = canvas_set_bounds, + .get_bounds = canvas_get_bounds, + .set_property = canvas_set_property +}; + +static struct grub_gui_container_ops canvas_ops = +{ + .add = canvas_add, + .remove = canvas_remove, + .iterate_children = canvas_iterate_children +}; + +grub_gui_container_t +grub_gui_canvas_new (void) +{ + grub_gui_canvas_t canvas; + canvas = grub_zalloc (sizeof (*canvas)); + if (! canvas) + return 0; + canvas->container.ops = &canvas_ops; + canvas->container.component.ops = &canvas_comp_ops; + return (grub_gui_container_t) canvas; +} diff --git a/gfxmenu/gui_circular_progress.c b/gfxmenu/gui_circular_progress.c new file mode 100644 index 000000000..9a859ee2e --- /dev/null +++ b/gfxmenu/gui_circular_progress.c @@ -0,0 +1,302 @@ +/* gui_circular_process.c - GUI circular progress indicator component. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct grub_gui_circular_progress +{ + struct grub_gui_progress progress; + + grub_gui_container_t parent; + grub_video_rect_t bounds; + char *id; + int visible; + int start; + int end; + int value; + int num_ticks; + int start_angle; + int ticks_disappear; + char *theme_dir; + int need_to_load_pixmaps; + char *center_file; + char *tick_file; + struct grub_video_bitmap *center_bitmap; + struct grub_video_bitmap *tick_bitmap; +}; + +typedef struct grub_gui_circular_progress *circular_progress_t; + +static void +circprog_destroy (void *vself) +{ + circular_progress_t self = vself; + grub_free (self); +} + +static const char * +circprog_get_id (void *vself) +{ + circular_progress_t self = vself; + return self->id; +} + +static int +circprog_is_instance (void *vself __attribute__((unused)), const char *type) +{ + return grub_strcmp (type, "component") == 0; +} + +static struct grub_video_bitmap * +load_bitmap (const char *dir, const char *file) +{ + struct grub_video_bitmap *bitmap; + char *abspath; + + /* Check arguments. */ + if (! dir || ! file) + return 0; + + /* Resolve to an absolute path. */ + abspath = grub_resolve_relative_path (dir, file); + if (! abspath) + return 0; + + /* Load the image. */ + grub_errno = GRUB_ERR_NONE; + grub_video_bitmap_load (&bitmap, abspath); + grub_errno = GRUB_ERR_NONE; + + grub_free (abspath); + return bitmap; +} + +static int +check_pixmaps (circular_progress_t self) +{ + if (self->need_to_load_pixmaps) + { + if (self->center_bitmap) + grub_video_bitmap_destroy (self->center_bitmap); + self->center_bitmap = load_bitmap (self->theme_dir, self->center_file); + self->tick_bitmap = load_bitmap (self->theme_dir, self->tick_file); + self->need_to_load_pixmaps = 0; + } + + return (self->center_bitmap != 0 && self->tick_bitmap != 0); +} + +static void +circprog_paint (void *vself, const grub_video_rect_t *region) +{ + circular_progress_t self = vself; + + if (! self->visible) + return; + + if (!grub_video_have_common_points (region, &self->bounds)) + return; + + if (! check_pixmaps (self)) + return; + + grub_video_rect_t vpsave; + grub_gui_set_viewport (&self->bounds, &vpsave); + + int width = self->bounds.width; + int height = self->bounds.height; + int center_width = grub_video_bitmap_get_width (self->center_bitmap); + int center_height = grub_video_bitmap_get_height (self->center_bitmap); + int tick_width = grub_video_bitmap_get_width (self->tick_bitmap); + int tick_height = grub_video_bitmap_get_height (self->tick_bitmap); + grub_video_blit_bitmap (self->center_bitmap, GRUB_VIDEO_BLIT_BLEND, + (width - center_width) / 2, + (height - center_height) / 2, 0, 0, + center_width, center_height); + + int radius = width / 2 - tick_width / 2 - 1; + int nticks; + int tick_begin; + int tick_end; + if (self->end == self->start) + nticks = 0; + else + nticks = (self->num_ticks + * (self->value - self->start) + / (self->end - self->start)); + /* Do ticks appear or disappear as the value approached the end? */ + if (self->ticks_disappear) + { + tick_begin = nticks; + tick_end = self->num_ticks - 1; + } + else + { + tick_begin = 0; + tick_end = nticks - 1; + } + + int i; + for (i = tick_begin; i < tick_end; i++) + { + int x; + int y; + int angle; + + /* Calculate the location of the tick. */ + angle = self->start_angle + i * GRUB_TRIG_ANGLE_MAX / self->num_ticks; + x = width / 2 + (grub_cos (angle) * radius / GRUB_TRIG_FRACTION_SCALE); + y = height / 2 + (grub_sin (angle) * radius / GRUB_TRIG_FRACTION_SCALE); + + /* Adjust (x,y) so the tick is centered. */ + x -= tick_width / 2; + y -= tick_height / 2; + + /* Draw the tick. */ + grub_video_blit_bitmap (self->tick_bitmap, GRUB_VIDEO_BLIT_BLEND, + x, y, 0, 0, tick_width, tick_height); + } + + grub_gui_restore_viewport (&vpsave); +} + +static void +circprog_set_parent (void *vself, grub_gui_container_t parent) +{ + circular_progress_t self = vself; + self->parent = parent; +} + +static grub_gui_container_t +circprog_get_parent (void *vself) +{ + circular_progress_t self = vself; + return self->parent; +} + +static void +circprog_set_bounds (void *vself, const grub_video_rect_t *bounds) +{ + circular_progress_t self = vself; + self->bounds = *bounds; +} + +static void +circprog_get_bounds (void *vself, grub_video_rect_t *bounds) +{ + circular_progress_t self = vself; + *bounds = self->bounds; +} + +static grub_err_t +circprog_set_property (void *vself, const char *name, const char *value) +{ + circular_progress_t self = vself; + if (grub_strcmp (name, "num_ticks") == 0) + { + self->num_ticks = grub_strtol (value, 0, 10); + } + else if (grub_strcmp (name, "start_angle") == 0) + { + self->start_angle = grub_strtol (value, 0, 10); + } + else if (grub_strcmp (name, "ticks_disappear") == 0) + { + self->ticks_disappear = grub_strcmp (value, "false") != 0; + } + else if (grub_strcmp (name, "center_bitmap") == 0) + { + self->need_to_load_pixmaps = 1; + grub_free (self->center_file); + self->center_file = value ? grub_strdup (value) : 0; + } + else if (grub_strcmp (name, "tick_bitmap") == 0) + { + self->need_to_load_pixmaps = 1; + grub_free (self->tick_file); + self->tick_file = value ? grub_strdup (value) : 0; + } + else if (grub_strcmp (name, "theme_dir") == 0) + { + self->need_to_load_pixmaps = 1; + grub_free (self->theme_dir); + self->theme_dir = value ? grub_strdup (value) : 0; + } + else if (grub_strcmp (name, "id") == 0) + { + grub_free (self->id); + if (value) + self->id = grub_strdup (value); + else + self->id = 0; + } + return grub_errno; +} + +static void +circprog_set_state (void *vself, int visible, int start, + int current, int end) +{ + circular_progress_t self = vself; + self->visible = visible; + self->start = start; + self->value = current; + self->end = end; +} + +static struct grub_gui_component_ops circprog_ops = +{ + .destroy = circprog_destroy, + .get_id = circprog_get_id, + .is_instance = circprog_is_instance, + .paint = circprog_paint, + .set_parent = circprog_set_parent, + .get_parent = circprog_get_parent, + .set_bounds = circprog_set_bounds, + .get_bounds = circprog_get_bounds, + .set_property = circprog_set_property +}; + +static struct grub_gui_progress_ops circprog_prog_ops = + { + .set_state = circprog_set_state + }; + +grub_gui_component_t +grub_gui_circular_progress_new (void) +{ + circular_progress_t self; + self = grub_zalloc (sizeof (*self)); + if (! self) + return 0; + self->progress.ops = &circprog_prog_ops; + self->progress.component.ops = &circprog_ops; + self->visible = 1; + self->num_ticks = 64; + self->start_angle = -64; + + return (grub_gui_component_t) self; +} diff --git a/gfxmenu/gui_image.c b/gfxmenu/gui_image.c new file mode 100644 index 000000000..3988f4ba8 --- /dev/null +++ b/gfxmenu/gui_image.c @@ -0,0 +1,269 @@ +/* gui_image.c - GUI component to display an image. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +struct grub_gui_image +{ + struct grub_gui_component component; + + grub_gui_container_t parent; + grub_video_rect_t bounds; + char *id; + char *theme_dir; + struct grub_video_bitmap *raw_bitmap; + struct grub_video_bitmap *bitmap; +}; + +typedef struct grub_gui_image *grub_gui_image_t; + +static void +image_destroy (void *vself) +{ + grub_gui_image_t self = vself; + + /* Free the scaled bitmap, unless it's a reference to the raw bitmap. */ + if (self->bitmap && (self->bitmap != self->raw_bitmap)) + grub_video_bitmap_destroy (self->bitmap); + if (self->raw_bitmap) + grub_video_bitmap_destroy (self->raw_bitmap); + + grub_free (self); +} + +static const char * +image_get_id (void *vself) +{ + grub_gui_image_t self = vself; + return self->id; +} + +static int +image_is_instance (void *vself __attribute__((unused)), const char *type) +{ + return grub_strcmp (type, "component") == 0; +} + +static void +image_paint (void *vself, const grub_video_rect_t *region) +{ + grub_gui_image_t self = vself; + grub_video_rect_t vpsave; + + if (! self->bitmap) + return; + if (!grub_video_have_common_points (region, &self->bounds)) + return; + + grub_gui_set_viewport (&self->bounds, &vpsave); + grub_video_blit_bitmap (self->bitmap, GRUB_VIDEO_BLIT_BLEND, + 0, 0, 0, 0, + grub_video_bitmap_get_width (self->bitmap), + grub_video_bitmap_get_height (self->bitmap)); + grub_gui_restore_viewport (&vpsave); +} + +static void +image_set_parent (void *vself, grub_gui_container_t parent) +{ + grub_gui_image_t self = vself; + self->parent = parent; +} + +static grub_gui_container_t +image_get_parent (void *vself) +{ + grub_gui_image_t self = vself; + return self->parent; +} + +static grub_err_t +rescale_image (grub_gui_image_t self) +{ + if (! self->raw_bitmap) + { + if (self->bitmap) + { + grub_video_bitmap_destroy (self->bitmap); + self->bitmap = 0; + } + return grub_errno; + } + + unsigned width = self->bounds.width; + unsigned height = self->bounds.height; + + if (self->bitmap + && (grub_video_bitmap_get_width (self->bitmap) == width) + && (grub_video_bitmap_get_height (self->bitmap) == height)) + { + /* Nothing to do; already the right size. */ + return grub_errno; + } + + /* Free any old scaled bitmap, + *unless* it's a reference to the raw bitmap. */ + if (self->bitmap && (self->bitmap != self->raw_bitmap)) + grub_video_bitmap_destroy (self->bitmap); + + self->bitmap = 0; + + /* Create a scaled bitmap, unless the requested size is the same + as the raw size -- in that case a reference is made. */ + if (grub_video_bitmap_get_width (self->raw_bitmap) == width + && grub_video_bitmap_get_height (self->raw_bitmap) == height) + { + self->bitmap = self->raw_bitmap; + return grub_errno; + } + + /* Don't scale to an invalid size. */ + if (width == 0 || height == 0) + return grub_errno; + + /* Create the scaled bitmap. */ + grub_video_bitmap_create_scaled (&self->bitmap, + width, + height, + self->raw_bitmap, + GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST); + if (grub_errno != GRUB_ERR_NONE) + { + grub_error_push (); + grub_error (grub_errno, "failed to scale bitmap for image component"); + } + return grub_errno; +} + +static void +image_set_bounds (void *vself, const grub_video_rect_t *bounds) +{ + grub_gui_image_t self = vself; + self->bounds = *bounds; + rescale_image (self); +} + +static void +image_get_bounds (void *vself, grub_video_rect_t *bounds) +{ + grub_gui_image_t self = vself; + *bounds = self->bounds; +} + +/* FIXME: inform rendering system it's not forced minimum. */ +static void +image_get_minimal_size (void *vself, unsigned *width, unsigned *height) +{ + grub_gui_image_t self = vself; + + if (self->raw_bitmap) + { + *width = grub_video_bitmap_get_width (self->raw_bitmap); + *height = grub_video_bitmap_get_height (self->raw_bitmap); + } + else + { + *width = 0; + *height = 0; + } +} + +static grub_err_t +load_image (grub_gui_image_t self, const char *path) +{ + struct grub_video_bitmap *bitmap; + if (grub_video_bitmap_load (&bitmap, path) != GRUB_ERR_NONE) + return grub_errno; + + if (self->bitmap && (self->bitmap != self->raw_bitmap)) + grub_video_bitmap_destroy (self->bitmap); + if (self->raw_bitmap) + grub_video_bitmap_destroy (self->raw_bitmap); + + self->raw_bitmap = bitmap; + return rescale_image (self); +} + +static grub_err_t +image_set_property (void *vself, const char *name, const char *value) +{ + grub_gui_image_t self = vself; + if (grub_strcmp (name, "theme_dir") == 0) + { + grub_free (self->theme_dir); + self->theme_dir = grub_strdup (value); + } + else if (grub_strcmp (name, "file") == 0) + { + char *absvalue; + grub_err_t err; + + /* Resolve to an absolute path. */ + if (! self->theme_dir) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "unspecified theme_dir"); + absvalue = grub_resolve_relative_path (self->theme_dir, value); + if (! absvalue) + return grub_errno; + + err = load_image (self, absvalue); + grub_free (absvalue); + + return err; + } + else if (grub_strcmp (name, "id") == 0) + { + grub_free (self->id); + if (value) + self->id = grub_strdup (value); + else + self->id = 0; + } + return grub_errno; +} + +static struct grub_gui_component_ops image_ops = +{ + .destroy = image_destroy, + .get_id = image_get_id, + .is_instance = image_is_instance, + .paint = image_paint, + .set_parent = image_set_parent, + .get_parent = image_get_parent, + .set_bounds = image_set_bounds, + .get_bounds = image_get_bounds, + .get_minimal_size = image_get_minimal_size, + .set_property = image_set_property +}; + +grub_gui_component_t +grub_gui_image_new (void) +{ + grub_gui_image_t image; + image = grub_zalloc (sizeof (*image)); + if (! image) + return 0; + image->component.ops = &image_ops; + return (grub_gui_component_t) image; +} + diff --git a/gfxmenu/gui_label.c b/gfxmenu/gui_label.c new file mode 100644 index 000000000..a9dd575ac --- /dev/null +++ b/gfxmenu/gui_label.c @@ -0,0 +1,226 @@ +/* gui_label.c - GUI component to display a line of text. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include + +static const char *align_options[] = +{ + "left", + "center", + "right", + 0 +}; + +enum align_mode { + align_left, + align_center, + align_right +}; + +struct grub_gui_label +{ + struct grub_gui_component comp; + + grub_gui_container_t parent; + grub_video_rect_t bounds; + char *id; + int visible; + char *text; + grub_font_t font; + grub_gui_color_t color; + enum align_mode align; +}; + +typedef struct grub_gui_label *grub_gui_label_t; + +static void +label_destroy (void *vself) +{ + grub_gui_label_t self = vself; + grub_free (self->text); + grub_free (self); +} + +static const char * +label_get_id (void *vself) +{ + grub_gui_label_t self = vself; + return self->id; +} + +static int +label_is_instance (void *vself __attribute__((unused)), const char *type) +{ + return grub_strcmp (type, "component") == 0; +} + +static void +label_paint (void *vself, const grub_video_rect_t *region) +{ + grub_gui_label_t self = vself; + + if (! self->visible) + return; + + if (!grub_video_have_common_points (region, &self->bounds)) + return; + + /* Calculate the starting x coordinate. */ + int left_x; + if (self->align == align_left) + left_x = 0; + else if (self->align == align_center) + left_x = ((self->bounds.width + - grub_font_get_string_width (self->font, self->text)) + ) / 2; + else if (self->align == align_right) + left_x = (self->bounds.width + - grub_font_get_string_width (self->font, self->text)); + else + return; /* Invalid alignment. */ + + grub_video_rect_t vpsave; + grub_gui_set_viewport (&self->bounds, &vpsave); + grub_font_draw_string (self->text, + self->font, + grub_gui_map_color (self->color), + left_x, + grub_font_get_ascent (self->font)); + grub_gui_restore_viewport (&vpsave); +} + +static void +label_set_parent (void *vself, grub_gui_container_t parent) +{ + grub_gui_label_t self = vself; + self->parent = parent; +} + +static grub_gui_container_t +label_get_parent (void *vself) +{ + grub_gui_label_t self = vself; + return self->parent; +} + +static void +label_set_bounds (void *vself, const grub_video_rect_t *bounds) +{ + grub_gui_label_t self = vself; + self->bounds = *bounds; +} + +static void +label_get_bounds (void *vself, grub_video_rect_t *bounds) +{ + grub_gui_label_t self = vself; + *bounds = self->bounds; +} + +static void +label_get_minimal_size (void *vself, unsigned *width, unsigned *height) +{ + grub_gui_label_t self = vself; + *width = grub_font_get_string_width (self->font, self->text); + *height = (grub_font_get_ascent (self->font) + + grub_font_get_descent (self->font)); +} + +static grub_err_t +label_set_property (void *vself, const char *name, const char *value) +{ + grub_gui_label_t self = vself; + if (grub_strcmp (name, "text") == 0) + { + grub_free (self->text); + if (! value) + value = ""; + self->text = grub_strdup (value); + } + else if (grub_strcmp (name, "font") == 0) + { + self->font = grub_font_get (value); + } + else if (grub_strcmp (name, "color") == 0) + { + grub_gui_parse_color (value, &self->color); + } + else if (grub_strcmp (name, "align") == 0) + { + int i; + for (i = 0; align_options[i]; i++) + { + if (grub_strcmp (align_options[i], value) == 0) + { + self->align = i; /* Set the alignment mode. */ + break; + } + } + } + else if (grub_strcmp (name, "visible") == 0) + { + self->visible = grub_strcmp (value, "false") != 0; + } + else if (grub_strcmp (name, "id") == 0) + { + grub_free (self->id); + if (value) + self->id = grub_strdup (value); + else + self->id = 0; + } + return GRUB_ERR_NONE; +} + +static struct grub_gui_component_ops label_ops = +{ + .destroy = label_destroy, + .get_id = label_get_id, + .is_instance = label_is_instance, + .paint = label_paint, + .set_parent = label_set_parent, + .get_parent = label_get_parent, + .set_bounds = label_set_bounds, + .get_bounds = label_get_bounds, + .get_minimal_size = label_get_minimal_size, + .set_property = label_set_property +}; + +grub_gui_component_t +grub_gui_label_new (void) +{ + grub_gui_label_t label; + label = grub_zalloc (sizeof (*label)); + if (! label) + return 0; + label->comp.ops = &label_ops; + label->visible = 1; + label->text = grub_strdup (""); + label->font = grub_font_get ("Unknown Regular 16"); + label->color.red = 0; + label->color.green = 0; + label->color.blue = 0; + label->color.alpha = 255; + label->align = align_left; + return (grub_gui_component_t) label; +} diff --git a/gfxmenu/gui_list.c b/gfxmenu/gui_list.c new file mode 100644 index 000000000..0d771413f --- /dev/null +++ b/gfxmenu/gui_list.c @@ -0,0 +1,612 @@ +/* gui_list.c - GUI component to display a selectable list of items. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +struct grub_gui_list_impl +{ + struct grub_gui_list list; + + grub_gui_container_t parent; + grub_video_rect_t bounds; + char *id; + int visible; + + int icon_width; + int icon_height; + int item_height; + int item_padding; + int item_icon_space; + int item_spacing; + grub_font_t item_font; + grub_font_t selected_item_font; + grub_gui_color_t item_color; + int selected_item_color_set; + grub_gui_color_t selected_item_color; + + int draw_scrollbar; + int need_to_recreate_scrollbar; + char *scrollbar_frame_pattern; + char *scrollbar_thumb_pattern; + grub_gfxmenu_box_t scrollbar_frame; + grub_gfxmenu_box_t scrollbar_thumb; + int scrollbar_width; + + int first_shown_index; + + int need_to_recreate_boxes; + char *theme_dir; + char *menu_box_pattern; + char *selected_item_box_pattern; + grub_gfxmenu_box_t menu_box; + grub_gfxmenu_box_t selected_item_box; + + grub_gfxmenu_icon_manager_t icon_manager; + + grub_gfxmenu_view_t view; +}; + +typedef struct grub_gui_list_impl *list_impl_t; + +static void +list_destroy (void *vself) +{ + list_impl_t self = vself; + + grub_free (self->theme_dir); + grub_free (self->menu_box_pattern); + grub_free (self->selected_item_box_pattern); + if (self->menu_box) + self->menu_box->destroy (self->menu_box); + if (self->selected_item_box) + self->selected_item_box->destroy (self->selected_item_box); + if (self->icon_manager) + grub_gfxmenu_icon_manager_destroy (self->icon_manager); + + grub_free (self); +} + +static int +get_num_shown_items (list_impl_t self) +{ + int boxpad = self->item_padding; + int item_vspace = self->item_spacing; + int item_height = self->item_height; + + grub_gfxmenu_box_t box = self->menu_box; + int box_top_pad = box->get_top_pad (box); + int box_bottom_pad = box->get_bottom_pad (box); + + return (self->bounds.height + item_vspace - 2 * boxpad + - box_top_pad - box_bottom_pad) / (item_height + item_vspace); +} + +static int +check_boxes (list_impl_t self) +{ + if (self->need_to_recreate_boxes) + { + grub_gui_recreate_box (&self->menu_box, + self->menu_box_pattern, + self->theme_dir); + + grub_gui_recreate_box (&self->selected_item_box, + self->selected_item_box_pattern, + self->theme_dir); + + self->need_to_recreate_boxes = 0; + } + + return (self->menu_box != 0 && self->selected_item_box != 0); +} + +static int +check_scrollbar (list_impl_t self) +{ + if (self->need_to_recreate_scrollbar) + { + grub_gui_recreate_box (&self->scrollbar_frame, + self->scrollbar_frame_pattern, + self->theme_dir); + + grub_gui_recreate_box (&self->scrollbar_thumb, + self->scrollbar_thumb_pattern, + self->theme_dir); + + self->need_to_recreate_scrollbar = 0; + } + + return (self->scrollbar_frame != 0 && self->scrollbar_thumb != 0); +} + +static const char * +list_get_id (void *vself) +{ + list_impl_t self = vself; + return self->id; +} + +static int +list_is_instance (void *vself __attribute__((unused)), const char *type) +{ + return (grub_strcmp (type, "component") == 0 + || grub_strcmp (type, "list") == 0); +} + +static struct grub_video_bitmap * +get_item_icon (list_impl_t self, int item_index) +{ + grub_menu_entry_t entry; + entry = grub_menu_get_entry (self->view->menu, item_index); + if (! entry) + return 0; + + return grub_gfxmenu_icon_manager_get_icon (self->icon_manager, entry); +} + +static void +make_selected_item_visible (list_impl_t self) +{ + int selected_index = self->view->selected; + if (selected_index < 0) + return; /* No item is selected. */ + int num_shown_items = get_num_shown_items (self); + int last_shown_index = self->first_shown_index + (num_shown_items - 1); + if (selected_index < self->first_shown_index) + self->first_shown_index = selected_index; + else if (selected_index > last_shown_index) + self->first_shown_index = selected_index - (num_shown_items - 1); +} + +/* Draw a scrollbar on the menu. */ +static void +draw_scrollbar (list_impl_t self, + int value, int extent, int min, int max, + int rightx, int topy, int height) +{ + grub_gfxmenu_box_t frame = self->scrollbar_frame; + grub_gfxmenu_box_t thumb = self->scrollbar_thumb; + int frame_vertical_pad = (frame->get_top_pad (frame) + + frame->get_bottom_pad (frame)); + int frame_horizontal_pad = (frame->get_left_pad (frame) + + frame->get_right_pad (frame)); + int tracktop = topy + frame->get_top_pad (frame); + int tracklen = height - frame_vertical_pad; + frame->set_content_size (frame, self->scrollbar_width, tracklen); + int thumby = tracktop + tracklen * (value - min) / (max - min); + int thumbheight = tracklen * extent / (max - min) + 1; + thumb->set_content_size (thumb, + self->scrollbar_width - frame_horizontal_pad, + thumbheight - (thumb->get_top_pad (thumb) + + thumb->get_bottom_pad (thumb))); + frame->draw (frame, + rightx - (self->scrollbar_width + frame_horizontal_pad), + topy); + thumb->draw (thumb, + rightx - (self->scrollbar_width - frame->get_right_pad (frame)), + thumby); +} + +/* Draw the list of items. */ +static void +draw_menu (list_impl_t self, int width, int drawing_scrollbar, + int num_shown_items) +{ + if (! self->menu_box || ! self->selected_item_box) + return; + + int boxpad = self->item_padding; + int icon_text_space = self->item_icon_space; + int item_vspace = self->item_spacing; + + int ascent = grub_font_get_ascent (self->item_font); + int descent = grub_font_get_descent (self->item_font); + int item_height = self->item_height; + + 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; + int item_left = boxpad + sel_leftpad; + int menu_index; + int visible_index; + + for (visible_index = 0, menu_index = self->first_shown_index; + visible_index < num_shown_items && menu_index < self->view->menu->size; + visible_index++, menu_index++) + { + int is_selected = (menu_index == self->view->selected); + + 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, + item_top - sel_toppad); + } + + struct grub_video_bitmap *icon; + if ((icon = get_item_icon (self, menu_index)) != 0) + grub_video_blit_bitmap (icon, GRUB_VIDEO_BLIT_BLEND, + item_left, + item_top + (item_height - self->icon_height) / 2, + 0, 0, self->icon_width, self->icon_height); + + const char *item_title = + grub_menu_get_entry (self->view->menu, menu_index)->title; + grub_font_t font = + (is_selected && self->selected_item_font + ? self->selected_item_font + : self->item_font); + grub_gui_color_t text_color = + ((is_selected && self->selected_item_color_set) + ? self->selected_item_color + : self->item_color); + grub_font_draw_string (item_title, + font, + grub_gui_map_color (text_color), + item_left + self->icon_width + icon_text_space, + (item_top + (item_height - (ascent + descent)) + / 2 + ascent)); + + item_top += item_height + item_vspace; + } +} + +static void +list_paint (void *vself, const grub_video_rect_t *region) +{ + list_impl_t self = vself; + grub_video_rect_t vpsave; + + if (! self->visible) + return; + if (!grub_video_have_common_points (region, &self->bounds)) + return; + + check_boxes (self); + + if (! self->menu_box || ! self->selected_item_box) + return; + + grub_gui_set_viewport (&self->bounds, &vpsave); + { + grub_gfxmenu_box_t box = self->menu_box; + int box_left_pad = box->get_left_pad (box); + int box_top_pad = box->get_top_pad (box); + int box_right_pad = box->get_right_pad (box); + int box_bottom_pad = box->get_bottom_pad (box); + grub_video_rect_t vpsave2, content_rect; + int num_shown_items = get_num_shown_items (self); + int drawing_scrollbar = (self->draw_scrollbar + && (num_shown_items < self->view->menu->size) + && check_scrollbar (self)); + + content_rect.x = box_left_pad; + content_rect.y = box_top_pad; + content_rect.width = self->bounds.width - box_left_pad - box_right_pad; + content_rect.height = self->bounds.height - box_top_pad - box_bottom_pad; + + box->set_content_size (box, content_rect.width, content_rect.height); + + box->draw (box, 0, 0); + + grub_gui_set_viewport (&content_rect, &vpsave2); + draw_menu (self, content_rect.width, drawing_scrollbar, num_shown_items); + grub_gui_restore_viewport (&vpsave2); + + if (drawing_scrollbar) + draw_scrollbar (self, + self->first_shown_index, num_shown_items, + 0, self->view->menu->size, + self->bounds.width - box_right_pad + + self->scrollbar_width, + box_top_pad + self->item_padding, + self->bounds.height - box_top_pad - box_bottom_pad); + } + + grub_gui_restore_viewport (&vpsave); +} + +static void +list_set_parent (void *vself, grub_gui_container_t parent) +{ + list_impl_t self = vself; + self->parent = parent; +} + +static grub_gui_container_t +list_get_parent (void *vself) +{ + list_impl_t self = vself; + return self->parent; +} + +static void +list_set_bounds (void *vself, const grub_video_rect_t *bounds) +{ + list_impl_t self = vself; + self->bounds = *bounds; +} + +static void +list_get_bounds (void *vself, grub_video_rect_t *bounds) +{ + list_impl_t self = vself; + *bounds = self->bounds; +} + +static void +list_get_minimal_size (void *vself, unsigned *width, unsigned *height) +{ + list_impl_t self = vself; + + if (check_boxes (self)) + { + int boxpad = self->item_padding; + int item_vspace = self->item_spacing; + int item_height = self->item_height; + int num_items = 3; + + grub_gfxmenu_box_t box = self->menu_box; + int box_left_pad = box->get_left_pad (box); + int box_top_pad = box->get_top_pad (box); + int box_right_pad = box->get_right_pad (box); + int box_bottom_pad = box->get_bottom_pad (box); + unsigned width_s; + + *width = grub_font_get_string_width (self->item_font, "Typical OS"); + width_s = grub_font_get_string_width (self->selected_item_font, + "Typical OS"); + if (*width < width_s) + *width = width_s; + + *width += 2 * boxpad + box_left_pad + box_right_pad; + + /* Set the menu box height to fit the items. */ + *height = (item_height * num_items + + item_vspace * (num_items - 1) + + 2 * boxpad + + box_top_pad + box_bottom_pad); + } + else + { + *width = 0; + *height = 0; + } +} + +static grub_err_t +list_set_property (void *vself, const char *name, const char *value) +{ + list_impl_t self = vself; + if (grub_strcmp (name, "item_font") == 0) + { + self->item_font = grub_font_get (value); + } + else if (grub_strcmp (name, "selected_item_font") == 0) + { + if (! value || grub_strcmp (value, "inherit") == 0) + self->selected_item_font = 0; + else + self->selected_item_font = grub_font_get (value); + } + else if (grub_strcmp (name, "item_color") == 0) + { + grub_gui_parse_color (value, &self->item_color); + } + else if (grub_strcmp (name, "selected_item_color") == 0) + { + if (! value || grub_strcmp (value, "inherit") == 0) + { + self->selected_item_color_set = 0; + } + else + { + if (grub_gui_parse_color (value, &self->selected_item_color) + == GRUB_ERR_NONE) + self->selected_item_color_set = 1; + } + } + else if (grub_strcmp (name, "icon_width") == 0) + { + self->icon_width = grub_strtol (value, 0, 10); + grub_gfxmenu_icon_manager_set_icon_size (self->icon_manager, + self->icon_width, + self->icon_height); + } + else if (grub_strcmp (name, "icon_height") == 0) + { + self->icon_height = grub_strtol (value, 0, 10); + grub_gfxmenu_icon_manager_set_icon_size (self->icon_manager, + self->icon_width, + self->icon_height); + } + else if (grub_strcmp (name, "item_height") == 0) + { + self->item_height = grub_strtol (value, 0, 10); + } + else if (grub_strcmp (name, "item_padding") == 0) + { + self->item_padding = grub_strtol (value, 0, 10); + } + else if (grub_strcmp (name, "item_icon_space") == 0) + { + self->item_icon_space = grub_strtol (value, 0, 10); + } + else if (grub_strcmp (name, "item_spacing") == 0) + { + self->item_spacing = grub_strtol (value, 0, 10); + } + else if (grub_strcmp (name, "visible") == 0) + { + self->visible = grub_strcmp (value, "false") != 0; + } + else if (grub_strcmp (name, "menu_pixmap_style") == 0) + { + self->need_to_recreate_boxes = 1; + grub_free (self->menu_box_pattern); + self->menu_box_pattern = value ? grub_strdup (value) : 0; + } + else if (grub_strcmp (name, "selected_item_pixmap_style") == 0) + { + self->need_to_recreate_boxes = 1; + grub_free (self->selected_item_box_pattern); + self->selected_item_box_pattern = value ? grub_strdup (value) : 0; + } + else if (grub_strcmp (name, "scrollbar_frame") == 0) + { + self->need_to_recreate_scrollbar = 1; + grub_free (self->scrollbar_frame_pattern); + self->scrollbar_frame_pattern = value ? grub_strdup (value) : 0; + } + else if (grub_strcmp (name, "scrollbar_thumb") == 0) + { + self->need_to_recreate_scrollbar = 1; + grub_free (self->scrollbar_thumb_pattern); + self->scrollbar_thumb_pattern = value ? grub_strdup (value) : 0; + } + else if (grub_strcmp (name, "scrollbar_width") == 0) + { + self->scrollbar_width = grub_strtol (value, 0, 10); + } + else if (grub_strcmp (name, "scrollbar") == 0) + { + self->draw_scrollbar = grub_strcmp (value, "false") != 0; + } + else if (grub_strcmp (name, "theme_dir") == 0) + { + self->need_to_recreate_boxes = 1; + grub_free (self->theme_dir); + self->theme_dir = value ? grub_strdup (value) : 0; + } + else if (grub_strcmp (name, "id") == 0) + { + grub_free (self->id); + if (value) + self->id = grub_strdup (value); + else + self->id = 0; + } + return grub_errno; +} + +/* Set necessary information that the gfxmenu view provides. */ +static void +list_set_view_info (void *vself, + grub_gfxmenu_view_t view) +{ + list_impl_t self = vself; + grub_gfxmenu_icon_manager_set_theme_path (self->icon_manager, + view->theme_path); + self->view = view; +} + +static struct grub_gui_component_ops list_comp_ops = + { + .destroy = list_destroy, + .get_id = list_get_id, + .is_instance = list_is_instance, + .paint = list_paint, + .set_parent = list_set_parent, + .get_parent = list_get_parent, + .set_bounds = list_set_bounds, + .get_bounds = list_get_bounds, + .get_minimal_size = list_get_minimal_size, + .set_property = list_set_property + }; + +static struct grub_gui_list_ops list_ops = +{ + .set_view_info = list_set_view_info +}; + +grub_gui_component_t +grub_gui_list_new (void) +{ + list_impl_t self; + grub_font_t default_font; + grub_gui_color_t default_fg_color; + grub_gui_color_t default_bg_color; + + self = grub_zalloc (sizeof (*self)); + if (! self) + return 0; + + self->list.ops = &list_ops; + self->list.component.ops = &list_comp_ops; + + self->visible = 1; + + default_font = grub_font_get ("Unknown Regular 16"); + default_fg_color = grub_gui_color_rgb (0, 0, 0); + default_bg_color = grub_gui_color_rgb (255, 255, 255); + + self->icon_width = 32; + self->icon_height = 32; + self->item_height = 42; + self->item_padding = 14; + self->item_icon_space = 4; + self->item_spacing = 16; + self->item_font = default_font; + self->selected_item_font = 0; /* Default to using the item_font. */ + self->item_color = default_fg_color; + self->selected_item_color_set = 0; /* Default to using the item_color. */ + self->selected_item_color = default_fg_color; + + self->draw_scrollbar = 1; + self->need_to_recreate_scrollbar = 1; + self->scrollbar_frame = 0; + self->scrollbar_thumb = 0; + self->scrollbar_frame_pattern = 0; + self->scrollbar_thumb_pattern = 0; + self->scrollbar_width = 16; + + self->first_shown_index = 0; + + self->need_to_recreate_boxes = 0; + self->theme_dir = 0; + self->menu_box_pattern = 0; + self->selected_item_box_pattern = 0; + self->menu_box = grub_gfxmenu_create_box (0, 0); + self->selected_item_box = grub_gfxmenu_create_box (0, 0); + + self->icon_manager = grub_gfxmenu_icon_manager_new (); + if (! self->icon_manager) + { + self->list.component.ops->destroy (self); + return 0; + } + grub_gfxmenu_icon_manager_set_icon_size (self->icon_manager, + self->icon_width, + self->icon_height); + return (grub_gui_component_t) self; +} diff --git a/gfxmenu/gui_progress_bar.c b/gfxmenu/gui_progress_bar.c new file mode 100644 index 000000000..d786aae31 --- /dev/null +++ b/gfxmenu/gui_progress_bar.c @@ -0,0 +1,384 @@ +/* gui_progress_bar.c - GUI progress bar component. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct grub_gui_progress_bar +{ + struct grub_gui_progress progress; + + grub_gui_container_t parent; + grub_video_rect_t bounds; + char *id; + int visible; + int start; + int end; + int value; + int show_text; + char *template; + grub_font_t font; + grub_gui_color_t text_color; + grub_gui_color_t border_color; + grub_gui_color_t bg_color; + grub_gui_color_t fg_color; + + char *theme_dir; + int need_to_recreate_pixmaps; + int pixmapbar_available; + char *bar_pattern; + char *highlight_pattern; + grub_gfxmenu_box_t bar_box; + grub_gfxmenu_box_t highlight_box; +}; + +typedef struct grub_gui_progress_bar *grub_gui_progress_bar_t; + +static void +progress_bar_destroy (void *vself) +{ + grub_gui_progress_bar_t self = vself; + grub_free (self); +} + +static const char * +progress_bar_get_id (void *vself) +{ + grub_gui_progress_bar_t self = vself; + return self->id; +} + +static int +progress_bar_is_instance (void *vself __attribute__((unused)), const char *type) +{ + return grub_strcmp (type, "component") == 0; +} + +static int +check_pixmaps (grub_gui_progress_bar_t self) +{ + if (!self->pixmapbar_available) + return 0; + if (self->need_to_recreate_pixmaps) + { + grub_gui_recreate_box (&self->bar_box, + self->bar_pattern, + self->theme_dir); + + grub_gui_recreate_box (&self->highlight_box, + self->highlight_pattern, + self->theme_dir); + + self->need_to_recreate_pixmaps = 0; + } + + return (self->bar_box != 0 && self->highlight_box != 0); +} + +static void +draw_filled_rect_bar (grub_gui_progress_bar_t self) +{ + /* Set the progress bar's frame. */ + grub_video_rect_t f; + f.x = 1; + f.y = 1; + f.width = self->bounds.width - 2; + f.height = self->bounds.height - 2; + + /* Border. */ + grub_video_fill_rect (grub_gui_map_color (self->border_color), + f.x - 1, f.y - 1, + f.width + 2, f.height + 2); + + /* Bar background. */ + int barwidth = (f.width + * (self->value - self->start) + / (self->end - self->start)); + grub_video_fill_rect (grub_gui_map_color (self->bg_color), + f.x + barwidth, f.y, + f.width - barwidth, f.height); + + /* Bar foreground. */ + grub_video_fill_rect (grub_gui_map_color (self->fg_color), + f.x, f.y, + barwidth, f.height); +} + +static void +draw_pixmap_bar (grub_gui_progress_bar_t self) +{ + grub_gfxmenu_box_t bar = self->bar_box; + grub_gfxmenu_box_t hl = self->highlight_box; + int w = self->bounds.width; + int h = self->bounds.height; + int bar_l_pad = bar->get_left_pad (bar); + int bar_r_pad = bar->get_right_pad (bar); + int bar_t_pad = bar->get_top_pad (bar); + int bar_b_pad = bar->get_bottom_pad (bar); + int bar_h_pad = bar_l_pad + bar_r_pad; + int bar_v_pad = bar_t_pad + bar_b_pad; + int tracklen = w - bar_h_pad; + int trackheight = h - bar_v_pad; + int barwidth; + + bar->set_content_size (bar, tracklen, trackheight); + + barwidth = (tracklen * (self->value - self->start) + / (self->end - self->start)); + + hl->set_content_size (hl, barwidth, h - bar_v_pad); + + bar->draw (bar, 0, 0); + hl->draw (hl, bar_l_pad, bar_t_pad); +} + +static void +draw_text (grub_gui_progress_bar_t self) +{ + if (self->template) + { + grub_font_t font = self->font; + grub_video_color_t text_color = grub_gui_map_color (self->text_color); + int width = self->bounds.width; + int height = self->bounds.height; + char *text; + text = grub_xasprintf (self->template, + self->value > 0 ? self->value : -self->value); + if (!text) + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + return; + } + /* Center the text. */ + int text_width = grub_font_get_string_width (font, text); + int x = (width - text_width) / 2; + int y = ((height - grub_font_get_descent (font)) / 2 + + grub_font_get_ascent (font) / 2); + grub_font_draw_string (text, font, text_color, x, y); + } +} + +static void +progress_bar_paint (void *vself, const grub_video_rect_t *region) +{ + grub_gui_progress_bar_t self = vself; + grub_video_rect_t vpsave; + + if (! self->visible) + return; + if (!grub_video_have_common_points (region, &self->bounds)) + return; + + if (self->end == self->start) + return; + + grub_gui_set_viewport (&self->bounds, &vpsave); + + if (check_pixmaps (self)) + draw_pixmap_bar (self); + else + draw_filled_rect_bar (self); + + draw_text (self); + + grub_gui_restore_viewport (&vpsave); +} + +static void +progress_bar_set_parent (void *vself, grub_gui_container_t parent) +{ + grub_gui_progress_bar_t self = vself; + self->parent = parent; +} + +static grub_gui_container_t +progress_bar_get_parent (void *vself) +{ + grub_gui_progress_bar_t self = vself; + return self->parent; +} + +static void +progress_bar_set_bounds (void *vself, const grub_video_rect_t *bounds) +{ + grub_gui_progress_bar_t self = vself; + self->bounds = *bounds; +} + +static void +progress_bar_get_bounds (void *vself, grub_video_rect_t *bounds) +{ + grub_gui_progress_bar_t self = vself; + *bounds = self->bounds; +} + +static void +progress_bar_get_minimal_size (void *vself, + unsigned *width, unsigned *height) +{ + unsigned text_width = 0, text_height = 0; + grub_gui_progress_bar_t self = vself; + + if (self->template) + { + text_width = grub_font_get_string_width (self->font, self->template); + text_width += grub_font_get_string_width (self->font, "XXXXXXXXXX"); + text_height = grub_font_get_descent (self->font) + + grub_font_get_ascent (self->font); + } + *width = 200; + if (*width < text_width) + *width = text_width; + *height = 28; + if (*height < text_height) + *height = text_height; +} + +static void +progress_bar_set_state (void *vself, int visible, int start, + int current, int end) +{ + grub_gui_progress_bar_t self = vself; + self->visible = visible; + self->start = start; + self->value = current; + self->end = end; +} + +static grub_err_t +progress_bar_set_property (void *vself, const char *name, const char *value) +{ + grub_gui_progress_bar_t self = vself; + if (grub_strcmp (name, "text") == 0) + { + grub_free (self->template); + if (grub_strcmp (value, "@TIMEOUT_NOTIFICATION_LONG@") == 0) + value + = _("The highlighted entry will be executed automatically in %ds."); + else if (grub_strcmp (value, "@TIMEOUT_NOTIFICATION_MIDDLE@") == 0) + /* TRANSLATORS: 's' stands for seconds. + It's a standalone timeout notification. + Please use the short form in your language. */ + value = _("%ds remaining."); + else if (grub_strcmp (value, "@TIMEOUT_NOTIFICATION_SHORT@") == 0) + /* TRANSLATORS: 's' stands for seconds. + It's a standalone timeout notification. + Please use the shortest form available in you language. */ + value = _("%ds"); + + self->template = grub_strdup (value); + } + else if (grub_strcmp (name, "font") == 0) + { + self->font = grub_font_get (value); + } + else if (grub_strcmp (name, "text_color") == 0) + { + grub_gui_parse_color (value, &self->text_color); + } + else if (grub_strcmp (name, "border_color") == 0) + { + grub_gui_parse_color (value, &self->border_color); + } + else if (grub_strcmp (name, "bg_color") == 0) + { + grub_gui_parse_color (value, &self->bg_color); + } + else if (grub_strcmp (name, "fg_color") == 0) + { + grub_gui_parse_color (value, &self->fg_color); + } + else if (grub_strcmp (name, "bar_style") == 0) + { + self->need_to_recreate_pixmaps = 1; + self->pixmapbar_available = 1; + grub_free (self->bar_pattern); + self->bar_pattern = value ? grub_strdup (value) : 0; + } + else if (grub_strcmp (name, "highlight_style") == 0) + { + self->need_to_recreate_pixmaps = 1; + self->pixmapbar_available = 1; + grub_free (self->highlight_pattern); + self->highlight_pattern = value ? grub_strdup (value) : 0; + } + else if (grub_strcmp (name, "theme_dir") == 0) + { + self->need_to_recreate_pixmaps = 1; + grub_free (self->theme_dir); + self->theme_dir = value ? grub_strdup (value) : 0; + } + else if (grub_strcmp (name, "id") == 0) + { + grub_free (self->id); + if (value) + self->id = grub_strdup (value); + else + self->id = 0; + } + return grub_errno; +} + +static struct grub_gui_component_ops progress_bar_ops = +{ + .destroy = progress_bar_destroy, + .get_id = progress_bar_get_id, + .is_instance = progress_bar_is_instance, + .paint = progress_bar_paint, + .set_parent = progress_bar_set_parent, + .get_parent = progress_bar_get_parent, + .set_bounds = progress_bar_set_bounds, + .get_bounds = progress_bar_get_bounds, + .get_minimal_size = progress_bar_get_minimal_size, + .set_property = progress_bar_set_property +}; + +static struct grub_gui_progress_ops progress_bar_pb_ops = + { + .set_state = progress_bar_set_state + }; + +grub_gui_component_t +grub_gui_progress_bar_new (void) +{ + grub_gui_progress_bar_t self; + self = grub_zalloc (sizeof (*self)); + if (! self) + return 0; + self->progress.ops = &progress_bar_pb_ops; + self->progress.component.ops = &progress_bar_ops; + self->visible = 1; + self->font = grub_font_get ("Unknown Regular 16"); + grub_gui_color_t black = { .red = 0, .green = 0, .blue = 0, .alpha = 255 }; + grub_gui_color_t gray = { .red = 128, .green = 128, .blue = 128, .alpha = 255 }; + grub_gui_color_t lightgray = { .red = 200, .green = 200, .blue = 200, .alpha = 255 }; + self->text_color = black; + self->border_color = black; + self->bg_color = gray; + self->fg_color = lightgray; + + return (grub_gui_component_t) self; +} diff --git a/gfxmenu/gui_string_util.c b/gfxmenu/gui_string_util.c new file mode 100644 index 000000000..8c51e396a --- /dev/null +++ b/gfxmenu/gui_string_util.c @@ -0,0 +1,327 @@ +/* gui_string_util.c - String utilities used by the GUI system. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include + +/* Create a new NUL-terminated string on the heap as a substring of BUF. + The range of buf included is the half-open interval [START,END). + The index START is inclusive, END is exclusive. */ +char * +grub_new_substring (const char *buf, + grub_size_t start, grub_size_t end) +{ + if (end < start) + return 0; + grub_size_t len = end - start; + char *s = grub_malloc (len + 1); + if (! s) + return 0; + grub_memcpy (s, buf + start, len); + s[len] = '\0'; + return s; +} + +/* Eliminate "." and ".." path elements from PATH. A new heap-allocated + string is returned. */ +static char * +canonicalize_path (const char *path) +{ + int i; + const char *p; + char *newpath = 0; + + /* Count the path components in path. */ + int components = 1; + for (p = path; *p; p++) + if (*p == '/') + components++; + + char **path_array = grub_malloc (components * sizeof (*path_array)); + if (! path_array) + return 0; + + /* Initialize array elements to NULL pointers; in case once of the + allocations fails, the cleanup code can just call grub_free() for all + pointers in the array. */ + for (i = 0; i < components; i++) + path_array[i] = 0; + + /* Parse the path into path_array. */ + p = path; + for (i = 0; i < components && p; i++) + { + /* Find the end of the path element. */ + const char *end = grub_strchr (p, '/'); + if (!end) + end = p + grub_strlen (p); + + /* Copy the element. */ + path_array[i] = grub_new_substring (p, 0, end - p); + if (! path_array[i]) + goto cleanup; + + /* Advance p to point to the start of the next element, or NULL. */ + if (*end) + p = end + 1; + else + p = 0; + } + + /* Eliminate '.' and '..' elements from the path array. */ + int newpath_length = 0; + for (i = components - 1; i >= 0; --i) + { + if (! grub_strcmp (path_array[i], ".")) + { + grub_free (path_array[i]); + path_array[i] = 0; + } + else if (! grub_strcmp (path_array[i], "..") + && i > 0) + { + /* Delete the '..' and the prior path element. */ + grub_free (path_array[i]); + path_array[i] = 0; + --i; + grub_free (path_array[i]); + path_array[i] = 0; + } + else + { + newpath_length += grub_strlen (path_array[i]) + 1; + } + } + + /* Construct a new path string. */ + newpath = grub_malloc (newpath_length + 1); + if (! newpath) + goto cleanup; + + newpath[0] = '\0'; + char *newpath_end = newpath; + int first = 1; + for (i = 0; i < components; i++) + { + char *element = path_array[i]; + if (element) + { + /* For all components but the first, prefix with a slash. */ + if (! first) + newpath_end = grub_stpcpy (newpath_end, "/"); + newpath_end = grub_stpcpy (newpath_end, element); + first = 0; + } + } + +cleanup: + for (i = 0; i < components; i++) + grub_free (path_array[i]); + grub_free (path_array); + + return newpath; +} + +/* Return a new heap-allocated string representing to absolute path + to the file referred to by PATH. If PATH is an absolute path, then + the returned path is a copy of PATH. If PATH is a relative path, then + BASE is with PATH used to construct the absolute path. */ +char * +grub_resolve_relative_path (const char *base, const char *path) +{ + char *abspath; + char *canonpath; + char *p; + grub_size_t l; + + /* If PATH is an absolute path, then just use it as is. */ + if (path[0] == '/' || path[0] == '(') + return canonicalize_path (path); + + abspath = grub_malloc (grub_strlen (base) + grub_strlen (path) + 3); + if (! abspath) + return 0; + + /* Concatenate BASE and PATH. */ + p = grub_stpcpy (abspath, base); + l = grub_strlen (abspath); + if (l == 0 || abspath[l-1] != '/') + { + *p = '/'; + p++; + *p = 0; + } + grub_stpcpy (p, path); + + canonpath = canonicalize_path (abspath); + if (! canonpath) + return abspath; + + grub_free (abspath); + return canonpath; +} + +/* Get the path of the directory where the file at FILE_PATH is located. + FILE_PATH should refer to a file, not a directory. The returned path + includes a trailing slash. + This does not handle GRUB "(hd0,0)" paths properly yet since it only + looks at slashes. */ +char * +grub_get_dirname (const char *file_path) +{ + int i; + int last_slash; + + last_slash = -1; + for (i = grub_strlen (file_path) - 1; i >= 0; --i) + { + if (file_path[i] == '/') + { + last_slash = i; + break; + } + } + if (last_slash == -1) + return grub_strdup ("/"); + + return grub_new_substring (file_path, 0, last_slash + 1); +} + +static __inline int +my_isxdigit (char c) +{ + return ((c >= '0' && c <= '9') + || (c >= 'a' && c <= 'f') + || (c >= 'A' && c <= 'F')); +} + +static int +parse_hex_color_component (const char *s, unsigned start, unsigned end) +{ + unsigned len; + char buf[3]; + + len = end - start; + /* Check the limits so we don't overrun the buffer. */ + if (len < 1 || len > 2) + return 0; + + if (len == 1) + { + buf[0] = s[start]; /* Get the first and only hex digit. */ + buf[1] = buf[0]; /* Duplicate the hex digit. */ + } + else if (len == 2) + { + buf[0] = s[start]; + buf[1] = s[start + 1]; + } + + buf[2] = '\0'; + + return grub_strtoul (buf, 0, 16); +} + +/* Parse a color string of the form "r, g, b", "#RGB", "#RGBA", + "#RRGGBB", or "#RRGGBBAA". */ +grub_err_t +grub_gui_parse_color (const char *s, grub_gui_color_t *color) +{ + grub_gui_color_t c; + + /* Skip whitespace. */ + while (*s && grub_isspace (*s)) + s++; + + if (*s == '#') + { + /* HTML-style. Number if hex digits: + [6] #RRGGBB [3] #RGB + [8] #RRGGBBAA [4] #RGBA */ + + s++; /* Skip the '#'. */ + /* Count the hexits to determine the format. */ + int hexits = 0; + const char *end = s; + while (my_isxdigit (*end)) + { + end++; + hexits++; + } + + /* Parse the color components based on the format. */ + if (hexits == 3 || hexits == 4) + { + c.red = parse_hex_color_component (s, 0, 1); + c.green = parse_hex_color_component (s, 1, 2); + c.blue = parse_hex_color_component (s, 2, 3); + if (hexits == 4) + c.alpha = parse_hex_color_component (s, 3, 4); + else + c.alpha = 255; + } + else if (hexits == 6 || hexits == 8) + { + c.red = parse_hex_color_component (s, 0, 2); + c.green = parse_hex_color_component (s, 2, 4); + c.blue = parse_hex_color_component (s, 4, 6); + if (hexits == 8) + c.alpha = parse_hex_color_component (s, 6, 8); + else + c.alpha = 255; + } + else + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "invalid HTML-type color string `%s'", s); + } + else if (grub_isdigit (*s)) + { + /* Comma separated decimal values. */ + c.red = grub_strtoul (s, 0, 0); + if ((s = grub_strchr (s, ',')) == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "missing 1st comma separator in color `%s'", s); + s++; + c.green = grub_strtoul (s, 0, 0); + if ((s = grub_strchr (s, ',')) == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "missing 2nd comma separator in color `%s'", s); + s++; + c.blue = grub_strtoul (s, 0, 0); + if ((s = grub_strchr (s, ',')) == 0) + c.alpha = 255; + else + { + s++; + c.alpha = grub_strtoul (s, 0, 0); + } + } + else + { + if (! grub_gui_get_named_color (s, &c)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "invalid named color `%s'", s); + } + + if (grub_errno == GRUB_ERR_NONE) + *color = c; + return grub_errno; +} diff --git a/gfxmenu/gui_util.c b/gfxmenu/gui_util.c new file mode 100644 index 000000000..eba7bb39e --- /dev/null +++ b/gfxmenu/gui_util.c @@ -0,0 +1,101 @@ +/* gui_util.c - GUI utility functions. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include + + +struct find_by_id_state +{ + const char *match_id; + grub_gui_component_callback match_callback; + void *match_userdata; +}; + +static void +find_by_id_recursively (grub_gui_component_t component, void *userdata) +{ + struct find_by_id_state *state; + const char *id; + + state = (struct find_by_id_state *) userdata; + id = component->ops->get_id (component); + if (id && grub_strcmp (id, state->match_id) == 0) + state->match_callback (component, state->match_userdata); + + if (component->ops->is_instance (component, "container")) + { + grub_gui_container_t container; + container = (grub_gui_container_t) component; + container->ops->iterate_children (container, + find_by_id_recursively, + state); + } +} + +void +grub_gui_find_by_id (grub_gui_component_t root, + const char *id, + grub_gui_component_callback cb, + void *userdata) +{ + struct find_by_id_state state; + state.match_id = id; + state.match_callback = cb; + state.match_userdata = userdata; + find_by_id_recursively (root, &state); +} + + +struct iterate_recursively_state +{ + grub_gui_component_callback callback; + void *userdata; +}; + +static +void iterate_recursively_cb (grub_gui_component_t component, void *userdata) +{ + struct iterate_recursively_state *state; + + state = (struct iterate_recursively_state *) userdata; + state->callback (component, state->userdata); + + if (component->ops->is_instance (component, "container")) + { + grub_gui_container_t container; + container = (grub_gui_container_t) component; + container->ops->iterate_children (container, + iterate_recursively_cb, + state); + } +} + +void +grub_gui_iterate_recursively (grub_gui_component_t root, + grub_gui_component_callback cb, + void *userdata) +{ + struct iterate_recursively_state state; + state.callback = cb; + state.userdata = userdata; + iterate_recursively_cb (root, &state); +} diff --git a/gfxmenu/icon_manager.c b/gfxmenu/icon_manager.c new file mode 100644 index 000000000..0c304ede0 --- /dev/null +++ b/gfxmenu/icon_manager.c @@ -0,0 +1,263 @@ +/* icon_manager.c - gfxmenu icon manager. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Currently hard coded to '.png' extension. */ +static const char icon_extension[] = ".png"; + +typedef struct icon_entry +{ + char *class_name; + struct grub_video_bitmap *bitmap; + struct icon_entry *next; +} *icon_entry_t; + +struct grub_gfxmenu_icon_manager +{ + char *theme_path; + int icon_width; + int icon_height; + + /* Icon cache: linked list w/ dummy head node. */ + struct icon_entry cache; +}; + + +/* Create a new icon manager and return a point to it. */ +grub_gfxmenu_icon_manager_t +grub_gfxmenu_icon_manager_new (void) +{ + grub_gfxmenu_icon_manager_t mgr; + mgr = grub_malloc (sizeof (*mgr)); + if (! mgr) + return 0; + + mgr->theme_path = 0; + mgr->icon_width = 0; + mgr->icon_height = 0; + + /* Initialize the dummy head node. */ + mgr->cache.class_name = 0; + mgr->cache.bitmap = 0; + mgr->cache.next = 0; + + return mgr; +} + +/* Destroy the icon manager MGR, freeing all resources used by it. + +Note: Any bitmaps returned by grub_gfxmenu_icon_manager_get_icon() +are destroyed and must not be used by the caller after this function +is called. */ +void +grub_gfxmenu_icon_manager_destroy (grub_gfxmenu_icon_manager_t mgr) +{ + grub_gfxmenu_icon_manager_clear_cache (mgr); + grub_free (mgr->theme_path); + grub_free (mgr); +} + +/* Clear the icon cache. */ +void +grub_gfxmenu_icon_manager_clear_cache (grub_gfxmenu_icon_manager_t mgr) +{ + icon_entry_t cur; + icon_entry_t next; + for (cur = mgr->cache.next; cur; cur = next) + { + next = cur->next; + grub_free (cur->class_name); + grub_video_bitmap_destroy (cur->bitmap); + grub_free (cur); + } + mgr->cache.next = 0; +} + +/* Set the theme path. If the theme path is changed, the icon cache + is cleared. */ +void +grub_gfxmenu_icon_manager_set_theme_path (grub_gfxmenu_icon_manager_t mgr, + const char *path) +{ + /* Clear the cache if the theme path has changed. */ + if (((mgr->theme_path == 0) != (path == 0)) + || (grub_strcmp (mgr->theme_path, path) != 0)) + grub_gfxmenu_icon_manager_clear_cache (mgr); + + grub_free (mgr->theme_path); + mgr->theme_path = path ? grub_strdup (path) : 0; +} + +/* Set the icon size. When icons are requested from the icon manager, + they are scaled to this size before being returned. If the size is + changed, the icon cache is cleared. */ +void +grub_gfxmenu_icon_manager_set_icon_size (grub_gfxmenu_icon_manager_t mgr, + int width, int height) +{ + /* If the width or height is changed, we must clear the cache, since the + scaled bitmaps are stored in the cache. */ + if (width != mgr->icon_width || height != mgr->icon_height) + grub_gfxmenu_icon_manager_clear_cache (mgr); + + mgr->icon_width = width; + mgr->icon_height = height; +} + +/* Try to load an icon for the specified CLASS_NAME in the directory DIR. + Returns 0 if the icon could not be loaded, or returns a pointer to a new + bitmap if it was successful. */ +static struct grub_video_bitmap * +try_loading_icon (grub_gfxmenu_icon_manager_t mgr, + const char *dir, const char *class_name) +{ + char *path; + int l; + + path = grub_malloc (grub_strlen (dir) + grub_strlen (class_name) + + grub_strlen (icon_extension) + 3); + if (! path) + return 0; + + grub_strcpy (path, dir); + l = grub_strlen (path); + if (path[l-1] != '/') + { + path[l] = '/'; + path[l+1] = 0; + } + grub_strcat (path, class_name); + grub_strcat (path, icon_extension); + + struct grub_video_bitmap *raw_bitmap; + grub_video_bitmap_load (&raw_bitmap, path); + grub_free (path); + grub_errno = GRUB_ERR_NONE; /* Critical to clear the error!! */ + if (! raw_bitmap) + return 0; + + struct grub_video_bitmap *scaled_bitmap; + grub_video_bitmap_create_scaled (&scaled_bitmap, + mgr->icon_width, mgr->icon_height, + raw_bitmap, + GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST); + grub_video_bitmap_destroy (raw_bitmap); + if (! scaled_bitmap) + { + grub_error_push (); + grub_error (grub_errno, "failed to scale icon"); + return 0; + } + + return scaled_bitmap; +} + +/* Get the icon for the specified class CLASS_NAME. If an icon for + CLASS_NAME already exists in the cache, then a reference to the cached + bitmap is returned. If it is not cached, then it is loaded and cached. + If no icon could be could for CLASS_NAME, then 0 is returned. */ +static struct grub_video_bitmap * +get_icon_by_class (grub_gfxmenu_icon_manager_t mgr, const char *class_name) +{ + /* First check the icon cache. */ + icon_entry_t entry; + for (entry = mgr->cache.next; entry; entry = entry->next) + { + if (grub_strcmp (entry->class_name, class_name) == 0) + return entry->bitmap; + } + + if (! mgr->theme_path) + return 0; + + /* Otherwise, we search for an icon to load. */ + char *theme_dir = grub_get_dirname (mgr->theme_path); + char *icons_dir; + struct grub_video_bitmap *icon; + icon = 0; + /* First try the theme's own icons, from "grub/themes/NAME/icons/" */ + icons_dir = grub_resolve_relative_path (theme_dir, "icons/"); + if (icons_dir) + { + icon = try_loading_icon (mgr, icons_dir, class_name); + grub_free (icons_dir); + } + + grub_free (theme_dir); + if (! icon) + { + const char *icondir; + + icondir = grub_env_get ("icondir"); + if (icondir) + icon = try_loading_icon (mgr, icondir, class_name); + } + + /* No icon was found. */ + /* This should probably be noted in the cache, so that a search is not + performed each time an icon for CLASS_NAME is requested. */ + if (! icon) + return 0; + + /* Insert a new cache entry for this icon. */ + entry = grub_malloc (sizeof (*entry)); + if (! entry) + { + grub_video_bitmap_destroy (icon); + return 0; + } + entry->class_name = grub_strdup (class_name); + entry->bitmap = icon; + entry->next = mgr->cache.next; + mgr->cache.next = entry; /* Link it into the cache. */ + return entry->bitmap; +} + +/* Get the best available icon for ENTRY. Beginning with the first class + listed in the menu entry and proceeding forward, an icon for each class + is searched for. The first icon found is returned. The returned icon + is scaled to the size specified by + grub_gfxmenu_icon_manager_set_icon_size(). + + Note: Bitmaps returned by this function are destroyed when the + icon manager is destroyed. + */ +struct grub_video_bitmap * +grub_gfxmenu_icon_manager_get_icon (grub_gfxmenu_icon_manager_t mgr, + grub_menu_entry_t entry) +{ + struct grub_menu_entry_class *c; + struct grub_video_bitmap *icon; + + /* Try each class in succession. */ + icon = 0; + for (c = entry->classes->next; c && ! icon; c = c->next) + icon = get_icon_by_class (mgr, c->name); + return icon; +} diff --git a/gfxmenu/model.c b/gfxmenu/model.c new file mode 100644 index 000000000..e69de29bb diff --git a/gfxmenu/named_colors.c b/gfxmenu/named_colors.c new file mode 100644 index 000000000..eedbc47fb --- /dev/null +++ b/gfxmenu/named_colors.c @@ -0,0 +1,209 @@ +/* named_colors.c - Named color values. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include + +struct named_color +{ + const char *name; + grub_gui_color_t color; +}; + +/* + Named color list generated from the list of SVG color keywords from + , + processed through the following Perl command: + perl -ne 'chomp;split;print "{ \"$_[0]\", RGB_COLOR($_[2]) },\n"' + */ + +#define RGB_COLOR(r,g,b) {.red = r, .green = g, .blue = b, .alpha = 255} + +static struct named_color named_colors[] = +{ + { "aliceblue", RGB_COLOR(240,248,255) }, + { "antiquewhite", RGB_COLOR(250,235,215) }, + { "aqua", RGB_COLOR(0,255,255) }, + { "aquamarine", RGB_COLOR(127,255,212) }, + { "azure", RGB_COLOR(240,255,255) }, + { "beige", RGB_COLOR(245,245,220) }, + { "bisque", RGB_COLOR(255,228,196) }, + { "black", RGB_COLOR(0,0,0) }, + { "blanchedalmond", RGB_COLOR(255,235,205) }, + { "blue", RGB_COLOR(0,0,255) }, + { "blueviolet", RGB_COLOR(138,43,226) }, + { "brown", RGB_COLOR(165,42,42) }, + { "burlywood", RGB_COLOR(222,184,135) }, + { "cadetblue", RGB_COLOR(95,158,160) }, + { "chartreuse", RGB_COLOR(127,255,0) }, + { "chocolate", RGB_COLOR(210,105,30) }, + { "coral", RGB_COLOR(255,127,80) }, + { "cornflowerblue", RGB_COLOR(100,149,237) }, + { "cornsilk", RGB_COLOR(255,248,220) }, + { "crimson", RGB_COLOR(220,20,60) }, + { "cyan", RGB_COLOR(0,255,255) }, + { "darkblue", RGB_COLOR(0,0,139) }, + { "darkcyan", RGB_COLOR(0,139,139) }, + { "darkgoldenrod", RGB_COLOR(184,134,11) }, + { "darkgray", RGB_COLOR(169,169,169) }, + { "darkgreen", RGB_COLOR(0,100,0) }, + { "darkgrey", RGB_COLOR(169,169,169) }, + { "darkkhaki", RGB_COLOR(189,183,107) }, + { "darkmagenta", RGB_COLOR(139,0,139) }, + { "darkolivegreen", RGB_COLOR(85,107,47) }, + { "darkorange", RGB_COLOR(255,140,0) }, + { "darkorchid", RGB_COLOR(153,50,204) }, + { "darkred", RGB_COLOR(139,0,0) }, + { "darksalmon", RGB_COLOR(233,150,122) }, + { "darkseagreen", RGB_COLOR(143,188,143) }, + { "darkslateblue", RGB_COLOR(72,61,139) }, + { "darkslategray", RGB_COLOR(47,79,79) }, + { "darkslategrey", RGB_COLOR(47,79,79) }, + { "darkturquoise", RGB_COLOR(0,206,209) }, + { "darkviolet", RGB_COLOR(148,0,211) }, + { "deeppink", RGB_COLOR(255,20,147) }, + { "deepskyblue", RGB_COLOR(0,191,255) }, + { "dimgray", RGB_COLOR(105,105,105) }, + { "dimgrey", RGB_COLOR(105,105,105) }, + { "dodgerblue", RGB_COLOR(30,144,255) }, + { "firebrick", RGB_COLOR(178,34,34) }, + { "floralwhite", RGB_COLOR(255,250,240) }, + { "forestgreen", RGB_COLOR(34,139,34) }, + { "fuchsia", RGB_COLOR(255,0,255) }, + { "gainsboro", RGB_COLOR(220,220,220) }, + { "ghostwhite", RGB_COLOR(248,248,255) }, + { "gold", RGB_COLOR(255,215,0) }, + { "goldenrod", RGB_COLOR(218,165,32) }, + { "gray", RGB_COLOR(128,128,128) }, + { "green", RGB_COLOR(0,128,0) }, + { "greenyellow", RGB_COLOR(173,255,47) }, + { "grey", RGB_COLOR(128,128,128) }, + { "honeydew", RGB_COLOR(240,255,240) }, + { "hotpink", RGB_COLOR(255,105,180) }, + { "indianred", RGB_COLOR(205,92,92) }, + { "indigo", RGB_COLOR(75,0,130) }, + { "ivory", RGB_COLOR(255,255,240) }, + { "khaki", RGB_COLOR(240,230,140) }, + { "lavender", RGB_COLOR(230,230,250) }, + { "lavenderblush", RGB_COLOR(255,240,245) }, + { "lawngreen", RGB_COLOR(124,252,0) }, + { "lemonchiffon", RGB_COLOR(255,250,205) }, + { "lightblue", RGB_COLOR(173,216,230) }, + { "lightcoral", RGB_COLOR(240,128,128) }, + { "lightcyan", RGB_COLOR(224,255,255) }, + { "lightgoldenrodyellow", RGB_COLOR(250,250,210) }, + { "lightgray", RGB_COLOR(211,211,211) }, + { "lightgreen", RGB_COLOR(144,238,144) }, + { "lightgrey", RGB_COLOR(211,211,211) }, + { "lightpink", RGB_COLOR(255,182,193) }, + { "lightsalmon", RGB_COLOR(255,160,122) }, + { "lightseagreen", RGB_COLOR(32,178,170) }, + { "lightskyblue", RGB_COLOR(135,206,250) }, + { "lightslategray", RGB_COLOR(119,136,153) }, + { "lightslategrey", RGB_COLOR(119,136,153) }, + { "lightsteelblue", RGB_COLOR(176,196,222) }, + { "lightyellow", RGB_COLOR(255,255,224) }, + { "lime", RGB_COLOR(0,255,0) }, + { "limegreen", RGB_COLOR(50,205,50) }, + { "linen", RGB_COLOR(250,240,230) }, + { "magenta", RGB_COLOR(255,0,255) }, + { "maroon", RGB_COLOR(128,0,0) }, + { "mediumaquamarine", RGB_COLOR(102,205,170) }, + { "mediumblue", RGB_COLOR(0,0,205) }, + { "mediumorchid", RGB_COLOR(186,85,211) }, + { "mediumpurple", RGB_COLOR(147,112,219) }, + { "mediumseagreen", RGB_COLOR(60,179,113) }, + { "mediumslateblue", RGB_COLOR(123,104,238) }, + { "mediumspringgreen", RGB_COLOR(0,250,154) }, + { "mediumturquoise", RGB_COLOR(72,209,204) }, + { "mediumvioletred", RGB_COLOR(199,21,133) }, + { "midnightblue", RGB_COLOR(25,25,112) }, + { "mintcream", RGB_COLOR(245,255,250) }, + { "mistyrose", RGB_COLOR(255,228,225) }, + { "moccasin", RGB_COLOR(255,228,181) }, + { "navajowhite", RGB_COLOR(255,222,173) }, + { "navy", RGB_COLOR(0,0,128) }, + { "oldlace", RGB_COLOR(253,245,230) }, + { "olive", RGB_COLOR(128,128,0) }, + { "olivedrab", RGB_COLOR(107,142,35) }, + { "orange", RGB_COLOR(255,165,0) }, + { "orangered", RGB_COLOR(255,69,0) }, + { "orchid", RGB_COLOR(218,112,214) }, + { "palegoldenrod", RGB_COLOR(238,232,170) }, + { "palegreen", RGB_COLOR(152,251,152) }, + { "paleturquoise", RGB_COLOR(175,238,238) }, + { "palevioletred", RGB_COLOR(219,112,147) }, + { "papayawhip", RGB_COLOR(255,239,213) }, + { "peachpuff", RGB_COLOR(255,218,185) }, + { "peru", RGB_COLOR(205,133,63) }, + { "pink", RGB_COLOR(255,192,203) }, + { "plum", RGB_COLOR(221,160,221) }, + { "powderblue", RGB_COLOR(176,224,230) }, + { "purple", RGB_COLOR(128,0,128) }, + { "red", RGB_COLOR(255,0,0) }, + { "rosybrown", RGB_COLOR(188,143,143) }, + { "royalblue", RGB_COLOR(65,105,225) }, + { "saddlebrown", RGB_COLOR(139,69,19) }, + { "salmon", RGB_COLOR(250,128,114) }, + { "sandybrown", RGB_COLOR(244,164,96) }, + { "seagreen", RGB_COLOR(46,139,87) }, + { "seashell", RGB_COLOR(255,245,238) }, + { "sienna", RGB_COLOR(160,82,45) }, + { "silver", RGB_COLOR(192,192,192) }, + { "skyblue", RGB_COLOR(135,206,235) }, + { "slateblue", RGB_COLOR(106,90,205) }, + { "slategray", RGB_COLOR(112,128,144) }, + { "slategrey", RGB_COLOR(112,128,144) }, + { "snow", RGB_COLOR(255,250,250) }, + { "springgreen", RGB_COLOR(0,255,127) }, + { "steelblue", RGB_COLOR(70,130,180) }, + { "tan", RGB_COLOR(210,180,140) }, + { "teal", RGB_COLOR(0,128,128) }, + { "thistle", RGB_COLOR(216,191,216) }, + { "tomato", RGB_COLOR(255,99,71) }, + { "turquoise", RGB_COLOR(64,224,208) }, + { "violet", RGB_COLOR(238,130,238) }, + { "wheat", RGB_COLOR(245,222,179) }, + { "white", RGB_COLOR(255,255,255) }, + { "whitesmoke", RGB_COLOR(245,245,245) }, + { "yellow", RGB_COLOR(255,255,0) }, + { "yellowgreen", RGB_COLOR(154,205,50) }, + { 0, { 0, 0, 0, 0 } } /* Terminator. */ +}; + +/* Get the color named NAME. If the color was found, returns 1 and + stores the color into *COLOR. If the color was not found, returns 0 and + does not modify *COLOR. */ +int +grub_gui_get_named_color (const char *name, + grub_gui_color_t *color) +{ + int i; + for (i = 0; named_colors[i].name; i++) + { + if (grub_strcmp (named_colors[i].name, name) == 0) + { + *color = named_colors[i].color; + return 1; + } + } + return 0; +} diff --git a/gfxmenu/theme_loader.c b/gfxmenu/theme_loader.c new file mode 100644 index 000000000..3854c6c53 --- /dev/null +++ b/gfxmenu/theme_loader.c @@ -0,0 +1,723 @@ +/* theme_loader.c - Theme file loader for gfxmenu. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Construct a new box widget using ABSPATTERN to find the pixmap files for + it, storing the new box instance at *BOXPTR. + PATTERN should be of the form: "(hd0,0)/somewhere/style*.png". + The '*' then gets substituted with the various pixmap names that the + box uses. */ +static grub_err_t +recreate_box_absolute (grub_gfxmenu_box_t *boxptr, const char *abspattern) +{ + char *prefix; + char *suffix; + char *star; + grub_gfxmenu_box_t box; + + star = grub_strchr (abspattern, '*'); + if (! star) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "missing `*' in box pixmap pattern `%s'", abspattern); + + /* Prefix: Get the part before the '*'. */ + prefix = grub_malloc (star - abspattern + 1); + if (! prefix) + return grub_errno; + + grub_memcpy (prefix, abspattern, star - abspattern); + prefix[star - abspattern] = '\0'; + + /* Suffix: Everything after the '*' is the suffix. */ + suffix = star + 1; + + box = grub_gfxmenu_create_box (prefix, suffix); + grub_free (prefix); + if (! box) + return grub_errno; + + if (*boxptr) + (*boxptr)->destroy (*boxptr); + *boxptr = box; + return grub_errno; +} + + +/* Construct a new box widget using PATTERN to find the pixmap files for it, + storing the new widget at *BOXPTR. PATTERN should be of the form: + "somewhere/style*.png". The '*' then gets substituted with the various + pixmap names that the widget uses. + + Important! The value of *BOXPTR must be initialized! It must either + (1) Be 0 (a NULL pointer), or + (2) Be a pointer to a valid 'grub_gfxmenu_box_t' instance. + In this case, the previous instance is destroyed. */ +grub_err_t +grub_gui_recreate_box (grub_gfxmenu_box_t *boxptr, + const char *pattern, const char *theme_dir) +{ + char *abspattern; + + /* Check arguments. */ + if (! pattern) + { + /* If no pixmap pattern is given, then just create an empty box. */ + if (*boxptr) + (*boxptr)->destroy (*boxptr); + *boxptr = grub_gfxmenu_create_box (0, 0); + return grub_errno; + } + + if (! theme_dir) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "styled box missing theme directory"); + + /* Resolve to an absolute path. */ + abspattern = grub_resolve_relative_path (theme_dir, pattern); + if (! abspattern) + return grub_errno; + + /* Create the box. */ + recreate_box_absolute (boxptr, abspattern); + grub_free (abspattern); + return grub_errno; +} + +/* Set the specified property NAME on the view to the given string VALUE. + The caller is responsible for the lifetimes of NAME and VALUE. */ +static grub_err_t +theme_set_string (grub_gfxmenu_view_t view, + const char *name, + const char *value, + const char *theme_dir, + const char *filename, + int line_num, + int col_num) +{ + if (! grub_strcmp ("title-font", name)) + view->title_font = grub_font_get (value); + else if (! grub_strcmp ("message-font", name)) + view->message_font = grub_font_get (value); + else if (! grub_strcmp ("terminal-font", name)) + { + grub_free (view->terminal_font_name); + view->terminal_font_name = grub_strdup (value); + if (! view->terminal_font_name) + return grub_errno; + } + else if (! grub_strcmp ("title-color", name)) + grub_gui_parse_color (value, &view->title_color); + else if (! grub_strcmp ("message-color", name)) + grub_gui_parse_color (value, &view->message_color); + else if (! grub_strcmp ("message-bg-color", name)) + grub_gui_parse_color (value, &view->message_bg_color); + else if (! grub_strcmp ("desktop-image", name)) + { + struct grub_video_bitmap *raw_bitmap; + struct grub_video_bitmap *scaled_bitmap; + char *path; + path = grub_resolve_relative_path (theme_dir, value); + if (! path) + return grub_errno; + if (grub_video_bitmap_load (&raw_bitmap, path) != GRUB_ERR_NONE) + { + grub_free (path); + return grub_errno; + } + grub_free(path); + grub_video_bitmap_create_scaled (&scaled_bitmap, + view->screen.width, + view->screen.height, + raw_bitmap, + GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST); + grub_video_bitmap_destroy (raw_bitmap); + if (! scaled_bitmap) + { + grub_error_push (); + return grub_error (grub_errno, "error scaling desktop image"); + } + + grub_video_bitmap_destroy (view->desktop_image); + view->desktop_image = scaled_bitmap; + } + else if (! grub_strcmp ("desktop-color", name)) + grub_gui_parse_color (value, &view->desktop_color); + else if (! grub_strcmp ("terminal-box", name)) + { + grub_err_t err; + err = grub_gui_recreate_box (&view->terminal_box, value, theme_dir); + if (err != GRUB_ERR_NONE) + return err; + } + else if (! grub_strcmp ("title-text", name)) + { + grub_free (view->title_text); + view->title_text = grub_strdup (value); + if (! view->title_text) + return grub_errno; + } + else + { + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "%s:%d:%d unknown property `%s'", + filename, line_num, col_num, name); + } + return grub_errno; +} + +struct parsebuf +{ + char *buf; + int pos; + int len; + int line_num; + int col_num; + const char *filename; + char *theme_dir; + grub_gfxmenu_view_t view; +}; + +static int +has_more (struct parsebuf *p) +{ + return p->pos < p->len; +} + +static int +read_char (struct parsebuf *p) +{ + if (has_more (p)) + { + char c; + c = p->buf[p->pos++]; + if (c == '\n') + { + p->line_num++; + p->col_num = 1; + } + else + { + p->col_num++; + } + return c; + } + else + return -1; +} + +static int +peek_char (struct parsebuf *p) +{ + if (has_more (p)) + return p->buf[p->pos]; + else + return -1; +} + +static int +is_whitespace (char c) +{ + return (c == ' ' + || c == '\t' + || c == '\r' + || c == '\n' + || c == '\f'); +} + +static void +skip_whitespace (struct parsebuf *p) +{ + while (has_more (p) && is_whitespace(peek_char (p))) + read_char (p); +} + +static void +advance_to_next_line (struct parsebuf *p) +{ + int c; + + /* Eat characters up to the newline. */ + do + { + c = read_char (p); + } + while (c != -1 && c != '\n'); +} + +static int +is_identifier_char (int c) +{ + return (c != -1 + && (grub_isalpha(c) + || grub_isdigit(c) + || c == '_' + || c == '-')); +} + +static char * +read_identifier (struct parsebuf *p) +{ + /* Index of the first character of the identifier in p->buf. */ + int start; + /* Next index after the last character of the identifer in p->buf. */ + int end; + + skip_whitespace (p); + + /* Capture the start of the identifier. */ + start = p->pos; + + /* Scan for the end. */ + while (is_identifier_char (peek_char (p))) + read_char (p); + end = p->pos; + + if (end - start < 1) + return 0; + + return grub_new_substring (p->buf, start, end); +} + +static char * +read_expression (struct parsebuf *p) +{ + int start; + int end; + + skip_whitespace (p); + if (peek_char (p) == '"') + { + /* Read as a quoted string. + The quotation marks are not included in the expression value. */ + /* Skip opening quotation mark. */ + read_char (p); + start = p->pos; + while (has_more (p) && peek_char (p) != '"') + read_char (p); + end = p->pos; + /* Skip the terminating quotation mark. */ + read_char (p); + } + else if (peek_char (p) == '(') + { + /* Read as a parenthesized string -- for tuples/coordinates. */ + /* The parentheses are included in the expression value. */ + int c; + + start = p->pos; + do + { + c = read_char (p); + } + while (c != -1 && c != ')'); + end = p->pos; + } + else if (has_more (p)) + { + /* Read as a single word -- for numeric values or words without + whitespace. */ + start = p->pos; + while (has_more (p) && ! is_whitespace (peek_char (p))) + read_char (p); + end = p->pos; + } + else + { + /* The end of the theme file has been reached. */ + grub_error (GRUB_ERR_IO, "%s:%d:%d expression expected in theme file", + p->filename, p->line_num, p->col_num); + return 0; + } + + return grub_new_substring (p->buf, start, end); +} + +static grub_err_t +parse_proportional_spec (char *value, signed *abs, grub_fixed_signed_t *prop) +{ + signed num; + char *ptr; + int sig = 0; + *abs = 0; + *prop = 0; + ptr = value; + while (*ptr) + { + sig = 0; + + while (*ptr == '-' || *ptr == '+') + { + if (*ptr == '-') + sig = !sig; + ptr++; + } + + num = grub_strtoul (ptr, &ptr, 0); + if (grub_errno) + return grub_errno; + if (sig) + num = -num; + if (*ptr == '%') + { + *prop += grub_fixed_fsf_divide (grub_signed_to_fixed (num), 100); + ptr++; + } + else + *abs += num; + } + return GRUB_ERR_NONE; +} + + +/* Read a GUI object specification from the theme file. + Any components created will be added to the GUI container PARENT. */ +static grub_err_t +read_object (struct parsebuf *p, grub_gui_container_t parent) +{ + grub_video_rect_t bounds; + + char *name; + name = read_identifier (p); + if (! name) + goto cleanup; + + grub_gui_component_t component = 0; + if (grub_strcmp (name, "label") == 0) + { + component = grub_gui_label_new (); + } + else if (grub_strcmp (name, "image") == 0) + { + component = grub_gui_image_new (); + } + else if (grub_strcmp (name, "vbox") == 0) + { + component = (grub_gui_component_t) grub_gui_vbox_new (); + } + else if (grub_strcmp (name, "hbox") == 0) + { + component = (grub_gui_component_t) grub_gui_hbox_new (); + } + else if (grub_strcmp (name, "canvas") == 0) + { + component = (grub_gui_component_t) grub_gui_canvas_new (); + } + else if (grub_strcmp (name, "progress_bar") == 0) + { + component = grub_gui_progress_bar_new (); + } + else if (grub_strcmp (name, "circular_progress") == 0) + { + component = grub_gui_circular_progress_new (); + } + else if (grub_strcmp (name, "boot_menu") == 0) + { + component = grub_gui_list_new (); + } + else + { + /* Unknown type. */ + grub_error (GRUB_ERR_IO, "%s:%d:%d unknown object type `%s'", + p->filename, p->line_num, p->col_num, name); + goto cleanup; + } + + if (! component) + goto cleanup; + + /* Inform the component about the theme so it can find its resources. */ + component->ops->set_property (component, "theme_dir", p->theme_dir); + component->ops->set_property (component, "theme_path", p->filename); + + /* Add the component as a child of PARENT. */ + bounds.x = 0; + bounds.y = 0; + bounds.width = -1; + bounds.height = -1; + component->ops->set_bounds (component, &bounds); + parent->ops->add (parent, component); + + skip_whitespace (p); + if (read_char (p) != '{') + { + grub_error (GRUB_ERR_IO, + "%s:%d:%d expected `{' after object type name `%s'", + p->filename, p->line_num, p->col_num, name); + goto cleanup; + } + + while (has_more (p)) + { + skip_whitespace (p); + + /* Check whether the end has been encountered. */ + if (peek_char (p) == '}') + { + /* Skip the closing brace. */ + read_char (p); + break; + } + + if (peek_char (p) == '#') + { + /* Skip comments. */ + advance_to_next_line (p); + continue; + } + + if (peek_char (p) == '+') + { + /* Skip the '+'. */ + read_char (p); + + /* Check whether this component is a container. */ + if (component->ops->is_instance (component, "container")) + { + /* Read the sub-object recursively and add it as a child. */ + if (read_object (p, (grub_gui_container_t) component) != 0) + goto cleanup; + /* After reading the sub-object, resume parsing, expecting + another property assignment or sub-object definition. */ + continue; + } + else + { + grub_error (GRUB_ERR_IO, + "%s:%d:%d attempted to add object to non-container", + p->filename, p->line_num, p->col_num); + goto cleanup; + } + } + + char *property; + property = read_identifier (p); + if (! property) + { + grub_error (GRUB_ERR_IO, "%s:%d:%d identifier expected in theme file", + p->filename, p->line_num, p->col_num); + goto cleanup; + } + + skip_whitespace (p); + if (read_char (p) != '=') + { + grub_error (GRUB_ERR_IO, + "%s:%d:%d expected `=' after property name `%s'", + p->filename, p->line_num, p->col_num, property); + grub_free (property); + goto cleanup; + } + skip_whitespace (p); + + char *value; + value = read_expression (p); + if (! value) + { + grub_free (property); + goto cleanup; + } + + /* Handle the property value. */ + if (grub_strcmp (property, "left") == 0) + parse_proportional_spec (value, &component->x, &component->xfrac); + else if (grub_strcmp (property, "top") == 0) + parse_proportional_spec (value, &component->y, &component->yfrac); + else if (grub_strcmp (property, "width") == 0) + parse_proportional_spec (value, &component->w, &component->wfrac); + else if (grub_strcmp (property, "height") == 0) + parse_proportional_spec (value, &component->h, &component->hfrac); + else + /* General property handling. */ + component->ops->set_property (component, property, value); + + grub_free (value); + grub_free (property); + if (grub_errno != GRUB_ERR_NONE) + goto cleanup; + } + +cleanup: + grub_free (name); + return grub_errno; +} + +static grub_err_t +read_property (struct parsebuf *p) +{ + char *name; + + /* Read the property name. */ + name = read_identifier (p); + if (! name) + { + advance_to_next_line (p); + return grub_errno; + } + + /* Skip whitespace before separator. */ + skip_whitespace (p); + + /* Read separator. */ + if (read_char (p) != ':') + { + grub_error (GRUB_ERR_IO, + "%s:%d:%d missing separator after property name `%s'", + p->filename, p->line_num, p->col_num, name); + goto done; + } + + /* Skip whitespace after separator. */ + skip_whitespace (p); + + /* Get the value based on its type. */ + if (peek_char (p) == '"') + { + /* String value (e.g., '"My string"'). */ + char *value = read_expression (p); + if (! value) + { + grub_error (GRUB_ERR_IO, "%s:%d:%d missing property value", + p->filename, p->line_num, p->col_num); + goto done; + } + /* If theme_set_string results in an error, grub_errno will be returned + below. */ + theme_set_string (p->view, name, value, p->theme_dir, + p->filename, p->line_num, p->col_num); + grub_free (value); + } + else + { + grub_error (GRUB_ERR_IO, + "%s:%d:%d property value invalid; " + "enclose literal values in quotes (\")", + p->filename, p->line_num, p->col_num); + goto done; + } + +done: + grub_free (name); + return grub_errno; +} + +/* Set properties on the view based on settings from the specified + theme file. */ +grub_err_t +grub_gfxmenu_view_load_theme (grub_gfxmenu_view_t view, const char *theme_path) +{ + grub_file_t file; + struct parsebuf p; + + p.view = view; + p.theme_dir = grub_get_dirname (theme_path); + + file = grub_file_open (theme_path); + if (! file) + { + grub_free (p.theme_dir); + return grub_errno; + } + + p.len = grub_file_size (file); + p.buf = grub_malloc (p.len); + p.pos = 0; + p.line_num = 1; + p.col_num = 1; + p.filename = theme_path; + if (! p.buf) + { + grub_file_close (file); + grub_free (p.theme_dir); + return grub_errno; + } + if (grub_file_read (file, p.buf, p.len) != p.len) + { + grub_free (p.buf); + grub_file_close (file); + grub_free (p.theme_dir); + return grub_errno; + } + + if (view->canvas) + view->canvas->component.ops->destroy (view->canvas); + + view->canvas = grub_gui_canvas_new (); + ((grub_gui_component_t) view->canvas) + ->ops->set_bounds ((grub_gui_component_t) view->canvas, + &view->screen); + + while (has_more (&p)) + { + /* Skip comments (lines beginning with #). */ + if (peek_char (&p) == '#') + { + advance_to_next_line (&p); + continue; + } + + /* Find the first non-whitespace character. */ + skip_whitespace (&p); + + /* Handle the content. */ + if (peek_char (&p) == '+') + { + /* Skip the '+'. */ + read_char (&p); + read_object (&p, view->canvas); + } + else + { + read_property (&p); + } + + if (grub_errno != GRUB_ERR_NONE) + goto fail; + } + + /* Set the new theme path. */ + grub_free (view->theme_path); + view->theme_path = grub_strdup (theme_path); + goto cleanup; + +fail: + if (view->canvas) + { + view->canvas->component.ops->destroy (view->canvas); + view->canvas = 0; + } + +cleanup: + grub_free (p.buf); + grub_file_close (file); + grub_free (p.theme_dir); + return grub_errno; +} diff --git a/gfxmenu/view.c b/gfxmenu/view.c new file mode 100644 index 000000000..bf637a96d --- /dev/null +++ b/gfxmenu/view.c @@ -0,0 +1,486 @@ +/* view.c - Graphical menu interface MVC view. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* The component ID identifying GUI components to be updated as the timeout + status changes. */ +#define TIMEOUT_COMPONENT_ID "__timeout__" + +static void +init_terminal (grub_gfxmenu_view_t view); +static grub_video_rect_t term_rect; +static grub_gfxmenu_view_t term_view; + +/* Create a new view object, loading the theme specified by THEME_PATH and + associating MODEL with the view. */ +grub_gfxmenu_view_t +grub_gfxmenu_view_new (const char *theme_path, + int width, int height) +{ + grub_gfxmenu_view_t view; + grub_font_t default_font; + grub_gui_color_t default_fg_color; + grub_gui_color_t default_bg_color; + + view = grub_malloc (sizeof (*view)); + if (! view) + return 0; + + view->screen.x = 0; + view->screen.y = 0; + view->screen.width = width; + view->screen.height = height; + + default_font = grub_font_get ("Unknown Regular 16"); + default_fg_color = grub_gui_color_rgb (0, 0, 0); + default_bg_color = grub_gui_color_rgb (255, 255, 255); + + view->canvas = 0; + + view->title_font = default_font; + view->message_font = default_font; + view->terminal_font_name = grub_strdup ("Fixed 10"); + view->title_color = default_fg_color; + view->message_color = default_bg_color; + view->message_bg_color = default_fg_color; + view->desktop_image = 0; + view->desktop_color = default_bg_color; + view->terminal_box = grub_gfxmenu_create_box (0, 0); + view->title_text = grub_strdup ("GRUB Boot Menu"); + view->progress_message_text = 0; + view->theme_path = 0; + + /* Set the timeout bar's frame. */ + view->progress_message_frame.width = view->screen.width * 4 / 5; + view->progress_message_frame.height = 50; + view->progress_message_frame.x = view->screen.x + + (view->screen.width - view->progress_message_frame.width) / 2; + view->progress_message_frame.y = view->screen.y + + view->screen.height - 90 - 20 - view->progress_message_frame.height; + + if (grub_gfxmenu_view_load_theme (view, theme_path) != 0) + { + grub_gfxmenu_view_destroy (view); + return 0; + } + + return view; +} + +/* Destroy the view object. All used memory is freed. */ +void +grub_gfxmenu_view_destroy (grub_gfxmenu_view_t view) +{ + if (!view) + return; + grub_video_bitmap_destroy (view->desktop_image); + if (view->terminal_box) + view->terminal_box->destroy (view->terminal_box); + grub_free (view->terminal_font_name); + grub_free (view->title_text); + grub_free (view->progress_message_text); + grub_free (view->theme_path); + if (view->canvas) + view->canvas->component.ops->destroy (view->canvas); + grub_free (view); +} + +static void +redraw_background (grub_gfxmenu_view_t view, + const grub_video_rect_t *bounds) +{ + if (view->desktop_image) + { + struct grub_video_bitmap *img = view->desktop_image; + grub_video_blit_bitmap (img, GRUB_VIDEO_BLIT_REPLACE, + bounds->x, bounds->y, + bounds->x - view->screen.x, + bounds->y - view->screen.y, + bounds->width, bounds->height); + } + else + { + grub_video_fill_rect (grub_gui_map_color (view->desktop_color), + bounds->x, bounds->y, + bounds->width, bounds->height); + } +} + +static void +draw_title (grub_gfxmenu_view_t view) +{ + if (! view->title_text) + return; + + /* Center the title. */ + int title_width = grub_font_get_string_width (view->title_font, + view->title_text); + int x = (view->screen.width - title_width) / 2; + int y = 40 + grub_font_get_ascent (view->title_font); + grub_font_draw_string (view->title_text, + view->title_font, + grub_gui_map_color (view->title_color), + x, y); +} + +struct progress_value_data +{ + int visible; + int start; + int end; + int value; +}; + +static void +update_timeout_visit (grub_gui_component_t component, + void *userdata) +{ + struct progress_value_data *pv; + pv = (struct progress_value_data *) userdata; + + ((struct grub_gui_progress *) component)->ops + ->set_state ((struct grub_gui_progress *) component, + pv->visible, pv->start, pv->value, pv->end); +} + +void +grub_gfxmenu_print_timeout (int timeout, void *data) +{ + struct grub_gfxmenu_view *view = data; + + struct progress_value_data pv; + + auto void redraw_timeout_visit (grub_gui_component_t component, + void *userdata __attribute__ ((unused))); + + auto void redraw_timeout_visit (grub_gui_component_t component, + void *userdata __attribute__ ((unused))) + { + grub_video_rect_t bounds; + component->ops->get_bounds (component, &bounds); + grub_gfxmenu_view_redraw (view, &bounds); + } + + if (view->first_timeout == -1) + view->first_timeout = timeout; + + pv.visible = 1; + pv.start = -(view->first_timeout + 1); + pv.end = 0; + pv.value = -timeout; + + grub_gui_find_by_id ((grub_gui_component_t) view->canvas, + TIMEOUT_COMPONENT_ID, update_timeout_visit, &pv); + grub_gui_find_by_id ((grub_gui_component_t) view->canvas, + TIMEOUT_COMPONENT_ID, redraw_timeout_visit, &pv); + grub_video_swap_buffers (); + if (view->double_repaint) + grub_gui_find_by_id ((grub_gui_component_t) view->canvas, + TIMEOUT_COMPONENT_ID, redraw_timeout_visit, &pv); +} + +void +grub_gfxmenu_clear_timeout (void *data) +{ + struct progress_value_data pv; + struct grub_gfxmenu_view *view = data; + + auto void redraw_timeout_visit (grub_gui_component_t component, + void *userdata __attribute__ ((unused))); + + auto void redraw_timeout_visit (grub_gui_component_t component, + void *userdata __attribute__ ((unused))) + { + grub_video_rect_t bounds; + component->ops->get_bounds (component, &bounds); + grub_gfxmenu_view_redraw (view, &bounds); + } + + pv.visible = 0; + pv.start = 1; + pv.end = 0; + pv.value = 0; + + grub_gui_find_by_id ((grub_gui_component_t) view->canvas, + TIMEOUT_COMPONENT_ID, update_timeout_visit, &pv); + grub_gui_find_by_id ((grub_gui_component_t) view->canvas, + TIMEOUT_COMPONENT_ID, redraw_timeout_visit, &pv); + grub_video_swap_buffers (); + if (view->double_repaint) + grub_gui_find_by_id ((grub_gui_component_t) view->canvas, + TIMEOUT_COMPONENT_ID, redraw_timeout_visit, &pv); +} + +static void +update_menu_visit (grub_gui_component_t component, + void *userdata) +{ + grub_gfxmenu_view_t view; + view = userdata; + if (component->ops->is_instance (component, "list")) + { + grub_gui_list_t list = (grub_gui_list_t) component; + list->ops->set_view_info (list, view); + } +} + +/* Update any boot menu components with the current menu model and + theme path. */ +static void +update_menu_components (grub_gfxmenu_view_t view) +{ + grub_gui_iterate_recursively ((grub_gui_component_t) view->canvas, + update_menu_visit, view); +} + +static void +draw_message (grub_gfxmenu_view_t view) +{ + char *text = view->progress_message_text; + grub_video_rect_t f = view->progress_message_frame; + if (! text) + return; + + grub_font_t font = view->message_font; + grub_video_color_t color = grub_gui_map_color (view->message_color); + + /* Border. */ + grub_video_fill_rect (color, + f.x-1, f.y-1, f.width+2, f.height+2); + /* Fill. */ + grub_video_fill_rect (grub_gui_map_color (view->message_bg_color), + f.x, f.y, f.width, f.height); + + /* Center the text. */ + int text_width = grub_font_get_string_width (font, text); + int x = f.x + (f.width - text_width) / 2; + int y = (f.y + (f.height - grub_font_get_descent (font)) / 2 + + grub_font_get_ascent (font) / 2); + grub_font_draw_string (text, font, color, x, y); +} + +void +grub_gfxmenu_view_redraw (grub_gfxmenu_view_t view, + const grub_video_rect_t *region) +{ + if (grub_video_have_common_points (&term_rect, region)) + grub_gfxterm_schedule_repaint (); + + grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); + + redraw_background (view, region); + if (view->canvas) + view->canvas->component.ops->paint (view->canvas, region); + draw_title (view); + if (grub_video_have_common_points (&view->progress_message_frame, region)) + draw_message (view); +} + +void +grub_gfxmenu_view_draw (grub_gfxmenu_view_t view) +{ + init_terminal (view); + + /* Clear the screen; there may be garbage left over in video memory. */ + grub_video_fill_rect (grub_video_map_rgb (0, 0, 0), + view->screen.x, view->screen.y, + view->screen.width, view->screen.height); + grub_video_swap_buffers (); + if (view->double_repaint) + grub_video_fill_rect (grub_video_map_rgb (0, 0, 0), + view->screen.x, view->screen.y, + view->screen.width, view->screen.height); + + update_menu_components (view); + + grub_gfxmenu_view_redraw (view, &view->screen); + grub_video_swap_buffers (); + if (view->double_repaint) + grub_gfxmenu_view_redraw (view, &view->screen); +} + +static void +redraw_menu_visit (grub_gui_component_t component, + void *userdata) +{ + grub_gfxmenu_view_t view; + view = userdata; + if (component->ops->is_instance (component, "list")) + { + grub_gui_list_t list; + grub_video_rect_t bounds; + + list = (grub_gui_list_t) component; + component->ops->get_bounds (component, &bounds); + grub_gfxmenu_view_redraw (view, &bounds); + } +} + +void +grub_gfxmenu_redraw_menu (grub_gfxmenu_view_t view) +{ + update_menu_components (view); + + grub_gui_iterate_recursively ((grub_gui_component_t) view->canvas, + redraw_menu_visit, view); + grub_video_swap_buffers (); + if (view->double_repaint) + { + grub_gui_iterate_recursively ((grub_gui_component_t) view->canvas, + redraw_menu_visit, view); + } +} + +void +grub_gfxmenu_set_chosen_entry (int entry, void *data) +{ + grub_gfxmenu_view_t view = data; + + view->selected = entry; + grub_gfxmenu_redraw_menu (view); +} + +static void +grub_gfxmenu_draw_terminal_box (void) +{ + grub_gfxmenu_box_t term_box; + + term_box = term_view->terminal_box; + if (!term_box) + return; + + term_box->set_content_size (term_box, term_rect.width, + term_rect.height); + + 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 +init_terminal (grub_gfxmenu_view_t view) +{ + term_rect.width = view->screen.width * 7 / 10; + term_rect.height = view->screen.height * 7 / 10; + + term_rect.x = view->screen.x + view->screen.width * (10 - 7) / 10 / 2; + term_rect.y = view->screen.y + view->screen.height * (10 - 7) / 10 / 2; + + term_view = view; + + /* Note: currently there is no API for changing the gfxterm font + on the fly, so whatever font the initially loaded theme specifies + will be permanent. */ + grub_gfxterm_set_window (GRUB_VIDEO_RENDER_TARGET_DISPLAY, term_rect.x, + term_rect.y, + term_rect.width, term_rect.height, + view->double_repaint, view->terminal_font_name, 3); + grub_gfxterm_decorator_hook = grub_gfxmenu_draw_terminal_box; +} + +/* FIXME: previously notifications were displayed in special case. + Is it necessary? + */ +#if 0 +/* Sets MESSAGE as the progress message for the view. + MESSAGE can be 0, in which case no message is displayed. */ +static void +set_progress_message (grub_gfxmenu_view_t view, const char *message) +{ + grub_free (view->progress_message_text); + if (message) + view->progress_message_text = grub_strdup (message); + else + view->progress_message_text = 0; +} + +static void +notify_booting (grub_menu_entry_t entry, void *userdata) +{ + grub_gfxmenu_view_t view = (grub_gfxmenu_view_t) userdata; + + char *s = grub_malloc (100 + grub_strlen (entry->title)); + if (!s) + return; + + grub_sprintf (s, "Booting '%s'", entry->title); + set_progress_message (view, s); + grub_free (s); + grub_gfxmenu_view_redraw (view, &view->progress_message_frame); + grub_video_swap_buffers (); + if (view->double_repaint) + grub_gfxmenu_view_redraw (view, &view->progress_message_frame); +} + +static void +notify_fallback (grub_menu_entry_t entry, void *userdata) +{ + grub_gfxmenu_view_t view = (grub_gfxmenu_view_t) userdata; + + char *s = grub_malloc (100 + grub_strlen (entry->title)); + if (!s) + return; + + grub_sprintf (s, "Falling back to '%s'", entry->title); + set_progress_message (view, s); + grub_free (s); + grub_gfxmenu_view_redraw (view, &view->progress_message_frame); + grub_video_swap_buffers (); + if (view->double_repaint) + grub_gfxmenu_view_redraw (view, &view->progress_message_frame); +} + +static void +notify_execution_failure (void *userdata __attribute__ ((unused))) +{ +} + + +static struct grub_menu_execute_callback execute_callback = +{ + .notify_booting = notify_booting, + .notify_fallback = notify_fallback, + .notify_failure = notify_execution_failure +}; + +#endif diff --git a/gfxmenu/widget-box.c b/gfxmenu/widget-box.c new file mode 100644 index 000000000..079fd66d4 --- /dev/null +++ b/gfxmenu/widget-box.c @@ -0,0 +1,313 @@ +/* widget_box.c - Pixmap-stylized box widget. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +enum box_pixmaps +{ + BOX_PIXMAP_NW, BOX_PIXMAP_NE, BOX_PIXMAP_SE, BOX_PIXMAP_SW, + BOX_PIXMAP_N, BOX_PIXMAP_E, BOX_PIXMAP_S, BOX_PIXMAP_W, + BOX_PIXMAP_CENTER +}; + +static const char *box_pixmap_names[] = { + /* Corners: */ + "nw", "ne", "se", "sw", + /* Sides: */ + "n", "e", "s", "w", + /* Center: */ + "c" +}; + +#define BOX_NUM_PIXMAPS (sizeof(box_pixmap_names)/sizeof(*box_pixmap_names)) + +static int +get_height (struct grub_video_bitmap *bitmap) +{ + if (bitmap) + return grub_video_bitmap_get_height (bitmap); + else + return 0; +} + +static int +get_width (struct grub_video_bitmap *bitmap) +{ + if (bitmap) + return grub_video_bitmap_get_width (bitmap); + else + return 0; +} + +static void +blit (grub_gfxmenu_box_t self, int pixmap_index, int x, int y) +{ + struct grub_video_bitmap *bitmap; + bitmap = self->scaled_pixmaps[pixmap_index]; + if (! bitmap) + return; + grub_video_blit_bitmap (bitmap, GRUB_VIDEO_BLIT_BLEND, + x, y, 0, 0, + grub_video_bitmap_get_width (bitmap), + grub_video_bitmap_get_height (bitmap)); +} + +static void +draw (grub_gfxmenu_box_t self, int x, int y) +{ + int height_n; + int height_s; + int height_e; + int height_w; + int width_n; + int width_s; + int width_e; + int width_w; + + height_n = get_height (self->scaled_pixmaps[BOX_PIXMAP_N]); + height_s = get_height (self->scaled_pixmaps[BOX_PIXMAP_S]); + height_e = get_height (self->scaled_pixmaps[BOX_PIXMAP_E]); + height_w = get_height (self->scaled_pixmaps[BOX_PIXMAP_W]); + width_n = get_width (self->scaled_pixmaps[BOX_PIXMAP_N]); + width_s = get_width (self->scaled_pixmaps[BOX_PIXMAP_S]); + width_e = get_width (self->scaled_pixmaps[BOX_PIXMAP_E]); + width_w = get_width (self->scaled_pixmaps[BOX_PIXMAP_W]); + + /* Draw sides. */ + blit (self, BOX_PIXMAP_N, x + width_w, y); + blit (self, BOX_PIXMAP_S, x + width_w, y + height_n + self->content_height); + blit (self, BOX_PIXMAP_E, x + width_w + self->content_width, y + height_n); + blit (self, BOX_PIXMAP_W, x, y + height_n); + + /* Draw corners. */ + blit (self, BOX_PIXMAP_NW, x, y); + blit (self, BOX_PIXMAP_NE, x + width_w + self->content_width, y); + blit (self, BOX_PIXMAP_SE, + x + width_w + self->content_width, + y + height_n + self->content_height); + blit (self, BOX_PIXMAP_SW, x, y + height_n + self->content_height); + + /* Draw center. */ + blit (self, BOX_PIXMAP_CENTER, x + width_w, y + height_n); +} + +static grub_err_t +scale_pixmap (grub_gfxmenu_box_t self, int i, int w, int h) +{ + struct grub_video_bitmap **scaled = &self->scaled_pixmaps[i]; + struct grub_video_bitmap *raw = self->raw_pixmaps[i]; + + if (raw == 0) + return grub_errno; + + if (w == -1) + w = grub_video_bitmap_get_width (raw); + if (h == -1) + h = grub_video_bitmap_get_height (raw); + + if (*scaled == 0 + || ((int) grub_video_bitmap_get_width (*scaled) != w) + || ((int) grub_video_bitmap_get_height (*scaled) != h)) + { + if (*scaled) + { + grub_video_bitmap_destroy (*scaled); + *scaled = 0; + } + + /* Don't try to create a bitmap with a zero dimension. */ + if (w != 0 && h != 0) + grub_video_bitmap_create_scaled (scaled, w, h, raw, + GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST); + if (grub_errno != GRUB_ERR_NONE) + { + grub_error_push (); + grub_error (grub_errno, + "failed to scale bitmap for styled box pixmap #%d", i); + } + } + + return grub_errno; +} + +static void +set_content_size (grub_gfxmenu_box_t self, + int width, int height) +{ + self->content_width = width; + self->content_height = height; + + /* Resize sides to match the width and height. */ + /* It is assumed that the corners width/height match the adjacent sides. */ + + /* Resize N and S sides to match width. */ + if (scale_pixmap(self, BOX_PIXMAP_N, width, -1) != GRUB_ERR_NONE) + return; + if (scale_pixmap(self, BOX_PIXMAP_S, width, -1) != GRUB_ERR_NONE) + return; + + /* Resize E and W sides to match height. */ + if (scale_pixmap(self, BOX_PIXMAP_E, -1, height) != GRUB_ERR_NONE) + return; + if (scale_pixmap(self, BOX_PIXMAP_W, -1, height) != GRUB_ERR_NONE) + return; + + /* Don't scale the corners--they are assumed to match the sides. */ + if (scale_pixmap(self, BOX_PIXMAP_NW, -1, -1) != GRUB_ERR_NONE) + return; + if (scale_pixmap(self, BOX_PIXMAP_SW, -1, -1) != GRUB_ERR_NONE) + return; + if (scale_pixmap(self, BOX_PIXMAP_NE, -1, -1) != GRUB_ERR_NONE) + return; + if (scale_pixmap(self, BOX_PIXMAP_SE, -1, -1) != GRUB_ERR_NONE) + return; + + /* Scale the center area. */ + if (scale_pixmap(self, BOX_PIXMAP_CENTER, width, height) != GRUB_ERR_NONE) + return; +} + +static int +get_left_pad (grub_gfxmenu_box_t self) +{ + return get_width (self->raw_pixmaps[BOX_PIXMAP_W]); +} + +static int +get_top_pad (grub_gfxmenu_box_t self) +{ + return get_height (self->raw_pixmaps[BOX_PIXMAP_N]); +} + +static int +get_right_pad (grub_gfxmenu_box_t self) +{ + return get_width (self->raw_pixmaps[BOX_PIXMAP_E]); +} + +static int +get_bottom_pad (grub_gfxmenu_box_t self) +{ + return get_height (self->raw_pixmaps[BOX_PIXMAP_S]); +} + +static void +destroy (grub_gfxmenu_box_t self) +{ + unsigned i; + for (i = 0; i < BOX_NUM_PIXMAPS; i++) + { + if (self->raw_pixmaps[i]) + grub_video_bitmap_destroy(self->raw_pixmaps[i]); + self->raw_pixmaps[i] = 0; + + if (self->scaled_pixmaps[i]) + grub_video_bitmap_destroy(self->scaled_pixmaps[i]); + self->scaled_pixmaps[i] = 0; + } + grub_free (self->raw_pixmaps); + self->raw_pixmaps = 0; + grub_free (self->scaled_pixmaps); + self->scaled_pixmaps = 0; + + /* Free self: must be the last step! */ + grub_free (self); +} + + +/* Create a new box. If PIXMAPS_PREFIX and PIXMAPS_SUFFIX are both non-null, + then an attempt is made to load the north, south, east, west, northwest, + northeast, southeast, southwest, and center pixmaps. + If either PIXMAPS_PREFIX or PIXMAPS_SUFFIX is 0, then no pixmaps are + loaded, and the box has zero-width borders and is drawn transparent. */ +grub_gfxmenu_box_t +grub_gfxmenu_create_box (const char *pixmaps_prefix, + const char *pixmaps_suffix) +{ + unsigned i; + grub_gfxmenu_box_t box; + + box = (grub_gfxmenu_box_t) grub_malloc (sizeof (*box)); + if (! box) + return 0; + + box->content_width = 0; + box->content_height = 0; + box->raw_pixmaps = + (struct grub_video_bitmap **) + grub_malloc (BOX_NUM_PIXMAPS * sizeof (struct grub_video_bitmap *)); + box->scaled_pixmaps = + (struct grub_video_bitmap **) + grub_malloc (BOX_NUM_PIXMAPS * sizeof (struct grub_video_bitmap *)); + + /* Initialize all pixmap pointers to NULL so that proper destruction can + be performed if an error is encountered partway through construction. */ + for (i = 0; i < BOX_NUM_PIXMAPS; i++) + box->raw_pixmaps[i] = 0; + for (i = 0; i < BOX_NUM_PIXMAPS; i++) + box->scaled_pixmaps[i] = 0; + + /* Load the pixmaps. */ + for (i = 0; i < BOX_NUM_PIXMAPS; i++) + { + if (pixmaps_prefix && pixmaps_suffix) + { + char *path; + char *path_end; + + path = grub_malloc (grub_strlen (pixmaps_prefix) + + grub_strlen (box_pixmap_names[i]) + + grub_strlen (pixmaps_suffix) + + 1); + if (! path) + goto fail_and_destroy; + + /* Construct the specific path for this pixmap. */ + path_end = grub_stpcpy (path, pixmaps_prefix); + path_end = grub_stpcpy (path_end, box_pixmap_names[i]); + path_end = grub_stpcpy (path_end, pixmaps_suffix); + + grub_video_bitmap_load (&box->raw_pixmaps[i], path); + grub_free (path); + + /* Ignore missing pixmaps. */ + grub_errno = GRUB_ERR_NONE; + } + } + + box->draw = draw; + box->set_content_size = set_content_size; + box->get_left_pad = get_left_pad; + box->get_top_pad = get_top_pad; + box->get_right_pad = get_right_pad; + box->get_bottom_pad = get_bottom_pad; + box->destroy = destroy; + return box; + +fail_and_destroy: + destroy (box); + return 0; +} diff --git a/gnulib/getdelim.c b/gnulib/getdelim.c index 12f2167c9..85818b565 100644 --- a/gnulib/getdelim.c +++ b/gnulib/getdelim.c @@ -27,6 +27,7 @@ #include #include #include +#include #ifndef SSIZE_MAX # define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) diff --git a/hook/datehook.c b/hook/datehook.c index b7663cc21..4876e1198 100644 --- a/hook/datehook.c +++ b/hook/datehook.c @@ -76,7 +76,7 @@ grub_read_hook_datetime (struct grub_env_var *var, return grub_get_weekday_name (&datetime); } - grub_sprintf (buf, "%d", n); + grub_snprintf (buf, sizeof (buf), "%d", n); break; } } diff --git a/include/grub/aout.h b/include/grub/aout.h index c5650ddf8..04e85f8b0 100644 --- a/include/grub/aout.h +++ b/include/grub/aout.h @@ -16,6 +16,38 @@ * along with GRUB. If not, see . */ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)exec.h 8.1 (Berkeley) 6/11/93 + * $FreeBSD$ + */ + #ifndef GRUB_AOUT_HEADER #define GRUB_AOUT_HEADER 1 diff --git a/include/grub/at_keyboard.h b/include/grub/at_keyboard.h new file mode 100644 index 000000000..10421540a --- /dev/null +++ b/include/grub/at_keyboard.h @@ -0,0 +1,54 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007,2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_AT_KEYBOARD_HEADER +#define GRUB_AT_KEYBOARD_HEADER 1 + +#define SHIFT_L 0x2a +#define SHIFT_R 0x36 +#define CTRL 0x1d +#define ALT 0x38 +#define CAPS_LOCK 0x3a +#define NUM_LOCK 0x45 +#define SCROLL_LOCK 0x46 + +/* Used for sending commands to the controller. */ +#define KEYBOARD_COMMAND_ISREADY(x) !((x) & 0x02) +#define KEYBOARD_COMMAND_READ 0x20 +#define KEYBOARD_COMMAND_WRITE 0x60 +#define KEYBOARD_COMMAND_REBOOT 0xfe + +#define KEYBOARD_SCANCODE_SET1 0x40 + +#define KEYBOARD_ISMAKE(x) !((x) & 0x80) +#define KEYBOARD_ISREADY(x) ((x) & 0x01) +#define KEYBOARD_SCANCODE(x) ((x) & 0x7f) + +#ifdef GRUB_MACHINE_IEEE1275 +#define OLPC_UP GRUB_TERM_UP +#define OLPC_DOWN GRUB_TERM_DOWN +#define OLPC_LEFT GRUB_TERM_LEFT +#define OLPC_RIGHT GRUB_TERM_RIGHT +#else +#define OLPC_UP '\0' +#define OLPC_DOWN '\0' +#define OLPC_LEFT '\0' +#define OLPC_RIGHT '\0' +#endif + +#endif diff --git a/include/grub/ata.h b/include/grub/ata.h index aaa2e147a..940e67102 100644 --- a/include/grub/ata.h +++ b/include/grub/ata.h @@ -98,8 +98,8 @@ struct grub_ata_device /* IO addresses on which the registers for this device can be found. */ - int ioaddress; - int ioaddress2; + grub_port_t ioaddress; + grub_port_t ioaddress2; /* Two devices can be connected to a single cable. Use this field to select device 0 (commonly known as "master") or device 1 diff --git a/include/grub/bitmap.h b/include/grub/bitmap.h index 42c439d69..6e300391a 100644 --- a/include/grub/bitmap.h +++ b/include/grub/bitmap.h @@ -47,24 +47,24 @@ struct grub_video_bitmap_reader }; typedef struct grub_video_bitmap_reader *grub_video_bitmap_reader_t; -void grub_video_bitmap_reader_register (grub_video_bitmap_reader_t reader); -void grub_video_bitmap_reader_unregister (grub_video_bitmap_reader_t reader); +void EXPORT_FUNC (grub_video_bitmap_reader_register) (grub_video_bitmap_reader_t reader); +void EXPORT_FUNC (grub_video_bitmap_reader_unregister) (grub_video_bitmap_reader_t reader); -grub_err_t grub_video_bitmap_create (struct grub_video_bitmap **bitmap, - unsigned int width, unsigned int height, - enum grub_video_blit_format blit_format); +grub_err_t EXPORT_FUNC (grub_video_bitmap_create) (struct grub_video_bitmap **bitmap, + unsigned int width, unsigned int height, + enum grub_video_blit_format blit_format); -grub_err_t grub_video_bitmap_destroy (struct grub_video_bitmap *bitmap); +grub_err_t EXPORT_FUNC (grub_video_bitmap_destroy) (struct grub_video_bitmap *bitmap); -grub_err_t grub_video_bitmap_load (struct grub_video_bitmap **bitmap, - const char *filename); +grub_err_t EXPORT_FUNC (grub_video_bitmap_load) (struct grub_video_bitmap **bitmap, + const char *filename); -unsigned int grub_video_bitmap_get_width (struct grub_video_bitmap *bitmap); -unsigned int grub_video_bitmap_get_height (struct grub_video_bitmap *bitmap); +unsigned int EXPORT_FUNC (grub_video_bitmap_get_width) (struct grub_video_bitmap *bitmap); +unsigned int EXPORT_FUNC (grub_video_bitmap_get_height) (struct grub_video_bitmap *bitmap); -void grub_video_bitmap_get_mode_info (struct grub_video_bitmap *bitmap, - struct grub_video_mode_info *mode_info); +void EXPORT_FUNC (grub_video_bitmap_get_mode_info) (struct grub_video_bitmap *bitmap, + struct grub_video_mode_info *mode_info); -void *grub_video_bitmap_get_data (struct grub_video_bitmap *bitmap); +void *EXPORT_FUNC (grub_video_bitmap_get_data) (struct grub_video_bitmap *bitmap); #endif /* ! GRUB_BITMAP_HEADER */ diff --git a/include/grub/bitmap_scale.h b/include/grub/bitmap_scale.h new file mode 100644 index 000000000..dce9fbbf2 --- /dev/null +++ b/include/grub/bitmap_scale.h @@ -0,0 +1,49 @@ +/* bitmap_scale.h - Bitmap scaling functions. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_BITMAP_SCALE_HEADER +#define GRUB_BITMAP_SCALE_HEADER 1 + +#include +#include +#include + +enum grub_video_bitmap_scale_method +{ + /* Choose the fastest interpolation algorithm. */ + GRUB_VIDEO_BITMAP_SCALE_METHOD_FASTEST, + /* Choose the highest quality interpolation algorithm. */ + GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST, + + /* Specific algorithms: */ + /* Nearest neighbor interpolation. */ + GRUB_VIDEO_BITMAP_SCALE_METHOD_NEAREST, + /* Bilinear interpolation. */ + GRUB_VIDEO_BITMAP_SCALE_METHOD_BILINEAR +}; + +grub_err_t +EXPORT_FUNC (grub_video_bitmap_create_scaled) (struct grub_video_bitmap **dst, + int dst_width, int dst_height, + struct grub_video_bitmap *src, + enum + grub_video_bitmap_scale_method + scale_method); + +#endif /* ! GRUB_BITMAP_SCALE_HEADER */ diff --git a/include/grub/bufio.h b/include/grub/bufio.h index 9a2294c26..acdd0c882 100644 --- a/include/grub/bufio.h +++ b/include/grub/bufio.h @@ -22,7 +22,7 @@ #include -grub_file_t grub_bufio_open (grub_file_t io, int size); -grub_file_t grub_buffile_open (const char *name, int size); +grub_file_t EXPORT_FUNC (grub_bufio_open) (grub_file_t io, int size); +grub_file_t EXPORT_FUNC (grub_buffile_open) (const char *name, int size); #endif /* ! GRUB_BUFIO_H */ diff --git a/include/grub/cache.h b/include/grub/cache.h index 745af43c3..27e44f0a2 100644 --- a/include/grub/cache.h +++ b/include/grub/cache.h @@ -23,6 +23,14 @@ #include #include +#if defined (__i386__) || defined (__x86_64__) +static inline void +grub_arch_sync_caches (void *address __attribute__ ((unused)), + grub_size_t len __attribute__ ((unused))) +{ +} +#else void EXPORT_FUNC(grub_arch_sync_caches) (void *address, grub_size_t len); +#endif #endif /* ! GRUB_CACHE_HEADER */ diff --git a/include/grub/cmos.h b/include/grub/cmos.h new file mode 100644 index 000000000..f508e3bf6 --- /dev/null +++ b/include/grub/cmos.h @@ -0,0 +1,72 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008, 2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_CMOS_H +#define GRUB_CMOS_H 1 + +#include +#include +#include + +#define GRUB_CMOS_INDEX_SECOND 0 +#define GRUB_CMOS_INDEX_SECOND_ALARM 1 +#define GRUB_CMOS_INDEX_MINUTE 2 +#define GRUB_CMOS_INDEX_MINUTE_ALARM 3 +#define GRUB_CMOS_INDEX_HOUR 4 +#define GRUB_CMOS_INDEX_HOUR_ALARM 5 +#define GRUB_CMOS_INDEX_DAY_OF_WEEK 6 +#define GRUB_CMOS_INDEX_DAY_OF_MONTH 7 +#define GRUB_CMOS_INDEX_MONTH 8 +#define GRUB_CMOS_INDEX_YEAR 9 + +#define GRUB_CMOS_INDEX_STATUS_A 0xA +#define GRUB_CMOS_INDEX_STATUS_B 0xB +#define GRUB_CMOS_INDEX_STATUS_C 0xC +#define GRUB_CMOS_INDEX_STATUS_D 0xD + +#define GRUB_CMOS_STATUS_B_DAYLIGHT 1 +#define GRUB_CMOS_STATUS_B_24HOUR 2 +#define GRUB_CMOS_STATUS_B_BINARY 4 + +static inline grub_uint8_t +grub_bcd_to_num (grub_uint8_t a) +{ + return ((a >> 4) * 10 + (a & 0xF)); +} + +static inline grub_uint8_t +grub_num_to_bcd (grub_uint8_t a) +{ + return (((a / 10) << 4) + (a % 10)); +} + +static inline grub_uint8_t +grub_cmos_read (grub_uint8_t index) +{ + grub_outb (index, GRUB_CMOS_ADDR_REG); + return grub_inb (GRUB_CMOS_DATA_REG); +} + +static inline void +grub_cmos_write (grub_uint8_t index, grub_uint8_t value) +{ + grub_outb (index, GRUB_CMOS_ADDR_REG); + grub_outb (value, GRUB_CMOS_DATA_REG); +} + +#endif /* GRUB_CMOS_H */ diff --git a/include/grub/dl.h b/include/grub/dl.h index 3f8b328da..ac0ecd336 100644 --- a/include/grub/dl.h +++ b/include/grub/dl.h @@ -110,10 +110,15 @@ int EXPORT_FUNC(grub_dl_unref) (grub_dl_t mod); #endif void EXPORT_FUNC(grub_dl_iterate) (int (*hook) (grub_dl_t mod)); grub_dl_t EXPORT_FUNC(grub_dl_get) (const char *name); -grub_err_t EXPORT_FUNC(grub_dl_register_symbol) (const char *name, void *addr, - grub_dl_t mod); +grub_err_t grub_dl_register_symbol (const char *name, void *addr, + grub_dl_t mod); grub_err_t grub_arch_dl_check_header (void *ehdr); grub_err_t grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr); +#if defined (_mips) && ! defined (GRUB_UTIL) +#define GRUB_LINKER_HAVE_INIT 1 +void grub_arch_dl_init_linker (void); +#endif + #endif /* ! GRUB_DL_H */ diff --git a/include/grub/elfload.h b/include/grub/elfload.h index 6e09e0d05..77ee41675 100644 --- a/include/grub/elfload.h +++ b/include/grub/elfload.h @@ -46,12 +46,12 @@ grub_elf_t grub_elf_file (grub_file_t); grub_err_t grub_elf_close (grub_elf_t); int grub_elf_is_elf32 (grub_elf_t); -grub_size_t grub_elf32_size (grub_elf_t); +grub_size_t grub_elf32_size (grub_elf_t, Elf32_Addr *); grub_err_t grub_elf32_load (grub_elf_t, grub_elf32_load_hook_t, grub_addr_t *, grub_size_t *); int grub_elf_is_elf64 (grub_elf_t); -grub_size_t grub_elf64_size (grub_elf_t); +grub_size_t grub_elf64_size (grub_elf_t, Elf64_Addr *); grub_err_t grub_elf64_load (grub_elf_t, grub_elf64_load_hook_t, grub_addr_t *, grub_size_t *); diff --git a/include/grub/env.h b/include/grub/env.h index 440185a59..ae4fd8745 100644 --- a/include/grub/env.h +++ b/include/grub/env.h @@ -22,6 +22,7 @@ #include #include #include +#include struct grub_env_var; @@ -30,18 +31,6 @@ typedef char *(*grub_env_read_hook_t) (struct grub_env_var *var, typedef char *(*grub_env_write_hook_t) (struct grub_env_var *var, const char *val); -enum grub_env_var_type - { - /* The default variable type which is local in current context. */ - GRUB_ENV_VAR_LOCAL, - - /* The exported type, which is passed to new contexts. */ - GRUB_ENV_VAR_GLOBAL, - - /* The data slot type, which is used to store arbitrary data. */ - GRUB_ENV_VAR_DATA - }; - struct grub_env_var { char *name; @@ -50,23 +39,24 @@ struct grub_env_var grub_env_write_hook_t write_hook; struct grub_env_var *next; struct grub_env_var **prevp; - enum grub_env_var_type type; + int global; }; grub_err_t EXPORT_FUNC(grub_env_set) (const char *name, const char *val); char *EXPORT_FUNC(grub_env_get) (const char *name); void EXPORT_FUNC(grub_env_unset) (const char *name); void EXPORT_FUNC(grub_env_iterate) (int (*func) (struct grub_env_var *var)); +struct grub_env_var *EXPORT_FUNC(grub_env_find) (const char *name); grub_err_t EXPORT_FUNC(grub_register_variable_hook) (const char *name, grub_env_read_hook_t read_hook, grub_env_write_hook_t write_hook); -grub_err_t EXPORT_FUNC(grub_env_context_open) (int export); -grub_err_t EXPORT_FUNC(grub_env_context_close) (void); -grub_err_t EXPORT_FUNC(grub_env_export) (const char *name); -grub_err_t EXPORT_FUNC(grub_env_set_data_slot) (const char *name, - const void *ptr); -void *EXPORT_FUNC(grub_env_get_data_slot) (const char *name); -void EXPORT_FUNC(grub_env_unset_data_slot) (const char *name); +grub_err_t grub_env_context_open (int export); +grub_err_t grub_env_context_close (void); +grub_err_t grub_env_export (const char *name); + +void grub_env_unset_menu (void); +grub_menu_t grub_env_get_menu (void); +void grub_env_set_menu (grub_menu_t nmenu); #endif /* ! GRUB_ENV_HEADER */ diff --git a/include/grub/env_private.h b/include/grub/env_private.h new file mode 100644 index 000000000..bb001533f --- /dev/null +++ b/include/grub/env_private.h @@ -0,0 +1,46 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2005,2006,2007,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_ENV_PRIVATE_HEADER +#define GRUB_ENV_PRIVATE_HEADER 1 + +#include + +/* The size of the hash table. */ +#define HASHSZ 13 + +/* A hashtable for quick lookup of variables. */ +struct grub_env_context +{ + /* A hash table for variables. */ + struct grub_env_var *vars[HASHSZ]; + + /* One level deeper on the stack. */ + struct grub_env_context *prev; +}; + +/* This is used for sorting only. */ +struct grub_env_sorted_var +{ + struct grub_env_var *var; + struct grub_env_sorted_var *next; +}; + +extern struct grub_env_context *EXPORT_VAR(grub_current_context); + +#endif /* ! GRUB_ENV_PRIVATE_HEADER */ diff --git a/include/grub/err.h b/include/grub/err.h index 7a5ce1ae0..e44705389 100644 --- a/include/grub/err.h +++ b/include/grub/err.h @@ -66,7 +66,7 @@ void EXPORT_FUNC(grub_fatal) (const char *fmt, ...) __attribute__ ((noreturn)); void EXPORT_FUNC(grub_error_push) (void); int EXPORT_FUNC(grub_error_pop) (void); void EXPORT_FUNC(grub_print_error) (void); -int EXPORT_FUNC(grub_err_printf) (const char *fmt, ...) -__attribute__ ((format (printf, 1, 2))); +int grub_err_printf (const char *fmt, ...) + __attribute__ ((format (printf, 1, 2))); #endif /* ! GRUB_ERR_HEADER */ diff --git a/include/grub/font.h b/include/grub/font.h index 8a5f3ac7d..7c5c17403 100644 --- a/include/grub/font.h +++ b/include/grub/font.h @@ -21,6 +21,7 @@ #include #include +#include /* Forward declaration of opaque structure grub_font. Users only pass struct grub_font pointers to the font module functions, @@ -80,36 +81,38 @@ int grub_font_load (const char *filename); "Family Name Bold Italic 14", where Bold and Italic are optional. If no font matches the name specified, the most recently loaded font is returned as a fallback. */ -grub_font_t grub_font_get (const char *font_name); +grub_font_t EXPORT_FUNC (grub_font_get) (const char *font_name); -const char *grub_font_get_name (grub_font_t font); +const char *EXPORT_FUNC (grub_font_get_name) (grub_font_t font); -int grub_font_get_max_char_width (grub_font_t font); +int EXPORT_FUNC (grub_font_get_max_char_width) (grub_font_t font); -int grub_font_get_max_char_height (grub_font_t font); +int EXPORT_FUNC (grub_font_get_max_char_height) (grub_font_t font); -int grub_font_get_ascent (grub_font_t font); +int EXPORT_FUNC (grub_font_get_ascent) (grub_font_t font); -int grub_font_get_descent (grub_font_t font); +int EXPORT_FUNC (grub_font_get_descent) (grub_font_t font); -int grub_font_get_leading (grub_font_t font); +int EXPORT_FUNC (grub_font_get_leading) (grub_font_t font); -int grub_font_get_height (grub_font_t font); +int EXPORT_FUNC (grub_font_get_height) (grub_font_t font); -int grub_font_get_string_width (grub_font_t font, const char *str); +int EXPORT_FUNC (grub_font_get_string_width) (grub_font_t font, + const char *str); -struct grub_font_glyph *grub_font_get_glyph (grub_font_t font, - grub_uint32_t code); +struct grub_font_glyph *EXPORT_FUNC (grub_font_get_glyph) (grub_font_t font, + grub_uint32_t code); -struct grub_font_glyph *grub_font_get_glyph_with_fallback (grub_font_t font, - grub_uint32_t code); +struct grub_font_glyph *EXPORT_FUNC (grub_font_get_glyph_with_fallback) (grub_font_t font, + grub_uint32_t code); -grub_err_t grub_font_draw_glyph (struct grub_font_glyph *glyph, - grub_video_color_t color, - int left_x, int baseline_y); +grub_err_t EXPORT_FUNC (grub_font_draw_glyph) (struct grub_font_glyph *glyph, + grub_video_color_t color, + int left_x, int baseline_y); -grub_err_t grub_font_draw_string (const char *str, grub_font_t font, - grub_video_color_t color, - int left_x, int baseline_y); +grub_err_t EXPORT_FUNC (grub_font_draw_string) (const char *str, + grub_font_t font, + grub_video_color_t color, + int left_x, int baseline_y); #endif /* ! GRUB_FONT_HEADER */ diff --git a/include/grub/fontformat.h b/include/grub/fontformat.h new file mode 100644 index 000000000..b5060588c --- /dev/null +++ b/include/grub/fontformat.h @@ -0,0 +1,38 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_FONT_FORMAT_HEADER +#define GRUB_FONT_FORMAT_HEADER 1 + +/* FONT_FORMAT_PFF2_MAGIC use only 4 relevants bytes and the \0. */ +#define FONT_FORMAT_PFF2_MAGIC "PFF2" +#define FONT_FORMAT_SECTION_NAMES_FILE "FILE" +#define FONT_FORMAT_SECTION_NAMES_FONT_NAME "NAME" +#define FONT_FORMAT_SECTION_NAMES_POINT_SIZE "PTSZ" +#define FONT_FORMAT_SECTION_NAMES_WEIGHT "WEIG" +#define FONT_FORMAT_SECTION_NAMES_MAX_CHAR_WIDTH "MAXW" +#define FONT_FORMAT_SECTION_NAMES_MAX_CHAR_HEIGHT "MAXH" +#define FONT_FORMAT_SECTION_NAMES_ASCENT "ASCE" +#define FONT_FORMAT_SECTION_NAMES_DESCENT "DESC" +#define FONT_FORMAT_SECTION_NAMES_CHAR_INDEX "CHIX" +#define FONT_FORMAT_SECTION_NAMES_DATA "DATA" +#define FONT_FORMAT_SECTION_NAMES_FAMILY "FAMI" +#define FONT_FORMAT_SECTION_NAMES_SLAN "SLAN" + +#endif /* ! GRUB_FONT_FORMAT_HEADER */ + diff --git a/include/grub/gfxmenu_model.h b/include/grub/gfxmenu_model.h new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/include/grub/gfxmenu_model.h @@ -0,0 +1 @@ + diff --git a/include/grub/gfxmenu_view.h b/include/grub/gfxmenu_view.h new file mode 100644 index 000000000..7cbfa89d3 --- /dev/null +++ b/include/grub/gfxmenu_view.h @@ -0,0 +1,107 @@ +/* gfxmenu_view.h - gfxmenu view interface. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_GFXMENU_VIEW_HEADER +#define GRUB_GFXMENU_VIEW_HEADER 1 + +#include +#include +#include +#include +#include + +struct grub_gfxmenu_view; /* Forward declaration of opaque type. */ +typedef struct grub_gfxmenu_view *grub_gfxmenu_view_t; + + +grub_gfxmenu_view_t grub_gfxmenu_view_new (const char *theme_path, + int width, int height); + +void grub_gfxmenu_view_destroy (grub_gfxmenu_view_t view); + +/* Set properties on the view based on settings from the specified + theme file. */ +grub_err_t grub_gfxmenu_view_load_theme (grub_gfxmenu_view_t view, + const char *theme_path); + +grub_err_t grub_gui_recreate_box (grub_gfxmenu_box_t *boxptr, + const char *pattern, const char *theme_dir); + +void grub_gfxmenu_view_draw (grub_gfxmenu_view_t view); + +void +grub_gfxmenu_redraw_menu (grub_gfxmenu_view_t view); + +void +grub_gfxmenu_redraw_timeout (grub_gfxmenu_view_t view); + +void +grub_gfxmenu_view_redraw (grub_gfxmenu_view_t view, + const grub_video_rect_t *region); + +void +grub_gfxmenu_clear_timeout (void *data); +void +grub_gfxmenu_print_timeout (int timeout, void *data); +void +grub_gfxmenu_set_chosen_entry (int entry, void *data); + +/* Implementation details -- this should not be used outside of the + view itself. */ + +#include +#include +#include +#include +#include + +/* Definition of the private representation of the view. */ +struct grub_gfxmenu_view +{ + grub_video_rect_t screen; + + grub_font_t title_font; + grub_font_t message_font; + char *terminal_font_name; + grub_gui_color_t title_color; + grub_gui_color_t message_color; + grub_gui_color_t message_bg_color; + struct grub_video_bitmap *desktop_image; + grub_gui_color_t desktop_color; + grub_gfxmenu_box_t terminal_box; + char *title_text; + char *progress_message_text; + char *theme_path; + + grub_gui_container_t canvas; + + int double_repaint; + + int selected; + + grub_video_rect_t progress_message_frame; + + grub_menu_t menu; + + int nested; + + int first_timeout; +}; + +#endif /* ! GRUB_GFXMENU_VIEW_HEADER */ diff --git a/include/grub/gfxterm.h b/include/grub/gfxterm.h new file mode 100644 index 000000000..295354baf --- /dev/null +++ b/include/grub/gfxterm.h @@ -0,0 +1,44 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006,2007,2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_GFXTERM_HEADER +#define GRUB_GFXTERM_HEADER 1 + +#include +#include +#include +#include + +grub_err_t +EXPORT_FUNC (grub_gfxterm_set_window) (struct grub_video_render_target *target, + int x, int y, int width, int height, + int double_repaint, + const char *font_name, int border_width); + +typedef void (*grub_gfxterm_repaint_callback_t)(int x, int y, + int width, int height); + +void grub_gfxterm_set_repaint_callback (grub_gfxterm_repaint_callback_t func); + +void EXPORT_FUNC (grub_gfxterm_schedule_repaint) (void); + +grub_err_t EXPORT_FUNC (grub_gfxterm_fullscreen) (void); + +extern void (*EXPORT_VAR (grub_gfxterm_decorator_hook)) (void); + +#endif /* ! GRUB_GFXTERM_HEADER */ diff --git a/include/grub/gfxwidgets.h b/include/grub/gfxwidgets.h new file mode 100644 index 000000000..f9678bf9e --- /dev/null +++ b/include/grub/gfxwidgets.h @@ -0,0 +1,49 @@ +/* gfxwidgets.h - Widgets for the graphical menu (gfxmenu). */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_GFXWIDGETS_HEADER +#define GRUB_GFXWIDGETS_HEADER 1 + +#include + +typedef struct grub_gfxmenu_box *grub_gfxmenu_box_t; + +struct grub_gfxmenu_box +{ + /* The size of the content. */ + int content_width; + int content_height; + + struct grub_video_bitmap **raw_pixmaps; + struct grub_video_bitmap **scaled_pixmaps; + + void (*draw) (grub_gfxmenu_box_t self, int x, int y); + void (*set_content_size) (grub_gfxmenu_box_t self, + int width, int height); + int (*get_left_pad) (grub_gfxmenu_box_t self); + int (*get_top_pad) (grub_gfxmenu_box_t self); + int (*get_right_pad) (grub_gfxmenu_box_t self); + int (*get_bottom_pad) (grub_gfxmenu_box_t self); + void (*destroy) (grub_gfxmenu_box_t self); +}; + +grub_gfxmenu_box_t grub_gfxmenu_create_box (const char *pixmaps_prefix, + const char *pixmaps_suffix); + +#endif /* ! GRUB_GFXWIDGETS_HEADER */ diff --git a/include/grub/gui.h b/include/grub/gui.h new file mode 100644 index 000000000..7bd71acd3 --- /dev/null +++ b/include/grub/gui.h @@ -0,0 +1,230 @@ +/* gui.h - GUI components header file. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include + +#ifndef GRUB_GUI_H +#define GRUB_GUI_H 1 + +/* A representation of a color. Unlike grub_video_color_t, this + representation is independent of any video mode specifics. */ +typedef struct grub_gui_color +{ + grub_uint8_t red; + grub_uint8_t green; + grub_uint8_t blue; + grub_uint8_t alpha; +} grub_gui_color_t; + +typedef struct grub_gui_component *grub_gui_component_t; +typedef struct grub_gui_container *grub_gui_container_t; +typedef struct grub_gui_list *grub_gui_list_t; + +typedef void (*grub_gui_component_callback) (grub_gui_component_t component, + void *userdata); + +/* Component interface. */ + +struct grub_gui_component_ops +{ + void (*destroy) (void *self); + const char * (*get_id) (void *self); + int (*is_instance) (void *self, const char *type); + void (*paint) (void *self, const grub_video_rect_t *bounds); + void (*set_parent) (void *self, grub_gui_container_t parent); + grub_gui_container_t (*get_parent) (void *self); + void (*set_bounds) (void *self, const grub_video_rect_t *bounds); + void (*get_bounds) (void *self, grub_video_rect_t *bounds); + void (*get_minimal_size) (void *self, unsigned *width, unsigned *height); + grub_err_t (*set_property) (void *self, const char *name, const char *value); + void (*repaint) (void *self, int second_pass); +}; + +struct grub_gui_container_ops +{ + void (*add) (void *self, grub_gui_component_t comp); + void (*remove) (void *self, grub_gui_component_t comp); + void (*iterate_children) (void *self, + grub_gui_component_callback cb, void *userdata); +}; + +struct grub_gui_list_ops +{ + void (*set_view_info) (void *self, + grub_gfxmenu_view_t view); +}; + +struct grub_gui_progress_ops +{ + void (*set_state) (void *self, int visible, int start, int current, int end); +}; + +typedef signed grub_fixed_signed_t; +#define GRUB_FIXED_1 0x10000 + +static inline signed +grub_fixed_sfs_divide (signed a, grub_fixed_signed_t b) +{ + return (a * GRUB_FIXED_1) / b; +} + +static inline grub_fixed_signed_t +grub_fixed_fsf_divide (grub_fixed_signed_t a, signed b) +{ + return a / b; +} + +static inline signed +grub_fixed_sfs_multiply (signed a, grub_fixed_signed_t b) +{ + return (a * b) / GRUB_FIXED_1; +} + +static inline signed +grub_fixed_to_signed (grub_fixed_signed_t in) +{ + return in / GRUB_FIXED_1; +} + +static inline grub_fixed_signed_t +grub_signed_to_fixed (signed in) +{ + return in * GRUB_FIXED_1; +} + +struct grub_gui_component +{ + struct grub_gui_component_ops *ops; + signed x; + grub_fixed_signed_t xfrac; + signed y; + grub_fixed_signed_t yfrac; + signed w; + grub_fixed_signed_t wfrac; + signed h; + grub_fixed_signed_t hfrac; +}; + +struct grub_gui_progress +{ + struct grub_gui_component component; + struct grub_gui_progress_ops *ops; +}; + +struct grub_gui_container +{ + struct grub_gui_component component; + struct grub_gui_container_ops *ops; +}; + +struct grub_gui_list +{ + struct grub_gui_component component; + struct grub_gui_list_ops *ops; +}; + + +/* Interfaces to concrete component classes. */ + +grub_gui_container_t grub_gui_canvas_new (void); +grub_gui_container_t grub_gui_vbox_new (void); +grub_gui_container_t grub_gui_hbox_new (void); +grub_gui_component_t grub_gui_label_new (void); +grub_gui_component_t grub_gui_image_new (void); +grub_gui_component_t grub_gui_progress_bar_new (void); +grub_gui_component_t grub_gui_list_new (void); +grub_gui_component_t grub_gui_circular_progress_new (void); + +/* Manipulation functions. */ + +/* Visit all components with the specified ID. */ +void grub_gui_find_by_id (grub_gui_component_t root, + const char *id, + grub_gui_component_callback cb, + void *userdata); + +/* Visit all components. */ +void grub_gui_iterate_recursively (grub_gui_component_t root, + grub_gui_component_callback cb, + void *userdata); + +/* Helper functions. */ + +static __inline void +grub_gui_save_viewport (grub_video_rect_t *r) +{ + grub_video_get_viewport ((unsigned *) &r->x, + (unsigned *) &r->y, + (unsigned *) &r->width, + (unsigned *) &r->height); +} + +static __inline void +grub_gui_restore_viewport (const grub_video_rect_t *r) +{ + grub_video_set_viewport (r->x, r->y, r->width, r->height); +} + +/* Set a new viewport relative the the current one, saving the current + viewport in OLD so it can be later restored. */ +static __inline void +grub_gui_set_viewport (const grub_video_rect_t *r, grub_video_rect_t *old) +{ + grub_gui_save_viewport (old); + grub_video_set_viewport (old->x + r->x, + old->y + r->y, + r->width, + r->height); +} + +static __inline grub_gui_color_t +grub_gui_color_rgb (int r, int g, int b) +{ + grub_gui_color_t c; + c.red = r; + c.green = g; + c.blue = b; + c.alpha = 255; + return c; +} + +static __inline grub_video_color_t +grub_gui_map_color (grub_gui_color_t c) +{ + return grub_video_map_rgba (c.red, c.green, c.blue, c.alpha); +} + +static inline int +grub_video_have_common_points (const grub_video_rect_t *a, + const grub_video_rect_t *b) +{ + if (!((a->x <= b->x && b->x <= a->x + a->width) + || (b->x <= a->x && a->x <= b->x + b->width))) + return 0; + if (!((a->y <= b->y && b->y <= a->y + a->height) + || (b->y <= a->y && a->y <= b->y + b->height))) + return 0; + return 1; +} + +#endif /* ! GRUB_GUI_H */ diff --git a/include/grub/gui_string_util.h b/include/grub/gui_string_util.h new file mode 100644 index 000000000..1baa2eede --- /dev/null +++ b/include/grub/gui_string_util.h @@ -0,0 +1,37 @@ +/* gui_string_util.h - String utilities for the graphical menu interface. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_GUI_STRING_UTIL_HEADER +#define GRUB_GUI_STRING_UTIL_HEADER 1 + +#include +#include + +char *grub_new_substring (const char *buf, + grub_size_t start, grub_size_t end); + +char *grub_resolve_relative_path (const char *base, const char *path); + +char *grub_get_dirname (const char *file_path); + +int grub_gui_get_named_color (const char *name, grub_gui_color_t *color); + +grub_err_t grub_gui_parse_color (const char *s, grub_gui_color_t *color); + +#endif /* GRUB_GUI_STRING_UTIL_HEADER */ diff --git a/include/grub/i18n.h b/include/grub/i18n.h index 4d4a0b7bd..0cba54765 100644 --- a/include/grub/i18n.h +++ b/include/grub/i18n.h @@ -22,7 +22,6 @@ #include #include -const char *EXPORT_FUNC(grub_gettext_dummy) (const char *s); extern const char *(*EXPORT_VAR(grub_gettext)) (const char *s); /* NLS can be disabled through the configure --disable-nls option. */ diff --git a/include/grub/i386/at_keyboard.h b/include/grub/i386/at_keyboard.h index e6ee60d28..da4e80654 100644 --- a/include/grub/i386/at_keyboard.h +++ b/include/grub/i386/at_keyboard.h @@ -19,40 +19,7 @@ #ifndef GRUB_CPU_AT_KEYBOARD_HEADER #define GRUB_CPU_AT_KEYBOARD_HEADER 1 - -#define SHIFT_L 0x2a -#define SHIFT_R 0x36 -#define CTRL 0x1d -#define ALT 0x38 -#define CAPS_LOCK 0x3a -#define NUM_LOCK 0x45 -#define SCROLL_LOCK 0x46 - #define KEYBOARD_REG_DATA 0x60 #define KEYBOARD_REG_STATUS 0x64 -/* Used for sending commands to the controller. */ -#define KEYBOARD_COMMAND_ISREADY(x) !((x) & 0x02) -#define KEYBOARD_COMMAND_READ 0x20 -#define KEYBOARD_COMMAND_WRITE 0x60 -#define KEYBOARD_COMMAND_REBOOT 0xfe - -#define KEYBOARD_SCANCODE_SET1 0x40 - -#define KEYBOARD_ISMAKE(x) !((x) & 0x80) -#define KEYBOARD_ISREADY(x) ((x) & 0x01) -#define KEYBOARD_SCANCODE(x) ((x) & 0x7f) - -#ifdef GRUB_MACHINE_IEEE1275 -#define OLPC_UP GRUB_TERM_UP -#define OLPC_DOWN GRUB_TERM_DOWN -#define OLPC_LEFT GRUB_TERM_LEFT -#define OLPC_RIGHT GRUB_TERM_RIGHT -#else -#define OLPC_UP '\0' -#define OLPC_DOWN '\0' -#define OLPC_LEFT '\0' -#define OLPC_RIGHT '\0' -#endif - #endif diff --git a/include/grub/i386/bsd.h b/include/grub/i386/bsd.h index 8ffaf7d18..4d55f04fb 100644 --- a/include/grub/i386/bsd.h +++ b/include/grub/i386/bsd.h @@ -20,6 +20,13 @@ #define GRUB_BSD_CPU_HEADER 1 #include +#include +#include +#include +#include +#include +#include + enum bsd_kernel_types { @@ -31,61 +38,11 @@ enum bsd_kernel_types #define GRUB_BSD_TEMP_BUFFER 0x80000 -#define FREEBSD_RB_ASKNAME (1 << 0) /* ask for file name to reboot from */ -#define FREEBSD_RB_SINGLE (1 << 1) /* reboot to single user only */ -#define FREEBSD_RB_NOSYNC (1 << 2) /* dont sync before reboot */ -#define FREEBSD_RB_HALT (1 << 3) /* don't reboot, just halt */ -#define FREEBSD_RB_INITNAME (1 << 4) /* name given for /etc/init (unused) */ -#define FREEBSD_RB_DFLTROOT (1 << 5) /* use compiled-in rootdev */ -#define FREEBSD_RB_KDB (1 << 6) /* give control to kernel debugger */ -#define FREEBSD_RB_RDONLY (1 << 7) /* mount root fs read-only */ -#define FREEBSD_RB_DUMP (1 << 8) /* dump kernel memory before reboot */ -#define FREEBSD_RB_MINIROOT (1 << 9) /* mini-root present in memory at boot time */ -#define FREEBSD_RB_CONFIG (1 << 10) /* invoke user configuration routing */ -#define FREEBSD_RB_VERBOSE (1 << 11) /* print all potentially useful info */ -#define FREEBSD_RB_SERIAL (1 << 12) /* user serial port as console */ -#define FREEBSD_RB_CDROM (1 << 13) /* use cdrom as root */ -#define FREEBSD_RB_GDB (1 << 15) /* use GDB remote debugger instead of DDB */ -#define FREEBSD_RB_MUTE (1 << 16) /* Come up with the console muted */ -#define FREEBSD_RB_PAUSE (1 << 20) -#define FREEBSD_RB_QUIET (1 << 21) -#define FREEBSD_RB_NOINTR (1 << 28) -#define FREENSD_RB_MULTIPLE (1 << 29) /* Use multiple consoles */ -#define FREEBSD_RB_DUAL FREENSD_RB_MULTIPLE -#define FREEBSD_RB_BOOTINFO (1 << 31) /* have `struct bootinfo *' arg */ - -#define FREEBSD_B_DEVMAGIC 0xa0000000 -#define FREEBSD_B_SLICESHIFT 20 -#define FREEBSD_B_UNITSHIFT 16 -#define FREEBSD_B_PARTSHIFT 8 -#define FREEBSD_B_TYPESHIFT 0 - -#define FREEBSD_BOOTINFO_VERSION 1 -#define FREEBSD_N_BIOS_GEOM 8 - -#define FREEBSD_MODINFO_END 0x0000 /* End of list */ -#define FREEBSD_MODINFO_NAME 0x0001 /* Name of module (string) */ -#define FREEBSD_MODINFO_TYPE 0x0002 /* Type of module (string) */ -#define FREEBSD_MODINFO_ADDR 0x0003 /* Loaded address */ -#define FREEBSD_MODINFO_SIZE 0x0004 /* Size of module */ -#define FREEBSD_MODINFO_EMPTY 0x0005 /* Has been deleted */ -#define FREEBSD_MODINFO_ARGS 0x0006 /* Parameters string */ -#define FREEBSD_MODINFO_METADATA 0x8000 /* Module-specfic */ - -#define FREEBSD_MODINFOMD_AOUTEXEC 0x0001 /* a.out exec header */ -#define FREEBSD_MODINFOMD_ELFHDR 0x0002 /* ELF header */ -#define FREEBSD_MODINFOMD_SSYM 0x0003 /* start of symbols */ -#define FREEBSD_MODINFOMD_ESYM 0x0004 /* end of symbols */ -#define FREEBSD_MODINFOMD_DYNAMIC 0x0005 /* _DYNAMIC pointer */ -#define FREEBSD_MODINFOMD_ENVP 0x0006 /* envp[] */ -#define FREEBSD_MODINFOMD_HOWTO 0x0007 /* boothowto */ -#define FREEBSD_MODINFOMD_KERNEND 0x0008 /* kernend */ -#define FREEBSD_MODINFOMD_SHDR 0x0009 /* section header table */ -#define FREEBSD_MODINFOMD_NOCOPY 0x8000 /* don't copy this metadata to the kernel */ - -#define FREEBSD_MODINFOMD_SMAP 0x1001 - -#define FREEBSD_MODINFOMD_DEPLIST (0x4001 | FREEBSD_MODINFOMD_NOCOPY) /* depends on */ +#define FREEBSD_B_DEVMAGIC OPENBSD_B_DEVMAGIC +#define FREEBSD_B_SLICESHIFT OPENBSD_B_CTRLSHIFT +#define FREEBSD_B_UNITSHIFT OPENBSD_B_UNITSHIFT +#define FREEBSD_B_PARTSHIFT OPENBSD_B_PARTSHIFT +#define FREEBSD_B_TYPESHIFT OPENBSD_B_TYPESHIFT #define FREEBSD_MODTYPE_KERNEL "elf kernel" #define FREEBSD_MODTYPE_KERNEL64 "elf64 kernel" @@ -93,64 +50,21 @@ enum bsd_kernel_types #define FREEBSD_MODTYPE_ELF_MODULE_OBJ "elf obj module" #define FREEBSD_MODTYPE_RAW "raw" +#define FREEBSD_BOOTINFO_VERSION 1 + struct grub_freebsd_bootinfo { - grub_uint32_t bi_version; - grub_uint8_t *bi_kernelname; - struct nfs_diskless *bi_nfs_diskless; - grub_uint32_t bi_n_bios_used; - grub_uint32_t bi_bios_geom[FREEBSD_N_BIOS_GEOM]; - grub_uint32_t bi_size; - grub_uint8_t bi_memsizes_valid; - grub_uint8_t bi_bios_dev; - grub_uint8_t bi_pad[2]; - grub_uint32_t bi_basemem; - grub_uint32_t bi_extmem; - grub_uint32_t bi_symtab; - grub_uint32_t bi_esymtab; - grub_uint32_t bi_kernend; - grub_uint32_t bi_envp; - grub_uint32_t bi_modulep; + grub_uint32_t version; + grub_uint8_t unused1[44]; + grub_uint32_t length; + grub_uint8_t unused2; + grub_uint8_t boot_device; + grub_uint8_t unused3[18]; + grub_uint32_t kern_end; + grub_uint32_t environment; + grub_uint32_t tags; } __attribute__ ((packed)); -#define OPENBSD_RB_ASKNAME (1 << 0) /* ask for file name to reboot from */ -#define OPENBSD_RB_SINGLE (1 << 1) /* reboot to single user only */ -#define OPENBSD_RB_NOSYNC (1 << 2) /* dont sync before reboot */ -#define OPENBSD_RB_HALT (1 << 3) /* don't reboot, just halt */ -#define OPENBSD_RB_INITNAME (1 << 4) /* name given for /etc/init (unused) */ -#define OPENBSD_RB_DFLTROOT (1 << 5) /* use compiled-in rootdev */ -#define OPENBSD_RB_KDB (1 << 6) /* give control to kernel debugger */ -#define OPENBSD_RB_RDONLY (1 << 7) /* mount root fs read-only */ -#define OPENBSD_RB_DUMP (1 << 8) /* dump kernel memory before reboot */ -#define OPENBSD_RB_MINIROOT (1 << 9) /* mini-root present in memory at boot time */ -#define OPENBSD_RB_CONFIG (1 << 10) /* change configured devices */ -#define OPENBSD_RB_TIMEBAD (1 << 11) /* don't call resettodr() in boot() */ -#define OPENBSD_RB_POWERDOWN (1 << 12) /* attempt to power down machine */ -#define OPENBSD_RB_SERCONS (1 << 13) /* use serial console if available */ -#define OPENBSD_RB_USERREQ (1 << 14) /* boot() called at user request (e.g. ddb) */ - -#define OPENBSD_B_DEVMAGIC 0xa0000000 -#define OPENBSD_B_ADAPTORSHIFT 24 -#define OPENBSD_B_CTRLSHIFT 20 -#define OPENBSD_B_UNITSHIFT 16 -#define OPENBSD_B_PARTSHIFT 8 -#define OPENBSD_B_TYPESHIFT 0 - -#define OPENBSD_BOOTARG_APIVER (OPENBSD_BAPIV_VECTOR | \ - OPENBSD_BAPIV_ENV | \ - OPENBSD_BAPIV_BMEMMAP) - -#define OPENBSD_BAPIV_ANCIENT 0x0 /* MD old i386 bootblocks */ -#define OPENBSD_BAPIV_VARS 0x1 /* MD structure w/ add info passed */ -#define OPENBSD_BAPIV_VECTOR 0x2 /* MI vector of MD structures passed */ -#define OPENBSD_BAPIV_ENV 0x4 /* MI environment vars vector */ -#define OPENBSD_BAPIV_BMEMMAP 0x8 /* MI memory map passed is in bytes */ - -#define OPENBSD_BOOTARG_ENV 0x1000 -#define OPENBSD_BOOTARG_END -1 - -#define OPENBSD_BOOTARG_MMAP 0 - struct grub_openbsd_bios_mmap { grub_uint64_t addr; @@ -162,97 +76,6 @@ struct grub_openbsd_bios_mmap grub_uint32_t type; }; -struct grub_openbsd_bootargs -{ - int ba_type; - int ba_size; - struct grub_openbsd_bootargs *ba_next; -} __attribute__ ((packed)); - -#define NETBSD_RB_AUTOBOOT 0 /* flags for system auto-booting itself */ - -#define NETBSD_RB_ASKNAME (1 << 0) /* ask for file name to reboot from */ -#define NETBSD_RB_SINGLE (1 << 1) /* reboot to single user only */ -#define NETBSD_RB_NOSYNC (1 << 2) /* dont sync before reboot */ -#define NETBSD_RB_HALT (1 << 3) /* don't reboot, just halt */ -#define NETBSD_RB_INITNAME (1 << 4) /* name given for /etc/init (unused) */ -#define NETBSD_RB_UNUSED1 (1 << 5) /* was RB_DFLTROOT, obsolete */ -#define NETBSD_RB_KDB (1 << 6) /* give control to kernel debugger */ -#define NETBSD_RB_RDONLY (1 << 7) /* mount root fs read-only */ -#define NETBSD_RB_DUMP (1 << 8) /* dump kernel memory before reboot */ -#define NETBSD_RB_MINIROOT (1 << 9) /* mini-root present in memory at boot time */ -#define NETBSD_RB_STRING (1 << 10) /* use provided bootstr */ -#define NETBSD_RB_POWERDOWN ((1 << 11) | RB_HALT) /* turn power off (or at least halt) */ -#define NETBSD_RB_USERCONFIG (1 << 12) /* change configured devices */ - -#define NETBSD_AB_NORMAL 0 /* boot normally (default) */ - -#define NETBSD_AB_QUIET (1 << 16) /* boot quietly */ -#define NETBSD_AB_VERBOSE (1 << 17) /* boot verbosely */ -#define NETBSD_AB_SILENT (1 << 18) /* boot silently */ -#define NETBSD_AB_DEBUG (1 << 19) /* boot with debug messages */ -#define NETBSD_AB_NOSMP (1 << 28) /* Boot without SMP support. */ -#define NETBSD_AB_NOACPI (1 << 29) /* Boot without ACPI support. */ - -struct grub_netbsd_bootinfo -{ - grub_uint32_t bi_count; - void *bi_data[1]; -}; - -#define NETBSD_BTINFO_BOOTPATH 0 -#define NETBSD_BTINFO_ROOTDEVICE 1 -#define NETBSD_BTINFO_BOOTDISK 3 -#define NETBSD_BTINFO_MEMMAP 9 - -struct grub_netbsd_btinfo_common -{ - int len; - int type; -}; - -struct grub_netbsd_btinfo_mmap_header -{ - struct grub_netbsd_btinfo_common common; - grub_uint32_t count; -}; - -struct grub_netbsd_btinfo_mmap_entry -{ - grub_uint64_t addr; - grub_uint64_t len; -#define NETBSD_MMAP_AVAILABLE 1 -#define NETBSD_MMAP_RESERVED 2 -#define NETBSD_MMAP_ACPI 3 -#define NETBSD_MMAP_NVS 4 - grub_uint32_t type; -}; - -struct grub_netbsd_btinfo_bootpath -{ - struct grub_netbsd_btinfo_common common; - char bootpath[80]; -}; - -struct grub_netbsd_btinfo_rootdevice -{ - struct grub_netbsd_btinfo_common common; - char devname[16]; -}; - -struct grub_netbsd_btinfo_bootdisk -{ - struct grub_netbsd_btinfo_common common; - int labelsector; /* label valid if != -1 */ - struct - { - grub_uint16_t type, checksum; - char packname[16]; - } label; - int biosdev; - int partition; -}; - void grub_unix_real_boot (grub_addr_t entry, ...) __attribute__ ((cdecl,noreturn)); grub_err_t grub_freebsd_load_elfmodule32 (grub_file_t file, int argc, diff --git a/include/grub/i386/cmos.h b/include/grub/i386/cmos.h index 1c0530dba..8b1fa3586 100644 --- a/include/grub/i386/cmos.h +++ b/include/grub/i386/cmos.h @@ -20,55 +20,9 @@ #define GRUB_CPU_CMOS_H 1 #include -#include +#include #define GRUB_CMOS_ADDR_REG 0x70 #define GRUB_CMOS_DATA_REG 0x71 -#define GRUB_CMOS_INDEX_SECOND 0 -#define GRUB_CMOS_INDEX_SECOND_ALARM 1 -#define GRUB_CMOS_INDEX_MINUTE 2 -#define GRUB_CMOS_INDEX_MINUTE_ALARM 3 -#define GRUB_CMOS_INDEX_HOUR 4 -#define GRUB_CMOS_INDEX_HOUR_ALARM 5 -#define GRUB_CMOS_INDEX_DAY_OF_WEEK 6 -#define GRUB_CMOS_INDEX_DAY_OF_MONTH 7 -#define GRUB_CMOS_INDEX_MONTH 8 -#define GRUB_CMOS_INDEX_YEAR 9 - -#define GRUB_CMOS_INDEX_STATUS_A 0xA -#define GRUB_CMOS_INDEX_STATUS_B 0xB -#define GRUB_CMOS_INDEX_STATUS_C 0xC -#define GRUB_CMOS_INDEX_STATUS_D 0xD - -#define GRUB_CMOS_STATUS_B_DAYLIGHT 1 -#define GRUB_CMOS_STATUS_B_24HOUR 2 -#define GRUB_CMOS_STATUS_B_BINARY 4 - -static inline grub_uint8_t -grub_bcd_to_num (grub_uint8_t a) -{ - return ((a >> 4) * 10 + (a & 0xF)); -} - -static inline grub_uint8_t -grub_num_to_bcd (grub_uint8_t a) -{ - return (((a / 10) << 4) + (a % 10)); -} - -static inline grub_uint8_t -grub_cmos_read (grub_uint8_t index) -{ - grub_outb (index, GRUB_CMOS_ADDR_REG); - return grub_inb (GRUB_CMOS_DATA_REG); -} - -static inline void -grub_cmos_write (grub_uint8_t index, grub_uint8_t value) -{ - grub_outb (index, GRUB_CMOS_ADDR_REG); - grub_outb (value, GRUB_CMOS_DATA_REG); -} - #endif /* GRUB_CPU_CMOS_H */ diff --git a/include/grub/i386/coreboot/serial.h b/include/grub/i386/coreboot/serial.h index 2c527f626..b6819d587 100644 --- a/include/grub/i386/coreboot/serial.h +++ b/include/grub/i386/coreboot/serial.h @@ -1 +1,24 @@ -#include +/* + * 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_MACHINE_SERIAL_HEADER +#define GRUB_MACHINE_SERIAL_HEADER 1 + +#define GRUB_MACHINE_SERIAL_PORTS { 0x3f8, 0x2f8, 0x3e8, 0x2e8 } + +#endif diff --git a/include/grub/i386/freebsd_linker.h b/include/grub/i386/freebsd_linker.h new file mode 100644 index 000000000..3c1eb64b6 --- /dev/null +++ b/include/grub/i386/freebsd_linker.h @@ -0,0 +1,74 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +/*- + * Copyright (c) 1997-2000 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: stable/8/sys/sys/linker.h 199583 2009-11-20 15:27:52Z jhb $ + */ + +#ifndef GRUB_FREEBSD_LINKER_CPU_HEADER +#define GRUB_FREEBSD_LINKER_CPU_HEADER 1 + +#define FREEBSD_MODINFO_END 0x0000 /* End of list */ +#define FREEBSD_MODINFO_NAME 0x0001 /* Name of module (string) */ +#define FREEBSD_MODINFO_TYPE 0x0002 /* Type of module (string) */ +#define FREEBSD_MODINFO_ADDR 0x0003 /* Loaded address */ +#define FREEBSD_MODINFO_SIZE 0x0004 /* Size of module */ +#define FREEBSD_MODINFO_EMPTY 0x0005 /* Has been deleted */ +#define FREEBSD_MODINFO_ARGS 0x0006 /* Parameters string */ +#define FREEBSD_MODINFO_METADATA 0x8000 /* Module-specfic */ + +#define FREEBSD_MODINFOMD_AOUTEXEC 0x0001 /* a.out exec header */ +#define FREEBSD_MODINFOMD_ELFHDR 0x0002 /* ELF header */ +#define FREEBSD_MODINFOMD_SSYM 0x0003 /* start of symbols */ +#define FREEBSD_MODINFOMD_ESYM 0x0004 /* end of symbols */ +#define FREEBSD_MODINFOMD_DYNAMIC 0x0005 /* _DYNAMIC pointer */ +#define FREEBSD_MODINFOMD_ENVP 0x0006 /* envp[] */ +#define FREEBSD_MODINFOMD_HOWTO 0x0007 /* boothowto */ +#define FREEBSD_MODINFOMD_KERNEND 0x0008 /* kernend */ +#define FREEBSD_MODINFOMD_SHDR 0x0009 /* section header table */ +#define FREEBSD_MODINFOMD_NOCOPY 0x8000 /* don't copy this metadata to the kernel */ + +#define FREEBSD_MODINFOMD_SMAP 0x1001 + +#define FREEBSD_MODINFOMD_DEPLIST (0x4001 | FREEBSD_MODINFOMD_NOCOPY) /* depends on */ + +#endif diff --git a/include/grub/i386/freebsd_reboot.h b/include/grub/i386/freebsd_reboot.h new file mode 100644 index 000000000..9c17f6efa --- /dev/null +++ b/include/grub/i386/freebsd_reboot.h @@ -0,0 +1,77 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +/*- + * Copyright (c) 1982, 1986, 1988, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)reboot.h 8.3 (Berkeley) 12/13/94 + * $FreeBSD: stable/8/sys/sys/reboot.h 199583 2009-11-20 15:27:52Z jhb $ + */ + +#ifndef GRUB_FREEBSD_REBOOT_CPU_HEADER +#define GRUB_FREEBSD_REBOOT_CPU_HEADER 1 + +#define FREEBSD_RB_ASKNAME (1 << 0) /* ask for file name to reboot from */ +#define FREEBSD_RB_SINGLE (1 << 1) /* reboot to single user only */ +#define FREEBSD_RB_NOSYNC (1 << 2) /* dont sync before reboot */ +#define FREEBSD_RB_HALT (1 << 3) /* don't reboot, just halt */ +#define FREEBSD_RB_INITNAME (1 << 4) /* name given for /etc/init (unused) */ +#define FREEBSD_RB_DFLTROOT (1 << 5) /* use compiled-in rootdev */ +#define FREEBSD_RB_KDB (1 << 6) /* give control to kernel debugger */ +#define FREEBSD_RB_RDONLY (1 << 7) /* mount root fs read-only */ +#define FREEBSD_RB_DUMP (1 << 8) /* dump kernel memory before reboot */ +#define FREEBSD_RB_MINIROOT (1 << 9) /* mini-root present in memory at boot time */ +#define FREEBSD_RB_CONFIG (1 << 10) /* invoke user configuration routing */ +#define FREEBSD_RB_VERBOSE (1 << 11) /* print all potentially useful info */ +#define FREEBSD_RB_SERIAL (1 << 12) /* user serial port as console */ +#define FREEBSD_RB_CDROM (1 << 13) /* use cdrom as root */ +#define FREEBSD_RB_GDB (1 << 15) /* use GDB remote debugger instead of DDB */ +#define FREEBSD_RB_MUTE (1 << 16) /* Come up with the console muted */ +#define FREEBSD_RB_PAUSE (1 << 20) +#define FREEBSD_RB_QUIET (1 << 21) +#define FREEBSD_RB_NOINTR (1 << 28) +#define FREENSD_RB_MULTIPLE (1 << 29) /* Use multiple consoles */ +#define FREEBSD_RB_DUAL FREENSD_RB_MULTIPLE +#define FREEBSD_RB_BOOTINFO (1 << 31) /* have `struct bootinfo *' arg */ + +#endif diff --git a/include/grub/i386/ieee1275/serial.h b/include/grub/i386/ieee1275/serial.h index 2c527f626..2d8563414 100644 --- a/include/grub/i386/ieee1275/serial.h +++ b/include/grub/i386/ieee1275/serial.h @@ -1 +1 @@ -#include +#include diff --git a/include/grub/i386/io.h b/include/grub/i386/io.h index 0e567766b..ae12a3e3d 100644 --- a/include/grub/i386/io.h +++ b/include/grub/i386/io.h @@ -21,6 +21,8 @@ #ifndef GRUB_IO_H #define GRUB_IO_H 1 +typedef unsigned short int grub_port_t; + static __inline unsigned char grub_inb (unsigned short int port) { diff --git a/include/grub/i386/linux.h b/include/grub/i386/linux.h index 8a5a84da3..f02a722d6 100644 --- a/include/grub/i386/linux.h +++ b/include/grub/i386/linux.h @@ -79,9 +79,9 @@ struct grub_e820_mmap grub_uint32_t type; } __attribute__((packed)); -#define GRUB_VIDEO_TYPE_TEXT 0x01 -#define GRUB_VIDEO_TYPE_VLFB 0x23 /* VESA VGA in graphic mode */ -#define GRUB_VIDEO_TYPE_EFI 0x70 +#define GRUB_VIDEO_LINUX_TYPE_TEXT 0x01 +#define GRUB_VIDEO_LINUX_TYPE_VESA 0x23 /* VESA VGA in graphic mode. */ +#define GRUB_VIDEO_LINUX_TYPE_SIMPLE 0x70 /* Linear framebuffer without any additional functions. */ /* For the Linux/i386 boot protocol version 2.03. */ struct linux_kernel_header diff --git a/include/grub/i386/netbsd_bootinfo.h b/include/grub/i386/netbsd_bootinfo.h new file mode 100644 index 000000000..776ecf3b0 --- /dev/null +++ b/include/grub/i386/netbsd_bootinfo.h @@ -0,0 +1,112 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +/* $NetBSD: bootinfo.h,v 1.16 2009/08/24 02:15:46 jmcneill Exp $ */ + +/* + * Copyright (c) 1997 + * Matthias Drochner. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef GRUB_NETBSD_BOOTINFO_CPU_HEADER +#define GRUB_NETBSD_BOOTINFO_CPU_HEADER 1 + +#include + + +#define NETBSD_BTINFO_BOOTPATH 0 +#define NETBSD_BTINFO_ROOTDEVICE 1 +#define NETBSD_BTINFO_BOOTDISK 3 +#define NETBSD_BTINFO_MEMMAP 9 + +struct grub_netbsd_btinfo_common +{ + int len; + int type; +}; + +struct grub_netbsd_btinfo_mmap_header +{ + struct grub_netbsd_btinfo_common common; + grub_uint32_t count; +}; + +struct grub_netbsd_btinfo_mmap_entry +{ + grub_uint64_t addr; + grub_uint64_t len; +#define NETBSD_MMAP_AVAILABLE 1 +#define NETBSD_MMAP_RESERVED 2 +#define NETBSD_MMAP_ACPI 3 +#define NETBSD_MMAP_NVS 4 + grub_uint32_t type; +}; + +struct grub_netbsd_btinfo_bootpath +{ + struct grub_netbsd_btinfo_common common; + char bootpath[80]; +}; + +struct grub_netbsd_btinfo_rootdevice +{ + struct grub_netbsd_btinfo_common common; + char devname[16]; +}; + +struct grub_netbsd_btinfo_bootdisk +{ + struct grub_netbsd_btinfo_common common; + int labelsector; /* label valid if != -1 */ + struct + { + grub_uint16_t type, checksum; + char packname[16]; + } label; + int biosdev; + int partition; +}; + +struct grub_netbsd_bootinfo +{ + grub_uint32_t bi_count; + void *bi_data[1]; +}; + +#endif diff --git a/include/grub/i386/netbsd_reboot.h b/include/grub/i386/netbsd_reboot.h new file mode 100644 index 000000000..ee82455bc --- /dev/null +++ b/include/grub/i386/netbsd_reboot.h @@ -0,0 +1,81 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +/* $NetBSD: reboot.h,v 1.25 2007/12/25 18:33:48 perry Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1988, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)reboot.h 8.3 (Berkeley) 12/13/94 + */ + +#ifndef GRUB_NETBSD_REBOOT_CPU_HEADER +#define GRUB_NETBSD_REBOOT_CPU_HEADER 1 + +#define NETBSD_RB_AUTOBOOT 0 /* flags for system auto-booting itself */ + +#define NETBSD_RB_ASKNAME (1 << 0) /* ask for file name to reboot from */ +#define NETBSD_RB_SINGLE (1 << 1) /* reboot to single user only */ +#define NETBSD_RB_NOSYNC (1 << 2) /* dont sync before reboot */ +#define NETBSD_RB_HALT (1 << 3) /* don't reboot, just halt */ +#define NETBSD_RB_INITNAME (1 << 4) /* name given for /etc/init (unused) */ +#define NETBSD_RB_UNUSED1 (1 << 5) /* was RB_DFLTROOT, obsolete */ +#define NETBSD_RB_KDB (1 << 6) /* give control to kernel debugger */ +#define NETBSD_RB_RDONLY (1 << 7) /* mount root fs read-only */ +#define NETBSD_RB_DUMP (1 << 8) /* dump kernel memory before reboot */ +#define NETBSD_RB_MINIROOT (1 << 9) /* mini-root present in memory at boot time */ +#define NETBSD_RB_STRING (1 << 10) /* use provided bootstr */ +#define NETBSD_RB_POWERDOWN ((1 << 11) | RB_HALT) /* turn power off (or at least halt) */ +#define NETBSD_RB_USERCONFIG (1 << 12) /* change configured devices */ + +#define NETBSD_AB_NORMAL 0 /* boot normally (default) */ + +#define NETBSD_AB_QUIET (1 << 16) /* boot quietly */ +#define NETBSD_AB_VERBOSE (1 << 17) /* boot verbosely */ +#define NETBSD_AB_SILENT (1 << 18) /* boot silently */ +#define NETBSD_AB_DEBUG (1 << 19) /* boot with debug messages */ +#define NETBSD_AB_NOSMP (1 << 28) /* Boot without SMP support. */ +#define NETBSD_AB_NOACPI (1 << 29) /* Boot without ACPI support. */ + + +#endif diff --git a/include/grub/i386/openbsd_bootarg.h b/include/grub/i386/openbsd_bootarg.h new file mode 100644 index 000000000..ccbe1ca12 --- /dev/null +++ b/include/grub/i386/openbsd_bootarg.h @@ -0,0 +1,72 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +/* $OpenBSD: bootarg.h,v 1.11 2003/06/02 20:20:54 mickey Exp $ */ + +/* + * Copyright (c) 1996-1999 Michael Shalayeff + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef GRUB_OPENBSD_BOOTARG_CPU_HEADER +#define GRUB_OPENBSD_BOOTARG_CPU_HEADER 1 + +#define OPENBSD_BOOTARG_APIVER (OPENBSD_BAPIV_VECTOR | \ + OPENBSD_BAPIV_ENV | \ + OPENBSD_BAPIV_BMEMMAP) + +#define OPENBSD_BAPIV_ANCIENT 0x0 /* MD old i386 bootblocks */ +#define OPENBSD_BAPIV_VARS 0x1 /* MD structure w/ add info passed */ +#define OPENBSD_BAPIV_VECTOR 0x2 /* MI vector of MD structures passed */ +#define OPENBSD_BAPIV_ENV 0x4 /* MI environment vars vector */ +#define OPENBSD_BAPIV_BMEMMAP 0x8 /* MI memory map passed is in bytes */ + +#define OPENBSD_BOOTARG_ENV 0x1000 +#define OPENBSD_BOOTARG_END -1 + +#define OPENBSD_BOOTARG_MMAP 0 + +struct grub_openbsd_bootargs +{ + int ba_type; + int ba_size; + struct grub_openbsd_bootargs *ba_next; +} __attribute__ ((packed)); + +#endif diff --git a/include/grub/i386/openbsd_reboot.h b/include/grub/i386/openbsd_reboot.h new file mode 100644 index 000000000..3f6571a44 --- /dev/null +++ b/include/grub/i386/openbsd_reboot.h @@ -0,0 +1,79 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +/* $OpenBSD: reboot.h,v 1.13 2004/03/10 23:02:53 tom Exp $ */ +/* $NetBSD: reboot.h,v 1.9 1996/04/22 01:23:25 christos Exp $ */ + +/* + * Copyright (c) 1982, 1986, 1988, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)reboot.h 8.2 (Berkeley) 7/10/94 + */ + +#ifndef GRUB_OPENBSD_REBOOT_CPU_HEADER +#define GRUB_OPENBSD_REBOOT_CPU_HEADER 1 + +#define OPENBSD_RB_ASKNAME (1 << 0) /* ask for file name to reboot from */ +#define OPENBSD_RB_SINGLE (1 << 1) /* reboot to single user only */ +#define OPENBSD_RB_NOSYNC (1 << 2) /* dont sync before reboot */ +#define OPENBSD_RB_HALT (1 << 3) /* don't reboot, just halt */ +#define OPENBSD_RB_INITNAME (1 << 4) /* name given for /etc/init (unused) */ +#define OPENBSD_RB_DFLTROOT (1 << 5) /* use compiled-in rootdev */ +#define OPENBSD_RB_KDB (1 << 6) /* give control to kernel debugger */ +#define OPENBSD_RB_RDONLY (1 << 7) /* mount root fs read-only */ +#define OPENBSD_RB_DUMP (1 << 8) /* dump kernel memory before reboot */ +#define OPENBSD_RB_MINIROOT (1 << 9) /* mini-root present in memory at boot time */ +#define OPENBSD_RB_CONFIG (1 << 10) /* change configured devices */ +#define OPENBSD_RB_TIMEBAD (1 << 11) /* don't call resettodr() in boot() */ +#define OPENBSD_RB_POWERDOWN (1 << 12) /* attempt to power down machine */ +#define OPENBSD_RB_SERCONS (1 << 13) /* use serial console if available */ +#define OPENBSD_RB_USERREQ (1 << 14) /* boot() called at user request (e.g. ddb) */ + +#define OPENBSD_B_DEVMAGIC 0xa0000000 +#define OPENBSD_B_ADAPTORSHIFT 24 +#define OPENBSD_B_CTRLSHIFT 20 +#define OPENBSD_B_UNITSHIFT 16 +#define OPENBSD_B_PARTSHIFT 8 +#define OPENBSD_B_TYPESHIFT 0 + +#endif diff --git a/include/grub/i386/pc/boot.h b/include/grub/i386/pc/boot.h index 508b10742..e88c62b71 100644 --- a/include/grub/i386/pc/boot.h +++ b/include/grub/i386/pc/boot.h @@ -66,6 +66,8 @@ /* The size of a block list used in the kernel startup code. */ #define GRUB_BOOT_MACHINE_LIST_SIZE 12 +#define GRUB_BOOT_MACHINE_PXE_DL 0x7f + #ifndef ASM_FILE /* This is the blocklist used in the diskboot image. */ diff --git a/include/grub/i386/pc/vbe.h b/include/grub/i386/pc/vbe.h index 9c4c4dd3d..abf246fa1 100644 --- a/include/grub/i386/pc/vbe.h +++ b/include/grub/i386/pc/vbe.h @@ -19,8 +19,6 @@ #ifndef GRUB_VBE_MACHINE_HEADER #define GRUB_VBE_MACHINE_HEADER 1 -#include - /* Default video mode to be used. */ #define GRUB_VBE_DEFAULT_VIDEO_MODE 0x101 diff --git a/include/grub/i386/pci.h b/include/grub/i386/pci.h index 31217d5f5..bab42adb6 100644 --- a/include/grub/i386/pci.h +++ b/include/grub/i386/pci.h @@ -22,8 +22,11 @@ #include #include +#define GRUB_MACHINE_PCI_IO_BASE 0 #define GRUB_PCI_ADDR_REG 0xcf8 #define GRUB_PCI_DATA_REG 0xcfc +#define GRUB_PCI_NUM_BUS 256 +#define GRUB_PCI_NUM_DEVICES 32 static inline grub_uint32_t grub_pci_read (grub_pci_address_t addr) @@ -67,12 +70,12 @@ grub_pci_write_byte (grub_pci_address_t addr, grub_uint8_t data) grub_outb (data, GRUB_PCI_DATA_REG + (addr & 3)); } -static inline void * +static inline volatile void * grub_pci_device_map_range (grub_pci_device_t dev __attribute__ ((unused)), grub_addr_t base, grub_size_t size __attribute__ ((unused))) { - return (void *) base; + return (volatile void *) base; } static inline void diff --git a/include/grub/icon_manager.h b/include/grub/icon_manager.h new file mode 100644 index 000000000..81c488416 --- /dev/null +++ b/include/grub/icon_manager.h @@ -0,0 +1,41 @@ +/* icon_manager.h - gfxmenu icon manager. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_ICON_MANAGER_HEADER +#define GRUB_ICON_MANAGER_HEADER 1 + +#include +#include + +/* Forward declaration of opaque structure handle type. */ +typedef struct grub_gfxmenu_icon_manager *grub_gfxmenu_icon_manager_t; + +grub_gfxmenu_icon_manager_t grub_gfxmenu_icon_manager_new (void); +void grub_gfxmenu_icon_manager_destroy (grub_gfxmenu_icon_manager_t mgr); +void grub_gfxmenu_icon_manager_clear_cache (grub_gfxmenu_icon_manager_t mgr); +void grub_gfxmenu_icon_manager_set_theme_path (grub_gfxmenu_icon_manager_t mgr, + const char *path); +void grub_gfxmenu_icon_manager_set_icon_size (grub_gfxmenu_icon_manager_t mgr, + int width, int height); +struct grub_video_bitmap * +grub_gfxmenu_icon_manager_get_icon (grub_gfxmenu_icon_manager_t mgr, + grub_menu_entry_t entry); + +#endif /* GRUB_ICON_MANAGER_HEADER */ + diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h index 8b31e32e2..62e8f3812 100644 --- a/include/grub/ieee1275/ieee1275.h +++ b/include/grub/ieee1275/ieee1275.h @@ -138,7 +138,7 @@ int EXPORT_FUNC(grub_ieee1275_read) (grub_ieee1275_ihandle_t ihandle, void *buffer, grub_size_t len, grub_ssize_t *actualp); int EXPORT_FUNC(grub_ieee1275_seek) (grub_ieee1275_ihandle_t ihandle, - int pos_hi, int pos_lo, + grub_disk_addr_t pos, grub_ssize_t *result); int EXPORT_FUNC(grub_ieee1275_peer) (grub_ieee1275_phandle_t node, grub_ieee1275_phandle_t *result); @@ -173,6 +173,10 @@ grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate) (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); int EXPORT_FUNC(grub_claimmap) (grub_addr_t addr, grub_size_t size); +int +EXPORT_FUNC(grub_ieee1275_map) (grub_addr_t phys, grub_addr_t virt, + grub_size_t size, grub_uint32_t mode); + char *EXPORT_FUNC(grub_ieee1275_encode_devname) (const char *path); char *EXPORT_FUNC(grub_ieee1275_get_filename) (const char *path); diff --git a/include/grub/kernel.h b/include/grub/kernel.h index 75ec77c2a..9586a90b9 100644 --- a/include/grub/kernel.h +++ b/include/grub/kernel.h @@ -26,7 +26,8 @@ enum { OBJ_TYPE_ELF, OBJ_TYPE_MEMDISK, - OBJ_TYPE_CONFIG + OBJ_TYPE_CONFIG, + OBJ_TYPE_FONT }; /* The module header. */ diff --git a/include/grub/menu.h b/include/grub/menu.h index c7114a93b..78f461b92 100644 --- a/include/grub/menu.h +++ b/include/grub/menu.h @@ -83,7 +83,6 @@ typedef struct grub_menu_execute_callback } *grub_menu_execute_callback_t; - grub_menu_entry_t grub_menu_get_entry (grub_menu_t menu, int no); int grub_menu_get_timeout (void); void grub_menu_set_timeout (int timeout); @@ -93,5 +92,6 @@ void grub_menu_execute_with_fallback (grub_menu_t menu, grub_menu_execute_callback_t callback, void *callback_data); void grub_menu_entry_run (grub_menu_entry_t entry); +int grub_menu_get_default_entry_index (grub_menu_t menu); #endif /* GRUB_MENU_HEADER */ diff --git a/include/grub/mips/at_keyboard.h b/include/grub/mips/at_keyboard.h new file mode 100644 index 000000000..0c307537d --- /dev/null +++ b/include/grub/mips/at_keyboard.h @@ -0,0 +1 @@ +#include diff --git a/include/grub/mips/cache.h b/include/grub/mips/cache.h new file mode 100644 index 000000000..c3470571e --- /dev/null +++ b/include/grub/mips/cache.h @@ -0,0 +1,27 @@ +/* cache.h - Flush the processor's cache. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2004,2007 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_CPU_CACHE_H +#define GRUB_CPU_CACHE_H 1 + +#include +#include + +void EXPORT_FUNC(grub_cpu_flush_cache) (void *start, grub_size_t size, int type); +#endif diff --git a/include/grub/mips/cmos.h b/include/grub/mips/cmos.h new file mode 100644 index 000000000..79a7a4c1b --- /dev/null +++ b/include/grub/mips/cmos.h @@ -0,0 +1 @@ +#include diff --git a/include/grub/mips/io.h b/include/grub/mips/io.h new file mode 100644 index 000000000..dee76bde5 --- /dev/null +++ b/include/grub/mips/io.h @@ -0,0 +1,62 @@ +/* + * 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_IO_H +#define GRUB_IO_H 1 + +#include + +typedef grub_addr_t grub_port_t; + +static __inline unsigned char +grub_inb (grub_port_t port) +{ + return *(volatile grub_uint8_t *) port; +} + +static __inline unsigned short int +grub_inw (grub_port_t port) +{ + return *(volatile grub_uint16_t *) port; +} + +static __inline unsigned int +grub_inl (grub_port_t port) +{ + return *(volatile grub_uint32_t *) port; +} + +static __inline void +grub_outb (unsigned char value, grub_port_t port) +{ + *(volatile grub_uint8_t *) port = value; +} + +static __inline void +grub_outw (unsigned short int value, grub_port_t port) +{ + *(volatile grub_uint16_t *) port = value; +} + +static __inline void +grub_outl (unsigned int value, grub_port_t port) +{ + *(volatile grub_uint32_t *) port = value; +} + +#endif /* _SYS_IO_H */ diff --git a/include/grub/mips/kernel.h b/include/grub/mips/kernel.h new file mode 100644 index 000000000..8b68f7b6b --- /dev/null +++ b/include/grub/mips/kernel.h @@ -0,0 +1,65 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2005,2006,2007,2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_KERNEL_CPU_HEADER +#define GRUB_KERNEL_CPU_HEADER 1 + +#define GRUB_MOD_ALIGN 0x1 +/* Non-zero value is only needed for PowerMacs. */ +#define GRUB_MOD_GAP 0x0 + +#define GRUB_KERNEL_MACHINE_LINK_ALIGN 32 + +#define GRUB_KERNEL_CPU_RAW_SIZE 0x200 +#define GRUB_KERNEL_CPU_COMPRESSED_SIZE 0x8 +#define GRUB_KERNEL_CPU_TOTAL_MODULE_SIZE 0xc +#define GRUB_KERNEL_CPU_KERNEL_IMAGE_SIZE 0x10 + +#define GRUB_KERNEL_CPU_PREFIX GRUB_KERNEL_CPU_RAW_SIZE +#define GRUB_KERNEL_CPU_DATA_END GRUB_KERNEL_CPU_RAW_SIZE + 0x48 + +#define GRUB_KERNEL_MACHINE_RAW_SIZE GRUB_KERNEL_CPU_RAW_SIZE + +#define GRUB_KERNEL_MACHINE_PREFIX GRUB_KERNEL_CPU_PREFIX +#define GRUB_KERNEL_MACHINE_DATA_END GRUB_KERNEL_CPU_DATA_END +#define GRUB_KERNEL_MACHINE_KERNEL_IMAGE_SIZE GRUB_KERNEL_CPU_KERNEL_IMAGE_SIZE +#define GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE GRUB_KERNEL_CPU_TOTAL_MODULE_SIZE +#define GRUB_KERNEL_MACHINE_COMPRESSED_SIZE GRUB_KERNEL_CPU_COMPRESSED_SIZE + +#define GRUB_PLATFORM_IMAGE_FORMATS "raw, elf" +#define GRUB_PLATFORM_IMAGE_DEFAULT_FORMAT "raw" + +#define GRUB_PLATFORM_IMAGE_DEFAULT GRUB_PLATFORM_IMAGE_RAW + +#ifndef ASM_FILE + +typedef enum { + GRUB_PLATFORM_IMAGE_RAW, + GRUB_PLATFORM_IMAGE_ELF +} + grub_platform_image_format_t; +#define GRUB_PLATFORM_IMAGE_RAW GRUB_PLATFORM_IMAGE_RAW +#define GRUB_PLATFORM_IMAGE_ELF GRUB_PLATFORM_IMAGE_ELF + +/* The prefix which points to the directory where GRUB modules and its + configuration file are located. */ +extern char grub_prefix[]; + +#endif + +#endif diff --git a/include/grub/mips/libgcc.h b/include/grub/mips/libgcc.h new file mode 100644 index 000000000..f06ea1c1c --- /dev/null +++ b/include/grub/mips/libgcc.h @@ -0,0 +1,38 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2004,2007,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 + +#ifdef HAVE___ASHLDI3 +void EXPORT_FUNC (__ashldi3) (void); +#endif +#ifdef HAVE___ASHRDI3 +void EXPORT_FUNC (__ashrdi3) (void); +#endif +#ifdef HAVE___LSHRDI3 +void EXPORT_FUNC (__lshrdi3) (void); +#endif +#ifdef HAVE___UCMPDI2 +void EXPORT_FUNC (__ucmpdi2) (void); +#endif +#ifdef HAVE___BSWAPSI2 +void EXPORT_FUNC (__bswapsi2) (void); +#endif +#ifdef HAVE___BSWAPDI2 +void EXPORT_FUNC (__bswapdi2) (void); +#endif diff --git a/include/grub/mips/pci.h b/include/grub/mips/pci.h new file mode 100644 index 000000000..8b49d8479 --- /dev/null +++ b/include/grub/mips/pci.h @@ -0,0 +1 @@ +#include diff --git a/include/grub/mips/qemu-mips/boot.h b/include/grub/mips/qemu-mips/boot.h new file mode 100644 index 000000000..e69de29bb diff --git a/include/grub/mips/qemu-mips/kernel.h b/include/grub/mips/qemu-mips/kernel.h new file mode 100644 index 000000000..dbf74c1b2 --- /dev/null +++ b/include/grub/mips/qemu-mips/kernel.h @@ -0,0 +1,36 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2005,2006,2007,2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_KERNEL_MACHINE_HEADER +#define GRUB_KERNEL_MACHINE_HEADER 1 + +#include +#include + +#ifndef ASM_FILE + +void EXPORT_FUNC (grub_reboot) (void); +void EXPORT_FUNC (grub_halt) (void); + +/* The prefix which points to the directory where GRUB modules and its + configuration file are located. */ +extern char grub_prefix[]; + +#endif + +#endif /* ! GRUB_KERNEL_MACHINE_HEADER */ diff --git a/include/grub/mips/qemu-mips/loader.h b/include/grub/mips/qemu-mips/loader.h new file mode 100644 index 000000000..e69de29bb diff --git a/include/grub/mips/qemu-mips/memory.h b/include/grub/mips/qemu-mips/memory.h new file mode 100644 index 000000000..87e68674e --- /dev/null +++ b/include/grub/mips/qemu-mips/memory.h @@ -0,0 +1,54 @@ +/* + * 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_MEMORY_MACHINE_HEADER +#define GRUB_MEMORY_MACHINE_HEADER 1 + +#ifndef ASM_FILE +#include +#include +#include +#endif + +#define GRUB_MACHINE_MEMORY_STACK_HIGH 0x80f00000 +#define GRUB_MACHINE_MEMORY_USABLE 0x81000000 + +#define GRUB_MACHINE_MEMORY_AVAILABLE 1 + +#ifndef ASM_FILE +grub_err_t EXPORT_FUNC (grub_machine_mmap_iterate) +(int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); +grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate) + (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); + +static inline grub_err_t +grub_machine_mmap_register (grub_uint64_t start __attribute__ ((unused)), + grub_uint64_t size __attribute__ ((unused)), + int type __attribute__ ((unused)), + int handle __attribute__ ((unused))) +{ + return GRUB_ERR_NONE; +} +static inline grub_err_t +grub_machine_mmap_unregister (int handle __attribute__ ((unused))) +{ + return GRUB_ERR_NONE; +} +#endif + +#endif diff --git a/include/grub/mips/qemu-mips/serial.h b/include/grub/mips/qemu-mips/serial.h new file mode 100644 index 000000000..1f8ce0804 --- /dev/null +++ b/include/grub/mips/qemu-mips/serial.h @@ -0,0 +1,24 @@ +/* + * 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_MACHINE_SERIAL_HEADER +#define GRUB_MACHINE_SERIAL_HEADER 1 + +#define GRUB_MACHINE_SERIAL_PORTS { 0x140003f8 } + +#endif diff --git a/include/grub/mips/qemu-mips/time.h b/include/grub/mips/qemu-mips/time.h new file mode 100644 index 000000000..a73f64dea --- /dev/null +++ b/include/grub/mips/qemu-mips/time.h @@ -0,0 +1,34 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2004,2005,2007 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef KERNEL_MACHINE_TIME_HEADER +#define KERNEL_MACHINE_TIME_HEADER 1 + +#include + +#define GRUB_TICKS_PER_SECOND 1000 + +/* Return the real time in ticks. */ +grub_uint32_t EXPORT_FUNC (grub_get_rtc) (void); + +static inline void +grub_cpu_idle(void) +{ +} + +#endif /* ! KERNEL_MACHINE_TIME_HEADER */ diff --git a/include/grub/mips/relocator.h b/include/grub/mips/relocator.h new file mode 100644 index 000000000..838ef832f --- /dev/null +++ b/include/grub/mips/relocator.h @@ -0,0 +1,39 @@ +/* + * 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_RELOCATOR_CPU_HEADER +#define GRUB_RELOCATOR_CPU_HEADER 1 + +#include +#include + +struct grub_relocator32_state +{ + /* gpr[0] is ignored since it's hardwired to 0. */ + grub_uint32_t gpr[32]; + /* Register holding target $pc. */ + int jumpreg; +}; + +void *grub_relocator32_alloc (grub_size_t size); +grub_err_t grub_relocator32_boot (void *relocator, grub_uint32_t dest, + struct grub_relocator32_state state); +void *grub_relocator32_realloc (void *relocator, grub_size_t size); +void grub_relocator32_free (void *relocator); + +#endif /* ! GRUB_RELOCATOR_CPU_HEADER */ diff --git a/include/grub/mips/setjmp.h b/include/grub/mips/setjmp.h new file mode 100644 index 000000000..5e5985586 --- /dev/null +++ b/include/grub/mips/setjmp.h @@ -0,0 +1,27 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2004,2006,2007,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_SETJMP_CPU_HEADER +#define GRUB_SETJMP_CPU_HEADER 1 + +typedef unsigned long grub_jmp_buf[11]; + +int grub_setjmp (grub_jmp_buf env) __attribute__ ((returns_twice)); +void grub_longjmp (grub_jmp_buf env, int val) __attribute__ ((noreturn)); + +#endif /* ! GRUB_SETJMP_CPU_HEADER */ diff --git a/include/grub/mips/time.h b/include/grub/mips/time.h new file mode 100644 index 000000000..e69de29bb diff --git a/include/grub/mips/types.h b/include/grub/mips/types.h new file mode 100644 index 000000000..fe09afa3e --- /dev/null +++ b/include/grub/mips/types.h @@ -0,0 +1,38 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2006,2007,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_TYPES_CPU_HEADER +#define GRUB_TYPES_CPU_HEADER 1 + +/* The size of void *. */ +#define GRUB_TARGET_SIZEOF_VOID_P 4 + +/* The size of long. */ +#define GRUB_TARGET_SIZEOF_LONG 4 + +#ifdef GRUB_CPU_MIPSEL +/* mipsEL is little-endian. */ +#undef GRUB_TARGET_WORDS_BIGENDIAN +#elif defined (GRUB_CPU_MIPS) +/* mips is big-endian. */ +#define GRUB_TARGET_WORDS_BIGENDIAN +#elif !defined (GRUB_SYMBOL_GENERATOR) +#error Neither GRUB_CPU_MIPS nor GRUB_CPU_MIPSEL is defined +#endif + +#endif /* ! GRUB_TYPES_CPU_HEADER */ diff --git a/include/grub/mips/yeeloong/at_keyboard.h b/include/grub/mips/yeeloong/at_keyboard.h new file mode 100644 index 000000000..f279ac86d --- /dev/null +++ b/include/grub/mips/yeeloong/at_keyboard.h @@ -0,0 +1,25 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2007,2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_MACHINE_AT_KEYBOARD_HEADER +#define GRUB_MACHINE_AT_KEYBOARD_HEADER 1 + +#define KEYBOARD_REG_DATA 0xbfd00060 +#define KEYBOARD_REG_STATUS 0xbfd00064 + +#endif diff --git a/include/grub/mips/yeeloong/boot.h b/include/grub/mips/yeeloong/boot.h new file mode 100644 index 000000000..e69de29bb diff --git a/include/grub/mips/yeeloong/cmos.h b/include/grub/mips/yeeloong/cmos.h new file mode 100644 index 000000000..f2a32d736 --- /dev/null +++ b/include/grub/mips/yeeloong/cmos.h @@ -0,0 +1,28 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_CPU_CMOS_H +#define GRUB_CPU_CMOS_H 1 + +#include +#include + +#define GRUB_CMOS_ADDR_REG 0xbfd00070 +#define GRUB_CMOS_DATA_REG 0xbfd00071 + +#endif /* GRUB_CPU_CMOS_H */ diff --git a/include/grub/mips/yeeloong/kernel.h b/include/grub/mips/yeeloong/kernel.h new file mode 100644 index 000000000..230455dbf --- /dev/null +++ b/include/grub/mips/yeeloong/kernel.h @@ -0,0 +1,32 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2005,2006,2007,2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_KERNEL_MACHINE_HEADER +#define GRUB_KERNEL_MACHINE_HEADER 1 + +#include +#include + +#ifndef ASM_FILE + +void EXPORT_FUNC (grub_reboot) (void); +void EXPORT_FUNC (grub_halt) (void); + +#endif + +#endif /* ! GRUB_KERNEL_MACHINE_HEADER */ diff --git a/include/grub/mips/yeeloong/loader.h b/include/grub/mips/yeeloong/loader.h new file mode 100644 index 000000000..e69de29bb diff --git a/include/grub/mips/yeeloong/memory.h b/include/grub/mips/yeeloong/memory.h new file mode 100644 index 000000000..922db2404 --- /dev/null +++ b/include/grub/mips/yeeloong/memory.h @@ -0,0 +1,68 @@ +/* + * 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_MEMORY_MACHINE_HEADER +#define GRUB_MEMORY_MACHINE_HEADER 1 + +#ifndef ASM_FILE +#include +#include +#include +#endif + +#define GRUB_MACHINE_MEMORY_STACK_HIGH 0x801ffff0 +#define GRUB_ARCH_LOWMEMVSTART 0x80000000 +#define GRUB_ARCH_LOWMEMPSTART 0x00000000 +#define GRUB_ARCH_LOWMEMMAXSIZE 0x10000000 +#define GRUB_ARCH_HIGHMEMPSTART 0x10000000 + + +#define GRUB_MACHINE_MEMORY_AVAILABLE 1 +#define GRUB_MACHINE_MEMORY_MAX_TYPE 1 + /* This one is special: it's used internally but is never reported + by firmware. */ +#define GRUB_MACHINE_MEMORY_HOLE 2 +#define GRUB_MACHINE_MEMORY_RESERVED GRUB_MACHINE_MEMORY_HOLE + +#ifndef ASM_FILE +grub_err_t EXPORT_FUNC (grub_machine_mmap_iterate) +(int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); + +static inline grub_err_t +grub_machine_mmap_register (grub_uint64_t start __attribute__ ((unused)), + grub_uint64_t size __attribute__ ((unused)), + int type __attribute__ ((unused)), + int handle __attribute__ ((unused))) +{ + return GRUB_ERR_NONE; +} +static inline grub_err_t +grub_machine_mmap_unregister (int handle __attribute__ ((unused))) +{ + return GRUB_ERR_NONE; +} + +grub_uint64_t grub_mmap_get_lower (void); +grub_uint64_t grub_mmap_get_upper (void); + +extern grub_uint32_t EXPORT_VAR (grub_arch_memsize); +extern grub_uint32_t EXPORT_VAR (grub_arch_highmemsize); + +#endif + +#endif diff --git a/include/grub/mips/yeeloong/pci.h b/include/grub/mips/yeeloong/pci.h new file mode 100644 index 000000000..c7bd31d4f --- /dev/null +++ b/include/grub/mips/yeeloong/pci.h @@ -0,0 +1,105 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_MACHINE_PCI_H +#define GRUB_MACHINE_PCI_H 1 + +#include +#include + +#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_CTRL_REG (*(volatile grub_uint32_t *) 0xbfe00110) +#define GRUB_MACHINE_PCI_WIN_MASK_SIZE 6 +#define GRUB_MACHINE_PCI_WIN_MASK ((1 << GRUB_MACHINE_PCI_WIN_MASK_SIZE) - 1) + +/* We have 3 PCI windows. */ +#define GRUB_MACHINE_PCI_NUM_WIN 3 +/* Each window is 64MiB. */ +#define GRUB_MACHINE_PCI_WIN_SHIFT 26 +#define GRUB_MACHINE_PCI_WIN_OFFSET_MASK ((1 << GRUB_MACHINE_PCI_WIN_SHIFT) - 1) + +#define GRUB_MACHINE_PCI_WIN_SIZE 0x04000000 +/* Graphical acceleration takes 1 MiB away. */ +#define GRUB_MACHINE_PCI_WIN1_SIZE 0x03f00000 + +#define GRUB_MACHINE_PCI_WIN1_ADDR 0xb0000000 +#define GRUB_MACHINE_PCI_WIN2_ADDR 0xb4000000 +#define GRUB_MACHINE_PCI_WIN3_ADDR 0xb8000000 + +static inline grub_uint32_t +grub_pci_read (grub_pci_address_t addr) +{ + GRUB_MACHINE_PCI_CONF_CTRL_REG = 1 << ((addr >> 11) & 0xf); + return *(volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONFSPACE + | (addr & 0x03ff)); +} + +static inline grub_uint16_t +grub_pci_read_word (grub_pci_address_t addr) +{ + GRUB_MACHINE_PCI_CONF_CTRL_REG = 1 << ((addr >> 11) & 0xf); + return *(volatile grub_uint16_t *) (GRUB_MACHINE_PCI_CONFSPACE + | (addr & 0x03ff)); +} + +static inline grub_uint8_t +grub_pci_read_byte (grub_pci_address_t addr) +{ + GRUB_MACHINE_PCI_CONF_CTRL_REG = 1 << ((addr >> 11) & 0xf); + return *(volatile grub_uint8_t *) (GRUB_MACHINE_PCI_CONFSPACE + | (addr & 0x03ff)); +} + +static inline void +grub_pci_write (grub_pci_address_t addr, grub_uint32_t data) +{ + GRUB_MACHINE_PCI_CONF_CTRL_REG = 1 << ((addr >> 11) & 0xf); + *(volatile grub_uint32_t *) (GRUB_MACHINE_PCI_CONFSPACE + | (addr & 0x03ff)) = data; +} + +static inline void +grub_pci_write_word (grub_pci_address_t addr, grub_uint16_t data) +{ + GRUB_MACHINE_PCI_CONF_CTRL_REG = 1 << ((addr >> 11) & 0xf); + *(volatile grub_uint16_t *) (GRUB_MACHINE_PCI_CONFSPACE + | (addr & 0x03ff)) = data; +} + +static inline void +grub_pci_write_byte (grub_pci_address_t addr, grub_uint8_t data) +{ + GRUB_MACHINE_PCI_CONF_CTRL_REG = 1 << ((addr >> 11) & 0xf); + *(volatile grub_uint8_t *) (GRUB_MACHINE_PCI_CONFSPACE + | (addr & 0x03ff)) = data; +} + +volatile void * +grub_pci_device_map_range (grub_pci_device_t dev __attribute__ ((unused)), + 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))); + +#endif /* GRUB_MACHINE_PCI_H */ diff --git a/include/grub/mips/yeeloong/serial.h b/include/grub/mips/yeeloong/serial.h new file mode 100644 index 000000000..9390ea18a --- /dev/null +++ b/include/grub/mips/yeeloong/serial.h @@ -0,0 +1,24 @@ +/* + * 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_MACHINE_SERIAL_HEADER +#define GRUB_MACHINE_SERIAL_HEADER 1 + +#define GRUB_MACHINE_SERIAL_PORTS { 0xbff003f8 } + +#endif diff --git a/include/grub/mips/yeeloong/time.h b/include/grub/mips/yeeloong/time.h new file mode 100644 index 000000000..7f468bf12 --- /dev/null +++ b/include/grub/mips/yeeloong/time.h @@ -0,0 +1,37 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2004,2005,2007 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef KERNEL_MACHINE_TIME_HEADER +#define KERNEL_MACHINE_TIME_HEADER 1 + +#include + +#define GRUB_TICKS_PER_SECOND (grub_arch_cpuclock / 2) + +/* Return the real time in ticks. */ +grub_uint64_t EXPORT_FUNC (grub_get_rtc) (void); + +extern grub_uint32_t EXPORT_VAR (grub_arch_busclock); +extern grub_uint32_t EXPORT_VAR (grub_arch_cpuclock); + +static inline void +grub_cpu_idle(void) +{ +} + +#endif /* ! KERNEL_MACHINE_TIME_HEADER */ diff --git a/include/grub/misc.h b/include/grub/misc.h index 48eb1fcdd..dcbafba87 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -110,6 +110,12 @@ char *EXPORT_FUNC(grub_strstr) (const char *haystack, const char *needle); int EXPORT_FUNC(grub_isspace) (int c); int EXPORT_FUNC(grub_isprint) (int c); +static inline int +grub_iscntrl (int c) +{ + return (c >= 0x00 && c <= 0x1F) || c == 0x7F; +} + static inline int grub_isalpha (int c) { @@ -128,6 +134,12 @@ grub_isdigit (int c) return (c >= '0' && c <= '9'); } +static inline int +grub_isalnum (int c) +{ + return grub_isalpha (c) || grub_isdigit (c); +} + static inline int grub_tolower (int c) { @@ -182,6 +194,43 @@ grub_strncasecmp (const char *s1, const char *s2, grub_size_t n) unsigned long EXPORT_FUNC(grub_strtoul) (const char *str, char **end, int base); unsigned long long EXPORT_FUNC(grub_strtoull) (const char *str, char **end, int base); + +static inline long +grub_strtol (const char *str, char **end, int base) +{ + int negative = 0; + unsigned long magnitude; + + while (*str && grub_isspace (*str)) + str++; + + if (*str == '-') + { + negative = 1; + str++; + } + + magnitude = grub_strtoull (str, end, base); + if (negative) + { + if (magnitude > (unsigned long) GRUB_LONG_MAX + 1) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "negative overflow"); + return GRUB_LONG_MIN; + } + return -((long) magnitude); + } + else + { + if (magnitude > GRUB_LONG_MAX) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "positive overflow"); + return GRUB_LONG_MAX; + } + return (long) magnitude; + } +} + char *EXPORT_FUNC(grub_strdup) (const char *s); char *EXPORT_FUNC(grub_strndup) (const char *s, grub_size_t n); void *EXPORT_FUNC(grub_memset) (void *s, int c, grub_size_t n); @@ -195,8 +244,13 @@ void EXPORT_FUNC(grub_real_dprintf) (const char *file, const char *condition, const char *fmt, ...) __attribute__ ((format (printf, 4, 5))); int EXPORT_FUNC(grub_vprintf) (const char *fmt, va_list args); -int EXPORT_FUNC(grub_sprintf) (char *str, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); -int EXPORT_FUNC(grub_vsprintf) (char *str, const char *fmt, va_list args); +int EXPORT_FUNC(grub_snprintf) (char *str, grub_size_t n, const char *fmt, ...) + __attribute__ ((format (printf, 3, 4))); +int EXPORT_FUNC(grub_vsnprintf) (char *str, grub_size_t n, const char *fmt, + va_list args); +char *EXPORT_FUNC(grub_xasprintf) (const char *fmt, ...) + __attribute__ ((format (printf, 1, 2))); +char *EXPORT_FUNC(grub_xvasprintf) (const char *fmt, va_list args); void EXPORT_FUNC(grub_exit) (void) __attribute__ ((noreturn)); void EXPORT_FUNC(grub_abort) (void) __attribute__ ((noreturn)); grub_size_t EXPORT_FUNC(grub_utf8_to_ucs4) (grub_uint32_t *dest, diff --git a/include/grub/multiboot.h b/include/grub/multiboot.h index 8a7289820..27d4d816d 100644 --- a/include/grub/multiboot.h +++ b/include/grub/multiboot.h @@ -45,7 +45,6 @@ grub_err_t grub_multiboot_add_module (grub_addr_t start, grub_size_t size, void grub_multiboot_set_bootdev (void); grub_uint32_t grub_get_multiboot_mmap_len (void); -void grub_fill_multiboot_mmap (struct multiboot_mmap_entry *first_entry); grub_err_t grub_multiboot_set_video_mode (void); #if defined (GRUB_MACHINE_PCBIOS) || defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU) diff --git a/include/grub/multiboot2.h b/include/grub/multiboot2.h deleted file mode 100644 index af10cdc21..000000000 --- a/include/grub/multiboot2.h +++ /dev/null @@ -1,70 +0,0 @@ -/* multiboot2.h - multiboot2 header file with grub definitions. */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2005,2007 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GRUB. If not, see . - */ - -#ifndef GRUB_MULTIBOOT2_HEADER -#define GRUB_MULTIBOOT2_HEADER 1 - -#include -#include -#include - -#ifndef GRUB_UTIL -typedef grub_uint32_t uint32_t; -typedef grub_uint64_t uint64_t; -#define __WORDSIZE GRUB_TARGET_WORDSIZE -#endif - -struct multiboot2_tag_header; - -grub_err_t -grub_mb2_tag_alloc (grub_addr_t *addr, int key, grub_size_t len); - -grub_err_t -grub_mb2_tags_arch_create (void); - -void -grub_mb2_arch_boot (grub_addr_t entry, void *tags); - -void -grub_mb2_arch_unload (struct multiboot2_tag_header *tags); - -grub_err_t -grub_mb2_arch_elf32_hook (Elf32_Phdr *phdr, grub_addr_t *addr, int *do_load); - -grub_err_t -grub_mb2_arch_elf64_hook (Elf64_Phdr *phdr, grub_addr_t *addr, int *do_load); - -grub_err_t -grub_mb2_arch_module_alloc (grub_size_t size, grub_addr_t *addr); - -grub_err_t -grub_mb2_arch_module_free (grub_addr_t addr, grub_size_t size); - -void -grub_multiboot2 (int argc, char *argv[]); - -void -grub_module2 (int argc, char *argv[]); - -#define for_each_tag(tag, tags) \ - for (tag = tags; \ - tag && tag->key != MULTIBOOT2_TAG_END; \ - tag = (struct multiboot2_tag_header *)((char *)tag + tag->len)) - -#endif /* ! GRUB_MULTIBOOT2_HEADER */ diff --git a/include/grub/normal.h b/include/grub/normal.h index 58b2c7966..fe45ddf71 100644 --- a/include/grub/normal.h +++ b/include/grub/normal.h @@ -101,43 +101,16 @@ void read_command_list (void); /* Defined in `autofs.c'. */ void read_fs_list (void); +void grub_context_init (void); +void grub_context_fini (void); + void read_crypto_list (void); void read_terminal_list (void); void grub_set_more (int onoff); -#ifdef GRUB_UTIL -void grub_normal_init (void); -void grub_normal_fini (void); -void grub_hello_init (void); -void grub_hello_fini (void); -void grub_ls_init (void); -void grub_ls_fini (void); -void grub_cat_init (void); -void grub_cat_fini (void); -void grub_boot_init (void); -void grub_boot_fini (void); -void grub_cmp_init (void); -void grub_cmp_fini (void); -void grub_terminal_init (void); -void grub_terminal_fini (void); -void grub_loop_init (void); -void grub_loop_fini (void); -void grub_help_init (void); -void grub_help_fini (void); -void grub_halt_init (void); -void grub_halt_fini (void); -void grub_reboot_init (void); -void grub_reboot_fini (void); -void grub_configfile_init (void); -void grub_configfile_fini (void); -void grub_search_init (void); -void grub_search_fini (void); -void grub_test_init (void); -void grub_test_fini (void); -void grub_blocklist_init (void); -void grub_blocklist_fini (void); -#endif +int grub_normal_get_line_counter (void); +void grub_install_newline_hook (void); #endif /* ! GRUB_NORMAL_HEADER */ diff --git a/include/grub/partition.h b/include/grub/partition.h index d35658cdd..faa89cea6 100644 --- a/include/grub/partition.h +++ b/include/grub/partition.h @@ -83,20 +83,6 @@ void EXPORT_FUNC(grub_partition_map_register) (grub_partition_map_t partmap); void EXPORT_FUNC(grub_partition_map_unregister) (grub_partition_map_t partmap); -#ifdef GRUB_UTIL -void grub_msdos_partition_map_init (void); -void grub_msdos_partition_map_fini (void); -void grub_amiga_partition_map_init (void); -void grub_amiga_partition_map_fini (void); -void grub_apple_partition_map_init (void); -void grub_apple_partition_map_fini (void); -void grub_sun_partition_map_init (void); -void grub_sun_partition_map_fini (void); -void grub_gpt_partition_map_init (void); -void grub_gpt_partition_map_fini (void); -void grub_apple_partition_map_init (void); -void grub_apple_partition_map_fini (void); -#endif static inline grub_disk_addr_t grub_partition_get_start (const grub_partition_t p) diff --git a/include/grub/pci.h b/include/grub/pci.h index 2bea05410..1f3ac7fc7 100644 --- a/include/grub/pci.h +++ b/include/grub/pci.h @@ -35,6 +35,37 @@ #define GRUB_PCI_ADDR_MEM_MASK ~0xf #define GRUB_PCI_ADDR_IO_MASK ~0x03 +#define GRUB_PCI_REG_PCI_ID 0x00 +#define GRUB_PCI_REG_VENDOR 0x00 +#define GRUB_PCI_REG_DEVICE 0x02 +#define GRUB_PCI_REG_COMMAND 0x04 +#define GRUB_PCI_REG_STATUS 0x06 +#define GRUB_PCI_REG_REVISION 0x08 +#define GRUB_PCI_REG_CLASS 0x08 +#define GRUB_PCI_REG_CACHELINE 0x0c +#define GRUB_PCI_REG_LAT_TIMER 0x0d +#define GRUB_PCI_REG_HEADER_TYPE 0x0e +#define GRUB_PCI_REG_BIST 0x0f +#define GRUB_PCI_REG_ADDRESSES 0x10 + +/* Beware that 64-bit address takes 2 registers. */ +#define GRUB_PCI_REG_ADDRESS_REG0 0x10 +#define GRUB_PCI_REG_ADDRESS_REG1 0x14 +#define GRUB_PCI_REG_ADDRESS_REG2 0x18 +#define GRUB_PCI_REG_ADDRESS_REG3 0x1c +#define GRUB_PCI_REG_ADDRESS_REG4 0x20 +#define GRUB_PCI_REG_ADDRESS_REG5 0x24 + +#define GRUB_PCI_REG_CIS_POINTER 0x28 +#define GRUB_PCI_REG_SUBVENDOR 0x2c +#define GRUB_PCI_REG_SUBSYSTEM 0x2e +#define GRUB_PCI_REG_ROM_ADDRESS 0x30 +#define GRUB_PCI_REG_CAP_POINTER 0x34 +#define GRUB_PCI_REG_IRQ_LINE 0x3c +#define GRUB_PCI_REG_IRQ_PIN 0x3d +#define GRUB_PCI_REG_MIN_GNT 0x3e +#define GRUB_PCI_REG_MAX_LAT 0x3f + typedef grub_uint32_t grub_pci_id_t; #ifdef GRUB_UTIL diff --git a/include/grub/powerpc/ieee1275/ieee1275.h b/include/grub/powerpc/ieee1275/ieee1275.h index 7e93055c9..3c7683fad 100644 --- a/include/grub/powerpc/ieee1275/ieee1275.h +++ b/include/grub/powerpc/ieee1275/ieee1275.h @@ -22,6 +22,7 @@ #include +#define GRUB_IEEE1275_CELL_SIZEOF 4 typedef grub_uint32_t grub_ieee1275_cell_t; #endif /* ! GRUB_IEEE1275_MACHINE_HEADER */ diff --git a/include/grub/powerpc/libgcc.h b/include/grub/powerpc/libgcc.h index 452ad4366..6be122308 100644 --- a/include/grub/powerpc/libgcc.h +++ b/include/grub/powerpc/libgcc.h @@ -33,3 +33,42 @@ void EXPORT_FUNC (__trampoline_setup) (void); #ifdef HAVE___UCMPDI2 void EXPORT_FUNC (__ucmpdi2) (void); #endif + +#ifdef HAVE__RESTGPR_14_X +void EXPORT_FUNC (_restgpr_14_x) (void); +void EXPORT_FUNC (_restgpr_15_x) (void); +void EXPORT_FUNC (_restgpr_16_x) (void); +void EXPORT_FUNC (_restgpr_17_x) (void); +void EXPORT_FUNC (_restgpr_18_x) (void); +void EXPORT_FUNC (_restgpr_19_x) (void); +void EXPORT_FUNC (_restgpr_20_x) (void); +void EXPORT_FUNC (_restgpr_21_x) (void); +void EXPORT_FUNC (_restgpr_22_x) (void); +void EXPORT_FUNC (_restgpr_23_x) (void); +void EXPORT_FUNC (_restgpr_24_x) (void); +void EXPORT_FUNC (_restgpr_25_x) (void); +void EXPORT_FUNC (_restgpr_26_x) (void); +void EXPORT_FUNC (_restgpr_27_x) (void); +void EXPORT_FUNC (_restgpr_28_x) (void); +void EXPORT_FUNC (_restgpr_29_x) (void); +void EXPORT_FUNC (_restgpr_30_x) (void); +void EXPORT_FUNC (_restgpr_31_x) (void); +void EXPORT_FUNC (_savegpr_14) (void); +void EXPORT_FUNC (_savegpr_15) (void); +void EXPORT_FUNC (_savegpr_16) (void); +void EXPORT_FUNC (_savegpr_17) (void); +void EXPORT_FUNC (_savegpr_18) (void); +void EXPORT_FUNC (_savegpr_19) (void); +void EXPORT_FUNC (_savegpr_20) (void); +void EXPORT_FUNC (_savegpr_21) (void); +void EXPORT_FUNC (_savegpr_22) (void); +void EXPORT_FUNC (_savegpr_23) (void); +void EXPORT_FUNC (_savegpr_24) (void); +void EXPORT_FUNC (_savegpr_25) (void); +void EXPORT_FUNC (_savegpr_26) (void); +void EXPORT_FUNC (_savegpr_27) (void); +void EXPORT_FUNC (_savegpr_28) (void); +void EXPORT_FUNC (_savegpr_29) (void); +void EXPORT_FUNC (_savegpr_30) (void); +void EXPORT_FUNC (_savegpr_31) (void); +#endif diff --git a/include/grub/i386/pc/serial.h b/include/grub/serial.h similarity index 96% rename from include/grub/i386/pc/serial.h rename to include/grub/serial.h index 0632ff79d..1c35b4093 100644 --- a/include/grub/i386/pc/serial.h +++ b/include/grub/serial.h @@ -17,8 +17,8 @@ * along with GRUB. If not, see . */ -#ifndef GRUB_SERIAL_MACHINE_HEADER -#define GRUB_SERIAL_MACHINE_HEADER 1 +#ifndef GRUB_SERIAL_HEADER +#define GRUB_SERIAL_HEADER 1 /* Macros. */ diff --git a/include/grub/sparc64/ieee1275/ieee1275.h b/include/grub/sparc64/ieee1275/ieee1275.h index b25e98a6d..527c46ae7 100644 --- a/include/grub/sparc64/ieee1275/ieee1275.h +++ b/include/grub/sparc64/ieee1275/ieee1275.h @@ -22,6 +22,7 @@ #include +#define GRUB_IEEE1275_CELL_SIZEOF 8 typedef grub_uint64_t grub_ieee1275_cell_t; /* Encoding of 'mode' argument to grub_ieee1275_map_physical() */ @@ -36,10 +37,6 @@ typedef grub_uint64_t grub_ieee1275_cell_t; #define IEEE1275_MAP_DEFAULT (IEEE1275_MAP_WRITE | IEEE1275_MAP_READ | \ IEEE1275_MAP_EXEC | IEEE1275_MAP_CACHED) -extern int EXPORT_FUNC(grub_ieee1275_map_physical) (grub_addr_t paddr, - grub_addr_t vaddr, - grub_size_t size, - grub_uint32_t mode); extern int EXPORT_FUNC(grub_ieee1275_claim_vaddr) (grub_addr_t vaddr, grub_size_t size); extern int EXPORT_FUNC(grub_ieee1275_alloc_physmem) (grub_addr_t *paddr, diff --git a/include/grub/term.h b/include/grub/term.h index 3d644b848..143aabe1e 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -208,9 +208,8 @@ grub_term_register_input (const char *name __attribute__ ((unused)), else { /* If this is the first terminal, enable automatically. */ - if (term->init) - term->init (); - grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs), GRUB_AS_LIST (term)); + if (! term->init || term->init () == GRUB_ERR_NONE) + grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs), GRUB_AS_LIST (term)); } } @@ -224,10 +223,9 @@ grub_term_register_output (const char *name __attribute__ ((unused)), else { /* If this is the first terminal, enable automatically. */ - if (term->init) - term->init (); - grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs), - GRUB_AS_LIST (term)); + if (! term->init || term->init () == GRUB_ERR_NONE) + grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs), + GRUB_AS_LIST (term)); } } diff --git a/include/grub/test.h b/include/grub/test.h index 544e1c817..a7d3a2399 100644 --- a/include/grub/test.h +++ b/include/grub/test.h @@ -1,3 +1,21 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + #ifndef GRUB_TEST_HEADER #define GRUB_TEST_HEADER diff --git a/include/grub/time.h b/include/grub/time.h index 115fbd95e..ae2617edb 100644 --- a/include/grub/time.h +++ b/include/grub/time.h @@ -23,8 +23,10 @@ #include #include -#ifdef GRUB_MACHINE_EMU +#if defined (GRUB_MACHINE_EMU) || defined (GRUB_UTIL) #define GRUB_TICKS_PER_SECOND 100000 +/* Return the real time in ticks. */ +grub_uint32_t EXPORT_FUNC (grub_get_rtc) (void); #else #include #endif diff --git a/include/grub/trig.h b/include/grub/trig.h new file mode 100644 index 000000000..2512a5f07 --- /dev/null +++ b/include/grub/trig.h @@ -0,0 +1,44 @@ +/* trig.h - Trigonometric function support. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_TRIG_HEADER +#define GRUB_TRIG_HEADER 1 + +#define GRUB_TRIG_ANGLE_MAX 256 +#define GRUB_TRIG_ANGLE_MASK 255 +#define GRUB_TRIG_FRACTION_SCALE 16384 + +extern short grub_trig_sintab[]; +extern short grub_trig_costab[]; + +static __inline int +grub_sin (int x) +{ + x &= GRUB_TRIG_ANGLE_MASK; + return grub_trig_sintab[x]; +} + +static __inline int +grub_cos (int x) +{ + x &= GRUB_TRIG_ANGLE_MASK; + return grub_trig_costab[x]; +} + +#endif /* ! GRUB_TRIG_HEADER */ diff --git a/include/grub/types.h b/include/grub/types.h index 93174b424..9eaafd0c1 100644 --- a/include/grub/types.h +++ b/include/grub/types.h @@ -223,4 +223,10 @@ static inline grub_uint64_t grub_swap_bytes64(grub_uint64_t x) # endif #endif /* ! WORDS_BIGENDIAN */ +#if GRUB_TARGET_SIZEOF_VOID_P == 8 +# define grub_host_to_target_addr(x) grub_host_to_target64(x) +#else +# define grub_host_to_target_addr(x) grub_host_to_target32(x) +#endif + #endif /* ! GRUB_TYPES_HEADER */ diff --git a/include/grub/video.h b/include/grub/video.h index 437c98eb9..57f2b37f2 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -34,6 +34,10 @@ struct grub_video_render_target; struct grub_video_bitmap; /* Defines used to describe video mode or rendering target. */ +/* If following is set render target contains currenly displayed image + after swapping buffers (otherwise it contains previously displayed image). + */ +#define GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP 0x00000080 #define GRUB_VIDEO_MODE_TYPE_PURE_TEXT 0x00000040 #define GRUB_VIDEO_MODE_TYPE_ALPHA 0x00000020 #define GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED 0x00000010 @@ -48,6 +52,8 @@ struct grub_video_bitmap; #define GRUB_VIDEO_MODE_TYPE_DEPTH_MASK 0x0000ff00 #define GRUB_VIDEO_MODE_TYPE_DEPTH_POS 8 +/* The basic render target representing the whole display. This always + renders to the back buffer when double-buffering is in use. */ #define GRUB_VIDEO_RENDER_TARGET_DISPLAY \ ((struct grub_video_render_target *) 0) @@ -151,6 +157,16 @@ struct grub_video_mode_info grub_uint8_t fg_alpha; }; +/* A 2D rectangle type. */ +struct grub_video_rect +{ + unsigned x; + unsigned y; + unsigned width; + unsigned height; +}; +typedef struct grub_video_rect grub_video_rect_t; + struct grub_video_palette_data { grub_uint8_t r; /* Red color value (0-255). */ @@ -180,7 +196,7 @@ struct grub_video_adapter grub_err_t (*fini) (void); grub_err_t (*setup) (unsigned int width, unsigned int height, - unsigned int mode_type); + unsigned int mode_type, unsigned int mode_mask); grub_err_t (*get_info) (struct grub_video_mode_info *mode_info); @@ -243,13 +259,13 @@ struct grub_video_adapter }; typedef struct grub_video_adapter *grub_video_adapter_t; -void grub_video_register (grub_video_adapter_t adapter); +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)); -grub_err_t grub_video_restore (void); +grub_err_t EXPORT_FUNC (grub_video_restore) (void); -grub_err_t grub_video_get_info (struct grub_video_mode_info *mode_info); +grub_err_t EXPORT_FUNC (grub_video_get_info) (struct grub_video_mode_info *mode_info); /* Framebuffer address may change as a part of normal operation (e.g. double buffering). That's why you need to stop video subsystem to be @@ -267,57 +283,78 @@ grub_err_t grub_video_set_palette (unsigned int start, unsigned int count, grub_err_t grub_video_get_palette (unsigned int start, unsigned int count, struct grub_video_palette_data *palette_data); -grub_err_t grub_video_set_viewport (unsigned int x, unsigned int y, - unsigned int width, unsigned int height); +grub_err_t EXPORT_FUNC (grub_video_set_viewport) (unsigned int x, + unsigned int y, + unsigned int width, + unsigned int height); -grub_err_t grub_video_get_viewport (unsigned int *x, unsigned int *y, - unsigned int *width, unsigned int *height); +grub_err_t EXPORT_FUNC (grub_video_get_viewport) (unsigned int *x, + unsigned int *y, + unsigned int *width, + unsigned int *height); -grub_video_color_t grub_video_map_color (grub_uint32_t color_name); +grub_video_color_t EXPORT_FUNC (grub_video_map_color) (grub_uint32_t color_name); -grub_video_color_t grub_video_map_rgb (grub_uint8_t red, grub_uint8_t green, - grub_uint8_t blue); +grub_video_color_t EXPORT_FUNC (grub_video_map_rgb) (grub_uint8_t red, + grub_uint8_t green, + grub_uint8_t blue); -grub_video_color_t grub_video_map_rgba (grub_uint8_t red, grub_uint8_t green, - grub_uint8_t blue, grub_uint8_t alpha); +grub_video_color_t EXPORT_FUNC (grub_video_map_rgba) (grub_uint8_t red, + grub_uint8_t green, + grub_uint8_t blue, + grub_uint8_t alpha); -grub_err_t grub_video_unmap_color (grub_video_color_t color, - grub_uint8_t *red, grub_uint8_t *green, - grub_uint8_t *blue, grub_uint8_t *alpha); +grub_err_t EXPORT_FUNC (grub_video_unmap_color) (grub_video_color_t color, + grub_uint8_t *red, + grub_uint8_t *green, + grub_uint8_t *blue, + grub_uint8_t *alpha); -grub_err_t grub_video_fill_rect (grub_video_color_t color, int x, int y, - unsigned int width, unsigned int height); +grub_err_t EXPORT_FUNC (grub_video_fill_rect) (grub_video_color_t color, + int x, int y, + unsigned int width, + unsigned int height); -grub_err_t grub_video_blit_bitmap (struct grub_video_bitmap *bitmap, - 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 EXPORT_FUNC (grub_video_blit_bitmap) (struct grub_video_bitmap *bitmap, + 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 grub_video_blit_render_target (struct grub_video_render_target *source, - 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 EXPORT_FUNC (grub_video_blit_render_target) (struct grub_video_render_target *source, + 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 grub_video_scroll (grub_video_color_t color, int dx, int dy); -grub_err_t grub_video_swap_buffers (void); +grub_err_t EXPORT_FUNC (grub_video_swap_buffers) (void); -grub_err_t grub_video_create_render_target (struct grub_video_render_target **result, - unsigned int width, - unsigned int height, - unsigned int mode_type); +grub_err_t EXPORT_FUNC (grub_video_create_render_target) (struct grub_video_render_target **result, + unsigned int width, + unsigned int height, + unsigned int mode_type); -grub_err_t grub_video_delete_render_target (struct grub_video_render_target *target); +grub_err_t EXPORT_FUNC (grub_video_delete_render_target) (struct grub_video_render_target *target); -grub_err_t grub_video_set_active_render_target (struct grub_video_render_target *target); +grub_err_t EXPORT_FUNC (grub_video_set_active_render_target) (struct grub_video_render_target *target); grub_err_t grub_video_get_active_render_target (struct grub_video_render_target **target); -grub_err_t grub_video_set_mode (const char *modestring, - int NESTED_FUNC_ATTR (*hook) (grub_video_adapter_t p, - struct grub_video_mode_info *mode_info)); +grub_err_t EXPORT_FUNC (grub_video_set_mode) (const char *modestring, + unsigned int modemask, + unsigned int modevalue); + +static inline int +grub_video_check_mode_flag (unsigned int flags, unsigned int mask, + unsigned int flag, int def) +{ + return (flag & mask) ? !! (flags & flag) : def; +} grub_video_driver_id_t grub_video_get_driver_id (void); diff --git a/include/grub/video_fb.h b/include/grub/video_fb.h index 17debd69f..3046a597b 100644 --- a/include/grub/video_fb.h +++ b/include/grub/video_fb.h @@ -115,4 +115,15 @@ grub_video_fb_get_active_render_target (struct grub_video_fbrender_target **targ grub_err_t grub_video_fb_set_active_render_target (struct grub_video_fbrender_target *target); +typedef grub_err_t +(*grub_video_fb_doublebuf_update_screen_t) (struct grub_video_fbrender_target *front, + struct grub_video_fbrender_target *back); + +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); + #endif /* ! GRUB_VIDEO_FB_HEADER */ diff --git a/include/grub/x86_64/at_keyboard.h b/include/grub/x86_64/at_keyboard.h new file mode 100644 index 000000000..c632aa85c --- /dev/null +++ b/include/grub/x86_64/at_keyboard.h @@ -0,0 +1 @@ +#include diff --git a/include/grub/xnu.h b/include/grub/xnu.h index 6ce17c25e..6089aad34 100644 --- a/include/grub/xnu.h +++ b/include/grub/xnu.h @@ -108,5 +108,8 @@ extern grub_uint32_t grub_xnu_heap_real_start; extern grub_size_t grub_xnu_heap_size; extern void *grub_xnu_heap_start; extern struct grub_video_bitmap *grub_xnu_bitmap; +typedef enum {GRUB_XNU_BITMAP_CENTER, GRUB_XNU_BITMAP_STRETCH} + grub_xnu_bitmap_mode_t; +extern grub_xnu_bitmap_mode_t grub_xnu_bitmap_mode; extern int grub_xnu_is_64bit; #endif diff --git a/include/multiboot.h b/include/multiboot.h index 57c154c98..c529c5c5f 100644 --- a/include/multiboot.h +++ b/include/multiboot.h @@ -233,6 +233,8 @@ struct multiboot_mmap_entry multiboot_uint64_t len; #define MULTIBOOT_MEMORY_AVAILABLE 1 #define MULTIBOOT_MEMORY_RESERVED 2 +#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3 +#define MULTIBOOT_MEMORY_NVS 4 multiboot_uint32_t type; } __attribute__((packed)); typedef struct multiboot_mmap_entry multiboot_memory_map_t; diff --git a/include/multiboot2.h b/include/multiboot2.h index a76364fa7..20c5c5696 100644 --- a/include/multiboot2.h +++ b/include/multiboot2.h @@ -107,6 +107,8 @@ struct multiboot_mmap_entry multiboot_uint64_t len; #define MULTIBOOT_MEMORY_AVAILABLE 1 #define MULTIBOOT_MEMORY_RESERVED 2 +#define MULTIBOOT_MEMORY_ACPI_RECLAIMABLE 3 +#define MULTIBOOT_MEMORY_NVS 4 multiboot_uint32_t type; } __attribute__((packed)); typedef struct multiboot_mmap_entry multiboot_memory_map_t; diff --git a/io/gzio.c b/io/gzio.c index 39f6d7b13..9bf609105 100644 --- a/io/gzio.c +++ b/io/gzio.c @@ -1121,14 +1121,13 @@ grub_gzio_open (grub_file_t io, int transparent) if (! file) return 0; - gzio = grub_malloc (sizeof (*gzio)); + gzio = grub_zalloc (sizeof (*gzio)); if (! gzio) { grub_free (file); return 0; } - grub_memset (gzio, 0, sizeof (*gzio)); gzio->file = io; file->device = io->device; diff --git a/kern/corecmd.c b/kern/corecmd.c index 3e508cd2c..8b8df63cb 100644 --- a/kern/corecmd.c +++ b/kern/corecmd.c @@ -73,18 +73,6 @@ grub_core_cmd_unset (struct grub_command *cmd __attribute__ ((unused)), return 0; } -static grub_err_t -grub_core_cmd_export (struct grub_command *cmd __attribute__ ((unused)), - int argc, char **args) -{ - if (argc < 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, - "no environment variable specified"); - - grub_env_export (args[0]); - return 0; -} - /* insmod MODULE */ static grub_err_t grub_core_cmd_insmod (struct grub_command *cmd __attribute__ ((unused)), @@ -193,8 +181,6 @@ grub_register_core_commands (void) "[ENVVAR=VALUE]", "Set an environment variable."); grub_register_command ("unset", grub_core_cmd_unset, "ENVVAR", "Remove an environment variable."); - grub_register_command ("export", grub_core_cmd_export, - "ENVVAR", "Export a variable."); grub_register_command ("ls", grub_core_cmd_ls, "[ARG]", "List devices or files."); grub_register_command ("insmod", grub_core_cmd_insmod, diff --git a/kern/device.c b/kern/device.c index f519c63b2..cd019fdaf 100644 --- a/kern/device.c +++ b/kern/device.c @@ -86,7 +86,7 @@ grub_device_iterate (int (*hook) (const char *name)) struct part_ent { struct part_ent *next; - char name[0]; + char *name; } *ents; int iterate_disk (const char *disk_name) @@ -118,6 +118,7 @@ grub_device_iterate (int (*hook) (const char *name)) if (!ret) ret = hook (p->name); + grub_free (p->name); grub_free (p); p = next; } @@ -138,15 +139,20 @@ grub_device_iterate (int (*hook) (const char *name)) if (! partition_name) return 1; - p = grub_malloc (sizeof (p->next) + grub_strlen (disk->name) + 1 + - grub_strlen (partition_name) + 1); + p = grub_malloc (sizeof (*p)); if (!p) { grub_free (partition_name); return 1; } - grub_sprintf (p->name, "%s,%s", disk->name, partition_name); + p->name = grub_xasprintf ("%s,%s", disk->name, partition_name); + if (!p->name) + { + grub_free (partition_name); + grub_free (p); + return 1; + } grub_free (partition_name); p->next = ents; diff --git a/kern/disk.c b/kern/disk.c index 544896f2f..5c30e1727 100644 --- a/kern/disk.c +++ b/kern/disk.c @@ -441,7 +441,7 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, grub_errno = GRUB_ERR_NONE; - num = ((size + GRUB_DISK_SECTOR_SIZE - 1) + num = ((size + real_offset + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS); p = grub_realloc (tmp_buf, num << GRUB_DISK_SECTOR_BITS); @@ -464,12 +464,14 @@ grub_disk_read (grub_disk_t disk, grub_disk_addr_t sector, if (disk->read_hook) while (size) { + grub_size_t to_read = (size > GRUB_DISK_SECTOR_SIZE) ? GRUB_DISK_SECTOR_SIZE : size; (disk->read_hook) (sector, real_offset, - ((size > GRUB_DISK_SECTOR_SIZE) - ? GRUB_DISK_SECTOR_SIZE - : size)); + to_read); + if (grub_errno != GRUB_ERR_NONE) + goto finish; + sector++; - size -= GRUB_DISK_SECTOR_SIZE - real_offset; + size -= to_read - real_offset; real_offset = 0; } diff --git a/kern/dl.c b/kern/dl.c index 20ab1c5c2..4735a004a 100644 --- a/kern/dl.c +++ b/kern/dl.c @@ -341,6 +341,7 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e) switch (type) { case STT_NOTYPE: + case STT_OBJECT: /* Resolve a global symbol. */ if (sym->st_name != 0 && sym->st_shndx == 0) { @@ -350,15 +351,13 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e) "the symbol `%s' not found", name); } else - sym->st_value = 0; - break; - - case STT_OBJECT: - sym->st_value += (Elf_Addr) grub_dl_get_section_addr (mod, - sym->st_shndx); - if (bind != STB_LOCAL) - if (grub_dl_register_symbol (name, (void *) sym->st_value, mod)) - return grub_errno; + { + sym->st_value += (Elf_Addr) grub_dl_get_section_addr (mod, + sym->st_shndx); + if (bind != STB_LOCAL) + if (grub_dl_register_symbol (name, (void *) sym->st_value, mod)) + return grub_errno; + } break; case STT_FUNC: @@ -628,12 +627,10 @@ grub_dl_load (const char *name) return 0; } - filename = (char *) grub_malloc (grub_strlen (grub_dl_dir) + 1 - + grub_strlen (name) + 4 + 1); + filename = grub_xasprintf ("%s/%s.mod", grub_dl_dir, name); if (! filename) return 0; - grub_sprintf (filename, "%s/%s.mod", grub_dl_dir, name); mod = grub_dl_load_file (filename); grub_free (filename); diff --git a/kern/efi/efi.c b/kern/efi/efi.c index c6ce04c5e..d8b225535 100644 --- a/kern/efi/efi.c +++ b/kern/efi/efi.c @@ -1,7 +1,7 @@ /* efi.c - generic EFI support */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2006,2007,2008,2009 Free Software Foundation, Inc. + * Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -162,6 +162,8 @@ grub_exit (void) for (;;) ; } +/* On i386, a firmware-independant grub_reboot() is provided by realmode.S. */ +#ifndef __i386__ void grub_reboot (void) { @@ -169,6 +171,7 @@ grub_reboot (void) efi_call_4 (grub_efi_system_table->runtime_services->reset_system, GRUB_EFI_RESET_COLD, GRUB_EFI_SUCCESS, 0, NULL); } +#endif void grub_halt (void) diff --git a/kern/efi/init.c b/kern/efi/init.c index 8862eb2f9..a0b4ff779 100644 --- a/kern/efi/init.c +++ b/kern/efi/init.c @@ -63,11 +63,10 @@ grub_efi_set_prefix (void) if (p) *p = '\0'; - prefix = grub_malloc (1 + grub_strlen (device) + 1 - + grub_strlen (file) + 1); + prefix = grub_xasprintf ("(%s)%s", device, file); if (prefix) { - grub_sprintf (prefix, "(%s)%s", device, file); + grub_env_set ("prefix", prefix); grub_free (prefix); } diff --git a/kern/elf.c b/kern/elf.c index 7625f6acd..d9948a822 100644 --- a/kern/elf.c +++ b/kern/elf.c @@ -172,7 +172,7 @@ grub_elf32_phdr_iterate (grub_elf_t elf, /* Calculate the amount of memory spanned by the segments. */ grub_size_t -grub_elf32_size (grub_elf_t elf) +grub_elf32_size (grub_elf_t elf, Elf32_Addr *base) { Elf32_Addr segments_start = (Elf32_Addr) -1; Elf32_Addr segments_end = 0; @@ -198,6 +198,9 @@ grub_elf32_size (grub_elf_t elf) grub_elf32_phdr_iterate (elf, calcsize, 0); + if (base) + *base = 0; + if (nr_phdrs == 0) { grub_error (GRUB_ERR_BAD_OS, "no program headers present"); @@ -211,10 +214,12 @@ grub_elf32_size (grub_elf_t elf) return 0; } + if (base) + *base = segments_start; + return segments_end - segments_start; } - /* Load every loadable segment into memory specified by `_load_hook'. */ grub_err_t grub_elf32_load (grub_elf_t _elf, grub_elf32_load_hook_t _load_hook, @@ -353,7 +358,7 @@ grub_elf64_phdr_iterate (grub_elf_t elf, /* Calculate the amount of memory spanned by the segments. */ grub_size_t -grub_elf64_size (grub_elf_t elf) +grub_elf64_size (grub_elf_t elf, Elf64_Addr *base) { Elf64_Addr segments_start = (Elf64_Addr) -1; Elf64_Addr segments_end = 0; @@ -379,6 +384,9 @@ grub_elf64_size (grub_elf_t elf) grub_elf64_phdr_iterate (elf, calcsize, 0); + if (base) + *base = 0; + if (nr_phdrs == 0) { grub_error (GRUB_ERR_BAD_OS, "no program headers present"); @@ -392,6 +400,9 @@ grub_elf64_size (grub_elf_t elf) return 0; } + if (base) + *base = segments_start; + return segments_end - segments_start; } diff --git a/kern/env.c b/kern/env.c index 8f94e891e..84b3a001d 100644 --- a/kern/env.c +++ b/kern/env.c @@ -18,34 +18,15 @@ */ #include +#include #include #include -/* The size of the hash table. */ -#define HASHSZ 13 - -/* A hashtable for quick lookup of variables. */ -struct grub_env_context -{ - /* A hash table for variables. */ - struct grub_env_var *vars[HASHSZ]; - - /* One level deeper on the stack. */ - struct grub_env_context *prev; -}; - -/* This is used for sorting only. */ -struct grub_env_sorted_var -{ - struct grub_env_var *var; - struct grub_env_sorted_var *next; -}; - /* The initial context. */ static struct grub_env_context initial_context; /* The current context. */ -static struct grub_env_context *current_context = &initial_context; +struct grub_env_context *grub_current_context = &initial_context; /* Return the hash representation of the string S. */ static unsigned int @@ -60,88 +41,20 @@ grub_env_hashval (const char *s) return i % HASHSZ; } -static struct grub_env_var * +struct grub_env_var * grub_env_find (const char *name) { struct grub_env_var *var; int idx = grub_env_hashval (name); /* Look for the variable in the current context. */ - for (var = current_context->vars[idx]; var; var = var->next) + for (var = grub_current_context->vars[idx]; var; var = var->next) if (grub_strcmp (var->name, name) == 0) return var; return 0; } -grub_err_t -grub_env_context_open (int export) -{ - struct grub_env_context *context; - int i; - - context = grub_zalloc (sizeof (*context)); - if (! context) - return grub_errno; - - context->prev = current_context; - current_context = context; - - /* Copy exported variables. */ - for (i = 0; i < HASHSZ; i++) - { - struct grub_env_var *var; - - for (var = context->prev->vars[i]; var; var = var->next) - { - if (export && var->type == GRUB_ENV_VAR_GLOBAL) - { - if (grub_env_set (var->name, var->value) != GRUB_ERR_NONE) - { - grub_env_context_close (); - return grub_errno; - } - grub_env_export (var->name); - grub_register_variable_hook (var->name, var->read_hook, var->write_hook); - } - } - } - - return GRUB_ERR_NONE; -} - -grub_err_t -grub_env_context_close (void) -{ - struct grub_env_context *context; - int i; - - if (! current_context->prev) - grub_fatal ("cannot close the initial context"); - - /* Free the variables associated with this context. */ - for (i = 0; i < HASHSZ; i++) - { - struct grub_env_var *p, *q; - - for (p = current_context->vars[i]; p; p = q) - { - q = p->next; - grub_free (p->name); - if (p->type != GRUB_ENV_VAR_DATA) - grub_free (p->value); - grub_free (p); - } - } - - /* Restore the previous context. */ - context = current_context->prev; - grub_free (current_context); - current_context = context; - - return GRUB_ERR_NONE; -} - static void grub_env_insert (struct grub_env_context *context, struct grub_env_var *var) @@ -165,26 +78,6 @@ grub_env_remove (struct grub_env_var *var) var->next->prevp = var->prevp; } -grub_err_t -grub_env_export (const char *name) -{ - struct grub_env_var *var; - - var = grub_env_find (name); - if (! var) - { - grub_err_t err; - - err = grub_env_set (name, ""); - if (err) - return err; - var = grub_env_find (name); - } - var->type = GRUB_ENV_VAR_GLOBAL; - - return GRUB_ERR_NONE; -} - grub_err_t grub_env_set (const char *name, const char *val) { @@ -216,9 +109,8 @@ grub_env_set (const char *name, const char *val) if (! var) return grub_errno; - /* This is not necessary, because GRUB_ENV_VAR_LOCAL == 0. But leave - this for readability. */ - var->type = GRUB_ENV_VAR_LOCAL; + /* This is not necessary. But leave this for readability. */ + var->global = 0; var->name = grub_strdup (name); if (! var->name) @@ -228,7 +120,7 @@ grub_env_set (const char *name, const char *val) if (! var->value) goto fail; - grub_env_insert (current_context, var); + grub_env_insert (grub_current_context, var); return GRUB_ERR_NONE; @@ -273,8 +165,7 @@ grub_env_unset (const char *name) grub_env_remove (var); grub_free (var->name); - if (var->type != GRUB_ENV_VAR_DATA) - grub_free (var->value); + grub_free (var->value); grub_free (var); } @@ -290,14 +181,10 @@ grub_env_iterate (int (*func) (struct grub_env_var *var)) { struct grub_env_var *var; - for (var = current_context->vars[i]; var; var = var->next) + for (var = grub_current_context->vars[i]; var; var = var->next) { struct grub_env_sorted_var *p, **q; - /* Ignore data slots. */ - if (var->type == GRUB_ENV_VAR_DATA) - continue; - sorted_var = grub_malloc (sizeof (*sorted_var)); if (! sorted_var) goto fail; @@ -353,84 +240,3 @@ grub_register_variable_hook (const char *name, return GRUB_ERR_NONE; } - -static char * -mangle_data_slot_name (const char *name) -{ - char *mangled_name; - - mangled_name = grub_malloc (grub_strlen (name) + 2); - if (! mangled_name) - return 0; - - grub_sprintf (mangled_name, "\e%s", name); - return mangled_name; -} - -grub_err_t -grub_env_set_data_slot (const char *name, const void *ptr) -{ - char *mangled_name; - struct grub_env_var *var; - - mangled_name = mangle_data_slot_name (name); - if (! mangled_name) - goto fail; - - /* If the variable does already exist, just update the variable. */ - var = grub_env_find (mangled_name); - if (var) - { - var->value = (char *) ptr; - return GRUB_ERR_NONE; - } - - /* The variable does not exist, so create a new one. */ - var = grub_zalloc (sizeof (*var)); - if (! var) - goto fail; - - var->type = GRUB_ENV_VAR_DATA; - var->name = mangled_name; - var->value = (char *) ptr; - - grub_env_insert (current_context, var); - - return GRUB_ERR_NONE; - - fail: - - grub_free (mangled_name); - return grub_errno; -} - -void * -grub_env_get_data_slot (const char *name) -{ - char *mangled_name; - void *ptr = 0; - - mangled_name = mangle_data_slot_name (name); - if (! mangled_name) - goto fail; - - ptr = grub_env_get (mangled_name); - grub_free (mangled_name); - - fail: - - return ptr; -} - -void -grub_env_unset_data_slot (const char *name) -{ - char *mangled_name; - - mangled_name = mangle_data_slot_name (name); - if (! mangled_name) - return; - - grub_env_unset (mangled_name); - grub_free (mangled_name); -} diff --git a/kern/err.c b/kern/err.c index 1a881db25..8272467f5 100644 --- a/kern/err.c +++ b/kern/err.c @@ -45,7 +45,7 @@ grub_error (grub_err_t n, const char *fmt, ...) grub_errno = n; va_start (ap, fmt); - grub_vsprintf (grub_errmsg, _(fmt), ap); + grub_vsnprintf (grub_errmsg, sizeof (grub_errmsg), _(fmt), ap); va_end (ap); return n; diff --git a/kern/i386/coreboot/init.c b/kern/i386/coreboot/init.c index 550a2a60a..5f80f28c1 100644 --- a/kern/i386/coreboot/init.c +++ b/kern/i386/coreboot/init.c @@ -67,12 +67,6 @@ grub_exit (void) grub_cpu_idle (); } -void -grub_arch_sync_caches (void *address __attribute__ ((unused)), - grub_size_t len __attribute__ ((unused))) -{ -} - void grub_machine_init (void) { diff --git a/kern/i386/efi/init.c b/kern/i386/efi/init.c index e1950d758..f73f828c6 100644 --- a/kern/i386/efi/init.c +++ b/kern/i386/efi/init.c @@ -45,9 +45,3 @@ grub_machine_set_prefix (void) { grub_efi_set_prefix (); } - -void -grub_arch_sync_caches (void *address __attribute__ ((unused)), - grub_size_t len __attribute__ ((unused))) -{ -} diff --git a/kern/i386/efi/startup.S b/kern/i386/efi/startup.S index b88628010..5b464ab83 100644 --- a/kern/i386/efi/startup.S +++ b/kern/i386/efi/startup.S @@ -1,7 +1,7 @@ /* startup.S - bootstrap GRUB itself */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2006,2007 Free Software Foundation, Inc. + * Copyright (C) 2006,2007,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 @@ -62,3 +62,5 @@ codestart: movl %eax, EXT_C(grub_efi_system_table) call EXT_C(grub_main) ret + +#include "../realmode.S" diff --git a/kern/i386/ieee1275/init.c b/kern/i386/ieee1275/init.c index 7658ee1a7..9fb98739b 100644 --- a/kern/i386/ieee1275/init.c +++ b/kern/i386/ieee1275/init.c @@ -26,9 +26,3 @@ void grub_stop_floppy (void) { } - -void -grub_arch_sync_caches (void *address __attribute__ ((unused)), - grub_size_t len __attribute__ ((unused))) -{ -} diff --git a/kern/i386/pc/init.c b/kern/i386/pc/init.c index 0f2374c6d..fa646df19 100644 --- a/kern/i386/pc/init.c +++ b/kern/i386/pc/init.c @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc. + * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -46,32 +47,40 @@ static int num_regions; grub_addr_t grub_os_area_addr; grub_size_t grub_os_area_size; -void -grub_arch_sync_caches (void *address __attribute__ ((unused)), - grub_size_t len __attribute__ ((unused))) -{ -} - static char * make_install_device (void) { /* XXX: This should be enough. */ - char dev[100]; + char dev[100], *ptr = dev; if (grub_prefix[0] != '(') { /* No hardcoded root partition - make it from the boot drive and the partition number encoded at the install time. */ - grub_sprintf (dev, "(%cd%u", (grub_boot_drive & 0x80) ? 'h' : 'f', - grub_boot_drive & 0x7f); + if (grub_boot_drive == GRUB_BOOT_MACHINE_PXE_DL) + { + grub_strcpy (dev, "(pxe"); + ptr += sizeof ("(pxe") - 1; + } + else + { + grub_snprintf (dev, sizeof (dev), + "(%cd%u", (grub_boot_drive & 0x80) ? 'h' : 'f', + grub_boot_drive & 0x7f); + ptr += grub_strlen (ptr); - if (grub_install_dos_part >= 0) - grub_sprintf (dev + grub_strlen (dev), ",%u", grub_install_dos_part + 1); + if (grub_install_dos_part >= 0) + grub_snprintf (ptr, sizeof (dev) - (ptr - dev), + ",%u", grub_install_dos_part + 1); + ptr += grub_strlen (ptr); - if (grub_install_bsd_part >= 0) - grub_sprintf (dev + grub_strlen (dev), ",%c", grub_install_bsd_part + 'a'); + if (grub_install_bsd_part >= 0) + grub_snprintf (ptr, sizeof (dev) - (ptr - dev), ",%c", + grub_install_bsd_part + 'a'); + ptr += grub_strlen (ptr); + } - grub_sprintf (dev + grub_strlen (dev), ")%s", grub_prefix); + grub_snprintf (ptr, sizeof (dev) - (ptr - dev), ")%s", grub_prefix); grub_strcpy (grub_prefix, dev); } diff --git a/kern/i386/qemu/mmap.c b/kern/i386/qemu/mmap.c index 4ccae023a..c7fc4f45e 100644 --- a/kern/i386/qemu/mmap.c +++ b/kern/i386/qemu/mmap.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #define QEMU_CMOS_MEMSIZE_HIGH 0x35 #define QEMU_CMOS_MEMSIZE_LOW 0x34 diff --git a/kern/i386/realmode.S b/kern/i386/realmode.S index a74eb1217..578c8d2a8 100644 --- a/kern/i386/realmode.S +++ b/kern/i386/realmode.S @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2009 Free Software Foundation, Inc. + * Copyright (C) 1999,2000,2001,2002,2003,2005,2006,2007,2009,2010 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,6 +16,7 @@ * along with GRUB. If not, see . */ +#include /* * Note: These functions defined in this file may be called from C. diff --git a/kern/ieee1275/ieee1275.c b/kern/ieee1275/ieee1275.c index 8a5773c23..9e2919172 100644 --- a/kern/ieee1275/ieee1275.c +++ b/kern/ieee1275/ieee1275.c @@ -284,8 +284,8 @@ grub_ieee1275_read (grub_ieee1275_ihandle_t ihandle, void *buffer, } int -grub_ieee1275_seek (grub_ieee1275_ihandle_t ihandle, int pos_hi, - int pos_lo, grub_ssize_t *result) +grub_ieee1275_seek (grub_ieee1275_ihandle_t ihandle, grub_disk_addr_t pos, + grub_ssize_t *result) { struct write_args { @@ -299,8 +299,15 @@ grub_ieee1275_seek (grub_ieee1275_ihandle_t ihandle, int pos_hi, INIT_IEEE1275_COMMON (&args.common, "seek", 3, 1); args.ihandle = ihandle; - args.pos_hi = (grub_ieee1275_cell_t) pos_hi; - args.pos_lo = (grub_ieee1275_cell_t) pos_lo; + /* To prevent stupid gcc warning. */ +#if GRUB_IEEE1275_CELL_SIZEOF >= 8 + args.pos_hi = 0; + args.pos_lo = pos; +#else + args.pos_hi = (grub_ieee1275_cell_t) (pos >> (8 * GRUB_IEEE1275_CELL_SIZEOF)); + args.pos_lo = (grub_ieee1275_cell_t) + (pos & ((1ULL << (8 * GRUB_IEEE1275_CELL_SIZEOF)) - 1)); +#endif if (IEEE1275_CALL_ENTRY_FN (&args) == -1) return -1; diff --git a/kern/ieee1275/init.c b/kern/ieee1275/init.c index 3e11d2369..f3a4f4d81 100644 --- a/kern/ieee1275/init.c +++ b/kern/ieee1275/init.c @@ -75,10 +75,6 @@ grub_machine_set_prefix (void) char *filename; char *prefix; - if (grub_env_get ("prefix")) - /* We already set prefix in grub_machine_init(). */ - return; - if (grub_prefix[0]) { grub_env_set ("prefix", grub_prefix); @@ -111,11 +107,12 @@ grub_machine_set_prefix (void) *lastslash = '\0'; grub_translate_ieee1275_path (filename); - newprefix = grub_malloc (grub_strlen (prefix) - + grub_strlen (filename)); - grub_sprintf (newprefix, "%s%s", prefix, filename); - grub_free (prefix); - prefix = newprefix; + newprefix = grub_xasprintf ("%s%s", prefix, filename); + if (newprefix) + { + grub_free (prefix); + prefix = newprefix; + } } } diff --git a/kern/ieee1275/openfw.c b/kern/ieee1275/openfw.c index c38eb450f..13fccbf9a 100644 --- a/kern/ieee1275/openfw.c +++ b/kern/ieee1275/openfw.c @@ -38,7 +38,7 @@ grub_children_iterate (char *devpath, grub_ieee1275_phandle_t dev; grub_ieee1275_phandle_t child; char *childtype, *childpath; - char *childname, *fullname; + char *childname; int ret = 0; if (grub_ieee1275_finddevice (devpath, &dev)) @@ -63,19 +63,12 @@ grub_children_iterate (char *devpath, grub_free (childtype); return 0; } - fullname = grub_malloc (IEEE1275_MAX_PATH_LEN); - if (!fullname) - { - grub_free (childname); - grub_free (childpath); - grub_free (childtype); - return 0; - } do { struct grub_ieee1275_devalias alias; grub_ssize_t actual; + char *fullname; if (grub_ieee1275_get_property (child, "device_type", childtype, IEEE1275_MAX_PROP_LEN, &actual)) @@ -89,18 +82,25 @@ grub_children_iterate (char *devpath, IEEE1275_MAX_PROP_LEN, &actual)) continue; - grub_sprintf (fullname, "%s/%s", devpath, childname); + fullname = grub_xasprintf ("%s/%s", devpath, childname); + if (!fullname) + { + grub_free (childname); + grub_free (childpath); + grub_free (childtype); + return 0; + } alias.type = childtype; alias.path = childpath; alias.name = fullname; ret = hook (&alias); + grub_free (fullname); if (ret) break; } while (grub_ieee1275_peer (child, &child)); - grub_free (fullname); grub_free (childname); grub_free (childpath); grub_free (childtype); @@ -135,7 +135,7 @@ grub_devalias_iterate (int (*hook) (struct grub_ieee1275_devalias *alias)) /* Find the first property. */ aliasname[0] = '\0'; - while (grub_ieee1275_next_property (aliases, aliasname, aliasname)) + while (grub_ieee1275_next_property (aliases, aliasname, aliasname) > 0) { grub_ieee1275_phandle_t dev; grub_ssize_t pathlen; @@ -199,9 +199,9 @@ nextprop: } /* Call the "map" method of /chosen/mmu. */ -static int -grub_map (grub_addr_t phys, grub_addr_t virt, grub_uint32_t size, - grub_uint8_t mode) +int +grub_ieee1275_map (grub_addr_t phys, grub_addr_t virt, grub_size_t size, + grub_uint32_t mode) { struct map_args { struct grub_ieee1275_common_hdr common; @@ -210,17 +210,30 @@ grub_map (grub_addr_t phys, grub_addr_t virt, grub_uint32_t size, grub_ieee1275_cell_t mode; grub_ieee1275_cell_t size; grub_ieee1275_cell_t virt; - grub_ieee1275_cell_t phys; +#ifdef GRUB_MACHINE_SPARC64 + grub_ieee1275_cell_t phys_high; +#endif + grub_ieee1275_cell_t phys_low; grub_ieee1275_cell_t catch_result; } args; - INIT_IEEE1275_COMMON (&args.common, "call-method", 6, 1); + INIT_IEEE1275_COMMON (&args.common, "call-method", +#ifdef GRUB_MACHINE_SPARC64 + 7, +#else + 6, +#endif + 1); args.method = (grub_ieee1275_cell_t) "map"; args.ihandle = grub_ieee1275_mmu; - args.phys = phys; +#ifdef GRUB_MACHINE_SPARC64 + args.phys_high = 0; +#endif + args.phys_low = phys; args.virt = virt; args.size = size; args.mode = mode; /* Format is WIMG0PP. */ + args.catch_result = (grub_ieee1275_cell_t) -1; if (IEEE1275_CALL_ENTRY_FN (&args) == -1) return -1; @@ -235,7 +248,7 @@ grub_claimmap (grub_addr_t addr, grub_size_t size) return -1; if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_REAL_MODE) - && grub_map (addr, addr, size, 0x00)) + && grub_ieee1275_map (addr, addr, size, 0x00)) { grub_printf ("map failed: address 0x%llx, size 0x%llx\n", (long long) addr, (long long) size); @@ -330,12 +343,11 @@ grub_ieee1275_parse_args (const char *path, enum grub_ieee1275_parse_type ptype) { char *filepath = comma + 1; - ret = grub_malloc (grub_strlen (filepath) + 1); /* Make sure filepath has leading backslash. */ if (filepath[0] != '\\') - grub_sprintf (ret, "\\%s", filepath); + ret = grub_xasprintf ("\\%s", filepath); else - grub_strcpy (ret, filepath); + ret = grub_strdup (filepath); } } else if (ptype == GRUB_PARSE_PARTITION) @@ -375,7 +387,7 @@ grub_ieee1275_encode_devname (const char *path) char *partition = grub_ieee1275_parse_args (path, GRUB_PARSE_PARTITION); char *encoding; - if (partition) + if (partition && partition[0]) { unsigned int partno = grub_strtoul (partition, 0, 0); @@ -383,15 +395,10 @@ grub_ieee1275_encode_devname (const char *path) /* GRUB partition 1 is OF partition 0. */ partno++; - /* Assume partno will require less than five bytes to encode. */ - encoding = grub_malloc (grub_strlen (device) + 3 + 5); - grub_sprintf (encoding, "(%s,%d)", device, partno); + encoding = grub_xasprintf ("(%s,%d)", device, partno); } else - { - encoding = grub_malloc (grub_strlen (device) + 2); - grub_sprintf (encoding, "(%s)", device); - } + encoding = grub_xasprintf ("(%s)", device); grub_free (partition); grub_free (device); @@ -411,8 +418,9 @@ grub_reboot (void) void grub_halt (void) { - /* Not standardized. We try both known commands. */ + /* Not standardized. We try three known commands. */ grub_ieee1275_interpret ("shut-down", 0); grub_ieee1275_interpret ("power-off", 0); + grub_ieee1275_interpret ("poweroff", 0); } diff --git a/kern/main.c b/kern/main.c index 7250c73e0..e7566fab9 100644 --- a/kern/main.c +++ b/kern/main.c @@ -68,6 +68,9 @@ grub_load_modules (void) (header->size - sizeof (struct grub_module_header)))) grub_fatal ("%s", grub_errmsg); + if (grub_errno) + grub_print_error (); + return 0; } @@ -114,7 +117,6 @@ grub_set_root_dev (void) const char *prefix; grub_register_variable_hook ("root", 0, grub_env_write_root); - grub_env_export ("root"); prefix = grub_env_get ("prefix"); @@ -159,12 +161,14 @@ grub_main (void) /* Load pre-loaded modules and free the space. */ grub_register_exported_symbols (); +#ifdef GRUB_LINKER_HAVE_INIT + grub_arch_dl_init_linker (); +#endif grub_load_modules (); /* It is better to set the root device as soon as possible, for convenience. */ grub_machine_set_prefix (); - grub_env_export ("prefix"); grub_set_root_dev (); grub_register_core_commands (); diff --git a/kern/mips/cache.S b/kern/mips/cache.S new file mode 100644 index 000000000..2c35b6da2 --- /dev/null +++ b/kern/mips/cache.S @@ -0,0 +1,7 @@ + +#include + +FUNCTION (grub_cpu_flush_cache) +FUNCTION (grub_arch_sync_caches) +#include "cache_flush.S" + j $ra diff --git a/kern/mips/cache_flush.S b/kern/mips/cache_flush.S new file mode 100644 index 000000000..5667ee7b4 --- /dev/null +++ b/kern/mips/cache_flush.S @@ -0,0 +1,23 @@ + move $t2, $a0 + addu $t3, $a0, $a1 + srl $t2, $t2, 5 + sll $t2, $t2, 5 + addu $t3, $t3, 0x1f + srl $t3, $t3, 5 + sll $t3, $t3, 5 + move $t0, $t2 + subu $t1, $t3, $t2 +1: + cache 1, 0($t0) + addiu $t0, $t0, 0x1 + addiu $t1, $t1, 0xffff + bne $t1, $zero, 1b + sync + move $t0, $t2 + subu $t1, $t3, $t2 +2: + cache 0, 0($t0) + addiu $t0, $t0, 0x1 + addiu $t1, $t1, 0xffff + bne $t1, $zero, 2b + sync diff --git a/kern/mips/dl.c b/kern/mips/dl.c new file mode 100644 index 000000000..485955e7f --- /dev/null +++ b/kern/mips/dl.c @@ -0,0 +1,237 @@ +/* dl-386.c - arch-dependent part of loadable module support */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2005,2007,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 + +/* Dummy __gnu_local_gp. Resolved by linker. */ +static char __gnu_local_gp_dummy; + +/* Check if EHDR is a valid ELF header. */ +grub_err_t +grub_arch_dl_check_header (void *ehdr) +{ + Elf_Ehdr *e = ehdr; + + /* Check the magic numbers. */ +#ifdef WORDS_BIGENDIAN + if (e->e_ident[EI_CLASS] != ELFCLASS32 + || e->e_ident[EI_DATA] != ELFDATA2MSB + || e->e_machine != EM_MIPS) +#else + if (e->e_ident[EI_CLASS] != ELFCLASS32 + || e->e_ident[EI_DATA] != ELFDATA2LSB + || e->e_machine != EM_MIPS) +#endif + return grub_error (GRUB_ERR_BAD_OS, "invalid arch specific ELF magic"); + + return GRUB_ERR_NONE; +} + +/* Relocate symbols. */ +grub_err_t +grub_arch_dl_relocate_symbols (grub_dl_t mod, void *ehdr) +{ + Elf_Ehdr *e = ehdr; + Elf_Shdr *s; + Elf_Word entsize; + unsigned i; + grub_size_t gp_size = 0; + /* FIXME: suboptimal. */ + grub_uint32_t *gp, *gpptr; + grub_uint32_t gp0; + + /* Find a symbol table. */ + for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) + if (s->sh_type == SHT_SYMTAB) + break; + + if (i == e->e_shnum) + return grub_error (GRUB_ERR_BAD_MODULE, "no symtab found"); + + entsize = s->sh_entsize; + + /* Find reginfo. */ + for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) + if (s->sh_type == SHT_MIPS_REGINFO) + break; + + if (i == e->e_shnum) + return grub_error (GRUB_ERR_BAD_MODULE, "no reginfo found"); + + gp0 = ((grub_uint32_t *)((char *) e + s->sh_offset))[5]; + + for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) + if (s->sh_type == SHT_REL) + { + grub_dl_segment_t seg; + + /* Find the target segment. */ + for (seg = mod->segment; seg; seg = seg->next) + if (seg->section == s->sh_info) + break; + + if (seg) + { + Elf_Rel *rel, *max; + + for (rel = (Elf_Rel *) ((char *) e + s->sh_offset), + max = rel + s->sh_size / s->sh_entsize; + rel < max; + rel++) + switch (ELF_R_TYPE (rel->r_info)) + { + case R_MIPS_GOT16: + case R_MIPS_CALL16: + case R_MIPS_GPREL32: + gp_size += 4; + break; + } + } + } + + if (gp_size > 0x08000) + return grub_error (GRUB_ERR_OUT_OF_RANGE, "__gnu_local_gp is too big\n"); + + gpptr = gp = grub_malloc (gp_size); + if (!gp) + return grub_errno; + + for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff); + i < e->e_shnum; + i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize)) + if (s->sh_type == SHT_REL) + { + grub_dl_segment_t seg; + + /* Find the target segment. */ + for (seg = mod->segment; seg; seg = seg->next) + if (seg->section == s->sh_info) + break; + + if (seg) + { + Elf_Rel *rel, *max; + + for (rel = (Elf_Rel *) ((char *) e + s->sh_offset), + max = rel + s->sh_size / s->sh_entsize; + rel < max; + rel++) + { + Elf_Word *addr; + Elf_Sym *sym; + + if (seg->size < rel->r_offset) + return grub_error (GRUB_ERR_BAD_MODULE, + "reloc offset is out of the segment"); + + addr = (Elf_Word *) ((char *) seg->addr + rel->r_offset); + sym = (Elf_Sym *) ((char *) mod->symtab + + entsize * ELF_R_SYM (rel->r_info)); + if (sym->st_value == (grub_addr_t) &__gnu_local_gp_dummy) + sym->st_value = (grub_addr_t) gp; + + switch (ELF_R_TYPE (rel->r_info)) + { + case R_MIPS_HI16: + { + grub_uint32_t value; + Elf_Rel *rel2; + + /* Handle partner lo16 relocation. Lower part is + treated as signed. Hence add 0x8000 to compensate. + */ + value = (*(grub_uint16_t *) addr << 16) + + sym->st_value + 0x8000; + for (rel2 = rel + 1; rel2 < max; rel2++) + if (ELF_R_SYM (rel2->r_info) + == ELF_R_SYM (rel->r_info) + && ELF_R_TYPE (rel2->r_info) == R_MIPS_LO16) + { + value += *(grub_int16_t *) + ((char *) seg->addr + rel2->r_offset); + break; + } + *(grub_uint16_t *) addr = (value >> 16) & 0xffff; + } + break; + case R_MIPS_LO16: + *(grub_uint16_t *) addr += (sym->st_value) & 0xffff; + break; + case R_MIPS_32: + *(grub_uint32_t *) addr += sym->st_value; + break; + case R_MIPS_GPREL32: + *(grub_uint32_t *) addr = sym->st_value + + *(grub_uint32_t *) addr + gp0 - (grub_uint32_t)gp; + break; + + case R_MIPS_26: + { + grub_uint32_t value; + grub_uint32_t raw; + raw = (*(grub_uint32_t *) addr) & 0x3ffffff; + value = raw << 2; + value += sym->st_value; + raw = (value >> 2) & 0x3ffffff; + + *(grub_uint32_t *) addr = + raw | ((*(grub_uint32_t *) addr) & 0xfc000000); + } + break; + case R_MIPS_GOT16: + case R_MIPS_CALL16: + /* FIXME: reuse*/ + *gpptr = sym->st_value + *(grub_uint16_t *) addr; + *(grub_uint16_t *) addr + = sizeof (grub_uint32_t) * (gpptr - gp); + gpptr++; + break; + default: + { + grub_free (gp); + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "Unknown relocation type %d\n", + ELF_R_TYPE (rel->r_info)); + } + break; + } + } + } + } + + return GRUB_ERR_NONE; +} + +void +grub_arch_dl_init_linker (void) +{ + grub_dl_register_symbol ("__gnu_local_gp", &__gnu_local_gp_dummy, 0); +} + diff --git a/kern/mips/init.c b/kern/mips/init.c new file mode 100644 index 000000000..5adcedcbb --- /dev/null +++ b/kern/mips/init.c @@ -0,0 +1,35 @@ +/* + * 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 + +void +grub_machine_set_prefix (void) +{ + grub_env_set ("prefix", grub_prefix); +} + +extern char _end[]; + +grub_addr_t +grub_arch_modules_addr (void) +{ + return (grub_addr_t) _end; +} diff --git a/kern/mips/qemu-mips/init.c b/kern/mips/qemu-mips/init.c new file mode 100644 index 000000000..866c7a82a --- /dev/null +++ b/kern/mips/qemu-mips/init.c @@ -0,0 +1,61 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RAMSIZE (*(grub_uint32_t *) ((16 << 20) - 264)) + +grub_uint32_t +grub_get_rtc (void) +{ + static int calln = 0; + return calln++; +} + +void +grub_machine_init (void) +{ + grub_mm_init_region ((void *) GRUB_MACHINE_MEMORY_USABLE, + RAMSIZE - (GRUB_MACHINE_MEMORY_USABLE & 0x7fffffff)); + grub_install_get_time_ms (grub_rtc_get_time_ms); +} + +void +grub_machine_fini (void) +{ +} + +void +grub_exit (void) +{ + while (1); +} + +void +grub_halt (void) +{ + while (1); +} + +void +grub_reboot (void) +{ + while (1); +} + +grub_err_t +grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, + grub_uint64_t, + grub_uint32_t)) +{ + hook (0, RAMSIZE, + GRUB_MACHINE_MEMORY_AVAILABLE); + return GRUB_ERR_NONE; +} diff --git a/kern/mips/startup.S b/kern/mips/startup.S new file mode 100644 index 000000000..5e3fb7ad5 --- /dev/null +++ b/kern/mips/startup.S @@ -0,0 +1,218 @@ +/* startup.S - Startup code for the MIPS. */ +/* + * 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 + +#define BASE_ADDR 8 + +.extern __bss_start +.extern _end + + .globl __start, _start, start +__start: +_start: +start: + bal codestart +base: + . = _start + GRUB_KERNEL_CPU_COMPRESSED_SIZE +compressed_size: + .long 0 + . = _start + GRUB_KERNEL_CPU_TOTAL_MODULE_SIZE +total_module_size: + .long 0 + . = _start + GRUB_KERNEL_CPU_KERNEL_IMAGE_SIZE +kernel_image_size: + .long 0 +codestart: + /* Save our base. */ + move $s0, $ra + + /* Parse arguments. Has to be done before relocation. + So need to do it in asm. */ +#ifdef GRUB_MACHINE_MIPS_YEELOONG + /* $a2 has the environment. */ + move $t0, $a2 +argcont: + lw $t1, 0($t0) + beq $t1, $zero, argdone +#define DO_PARSE(str, reg) \ + addiu $t2, $s0, (str-base);\ + bal parsestr;\ + beq $v0, $zero, 1f;\ + move reg, $v0;\ + b 2f;\ +1: + DO_PARSE (busclockstr, $s2) + DO_PARSE (cpuclockstr, $s3) + DO_PARSE (memsizestr, $s4) + DO_PARSE (highmemsizestr, $s5) +2: + addiu $t0, $t0, 4 + b argcont +parsestr: + move $v0, $zero + move $t3, $t1 +3: + lb $t4, 0($t2) + lb $t5, 0($t3) + addiu $t2, $t2, 1 + addiu $t3, $t3, 1 + beq $t5, $zero, 1f + beq $t5, $t4, 3b + bne $t4, $zero, 1f + + addiu $t3, $t3, 0xffff +digcont: + lb $t5, 0($t3) + /* Substract '0' from digit. */ + addiu $t5, $t5, 0xffd0 + bltz $t5, 1f + addiu $t4, $t5, 0xfff7 + bgtz $t4, 1f + /* Multiply $v0 by 10 with bitshifts. */ + sll $v0, $v0, 1 + sll $t4, $v0, 2 + addu $v0, $v0, $t4 + addu $v0, $v0, $t5 + addiu $t3, $t3, 1 + b digcont +1: + jr $ra +busclockstr: .asciiz "busclock=" +cpuclockstr: .asciiz "cpuclock=" +memsizestr: .asciiz "memsize=" +highmemsizestr: .asciiz "highmemsize=" + .p2align 2 +argdone: +#endif + + /* Decompress the payload. */ + addiu $a0, $s0, GRUB_KERNEL_CPU_RAW_SIZE - BASE_ADDR + lui $a1, %hi(compressed) + addiu $a1, %lo(compressed) + lw $a2, (GRUB_KERNEL_CPU_COMPRESSED_SIZE - BASE_ADDR)($s0) + move $s1, $a1 + + /* $a0 contains source compressed address, $a1 is destination, + $a2 is compressed size. FIXME: put LZMA here. Don't clober $s0, + $s1, $s2, $s3, $s4 and $s5. + On return $v0 contains uncompressed size. + */ + move $v0, $a2 +reloccont: + lb $t4, 0($a0) + sb $t4, 0($a1) + addiu $a1,$a1,1 + addiu $a0,$a0,1 + addiu $a2, 0xffff + bne $a2, $0, reloccont + + move $a0, $s1 + move $a1, $v0 + +#include "cache_flush.S" + + lui $t1, %hi(cont) + addiu $t1, %lo(cont) + + jr $t1 + . = _start + GRUB_KERNEL_CPU_RAW_SIZE +compressed: + . = _start + GRUB_KERNEL_CPU_PREFIX + +VARIABLE(grub_prefix) + + /* to be filled by grub-mkelfimage */ + + /* + * Leave some breathing room for the prefix. + */ + + . = _start + GRUB_KERNEL_CPU_DATA_END +#ifdef GRUB_MACHINE_MIPS_YEELOONG +VARIABLE (grub_arch_busclock) + .long 0 +VARIABLE (grub_arch_cpuclock) + .long 0 +VARIABLE (grub_arch_memsize) + .long 0 +VARIABLE (grub_arch_highmemsize) + .long 0 +#endif +cont: + +#ifdef GRUB_MACHINE_MIPS_YEELOONG + lui $t1, %hi(grub_arch_busclock) + addiu $t1, %lo(grub_arch_busclock) + sw $s2, 0($t1) + sw $s3, 4($t1) + sw $s4, 8($t1) + sw $s5, 12($t1) +#endif + + /* Move the modules out of BSS. */ + lui $t1, %hi(_start) + addiu $t1, %lo(_start) + lw $t2, (GRUB_KERNEL_CPU_KERNEL_IMAGE_SIZE - BASE_ADDR)($s0) + addu $t2, $t1, $t2 + + lui $t1, %hi(_end) + addiu $t1, %lo(_end) + addiu $t1, (GRUB_MOD_ALIGN-1) + li $t3, (GRUB_MOD_ALIGN-1) + nor $t3, $t3, $0 + and $t1, $t1, $t3 + + lw $t3, (GRUB_KERNEL_CPU_TOTAL_MODULE_SIZE - BASE_ADDR)($s0) + + /* Backward copy. */ + add $t1, $t1, $t3 + add $t2, $t2, $t3 + addiu $t1, $t1, 0xffff + addiu $t2, $t2, 0xffff + + /* $t2 is source. $t1 is destination. $t3 is size. */ +modulesmovcont: + lb $t4, 0($t2) + sb $t4, 0($t1) + addiu $t1,$t1,0xffff + addiu $t2,$t2,0xffff + addiu $t3, 0xffff + bne $t3, $0, modulesmovcont + + /* Clean BSS. */ + + lui $t1, %hi(__bss_start) + addiu $t1, %lo(__bss_start) + lui $t2, %hi(_end) + addiu $t2, %lo(_end) +bsscont: + sb $0,0($t1) + addiu $t1,$t1,1 + sltu $t3,$t1,$t2 + bne $t3, $0, bsscont + + li $sp, GRUB_MACHINE_MEMORY_STACK_HIGH + lui $t1, %hi(grub_main) + addiu $t1, %lo(grub_main) + + jr $t1 + diff --git a/kern/mips/yeeloong/init.c b/kern/mips/yeeloong/init.c new file mode 100644 index 000000000..14e8a39a2 --- /dev/null +++ b/kern/mips/yeeloong/init.c @@ -0,0 +1,131 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009,2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern void grub_video_sm712_init (void); +extern void grub_video_video_init (void); +extern void grub_video_bitmap_init (void); +extern void grub_font_manager_init (void); +extern void grub_term_gfxterm_init (void); +extern void grub_at_keyboard_init (void); + +/* FIXME: use interrupt to count high. */ +grub_uint64_t +grub_get_rtc (void) +{ + static grub_uint32_t high = 0; + static grub_uint32_t last = 0; + grub_uint32_t low; + + asm volatile ("mfc0 %0, $9": "=r" (low)); + if (low < last) + high++; + last = low; + + return (((grub_uint64_t) high) << 32) | low; +} + +grub_err_t +grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, + grub_uint64_t, + grub_uint32_t)) +{ + hook (GRUB_ARCH_LOWMEMPSTART, grub_arch_memsize << 20, + GRUB_MACHINE_MEMORY_AVAILABLE); + hook (GRUB_ARCH_HIGHMEMPSTART, grub_arch_highmemsize << 20, + GRUB_MACHINE_MEMORY_AVAILABLE); + return GRUB_ERR_NONE; +} + + +static void * +get_modules_end (void) +{ + struct grub_module_info *modinfo; + struct grub_module_header *header; + grub_addr_t modbase; + + modbase = grub_arch_modules_addr (); + modinfo = (struct grub_module_info *) modbase; + + /* Check if there are any modules. */ + if ((modinfo == 0) || modinfo->magic != GRUB_MODULE_MAGIC) + return modinfo; + + for (header = (struct grub_module_header *) (modbase + modinfo->offset); + header < (struct grub_module_header *) (modbase + modinfo->size); + header = (struct grub_module_header *) ((char *) header + header->size)); + + return header; +} + +void +grub_machine_init (void) +{ + void *modend; + modend = get_modules_end (); + grub_mm_init_region (modend, (grub_arch_memsize << 20) + - (((grub_addr_t) modend) - GRUB_ARCH_LOWMEMVSTART)); + /* FIXME: use upper memory as well. */ + grub_install_get_time_ms (grub_rtc_get_time_ms); + + /* Initialize output terminal (can't be done earlier, as gfxterm + relies on a working heap. */ + grub_video_sm712_init (); + grub_video_video_init (); + grub_video_bitmap_init (); + grub_font_manager_init (); + grub_term_gfxterm_init (); + + grub_at_keyboard_init (); +} + +void +grub_machine_fini (void) +{ +} + +void +grub_exit (void) +{ + while (1); +} + +void +grub_halt (void) +{ + while (1); +} + +void +grub_reboot (void) +{ + while (1); +} + diff --git a/kern/misc.c b/kern/misc.c index 3a2cf9ed9..4772e22b0 100644 --- a/kern/misc.c +++ b/kern/misc.c @@ -25,6 +25,9 @@ #include #include +static int +grub_vsnprintf_real (char *str, grub_size_t n, const char *fmt, va_list args); + static int grub_iswordseparator (int c) { @@ -32,7 +35,7 @@ grub_iswordseparator (int c) } /* grub_gettext_dummy is not translating anything. */ -const char * +static const char * grub_gettext_dummy (const char *s) { return s; @@ -202,8 +205,7 @@ grub_vprintf (const char *fmt, va_list args) { int ret; - ret = grub_vsprintf (0, fmt, args); - grub_refresh (); + ret = grub_vsnprintf_real (0, 0, fmt, args); return ret; } @@ -636,11 +638,11 @@ grub_lltoa (char *str, int c, unsigned long long n) return p; } -int -grub_vsprintf (char *str, const char *fmt, va_list args) +static int +grub_vsnprintf_real (char *str, grub_size_t max_len, const char *fmt, va_list args) { char c; - int count = 0; + grub_size_t count = 0; auto void write_char (unsigned char ch); auto void write_str (const char *s); auto void write_fill (const char ch, int n); @@ -648,7 +650,10 @@ grub_vsprintf (char *str, const char *fmt, va_list args) void write_char (unsigned char ch) { if (str) - *str++ = ch; + { + if (count < max_len) + *str++ = ch; + } else grub_putchar (ch); @@ -870,20 +875,68 @@ grub_vsprintf (char *str, const char *fmt, va_list args) if (str) *str = '\0'; - if (count && !str) - grub_refresh (); - return count; } int -grub_sprintf (char *str, const char *fmt, ...) +grub_vsnprintf (char *str, grub_size_t n, const char *fmt, va_list ap) +{ + grub_size_t ret; + + if (!n) + return 0; + + n--; + + ret = grub_vsnprintf_real (str, n, fmt, ap); + + return ret < n ? ret : n; +} + +int +grub_snprintf (char *str, grub_size_t n, const char *fmt, ...) { va_list ap; int ret; va_start (ap, fmt); - ret = grub_vsprintf (str, fmt, ap); + ret = grub_vsnprintf (str, n, fmt, ap); + va_end (ap); + + return ret; +} + +#define PREALLOC_SIZE 255 + +char * +grub_xvasprintf (const char *fmt, va_list ap) +{ + grub_size_t s, as = PREALLOC_SIZE; + char *ret; + + while (1) + { + ret = grub_malloc (as + 1); + if (!ret) + return NULL; + + s = grub_vsnprintf_real (ret, as, fmt, ap); + if (s <= as) + return ret; + + grub_free (ret); + as = s; + } +} + +char * +grub_xasprintf (const char *fmt, ...) +{ + va_list ap; + char *ret; + + va_start (ap, fmt); + ret = grub_xvasprintf (fmt, ap); va_end (ap); return ret; @@ -918,6 +971,10 @@ grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize, { /* invalid */ code = '?'; + /* Character c may be valid, don't eat it. */ + src--; + if (srcsize != (grub_size_t)-1) + srcsize++; count = 0; } else diff --git a/kern/rescue_reader.c b/kern/rescue_reader.c index 732124b1a..f573cf41f 100644 --- a/kern/rescue_reader.c +++ b/kern/rescue_reader.c @@ -1,7 +1,7 @@ /* rescue_reader.c - rescue mode reader */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2009 Free Software Foundation, Inc. + * Copyright (C) 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 @@ -83,7 +83,7 @@ grub_rescue_run (void) grub_errno = GRUB_ERR_NONE; grub_rescue_read_line (&line, 0); - if (! line) + if (! line || line[0] == '\0') continue; grub_parser_get_current ()->parse_line (line, grub_rescue_read_line); diff --git a/kern/sparc64/ieee1275/crt0.S b/kern/sparc64/ieee1275/crt0.S index 4e67cbc19..3749f3005 100644 --- a/kern/sparc64/ieee1275/crt0.S +++ b/kern/sparc64/ieee1275/crt0.S @@ -53,12 +53,16 @@ codestart: or %o3, %lo(_end), %o3 sethi %hi(grub_total_module_size), %o4 lduw [%o4 + %lo(grub_total_module_size)], %o4 + add %o2, %o4, %o2 + add %o3, %o4, %o3 + sub %o2, 4, %o2 + sub %o3, 4, %o3 1: lduw [%o2], %o5 stw %o5, [%o3] subcc %o4, 4, %o4 - add %o2, 4, %o2 + sub %o2, 4, %o2 bne,pt %icc, 1b - add %o3, 4, %o3 + sub %o3, 4, %o3 /* Now it's safe to clear out the BSS. */ sethi %hi(__bss_start), %o2 diff --git a/kern/sparc64/ieee1275/ieee1275.c b/kern/sparc64/ieee1275/ieee1275.c index 438a171ca..53be692c3 100644 --- a/kern/sparc64/ieee1275/ieee1275.c +++ b/kern/sparc64/ieee1275/ieee1275.c @@ -21,39 +21,6 @@ /* Sun specific ieee1275 interfaces used by GRUB. */ -int -grub_ieee1275_map_physical (grub_addr_t paddr, grub_addr_t vaddr, - grub_size_t size, grub_uint32_t mode) -{ - struct map_physical_args - { - struct grub_ieee1275_common_hdr common; - grub_ieee1275_cell_t method; - grub_ieee1275_cell_t ihandle; - grub_ieee1275_cell_t mode; - grub_ieee1275_cell_t size; - grub_ieee1275_cell_t virt; - grub_ieee1275_cell_t phys_high; - grub_ieee1275_cell_t phys_low; - grub_ieee1275_cell_t catch_result; - } - args; - - INIT_IEEE1275_COMMON (&args.common, "call-method", 7, 1); - args.method = (grub_ieee1275_cell_t) "map"; - args.ihandle = grub_ieee1275_mmu; - args.mode = mode; - args.size = size; - args.virt = vaddr; - args.phys_high = 0; - args.phys_low = paddr; - args.catch_result = (grub_ieee1275_cell_t) -1; - - if (IEEE1275_CALL_ENTRY_FN (&args) == -1) - return -1; - return args.catch_result; -} - int grub_ieee1275_claim_vaddr (grub_addr_t vaddr, grub_size_t size) { diff --git a/kern/sparc64/ieee1275/init.c b/kern/sparc64/ieee1275/init.c index 699f9631b..115328f40 100644 --- a/kern/sparc64/ieee1275/init.c +++ b/kern/sparc64/ieee1275/init.c @@ -90,10 +90,7 @@ grub_machine_set_prefix (void) } prefix = grub_ieee1275_encode_devname (bootpath); - path = grub_malloc (grub_strlen (grub_prefix) - + grub_strlen (prefix) - + 2); - grub_sprintf(path, "%s%s", prefix, grub_prefix); + path = grub_xasprintf("%s%s", prefix, grub_prefix); grub_strcpy (grub_prefix, path); diff --git a/kern/term.c b/kern/term.c index 50fbbf302..6e3a2b454 100644 --- a/kern/term.c +++ b/kern/term.c @@ -57,16 +57,17 @@ grub_putchar (int c) { static grub_size_t size = 0; static grub_uint8_t buf[6]; + grub_uint8_t *rest; grub_uint32_t code; - grub_size_t ret; buf[size++] = c; - ret = grub_utf8_to_ucs4 (&code, 1, buf, size, 0); - if (ret != 0) + while (grub_utf8_to_ucs4 (&code, 1, buf, size, (const grub_uint8_t **) &rest) + != 0) { struct grub_term_output *term; - size = 0; + size -= rest - buf; + grub_memmove (buf, rest, size); FOR_ACTIVE_TERM_OUTPUTS(term) grub_putcode (code, term); if (code == '\n' && grub_newline_hook) @@ -79,6 +80,8 @@ grub_getkey (void) { grub_term_input_t term; + grub_refresh (); + while (1) { FOR_ACTIVE_TERM_INPUTS(term) diff --git a/lib/i386/datetime.c b/lib/cmos_datetime.c similarity index 95% rename from lib/i386/datetime.c rename to lib/cmos_datetime.c index 63858ed03..8db60b48c 100644 --- a/lib/i386/datetime.c +++ b/lib/cmos_datetime.c @@ -1,7 +1,7 @@ -/* kern/i386/datetime.c - x86 CMOS datetime function. +/* kern/cmos_datetime.c - CMOS datetime function. * * GRUB -- GRand Unified Bootloader - * Copyright (C) 2008 Free Software Foundation, Inc. + * Copyright (C) 2008,2009 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,7 +18,7 @@ */ #include -#include +#include grub_err_t grub_get_datetime (struct grub_datetime *datetime) diff --git a/lib/hexdump.c b/lib/hexdump.c index 800beb2ba..317635a2b 100644 --- a/lib/hexdump.c +++ b/lib/hexdump.c @@ -31,21 +31,22 @@ hexdump (unsigned long bse, char *buf, int len) { int cnt, i; - pos = grub_sprintf (line, "%08lx ", bse); + pos = grub_snprintf (line, sizeof (line), "%08lx ", bse); cnt = 16; if (cnt > len) cnt = len; for (i = 0; i < cnt; i++) { - pos += grub_sprintf (&line[pos], "%02x ", (unsigned char) buf[i]); + pos += grub_snprintf (&line[pos], sizeof (line) - pos, + "%02x ", (unsigned char) buf[i]); if ((i & 7) == 7) line[pos++] = ' '; } for (; i < 16; i++) { - pos += grub_sprintf (&line[pos], " "); + pos += grub_snprintf (&line[pos], sizeof (line) - pos, " "); if ((i & 7) == 7) line[pos++] = ' '; } diff --git a/lib/mips/relocator.c b/lib/mips/relocator.c index 796473bf7..118ddbd6f 100644 --- a/lib/mips/relocator.c +++ b/lib/mips/relocator.c @@ -36,7 +36,7 @@ extern grub_uint8_t grub_relocator32_backward_start; extern grub_uint8_t grub_relocator32_backward_end; #define REGW_SIZEOF (2 * sizeof (grub_uint32_t)) -#define JUMP_SIZEOF (sizeof (grub_uint32_t)) +#define JUMP_SIZEOF (2 * sizeof (grub_uint32_t)) #define RELOCATOR_SRC_SIZEOF(x) (&grub_relocator32_##x##_end \ - &grub_relocator32_##x##_start) @@ -64,6 +64,9 @@ write_jump (int regn, void **target) /* j $r. */ *(grub_uint32_t *) *target = (regn<<21) | 0x8; *target = ((grub_uint32_t *) *target) + 1; + /* nop. */ + *(grub_uint32_t *) *target = 0; + *target = ((grub_uint32_t *) *target) + 1; } static void diff --git a/lib/mips/relocator_asm.S b/lib/mips/relocator_asm.S index 9daf0d32f..ff4fa31e0 100644 --- a/lib/mips/relocator_asm.S +++ b/lib/mips/relocator_asm.S @@ -21,8 +21,8 @@ .p2align 4 /* force 16-byte alignment */ VARIABLE (grub_relocator32_forward_start) - move $12, $9 - move $13, $10 + move $a0, $9 + move $a1, $10 copycont1: lb $11,0($8) @@ -32,31 +32,13 @@ copycont1: addiu $10, $10, 0xffff bne $10, $0, copycont1 - move $9, $12 - move $10, $13 -cachecont1a: - cache 1,0($12) - addiu $12, $12, 0x1 - addiu $13, $13, 0xffff - bne $13, $0, cachecont1a - - sync - - move $12, $9 - move $13, $10 -cachecont1b: - cache 0,0($12) - addiu $12, $12, 0x1 - addiu $13, $13, 0xffff - bne $13, $0, cachecont1b - - sync +#include "../../kern/mips/cache_flush.S" VARIABLE (grub_relocator32_forward_end) VARIABLE (grub_relocator32_backward_start) - move $12, $9 - move $13, $10 + move $a0, $9 + move $a1, $10 addu $9, $9, $10 addu $8, $8, $10 @@ -71,23 +53,6 @@ copycont2: addiu $10, 0xffff bne $10, $0, copycont2 - move $9, $12 - move $10, $13 -cachecont2a: - cache 1,0($12) - addiu $12, $12, 0x1 - addiu $13, $13, 0xffff - bne $13, $0, cachecont2a +#include "../../kern/mips/cache_flush.S" - sync - - move $12, $9 - move $13, $10 -cachecont2b: - cache 0,0($12) - addiu $12, $12, 0x1 - addiu $13, $13, 0xffff - bne $13, $0, cachecont2b - - sync VARIABLE (grub_relocator32_backward_end) diff --git a/lib/mips/setjmp.S b/lib/mips/setjmp.S new file mode 100644 index 000000000..8ab6222c4 --- /dev/null +++ b/lib/mips/setjmp.S @@ -0,0 +1,65 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2007,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 + + .file "setjmp.S" + + .text + +/* + * int grub_setjmp (grub_jmp_buf env) + */ +FUNCTION(grub_setjmp) + sw $s0, 0($a0) + sw $s1, 4($a0) + sw $s2, 8($a0) + sw $s3, 12($a0) + sw $s4, 16($a0) + sw $s5, 20($a0) + sw $s6, 24($a0) + sw $s7, 28($a0) + sw $s8, 32($a0) + sw $gp, 36($a0) + sw $sp, 40($a0) + sw $ra, 44($a0) + move $v0, $zero + move $v1, $zero + jr $ra +/* + * int grub_longjmp (grub_jmp_buf env, int val) + */ +FUNCTION(grub_longjmp) + lw $s0, 0($a0) + lw $s1, 4($a0) + lw $s2, 8($a0) + lw $s3, 12($a0) + lw $s4, 16($a0) + lw $s5, 20($a0) + lw $s6, 24($a0) + lw $s7, 28($a0) + lw $s8, 32($a0) + lw $gp, 36($a0) + lw $sp, 40($a0) + lw $ra, 44($a0) + move $v0, $a1 + bne $v0, $zero, 1f + addiu $v0, $v0, 1 +1: + move $v1, $zero + jr $ra diff --git a/loader/i386/bsd.c b/loader/i386/bsd.c index 49be758c6..949de408d 100644 --- a/loader/i386/bsd.c +++ b/loader/i386/bsd.c @@ -154,8 +154,8 @@ grub_bsd_get_device (grub_uint32_t * biosdev, dev = grub_device_open (0); if (dev && dev->disk && dev->disk->partition) { - - p = dev->disk->partition->partmap->get_name (dev->disk->partition); + char *p0; + p0 = p = dev->disk->partition->partmap->get_name (dev->disk->partition); if (p) { if ((p[0] >= '0') && (p[0] <= '9')) @@ -169,6 +169,7 @@ grub_bsd_get_device (grub_uint32_t * biosdev, if ((p[0] >= 'a') && (p[0] <= 'z')) *part = p[0] - 'a'; } + grub_free (p0); } if (dev) grub_device_close (dev); @@ -461,14 +462,14 @@ grub_freebsd_boot (void) } grub_memset (&bi, 0, sizeof (bi)); - bi.bi_version = FREEBSD_BOOTINFO_VERSION; - bi.bi_size = sizeof (bi); + bi.version = FREEBSD_BOOTINFO_VERSION; + bi.length = sizeof (bi); grub_bsd_get_device (&biosdev, &unit, &slice, &part); bootdev = (FREEBSD_B_DEVMAGIC + ((slice + 1) << FREEBSD_B_SLICESHIFT) + (unit << FREEBSD_B_UNITSHIFT) + (part << FREEBSD_B_PARTSHIFT)); - bi.bi_bios_dev = biosdev; + bi.boot_device = biosdev; p = (char *) kern_end; @@ -478,7 +479,7 @@ grub_freebsd_boot (void) { *(p++) = 0; - bi.bi_envp = kern_end; + bi.environment = kern_end; kern_end = ALIGN_PAGE ((grub_uint32_t) p); } @@ -491,25 +492,25 @@ grub_freebsd_boot (void) return grub_errno; grub_memcpy ((char *) kern_end, mod_buf, mod_buf_len); - bi.bi_modulep = kern_end; + bi.tags = kern_end; kern_end = ALIGN_PAGE (kern_end + mod_buf_len); if (is_64bit) kern_end += 4096 * 4; - md_ofs = bi.bi_modulep + kern_end_mdofs; + md_ofs = bi.tags + kern_end_mdofs; ofs = (is_64bit) ? 16 : 12; *((grub_uint32_t *) md_ofs) = kern_end; md_ofs -= ofs; - *((grub_uint32_t *) md_ofs) = bi.bi_envp; + *((grub_uint32_t *) md_ofs) = bi.environment; md_ofs -= ofs; *((grub_uint32_t *) md_ofs) = bootflags; } - bi.bi_kernend = kern_end; + bi.kern_end = kern_end; - grub_video_set_mode ("text", NULL); + grub_video_set_mode ("text", 0, 0); if (is_64bit) { @@ -554,12 +555,12 @@ grub_freebsd_boot (void) &grub_bsd64_trampoline_end - &grub_bsd64_trampoline_start); /* Launch trampoline. */ - launch_trampoline (entry, entry_hi, pagetable, bi.bi_modulep, + launch_trampoline (entry, entry_hi, pagetable, bi.tags, kern_end); } else grub_unix_real_boot (entry, bootflags | FREEBSD_RB_BOOTINFO, bootdev, - 0, 0, 0, &bi, bi.bi_modulep, kern_end); + 0, 0, 0, &bi, bi.tags, kern_end); /* Not reached. */ return GRUB_ERR_NONE; @@ -619,7 +620,7 @@ grub_openbsd_boot (void) pa->ba_type = OPENBSD_BOOTARG_END; pa++; - grub_video_set_mode ("text", NULL); + grub_video_set_mode ("text", 0, 0); grub_unix_real_boot (entry, bootflags, openbsd_root, OPENBSD_BOOTARG_APIVER, 0, (grub_uint32_t) (grub_mmap_get_upper () >> 10), @@ -717,7 +718,7 @@ grub_netbsd_boot (void) bootinfo->bi_data[0] = mmap; } - grub_video_set_mode ("text", NULL); + grub_video_set_mode ("text", 0, 0); grub_unix_real_boot (entry, bootflags, 0, bootinfo, 0, (grub_uint32_t) (grub_mmap_get_upper () >> 10), @@ -1145,14 +1146,20 @@ grub_cmd_freebsd_loadenv (grub_command_t cmd __attribute__ ((unused)), if (*curr) { - char name[grub_strlen (curr) + sizeof("kFreeBSD.")]; + char *name; if (*p == '"') p++; - grub_sprintf (name, "kFreeBSD.%s", curr); - if (grub_env_set (name, p)) + name = grub_xasprintf ("kFreeBSD.%s", curr); + if (!name) goto fail; + if (grub_env_set (name, p)) + { + grub_free (name); + goto fail; + } + grub_free (name); } } diff --git a/loader/i386/efi/linux.c b/loader/i386/efi/linux.c index 1abcc06db..a6db22e22 100644 --- a/loader/i386/efi/linux.c +++ b/loader/i386/efi/linux.c @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2006,2007,2008,2009 Free Software Foundation, Inc. + * Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -478,7 +478,7 @@ find_framebuf (grub_uint32_t *fb_base, grub_uint32_t *line_len) { grub_pci_address_t addr; - addr = grub_pci_make_address (dev, 2); + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); if (grub_pci_read (addr) >> 24 == 0x3) { int i; @@ -576,7 +576,7 @@ grub_linux_setup_video (struct linux_kernel_params *params) params->lfb_line_len = line_len; params->lfb_base = fb_base; - params->lfb_size = (line_len * params->lfb_height + 65535) >> 16; + params->lfb_size = ALIGN_UP (line_len * params->lfb_height, 65536); params->red_mask_size = 8; params->red_field_pos = 16; @@ -587,7 +587,7 @@ grub_linux_setup_video (struct linux_kernel_params *params) params->reserved_mask_size = 8; params->reserved_field_pos = 24; - params->have_vga = GRUB_VIDEO_TYPE_VLFB; + params->have_vga = GRUB_VIDEO_LINUX_TYPE_VESA; params->vid_mode = 0x338; /* 1024x768x32 */ return 0; @@ -676,8 +676,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), goto fail; } - /* XXX Linux assumes that only elilo can boot Linux on EFI!!! */ - params->type_of_loader = (LINUX_LOADER_ID_ELILO << 4); + params->type_of_loader = (LINUX_LOADER_ID_GRUB << 4); params->cl_magic = GRUB_LINUX_CL_MAGIC; params->cl_offset = 0x1000; @@ -852,7 +851,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), else if (grub_memcmp (argv[i], "video=efifb", 11) == 0) { if (params->have_vga) - params->have_vga = GRUB_VIDEO_TYPE_EFI; + params->have_vga = GRUB_VIDEO_LINUX_TYPE_SIMPLE; } /* Specify the boot file. */ diff --git a/loader/i386/efi/xnu.c b/loader/i386/efi/xnu.c index a7ede1960..e80f7f3dd 100644 --- a/loader/i386/efi/xnu.c +++ b/loader/i386/efi/xnu.c @@ -79,7 +79,7 @@ find_framebuf (grub_uint32_t *fb_base, grub_uint32_t *line_len) { grub_pci_address_t addr; - addr = grub_pci_make_address (dev, 2); + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); if (grub_pci_read (addr) >> 24 == 0x3) { int i; diff --git a/loader/i386/linux.c b/loader/i386/linux.c index 43c455cd6..d3d935182 100644 --- a/loader/i386/linux.c +++ b/loader/i386/linux.c @@ -394,12 +394,15 @@ grub_linux_setup_video (struct linux_kernel_params *params) { struct grub_video_mode_info mode_info; void *framebuffer; - int ret; + grub_err_t err; - ret = grub_video_get_info_and_fini (&mode_info, &framebuffer); + err = grub_video_get_info_and_fini (&mode_info, &framebuffer); - if (ret) - return 1; + if (err) + { + grub_errno = GRUB_ERR_NONE; + return 1; + } params->lfb_width = mode_info.width; params->lfb_height = mode_info.height; @@ -407,7 +410,7 @@ grub_linux_setup_video (struct linux_kernel_params *params) params->lfb_line_len = mode_info.pitch; params->lfb_base = (grub_size_t) framebuffer; - params->lfb_size = (params->lfb_line_len * params->lfb_height + 65535) >> 16; + params->lfb_size = ALIGN_UP (params->lfb_line_len * params->lfb_height, 65536); params->red_mask_size = mode_info.red_mask_size; params->red_field_pos = mode_info.red_field_pos; @@ -519,16 +522,14 @@ grub_linux_boot (void) May change in future if we have modes without framebuffer. */ if (modevar && *modevar != 0) { - tmp = grub_malloc (grub_strlen (modevar) - + sizeof (";text")); + tmp = grub_xasprintf ("%s;text", modevar); if (! tmp) return grub_errno; - grub_sprintf (tmp, "%s;text", modevar); - err = grub_video_set_mode (tmp, 0); + err = grub_video_set_mode (tmp, 0, 0); grub_free (tmp); } else - err = grub_video_set_mode ("text", 0); + err = grub_video_set_mode ("text", 0, 0); if (err) { @@ -538,16 +539,22 @@ grub_linux_boot (void) } if (! grub_linux_setup_video (params)) - params->have_vga = GRUB_VIDEO_TYPE_VLFB; + { + /* Use generic framebuffer unless VESA is known to be supported. */ + if (params->have_vga != GRUB_VIDEO_LINUX_TYPE_VESA) + params->have_vga = GRUB_VIDEO_LINUX_TYPE_SIMPLE; + else + params->lfb_size >>= 16; + } else { - params->have_vga = GRUB_VIDEO_TYPE_TEXT; + params->have_vga = GRUB_VIDEO_LINUX_TYPE_TEXT; params->video_width = 80; params->video_height = 25; } /* Initialize these last, because terminal position could be affected by printfs above. */ - if (params->have_vga == GRUB_VIDEO_TYPE_TEXT) + if (params->have_vga == GRUB_VIDEO_LINUX_TYPE_TEXT) { grub_term_output_t term; int found = 0; @@ -796,19 +803,22 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), break; } - buf = grub_malloc (sizeof ("WWWWxHHHHxDD;WWWWxHHHH")); - if (! buf) - goto fail; + /* We can't detect VESA, but user is implicitly telling us that it + is built-in because `vga=' parameter was used. */ + params->have_vga = GRUB_VIDEO_LINUX_TYPE_VESA; linux_mode = &linux_vesafb_modes[vid_mode - GRUB_LINUX_VID_MODE_VESA_START]; - grub_sprintf (buf, "%ux%ux%u,%ux%u", - linux_vesafb_res[linux_mode->res_index].width, - linux_vesafb_res[linux_mode->res_index].height, - linux_mode->depth, - linux_vesafb_res[linux_mode->res_index].width, - linux_vesafb_res[linux_mode->res_index].height); + buf = grub_xasprintf ("%ux%ux%u,%ux%u", + linux_vesafb_res[linux_mode->res_index].width, + linux_vesafb_res[linux_mode->res_index].height, + linux_mode->depth, + linux_vesafb_res[linux_mode->res_index].width, + linux_vesafb_res[linux_mode->res_index].height); + if (! buf) + goto fail; + grub_printf ("%s is deprecated. " "Use set gfxpayload=%s before " "linux command instead.\n", diff --git a/loader/i386/multiboot.c b/loader/i386/multiboot.c index 86bb91ec8..5f9751f33 100644 --- a/loader/i386/multiboot.c +++ b/loader/i386/multiboot.c @@ -86,36 +86,6 @@ grub_get_multiboot_mmap_len (void) return count * sizeof (struct multiboot_mmap_entry); } -/* Fill previously allocated Multiboot mmap. */ -void -grub_fill_multiboot_mmap (struct multiboot_mmap_entry *first_entry) -{ - struct multiboot_mmap_entry *mmap_entry = (struct multiboot_mmap_entry *) first_entry; - - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); - int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) - { - mmap_entry->addr = addr; - mmap_entry->len = size; - switch (type) - { - case GRUB_MACHINE_MEMORY_AVAILABLE: - mmap_entry->type = MULTIBOOT_MEMORY_AVAILABLE; - break; - - default: - mmap_entry->type = MULTIBOOT_MEMORY_RESERVED; - break; - } - mmap_entry->size = sizeof (struct multiboot_mmap_entry) - sizeof (mmap_entry->size); - mmap_entry++; - - return 0; - } - - grub_mmap_iterate (hook); -} - grub_err_t grub_multiboot_set_video_mode (void) { @@ -126,21 +96,19 @@ grub_multiboot_set_video_mode (void) { modevar = grub_env_get ("gfxpayload"); if (! modevar || *modevar == 0) - err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0); + err = grub_video_set_mode (DEFAULT_VIDEO_MODE, 0, 0); else { char *tmp; - tmp = grub_malloc (grub_strlen (modevar) - + sizeof (DEFAULT_VIDEO_MODE) + 1); + tmp = grub_xasprintf ("%s;" DEFAULT_VIDEO_MODE, modevar); if (! tmp) return grub_errno; - grub_sprintf (tmp, "%s;" DEFAULT_VIDEO_MODE, modevar); - err = grub_video_set_mode (tmp, 0); + err = grub_video_set_mode (tmp, 0, 0); grub_free (tmp); } } else - err = grub_video_set_mode ("text", 0); + err = grub_video_set_mode ("text", 0, 0); return err; } @@ -385,17 +353,20 @@ grub_multiboot (int argc, char *argv[]) case 0: { - char buf[sizeof ("XXXXXXXXXXxXXXXXXXXXXxXXXXXXXXXX,XXXXXXXXXXxXXXXXXXXXX,auto")]; + char *buf; if (header->depth && header->width && header->height) - grub_sprintf (buf, "%dx%dx%d,%dx%d,auto", header->width, - header->height, header->depth, header->width, - header->height); + buf = grub_xasprintf ("%dx%dx%d,%dx%d,auto", header->width, + header->height, header->depth, header->width, + header->height); else if (header->width && header->height) - grub_sprintf (buf, "%dx%d,auto", header->width, header->height); + buf = grub_xasprintf ("%dx%d,auto", header->width, header->height); else - grub_sprintf (buf, "auto"); + buf = grub_strdup ("auto"); + if (!buf) + goto fail; grub_env_set ("gfxpayload", buf); + grub_free (buf); break; } } diff --git a/loader/i386/multiboot_mbi.c b/loader/i386/multiboot_mbi.c index 3e63b3456..a8133a705 100644 --- a/loader/i386/multiboot_mbi.c +++ b/loader/i386/multiboot_mbi.c @@ -61,40 +61,48 @@ grub_multiboot_get_mbi_size (void) + 256 * sizeof (struct multiboot_color); } -#if GRUB_MACHINE_HAS_VBE -static grub_err_t -fill_vbe_info (struct multiboot_info *mbi, - struct grub_vbe_mode_info_block **vbe_mode_info_out, - grub_uint8_t *ptrorig, grub_addr_t ptrdest) +/* Fill previously allocated Multiboot mmap. */ +static void +grub_fill_multiboot_mmap (struct multiboot_mmap_entry *first_entry) { - struct grub_vbe_info_block *vbe_control_info; - struct grub_vbe_mode_info_block *vbe_mode_info; - grub_err_t err; + struct multiboot_mmap_entry *mmap_entry = (struct multiboot_mmap_entry *) first_entry; - vbe_control_info = (struct grub_vbe_info_block *) ptrorig; - mbi->vbe_control_info = ptrdest; - ptrorig += sizeof (struct grub_vbe_info_block); - ptrdest += sizeof (struct grub_vbe_info_block); - vbe_mode_info = (struct grub_vbe_mode_info_block *) ptrorig; - mbi->vbe_mode_info = ptrdest; - ptrorig += sizeof (struct grub_vbe_mode_info_block); - ptrdest += sizeof (struct grub_vbe_mode_info_block); - - err = grub_multiboot_fill_vbe_info_real (vbe_control_info, vbe_mode_info, - &mbi->vbe_mode, - &mbi->vbe_interface_seg, - &mbi->vbe_interface_off, - &mbi->vbe_interface_len); - if (err) - return err; - mbi->flags |= MULTIBOOT_INFO_VBE_INFO; - if (vbe_mode_info_out) - *vbe_mode_info_out = vbe_mode_info; - return GRUB_ERR_NONE; -} + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) + { + mmap_entry->addr = addr; + mmap_entry->len = size; + switch (type) + { + case GRUB_MACHINE_MEMORY_AVAILABLE: + mmap_entry->type = MULTIBOOT_MEMORY_AVAILABLE; + break; +#ifdef GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE + case GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE: + mmap_entry->type = MULTIBOOT_MEMORY_ACPI_RECLAIMABLE; + break; #endif +#ifdef GRUB_MACHINE_MEMORY_NVS + case GRUB_MACHINE_MEMORY_NVS: + mmap_entry->type = MULTIBOOT_MEMORY_NVS; + break; +#endif + + default: + mmap_entry->type = MULTIBOOT_MEMORY_RESERVED; + break; + } + mmap_entry->size = sizeof (struct multiboot_mmap_entry) - sizeof (mmap_entry->size); + mmap_entry++; + + return 0; + } + + grub_mmap_iterate (hook); +} + static grub_err_t retrieve_video_parameters (struct multiboot_info *mbi, grub_uint8_t *ptrorig, grub_uint32_t ptrdest) @@ -115,33 +123,8 @@ retrieve_video_parameters (struct multiboot_info *mbi, grub_video_get_palette (0, ARRAY_SIZE (palette), palette); driv_id = grub_video_get_driver_id (); -#if GRUB_MACHINE_HAS_VGA_TEXT - if (driv_id == GRUB_VIDEO_DRIVER_NONE) - { - struct grub_vbe_mode_info_block *vbe_mode_info; - err = fill_vbe_info (mbi, &vbe_mode_info, ptrorig, ptrdest); - if (err) - return err; - if (vbe_mode_info->memory_model == GRUB_VBE_MEMORY_MODEL_TEXT) - { - mbi->framebuffer_addr = 0xb8000; - - mbi->framebuffer_pitch = 2 * vbe_mode_info->x_resolution; - mbi->framebuffer_width = vbe_mode_info->x_resolution; - mbi->framebuffer_height = vbe_mode_info->y_resolution; - - mbi->framebuffer_bpp = 16; - - mbi->framebuffer_type = MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT; - - mbi->flags |= MULTIBOOT_INFO_FRAMEBUFFER_INFO; - } - return GRUB_ERR_NONE; - } -#else if (driv_id == GRUB_VIDEO_DRIVER_NONE) return GRUB_ERR_NONE; -#endif err = grub_video_get_info_and_fini (&mode_info, &framebuffer); if (err) @@ -189,15 +172,6 @@ retrieve_video_parameters (struct multiboot_info *mbi, mbi->flags |= MULTIBOOT_INFO_FRAMEBUFFER_INFO; -#if GRUB_MACHINE_HAS_VBE - if (driv_id == GRUB_VIDEO_DRIVER_VBE) - { - err = fill_vbe_info (mbi, NULL, ptrorig, ptrdest); - if (err) - return err; - } -#endif - return GRUB_ERR_NONE; } @@ -423,8 +397,8 @@ grub_multiboot_set_bootdev (void) dev = grub_device_open (0); if (dev && dev->disk && dev->disk->partition) { - - p = dev->disk->partition->partmap->get_name (dev->disk->partition); + char *p0; + p = p0 = dev->disk->partition->partmap->get_name (dev->disk->partition); if (p) { if ((p[0] >= '0') && (p[0] <= '9')) @@ -438,6 +412,7 @@ grub_multiboot_set_bootdev (void) if ((p[0] >= 'a') && (p[0] <= 'z')) part = p[0] - 'a'; } + grub_free (p0); } if (dev) grub_device_close (dev); diff --git a/loader/i386/multiboot_mbi2.c b/loader/i386/multiboot_mbi2.c index 636b63923..a53bbe50a 100644 --- a/loader/i386/multiboot_mbi2.c +++ b/loader/i386/multiboot_mbi2.c @@ -104,6 +104,48 @@ fill_vbe_info (struct grub_vbe_mode_info_block **vbe_mode_info_out, #endif +/* Fill previously allocated Multiboot mmap. */ +static void +grub_fill_multiboot_mmap (struct multiboot_mmap_entry *first_entry) +{ + struct multiboot_mmap_entry *mmap_entry = (struct multiboot_mmap_entry *) first_entry; + + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) + { + mmap_entry->addr = addr; + mmap_entry->len = size; + switch (type) + { + case GRUB_MACHINE_MEMORY_AVAILABLE: + mmap_entry->type = MULTIBOOT_MEMORY_AVAILABLE; + break; + +#ifdef GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE + case GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE: + mmap_entry->type = MULTIBOOT_MEMORY_ACPI_RECLAIMABLE; + break; +#endif + +#ifdef GRUB_MACHINE_MEMORY_NVS + case GRUB_MACHINE_MEMORY_NVS: + mmap_entry->type = MULTIBOOT_MEMORY_NVS; + break; +#endif + + default: + mmap_entry->type = MULTIBOOT_MEMORY_RESERVED; + break; + } + mmap_entry->size = sizeof (struct multiboot_mmap_entry) - sizeof (mmap_entry->size); + mmap_entry++; + + return 0; + } + + grub_mmap_iterate (hook); +} + static grub_err_t retrieve_video_parameters (grub_uint8_t **ptrorig) { diff --git a/loader/i386/pc/chainloader.c b/loader/i386/pc/chainloader.c index 1d6de1de7..fbc356895 100644 --- a/loader/i386/pc/chainloader.c +++ b/loader/i386/pc/chainloader.c @@ -43,7 +43,7 @@ static void *boot_part_addr; static grub_err_t grub_chainloader_boot (void) { - grub_video_set_mode ("text", NULL); + grub_video_set_mode ("text", 0, 0); grub_chainloader_real_boot (boot_drive, boot_part_addr); /* Never reach here. */ diff --git a/loader/i386/pc/linux.c b/loader/i386/pc/linux.c index 96973adb9..0fa9abc12 100644 --- a/loader/i386/pc/linux.c +++ b/loader/i386/pc/linux.c @@ -53,7 +53,7 @@ grub_linux_unload (void) static grub_err_t grub_linux16_boot (void) { - grub_video_set_mode ("text", NULL); + grub_video_set_mode ("text", 0, 0); grub_linux16_real_boot (); /* Not reached. */ diff --git a/loader/i386/pc/xnu.c b/loader/i386/pc/xnu.c index ebb176bb4..39a595d9b 100644 --- a/loader/i386/pc/xnu.c +++ b/loader/i386/pc/xnu.c @@ -22,20 +22,12 @@ #include #include #include +#include #define min(a,b) (((a) < (b)) ? (a) : (b)) #define max(a,b) (((a) > (b)) ? (a) : (b)) -#define DEFAULT_VIDEO_MODE "1024x768x32,800x600x32,640x480x32" - -static int NESTED_FUNC_ATTR video_hook (grub_video_adapter_t p __attribute__ ((unused)), - struct grub_video_mode_info *info) -{ - if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT) - return 0; - - return 1; -} +#define DEFAULT_VIDEO_MODE "auto" /* Setup video for xnu. */ grub_err_t @@ -43,53 +35,74 @@ grub_xnu_set_video (struct grub_xnu_boot_params *params) { struct grub_video_mode_info mode_info; int ret; - char *tmp, *modevar; + char *tmp; + const char *modevar; void *framebuffer; grub_err_t err; + struct grub_video_bitmap *bitmap = NULL; modevar = grub_env_get ("gfxpayload"); + /* Consider only graphical 32-bit deep modes. */ if (! modevar || *modevar == 0) - err = grub_video_set_mode (DEFAULT_VIDEO_MODE, video_hook); + err = grub_video_set_mode (DEFAULT_VIDEO_MODE, + GRUB_VIDEO_MODE_TYPE_PURE_TEXT + | GRUB_VIDEO_MODE_TYPE_DEPTH_MASK, + 32 << GRUB_VIDEO_MODE_TYPE_DEPTH_POS); else { - tmp = grub_malloc (grub_strlen (modevar) - + sizeof (DEFAULT_VIDEO_MODE) + 1); + tmp = grub_xasprintf ("%s;" DEFAULT_VIDEO_MODE, modevar); if (! tmp) - return grub_error (GRUB_ERR_OUT_OF_MEMORY, - "couldn't allocate temporary storag"); - grub_sprintf (tmp, "%s;" DEFAULT_VIDEO_MODE, modevar); - err = grub_video_set_mode (tmp, video_hook); + return grub_errno; + err = grub_video_set_mode (tmp, + GRUB_VIDEO_MODE_TYPE_PURE_TEXT + | GRUB_VIDEO_MODE_TYPE_DEPTH_MASK, + 32 << GRUB_VIDEO_MODE_TYPE_DEPTH_POS); grub_free (tmp); } if (err) return err; + ret = grub_video_get_info (&mode_info); + if (ret) + return grub_error (GRUB_ERR_IO, "couldn't retrieve video parameters"); + if (grub_xnu_bitmap) + { + if (grub_xnu_bitmap_mode == GRUB_XNU_BITMAP_STRETCH) + err = grub_video_bitmap_create_scaled (&bitmap, + mode_info.width, + mode_info.height, + grub_xnu_bitmap, + GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST); + else + bitmap = grub_xnu_bitmap; + } + + if (bitmap) { int x, y; - x = mode_info.width - grub_xnu_bitmap->mode_info.width; + x = mode_info.width - bitmap->mode_info.width; x /= 2; - y = mode_info.height - grub_xnu_bitmap->mode_info.height; + y = mode_info.height - bitmap->mode_info.height; y /= 2; - err = grub_video_blit_bitmap (grub_xnu_bitmap, + err = grub_video_blit_bitmap (bitmap, GRUB_VIDEO_BLIT_REPLACE, x > 0 ? x : 0, y > 0 ? y : 0, x < 0 ? -x : 0, y < 0 ? -y : 0, - min (grub_xnu_bitmap->mode_info.width, + min (bitmap->mode_info.width, mode_info.width), - min (grub_xnu_bitmap->mode_info.height, + 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); @@ -102,8 +115,8 @@ 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 = grub_xnu_bitmap - ? GRUB_XNU_VIDEO_SPLASH : GRUB_XNU_VIDEO_TEXT_IN_VIDEO; + params->lfb_mode = bitmap ? GRUB_XNU_VIDEO_SPLASH + : GRUB_XNU_VIDEO_TEXT_IN_VIDEO; return GRUB_ERR_NONE; } diff --git a/loader/i386/xnu.c b/loader/i386/xnu.c index 23a8a6f7b..8000579d0 100644 --- a/loader/i386/xnu.c +++ b/loader/i386/xnu.c @@ -749,11 +749,13 @@ grub_cpu_xnu_fill_devicetree (void) #endif /* The name of key for new table. */ - grub_sprintf (guidbuf, "%08x-%04x-%04x-%02x%02x-", - guid.data1, guid.data2, guid.data3, guid.data4[0], - guid.data4[1]); + grub_snprintf (guidbuf, sizeof (guidbuf), "%08x-%04x-%04x-%02x%02x-", + guid.data1, guid.data2, guid.data3, guid.data4[0], + guid.data4[1]); for (j = 2; j < 8; j++) - grub_sprintf (guidbuf + grub_strlen (guidbuf), "%02x", guid.data4[j]); + grub_snprintf (guidbuf + grub_strlen (guidbuf), + sizeof (guidbuf) - grub_strlen (guidbuf), + "%02x", guid.data4[j]); /* For some reason GUID has to be in uppercase. */ for (j = 0; guidbuf[j] ; j++) if (guidbuf[j] >= 'a' && guidbuf[j] <= 'f') diff --git a/loader/mips/linux.c b/loader/mips/linux.c new file mode 100644 index 000000000..64497f466 --- /dev/null +++ b/loader/mips/linux.c @@ -0,0 +1,398 @@ +/* linux.c - boot Linux */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2004,2005,2007,2009,2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* For frequencies. */ +#include +#include + +#define ELF32_LOADMASK (0x00000000UL) +#define ELF64_LOADMASK (0x0000000000000000ULL) + +static grub_dl_t my_mod; + +static int loaded; + +static grub_size_t linux_size; + +static grub_uint8_t *playground; +static grub_addr_t target_addr, entry_addr; +static int linux_argc; +static grub_off_t argv_off, envp_off; +static grub_off_t rd_addr_arg_off, rd_size_arg_off; +static int initrd_loaded = 0; + +static grub_err_t +grub_linux_boot (void) +{ + struct grub_relocator32_state state; + + /* Boot the kernel. */ + state.gpr[1] = entry_addr; + state.gpr[4] = linux_argc; + state.gpr[5] = target_addr + argv_off; + state.gpr[6] = target_addr + envp_off; + state.jumpreg = 1; + grub_relocator32_boot (playground, target_addr, state); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_linux_release_mem (void) +{ + grub_relocator32_free (playground); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_linux_unload (void) +{ + grub_err_t err; + + err = grub_linux_release_mem (); + grub_dl_unref (my_mod); + + loaded = 0; + + return err; +} + +static grub_err_t +grub_linux_load32 (grub_elf_t elf, void **extra_mem, grub_size_t extra_size) +{ + Elf32_Addr base; + int extraoff; + + /* Linux's entry point incorrectly contains a virtual address. */ + entry_addr = elf->ehdr.ehdr32.e_entry & ~ELF32_LOADMASK; + + linux_size = grub_elf32_size (elf, &base); + if (linux_size == 0) + return grub_errno; + target_addr = base; + /* Pad it; the kernel scribbles over memory beyond its load address. */ + linux_size += 0x100000; + linux_size = ALIGN_UP (base + linux_size, 4) - base; + extraoff = linux_size; + linux_size += extra_size; + + playground = grub_relocator32_alloc (linux_size); + if (!playground) + return grub_errno; + + *extra_mem = playground + extraoff; + + /* Now load the segments into the area we claimed. */ + auto grub_err_t offset_phdr (Elf32_Phdr *phdr, grub_addr_t *addr, int *do_load); + grub_err_t offset_phdr (Elf32_Phdr *phdr, grub_addr_t *addr, int *do_load) + { + if (phdr->p_type != PT_LOAD) + { + *do_load = 0; + return 0; + } + *do_load = 1; + + /* Linux's program headers incorrectly contain virtual addresses. + * Translate those to physical, and offset to the area we claimed. */ + *addr = (grub_addr_t) (phdr->p_paddr - base + playground); + return 0; + } + return grub_elf32_load (elf, offset_phdr, 0, 0); +} + +static grub_err_t +grub_linux_load64 (grub_elf_t elf, void **extra_mem, grub_size_t extra_size) +{ + Elf64_Addr base; + int extraoff; + + /* Linux's entry point incorrectly contains a virtual address. */ + entry_addr = elf->ehdr.ehdr64.e_entry & ~ELF64_LOADMASK; + + linux_size = grub_elf64_size (elf, &base); + if (linux_size == 0) + return grub_errno; + target_addr = base; + /* Pad it; the kernel scribbles over memory beyond its load address. */ + linux_size += 0x100000; + linux_size = ALIGN_UP (base + linux_size, 4) - base; + extraoff = linux_size; + linux_size += extra_size; + + playground = grub_relocator32_alloc (linux_size); + if (!playground) + return grub_errno; + + *extra_mem = playground + extraoff; + + /* Now load the segments into the area we claimed. */ + auto grub_err_t offset_phdr (Elf64_Phdr *phdr, grub_addr_t *addr, int *do_load); + grub_err_t offset_phdr (Elf64_Phdr *phdr, grub_addr_t *addr, int *do_load) + { + if (phdr->p_type != PT_LOAD) + { + *do_load = 0; + return 0; + } + *do_load = 1; + /* Linux's program headers incorrectly contain virtual addresses. + * Translate those to physical, and offset to the area we claimed. */ + *addr = (grub_addr_t) (phdr->p_paddr - base + playground); + return 0; + } + return grub_elf64_load (elf, offset_phdr, 0, 0); +} + +static grub_err_t +grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + grub_elf_t elf = 0; + int i; + int size; + void *extra = NULL; + grub_uint32_t *linux_argv, *linux_envp; + char *linux_args, *linux_envs; + grub_err_t err; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "no kernel specified"); + + elf = grub_elf_open (argv[0]); + if (! elf) + return grub_errno; + + if (elf->ehdr.ehdr32.e_type != ET_EXEC) + { + grub_elf_close (elf); + return grub_error (GRUB_ERR_UNKNOWN_OS, + "this ELF file is not of the right type\n"); + } + + /* Release the previously used memory. */ + grub_loader_unset (); + loaded = 0; + + /* For arguments. */ + linux_argc = argc; + /* Main arguments. */ + size = (linux_argc) * sizeof (grub_uint32_t); + /* Initrd address and size. */ + size += 2 * sizeof (grub_uint32_t); + /* NULL terminator. */ + size += sizeof (grub_uint32_t); + + /* First argument is always "a0". */ + size += ALIGN_UP (sizeof ("a0"), 4); + /* Normal arguments. */ + for (i = 1; i < argc; i++) + size += ALIGN_UP (grub_strlen (argv[i]) + 1, 4); + + /* rd arguments. */ + size += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4); + size += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4); + + /* For the environment. */ + size += sizeof (grub_uint32_t); + size += 4 * sizeof (grub_uint32_t); + size += ALIGN_UP (sizeof ("memsize=XXXXXXXXXXXXXXXXXXXX"), 4) + + ALIGN_UP (sizeof ("highmemsize=XXXXXXXXXXXXXXXXXXXX"), 4) + + ALIGN_UP (sizeof ("busclock=XXXXXXXXXX"), 4) + + ALIGN_UP (sizeof ("cpuclock=XXXXXXXXXX"), 4); + + if (grub_elf_is_elf32 (elf)) + err = grub_linux_load32 (elf, &extra, size); + else + if (grub_elf_is_elf64 (elf)) + err = grub_linux_load64 (elf, &extra, size); + else + err = grub_error (GRUB_ERR_BAD_FILE_TYPE, "unknown ELF class"); + + grub_elf_close (elf); + + if (err) + return err; + + linux_argv = extra; + argv_off = (grub_uint8_t *) linux_argv - (grub_uint8_t *) playground; + extra = linux_argv + (linux_argc + 1 + 2); + linux_args = extra; + + grub_memcpy (linux_args, "a0", sizeof ("a0")); + *linux_argv = (grub_uint8_t *) linux_args - (grub_uint8_t *) playground + + target_addr; + linux_argv++; + linux_args += ALIGN_UP (sizeof ("a0"), 4); + + for (i = 1; i < argc; i++) + { + grub_memcpy (linux_args, argv[i], grub_strlen (argv[i]) + 1); + *linux_argv = (grub_uint8_t *) linux_args - (grub_uint8_t *) playground + + target_addr; + linux_argv++; + linux_args += ALIGN_UP (grub_strlen (argv[i]) + 1, 4); + } + + /* Reserve space for rd arguments. */ + rd_addr_arg_off = (grub_uint8_t *) linux_args - (grub_uint8_t *) playground; + linux_args += ALIGN_UP (sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), 4); + *linux_argv = 0; + linux_argv++; + + rd_size_arg_off = (grub_uint8_t *) linux_args - (grub_uint8_t *) playground; + linux_args += ALIGN_UP (sizeof ("rd_size=0xXXXXXXXXXXXXXXXX"), 4); + *linux_argv = 0; + linux_argv++; + + *linux_argv = 0; + + extra = linux_args; + + linux_envp = extra; + envp_off = (grub_uint8_t *) linux_envp - (grub_uint8_t *) playground; + linux_envs = (char *) (linux_envp + 5); + grub_snprintf (linux_envs, sizeof ("memsize=XXXXXXXXXXXXXXXXXXXX"), + "memsize=%lld", + (unsigned long long) grub_mmap_get_lower () >> 20); + linux_envp[0] = (grub_uint8_t *) linux_envs - (grub_uint8_t *) playground + + target_addr; + linux_envs += ALIGN_UP (grub_strlen (linux_envs) + 1, 4); + grub_snprintf (linux_envs, sizeof ("highmemsize=XXXXXXXXXXXXXXXXXXXX"), + "highmemsize=%lld", + (unsigned long long) grub_mmap_get_upper () >> 20); + linux_envp[1] = (grub_uint8_t *) linux_envs - (grub_uint8_t *) playground + + target_addr; + linux_envs += ALIGN_UP (grub_strlen (linux_envs) + 1, 4); + + grub_snprintf (linux_envs, sizeof ("busclock=XXXXXXXXXX"), + "busclock=%d", grub_arch_busclock); + linux_envp[2] = (grub_uint8_t *) linux_envs - (grub_uint8_t *) playground + + target_addr; + linux_envs += ALIGN_UP (grub_strlen (linux_envs) + 1, 4); + grub_snprintf (linux_envs, sizeof ("cpuclock=XXXXXXXXXX"), + "cpuclock=%d", grub_arch_cpuclock); + linux_envp[3] = (grub_uint8_t *) linux_envs - (grub_uint8_t *) playground + + target_addr; + linux_envs += ALIGN_UP (grub_strlen (linux_envs) + 1, 4); + + + linux_envp[4] = 0; + + grub_loader_set (grub_linux_boot, grub_linux_unload, 1); + initrd_loaded = 0; + loaded = 1; + grub_dl_ref (my_mod); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + grub_file_t file = 0; + grub_ssize_t size; + grub_size_t overhead; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "no initrd specified"); + + if (!loaded) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "you need to load Linux first."); + + if (initrd_loaded) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "only one initrd can be loaded."); + + file = grub_file_open (argv[0]); + if (! file) + return grub_errno; + + size = grub_file_size (file); + + overhead = ALIGN_UP (target_addr + linux_size + 0x10000, 0x10000) + - (target_addr + linux_size); + + playground = grub_relocator32_realloc (playground, + linux_size + overhead + size); + + if (!playground) + { + grub_file_close (file); + return grub_errno; + } + + if (grub_file_read (file, playground + linux_size + overhead, size) != size) + { + grub_error (GRUB_ERR_FILE_READ_ERROR, "couldn't read file"); + grub_file_close (file); + + return grub_errno; + } + + grub_snprintf ((char *) playground + rd_addr_arg_off, + sizeof ("rd_start=0xXXXXXXXXXXXXXXXX"), "rd_start=0x%llx", + (unsigned long long) target_addr + linux_size + overhead); + ((grub_uint32_t *) (playground + argv_off))[linux_argc] + = target_addr + rd_addr_arg_off; + linux_argc++; + + grub_snprintf ((char *) playground + rd_size_arg_off, + sizeof ("rd_size=0xXXXXXXXXXXXXXXXXX"), "rd_size=0x%llx", + (unsigned long long) size); + ((grub_uint32_t *) (playground + argv_off))[linux_argc] + = target_addr + rd_size_arg_off; + linux_argc++; + + initrd_loaded = 1; + + grub_file_close (file); + + return GRUB_ERR_NONE; +} + +static grub_command_t cmd_linux, cmd_initrd; + +GRUB_MOD_INIT(linux) +{ + cmd_linux = grub_register_command ("linux", grub_cmd_linux, + 0, N_("Load Linux.")); + cmd_initrd = grub_register_command ("initrd", grub_cmd_initrd, + 0, N_("Load initrd.")); + my_mod = mod; +} + +GRUB_MOD_FINI(linux) +{ + grub_unregister_command (cmd_linux); + grub_unregister_command (cmd_initrd); +} diff --git a/loader/powerpc/ieee1275/linux.c b/loader/powerpc/ieee1275/linux.c index 39ba2ad0a..930c0cb41 100644 --- a/loader/powerpc/ieee1275/linux.c +++ b/loader/powerpc/ieee1275/linux.c @@ -111,7 +111,7 @@ grub_linux_load32 (grub_elf_t elf) if (entry == 0) entry = 0x01400000; - linux_size = grub_elf32_size (elf); + linux_size = grub_elf32_size (elf, 0); if (linux_size == 0) return grub_errno; /* Pad it; the kernel scribbles over memory beyond its load address. */ @@ -161,7 +161,7 @@ grub_linux_load64 (grub_elf_t elf) if (entry == 0) entry = 0x01400000; - linux_size = grub_elf64_size (elf); + linux_size = grub_elf64_size (elf, 0); if (linux_size == 0) return grub_errno; /* Pad it; the kernel scribbles over memory beyond its load address. */ diff --git a/loader/sparc64/ieee1275/linux.c b/loader/sparc64/ieee1275/linux.c index 4d5723c19..24a6849a6 100644 --- a/loader/sparc64/ieee1275/linux.c +++ b/loader/sparc64/ieee1275/linux.c @@ -173,12 +173,6 @@ grub_linux_unload (void) #define FOUR_MB (4 * 1024 * 1024) -static grub_addr_t -align_addr(grub_addr_t val, grub_addr_t align) -{ - return (val + (align - 1)) & ~(align - 1); -} - static grub_addr_t alloc_phys (grub_addr_t size) { @@ -192,39 +186,39 @@ alloc_phys (grub_addr_t size) if (type != 1) return 0; - addr = align_addr (addr, FOUR_MB); - if (addr >= end) + addr = ALIGN_UP (addr, FOUR_MB); + if (addr + size >= end) return 0; if (addr >= grub_phys_start && addr < grub_phys_end) { - addr = align_addr (grub_phys_end, FOUR_MB); - if (addr >= end) + addr = ALIGN_UP (grub_phys_end, FOUR_MB); + if (addr + size >= end) return 0; } if ((addr + size) >= grub_phys_start && (addr + size) < grub_phys_end) { - addr = align_addr (grub_phys_end, FOUR_MB); - if (addr >= end) + addr = ALIGN_UP (grub_phys_end, FOUR_MB); + if (addr + size >= end) return 0; } if (loaded) { - grub_addr_t linux_end = align_addr (linux_paddr + linux_size, FOUR_MB); + grub_addr_t linux_end = ALIGN_UP (linux_paddr + linux_size, FOUR_MB); if (addr >= linux_paddr && addr < linux_end) { addr = linux_end; - if (addr >= end) + if (addr + size >= end) return 0; } if ((addr + size) >= linux_paddr && (addr + size) < linux_end) { addr = linux_end; - if (addr >= end) + if (addr + size >= end) return 0; } } @@ -247,7 +241,7 @@ grub_linux_load64 (grub_elf_t elf) linux_entry = elf->ehdr.ehdr64.e_entry; linux_addr = 0x40004000; off = 0x4000; - linux_size = grub_elf64_size (elf); + linux_size = grub_elf64_size (elf, 0); if (linux_size == 0) return grub_errno; @@ -258,8 +252,8 @@ grub_linux_load64 (grub_elf_t elf) if (paddr == (grub_addr_t) -1) return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't allocate physical memory"); - ret = grub_ieee1275_map_physical (paddr, linux_addr - off, - linux_size + off, IEEE1275_MAP_DEFAULT); + ret = grub_ieee1275_map (paddr, linux_addr - off, + linux_size + off, IEEE1275_MAP_DEFAULT); if (ret) return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't map physical memory"); @@ -409,7 +403,7 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), "couldn't allocate physical memory"); goto fail; } - ret = grub_ieee1275_map_physical (paddr, addr, size, IEEE1275_MAP_DEFAULT); + ret = grub_ieee1275_map (paddr, addr, size, IEEE1275_MAP_DEFAULT); if (ret) { grub_error (GRUB_ERR_OUT_OF_MEMORY, diff --git a/loader/xnu.c b/loader/xnu.c index c3dcee3ed..cf9fa740b 100644 --- a/loader/xnu.c +++ b/loader/xnu.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -569,10 +570,9 @@ grub_xnu_register_memory (char *prefix, int *suffix, return grub_error (GRUB_ERR_OUT_OF_MEMORY, "can't register memory"); if (suffix) { - driverkey->name = grub_malloc (grub_strlen (prefix) + 10); + driverkey->name = grub_xasprintf ("%s%d", prefix, (*suffix)++); if (!driverkey->name) return grub_error (GRUB_ERR_OUT_OF_MEMORY, "can't register memory"); - grub_sprintf (driverkey->name, "%s%d", prefix, (*suffix)++); } else driverkey->name = grub_strdup (prefix); @@ -1355,18 +1355,37 @@ grub_xnu_fill_devicetree (void) } struct grub_video_bitmap *grub_xnu_bitmap = 0; +grub_xnu_bitmap_mode_t grub_xnu_bitmap_mode; + +/* Option array indices. */ +#define XNU_SPLASH_CMD_ARGINDEX_MODE 0 + +static const struct grub_arg_option xnu_splash_cmd_options[] = + { + {"mode", 'm', 0, "Background image mode.", "stretch|normal", + ARG_TYPE_STRING}, + {0, 0, 0, 0, 0, 0} + }; static grub_err_t -grub_cmd_xnu_splash (grub_command_t cmd __attribute__ ((unused)), +grub_cmd_xnu_splash (grub_extcmd_t cmd, int argc, char *args[]) { grub_err_t err; if (argc != 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); + if (cmd->state[XNU_SPLASH_CMD_ARGINDEX_MODE].set && + grub_strcmp (cmd->state[XNU_SPLASH_CMD_ARGINDEX_MODE].arg, + "stretch") == 0) + grub_xnu_bitmap_mode = GRUB_XNU_BITMAP_STRETCH; + else + grub_xnu_bitmap_mode = GRUB_XNU_BITMAP_CENTER; + err = grub_video_bitmap_load (&grub_xnu_bitmap, args[0]); if (err) grub_xnu_bitmap = 0; + return err; } @@ -1400,7 +1419,8 @@ grub_xnu_unlock () } static grub_command_t cmd_kernel64, cmd_kernel, cmd_mkext, cmd_kext; -static grub_command_t cmd_kextdir, cmd_ramdisk, cmd_resume, cmd_splash; +static grub_command_t cmd_kextdir, cmd_ramdisk, cmd_resume; +static grub_extcmd_t cmd_splash; GRUB_MOD_INIT(xnu) { @@ -1416,10 +1436,13 @@ GRUB_MOD_INIT(xnu) N_("DIRECTORY [OSBundleRequired]"), N_("Load XNU extension directory.")); cmd_ramdisk = grub_register_command ("xnu_ramdisk", grub_cmd_xnu_ramdisk, 0, - N_("Load XNU ramdisk. " - "It will be seen as md0.")); - cmd_splash = grub_register_command ("xnu_splash", grub_cmd_xnu_splash, 0, - N_("Load a splash image for XNU.")); + "Load XNU ramdisk. " + "It will be seen as md0."); + cmd_splash = grub_register_extcmd ("xnu_splash", + grub_cmd_xnu_splash, + GRUB_COMMAND_FLAG_BOTH, 0, + N_("Load a splash image for XNU."), + xnu_splash_cmd_options); #ifndef GRUB_UTIL cmd_resume = grub_register_command ("xnu_resume", grub_cmd_xnu_resume, @@ -1441,8 +1464,8 @@ GRUB_MOD_FINI(xnu) grub_unregister_command (cmd_kextdir); grub_unregister_command (cmd_ramdisk); grub_unregister_command (cmd_kernel); + grub_unregister_extcmd (cmd_splash); grub_unregister_command (cmd_kernel64); - grub_unregister_command (cmd_splash); grub_cpu_xnu_fini (); } diff --git a/mmap/mips/yeeloong/uppermem.c b/mmap/mips/yeeloong/uppermem.c new file mode 100644 index 000000000..3c5f814de --- /dev/null +++ b/mmap/mips/yeeloong/uppermem.c @@ -0,0 +1,66 @@ +/* Compute amount of lower and upper memory till the first hole. */ +/* + * 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 + +grub_uint64_t +grub_mmap_get_lower (void) +{ + grub_uint64_t lower = 0; + + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, + grub_uint32_t type) + { + if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + return 0; + if (addr == 0) + lower = size; + return 0; + } + + grub_mmap_iterate (hook); + if (lower > GRUB_ARCH_LOWMEMMAXSIZE) + lower = GRUB_ARCH_LOWMEMMAXSIZE; + return lower; +} + +grub_uint64_t +grub_mmap_get_upper (void) +{ + grub_uint64_t upper = 0; + + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, + grub_uint32_t type) + { + if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + return 0; + if (addr <= GRUB_ARCH_HIGHMEMPSTART && addr + size + > GRUB_ARCH_HIGHMEMPSTART) + upper = addr + size - GRUB_ARCH_HIGHMEMPSTART; + return 0; + } + + grub_mmap_iterate (hook); + return upper; +} diff --git a/mmap/mmap.c b/mmap/mmap.c index 874a238b2..c22be0a56 100644 --- a/mmap/mmap.c +++ b/mmap/mmap.c @@ -52,7 +52,7 @@ grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, #ifdef GRUB_MACHINE_MEMORY_AVAILABLE [GRUB_MACHINE_MEMORY_AVAILABLE] = 1, #endif -#ifdef GRUB_MACHINE_MEMORY_RESERVED +#if defined (GRUB_MACHINE_MEMORY_RESERVED) && GRUB_MACHINE_MEMORY_RESERVED != GRUB_MACHINE_MEMORY_HOLE [GRUB_MACHINE_MEMORY_RESERVED] = 3, #endif #ifdef GRUB_MACHINE_MEMORY_ACPI diff --git a/normal/autofs.c b/normal/autofs.c index d1ef761fb..11b3fc1be 100644 --- a/normal/autofs.c +++ b/normal/autofs.c @@ -38,6 +38,9 @@ autoload_fs_module (void) if (! grub_dl_get (p->name) && grub_dl_load (p->name)) return 1; + if (grub_errno) + grub_print_error (); + fs_module_list = p->next; grub_free (p->name); grub_free (p); @@ -57,14 +60,12 @@ read_fs_list (void) { char *filename; - filename = grub_malloc (grub_strlen (prefix) + sizeof ("/fs.lst")); + filename = grub_xasprintf ("%s/fs.lst", prefix); if (filename) { grub_file_t file; grub_fs_autoload_hook_t tmp_autoload_hook; - grub_sprintf (filename, "%s/fs.lst", prefix); - /* This rules out the possibility that read_fs_list() is invoked recursively when we call grub_file_open() below. */ tmp_autoload_hook = grub_fs_autoload_hook; diff --git a/normal/cmdline.c b/normal/cmdline.c index bcffffeab..05d665411 100644 --- a/normal/cmdline.c +++ b/normal/cmdline.c @@ -303,8 +303,9 @@ grub_cmdline_get (const char *prompt) grub_memmove (buf + lpos, str, len * sizeof (grub_uint32_t)); llen += len; + cl_set_pos_all (); + cl_print_all (lpos, 0); lpos += len; - cl_print_all (lpos - len, 0); cl_set_pos_all (); } } @@ -384,6 +385,8 @@ grub_cmdline_get (const char *prompt) if (hist_used == 0) grub_history_add (buf, llen); + grub_refresh (); + while ((key = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != '\n' && key != '\r') { switch (key) @@ -419,10 +422,13 @@ grub_cmdline_get (const char *prompt) int restore; char *insertu8; char *bufu8; + grub_uint32_t c; + c = buf[lpos]; buf[lpos] = '\0'; bufu8 = grub_ucs4_to_utf8_alloc (buf, lpos); + buf[lpos] = c; if (!bufu8) { grub_print_error (); @@ -462,13 +468,24 @@ grub_cmdline_get (const char *prompt) insertlen, 0); if (t > 0) { - insert[t] = 0; - cl_insert (insert); + if (insert[t-1] == ' ' && buf[lpos] == ' ') + { + insert[t-1] = 0; + if (t != 1) + cl_insert (insert); + lpos++; + } + else + { + insert[t] = 0; + cl_insert (insert); + } } grub_free (insertu8); grub_free (insert); } + cl_set_pos_all (); } break; @@ -593,6 +610,7 @@ grub_cmdline_get (const char *prompt) } break; } + grub_refresh (); } diff --git a/normal/completion.c b/normal/completion.c index f9d8307e8..13e8f7a6b 100644 --- a/normal/completion.c +++ b/normal/completion.c @@ -107,17 +107,12 @@ iterate_partition (grub_disk_t disk, const grub_partition_t p) if (! partition_name) return 1; - name = grub_malloc (grub_strlen (disk_name) + 1 - + grub_strlen (partition_name) + 1); - if (! name) - { - grub_free (partition_name); - return 1; - } - - grub_sprintf (name, "%s,%s", disk_name, partition_name); + name = grub_xasprintf ("%s,%s", disk_name, partition_name); grub_free (partition_name); + if (! name) + return 1; + ret = add_completion (name, ")", GRUB_COMPLETION_TYPE_PARTITION); grub_free (name); return ret; @@ -141,11 +136,15 @@ iterate_dir (const char *filename, const struct grub_dirhook_info *info) } else if (grub_strcmp (filename, ".") && grub_strcmp (filename, "..")) { - char fname[grub_strlen (filename) + 2]; + char *fname; - grub_sprintf (fname, "%s/", filename); + fname = grub_xasprintf ("%s/", filename); if (add_completion (fname, "", GRUB_COMPLETION_TYPE_FILE)) - return 1; + { + grub_free (fname); + return 1; + } + grub_free (fname); } return 0; @@ -360,8 +359,9 @@ complete_arguments (char *command) if (!option->longarg) continue; - longarg = grub_malloc (grub_strlen (option->longarg)); - grub_sprintf (longarg, "--%s", option->longarg); + longarg = grub_xasprintf ("--%s", option->longarg); + if (!longarg) + return 1; if (add_completion (longarg, " ", GRUB_COMPLETION_TYPE_ARGUMENT)) { diff --git a/normal/context.c b/normal/context.c new file mode 100644 index 000000000..08a841699 --- /dev/null +++ b/normal/context.c @@ -0,0 +1,182 @@ +/* env.c - Environment variables */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2005,2006,2007,2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +struct menu_pointer +{ + grub_menu_t menu; + struct menu_pointer *prev; +}; + +struct menu_pointer initial_menu; +struct menu_pointer *current_menu = &initial_menu; + +void +grub_env_unset_menu (void) +{ + current_menu->menu = NULL; +} + +grub_menu_t +grub_env_get_menu (void) +{ + return current_menu->menu; +} + +void +grub_env_set_menu (grub_menu_t nmenu) +{ + current_menu->menu = nmenu; +} + +grub_err_t +grub_env_context_open (int export) +{ + struct grub_env_context *context; + int i; + struct menu_pointer *menu; + + context = grub_zalloc (sizeof (*context)); + if (! context) + return grub_errno; + menu = grub_zalloc (sizeof (*menu)); + if (! menu) + return grub_errno; + + context->prev = grub_current_context; + grub_current_context = context; + + menu->prev = current_menu; + current_menu = menu; + + /* Copy exported variables. */ + for (i = 0; i < HASHSZ; i++) + { + struct grub_env_var *var; + + for (var = context->prev->vars[i]; var; var = var->next) + { + if (export && var->global) + { + if (grub_env_set (var->name, var->value) != GRUB_ERR_NONE) + { + grub_env_context_close (); + return grub_errno; + } + grub_env_export (var->name); + grub_register_variable_hook (var->name, var->read_hook, var->write_hook); + } + } + } + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_env_context_close (void) +{ + struct grub_env_context *context; + int i; + struct menu_pointer *menu; + + if (! grub_current_context->prev) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "cannot close the initial context"); + + /* Free the variables associated with this context. */ + for (i = 0; i < HASHSZ; i++) + { + struct grub_env_var *p, *q; + + for (p = grub_current_context->vars[i]; p; p = q) + { + q = p->next; + grub_free (p->name); + grub_free (p->value); + grub_free (p); + } + } + + /* Restore the previous context. */ + context = grub_current_context->prev; + grub_free (grub_current_context); + grub_current_context = context; + + menu = current_menu->prev; + grub_free (current_menu); + current_menu = menu; + + return GRUB_ERR_NONE; +} + +grub_err_t +grub_env_export (const char *name) +{ + struct grub_env_var *var; + + var = grub_env_find (name); + if (! var) + { + grub_err_t err; + + err = grub_env_set (name, ""); + if (err) + return err; + var = grub_env_find (name); + } + var->global = 1; + + return GRUB_ERR_NONE; +} + +static grub_command_t export_cmd; + +static grub_err_t +grub_cmd_export (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + if (argc < 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "no environment variable specified"); + + grub_env_export (args[0]); + return 0; +} + +void +grub_context_init (void) +{ + grub_env_export ("root"); + grub_env_export ("prefix"); + + export_cmd = grub_register_command ("export", grub_cmd_export, + "export ENVVAR", "Export a variable."); +} + +void +grub_context_fini (void) +{ + grub_unregister_command (export_cmd); +} diff --git a/normal/crypto.c b/normal/crypto.c index 67330272a..f051e2c4c 100644 --- a/normal/crypto.c +++ b/normal/crypto.c @@ -80,22 +80,22 @@ read_crypto_list (void) return; } - filename = grub_malloc (grub_strlen (prefix) + sizeof ("/crypto.lst")); + filename = grub_xasprintf ("%s/crypto.lst", prefix); if (!filename) { grub_errno = GRUB_ERR_NONE; return; } - grub_sprintf (filename, "%s/crypto.lst", prefix); file = grub_file_open (filename); + grub_free (filename); if (!file) { grub_errno = GRUB_ERR_NONE; return; } - /* Override previous commands.lst. */ + /* Override previous crypto.lst. */ grub_crypto_spec_free (); for (;; grub_free (buf)) diff --git a/normal/dyncmd.c b/normal/dyncmd.c index e797d574f..ca9a82289 100644 --- a/normal/dyncmd.c +++ b/normal/dyncmd.c @@ -69,12 +69,11 @@ read_command_list (void) { char *filename; - filename = grub_malloc (grub_strlen (prefix) + sizeof ("/command.lst")); + filename = grub_xasprintf ("%s/command.lst", prefix); if (filename) { grub_file_t file; - grub_sprintf (filename, "%s/command.lst", prefix); file = grub_file_open (filename); if (file) { diff --git a/normal/handler.c b/normal/handler.c index b44dc7a68..686626929 100644 --- a/normal/handler.c +++ b/normal/handler.c @@ -172,12 +172,11 @@ read_handler_list (void) { char *filename; - filename = grub_malloc (grub_strlen (prefix) + sizeof ("/handler.lst")); + filename = grub_xasprintf ("%s/handler.lst", prefix); if (filename) { grub_file_t file; - grub_sprintf (filename, "%s/handler.lst", prefix); file = grub_file_open (filename); if (file) { diff --git a/normal/main.c b/normal/main.c index 7a5e3ee8e..5a5467485 100644 --- a/normal/main.c +++ b/normal/main.c @@ -137,7 +137,7 @@ free_menu (grub_menu_t menu) } grub_free (menu); - grub_env_unset_data_slot ("menu"); + grub_env_unset_menu (); } static void @@ -178,7 +178,7 @@ grub_normal_add_menu_entry (int argc, const char **args, return grub_errno; classes_tail = classes_head; - menu = grub_env_get_data_slot ("menu"); + menu = grub_env_get_menu (); if (! menu) return grub_error (GRUB_ERR_MENU, "no menu context"); @@ -361,14 +361,14 @@ read_config_file (const char *config) grub_menu_t newmenu; - newmenu = grub_env_get_data_slot ("menu"); + newmenu = grub_env_get_menu (); if (! newmenu) { newmenu = grub_zalloc (sizeof (*newmenu)); if (! newmenu) return 0; - grub_env_set_data_slot ("menu", newmenu); + grub_env_set_menu (newmenu); } /* Try to open the config file. */ @@ -406,18 +406,19 @@ grub_normal_init_page (struct grub_term_output *term) int msg_len; int posx; const char *msg = _("GNU GRUB version %s"); - - char *msg_formatted = grub_malloc (grub_strlen(msg) + - grub_strlen(PACKAGE_VERSION)); + char *msg_formatted; grub_uint32_t *unicode_msg; grub_uint32_t *last_position; grub_term_cls (term); - grub_sprintf (msg_formatted, msg, PACKAGE_VERSION); + msg_formatted = grub_xasprintf (msg, PACKAGE_VERSION); + if (!msg_formatted) + return; msg_len = grub_utf8_to_ucs4_alloc (msg_formatted, &unicode_msg, &last_position); + grub_free (msg_formatted); if (msg_len < 0) { @@ -502,11 +503,10 @@ grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)), prefix = grub_env_get ("prefix"); if (prefix) { - config = grub_malloc (grub_strlen (prefix) + sizeof ("/grub.cfg")); + config = grub_xasprintf ("%s/grub.cfg", prefix); if (! config) goto quit; - grub_sprintf (config, "%s/grub.cfg", prefix); grub_enter_normal_mode (config); grub_free (config); } @@ -540,10 +540,11 @@ grub_normal_reader_init (int nested) "the first word, TAB lists possible command completions. Anywhere " "else TAB lists possible device or file completions. %s"); const char *msg_esc = _("ESC at any time exits."); - char *msg_formatted = grub_malloc (sizeof (char) * (grub_strlen (msg) + - grub_strlen(msg_esc) + 1)); + char *msg_formatted; - grub_sprintf (msg_formatted, msg, nested ? msg_esc : ""); + msg_formatted = grub_xasprintf (msg, nested ? msg_esc : ""); + if (!msg_formatted) + return grub_errno; FOR_ACTIVE_TERM_OUTPUTS(term) { @@ -563,12 +564,15 @@ static grub_err_t grub_normal_read_line_real (char **line, int cont, int nested) { grub_parser_t parser = grub_parser_get_current (); - char prompt[sizeof(">") + grub_strlen (parser->name)]; + char *prompt; if (cont) - grub_sprintf (prompt, ">"); + prompt = grub_xasprintf (">"); else - grub_sprintf (prompt, "%s>", parser->name); + prompt = grub_xasprintf ("%s>", parser->name); + + if (!prompt) + return grub_errno; while (1) { @@ -579,10 +583,13 @@ 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; } @@ -639,12 +646,15 @@ grub_env_write_pager (struct grub_env_var *var __attribute__ ((unused)), GRUB_MOD_INIT(normal) { + grub_context_init (); + /* Normal mode shouldn't be unloaded. */ if (mod) grub_dl_ref (mod); grub_set_history (GRUB_DEFAULT_HISTORY_SIZE); + grub_install_newline_hook (); grub_register_variable_hook ("pager", 0, grub_env_write_pager); /* Register a command "normal" for the rescue mode. */ @@ -664,6 +674,8 @@ GRUB_MOD_INIT(normal) GRUB_MOD_FINI(normal) { + grub_context_fini (); + grub_set_history (0); grub_register_variable_hook ("pager", 0, 0); grub_fs_autoload_hook = 0; diff --git a/normal/menu.c b/normal/menu.c index 17730eff3..07951dacc 100644 --- a/normal/menu.c +++ b/normal/menu.c @@ -1,7 +1,7 @@ /* menu.c - General supporting functionality for menus. */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2003,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc. + * Copyright (C) 2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -98,7 +98,7 @@ grub_menu_set_timeout (int timeout) { char buf[16]; - grub_sprintf (buf, "%d", timeout); + grub_snprintf (buf, sizeof (buf), "%d", timeout); grub_env_set ("timeout", buf); } } @@ -362,6 +362,8 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) if (timeout > 0) menu_print_timeout (timeout); + else + clear_timeout (); while (1) { @@ -519,7 +521,7 @@ notify_execution_failure (void *userdata __attribute__((unused))) grub_errno = GRUB_ERR_NONE; } grub_printf ("\n "); - grub_printf_ (N_("Failed to boot default entries.\n")); + grub_printf_ (N_("Failed to boot both default and fallback entries.\n")); grub_wait_after_message (); } @@ -557,14 +559,14 @@ show_menu (grub_menu_t menu, int nested) } else { + int lines_before = grub_normal_get_line_counter (); grub_errno = GRUB_ERR_NONE; grub_menu_execute_entry (e); - if (grub_errno != GRUB_ERR_NONE) - { - grub_print_error (); - grub_errno = GRUB_ERR_NONE; - grub_wait_after_message (); - } + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + + if (lines_before != grub_normal_get_line_counter ()) + grub_wait_after_message (); } } diff --git a/normal/menu_text.c b/normal/menu_text.c index cab1d22f8..b39f57512 100644 --- a/normal/menu_text.c +++ b/normal/menu_text.c @@ -183,13 +183,14 @@ command-line or ESC to return menu."), STANDARD_MARGIN, STANDARD_MARGIN, } else { - const char *msg = _("Use the %C and %C keys to select which \ -entry is highlighted.\n"); - char *msg_translated = - grub_malloc (sizeof (char) * grub_strlen (msg) + 1); + const char *msg = _("Use the %C and %C keys to select which " + "entry is highlighted.\n"); + char *msg_translated; - grub_sprintf (msg_translated, msg, (grub_uint32_t) GRUB_TERM_DISP_UP, - (grub_uint32_t) GRUB_TERM_DISP_DOWN); + msg_translated = grub_xasprintf (msg, (grub_uint32_t) GRUB_TERM_DISP_UP, + (grub_uint32_t) GRUB_TERM_DISP_DOWN); + if (!msg_translated) + return; grub_putchar ('\n'); grub_print_message_indented (msg_translated, STANDARD_MARGIN, STANDARD_MARGIN, term); @@ -366,7 +367,7 @@ menu_text_print_timeout (int timeout, void *dataptr) grub_term_gotoxy (data->term, 0, grub_term_height (data->term) - 3); - msg_translated = grub_malloc (sizeof (char) * grub_strlen (msg) + 5); + msg_translated = grub_xasprintf (msg, timeout); if (!msg_translated) { grub_print_error (); @@ -374,7 +375,6 @@ menu_text_print_timeout (int timeout, void *dataptr) return; } - grub_sprintf (msg_translated, msg, timeout); grub_print_message_indented (msg_translated, 3, 0, data->term); posx = grub_term_getxy (data->term) >> 8; diff --git a/normal/term.c b/normal/term.c index 667d27ee9..7bedd6799 100644 --- a/normal/term.c +++ b/normal/term.c @@ -30,6 +30,14 @@ static unsigned grub_more_lines; /* If the more pager is active. */ static int grub_more; +static int grub_normal_line_counter = 0; + +int +grub_normal_get_line_counter (void) +{ + return grub_normal_line_counter; +} + static void process_newline (void) { @@ -41,6 +49,8 @@ process_newline (void) height = grub_term_height (cur); grub_more_lines++; + grub_normal_line_counter++; + if (grub_more && grub_more_lines >= height - 1) { char key; @@ -76,6 +86,11 @@ grub_set_more (int onoff) grub_more--; grub_more_lines = 0; +} + +void +grub_install_newline_hook (void) +{ grub_newline_hook = process_newline; } @@ -150,7 +165,6 @@ grub_terminal_autoload_free (void) grub_term_output_autoload = NULL; } - /* Read the file terminal.lst for auto-loading. */ void read_terminal_list (void) @@ -167,15 +181,15 @@ read_terminal_list (void) return; } - filename = grub_malloc (grub_strlen (prefix) + sizeof ("/terminal.lst")); + filename = grub_xasprintf ("%s/terminal.lst", prefix); if (!filename) { grub_errno = GRUB_ERR_NONE; return; } - grub_sprintf (filename, "%s/terminal.lst", prefix); file = grub_file_open (filename); + grub_free (filename); if (!file) { grub_errno = GRUB_ERR_NONE; diff --git a/partmap/acorn.c b/partmap/acorn.c index 076d998f8..081b6ee94 100644 --- a/partmap/acorn.c +++ b/partmap/acorn.c @@ -175,14 +175,7 @@ fail: static char * acorn_partition_map_get_name (const grub_partition_t p) { - char *name; - - name = grub_malloc (13); - if (! name) - return 0; - - grub_sprintf (name, "%d", p->index + 1); - return name; + return grub_xasprintf ("%d", p->index + 1); } diff --git a/partmap/amiga.c b/partmap/amiga.c index e8ba9181c..f832db354 100644 --- a/partmap/amiga.c +++ b/partmap/amiga.c @@ -184,14 +184,7 @@ amiga_partition_map_probe (grub_disk_t disk, const char *str) static char * amiga_partition_map_get_name (const grub_partition_t p) { - char *name; - - name = grub_malloc (13); - if (! name) - return 0; - - grub_sprintf (name, "%d", p->index + 1); - return name; + return grub_xasprintf ("%d", p->index + 1); } diff --git a/partmap/apple.c b/partmap/apple.c index 7934c90fd..a1a645acf 100644 --- a/partmap/apple.c +++ b/partmap/apple.c @@ -227,14 +227,7 @@ apple_partition_map_probe (grub_disk_t disk, const char *str) static char * apple_partition_map_get_name (const grub_partition_t p) { - char *name; - - name = grub_malloc (13); - if (! name) - return 0; - - grub_sprintf (name, "%d", p->index + 1); - return name; + return grub_xasprintf ("%d", p->index + 1); } diff --git a/partmap/gpt.c b/partmap/gpt.c index 4a4957437..cb1229bee 100644 --- a/partmap/gpt.c +++ b/partmap/gpt.c @@ -162,14 +162,7 @@ gpt_partition_map_probe (grub_disk_t disk, const char *str) static char * gpt_partition_map_get_name (const grub_partition_t p) { - char *name; - - name = grub_malloc (13); - if (! name) - return 0; - - grub_sprintf (name, "%d", p->index + 1); - return name; + return grub_xasprintf ("%d", p->index + 1); } diff --git a/partmap/msdos.c b/partmap/msdos.c index 6ba7fb927..1c3861cc7 100644 --- a/partmap/msdos.c +++ b/partmap/msdos.c @@ -300,21 +300,15 @@ pc_partition_map_probe (grub_disk_t disk, const char *str) static char * pc_partition_map_get_name (const grub_partition_t p) { - char *name; struct grub_msdos_partition *pcdata = p->data; - name = grub_malloc (13); - if (! name) - return 0; - if (pcdata->bsd_part < 0) - grub_sprintf (name, "%d", pcdata->dos_part + 1); + return grub_xasprintf ("%d", pcdata->dos_part + 1); else if (pcdata->dos_part < 0) - grub_sprintf (name, "%c", pcdata->bsd_part + 'a'); + return grub_xasprintf ("%c", pcdata->bsd_part + 'a'); else - grub_sprintf (name, "%d,%c", pcdata->dos_part + 1, pcdata->bsd_part + 'a'); - - return name; + return grub_xasprintf ("%d,%c", pcdata->dos_part + 1, + pcdata->bsd_part + 'a'); } diff --git a/partmap/sun.c b/partmap/sun.c index e816ec17a..df9adb0c0 100644 --- a/partmap/sun.c +++ b/partmap/sun.c @@ -91,6 +91,7 @@ sun_partition_map_iterate (grub_disk_t disk, struct grub_disk raw; struct grub_sun_block block; int partnum; + grub_err_t err; raw = *disk; raw.partition = 0; @@ -100,36 +101,47 @@ sun_partition_map_iterate (grub_disk_t disk, return grub_errno; p->partmap = &grub_sun_partition_map; - if (grub_disk_read (&raw, 0, 0, sizeof (struct grub_sun_block), - &block) == GRUB_ERR_NONE) + err = grub_disk_read (&raw, 0, 0, sizeof (struct grub_sun_block), + &block); + if (err) { - if (GRUB_PARTMAP_SUN_MAGIC != grub_be_to_cpu16 (block.magic)) - grub_error (GRUB_ERR_BAD_PART_TABLE, "not a sun partition table"); + grub_free (p); + return err; + } - if (! grub_sun_is_valid (&block)) - grub_error (GRUB_ERR_BAD_PART_TABLE, "invalid checksum"); + if (GRUB_PARTMAP_SUN_MAGIC != grub_be_to_cpu16 (block.magic)) + { + grub_free (p); + return grub_error (GRUB_ERR_BAD_PART_TABLE, + "not a sun partition table"); + } - /* Maybe another error value would be better, because partition - table _is_ recognized but invalid. */ - for (partnum = 0; partnum < GRUB_PARTMAP_SUN_MAX_PARTS; partnum++) + if (! grub_sun_is_valid (&block)) + { + grub_free (p); + return grub_error (GRUB_ERR_BAD_PART_TABLE, "invalid checksum"); + } + + /* Maybe another error value would be better, because partition + table _is_ recognized but invalid. */ + for (partnum = 0; partnum < GRUB_PARTMAP_SUN_MAX_PARTS; partnum++) + { + struct grub_sun_partition_descriptor *desc; + + if (block.infos[partnum].id == 0 + || block.infos[partnum].id == GRUB_PARTMAP_SUN_WHOLE_DISK_ID) + continue; + + desc = &block.partitions[partnum]; + p->start = ((grub_uint64_t) grub_be_to_cpu32 (desc->start_cylinder) + * grub_be_to_cpu16 (block.ntrks) + * grub_be_to_cpu16 (block.nsect)); + p->len = grub_be_to_cpu32 (desc->num_sectors); + p->index = partnum; + if (p->len) { - struct grub_sun_partition_descriptor *desc; - - if (block.infos[partnum].id == 0 - || block.infos[partnum].id == GRUB_PARTMAP_SUN_WHOLE_DISK_ID) - continue; - - desc = &block.partitions[partnum]; - p->start = ((grub_uint64_t) grub_be_to_cpu32 (desc->start_cylinder) - * grub_be_to_cpu16 (block.ntrks) - * grub_be_to_cpu16 (block.nsect)); - p->len = grub_be_to_cpu32 (desc->num_sectors); - p->index = partnum; - if (p->len) - { - if (hook (disk, p)) - partnum = GRUB_PARTMAP_SUN_MAX_PARTS; - } + if (hook (disk, p)) + partnum = GRUB_PARTMAP_SUN_MAX_PARTS; } } @@ -184,13 +196,7 @@ sun_partition_map_probe (grub_disk_t disk, const char *str) static char * sun_partition_map_get_name (const grub_partition_t p) { - char *name; - - name = grub_malloc (13); - if (name) - grub_sprintf (name, "%d", p->index + 1); - - return name; + return grub_xasprintf ("%d", p->index + 1); } /* Partition map type. */ diff --git a/po/POTFILES b/po/POTFILES index 32927256c..5fabb0634 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -75,16 +75,7 @@ normal/menu_entry.c normal/menu_text.c normal/misc.c -term/i386/pc/serial.c +term/serial.c -util/i386/pc/grub-mkimage.c +util/grub-mkrawimage.c util/i386/pc/grub-setup.c - -util/mkisofs/eltorito.c -util/mkisofs/joliet.c -util/mkisofs/mkisofs.c -util/mkisofs/mkisofs.h -util/mkisofs/multi.c -util/mkisofs/rock.c -util/mkisofs/tree.c -util/mkisofs/write.c diff --git a/script/execute.c b/script/execute.c index 08224fc7d..6e914aeeb 100644 --- a/script/execute.c +++ b/script/execute.c @@ -92,7 +92,7 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd) grub_err_t ret = 0; int argcount = 0; grub_script_function_t func = 0; - char errnobuf[6]; + char errnobuf[18]; char *cmdname; /* Lookup the command. */ @@ -100,7 +100,6 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd) grubcmd = grub_command_find (cmdname); if (! grubcmd) { - /* Ignore errors. */ grub_errno = GRUB_ERR_NONE; /* It's not a GRUB command, try all functions. */ @@ -123,9 +122,11 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd) } grub_free (assign); - grub_sprintf (errnobuf, "%d", grub_errno); + grub_snprintf (errnobuf, sizeof (errnobuf), "%d", grub_errno); grub_env_set ("?", errnobuf); + grub_print_error (); + return 0; } } @@ -156,7 +157,12 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd) grub_free (args[i]); grub_free (args); - grub_sprintf (errnobuf, "%d", ret); + if (grub_errno == GRUB_ERR_TEST_FAILURE) + grub_errno = GRUB_ERR_NONE; + + grub_print_error (); + + grub_snprintf (errnobuf, sizeof (errnobuf), "%d", ret); grub_env_set ("?", errnobuf); return ret; diff --git a/term/i386/pc/at_keyboard.c b/term/at_keyboard.c similarity index 94% rename from term/i386/pc/at_keyboard.c rename to term/at_keyboard.c index 6382c954a..1f84ae71a 100644 --- a/term/i386/pc/at_keyboard.c +++ b/term/at_keyboard.c @@ -17,13 +17,14 @@ */ #include -#include -#include -#include +#include +#include +#include #include #include static short at_keyboard_status = 0; +static int pending_key = -1; #define KEYBOARD_STATUS_SHIFT_L (1 << 0) #define KEYBOARD_STATUS_SHIFT_R (1 << 1) @@ -237,14 +238,27 @@ grub_at_keyboard_getkey_noblock (void) static int grub_at_keyboard_checkkey (void) { - /* FIXME: this will be triggered by BREAK events. */ - return KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS)) ? 1 : -1; + if (pending_key != -1) + return 1; + + pending_key = grub_at_keyboard_getkey_noblock (); + + if (pending_key != -1) + return 1; + + return -1; } static int grub_at_keyboard_getkey (void) { int key; + if (pending_key != -1) + { + key = pending_key; + pending_key = -1; + return key; + } do { key = grub_at_keyboard_getkey_noblock (); @@ -255,6 +269,8 @@ grub_at_keyboard_getkey (void) static grub_err_t grub_keyboard_controller_init (void) { + pending_key = -1; + at_keyboard_status = 0; grub_keyboard_controller_orig = grub_keyboard_controller_read (); grub_keyboard_controller_write (grub_keyboard_controller_orig | KEYBOARD_SCANCODE_SET1); return GRUB_ERR_NONE; diff --git a/term/gfxterm.c b/term/gfxterm.c index fa19a5d85..c18f43fee 100644 --- a/term/gfxterm.c +++ b/term/gfxterm.c @@ -24,10 +24,13 @@ #include #include #include +#include #include #include +#include +#include -#define DEFAULT_VIDEO_MODE "1024x768,800x600,640x480" +#define DEFAULT_VIDEO_MODE "auto" #define DEFAULT_BORDER_WIDTH 10 #define DEFAULT_STANDARD_COLOR 0x07 @@ -95,15 +98,33 @@ struct grub_virtual_screen /* Color settings. */ grub_video_color_t fg_color; grub_video_color_t bg_color; + grub_video_color_t bg_color_display; /* Text buffer for virtual screen. Contains (columns * rows) number of entries. */ struct grub_colored_char *text_buffer; + + int total_scroll; }; -static struct grub_virtual_screen virtual_screen; +struct grub_gfxterm_window +{ + unsigned x; + unsigned y; + unsigned width; + unsigned height; + int double_repaint; +}; -static struct grub_video_mode_info mode_info; +static struct grub_video_render_target *render_target; +void (*grub_gfxterm_decorator_hook) (void) = NULL; +static struct grub_gfxterm_window window; +static struct grub_virtual_screen virtual_screen; +static grub_gfxterm_repaint_callback_t repaint_callback; +static int repaint_schedulded = 0; +static int repaint_was_schedulded = 0; + +static void destroy_window (void); static struct grub_video_render_target *text_layer; @@ -124,6 +145,8 @@ static unsigned int calculate_normal_character_width (grub_font_t font); static unsigned char calculate_character_width (struct grub_font_glyph *glyph); +static void grub_gfxterm_refresh (void); + static void set_term_color (grub_uint8_t term_color) { @@ -201,6 +224,7 @@ grub_virtual_screen_setup (unsigned int x, unsigned int y, virtual_screen.cursor_x = 0; virtual_screen.cursor_y = 0; virtual_screen.cursor_state = 1; + virtual_screen.total_scroll = 0; /* Calculate size of text buffer. */ virtual_screen.columns = virtual_screen.width / virtual_screen.normal_char_width; @@ -235,7 +259,9 @@ grub_virtual_screen_setup (unsigned int x, unsigned int y, set_term_color (virtual_screen.term_color); - grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); + grub_video_set_active_render_target (render_target); + + virtual_screen.bg_color_display = grub_video_map_rgba(0, 0, 0, 0); /* Clear out text buffer. */ for (i = 0; i < virtual_screen.columns * virtual_screen.rows; i++) @@ -244,75 +270,122 @@ grub_virtual_screen_setup (unsigned int x, unsigned int y, return grub_errno; } -static int NESTED_FUNC_ATTR video_hook (grub_video_adapter_t p __attribute__ ((unused)), - struct grub_video_mode_info *info) +void +grub_gfxterm_schedule_repaint (void) { - return ! (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT); + repaint_schedulded = 1; } -static grub_err_t -grub_gfxterm_init (void) +grub_err_t +grub_gfxterm_set_window (struct grub_video_render_target *target, + int x, int y, int width, int height, + int double_repaint, + const char *font_name, int border_width) { - char *font_name; - char *modevar; - char *tmp; - grub_video_color_t color; - int width; - int height; - grub_err_t err; + /* Clean up any prior instance. */ + destroy_window (); - /* Select the font to use. */ - font_name = grub_env_get ("gfxterm_font"); - if (! font_name) - font_name = ""; /* Allow fallback to any font. */ + /* Set the render target. */ + render_target = target; - /* Parse gfxmode environment variable if set. */ - modevar = grub_env_get ("gfxmode"); - if (! modevar || *modevar == 0) - err = grub_video_set_mode (DEFAULT_VIDEO_MODE, video_hook); - else + /* Create virtual screen. */ + if (grub_virtual_screen_setup (border_width, border_width, + width - 2 * border_width, + height - 2 * border_width, + font_name) + != GRUB_ERR_NONE) { - tmp = grub_malloc (grub_strlen (modevar) - + sizeof (DEFAULT_VIDEO_MODE) + 1); - grub_sprintf (tmp, "%s;" DEFAULT_VIDEO_MODE, modevar); - err = grub_video_set_mode (tmp, video_hook); - grub_free (tmp); + return grub_errno; } - if (err) - return err; + /* Set window bounds. */ + window.x = x; + window.y = y; + window.width = width; + window.height = height; + window.double_repaint = double_repaint; + + dirty_region_reset (); + grub_gfxterm_schedule_repaint (); + + return grub_errno; +} + +grub_err_t +grub_gfxterm_fullscreen (void) +{ + const char *font_name; + struct grub_video_mode_info mode_info; + grub_video_color_t color; + grub_err_t err; + int double_redraw; err = grub_video_get_info (&mode_info); /* Figure out what mode we ended up. */ if (err) return err; + grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); + + double_redraw = mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED + && !(mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP); + /* Make sure screen is black. */ color = grub_video_map_rgb (0, 0, 0); grub_video_fill_rect (color, 0, 0, mode_info.width, mode_info.height); + if (double_redraw) + { + grub_video_swap_buffers (); + grub_video_fill_rect (color, 0, 0, mode_info.width, mode_info.height); + } bitmap = 0; - /* Leave borders for virtual screen. */ - width = mode_info.width - (2 * DEFAULT_BORDER_WIDTH); - height = mode_info.height - (2 * DEFAULT_BORDER_WIDTH); + /* Select the font to use. */ + font_name = grub_env_get ("gfxterm_font"); + if (! font_name) + font_name = ""; /* Allow fallback to any font. */ - /* Create virtual screen. */ - if (grub_virtual_screen_setup (DEFAULT_BORDER_WIDTH, DEFAULT_BORDER_WIDTH, - width, height, font_name) != GRUB_ERR_NONE) - { - grub_video_restore (); - return grub_errno; - } + grub_gfxterm_decorator_hook = NULL; - /* Mark whole screen as dirty. */ - dirty_region_reset (); - dirty_region_add (0, 0, mode_info.width, mode_info.height); - - return (grub_errno = GRUB_ERR_NONE); + return grub_gfxterm_set_window (GRUB_VIDEO_RENDER_TARGET_DISPLAY, + 0, 0, mode_info.width, mode_info.height, + double_redraw, + font_name, DEFAULT_BORDER_WIDTH); } static grub_err_t -grub_gfxterm_fini (void) +grub_gfxterm_init (void) +{ + char *tmp; + grub_err_t err; + const char *modevar; + + /* Parse gfxmode environment variable if set. */ + modevar = grub_env_get ("gfxmode"); + if (! modevar || *modevar == 0) + err = grub_video_set_mode (DEFAULT_VIDEO_MODE, + GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0); + else + { + tmp = grub_xasprintf ("%s;" DEFAULT_VIDEO_MODE, modevar); + if (!tmp) + return grub_errno; + err = grub_video_set_mode (tmp, GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0); + grub_free (tmp); + } + + if (err) + return err; + + err = grub_gfxterm_fullscreen (); + if (err) + grub_video_restore (); + + return err; +} + +static void +destroy_window (void) { if (bitmap) { @@ -320,10 +393,18 @@ grub_gfxterm_fini (void) bitmap = 0; } + repaint_callback = 0; grub_virtual_screen_free (); +} +static grub_err_t +grub_gfxterm_fini (void) +{ + destroy_window (); grub_video_restore (); + /* Clear error state. */ + grub_errno = GRUB_ERR_NONE; return GRUB_ERR_NONE; } @@ -332,9 +413,15 @@ redraw_screen_rect (unsigned int x, unsigned int y, unsigned int width, unsigned int height) { grub_video_color_t color; + grub_video_rect_t saved_view; - grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); - + 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); if (bitmap) { @@ -345,7 +432,7 @@ redraw_screen_rect (unsigned int x, unsigned int y, /* If bitmap is smaller than requested blit area, use background color. */ - color = virtual_screen.bg_color; + color = virtual_screen.bg_color_display; /* Fill right side of the bitmap if needed. */ if ((x + width >= bitmap_width) && (y < bitmap_height)) @@ -392,7 +479,7 @@ redraw_screen_rect (unsigned int x, unsigned int y, else { /* Render background layer. */ - color = virtual_screen.bg_color; + color = virtual_screen.bg_color_display; grub_video_fill_rect (color, x, y, width, height); /* Render text layer as replaced (to get texts background color). */ @@ -401,6 +488,14 @@ redraw_screen_rect (unsigned int x, unsigned int y, y - virtual_screen.offset_y, width, height); } + + /* 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); + + if (repaint_callback) + repaint_callback (x, y, width, height); } static void @@ -410,6 +505,7 @@ dirty_region_reset (void) dirty_region.top_left_y = -1; dirty_region.bottom_right_x = -1; dirty_region.bottom_right_y = -1; + repaint_was_schedulded = 0; } static int @@ -429,6 +525,16 @@ dirty_region_add (int x, int y, unsigned int width, unsigned int height) if ((width == 0) || (height == 0)) return; + if (repaint_schedulded) + { + x = virtual_screen.offset_x; + y = virtual_screen.offset_y; + width = virtual_screen.width; + height = virtual_screen.height; + repaint_schedulded = 0; + repaint_was_schedulded = 1; + } + if (dirty_region_is_empty ()) { dirty_region.top_left_x = x; @@ -475,13 +581,14 @@ dirty_region_redraw (void) width = dirty_region.bottom_right_x - x + 1; height = dirty_region.bottom_right_y - y + 1; - redraw_screen_rect (x, y, width, height); + if (repaint_was_schedulded && grub_gfxterm_decorator_hook) + grub_gfxterm_decorator_hook (); - dirty_region_reset (); + redraw_screen_rect (x, y, width, height); } -static void -write_char (void) +static inline void +paint_char (unsigned cx, unsigned cy) { struct grub_colored_char *p; struct grub_font_glyph *glyph; @@ -493,10 +600,12 @@ write_char (void) unsigned int height; unsigned int width; + if (cy + virtual_screen.total_scroll >= virtual_screen.rows) + return; + /* Find out active character. */ p = (virtual_screen.text_buffer - + virtual_screen.cursor_x - + (virtual_screen.cursor_y * virtual_screen.columns)); + + cx + (cy * virtual_screen.columns)); p -= p->index; @@ -510,68 +619,163 @@ write_char (void) color = p->fg_color; bgcolor = p->bg_color; - x = virtual_screen.cursor_x * virtual_screen.normal_char_width; - y = virtual_screen.cursor_y * virtual_screen.normal_char_height; + x = cx * virtual_screen.normal_char_width; + y = (cy + virtual_screen.total_scroll) * virtual_screen.normal_char_height; /* Render glyph to text layer. */ grub_video_set_active_render_target (text_layer); grub_video_fill_rect (bgcolor, x, y, width, height); grub_font_draw_glyph (glyph, color, x, y + ascent); - grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); + grub_video_set_active_render_target (render_target); /* Mark character to be drawn. */ dirty_region_add (virtual_screen.offset_x + x, virtual_screen.offset_y + y, width, height); } -static void +static inline void +write_char (void) +{ + paint_char (virtual_screen.cursor_x, virtual_screen.cursor_y); +} + +static inline void draw_cursor (int show) { + unsigned int x; + unsigned int y; + unsigned int width; + unsigned int height; + grub_video_color_t color; + write_char (); - if (show) + if (!show) + return; + + if (virtual_screen.cursor_y + virtual_screen.total_scroll + >= virtual_screen.rows) + return; + + /* Determine cursor properties and position on text layer. */ + x = virtual_screen.cursor_x * virtual_screen.normal_char_width; + width = virtual_screen.normal_char_width; + color = virtual_screen.fg_color; + y = ((virtual_screen.cursor_y + virtual_screen.total_scroll) + * virtual_screen.normal_char_height + + grub_font_get_ascent (virtual_screen.font)); + height = 2; + + /* Render cursor to text layer. */ + grub_video_set_active_render_target (text_layer); + grub_video_fill_rect (color, x, y, width, height); + grub_video_set_active_render_target (render_target); + + /* Mark cursor to be redrawn. */ + dirty_region_add (virtual_screen.offset_x + x, + virtual_screen.offset_y + y, + width, height); +} + +static void +real_scroll (void) +{ + unsigned int i, j, was_scroll; + grub_video_color_t color; + + if (!virtual_screen.total_scroll) + return; + + /* If we have bitmap, re-draw screen, otherwise scroll physical screen too. */ + if (bitmap) { - unsigned int x; - unsigned int y; - unsigned int width; - unsigned int height; - grub_video_color_t color; - - /* Determine cursor properties and position on text layer. */ - x = virtual_screen.cursor_x * virtual_screen.normal_char_width; - width = virtual_screen.normal_char_width; - color = virtual_screen.fg_color; - y = (virtual_screen.cursor_y * virtual_screen.normal_char_height - + grub_font_get_ascent (virtual_screen.font)); - height = 2; - - /* Render cursor to text layer. */ + /* Scroll physical screen. */ grub_video_set_active_render_target (text_layer); - grub_video_fill_rect (color, x, y, width, height); - grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); + color = virtual_screen.bg_color; + grub_video_scroll (color, 0, -virtual_screen.normal_char_height + * virtual_screen.total_scroll); - /* Mark cursor to be redrawn. */ - dirty_region_add (virtual_screen.offset_x + x, - virtual_screen.offset_y + y, - width, height); + /* Mark virtual screen to be redrawn. */ + dirty_region_add_virtualscreen (); } + else + { + grub_video_rect_t saved_view; + + /* Remove cursor. */ + 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; + + color = virtual_screen.bg_color; + + while (i--) + { + /* Clear new border area. */ + grub_video_fill_rect (color, + virtual_screen.offset_x, + virtual_screen.offset_y, + virtual_screen.width, + virtual_screen.normal_char_height + * virtual_screen.total_scroll); + + grub_video_set_active_render_target (render_target); + dirty_region_redraw (); + + /* Scroll physical screen. */ + grub_video_scroll (color, 0, -virtual_screen.normal_char_height + * virtual_screen.total_scroll); + + if (i) + grub_video_swap_buffers (); + } + dirty_region_reset (); + + /* Scroll physical screen. */ + grub_video_set_active_render_target (text_layer); + color = virtual_screen.bg_color; + 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); + + } + + was_scroll = virtual_screen.total_scroll; + virtual_screen.total_scroll = 0; + + if (was_scroll > virtual_screen.rows) + was_scroll = virtual_screen.rows; + + /* Draw shadow part. */ + for (i = virtual_screen.rows - was_scroll; + i < virtual_screen.rows; i++) + for (j = 0; j < virtual_screen.columns; j++) + paint_char (j, i); + + /* Draw cursor if visible. */ + if (virtual_screen.cursor_state) + draw_cursor (1); + + if (repaint_callback) + repaint_callback (window.x, window.y, window.width, window.height); } static void scroll_up (void) { unsigned int i; - grub_video_color_t color; - - /* If we don't have background bitmap, remove cursor. */ - if (!bitmap) - { - /* Remove cursor. */ - draw_cursor (0); - - /* Redraw only changed regions. */ - dirty_region_redraw (); - } /* Scroll text buffer with one line to up. */ grub_memmove (virtual_screen.text_buffer, @@ -586,32 +790,7 @@ scroll_up (void) i++) clear_char (&(virtual_screen.text_buffer[i])); - /* Scroll physical screen. */ - grub_video_set_active_render_target (text_layer); - color = virtual_screen.bg_color; - grub_video_scroll (color, 0, -virtual_screen.normal_char_height); - grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); - - /* If we have bitmap, re-draw screen, otherwise scroll physical screen too. */ - if (bitmap) - { - /* Mark virtual screen to be redrawn. */ - dirty_region_add_virtualscreen (); - } - else - { - /* Clear new border area. */ - grub_video_fill_rect (color, - virtual_screen.offset_x, virtual_screen.offset_y, - virtual_screen.width, virtual_screen.normal_char_height); - - /* Scroll physical screen. */ - grub_video_scroll (color, 0, -virtual_screen.normal_char_height); - - /* Draw cursor if visible. */ - if (virtual_screen.cursor_state) - draw_cursor (1); - } + virtual_screen.total_scroll++; } static void @@ -814,11 +993,14 @@ grub_gfxterm_cls (void) /* Clear text layer. */ grub_video_set_active_render_target (text_layer); color = virtual_screen.bg_color; - grub_video_fill_rect (color, 0, 0, mode_info.width, mode_info.height); - grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); + grub_video_fill_rect (color, 0, 0, + virtual_screen.width, virtual_screen.height); + grub_video_set_active_render_target (render_target); /* Mark virtual screen to be redrawn. */ dirty_region_add_virtualscreen (); + + grub_gfxterm_refresh (); } static void @@ -879,15 +1061,41 @@ grub_gfxterm_setcursor (int on) static void grub_gfxterm_refresh (void) { + real_scroll (); + /* Redraw only changed regions. */ dirty_region_redraw (); + + grub_video_swap_buffers (); + + if (window.double_repaint) + dirty_region_redraw (); + dirty_region_reset (); } +void +grub_gfxterm_set_repaint_callback (grub_gfxterm_repaint_callback_t func) +{ + repaint_callback = func; +} + +/* Option array indices. */ +#define BACKGROUND_CMD_ARGINDEX_MODE 0 + +static const struct grub_arg_option background_image_cmd_options[] = + { + {"mode", 'm', 0, "Background image mode.", "stretch|normal", + ARG_TYPE_STRING}, + {0, 0, 0, 0, 0, 0} + }; + static grub_err_t -grub_gfxterm_background_image_cmd (grub_command_t cmd __attribute__ ((unused)), +grub_gfxterm_background_image_cmd (grub_extcmd_t cmd __attribute__ ((unused)), int argc, char **args) { + struct grub_arg_list *state = cmd->state; + /* Check that we have video adapter active. */ if (grub_video_get_info(NULL) != GRUB_ERR_NONE) return grub_errno; @@ -899,8 +1107,7 @@ grub_gfxterm_background_image_cmd (grub_command_t cmd __attribute__ ((unused)), bitmap = 0; /* Mark whole screen as dirty. */ - dirty_region_reset (); - dirty_region_add (0, 0, mode_info.width, mode_info.height); + dirty_region_add (0, 0, window.width, window.height); } /* If filename was provided, try to load that. */ @@ -911,16 +1118,38 @@ grub_gfxterm_background_image_cmd (grub_command_t cmd __attribute__ ((unused)), if (grub_errno != GRUB_ERR_NONE) return grub_errno; + /* Determine if the bitmap should be scaled to fit the screen. */ + if (!state[BACKGROUND_CMD_ARGINDEX_MODE].set + || grub_strcmp (state[BACKGROUND_CMD_ARGINDEX_MODE].arg, + "stretch") == 0) + { + if (window.width != grub_video_bitmap_get_width (bitmap) + || window.height != grub_video_bitmap_get_height (bitmap)) + { + struct grub_video_bitmap *scaled_bitmap; + grub_video_bitmap_create_scaled (&scaled_bitmap, + window.width, + window.height, + bitmap, + GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST); + if (grub_errno == GRUB_ERR_NONE) + { + /* Replace the original bitmap with the scaled one. */ + grub_video_bitmap_destroy (bitmap); + bitmap = scaled_bitmap; + } + } + } + /* If bitmap was loaded correctly, display it. */ if (bitmap) { /* Determine bitmap dimensions. */ bitmap_width = grub_video_bitmap_get_width (bitmap); - bitmap_height = grub_video_bitmap_get_width (bitmap); + bitmap_height = grub_video_bitmap_get_height (bitmap); /* Mark whole screen as dirty. */ - dirty_region_reset (); - dirty_region_add (0, 0, mode_info.width, mode_info.height); + dirty_region_add (0, 0, window.width, window.height); } } @@ -949,18 +1178,22 @@ static struct grub_term_output grub_video_term = .next = 0 }; -static grub_command_t cmd; +static grub_extcmd_t background_image_cmd_handle; GRUB_MOD_INIT(term_gfxterm) { grub_term_register_output ("gfxterm", &grub_video_term); - cmd = grub_register_command ("background_image", - grub_gfxterm_background_image_cmd, - 0, "Load background image for active terminal."); + background_image_cmd_handle = + grub_register_extcmd ("background_image", + grub_gfxterm_background_image_cmd, + GRUB_COMMAND_FLAG_BOTH, + "[-m (stretch|normal)] FILE", + "Load background image for active terminal.", + background_image_cmd_options); } GRUB_MOD_FINI(term_gfxterm) { - grub_unregister_command (cmd); + grub_unregister_extcmd (background_image_cmd_handle); grub_term_unregister_output (&grub_video_term); } diff --git a/term/ieee1275/ofconsole.c b/term/ieee1275/ofconsole.c index a9834e23e..c0f895a15 100644 --- a/term/ieee1275/ofconsole.c +++ b/term/ieee1275/ofconsole.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -77,7 +78,52 @@ grub_ofconsole_writeesc (const char *str) static void grub_ofconsole_putchar (grub_uint32_t c) { - char chr = c; + char chr; + + if (c > 0x7F) + { + /* Better than nothing. */ + switch (c) + { + case GRUB_TERM_DISP_LEFT: + c = '<'; + break; + + case GRUB_TERM_DISP_UP: + c = '^'; + break; + + case GRUB_TERM_DISP_RIGHT: + c = '>'; + break; + + case GRUB_TERM_DISP_DOWN: + c = 'v'; + break; + + case GRUB_TERM_DISP_HLINE: + c = '-'; + break; + + case GRUB_TERM_DISP_VLINE: + c = '|'; + break; + + case GRUB_TERM_DISP_UL: + case GRUB_TERM_DISP_UR: + case GRUB_TERM_DISP_LL: + case GRUB_TERM_DISP_LR: + c = '+'; + break; + + default: + c = '?'; + break; + } + } + + chr = c; + if (c == '\n') { grub_curr_y++; @@ -109,7 +155,7 @@ grub_ofconsole_getcharwidth (grub_uint32_t c __attribute__((unused))) static void grub_ofconsole_setcolorstate (grub_term_color_state state) { - char setcol[20]; + char setcol[256]; int fg; int bg; @@ -128,7 +174,7 @@ grub_ofconsole_setcolorstate (grub_term_color_state state) return; } - grub_sprintf (setcol, "\e[3%dm\e[4%dm", fg, bg); + grub_snprintf (setcol, sizeof (setcol), "\e[3%dm\e[4%dm", fg, bg); grub_ofconsole_writeesc (setcol); } @@ -156,42 +202,81 @@ grub_ofconsole_readkey (int *key) grub_ieee1275_read (stdin_ihandle, &c, 1, &actual); - if (actual > 0 && c == '\e') - { - grub_ieee1275_read (stdin_ihandle, &c, 1, &actual); - if (actual <= 0) + if (actual > 0) + switch(c) + { + case 0x7f: + /* Backspace: Ctrl-h. */ + c = '\b'; + break; + case '\e': { - *key = '\e'; - return 1; + grub_uint64_t start; + grub_ieee1275_read (stdin_ihandle, &c, 1, &actual); + + /* On 9600 we have to wait up to 12 milliseconds. */ + start = grub_get_time_ms (); + while (actual <= 0 && grub_get_time_ms () - start < 12) + grub_ieee1275_read (stdin_ihandle, &c, 1, &actual); + + if (actual <= 0) + { + *key = '\e'; + return 1; + } + + if (c != '[') + return 0; + + grub_ieee1275_read (stdin_ihandle, &c, 1, &actual); + + /* On 9600 we have to wait up to 12 milliseconds. */ + start = grub_get_time_ms (); + while (actual <= 0 && grub_get_time_ms () - start < 12) + grub_ieee1275_read (stdin_ihandle, &c, 1, &actual); + if (actual <= 0) + return 0; + + switch (c) + { + case 'A': + /* Up: Ctrl-p. */ + c = GRUB_TERM_UP; + break; + case 'B': + /* Down: Ctrl-n. */ + c = GRUB_TERM_DOWN; + break; + case 'C': + /* Right: Ctrl-f. */ + c = GRUB_TERM_RIGHT; + break; + case 'D': + /* Left: Ctrl-b. */ + c = GRUB_TERM_LEFT; + break; + case '3': + { + grub_ieee1275_read (stdin_ihandle, &c, 1, &actual); + /* On 9600 we have to wait up to 12 milliseconds. */ + start = grub_get_time_ms (); + while (actual <= 0 && grub_get_time_ms () - start < 12) + grub_ieee1275_read (stdin_ihandle, &c, 1, &actual); + + if (actual <= 0) + return 0; + + /* Delete: Ctrl-d. */ + if (c == '~') + c = GRUB_TERM_DC; + else + return 0; + break; + } + break; + } } - - if (c != 91) - return 0; - - grub_ieee1275_read (stdin_ihandle, &c, 1, &actual); - if (actual <= 0) - return 0; - - switch (c) - { - case 65: - /* Up: Ctrl-p. */ - c = 16; - break; - case 66: - /* Down: Ctrl-n. */ - c = 14; - break; - case 67: - /* Right: Ctrl-f. */ - c = 6; - break; - case 68: - /* Left: Ctrl-b. */ - c = 2; - break; - } - } + } *key = c; return actual > 0; @@ -243,37 +328,28 @@ static void grub_ofconsole_dimensions (void) { grub_ieee1275_ihandle_t options; - char *val; grub_ssize_t lval; if (! grub_ieee1275_finddevice ("/options", &options) && options != (grub_ieee1275_ihandle_t) -1) { if (! grub_ieee1275_get_property_length (options, "screen-#columns", - &lval) && lval != -1) + &lval) + && lval >= 0 && lval < 1024) { - val = grub_malloc (lval); - if (val) - { - if (! grub_ieee1275_get_property (options, "screen-#columns", - val, lval, 0)) - grub_ofconsole_width = (grub_uint8_t) grub_strtoul (val, 0, 10); + char val[lval]; - grub_free (val); - } + if (! grub_ieee1275_get_property (options, "screen-#columns", + val, lval, 0)) + grub_ofconsole_width = (grub_uint8_t) grub_strtoul (val, 0, 10); } - if (! grub_ieee1275_get_property_length (options, "screen-#rows", - &lval) && lval != -1) + if (! grub_ieee1275_get_property_length (options, "screen-#rows", &lval) + && lval >= 0 && lval < 1024) { - val = grub_malloc (lval); - if (val) - { - if (! grub_ieee1275_get_property (options, "screen-#rows", - val, lval, 0)) - grub_ofconsole_height = (grub_uint8_t) grub_strtoul (val, 0, 10); - - grub_free (val); - } + char val[lval]; + if (! grub_ieee1275_get_property (options, "screen-#rows", + val, lval, 0)) + grub_ofconsole_height = (grub_uint8_t) grub_strtoul (val, 0, 10); } } @@ -293,14 +369,13 @@ grub_ofconsole_getwh (void) static void grub_ofconsole_gotoxy (grub_uint8_t x, grub_uint8_t y) { - char s[11]; /* 5 + 3 + 3. */ - if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_ANSI)) { + char s[256]; grub_curr_x = x; grub_curr_y = y; - grub_sprintf (s, "\e[%d;%dH", y + 1, x + 1); + grub_snprintf (s, sizeof (s), "\e[%d;%dH", y + 1, x + 1); grub_ofconsole_writeesc (s); } else diff --git a/term/i386/pc/serial.c b/term/serial.c similarity index 94% rename from term/i386/pc/serial.c rename to term/serial.c index 8d09f6211..05497ce40 100644 --- a/term/i386/pc/serial.c +++ b/term/serial.c @@ -17,8 +17,7 @@ */ #include -#include -#include +#include #include #include #include @@ -29,9 +28,8 @@ #include #define TEXT_WIDTH 80 -#define TEXT_HEIGHT 25 +#define TEXT_HEIGHT 24 -static struct grub_term_output grub_serial_term_output; static unsigned int xpos, ypos; static unsigned int keep_track = 1; static unsigned int registered = 0; @@ -40,6 +38,8 @@ static unsigned int registered = 0; static char input_buf[8]; static unsigned int npending = 0; +static struct grub_term_output grub_serial_term_output; + /* Argument options. */ static const struct grub_arg_option options[] = { @@ -55,7 +55,7 @@ static const struct grub_arg_option options[] = /* Serial port settings. */ struct serial_port { - unsigned short port; + grub_port_t port; unsigned short divisor; unsigned short word_len; unsigned int parity; @@ -69,12 +69,13 @@ static struct serial_port serial_settings; static const unsigned short *serial_hw_io_addr = (const unsigned short *) GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR; #define GRUB_SERIAL_PORT_NUM 4 #else -static const unsigned short serial_hw_io_addr[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; +#include +static const grub_port_t serial_hw_io_addr[] = GRUB_MACHINE_SERIAL_PORTS; #define GRUB_SERIAL_PORT_NUM (ARRAY_SIZE(serial_hw_io_addr)) #endif /* Return the port number for the UNITth serial device. */ -static inline unsigned short +static inline grub_port_t serial_hw_get_port (const unsigned int unit) { if (unit < GRUB_SERIAL_PORT_NUM) @@ -150,7 +151,7 @@ serial_translate_key_sequence (void) if (input_buf[0] != '\e' || input_buf[1] != '[') return; - for (i = 0; ARRAY_SIZE (three_code_table); i++) + for (i = 0; i < ARRAY_SIZE (three_code_table); i++) if (three_code_table[i].key == input_buf[2]) { input_buf[0] = three_code_table[i].ascii; @@ -231,7 +232,12 @@ serial_get_divisor (unsigned int speed) /* Set the baud rate. */ for (i = 0; i < sizeof (divisor_tab) / sizeof (divisor_tab[0]); i++) if (divisor_tab[i].speed == speed) + /* UART in Yeeloong runs twice the usual rate. */ +#ifdef GRUB_MACHINE_MIPS_YEELOONG + return 2 * divisor_tab[i].div; +#else return divisor_tab[i].div; +#endif return 0; } @@ -255,6 +261,9 @@ grub_serial_getkey (void) ; c = input_buf[0]; + if (c == 0x7f) + c = GRUB_TERM_BACKSPACE; + grub_memmove (input_buf, input_buf + 1, --npending); return c; @@ -288,11 +297,14 @@ serial_hw_init (void) | serial_settings.stop_bits); grub_outb (status, serial_settings.port + UART_LCR); + /* In Yeeloong serial port has only 3 wires. */ +#ifndef GRUB_MACHINE_MIPS_YEELOONG /* Enable the FIFO. */ grub_outb (UART_ENABLE_FIFO, serial_settings.port + UART_FCR); /* Turn on DTR, RTS, and OUT2. */ grub_outb (UART_ENABLE_MODEM, serial_settings.port + UART_MCR); +#endif /* Drain the input buffer. */ while (grub_serial_checkkey () != -1) @@ -365,7 +377,7 @@ grub_serial_putchar (grub_uint32_t c) break; case '\n': - if (ypos < TEXT_HEIGHT) + if (ypos < TEXT_HEIGHT - 1) ypos++; break; @@ -504,7 +516,7 @@ grub_cmd_serial (grub_extcmd_t cmd, } if (state[1].set) - serial_settings.port = (unsigned short) grub_strtoul (state[1].arg, 0, 0); + serial_settings.port = (grub_port_t) grub_strtoul (state[1].arg, 0, 0); if (state[2].set) { @@ -604,12 +616,16 @@ GRUB_MOD_INIT(serial) { cmd = grub_register_extcmd ("serial", grub_cmd_serial, GRUB_COMMAND_FLAG_BOTH, - N_("[OPTIONS...]"), - N_("Configure serial port."), options); + "serial [OPTIONS...]", + "Configure serial port.", options); /* Set default settings. */ serial_settings.port = serial_hw_get_port (0); +#ifdef GRUB_MACHINE_MIPS_YEELOONG + serial_settings.divisor = serial_get_divisor (115200); +#else serial_settings.divisor = serial_get_divisor (9600); +#endif serial_settings.word_len = UART_8BITS_WORD; serial_settings.parity = UART_NO_PARITY; serial_settings.stop_bits = UART_1_STOP_BIT; diff --git a/term/tparm.c b/term/tparm.c index fa25bd32c..adf0b3a7c 100644 --- a/term/tparm.c +++ b/term/tparm.c @@ -167,7 +167,7 @@ save_text(const char *fmt, const char *s, int len) get_space(s_len + 1); - (void) grub_sprintf(out_buff + out_used, fmt, s); + (void) grub_snprintf(out_buff + out_used, s_len + 1, fmt, s); out_used += grub_strlen(out_buff + out_used); } @@ -179,7 +179,7 @@ save_number(const char *fmt, int number, int len) get_space((unsigned) len + 1); - (void) grub_sprintf(out_buff + out_used, fmt, number); + (void) grub_snprintf(out_buff + out_used, len + 1, fmt, number); out_used += grub_strlen(out_buff + out_used); } diff --git a/tests/example_functional_test.c b/tests/example_functional_test.c index 475d1c7f0..6802d2d53 100644 --- a/tests/example_functional_test.c +++ b/tests/example_functional_test.c @@ -1,3 +1,21 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + /* All tests need to include test.h for GRUB testing framework. */ #include @@ -10,7 +28,7 @@ example_test (void) /* Check if 1st argument is true and report with custom error message. */ grub_test_assert (2 == 2, "2 equal 2 expected"); - grub_test_assert (2 == 3, "2 is not equal to %d", 3); + grub_test_assert (2 != 3, "2 matches %d", 3); } /* Register example_test method as a functional test. */ diff --git a/tests/example_unit_test.c b/tests/example_unit_test.c index e2fad06ff..d721a9d0a 100644 --- a/tests/example_unit_test.c +++ b/tests/example_unit_test.c @@ -1,3 +1,21 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + /* Unit tests are normal programs, so they can include C library. */ #include @@ -13,7 +31,7 @@ example_test (void) /* Check if 1st argument is true and report with custom error message. */ grub_test_assert (2 == 2, "2 equal 2 expected"); - grub_test_assert (2 == 3, "2 is not equal to %d", 3); + grub_test_assert (2 != 3, "2 matches %d", 3); } /* Register example_test method as a unit test. */ diff --git a/tests/lib/functional_test.c b/tests/lib/functional_test.c index 8ad034503..8ff08cf8a 100644 --- a/tests/lib/functional_test.c +++ b/tests/lib/functional_test.c @@ -1,3 +1,21 @@ +/* + * 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 diff --git a/tests/lib/test.c b/tests/lib/test.c index aba2f4415..b5c054370 100644 --- a/tests/lib/test.c +++ b/tests/lib/test.c @@ -1,3 +1,21 @@ +/* + * 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 @@ -29,19 +47,16 @@ add_failure (const char *file, const char *funp, grub_uint32_t line, const char *fmt, va_list args) { - char buf[1024]; grub_test_failure_t failure; failure = (grub_test_failure_t) grub_malloc (sizeof (*failure)); if (!failure) return; - grub_vsprintf (buf, fmt, args); - failure->file = grub_strdup (file ? : ""); failure->funp = grub_strdup (funp ? : ""); failure->line = line; - failure->message = grub_strdup (buf); + failure->message = grub_xvasprintf (fmt, args); grub_list_push (GRUB_AS_LIST_P (&failure_list), GRUB_AS_LIST (failure)); } diff --git a/tests/lib/unit_test.c b/tests/lib/unit_test.c index 2ca011433..e461150de 100644 --- a/tests/lib/unit_test.c +++ b/tests/lib/unit_test.c @@ -1,3 +1,21 @@ +/* + * 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 diff --git a/util/bin2h.c b/util/bin2h.c new file mode 100644 index 000000000..e81ede8c6 --- /dev/null +++ b/util/bin2h.c @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2008,2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include + +#define _GNU_SOURCE 1 +#include + +#include "progname.h" + +static struct option options[] = + { + {"help", no_argument, 0, 'h' }, + {"version", no_argument, 0, 'V' }, + {0, 0, 0, 0 } + }; + +static void +usage (int status) +{ + if (status) + fprintf (stderr, + "Try ``%s --help'' for more information.\n", program_name); + else + printf ("\ +Usage: %s [OPTIONS] SYMBOL-NAME\n\ +\n\ +Convert a binary file to a C header.\n\ +\n\ + -h, --help display this message and exit\n\ + -V, --version print version information and exit\n\ +\n\ +Report bugs to <%s>.\n\ +", program_name, PACKAGE_BUGREPORT); + + exit (status); +} + +int +main (int argc, char *argv[]) +{ + int b, i; + char *sym; + + set_program_name (argv[0]); + + /* Check for options. */ + while (1) + { + int c = getopt_long (argc, argv, "snm:r:hVv", options, 0); + + if (c == -1) + break; + else + switch (c) + { + case 'h': + usage (0); + break; + + case 'V': + printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); + return 0; + + default: + usage (1); + break; + } + } + + if (optind >= argc) + usage (1); + + if (optind + 1 != argc) + usage (1); + + sym = argv[optind]; + + b = getchar (); + if (b == EOF) + goto abort; + + printf ("/* THIS CHUNK OF BYTES IS AUTOMATICALY GENERATED */\n" + "unsigned char %s[] =\n{\n", sym); + + while (1) + { + printf ("0x%02x", b); + + b = getchar (); + if (b == EOF) + goto end; + + for (i = 0; i < 16 - 1; i++) + { + printf (", 0x%02x", b); + + b = getchar (); + if (b == EOF) + goto end; + } + + printf (",\n"); + } + +end: + printf ("\n};\n"); + +abort: + exit (0); +} diff --git a/util/elf/grub-mkimage.c b/util/elf/grub-mkimage.c index 6ba8b1ae2..04a19bc4e 100644 --- a/util/elf/grub-mkimage.c +++ b/util/elf/grub-mkimage.c @@ -100,7 +100,7 @@ load_note (Elf32_Phdr *phdr, FILE *out) void load_modules (grub_addr_t modbase, Elf32_Phdr *phdr, const char *dir, - char *mods[], FILE *out, char *memdisk_path) + char *mods[], FILE *out, char *memdisk_path, char *config_path) { char *module_img; struct grub_util_path_list *path_list; @@ -109,6 +109,7 @@ load_modules (grub_addr_t modbase, Elf32_Phdr *phdr, const char *dir, size_t offset; size_t total_module_size; size_t memdisk_size = 0; + size_t config_size = 0; path_list = grub_util_resolve_dependencies (dir, "moddep.lst", mods); @@ -122,6 +123,13 @@ load_modules (grub_addr_t modbase, Elf32_Phdr *phdr, const char *dir, total_module_size += memdisk_size + sizeof (struct grub_module_header); } + if (config_path) + { + config_size = ALIGN_UP(grub_util_get_image_size (config_path), 512); + grub_util_info ("the size of memory disk is 0x%x", config_size); + total_module_size += config_size + sizeof (struct grub_module_header); + } + for (p = path_list; p; p = p->next) { total_module_size += (grub_util_get_image_size (p->name) @@ -168,6 +176,19 @@ load_modules (grub_addr_t modbase, Elf32_Phdr *phdr, const char *dir, offset += memdisk_size; } + if (config_path) + { + struct grub_module_header *header; + + header = (struct grub_module_header *) (module_img + offset); + header->type = OBJ_TYPE_CONFIG; + header->size = grub_host_to_target32 (config_size + sizeof (*header)); + offset += sizeof (*header); + + grub_util_load_image (config_path, module_img + offset); + offset += config_size; + } + /* Write the module data to the new segment. */ grub_util_write_image_at (module_img, total_module_size, @@ -184,7 +205,7 @@ load_modules (grub_addr_t modbase, Elf32_Phdr *phdr, const char *dir, } void -add_segments (char *dir, char *prefix, FILE *out, int chrp, char *mods[], char *memdisk_path) +add_segments (char *dir, char *prefix, FILE *out, int chrp, char *mods[], char *memdisk_path, char *config_path) { Elf32_Ehdr ehdr; Elf32_Phdr *phdrs = NULL; @@ -273,7 +294,7 @@ add_segments (char *dir, char *prefix, FILE *out, int chrp, char *mods[], char * phdr->p_offset = grub_host_to_target32 (ALIGN_UP (grub_util_get_fp_size (out), GRUB_TARGET_SIZEOF_LONG)); - load_modules (modbase, phdr, dir, mods, out, memdisk_path); + load_modules (modbase, phdr, dir, mods, out, memdisk_path, config_path); } if (chrp) @@ -316,6 +337,7 @@ static struct option options[] = {"directory", required_argument, 0, 'd'}, {"prefix", required_argument, 0, 'p'}, {"memdisk", required_argument, 0, 'm'}, + {"config", required_argument, 0, 'c'}, {"output", required_argument, 0, 'o'}, {"help", no_argument, 0, 'h'}, {"note", no_argument, 0, 'n'}, @@ -328,7 +350,7 @@ static void usage (int status) { if (status) - fprintf (stderr, "Try ``%s --help'' for more information.\n", program_name); + fprintf (stderr, "Try `%s --help' for more information.\n", program_name); else printf ("\ Usage: %s -o FILE [OPTION]... [MODULES]\n\ @@ -338,6 +360,7 @@ Make a bootable image of GRUB.\n\ -d, --directory=DIR use images and modules under DIR [default=%s]\n\ -p, --prefix=DIR set grub_prefix directory\n\ -m, --memdisk=FILE embed FILE as a memdisk image\n\ + -c, --config=FILE embed FILE as boot config\n\ -o, --output=FILE output a generated image to FILE\n\ -h, --help display this message and exit\n\ -n, --note add NOTE segment for CHRP Open Firmware\n\ @@ -358,6 +381,7 @@ main (int argc, char *argv[]) char *dir = NULL; char *prefix = NULL; char *memdisk = NULL; + char *config = NULL; int chrp = 0; set_program_name (argv[0]); @@ -366,7 +390,7 @@ main (int argc, char *argv[]) while (1) { - int c = getopt_long (argc, argv, "d:p:m:o:hVvn", options, 0); + int c = getopt_long (argc, argv, "d:p:m:c:o:hVvn", options, 0); if (c == -1) break; @@ -392,6 +416,13 @@ main (int argc, char *argv[]) prefix = xstrdup ("(memdisk)/boot/grub"); break; + case 'c': + if (config) + free (config); + config = xstrdup (optarg); + + break; + case 'h': usage (0); break; @@ -422,7 +453,8 @@ main (int argc, char *argv[]) if (! fp) grub_util_error ("cannot open %s", output); - add_segments (dir ? : GRUB_LIBDIR, prefix, fp, chrp, argv + optind, memdisk); + add_segments (dir ? : GRUB_LIBDIR, prefix, fp, chrp, argv + optind, memdisk, + config); fclose (fp); diff --git a/util/getroot.c b/util/getroot.c index 22ad7e967..82393635c 100644 --- a/util/getroot.c +++ b/util/getroot.c @@ -115,14 +115,14 @@ grub_get_prefix (const char *dir) saved_cwd = xgetcwd (); if (chdir (dir) < 0) - grub_util_error ("Cannot change directory to `%s'", dir); + grub_util_error ("cannot change directory to `%s'", dir); abs_dir = xgetcwd (); strip_extra_slashes (abs_dir); prev_dir = xstrdup (abs_dir); if (stat (".", &prev_st) < 0) - grub_util_error ("Cannot stat `%s'", dir); + grub_util_error ("cannot stat `%s'", dir); if (! S_ISDIR (prev_st.st_mode)) grub_util_error ("`%s' is not a directory", dir); @@ -130,13 +130,13 @@ grub_get_prefix (const char *dir) while (1) { if (chdir ("..") < 0) - grub_util_error ("Cannot change directory to the parent"); + grub_util_error ("cannot change directory to the parent"); if (stat (".", &st) < 0) - grub_util_error ("Cannot stat current directory"); + grub_util_error ("cannot stat current directory"); if (! S_ISDIR (st.st_mode)) - grub_util_error ("Current directory is not a directory???"); + grub_util_error ("current directory is not a directory???"); if (prev_st.st_dev != st.st_dev || prev_st.st_ino == st.st_ino) break; @@ -153,7 +153,7 @@ grub_get_prefix (const char *dir) strip_extra_slashes (prefix); if (chdir (saved_cwd) < 0) - grub_util_error ("Cannot change directory to `%s'", dir); + grub_util_error ("cannot change directory to `%s'", dir); #ifdef __CYGWIN__ if (st.st_dev != (DEV_CYGDRIVE_MAJOR << 16)) @@ -236,7 +236,7 @@ find_root_device (const char *dir, dev_t dev) if (res) { if (chdir (saved_cwd) < 0) - grub_util_error ("Cannot restore the original directory"); + grub_util_error ("cannot restore the original directory"); free (saved_cwd); closedir (dp); @@ -279,7 +279,7 @@ find_root_device (const char *dir, dev_t dev) continue; if (chdir (saved_cwd) < 0) - grub_util_error ("Cannot restore the original directory"); + grub_util_error ("cannot restore the original directory"); free (saved_cwd); closedir (dp); @@ -288,7 +288,7 @@ find_root_device (const char *dir, dev_t dev) } if (chdir (saved_cwd) < 0) - grub_util_error ("Cannot restore the original directory"); + grub_util_error ("cannot restore the original directory"); free (saved_cwd); closedir (dp); @@ -445,7 +445,7 @@ grub_guess_root_device (const char *dir) struct stat st; if (stat (dir, &st) < 0) - grub_util_error ("Cannot stat `%s'", dir); + grub_util_error ("cannot stat `%s'", dir); #ifdef __CYGWIN__ /* Cygwin specific function. */ @@ -460,7 +460,8 @@ grub_guess_root_device (const char *dir) return os_dev; } -int + +static int grub_util_is_dmraid (const char *os_dev) { if (! strncmp (os_dev, "/dev/mapper/nvidia_", 19)) @@ -591,7 +592,7 @@ grub_util_get_grub_dev (const char *os_dev) free (p); } else - grub_util_error ("Unknown kind of RAID device `%s'", os_dev); + grub_util_error ("unknown kind of RAID device `%s'", os_dev); break; @@ -608,7 +609,7 @@ grub_util_check_block_device (const char *blk_dev) struct stat st; if (stat (blk_dev, &st) < 0) - grub_util_error ("Cannot stat `%s'", blk_dev); + grub_util_error ("cannot stat `%s'", blk_dev); if (S_ISBLK (st.st_mode)) return (blk_dev); @@ -622,7 +623,7 @@ grub_util_check_char_device (const char *blk_dev) struct stat st; if (stat (blk_dev, &st) < 0) - grub_util_error ("Cannot stat `%s'", blk_dev); + grub_util_error ("cannot stat `%s'", blk_dev); if (S_ISCHR (st.st_mode)) return (blk_dev); diff --git a/util/grub-editenv.c b/util/grub-editenv.c index 1fb1422df..f21042c97 100644 --- a/util/grub-editenv.c +++ b/util/grub-editenv.c @@ -69,10 +69,10 @@ static void usage (int status) { if (status) - fprintf (stderr, "Try ``grub-editenv --help'' for more information.\n"); + fprintf (stderr, "Try `%s --help' for more information.\n", program_name); else printf ("\ -Usage: grub-editenv [OPTIONS] [FILENAME] COMMAND\n\ +Usage: %s [OPTIONS] [FILENAME] COMMAND\n\ \n\ Tool to edit environment block.\n\ \nCommands:\n\ @@ -88,7 +88,7 @@ Tool to edit environment block.\n\ If not given explicitly, FILENAME defaults to %s.\n\ \n\ Report bugs to <%s>.\n", -DEFAULT_DIRECTORY "/" GRUB_ENVBLK_DEFCFG, PACKAGE_BUGREPORT); +program_name, DEFAULT_DIRECTORY "/" GRUB_ENVBLK_DEFCFG, PACKAGE_BUGREPORT); exit (status); } diff --git a/util/grub-emu.c b/util/grub-emu.c index 3f2acaaec..554556ae8 100644 --- a/util/grub-emu.c +++ b/util/grub-emu.c @@ -40,6 +40,7 @@ #include +#define ENABLE_RELOCATABLE 0 #include "progname.h" /* Used for going back to the main function. */ @@ -51,7 +52,7 @@ static char *prefix = NULL; grub_addr_t grub_arch_modules_addr (void) { - return NULL; + return 0; } grub_err_t @@ -129,10 +130,10 @@ usage (int status) { if (status) fprintf (stderr, - "Try ``grub-emu --help'' for more information.\n"); + "Try `%s --help' for more information.\n", program_name); else printf ( - "Usage: grub-emu [OPTION]...\n" + "Usage: %s [OPTION]...\n" "\n" "GRUB emulator.\n" "\n" @@ -144,7 +145,7 @@ usage (int status) " -h, --help display this message and exit\n" " -V, --version print version information and exit\n" "\n" - "Report bugs to <%s>.\n", DEFAULT_DEVICE_MAP, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT); + "Report bugs to <%s>.\n", program_name, DEFAULT_DEVICE_MAP, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT); return status; } @@ -220,14 +221,14 @@ main (int argc, char *argv[]) { char *device_name = grub_guess_root_device (dir); if (! device_name) - grub_util_error ("cannot find a device for %s.\n", dir); + grub_util_error ("cannot find a device for %s", dir); root_dev = grub_util_get_grub_dev (device_name); if (! root_dev) { grub_util_info ("guessing the root device failed, because of `%s'", grub_errmsg); - grub_util_error ("Cannot guess the root device. Specify the option ``--root-device''."); + grub_util_error ("cannot guess the root device. Specify the option `--root-device'"); } } diff --git a/util/grub-fstest.c b/util/grub-fstest.c index 586dda0f9..c03c43451 100644 --- a/util/grub-fstest.c +++ b/util/grub-fstest.c @@ -71,7 +71,7 @@ execute_command (char *name, int n, char **args) cmd = grub_command_find (name); if (! cmd) - grub_util_error ("Can\'t find command %s", name); + grub_util_error ("can\'t find command %s", name); return (cmd->func) (cmd, n, args); } @@ -100,9 +100,9 @@ read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len)) dev = grub_device_open (0); if ((! dev) || (! dev->disk)) - grub_util_error ("Can\'t open device."); + grub_util_error ("can\'t open device"); - grub_util_info ("total sectors : %lld.", + grub_util_info ("total sectors : %lld", (unsigned long long) dev->disk->total_sectors); if (! leng) @@ -115,7 +115,7 @@ read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len)) len = (leng > BUF_SIZE) ? BUF_SIZE : leng; if (grub_disk_read (dev->disk, 0, skip, len, buf)) - grub_util_error ("Disk read fails at offset %lld, length %d.", + grub_util_error ("disk read fails at offset %lld, length %d", skip, len); if (hook (skip, buf, len)) @@ -132,15 +132,15 @@ read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len)) file = grub_file_open (pathname); if (!file) { - grub_util_error ("cannot open file %s.", pathname); + grub_util_error ("cannot open file %s", pathname); return; } - grub_util_info ("file size : %lld.", (unsigned long long) file->size); + grub_util_info ("file size : %lld", (unsigned long long) file->size); if (skip > file->size) { - grub_util_error ("invalid skip value %lld.", (unsigned long long) skip); + grub_util_error ("invalid skip value %lld", (unsigned long long) skip); return; } @@ -158,7 +158,7 @@ read_file (char *pathname, int (*hook) (grub_off_t ofs, char *buf, int len)) sz = grub_file_read (file, buf, (len > BUF_SIZE) ? BUF_SIZE : len); if (sz < 0) { - grub_util_error ("read error at offset %llu.", ofs); + grub_util_error ("read error at offset %llu", ofs); break; } @@ -184,7 +184,7 @@ cmd_cp (char *src, char *dest) if ((int) fwrite (buf, 1, len, ff) != len) { - grub_util_error ("write error."); + grub_util_error ("write error"); return 1; } @@ -194,7 +194,7 @@ cmd_cp (char *src, char *dest) ff = fopen (dest, "wb"); if (ff == NULL) { - grub_util_error ("open error."); + grub_util_error ("open error"); return; } read_file (src, cp_hook); @@ -212,7 +212,7 @@ cmd_cmp (char *src, char *dest) { if ((int) fread (buf_1, 1, len, ff) != len) { - grub_util_error ("read error at offset %llu.", ofs); + grub_util_error ("read error at offset %llu", ofs); return 1; } @@ -223,7 +223,7 @@ cmd_cmp (char *src, char *dest) for (i = 0; i < len; i++, ofs++) if (buf_1[i] != buf[i]) { - grub_util_error ("compare fail at offset %llu.", ofs); + grub_util_error ("compare fail at offset %llu", ofs); return 1; } } @@ -233,12 +233,12 @@ cmd_cmp (char *src, char *dest) ff = fopen (dest, "rb"); if (ff == NULL) { - grub_util_error ("open error."); + grub_util_error ("open error"); return; } if ((skip) && (fseeko (ff, skip, SEEK_SET))) - grub_util_error ("seek error."); + grub_util_error ("seek error"); read_file (src, cmp_hook); fclose (ff); @@ -278,21 +278,31 @@ cmd_crc (char *pathname) static void fstest (char **images, int num_disks, int cmd, int n, char **args) { - char host_file[128]; - char loop_name[8]; - char *argv[3] = { "-p", loop_name, host_file}; + char *host_file; + char *loop_name; + char *argv[3]; int i; + argv[0] = "-p"; + for (i = 0; i < num_disks; i++) { - if (grub_strlen (images[i]) + 7 > sizeof (host_file)) - grub_util_error ("Pathname %s too long.", images[i]); + loop_name = grub_xasprintf ("loop%d", i); + if (!loop_name) + grub_util_error (grub_errmsg); - grub_sprintf (loop_name, "loop%d", i); - grub_sprintf (host_file, "(host)%s", images[i]); + host_file = grub_xasprintf ("(host)%s", images[i]); + if (!host_file) + grub_util_error (grub_errmsg); + + argv[1] = loop_name; + argv[2] = host_file; if (execute_command ("loopback", 3, argv)) - grub_util_error ("loopback command fails."); + grub_util_error ("loopback command fails"); + + grub_free (loop_name); + grub_free (host_file); } grub_lvm_fini (); @@ -328,8 +338,15 @@ fstest (char **images, int num_disks, int cmd, int n, char **args) for (i = 0; i < num_disks; i++) { - grub_sprintf (loop_name, "loop%d", i); + loop_name = grub_xasprintf ("loop%d", i); + if (!loop_name) + grub_util_error (grub_errmsg); + + argv[1] = loop_name; + execute_command ("loopback", 2, argv); + + grub_free (loop_name); } } @@ -349,7 +366,7 @@ static void usage (int status) { if (status) - fprintf (stderr, "Try ``%s --help'' for more information.\n", program_name); + fprintf (stderr, "Try `%s --help' for more information.\n", program_name); else printf ("\ Usage: %s [OPTION]... IMAGE_PATH COMMANDS\n\ diff --git a/util/grub-install.in b/util/grub-install.in index 4d814b085..bb323d706 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -30,10 +30,11 @@ PACKAGE_VERSION=@PACKAGE_VERSION@ target_cpu=@target_cpu@ platform=@platform@ host_os=@host_os@ +font=@datadir@/@PACKAGE_TARNAME@/ascii.pf2 pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}` grub_setup=${sbindir}/`echo grub-setup | sed ${transform}` -if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then +if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] || [ "${target_cpu}-${platform}" = "mips-yeeloong" ] ; then grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` else grub_mkimage=${bindir}/`echo grub-mkelfimage | sed ${transform}` @@ -83,6 +84,11 @@ if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then cat <&2 usage exit 1 @@ -297,15 +305,17 @@ prefix_drive= config_opt= if [ "x${devabstraction_module}" = "x" ] ; then - if echo "${install_device}" | grep -qx "(.*)" ; then - install_drive="${install_device}" - else - install_drive="`$grub_probe --target=drive --device ${install_device}`" + if [ x"${install_device}" != x ]; then + if echo "${install_device}" | grep -qx "(.*)" ; then + install_drive="${install_device}" + else + install_drive="`$grub_probe --target=drive --device ${install_device}`" + fi + install_drive="`echo ${install_drive} | sed -e s/,[0-9]*[a-z]*//g`" fi grub_drive="`$grub_probe --target=drive --device ${grub_device}`" # Strip partition number - install_drive="`echo ${install_drive} | sed -e s/,[0-9]*[a-z]*//g`" grub_drive="`echo ${grub_drive} | sed -e s/,[0-9]*[a-z]*//g`" if [ "$disk_module" = ata ] ; then # generic method (used on coreboot and ata mod) @@ -339,6 +349,8 @@ if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" # Now perform the installation. $grub_setup ${setup_verbose} ${setup_force} --directory=${grubdir} --device-map=${device_map} \ ${install_device} || exit 1 +elif [ "${target_cpu}-${platform}" = "mips-yeeloong" ] ; then + $grub_mkimage ${config_opt} -f ${font} -d ${pkglibdir} -O elf --output=/boot/grub.elf --prefix=${prefix_drive}${relative_grubdir} $modules || exit 1 else $grub_mkimage ${config_opt} -d ${pkglibdir} --output=/boot/multiboot.img --prefix=${prefix_drive}${relative_grubdir} $modules || exit 1 fi diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in index 49e52b313..daa110be7 100644 --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in @@ -220,7 +220,11 @@ export GRUB_DEFAULT \ GRUB_DISABLE_LINUX_UUID \ GRUB_DISABLE_LINUX_RECOVERY \ GRUB_GFXMODE \ - GRUB_DISABLE_OS_PROBER + GRUB_THEME \ + GRUB_GFXPAYLOAD_LINUX \ + GRUB_DISABLE_OS_PROBER \ + GRUB_INIT_TUNE \ + GRUB_SAVEDEFAULT if test "x${grub_cfg}" != "x"; then rm -f ${grub_cfg}.new diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in index fc24c7b70..bcd6baffb 100644 --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in @@ -96,7 +96,7 @@ convert_system_path_to_grub_path () save_default_entry () { - if [ "x${GRUB_DEFAULT}" = "xsaved" ] ; then + if [ "x${GRUB_SAVEDEFAULT}" = "xtrue" ] ; then cat << EOF savedefault EOF @@ -120,7 +120,7 @@ prepare_grub_to_access_device () # If there's a filesystem UUID that GRUB is capable of identifying, use it; # otherwise set root as per value in device.map. - echo "set root=`${grub_probe} --device ${device} --target=drive`" + echo "set root='`${grub_probe} --device ${device} --target=drive`'" if fs_uuid="`${grub_probe} --device ${device} --target=fs_uuid 2> /dev/null`" ; then echo "search --no-floppy --fs-uuid --set ${fs_uuid}" fi diff --git a/util/grub-mkdevicemap.c b/util/grub-mkdevicemap.c index b4febbb8d..c68482af1 100644 --- a/util/grub-mkdevicemap.c +++ b/util/grub-mkdevicemap.c @@ -84,7 +84,7 @@ usage (int status) { if (status) fprintf (stderr, - "Try ``%s --help'' for more information.\n", program_name); + "Try `%s --help' for more information.\n", program_name); else printf ("\ Usage: %s [OPTION]...\n\ diff --git a/util/grub-mkfont.c b/util/grub-mkfont.c index 3d1c6faac..51e2e494c 100644 --- a/util/grub-mkfont.c +++ b/util/grub-mkfont.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -49,6 +50,12 @@ struct grub_glyph_info grub_uint8_t bitmap[0]; }; +enum file_formats +{ + PF2, + ASCII_BITMAPS +}; + #define GRUB_FONT_FLAG_BOLD 1 #define GRUB_FONT_FLAG_NOBITMAP 2 #define GRUB_FONT_FLAG_NOHINTING 4 @@ -87,6 +94,7 @@ static struct option options[] = {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, {"verbose", no_argument, 0, 'v'}, + {"ascii-bitmaps", no_argument, 0, 0x102}, {0, 0, 0, 0} }; @@ -96,12 +104,13 @@ static void usage (int status) { if (status) - fprintf (stderr, "Try ``%s --help'' for more information.\n", program_name); + fprintf (stderr, "Try `%s --help' for more information.\n", program_name); else printf ("\ Usage: %s [OPTIONS] FONT_FILES\n\ \nOptions:\n\ -o, --output=FILE_NAME set output file name\n\ + --ascii-bitmaps save only the ASCII bitmaps\n\ -i, --index=N set face index\n\ -r, --range=A-B[,C-D] set font range\n\ -n, --name=S set font family name\n\ @@ -337,7 +346,39 @@ print_glyphs (struct grub_font_info *font_info) } void -write_font (struct grub_font_info *font_info, char *output_file) +write_font_ascii_bitmap (struct grub_font_info *font_info, char *output_file) +{ + FILE *file; + struct grub_glyph_info *glyph; + int num; + + file = fopen (output_file, "wb"); + if (! file) + grub_util_error ("Can\'t write to file %s.", output_file); + + int correct_size; + for (glyph = font_info->glyph, num = 0; glyph; glyph = glyph->next, num++) + { + correct_size = 1; + if (glyph->width != 8 || glyph->height != 16) + { + /* printf ("Width or height from glyph U+%04x not supported, skipping.\n", glyph->char_code); */ + correct_size = 0; + } + int row; + for (row = 0; row < glyph->height; row++) + { + if (correct_size) + fwrite (&glyph->bitmap[row], sizeof(glyph->bitmap[row]), 1, file); + else + fwrite (&correct_size, 1, 1, file); + } + } + fclose (file); +} + +void +write_font_pf2 (struct grub_font_info *font_info, char *output_file) { FILE *file; grub_uint32_t leng, data; @@ -347,14 +388,15 @@ write_font (struct grub_font_info *font_info, char *output_file) file = fopen (output_file, "wb"); if (! file) - grub_util_error ("Can\'t write to file %s.", output_file); + grub_util_error ("can\'t write to file %s.", output_file); offset = 0; leng = grub_cpu_to_be32 (4); - grub_util_write_image ("FILE", 4, file); + grub_util_write_image (FONT_FORMAT_SECTION_NAMES_FILE, + sizeof(FONT_FORMAT_SECTION_NAMES_FILE) - 1, file); grub_util_write_image ((char *) &leng, 4, file); - grub_util_write_image ("PFF2", 4, file); + grub_util_write_image (FONT_FORMAT_PFF2_MAGIC, 4, file); offset += 12; if (! font_info->name) @@ -376,20 +418,25 @@ write_font (struct grub_font_info *font_info, char *output_file) font_name = xasprintf ("%s %s %d", font_info->name, &style_name[1], font_info->size); - write_string_section ("NAME", font_name, &offset, file); - write_string_section ("FAMI", font_info->name, &offset, file); - write_string_section ("WEIG", + write_string_section (FONT_FORMAT_SECTION_NAMES_FONT_NAME, + font_name, &offset, file); + write_string_section (FONT_FORMAT_SECTION_NAMES_FAMILY, + font_info->name, &offset, file); + write_string_section (FONT_FORMAT_SECTION_NAMES_WEIGHT, (font_info->style & FT_STYLE_FLAG_BOLD) ? "bold" : "normal", &offset, file); - write_string_section ("SLAN", + write_string_section (FONT_FORMAT_SECTION_NAMES_SLAN, (font_info->style & FT_STYLE_FLAG_ITALIC) ? "italic" : "normal", &offset, file); - write_be16_section ("PTSZ", font_info->size, &offset, file); - write_be16_section ("MAXW", font_info->max_width, &offset, file); - write_be16_section ("MAXH", font_info->max_height, &offset, file); + write_be16_section (FONT_FORMAT_SECTION_NAMES_POINT_SIZE, + font_info->size, &offset, file); + write_be16_section (FONT_FORMAT_SECTION_NAMES_MAX_CHAR_WIDTH, + font_info->max_width, &offset, file); + write_be16_section (FONT_FORMAT_SECTION_NAMES_MAX_CHAR_HEIGHT, + font_info->max_height, &offset, file); if (! font_info->desc) { @@ -407,8 +454,10 @@ write_font (struct grub_font_info *font_info, char *output_file) font_info->asce = font_info->max_y; } - write_be16_section ("ASCE", font_info->asce, &offset, file); - write_be16_section ("DESC", font_info->desc, &offset, file); + write_be16_section (FONT_FORMAT_SECTION_NAMES_ASCENT, + font_info->asce, &offset, file); + write_be16_section (FONT_FORMAT_SECTION_NAMES_DESCENT, + font_info->desc, &offset, file); if (font_verbosity > 0) { @@ -439,7 +488,9 @@ write_font (struct grub_font_info *font_info, char *output_file) printf ("Number of glyph: %d\n", num); leng = grub_cpu_to_be32 (num * 9); - grub_util_write_image ("CHIX", 4, file); + grub_util_write_image (FONT_FORMAT_SECTION_NAMES_CHAR_INDEX, + sizeof(FONT_FORMAT_SECTION_NAMES_CHAR_INDEX) - 1, + file); grub_util_write_image ((char *) &leng, 4, file); offset += 8 + num * 9 + 8; @@ -455,7 +506,8 @@ write_font (struct grub_font_info *font_info, char *output_file) } leng = 0xffffffff; - grub_util_write_image ("DATA", 4, file); + grub_util_write_image (FONT_FORMAT_SECTION_NAMES_DATA, + sizeof(FONT_FORMAT_SECTION_NAMES_DATA) - 1, file); grub_util_write_image ((char *) &leng, 4, file); for (cur = font_info->glyph; cur; cur = cur->next) @@ -473,9 +525,6 @@ write_font (struct grub_font_info *font_info, char *output_file) grub_util_write_image ((char *) &cur->bitmap[0], cur->bitmap_size, file); } - if (font_verbosity > 1) - print_glyphs (font_info); - fclose (file); } @@ -487,6 +536,7 @@ main (int argc, char *argv[]) int font_index = 0; int font_size = 0; char *output_file = NULL; + enum file_formats file_format = PF2; memset (&font_info, 0, sizeof (font_info)); @@ -546,13 +596,13 @@ main (int argc, char *argv[]) a = strtoul (p, &p, 0); if (*p != '-') - grub_util_error ("Invalid font range"); + grub_util_error ("invalid font range"); b = strtoul (p + 1, &p, 0); if ((font_info.num_range & (GRUB_FONT_RANGE_BLOCK - 1)) == 0) font_info.ranges = xrealloc (font_info.ranges, (font_info.num_range + GRUB_FONT_RANGE_BLOCK) * - sizeof (int) * 2); + sizeof (grub_uint32_t) * 2); font_info.ranges[font_info.num_range * 2] = a; font_info.ranges[font_info.num_range * 2 + 1] = b; @@ -561,7 +611,7 @@ main (int argc, char *argv[]) if (*p) { if (*p != ',') - grub_util_error ("Invalid font range"); + grub_util_error ("invalid font range"); else p++; } @@ -591,14 +641,35 @@ main (int argc, char *argv[]) font_verbosity++; break; + case 0x102: + file_format = ASCII_BITMAPS; + break; + default: usage (1); break; } } + if (file_format == ASCII_BITMAPS && font_info.num_range > 0) + { + grub_util_error ("Option --ascii-bitmaps doesn't accept ranges (use ASCII)."); + return 1; + } + + else if (file_format == ASCII_BITMAPS) + { + font_info.ranges = xrealloc (font_info.ranges, + GRUB_FONT_RANGE_BLOCK * + sizeof (grub_uint32_t) * 2); + + font_info.ranges[0] = (grub_uint32_t) 0x00; + font_info.ranges[1] = (grub_uint32_t) 0x7f; + font_info.num_range = 1; + } + if (! output_file) - grub_util_error ("No output file is specified."); + grub_util_error ("no output file is specified"); if (FT_Init_FreeType (&ft_lib)) grub_util_error ("FT_Init_FreeType fails"); @@ -610,7 +681,7 @@ main (int argc, char *argv[]) if (FT_New_Face (ft_lib, argv[optind], font_index, &ft_face)) { - grub_util_info ("Can't open file %s, index %d\n", argv[optind], + grub_util_info ("can't open file %s, index %d", argv[optind], font_index); continue; } @@ -638,7 +709,13 @@ main (int argc, char *argv[]) FT_Done_FreeType (ft_lib); - write_font (&font_info, output_file); + if (file_format == PF2) + write_font_pf2 (&font_info, output_file); + else if (file_format == ASCII_BITMAPS) + write_font_ascii_bitmap (&font_info, output_file); + + if (font_verbosity > 1) + print_glyphs (&font_info); return 0; } diff --git a/util/grub-mkpasswd-pbkdf2.c b/util/grub-mkpasswd-pbkdf2.c index b27a4e893..a00b1e990 100644 --- a/util/grub-mkpasswd-pbkdf2.c +++ b/util/grub-mkpasswd-pbkdf2.c @@ -50,9 +50,9 @@ grub_vprintf (const char *fmt, va_list args) } int -grub_vsprintf (char *str, const char *fmt, va_list args) +grub_vsnprintf (char *str, grub_size_t n, const char *fmt, va_list args) { - return vsprintf (str, fmt, args); + return vsnprintf (str, n, fmt, args); } void @@ -74,16 +74,16 @@ static void usage (int status) { if (status) - fprintf (stderr, "Try ``grub-scrypt --help'' for more information.\n"); + fprintf (stderr, "Try `%s --help' for more information.\n", program_name); else printf ("\ -Usage: grub-scrypt [OPTIONS]\n\ +Usage: %s [OPTIONS]\n\ \nOptions:\n\ -c number, --iteration-count=number Number of PBKDF2 iterations\n\ -l number, --buflen=number Length of generated hash\n\ -s number, --salt=number Length of salt\n\ \n\ -Report bugs to <%s>.\n", PACKAGE_BUGREPORT); +Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT); exit (status); } @@ -165,12 +165,12 @@ main (int argc, char *argv[]) bufhex = malloc (buflen * 2 + 1); if (!bufhex) - grub_util_error ("Out of memory"); + grub_util_error ("out of memory"); buf = malloc (buflen); if (!buf) { free (bufhex); - grub_util_error ("Out of memory"); + grub_util_error ("out of memory"); } salt = malloc (saltlen); @@ -178,7 +178,7 @@ main (int argc, char *argv[]) { free (bufhex); free (buf); - grub_util_error ("Out of memory"); + grub_util_error ("out of memory"); } salthex = malloc (saltlen * 2 + 1); if (!salthex) @@ -186,7 +186,7 @@ main (int argc, char *argv[]) free (salt); free (bufhex); free (buf); - grub_util_error ("Out of memory"); + grub_util_error ("out of memory"); } /* Disable echoing. Based on glibc. */ @@ -225,7 +225,7 @@ main (int argc, char *argv[]) /* Restore the original setting. */ if (tty_changed) (void) tcsetattr (fileno (in), TCSAFLUSH, &s); - grub_util_error ("Failure to read password"); + grub_util_error ("failure to read password"); } if (nr >= 1 && pass1[nr-1] == '\n') pass1[nr-1] = 0; @@ -249,7 +249,7 @@ main (int argc, char *argv[]) free (bufhex); free (salthex); free (salt); - grub_util_error ("Failure to read password"); + grub_util_error ("failure to read password"); } if (nr >= 1 && pass2[nr-1] == '\n') pass2[nr-1] = 0; @@ -264,7 +264,7 @@ main (int argc, char *argv[]) free (bufhex); free (salthex); free (salt); - grub_util_error ("Passwords don't match"); + grub_util_error ("passwords don't match"); } memset (pass2, 0, strlen (pass2)); free (pass2); @@ -286,7 +286,7 @@ main (int argc, char *argv[]) free (salthex); free (salt); fclose (f); - grub_util_error ("Couldn't retrieve random data for salt"); + grub_util_error ("couldn't retrieve random data for salt"); } rd = fread (salt, 1, saltlen, f); if (rd != saltlen) @@ -299,7 +299,7 @@ main (int argc, char *argv[]) free (salthex); free (salt); fclose (f); - grub_util_error ("Couldn't retrieve random data for salt"); + grub_util_error ("couldn't retrieve random data for salt"); } fclose (f); } @@ -321,7 +321,7 @@ main (int argc, char *argv[]) memset (salthex, 0, 2 * saltlen); free (salt); free (salthex); - grub_util_error ("Cryptographic error number %d", gcry_err); + grub_util_error ("cryptographic error number %d", gcry_err); } hexify (bufhex, buf, buflen); diff --git a/util/i386/pc/grub-mkimage.c b/util/grub-mkrawimage.c similarity index 62% rename from util/i386/pc/grub-mkimage.c rename to util/grub-mkrawimage.c index ebf1bc7ff..dd84f2d81 100644 --- a/util/i386/pc/grub-mkimage.c +++ b/util/grub-mkrawimage.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -40,6 +41,8 @@ #include "progname.h" +#define ALIGN_ADDR(x) (ALIGN_UP((x), GRUB_TARGET_SIZEOF_VOID_P)) + #ifdef ENABLE_LZMA #include @@ -95,12 +98,19 @@ compress_kernel (char *kernel_img, size_t kernel_size, static void generate_image (const char *dir, char *prefix, FILE *out, char *mods[], - char *memdisk_path, char *config_path) + char *memdisk_path, char *font_path, char *config_path, +#ifdef GRUB_PLATFORM_IMAGE_DEFAULT + grub_platform_image_format_t format +#else + int dummy __attribute__ ((unused)) +#endif + +) { - char *kernel_img, *boot_img, *core_img; - size_t kernel_size, boot_size, total_module_size, core_size; - size_t memdisk_size = 0, config_size = 0; - char *kernel_path, *boot_path; + char *kernel_img, *core_img; + size_t kernel_size, total_module_size, core_size; + size_t memdisk_size = 0, font_size = 0, config_size = 0, config_size_pure = 0; + char *kernel_path; size_t offset; struct grub_util_path_list *path_list, *p, *next; struct grub_module_info *modinfo; @@ -119,15 +129,22 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], total_module_size += memdisk_size + sizeof (struct grub_module_header); } + if (font_path) + { + font_size = ALIGN_ADDR (grub_util_get_image_size (font_path)); + total_module_size += font_size + sizeof (struct grub_module_header); + } + if (config_path) { - config_size = grub_util_get_image_size (config_path) + 1; + config_size_pure = grub_util_get_image_size (config_path) + 1; + config_size = ALIGN_ADDR (config_size_pure); grub_util_info ("the size of config file is 0x%x", config_size); total_module_size += config_size + sizeof (struct grub_module_header); } for (p = path_list; p; p = p->next) - total_module_size += (grub_util_get_image_size (p->name) + total_module_size += (ALIGN_ADDR (grub_util_get_image_size (p->name)) + sizeof (struct grub_module_header)); grub_util_info ("the total module size is 0x%x", total_module_size); @@ -142,23 +159,25 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], /* Fill in the grub_module_info structure. */ modinfo = (struct grub_module_info *) (kernel_img + kernel_size); memset (modinfo, 0, sizeof (struct grub_module_info)); - modinfo->magic = GRUB_MODULE_MAGIC; - modinfo->offset = sizeof (struct grub_module_info); - modinfo->size = total_module_size; + modinfo->magic = grub_host_to_target32 (GRUB_MODULE_MAGIC); + modinfo->offset = grub_host_to_target_addr (sizeof (struct grub_module_info)); + modinfo->size = grub_host_to_target_addr (total_module_size); offset = kernel_size + sizeof (struct grub_module_info); for (p = path_list; p; p = p->next) { struct grub_module_header *header; - size_t mod_size; + size_t mod_size, orig_size; - mod_size = grub_util_get_image_size (p->name); + orig_size = grub_util_get_image_size (p->name); + mod_size = ALIGN_ADDR (orig_size); header = (struct grub_module_header *) (kernel_img + offset); memset (header, 0, sizeof (struct grub_module_header)); - header->type = OBJ_TYPE_ELF; + header->type = grub_host_to_target32 (OBJ_TYPE_ELF); header->size = grub_host_to_target32 (mod_size + sizeof (*header)); offset += sizeof (*header); + memset (kernel_img + offset + orig_size, 0, mod_size - orig_size); grub_util_load_image (p->name, kernel_img + offset); offset += mod_size; @@ -170,7 +189,7 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], header = (struct grub_module_header *) (kernel_img + offset); memset (header, 0, sizeof (struct grub_module_header)); - header->type = OBJ_TYPE_MEMDISK; + header->type = grub_host_to_target32 (OBJ_TYPE_MEMDISK); header->size = grub_host_to_target32 (memdisk_size + sizeof (*header)); offset += sizeof (*header); @@ -178,19 +197,33 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], offset += memdisk_size; } + if (font_path) + { + struct grub_module_header *header; + + header = (struct grub_module_header *) (kernel_img + offset); + memset (header, 0, sizeof (struct grub_module_header)); + header->type = grub_host_to_target32 (OBJ_TYPE_FONT); + header->size = grub_host_to_target32 (font_size + sizeof (*header)); + offset += sizeof (*header); + + grub_util_load_image (font_path, kernel_img + offset); + offset += font_size; + } + if (config_path) { struct grub_module_header *header; header = (struct grub_module_header *) (kernel_img + offset); memset (header, 0, sizeof (struct grub_module_header)); - header->type = OBJ_TYPE_CONFIG; + header->type = grub_host_to_target32 (OBJ_TYPE_CONFIG); header->size = grub_host_to_target32 (config_size + sizeof (*header)); offset += sizeof (*header); grub_util_load_image (config_path, kernel_img + offset); + *(kernel_img + offset + config_size_pure - 1) = 0; offset += config_size; - *(kernel_img + offset - 1) = 0; } grub_util_info ("kernel_img=%p, kernel_size=0x%x", kernel_img, kernel_size); @@ -202,29 +235,33 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], #if defined(GRUB_MACHINE_PCBIOS) { unsigned num; + char *boot_path, *boot_img; + size_t boot_size; num = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS); if (num > 0xffff) grub_util_error (_("the core image is too big")); - + boot_path = grub_util_get_path (dir, "diskboot.img"); boot_size = grub_util_get_image_size (boot_path); if (boot_size != GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("diskboot.img size must be %u bytes"), GRUB_DISK_SECTOR_SIZE); - + grub_util_error (_("diskboot.img size must be %u bytes"), + GRUB_DISK_SECTOR_SIZE); + boot_img = grub_util_read_image (boot_path); - + { struct grub_boot_blocklist *block; block = (struct grub_boot_blocklist *) (boot_img - + GRUB_DISK_SECTOR_SIZE - - sizeof (*block)); + + GRUB_DISK_SECTOR_SIZE + - sizeof (*block)); block->len = grub_host_to_target16 (num); /* This is filled elsewhere. Verify it just in case. */ - assert (block->segment == grub_host_to_target16 (GRUB_BOOT_MACHINE_KERNEL_SEG - + (GRUB_DISK_SECTOR_SIZE >> 4))); + assert (block->segment + == grub_host_to_target16 (GRUB_BOOT_MACHINE_KERNEL_SEG + + (GRUB_DISK_SECTOR_SIZE >> 4))); } - + grub_util_write_image (boot_img, boot_size, out); free (boot_img); free (boot_path); @@ -233,6 +270,8 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], { char *rom_img; size_t rom_size; + char *boot_path, *boot_img; + size_t boot_size; boot_path = grub_util_get_path (dir, "boot.img"); boot_size = grub_util_get_image_size (boot_path); @@ -245,12 +284,12 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], memset (rom_img, 0, rom_size); *((grub_int32_t *) (core_img + GRUB_KERNEL_MACHINE_CORE_ENTRY_ADDR)) - = grub_cpu_to_le32 ((grub_uint32_t) -rom_size); + = grub_host_to_target32 ((grub_uint32_t) -rom_size); memcpy (rom_img, core_img, core_size); *((grub_int32_t *) (boot_img + GRUB_BOOT_MACHINE_CORE_ENTRY_ADDR)) - = grub_cpu_to_le32 ((grub_uint32_t) -rom_size); + = grub_host_to_target32 ((grub_uint32_t) -rom_size); memcpy (rom_img + rom_size - boot_size, boot_img, boot_size); @@ -261,18 +300,17 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], free (boot_img); free (boot_path); } - #endif #ifdef GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE *((grub_uint32_t *) (core_img + GRUB_KERNEL_MACHINE_TOTAL_MODULE_SIZE)) - = grub_cpu_to_le32 (total_module_size); + = grub_host_to_target32 (total_module_size); #endif *((grub_uint32_t *) (core_img + GRUB_KERNEL_MACHINE_KERNEL_IMAGE_SIZE)) - = grub_cpu_to_le32 (kernel_size); + = grub_host_to_target32 (kernel_size); #ifdef GRUB_KERNEL_MACHINE_COMPRESSED_SIZE *((grub_uint32_t *) (core_img + GRUB_KERNEL_MACHINE_COMPRESSED_SIZE)) - = grub_cpu_to_le32 (core_size - GRUB_KERNEL_MACHINE_RAW_SIZE); + = grub_host_to_target32 (core_size - GRUB_KERNEL_MACHINE_RAW_SIZE); #endif #if defined(GRUB_KERNEL_MACHINE_INSTALL_DOS_PART) && defined(GRUB_KERNEL_MACHINE_INSTALL_BSD_PART) @@ -281,16 +319,79 @@ generate_image (const char *dir, char *prefix, FILE *out, char *mods[], if (prefix[0] == '(') { *((grub_int32_t *) (core_img + GRUB_KERNEL_MACHINE_INSTALL_DOS_PART)) - = grub_cpu_to_le32 (-2); + = grub_host_to_target32 (-2); *((grub_int32_t *) (core_img + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART)) - = grub_cpu_to_le32 (-2); + = grub_host_to_target32 (-2); } #endif #ifdef GRUB_MACHINE_PCBIOS if (GRUB_KERNEL_MACHINE_LINK_ADDR + core_size > GRUB_MEMORY_MACHINE_UPPER) - grub_util_error (_("Core image is too big (%p > %p)\n"), - GRUB_KERNEL_MACHINE_LINK_ADDR + core_size, GRUB_MEMORY_MACHINE_UPPER); + grub_util_error (_("core image is too big (%p > %p)"), + GRUB_KERNEL_MACHINE_LINK_ADDR + core_size, + GRUB_MEMORY_MACHINE_UPPER); +#endif + +#if defined(GRUB_MACHINE_MIPS) + if (format == GRUB_PLATFORM_IMAGE_ELF) + { + char *elf_img; + size_t program_size; + Elf32_Ehdr *ehdr; + Elf32_Phdr *phdr; + grub_uint32_t target_addr; + + program_size = ALIGN_ADDR (core_size); + + elf_img = xmalloc (program_size + sizeof (*ehdr) + sizeof (*phdr)); + memset (elf_img, 0, program_size + sizeof (*ehdr) + sizeof (*phdr)); + memcpy (elf_img + sizeof (*ehdr) + sizeof (*phdr), core_img, core_size); + ehdr = (void *) elf_img; + phdr = (void *) (elf_img + sizeof (*ehdr)); + memcpy (ehdr->e_ident, ELFMAG, SELFMAG); + ehdr->e_ident[EI_CLASS] = ELFCLASS32; +#ifdef GRUB_CPU_MIPSEL + ehdr->e_ident[EI_DATA] = ELFDATA2LSB; +#else + ehdr->e_ident[EI_DATA] = ELFDATA2MSB; +#endif + ehdr->e_ident[EI_VERSION] = EV_CURRENT; + ehdr->e_ident[EI_OSABI] = ELFOSABI_NONE; + ehdr->e_type = grub_host_to_target16 (ET_EXEC); + ehdr->e_machine = grub_host_to_target16 (EM_MIPS); + ehdr->e_version = grub_host_to_target32 (EV_CURRENT); + + ehdr->e_phoff = grub_host_to_target32 ((char *) phdr - (char *) ehdr); + ehdr->e_phentsize = grub_host_to_target16 (sizeof (*phdr)); + ehdr->e_phnum = grub_host_to_target16 (1); + + /* No section headers. */ + ehdr->e_shoff = grub_host_to_target32 (0); + ehdr->e_shentsize = grub_host_to_target16 (0); + ehdr->e_shnum = grub_host_to_target16 (0); + ehdr->e_shstrndx = grub_host_to_target16 (0); + + ehdr->e_ehsize = grub_host_to_target16 (sizeof (*ehdr)); + + phdr->p_type = grub_host_to_target32 (PT_LOAD); + phdr->p_offset = grub_host_to_target32 (sizeof (*ehdr) + sizeof (*phdr)); + phdr->p_flags = grub_host_to_target32 (PF_R | PF_W | PF_X); + + target_addr = ALIGN_UP (GRUB_KERNEL_MACHINE_LINK_ADDR + + kernel_size + total_module_size, 32); + ehdr->e_entry = grub_host_to_target32 (target_addr); + phdr->p_vaddr = grub_host_to_target32 (target_addr); + phdr->p_paddr = grub_host_to_target32 (target_addr); + phdr->p_align = grub_host_to_target32 (GRUB_KERNEL_MACHINE_LINK_ALIGN); + ehdr->e_flags = grub_host_to_target32 (0x1000 | EF_MIPS_NOREORDER + | EF_MIPS_PIC | EF_MIPS_CPIC); + phdr->p_filesz = grub_host_to_target32 (core_size); + phdr->p_memsz = grub_host_to_target32 (core_size); + + free (core_img); + core_img = elf_img; + core_size = program_size + sizeof (*ehdr) + sizeof (*phdr); + } #endif grub_util_write_image (core_img, core_size, out); @@ -314,8 +415,12 @@ static struct option options[] = {"directory", required_argument, 0, 'd'}, {"prefix", required_argument, 0, 'p'}, {"memdisk", required_argument, 0, 'm'}, + {"font", required_argument, 0, 'f'}, {"config", required_argument, 0, 'c'}, {"output", required_argument, 0, 'o'}, +#ifdef GRUB_PLATFORM_IMAGE_DEFAULT + {"format", required_argument, 0, 'O'}, +#endif {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, {"verbose", no_argument, 0, 'v'}, @@ -326,24 +431,36 @@ static void usage (int status) { if (status) - fprintf (stderr, _("Try ``%s --help'' for more information.\n"), program_name); + fprintf (stderr, _("Try `%s --help' for more information.\n"), program_name); else printf (_("\ -Usage: grub-mkimage [OPTION]... [MODULES]\n\ +Usage: %s [OPTION]... [MODULES]\n\ \n\ Make a bootable image of GRUB.\n\ \n\ -d, --directory=DIR use images and modules under DIR [default=%s]\n\ -p, --prefix=DIR set grub_prefix directory [default=%s]\n\ -m, --memdisk=FILE embed FILE as a memdisk image\n\ + -f, --font=FILE embed FILE as a boot font\n\ -c, --config=FILE embed FILE as boot config\n\ - -o, --output=FILE output a generated image to FILE [default=stdout]\n\ + -o, --output=FILE output a generated image to FILE [default=stdout]\n" +#ifdef GRUB_PLATFORM_IMAGE_DEFAULT + "\ + -O, --format=FORMAT generate an image in format [default=%s]\n\ + available formats: %s\n" +#endif + "\ -h, --help display this message and exit\n\ -V, --version print version information and exit\n\ -v, --verbose print verbose messages\n\ \n\ Report bugs to <%s>.\n\ -"), GRUB_LIBDIR, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT); +"), +program_name, GRUB_LIBDIR, DEFAULT_DIRECTORY, +#ifdef GRUB_PLATFORM_IMAGE_DEFAULT + GRUB_PLATFORM_IMAGE_DEFAULT_FORMAT, GRUB_PLATFORM_IMAGE_FORMATS, +#endif +PACKAGE_BUGREPORT); exit (status); } @@ -355,8 +472,12 @@ main (int argc, char *argv[]) char *dir = NULL; char *prefix = NULL; char *memdisk = NULL; + char *font = NULL; char *config = NULL; FILE *fp = stdout; +#ifdef GRUB_PLATFORM_IMAGE_DEFAULT + grub_platform_image_format_t format = GRUB_PLATFORM_IMAGE_DEFAULT; +#endif set_program_name (argv[0]); @@ -364,7 +485,7 @@ main (int argc, char *argv[]) while (1) { - int c = getopt_long (argc, argv, "d:p:m:c:o:hVv", options, 0); + int c = getopt_long (argc, argv, "d:p:m:c:o:O:f:hVv", options, 0); if (c == -1) break; @@ -378,6 +499,22 @@ main (int argc, char *argv[]) output = xstrdup (optarg); break; +#ifdef GRUB_PLATFORM_IMAGE_DEFAULT + case 'O': +#ifdef GRUB_PLATFORM_IMAGE_RAW + if (strcmp (optarg, "raw") == 0) + format = GRUB_PLATFORM_IMAGE_RAW; + else +#endif +#ifdef GRUB_PLATFORM_IMAGE_ELF + if (strcmp (optarg, "elf") == 0) + format = GRUB_PLATFORM_IMAGE_ELF; + else +#endif + usage (1); + break; +#endif + case 'd': if (dir) free (dir); @@ -397,6 +534,13 @@ main (int argc, char *argv[]) prefix = xstrdup ("(memdisk)/boot/grub"); break; + case 'f': + if (font) + free (font); + + font = xstrdup (optarg); + break; + case 'c': if (config) free (config); @@ -438,7 +582,13 @@ main (int argc, char *argv[]) } generate_image (dir ? : GRUB_LIBDIR, prefix ? : DEFAULT_DIRECTORY, fp, - argv + optind, memdisk, config); + argv + optind, memdisk, font, config, +#ifdef GRUB_PLATFORM_IMAGE_DEFAULT + format +#else + 0 +#endif + ); fclose (fp); diff --git a/util/grub-mkrelpath.c b/util/grub-mkrelpath.c index 62e400814..327f0c866 100644 --- a/util/grub-mkrelpath.c +++ b/util/grub-mkrelpath.c @@ -34,7 +34,7 @@ static void usage (int status) { if (status) - fprintf (stderr, "Try ``%s --help'' for more information.\n", program_name); + fprintf (stderr, "Try `%s --help' for more information.\n", program_name); else printf ("\ Usage: %s [OPTIONS] PATH\n\ diff --git a/util/grub-mkrescue.in b/util/grub-mkrescue.in index 6b3c9ecb8..592cf2df6 100644 --- a/util/grub-mkrescue.in +++ b/util/grub-mkrescue.in @@ -86,7 +86,15 @@ if [ "x${output_image}" = x ] ; then exit 1 fi -iso9660_dir=`mktemp -d` +if test "x$TMP" != x; then + MKTEMP_TEMPLATE="$TMP/grub-mkrescue.XXXXXXXXXX" +elif test "x$TEMP" != x; then + MKTEMP_TEMPLATE="$TEMP/grub-mkrescue.XXXXXXXXXX" +else + MKTEMP_TEMPLATE="/tmp/grub-mkrescue.XXXXXXXXXX" +fi + +iso9660_dir=`mktemp -d "$MKTEMP_TEMPLATE"` mkdir -p ${iso9660_dir}/boot/grub process_input_dir () @@ -133,8 +141,8 @@ fi # build coreboot core.img if test -e "${coreboot_dir}" ; then echo "Enabling coreboot support ..." - memdisk_img=`mktemp` - memdisk_dir=`mktemp -d` + memdisk_img=`mktemp "$MKTEMP_TEMPLATE"` + memdisk_dir=`mktemp -d "$MKTEMP_TEMPLATE"` mkdir -p ${memdisk_dir}/boot/grub # obtain date-based UUID iso_uuid=$(date +%Y-%m-%d-%H-%M-%S-00) @@ -162,12 +170,12 @@ fi # build BIOS core.img if test -e "${pc_dir}" ; then echo "Enabling BIOS support ..." - core_img=`mktemp` + core_img=`mktemp "$MKTEMP_TEMPLATE"` grub-mkimage -d ${pc_dir}/ -o ${core_img} --prefix=/boot/grub/i386-pc \ iso9660 biosdisk cat ${pc_dir}/cdboot.img ${core_img} > ${iso9660_dir}/boot/grub/i386-pc/eltorito.img - embed_img=`mktemp` + embed_img=`mktemp "$MKTEMP_TEMPLATE"` cat ${pc_dir}/boot.img ${core_img} > ${embed_img} rm -f ${core_img} diff --git a/util/grub-pe2elf.c b/util/grub-pe2elf.c index fb370d9ec..f370bbfa8 100644 --- a/util/grub-pe2elf.c +++ b/util/grub-pe2elf.c @@ -29,6 +29,8 @@ #include #include +#include "progname.h" + static struct option options[] = { {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, @@ -40,7 +42,7 @@ static void usage (int status) { if (status) - fprintf (stderr, "Try ``%s --help'' for more information.\n", program_name); + fprintf (stderr, "Try `%s --help' for more information.\n", program_name); else printf ("\ Usage: %s [OPTIONS] input [output]\n\ @@ -182,7 +184,7 @@ write_section_data (FILE* fp, char *image, char name[5 + strlen (pe_shdr->name)]; if (num_sections >= MAX_SECTIONS) - grub_util_error ("Too many sections"); + grub_util_error ("too many sections"); sprintf (name, ".rel%s", pe_shdr->name); @@ -230,14 +232,14 @@ write_reloc_section (FILE* fp, char *image, if ((pe_rel->symtab_index >= pe_chdr->num_symbols) || (symtab_map[pe_rel->symtab_index] == -1)) - grub_util_error ("Invalid symbol"); + grub_util_error ("invalid symbol"); if (pe_rel->type == GRUB_PE32_REL_I386_DIR32) type = R_386_32; else if (pe_rel->type == GRUB_PE32_REL_I386_REL32) type = R_386_PC32; else - grub_util_error ("Unknown pe relocation type %d\n", pe_rel->type); + grub_util_error ("unknown pe relocation type %d\n", pe_rel->type); ofs = pe_rel->offset - pe_sec->virtual_address; addr = (grub_uint32_t *)(image + pe_sec->raw_data_offset + ofs); @@ -248,14 +250,14 @@ write_reloc_section (FILE* fp, char *image, code = image[pe_sec->raw_data_offset + ofs - 1]; if (((code != 0xe8) && (code != 0xe9)) || (*addr)) - grub_util_error ("Invalid relocation (%x %x)", code, *addr); + grub_util_error ("invalid relocation (%x %x)", code, *addr); modified = 1; if (symtab[symtab_map[pe_rel->symtab_index]].st_shndx) { if (symtab[symtab_map[pe_rel->symtab_index]].st_shndx != shdr[i].sh_info) - grub_util_error ("Cross section call is not allowed"); + grub_util_error ("cross section call is not allowed"); *addr = (symtab[symtab_map[pe_rel->symtab_index]].st_value - ofs - 4); @@ -440,7 +442,7 @@ convert_pe (FILE* fp, char *image) pe_chdr = (struct grub_pe32_coff_header *) image; if (grub_le_to_cpu16 (pe_chdr->machine) != GRUB_PE32_MACHINE_I386) - grub_util_error ("Invalid coff image"); + grub_util_error ("invalid coff image"); strtab = xmalloc (STRTAB_BLOCK); strtab_max = STRTAB_BLOCK; diff --git a/util/grub-probe.c b/util/grub-probe.c index 4ba8a98e5..ba2fe4c35 100644 --- a/util/grub-probe.c +++ b/util/grub-probe.c @@ -84,7 +84,7 @@ probe_partmap (grub_disk_t disk) { if (disk->partition == NULL) { - grub_util_info ("No partition map found for %s", disk->name); + grub_util_info ("no partition map found for %s", disk->name); return; } @@ -94,6 +94,11 @@ probe_partmap (grub_disk_t disk) static int probe_raid_level (grub_disk_t disk) { + /* disk might be NULL in the case of a LVM physical volume with no LVM + signature. Ignore such cases here. */ + if (!disk) + return -1; + if (disk->dev->id != GRUB_DISK_DEVICE_RAID_ID) return -1; @@ -113,17 +118,17 @@ probe (const char *path, char *device_name) { #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) if (! grub_util_check_char_device (device_name)) - grub_util_error ("%s is not a character device.\n", device_name); + grub_util_error ("%s is not a character device", device_name); #else if (! grub_util_check_block_device (device_name)) - grub_util_error ("%s is not a block device.\n", device_name); + grub_util_error ("%s is not a block device", device_name); #endif } else device_name = grub_guess_root_device (path); if (! device_name) - grub_util_error ("cannot find a device for %s (is /dev mounted?).\n", path); + grub_util_error ("cannot find a device for %s (is /dev mounted?)", path); if (print == PRINT_DEVICE) { @@ -133,7 +138,7 @@ probe (const char *path, char *device_name) drive_name = grub_util_get_grub_dev (device_name); if (! drive_name) - grub_util_error ("Cannot find a GRUB drive for %s. Check your device.map.\n", device_name); + grub_util_error ("cannot find a GRUB drive for %s. Check your device.map", device_name); if (print == PRINT_DRIVE) { @@ -309,7 +314,7 @@ usage (int status) { if (status) fprintf (stderr, - "Try ``%s --help'' for more information.\n", program_name); + "Try `%s --help' for more information.\n", program_name); else printf ("\ Usage: %s [OPTION]... [PATH|DEVICE]\n\ diff --git a/util/grub-script-check.c b/util/grub-script-check.c new file mode 100644 index 000000000..5bc5df1c1 --- /dev/null +++ b/util/grub-script-check.c @@ -0,0 +1,254 @@ +/* grub-script-check.c - check grub script file for syntax errors */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define _GNU_SOURCE 1 + +#include +#include +#include +#include +#include +#include + +#include "progname.h" + +void +grub_putchar (int c) +{ + putchar (c); +} + +int +grub_getkey (void) +{ + return -1; +} + +void +grub_refresh (void) +{ + fflush (stdout); +} + +char * +grub_script_execute_argument_to_string (struct grub_script_arg *arg __attribute__ ((unused))) +{ + return 0; +} + +grub_err_t +grub_script_execute_cmdline (struct grub_script_cmd *cmd __attribute__ ((unused))) +{ + return 0; +} + +grub_err_t +grub_script_execute_cmdblock (struct grub_script_cmd *cmd __attribute__ ((unused))) +{ + return 0; +} + +grub_err_t +grub_script_execute_cmdif (struct grub_script_cmd *cmd __attribute__ ((unused))) +{ + return 0; +} + +grub_err_t +grub_script_execute_menuentry (struct grub_script_cmd *cmd __attribute__ ((unused))) +{ + return 0; +} + +grub_err_t +grub_script_execute (struct grub_script *script) +{ + if (script == 0 || script->cmd == 0) + return 0; + + return script->cmd->exec (script->cmd); +} + +static struct option options[] = + { + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'V'}, + {"verbose", no_argument, 0, 'v'}, + {0, 0, 0, 0} + }; + +static void +usage (int status) +{ + if (status) + fprintf (stderr, + "Try ``%s --help'' for more information.\n", program_name); + else + printf ("\ +Usage: %s [PATH]\n\ +\n\ +Checks GRUB script configuration file for syntax errors.\n\ +\n\ + -h, --help display this message and exit\n\ + -V, --version print version information and exit\n\ + -v, --verbose print script being processed\n\ +\n\ +Report bugs to <%s>.\n\ +", program_name, + PACKAGE_BUGREPORT); + exit (status); +} + +int +main (int argc, char *argv[]) +{ + char *argument; + char *input; + FILE *file = 0; + int verbose = 0; + struct grub_script *script; + + auto grub_err_t get_config_line (char **line, int cont); + grub_err_t get_config_line (char **line, int cont __attribute__ ((unused))) + { + int i; + char *cmdline = 0; + size_t len = 0; + ssize_t read; + + read = getline(&cmdline, &len, (file ?: stdin)); + if (read == -1) + { + *line = 0; + grub_errno = GRUB_ERR_READ_ERROR; + + if (cmdline) + free (cmdline); + return grub_errno; + } + + if (verbose) + grub_printf("%s", cmdline); + + for (i = 0; cmdline[i] != '\0'; i++) + { + /* Replace tabs and carriage returns with spaces. */ + if (cmdline[i] == '\t' || cmdline[i] == '\r') + cmdline[i] = ' '; + + /* Replace '\n' with '\0'. */ + if (cmdline[i] == '\n') + cmdline[i] = '\0'; + } + + *line = grub_strdup (cmdline); + + free (cmdline); + return 0; + } + + set_program_name (argv[0]); + grub_util_init_nls (); + + /* Check for options. */ + while (1) + { + int c = getopt_long (argc, argv, "hvV", options, 0); + + if (c == -1) + break; + else + switch (c) + { + case 'h': + usage (0); + break; + + case 'V': + printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); + return 0; + + case 'v': + verbose = 1; + break; + + default: + usage (1); + break; + } + } + + /* Obtain ARGUMENT. */ + if (optind >= argc) + { + file = 0; /* read from stdin */ + } + else if (optind + 1 != argc) + { + fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind + 1]); + usage (1); + } + else + { + argument = argv[optind]; + file = fopen (argument, "r"); + if (! file) + { + fprintf (stderr, "%s: %s: %s\n", program_name, argument, strerror(errno)); + usage (1); + } + } + + /* Initialize all modules. */ + grub_init_all (); + + do + { + input = 0; + get_config_line(&input, 0); + if (! input) + break; + + script = grub_script_parse (input, get_config_line); + if (script) + { + grub_script_execute (script); + grub_script_free (script); + } + + grub_free (input); + } while (script != 0); + + /* Free resources. */ + grub_fini_all (); + if (file) fclose (file); + + return (script == 0); +} diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in index 0048ebed1..c86f7b867 100644 --- a/util/grub.d/00_header.in +++ b/util/grub.d/00_header.in @@ -1,7 +1,7 @@ #! /bin/sh -e # grub-mkconfig helper script. -# Copyright (C) 2006,2007,2008,2009 Free Software Foundation, Inc. +# Copyright (C) 2006,2007,2008,2009,2010 Free Software Foundation, Inc. # # GRUB is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -103,6 +103,18 @@ if loadfont `make_system_path_relative_to_its_root ${GRUB_FONT_PATH}` ; then # understand terminal_output terminal gfxterm fi +EOF +if [ x$GRUB_THEME != x ] && [ -f $GRUB_THEME ] \ + && is_path_readable_by_grub $GRUB_THEME; then + echo "Found theme: $GRUB_THEME" >&2 + prepare_grub_to_access_device `${grub_probe} --target=device $GRUB_THEME` | sed -e "s/^/ /" + cat << EOF + insmod gfxmenu + set theme=(\$root)`make_system_path_relative_to_its_root $GRUB_THEME` + set menuviewer=gfxmenu +EOF +fi + cat << EOF fi EOF ;; @@ -122,8 +134,9 @@ esac # Gettext variables and module if [ "x${LANG}" != "xC" ] ; then + prepare_grub_to_access_device $(${grub_probe} --target=device ${locale_dir}) cat << EOF -set locale_dir=${locale_dir} +set locale_dir=(\$root)$(make_system_path_relative_to_its_root ${locale_dir}) set lang=${grub_lang} insmod gettext EOF @@ -145,3 +158,11 @@ else set timeout=${GRUB_TIMEOUT} EOF fi + +# Play an initial tune +if [ "x${GRUB_INIT_TUNE}" != "x" ] ; then + cat << EOF +insmod play +play ${GRUB_INIT_TUNE} +EOF +fi diff --git a/util/grub.d/10_hurd.in b/util/grub.d/10_hurd.in index 65a9a70b1..fbb4eb752 100644 --- a/util/grub.d/10_hurd.in +++ b/util/grub.d/10_hurd.in @@ -21,10 +21,13 @@ exec_prefix=@exec_prefix@ libdir=@libdir@ . ${libdir}/grub/grub-mkconfig_lib +CLASS="--class gnu --class os" + if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then OS=GNU else OS="${GRUB_DISTRIBUTOR} GNU/Hurd" + CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr '[A-Z]' '[a-z]') ${CLASS}" fi at_least_one=false @@ -69,7 +72,7 @@ if ${all_of_them} && test -e /lib/ld.so.1 ; then : ; else fi cat << EOF -menuentry "${OS}" { +menuentry "${OS}" ${CLASS} { EOF prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/" cat << EOF @@ -89,3 +92,25 @@ cat << EOF module /lib/ld.so.1 exec /hurd/exec '\$(exec-task=task-create)' } EOF + +cat << EOF +menuentry "${OS} (recovery mode)" { +EOF +prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/" +cat << EOF + echo $(gettext "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 + echo $(gettext "Loading the Hurd ...") + module /hurd/${hurd_fs}.static ${hurd_fs} \\ + --multiboot-command-line='\${kernel-command-line}' \\ + --host-priv-port='\${host-port}' \\ + --device-master-port='\${device-port}' \\ + --exec-server-task='\${exec-task}' -T typed '\${root}' \\ + '\$(task-create)' '\$(task-resume)' + module /lib/ld.so.1 exec /hurd/exec '\$(exec-task=task-create)' +} +EOF diff --git a/util/grub.d/10_kfreebsd.in b/util/grub.d/10_kfreebsd.in index b84b90a33..dc87d6162 100644 --- a/util/grub.d/10_kfreebsd.in +++ b/util/grub.d/10_kfreebsd.in @@ -22,13 +22,20 @@ bindir=@bindir@ libdir=@libdir@ . ${libdir}/grub/grub-mkconfig_lib -. ${bindir}/gettext.sh export TEXTDOMAIN=@PACKAGE@ -export TEXTDOMAINDIR=@localedir@ +export TEXTDOMAINDIR=@LOCALEDIR@ + +CLASS="--class os" case "${GRUB_DISTRIBUTOR}" in - Debian) OS="${GRUB_DISTRIBUTOR} GNU/kFreeBSD" ;; - *) OS="FreeBSD" ;; + Debian) + OS="${GRUB_DISTRIBUTOR} GNU/kFreeBSD" + CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr '[A-Z]' '[a-z]') --class gnu-kfreebsd --class gnu ${CLASS}" + ;; + *) + OS="FreeBSD" + CLASS="--class freebsd --class bsd ${CLASS}" + ;; esac kfreebsd_entry () @@ -38,7 +45,7 @@ kfreebsd_entry () recovery="$3" # not used yet args="$4" # not used yet title="$(gettext "%s, with kFreeBSD %s")" - printf "menuentry \"${title}\" {\n" "${os}" "${version}" + printf "menuentry \"${title}\" ${CLASS} {\n" "${os}" "${version}" save_default_entry | sed -e "s/^/\t/" if [ -z "${prepare_boot_cache}" ]; then prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")" diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in index 3ecf454e2..2c60bc681 100644 --- a/util/grub.d/10_linux.in +++ b/util/grub.d/10_linux.in @@ -22,14 +22,16 @@ bindir=@bindir@ libdir=@libdir@ . ${libdir}/grub/grub-mkconfig_lib -. ${bindir}/gettext.sh export TEXTDOMAIN=@PACKAGE@ -export TEXTDOMAINDIR=@localedir@ +export TEXTDOMAINDIR=@LOCALEDIR@ + +CLASS="--class gnu-linux --class gnu --class os" if [ "x${GRUB_DISTRIBUTOR}" = "x" ] ; then OS=GNU/Linux else OS="${GRUB_DISTRIBUTOR} GNU/Linux" + CLASS="--class $(echo ${GRUB_DISTRIBUTOR} | tr '[A-Z]' '[a-z]') ${CLASS}" fi # loop-AES arranges things so that /dev/loop/X can be our root device, but @@ -58,8 +60,24 @@ linux_entry () else title="$(gettext "%s, with Linux %s")" fi - printf "menuentry \"${title}\" {\n" "${os}" "${version}" + printf "menuentry \"${title}\" ${CLASS} {\n" "${os}" "${version}" save_default_entry | sed -e "s/^/\t/" + + # 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 + 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 + set gfxpayload=keep +EOF + fi + else + cat << EOF + set gfxpayload=$GRUB_GFXPAYLOAD_LINUX +EOF + fi + if [ -z "${prepare_boot_cache}" ]; then prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")" fi diff --git a/util/hostdisk.c b/util/hostdisk.c index c94f4237e..98d3d53ae 100644 --- a/util/hostdisk.c +++ b/util/hostdisk.c @@ -137,7 +137,7 @@ find_grub_drive (const char *name) } static int -find_free_slot () +find_free_slot (void) { unsigned int i; @@ -336,11 +336,12 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags) char dev[PATH_MAX]; strcpy (dev, map[disk->id].device); - if (disk->partition && strncmp (map[disk->id].device, "/dev/", 5) == 0) + if (disk->partition && sector >= disk->partition->start + && strncmp (map[disk->id].device, "/dev/", 5) == 0) is_partition = linux_find_partition (dev, disk->partition->start); /* Open the partition. */ - grub_dprintf ("hostdisk", "opening the device `%s' in open_device()", dev); + grub_dprintf ("hostdisk", "opening the device `%s' in open_device()\n", dev); fd = open (dev, flags); if (fd < 0) { @@ -490,6 +491,23 @@ grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector, { int fd; + /* Split pre-partition and partition reads. */ + if (disk->partition && sector < disk->partition->start + && sector + size > disk->partition->start) + { + grub_err_t err; + err = grub_util_biosdisk_read (disk, sector, + disk->partition->start - sector, + buf); + if (err) + return err; + + return grub_util_biosdisk_read (disk, disk->partition->start, + size - (disk->partition->start - sector), + buf + ((disk->partition->start - sector) + << GRUB_DISK_SECTOR_BITS)); + } + fd = open_device (disk, sector, O_RDONLY); if (fd < 0) return grub_errno; @@ -527,6 +545,23 @@ grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector, { int fd; + /* Split pre-partition and partition writes. */ + if (disk->partition && sector < disk->partition->start + && sector + size > disk->partition->start) + { + grub_err_t err; + err = grub_util_biosdisk_write (disk, sector, + disk->partition->start - sector, + buf); + if (err) + return err; + + return grub_util_biosdisk_write (disk, disk->partition->start, + size - (disk->partition->start - sector), + buf + ((disk->partition->start - sector) + << GRUB_DISK_SECTOR_BITS)); + } + fd = open_device (disk, sector, O_WRONLY); if (fd < 0) return grub_errno; @@ -568,7 +603,7 @@ read_device_map (const char *dev_map) fp = fopen (dev_map, "r"); if (! fp) { - grub_util_info (_("Cannot open `%s'"), dev_map); + grub_util_info (_("cannot open `%s'"), dev_map); return; } @@ -639,7 +674,7 @@ read_device_map (const char *dev_map) symbolic links. */ map[drive].device = xmalloc (PATH_MAX); if (! realpath (p, map[drive].device)) - grub_util_error ("Cannot get the real path of `%s'", p); + grub_util_error ("cannot get the real path of `%s'", p); #else map[drive].device = xstrdup (p); #endif @@ -946,10 +981,10 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev) struct hd_geometry hdg; int dos_part = -1; int bsd_part = -1; - auto int find_partition (grub_disk_t disk, + auto int find_partition (grub_disk_t dsk, const grub_partition_t partition); - int find_partition (grub_disk_t disk __attribute__ ((unused)), + int find_partition (grub_disk_t dsk __attribute__ ((unused)), const grub_partition_t partition) { struct grub_msdos_partition *pcdata = NULL; diff --git a/util/hostfs.c b/util/hostfs.c index df930b42e..501ad4664 100644 --- a/util/hostfs.c +++ b/util/hostfs.c @@ -1,7 +1,7 @@ /* hostfs.c - Dummy filesystem to provide access to the hosts filesystem */ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2007,2008,2009 Free Software Foundation, Inc. + * Copyright (C) 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 @@ -26,6 +26,7 @@ #include #include +#include /* dirent.d_type is a BSD extension, not part of POSIX */ @@ -118,10 +119,17 @@ grub_hostfs_read (grub_file_t file, char *buf, grub_size_t len) FILE *f; f = (FILE *) file->data; - fseeko (f, file->offset, SEEK_SET); - int s = fread (buf, 1, len, f); + if (fseeko (f, file->offset, SEEK_SET) != 0) + { + grub_error (GRUB_ERR_OUT_OF_RANGE, "fseeko: %s", strerror (errno)); + return -1; + } - return s; + unsigned int s = fread (buf, 1, len, f); + if (s != len) + grub_error (GRUB_ERR_FILE_READ_ERROR, "fread: %s", strerror (errno)); + + return (signed) s; } static grub_err_t diff --git a/util/i386/efi/grub-install.in b/util/i386/efi/grub-install.in index caa7be7e4..6a8573e81 100644 --- a/util/i386/efi/grub-install.in +++ b/util/i386/efi/grub-install.in @@ -180,6 +180,14 @@ for file in ${pkglibdir}/*.mod ${pkglibdir}/*.lst; do cp -f $file ${grubdir} || exit 1 done +# Copy gettext files +mkdir -p ${grubdir}/locale/ +for file in ${grubdir}/locale/*.mo ${pkglibdir}/locale/*.mo; do + if test -f "$file"; then + cp -f "$file" ${grubdir}/locale/ + fi +done + if ! test -f ${grubdir}/grubenv; then $grub_editenv ${grubdir}/grubenv create fi diff --git a/util/i386/efi/grub-mkimage.c b/util/i386/efi/grub-mkimage.c index 7f5141531..f8c0f152e 100644 --- a/util/i386/efi/grub-mkimage.c +++ b/util/i386/efi/grub-mkimage.c @@ -778,7 +778,7 @@ make_reloc_section (FILE *out, Elf_Addr current_address, Elf_Ehdr *e, if ((ELF_R_TYPE (info) == R_X86_64_32) || (ELF_R_TYPE (info) == R_X86_64_32S)) { - grub_util_error ("Can\'t add fixup entry for R_X86_64_32(S)"); + grub_util_error ("can\'t add fixup entry for R_X86_64_32(S)"); } else if (ELF_R_TYPE (info) == R_X86_64_64) { @@ -1029,10 +1029,10 @@ static void usage (int status) { if (status) - fprintf (stderr, "Try ``grub-mkimage --help'' for more information.\n"); + fprintf (stderr, "Try `%s --help' for more information.\n", program_name); else printf ("\ -Usage: grub-mkimage -o FILE [OPTION]... [MODULES]\n\ +Usage: %s -o FILE [OPTION]... [MODULES]\n\ \n\ Make a bootable image of GRUB.\n\ \n\ @@ -1044,7 +1044,7 @@ Make a bootable image of GRUB.\n\ -v, --verbose print verbose messages\n\ \n\ Report bugs to <%s>.\n\ -", GRUB_LIBDIR, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT); +", program_name, GRUB_LIBDIR, DEFAULT_DIRECTORY, PACKAGE_BUGREPORT); exit (status); } diff --git a/util/i386/pc/grub-setup.c b/util/i386/pc/grub-setup.c index 909a521eb..4e2517ef2 100644 --- a/util/i386/pc/grub-setup.c +++ b/util/i386/pc/grub-setup.c @@ -156,7 +156,7 @@ setup (const char *dir, sector, offset, length); if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("The first sector of the core file is not sector-aligned")); + grub_util_error (_("the first sector of the core file is not sector-aligned")); first_sector = sector; } @@ -170,7 +170,7 @@ setup (const char *dir, sector, offset, length, (unsigned) current_segment); if (offset != 0 || last_length != GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("Non-sector-aligned data is found in the core file")); + grub_util_error (_("non-sector-aligned data is found in the core file")); if (block != first_block && (grub_le_to_cpu64 (prev->start) @@ -184,7 +184,7 @@ setup (const char *dir, block--; if (block->len) - grub_util_error (_("The sectors of the core file are too fragmented")); + grub_util_error (_("the sectors of the core file are too fragmented")); } last_length = length; @@ -195,7 +195,7 @@ setup (const char *dir, boot_path = grub_util_get_path (dir, boot_file); boot_size = grub_util_get_image_size (boot_path); if (boot_size != GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("The size of `%s' is not %u"), + grub_util_error (_("the size of `%s' is not %u"), boot_path, GRUB_DISK_SECTOR_SIZE); boot_img = grub_util_read_image (boot_path); free (boot_path); @@ -212,9 +212,9 @@ setup (const char *dir, core_sectors = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS); if (core_size < GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("The size of `%s' is too small"), core_path); + grub_util_error (_("the size of `%s' is too small"), core_path); else if (core_size > 0xFFFF * GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("The size of `%s' is too large"), core_path); + grub_util_error (_("the size of `%s' is too large"), core_path); core_img = grub_util_read_image (core_path); @@ -251,7 +251,7 @@ setup (const char *dir, grub_fs_t fs; fs = grub_fs_probe (dest_dev); if (! fs) - grub_util_error (_("Unable to identify a filesystem in %s; safety check can't be performed"), + grub_util_error (_("unable to identify a filesystem in %s; safety check can't be performed"), dest_dev->disk->name); if (! fs->reserved_first_sector) @@ -304,7 +304,7 @@ setup (const char *dir, bsd_part = -1; } else - grub_util_error (_("No DOS-style partitions found")); + grub_util_error (_("no DOS-style partitions found")); } else dos_part = bsd_part = -1; @@ -413,14 +413,14 @@ setup (const char *dir, unable_to_embed: if (must_embed) - grub_util_error (_("Embedding is not possible, but this is required when " - "the root device is on a RAID array or LVM volume.")); + grub_util_error (_("embedding is not possible, but this is required when " + "the root device is on a RAID array or LVM volume")); grub_util_warn (_("Embedding is not possible. GRUB can only be installed in this " "setup by using blocklists. However, blocklists are UNRELIABLE and " "its use is discouraged.")); if (! force) - grub_util_error (_("If you really want blocklists, use --force.")); + grub_util_error (_("if you really want blocklists, use --force")); /* Make sure that GRUB reads the identical image as the OS. */ tmp_img = xmalloc (core_size); @@ -495,7 +495,7 @@ unable_to_embed: } if (i == MAX_TRIES) - grub_util_error (_("Cannot read `%s' correctly"), core_path_dev); + grub_util_error (_("cannot read `%s' correctly"), core_path_dev); /* Clean out the blocklists. */ block = first_block; @@ -508,7 +508,7 @@ unable_to_embed: block--; if ((char *) block <= core_img) - grub_util_error (_("No terminator in the core image")); + grub_util_error (_("no terminator in the core image")); } /* Now read the core image to determine where the sectors are. */ @@ -519,13 +519,13 @@ unable_to_embed: file->read_hook = save_first_sector; if (grub_file_read (file, tmp_img, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("Failed to read the first sector of the core image")); + grub_util_error (_("failed to read the first sector of the core image")); block = first_block; file->read_hook = save_blocklists; if (grub_file_read (file, tmp_img, core_size - GRUB_DISK_SECTOR_SIZE) != (grub_ssize_t) core_size - GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("Failed to read the rest sectors of the core image")); + grub_util_error (_("failed to read the rest sectors of the core image")); grub_file_close (file); @@ -544,7 +544,7 @@ unable_to_embed: grub_util_info ("opening the core image `%s'", core_path); fp = fopen (core_path, "r+b"); if (! fp) - grub_util_error (_("Cannot open `%s'"), core_path); + grub_util_error (_("cannot open `%s'"), core_path); grub_util_write_image (core_img, GRUB_DISK_SECTOR_SIZE * 2, fp); fclose (fp); @@ -584,13 +584,13 @@ static void usage (int status) { if (status) - fprintf (stderr, _("Try ``%s --help'' for more information.\n"), program_name); + fprintf (stderr, _("Try `%s --help' for more information.\n"), program_name); else printf (_("\ -Usage: grub-setup [OPTION]... DEVICE\n\ +Usage: %s [OPTION]... DEVICE\n\ \n\ Set up images to boot from DEVICE.\n\ -DEVICE must be a GRUB device (e.g. ``(hd0,1)'').\n\ +DEVICE must be a GRUB device (e.g. `(hd0,1)').\n\ \n\ -b, --boot-image=FILE use FILE as the boot image [default=%s]\n\ -c, --core-image=FILE use FILE as the core image [default=%s]\n\ @@ -605,6 +605,7 @@ DEVICE must be a GRUB device (e.g. ``(hd0,1)'').\n\ \n\ Report bugs to <%s>.\n\ "), + program_name, DEFAULT_BOOT_FILE, DEFAULT_CORE_FILE, DEFAULT_DIRECTORY, DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT); @@ -751,7 +752,7 @@ main (int argc, char *argv[]) char *tmp = get_device_name (root_dev); if (! tmp) - grub_util_error (_("Invalid root device `%s'"), root_dev); + grub_util_error (_("invalid root device `%s'"), root_dev); tmp = xstrdup (tmp); free (root_dev); @@ -764,7 +765,7 @@ main (int argc, char *argv[]) { grub_util_info ("guessing the root device failed, because of `%s'", grub_errmsg); - grub_util_error (_("Cannot guess the root device. Specify the option ``--root-device''.")); + grub_util_error (_("cannot guess the root device. Specify the option `--root-device'")); } } diff --git a/util/ieee1275/grub-install.in b/util/ieee1275/grub-install.in index 9a26b0dca..97c485d55 100644 --- a/util/ieee1275/grub-install.in +++ b/util/ieee1275/grub-install.in @@ -46,8 +46,8 @@ install_device= debug=no update_nvram=yes -ofpathname=/usr/sbin/ofpathname -nvsetenv=/sbin/nvsetenv +ofpathname=`which ofpathname` +nvsetenv=`which nvsetenv` # Usage: usage # Print the usage. @@ -216,11 +216,11 @@ if test $update_nvram = yes; then } # Point boot-device at the new grub install - boot_device="boot-device $ofpath:$partno,\\grub" - "$nvsetenv" "$boot_device" || { + boot_device="$ofpath:$partno,\\grub" + "$nvsetenv" boot-device "$boot_device" || { echo "$nvsetenv failed." echo "You will have to set boot-device manually. At the Open Firmware prompt, type:" - echo " setenv $boot_device" + echo " setenv boot-device $boot_device" exit 1 } fi diff --git a/util/ieee1275/ofpath.c b/util/ieee1275/ofpath.c index e90488fc3..79a0e8be5 100644 --- a/util/ieee1275/ofpath.c +++ b/util/ieee1275/ofpath.c @@ -131,12 +131,12 @@ block_device_get_sysfs_path_and_link(const char *devicenode, snprintf(sysfs_path, sysfs_path_len, "/sys/block/%s", devicenode); if (!realpath (sysfs_path, rpath)) - grub_util_error ("Cannot get the real path of `%s'", sysfs_path); + grub_util_error ("cannot get the real path of `%s'", sysfs_path); strcat(rpath, "/device"); if (!realpath (rpath, sysfs_path)) - grub_util_error ("Cannot get the real path of `%s'", rpath); + grub_util_error ("cannot get the real path of `%s'", rpath); free (rpath); } @@ -247,12 +247,12 @@ vendor_is_ATA(const char *path) snprintf(buf, PATH_MAX, "%s/vendor", path); fd = open(buf, O_RDONLY); if (fd < 0) - grub_util_error ("Cannot open 'vendor' node of `%s'", path); + grub_util_error ("cannot open 'vendor' node of `%s'", path); memset(buf, 0, PATH_MAX); err = read(fd, buf, PATH_MAX); if (err < 0) - grub_util_error ("Cannot read 'vendor' node of `%s'", path); + grub_util_error ("cannot read 'vendor' node of `%s'", path); close(fd); @@ -288,7 +288,7 @@ check_sas (char *sysfs_path, int *tgt) fd = open(path, O_RDONLY); if (fd < 0) - grub_util_error("Cannot open SAS PHY ID '%s'\n", path); + grub_util_error("cannot open SAS PHY ID `%s'\n", path); memset (phy, 0, sizeof (phy)); read (fd, phy, sizeof (phy)); @@ -375,7 +375,7 @@ grub_util_devname_to_ofpath (char *devname) name_buf = xmalloc (PATH_MAX); name_buf = realpath (devname, name_buf); if (! name_buf) - grub_util_error ("Cannot get the real path of `%s'", devname); + grub_util_error ("cannot get the real path of `%s'", devname); device = get_basename (devname); devnode = strip_trailing_digits (devname); diff --git a/util/import_gcry.py b/util/import_gcry.py index d71924d53..b9c3edcde 100644 --- a/util/import_gcry.py +++ b/util/import_gcry.py @@ -62,6 +62,7 @@ mdblocksizes = {"_gcry_digest_spec_crc32" : 64, "_gcry_digest_spec_whirlpool" : 64} cryptolist = open (os.path.join (cipher_dir_out, "crypto.lst"), "w") +conf.write ("MAINTAINER_CLEANFILES += $(srcdir)/conf/gcry.rmk $(srcdir)/lib/libgcrypt-grub/cipher/ChangeLog $(srcdir)/lib/libgcrypt-grub/cipher/cipher.h $(srcdir)/lib/libgcrypt-grub/cipher/crypto.lst $(srcdir)/lib/libgcrypt-grub/cipher/g10lib.h $(srcdir)/lib/libgcrypt-grub/cipher/memory.h $(srcdir)/lib/libgcrypt-grub/cipher/types.h\n"); # rijndael is the only cipher using aliases. So no need for mangling, just # hardcode it @@ -87,6 +88,7 @@ for cipher_file in cipher_files: continue nch = False if re.match (".*\.[ch]$", cipher_file): + conf.write ("MAINTAINER_CLEANFILES += $(srcdir)/lib/libgcrypt-grub/cipher/" + cipher_file + "\n"); isc = re.match (".*\.c$", cipher_file) f = open (infile, "r") fw = open (outfile, "w") diff --git a/util/lvm.c b/util/lvm.c index 8a8ed1e4c..0a0916344 100644 --- a/util/lvm.c +++ b/util/lvm.c @@ -26,6 +26,8 @@ #include #include +#define LVM_DEV_MAPPER_STRING "/dev/mapper/" + int grub_util_lvm_isvolume (char *name) { @@ -33,10 +35,10 @@ grub_util_lvm_isvolume (char *name) struct stat st; int err; - devname = xmalloc (strlen (name) + 13); + devname = xmalloc (strlen (name) + sizeof (LVM_DEV_MAPPER_STRING)); - strcpy (devname, "/dev/mapper/"); - strcpy (devname+12, name); + strcpy (devname, LVM_DEV_MAPPER_STRING); + strcpy (devname + sizeof(LVM_DEV_MAPPER_STRING) - 1, name); err = stat (devname, &st); free (devname); diff --git a/util/misc.c b/util/misc.c index 47dd8c78d..8c79e8d9b 100644 --- a/util/misc.c +++ b/util/misc.c @@ -30,6 +30,9 @@ #include #include #include +#ifdef HAVE_LIMITS_H +#include +#endif #include #include @@ -40,6 +43,7 @@ #include #include +#define ENABLE_RELOCATABLE 0 #include "progname.h" /* Include malloc.h, only if memalign is available. It is known that @@ -60,11 +64,12 @@ grub_util_warn (const char *fmt, ...) { va_list ap; - fprintf (stderr, "%s: warn: ", program_name); + fprintf (stderr, _("%s: warn:"), program_name); + fprintf (stderr, " "); va_start (ap, fmt); vfprintf (stderr, fmt, ap); va_end (ap); - fputc ('\n', stderr); + fprintf (stderr, ".\n"); fflush (stderr); } @@ -75,11 +80,12 @@ grub_util_info (const char *fmt, ...) { va_list ap; - fprintf (stderr, "%s: info: ", program_name); + fprintf (stderr, _("%s: info:"), program_name); + fprintf (stderr, " "); va_start (ap, fmt); vfprintf (stderr, fmt, ap); va_end (ap); - fputc ('\n', stderr); + fprintf (stderr, ".\n"); fflush (stderr); } } @@ -89,11 +95,12 @@ grub_util_error (const char *fmt, ...) { va_list ap; - fprintf (stderr, "%s: error: ", program_name); + fprintf (stderr, _("%s: error:"), program_name); + fprintf (stderr, " "); va_start (ap, fmt); vfprintf (stderr, fmt, ap); va_end (ap); - fputc ('\n', stderr); + fprintf (stderr, ".\n"); exit (1); } @@ -136,13 +143,13 @@ char * xstrdup (const char *str) { size_t len; - char *dup; + char *newstr; len = strlen (str); - dup = (char *) xmalloc (len + 1); - memcpy (dup, str, len + 1); + newstr = (char *) xmalloc (len + 1); + memcpy (newstr, str, len + 1); - return dup; + return newstr; } char * @@ -365,11 +372,13 @@ grub_millisleep (grub_uint32_t ms) #endif +#if !(defined (__i386__) || defined (__x86_64__)) void grub_arch_sync_caches (void *address __attribute__ ((unused)), grub_size_t len __attribute__ ((unused))) { } +#endif #ifndef HAVE_VASPRINTF @@ -510,13 +519,13 @@ make_system_path_relative_to_its_root (const char *path) grub_util_error ("failed to get canonical path of %s", path); len = strlen (p) + 1; - buf = strdup (p); + buf = xstrdup (p); free (p); if (stat (buf, &st) < 0) grub_util_error ("cannot stat %s: %s", buf, strerror (errno)); - buf2 = strdup (buf); + buf2 = xstrdup (buf); num = st.st_dev; /* This loop sets offset to the number of chars of the root @@ -538,12 +547,16 @@ make_system_path_relative_to_its_root (const char *path) /* buf is another filesystem; we found it. */ if (st.st_dev != num) { - /* offset == 0 means path given is the mount point. */ + /* offset == 0 means path given is the mount point. + This works around special-casing of "/" in Un*x. This function never + prints trailing slashes (so that its output can be appended a slash + unconditionally). Each slash in is considered a preceding slash, and + therefore the root directory is an empty string. */ if (offset == 0) { free (buf); free (buf2); - return strdup ("/"); + return xstrdup (""); } else break; @@ -560,11 +573,19 @@ make_system_path_relative_to_its_root (const char *path) buf2[len - 1] = '\0'; len--; } - return buf2; + if (len > 1) + return buf2; + else + { + /* This means path given is just a backslash. As above + we have to return an empty string. */ + free (buf2); + return xstrdup (""); + } } } free (buf); - buf3 = strdup (buf2 + offset); + buf3 = xstrdup (buf2 + offset); free (buf2); len = strlen (buf3); diff --git a/util/mkisofs/eltorito.c b/util/mkisofs/eltorito.c index a134dfc48..1d2a715e0 100644 --- a/util/mkisofs/eltorito.c +++ b/util/mkisofs/eltorito.c @@ -288,7 +288,7 @@ void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc) struct eltorito_boot_info bi_table; bootimage = fopen (de->whole_name, "r+b"); if (bootimage == NULL) - error (1, errno, _("Error opening boot image file '%s' for update"), + error (1, errno, _("Error opening boot image file `%s' for update"), de->whole_name); /* Compute checksum of boot image, sans 64 bytes */ total_len = 0; @@ -296,7 +296,7 @@ void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc) while ((len = fread (csum_buffer, 1, SECTOR_SIZE, bootimage)) > 0) { if (total_len & 3) - error (1, 0, _("Odd alignment at non-end-of-file in boot image '%s'"), + error (1, 0, _("Odd alignment at non-end-of-file in boot image `%s'"), de->whole_name); if (total_len < 64) memset (csum_buffer, 0, 64 - total_len); @@ -308,7 +308,7 @@ void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc) } if (total_len != de->size) - error (1, 0, _("Boot image file '%s' changed unexpectedly"), + error (1, 0, _("Boot image file `%s' changed unexpectedly"), de->whole_name); /* End of file, set position to byte 8 */ fseeko (bootimage, (off_t) 8, SEEK_SET); diff --git a/util/mkisofs/rock.c b/util/mkisofs/rock.c index f18b0bd83..a7a39f774 100644 --- a/util/mkisofs/rock.c +++ b/util/mkisofs/rock.c @@ -306,7 +306,7 @@ int deep_opt; * the symbolic link won't fit into one SL System Use Field * print an error message and continue with splited one */ - fprintf (stderr, _("symbolic link ``%s'' too long for one SL System Use Field, splitting"), cpnt); + fprintf (stderr, _("symbolic link `%s' too long for one SL System Use Field, splitting"), cpnt); } if(MAYBE_ADD_CE_ENTRY(SL_SIZE + sl_bytes)) add_CE_entry(); } diff --git a/util/mkisofs/write.c b/util/mkisofs/write.c index 5447229c8..e1cdd213e 100644 --- a/util/mkisofs/write.c +++ b/util/mkisofs/write.c @@ -158,7 +158,7 @@ void FDECL4(xfwrite, void *, buffer, uint64_t, count, uint64_t, size, FILE *, fi sprintf(nbuf, "%s_%02d", outfile, idx++); file = freopen(nbuf, "wb", file); if (file == NULL) - error (1, errno, _("Cannot open '%s'"), nbuf); + error (1, errno, _("Cannot open `%s'"), nbuf); } while(count) diff --git a/util/pci.c b/util/pci.c index a0c1867be..420ae320b 100644 --- a/util/pci.c +++ b/util/pci.c @@ -26,7 +26,7 @@ grub_pci_make_address (grub_pci_device_t dev, int reg) { grub_pci_address_t ret; ret.dev = dev; - ret.pos = reg << 2; + ret.pos = reg; return ret; } diff --git a/util/raid.c b/util/raid.c index 83a0ee6e2..ec3ecd26e 100644 --- a/util/raid.c +++ b/util/raid.c @@ -50,7 +50,7 @@ grub_util_getdiskname (int major, int minor) else if (major == SCSI_DISK0_MAJOR) sprintf (name, "/dev/sd%c", 'a' + minor / 16); else - grub_util_error ("Unknown device number: %d, %d", major, minor); + grub_util_error ("unknown device number: %d, %d", major, minor); return name; } @@ -72,7 +72,7 @@ grub_util_raid_getmembers (char *name) fd = open (devname, O_RDONLY); if (fd == -1) - grub_util_error ("Can't open %s: %s", devname, strerror (errno)); + grub_util_error ("can't open %s: %s", devname, strerror (errno)); free (devname); @@ -81,7 +81,7 @@ grub_util_raid_getmembers (char *name) grub_util_error ("ioctl RAID_VERSION error: %s", strerror (errno)); if (version.major != 0 || version.minor != 90) - grub_util_error ("Unsupported RAID version: %d.%d", + grub_util_error ("unsupported RAID version: %d.%d", version.major, version.minor); ret = ioctl (fd, GET_ARRAY_INFO, &info); diff --git a/util/sdl.c b/util/sdl.c new file mode 100644 index 000000000..d261db6b0 --- /dev/null +++ b/util/sdl.c @@ -0,0 +1,237 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2005,2006,2007,2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#define grub_video_render_target grub_video_fbrender_target + +#include +#include +#include +#include +#include +#include +#include +#include + +static SDL_Surface *window = 0; +static struct grub_video_render_target *sdl_render_target; +static struct grub_video_mode_info mode_info; + +static grub_err_t +grub_video_sdl_set_palette (unsigned int start, unsigned int count, + struct grub_video_palette_data *palette_data); + +static grub_err_t +grub_video_sdl_init (void) +{ + window = 0; + + if (SDL_Init (SDL_INIT_VIDEO) < 0) + return grub_error (GRUB_ERR_BAD_DEVICE, "Couldn't init SDL: %s", + SDL_GetError ()); + + grub_memset (&mode_info, 0, sizeof (mode_info)); + + return grub_video_fb_init (); +} + +static grub_err_t +grub_video_sdl_fini (void) +{ + SDL_Quit (); + window = 0; + + grub_memset (&mode_info, 0, sizeof (mode_info)); + + return grub_video_fb_fini (); +} + +static inline unsigned int +get_mask_size (grub_uint32_t mask) +{ + unsigned i; + for (i = 0; mask > 1U << i; i++); + return i; +} + +static grub_err_t +grub_video_sdl_setup (unsigned int width, unsigned int height, + unsigned int mode_type, unsigned int mode_mask) +{ + int depth; + int flags = 0; + grub_err_t err; + + /* 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 (depth == 0) + depth = 32; + + if (width == 0 && height == 0) + { + width = 800; + height = 600; + } + + if ((mode_type & GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED) + || !(mode_mask & GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED)) + flags |= SDL_DOUBLEBUF; + + window = SDL_SetVideoMode (width, height, depth, flags | SDL_HWSURFACE); + if (! window) + window = SDL_SetVideoMode (width, height, depth, flags | SDL_SWSURFACE); + if (! window) + return grub_error (GRUB_ERR_BAD_DEVICE, "Couldn't open window: %s", + SDL_GetError ()); + + grub_memset (&sdl_render_target, 0, sizeof (sdl_render_target)); + + mode_info.width = window->w; + mode_info.height = window->h; + mode_info.mode_type = 0; + if (window->flags & SDL_DOUBLEBUF) + mode_info.mode_type + |= GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED; + if (window->format->palette) + mode_info.mode_type |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; + else + mode_info.mode_type |= GRUB_VIDEO_MODE_TYPE_RGB; + + mode_info.bpp = window->format->BitsPerPixel; + mode_info.bytes_per_pixel = window->format->BytesPerPixel; + mode_info.pitch = window->pitch; + + /* In index color mode, number of colors. In RGB mode this is 256. */ + if (window->format->palette) + mode_info.number_of_colors + = 1 << window->format->BitsPerPixel; + else + mode_info.number_of_colors = 256; + + if (! window->format->palette) + { + mode_info.red_mask_size + = get_mask_size (window->format->Rmask >> window->format->Rshift); + mode_info.red_field_pos = window->format->Rshift; + mode_info.green_mask_size + = get_mask_size (window->format->Gmask >> window->format->Gshift); + mode_info.green_field_pos = window->format->Gshift; + mode_info.blue_mask_size + = get_mask_size (window->format->Bmask >> window->format->Bshift); + mode_info.blue_field_pos = window->format->Bshift; + mode_info.reserved_mask_size + = get_mask_size (window->format->Amask >> window->format->Ashift); + mode_info.reserved_field_pos = window->format->Ashift; + mode_info.blit_format + = grub_video_get_blit_format (&mode_info); + } + + err = grub_video_fb_create_render_target_from_pointer (&sdl_render_target, + &mode_info, + window->pixels); + if (err) + return err; + + /* Copy default palette to initialize emulated palette. */ + grub_video_sdl_set_palette (0, (sizeof (grub_video_fbstd_colors) + / sizeof (grub_video_fbstd_colors[0])), + grub_video_fbstd_colors); + + /* Reset render target to SDL one. */ + return grub_video_fb_set_active_render_target (sdl_render_target); +} + +static grub_err_t +grub_video_sdl_set_palette (unsigned int start, unsigned int count, + struct grub_video_palette_data *palette_data) +{ + unsigned i; + if (window->format->palette) + { + SDL_Color *tmp = grub_malloc (count * sizeof (tmp[0])); + for (i = 0; i < count; i++) + { + tmp[i].r = palette_data[i].r; + tmp[i].g = palette_data[i].g; + tmp[i].b = palette_data[i].b; + tmp[i].unused = palette_data[i].a; + } + SDL_SetColors (window, tmp, start, count); + grub_free (tmp); + } + + return grub_video_fb_set_palette (start, count, palette_data); +} + +static grub_err_t +grub_video_sdl_swap_buffers (void) +{ + if (SDL_Flip (window) < 0) + return grub_error (GRUB_ERR_BAD_DEVICE, "couldn't swap buffers: %s", + SDL_GetError ()); + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_video_sdl_set_active_render_target (struct grub_video_render_target *target) +{ + if (target == GRUB_VIDEO_RENDER_TARGET_DISPLAY) + return grub_video_fb_set_active_render_target (sdl_render_target); + + return grub_video_fb_set_active_render_target (target); +} + +static struct grub_video_adapter grub_video_sdl_adapter = + { + .name = "SDL Video Driver", + + .init = grub_video_sdl_init, + .fini = grub_video_sdl_fini, + .setup = grub_video_sdl_setup, + .get_info = grub_video_fb_get_info, + .set_palette = grub_video_sdl_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_sdl_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_sdl_set_active_render_target, + .get_active_render_target = grub_video_fb_get_active_render_target, + + .next = 0 + }; + +GRUB_MOD_INIT(sdl) +{ + grub_video_register (&grub_video_sdl_adapter); +} + +GRUB_MOD_FINI(sdl) +{ + grub_video_unregister (&grub_video_sdl_adapter); +} diff --git a/util/sparc64/ieee1275/grub-mkimage.c b/util/sparc64/ieee1275/grub-mkimage.c index 96ddfe3d7..6907b8d8a 100644 --- a/util/sparc64/ieee1275/grub-mkimage.c +++ b/util/sparc64/ieee1275/grub-mkimage.c @@ -191,7 +191,7 @@ static void usage (int status) { if (status) - fprintf (stderr, "Try ``%s --help'' for more information.\n", program_name); + fprintf (stderr, "Try `%s --help' for more information.\n", program_name); else printf ("\ Usage: %s [OPTION]... [MODULES]\n\ diff --git a/util/sparc64/ieee1275/grub-setup.c b/util/sparc64/ieee1275/grub-setup.c index 9d8e67562..c39ea853f 100644 --- a/util/sparc64/ieee1275/grub-setup.c +++ b/util/sparc64/ieee1275/grub-setup.c @@ -161,7 +161,7 @@ setup (const char *prefix, const char *dir, grub_util_info ("first sector is <%llu,%u,%u>", sector, offset, length); if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE) - grub_util_error ("The first sector of the core file " + grub_util_error ("the first sector of the core file " "is not sector-aligned"); first_sector = sector; @@ -176,7 +176,7 @@ setup (const char *prefix, const char *dir, grub_util_info ("saving <%llu,%u,%u>", sector, offset, length); if (offset != 0 || last_length != GRUB_DISK_SECTOR_SIZE) - grub_util_error ("Non-sector-aligned data is found in the core file"); + grub_util_error ("non-sector-aligned data is found in the core file"); if (block != first_block && (grub_be_to_cpu64 (prev->start) @@ -189,7 +189,7 @@ setup (const char *prefix, const char *dir, block--; if (block->len) - grub_util_error ("The sectors of the core file are too fragmented"); + grub_util_error ("the sectors of the core file are too fragmented"); } last_length = length; @@ -201,7 +201,7 @@ setup (const char *prefix, const char *dir, boot_path = grub_util_get_path (dir, boot_file); boot_size = grub_util_get_image_size (boot_path); if (boot_size != GRUB_DISK_SECTOR_SIZE) - grub_util_error ("The size of `%s' is not %d", + grub_util_error ("the size of `%s' is not %d", boot_path, GRUB_DISK_SECTOR_SIZE); boot_img = grub_util_read_image (boot_path); free (boot_path); @@ -219,7 +219,7 @@ setup (const char *prefix, const char *dir, core_sectors = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) >> GRUB_DISK_SECTOR_BITS); if (core_size < GRUB_DISK_SECTOR_SIZE) - grub_util_error ("The size of `%s' is too small", core_path); + grub_util_error ("the size of `%s' is too small", core_path); core_img = grub_util_read_image (core_path); free (core_path); @@ -229,7 +229,7 @@ setup (const char *prefix, const char *dir, + GRUB_DISK_SECTOR_SIZE - sizeof (*block)); - grub_util_info ("root is '%s', dest is '%s', and dest_ofpath is '%s'", + grub_util_info ("root is `%s', dest is `%s', and dest_ofpath is `%s'", root, dest, dest_ofpath); /* Open the root device and the destination device. */ @@ -320,7 +320,7 @@ setup (const char *prefix, const char *dir, } if (i == MAX_TRIES) - grub_util_error ("Cannot read `%s' correctly", core_path); + grub_util_error ("cannot read `%s' correctly", core_path); /* Clean out the blocklists. */ block = first_block; @@ -332,7 +332,7 @@ setup (const char *prefix, const char *dir, block--; if ((char *) block <= core_img) - grub_util_error ("No terminator in the core image"); + grub_util_error ("no terminator in the core image"); } /* Now read the core image to determine where the sectors are. */ @@ -343,13 +343,13 @@ setup (const char *prefix, const char *dir, file->read_hook = save_first_sector; if (grub_file_read (file, tmp_img, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE) - grub_util_error ("Failed to read the first sector of the core image"); + grub_util_error ("failed to read the first sector of the core image"); block = first_block; file->read_hook = save_blocklists; if (grub_file_read (file, tmp_img, core_size - GRUB_DISK_SECTOR_SIZE) != (grub_ssize_t) core_size - GRUB_DISK_SECTOR_SIZE) - grub_util_error ("Failed to read the rest sectors of the core image"); + grub_util_error ("failed to read the rest sectors of the core image"); grub_file_close (file); @@ -368,7 +368,7 @@ setup (const char *prefix, const char *dir, grub_util_info ("opening the core image `%s'", core_path); fp = fopen (core_path, "r+b"); if (! fp) - grub_util_error ("Cannot open `%s'", core_path); + grub_util_error ("cannot open `%s'", core_path); grub_util_write_image (core_img, GRUB_DISK_SECTOR_SIZE, fp); fclose (fp); @@ -404,13 +404,13 @@ static void usage (int status) { if (status) - fprintf (stderr, "Try ``%s --help'' for more information.\n", program_name); + fprintf (stderr, "Try `%s --help' for more information.\n", program_name); else printf ("\ Usage: %s [OPTION]... DEVICE\n\ \n\ Set up images to boot from DEVICE.\n\ -DEVICE must be a GRUB device (e.g. ``(hd0,1)'').\n\ +DEVICE must be a GRUB device (e.g. `(hd0,1)').\n\ \n\ -b, --boot-image=FILE use FILE as the boot image [default=%s]\n\ -c, --core-image=FILE use FILE as the core image [default=%s]\n\ @@ -559,14 +559,14 @@ find_dest_dev (struct grub_setup_info *gp, char *argv[]) fprintf (stderr, "Invalid device `%s'.\n", argv[optind]); usage (1); } - grub_util_info ("transformed OS device '%s' into GRUB device '%s'", + grub_util_info ("transformed OS device `%s' into GRUB device `%s'", argv[optind], gp->dest_dev); } else { /* For simplicity. */ gp->dest_dev = xstrdup (gp->dest_dev); - grub_util_info ("Using '%s' as GRUB device", gp->dest_dev); + grub_util_info ("Using `%s' as GRUB device", gp->dest_dev); } } @@ -578,7 +578,7 @@ check_root_dev (struct grub_setup_info *gp) char *tmp = get_device_name (gp->root_dev); if (! tmp) - grub_util_error ("Invalid root device `%s'", gp->root_dev); + grub_util_error ("invalid root device `%s'", gp->root_dev); tmp = xstrdup (tmp); free (gp->root_dev); @@ -594,11 +594,11 @@ check_root_dev (struct grub_setup_info *gp) { grub_util_info ("guessing the root device failed, because of `%s'", grub_errmsg); - grub_util_error ("Cannot guess the root device. " - "Specify the option ``--root-device''."); + grub_util_error ("cannot guess the root device. " + "Specify the option `--root-device'"); } - grub_util_info ("Guessed root device '%s' and root_dev '%s' from " - "dir '%s'", root_device, gp->root_dev, dir); + grub_util_info ("guessed root device `%s' and root_dev `%s' from " + "dir `%s'", root_device, gp->root_dev, dir); } } diff --git a/video/bitmap_scale.c b/video/bitmap_scale.c new file mode 100644 index 000000000..6f8ff247e --- /dev/null +++ b/video/bitmap_scale.c @@ -0,0 +1,308 @@ +/* bitmap_scale.c - Bitmap scaling. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2006,2007,2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include + +/* Prototypes for module-local functions. */ +static grub_err_t scale_nn (struct grub_video_bitmap *dst, + struct grub_video_bitmap *src); +static grub_err_t scale_bilinear (struct grub_video_bitmap *dst, + struct grub_video_bitmap *src); + +/* This function creates a new scaled version of the bitmap SRC. The new + bitmap has dimensions DST_WIDTH by DST_HEIGHT. The scaling algorithm + is given by SCALE_METHOD. If an error is encountered, the return code is + not equal to GRUB_ERR_NONE, and the bitmap DST is either not created, or + it is destroyed before this function returns. + + Supports only direct color modes which have components separated + into bytes (e.g., RGBA 8:8:8:8 or BGR 8:8:8 true color). + But because of this simplifying assumption, the implementation is + greatly simplified. */ +grub_err_t +grub_video_bitmap_create_scaled (struct grub_video_bitmap **dst, + int dst_width, int dst_height, + struct grub_video_bitmap *src, + enum grub_video_bitmap_scale_method + scale_method) +{ + *dst = 0; + + /* Verify the simplifying assumptions. */ + if (src == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "null src bitmap in grub_video_bitmap_create_scaled"); + if (src->mode_info.red_field_pos % 8 != 0 + || src->mode_info.green_field_pos % 8 != 0 + || src->mode_info.blue_field_pos % 8 != 0 + || src->mode_info.reserved_field_pos % 8 != 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "src format not supported for scale"); + if (src->mode_info.width == 0 || src->mode_info.height == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "source bitmap has a zero dimension"); + if (dst_width <= 0 || dst_height <= 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "requested to scale to a size w/ a zero dimension"); + if (src->mode_info.bytes_per_pixel * 8 != src->mode_info.bpp) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "bitmap to scale has inconsistent Bpp and bpp"); + + /* Create the new bitmap. */ + grub_err_t ret; + ret = grub_video_bitmap_create (dst, dst_width, dst_height, + src->mode_info.blit_format); + if (ret != GRUB_ERR_NONE) + return ret; /* Error. */ + + switch (scale_method) + { + case GRUB_VIDEO_BITMAP_SCALE_METHOD_FASTEST: + case GRUB_VIDEO_BITMAP_SCALE_METHOD_NEAREST: + ret = scale_nn (*dst, src); + break; + case GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST: + case GRUB_VIDEO_BITMAP_SCALE_METHOD_BILINEAR: + ret = scale_bilinear (*dst, src); + break; + default: + ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid scale_method value"); + break; + } + + if (ret == GRUB_ERR_NONE) + { + /* Success: *dst is now a pointer to the scaled bitmap. */ + return GRUB_ERR_NONE; + } + else + { + /* Destroy the bitmap and return the error code. */ + grub_video_bitmap_destroy (*dst); + *dst = 0; + return ret; + } +} + +/* Nearest neighbor bitmap scaling algorithm. + + Copy the bitmap SRC to the bitmap DST, scaling the bitmap to fit the + dimensions of DST. This function uses the nearest neighbor algorithm to + interpolate the pixels. + + Supports only direct color modes which have components separated + into bytes (e.g., RGBA 8:8:8:8 or BGR 8:8:8 true color). + But because of this simplifying assumption, the implementation is + greatly simplified. */ +static grub_err_t +scale_nn (struct grub_video_bitmap *dst, struct grub_video_bitmap *src) +{ + /* Verify the simplifying assumptions. */ + if (dst == 0 || src == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "null bitmap in scale_nn"); + if (dst->mode_info.red_field_pos % 8 != 0 + || dst->mode_info.green_field_pos % 8 != 0 + || dst->mode_info.blue_field_pos % 8 != 0 + || dst->mode_info.reserved_field_pos % 8 != 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "dst format not supported"); + if (src->mode_info.red_field_pos % 8 != 0 + || src->mode_info.green_field_pos % 8 != 0 + || src->mode_info.blue_field_pos % 8 != 0 + || src->mode_info.reserved_field_pos % 8 != 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "src format not supported"); + if (dst->mode_info.red_field_pos != src->mode_info.red_field_pos + || dst->mode_info.red_mask_size != src->mode_info.red_mask_size + || dst->mode_info.green_field_pos != src->mode_info.green_field_pos + || dst->mode_info.green_mask_size != src->mode_info.green_mask_size + || dst->mode_info.blue_field_pos != src->mode_info.blue_field_pos + || dst->mode_info.blue_mask_size != src->mode_info.blue_mask_size + || dst->mode_info.reserved_field_pos != + src->mode_info.reserved_field_pos + || dst->mode_info.reserved_mask_size != + src->mode_info.reserved_mask_size) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "dst and src not compatible"); + if (dst->mode_info.bytes_per_pixel != src->mode_info.bytes_per_pixel) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "dst and src not compatible"); + if (dst->mode_info.width == 0 || dst->mode_info.height == 0 + || src->mode_info.width == 0 || src->mode_info.height == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "bitmap has a zero dimension"); + + grub_uint8_t *ddata = dst->data; + grub_uint8_t *sdata = src->data; + int dw = dst->mode_info.width; + int dh = dst->mode_info.height; + int sw = src->mode_info.width; + int sh = src->mode_info.height; + int dstride = dst->mode_info.pitch; + int sstride = src->mode_info.pitch; + /* bytes_per_pixel is the same for both src and dst. */ + int bytes_per_pixel = dst->mode_info.bytes_per_pixel; + + int dy; + for (dy = 0; dy < dh; dy++) + { + int dx; + for (dx = 0; dx < dw; dx++) + { + grub_uint8_t *dptr; + grub_uint8_t *sptr; + int sx; + int sy; + int comp; + + /* Compute the source coordinate that the destination coordinate + maps to. Note: sx/sw = dx/dw => sx = sw*dx/dw. */ + sx = sw * dx / dw; + sy = sh * dy / dh; + + /* Get the address of the pixels in src and dst. */ + dptr = ddata + dy * dstride + dx * bytes_per_pixel; + sptr = sdata + sy * sstride + sx * bytes_per_pixel; + + /* Copy the pixel color value. */ + for (comp = 0; comp < bytes_per_pixel; comp++) + dptr[comp] = sptr[comp]; + } + } + return GRUB_ERR_NONE; +} + +/* Bilinear interpolation image scaling algorithm. + + Copy the bitmap SRC to the bitmap DST, scaling the bitmap to fit the + dimensions of DST. This function uses the bilinear interpolation algorithm + to interpolate the pixels. + + Supports only direct color modes which have components separated + into bytes (e.g., RGBA 8:8:8:8 or BGR 8:8:8 true color). + But because of this simplifying assumption, the implementation is + greatly simplified. */ +static grub_err_t +scale_bilinear (struct grub_video_bitmap *dst, struct grub_video_bitmap *src) +{ + /* Verify the simplifying assumptions. */ + if (dst == 0 || src == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "null bitmap in scale func"); + if (dst->mode_info.red_field_pos % 8 != 0 + || dst->mode_info.green_field_pos % 8 != 0 + || dst->mode_info.blue_field_pos % 8 != 0 + || dst->mode_info.reserved_field_pos % 8 != 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "dst format not supported"); + if (src->mode_info.red_field_pos % 8 != 0 + || src->mode_info.green_field_pos % 8 != 0 + || src->mode_info.blue_field_pos % 8 != 0 + || src->mode_info.reserved_field_pos % 8 != 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "src format not supported"); + if (dst->mode_info.red_field_pos != src->mode_info.red_field_pos + || dst->mode_info.red_mask_size != src->mode_info.red_mask_size + || dst->mode_info.green_field_pos != src->mode_info.green_field_pos + || dst->mode_info.green_mask_size != src->mode_info.green_mask_size + || dst->mode_info.blue_field_pos != src->mode_info.blue_field_pos + || dst->mode_info.blue_mask_size != src->mode_info.blue_mask_size + || dst->mode_info.reserved_field_pos != + src->mode_info.reserved_field_pos + || dst->mode_info.reserved_mask_size != + src->mode_info.reserved_mask_size) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "dst and src not compatible"); + if (dst->mode_info.bytes_per_pixel != src->mode_info.bytes_per_pixel) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "dst and src not compatible"); + if (dst->mode_info.width == 0 || dst->mode_info.height == 0 + || src->mode_info.width == 0 || src->mode_info.height == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "bitmap has a zero dimension"); + + grub_uint8_t *ddata = dst->data; + grub_uint8_t *sdata = src->data; + int dw = dst->mode_info.width; + int dh = dst->mode_info.height; + int sw = src->mode_info.width; + int sh = src->mode_info.height; + int dstride = dst->mode_info.pitch; + int sstride = src->mode_info.pitch; + /* bytes_per_pixel is the same for both src and dst. */ + int bytes_per_pixel = dst->mode_info.bytes_per_pixel; + + int dy; + for (dy = 0; dy < dh; dy++) + { + int dx; + for (dx = 0; dx < dw; dx++) + { + grub_uint8_t *dptr; + grub_uint8_t *sptr; + int sx; + int sy; + int comp; + + /* Compute the source coordinate that the destination coordinate + maps to. Note: sx/sw = dx/dw => sx = sw*dx/dw. */ + sx = sw * dx / dw; + sy = sh * dy / dh; + + /* Get the address of the pixels in src and dst. */ + dptr = ddata + dy * dstride + dx * bytes_per_pixel; + sptr = sdata + sy * sstride + sx * bytes_per_pixel; + + /* If we have enough space to do so, use bilinear interpolation. + Otherwise, fall back to nearest neighbor for this pixel. */ + if (sx < sw - 1 && sy < sh - 1) + { + /* Do bilinear interpolation. */ + + /* Fixed-point .8 numbers representing the fraction of the + distance in the x (u) and y (v) direction within the + box of 4 pixels in the source. */ + int u = (256 * sw * dx / dw) - (sx * 256); + int v = (256 * sh * dy / dh) - (sy * 256); + + for (comp = 0; comp < bytes_per_pixel; comp++) + { + /* Get the component's values for the + four source corner pixels. */ + grub_uint8_t f00 = sptr[comp]; + grub_uint8_t f10 = sptr[comp + bytes_per_pixel]; + grub_uint8_t f01 = sptr[comp + sstride]; + grub_uint8_t f11 = sptr[comp + sstride + bytes_per_pixel]; + + /* Do linear interpolations along the top and bottom + rows of the box. */ + grub_uint8_t f0y = (256 - v) * f00 / 256 + v * f01 / 256; + grub_uint8_t f1y = (256 - v) * f10 / 256 + v * f11 / 256; + + /* Interpolate vertically. */ + grub_uint8_t fxy = (256 - u) * f0y / 256 + u * f1y / 256; + + dptr[comp] = fxy; + } + } + else + { + /* Fall back to nearest neighbor interpolation. */ + /* Copy the pixel color value. */ + for (comp = 0; comp < bytes_per_pixel; comp++) + dptr[comp] = sptr[comp]; + } + } + } + return GRUB_ERR_NONE; +} diff --git a/video/efi_gop.c b/video/efi_gop.c index 13ef0ddae..86a2881f8 100644 --- a/video/efi_gop.c +++ b/video/efi_gop.c @@ -185,7 +185,7 @@ grub_video_gop_fill_mode_info (struct grub_efi_gop_mode_info *in, static grub_err_t grub_video_gop_setup (unsigned int width, unsigned int height, - unsigned int mode_type) + unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused))) { unsigned int depth; struct grub_efi_gop_mode_info *info = NULL; diff --git a/video/efi_uga.c b/video/efi_uga.c index 7ef7594cc..eb4e6b42e 100644 --- a/video/efi_uga.c +++ b/video/efi_uga.c @@ -92,7 +92,7 @@ find_framebuf (grub_uint32_t *fb_base, grub_uint32_t *line_len) { grub_pci_address_t addr; - addr = grub_pci_make_address (dev, 2); + addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); if (grub_pci_read (addr) >> 24 == 0x3) { int i; @@ -198,7 +198,7 @@ grub_video_uga_fini (void) static grub_err_t grub_video_uga_setup (unsigned int width, unsigned int height, - unsigned int mode_type) + unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused))) { unsigned int depth; int found = 0; diff --git a/video/fb/video_fb.c b/video/fb/video_fb.c index 5532a343c..9c5577bb9 100644 --- a/video/fb/video_fb.c +++ b/video/fb/video_fb.c @@ -66,6 +66,8 @@ grub_video_fb_init (void) grub_err_t grub_video_fb_fini (void) { + /* TODO: destroy render targets. */ + grub_free (palette); render_target = 0; palette = 0; @@ -974,32 +976,85 @@ grub_video_fb_scroll (grub_video_color_t color, int dx, int dy) { /* 3. Move data in render target. */ struct grub_video_fbblit_info target; - grub_uint8_t *src; - grub_uint8_t *dst; - int j; + int i, j; + int linedelta, linelen; target.mode_info = &render_target->mode_info; target.data = render_target->data; - /* Check vertical direction of the move. */ - if (dy <= 0) - /* 3a. Move data upwards. */ - for (j = 0; j < height; j++) - { - dst = grub_video_fb_get_video_ptr (&target, dst_x, dst_y + j); - src = grub_video_fb_get_video_ptr (&target, src_x, src_y + j); - grub_memmove (dst, src, - width * target.mode_info->bytes_per_pixel); - } + linedelta = target.mode_info->pitch + - width * target.mode_info->bytes_per_pixel; + linelen = width * target.mode_info->bytes_per_pixel; +#define DO_SCROLL \ + /* Check vertical direction of the move. */ \ + if (dy < 0 || (dy == 0 && dx < 0)) \ + { \ + dst = (void *) grub_video_fb_get_video_ptr (&target, \ + dst_x, dst_y); \ + src = (void *) grub_video_fb_get_video_ptr (&target, \ + src_x, src_y); \ + /* 3a. Move data upwards. */ \ + for (j = 0; j < height; j++) \ + { \ + for (i = 0; i < linelen; i++) \ + *(dst++) = *(src++); \ + dst += linedelta; \ + src += linedelta; \ + } \ + } \ + else \ + { \ + /* 3b. Move data downwards. */ \ + dst = (void *) grub_video_fb_get_video_ptr (&target, \ + dst_x + width, \ + dst_y + height - 1); \ + src = (void *) grub_video_fb_get_video_ptr (&target, \ + src_x + width, \ + src_y + height - 1); \ + dst--; \ + src--; \ + for (j = 0; j < height; j++) \ + { \ + for (i = 0; i < linelen; i++) \ + *(dst--) = *(src--); \ + dst -= linedelta; \ + src -= linedelta; \ + } \ + } + + /* If everything is aligned on 32-bit use 32-bit copy. */ + if ((grub_addr_t) grub_video_fb_get_video_ptr (&target, src_x, src_y) + % sizeof (grub_uint32_t) == 0 + && (grub_addr_t) grub_video_fb_get_video_ptr (&target, dst_x, dst_y) + % sizeof (grub_uint32_t) == 0 + && linelen % sizeof (grub_uint32_t) == 0 + && linedelta % sizeof (grub_uint32_t) == 0) + { + grub_uint32_t *src, *dst; + linelen /= sizeof (grub_uint32_t); + linedelta /= sizeof (grub_uint32_t); + DO_SCROLL + } + /* If everything is aligned on 16-bit use 16-bit copy. */ + else if ((grub_addr_t) grub_video_fb_get_video_ptr (&target, src_x, src_y) + % sizeof (grub_uint16_t) == 0 + && (grub_addr_t) grub_video_fb_get_video_ptr (&target, + dst_x, dst_y) + % sizeof (grub_uint16_t) == 0 + && linelen % sizeof (grub_uint16_t) == 0 + && linedelta % sizeof (grub_uint16_t) == 0) + { + grub_uint16_t *src, *dst; + linelen /= sizeof (grub_uint16_t); + linedelta /= sizeof (grub_uint16_t); + DO_SCROLL + } + /* If not aligned at all use 8-bit copy. */ else - /* 3b. Move data downwards. */ - for (j = (height - 1); j >= 0; j--) - { - dst = grub_video_fb_get_video_ptr (&target, dst_x, dst_y + j); - src = grub_video_fb_get_video_ptr (&target, src_x, src_y + j); - grub_memmove (dst, src, - width * target.mode_info->bytes_per_pixel); - } + { + grub_uint8_t *src, *dst; + DO_SCROLL + } } /* 4. Fill empty space with specified color. In this implementation @@ -1182,3 +1237,53 @@ grub_video_fb_get_active_render_target (struct grub_video_fbrender_target **targ return GRUB_ERR_NONE; } + +static grub_err_t +doublebuf_blit_update_screen (struct grub_video_fbrender_target *front, + struct grub_video_fbrender_target *back) +{ + grub_memcpy (front->data, back->data, + front->mode_info.pitch * front->mode_info.height); + return GRUB_ERR_NONE; +} + +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) + { + grub_video_fb_delete_render_target (*front); + *front = 0; + return grub_errno; + } + + err = grub_video_fb_create_render_target_from_pointer (back, &mode_info, + offscreen_buffer); + + if (err) + { + grub_video_fb_delete_render_target (*front); + grub_free (offscreen_buffer); + *front = 0; + return grub_errno; + } + (*back)->is_allocated = 1; + + *update_screen = doublebuf_blit_update_screen; + + return GRUB_ERR_NONE; +} diff --git a/video/i386/pc/vbe.c b/video/i386/pc/vbe.c index 918bab0b0..72b8f1831 100644 --- a/video/i386/pc/vbe.c +++ b/video/i386/pc/vbe.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -39,13 +40,25 @@ static grub_uint32_t last_set_mode = 3; static struct { struct grub_video_mode_info mode_info; - struct grub_video_render_target *render_target; + 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; @@ -350,6 +363,7 @@ static grub_err_t grub_video_vbe_fini (void) { grub_vbe_status_t status; + grub_err_t err; /* Restore old video mode. */ status = grub_vbe_bios_set_mode (initial_vbe_mode, 0); @@ -362,14 +376,193 @@ grub_video_vbe_fini (void) grub_free (vbe_mode_list); vbe_mode_list = NULL; - /* TODO: destroy render targets. */ + err = grub_video_fb_fini (); + grub_free (framebuffer.offscreen_buffer); + return err; +} - return grub_video_fb_fini (); +/* + Set framebuffer render target page and display the proper page, based on + `doublebuf_state.render_page' and `doublebuf_state.displayed_page', + respectively. +*/ +static grub_err_t +doublebuf_pageflipping_commit (void) +{ + /* Tell the video adapter to display the new front page. */ + int display_start_line + = framebuffer.mode_info.height * framebuffer.displayed_page; + + grub_vbe_status_t vbe_err = + grub_vbe_bios_set_display_start (0, display_start_line); + + if (vbe_err != GRUB_VBE_STATUS_OK) + return grub_error (GRUB_ERR_IO, "couldn't commit pageflip"); + + 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_type, unsigned int mode_mask) { grub_uint16_t *p; struct grub_vbe_mode_info_block vbe_mode_info; @@ -415,32 +608,40 @@ grub_video_vbe_setup (unsigned int width, unsigned int height, /* Not compatible memory model. */ continue; - if ((vbe_mode_info.x_resolution != width) - || (vbe_mode_info.y_resolution != height)) + if (((vbe_mode_info.x_resolution != width) + || (vbe_mode_info.y_resolution != height)) && width != 0 && height != 0) /* Non matching resolution. */ continue; /* Check if user requested RGB or index color mode. */ - if ((mode_type & GRUB_VIDEO_MODE_TYPE_COLOR_MASK) != 0) + if ((mode_mask & GRUB_VIDEO_MODE_TYPE_COLOR_MASK) != 0) { - if (((mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0) - && (vbe_mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL)) - /* Requested only index color modes. */ - continue; + unsigned my_mode_type = 0; - if (((mode_type & GRUB_VIDEO_MODE_TYPE_RGB) != 0) - && (vbe_mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR)) - /* Requested only RGB modes. */ - continue; + if (vbe_mode_info.memory_model == GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL) + my_mode_type |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; + + if (vbe_mode_info.memory_model == GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR) + my_mode_type |= GRUB_VIDEO_MODE_TYPE_RGB; + + if ((my_mode_type & mode_mask + & (GRUB_VIDEO_MODE_TYPE_RGB | GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)) + != (mode_type & mode_mask + & (GRUB_VIDEO_MODE_TYPE_RGB + | GRUB_VIDEO_MODE_TYPE_INDEX_COLOR))) + continue; } /* If there is a request for specific depth, ignore others. */ if ((depth != 0) && (vbe_mode_info.bits_per_pixel != depth)) continue; - /* Select mode with most number of bits per pixel. */ + /* Select mode with most of "volume" (size of framebuffer in bits). */ if (best_vbe_mode != 0) - if (vbe_mode_info.bits_per_pixel < best_vbe_mode_info.bits_per_pixel) + if ((grub_uint64_t) vbe_mode_info.bits_per_pixel + * vbe_mode_info.x_resolution * vbe_mode_info.y_resolution + < (grub_uint64_t) best_vbe_mode_info.bits_per_pixel + * best_vbe_mode_info.x_resolution * best_vbe_mode_info.y_resolution) continue; /* Save so far best mode information for later use. */ @@ -483,12 +684,12 @@ grub_video_vbe_setup (unsigned int width, unsigned int height, framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info); - err = grub_video_fb_create_render_target_from_pointer (&framebuffer.render_target, &framebuffer.mode_info, framebuffer.ptr); - + /* Set up double buffering and targets. */ + err = double_buffering_init (mode_type, mode_mask); if (err) return err; - err = grub_video_fb_set_active_render_target (framebuffer.render_target); + err = grub_video_fb_set_active_render_target (framebuffer.back_target); if (err) return err; @@ -525,7 +726,15 @@ grub_video_vbe_set_palette (unsigned int start, unsigned int count, static grub_err_t grub_video_vbe_swap_buffers (void) { - /* TODO: Implement buffer swapping. */ + 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; } @@ -533,27 +742,42 @@ 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.render_target; + 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; + *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; } - static struct grub_video_adapter grub_video_vbe_adapter = { .name = "VESA BIOS Extension Video Driver", @@ -580,7 +804,7 @@ static struct grub_video_adapter grub_video_vbe_adapter = .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_fb_get_active_render_target, + .get_active_render_target = grub_video_vbe_get_active_render_target, .next = 0 }; diff --git a/video/sm712.c b/video/sm712.c new file mode 100644 index 000000000..a86470b7d --- /dev/null +++ b/video/sm712.c @@ -0,0 +1,229 @@ +/* + * 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 + +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; +} framebuffer; + +static grub_err_t +grub_video_sm712_video_init (void) +{ + /* Reset frame buffer. */ + grub_memset (&framebuffer, 0, sizeof(framebuffer)); + + return grub_video_fb_init (); +} + +static grub_err_t +grub_video_sm712_video_fini (void) +{ + if (framebuffer.mapped) + grub_pci_device_unmap_range (framebuffer.dev, framebuffer.ptr, + 1024 * 600 * 2); + + return grub_video_fb_fini (); +} + +static grub_err_t +grub_video_sm712_setup (unsigned int width, unsigned int height, + unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused))) +{ + int depth; + grub_err_t err; + int found = 0; + + 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 __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 || pciid != 0x0712126f) + return 0; + + found = 1; + + addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0); + framebuffer.base = grub_pci_read (addr); + 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 != 1024 && width != 0) || (height != 600 && height != 0) + || (depth != 16 && depth != 0)) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "Only 1024x600x16 is supported"); + + 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 */ + } + + /* Fill mode info details. */ + framebuffer.mode_info.width = 1024; + framebuffer.mode_info.height = 600; + framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB; + framebuffer.mode_info.bpp = 16; + framebuffer.mode_info.bytes_per_pixel = 2; + framebuffer.mode_info.pitch = 1024 * 2; + framebuffer.mode_info.number_of_colors = 256; + 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; + framebuffer.mode_info.reserved_mask_size = 0; + framebuffer.mode_info.reserved_field_pos = 0; + framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info); + /* We can safely discard volatile attribute. */ + framebuffer.ptr = (void *) grub_pci_device_map_range (framebuffer.dev, + framebuffer.base, + 1024 * 600 * 2); + framebuffer.mapped = 1; + + err = grub_video_fb_create_render_target_from_pointer (&framebuffer.render_target, &framebuffer.mode_info, framebuffer.ptr); + + if (err) + return err; + + err = grub_video_fb_set_active_render_target (framebuffer.render_target); + + if (err) + return err; + + /* Copy default palette to initialize emulated palette. */ + err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, + grub_video_fbstd_colors); + return err; +} + +static grub_err_t +grub_video_sm712_set_palette (unsigned int start, unsigned int count, + struct grub_video_palette_data *palette_data) +{ + if (framebuffer.index_color_mode) + { + /* TODO: Implement setting indexed color mode palette to hardware. */ + } + + /* Then set color to emulated palette. */ + return grub_video_fb_set_palette (start, count, palette_data); +} + +static grub_err_t +grub_video_sm712_swap_buffers (void) +{ + /* TODO: Implement buffer swapping. */ + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_video_sm712_set_active_render_target (struct grub_video_render_target *target) +{ + if (target == GRUB_VIDEO_RENDER_TARGET_DISPLAY) + target = framebuffer.render_target; + + return grub_video_fb_set_active_render_target (target); +} + +static grub_err_t +grub_video_sm712_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; + + grub_video_fb_fini (); + + return GRUB_ERR_NONE; +} + + +static struct grub_video_adapter grub_video_sm712_adapter = + { + .name = "SM712 Video Driver", + + .init = grub_video_sm712_video_init, + .fini = grub_video_sm712_video_fini, + .setup = grub_video_sm712_setup, + .get_info = grub_video_fb_get_info, + .get_info_and_fini = grub_video_sm712_get_info_and_fini, + .set_palette = grub_video_sm712_set_palette, + .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_sm712_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_sm712_set_active_render_target, + .get_active_render_target = grub_video_fb_get_active_render_target, + + .next = 0 + }; + +GRUB_MOD_INIT(video_sm712) +{ + grub_video_register (&grub_video_sm712_adapter); +} + +GRUB_MOD_FINI(video_sm712) +{ + grub_video_unregister (&grub_video_sm712_adapter); +} diff --git a/video/video.c b/video/video.c index e678c2982..f6b1aad9e 100644 --- a/video/video.c +++ b/video/video.c @@ -407,21 +407,81 @@ grub_video_get_active_render_target (struct grub_video_render_target **target) return grub_video_adapter_active->get_active_render_target (target); } +/* Parse x[x]*/ +static grub_err_t +parse_modespec (const char *current_mode, int *width, int *height, int *depth) +{ + const char *value; + const char *param = current_mode; + + *width = *height = *depth = -1; + + if (grub_strcmp (param, "auto") == 0) + { + *width = *height = 0; + return GRUB_ERR_NONE; + } + + /* Find width value. */ + value = param; + param = grub_strchr(param, 'x'); + if (param == NULL) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "Invalid mode: %s\n", + current_mode); + + param++; + + *width = grub_strtoul (value, 0, 0); + if (grub_errno != GRUB_ERR_NONE) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "Invalid mode: %s\n", + current_mode); + + /* Find height value. */ + value = param; + param = grub_strchr(param, 'x'); + if (param == NULL) + { + *height = grub_strtoul (value, 0, 0); + if (grub_errno != GRUB_ERR_NONE) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "Invalid mode: %s\n", + current_mode); + } + else + { + /* We have optional color depth value. */ + param++; + + *height = grub_strtoul (value, 0, 0); + if (grub_errno != GRUB_ERR_NONE) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "Invalid mode: %s\n", + current_mode); + + /* Convert color depth value. */ + value = param; + *depth = grub_strtoul (value, 0, 0); + if (grub_errno != GRUB_ERR_NONE) + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "Invalid mode: %s\n", + current_mode); + } + return GRUB_ERR_NONE; +} + grub_err_t grub_video_set_mode (const char *modestring, - int NESTED_FUNC_ATTR (*hook) (grub_video_adapter_t p, - struct grub_video_mode_info *mode_info)) + unsigned int modemask, + unsigned int modevalue) { char *tmp; char *next_mode; char *current_mode; - char *param; - char *value; char *modevar; - int width = -1; - int height = -1; - int depth = -1; - int flags = 0; + + modevalue &= modemask; /* Take copy of env.var. as we don't want to modify that. */ modevar = grub_strdup (modestring); @@ -437,26 +497,26 @@ grub_video_set_mode (const char *modestring, || grub_memcmp (next_mode, "keep,", sizeof ("keep,") - 1) == 0 || grub_memcmp (next_mode, "keep;", sizeof ("keep;") - 1) == 0) { - struct grub_video_mode_info mode_info; int suitable = 1; grub_err_t err; - grub_memset (&mode_info, 0, sizeof (mode_info)); - if (grub_video_adapter_active) { + struct grub_video_mode_info mode_info; + grub_memset (&mode_info, 0, sizeof (mode_info)); err = grub_video_get_info (&mode_info); if (err) { suitable = 0; grub_errno = GRUB_ERR_NONE; } + if ((mode_info.mode_type & modemask) != modevalue) + suitable = 0; } - else - mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_PURE_TEXT; + else if (((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modemask) != 0) + && ((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modevalue) == 0)) + suitable = 0; - if (suitable && hook) - suitable = hook (grub_video_adapter_active, &mode_info); if (suitable) { grub_free (modevar); @@ -490,15 +550,16 @@ grub_video_set_mode (const char *modestring, /* Loop until all modes has been tested out. */ while (next_mode != NULL) { + int width = -1; + int height = -1; + int depth = -1; + grub_err_t err; + unsigned int flags = modevalue; + unsigned int flagmask = modemask; + /* Use last next_mode as current mode. */ tmp = next_mode; - /* Reset video mode settings. */ - width = -1; - height = -1; - depth = -1; - flags = 0; - /* Save position of next mode and separate modes. */ for (; *next_mode; next_mode++) if (*next_mode == ',' || *next_mode == ';') @@ -517,19 +578,16 @@ grub_video_set_mode (const char *modestring, /* Initialize token holders. */ current_mode = tmp; - param = tmp; - value = NULL; /* XXX: we assume that we're in pure text mode if no video mode is initialized. Is it always true? */ - if (grub_strcmp (param, "text") == 0) + if (grub_strcmp (current_mode, "text") == 0) { struct grub_video_mode_info mode_info; grub_memset (&mode_info, 0, sizeof (mode_info)); - mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_PURE_TEXT; - - if (! hook || hook (0, &mode_info)) + if (((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modemask) == 0) + || ((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modevalue) != 0)) { /* Valid mode found from adapter, and it has been activated. Specify it as active adapter. */ @@ -542,121 +600,31 @@ grub_video_set_mode (const char *modestring, } } - /* Parse x[x]*/ - - /* Find width value. */ - value = param; - param = grub_strchr(param, 'x'); - if (param == NULL) + err = parse_modespec (current_mode, &width, &height, &depth); + if (err) { - grub_err_t rc; - - /* First setup error message. */ - rc = grub_error (GRUB_ERR_BAD_ARGUMENT, - "invalid mode: %s", - current_mode); - /* Free memory before returning. */ grub_free (modevar); - return rc; - } - - *param = 0; - param++; - - width = grub_strtoul (value, 0, 0); - if (grub_errno != GRUB_ERR_NONE) - { - grub_err_t rc; - - /* First setup error message. */ - rc = grub_error (GRUB_ERR_BAD_ARGUMENT, - "invalid mode: %s", - current_mode); - - /* Free memory before returning. */ - grub_free (modevar); - - return rc; - } - - /* Find height value. */ - value = param; - param = grub_strchr(param, 'x'); - if (param == NULL) - { - height = grub_strtoul (value, 0, 0); - if (grub_errno != GRUB_ERR_NONE) - { - grub_err_t rc; - - /* First setup error message. */ - rc = grub_error (GRUB_ERR_BAD_ARGUMENT, - "invalid mode: %s", - current_mode); - - /* Free memory before returning. */ - grub_free (modevar); - - return rc; - } - } - else - { - /* We have optional color depth value. */ - *param = 0; - param++; - - height = grub_strtoul (value, 0, 0); - if (grub_errno != GRUB_ERR_NONE) - { - grub_err_t rc; - - /* First setup error message. */ - rc = grub_error (GRUB_ERR_BAD_ARGUMENT, - "invalid mode: %s", - current_mode); - - /* Free memory before returning. */ - grub_free (modevar); - - return rc; - } - - /* Convert color depth value. */ - value = param; - depth = grub_strtoul (value, 0, 0); - if (grub_errno != GRUB_ERR_NONE) - { - grub_err_t rc; - - /* First setup error message. */ - rc = grub_error (GRUB_ERR_BAD_ARGUMENT, - "invalid mode: %s", - current_mode); - - /* Free memory before returning. */ - grub_free (modevar); - - return rc; - } + return err; } /* Try out video mode. */ - /* If we have 8 or less bits, then assume that it is indexed color mode. */ - if ((depth <= 8) && (depth != -1)) - flags |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; + /* If user requested specific depth check if this depth is supported. */ + if (depth != -1 && (flagmask & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK) + && + (((flags & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK) + != ((depth << GRUB_VIDEO_MODE_TYPE_DEPTH_POS) + & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK)))) + continue; - /* We have more than 8 bits, then assume that it is RGB color mode. */ - if (depth > 8) - flags |= GRUB_VIDEO_MODE_TYPE_RGB; - - /* If user requested specific depth, forward that information to driver. */ if (depth != -1) - flags |= (depth << GRUB_VIDEO_MODE_TYPE_DEPTH_POS) - & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK; + { + flags |= (depth << GRUB_VIDEO_MODE_TYPE_DEPTH_POS) + & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK; + flagmask |= GRUB_VIDEO_MODE_TYPE_DEPTH_MASK; + } /* Try to initialize requested mode. Ignore any errors. */ grub_video_adapter_t p; @@ -664,7 +632,6 @@ grub_video_set_mode (const char *modestring, /* Loop thru all possible video adapter trying to find requested mode. */ for (p = grub_video_adapter_list; p; p = p->next) { - grub_err_t err; struct grub_video_mode_info mode_info; grub_memset (&mode_info, 0, sizeof (mode_info)); @@ -678,7 +645,7 @@ grub_video_set_mode (const char *modestring, } /* Try to initialize video mode. */ - err = p->setup (width, height, flags); + err = p->setup (width, height, flags, flagmask); if (err != GRUB_ERR_NONE) { p->fini (); @@ -694,7 +661,15 @@ grub_video_set_mode (const char *modestring, continue; } - if (hook && ! hook (p, &mode_info)) + flags = mode_info.mode_type & ~GRUB_VIDEO_MODE_TYPE_DEPTH_MASK; + flags |= (mode_info.bpp << GRUB_VIDEO_MODE_TYPE_DEPTH_POS) + & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK; + + /* Check that mode is suitable for upper layer. */ + if ((flags & GRUB_VIDEO_MODE_TYPE_PURE_TEXT) + ? (((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modemask) != 0) + && ((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modevalue) == 0)) + : ((flags & modemask) != modevalue)) { p->fini (); grub_errno = GRUB_ERR_NONE;