diff --git a/.bzrignore b/.bzrignore index 32b96b154..26558087a 100644 --- a/.bzrignore +++ b/.bzrignore @@ -40,6 +40,7 @@ grub-fstest grub_fstest_init.c grub_fstest_init.h grub-install +grub-macho2img grub-mk* grub-pbkdf2 grub-pe2elf diff --git a/ChangeLog b/ChangeLog index bc6b8fd18..7d82e08fb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,354 @@ +2010-08-20 Colin Watson + + * commands/i386/pc/sendkey.c (keysym_table): Rename "numlock" to + "numcenter" (I misunderstood the purpose of this entry). + * docs/grub.texi (sendkey): Likewise. + +2010-08-20 Colin Watson + + * commands/i386/pc/sendkey.c (options): Remove "keep" from all + status flag options; simply omitting the option is equivalent and + simpler. Rename "wait" to "pause". Rename "sysreq" to "sysrq". + (keysym_table): Rename "num5numlock" to "numlock". + (grub_cmd_sendkey): Reinitialise `andmask' and `ormask', so that we + can uniformly say that only the last of multiple `sendkey' + invocations has any effect. + * docs/grub.texi (sendkey): New section. + +2010-08-19 Colin Watson + + * commands/i386/pc/sendkey.c (options): Fix three typos. + +2010-08-19 Vladimir Serbinenko + + Implement sendkey support. + + * commands/i386/pc/sendkey.c: New file. + * conf/i386-pc.rmk (pkglib_MODULES): Add sendkey.mod. + (sendkey_mod_SOURCES): New variable. + (sendkey_mod_CFLAGS): Likewise. + (sendkey_mod_LDFLAGS): Likewise. + +2010-08-18 Colin Watson + + * configure.ac: Move AM_INIT_AUTOMAKE after AC_CANONICAL_TARGET to + fix warnings from Autoconf. + +2010-08-18 Colin Watson + + * acinclude.m4 (grub_ASM_USCORE): Use a more accurate grep pattern, + to avoid false positives with some assemblers that output things + like "someprefix_func" as part of their output. + +2010-08-15 Robert Millan + + * kern/emu/misc.c (grub_get_libzfs_handle): Handle libzfs_init() + errors. + * kern/emu/getroot.c (find_root_device_from_libzfs): Handle + grub_get_libzfs_handle() errors. + +2010-08-14 Robert Millan + + * kern/emu/misc.c (grub_find_zpool_from_dir): Abort function if + filesystem is not ZFS. + +2010-08-12 BVK Chaitanya + + Fix for misspelled color names defaulting to black/black (bug + reported by Doug Nazar) + + * include/grub/normal.h (grub_parse_color_name_pair): Add return + status to prototype. + * normal/color.c (grub_parse_color_name_pair): Return failure + status. + (grub_env_write_color_normal): Ignore bad color names. + (grub_env_write_color_highlight): Likewise. + * normal/main.c (GRUB_MOD_INIT): Set default color names. + +2010-08-12 BVK Chaitanya + + "shift" command support to GRUB script. + + * include/grub/script_sh.h (grub_script_shift): New prototype. + * script/execute.c (grub_script_shift): New function. + * script/main.c (grub_script_init): Register shift command. + (grub_script_fini): Unregister shift command. + * util/grub-script-check.c (grub_script_cmd_shift): New function. + + * tests/grub_script_shift.in: New testcase. + * conf/tests.rmk: Rules for new testcase. + +2010-08-12 BVK Chaitanya + + "continue" command support to GRUB script. + + * script/execute.c (grub_script_execute_cmdwhile): Continue support. + (grub_script_break): Continue support. + * script/main.c (grub_script_init): Register continue command. + (grub_script_fini): Unregister continue command. + + * tests/grub_script_continue.in: New testcase. + * conf/tests.rmk: Rules for new testcase. + +2010-08-12 BVK Chaitanya + + "break" command support to GRUB script. + + * conf/common.rmk: Rule updates to grub-script-check. + * include/grub/misc.h (grub_min): New function. + * include/grub/script_sh.h (grub_script_init): New prototype. + (grub_script_fini): New prototype. + (grub_script_break): New prototype. + * script/main.c (grub_script_init): New function. + (grub_script_fini): New function. + * script/execute.c (grub_script_break): New function. + * normal/main.c: Calls to grub_script_{init,fini}. + * util/grub-script-check.c (grub_script_break): New function. + + * tests/grub_script_break.in: New testcase. + * conf/tests.rmk: Rules for new test case. + +2010-08-12 BVK Chaitanya + + Function parameters support to GRUB script. + + * script/yylex.l (VARIABLE): Regular expression update. + * script/function.c (grub_script_function_call): Moved ... + * script/execute.c (grub_script_function_call): ... to here. + (grub_script_execute_arglist_to_argv): Removed. + (grub_script_arglist_to_argv): New function. + * script/argv.c: New file. + (grub_script_argv_free): New function. + (grub_script_argv_next): Likewise. + (grub_script_argv_append): Likewise. + (grub_script_argv_split_append): Likewise. + * include/grub/script_sh.h (grub_script_argv): New struct. + (grub_script_argv_free): New function. + (grub_script_argv_next): Likewise. + (grub_script_argv_append): Likewise. + (grub_script_argv_split_append): Likewise. + + * conf/common.rmk (normal.mod): New source script/argv.c. + + * tests/grub_script_echo1.in: More tests. + * tests/grub_script_vars1.in: Likewise. + * tests/grub_script_functions.in: New test case. + * conf/tests.rmk: Rules for new testcase. + +2010-08-12 BVK Chaitanya + + Remove grub_script_cmdblock struct. + + * include/grub/script_sh.h: Remove grub_script_cmdblock. + * script/parser.y: Likewise. + * script/execute.c: Rename cmdblock suffix to cmdlist. + * script/script.c: Likewise. + * util/grub-script-check.c: Likewise. + +2010-08-11 Yves Blusseau + + * .bzrignore: add grub-macho2img + +2010-08-11 Vladimir Serbinenko + + * kern/i386/qemu/init.c (grub_qemu_init_cirrus): Fix compilation error. + +2010-08-11 Vladimir Serbinenko + + Remove the dump of sm712 initialisation sequence. + + * include/grub/pci.h (GRUB_PCI_CLASS_SUBCLASS_VGA): New const. + * include/grub/vga.h (GRUB_VGA_IO_ARX_READ): New register. + (GRUB_VGA_IO_MISC_WRITE): Likewise. + (GRUB_VGA_CR_*): Added many registers. + (GRUB_VGA_SR_*): Likewise. + (GRUB_VGA_GR_*): Likewise. + (grub_vga_write_arx): New function. + (grub_video_hw_config): New struct. + (grub_vga_set_geometry): New function. + * kern/i386/qemu/init.c (load_palette): Use grub_vga_write_arx and + GRUB_PCI_CLASS_SUBCLASS_VGA. + * video/cirrus.c (grub_video_cirrus_setup): Use grub_vga_set_geometry. + * video/sm712.c (grub_sm712_write_reg): New function + (grub_sm712_read_reg): Likewise. + (grub_sm712_sr_write): Likewise. + (grub_sm712_gr_write): Likewise. + (grub_sm712_cr_write): Likewise. + (grub_sm712_write_arx): Likewise. + (grub_sm712_cr_shadow_write): Likewise. + (grub_sm712_write_dda_lookup): Likewise. + (grub_video_sm712_setup): Initialise the video rather then + blindly replay the dump. + (main) [TEST]: Add a routine to be able to compile as standalone for + tests. + * video/sm712_init.c (sm712_init): Removed. + (sm712_sr_seq1): New array. + (sm712_sr_seq2): Likewise. + +2010-08-10 Vladimir Serbinenko + + * include/grub/vga.h: Add missing grub/pci.h include. + +2010-08-10 Yves Blusseau + + * util/grub-macho2img.c (main): fix typo + +2010-08-10 Vladimir Serbinenko + + * include/grub/vga.h (grub_vga_gr_write): Add GRUB_MACHINE_PCI_IO_BASE. + (grub_vga_gr_read): Likewise. + (grub_vga_cr_write): Likewise. + (grub_vga_cr_read): Likewise. + (grub_vga_sr_write): Likewise. + (grub_vga_sr_read): Likewise. + (grub_vga_palette_read): Likewise. + (grub_vga_palette_write): Likewise. + * video/sm712.c (GRUB_SM712_REG_BASE): New definition. + (grub_sm712_sr_read): New function. + (grub_video_sm712_setup): Use grub_vga_sr_write and grub_sm712_sr_read. + * video/sm712_init.c (sm712_init): Substract GRUB_MACHINE_PCI_IO_BASE. + +2010-08-09 Robert Millan + + * kern/emu/misc.c (grub_make_system_path_relative_to_its_root): Filter + out unused variables on non-ZFS build. + +2010-08-08 Robert Millan + + Fix path generation for sub-filesystems in ZFS. + + * kern/emu/misc.c (grub_make_system_path_relative_to_its_root): Add + missing slash. + +2010-08-08 Robert Millan + + * util/grub-fstest.c (read_file, cmd_cmp): Improve error message. + +2010-08-08 Robert Millan + + * util/grub.d/10_kfreebsd.in: When files required for ZFS do not + exist, issue a proper error message (rely on `ls' for translated + strings). + +2010-08-08 Robert Millan + + Fix grub-probe invocation. + + * util/grub.d/10_kfreebsd.in: s/label/fs_label/g. + +2010-08-04 Robert Millan + + * configure.ac: Remove checks for getfsstat() and getmntany(). + Add checks for `' and `'. + * kern/emu/misc.c [HAVE_GETMNTANY]: Remove `'. + [HAVE_SYS_PARAM_H]: Include `'. + [HAVE_SYS_MOUNT_H]: Include `'. + [HAVE_LIBZFS && HAVE_LIBNVPAIR] (find_mount_point_from_dir): Remove + function. + (grub_find_zpool_from_dir): Use statfs() instead of indirect matching + via find_mount_point_from_dir() and getfsstat() / getmntany(). + +2010-08-04 Robert Millan + + * include/grub/emu/misc.h (grub_find_mount_point_from_dir) + (grub_find_zpool_from_mount_point): Merge into ... + (grub_find_zpool_from_dir): ... this. + * kern/emu/misc.c: Likewise. + + * kern/emu/misc.c + (grub_make_system_path_relative_to_its_root): Replace + grub_find_mount_point_from_dir() / grub_find_zpool_from_mount_point() + with grub_find_zpool_from_dir(). + * kern/emu/getroot.c (find_root_device_from_libzfs): Likewise. + +2010-08-04 Robert Millan + + Support OpenSolaris in ZFS device resolution. + + * configure.ac: Check for getmntany(). + * kern/emu/misc.c [HAVE_GETMNTANY]: Include `'. + [HAVE_GETMNTANY] (grub_find_zpool_from_mount_point): Add OpenSolaris + support. + +2010-08-03 Robert Millan + + Fix grub-emu build. + + * include/grub/util/misc.h: Move `' to ... + * include/grub/emu/misc.h: ... here. + + * include/grub/util/misc.h (grub_get_libzfs_handle): Move function ... + * include/grub/emu/misc.h (grub_get_libzfs_handle): ... here. + + * util/misc.c: Remove `'. + [HAVE_LIBZFS] (libzfs_handle, fini_libzfs) + (grub_get_libzfs_handle): Move to ... + * kern/emu/misc.c [HAVE_LIBZFS] (__libzfs_handle, fini_libzfs) + (grub_get_libzfs_handle): ... here. + +2010-08-03 BVK Chaitanya + + * script/execute.c (grub_script_execute_cmdline): Check for NULL + as command name case. + +2010-08-02 Colin Watson + + * disk/raid.c (insert_array): Select unique numbers for named arrays + as well, for use as keys in the disk cache. + +2010-08-01 Robert Millan + + * util/grub.d/10_kfreebsd.in: Initialize ${kfreebsd_device} as the + kFreeBSD device name, except on ZFS where the filesystem label is + used. + (kfreebsd_entry): On ZFS root, load `opensolaris.ko', `zfs.ko' and + `/boot/zfs/zpool.cache'. + Set mountfrom kernel variable using ${kfreebsd_device}. + +2010-08-01 Robert Millan + + Make it even harder to use uninitialized `libzfs_handle' (and + make the interface a bit simpler). + + * include/grub/util/misc.h (grub_util_init_libzfs) + (libzfs_handle): Remove. + (grub_get_libzfs_handle): New prototype. + + * util/misc.c [HAVE_LIBZFS] (libzfs_handle): Add `static' + attribute. + (grub_util_init_libzfs): Remove. + (grub_get_libzfs_handle): New function. + + * kern/emu/getroot.c (find_root_device_from_libzfs): Use + grub_get_libzfs_handle() to obtain a libzfs handle instead of + accessing `libzfs_handle' directly. + +2010-08-01 Robert Millan + + * include/grub/emu/misc.h (grub_find_mount_point_from_dir) + (grub_find_zpool_from_mount_point): New function prototypes. + + * kern/emu/getroot.c [HAVE_GETFSSTAT]: Move `' to ... + * kern/emu/misc.c [HAVE_GETFSSTAT]: ... here. + + * kern/emu/getroot.c (find_mount_point_from_dir): Move to ... + * kern/emu/misc.c (grub_find_mount_point_from_dir): ... this. Remove + `static' attribute. + + * kern/emu/getroot.c (find_root_device_from_libzfs): Split code for + finding zpool from mount point into ... + * kern/emu/misc.c (grub_find_zpool_from_mount_point): ... this. + + * kern/emu/misc.c (grub_make_system_path_relative_to_its_root): When + requested path is part of a ZFS pool, use + grub_find_zpool_from_mount_point() to detect its filesystem name, + and generate a path with `/fsname@path' syntax. + +2010-08-01 Colin Watson + + * include/grub/util/libzfs.h (libzfs_init): Set argument list to + (void) rather than () so that this is a proper prototype. + 2010-08-01 Vladimir Serbinenko * lib/arg.c (grub_arg_show_help): Add the necessary spacing. @@ -34,6 +385,27 @@ * kern/misc.c (grub_memset): Optimise to reduce cache stalls. +2010-08-01 Robert Millan + + * include/grub/emu/misc.h (grub_find_mount_point_from_dir) + (grub_find_zpool_from_mount_point): New function prototypes. + + * kern/emu/getroot.c [HAVE_GETFSSTAT]: Move `' to ... + * kern/emu/misc.c [HAVE_GETFSSTAT]: ... here. + + * kern/emu/getroot.c (find_mount_point_from_dir): Move to ... + * kern/emu/misc.c (grub_find_mount_point_from_dir): ... this. Remove + `static' attribute. + + * kern/emu/getroot.c (find_root_device_from_libzfs): Split code for + finding zpool from mount point into ... + * kern/emu/misc.c (grub_find_zpool_from_mount_point): ... this. + + * kern/emu/misc.c (grub_make_system_path_relative_to_its_root): When + requested path is part of a ZFS pool, use + grub_find_zpool_from_mount_point() to detect its filesystem name, + and generate a path with `/fsname@path' syntax. + 2010-08-01 Robert Millan Prevent accidental use of uninitialized libzfs_handle. diff --git a/acinclude.m4 b/acinclude.m4 index 72483b5d0..49760d5f0 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -38,6 +38,7 @@ 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_REQUIRE([AC_PROG_CC]) +AC_REQUIRE([AC_PROG_EGREP]) AC_MSG_CHECKING([if C symbols get an underscore after compilation]) AC_CACHE_VAL(grub_cv_asm_uscore, [cat > conftest.c <<\EOF @@ -56,7 +57,7 @@ else AC_MSG_ERROR([${CC-cc} failed to produce assembly code]) fi -if grep _func conftest.s >/dev/null 2>&1; then +if $EGREP '(^|[^_[:alnum]])_func' conftest.s >/dev/null 2>&1; then grub_cv_asm_uscore=yes else grub_cv_asm_uscore=no diff --git a/commands/i386/pc/sendkey.c b/commands/i386/pc/sendkey.c new file mode 100644 index 000000000..6c5602dec --- /dev/null +++ b/commands/i386/pc/sendkey.c @@ -0,0 +1,384 @@ +/* sendkey.c - fake keystroke. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2009 Free Software Foundation, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static char sendkey[0x20]; +/* Length of sendkey. */ +static int keylen = 0; +static int noled = 0; +static const struct grub_arg_option options[] = + { + {"num", 'n', 0, "set numlock mode", "[on|off]", ARG_TYPE_STRING}, + {"caps", 'c', 0, "set capslock mode", "[on|off]", ARG_TYPE_STRING}, + {"scroll", 's', 0, "set scrolllock mode", "[on|off]", ARG_TYPE_STRING}, + {"insert", 0, 0, "set insert mode", "[on|off]", ARG_TYPE_STRING}, + {"pause", 0, 0, "set pause mode", "[on|off]", ARG_TYPE_STRING}, + {"left-shift", 0, 0, "press left shift", "[on|off]", ARG_TYPE_STRING}, + {"right-shift", 0, 0, "press right shift", "[on|off]", ARG_TYPE_STRING}, + {"sysrq", 0, 0, "press SysRq", "[on|off]", ARG_TYPE_STRING}, + {"numkey", 0, 0, "press NumLock key", "[on|off]", ARG_TYPE_STRING}, + {"capskey", 0, 0, "press CapsLock key", "[on|off]", ARG_TYPE_STRING}, + {"scrollkey", 0, 0, "press ScrollLock key", "[on|off]", ARG_TYPE_STRING}, + {"insertkey", 0, 0, "press Insert key", "[on|off]", ARG_TYPE_STRING}, + {"left-alt", 0, 0, "press left alt", "[on|off]", ARG_TYPE_STRING}, + {"right-alt", 0, 0, "press right alt", "[on|off]", ARG_TYPE_STRING}, + {"left-ctrl", 0, 0, "press left ctrl", "[on|off]", ARG_TYPE_STRING}, + {"right-ctrl", 0, 0, "press right ctrl", "[on|off]", ARG_TYPE_STRING}, + {"no-led", 0, 0, "don't update LED state", 0, 0}, + {0, 0, 0, 0, 0, 0} + }; +static int simple_flag_offsets[] += {5, 6, 4, 7, 11, 1, 0, 10, 13, 14, 12, 15, 9, 3, 8, 2}; + +static grub_uint32_t andmask = 0xffffffff, ormask = 0; + +struct +keysym +{ + char *unshifted_name; /* the name in unshifted state */ + char *shifted_name; /* the name in shifted state */ + unsigned char unshifted_ascii; /* the ascii code in unshifted state */ + unsigned char shifted_ascii; /* the ascii code in shifted state */ + unsigned char keycode; /* keyboard scancode */ +}; + +/* The table for key symbols. If the "shifted" member of an entry is + NULL, the entry does not have shifted state. Copied from GRUB Legacy setkey fuction */ +static struct keysym keysym_table[] = +{ + {"escape", 0, 0x1b, 0, 0x01}, + {"1", "exclam", '1', '!', 0x02}, + {"2", "at", '2', '@', 0x03}, + {"3", "numbersign", '3', '#', 0x04}, + {"4", "dollar", '4', '$', 0x05}, + {"5", "percent", '5', '%', 0x06}, + {"6", "caret", '6', '^', 0x07}, + {"7", "ampersand", '7', '&', 0x08}, + {"8", "asterisk", '8', '*', 0x09}, + {"9", "parenleft", '9', '(', 0x0a}, + {"0", "parenright", '0', ')', 0x0b}, + {"minus", "underscore", '-', '_', 0x0c}, + {"equal", "plus", '=', '+', 0x0d}, + {"backspace", 0, '\b', 0, 0x0e}, + {"tab", 0, '\t', 0, 0x0f}, + {"q", "Q", 'q', 'Q', 0x10}, + {"w", "W", 'w', 'W', 0x11}, + {"e", "E", 'e', 'E', 0x12}, + {"r", "R", 'r', 'R', 0x13}, + {"t", "T", 't', 'T', 0x14}, + {"y", "Y", 'y', 'Y', 0x15}, + {"u", "U", 'u', 'U', 0x16}, + {"i", "I", 'i', 'I', 0x17}, + {"o", "O", 'o', 'O', 0x18}, + {"p", "P", 'p', 'P', 0x19}, + {"bracketleft", "braceleft", '[', '{', 0x1a}, + {"bracketright", "braceright", ']', '}', 0x1b}, + {"enter", 0, '\r', 0, 0x1c}, + {"control", 0, 0, 0, 0x1d}, + {"a", "A", 'a', 'A', 0x1e}, + {"s", "S", 's', 'S', 0x1f}, + {"d", "D", 'd', 'D', 0x20}, + {"f", "F", 'f', 'F', 0x21}, + {"g", "G", 'g', 'G', 0x22}, + {"h", "H", 'h', 'H', 0x23}, + {"j", "J", 'j', 'J', 0x24}, + {"k", "K", 'k', 'K', 0x25}, + {"l", "L", 'l', 'L', 0x26}, + {"semicolon", "colon", ';', ':', 0x27}, + {"quote", "doublequote", '\'', '"', 0x28}, + {"backquote", "tilde", '`', '~', 0x29}, + {"shift", 0, 0, 0, 0x2a}, + {"backslash", "bar", '\\', '|', 0x2b}, + {"z", "Z", 'z', 'Z', 0x2c}, + {"x", "X", 'x', 'X', 0x2d}, + {"c", "C", 'c', 'C', 0x2e}, + {"v", "V", 'v', 'V', 0x2f}, + {"b", "B", 'b', 'B', 0x30}, + {"n", "N", 'n', 'N', 0x31}, + {"m", "M", 'm', 'M', 0x32}, + {"comma", "less", ',', '<', 0x33}, + {"period", "greater", '.', '>', 0x34}, + {"slash", "question", '/', '?', 0x35}, + {"rshift", 0, 0, 0, 0x36}, + {"numasterisk", 0, '*', 0, 0x37}, + {"alt", 0, 0, 0, 0x38}, + {"space", 0, ' ', 0, 0x39}, + {"capslock", 0, 0, 0, 0x3a}, + {"F1", 0, 0, 0, 0x3b}, + {"F2", 0, 0, 0, 0x3c}, + {"F3", 0, 0, 0, 0x3d}, + {"F4", 0, 0, 0, 0x3e}, + {"F5", 0, 0, 0, 0x3f}, + {"F6", 0, 0, 0, 0x40}, + {"F7", 0, 0, 0, 0x41}, + {"F8", 0, 0, 0, 0x42}, + {"F9", 0, 0, 0, 0x43}, + {"F10", 0, 0, 0, 0x44}, + {"num7", "numhome", '7', 0, 0x47}, + {"num8", "numup", '8', 0, 0x48}, + {"num9", "numpgup", '9', 0, 0x49}, + {"numminus", 0, '-', 0, 0x4a}, + {"num4", "numleft", '4', 0, 0x4b}, + {"num5", "numcenter", '5', 0, 0x4c}, + {"num6", "numright", '6', 0, 0x4d}, + {"numplus", 0, '-', 0, 0x4e}, + {"num1", "numend", '1', 0, 0x4f}, + {"num2", "numdown", '2', 0, 0x50}, + {"num3", "numpgdown", '3', 0, 0x51}, + {"num0", "numinsert", '0', 0, 0x52}, + {"numperiod", "numdelete", 0, 0x7f, 0x53}, + {"F11", 0, 0, 0, 0x57}, + {"F12", 0, 0, 0, 0x58}, + {"numenter", 0, '\r', 0, 0xe0}, + {"numslash", 0, '/', 0, 0xe0}, + {"delete", 0, 0x7f, 0, 0xe0}, + {"insert", 0, 0xe0, 0, 0x52}, + {"home", 0, 0xe0, 0, 0x47}, + {"end", 0, 0xe0, 0, 0x4f}, + {"pgdown", 0, 0xe0, 0, 0x51}, + {"pgup", 0, 0xe0, 0, 0x49}, + {"down", 0, 0xe0, 0, 0x50}, + {"up", 0, 0xe0, 0, 0x48}, + {"left", 0, 0xe0, 0, 0x4b}, + {"right", 0, 0xe0, 0, 0x4d} +}; + +/* Set a simple flag in flags variable + OUTOFFSET - offset of flag in FLAGS, + OP - action id +*/ +static void +grub_sendkey_set_simple_flag (int outoffset, int op) +{ + if (op == 2) + { + andmask |= (1 << outoffset); + ormask &= ~(1 << outoffset); + } + else + { + andmask &= (~(1 << outoffset)); + if (op == 1) + ormask |= (1 << outoffset); + else + ormask &= ~(1 << outoffset); + } +} + +static int +grub_sendkey_parse_op (struct grub_arg_list state) +{ + if (! state.set) + return 2; + + if (grub_strcmp (state.arg, "off") == 0 || grub_strcmp (state.arg, "0") == 0 + || grub_strcmp (state.arg, "unpress") == 0) + return 0; + + if (grub_strcmp (state.arg, "on") == 0 || grub_strcmp (state.arg, "1") == 0 + || grub_strcmp (state.arg, "press") == 0) + return 1; + + return 2; +} + +static grub_uint32_t oldflags; + +static grub_err_t +grub_sendkey_postboot (void) +{ + /* For convention: pointer to flags. */ + grub_uint32_t *flags = (grub_uint32_t *) 0x417; + + *flags = oldflags; + + *((char *) 0x41a) = 0x1e; + *((char *) 0x41c) = 0x1e; + + return GRUB_ERR_NONE; +} + +/* Set keyboard buffer to our sendkey */ +static grub_err_t +grub_sendkey_preboot (int noret __attribute__ ((unused))) +{ + /* For convention: pointer to flags. */ + grub_uint32_t *flags = (grub_uint32_t *) 0x417; + + oldflags = *flags; + + /* Set the sendkey. */ + *((char *) 0x41a) = 0x1e; + *((char *) 0x41c) = keylen + 0x1e; + grub_memcpy ((char *) 0x41e, sendkey, 0x20); + + /* Transform "any ctrl" to "right ctrl" flag. */ + if (*flags & (1 << 8)) + *flags &= ~(1 << 2); + + /* Transform "any alt" to "right alt" flag. */ + if (*flags & (1 << 9)) + *flags &= ~(1 << 3); + + *flags = (*flags & andmask) | ormask; + + /* Transform "right ctrl" to "any ctrl" flag. */ + if (*flags & (1 << 8)) + *flags |= (1 << 2); + + /* Transform "right alt" to "any alt" flag. */ + if (*flags & (1 << 9)) + *flags |= (1 << 3); + + /* Write new LED state */ + if (!noled) + { + int value = 0; + int failed; + /* Try 5 times */ + for (failed = 0; failed < 5; failed++) + { + value = 0; + /* Send command change LEDs */ + grub_outb (0xed, 0x60); + + /* Wait */ + do + value = grub_inb (0x60); + while ((value != 0xfa) && (value != 0xfe)); + + if (value == 0xfa) + { + /* Set new LEDs*/ + grub_outb ((*flags >> 4) & 7, 0x60); + break; + } + } + } + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_sendkey (grub_extcmd_t cmd, int argc, char **args) +{ + struct grub_arg_list *state = cmd->state; + + auto int find_key_code (char *key); + auto int find_ascii_code (char *key); + + int find_key_code (char *key) + { + unsigned i; + + for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++) + { + if (keysym_table[i].unshifted_name + && grub_strcmp (key, keysym_table[i].unshifted_name) == 0) + return keysym_table[i].keycode; + else if (keysym_table[i].shifted_name + && grub_strcmp (key, keysym_table[i].shifted_name) == 0) + return keysym_table[i].keycode; + } + + return 0; + } + + int find_ascii_code (char *key) + { + unsigned i; + + for (i = 0; i < sizeof (keysym_table) / sizeof (keysym_table[0]); i++) + { + if (keysym_table[i].unshifted_name + && grub_strcmp (key, keysym_table[i].unshifted_name) == 0) + return keysym_table[i].unshifted_ascii; + else if (keysym_table[i].shifted_name + && grub_strcmp (key, keysym_table[i].shifted_name) == 0) + return keysym_table[i].shifted_ascii; + } + + return 0; + } + + andmask = 0xffffffff; + ormask = 0; + + { + int i; + + keylen = 0; + + for (i = 0; i < argc && keylen < 0x20; i++) + { + int key_code; + + key_code = find_key_code (args[i]); + if (key_code) + { + sendkey[keylen++] = find_ascii_code (args[i]); + sendkey[keylen++] = key_code; + } + } + } + + { + unsigned i; + for (i = 0; i < sizeof (simple_flag_offsets) + / sizeof (simple_flag_offsets[0]); i++) + grub_sendkey_set_simple_flag (simple_flag_offsets[i], + grub_sendkey_parse_op(state[i])); + } + + /* Set noled. */ + noled = (state[sizeof (simple_flag_offsets) + / sizeof (simple_flag_offsets[0])].set); + + return GRUB_ERR_NONE; +} + +static grub_extcmd_t cmd; +static void *preboot_hook; + +GRUB_MOD_INIT (sendkey) +{ + cmd = grub_register_extcmd ("sendkey", grub_cmd_sendkey, + GRUB_COMMAND_FLAG_BOTH, + "sendkey [KEYSTROKE1] [KEYSTROKE2] ...", + "Emulate a keystroke", options); + + preboot_hook + = grub_loader_register_preboot_hook (grub_sendkey_preboot, + grub_sendkey_postboot, + GRUB_LOADER_PREBOOT_HOOK_PRIO_CONSOLE); +} + +GRUB_MOD_FINI (sendkey) +{ + grub_unregister_extcmd (cmd); + grub_loader_unregister_preboot_hook (preboot_hook); +} diff --git a/conf/common.rmk b/conf/common.rmk index f92e5bc4c..908bd74e8 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -94,7 +94,7 @@ grub_script_check_SOURCES = gnulib/progname.c gnulib/getdelim.c gnulib/getline.c util/grub-script-check.c util/misc.c kern/emu/misc.c kern/emu/mm.c \ script/main.c script/script.c script/function.c script/lexer.c \ kern/err.c kern/list.c \ - kern/misc.c kern/env.c grub_script.tab.c \ + kern/command.c kern/misc.c kern/env.c grub_script.tab.c \ grub_script.yy.c grub_script_check_CFLAGS = $(GNULIB_UTIL_CFLAGS) grub_script_check_DEPENDENCIES = grub_script.tab.h @@ -636,7 +636,7 @@ normal_mod_SOURCES = normal/main.c normal/cmdline.c normal/dyncmd.c \ normal/color.c normal/completion.c normal/datetime.c normal/menu.c \ normal/menu_entry.c normal/menu_text.c normal/charset.c \ normal/misc.c normal/crypto.c normal/term.c normal/context.c \ - script/main.c script/script.c script/execute.c unidata.c \ + script/main.c script/script.c script/execute.c script/argv.c unidata.c \ script/function.c script/lexer.c grub_script.tab.c grub_script.yy.c normal_mod_CFLAGS = $(COMMON_CFLAGS) $(POSIX_CFLAGS) -Wno-error normal_mod_LDFLAGS = $(COMMON_LDFLAGS) diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index 9c77a9d1d..e9c0b4202 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -253,6 +253,12 @@ datetime_mod_SOURCES = lib/cmos_datetime.c datetime_mod_CFLAGS = $(COMMON_CFLAGS) datetime_mod_LDFLAGS = $(COMMON_LDFLAGS) +# For sendkey.mod +pkglib_MODULES += sendkey.mod +sendkey_mod_SOURCES = commands/i386/pc/sendkey.c +sendkey_mod_CFLAGS = $(COMMON_CFLAGS) +sendkey_mod_LDFLAGS = $(COMMON_LDFLAGS) + # For ata_pthru.mod. ata_pthru_mod_SOURCES = disk/ata_pthru.c ata_pthru_mod_CFLAGS = $(COMMON_CFLAGS) diff --git a/conf/tests.rmk b/conf/tests.rmk index 9af2f8f86..c14fe0fda 100644 --- a/conf/tests.rmk +++ b/conf/tests.rmk @@ -71,6 +71,18 @@ grub_script_dollar_SOURCES = tests/grub_script_dollar.in check_SCRIPTS += grub_script_comments grub_script_comments_SOURCES = tests/grub_script_comments.in +check_SCRIPTS += grub_script_functions +grub_script_functions_SOURCES = tests/grub_script_functions.in + +check_SCRIPTS += grub_script_break +grub_script_break_SOURCES = tests/grub_script_break.in + +check_SCRIPTS += grub_script_continue +grub_script_continue_SOURCES = tests/grub_script_continue.in + +check_SCRIPTS += grub_script_shift +grub_script_shift_SOURCES = tests/grub_script_shift.in + # List of tests to execute on "make check" # SCRIPTED_TESTS = example_scripted_test # SCRIPTED_TESTS += example_grub_script_test @@ -87,6 +99,10 @@ SCRIPTED_TESTS += grub_script_blanklines SCRIPTED_TESTS += grub_script_final_semicolon SCRIPTED_TESTS += grub_script_dollar SCRIPTED_TESTS += grub_script_comments +SCRIPTED_TESTS += grub_script_functions +SCRIPTED_TESTS += grub_script_break +SCRIPTED_TESTS += grub_script_continue +SCRIPTED_TESTS += grub_script_shift # dependencies between tests and testing-tools $(SCRIPTED_TESTS): grub-shell grub-shell-tester diff --git a/configure.ac b/configure.ac index 6169a2fb5..4091b4fa2 100644 --- a/configure.ac +++ b/configure.ac @@ -32,7 +32,6 @@ dnl type. AC_INIT([GRUB],[1.98],[bug-grub@gnu.org]) -AM_INIT_AUTOMAKE() AC_PREREQ(2.60) AC_CONFIG_SRCDIR([include/grub/dl.h]) AC_CONFIG_HEADER([config.h]) @@ -41,6 +40,8 @@ AC_CONFIG_HEADER([config.h]) AC_CANONICAL_HOST AC_CANONICAL_TARGET +AM_INIT_AUTOMAKE() + # Program name transformations AC_ARG_PROGRAM @@ -247,8 +248,8 @@ else fi # Check for functions and headers. -AC_CHECK_FUNCS(posix_memalign memalign asprintf vasprintf getfsstat) -AC_CHECK_HEADERS(libzfs.h libnvpair.h) +AC_CHECK_FUNCS(posix_memalign memalign asprintf vasprintf) +AC_CHECK_HEADERS(libzfs.h libnvpair.h sys/param.h sys/mount.h) # For opendisk() and getrawpartition() on NetBSD. # Used in util/deviceiter.c and in util/hostdisk.c. diff --git a/disk/raid.c b/disk/raid.c index 7dfd4bd81..51a4b00e2 100644 --- a/disk/raid.c +++ b/disk/raid.c @@ -528,25 +528,28 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array, grub_memset (&array->device, 0, sizeof (array->device)); grub_memset (&array->start_sector, 0, sizeof (array->start_sector)); - if (array->name) - goto skip_duplicate_check; - /* Check whether we don't have multiple arrays with the same number. */ - for (p = array_list; p != NULL; p = p->next) - { - if (! p->name && p->number == array->number) - break; - } + if (! array->name) + { + for (p = array_list; p != NULL; p = p->next) + { + if (! p->name && p->number == array->number) + break; + } + } - if (p) + if (array->name || p) { - /* The number is already in use, so we need to find a new one. */ - int i = 0; + /* The number is already in use, so we need to find a new one. + (Or, in the case of named arrays, the array doesn't have its + own number, but we need one that doesn't clash for use as a key + in the disk cache. */ + int i = array->name ? 0x40000000 : 0; while (1) { for (p = array_list; p != NULL; p = p->next) { - if (! p->name && p->number == i) + if (p->number == i) break; } @@ -560,7 +563,7 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array, i++; } } - skip_duplicate_check: + /* mdraid 1.x superblocks have only a name stored not a number. Use it directly as GRUB device. */ if (! array->name) diff --git a/docs/grub.texi b/docs/grub.texi index 583cf98cb..9845c7a6f 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -2094,6 +2094,7 @@ you forget a command, you can run the command @command{help} * pxe_unload:: Unload the PXE environment * reboot:: Reboot your computer * search:: Search devices by file, label, or UUID +* sendkey:: Emulate keystrokes * set:: Set an environment variable * unset:: Unset an environment variable * uppermem:: Set the upper memory size @@ -2604,6 +2605,154 @@ commands are aliases for @samp{search --file}, @samp{search --label}, and @end deffn +@node sendkey +@subsection sendkey + +@deffn Command sendkey @ + [@option{--num}|@option{--caps}|@option{--scroll}|@option{--insert}|@ +@option{--pause}|@option{--left-shift}|@option{--right-shift}|@ +@option{--sysrq}|@option{--numkey}|@option{--capskey}|@option{--scrollkey}|@ +@option{--insertkey}|@option{--left-alt}|@option{--right-alt}|@ +@option{--left-ctrl}|@option{--right-ctrl} @ + @samp{on}|@samp{off}]@dots{} @ + [@option{no-led}] @ + keystroke +Insert keystrokes into the keyboard buffer when booting. Sometimes an +operating system or chainloaded boot loader requires particular keys to be +pressed: for example, one might need to press a particular key to enter +"safe mode", or when chainloading another boot loader one might send +keystrokes to it to navigate its menu. + +You may provide up to 16 keystrokes (the length of the BIOS keyboard +buffer). Keystroke names may be upper-case or lower-case letters, digits, +or taken from the following table: + +@c Please keep this table in the same order as in +@c commands/i386/pc/sendkey.c, for ease of maintenance. +@c Exception: The function and numeric keys are sorted, for aesthetics. + +@multitable @columnfractions .4 .5 +@headitem Name @tab Key +@item escape @tab Escape +@item exclam @tab ! +@item at @tab @@ +@item numbersign @tab # +@item dollar @tab $ +@item percent @tab % +@item caret @tab ^ +@item ampersand @tab & +@item asterisk @tab * +@item parenleft @tab ( +@item parenright @tab ) +@item minus @tab - +@item underscore @tab _ +@item equal @tab = +@item plus @tab + +@item backspace @tab Backspace +@item tab @tab Tab +@item bracketleft @tab [ +@item braceleft @tab @{ +@item bracketright @tab ] +@item braceright @tab @} +@item enter @tab Enter +@item control @tab press and release Control +@item semicolon @tab ; +@item colon @tab : +@item quote @tab ' +@item doublequote @tab " +@item backquote @tab ` +@item tilde @tab ~ +@item shift @tab press and release left Shift +@item backslash @tab \ +@item bar @tab | +@item comma @tab , +@item less @tab < +@item period @tab . +@item greater @tab > +@item slash @tab / +@item question @tab ? +@item rshift @tab press and release right Shift +@item alt @tab press and release Alt +@item space @tab space bar +@item capslock @tab Caps Lock +@item F1 @tab F1 +@item F2 @tab F2 +@item F3 @tab F3 +@item F4 @tab F4 +@item F5 @tab F5 +@item F6 @tab F6 +@item F7 @tab F7 +@item F8 @tab F8 +@item F9 @tab F9 +@item F10 @tab F10 +@item F11 @tab F11 +@item F12 @tab F12 +@item num1 @tab 1 (numeric keypad) +@item num2 @tab 2 (numeric keypad) +@item num3 @tab 3 (numeric keypad) +@item num4 @tab 4 (numeric keypad) +@item num5 @tab 5 (numeric keypad) +@item num6 @tab 6 (numeric keypad) +@item num7 @tab 7 (numeric keypad) +@item num8 @tab 8 (numeric keypad) +@item num9 @tab 9 (numeric keypad) +@item num0 @tab 0 (numeric keypad) +@item numperiod @tab . (numeric keypad) +@item numend @tab End (numeric keypad) +@item numdown @tab Down (numeric keypad) +@item numpgdown @tab Page Down (numeric keypad) +@item numleft @tab Left (numeric keypad) +@item numcenter @tab 5 with Num Lock inactive (numeric keypad) +@item numright @tab Right (numeric keypad) +@item numhome @tab Home (numeric keypad) +@item numup @tab Up (numeric keypad) +@item numpgup @tab Page Up (numeric keypad) +@item numinsert @tab Insert (numeric keypad) +@item numdelete @tab Delete (numeric keypad) +@item numasterisk @tab * (numeric keypad) +@item numminus @tab - (numeric keypad) +@item numplus @tab + (numeric keypad) +@item numslash @tab / (numeric keypad) +@item numenter @tab Enter (numeric keypad) +@item delete @tab Delete +@item insert @tab Insert +@item home @tab Home +@item end @tab End +@item pgdown @tab Page Down +@item pgup @tab Page Up +@item down @tab Down +@item up @tab Up +@item left @tab Left +@item right @tab Right +@end multitable + +As well as keystrokes, the @command{sendkey} command takes various options +that affect the BIOS keyboard status flags. These options take an @samp{on} +or @samp{off} parameter, specifying that the corresponding status flag be +set or unset; omitting the option for a given status flag will leave that +flag at its initial state at boot. The @option{--num}, @option{--caps}, +@option{--scroll}, and @option{--insert} options emulate setting the +corresponding mode, while the @option{--numkey}, @option{--capskey}, +@option{--scrollkey}, and @option{--insertkey} options emulate pressing and +holding the corresponding key. The other status flag options are +self-explanatory. + +If the @option{--no-led} option is given, the status flag options will have +no effect on keyboard LEDs. + +If the @command{sendkey} command is given multiple times, then only the last +invocation has any effect. + +Since @command{sendkey} manipulates the BIOS keyboard buffer, it may cause +hangs, reboots, or other misbehaviour on some systems. If the operating +system or boot loader that runs after GRUB uses its own keyboard driver +rather than the BIOS keyboard functions, then @command{sendkey} will have no +effect. + +This command is only available on PC BIOS systems. +@end deffn + + @node set @subsection set diff --git a/include/grub/emu/misc.h b/include/grub/emu/misc.h index dc48d91a8..ebb81a37f 100644 --- a/include/grub/emu/misc.h +++ b/include/grub/emu/misc.h @@ -21,6 +21,7 @@ #include #include +#include #ifdef __CYGWIN__ # include @@ -44,7 +45,11 @@ extern const char *program_name; void grub_init_all (void); void grub_fini_all (void); -char *grub_make_system_path_relative_to_its_root (const char *path) __attribute__ ((warn_unused_result)); +void grub_find_zpool_from_dir (const char *dir, + char **poolname, char **poolfs); + +char *grub_make_system_path_relative_to_its_root (const char *path) + __attribute__ ((warn_unused_result)); void * EXPORT_FUNC(xmalloc) (grub_size_t size) __attribute__ ((warn_unused_result)); void * EXPORT_FUNC(xrealloc) (void *ptr, grub_size_t size) __attribute__ ((warn_unused_result)); @@ -69,4 +74,6 @@ extern char * canonicalize_file_name (const char *path); int grub_device_mapper_supported (void); #endif +libzfs_handle_t *grub_get_libzfs_handle (void); + #endif /* GRUB_EMU_MISC_H */ diff --git a/include/grub/misc.h b/include/grub/misc.h index eab01b0fb..df80cf192 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -288,6 +288,15 @@ grub_abs (int x) return (unsigned int) x; } +static inline long +grub_min (long x, long y) +{ + if (x < y) + return x; + else + return y; +} + static inline long grub_max (long x, long y) { diff --git a/include/grub/normal.h b/include/grub/normal.h index a33e42e61..2a0298bc6 100644 --- a/include/grub/normal.h +++ b/include/grub/normal.h @@ -73,7 +73,7 @@ grub_err_t grub_normal_print_device_info (const char *name); /* Defined in `color.c'. */ char *grub_env_write_color_normal (struct grub_env_var *var, const char *val); char *grub_env_write_color_highlight (struct grub_env_var *var, const char *val); -void grub_parse_color_name_pair (grub_uint8_t *ret, const char *name); +int grub_parse_color_name_pair (grub_uint8_t *ret, const char *name); /* Defined in `menu_text.c'. */ void grub_wait_after_message (void); diff --git a/include/grub/pci.h b/include/grub/pci.h index e6d6488f0..f34e3d907 100644 --- a/include/grub/pci.h +++ b/include/grub/pci.h @@ -80,6 +80,7 @@ #define GRUB_PCI_STATUS_DEVSEL_TIMING_SHIFT 9 #define GRUB_PCI_STATUS_DEVSEL_TIMING_MASK 0x0600 +#define GRUB_PCI_CLASS_SUBCLASS_VGA 0x0300 #ifndef ASM_FILE typedef grub_uint32_t grub_pci_id_t; diff --git a/include/grub/script_sh.h b/include/grub/script_sh.h index 7d6129243..77e807360 100644 --- a/include/grub/script_sh.h +++ b/include/grub/script_sh.h @@ -23,6 +23,7 @@ #include #include #include +#include struct grub_script_mem; @@ -63,6 +64,13 @@ struct grub_script_arg struct grub_script_arg *next; }; +/* An argument vector. */ +struct grub_script_argv +{ + unsigned argc; + char **args; +}; + /* A complete argument. It consists of a list of one or more `struct grub_script_arg's. */ struct grub_script_arglist @@ -82,15 +90,6 @@ struct grub_script_cmdline struct grub_script_arglist *arglist; }; -/* A block of commands, this can be used to group commands. */ -struct grub_script_cmdblock -{ - struct grub_script_cmd cmd; - - /* A chain of commands. */ - struct grub_script_cmd *cmdlist; -}; - /* An if statement. */ struct grub_script_cmdif { @@ -224,6 +223,14 @@ struct grub_parser_param struct grub_lexer_param *lexerstate; }; +void grub_script_init (void); +void grub_script_fini (void); + +void grub_script_argv_free (struct grub_script_argv *argv); +int grub_script_argv_next (struct grub_script_argv *argv); +int grub_script_argv_append (struct grub_script_argv *argv, const char *s); +int grub_script_argv_split_append (struct grub_script_argv *argv, char *s); + struct grub_script_arglist * grub_script_create_arglist (struct grub_parser_param *state); @@ -234,8 +241,6 @@ grub_script_add_arglist (struct grub_parser_param *state, struct grub_script_cmd * grub_script_create_cmdline (struct grub_parser_param *state, struct grub_script_arglist *arglist); -struct grub_script_cmd * -grub_script_create_cmdblock (struct grub_parser_param *state); struct grub_script_cmd * grub_script_create_cmdif (struct grub_parser_param *state, @@ -262,9 +267,9 @@ grub_script_create_cmdmenu (struct grub_parser_param *state, int options); struct grub_script_cmd * -grub_script_add_cmd (struct grub_parser_param *state, - struct grub_script_cmdblock *cmdblock, - struct grub_script_cmd *cmd); +grub_script_append_cmd (struct grub_parser_param *state, + struct grub_script_cmd *list, + struct grub_script_cmd *last); struct grub_script_arg * grub_script_arg_add (struct grub_parser_param *state, struct grub_script_arg *arg, @@ -301,7 +306,7 @@ void grub_script_yyerror (struct grub_parser_param *, char const *); /* Commands to execute, don't use these directly. */ grub_err_t grub_script_execute_cmdline (struct grub_script_cmd *cmd); -grub_err_t grub_script_execute_cmdblock (struct grub_script_cmd *cmd); +grub_err_t grub_script_execute_cmdlist (struct grub_script_cmd *cmd); grub_err_t grub_script_execute_cmdif (struct grub_script_cmd *cmd); grub_err_t grub_script_execute_cmdfor (struct grub_script_cmd *cmd); grub_err_t grub_script_execute_cmdwhile (struct grub_script_cmd *cmd); @@ -310,6 +315,12 @@ grub_err_t grub_script_execute_menuentry (struct grub_script_cmd *cmd); /* Execute any GRUB pre-parsed command or script. */ grub_err_t grub_script_execute (struct grub_script *script); +/* Break command for loops. */ +grub_err_t grub_script_break (grub_command_t cmd, int argc, char *argv[]); + +/* SHIFT command for GRUB script. */ +grub_err_t grub_script_shift (grub_command_t cmd, int argc, char *argv[]); + /* This variable points to the parsed command. This is used to communicate with the bison code. */ extern struct grub_script_cmd *grub_script_parsed; @@ -344,8 +355,9 @@ grub_script_function_t grub_script_function_create (struct grub_script_arg *func struct grub_script *cmd); void grub_script_function_remove (const char *name); grub_script_function_t grub_script_function_find (char *functionname); -int grub_script_function_call (grub_script_function_t func, - int argc, char **args); + +grub_err_t grub_script_function_call (grub_script_function_t func, + int argc, char **args); char ** grub_script_execute_arglist_to_argv (struct grub_script_arglist *arglist, int *count); diff --git a/include/grub/util/libzfs.h b/include/grub/util/libzfs.h index 9fbfd40d1..0500f70d7 100644 --- a/include/grub/util/libzfs.h +++ b/include/grub/util/libzfs.h @@ -30,7 +30,7 @@ typedef void libzfs_handle_t; typedef void zpool_handle_t; -extern libzfs_handle_t *libzfs_init (); +extern libzfs_handle_t *libzfs_init (void); extern void libzfs_fini (libzfs_handle_t *); extern zpool_handle_t *zpool_open (libzfs_handle_t *, const char *); diff --git a/include/grub/util/misc.h b/include/grub/util/misc.h index 3614c79c2..48dfbb868 100644 --- a/include/grub/util/misc.h +++ b/include/grub/util/misc.h @@ -29,7 +29,6 @@ #include #include #include -#include char *grub_util_get_path (const char *dir, const char *file); size_t grub_util_get_fp_size (FILE *fp); @@ -61,7 +60,4 @@ char *canonicalize_file_name (const char *path); void grub_util_init_nls (void); -void grub_util_init_libzfs (void); -extern libzfs_handle_t *libzfs_handle; - #endif /* ! GRUB_UTIL_MISC_HEADER */ diff --git a/include/grub/vga.h b/include/grub/vga.h index d4a1523a7..7f112d83a 100644 --- a/include/grub/vga.h +++ b/include/grub/vga.h @@ -19,9 +19,13 @@ #ifndef GRUB_VGA_HEADER #define GRUB_VGA_HEADER 1 +#include + enum { GRUB_VGA_IO_ARX = 0x3c0, + GRUB_VGA_IO_ARX_READ = 0x3c1, + GRUB_VGA_IO_MISC_WRITE = 0x3c2, GRUB_VGA_IO_SR_INDEX = 0x3c4, GRUB_VGA_IO_SR_DATA = 0x3c5, GRUB_VGA_IO_PIXEL_MASK = 0x3c6, @@ -39,8 +43,15 @@ enum enum { - GRUB_VGA_CR_WIDTH = 0x01, + GRUB_VGA_CR_HTOTAL = 0x00, + GRUB_VGA_CR_HORIZ_END = 0x01, + GRUB_VGA_CR_HBLANK_START = 0x02, + GRUB_VGA_CR_HBLANK_END = 0x03, + GRUB_VGA_CR_HORIZ_SYNC_PULSE_START = 0x04, + GRUB_VGA_CR_HORIZ_SYNC_PULSE_END = 0x05, + GRUB_VGA_CR_VERT_TOTAL = 0x06, GRUB_VGA_CR_OVERFLOW = 0x07, + GRUB_VGA_CR_BYTE_PANNING = 0x08, GRUB_VGA_CR_CELL_HEIGHT = 0x09, GRUB_VGA_CR_CURSOR_START = 0x0a, GRUB_VGA_CR_CURSOR_END = 0x0b, @@ -48,14 +59,71 @@ enum GRUB_VGA_CR_START_ADDR_LOW_REGISTER = 0x0d, GRUB_VGA_CR_CURSOR_ADDR_HIGH = 0x0e, GRUB_VGA_CR_CURSOR_ADDR_LOW = 0x0f, + GRUB_VGA_CR_VSYNC_START = 0x10, GRUB_VGA_CR_VSYNC_END = 0x11, - GRUB_VGA_CR_HEIGHT = 0x12, + GRUB_VGA_CR_VDISPLAY_END = 0x12, GRUB_VGA_CR_PITCH = 0x13, + GRUB_VGA_CR_UNDERLINE_LOCATION = 0x14, + GRUB_VGA_CR_VERTICAL_BLANK_START = 0x15, + GRUB_VGA_CR_VERTICAL_BLANK_END = 0x16, GRUB_VGA_CR_MODE = 0x17, GRUB_VGA_CR_LINE_COMPARE = 0x18, }; +enum + { + GRUB_VGA_CR_BYTE_PANNING_NORMAL = 0 + }; + +enum + { + GRUB_VGA_CR_UNDERLINE_LOCATION_DWORD_MODE = 0x40 + }; + +enum + { + GRUB_VGA_IO_MISC_COLOR = 0x01, + GRUB_VGA_IO_MISC_ENABLE_VRAM_ACCESS = 0x02, + GRUB_VGA_IO_MISC_EXTERNAL_CLOCK_0 = 0x08, + GRUB_VGA_IO_MISC_28MHZ = 0x04, + GRUB_VGA_IO_MISC_UPPER_64K = 0x20, + GRUB_VGA_IO_MISC_NEGATIVE_HORIZ_POLARITY = 0x40, + GRUB_VGA_IO_MISC_NEGATIVE_VERT_POLARITY = 0x80, + }; + +enum + { + GRUB_VGA_ARX_MODE = 0x10, + GRUB_VGA_ARX_OVERSCAN = 0x11, + GRUB_VGA_ARX_COLOR_PLANE_ENABLE = 0x12, + GRUB_VGA_ARX_HORIZONTAL_PANNING = 0x13, + GRUB_VGA_ARX_COLOR_SELECT = 0x14 + }; + +enum + { + GRUB_VGA_ARX_MODE_TEXT = 0x00, + GRUB_VGA_ARX_MODE_GRAPHICS = 0x01, + GRUB_VGA_ARX_MODE_ENABLE_256COLOR = 0x40 + }; + #define GRUB_VGA_CR_WIDTH_DIVISOR 8 + +#define GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END1_SHIFT 7 +#define GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END1_MASK 0x02 +#define GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END2_SHIFT 3 +#define GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END2_MASK 0x40 + +#define GRUB_VGA_CR_OVERFLOW_VERT_TOTAL1_SHIFT 8 +#define GRUB_VGA_CR_OVERFLOW_VERT_TOTAL1_MASK 0x01 +#define GRUB_VGA_CR_OVERFLOW_VERT_TOTAL2_SHIFT 4 +#define GRUB_VGA_CR_OVERFLOW_VERT_TOTAL2_MASK 0x20 + +#define GRUB_VGA_CR_OVERFLOW_VSYNC_START1_SHIFT 6 +#define GRUB_VGA_CR_OVERFLOW_VSYNC_START1_MASK 0x04 +#define GRUB_VGA_CR_OVERFLOW_VSYNC_START2_SHIFT 2 +#define GRUB_VGA_CR_OVERFLOW_VSYNC_START2_MASK 0x80 + #define GRUB_VGA_CR_OVERFLOW_HEIGHT1_SHIFT 7 #define GRUB_VGA_CR_OVERFLOW_HEIGHT1_MASK 0x02 #define GRUB_VGA_CR_OVERFLOW_HEIGHT2_SHIFT 3 @@ -65,7 +133,9 @@ enum #define GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_MASK 0x40 #define GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_SHIFT 3 - +#define GRUB_VGA_CR_CELL_HEIGHT_VERTICAL_BLANK_MASK 0x20 +#define GRUB_VGA_CR_CELL_HEIGHT_VERTICAL_BLANK_SHIFT 4 +#define GRUB_VGA_CR_CELL_HEIGHT_DOUBLE_SCAN 0x80 enum { GRUB_VGA_CR_CURSOR_START_DISABLE = (1 << 5) @@ -77,17 +147,26 @@ enum { GRUB_VGA_CR_MODE_NO_CGA = 0x01, GRUB_VGA_CR_MODE_NO_HERCULES = 0x02, + GRUB_VGA_CR_MODE_ADDRESS_WRAP = 0x20, GRUB_VGA_CR_MODE_BYTE_MODE = 0x40, GRUB_VGA_CR_MODE_TIMING_ENABLE = 0x80 }; enum { + GRUB_VGA_SR_RESET = 0, GRUB_VGA_SR_CLOCKING_MODE = 1, GRUB_VGA_SR_MAP_MASK_REGISTER = 2, + GRUB_VGA_SR_CHAR_MAP_SELECT = 3, GRUB_VGA_SR_MEMORY_MODE = 4, }; +enum + { + GRUB_VGA_SR_RESET_ASYNC = 1, + GRUB_VGA_SR_RESET_SYNC = 2 + }; + enum { GRUB_VGA_SR_CLOCKING_MODE_8_DOT_CLOCK = 1 @@ -96,19 +175,33 @@ enum enum { GRUB_VGA_SR_MEMORY_MODE_NORMAL = 0, - GRUB_VGA_SR_MEMORY_MODE_CHAIN4 = 8 + GRUB_VGA_SR_MEMORY_MODE_EXTERNAL_VIDEO_MEMORY = 2, + GRUB_VGA_SR_MEMORY_MODE_SEQUENTIAL_ADDRESSING = 4, + GRUB_VGA_SR_MEMORY_MODE_CHAIN4 = 8, }; enum { + GRUB_VGA_GR_SET_RESET_PLANE = 0, + GRUB_VGA_GR_SET_RESET_PLANE_ENABLE = 1, + GRUB_VGA_GR_COLOR_COMPARE = 2, GRUB_VGA_GR_DATA_ROTATE = 3, GRUB_VGA_GR_READ_MAP_REGISTER = 4, GRUB_VGA_GR_MODE = 5, GRUB_VGA_GR_GR6 = 6, + GRUB_VGA_GR_COLOR_COMPARE_DISABLE = 7, GRUB_VGA_GR_BITMASK = 8, GRUB_VGA_GR_MAX }; +#define GRUB_VGA_ALL_PLANES 0xf +#define GRUB_VGA_NO_PLANES 0x0 + +enum + { + GRUB_VGA_GR_DATA_ROTATE_NOP = 0 + }; + enum { GRUB_VGA_TEXT_TEXT_PLANE = 0, @@ -119,6 +212,7 @@ enum enum { GRUB_VGA_GR_GR6_GRAPHICS_MODE = 1, + GRUB_VGA_GR_GR6_MMAP_A0 = (1 << 2), GRUB_VGA_GR_GR6_MMAP_CGA = (3 << 2) }; @@ -126,70 +220,152 @@ enum { GRUB_VGA_GR_MODE_READ_MODE1 = 0x08, GRUB_VGA_GR_MODE_ODD_EVEN = 0x10, + GRUB_VGA_GR_MODE_ODD_EVEN_SHIFT = 0x20, GRUB_VGA_GR_MODE_256_COLOR = 0x40 }; static inline void grub_vga_gr_write (grub_uint8_t val, grub_uint8_t addr) { - grub_outb (addr, GRUB_VGA_IO_GR_INDEX); - grub_outb (val, GRUB_VGA_IO_GR_DATA); + grub_outb (addr, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_GR_INDEX); + grub_outb (val, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_GR_DATA); } static inline grub_uint8_t grub_vga_gr_read (grub_uint8_t addr) { - grub_outb (addr, GRUB_VGA_IO_GR_INDEX); - return grub_inb (GRUB_VGA_IO_GR_DATA); + grub_outb (addr, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_GR_INDEX); + return grub_inb (GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_GR_DATA); } static inline void grub_vga_cr_write (grub_uint8_t val, grub_uint8_t addr) { - grub_outb (addr, GRUB_VGA_IO_CR_INDEX); - grub_outb (val, GRUB_VGA_IO_CR_DATA); + grub_outb (addr, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_CR_INDEX); + grub_outb (val, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_CR_DATA); } static inline grub_uint8_t grub_vga_cr_read (grub_uint8_t addr) { - grub_outb (addr, GRUB_VGA_IO_CR_INDEX); - return grub_inb (GRUB_VGA_IO_CR_DATA); + grub_outb (addr, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_CR_INDEX); + return grub_inb (GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_CR_DATA); } static inline void grub_vga_sr_write (grub_uint8_t val, grub_uint8_t addr) { - grub_outb (addr, GRUB_VGA_IO_SR_INDEX); - grub_outb (val, GRUB_VGA_IO_SR_DATA); + grub_outb (addr, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_INDEX); + grub_outb (val, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_DATA); } static inline grub_uint8_t grub_vga_sr_read (grub_uint8_t addr) { - grub_outb (addr, GRUB_VGA_IO_SR_INDEX); - return grub_inb (GRUB_VGA_IO_SR_DATA); + grub_outb (addr, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_INDEX); + return grub_inb (GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_SR_DATA); } static inline void grub_vga_palette_read (grub_uint8_t addr, grub_uint8_t *r, grub_uint8_t *g, grub_uint8_t *b) { - grub_outb (addr, GRUB_VGA_IO_PALLETTE_READ_INDEX); - *r = grub_inb (GRUB_VGA_IO_PALLETTE_DATA); - *g = grub_inb (GRUB_VGA_IO_PALLETTE_DATA); - *b = grub_inb (GRUB_VGA_IO_PALLETTE_DATA); + grub_outb (addr, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_PALLETTE_READ_INDEX); + *r = grub_inb (GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_PALLETTE_DATA); + *g = grub_inb (GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_PALLETTE_DATA); + *b = grub_inb (GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_PALLETTE_DATA); } static inline void grub_vga_palette_write (grub_uint8_t addr, grub_uint8_t r, grub_uint8_t g, grub_uint8_t b) { - grub_outb (addr, GRUB_VGA_IO_PALLETTE_WRITE_INDEX); - grub_outb (r, GRUB_VGA_IO_PALLETTE_DATA); - grub_outb (g, GRUB_VGA_IO_PALLETTE_DATA); - grub_outb (b, GRUB_VGA_IO_PALLETTE_DATA); + grub_outb (addr, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_PALLETTE_WRITE_INDEX); + grub_outb (r, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_PALLETTE_DATA); + grub_outb (g, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_PALLETTE_DATA); + grub_outb (b, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_PALLETTE_DATA); } +static inline void +grub_vga_write_arx (grub_uint8_t val, grub_uint8_t addr) +{ + grub_inb (GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_INPUT_STATUS1_REGISTER); + grub_outb (addr, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_ARX); + grub_inb (GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_ARX_READ); + grub_outb (val, GRUB_MACHINE_PCI_IO_BASE + GRUB_VGA_IO_ARX); +} + +struct grub_video_hw_config +{ + unsigned vertical_total; + unsigned vertical_blank_start; + unsigned vertical_blank_end; + unsigned vertical_sync_start; + unsigned vertical_sync_end; + unsigned line_compare; + unsigned vdisplay_end; + unsigned pitch; + unsigned horizontal_total; + unsigned horizontal_blank_start; + unsigned horizontal_blank_end; + unsigned horizontal_sync_pulse_start; + unsigned horizontal_sync_pulse_end; + unsigned horizontal_end; +}; + +static inline void +grub_vga_set_geometry (struct grub_video_hw_config *config, + void (*cr_write) (grub_uint8_t val, grub_uint8_t addr)) +{ + unsigned vertical_total = config->vertical_total - 2; + unsigned vertical_blank_start = config->vertical_blank_start - 1; + unsigned vdisplay_end = config->vdisplay_end - 1; + grub_uint8_t overflow, cell_height_reg; + + /* Disable CR0-7 write protection. */ + cr_write (0, GRUB_VGA_CR_VSYNC_END); + + overflow = ((vertical_total >> GRUB_VGA_CR_OVERFLOW_VERT_TOTAL1_SHIFT) + & GRUB_VGA_CR_OVERFLOW_VERT_TOTAL1_MASK) + | ((vertical_total >> GRUB_VGA_CR_OVERFLOW_VERT_TOTAL2_SHIFT) + & GRUB_VGA_CR_OVERFLOW_VERT_TOTAL2_MASK) + | ((config->vertical_sync_start >> GRUB_VGA_CR_OVERFLOW_VSYNC_START2_SHIFT) + & GRUB_VGA_CR_OVERFLOW_VSYNC_START2_MASK) + | ((config->vertical_sync_start >> GRUB_VGA_CR_OVERFLOW_VSYNC_START1_SHIFT) + & GRUB_VGA_CR_OVERFLOW_VSYNC_START1_MASK) + | ((vdisplay_end >> GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END1_SHIFT) + & GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END1_MASK) + | ((vdisplay_end >> GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END2_SHIFT) + & GRUB_VGA_CR_OVERFLOW_VERT_DISPLAY_ENABLE_END2_MASK) + | ((config->vertical_sync_start >> GRUB_VGA_CR_OVERFLOW_VSYNC_START1_SHIFT) + & GRUB_VGA_CR_OVERFLOW_VSYNC_START1_MASK) + | ((config->line_compare >> GRUB_VGA_CR_OVERFLOW_LINE_COMPARE_SHIFT) + & GRUB_VGA_CR_OVERFLOW_LINE_COMPARE_MASK); + + cell_height_reg = ((vertical_blank_start + >> GRUB_VGA_CR_CELL_HEIGHT_VERTICAL_BLANK_SHIFT) + & GRUB_VGA_CR_CELL_HEIGHT_VERTICAL_BLANK_MASK) + | ((config->line_compare >> GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_SHIFT) + & GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_MASK); + + cr_write (config->horizontal_total - 1, GRUB_VGA_CR_HTOTAL); + cr_write (config->horizontal_end - 1, GRUB_VGA_CR_HORIZ_END); + cr_write (config->horizontal_blank_start - 1, GRUB_VGA_CR_HBLANK_START); + cr_write (config->horizontal_blank_end, GRUB_VGA_CR_HBLANK_END); + cr_write (config->horizontal_sync_pulse_start, + GRUB_VGA_CR_HORIZ_SYNC_PULSE_START); + cr_write (config->horizontal_sync_pulse_end, + GRUB_VGA_CR_HORIZ_SYNC_PULSE_END); + cr_write (vertical_total & 0xff, GRUB_VGA_CR_VERT_TOTAL); + cr_write (overflow, GRUB_VGA_CR_OVERFLOW); + cr_write (cell_height_reg, GRUB_VGA_CR_CELL_HEIGHT); + cr_write (config->vertical_sync_start & 0xff, GRUB_VGA_CR_VSYNC_START); + cr_write (config->vertical_sync_end & 0x0f, GRUB_VGA_CR_VSYNC_END); + cr_write (vdisplay_end & 0xff, GRUB_VGA_CR_VDISPLAY_END); + cr_write (config->pitch & 0xff, GRUB_VGA_CR_PITCH); + cr_write (vertical_blank_start & 0xff, GRUB_VGA_CR_VERTICAL_BLANK_START); + cr_write (config->vertical_blank_end & 0xff, GRUB_VGA_CR_VERTICAL_BLANK_END); + cr_write (config->line_compare & 0xff, GRUB_VGA_CR_LINE_COMPARE); +} #endif diff --git a/kern/emu/getroot.c b/kern/emu/getroot.c index 032608d1b..c0a10d22b 100644 --- a/kern/emu/getroot.c +++ b/kern/emu/getroot.c @@ -49,10 +49,6 @@ # include #endif -#ifdef HAVE_GETFSSTAT -# include -#endif - #include #include #include @@ -98,66 +94,6 @@ xgetcwd (void) return path; } -#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) - -static char * -find_mount_point_from_dir (const char *dir) -{ - struct stat st; - typeof (st.st_dev) fs; - char *prev, *next, *slash, *statdir; - - if (stat (dir, &st) == -1) - error (1, errno, "stat (%s)", dir); - - fs = st.st_dev; - - prev = xstrdup (dir); - - while (1) - { - /* Remove last slash. */ - next = xstrdup (prev); - slash = strrchr (next, '/'); - if (! slash) - { - free (next); - free (prev); - return NULL; - } - *slash = '\0'; - - /* A next empty string counts as /. */ - if (next[0] == '\0') - statdir = "/"; - else - statdir = next; - - if (stat (statdir, &st) == -1) - error (1, errno, "stat (%s)", next); - - if (st.st_dev != fs) - { - /* Found mount point. */ - free (next); - return prev; - } - - free (prev); - prev = next; - - /* We've already seen an empty string, which means we - reached /. Nothing left to do. */ - if (prev[0] == '\0') - { - free (prev); - return xstrdup ("/"); - } - } -} - -#endif - #ifdef __linux__ /* Statting something on a btrfs filesystem always returns a virtual device @@ -239,63 +175,29 @@ find_root_device_from_mountinfo (const char *dir) #endif /* __linux__ */ #if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) - -/* ZFS has similar problems to those of btrfs (see above). */ static char * find_root_device_from_libzfs (const char *dir) { - char *device = NULL; - char *poolname = NULL; - char *poolfs = NULL; - char *mnt_point; - char *slash; - - mnt_point = find_mount_point_from_dir (dir); - -#ifdef HAVE_GETFSSTAT - { - int mnt_count = getfsstat (NULL, 0, MNT_WAIT); - if (mnt_count == -1) - error (1, errno, "getfsstat"); - - struct statfs *mnt = xmalloc (mnt_count * sizeof (*mnt)); - - mnt_count = getfsstat (mnt, mnt_count * sizeof (*mnt), MNT_WAIT); - if (mnt_count == -1) - error (1, errno, "getfsstat"); - - unsigned int i; - for (i = 0; i < (unsigned) mnt_count; i++) - if (!strcmp (mnt[i].f_fstypename, "zfs") - && !strcmp (mnt[i].f_mntonname, mnt_point)) - { - poolname = xstrdup (mnt[i].f_mntfromname); - break; - } - - free (mnt); - } -#endif + char *device; + char *poolname; + char *poolfs; + grub_find_zpool_from_dir (dir, &poolname, &poolfs); if (! poolname) return NULL; - slash = strchr (poolname, '/'); - if (slash) - { - *slash = '\0'; - poolfs = slash + 1; - } - { zpool_handle_t *zpool; + libzfs_handle_t *libzfs; nvlist_t *nvlist; nvlist_t **nvlist_array; unsigned int nvlist_count; - grub_util_init_libzfs (); + libzfs = grub_get_libzfs_handle (); + if (! libzfs) + return NULL; - zpool = zpool_open (libzfs_handle, poolname); + zpool = zpool_open (libzfs, poolname); nvlist = zpool_get_config (zpool, NULL); if (nvlist_lookup_nvlist (nvlist, "vdev_tree", &nvlist) != 0) @@ -317,6 +219,8 @@ find_root_device_from_libzfs (const char *dir) } free (poolname); + if (poolfs) + free (poolfs); return device; } diff --git a/kern/emu/misc.c b/kern/emu/misc.c index 851da7a07..82f579616 100644 --- a/kern/emu/misc.c +++ b/kern/emu/misc.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -44,6 +45,22 @@ # include #endif +#ifdef HAVE_LIBZFS +# include +#endif + +#ifdef HAVE_LIBNVPAIR +# include +#endif + +#ifdef HAVE_SYS_PARAM_H +# include +#endif + +#ifdef HAVE_SYS_MOUNT_H +# include +#endif + int verbosity; void @@ -236,23 +253,87 @@ get_win32_path (const char *path) } #endif +#ifdef HAVE_LIBZFS +static libzfs_handle_t *__libzfs_handle; + +static void +fini_libzfs (void) +{ + libzfs_fini (__libzfs_handle); +} + +libzfs_handle_t * +grub_get_libzfs_handle (void) +{ + if (! __libzfs_handle) + { + __libzfs_handle = libzfs_init (); + + if (__libzfs_handle) + atexit (fini_libzfs); + } + + return __libzfs_handle; +} +#endif /* HAVE_LIBZFS */ + +#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) +/* ZFS has similar problems to those of btrfs (see above). */ +void +grub_find_zpool_from_dir (const char *dir, char **poolname, char **poolfs) +{ + struct statfs mnt; + char *slash; + + *poolname = *poolfs = NULL; + + if (statfs (dir, &mnt) != 0) + return; + + if (strcmp (mnt.f_fstypename, "zfs") != 0) + return; + + *poolname = xstrdup (mnt.f_mntfromname); + + slash = strchr (*poolname, '/'); + if (slash) + { + *slash = '\0'; + *poolfs = xstrdup (slash + 1); + } + else + *poolfs = xstrdup (""); +} +#endif + /* This function never prints trailing slashes (so that its output can be appended a slash unconditionally). */ char * grub_make_system_path_relative_to_its_root (const char *path) { struct stat st; - char *p, *buf, *buf2, *buf3; + char *p, *buf, *buf2, *buf3, *ret; uintptr_t offset = 0; dev_t num; size_t len; +#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) + char *poolfs = NULL; +#endif + /* canonicalize. */ p = canonicalize_file_name (path); - if (p == NULL) grub_util_error ("failed to get canonical path of %s", path); +#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) + /* For ZFS sub-pool filesystems, could be extended to others (btrfs?). */ + { + char *dummy; + grub_find_zpool_from_dir (p, &dummy, &poolfs); + } +#endif + len = strlen (p) + 1; buf = xstrdup (p); free (p); @@ -331,7 +412,17 @@ grub_make_system_path_relative_to_its_root (const char *path) len--; } - return buf3; +#if defined(HAVE_LIBZFS) && defined(HAVE_LIBNVPAIR) + if (poolfs) + { + ret = xasprintf ("/%s/@%s", poolfs, buf3); + free (buf3); + } + else +#endif + ret = buf3; + + return ret; } #ifdef HAVE_DEVICE_MAPPER diff --git a/kern/i386/qemu/init.c b/kern/i386/qemu/init.c index 201ba3633..054dfa86b 100644 --- a/kern/i386/qemu/init.c +++ b/kern/i386/qemu/init.c @@ -69,10 +69,7 @@ load_palette (void) { unsigned i; for (i = 0; i < 16; i++) - { - grub_outb (i, GRUB_VGA_IO_ARX); - grub_outb (i, GRUB_VGA_IO_ARX); - } + grub_vga_write_arx (i, i); for (i = 0; i < ARRAY_SIZE (colors); i++) grub_vga_palette_write (i, colors[i].r, colors[i].g, colors[i].b); @@ -90,7 +87,7 @@ grub_qemu_init_cirrus (void) addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); class = grub_pci_read (addr); - if (((class >> 16) & 0xffff) != 0x0300) + if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA) return 0; /* FIXME: chooose addresses dynamically. */ @@ -110,7 +107,7 @@ grub_qemu_init_cirrus (void) grub_pci_iterate (find_card); - grub_outb (1, 0x3c2); + grub_outb (GRUB_VGA_IO_MISC_COLOR, GRUB_VGA_IO_MISC_WRITE); load_font (); @@ -124,11 +121,11 @@ grub_qemu_init_cirrus (void) GRUB_VGA_SR_MAP_MASK_REGISTER); grub_vga_cr_write (15, GRUB_VGA_CR_CELL_HEIGHT); - grub_vga_cr_write (79, GRUB_VGA_CR_WIDTH); + grub_vga_cr_write (79, GRUB_VGA_CR_HORIZ_END); grub_vga_cr_write (40, GRUB_VGA_CR_PITCH); int vert = 25 * 16; - grub_vga_cr_write (vert & 0xff, GRUB_VGA_CR_HEIGHT); + grub_vga_cr_write (vert & 0xff, GRUB_VGA_CR_VDISPLAY_END); grub_vga_cr_write (((vert >> GRUB_VGA_CR_OVERFLOW_HEIGHT1_SHIFT) & GRUB_VGA_CR_OVERFLOW_HEIGHT1_MASK) | ((vert >> GRUB_VGA_CR_OVERFLOW_HEIGHT2_SHIFT) @@ -137,10 +134,8 @@ grub_qemu_init_cirrus (void) load_palette (); - grub_outb (0x10, 0x3c0); - grub_outb (0, 0x3c1); - grub_outb (0x14, 0x3c0); - grub_outb (0, 0x3c1); + grub_vga_write_arx (GRUB_VGA_ARX_MODE_TEXT, GRUB_VGA_ARX_MODE); + grub_vga_write_arx (0, GRUB_VGA_ARX_COLOR_SELECT); grub_vga_sr_write (GRUB_VGA_SR_CLOCKING_MODE_8_DOT_CLOCK, GRUB_VGA_SR_CLOCKING_MODE); diff --git a/normal/color.c b/normal/color.c index bae082911..a16d1c2f9 100644 --- a/normal/color.c +++ b/normal/color.c @@ -56,22 +56,23 @@ parse_color_name (grub_uint8_t *ret, char *name) return -1; } -void -grub_parse_color_name_pair (grub_uint8_t *ret, const char *name) +int +grub_parse_color_name_pair (grub_uint8_t *color, const char *name) { + int result = 1; grub_uint8_t fg, bg; char *fg_name, *bg_name; /* nothing specified by user */ if (name == NULL) - return; + return result; fg_name = grub_strdup (name); if (fg_name == NULL) { /* "out of memory" message was printed by grub_strdup() */ grub_wait_after_message (); - return; + return result; } bg_name = grub_strchr (fg_name, '/'); @@ -97,10 +98,12 @@ grub_parse_color_name_pair (grub_uint8_t *ret, const char *name) goto free_and_return; } - *ret = (bg << 4) | fg; + *color = (bg << 4) | fg; + result = 0; free_and_return: grub_free (fg_name); + return result; } static grub_uint8_t color_normal, color_highlight; @@ -122,10 +125,10 @@ set_colors (void) /* Replace default `normal' colors with the ones specified by user (if any). */ char * -grub_env_write_color_normal (struct grub_env_var *var __attribute__ ((unused)), - const char *val) +grub_env_write_color_normal (struct grub_env_var *var, const char *val) { - grub_parse_color_name_pair (&color_normal, val); + if (grub_parse_color_name_pair (&color_normal, val)) + return 0; set_colors (); @@ -134,10 +137,10 @@ grub_env_write_color_normal (struct grub_env_var *var __attribute__ ((unused)), /* Replace default `highlight' colors with the ones specified by user (if any). */ char * -grub_env_write_color_highlight (struct grub_env_var *var __attribute__ ((unused)), - const char *val) +grub_env_write_color_highlight (struct grub_env_var *var, const char *val) { - grub_parse_color_name_pair (&color_highlight, val); + if (grub_parse_color_name_pair (&color_highlight, val)) + return 0; set_colors (); diff --git a/normal/main.c b/normal/main.c index 710b68d14..49658fd24 100644 --- a/normal/main.c +++ b/normal/main.c @@ -675,6 +675,7 @@ static void (*grub_xputs_saved) (const char *str); GRUB_MOD_INIT(normal) { grub_context_init (); + grub_script_init (); grub_xputs_saved = grub_xputs; grub_xputs = grub_xputs_normal; @@ -704,11 +705,16 @@ GRUB_MOD_INIT(normal) /* Preserve hooks after context changes. */ grub_env_export ("color_normal"); grub_env_export ("color_highlight"); + + /* Set default color names. */ + grub_env_set ("color_normal", "white/black"); + grub_env_set ("color_highlight", "black/white"); } GRUB_MOD_FINI(normal) { grub_context_fini (); + grub_script_fini (); grub_xputs = grub_xputs_saved; diff --git a/script/argv.c b/script/argv.c new file mode 100644 index 000000000..b69ee39c5 --- /dev/null +++ b/script/argv.c @@ -0,0 +1,133 @@ +/* argv.c - methods for constructing argument vector */ +/* + * 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 + +/* Return nearest power of two that is >= v. */ +static unsigned +round_up_exp (unsigned v) +{ + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + + if (sizeof (v) > 4) + v |= v >> 32; + + v++; + v += (v == 0); + + return v; +} + +void +grub_script_argv_free (struct grub_script_argv *argv) +{ + unsigned i; + + if (argv->args) + { + for (i = 0; i < argv->argc; i++) + grub_free (argv->args[i]); + + grub_free (argv->args); + } + + argv->argc = 0; + argv->args = 0; +} + +/* Prepare for next argc. */ +int +grub_script_argv_next (struct grub_script_argv *argv) +{ + char **p = argv->args; + + if (argv->args && argv->args[argv->argc - 1] == 0) + return 0; + + p = grub_realloc (p, round_up_exp ((argv->argc + 2) * sizeof (char *))); + if (! p) + return 1; + + argv->argc++; + argv->args = p; + + if (argv->argc == 1) + argv->args[0] = 0; + argv->args[argv->argc] = 0; + return 0; +} + +/* Append `s' to the last argument. */ +int +grub_script_argv_append (struct grub_script_argv *argv, const char *s) +{ + int a, b; + char *p = argv->args[argv->argc - 1]; + + if (! s) + return 0; + + a = p ? grub_strlen (p) : 0; + b = grub_strlen (s); + + p = grub_realloc (p, round_up_exp ((a + b + 1) * sizeof (char))); + if (! p) + return 1; + + grub_strcpy (p + a, s); + argv->args[argv->argc - 1] = p; + return 0; +} + +/* Split `s' and append words as multiple arguments. */ +int +grub_script_argv_split_append (struct grub_script_argv *argv, char *s) +{ + char ch; + char *p; + int errors = 0; + + if (! s) + return 0; + + while (! errors && *s) + { + p = s; + while (*s && ! grub_isspace (*s)) + s++; + + ch = *s; + *s = '\0'; + errors += grub_script_argv_append (argv, p); + *s = ch; + + while (*s && grub_isspace (*s)) + s++; + + if (*s) + errors += grub_script_argv_next (argv); + } + return errors; +} diff --git a/script/execute.c b/script/execute.c index 40f161267..26a46b12b 100644 --- a/script/execute.c +++ b/script/execute.c @@ -30,6 +30,252 @@ is sizeof (int) * 3, and one extra for a possible -ve sign. */ #define ERRNO_DIGITS_MAX (sizeof (int) * 3 + 1) +static unsigned long is_continue; +static unsigned long active_loops; +static unsigned long active_breaks; + +/* Scope for grub script functions. */ +struct grub_script_scope +{ + struct grub_script_argv argv; +}; +static struct grub_script_scope *scope = 0; + +grub_err_t +grub_script_break (grub_command_t cmd, int argc, char *argv[]) +{ + char *p = 0; + unsigned long count; + + if (argc == 0) + count = 1; + + else if ((argc > 1) || (count = grub_strtoul (argv[0], &p, 10)) == 0 || + (*p != '\0')) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad break"); + + is_continue = grub_strcmp (cmd->name, "break") ? 1 : 0; + active_breaks = grub_min (active_loops, count); + return GRUB_ERR_NONE; +} + +grub_err_t +grub_script_shift (grub_command_t cmd __attribute__((unused)), + int argc, char *argv[]) +{ + char *p = 0; + unsigned long n = 0; + + if (! scope) + return GRUB_ERR_NONE; + + if (argc == 0) + n = 1; + + else if (argc > 1) + return GRUB_ERR_BAD_ARGUMENT; + + else + { + n = grub_strtoul (argv[0], &p, 10); + if (*p != '\0') + return GRUB_ERR_BAD_ARGUMENT; + } + + if (n > scope->argv.argc) + return GRUB_ERR_BAD_ARGUMENT; + + scope->argv.argc -= n; + scope->argv.args += n; + return GRUB_ERR_NONE; +} + +static int +grub_env_special (const char *name) +{ + if (grub_isdigit (name[0]) || + grub_strcmp (name, "#") == 0 || + grub_strcmp (name, "*") == 0 || + grub_strcmp (name, "@") == 0) + return 1; + return 0; +} + +static char ** +grub_script_env_get (const char *name, grub_script_arg_type_t type) +{ + struct grub_script_argv result = { 0, 0 }; + + if (grub_script_argv_next (&result)) + goto fail; + + if (! grub_env_special (name)) + { + char *v = grub_env_get (name); + if (v && v[0]) + { + if (type == GRUB_SCRIPT_ARG_TYPE_VAR) + { + if (grub_script_argv_split_append (&result, v)) + goto fail; + } + else + if (grub_script_argv_append (&result, v)) + goto fail; + } + } + else if (! scope) + { + if (grub_script_argv_append (&result, 0)) + goto fail; + } + else if (grub_strcmp (name, "#") == 0) + { + char buffer[ERRNO_DIGITS_MAX + 1]; + grub_snprintf (buffer, sizeof (buffer), "%u", scope->argv.argc); + if (grub_script_argv_append (&result, buffer)) + goto fail; + } + else if (grub_strcmp (name, "*") == 0) + { + unsigned i; + + for (i = 0; i < scope->argv.argc; i++) + if (type == GRUB_SCRIPT_ARG_TYPE_VAR) + { + if (i != 0 && grub_script_argv_next (&result)) + goto fail; + + if (grub_script_argv_split_append (&result, scope->argv.args[i])) + goto fail; + } + else + { + if (i != 0 && grub_script_argv_append (&result, " ")) + goto fail; + + if (grub_script_argv_append (&result, scope->argv.args[i])) + goto fail; + } + } + else if (grub_strcmp (name, "@") == 0) + { + unsigned i; + + for (i = 0; i < scope->argv.argc; i++) + { + if (i != 0 && grub_script_argv_next (&result)) + goto fail; + + if (type == GRUB_SCRIPT_ARG_TYPE_VAR) + { + if (grub_script_argv_split_append (&result, scope->argv.args[i])) + goto fail; + } + else + if (grub_script_argv_append (&result, scope->argv.args[i])) + goto fail; + } + } + else + { + unsigned long num = grub_strtoul (name, 0, 10); + if (num == 0) + ; /* XXX no file name, for now. */ + + else if (num <= scope->argv.argc) + { + if (type == GRUB_SCRIPT_ARG_TYPE_VAR) + { + if (grub_script_argv_split_append (&result, + scope->argv.args[num - 1])) + goto fail; + } + else + if (grub_script_argv_append (&result, scope->argv.args[num - 1])) + goto fail; + } + } + + return result.args; + + fail: + + grub_script_argv_free (&result); + return 0; +} + +static grub_err_t +grub_script_env_set (const char *name, const char *val) +{ + if (grub_env_special (name)) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad variable name"); + + return grub_env_set (name, val); +} + +/* Expand arguments in ARGLIST into multiple arguments. */ +static int +grub_script_arglist_to_argv (struct grub_script_arglist *arglist, + struct grub_script_argv *argv) +{ + int i; + char **values = 0; + struct grub_script_arg *arg = 0; + struct grub_script_argv result = { 0, 0 }; + + for (; arglist && arglist->arg; arglist = arglist->next) + { + if (grub_script_argv_next (&result)) + goto fail; + + arg = arglist->arg; + while (arg) + { + switch (arg->type) + { + case GRUB_SCRIPT_ARG_TYPE_VAR: + case GRUB_SCRIPT_ARG_TYPE_DQVAR: + values = grub_script_env_get (arg->str, arg->type); + for (i = 0; values && values[i]; i++) + { + if (i != 0 && grub_script_argv_next (&result)) + goto fail; + + if (grub_script_argv_append (&result, values[i])) + goto fail; + } + grub_free (values); + break; + + case GRUB_SCRIPT_ARG_TYPE_TEXT: + if (grub_strlen (arg->str) && + grub_script_argv_append (&result, arg->str)) + goto fail; + break; + + case GRUB_SCRIPT_ARG_TYPE_DQSTR: + case GRUB_SCRIPT_ARG_TYPE_SQSTR: + if (grub_script_argv_append (&result, arg->str)) + goto fail; + break; + } + arg = arg->next; + } + } + + if (! result.args[result.argc - 1]) + result.argc--; + + *argv = result; + return 0; + + fail: + + grub_script_argv_free (&result); + return 1; +} + static grub_err_t grub_script_execute_cmd (struct grub_script_cmd *cmd) { @@ -46,149 +292,27 @@ grub_script_execute_cmd (struct grub_script_cmd *cmd) return ret; } -#define ARG_ALLOCATION_UNIT (32 * sizeof (char)) -#define ARGV_ALLOCATION_UNIT (8 * sizeof (void*)) - -/* Expand arguments in ARGLIST into multiple arguments. */ -char ** -grub_script_execute_arglist_to_argv (struct grub_script_arglist *arglist, int *count) +/* Execute a function call. */ +grub_err_t +grub_script_function_call (grub_script_function_t func, int argc, char **args) { - int i; - int oom; - int argc; - int empty; - char *ptr; - char **argv; - char *value; - struct grub_script_arg *arg; + grub_err_t ret = 0; + unsigned long loops = active_loops; + struct grub_script_scope *old_scope; + struct grub_script_scope new_scope; - auto void push (char *str); - void push (char *str) - { - char **p; + active_loops = 0; + new_scope.argv.argc = argc; + new_scope.argv.args = args; - if (oom) - return; + old_scope = scope; + scope = &new_scope; - p = grub_realloc (argv, ALIGN_UP (sizeof(char*) * (argc + 1), ARGV_ALLOCATION_UNIT)); - if (!p) - oom = 1; - else - { - p[argc++] = str; - argv = p; - } - } + ret = grub_script_execute (func->func); - auto char* append (const char *str, grub_size_t nchar); - char* append (const char *str, grub_size_t nchar) - { - int len; - int old; - char *p; - - if (oom || !str) - return 0; - - len = nchar ?: grub_strlen (str); - old = argv[argc - 1] ? grub_strlen (argv[argc - 1]) : 0; - p = grub_realloc (argv[argc - 1], ALIGN_UP(old + len + 1, ARG_ALLOCATION_UNIT)); - - if (p) - { - grub_strncpy (p + old, str, len); - p[old + len] = '\0'; - } - else - { - oom = 1; - grub_free (argv[argc - 1]); - } - argv[argc - 1] = p; - return argv[argc - 1]; - } - - /* Move *STR to the begining of next word, but return current word. */ - auto char* move_to_next (char **str); - char* move_to_next (char **str) - { - char *end; - char *start; - - if (oom || !str || !*str) - return 0; - - start = *str; - while (*start && grub_isspace (*start)) start++; - if (*start == '\0') - return 0; - - end = start + 1; - while (*end && !grub_isspace (*end)) end++; - - *str = end; - return start; - } - - oom = 0; - argv = 0; - argc = 0; - push (0); - for (; arglist; arglist = arglist->next) - { - empty = 1; - arg = arglist->arg; - while (arg) - { - switch (arg->type) - { - case GRUB_SCRIPT_ARG_TYPE_VAR: - value = grub_env_get (arg->str); - while (value && *value && (ptr = move_to_next(&value))) - { - empty = 0; - append (ptr, value - ptr); - if (*value) push(0); - } - break; - - case GRUB_SCRIPT_ARG_TYPE_TEXT: - if (grub_strlen (arg->str) > 0) - { - empty = 0; - append (arg->str, 0); - } - break; - - case GRUB_SCRIPT_ARG_TYPE_DQSTR: - case GRUB_SCRIPT_ARG_TYPE_SQSTR: - empty = 0; - append (arg->str, 0); - break; - - case GRUB_SCRIPT_ARG_TYPE_DQVAR: - empty = 0; - append (grub_env_get (arg->str), 0); - break; - } - arg = arg->next; - } - if (!empty) - push (0); - } - - if (oom) - { - for (i = 0; i < argc; i++) - grub_free (argv[i]); - grub_free (argv); - argv = 0; - } - - if (argv) - *count = argc - 1; - - return argv; + active_loops = loops; + scope = old_scope; + return ret; } /* Execute a single command line. */ @@ -196,21 +320,18 @@ grub_err_t grub_script_execute_cmdline (struct grub_script_cmd *cmd) { struct grub_script_cmdline *cmdline = (struct grub_script_cmdline *) cmd; - char **args = 0; - int i = 0; grub_command_t grubcmd; grub_err_t ret = 0; - int argcount = 0; grub_script_function_t func = 0; char errnobuf[18]; char *cmdname; + struct grub_script_argv argv = { 0, 0 }; /* Lookup the command. */ - args = grub_script_execute_arglist_to_argv (cmdline->arglist, &argcount); - if (!args) + if (grub_script_arglist_to_argv (cmdline->arglist, &argv) || ! argv.args[0]) return grub_errno; - cmdname = args[0]; + cmdname = argv.args[0]; grubcmd = grub_command_find (cmdname); if (! grubcmd) { @@ -232,13 +353,14 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd) /* Create two strings and set the variable. */ *eq = '\0'; eq++; - grub_env_set (assign, eq); + grub_script_env_set (assign, eq); } grub_free (assign); grub_snprintf (errnobuf, sizeof (errnobuf), "%d", grub_errno); - grub_env_set ("?", errnobuf); + grub_script_env_set ("?", errnobuf); + grub_script_argv_free (&argv); grub_print_error (); return 0; @@ -247,14 +369,12 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd) /* Execute the GRUB command or function. */ if (grubcmd) - ret = (grubcmd->func) (grubcmd, argcount - 1, args + 1); + ret = (grubcmd->func) (grubcmd, argv.argc - 1, argv.args + 1); else - ret = grub_script_function_call (func, argcount - 1, args + 1); + ret = grub_script_function_call (func, argv.argc - 1, argv.args + 1); /* Free arguments. */ - for (i = 0; i < argcount; i++) - grub_free (args[i]); - grub_free (args); + grub_script_argv_free (&argv); if (grub_errno == GRUB_ERR_TEST_FAILURE) grub_errno = GRUB_ERR_NONE; @@ -269,13 +389,13 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd) /* Execute a block of one or more commands. */ grub_err_t -grub_script_execute_cmdblock (struct grub_script_cmd *cmd) +grub_script_execute_cmdlist (struct grub_script_cmd *list) { int ret = 0; - struct grub_script_cmdblock *cmdblock = (struct grub_script_cmdblock *) cmd; + struct grub_script_cmd *cmd; /* Loop over every command and execute it. */ - for (cmd = cmdblock->cmdlist; cmd; cmd = cmd->next) + for (cmd = list->next; cmd && ! active_breaks; cmd = cmd->next) ret = grub_script_execute_cmd (cmd); return ret; @@ -307,25 +427,34 @@ grub_script_execute_cmdif (struct grub_script_cmd *cmd) grub_err_t grub_script_execute_cmdfor (struct grub_script_cmd *cmd) { - int i; - int result; - char **args; - int argcount; + unsigned i; + grub_err_t result; + struct grub_script_argv argv = { 0, 0 }; + struct grub_script_cmdfor *cmdfor = (struct grub_script_cmdfor *) cmd; - args = grub_script_execute_arglist_to_argv (cmdfor->words, &argcount); - if (!args) + if (grub_script_arglist_to_argv (cmdfor->words, &argv)) return grub_errno; + active_loops++; result = 0; - for (i = 0; i < argcount; i++) + for (i = 0; i < argv.argc; i++) { - grub_env_set (cmdfor->name->str, args[i]); - result = grub_script_execute_cmd (cmdfor->list); - grub_free (args[i]); + if (is_continue && active_breaks == 1) + active_breaks = 0; + + if (! active_breaks) + { + grub_script_env_set (cmdfor->name->str, argv.args[i]); + result = grub_script_execute_cmd (cmdfor->list); + } } - grub_free (args); + if (active_breaks) + active_breaks--; + + active_loops--; + grub_script_argv_free (&argv); return result; } @@ -337,6 +466,7 @@ grub_script_execute_cmdwhile (struct grub_script_cmd *cmd) int result; struct grub_script_cmdwhile *cmdwhile = (struct grub_script_cmdwhile *) cmd; + active_loops++; result = 0; do { cond = grub_script_execute_cmd (cmdwhile->cond); @@ -344,8 +474,19 @@ grub_script_execute_cmdwhile (struct grub_script_cmd *cmd) break; result = grub_script_execute_cmd (cmdwhile->list); + + if (active_breaks == 1 && is_continue) + active_breaks = 0; + + if (active_breaks) + break; + } while (1); /* XXX Put a check for ^C here */ + if (active_breaks) + active_breaks--; + + active_loops--; return result; } @@ -354,26 +495,20 @@ grub_err_t grub_script_execute_menuentry (struct grub_script_cmd *cmd) { struct grub_script_cmd_menuentry *cmd_menuentry; - char **args = 0; - int argcount = 0; - int i = 0; + struct grub_script_argv argv = { 0, 0 }; cmd_menuentry = (struct grub_script_cmd_menuentry *) cmd; if (cmd_menuentry->arglist) { - args = grub_script_execute_arglist_to_argv (cmd_menuentry->arglist, &argcount); - if (!args) + if (grub_script_arglist_to_argv (cmd_menuentry->arglist, &argv)) return grub_errno; } - grub_normal_add_menu_entry (argcount, (const char **) args, + grub_normal_add_menu_entry (argv.argc, (const char **) argv.args, cmd_menuentry->sourcecode); - /* Free arguments. */ - for (i = 0; i < argcount; i++) - grub_free (args[i]); - grub_free (args); + grub_script_argv_free (&argv); return grub_errno; } diff --git a/script/function.c b/script/function.c index 810c65233..47b236652 100644 --- a/script/function.c +++ b/script/function.c @@ -103,12 +103,3 @@ grub_script_function_find (char *functionname) return func; } - -int -grub_script_function_call (grub_script_function_t func, - int argc __attribute__((unused)), - char **args __attribute__((unused))) -{ - /* XXX: Arguments are not supported yet. */ - return grub_script_execute (func->func); -} diff --git a/script/main.c b/script/main.c index 752a8cd8a..ff714d060 100644 --- a/script/main.c +++ b/script/main.c @@ -17,6 +17,7 @@ */ #include +#include #include #include @@ -39,3 +40,34 @@ grub_normal_parse_line (char *line, grub_reader_getline_t getline) return grub_errno; } + +static grub_command_t cmd_break; +static grub_command_t cmd_continue; +static grub_command_t cmd_shift; + +void +grub_script_init (void) +{ + cmd_break = grub_register_command ("break", grub_script_break, + N_("[n]"), N_("Exit from loops")); + cmd_continue = grub_register_command ("continue", grub_script_break, + N_("[n]"), N_("Continue loops")); + cmd_shift = grub_register_command ("shift", grub_script_shift, + N_("[n]"), N_("Shift positional parameters.")); +} + +void +grub_script_fini (void) +{ + if (cmd_break) + grub_unregister_command (cmd_break); + cmd_break = 0; + + if (cmd_continue) + grub_unregister_command (cmd_continue); + cmd_continue = 0; + + if (cmd_shift) + grub_unregister_command (cmd_shift); + cmd_shift = 0; +} diff --git a/script/parser.y b/script/parser.y index e85ba624d..99cd2ee31 100644 --- a/script/parser.y +++ b/script/parser.y @@ -97,9 +97,7 @@ script: newlines0 } | script statement delimiter newlines0 { - struct grub_script_cmdblock *cmdblock; - cmdblock = (struct grub_script_cmdblock *) $1; - $$ = grub_script_add_cmd (state, cmdblock, $2); + $$ = grub_script_append_cmd (state, $1, $2); } | error { @@ -185,13 +183,11 @@ command: grubcmd { $$ = $1; } /* A list of commands. */ commands1: newlines0 command { - $$ = grub_script_add_cmd (state, 0, $2); + $$ = grub_script_append_cmd (state, 0, $2); } | commands1 delimiters1 command { - struct grub_script_cmdblock *cmdblock; - cmdblock = (struct grub_script_cmdblock *) $1; - $$ = grub_script_add_cmd (state, cmdblock, $3); + $$ = grub_script_append_cmd (state, $1, $3); } ; diff --git a/script/script.c b/script/script.c index 4c87d9491..9cee40dcb 100644 --- a/script/script.c +++ b/script/script.c @@ -291,46 +291,40 @@ grub_script_create_cmdmenu (struct grub_parser_param *state, return (struct grub_script_cmd *) cmd; } -/* Create a block of commands. CMD contains the command that should - be added at the end of CMDBLOCK's list. If CMDBLOCK is zero, a new - cmdblock will be created. */ +/* Create a chain of commands. LAST contains the command that should + be added at the end of LIST's list. If LIST is zero, a new list + will be created. */ struct grub_script_cmd * -grub_script_add_cmd (struct grub_parser_param *state, - struct grub_script_cmdblock *cmdblock, - struct grub_script_cmd *cmd) +grub_script_append_cmd (struct grub_parser_param *state, + struct grub_script_cmd *list, + struct grub_script_cmd *last) { struct grub_script_cmd *ptr; - grub_dprintf ("scripting", "cmdblock\n"); + grub_dprintf ("scripting", "append command\n"); - if (!cmd) - return (struct grub_script_cmd *) cmdblock; + if (! last) + return list; - if (!cmdblock) + if (! list) { - cmdblock = grub_script_malloc (state, sizeof (*cmdblock)); - if (!cmdblock) + list = grub_script_malloc (state, sizeof (*list)); + if (! list) return 0; - cmdblock->cmd.exec = grub_script_execute_cmdblock; - cmdblock->cmd.next = 0; - cmdblock->cmdlist = cmd; - cmd->next = 0; + list->exec = grub_script_execute_cmdlist; + list->next = last; } else { - if (!cmdblock->cmdlist) - cmdblock->cmdlist = cmd; - else - { - ptr = cmdblock->cmdlist; - while (ptr->next) - ptr = ptr->next; - ptr->next = cmd; - } + ptr = list; + while (ptr->next) + ptr = ptr->next; + + ptr->next = last; } - return (struct grub_script_cmd *) cmdblock; + return list; } diff --git a/script/yylex.l b/script/yylex.l index e9659832b..45760c158 100644 --- a/script/yylex.l +++ b/script/yylex.l @@ -119,7 +119,8 @@ DIGITS [[:digit:]]+ NAME [[:alpha:]_][[:alnum:]_]* ESC \\. -VARIABLE ${NAME}|$\{{NAME}\}|${DIGITS}|$\{{DIGITS}\}|$\?|$\{\?\} +SPECIAL \?|\#|\*|\@ +VARIABLE ${NAME}|$\{{NAME}\}|${DIGITS}|$\{{DIGITS}\}|${SPECIAL}|$\{{SPECIAL}\} DQSTR \"([^\\\"]|{ESC})*\" SQSTR \'[^\']*\' WORD ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+ @@ -221,7 +222,7 @@ WORD ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+ } { - \? | + {SPECIAL} | {DIGITS} | {NAME} { COPY (yytext, yyleng); @@ -231,7 +232,7 @@ WORD ({CHAR}|{DQSTR}|{SQSTR}|{ESC}|{VARIABLE})+ else ARG (GRUB_SCRIPT_ARG_TYPE_DQVAR); } - \{\?\} | + \{{SPECIAL}\} | \{{DIGITS}\} | \{{NAME}\} { yytext[yyleng - 1] = '\0'; diff --git a/tests/grub_script_break.in b/tests/grub_script_break.in new file mode 100644 index 000000000..bf265e8b3 --- /dev/null +++ b/tests/grub_script_break.in @@ -0,0 +1,86 @@ +#! @builddir@/grub-shell-tester +# +# Copyright (C) 2010 Free Software Foundation, Inc. +# +# GRUB is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# GRUB is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GRUB. If not, see . + +# break without any arguments +for i in 1 2 3 4 5 6 7 8 9 10 +do + echo $i + if test "$i" = 5 + then + break + fi +done + +# break with one +for i in 1 2 3 4 5 6 7 8 9 10 +do + echo $i + if test "$i" = 5 + then + break 1 + fi +done + +# break with loop count +for i in 1 2 3 4 5 +do + for j in a b c d e f + do + echo "$i $j" + if test "$i" = 3 + then + if test "$j" = d + then + break 2 + fi + fi + done +done + +# break into middle loop +for i in 1 2 3 4 5 +do + for j in a b c d e f + do + echo "$i $j" + if test "$i" = 3 + then + if test "$j" = d + then + break 1 + fi + fi + done +done + +# while and until loops +a= +while test "$a" != "aaaaaaa" +do + a="a$a" + for i in 1 2 3 4 + do + b= + until test "$b" = "bbbbb" + do + b="b$b" + echo "$a $i $b" + if test "$i" = 3; then echo "break 2"; break 2; fi + done + done +done + diff --git a/tests/grub_script_continue.in b/tests/grub_script_continue.in new file mode 100644 index 000000000..4c28ce404 --- /dev/null +++ b/tests/grub_script_continue.in @@ -0,0 +1,86 @@ +#! @builddir@/grub-shell-tester +# +# Copyright (C) 2010 Free Software Foundation, Inc. +# +# GRUB is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# GRUB is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GRUB. If not, see . + +# continue without any arguments +for i in 1 2 3 4 5 6 7 8 9 10 +do + if test "$i" = 5 + then + continue + fi + echo $i +done + +# continue with one +for i in 1 2 3 4 5 6 7 8 9 10 +do + if test "$i" = 5 + then + continue 1 + fi + echo $i +done + +# continue with loop count +for i in 1 2 3 4 5 +do + for j in a b c d e f + do + if test "$i" = 3 + then + if test "$j" = d + then + continue 2 + fi + echo "$i $j" + fi + done +done + +# continue into middle loop +for i in 1 2 3 4 5 +do + for j in a b c d e f + do + if test "$i" = 3 + then + if test "$j" = d + then + continue 1 + fi + echo "$i $j" + fi + done +done + +# while and until loops +a= +while test "$a" != "aaaaaaa" +do + a="a$a" + for i in 1 2 3 4 + do + b= + until test "$b" = "bbbbb" + do + b="b$b" + if test "$i" = 3; then echo "continue 2"; continue 2; fi + echo "$a $i $b" + done + done +done + diff --git a/tests/grub_script_echo1.in b/tests/grub_script_echo1.in index 048907a76..554dd68ed 100644 --- a/tests/grub_script_echo1.in +++ b/tests/grub_script_echo1.in @@ -16,6 +16,33 @@ # You should have received a copy of the GNU General Public License # along with GRUB. If not, see . +# simple arguments +echo one two three +echo "one two three" +echo 'one two three' + +# empty arguments +echo a "" b +echo a '' b + +echo a $foo b +echo a ${foo} b + +echo a "$foo" b +echo a "${foo}" b + +# multi-part arguments +echo one"two"three +echo one${two}three +echo one"two"$three + +echo one'two'three +echo one${two}three +echo one'two'$three + +echo one'two'three"four"five${six}seven$eight + + foo=bar echo $foo ${foo} echo "$foo" "${foo}" diff --git a/tests/grub_script_functions.in b/tests/grub_script_functions.in new file mode 100644 index 000000000..3e69014d6 --- /dev/null +++ b/tests/grub_script_functions.in @@ -0,0 +1,147 @@ +#! @builddir@/grub-shell-tester + +# Run GRUB script in a Qemu instance +# 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 . + +echo parameter count +function fcount { + echo fcount "$#" +} + +fcount +fcount a +fcount a b + +echo parameter count, with nesting +function ffcount { + echo ffcount "$#" + fcount + fcount a + fcount a b +} + +ffcount +ffcount 1 +ffcount 1 2 + +echo parameters +function fparam { + echo fparam 1 $1 + echo fparam 2 $2 + echo fparam 3 $3 +} + +fparam +fparam a +fparam a b + +echo parameters, with nesting +function ffparam { + echo ffparam 1 $1 + echo ffparam 2 $2 + echo ffparam 3 $3 + fparam + fparam a + fparam a b +} + +ffparam +ffparam 1 +ffparam 1 2 + +echo parameter expansion with specials +function fstar { + for f in $* + do + echo fstar $f + done + + for f in aaa$*bbb + do + echo fstar $f + done +} + +fstar +fstar a +fstar a "1 2" +fstar a "1 2" b + +function fdqstar { + for f in "$*" + do + echo fdqstar $f + done + + for f in aaa"$*"bbb + do + echo fdqstar $f + done + + for f in "aaa$*bbb" + do + echo fdqstar $f + done +} + +fdqstar +fdqstar a +fdqstar a "1 2" +fdqstar a "1 2" b + +function fat { + for f in $@ + do + echo fat $f + done + + for f in aaa$@bbb + do + echo fat $f + done +} + +fat +fat a +fat a "1 2" +fat a "1 2" b +fat a "1 2" b "c d" +fat a "1 2" b "c d" e + +function fdqat { + for f in "$@" + do + echo fdqat $f + done + + for f in aaa"$@"bbb + do + echo fdqat $f + done + + for f in "aaa$@bbb" + do + echo fdqat $f + done +} + +# fdqat # this case needs special handling, lets ignore till we really need it. +fdqat a +fdqat a "1 2" +fdqat a "1 2" b +fdqat a "1 2" b "c d" +fdqat a "1 2" b "c d" e + diff --git a/tests/grub_script_shift.in b/tests/grub_script_shift.in new file mode 100644 index 000000000..785b9c396 --- /dev/null +++ b/tests/grub_script_shift.in @@ -0,0 +1,85 @@ +#! @builddir@/grub-shell-tester + +# Run GRUB script in a Qemu instance +# 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 . + +function f1 { + echo f1 '$@' $@ + echo f1 '$*' $* + echo f1 $# $1 $2 $3 + shift + echo f1 '$@' $@ + echo f1 '$*' $* + echo f1 $# $1 $2 $3 +} + +f1 +f1 a +f1 a b +f1 a b c +f1 a b c d +f1 a b c d e + +function f2 { + echo f1 '$@' $@ + echo f1 '$*' $* + echo f2 $# $1 $2 $3 + shift 1 + echo f1 '$@' $@ + echo f1 '$*' $* + echo f2 $# $1 $2 $3 +} + +f2 +f2 a +f2 a b +f2 a b c +f2 a b c d +f2 a b c d e + +function f3 { + echo f1 '$@' $@ + echo f1 '$*' $* + echo f3 $# $1 $2 $3 + shift 3 + echo f1 '$@' $@ + echo f1 '$*' $* + echo f3 $# $1 $2 $3 +} + +f3 +f3 a +f3 a b +f3 a b c +f3 a b c d +f3 a b c d e + +function f4 { + echo f1 '$@' $@ + echo f1 '$*' $* + echo f4 $# $1 $2 $3 + shift 100 + echo f1 '$@' $@ + echo f1 '$*' $* + echo f4 $# $1 $2 $3 +} + +f4 +f4 a +f4 a b +f4 a b c +f4 a b c d +f4 a b c d e diff --git a/tests/grub_script_vars1.in b/tests/grub_script_vars1.in index 9ff897627..77b3cf298 100644 --- a/tests/grub_script_vars1.in +++ b/tests/grub_script_vars1.in @@ -28,7 +28,7 @@ foo=foo echo "" $foo echo $bar $foo - + bar="" echo $bar $foo diff --git a/util/grub-fstest.c b/util/grub-fstest.c index f1692c0a3..2c80b964c 100644 --- a/util/grub-fstest.c +++ b/util/grub-fstest.c @@ -157,7 +157,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: %s", ofs, grub_errmsg); break; } @@ -211,7 +211,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: %s", ofs, grub_errmsg); return 1; } diff --git a/util/grub-macho2img.c b/util/grub-macho2img.c index 8683587be..23ffafb04 100644 --- a/util/grub-macho2img.c +++ b/util/grub-macho2img.c @@ -79,7 +79,7 @@ main (int argc, char **argv) fclose (in); fclose (out); free (buf); - printf ("Invalid Mach-O fle\n"); + printf ("Invalid Mach-O file\n"); return 4; } curcmd = (struct grub_macho_segment32 *) (buf + sizeof (*head)); diff --git a/util/grub-script-check.c b/util/grub-script-check.c index 5e2f37dab..4ca85c4bd 100644 --- a/util/grub-script-check.c +++ b/util/grub-script-check.c @@ -57,6 +57,22 @@ grub_refresh (void) fflush (stdout); } +grub_err_t +grub_script_break (grub_command_t cmd __attribute__((unused)), + int argc __attribute__((unused)), + char *argv[] __attribute__((unused))) +{ + return 0; +} + +grub_err_t +grub_script_shift (grub_command_t cmd __attribute__((unused)), + int argc __attribute__((unused)), + char *argv[] __attribute__((unused))) +{ + return 0; +} + char * grub_script_execute_argument_to_string (struct grub_script_arg *arg __attribute__ ((unused))) { @@ -70,7 +86,7 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd __attribute__ ((unused) } grub_err_t -grub_script_execute_cmdblock (struct grub_script_cmd *cmd __attribute__ ((unused))) +grub_script_execute_cmdlist (struct grub_script_cmd *cmd __attribute__ ((unused))) { return 0; } diff --git a/util/grub.d/10_kfreebsd.in b/util/grub.d/10_kfreebsd.in index f32da3013..3a42de529 100644 --- a/util/grub.d/10_kfreebsd.in +++ b/util/grub.d/10_kfreebsd.in @@ -74,8 +74,28 @@ EOF EOF fi + case "${kfreebsd_fs}" in + zfs) + for i in "${module_dir}/opensolaris.ko" "${module_dir}/zfs.ko" \ + "${dirname}/zfs/zpool.cache" ; do + ls "$i" > /dev/null + done + + printf '%s\n' "${prepare_module_dir_cache}" + cat << EOF + kfreebsd_module_elf ${module_dir_rel}/opensolaris.ko + kfreebsd_module_elf ${module_dir_rel}/zfs.ko +EOF + + printf '%s\n' "${prepare_boot_cache}" cat << EOF - set kFreeBSD.vfs.root.mountfrom=${kfreebsd_fs}:${GRUB_DEVICE} + kfreebsd_module ${rel_dirname}/zfs/zpool.cache type=/boot/zfs/zpool.cache +EOF + ;; + esac + + cat << EOF + set kFreeBSD.vfs.root.mountfrom=${kfreebsd_fs}:${kfreebsd_device} set kFreeBSD.vfs.root.mountfrom.options=rw } EOF @@ -105,6 +125,11 @@ while [ "x$list" != "x" ] ; do *) kfreebsd_fs=${GRUB_FS} ;; esac + case ${GRUB_FS} in + zfs) kfreebsd_device=$(grub-probe -t fs_label --device ${GRUB_DEVICE}) ;; + *) kfreebsd_device=${GRUB_DEVICE} ;; + esac + version=`echo $basename | sed -e "s,^[^0-9]*-,,g;s/\.gz$//g"` alt_version=`echo $version | sed -e "s,\.old$,,g"` diff --git a/util/misc.c b/util/misc.c index 2eff256bf..21dd211e1 100644 --- a/util/misc.c +++ b/util/misc.c @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include @@ -295,28 +294,7 @@ grub_util_init_nls (void) #endif /* (defined(ENABLE_NLS) && ENABLE_NLS) */ } -#ifdef HAVE_LIBZFS -libzfs_handle_t *libzfs_handle; - -static void -fini_libzfs (void) -{ - libzfs_fini (libzfs_handle); -} -#endif - -void -grub_util_init_libzfs (void) -{ -#ifdef HAVE_LIBZFS - if (! libzfs_handle) - { - libzfs_handle = libzfs_init (); - atexit (fini_libzfs); - } -#endif -} -#endif +#endif /* GRUB_UTIL */ int grub_dl_ref (grub_dl_t mod) diff --git a/video/cirrus.c b/video/cirrus.c index ccbab9d15..b8b0142ad 100644 --- a/video/cirrus.c +++ b/video/cirrus.c @@ -334,43 +334,26 @@ grub_video_cirrus_setup (unsigned int width, unsigned int height, } { - int pitch_reg, overflow_reg = 0, line_compare = 0x3ff; + struct grub_video_hw_config config = { + .pitch = pitch / GRUB_VGA_CR_PITCH_DIVISOR, + .line_compare = 0x3ff, + .vdisplay_end = height - 1, + .horizontal_end = width / GRUB_VGA_CR_WIDTH_DIVISOR + }; grub_uint8_t sr_ext = 0, hidden_dac = 0; - pitch_reg = pitch / GRUB_VGA_CR_PITCH_DIVISOR; - + grub_vga_set_geometry (&config, grub_vga_cr_write); + grub_vga_gr_write (GRUB_VGA_GR_MODE_256_COLOR | GRUB_VGA_GR_MODE_READ_MODE1, GRUB_VGA_GR_MODE); grub_vga_gr_write (GRUB_VGA_GR_GR6_GRAPHICS_MODE, GRUB_VGA_GR_GR6); grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_NORMAL, GRUB_VGA_SR_MEMORY_MODE); - /* Disable CR0-7 write protection. */ - grub_vga_cr_write (0, GRUB_VGA_CR_VSYNC_END); - - grub_vga_cr_write (width / GRUB_VGA_CR_WIDTH_DIVISOR - 1, - GRUB_VGA_CR_WIDTH); - grub_vga_cr_write ((height - 1) & 0xff, GRUB_VGA_CR_HEIGHT); - overflow_reg |= (((height - 1) >> GRUB_VGA_CR_OVERFLOW_HEIGHT1_SHIFT) & - GRUB_VGA_CR_OVERFLOW_HEIGHT1_MASK) - | (((height - 1) >> GRUB_VGA_CR_OVERFLOW_HEIGHT2_SHIFT) & - GRUB_VGA_CR_OVERFLOW_HEIGHT2_MASK); - - grub_vga_cr_write (pitch_reg & 0xff, GRUB_VGA_CR_PITCH); - - grub_vga_cr_write (line_compare & 0xff, GRUB_VGA_CR_LINE_COMPARE); - overflow_reg |= (line_compare >> GRUB_VGA_CR_OVERFLOW_LINE_COMPARE_SHIFT) - & GRUB_VGA_CR_OVERFLOW_LINE_COMPARE_MASK; - - grub_vga_cr_write (overflow_reg, GRUB_VGA_CR_OVERFLOW); - - grub_vga_cr_write ((pitch_reg >> CIRRUS_CR_EXTENDED_DISPLAY_PITCH_SHIFT) + grub_vga_cr_write ((config.pitch >> CIRRUS_CR_EXTENDED_DISPLAY_PITCH_SHIFT) & CIRRUS_CR_EXTENDED_DISPLAY_PITCH_MASK, CIRRUS_CR_EXTENDED_DISPLAY); - grub_vga_cr_write ((line_compare >> GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_SHIFT) - & GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_MASK, GRUB_VGA_CR_CELL_HEIGHT); - grub_vga_cr_write (GRUB_VGA_CR_MODE_TIMING_ENABLE | GRUB_VGA_CR_MODE_BYTE_MODE | GRUB_VGA_CR_MODE_NO_HERCULES | GRUB_VGA_CR_MODE_NO_CGA, diff --git a/video/sm712.c b/video/sm712.c index a58032c42..60f2c9089 100644 --- a/video/sm712.c +++ b/video/sm712.c @@ -26,10 +26,168 @@ #include #include #include +#include #include "sm712_init.c" #define GRUB_SM712_TOTAL_MEMORY_SPACE 0x700400 +#define GRUB_SM712_REG_BASE 0x700000 +#define GRUB_SM712_PCIID 0x0712126f + +enum + { + GRUB_SM712_SR_TV_CONTROL = 0x65, + GRUB_SM712_SR_RAM_LUT = 0x66, + GRUB_SM712_SR_CLOCK_CONTROL1 = 0x68, + GRUB_SM712_SR_CLOCK_CONTROL2 = 0x69, + GRUB_SM712_SR_VCLK_NUM = 0x6c, + GRUB_SM712_SR_VCLK_DENOM = 0x6d, + GRUB_SM712_SR_VCLK2_NUM = 0x6e, + GRUB_SM712_SR_VCLK2_DENOM = 0x6f, + GRUB_SM712_SR_POPUP_ICON_LOW = 0x80, + GRUB_SM712_SR_POPUP_ICON_HIGH = 0x81, + GRUB_SM712_SR_POPUP_ICON_CTRL = 0x82, + GRUB_SM712_SR_POPUP_ICON_COLOR1 = 0x84, + GRUB_SM712_SR_POPUP_ICON_COLOR2 = 0x85, + GRUB_SM712_SR_POPUP_ICON_COLOR3 = 0x86, + + GRUB_SM712_SR_HW_CURSOR_UPPER_LEFT_X_LOW = 0x88, + GRUB_SM712_SR_HW_CURSOR_UPPER_LEFT_X_HIGH = 0x89, + GRUB_SM712_SR_HW_CURSOR_UPPER_LEFT_Y_LOW = 0x8a, + GRUB_SM712_SR_HW_CURSOR_UPPER_LEFT_Y_HIGH = 0x8b, + GRUB_SM712_SR_HW_CURSOR_FG_COLOR = 0x8c, + GRUB_SM712_SR_HW_CURSOR_BG_COLOR = 0x8d, + + GRUB_SM712_SR_POPUP_ICON_X_LOW = 0x90, + GRUB_SM712_SR_POPUP_ICON_X_HIGH = 0x91, + GRUB_SM712_SR_POPUP_ICON_Y_LOW = 0x92, + GRUB_SM712_SR_POPUP_ICON_Y_HIGH = 0x93, + GRUB_SM712_SR_PANEL_HW_VIDEO_CONTROL = 0xa0, + GRUB_SM712_SR_PANEL_HW_VIDEO_COLOR_KEY_LOW = 0xa1, + GRUB_SM712_SR_PANEL_HW_VIDEO_COLOR_KEY_HIGH = 0xa2, + GRUB_SM712_SR_PANEL_HW_VIDEO_COLOR_KEY_MASK_LOW = 0xa3, + GRUB_SM712_SR_PANEL_HW_VIDEO_COLOR_KEY_MASK_HIGH = 0xa4, + GRUB_SM712_SR_PANEL_HW_VIDEO_RED_CONSTANT = 0xa5, + GRUB_SM712_SR_PANEL_HW_VIDEO_GREEN_CONSTANT = 0xa6, + GRUB_SM712_SR_PANEL_HW_VIDEO_BLUE_CONSTANT = 0xa7, + GRUB_SM712_SR_PANEL_HW_VIDEO_TOP_BOUNDARY = 0xa8, + GRUB_SM712_SR_PANEL_HW_VIDEO_LEFT_BOUNDARY = 0xa9, + GRUB_SM712_SR_PANEL_HW_VIDEO_BOTTOM_BOUNDARY = 0xaa, + GRUB_SM712_SR_PANEL_HW_VIDEO_RIGHT_BOUNDARY = 0xab, + GRUB_SM712_SR_PANEL_HW_VIDEO_TOP_LEFT_OVERFLOW_BOUNDARY = 0xac, + GRUB_SM712_SR_PANEL_HW_VIDEO_BOTTOM_RIGHT_OVERFLOW_BOUNDARY = 0xad, + GRUB_SM712_SR_PANEL_HW_VIDEO_VERTICAL_STRETCH_FACTOR = 0xae, + GRUB_SM712_SR_PANEL_HW_VIDEO_HORIZONTAL_STRETCH_FACTOR = 0xaf, + }; +enum + { + GRUB_SM712_SR_TV_CRT_SRAM = 0x00, + GRUB_SM712_SR_TV_LCD_SRAM = 0x08 + }; +enum + { + GRUB_SM712_SR_TV_ALT_CLOCK = 0x00, + GRUB_SM712_SR_TV_FREE_RUN_CLOCK = 0x04 + }; +enum + { + GRUB_SM712_SR_TV_CLOCK_CKIN_NTSC = 0x00, + GRUB_SM712_SR_TV_CLOCK_REFCLK_PAL = 0x04 + }; +enum + { + GRUB_SM712_SR_TV_HSYNC = 0x00, + GRUB_SM712_SR_TV_COMPOSITE_HSYNC = 0x01 + }; +enum + { + GRUB_SM712_SR_RAM_LUT_NORMAL = 0, + GRUB_SM712_SR_RAM_LUT_LCD_RAM_OFF = 0x80, + GRUB_SM712_SR_RAM_LUT_CRT_RAM_OFF = 0x40, + GRUB_SM712_SR_RAM_LUT_LCD_RAM_NO_WRITE = 0x20, + GRUB_SM712_SR_RAM_LUT_CRT_RAM_NO_WRITE = 0x10, + GRUB_SM712_SR_RAM_LUT_CRT_8BIT = 0x08, + GRUB_SM712_SR_RAM_LUT_CRT_GAMMA = 0x04 + }; + +enum + { + GRUB_SM712_SR_CLOCK_CONTROL1_VCLK_FROM_CCR = 0x40, + GRUB_SM712_SR_CLOCK_CONTROL1_8DOT_CLOCK = 0x10, + }; + +enum + { + GRUB_SM712_SR_CLOCK_CONTROL2_PROGRAM_VCLOCK = 0x03 + }; + +#define GRUB_SM712_SR_POPUP_ICON_HIGH_MASK 0x7 +#define GRUB_SM712_SR_POPUP_ICON_HIGH_HW_CURSOR_EN 0x80 + enum + { + GRUB_SM712_SR_POPUP_ICON_CTRL_DISABLED = 0, + GRUB_SM712_SR_POPUP_ICON_CTRL_ZOOM_ENABLED = 0x40, + GRUB_SM712_SR_POPUP_ICON_CTRL_ENABLED = 0x80 + }; +#define RGB332_BLACK 0 +#define RGB332_WHITE 0xff + + enum + { + GRUB_SM712_CR_OVERFLOW_INTERLACE = 0x30, + GRUB_SM712_CR_INTERLACE_RETRACE = 0x31, + GRUB_SM712_CR_TV_VDISPLAY_START = 0x32, + GRUB_SM712_CR_TV_VDISPLAY_END_HIGH = 0x33, + GRUB_SM712_CR_TV_VDISPLAY_END_LOW = 0x34, + GRUB_SM712_CR_DDA_CONTROL_LOW = 0x35, + GRUB_SM712_CR_DDA_CONTROL_HIGH = 0x36, + GRUB_SM712_CR_TV_EQUALIZER = 0x38, + GRUB_SM712_CR_TV_SERRATION = 0x39, + GRUB_SM712_CR_HSYNC_CTRL = 0x3a, + GRUB_SM712_CR_DEBUG = 0x3c, + GRUB_SM712_CR_SHADOW_VGA_HTOTAL = 0x40, + GRUB_SM712_CR_SHADOW_VGA_HBLANK_START = 0x41, + GRUB_SM712_CR_SHADOW_VGA_HBLANK_END = 0x42, + GRUB_SM712_CR_SHADOW_VGA_HRETRACE_START = 0x43, + GRUB_SM712_CR_SHADOW_VGA_HRETRACE_END = 0x44, + GRUB_SM712_CR_SHADOW_VGA_VERTICAL_TOTAL = 0x45, + GRUB_SM712_CR_SHADOW_VGA_VBLANK_START = 0x46, + GRUB_SM712_CR_SHADOW_VGA_VBLANK_END = 0x47, + GRUB_SM712_CR_SHADOW_VGA_VRETRACE_START = 0x48, + GRUB_SM712_CR_SHADOW_VGA_VRETRACE_END = 0x49, + GRUB_SM712_CR_SHADOW_VGA_OVERFLOW = 0x4a, + GRUB_SM712_CR_SHADOW_VGA_CELL_HEIGHT = 0x4b, + GRUB_SM712_CR_SHADOW_VGA_HDISPLAY_END = 0x4c, + GRUB_SM712_CR_SHADOW_VGA_VDISPLAY_END = 0x4d, + GRUB_SM712_CR_DDA_LOOKUP_REG3_START = 0x90, + GRUB_SM712_CR_DDA_LOOKUP_REG2_START = 0x91, + GRUB_SM712_CR_DDA_LOOKUP_REG1_START = 0xa0, + GRUB_SM712_CR_VCENTERING_OFFSET = 0xa6, + GRUB_SM712_CR_HCENTERING_OFFSET = 0xa7, + }; + +#define GRUB_SM712_CR_DEBUG_NONE 0 + +#define SM712_DDA_REG3_COMPARE_SHIFT 2 +#define SM712_DDA_REG3_COMPARE_MASK 0xfc +#define SM712_DDA_REG3_DDA_SHIFT 8 +#define SM712_DDA_REG3_DDA_MASK 0x3 +#define SM712_DDA_REG2_DDA_MASK 0xff +#define SM712_DDA_REG2_VCENTER_MASK 0x3f + +static struct +{ + grub_uint8_t compare; + grub_uint16_t dda; + grub_uint8_t vcentering; +} dda_lookups[] = { + { 21, 469, 2}, + { 23, 477, 2}, + { 33, 535, 2}, + { 35, 682, 21}, + { 34, 675, 2}, + { 55, 683, 6}, +}; static struct { @@ -42,6 +200,7 @@ static struct grub_pci_device_t dev; } framebuffer; +#ifndef TEST static grub_err_t grub_video_sm712_video_init (void) { @@ -60,6 +219,118 @@ grub_video_sm712_video_fini (void) return grub_video_fb_fini (); } +#endif + +static inline void +grub_sm712_write_reg (grub_uint8_t val, grub_uint16_t addr) +{ +#ifdef TEST + printf (" {1, 0x%x, 0x%x},\n", addr, val); +#else + *(volatile grub_uint8_t *) (framebuffer.ptr + GRUB_SM712_REG_BASE + + addr) = val; +#endif +} + +static inline grub_uint8_t +grub_sm712_read_reg (grub_uint16_t addr) +{ +#ifdef TEST + printf (" {-1, 0x%x, 0x5},\n", addr); +#else + return *(volatile grub_uint8_t *) (framebuffer.ptr + GRUB_SM712_REG_BASE + + addr); +#endif +} + +static inline grub_uint8_t +grub_sm712_sr_read (grub_uint8_t addr) +{ + grub_sm712_write_reg (addr, GRUB_VGA_IO_SR_INDEX); + return grub_sm712_read_reg (GRUB_VGA_IO_SR_DATA); +} + +static inline void +grub_sm712_sr_write (grub_uint8_t val, grub_uint8_t addr) +{ + grub_sm712_write_reg (addr, GRUB_VGA_IO_SR_INDEX); + grub_sm712_write_reg (val, GRUB_VGA_IO_SR_DATA); +} + +static inline void +grub_sm712_gr_write (grub_uint8_t val, grub_uint8_t addr) +{ + grub_sm712_write_reg (addr, GRUB_VGA_IO_GR_INDEX); + grub_sm712_write_reg (val, GRUB_VGA_IO_GR_DATA); +} + +static inline void +grub_sm712_cr_write (grub_uint8_t val, grub_uint8_t addr) +{ + grub_sm712_write_reg (addr, GRUB_VGA_IO_CR_INDEX); + grub_sm712_write_reg (val, GRUB_VGA_IO_CR_DATA); +} + +static inline void +grub_sm712_write_arx (grub_uint8_t val, grub_uint8_t addr) +{ + grub_sm712_read_reg (GRUB_VGA_IO_INPUT_STATUS1_REGISTER); + grub_sm712_write_reg (addr, GRUB_VGA_IO_ARX); + grub_sm712_read_reg (GRUB_VGA_IO_ARX_READ); + grub_sm712_write_reg (val, GRUB_VGA_IO_ARX); +} + +static inline void +grub_sm712_cr_shadow_write (grub_uint8_t val, grub_uint8_t addr) +{ + grub_uint8_t mapping[] = + { + [GRUB_VGA_CR_HTOTAL] = GRUB_SM712_CR_SHADOW_VGA_HTOTAL, + [GRUB_VGA_CR_HORIZ_END] = 0xff, + [GRUB_VGA_CR_HBLANK_START] = GRUB_SM712_CR_SHADOW_VGA_HBLANK_START, + [GRUB_VGA_CR_HBLANK_END] = GRUB_SM712_CR_SHADOW_VGA_HBLANK_END, + [GRUB_VGA_CR_HORIZ_SYNC_PULSE_START] = GRUB_SM712_CR_SHADOW_VGA_HRETRACE_START, + [GRUB_VGA_CR_HORIZ_SYNC_PULSE_END] = GRUB_SM712_CR_SHADOW_VGA_HRETRACE_END, + [GRUB_VGA_CR_VERT_TOTAL] = GRUB_SM712_CR_SHADOW_VGA_VERTICAL_TOTAL, + [GRUB_VGA_CR_OVERFLOW] = GRUB_SM712_CR_SHADOW_VGA_OVERFLOW, + [GRUB_VGA_CR_BYTE_PANNING] = 0xff, + [GRUB_VGA_CR_CELL_HEIGHT] = GRUB_SM712_CR_SHADOW_VGA_CELL_HEIGHT, + [GRUB_VGA_CR_CURSOR_START] = 0xff, + [GRUB_VGA_CR_CURSOR_END] = 0xff, + [GRUB_VGA_CR_START_ADDR_HIGH_REGISTER] = 0xff, + [GRUB_VGA_CR_START_ADDR_LOW_REGISTER] = 0xff, + [GRUB_VGA_CR_CURSOR_ADDR_HIGH] = 0xff, + [GRUB_VGA_CR_CURSOR_ADDR_LOW] = 0xff, + [GRUB_VGA_CR_VSYNC_START] = GRUB_SM712_CR_SHADOW_VGA_VRETRACE_START, + [GRUB_VGA_CR_VSYNC_END] = GRUB_SM712_CR_SHADOW_VGA_VRETRACE_END, + [GRUB_VGA_CR_VDISPLAY_END] = GRUB_SM712_CR_SHADOW_VGA_VDISPLAY_END, + [GRUB_VGA_CR_PITCH] = GRUB_SM712_CR_SHADOW_VGA_HDISPLAY_END, + [GRUB_VGA_CR_UNDERLINE_LOCATION] = 0xff, + + [GRUB_VGA_CR_VERTICAL_BLANK_START] = GRUB_SM712_CR_SHADOW_VGA_VBLANK_START, + [GRUB_VGA_CR_VERTICAL_BLANK_END] = GRUB_SM712_CR_SHADOW_VGA_VBLANK_END, + [GRUB_VGA_CR_MODE] = 0xff, + [GRUB_VGA_CR_LINE_COMPARE] = 0xff + }; + if (addr >= ARRAY_SIZE (mapping) || mapping[addr] == 0xff) + return; + grub_sm712_cr_write (val, mapping[addr]); +} + +static inline void +grub_sm712_write_dda_lookup (int idx, grub_uint8_t compare, grub_uint16_t dda, + grub_uint8_t vcentering) +{ + grub_sm712_cr_write (((compare << SM712_DDA_REG3_COMPARE_SHIFT) + & SM712_DDA_REG3_COMPARE_MASK) + | ((dda >> SM712_DDA_REG3_DDA_SHIFT) + & SM712_DDA_REG3_DDA_MASK), + GRUB_SM712_CR_DDA_LOOKUP_REG3_START + 2 * idx); + grub_sm712_cr_write (dda & SM712_DDA_REG2_DDA_MASK, + GRUB_SM712_CR_DDA_LOOKUP_REG2_START + 2 * idx); + grub_sm712_cr_write (vcentering & SM712_DDA_REG2_VCENTER_MASK, + GRUB_SM712_CR_DDA_LOOKUP_REG1_START + idx); +} static grub_err_t grub_video_sm712_setup (unsigned int width, unsigned int height, @@ -70,6 +341,7 @@ grub_video_sm712_setup (unsigned int width, unsigned int height, int found = 0; unsigned i; +#ifndef TEST 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))) { @@ -79,7 +351,8 @@ grub_video_sm712_setup (unsigned int width, unsigned int height, addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS); class = grub_pci_read (addr); - if (((class >> 16) & 0xffff) != 0x0300 || pciid != 0x0712126f) + if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA + || pciid != GRUB_SM712_PCIID) return 0; found = 1; @@ -103,7 +376,7 @@ grub_video_sm712_setup (unsigned int width, unsigned int height, grub_pci_iterate (find_card); if (!found) return grub_error (GRUB_ERR_IO, "Couldn't find graphics card"); - +#endif /* Fill mode info details. */ framebuffer.mode_info.width = 1024; framebuffer.mode_info.height = 600; @@ -120,8 +393,12 @@ grub_video_sm712_setup (unsigned int width, unsigned int height, 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); +#ifndef TEST + framebuffer.mode_info.blit_format + = grub_video_get_blit_format (&framebuffer.mode_info); +#endif +#ifndef TEST if (found && framebuffer.base == 0) { grub_pci_address_t addr; @@ -139,47 +416,280 @@ grub_video_sm712_setup (unsigned int width, unsigned int height, addr = grub_pci_make_address (framebuffer.dev, GRUB_PCI_REG_COMMAND); grub_pci_write (addr, 0x7); } +#endif /* We can safely discard volatile attribute. */ +#ifndef TEST framebuffer.ptr = (void *) grub_pci_device_map_range (framebuffer.dev, framebuffer.base, GRUB_SM712_TOTAL_MEMORY_SPACE); +#endif framebuffer.mapped = 1; /* Initialise SM712. */ - grub_outb (0x18, GRUB_MACHINE_PCI_IO_BASE + 0x3c4); - grub_outb (0x11, GRUB_MACHINE_PCI_IO_BASE + 0x3c5); +#ifndef TEST + /* FIXME */ + grub_vga_sr_write (0x11, 0x18); +#endif +#ifndef TEST /* Prevent garbage from appearing on the screen. */ grub_memset (framebuffer.ptr, 0, framebuffer.mode_info.height * framebuffer.mode_info.pitch); +#endif - for (i = 0; i < ARRAY_SIZE (sm712_init); i++) - switch (sm712_init[i].directive) + /* FIXME */ + grub_sm712_sr_write (0, 0x21); + grub_sm712_sr_write (0x7a, 0x62); + grub_sm712_sr_write (0x16, 0x6a); + grub_sm712_sr_write (0x2, 0x6b); + grub_sm712_write_reg (0, GRUB_VGA_IO_PIXEL_MASK); + grub_sm712_sr_write (GRUB_VGA_SR_RESET_ASYNC, GRUB_VGA_SR_RESET); + grub_sm712_write_reg (GRUB_VGA_IO_MISC_NEGATIVE_VERT_POLARITY + | GRUB_VGA_IO_MISC_NEGATIVE_HORIZ_POLARITY + | GRUB_VGA_IO_MISC_UPPER_64K + | GRUB_VGA_IO_MISC_EXTERNAL_CLOCK_0 + | GRUB_VGA_IO_MISC_ENABLE_VRAM_ACCESS + | GRUB_VGA_IO_MISC_COLOR, GRUB_VGA_IO_MISC_WRITE); + grub_sm712_sr_write (GRUB_VGA_SR_RESET_ASYNC | GRUB_VGA_SR_RESET_SYNC, + GRUB_VGA_SR_RESET); + grub_sm712_sr_write (GRUB_VGA_SR_CLOCKING_MODE_8_DOT_CLOCK, + GRUB_VGA_SR_CLOCKING_MODE); + grub_sm712_sr_write (GRUB_VGA_ALL_PLANES, GRUB_VGA_SR_MAP_MASK_REGISTER); + grub_sm712_sr_write (0, GRUB_VGA_SR_CHAR_MAP_SELECT); + grub_sm712_sr_write (GRUB_VGA_SR_MEMORY_MODE_CHAIN4 + | GRUB_VGA_SR_MEMORY_MODE_SEQUENTIAL_ADDRESSING + | GRUB_VGA_SR_MEMORY_MODE_EXTERNAL_VIDEO_MEMORY, + GRUB_VGA_SR_MEMORY_MODE); + + for (i = 0; i < ARRAY_SIZE (sm712_sr_seq1); i++) + grub_sm712_sr_write (sm712_sr_seq1[i], 0x10 + i); + + for (i = 0; i < ARRAY_SIZE (sm712_sr_seq2); i++) + grub_sm712_sr_write (sm712_sr_seq2[i], 0x30 + i); + + /* Undocumented. */ + grub_sm712_sr_write (0x1a, 0x63); + /* Undocumented. */ + grub_sm712_sr_write (0x1a, 0x64); + + grub_sm712_sr_write (GRUB_SM712_SR_TV_CRT_SRAM | GRUB_SM712_SR_TV_ALT_CLOCK + | GRUB_SM712_SR_TV_CLOCK_CKIN_NTSC + | GRUB_SM712_SR_TV_HSYNC, + GRUB_SM712_SR_TV_CONTROL); + + grub_sm712_sr_write (GRUB_SM712_SR_RAM_LUT_NORMAL, GRUB_SM712_SR_RAM_LUT); + + /* Undocumented. */ + grub_sm712_sr_write (0x00, 0x67); + + grub_sm712_sr_write (GRUB_SM712_SR_CLOCK_CONTROL1_VCLK_FROM_CCR + | GRUB_SM712_SR_CLOCK_CONTROL1_8DOT_CLOCK, + GRUB_SM712_SR_CLOCK_CONTROL1); + grub_sm712_sr_write (GRUB_SM712_SR_CLOCK_CONTROL2_PROGRAM_VCLOCK, + GRUB_SM712_SR_CLOCK_CONTROL2); + + grub_sm712_sr_write (82, GRUB_SM712_SR_VCLK_NUM); + grub_sm712_sr_write (137, GRUB_SM712_SR_VCLK_DENOM); + + grub_sm712_sr_write (9, GRUB_SM712_SR_VCLK2_NUM); + grub_sm712_sr_write (2, GRUB_SM712_SR_VCLK2_DENOM); + /* FIXME */ + grub_sm712_sr_write (0x04, 0x70); + /* FIXME */ + grub_sm712_sr_write (0x45, 0x71); + /* Undocumented */ + grub_sm712_sr_write (0x30, 0x72); + /* Undocumented */ + grub_sm712_sr_write (0x30, 0x73); + /* Undocumented */ + grub_sm712_sr_write (0x40, 0x74); + /* Undocumented */ + grub_sm712_sr_write (0x20, 0x75); + + grub_sm712_sr_write (0xff, GRUB_SM712_SR_POPUP_ICON_LOW); + grub_sm712_sr_write (GRUB_SM712_SR_POPUP_ICON_HIGH_MASK, + GRUB_SM712_SR_POPUP_ICON_HIGH); + grub_sm712_sr_write (GRUB_SM712_SR_POPUP_ICON_CTRL_DISABLED, + GRUB_SM712_SR_POPUP_ICON_CTRL); + /* Undocumented */ + grub_sm712_sr_write (0x0, 0x83); + + grub_sm712_sr_write (8, GRUB_SM712_SR_POPUP_ICON_COLOR1); + grub_sm712_sr_write (0, GRUB_SM712_SR_POPUP_ICON_COLOR2); + grub_sm712_sr_write (0x42, GRUB_SM712_SR_POPUP_ICON_COLOR3); + + /* Undocumented */ + grub_sm712_sr_write (0x3a, 0x87); + + /* Why theese coordinates? */ + grub_sm712_sr_write (0x59, GRUB_SM712_SR_HW_CURSOR_UPPER_LEFT_X_LOW); + grub_sm712_sr_write (0x02, GRUB_SM712_SR_HW_CURSOR_UPPER_LEFT_X_HIGH); + grub_sm712_sr_write (0x44, GRUB_SM712_SR_HW_CURSOR_UPPER_LEFT_Y_LOW); + grub_sm712_sr_write (0x02, GRUB_SM712_SR_HW_CURSOR_UPPER_LEFT_Y_HIGH); + + grub_sm712_sr_write (RGB332_BLACK, GRUB_SM712_SR_HW_CURSOR_FG_COLOR); + grub_sm712_sr_write (RGB332_WHITE, GRUB_SM712_SR_HW_CURSOR_BG_COLOR); + + /* Undocumented */ + grub_sm712_sr_write (0x3a, 0x8e); + grub_sm712_sr_write (0x3a, 0x8f); + + grub_sm712_sr_write (0, GRUB_SM712_SR_POPUP_ICON_X_LOW); + grub_sm712_sr_write (0, GRUB_SM712_SR_POPUP_ICON_X_HIGH); + grub_sm712_sr_write (0, GRUB_SM712_SR_POPUP_ICON_Y_LOW); + grub_sm712_sr_write (0, GRUB_SM712_SR_POPUP_ICON_Y_HIGH); + + grub_sm712_sr_write (0, GRUB_SM712_SR_PANEL_HW_VIDEO_CONTROL); + grub_sm712_sr_write (0x10, GRUB_SM712_SR_PANEL_HW_VIDEO_COLOR_KEY_LOW); + grub_sm712_sr_write (0x08, GRUB_SM712_SR_PANEL_HW_VIDEO_COLOR_KEY_HIGH); + grub_sm712_sr_write (0x00, GRUB_SM712_SR_PANEL_HW_VIDEO_COLOR_KEY_MASK_LOW); + grub_sm712_sr_write (0x02, GRUB_SM712_SR_PANEL_HW_VIDEO_COLOR_KEY_MASK_HIGH); + grub_sm712_sr_write (0xed, GRUB_SM712_SR_PANEL_HW_VIDEO_RED_CONSTANT); + grub_sm712_sr_write (0xed, GRUB_SM712_SR_PANEL_HW_VIDEO_GREEN_CONSTANT); + grub_sm712_sr_write (0xed, GRUB_SM712_SR_PANEL_HW_VIDEO_BLUE_CONSTANT); + + grub_sm712_sr_write (0x7b, GRUB_SM712_SR_PANEL_HW_VIDEO_TOP_BOUNDARY); + grub_sm712_sr_write (0xfb, GRUB_SM712_SR_PANEL_HW_VIDEO_LEFT_BOUNDARY); + grub_sm712_sr_write (0xff, GRUB_SM712_SR_PANEL_HW_VIDEO_BOTTOM_BOUNDARY); + grub_sm712_sr_write (0xff, GRUB_SM712_SR_PANEL_HW_VIDEO_RIGHT_BOUNDARY); + /* Doesn't match documentation? */ + grub_sm712_sr_write (0x97, GRUB_SM712_SR_PANEL_HW_VIDEO_TOP_LEFT_OVERFLOW_BOUNDARY); + grub_sm712_sr_write (0xef, GRUB_SM712_SR_PANEL_HW_VIDEO_BOTTOM_RIGHT_OVERFLOW_BOUNDARY); + + grub_sm712_sr_write (0xbf, GRUB_SM712_SR_PANEL_HW_VIDEO_VERTICAL_STRETCH_FACTOR); + grub_sm712_sr_write (0xdf, GRUB_SM712_SR_PANEL_HW_VIDEO_HORIZONTAL_STRETCH_FACTOR); + + grub_sm712_gr_write (GRUB_VGA_NO_PLANES, GRUB_VGA_GR_SET_RESET_PLANE); + grub_sm712_gr_write (GRUB_VGA_NO_PLANES, GRUB_VGA_GR_SET_RESET_PLANE_ENABLE); + grub_sm712_gr_write (GRUB_VGA_NO_PLANES, GRUB_VGA_GR_COLOR_COMPARE); + grub_sm712_gr_write (GRUB_VGA_GR_DATA_ROTATE_NOP, GRUB_VGA_GR_DATA_ROTATE); + grub_sm712_gr_write (GRUB_VGA_NO_PLANES, GRUB_VGA_GR_READ_MAP_REGISTER); + grub_sm712_gr_write (GRUB_VGA_GR_MODE_256_COLOR, GRUB_VGA_GR_MODE); + grub_sm712_gr_write (GRUB_VGA_GR_GR6_MMAP_A0 + | GRUB_VGA_GR_GR6_GRAPHICS_MODE, GRUB_VGA_GR_GR6); + grub_sm712_gr_write (GRUB_VGA_ALL_PLANES, GRUB_VGA_GR_COLOR_COMPARE_DISABLE); + grub_sm712_gr_write (0xff, GRUB_VGA_GR_BITMASK); + + /* Write palette mapping. */ + for (i = 0; i < 16; i++) + grub_sm712_write_arx (i, i); + + grub_sm712_write_arx (GRUB_VGA_ARX_MODE_ENABLE_256COLOR + | GRUB_VGA_ARX_MODE_GRAPHICS, GRUB_VGA_ARX_MODE); + grub_sm712_write_arx (0, GRUB_VGA_ARX_OVERSCAN); + grub_sm712_write_arx (GRUB_VGA_ALL_PLANES, GRUB_VGA_ARX_COLOR_PLANE_ENABLE); + grub_sm712_write_arx (0, GRUB_VGA_ARX_HORIZONTAL_PANNING); + grub_sm712_write_arx (0, GRUB_VGA_ARX_COLOR_SELECT); + + /* FIXME: compute this generically. */ + { + struct grub_video_hw_config config = { - case 1: - *(volatile grub_uint8_t *) ((char *) framebuffer.ptr - + sm712_init[i].addr) = sm712_init[i].val; - break; - case -1: - { - grub_uint8_t val = *(volatile grub_uint8_t *) - ((char *) framebuffer.ptr + sm712_init[i].addr); - (void) val; - } - break; - case 2: - *(volatile grub_uint16_t *) ((char *) framebuffer.ptr - + sm712_init[i].addr) = sm712_init[i].val; - break; - case 4: - *(volatile grub_uint32_t *) ((char *) framebuffer.ptr - + sm712_init[i].addr) = sm712_init[i].val; - break; - } + .vertical_total = 806, + .vertical_blank_start = 0x300, + .vertical_blank_end = 0, + .vertical_sync_start = 0x303, + .vertical_sync_end = 0x9, + .line_compare = 0x3ff, + .vdisplay_end = 0x300, + .pitch = 0x80, + .horizontal_total = 164, + .horizontal_end = 128, + .horizontal_blank_start = 128, + .horizontal_blank_end = 0, + .horizontal_sync_pulse_start = 133, + .horizontal_sync_pulse_end = 22 + }; + grub_vga_set_geometry (&config, grub_sm712_cr_write); + config.horizontal_sync_pulse_start = 134; + config.horizontal_sync_pulse_end = 21; + config.vertical_sync_start = 0x301; + config.vertical_sync_end = 0x0; + config.line_compare = 0x0ff; + config.vdisplay_end = 0x258; + config.pitch = 0x7f; + grub_vga_set_geometry (&config, grub_sm712_cr_shadow_write); + } - err = grub_video_fb_create_render_target_from_pointer (&framebuffer.render_target, &framebuffer.mode_info, framebuffer.ptr); + grub_sm712_cr_write (GRUB_VGA_CR_BYTE_PANNING_NORMAL, + GRUB_VGA_CR_BYTE_PANNING); + grub_sm712_cr_write (0, GRUB_VGA_CR_CURSOR_START); + grub_sm712_cr_write (0, GRUB_VGA_CR_CURSOR_END); + grub_sm712_cr_write (0, GRUB_VGA_CR_START_ADDR_HIGH_REGISTER); + grub_sm712_cr_write (0, GRUB_VGA_CR_START_ADDR_LOW_REGISTER); + grub_sm712_cr_write (0, GRUB_VGA_CR_CURSOR_ADDR_HIGH); + grub_sm712_cr_write (0, GRUB_VGA_CR_CURSOR_ADDR_LOW); + grub_sm712_cr_write (GRUB_VGA_CR_UNDERLINE_LOCATION_DWORD_MODE, + GRUB_VGA_CR_UNDERLINE_LOCATION); + grub_sm712_cr_write (GRUB_VGA_CR_MODE_ADDRESS_WRAP + | GRUB_VGA_CR_MODE_BYTE_MODE + | GRUB_VGA_CR_MODE_TIMING_ENABLE + | GRUB_VGA_CR_MODE_NO_CGA + | GRUB_VGA_CR_MODE_NO_HERCULES, + GRUB_VGA_CR_MODE); + + grub_sm712_cr_write (0, GRUB_SM712_CR_OVERFLOW_INTERLACE); + grub_sm712_cr_write (0, GRUB_SM712_CR_INTERLACE_RETRACE); + grub_sm712_cr_write (0, GRUB_SM712_CR_TV_VDISPLAY_START); + grub_sm712_cr_write (0, GRUB_SM712_CR_TV_VDISPLAY_END_HIGH); + grub_sm712_cr_write (0, GRUB_SM712_CR_TV_VDISPLAY_END_LOW); + grub_sm712_cr_write (0x80, GRUB_SM712_CR_DDA_CONTROL_LOW); + grub_sm712_cr_write (0x02, GRUB_SM712_CR_DDA_CONTROL_HIGH); + + /* Undocumented */ + grub_sm712_cr_write (0x20, 0x37); + + grub_sm712_cr_write (0, GRUB_SM712_CR_TV_EQUALIZER); + grub_sm712_cr_write (0, GRUB_SM712_CR_TV_SERRATION); + grub_sm712_cr_write (0, GRUB_SM712_CR_HSYNC_CTRL); + + /* Undocumented */ + grub_sm712_cr_write (0x40, 0x3b); + + grub_sm712_cr_write (GRUB_SM712_CR_DEBUG_NONE, GRUB_SM712_CR_DEBUG); + + /* Undocumented */ + grub_sm712_cr_write (0xff, 0x3d); + grub_sm712_cr_write (0x46, 0x3e); + grub_sm712_cr_write (0x91, 0x3f); + + for (i = 0; i < ARRAY_SIZE (dda_lookups); i++) + grub_sm712_write_dda_lookup (i, dda_lookups[i].compare, dda_lookups[i].dda, + dda_lookups[i].vcentering); + + /* Undocumented */ + grub_sm712_cr_write (0, 0x9c); + grub_sm712_cr_write (0, 0x9d); + grub_sm712_cr_write (0, 0x9e); + grub_sm712_cr_write (0, 0x9f); + + grub_sm712_cr_write (0, GRUB_SM712_CR_VCENTERING_OFFSET); + grub_sm712_cr_write (0, GRUB_SM712_CR_HCENTERING_OFFSET); + + grub_sm712_write_reg (GRUB_VGA_IO_MISC_NEGATIVE_HORIZ_POLARITY + | GRUB_VGA_IO_MISC_UPPER_64K + | GRUB_VGA_IO_MISC_28MHZ + | GRUB_VGA_IO_MISC_ENABLE_VRAM_ACCESS + | GRUB_VGA_IO_MISC_COLOR, + GRUB_VGA_IO_MISC_WRITE); + +#ifndef TEST + /* Undocumented? */ + *(volatile grub_uint32_t *) ((char *) framebuffer.ptr + 0x40c00c) = 0; + *(volatile grub_uint32_t *) ((char *) framebuffer.ptr + 0x40c040) = 0; + *(volatile grub_uint32_t *) ((char *) framebuffer.ptr + 0x40c000) = 0x20000; + *(volatile grub_uint32_t *) ((char *) framebuffer.ptr + 0x40c010) = 0x1020100; +#endif + + (void) grub_sm712_sr_read (0x16); + +#ifndef TEST + err = grub_video_fb_create_render_target_from_pointer (&framebuffer + .render_target, + &framebuffer.mode_info, + framebuffer.ptr); if (err) return err; @@ -192,9 +702,12 @@ grub_video_sm712_setup (unsigned int width, unsigned int height, /* Copy default palette to initialize emulated palette. */ err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, grub_video_fbstd_colors); +#endif return err; } +#ifndef TEST + static grub_err_t grub_video_sm712_swap_buffers (void) { @@ -223,7 +736,6 @@ grub_video_sm712_get_info_and_fini (struct grub_video_mode_info *mode_info, return GRUB_ERR_NONE; } - static struct grub_video_adapter grub_video_sm712_adapter = { .name = "SM712 Video Driver", @@ -266,3 +778,10 @@ GRUB_MOD_FINI(video_sm712) { grub_video_unregister (&grub_video_sm712_adapter); } +#else +int +main () +{ + grub_video_sm712_setup (1024, 600, 0, 0); +} +#endif diff --git a/video/sm712_init.c b/video/sm712_init.c index 02c64c453..cdb0b7383 100644 --- a/video/sm712_init.c +++ b/video/sm712_init.c @@ -1,546 +1,14 @@ /* Following sequence is a capture of sm712 initialisation sequence. */ -static struct -{ - int directive; - grub_uint32_t addr; - grub_uint32_t val; -} sm712_init[] = -{ - {1, 0x7003c4, 0x21}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x62}, - {1, 0x7003c5, 0x7a}, - {1, 0x7003c4, 0x6a}, - {1, 0x7003c5, 0x16}, - {1, 0x7003c4, 0x6b}, - {1, 0x7003c5, 0x2}, - {1, 0x7003c6, 0x0}, - {1, 0x7003c4, 0x0}, - {1, 0x7003c5, 0x1}, - {1, 0x7003c2, 0xeb}, - {1, 0x7003c4, 0x0}, - {1, 0x7003c5, 0x3}, - {1, 0x7003c4, 0x1}, - {1, 0x7003c5, 0x1}, - {1, 0x7003c4, 0x2}, - {1, 0x7003c5, 0xf}, - {1, 0x7003c4, 0x3}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x4}, - {1, 0x7003c5, 0xe}, - {1, 0x7003c4, 0x10}, - {1, 0x7003c5, 0xc8}, - {1, 0x7003c4, 0x11}, - {1, 0x7003c5, 0x40}, - {1, 0x7003c4, 0x12}, - {1, 0x7003c5, 0x14}, - {1, 0x7003c4, 0x13}, - {1, 0x7003c5, 0x60}, - {1, 0x7003c4, 0x14}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x15}, - {1, 0x7003c5, 0xa}, - {1, 0x7003c4, 0x16}, - {1, 0x7003c5, 0x92}, - {1, 0x7003c4, 0x17}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x18}, - {1, 0x7003c5, 0x51}, - {1, 0x7003c4, 0x19}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x1a}, - {1, 0x7003c5, 0x1}, - {1, 0x7003c4, 0x1b}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x1c}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x1d}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x1e}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x1f}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x20}, - {1, 0x7003c5, 0xc4}, - {1, 0x7003c4, 0x21}, - {1, 0x7003c5, 0x30}, - {1, 0x7003c4, 0x22}, - {1, 0x7003c5, 0x2}, - {1, 0x7003c4, 0x23}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x24}, - {1, 0x7003c5, 0x1}, - {1, 0x7003c4, 0x30}, - {1, 0x7003c5, 0x28}, - {1, 0x7003c4, 0x31}, - {1, 0x7003c5, 0x3}, - {1, 0x7003c4, 0x32}, - {1, 0x7003c5, 0x24}, - {1, 0x7003c4, 0x33}, - {1, 0x7003c5, 0x9}, - {1, 0x7003c4, 0x34}, - {1, 0x7003c5, 0xc0}, - {1, 0x7003c4, 0x35}, - {1, 0x7003c5, 0x3a}, - {1, 0x7003c4, 0x36}, - {1, 0x7003c5, 0x3a}, - {1, 0x7003c4, 0x37}, - {1, 0x7003c5, 0x3a}, - {1, 0x7003c4, 0x38}, - {1, 0x7003c5, 0x3a}, - {1, 0x7003c4, 0x39}, - {1, 0x7003c5, 0x3a}, - {1, 0x7003c4, 0x3a}, - {1, 0x7003c5, 0x3a}, - {1, 0x7003c4, 0x3b}, - {1, 0x7003c5, 0x3a}, - {1, 0x7003c4, 0x3c}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x3d}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x3e}, - {1, 0x7003c5, 0x3}, - {1, 0x7003c4, 0x3f}, - {1, 0x7003c5, 0xff}, - {1, 0x7003c4, 0x40}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x41}, - {1, 0x7003c5, 0xfc}, - {1, 0x7003c4, 0x42}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x43}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x44}, - {1, 0x7003c5, 0x20}, - {1, 0x7003c4, 0x45}, - {1, 0x7003c5, 0x18}, - {1, 0x7003c4, 0x46}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x47}, - {1, 0x7003c5, 0xfc}, - {1, 0x7003c4, 0x48}, - {1, 0x7003c5, 0x20}, - {1, 0x7003c4, 0x49}, - {1, 0x7003c5, 0xc}, - {1, 0x7003c4, 0x4a}, - {1, 0x7003c5, 0x44}, - {1, 0x7003c4, 0x4b}, - {1, 0x7003c5, 0x20}, - {1, 0x7003c4, 0x4c}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x4d}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x4e}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x4f}, - {1, 0x7003c5, 0x3a}, - {1, 0x7003c4, 0x50}, - {1, 0x7003c5, 0x6}, - {1, 0x7003c4, 0x51}, - {1, 0x7003c5, 0x68}, - {1, 0x7003c4, 0x52}, - {1, 0x7003c5, 0xa7}, - {1, 0x7003c4, 0x53}, - {1, 0x7003c5, 0x7f}, - {1, 0x7003c4, 0x54}, - {1, 0x7003c5, 0x83}, - {1, 0x7003c4, 0x55}, - {1, 0x7003c5, 0x24}, - {1, 0x7003c4, 0x56}, - {1, 0x7003c5, 0xff}, - {1, 0x7003c4, 0x57}, - {1, 0x7003c5, 0x3}, - {1, 0x7003c4, 0x58}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x59}, - {1, 0x7003c5, 0x60}, - {1, 0x7003c4, 0x5a}, - {1, 0x7003c5, 0x59}, - {1, 0x7003c4, 0x5b}, - {1, 0x7003c5, 0x3a}, - {1, 0x7003c4, 0x5c}, - {1, 0x7003c5, 0x3a}, - {1, 0x7003c4, 0x5d}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x5e}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x5f}, - {1, 0x7003c5, 0x3a}, - {1, 0x7003c4, 0x60}, - {1, 0x7003c5, 0x1}, - {1, 0x7003c4, 0x61}, - {1, 0x7003c5, 0x80}, - {1, 0x7003c4, 0x63}, - {1, 0x7003c5, 0x1a}, - {1, 0x7003c4, 0x64}, - {1, 0x7003c5, 0x1a}, - {1, 0x7003c4, 0x65}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x66}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x67}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x68}, - {1, 0x7003c5, 0x50}, - {1, 0x7003c4, 0x69}, - {1, 0x7003c5, 0x3}, - {1, 0x7003c4, 0x6c}, - {1, 0x7003c5, 0x52}, - {1, 0x7003c4, 0x6d}, - {1, 0x7003c5, 0x89}, - {1, 0x7003c4, 0x6e}, - {1, 0x7003c5, 0x9}, - {1, 0x7003c4, 0x6f}, - {1, 0x7003c5, 0x2}, - {1, 0x7003c4, 0x70}, - {1, 0x7003c5, 0x4}, - {1, 0x7003c4, 0x71}, - {1, 0x7003c5, 0x45}, - {1, 0x7003c4, 0x72}, - {1, 0x7003c5, 0x30}, - {1, 0x7003c4, 0x73}, - {1, 0x7003c5, 0x30}, - {1, 0x7003c4, 0x74}, - {1, 0x7003c5, 0x40}, - {1, 0x7003c4, 0x75}, - {1, 0x7003c5, 0x20}, - {1, 0x7003c4, 0x80}, - {1, 0x7003c5, 0xff}, - {1, 0x7003c4, 0x81}, - {1, 0x7003c5, 0x7}, - {1, 0x7003c4, 0x82}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x83}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x84}, - {1, 0x7003c5, 0x8}, - {1, 0x7003c4, 0x85}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x86}, - {1, 0x7003c5, 0x42}, - {1, 0x7003c4, 0x87}, - {1, 0x7003c5, 0x3a}, - {1, 0x7003c4, 0x88}, - {1, 0x7003c5, 0x59}, - {1, 0x7003c4, 0x89}, - {1, 0x7003c5, 0x2}, - {1, 0x7003c4, 0x8a}, - {1, 0x7003c5, 0x44}, - {1, 0x7003c4, 0x8b}, - {1, 0x7003c5, 0x2}, - {1, 0x7003c4, 0x8c}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x8d}, - {1, 0x7003c5, 0xff}, - {1, 0x7003c4, 0x8e}, - {1, 0x7003c5, 0x3a}, - {1, 0x7003c4, 0x8f}, - {1, 0x7003c5, 0x3a}, - {1, 0x7003c4, 0x90}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x91}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x92}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0x93}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0xa0}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0xa1}, - {1, 0x7003c5, 0x10}, - {1, 0x7003c4, 0xa2}, - {1, 0x7003c5, 0x8}, - {1, 0x7003c4, 0xa3}, - {1, 0x7003c5, 0x0}, - {1, 0x7003c4, 0xa4}, - {1, 0x7003c5, 0x2}, - {1, 0x7003c4, 0xa5}, - {1, 0x7003c5, 0xed}, - {1, 0x7003c4, 0xa6}, - {1, 0x7003c5, 0xed}, - {1, 0x7003c4, 0xa7}, - {1, 0x7003c5, 0xed}, - {1, 0x7003c4, 0xa8}, - {1, 0x7003c5, 0x7b}, - {1, 0x7003c4, 0xa9}, - {1, 0x7003c5, 0xfb}, - {1, 0x7003c4, 0xaa}, - {1, 0x7003c5, 0xff}, - {1, 0x7003c4, 0xab}, - {1, 0x7003c5, 0xff}, - {1, 0x7003c4, 0xac}, - {1, 0x7003c5, 0x97}, - {1, 0x7003c4, 0xad}, - {1, 0x7003c5, 0xef}, - {1, 0x7003c4, 0xae}, - {1, 0x7003c5, 0xbf}, - {1, 0x7003c4, 0xaf}, - {1, 0x7003c5, 0xdf}, - {1, 0x7003ce, 0x0}, - {1, 0x7003cf, 0x0}, - {1, 0x7003ce, 0x1}, - {1, 0x7003cf, 0x0}, - {1, 0x7003ce, 0x2}, - {1, 0x7003cf, 0x0}, - {1, 0x7003ce, 0x3}, - {1, 0x7003cf, 0x0}, - {1, 0x7003ce, 0x4}, - {1, 0x7003cf, 0x0}, - {1, 0x7003ce, 0x5}, - {1, 0x7003cf, 0x40}, - {1, 0x7003ce, 0x6}, - {1, 0x7003cf, 0x5}, - {1, 0x7003ce, 0x7}, - {1, 0x7003cf, 0xf}, - {1, 0x7003ce, 0x8}, - {1, 0x7003cf, 0xff}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x0}, - {-1, 0x7003c1, 0x3e}, - {1, 0x7003c0, 0x0}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x1}, - {-1, 0x7003c1, 0x3b}, - {1, 0x7003c0, 0x1}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x2}, - {-1, 0x7003c1, 0x3f}, - {1, 0x7003c0, 0x2}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x3}, - {-1, 0x7003c1, 0x3f}, - {1, 0x7003c0, 0x3}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x4}, - {-1, 0x7003c1, 0x3b}, - {1, 0x7003c0, 0x4}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x5}, - {-1, 0x7003c1, 0x2f}, - {1, 0x7003c0, 0x5}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x6}, - {-1, 0x7003c1, 0x3f}, - {1, 0x7003c0, 0x6}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x7}, - {-1, 0x7003c1, 0x3f}, - {1, 0x7003c0, 0x7}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x8}, - {-1, 0x7003c1, 0x3f}, - {1, 0x7003c0, 0x8}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x9}, - {-1, 0x7003c1, 0x3d}, - {1, 0x7003c0, 0x9}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0xa}, - {-1, 0x7003c1, 0x1f}, - {1, 0x7003c0, 0xa}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0xb}, - {-1, 0x7003c1, 0x1f}, - {1, 0x7003c0, 0xb}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0xc}, - {-1, 0x7003c1, 0x3f}, - {1, 0x7003c0, 0xc}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0xd}, - {-1, 0x7003c1, 0x3f}, - {1, 0x7003c0, 0xd}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0xe}, - {-1, 0x7003c1, 0x3f}, - {1, 0x7003c0, 0xe}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0xf}, - {-1, 0x7003c1, 0x2e}, - {1, 0x7003c0, 0xf}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x10}, - {-1, 0x7003c1, 0x0}, - {1, 0x7003c0, 0x41}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x11}, - {-1, 0x7003c1, 0x0}, - {1, 0x7003c0, 0x0}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x12}, - {-1, 0x7003c1, 0x0}, - {1, 0x7003c0, 0xf}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x13}, - {-1, 0x7003c1, 0x0}, - {1, 0x7003c0, 0x0}, - {-1, 0x7003da, 0x5}, - {1, 0x7003c0, 0x14}, - {-1, 0x7003c1, 0x0}, - {1, 0x7003c0, 0x0}, - {1, 0x7003d4, 0x0}, - {1, 0x7003d5, 0xa3}, - {1, 0x7003d4, 0x1}, - {1, 0x7003d5, 0x7f}, - {1, 0x7003d4, 0x2}, - {1, 0x7003d5, 0x7f}, - {1, 0x7003d4, 0x3}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x4}, - {1, 0x7003d5, 0x85}, - {1, 0x7003d4, 0x5}, - {1, 0x7003d5, 0x16}, - {1, 0x7003d4, 0x6}, - {1, 0x7003d5, 0x24}, - {1, 0x7003d4, 0x7}, - {1, 0x7003d5, 0xf5}, - {1, 0x7003d4, 0x8}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x9}, - {1, 0x7003d5, 0x60}, - {1, 0x7003d4, 0xa}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0xb}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0xc}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0xd}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0xe}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0xf}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x10}, - {1, 0x7003d5, 0x3}, - {1, 0x7003d4, 0x11}, - {1, 0x7003d5, 0x9}, - {1, 0x7003d4, 0x12}, - {1, 0x7003d5, 0xff}, - {1, 0x7003d4, 0x13}, - {1, 0x7003d5, 0x80}, - {1, 0x7003d4, 0x14}, - {1, 0x7003d5, 0x40}, - {1, 0x7003d4, 0x15}, - {1, 0x7003d5, 0xff}, - {1, 0x7003d4, 0x16}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x17}, - {1, 0x7003d5, 0xe3}, - {1, 0x7003d4, 0x18}, - {1, 0x7003d5, 0xff}, - {1, 0x7003d4, 0x30}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x31}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x32}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x33}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x34}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x35}, - {1, 0x7003d5, 0x80}, - {1, 0x7003d4, 0x36}, - {1, 0x7003d5, 0x2}, - {1, 0x7003d4, 0x37}, - {1, 0x7003d5, 0x20}, - {1, 0x7003d4, 0x38}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x39}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x3a}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x3b}, - {1, 0x7003d5, 0x40}, - {1, 0x7003d4, 0x3c}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x3d}, - {1, 0x7003d5, 0xff}, - {1, 0x7003d4, 0x3e}, - {1, 0x7003d5, 0x46}, - {1, 0x7003d4, 0x3f}, - {1, 0x7003d5, 0x91}, - {1, 0x7003d4, 0x40}, - {1, 0x7003d5, 0xa3}, - {1, 0x7003d4, 0x41}, - {1, 0x7003d5, 0x7f}, - {1, 0x7003d4, 0x42}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x43}, - {1, 0x7003d5, 0x86}, - {1, 0x7003d4, 0x44}, - {1, 0x7003d5, 0x15}, - {1, 0x7003d4, 0x45}, - {1, 0x7003d5, 0x24}, - {1, 0x7003d4, 0x46}, - {1, 0x7003d5, 0xff}, - {1, 0x7003d4, 0x47}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x48}, - {1, 0x7003d5, 0x1}, - {1, 0x7003d4, 0x49}, - {1, 0x7003d5, 0x7}, - {1, 0x7003d4, 0x4a}, - {1, 0x7003d5, 0xe5}, - {1, 0x7003d4, 0x4b}, - {1, 0x7003d5, 0x20}, - {1, 0x7003d4, 0x4c}, - {1, 0x7003d5, 0x7f}, - {1, 0x7003d4, 0x4d}, - {1, 0x7003d5, 0x57}, - {1, 0x7003d4, 0x90}, - {1, 0x7003d5, 0x55}, - {1, 0x7003d4, 0x91}, - {1, 0x7003d5, 0xd5}, - {1, 0x7003d4, 0x92}, - {1, 0x7003d5, 0x5d}, - {1, 0x7003d4, 0x93}, - {1, 0x7003d5, 0xdd}, - {1, 0x7003d4, 0x94}, - {1, 0x7003d5, 0x86}, - {1, 0x7003d4, 0x95}, - {1, 0x7003d5, 0x17}, - {1, 0x7003d4, 0x96}, - {1, 0x7003d5, 0x8e}, - {1, 0x7003d4, 0x97}, - {1, 0x7003d5, 0xaa}, - {1, 0x7003d4, 0x98}, - {1, 0x7003d5, 0x8a}, - {1, 0x7003d4, 0x99}, - {1, 0x7003d5, 0xa3}, - {1, 0x7003d4, 0x9a}, - {1, 0x7003d5, 0xde}, - {1, 0x7003d4, 0x9b}, - {1, 0x7003d5, 0xab}, - {1, 0x7003d4, 0x9c}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x9d}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x9e}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0x9f}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0xa0}, - {1, 0x7003d5, 0x2}, - {1, 0x7003d4, 0xa1}, - {1, 0x7003d5, 0x2}, - {1, 0x7003d4, 0xa2}, - {1, 0x7003d5, 0x2}, - {1, 0x7003d4, 0xa3}, - {1, 0x7003d5, 0x15}, - {1, 0x7003d4, 0xa4}, - {1, 0x7003d5, 0x2}, - {1, 0x7003d4, 0xa5}, - {1, 0x7003d5, 0x6}, - {1, 0x7003d4, 0xa6}, - {1, 0x7003d5, 0x0}, - {1, 0x7003d4, 0xa7}, - {1, 0x7003d5, 0x0}, - {1, 0x7003c2, 0x67}, - {4, 0x40c00c, 0x0}, - {4, 0x40c040, 0x0}, - {4, 0x40c000, 0x20000}, - {4, 0x40c010, 0x1020100}, - {1, 0x7003c4, 0x16}, - {-1, 0x7003c5, 0x17} -}; +static grub_uint8_t sm712_sr_seq1[] = + { 0xc8, 0x40, 0x14, 0x60, 0x0, 0xa, 0x92, 0x0, + 0x51, 0x00, 0x01, 0x00, 0x0, 0x0, 0x00, 0x0, + 0xc4, 0x30, 0x02, 0x00, 0x1 }; + +static grub_uint8_t sm712_sr_seq2[] = + { 0x28, 0x03, 0x24, 0x09, 0xc0, 0x3a, 0x3a, 0x3a, + 0x3a, 0x3a, 0x3a, 0x3a, 0x00, 0x00, 0x03, 0xff, + 0x00, 0xfc, 0x00, 0x00, 0x20, 0x18, 0x00, 0xfc, + 0x20, 0x0c, 0x44, 0x20, 0x00, 0x00, 0x00, 0x3a, + 0x06, 0x68, 0xa7, 0x7f, 0x83, 0x24, 0xff, 0x03, + 0x00, 0x60, 0x59, 0x3a, 0x3a, 0x00, 0x00, 0x3a, + 0x01, 0x80 };