From 7b74857658250b261fa7b89e27c405ceaf95f16e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 28 Dec 2009 14:02:23 +0100 Subject: [PATCH 001/214] Search hinting support --- commands/search.c | 24 ++++++++++++++++++------ commands/search_wrap.c | 11 +++++++---- include/grub/search.h | 9 ++++++--- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/commands/search.c b/commands/search.c index 01e83739b..c3626d352 100644 --- a/commands/search.c +++ b/commands/search.c @@ -30,7 +30,8 @@ #include void -FUNC_NAME (const char *key, const char *var, int no_floppy) +FUNC_NAME (const char *key, const char *var, int no_floppy, + const char **hints, unsigned nhints) { int count = 0; char *buf = NULL; @@ -118,22 +119,32 @@ FUNC_NAME (const char *key, const char *var, int no_floppy) return (found && var); } + auto void try (void); + void try (void) + { + unsigned i; + for (i = 0; i < nhints; i++) + if (iterate_device (hints[i])) + return; + grub_device_iterate (iterate_device); + } + /* First try without autoloading if we're setting variable. */ if (var) { saved_autoload = grub_fs_autoload_hook; grub_fs_autoload_hook = 0; - grub_device_iterate (iterate_device); + try (); /* Restore autoload hook. */ grub_fs_autoload_hook = saved_autoload; /* Retry with autoload if nothing found. */ if (grub_errno == GRUB_ERR_NONE && count == 0) - grub_device_iterate (iterate_device); + try (); } else - grub_device_iterate (iterate_device); + try (); grub_free (buf); @@ -148,7 +159,8 @@ grub_cmd_do_search (grub_command_t cmd __attribute__ ((unused)), int argc, if (argc == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, "no argument specified"); - FUNC_NAME (args[0], argc == 1 ? 0 : args[1], 0); + FUNC_NAME (args[0], argc == 1 ? 0 : args[1], 0, (const char **) (args + 2), + argc > 2 ? argc - 2 : 0); return grub_errno; } @@ -165,7 +177,7 @@ GRUB_MOD_INIT(search_fs_label) { cmd = grub_register_command (COMMAND_NAME, grub_cmd_do_search, - "NAME [VARIABLE]", + "NAME [VARIABLE] [HINTS]", "Search devices by " SEARCH_TARGET "." " If VARIABLE is specified, " "the first device found is set to a variable."); diff --git a/commands/search_wrap.c b/commands/search_wrap.c index 2891d85d7..eb9279e87 100644 --- a/commands/search_wrap.c +++ b/commands/search_wrap.c @@ -62,11 +62,14 @@ grub_cmd_search (grub_extcmd_t cmd, int argc, char **args) var = state[SEARCH_SET].arg ? state[SEARCH_SET].arg : "root"; if (state[SEARCH_LABEL].set) - grub_search_label (args[0], var, state[SEARCH_NO_FLOPPY].set); + grub_search_label (args[0], var, state[SEARCH_NO_FLOPPY].set, + (const char **) (args + 1), argc - 1); else if (state[SEARCH_FS_UUID].set) - grub_search_fs_uuid (args[0], var, state[SEARCH_NO_FLOPPY].set); + grub_search_fs_uuid (args[0], var, state[SEARCH_NO_FLOPPY].set, + (const char **) (args + 1), argc - 1); else if (state[SEARCH_FILE].set) - grub_search_fs_file (args[0], var, state[SEARCH_NO_FLOPPY].set); + grub_search_fs_file (args[0], var, state[SEARCH_NO_FLOPPY].set, + (const char **) (args + 1), argc - 1); else return grub_error (GRUB_ERR_INVALID_COMMAND, "unspecified search type"); @@ -80,7 +83,7 @@ GRUB_MOD_INIT(search) cmd = grub_register_extcmd ("search", grub_cmd_search, GRUB_COMMAND_FLAG_BOTH, - N_("search [-f|-l|-u|-s|-n] NAME"), + N_("[-f|-l|-u|-s|-n] NAME [HINTS]"), N_("Search devices by file, filesystem label" " or filesystem UUID." " If --set is specified, the first device found is" diff --git a/include/grub/search.h b/include/grub/search.h index e8f9db285..3c56f0305 100644 --- a/include/grub/search.h +++ b/include/grub/search.h @@ -19,8 +19,11 @@ #ifndef GRUB_SEARCH_HEADER #define GRUB_SEARCH_HEADER 1 -void grub_search_fs_file (const char *key, const char *var, int no_floppy); -void grub_search_fs_uuid (const char *key, const char *var, int no_floppy); -void grub_search_label (const char *key, const char *var, int no_floppy); +void grub_search_fs_file (const char *key, const char *var, int no_floppy, + const char **hints, unsigned nhints); +void grub_search_fs_uuid (const char *key, const char *var, int no_floppy, + const char **hints, unsigned nhints); +void grub_search_label (const char *key, const char *var, int no_floppy, + const char **hints, unsigned nhints); #endif From 41cf1ca332a9b5de3467ff89492c453121703db5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 4 May 2010 15:53:21 +0200 Subject: [PATCH 002/214] implement ACPI shutdown --- commands/acpihalt.c | 266 ++++++++++++++++++++++++++++++++++++++++ commands/i386/pc/halt.c | 4 + conf/i386-pc.rmk | 2 +- include/grub/acpi.h | 27 +++- 4 files changed, 296 insertions(+), 3 deletions(-) create mode 100644 commands/acpihalt.c diff --git a/commands/acpihalt.c b/commands/acpihalt.c new file mode 100644 index 000000000..2ba15468b --- /dev/null +++ b/commands/acpihalt.c @@ -0,0 +1,266 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include + +static inline grub_uint32_t +decode_length (const grub_uint8_t *ptr, int *numlen) +{ + int num_bytes, i; + grub_uint32_t ret; + if (*ptr < 64) + { + if (numlen) + *numlen = 1; + return *ptr; + } + num_bytes = *ptr >> 6; + if (numlen) + *numlen = num_bytes + 1; + ret = *ptr & 0xf; + ptr++; + for (i = 0; i < num_bytes; i++) + { + ret |= *ptr << (8 * i + 4); + ptr++; + } + return ret; +} + +static inline grub_uint32_t +skip_name_string (const grub_uint8_t *ptr, const grub_uint8_t *end) +{ + const grub_uint8_t *ptr0 = ptr; + + while (ptr < end && (*ptr == '^' || *ptr == '\\')) + ptr++; + switch (*ptr) + { + case '.': + ptr++; + ptr += 8; + break; + case '/': + ptr++; + ptr += 1 + (*ptr) * 4; + break; + case 0: + ptr++; + break; + default: + ptr += 4; + break; + } + return ptr - ptr0; +} + +static inline grub_uint32_t +skip_data_ref_object (const grub_uint8_t *ptr, const grub_uint8_t *end) +{ + grub_dprintf ("acpi", "data type = 0x%x\n", *ptr); + switch (*ptr) + { + case GRUB_ACPI_OPCODE_PACKAGE: + return 1 + decode_length (ptr + 1, 0); + case GRUB_ACPI_OPCODE_ZERO: + case GRUB_ACPI_OPCODE_ONES: + case GRUB_ACPI_OPCODE_ONE: + return 1; + case GRUB_ACPI_OPCODE_BYTE_CONST: + return 2; + case GRUB_ACPI_OPCODE_WORD_CONST: + return 3; + case GRUB_ACPI_OPCODE_DWORD_CONST: + return 5; + default: + if (*ptr == '^' || *ptr == '\\' || *ptr == '_' + || (*ptr >= 'A' && *ptr <= 'Z')) + return skip_name_string (ptr, end); + grub_printf ("Unknown opcode 0x%x\n", *ptr); + return 0; + } +} + +static inline grub_uint32_t +skip_ext_op (const grub_uint8_t *ptr, const grub_uint8_t *end) +{ + const grub_uint8_t *ptr0 = ptr; + int add; + grub_dprintf ("acpi", "Extended opcode: 0x%x\n", *ptr); + switch (*ptr) + { + case GRUB_ACPI_EXTOPCODE_MUTEX: + ptr++; + ptr += skip_name_string (ptr, end); + ptr++; + break; + case GRUB_ACPI_EXTOPCODE_OPERATION_REGION: + ptr++; + ptr += skip_name_string (ptr, end); + ptr++; + ptr += add = skip_data_ref_object (ptr, end); + if (!add) + return 0; + ptr += add = skip_data_ref_object (ptr, end); + if (!add) + return 0; + break; + case GRUB_ACPI_EXTOPCODE_FIELD_OP: + ptr++; + ptr += decode_length (ptr, 0); + break; + default: + grub_printf ("Unexpected extended opcode: 0x%x\n", *ptr); + return 0; + } + return ptr - ptr0; +} + +static int +get_sleep_type (grub_uint8_t *table, grub_uint8_t *end) +{ + grub_uint8_t *ptr, *prev; + int sleep_type = -1; + + ptr = table + sizeof (struct grub_acpi_table_header); + while (ptr < end && prev < ptr) + { + int add; + prev = ptr; + grub_dprintf ("acpi", "Opcode %x\n", *ptr); + grub_dprintf ("acpi", "Tell %x\n", ptr - table); + switch (*ptr) + { + case GRUB_ACPI_OPCODE_EXTOP: + ptr++; + ptr += add = skip_ext_op (ptr, end); + if (!add) + return -1; + break; + case GRUB_ACPI_OPCODE_NAME: + ptr++; + if (memcmp (ptr, "_S5_", 4) == 0) + { + int ll; + grub_uint8_t *ptr2 = ptr; + ptr2 += 4; + if (*ptr2 != 0x12) + { + grub_printf ("Unknown opcode in _S5: 0x%x\n", *ptr2); + return -1; + } + ptr2++; + decode_length (ptr2, &ll); + ptr2 += ll; + ptr2++; + switch (*ptr2) + { + case GRUB_ACPI_OPCODE_ZERO: + sleep_type = 0; + break; + case GRUB_ACPI_OPCODE_ONE: + sleep_type = 1; + break; + case GRUB_ACPI_OPCODE_BYTE_CONST: + sleep_type = ptr2[1]; + break; + default: + grub_printf ("Unknown data type in _S5: 0x%x\n", *ptr2); + return -1; + } + } + ptr += add = skip_name_string (ptr, end); + if (!add) + return -1; + ptr += add = skip_data_ref_object (ptr, end); + if (!add) + return -1; + break; + case GRUB_ACPI_OPCODE_SCOPE: + case GRUB_ACPI_OPCODE_IF: + case GRUB_ACPI_OPCODE_METHOD: + { + ptr++; + ptr += decode_length (ptr, 0); + break; + } + } + } + + grub_dprintf ("acpi", "TYP = %d\n", sleep_type); + return sleep_type; +} + +void +grub_acpi_halt (void) +{ + struct grub_acpi_rsdp_v20 *rsdp2; + struct grub_acpi_rsdp_v10 *rsdp1; + struct grub_acpi_table_header *rsdt; + grub_uint32_t *entry_ptr; + + rsdp2 = grub_acpi_get_rsdpv2 (); + if (rsdp2) + rsdp1 = &(rsdp2->rsdpv1); + else + rsdp1 = grub_acpi_get_rsdpv1 (); + grub_dprintf ("acpi", "rsdp1=%p\n", rsdp1); + if (!rsdp1) + return; + + rsdt = (struct grub_acpi_table_header *) rsdp1->rsdt_addr; + for (entry_ptr = (grub_uint32_t *) (rsdt + 1); + entry_ptr < (grub_uint32_t *) (((grub_uint8_t *) rsdt) + + rsdt->length); + entry_ptr++) + { + if (grub_memcmp ((void *)*entry_ptr, "FACP", 4) == 0) + { + grub_uint32_t port; + struct grub_acpi_fadt *fadt + = ((struct grub_acpi_fadt *) *entry_ptr); + struct grub_acpi_table_header *dsdt + = (struct grub_acpi_table_header *) fadt->dsdt_addr; + int sleep_type = -1; + + port = fadt->pm1a; + + grub_dprintf ("acpi", "PM1a port=%x\n", port); + + if (grub_memcmp (dsdt->signature, "DSDT", + sizeof (dsdt->signature)) != 0) + break; + + sleep_type = get_sleep_type ((grub_uint8_t *) dsdt, + (grub_uint8_t *) dsdt + dsdt->length); + + if (sleep_type < 0 || sleep_type >= 8) + break; + + grub_dprintf ("acpi", "SLP_TYP = %d, port = 0x%x\n", + sleep_type, port); + + grub_outw (GRUB_ACPI_SLP_EN + | (sleep_type << GRUB_ACPI_SLP_TYP_OFFSET), port & 0xffff); + } + } + + grub_printf ("ACPI shutdown failed\n"); +} diff --git a/commands/i386/pc/halt.c b/commands/i386/pc/halt.c index 4c39612ae..143f4a4ff 100644 --- a/commands/i386/pc/halt.c +++ b/commands/i386/pc/halt.c @@ -21,6 +21,7 @@ #include #include #include +#include static const struct grub_arg_option options[] = { @@ -36,6 +37,9 @@ grub_cmd_halt (grub_extcmd_t cmd, { struct grub_arg_list *state = cmd->state; int no_apm = 0; + + grub_acpi_halt (); + if (state[0].set) no_apm = 1; grub_halt (no_apm); diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index a5a1b08ea..13055b1c6 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -165,7 +165,7 @@ xnu_mod_LDFLAGS = $(COMMON_LDFLAGS) xnu_mod_ASFLAGS = $(COMMON_ASFLAGS) # For halt.mod. -halt_mod_SOURCES = commands/i386/pc/halt.c +halt_mod_SOURCES = commands/i386/pc/halt.c commands/acpihalt.c halt_mod_CFLAGS = $(COMMON_CFLAGS) halt_mod_LDFLAGS = $(COMMON_LDFLAGS) diff --git a/include/grub/acpi.h b/include/grub/acpi.h index 7933db824..ae83aed34 100644 --- a/include/grub/acpi.h +++ b/include/grub/acpi.h @@ -58,10 +58,12 @@ struct grub_acpi_fadt struct grub_acpi_table_header hdr; grub_uint32_t facs_addr; grub_uint32_t dsdt_addr; - grub_uint8_t somefields1[88]; + grub_uint8_t somefields1[20]; + grub_uint32_t pm1a; + grub_uint8_t somefields2[64]; grub_uint64_t facs_xaddr; grub_uint64_t dsdt_xaddr; - grub_uint8_t somefields2[96]; + grub_uint8_t somefields3[96]; } __attribute__ ((packed)); struct grub_acpi_rsdp_v10 *grub_acpi_get_rsdpv1 (void); @@ -72,4 +74,25 @@ grub_uint8_t grub_byte_checksum (void *base, grub_size_t size); grub_err_t grub_acpi_create_ebda (void); +void grub_acpi_halt (void); + +#define GRUB_ACPI_SLP_EN (1 << 13) +#define GRUB_ACPI_SLP_TYP_OFFSET 10 + +enum + { + GRUB_ACPI_OPCODE_ZERO = 0, GRUB_ACPI_OPCODE_ONE = 1, + GRUB_ACPI_OPCODE_NAME = 8, GRUB_ACPI_OPCODE_BYTE_CONST = 0x0a, + GRUB_ACPI_OPCODE_WORD_CONST = 0x0b, GRUB_ACPI_OPCODE_DWORD_CONST = 0x0c, + GRUB_ACPI_OPCODE_SCOPE = 0x10, GRUB_ACPI_OPCODE_PACKAGE = 0x12, + GRUB_ACPI_OPCODE_METHOD = 0x14, GRUB_ACPI_OPCODE_EXTOP = 0x5b, + GRUB_ACPI_OPCODE_IF = 0xa0, GRUB_ACPI_OPCODE_ONES = 0xff + }; +enum + { + GRUB_ACPI_EXTOPCODE_MUTEX = 0x01, + GRUB_ACPI_EXTOPCODE_OPERATION_REGION = 0x80, + GRUB_ACPI_EXTOPCODE_FIELD_OP = 0x81 + }; + #endif /* ! GRUB_ACPI_HEADER */ From 87fae34a1ff2b165ad532b251e328494797cfc8e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 10 May 2010 14:54:51 +0200 Subject: [PATCH 003/214] Skeleton for keyboard layouts --- commands/cat.c | 2 +- commands/keylayouts.c | 186 ++++++++++++++++++++++++++++++++++++++ commands/keystatus.c | 15 ++- commands/sleep.c | 3 +- conf/common.rmk | 5 + include/grub/term.h | 44 +++++---- kern/i386/pc/startup.S | 49 ---------- kern/rescue_reader.c | 2 +- kern/term.c | 36 +------- lib/crypto.c | 2 +- normal/auth.c | 2 +- normal/cmdline.c | 33 ++++--- normal/main.c | 2 +- normal/menu.c | 23 +++-- normal/menu_entry.c | 48 ++++++---- term/at_keyboard.c | 25 +++-- term/i386/pc/console.c | 1 + term/usb_keyboard.c | 6 +- util/grub-fstest.c | 7 +- util/grub-probe.c | 7 +- util/i386/pc/grub-setup.c | 7 +- 21 files changed, 337 insertions(+), 168 deletions(-) create mode 100644 commands/keylayouts.c diff --git a/commands/cat.c b/commands/cat.c index 3bdafc4c6..556196b4a 100644 --- a/commands/cat.c +++ b/commands/cat.c @@ -63,7 +63,7 @@ grub_cmd_cat (grub_command_t cmd __attribute__ ((unused)), } while (grub_checkkey () >= 0 && - (key = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != GRUB_TERM_ESC) + (key = grub_getkey ()) != GRUB_TERM_ESC) ; } diff --git a/commands/keylayouts.c b/commands/keylayouts.c new file mode 100644 index 000000000..35bbb8376 --- /dev/null +++ b/commands/keylayouts.c @@ -0,0 +1,186 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2003,2005,2007,2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +static int keyboard_map[128] = +{ + '\0', GRUB_TERM_ESC, '1', '2', '3', '4', '5', '6', + '7', '8', '9', '0', '-', '=', GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', + 'o', 'p', '[', ']', '\n', '\0', 'a', 's', + 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', + '\'', '`', '\0', '\\', 'z', 'x', 'c', 'v', + 'b', 'n', 'm', ',', '.', '/', '\0', '*', + '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', GRUB_TERM_KEY_HOME, + GRUB_TERM_KEY_UP, GRUB_TERM_KEY_NPAGE, '-', GRUB_TERM_KEY_LEFT, '\0', GRUB_TERM_KEY_RIGHT, '+', GRUB_TERM_KEY_END, + GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_PPAGE, '\0', GRUB_TERM_KEY_DC +}; + +/* Define scan codes. */ +#define GRUB_TERM_AT_KEY_LEFT 0x4B00 +#define GRUB_TERM_AT_KEY_RIGHT 0x4D00 +#define GRUB_TERM_AT_KEY_UP 0x4800 +#define GRUB_TERM_AT_KEY_DOWN 0x5000 +#define GRUB_TERM_AT_KEY_IC 0x5200 +#define GRUB_TERM_AT_KEY_DC 0x5300 +#define GRUB_TERM_AT_KEY_BACKSPACE 0x0008 +#define GRUB_TERM_AT_KEY_HOME 0x4700 +#define GRUB_TERM_AT_KEY_END 0x4F00 +#define GRUB_TERM_AT_KEY_NPAGE 0x5100 +#define GRUB_TERM_AT_KEY_PPAGE 0x4900 + +static int +get_abstract_code (grub_term_input_t term, int in) +{ + unsigned flags = 0; + switch (term->flags & GRUB_TERM_INPUT_FLAGS_TYPE_MASK) + { + default: + return in; + case GRUB_TERM_INPUT_FLAGS_TYPE_BIOS: + { + unsigned status = 0; + if (term->getkeystatus) + status = term->getkeystatus (); + if (status & GRUB_TERM_CAPS) + flags |= GRUB_TERM_CAPS; + } + /* Fall through. */ + case GRUB_TERM_INPUT_FLAGS_TYPE_AT: + { + struct { + int from, to; + } translations[] = + { + {GRUB_TERM_AT_KEY_LEFT, GRUB_TERM_KEY_LEFT}, + {GRUB_TERM_AT_KEY_RIGHT, GRUB_TERM_KEY_RIGHT}, + {GRUB_TERM_AT_KEY_UP, GRUB_TERM_KEY_UP}, + {GRUB_TERM_AT_KEY_DOWN, GRUB_TERM_KEY_DOWN}, + {GRUB_TERM_AT_KEY_HOME, GRUB_TERM_KEY_HOME}, + {GRUB_TERM_AT_KEY_END, GRUB_TERM_KEY_END}, + {GRUB_TERM_AT_KEY_DC, GRUB_TERM_KEY_DC}, + {GRUB_TERM_AT_KEY_PPAGE, GRUB_TERM_KEY_PPAGE}, + {GRUB_TERM_AT_KEY_NPAGE, GRUB_TERM_KEY_NPAGE} + }; + unsigned i; + for (i = 0; i < ARRAY_SIZE (translations); i++) + if (translations[i].from == (in & 0xffff)) + return translations[i].to | flags; + if ((term->flags & GRUB_TERM_INPUT_FLAGS_TYPE_MASK) + == GRUB_TERM_INPUT_FLAGS_TYPE_AT) + return in & ~0xff00; + /* Detect CTRL'ed keys. */ + if ((in & 0xff) > 0 && (in & 0xff) < 0x20 + && ((in & 0xffff) != (0x0100 | '\e')) + && ((in & 0xffff) != (0x0f00 | '\t')) + && ((in & 0xffff) != (0x0e00 | '\b')) + && ((in & 0xffff) != (0x1c00 | '\r')) + && ((in & 0xffff) != (0x1c00 | '\n'))) + return ((in & 0xff) - 1 + 'a') | flags | GRUB_TERM_CTRL; + /* Detect ALT'ed keys. */ + /* XXX no way to distinguish left and right ALT. */ + if (((in & 0xff) == 0) && keyboard_map[(in & 0xff00) >> 8] >= 'a' + && keyboard_map[(in & 0xff00) >> 8] <= 'z') + return keyboard_map[(in & 0xff00) >> 8] | flags | GRUB_TERM_ALT_GR; + + return (in & 0xff) | flags; + } + } +} + +static int +map (grub_term_input_t term __attribute__ ((unused)), int in) +{ + return in; +} + +static int +translate (grub_term_input_t term, int in) +{ + int code, code2; + code = get_abstract_code (term, in); + if ((code & GRUB_TERM_CAPS) && (code & 0xff) >= 'a' && (code & 0xff) <= 'z') + code = (code & 0xff) + 'A' - 'a'; + else if ((code & GRUB_TERM_CAPS) && (code & 0xff) >= 'A' + && (code & 0xff) <= 'Z') + code = (code & 0xff) + 'a' - 'A'; + + code2 = map (term, code & 0xff); + if ((code & GRUB_TERM_CAPS) && (code2 & 0xff) >= 'a' && (code2 & 0xff) <= 'z') + code2 = code2 + 'A' - 'a'; + else if ((code & GRUB_TERM_CAPS) && (code2 & 0xff) >= 'A' + && (code2 & 0xff) <= 'Z') + code2 = code2 + 'a' - 'A'; + return code2 | (code & ~0xffffff); +} + +static int +grub_getkey_smart (void) +{ + grub_term_input_t term; + + grub_refresh (); + + while (1) + { + FOR_ACTIVE_TERM_INPUTS(term) + { + int key = term->checkkey (); + if (key != -1) + return translate (term, term->getkey ()); + } + + grub_cpu_idle (); + } +} + +int +grub_checkkey (void) +{ + grub_term_input_t term; + + FOR_ACTIVE_TERM_INPUTS(term) + { + int key = term->checkkey (); + if (key != -1) + return translate (term, key); + } + + return -1; +} + +static int (*grub_getkey_saved) (void); + +GRUB_MOD_INIT(keylayouts) +{ + grub_getkey_saved = grub_getkey; + grub_getkey = grub_getkey_smart; +} + +GRUB_MOD_FINI(keylayouts) +{ + grub_getkey = grub_getkey_saved; +} diff --git a/commands/keystatus.c b/commands/keystatus.c index 838792889..fc4d11d73 100644 --- a/commands/keystatus.c +++ b/commands/keystatus.c @@ -31,7 +31,20 @@ static const struct grub_arg_option options[] = {0, 0, 0, 0, 0, 0} }; -#define grub_cur_term_input grub_term_get_current_input () +static int +grub_getkeystatus (void) +{ + int status = 0; + grub_term_input_t term; + + FOR_ACTIVE_TERM_INPUTS(term) + { + if (term->getkeystatus) + status |= term->getkeystatus (); + } + + return status; +} static grub_err_t grub_cmd_keystatus (grub_extcmd_t cmd, diff --git a/commands/sleep.c b/commands/sleep.c index ead279506..bce1aee1d 100644 --- a/commands/sleep.c +++ b/commands/sleep.c @@ -52,8 +52,7 @@ grub_interruptible_millisleep (grub_uint32_t ms) start = grub_get_time_ms (); while (grub_get_time_ms () - start < ms) - if (grub_checkkey () >= 0 && - GRUB_TERM_ASCII_CHAR (grub_getkey ()) == GRUB_TERM_ESC) + if (grub_checkkey () >= 0 && grub_getkey () == GRUB_TERM_ESC) return 1; return 0; diff --git a/conf/common.rmk b/conf/common.rmk index 4b39e9b71..13e1c7a6c 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -491,6 +491,11 @@ extcmd_mod_SOURCES = commands/extcmd.c lib/arg.c extcmd_mod_CFLAGS = $(COMMON_CFLAGS) extcmd_mod_LDFLAGS = $(COMMON_LDFLAGS) +pkglib_MODULES += keylayouts.mod +keylayouts_mod_SOURCES = commands/keylayouts.c +keylayouts_mod_CFLAGS = $(COMMON_CFLAGS) +keylayouts_mod_LDFLAGS = $(COMMON_LDFLAGS) + # For hello.mod. hello_mod_SOURCES = hello/hello.c hello_mod_CFLAGS = $(COMMON_CFLAGS) diff --git a/include/grub/term.h b/include/grub/term.h index 143aabe1e..a2fa80c1f 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -20,18 +20,27 @@ #define GRUB_TERM_HEADER 1 /* Internal codes used by GRUB to represent terminal input. */ -#define GRUB_TERM_LEFT 2 -#define GRUB_TERM_RIGHT 6 -#define GRUB_TERM_UP 16 -#define GRUB_TERM_DOWN 14 -#define GRUB_TERM_HOME 1 -#define GRUB_TERM_END 5 -#define GRUB_TERM_DC 4 -#define GRUB_TERM_PPAGE 7 -#define GRUB_TERM_NPAGE 3 +#define GRUB_TERM_CTRL 0x02000000 +#define GRUB_TERM_ALT 0x04000000 +/* Used by keylayouts code. Never returned in grub_getkey. */ +#define GRUB_TERM_ALT_GR 0x08000000 +#define GRUB_TERM_CAPS 0x10000000 + +/* Keys without associated character. */ +#define GRUB_TERM_EXTENDED 0x1000000 +#define GRUB_TERM_KEY_LEFT (GRUB_TERM_EXTENDED | 1) +#define GRUB_TERM_KEY_RIGHT (GRUB_TERM_EXTENDED | 2) +#define GRUB_TERM_KEY_UP (GRUB_TERM_EXTENDED | 3) +#define GRUB_TERM_KEY_DOWN (GRUB_TERM_EXTENDED | 4) +#define GRUB_TERM_KEY_HOME (GRUB_TERM_EXTENDED | 5) +#define GRUB_TERM_KEY_END (GRUB_TERM_EXTENDED | 6) +#define GRUB_TERM_KEY_DC (GRUB_TERM_EXTENDED | 7) +#define GRUB_TERM_KEY_PPAGE (GRUB_TERM_EXTENDED | 8) +#define GRUB_TERM_KEY_NPAGE (GRUB_TERM_EXTENDED | 9) + #define GRUB_TERM_ESC '\e' #define GRUB_TERM_TAB '\t' -#define GRUB_TERM_BACKSPACE 8 +#define GRUB_TERM_BACKSPACE '\b' #ifndef ASM_FILE @@ -135,9 +144,15 @@ struct grub_term_input /* Get keyboard modifier status. */ int (*getkeystatus) (void); + + grub_uint32_t flags; }; typedef struct grub_term_input *grub_term_input_t; +#define GRUB_TERM_INPUT_FLAGS_TYPE_MASK 0xf +#define GRUB_TERM_INPUT_FLAGS_TYPE_AT 0x1 +#define GRUB_TERM_INPUT_FLAGS_TYPE_BIOS 0x2 + struct grub_term_output { /* The next terminal. */ @@ -253,9 +268,8 @@ grub_term_unregister_output (grub_term_output_t term) void EXPORT_FUNC(grub_putchar) (int c); void EXPORT_FUNC(grub_putcode) (grub_uint32_t code, struct grub_term_output *term); -int EXPORT_FUNC(grub_getkey) (void); -int EXPORT_FUNC(grub_checkkey) (void); -int EXPORT_FUNC(grub_getkeystatus) (void); +extern int (*EXPORT_VAR(grub_getkey)) (void); +int grub_checkkey (void); void EXPORT_FUNC(grub_cls) (void); void EXPORT_FUNC(grub_setcolorstate) (grub_term_color_state state); void EXPORT_FUNC(grub_refresh) (void); @@ -409,10 +423,6 @@ grub_print_spaces (struct grub_term_output *term, int number_spaces) grub_putcode (' ', term); } - -/* For convenience. */ -#define GRUB_TERM_ASCII_CHAR(c) ((c) & 0xff) - #endif /* ! ASM_FILE */ #endif /* ! GRUB_TERM_HEADER */ diff --git a/kern/i386/pc/startup.S b/kern/i386/pc/startup.S index 374277767..6aa3297ab 100644 --- a/kern/i386/pc/startup.S +++ b/kern/i386/pc/startup.S @@ -1154,54 +1154,6 @@ FUNCTION(grub_console_real_putchar) * %al = ASCII character */ -/* this table is used in translate_keycode below */ -LOCAL (translation_table): - .word GRUB_CONSOLE_KEY_LEFT, GRUB_TERM_LEFT - .word GRUB_CONSOLE_KEY_RIGHT, GRUB_TERM_RIGHT - .word GRUB_CONSOLE_KEY_UP, GRUB_TERM_UP - .word GRUB_CONSOLE_KEY_DOWN, GRUB_TERM_DOWN - .word GRUB_CONSOLE_KEY_HOME, GRUB_TERM_HOME - .word GRUB_CONSOLE_KEY_END, GRUB_TERM_END - .word GRUB_CONSOLE_KEY_DC, GRUB_TERM_DC - .word GRUB_CONSOLE_KEY_BACKSPACE, GRUB_TERM_BACKSPACE - .word GRUB_CONSOLE_KEY_PPAGE, GRUB_TERM_PPAGE - .word GRUB_CONSOLE_KEY_NPAGE, GRUB_TERM_NPAGE - .word 0 - -/* - * translate_keycode translates the key code %dx to an ascii code. - */ - .code16 - -translate_keycode: - pushw %bx - pushw %si - -#ifdef __APPLE__ - movw $(ABS(LOCAL (translation_table)) - 0x10000), %si -#else - movw $ABS(LOCAL (translation_table)), %si -#endif - -1: lodsw - /* check if this is the end */ - testw %ax, %ax - jz 2f - /* load the ascii code into %ax */ - movw %ax, %bx - lodsw - /* check if this matches the key code */ - cmpw %bx, %dx - jne 1b - /* translate %dx, if successful */ - movw %ax, %dx - -2: popw %si - popw %bx - ret - - .code32 - FUNCTION(grub_console_getkey) pushl %ebp @@ -1228,7 +1180,6 @@ FUNCTION(grub_console_getkey) int $0x16 movw %ax, %dx /* real_to_prot uses %eax */ - call translate_keycode DATA32 call real_to_prot .code32 diff --git a/kern/rescue_reader.c b/kern/rescue_reader.c index f573cf41f..7cecac6ec 100644 --- a/kern/rescue_reader.c +++ b/kern/rescue_reader.c @@ -38,7 +38,7 @@ grub_rescue_read_line (char **line, int cont) grub_printf ((cont) ? "> " : "grub rescue> "); grub_memset (linebuf, 0, GRUB_RESCUE_BUF_SIZE); - while ((c = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != '\n' && c != '\r') + while ((c = grub_getkey ()) != '\n' && c != '\r') { if (grub_isprint (c)) { diff --git a/kern/term.c b/kern/term.c index 6e3a2b454..ab3d952fa 100644 --- a/kern/term.c +++ b/kern/term.c @@ -75,8 +75,8 @@ grub_putchar (int c) } } -int -grub_getkey (void) +static int +grub_getkey_dumb (void) { grub_term_input_t term; @@ -88,42 +88,14 @@ grub_getkey (void) { int key = term->checkkey (); if (key != -1) - return term->getkey (); + return term->getkey () & 0xff; } grub_cpu_idle (); } } -int -grub_checkkey (void) -{ - grub_term_input_t term; - - FOR_ACTIVE_TERM_INPUTS(term) - { - int key = term->checkkey (); - if (key != -1) - return key; - } - - return -1; -} - -int -grub_getkeystatus (void) -{ - int status = 0; - grub_term_input_t term; - - FOR_ACTIVE_TERM_INPUTS(term) - { - if (term->getkeystatus) - status |= term->getkeystatus (); - } - - return status; -} +int (*grub_getkey) (void) = grub_getkey_dumb; void grub_cls (void) diff --git a/lib/crypto.c b/lib/crypto.c index d11f0994f..405d18911 100644 --- a/lib/crypto.c +++ b/lib/crypto.c @@ -420,7 +420,7 @@ grub_password_get (char buf[], unsigned buf_size) while (1) { - key = GRUB_TERM_ASCII_CHAR (grub_getkey ()); + key = grub_getkey (); if (key == '\n' || key == '\r') break; diff --git a/normal/auth.c b/normal/auth.c index 156b84c37..76dfddb53 100644 --- a/normal/auth.c +++ b/normal/auth.c @@ -162,7 +162,7 @@ grub_username_get (char buf[], unsigned buf_size) while (1) { - key = GRUB_TERM_ASCII_CHAR (grub_getkey ()); + key = grub_getkey (); if (key == '\n' || key == '\r') break; diff --git a/normal/cmdline.c b/normal/cmdline.c index 05d665411..618e25e08 100644 --- a/normal/cmdline.c +++ b/normal/cmdline.c @@ -387,16 +387,18 @@ grub_cmdline_get (const char *prompt) grub_refresh (); - while ((key = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != '\n' && key != '\r') + while ((key = grub_getkey ()) != '\n' && key != '\r') { switch (key) { - case 1: /* Ctrl-a */ + case GRUB_TERM_CTRL | 'a': + case GRUB_TERM_KEY_HOME: lpos = 0; cl_set_pos_all (); break; - case 2: /* Ctrl-b */ + case GRUB_TERM_CTRL | 'b': + case GRUB_TERM_KEY_LEFT: if (lpos > 0) { lpos--; @@ -404,12 +406,14 @@ grub_cmdline_get (const char *prompt) } break; - case 5: /* Ctrl-e */ + case GRUB_TERM_CTRL | 'e': + case GRUB_TERM_KEY_END: lpos = llen; cl_set_pos_all (); break; - case 6: /* Ctrl-f */ + case GRUB_TERM_CTRL | 'f': + case GRUB_TERM_KEY_RIGHT: if (lpos < llen) { lpos++; @@ -417,7 +421,8 @@ grub_cmdline_get (const char *prompt) } break; - case 9: /* Ctrl-i or TAB */ + case GRUB_TERM_CTRL | 'i': + case '\t': { int restore; char *insertu8; @@ -489,7 +494,7 @@ grub_cmdline_get (const char *prompt) } break; - case 11: /* Ctrl-k */ + case GRUB_TERM_CTRL | 'k': if (lpos < llen) { if (kill_buf) @@ -513,7 +518,8 @@ grub_cmdline_get (const char *prompt) } break; - case 14: /* Ctrl-n */ + case GRUB_TERM_CTRL | 'n': + case GRUB_TERM_KEY_DOWN: { grub_uint32_t *hist; @@ -531,7 +537,9 @@ grub_cmdline_get (const char *prompt) break; } - case 16: /* Ctrl-p */ + + case GRUB_TERM_KEY_UP: + case GRUB_TERM_CTRL | 'p': { grub_uint32_t *hist; @@ -550,7 +558,7 @@ grub_cmdline_get (const char *prompt) } break; - case 21: /* Ctrl-u */ + case GRUB_TERM_CTRL | 'u': if (lpos > 0) { grub_size_t n = lpos; @@ -576,7 +584,7 @@ grub_cmdline_get (const char *prompt) } break; - case 25: /* Ctrl-y */ + case GRUB_TERM_CTRL | 'y': if (kill_buf) cl_insert (kill_buf); break; @@ -594,7 +602,8 @@ grub_cmdline_get (const char *prompt) break; /* fall through */ - case 4: /* Ctrl-d */ + case GRUB_TERM_CTRL | 'd': + case GRUB_TERM_KEY_DC: if (lpos < llen) cl_delete (1); break; diff --git a/normal/main.c b/normal/main.c index 4ed17e82c..ff4be3a79 100644 --- a/normal/main.c +++ b/normal/main.c @@ -163,7 +163,7 @@ static struct { {"backspace", '\b'}, {"tab", '\t'}, - {"delete", GRUB_TERM_DC} + {"delete", GRUB_TERM_KEY_DC} }; /* Add a menu entry to the current menu context (as given by the environment diff --git a/normal/menu.c b/normal/menu.c index 09c5fd1eb..b740ea3ca 100644 --- a/normal/menu.c +++ b/normal/menu.c @@ -397,7 +397,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) if (grub_checkkey () >= 0 || timeout < 0) { - c = GRUB_TERM_ASCII_CHAR (grub_getkey ()); + c = grub_getkey (); if (timeout >= 0) { @@ -408,31 +408,36 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) switch (c) { - case GRUB_TERM_HOME: + case GRUB_TERM_KEY_HOME: + case GRUB_TERM_CTRL | 'a': current_entry = 0; menu_set_chosen_entry (current_entry); break; - case GRUB_TERM_END: + case GRUB_TERM_KEY_END: + case GRUB_TERM_CTRL | 'e': current_entry = menu->size - 1; menu_set_chosen_entry (current_entry); break; - case GRUB_TERM_UP: + case GRUB_TERM_KEY_UP: + case GRUB_TERM_CTRL | 'p': case '^': if (current_entry > 0) current_entry--; menu_set_chosen_entry (current_entry); break; - case GRUB_TERM_DOWN: + case GRUB_TERM_CTRL | 'n': + case GRUB_TERM_KEY_DOWN: case 'v': if (current_entry < menu->size - 1) current_entry++; menu_set_chosen_entry (current_entry); break; - case GRUB_TERM_PPAGE: + case GRUB_TERM_CTRL | 'g': + case GRUB_TERM_KEY_PPAGE: if (current_entry < GRUB_MENU_PAGE_SIZE) current_entry = 0; else @@ -440,7 +445,8 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) menu_set_chosen_entry (current_entry); break; - case GRUB_TERM_NPAGE: + case GRUB_TERM_CTRL | 'c': + case GRUB_TERM_KEY_NPAGE: if (current_entry + GRUB_MENU_PAGE_SIZE < menu->size) current_entry += GRUB_MENU_PAGE_SIZE; else @@ -450,7 +456,8 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) case '\n': case '\r': - case 6: + case GRUB_TERM_KEY_RIGHT: + case GRUB_TERM_CTRL | 'f': menu_fini (); *auto_boot = 0; return current_entry; diff --git a/normal/menu_entry.c b/normal/menu_entry.c index 644fe90fd..0b03147dd 100644 --- a/normal/menu_entry.c +++ b/normal/menu_entry.c @@ -1262,7 +1262,7 @@ grub_menu_entry_run (grub_menu_entry_t entry) while (1) { - int c = GRUB_TERM_ASCII_CHAR (grub_getkey ()); + int c = grub_getkey (); if (screen->completion_shown) { @@ -1278,70 +1278,78 @@ grub_menu_entry_run (grub_menu_entry_t entry) switch (c) { - case 16: /* C-p */ + case GRUB_TERM_KEY_UP: + case GRUB_TERM_CTRL | 'p': if (! previous_line (screen, 1)) goto fail; break; - case 14: /* C-n */ + case GRUB_TERM_CTRL | 'n': + case GRUB_TERM_KEY_DOWN: if (! next_line (screen, 1)) goto fail; break; - case 6: /* C-f */ + case GRUB_TERM_CTRL | 'f': + case GRUB_TERM_KEY_RIGHT: if (! forward_char (screen, 1)) goto fail; break; - case 2: /* C-b */ + case GRUB_TERM_CTRL | 'b': + case GRUB_TERM_KEY_LEFT: if (! backward_char (screen, 1)) goto fail; break; - case 1: /* C-a */ + case GRUB_TERM_CTRL | 'a': + case GRUB_TERM_KEY_HOME: if (! beginning_of_line (screen, 1)) goto fail; break; - case 5: /* C-e */ + case GRUB_TERM_CTRL | 'e': + case GRUB_TERM_KEY_END: if (! end_of_line (screen, 1)) goto fail; break; - case '\t': /* C-i */ + case GRUB_TERM_CTRL | 'i': + case '\t': if (! complete (screen, prev_c == c, 1)) goto fail; break; - case 4: /* C-d */ + case GRUB_TERM_CTRL | 'd': + case GRUB_TERM_KEY_DC: if (! delete_char (screen, 1)) goto fail; break; - case 8: /* C-h */ + case GRUB_TERM_CTRL | 'h': if (! backward_delete_char (screen, 1)) goto fail; break; - case 11: /* C-k */ + case GRUB_TERM_CTRL | 'k': if (! kill_line (screen, prev_c == c, 1)) goto fail; break; - case 21: /* C-u */ + case GRUB_TERM_CTRL | 'u': /* FIXME: What behavior is good for this key? */ break; - case 25: /* C-y */ + case GRUB_TERM_CTRL | 'y': if (! yank (screen, 1)) goto fail; break; - case 12: /* C-l */ + case GRUB_TERM_CTRL | 'l': /* FIXME: centering. */ goto refresh; - case 15: /* C-o */ + case GRUB_TERM_CTRL | 'o': if (! open_line (screen, 1)) goto fail; break; @@ -1356,18 +1364,18 @@ grub_menu_entry_run (grub_menu_entry_t entry) destroy_screen (screen); return; - case 3: /* C-c */ + case GRUB_TERM_CTRL | 'c': grub_cmdline_run (1); goto refresh; - case 24: /* C-x */ + case GRUB_TERM_CTRL | 'x': if (! run (screen)) goto fail; goto refresh; - case 18: /* C-r */ - case 19: /* C-s */ - case 20: /* C-t */ + case GRUB_TERM_CTRL | 'r': + case GRUB_TERM_CTRL | 's': + case GRUB_TERM_CTRL | 't': /* FIXME */ break; diff --git a/term/at_keyboard.c b/term/at_keyboard.c index 1f84ae71a..f1932f64e 100644 --- a/term/at_keyboard.c +++ b/term/at_keyboard.c @@ -41,7 +41,7 @@ static grub_uint8_t led_status; #define KEYBOARD_LED_NUM (1 << 1) #define KEYBOARD_LED_CAPS (1 << 2) -static char keyboard_map[128] = +static int keyboard_map[128] = { '\0', GRUB_TERM_ESC, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, @@ -51,9 +51,9 @@ static char keyboard_map[128] = '\'', '`', '\0', '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', '\0', '*', '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0', - '\0', '\0', '\0', '\0', '\0', '\0', '\0', GRUB_TERM_HOME, - GRUB_TERM_UP, GRUB_TERM_NPAGE, '-', GRUB_TERM_LEFT, '\0', GRUB_TERM_RIGHT, '+', GRUB_TERM_END, - GRUB_TERM_DOWN, GRUB_TERM_PPAGE, '\0', GRUB_TERM_DC, '\0', '\0', '\0', '\0', + '\0', '\0', '\0', '\0', '\0', '\0', '\0', GRUB_TERM_KEY_HOME, + GRUB_TERM_KEY_UP, GRUB_TERM_KEY_NPAGE, '-', GRUB_TERM_KEY_LEFT, '\0', GRUB_TERM_KEY_RIGHT, '+', GRUB_TERM_KEY_END, + GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_PPAGE, '\0', GRUB_TERM_KEY_DC, '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', OLPC_UP, OLPC_DOWN, OLPC_LEFT, OLPC_RIGHT @@ -213,9 +213,8 @@ grub_at_keyboard_getkey_noblock (void) key = -1; break; default: - if (at_keyboard_status & (KEYBOARD_STATUS_CTRL_L | KEYBOARD_STATUS_CTRL_R)) - key = keyboard_map[code] - 'a' + 1; - else if ((at_keyboard_status & (KEYBOARD_STATUS_SHIFT_L | KEYBOARD_STATUS_SHIFT_R)) + if ((at_keyboard_status & (KEYBOARD_STATUS_SHIFT_L + | KEYBOARD_STATUS_SHIFT_R)) && keyboard_map_shift[code]) key = keyboard_map_shift[code]; else @@ -231,6 +230,17 @@ grub_at_keyboard_getkey_noblock (void) else if ((key >= 'A') && (key <= 'Z')) key += 'a' - 'A'; } + + if (at_keyboard_status & KEYBOARD_STATUS_ALT_L) + key |= GRUB_TERM_ALT; + if (at_keyboard_status & KEYBOARD_STATUS_ALT_R) + key |= GRUB_TERM_ALT_GR; + if (at_keyboard_status & (KEYBOARD_STATUS_CTRL_L + | KEYBOARD_STATUS_CTRL_R)) + key |= GRUB_TERM_CTRL; + + if (at_keyboard_status & KEYBOARD_STATUS_CAPS_LOCK) + key |= GRUB_TERM_CAPS; } return key; } @@ -290,6 +300,7 @@ static struct grub_term_input grub_at_keyboard_term = .fini = grub_keyboard_controller_fini, .checkkey = grub_at_keyboard_checkkey, .getkey = grub_at_keyboard_getkey, + .flags = GRUB_TERM_INPUT_FLAGS_TYPE_AT }; GRUB_MOD_INIT(at_keyboard) diff --git a/term/i386/pc/console.c b/term/i386/pc/console.c index 43cfe2f2a..09baabd8f 100644 --- a/term/i386/pc/console.c +++ b/term/i386/pc/console.c @@ -51,6 +51,7 @@ static struct grub_term_input grub_console_term_input = .checkkey = grub_console_checkkey, .getkey = grub_console_getkey, .getkeystatus = grub_console_getkeystatus, + .flags = GRUB_TERM_INPUT_FLAGS_TYPE_BIOS }; static struct grub_term_output grub_console_term_output = diff --git a/term/usb_keyboard.c b/term/usb_keyboard.c index 5d76c5e02..8f9a79ec4 100644 --- a/term/usb_keyboard.c +++ b/term/usb_keyboard.c @@ -28,7 +28,7 @@ #include -static char keyboard_map[128] = +static int keyboard_map[128] = { '\0', '\0', '\0', '\0', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', @@ -39,8 +39,8 @@ static char keyboard_map[128] = ']', '\\', '#', ';', '\'', '`', ',', '.', '/', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', - '\0', '\0', GRUB_TERM_HOME, GRUB_TERM_PPAGE, GRUB_TERM_DC, GRUB_TERM_END, GRUB_TERM_NPAGE, GRUB_TERM_RIGHT, - GRUB_TERM_LEFT, GRUB_TERM_DOWN, GRUB_TERM_UP + '\0', '\0', GRUB_TERM_KEY_HOME, GRUB_TERM_KEY_PPAGE, GRUB_TERM_KEY_DC, GRUB_TERM_KEY_END, GRUB_TERM_KEY_NPAGE, GRUB_TERM_KEY_RIGHT, + GRUB_TERM_KEY_LEFT, GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_UP }; static char keyboard_map_shift[128] = diff --git a/util/grub-fstest.c b/util/grub-fstest.c index c03c43451..14ddf2ad8 100644 --- a/util/grub-fstest.c +++ b/util/grub-fstest.c @@ -49,14 +49,13 @@ grub_putchar (int c) putchar (c); } -int -grub_getkey (void) +static int +grub_getkey_real (void) { return -1; } -struct grub_handler_class grub_term_input_class; -struct grub_handler_class grub_term_output_class; +int (*grub_getkey) (void) = grub_getkey_real; void grub_refresh (void) diff --git a/util/grub-probe.c b/util/grub-probe.c index bb41480e2..cb082da6d 100644 --- a/util/grub-probe.c +++ b/util/grub-probe.c @@ -64,14 +64,13 @@ grub_putchar (int c) putchar (c); } -int -grub_getkey (void) +static int +grub_getkey_real (void) { return -1; } -struct grub_handler_class grub_term_input_class; -struct grub_handler_class grub_term_output_class; +int (*grub_getkey) (void) = grub_getkey_real; void grub_refresh (void) diff --git a/util/i386/pc/grub-setup.c b/util/i386/pc/grub-setup.c index 63fa8c328..ffdb356a6 100644 --- a/util/i386/pc/grub-setup.c +++ b/util/i386/pc/grub-setup.c @@ -63,14 +63,13 @@ grub_putchar (int c) putchar (c); } -int -grub_getkey (void) +static int +grub_getkey_real (void) { return -1; } -struct grub_handler_class grub_term_input_class; -struct grub_handler_class grub_term_output_class; +int (*grub_getkey) (void) = grub_getkey_real; void grub_refresh (void) From 08bfb543c40ade8ed8d19dc9eb2d797172482282 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 10 May 2010 15:04:46 +0200 Subject: [PATCH 004/214] Add key_102 --- commands/keylayouts.c | 13 ++++++++++--- include/grub/term.h | 3 +++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/commands/keylayouts.c b/commands/keylayouts.c index 35bbb8376..24da21364 100644 --- a/commands/keylayouts.c +++ b/commands/keylayouts.c @@ -83,7 +83,9 @@ get_abstract_code (grub_term_input_t term, int in) {GRUB_TERM_AT_KEY_END, GRUB_TERM_KEY_END}, {GRUB_TERM_AT_KEY_DC, GRUB_TERM_KEY_DC}, {GRUB_TERM_AT_KEY_PPAGE, GRUB_TERM_KEY_PPAGE}, - {GRUB_TERM_AT_KEY_NPAGE, GRUB_TERM_KEY_NPAGE} + {GRUB_TERM_AT_KEY_NPAGE, GRUB_TERM_KEY_NPAGE}, + {0x5600 | '\\', GRUB_TERM_KEY_102}, + {0x5600 | '|', GRUB_TERM_KEY_SHIFT_102}, }; unsigned i; for (i = 0; i < ARRAY_SIZE (translations); i++) @@ -114,6 +116,11 @@ get_abstract_code (grub_term_input_t term, int in) static int map (grub_term_input_t term __attribute__ ((unused)), int in) { + if (in == GRUB_TERM_KEY_102) + return '\\'; + if (in == GRUB_TERM_KEY_SHIFT_102) + return '|'; + return in; } @@ -128,13 +135,13 @@ translate (grub_term_input_t term, int in) && (code & 0xff) <= 'Z') code = (code & 0xff) + 'a' - 'A'; - code2 = map (term, code & 0xff); + code2 = map (term, code & 0x1ffffff); if ((code & GRUB_TERM_CAPS) && (code2 & 0xff) >= 'a' && (code2 & 0xff) <= 'z') code2 = code2 + 'A' - 'a'; else if ((code & GRUB_TERM_CAPS) && (code2 & 0xff) >= 'A' && (code2 & 0xff) <= 'Z') code2 = code2 + 'a' - 'A'; - return code2 | (code & ~0xffffff); + return code2 | (code & ~0x1ffffff); } static int diff --git a/include/grub/term.h b/include/grub/term.h index a2fa80c1f..b3db120df 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -37,6 +37,9 @@ #define GRUB_TERM_KEY_DC (GRUB_TERM_EXTENDED | 7) #define GRUB_TERM_KEY_PPAGE (GRUB_TERM_EXTENDED | 8) #define GRUB_TERM_KEY_NPAGE (GRUB_TERM_EXTENDED | 9) +/* Used by keylayouts code. Never returned in grub_getkey. */ +#define GRUB_TERM_KEY_102 (GRUB_TERM_EXTENDED | 10) +#define GRUB_TERM_KEY_SHIFT_102 (GRUB_TERM_EXTENDED | 11) #define GRUB_TERM_ESC '\e' #define GRUB_TERM_TAB '\t' From 1ff38af9b95e76e9e63f85fa1981b0c89c132ed9 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 10 May 2010 20:57:01 +0200 Subject: [PATCH 005/214] Simplify AT keyboards and support 102nd key --- commands/keylayouts.c | 19 ++++++++----------- include/grub/term.h | 6 +++--- term/at_keyboard.c | 10 ++++++---- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/commands/keylayouts.c b/commands/keylayouts.c index 24da21364..9b1d92c73 100644 --- a/commands/keylayouts.c +++ b/commands/keylayouts.c @@ -58,19 +58,12 @@ get_abstract_code (grub_term_input_t term, int in) unsigned flags = 0; switch (term->flags & GRUB_TERM_INPUT_FLAGS_TYPE_MASK) { + case GRUB_TERM_INPUT_FLAGS_TYPE_TERMCODES: default: return in; case GRUB_TERM_INPUT_FLAGS_TYPE_BIOS: { unsigned status = 0; - if (term->getkeystatus) - status = term->getkeystatus (); - if (status & GRUB_TERM_CAPS) - flags |= GRUB_TERM_CAPS; - } - /* Fall through. */ - case GRUB_TERM_INPUT_FLAGS_TYPE_AT: - { struct { int from, to; } translations[] = @@ -88,12 +81,16 @@ get_abstract_code (grub_term_input_t term, int in) {0x5600 | '|', GRUB_TERM_KEY_SHIFT_102}, }; unsigned i; + + if (term->getkeystatus) + status = term->getkeystatus (); + if (status & GRUB_TERM_CAPS) + flags |= GRUB_TERM_CAPS; + for (i = 0; i < ARRAY_SIZE (translations); i++) if (translations[i].from == (in & 0xffff)) return translations[i].to | flags; - if ((term->flags & GRUB_TERM_INPUT_FLAGS_TYPE_MASK) - == GRUB_TERM_INPUT_FLAGS_TYPE_AT) - return in & ~0xff00; + /* Detect CTRL'ed keys. */ if ((in & 0xff) > 0 && (in & 0xff) < 0x20 && ((in & 0xffff) != (0x0100 | '\e')) diff --git a/include/grub/term.h b/include/grub/term.h index b3db120df..064093bc5 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -152,9 +152,9 @@ struct grub_term_input }; typedef struct grub_term_input *grub_term_input_t; -#define GRUB_TERM_INPUT_FLAGS_TYPE_MASK 0xf -#define GRUB_TERM_INPUT_FLAGS_TYPE_AT 0x1 -#define GRUB_TERM_INPUT_FLAGS_TYPE_BIOS 0x2 +#define GRUB_TERM_INPUT_FLAGS_TYPE_MASK 0xf +#define GRUB_TERM_INPUT_FLAGS_TYPE_TERMCODES 0x0 +#define GRUB_TERM_INPUT_FLAGS_TYPE_BIOS 0x1 struct grub_term_output { diff --git a/term/at_keyboard.c b/term/at_keyboard.c index f1932f64e..bf94200cc 100644 --- a/term/at_keyboard.c +++ b/term/at_keyboard.c @@ -53,13 +53,14 @@ static int keyboard_map[128] = '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', GRUB_TERM_KEY_HOME, GRUB_TERM_KEY_UP, GRUB_TERM_KEY_NPAGE, '-', GRUB_TERM_KEY_LEFT, '\0', GRUB_TERM_KEY_RIGHT, '+', GRUB_TERM_KEY_END, - GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_PPAGE, '\0', GRUB_TERM_KEY_DC, '\0', '\0', '\0', '\0', + GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_PPAGE, '\0', GRUB_TERM_KEY_DC, '\0', '\0', + GRUB_TERM_KEY_102, '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', OLPC_UP, OLPC_DOWN, OLPC_LEFT, OLPC_RIGHT }; -static char keyboard_map_shift[128] = +static int keyboard_map_shift[128] = { '\0', '\0', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '\0', '\0', @@ -67,7 +68,8 @@ static char keyboard_map_shift[128] = 'O', 'P', '{', '}', '\n', '\0', 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '\"', '~', '\0', '|', 'Z', 'X', 'C', 'V', - 'B', 'N', 'M', '<', '>', '?' + 'B', 'N', 'M', '<', '>', '?', + [0x56] = GRUB_TERM_KEY_SHIFT_102 }; static grub_uint8_t grub_keyboard_controller_orig; @@ -300,7 +302,7 @@ static struct grub_term_input grub_at_keyboard_term = .fini = grub_keyboard_controller_fini, .checkkey = grub_at_keyboard_checkkey, .getkey = grub_at_keyboard_getkey, - .flags = GRUB_TERM_INPUT_FLAGS_TYPE_AT + .flags = GRUB_TERM_INPUT_FLAGS_TYPE_TERMCODES }; GRUB_MOD_INIT(at_keyboard) From 176194068fd30237e1262271cb8d9cbfcd380fb0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 10 May 2010 21:23:40 +0200 Subject: [PATCH 006/214] cleaner AltGr handling --- commands/keylayouts.c | 31 ++++++++++++++++++++++--------- include/grub/term.h | 1 + 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/commands/keylayouts.c b/commands/keylayouts.c index 9b1d92c73..370d55c4f 100644 --- a/commands/keylayouts.c +++ b/commands/keylayouts.c @@ -111,8 +111,13 @@ get_abstract_code (grub_term_input_t term, int in) } static int -map (grub_term_input_t term __attribute__ ((unused)), int in) +map (grub_term_input_t term, int in) { + /* No match with AltGr. Interpret it as Alt rather than as L3 modifier then. + */ + if (in & GRUB_TERM_ALT_GR) + return map (term, in & ~GRUB_TERM_ALT_GR) | GRUB_TERM_ALT_GR; + if (in == GRUB_TERM_KEY_102) return '\\'; if (in == GRUB_TERM_KEY_SHIFT_102) @@ -124,7 +129,7 @@ map (grub_term_input_t term __attribute__ ((unused)), int in) static int translate (grub_term_input_t term, int in) { - int code, code2; + int code, flags; code = get_abstract_code (term, in); if ((code & GRUB_TERM_CAPS) && (code & 0xff) >= 'a' && (code & 0xff) <= 'z') code = (code & 0xff) + 'A' - 'a'; @@ -132,13 +137,21 @@ translate (grub_term_input_t term, int in) && (code & 0xff) <= 'Z') code = (code & 0xff) + 'a' - 'A'; - code2 = map (term, code & 0x1ffffff); - if ((code & GRUB_TERM_CAPS) && (code2 & 0xff) >= 'a' && (code2 & 0xff) <= 'z') - code2 = code2 + 'A' - 'a'; - else if ((code & GRUB_TERM_CAPS) && (code2 & 0xff) >= 'A' - && (code2 & 0xff) <= 'Z') - code2 = code2 + 'a' - 'A'; - return code2 | (code & ~0x1ffffff); + flags = code & ~(GRUB_TERM_KEY_MASK | GRUB_TERM_ALT_GR); + code &= (GRUB_TERM_KEY_MASK | GRUB_TERM_ALT_GR); + code = map (term, code); + /* Transform unconsumed AltGr into Alt. */ + if (code & GRUB_TERM_ALT_GR) + { + flags |= GRUB_TERM_ALT; + code &= ~GRUB_TERM_ALT_GR; + } + if ((flags & GRUB_TERM_CAPS) && code >= 'a' && code <= 'z') + code += 'A' - 'a'; + else if ((flags & GRUB_TERM_CAPS) && code >= 'A' + && code <= 'Z') + code += 'a' - 'A'; + return code | flags; } static int diff --git a/include/grub/term.h b/include/grub/term.h index 064093bc5..626349ac5 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -28,6 +28,7 @@ /* Keys without associated character. */ #define GRUB_TERM_EXTENDED 0x1000000 +#define GRUB_TERM_KEY_MASK 0x1ffffff #define GRUB_TERM_KEY_LEFT (GRUB_TERM_EXTENDED | 1) #define GRUB_TERM_KEY_RIGHT (GRUB_TERM_EXTENDED | 2) #define GRUB_TERM_KEY_UP (GRUB_TERM_EXTENDED | 3) From 9fbfb64abec41ceebbf4844efdd408ee2a681e9d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 10 May 2010 21:25:46 +0200 Subject: [PATCH 007/214] adjust usb_keyboard for keylayouts --- term/usb_keyboard.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/term/usb_keyboard.c b/term/usb_keyboard.c index 8f9a79ec4..5a388eb73 100644 --- a/term/usb_keyboard.c +++ b/term/usb_keyboard.c @@ -150,10 +150,16 @@ grub_usb_keyboard_checkkey (void) data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]); - /* Check if the Control or Shift key was pressed. */ - if (data[0] & 0x01 || data[0] & 0x10) - key = keyboard_map[data[2]] - 'a' + 1; - else if (data[0] & 0x02 || data[0] & 0x20) +#define GRUB_USB_KEYBOARD_LEFT_CTRL 0x01 +#define GRUB_USB_KEYBOARD_LEFT_SHIFT 0x02 +#define GRUB_USB_KEYBOARD_LEFT_ALT 0x04 +#define GRUB_USB_KEYBOARD_RIGHT_CTRL 0x10 +#define GRUB_USB_KEYBOARD_RIGHT_SHIFT 0x20 +#define GRUB_USB_KEYBOARD_RIGHT_ALT 0x40 + + /* Check if the Shift key was pressed. */ + if (data[0] & GRUB_USB_KEYBOARD_LEFT_SHIFT + || data[0] & GRUB_USB_KEYBOARD_RIGHT_SHIFT) key = keyboard_map_shift[data[2]]; else key = keyboard_map[data[2]]; @@ -161,6 +167,18 @@ grub_usb_keyboard_checkkey (void) if (key == 0) grub_printf ("Unknown key 0x%x detected\n", data[2]); + /* Check if the Ctrl key was pressed. */ + if (data[0] & GRUB_USB_KEYBOARD_LEFT_CTRL + || data[0] & GRUB_USB_KEYBOARD_RIGHT_CTRL) + key |= GRUB_TERM_CTRL; + + /* Check if the Alt key was pressed. */ + if (data[0] & GRUB_USB_KEYBOARD_LEFT_ALT) + key |= GRUB_TERM_ALT; + + if (data[0] & GRUB_USB_KEYBOARD_RIGHT_ALT) + key |= GRUB_TERM_ALT_GR; + #if 0 /* Wait until the key is released. */ while (!err && data[2]) @@ -314,6 +332,7 @@ static struct grub_term_input grub_usb_keyboard_term = .checkkey = grub_usb_keyboard_checkkey, .getkey = grub_usb_keyboard_getkey, .getkeystatus = grub_usb_keyboard_getkeystatus, + .flags = GRUB_TERM_INPUT_FLAGS_TYPE_TERMCODES, .next = 0 }; From 092fd48a25b748ff9969883815554f7980b34fe3 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 12 May 2010 15:19:01 +0200 Subject: [PATCH 008/214] legacy parser prototype --- commands/legacycfg.c | 521 +++++++++++++++++++++++++++++++++++++++++++ conf/i386-pc.rmk | 6 + 2 files changed, 527 insertions(+) create mode 100644 commands/legacycfg.c diff --git a/commands/legacycfg.c b/commands/legacycfg.c new file mode 100644 index 000000000..de4631140 --- /dev/null +++ b/commands/legacycfg.c @@ -0,0 +1,521 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct legacy_command +{ + const char *name; + const char *map; + unsigned argc; + enum { + TYPE_VERBATIM, + TYPE_FORCE_OPTION, + TYPE_NOAPM_OPTION, + TYPE_FILE, + TYPE_PARTITION, + TYPE_BOOL, + TYPE_INT + } argt[3]; + enum { + FLAG_IGNORE_REST = 1, + FLAG_ALL_VERBATIM = 2 + } flags; +}; + +struct legacy_command legacy_commands[] = + { + {"blocklist", "blocklist '%s'\n", 1, {TYPE_FILE}, 0}, + {"boot", "boot\n", 0, {}, 0}, + /* bootp unsupported. */ + {"cat", "cat '%s'\n", 1, {TYPE_FILE}, 0}, + {"chainloader", "chainloader %s '%s'\n", 2, {TYPE_FORCE_OPTION, TYPE_FILE}, + 0}, + {"cmp", "cmp '%s' '%s'\n", 2, {TYPE_FILE, TYPE_FILE}, FLAG_IGNORE_REST}, + /* FIXME: Implement command. */ + {"color", "legacy_color '%s' '%s'\n", 2, {TYPE_VERBATIM, TYPE_VERBATIM}, + FLAG_IGNORE_REST}, + {"configfile", "legacy_configfile '%s'\n", 1, {TYPE_FILE}, 0}, + {"debug", + "if [ -z \"$debug\" ]; then set debug=all; else set debug=; fi\n", + 0, {}, 0}, + /* FIXME: Implement command. */ + {"default", "legacy_default %s\n", 1, {TYPE_INT}, 0}, + /* dhcp unsupported. */ + /* displayapm unsupported. */ + {"displaymem", "lsmem\n", 0, {}, 0}, + /* embed unsupported. */ + {"fallback", "set fallback='%s'\n", 1, {TYPE_VERBATIM}, 0}, + {"find", "search -f '%s'\n", 1, {TYPE_FILE}, 0}, + /* fstest unsupported. */ + /* geometry unsupported. */ + {"halt", "halt %s\n", 1, {TYPE_NOAPM_OPTION}, 0}, + /* help unsupported. */ /* NUL_TERMINATE */ + /* hiddenmenu unsupported. */ + {"hide", "parttool '%s' hidden+\n", 1, {TYPE_PARTITION}, 0}, + /* ifconfig unsupported. */ + /* impsprobe unsupported. */ + /* FIXME: Implement command. */ + {"initrd", "legacy_initrd '%s'\n", 1, {TYPE_FILE}, 0}, + /* install unsupported. */ + /* ioprobe unsupported. */ + /* FIXME: implement command. */ + {"kernel", "legacy_kernel %s\n", 0, {}, FLAG_ALL_VERBATIM}, + /* lock is handled separately. */ + {"makeactive", "parttool '%s' boot+\n", 1, {TYPE_PARTITION}, 0}, + {"map", "drivemap '%s' '%s'\n", 2, {TYPE_PARTITION, TYPE_PARTITION}, + FLAG_IGNORE_REST}, + /* md5crypt unsupported. */ + {"module", "legacy_initrd '%s'\n", 1, {TYPE_FILE}, 0}, + /* modulenounzip unsupported. */ + {"pager", "set pager=%d\n", 1, {TYPE_BOOL}, 0}, + /* partnew unsupported. */ + {"parttype", "parttool '%s' type=%s\n", 2, {TYPE_PARTITION, TYPE_INT}, 0}, + /* password unsupported. */ /* NUL_TERMINATE */ + /* pause unsupported. */ + /* rarp unsupported. */ + {"read", "read_dword %s\n", 1, {TYPE_INT}, 0}, + {"reboot", "reboot\n", 0, {}, 0}, + {"root", "set root='%s'\n", 1, {TYPE_PARTITION}, 0}, + {"rootnoverify", "set root='%s'\n", 1, {TYPE_PARTITION}, 0}, + {"savedefault", "saved_entry=${chosen}; save_env saved_entry\n", 0, {}, 0}, + /* serial unsupported. */ + /* setkey unsupported. */ /* NUL_TERMINATE */ + /* setup unsupported. */ + /* terminal unsupported. */ /* NUL_TERMINATE */ + /* terminfo unsupported. */ /* NUL_TERMINATE */ + /* testload unsupported. */ + /* testvbe unsupported. */ + /* tftpserver unsupported. */ + {"timeout", "set timeout=%s\n", 1, {TYPE_INT}, 0}, + /* title is handled separately. */ + {"unhide", "parttool '%s' hidden-\n", 1, {TYPE_PARTITION}, 0}, + /* uppermem unsupported. */ + /* vbeprobe unsupported. */ + }; + +static char * +escape (const char *in) +{ + const char *ptr; + char *ret, *outptr; + int overhead = 0; + for (ptr = in; *ptr; ptr++) + if (*ptr == '\'' || *ptr == '\\') + overhead++; + ret = grub_malloc (ptr - in + overhead); + if (!ret) + return NULL; + outptr = ret; + for (ptr = in; *ptr; ptr++) + { + if (*ptr == '\'' || *ptr == '\\') + *outptr++ = '\\'; + + *outptr++ = *ptr; + } + return ret; +} + +static char * +adjust_file (const char *in) +{ + const char *comma, *ptr, *rest; + char *ret, *outptr; + int overhead = 0; + int part; + if (in[0] != '(') + return escape (in); + for (ptr = in + 1; *ptr && *ptr != ')' && *ptr != ','; ptr++) + if (*ptr == '\'' || *ptr == '\\') + overhead++; + comma = ptr; + if (*comma != ',') + return escape (in); + part = grub_strtoull (comma + 1, (char **) &rest, 0); + for (ptr = rest; *ptr; ptr++) + if (*ptr == '\'' || *ptr == '\\') + overhead++; + + /* 30 is enough for any number. */ + ret = grub_malloc (ptr - in + overhead + 30); + if (!ret) + return NULL; + + outptr = ret; + for (ptr = in; ptr <= comma; ptr++) + { + if (*ptr == '\'' || *ptr == '\\') + *outptr++ = '\\'; + + *outptr++ = *ptr; + } + grub_snprintf (outptr, 30, "%d", part + 1); + while (*outptr) + outptr++; + for (ptr = rest; ptr <= comma; ptr++) + { + if (*ptr == '\'' || *ptr == '\\') + *outptr++ = '\\'; + + *outptr++ = *ptr; + } + return ret; +} + +static char * +legacy_parse (char *buf, char **entryname) +{ + char *ptr; + char *cmdname; + unsigned i, cmdnum; + + for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++); + if ((!*ptr || *ptr == '#') && entryname && *entryname) + return buf; + if (!*ptr || *ptr == '#') + { + grub_free (buf); + return NULL; + } + + cmdname = ptr; + for (ptr = buf; !grub_isspace (*ptr) && *ptr != '='; ptr++); + + if (entryname && grub_strncmp ("title", cmdname, ptr - cmdname) == 0 + && ptr - cmdname == sizeof ("title") - 1) + { + for (; grub_isspace (*ptr) || *ptr == '='; ptr++); + *entryname = grub_strdup (ptr); + grub_free (buf); + return NULL; + } + + if (grub_strncmp ("lock", cmdname, ptr - cmdname) == 0 + && ptr - cmdname == sizeof ("lock") - 1) + { + /* FIXME */ + } + + for (cmdnum = 0; cmdnum < ARRAY_SIZE (legacy_commands); cmdnum++) + if (grub_strncmp (legacy_commands[cmdnum].name, cmdname, ptr - cmdname) == 0 + && legacy_commands[cmdnum].name[ptr - cmdname] == 0) + break; + if (cmdnum == ARRAY_SIZE (legacy_commands)) + return grub_xasprintf ("# Unsupported legacy command: %s\n", buf); + + for (; grub_isspace (*ptr) || *ptr == '='; ptr++); + + char *args[ARRAY_SIZE (legacy_commands[0].argt)]; + memset (args, 0, sizeof (args)); + + if (legacy_commands[cmdnum].flags & FLAG_ALL_VERBATIM) + { + char *arg0 = ptr, *outptr; + int overhead = 3; + while (*ptr) + { + char *curarg; + for (; grub_isspace (*ptr); ptr++); + curarg = ptr; + for (; *ptr && !grub_isspace (*ptr); ptr++) + if (*ptr == '\\' || *ptr == '\'') + overhead++; + if (ptr) + ptr++; + overhead += 3; + } + args[0] = grub_malloc (overhead + (ptr - arg0)); + if (!args[0]) + { + grub_free (buf); + return NULL; + } + ptr = arg0; + outptr = args[0]; + while (*ptr) + { + char *curarg; + for (; grub_isspace (*ptr); ptr++); + curarg = ptr; + if (outptr != args[0]) + *outptr++ = ' '; + *outptr++ = '\''; + for (; *ptr && !grub_isspace (*ptr); ptr++) + { + if (*ptr == '\\' || *ptr == '\'') + *outptr++ = '\\'; + *outptr++ = *ptr; + } + *outptr++ = '\''; + if (ptr) + ptr++; + overhead += 3; + } + } + + { + unsigned j = 0; + for (i = 0; i < legacy_commands[cmdnum].argc; i++) + { + char *curarg, *cptr = NULL, c; + for (; grub_isspace (*ptr); ptr++); + curarg = ptr; + for (; !grub_isspace (*ptr); ptr++); + if (i != legacy_commands[cmdnum].argc - 1 + || (legacy_commands[cmdnum].flags & FLAG_IGNORE_REST)) + { + cptr = ptr; + c = *cptr; + *ptr = 0; + } + ptr++; + switch (legacy_commands[cmdnum].argt[i]) + { + case TYPE_PARTITION: + case TYPE_FILE: + args[j++] = adjust_file (curarg); + break; + + case TYPE_VERBATIM: + args[j++] = escape (curarg); + break; + case TYPE_FORCE_OPTION: + if (grub_strcmp (curarg, "--force") == 0) + { + args[j++] = grub_strdup ("--force"); + break; + } + if (cptr) + *cptr = c; + ptr = curarg; + break; + case TYPE_NOAPM_OPTION: + if (grub_strcmp (curarg, "--no-apm") == 0) + { + args[j++] = grub_strdup ("--no-apm"); + break; + } + if (cptr) + *cptr = c; + ptr = curarg; + break; + case TYPE_INT: + { + char *brk; + int base = 10; + brk = curarg; + if (brk[0] == '0' && brk[1] == 'x') + base = 16; + else if (brk[0] == '0') + base = 8; + for (; *brk; brk++) + { + if (base == 8 && (*brk == '8' || *brk == '9')) + break; + if (grub_isdigit (*brk)) + continue; + if (base != 16) + break; + if (!(*brk >= 'a' && *brk <= 'f') + && !(*brk >= 'A' && *brk <= 'F')) + break; + } + if (brk == curarg) + args[j++] = grub_strdup ("0"); + else + args[j++] = grub_strndup (curarg, brk - curarg); + } + break; + case TYPE_BOOL: + if (curarg[0] == 'o' && curarg[1] == 'n' + && (curarg[2] == 0 || grub_isspace (curarg[2]))) + args[j++] = grub_strdup ("1"); + else + args[j++] = grub_strdup ("0"); + break; + } + } + } + grub_free (buf); + return grub_xasprintf (legacy_commands[cmdnum].map, args[0], args[1], args[2]); +} + +static grub_err_t +legacy_file (const char *filename) +{ + grub_file_t file; + char *entryname = NULL, *entrysrc = NULL; + grub_menu_t menu; + + file = grub_gzfile_open (filename, 1); + if (! file) + return grub_errno; + + menu = grub_env_get_menu (); + if (! menu) + { + menu = grub_zalloc (sizeof (*menu)); + if (! menu) + return grub_errno; + + grub_env_set_menu (menu); + } + + while (1) + { + char *buf = grub_file_getline (file); + char *parsed; + + if (!buf && grub_errno) + { + grub_file_close (file); + return grub_errno; + } + + if (!buf) + break; + + { + char *oldname = NULL; + + oldname = entryname; + parsed = legacy_parse (buf, &entryname); + if (oldname != entryname && oldname) + { + const char **args = grub_malloc (sizeof (args[0])); + if (!args) + { + grub_file_close (file); + return grub_errno; + } + args[0] = oldname; + grub_normal_add_menu_entry (1, args, entrysrc); + } + } + + if (parsed && !entryname) + { + auto grub_err_t getline (char **line, int cont); + grub_err_t getline (char **line __attribute__ ((unused)), + int cont __attribute__ ((unused))) + { + return GRUB_ERR_NONE; + } + + grub_normal_parse_line (parsed, getline); + grub_free (parsed); + } + else if (parsed) + { + if (!entrysrc) + entrysrc = parsed; + else + { + char *t; + + t = entrysrc; + entrysrc = grub_realloc (entrysrc, grub_strlen (entrysrc) + + grub_strlen (parsed) + 1); + if (!entrysrc) + { + grub_free (t); + grub_free (parsed); + return grub_errno; + } + grub_memcpy (entrysrc + grub_strlen (entrysrc), buf, + grub_strlen (parsed) + 1); + grub_free (parsed); + parsed = NULL; + } + } + } + grub_file_close (file); + + if (entryname) + { + const char **args = grub_malloc (sizeof (args[0])); + if (!args) + { + grub_file_close (file); + return grub_errno; + } + args[0] = entryname; + grub_normal_add_menu_entry (1, args, entrysrc); + } + + if (menu && menu->size) + grub_show_menu (menu, 1); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_legacy_source (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); + return legacy_file (args[0]); +} + +static grub_err_t +grub_cmd_legacy_configfile (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + grub_err_t ret; + if (argc != 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); + + grub_cls (); + grub_env_context_open (1); + + ret = legacy_file (args[0]); + grub_env_context_close (); + + return ret; +} + +static grub_command_t cmd_source, cmd_configfile; + +GRUB_MOD_INIT(legacycfg) +{ + cmd_source = grub_register_command ("legacy_source", + grub_cmd_legacy_source, + N_("FILE"), N_("Parse legacy config")); + cmd_configfile = grub_register_command ("legacy_configfile", + grub_cmd_legacy_configfile, + N_("FILE"), + N_("Parse legacy config")); +} + +GRUB_MOD_FINI(legacycfg) +{ + grub_unregister_command (cmd_source); + grub_unregister_command (cmd_configfile); +} diff --git a/conf/i386-pc.rmk b/conf/i386-pc.rmk index 5ff852f2e..791d64349 100644 --- a/conf/i386-pc.rmk +++ b/conf/i386-pc.rmk @@ -255,6 +255,12 @@ hdparm_mod_SOURCES = commands/hdparm.c lib/hexdump.c hdparm_mod_CFLAGS = $(COMMON_CFLAGS) hdparm_mod_LDFLAGS = $(COMMON_LDFLAGS) +# grub legacy ever supported only i386-pc. +pkglib_MODULES += legacycfg.mod +legacycfg_mod_SOURCES = commands/legacycfg.c +legacycfg_mod_CFLAGS = $(COMMON_CFLAGS) +legacycfg_mod_LDFLAGS = $(COMMON_LDFLAGS) + ifeq ($(enable_efiemu), yes) efiemu32.o: efiemu/runtime/efiemu.c $(TARGET_OBJ2ELF) From 68cc4355f8b31612a4edd7a6d6bb844857e1cfb0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 12 May 2010 17:51:22 +0200 Subject: [PATCH 009/214] Fix few bugs and put a cleaner way to handle kernel command --- commands/legacycfg.c | 151 +++++++++++++++++++++++++------------------ 1 file changed, 87 insertions(+), 64 deletions(-) diff --git a/commands/legacycfg.c b/commands/legacycfg.c index de4631140..6069fe746 100644 --- a/commands/legacycfg.c +++ b/commands/legacycfg.c @@ -27,24 +27,26 @@ #include #include #include +#include struct legacy_command { const char *name; const char *map; unsigned argc; - enum { + enum arg_type { TYPE_VERBATIM, TYPE_FORCE_OPTION, TYPE_NOAPM_OPTION, + TYPE_TYPE_OPTION, TYPE_FILE, TYPE_PARTITION, TYPE_BOOL, - TYPE_INT + TYPE_INT, + TYPE_REST_VERBATIM } argt[3]; enum { - FLAG_IGNORE_REST = 1, - FLAG_ALL_VERBATIM = 2 + FLAG_IGNORE_REST = 1 } flags; }; @@ -85,7 +87,8 @@ struct legacy_command legacy_commands[] = /* install unsupported. */ /* ioprobe unsupported. */ /* FIXME: implement command. */ - {"kernel", "legacy_kernel %s\n", 0, {}, FLAG_ALL_VERBATIM}, + {"kernel", "legacy_kernel %s '%s' %s\n", 3, {TYPE_TYPE_OPTION, TYPE_FILE, + TYPE_REST_VERBATIM}, 0}, /* lock is handled separately. */ {"makeactive", "parttool '%s' boot+\n", 1, {TYPE_PARTITION}, 0}, {"map", "drivemap '%s' '%s'\n", 2, {TYPE_PARTITION, TYPE_PARTITION}, @@ -116,6 +119,7 @@ struct legacy_command legacy_commands[] = /* title is handled separately. */ {"unhide", "parttool '%s' hidden-\n", 1, {TYPE_PARTITION}, 0}, /* uppermem unsupported. */ + {"uuid", "search -u '%s'\n", 1, {TYPE_VERBATIM}, 0}, /* vbeprobe unsupported. */ }; @@ -139,6 +143,7 @@ escape (const char *in) *outptr++ = *ptr; } + *outptr++ = 0; return ret; } @@ -188,6 +193,27 @@ adjust_file (const char *in) return ret; } +static int +is_option (enum arg_type opt, const char *curarg) +{ + switch (opt) + { + case TYPE_NOAPM_OPTION: + return grub_strcmp (curarg, "--no-apm") == 0; + case TYPE_FORCE_OPTION: + return grub_strcmp (curarg, "--force") == 0; + case TYPE_TYPE_OPTION: + return grub_strcmp (curarg, "--type=netbsd") == 0 + || grub_strcmp (curarg, "--type=freebsd") == 0 + || grub_strcmp (curarg, "--type=openbsd") == 0 + || grub_strcmp (curarg, "--type=linux") == 0 + || grub_strcmp (curarg, "--type=biglinux") == 0 + || grub_strcmp (curarg, "--type=multiboot") == 0; + default: + return 0; + } +} + static char * legacy_parse (char *buf, char **entryname) { @@ -197,7 +223,11 @@ legacy_parse (char *buf, char **entryname) for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++); if ((!*ptr || *ptr == '#') && entryname && *entryname) - return buf; + { + char *ret = grub_xasprintf ("%s\n", buf); + grub_free (buf); + return ret; + } if (!*ptr || *ptr == '#') { grub_free (buf); @@ -234,51 +264,6 @@ legacy_parse (char *buf, char **entryname) char *args[ARRAY_SIZE (legacy_commands[0].argt)]; memset (args, 0, sizeof (args)); - if (legacy_commands[cmdnum].flags & FLAG_ALL_VERBATIM) - { - char *arg0 = ptr, *outptr; - int overhead = 3; - while (*ptr) - { - char *curarg; - for (; grub_isspace (*ptr); ptr++); - curarg = ptr; - for (; *ptr && !grub_isspace (*ptr); ptr++) - if (*ptr == '\\' || *ptr == '\'') - overhead++; - if (ptr) - ptr++; - overhead += 3; - } - args[0] = grub_malloc (overhead + (ptr - arg0)); - if (!args[0]) - { - grub_free (buf); - return NULL; - } - ptr = arg0; - outptr = args[0]; - while (*ptr) - { - char *curarg; - for (; grub_isspace (*ptr); ptr++); - curarg = ptr; - if (outptr != args[0]) - *outptr++ = ' '; - *outptr++ = '\''; - for (; *ptr && !grub_isspace (*ptr); ptr++) - { - if (*ptr == '\\' || *ptr == '\'') - *outptr++ = '\\'; - *outptr++ = *ptr; - } - *outptr++ = '\''; - if (ptr) - ptr++; - overhead += 3; - } - } - { unsigned j = 0; for (i = 0; i < legacy_commands[cmdnum].argc; i++) @@ -294,7 +279,8 @@ legacy_parse (char *buf, char **entryname) c = *cptr; *ptr = 0; } - ptr++; + if (*ptr) + ptr++; switch (legacy_commands[cmdnum].argt[i]) { case TYPE_PARTITION: @@ -302,28 +288,65 @@ legacy_parse (char *buf, char **entryname) args[j++] = adjust_file (curarg); break; + case TYPE_REST_VERBATIM: + { + char *outptr, *outptr0; + int overhead = 3; + ptr = curarg; + while (*ptr) + { + for (; grub_isspace (*ptr); ptr++); + for (; *ptr && !grub_isspace (*ptr); ptr++) + if (*ptr == '\\' || *ptr == '\'') + overhead++; + if (*ptr) + ptr++; + overhead += 3; + } + outptr0 = args[j++] = grub_malloc (overhead + (ptr - curarg)); + if (!outptr0) + { + grub_free (buf); + return NULL; + } + ptr = curarg; + outptr = outptr0; + while (*ptr) + { + for (; grub_isspace (*ptr); ptr++); + if (outptr != outptr0) + *outptr++ = ' '; + *outptr++ = '\''; + for (; *ptr && !grub_isspace (*ptr); ptr++) + { + if (*ptr == '\\' || *ptr == '\'') + *outptr++ = '\\'; + *outptr++ = *ptr; + } + *outptr++ = '\''; + if (*ptr) + ptr++; + overhead += 3; + } + *outptr++ = 0; + } + break; + case TYPE_VERBATIM: args[j++] = escape (curarg); break; case TYPE_FORCE_OPTION: - if (grub_strcmp (curarg, "--force") == 0) - { - args[j++] = grub_strdup ("--force"); - break; - } - if (cptr) - *cptr = c; - ptr = curarg; - break; case TYPE_NOAPM_OPTION: - if (grub_strcmp (curarg, "--no-apm") == 0) + case TYPE_TYPE_OPTION: + if (is_option (legacy_commands[cmdnum].argt[i], curarg)) { - args[j++] = grub_strdup ("--no-apm"); + args[j++] = grub_strdup (curarg); break; } if (cptr) *cptr = c; ptr = curarg; + args[j++] = ""; break; case TYPE_INT: { @@ -448,7 +471,7 @@ legacy_file (const char *filename) grub_free (parsed); return grub_errno; } - grub_memcpy (entrysrc + grub_strlen (entrysrc), buf, + grub_memcpy (entrysrc + grub_strlen (entrysrc), parsed, grub_strlen (parsed) + 1); grub_free (parsed); parsed = NULL; From b07e88dc6add00f8860d2ab7b47dbf4d2982b38d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 12 May 2010 17:55:37 +0200 Subject: [PATCH 010/214] default support --- commands/legacycfg.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/commands/legacycfg.c b/commands/legacycfg.c index 6069fe746..46637c301 100644 --- a/commands/legacycfg.c +++ b/commands/legacycfg.c @@ -66,8 +66,7 @@ struct legacy_command legacy_commands[] = {"debug", "if [ -z \"$debug\" ]; then set debug=all; else set debug=; fi\n", 0, {}, 0}, - /* FIXME: Implement command. */ - {"default", "legacy_default %s\n", 1, {TYPE_INT}, 0}, + {"default", "set default='%s'; if [ x\"$default\" = xsaved ]; then load_env; set default=\"$saved_entry\"\n", 1, {TYPE_VERBATIM}, 0}, /* dhcp unsupported. */ /* displayapm unsupported. */ {"displaymem", "lsmem\n", 0, {}, 0}, From 67cb07a31bfc7269af7c3f411f636d8d275e72eb Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 12 May 2010 18:13:43 +0200 Subject: [PATCH 011/214] fix more bugs --- commands/legacycfg.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/commands/legacycfg.c b/commands/legacycfg.c index 46637c301..aaaac8112 100644 --- a/commands/legacycfg.c +++ b/commands/legacycfg.c @@ -66,10 +66,10 @@ struct legacy_command legacy_commands[] = {"debug", "if [ -z \"$debug\" ]; then set debug=all; else set debug=; fi\n", 0, {}, 0}, - {"default", "set default='%s'; if [ x\"$default\" = xsaved ]; then load_env; set default=\"$saved_entry\"\n", 1, {TYPE_VERBATIM}, 0}, + {"default", "set default='%s'; if [ x\"$default\" = xsaved ]; then load_env; set default=\"$saved_entry\"; fi\n", 1, {TYPE_VERBATIM}, 0}, /* dhcp unsupported. */ /* displayapm unsupported. */ - {"displaymem", "lsmem\n", 0, {}, 0}, + {"displaymem", "lsmmap\n", 0, {}, 0}, /* embed unsupported. */ {"fallback", "set fallback='%s'\n", 1, {TYPE_VERBATIM}, 0}, {"find", "search -f '%s'\n", 1, {TYPE_FILE}, 0}, @@ -234,7 +234,7 @@ legacy_parse (char *buf, char **entryname) } cmdname = ptr; - for (ptr = buf; !grub_isspace (*ptr) && *ptr != '='; ptr++); + for (ptr = buf; *ptr && !grub_isspace (*ptr) && *ptr != '='; ptr++); if (entryname && grub_strncmp ("title", cmdname, ptr - cmdname) == 0 && ptr - cmdname == sizeof ("title") - 1) @@ -267,7 +267,7 @@ legacy_parse (char *buf, char **entryname) unsigned j = 0; for (i = 0; i < legacy_commands[cmdnum].argc; i++) { - char *curarg, *cptr = NULL, c; + char *curarg, *cptr = NULL, c = 0; for (; grub_isspace (*ptr); ptr++); curarg = ptr; for (; !grub_isspace (*ptr); ptr++); @@ -451,6 +451,7 @@ legacy_file (const char *filename) } grub_normal_parse_line (parsed, getline); + grub_print_error (); grub_free (parsed); } else if (parsed) From a408e05187d5411e623c602e936df054c1934663 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 12 May 2010 18:24:02 +0200 Subject: [PATCH 012/214] Add serial command --- commands/legacycfg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commands/legacycfg.c b/commands/legacycfg.c index aaaac8112..8f02a028f 100644 --- a/commands/legacycfg.c +++ b/commands/legacycfg.c @@ -106,7 +106,7 @@ struct legacy_command legacy_commands[] = {"root", "set root='%s'\n", 1, {TYPE_PARTITION}, 0}, {"rootnoverify", "set root='%s'\n", 1, {TYPE_PARTITION}, 0}, {"savedefault", "saved_entry=${chosen}; save_env saved_entry\n", 0, {}, 0}, - /* serial unsupported. */ + {"serial", "serial %s\n", 1, {TYPE_REST_VERBATIM}, 0}, /* setkey unsupported. */ /* NUL_TERMINATE */ /* setup unsupported. */ /* terminal unsupported. */ /* NUL_TERMINATE */ From 8f937bfe07fd622bb982ca218e5e8e67345d7dba Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 12 May 2010 21:02:41 +0200 Subject: [PATCH 013/214] Fix makeactive syntax --- commands/legacycfg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commands/legacycfg.c b/commands/legacycfg.c index 8f02a028f..8077497f3 100644 --- a/commands/legacycfg.c +++ b/commands/legacycfg.c @@ -89,7 +89,7 @@ struct legacy_command legacy_commands[] = {"kernel", "legacy_kernel %s '%s' %s\n", 3, {TYPE_TYPE_OPTION, TYPE_FILE, TYPE_REST_VERBATIM}, 0}, /* lock is handled separately. */ - {"makeactive", "parttool '%s' boot+\n", 1, {TYPE_PARTITION}, 0}, + {"makeactive", "parttool \"$root\" boot+\n", 0, {}, 0}, {"map", "drivemap '%s' '%s'\n", 2, {TYPE_PARTITION, TYPE_PARTITION}, FLAG_IGNORE_REST}, /* md5crypt unsupported. */ From 7a6459e12d3dbc01020f0e6c6dcf12a2afdd3bc1 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 19 Aug 2010 01:07:50 +0200 Subject: [PATCH 014/214] support for Fn keys --- commands/keylayouts.c | 67 ++++++--------------------- commands/keystatus.c | 2 +- include/grub/at_keyboard.h | 24 ++++++++++ include/grub/term.h | 17 ++++++- normal/main.c | 15 +++++- normal/menu_entry.c | 3 ++ normal/menu_text.c | 9 +--- term/at_keyboard.c | 19 +------- term/efi/console.c | 94 +++++++------------------------------- term/terminfo.c | 34 +++++++------- term/usb_keyboard.c | 24 ++++++---- 11 files changed, 123 insertions(+), 185 deletions(-) diff --git a/commands/keylayouts.c b/commands/keylayouts.c index 370d55c4f..58baabe67 100644 --- a/commands/keylayouts.c +++ b/commands/keylayouts.c @@ -23,39 +23,13 @@ #include #include #include +#include -static int keyboard_map[128] = -{ - '\0', GRUB_TERM_ESC, '1', '2', '3', '4', '5', '6', - '7', '8', '9', '0', '-', '=', GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, - 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', - 'o', 'p', '[', ']', '\n', '\0', 'a', 's', - 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', - '\'', '`', '\0', '\\', 'z', 'x', 'c', 'v', - 'b', 'n', 'm', ',', '.', '/', '\0', '*', - '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0', - '\0', '\0', '\0', '\0', '\0', '\0', '\0', GRUB_TERM_KEY_HOME, - GRUB_TERM_KEY_UP, GRUB_TERM_KEY_NPAGE, '-', GRUB_TERM_KEY_LEFT, '\0', GRUB_TERM_KEY_RIGHT, '+', GRUB_TERM_KEY_END, - GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_PPAGE, '\0', GRUB_TERM_KEY_DC -}; - -/* Define scan codes. */ -#define GRUB_TERM_AT_KEY_LEFT 0x4B00 -#define GRUB_TERM_AT_KEY_RIGHT 0x4D00 -#define GRUB_TERM_AT_KEY_UP 0x4800 -#define GRUB_TERM_AT_KEY_DOWN 0x5000 -#define GRUB_TERM_AT_KEY_IC 0x5200 -#define GRUB_TERM_AT_KEY_DC 0x5300 -#define GRUB_TERM_AT_KEY_BACKSPACE 0x0008 -#define GRUB_TERM_AT_KEY_HOME 0x4700 -#define GRUB_TERM_AT_KEY_END 0x4F00 -#define GRUB_TERM_AT_KEY_NPAGE 0x5100 -#define GRUB_TERM_AT_KEY_PPAGE 0x4900 +GRUB_AT_KEY_KEYBOARD_MAP (keyboard_map); static int get_abstract_code (grub_term_input_t term, int in) { - unsigned flags = 0; switch (term->flags & GRUB_TERM_INPUT_FLAGS_TYPE_MASK) { case GRUB_TERM_INPUT_FLAGS_TYPE_TERMCODES: @@ -64,32 +38,18 @@ get_abstract_code (grub_term_input_t term, int in) case GRUB_TERM_INPUT_FLAGS_TYPE_BIOS: { unsigned status = 0; - struct { - int from, to; - } translations[] = - { - {GRUB_TERM_AT_KEY_LEFT, GRUB_TERM_KEY_LEFT}, - {GRUB_TERM_AT_KEY_RIGHT, GRUB_TERM_KEY_RIGHT}, - {GRUB_TERM_AT_KEY_UP, GRUB_TERM_KEY_UP}, - {GRUB_TERM_AT_KEY_DOWN, GRUB_TERM_KEY_DOWN}, - {GRUB_TERM_AT_KEY_HOME, GRUB_TERM_KEY_HOME}, - {GRUB_TERM_AT_KEY_END, GRUB_TERM_KEY_END}, - {GRUB_TERM_AT_KEY_DC, GRUB_TERM_KEY_DC}, - {GRUB_TERM_AT_KEY_PPAGE, GRUB_TERM_KEY_PPAGE}, - {GRUB_TERM_AT_KEY_NPAGE, GRUB_TERM_KEY_NPAGE}, - {0x5600 | '\\', GRUB_TERM_KEY_102}, - {0x5600 | '|', GRUB_TERM_KEY_SHIFT_102}, - }; - unsigned i; + unsigned flags = 0; if (term->getkeystatus) - status = term->getkeystatus (); + status = term->getkeystatus (term); if (status & GRUB_TERM_CAPS) flags |= GRUB_TERM_CAPS; - for (i = 0; i < ARRAY_SIZE (translations); i++) - if (translations[i].from == (in & 0xffff)) - return translations[i].to | flags; + if ((0x5600 | '\\') == (in & 0xffff)) + return GRUB_TERM_KEY_102 | flags; + + if ((0x5600 | '|') == (in & 0xffff)) + return GRUB_TERM_KEY_SHIFT_102 | flags; /* Detect CTRL'ed keys. */ if ((in & 0xff) > 0 && (in & 0xff) < 0x20 @@ -105,6 +65,9 @@ get_abstract_code (grub_term_input_t term, int in) && keyboard_map[(in & 0xff00) >> 8] <= 'z') return keyboard_map[(in & 0xff00) >> 8] | flags | GRUB_TERM_ALT_GR; + if ((in & 0xff) == 0) + return keyboard_map[(in & 0xff00) >> 8] | flags; + return (in & 0xff) | flags; } } @@ -165,9 +128,9 @@ grub_getkey_smart (void) { FOR_ACTIVE_TERM_INPUTS(term) { - int key = term->checkkey (); + int key = term->checkkey (term); if (key != -1) - return translate (term, term->getkey ()); + return translate (term, term->getkey (term)); } grub_cpu_idle (); @@ -181,7 +144,7 @@ grub_checkkey (void) FOR_ACTIVE_TERM_INPUTS(term) { - int key = term->checkkey (); + int key = term->checkkey (term); if (key != -1) return translate (term, key); } diff --git a/commands/keystatus.c b/commands/keystatus.c index fc4d11d73..9db92b942 100644 --- a/commands/keystatus.c +++ b/commands/keystatus.c @@ -40,7 +40,7 @@ grub_getkeystatus (void) FOR_ACTIVE_TERM_INPUTS(term) { if (term->getkeystatus) - status |= term->getkeystatus (); + status |= term->getkeystatus (term); } return status; diff --git a/include/grub/at_keyboard.h b/include/grub/at_keyboard.h index 10421540a..3f72fa879 100644 --- a/include/grub/at_keyboard.h +++ b/include/grub/at_keyboard.h @@ -51,4 +51,28 @@ #define OLPC_RIGHT '\0' #endif +#define GRUB_AT_KEY_KEYBOARD_MAP(name) \ +static const int name[128] = \ +{ \ + '\0', GRUB_TERM_ESC, '1', '2', '3', '4', '5', '6', \ + '7', '8', '9', '0', '-', '=', GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, \ + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', \ + 'o', 'p', '[', ']', '\n', '\0', 'a', 's', \ + 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', \ + '\'', '`', '\0', '\\', 'z', 'x', 'c', 'v', \ + 'b', 'n', 'm', ',', '.', '/', '\0', '*', \ + '\0', ' ', '\0', GRUB_TERM_KEY_F1, \ + GRUB_TERM_KEY_F2, GRUB_TERM_KEY_F3, GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5, \ + GRUB_TERM_KEY_F6, GRUB_TERM_KEY_F7, GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9, \ + GRUB_TERM_KEY_F10, '\0', '\0', GRUB_TERM_KEY_HOME, \ + GRUB_TERM_KEY_UP, GRUB_TERM_KEY_NPAGE, '-', GRUB_TERM_KEY_LEFT, \ + '\0', GRUB_TERM_KEY_RIGHT, '+', GRUB_TERM_KEY_END, \ + GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_PPAGE, \ + GRUB_TERM_KEY_INSERT, GRUB_TERM_KEY_DC, \ + '\0', '\0', GRUB_TERM_KEY_102, GRUB_TERM_KEY_F11, \ + GRUB_TERM_KEY_F12, '\0', '\0', '\0', '\0', '\0', '\0', '\0', \ + '\0', '\0', '\0', '\0', '\0', OLPC_UP, OLPC_DOWN, OLPC_LEFT, \ + OLPC_RIGHT \ +} + #endif diff --git a/include/grub/term.h b/include/grub/term.h index 7871c656f..dbafef0e1 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -38,10 +38,23 @@ #define GRUB_TERM_KEY_DC (GRUB_TERM_EXTENDED | 7) #define GRUB_TERM_KEY_PPAGE (GRUB_TERM_EXTENDED | 8) #define GRUB_TERM_KEY_NPAGE (GRUB_TERM_EXTENDED | 9) +#define GRUB_TERM_KEY_F1 (GRUB_TERM_EXTENDED | 10) +#define GRUB_TERM_KEY_F2 (GRUB_TERM_EXTENDED | 11) +#define GRUB_TERM_KEY_F3 (GRUB_TERM_EXTENDED | 12) +#define GRUB_TERM_KEY_F4 (GRUB_TERM_EXTENDED | 13) +#define GRUB_TERM_KEY_F5 (GRUB_TERM_EXTENDED | 14) +#define GRUB_TERM_KEY_F6 (GRUB_TERM_EXTENDED | 15) +#define GRUB_TERM_KEY_F7 (GRUB_TERM_EXTENDED | 16) +#define GRUB_TERM_KEY_F8 (GRUB_TERM_EXTENDED | 17) +#define GRUB_TERM_KEY_F9 (GRUB_TERM_EXTENDED | 18) +#define GRUB_TERM_KEY_F10 (GRUB_TERM_EXTENDED | 19) +#define GRUB_TERM_KEY_F11 (GRUB_TERM_EXTENDED | 20) +#define GRUB_TERM_KEY_F12 (GRUB_TERM_EXTENDED | 21) +#define GRUB_TERM_KEY_INSERT (GRUB_TERM_EXTENDED | 22) /* Used by keylayouts code. Never returned in grub_getkey. */ -#define GRUB_TERM_KEY_102 (GRUB_TERM_EXTENDED | 10) -#define GRUB_TERM_KEY_SHIFT_102 (GRUB_TERM_EXTENDED | 11) +#define GRUB_TERM_KEY_102 (GRUB_TERM_EXTENDED | 23) +#define GRUB_TERM_KEY_SHIFT_102 (GRUB_TERM_EXTENDED | 24) #define GRUB_TERM_ESC '\e' #define GRUB_TERM_TAB '\t' diff --git a/normal/main.c b/normal/main.c index 7582c7f13..6eee57799 100644 --- a/normal/main.c +++ b/normal/main.c @@ -164,7 +164,20 @@ static struct { {"backspace", '\b'}, {"tab", '\t'}, - {"delete", GRUB_TERM_KEY_DC} + {"delete", GRUB_TERM_KEY_DC}, + {"insert", GRUB_TERM_KEY_INSERT}, + {"f1", GRUB_TERM_KEY_F1}, + {"f2", GRUB_TERM_KEY_F2}, + {"f3", GRUB_TERM_KEY_F3}, + {"f4", GRUB_TERM_KEY_F4}, + {"f5", GRUB_TERM_KEY_F5}, + {"f6", GRUB_TERM_KEY_F6}, + {"f7", GRUB_TERM_KEY_F7}, + {"f8", GRUB_TERM_KEY_F8}, + {"f9", GRUB_TERM_KEY_F9}, + {"f10", GRUB_TERM_KEY_F10}, + {"f11", GRUB_TERM_KEY_F11}, + {"f12", GRUB_TERM_KEY_F12}, }; /* Add a menu entry to the current menu context (as given by the environment diff --git a/normal/menu_entry.c b/normal/menu_entry.c index 8e943612a..87292d445 100644 --- a/normal/menu_entry.c +++ b/normal/menu_entry.c @@ -1337,6 +1337,7 @@ grub_menu_entry_run (grub_menu_entry_t entry) break; case GRUB_TERM_CTRL | 'h': + case '\b': if (! backward_delete_char (screen, 1)) goto fail; break; @@ -1375,10 +1376,12 @@ grub_menu_entry_run (grub_menu_entry_t entry) return; case GRUB_TERM_CTRL | 'c': + case GRUB_TERM_KEY_F2: grub_cmdline_run (1); goto refresh; case GRUB_TERM_CTRL | 'x': + case GRUB_TERM_KEY_F10: { int chars_before = grub_normal_get_char_counter (); run (screen); diff --git a/normal/menu_text.c b/normal/menu_text.c index 3e3e7e2fa..fc4a89196 100644 --- a/normal/menu_text.c +++ b/normal/menu_text.c @@ -120,17 +120,10 @@ print_message (int nested, int edit, struct grub_term_output *term) if (edit) { grub_putcode ('\n', term); -#ifdef GRUB_MACHINE_EFI grub_print_message_indented (_("Minimum Emacs-like screen editing is \ -supported. TAB lists completions. Press F1 to boot, F2=Ctrl-a, F3=Ctrl-e, \ -F4 for a command-line or ESC to discard edits and return to the GRUB menu."), - STANDARD_MARGIN, STANDARD_MARGIN, term); -#else - grub_print_message_indented (_("Minimum Emacs-like screen editing is \ -supported. TAB lists completions. Press Ctrl-x to boot, Ctrl-c for a \ +supported. TAB lists completions. Press Ctrl-x or F10 to boot, Ctrl-c or F2 for a \ command-line or ESC to discard edits and return to the GRUB menu."), STANDARD_MARGIN, STANDARD_MARGIN, term); -#endif } else { diff --git a/term/at_keyboard.c b/term/at_keyboard.c index 683981be3..e89f3bf5b 100644 --- a/term/at_keyboard.c +++ b/term/at_keyboard.c @@ -41,24 +41,7 @@ static grub_uint8_t led_status; #define KEYBOARD_LED_NUM (1 << 1) #define KEYBOARD_LED_CAPS (1 << 2) -static int keyboard_map[128] = -{ - '\0', GRUB_TERM_ESC, '1', '2', '3', '4', '5', '6', - '7', '8', '9', '0', '-', '=', GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, - 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', - 'o', 'p', '[', ']', '\n', '\0', 'a', 's', - 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', - '\'', '`', '\0', '\\', 'z', 'x', 'c', 'v', - 'b', 'n', 'm', ',', '.', '/', '\0', '*', - '\0', ' ', '\0', '\0', '\0', '\0', '\0', '\0', - '\0', '\0', '\0', '\0', '\0', '\0', '\0', GRUB_TERM_KEY_HOME, - GRUB_TERM_KEY_UP, GRUB_TERM_KEY_NPAGE, '-', GRUB_TERM_KEY_LEFT, '\0', GRUB_TERM_KEY_RIGHT, '+', GRUB_TERM_KEY_END, - GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_PPAGE, '\0', GRUB_TERM_KEY_DC, '\0', '\0', - GRUB_TERM_KEY_102, '\0', - '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', - '\0', '\0', '\0', '\0', '\0', OLPC_UP, OLPC_DOWN, OLPC_LEFT, - OLPC_RIGHT -}; +GRUB_AT_KEY_KEYBOARD_MAP (keyboard_map); static int keyboard_map_shift[128] = { diff --git a/term/efi/console.c b/term/efi/console.c index dca002910..f47263ee4 100644 --- a/term/efi/console.c +++ b/term/efi/console.c @@ -100,6 +100,17 @@ grub_console_putchar (struct grub_term_output *term __attribute__ ((unused)), efi_call_2 (o->output_string, o, str); } +const unsigned efi_codes[] = + { + 0, GRUB_TERM_UP, GRUB_TERM_DOWN, GRUB_TERM_RIGHT, + GRUB_TERM_LEFT, GRUB_TERM_HOME, GRUB_TERM_END, GRUB_TERM_KEY_INSERT, + GRUB_TERM_DC, GRUB_TERM_KEY_PPAGE, GRUB_TERM_KEY_NPAGE, GRUB_TERM_KEY_F1, + GRUB_TERM_KEY_F2, GRUB_TERM_KEY_F3, GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5, + GRUB_TERM_KEY_F6, GRUB_TERM_KEY_F7, GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9, + GRUB_TERM_KEY_F10, 0, 0, '\e' + }; + + static int grub_console_checkkey (struct grub_term_input *term __attribute__ ((unused))) { @@ -112,85 +123,14 @@ grub_console_checkkey (struct grub_term_input *term __attribute__ ((unused))) i = grub_efi_system_table->con_in; status = efi_call_2 (i->read_key_stroke, i, &key); -#if 0 - switch (status) - { - case GRUB_EFI_SUCCESS: - { - grub_uint16_t xy; - xy = grub_getxy (); - grub_gotoxy (0, 0); - grub_printf ("scan_code=%x,unicode_char=%x ", - (unsigned) key.scan_code, - (unsigned) key.unicode_char); - grub_gotoxy (xy >> 8, xy & 0xff); - } - break; + if (status != GRUB_EFI_SUCCESS) + return -1; - case GRUB_EFI_NOT_READY: - //grub_printf ("not ready "); - break; - - default: - //grub_printf ("device error "); - break; - } -#endif - - if (status == GRUB_EFI_SUCCESS) - { - switch (key.scan_code) - { - case 0x00: - read_key = key.unicode_char; - break; - case 0x01: - read_key = GRUB_TERM_UP; - break; - case 0x02: - read_key = GRUB_TERM_DOWN; - break; - case 0x03: - read_key = GRUB_TERM_RIGHT; - break; - case 0x04: - read_key = GRUB_TERM_LEFT; - break; - case 0x05: - read_key = GRUB_TERM_HOME; - break; - case 0x06: - read_key = GRUB_TERM_END; - break; - case 0x07: - break; - case 0x08: - read_key = GRUB_TERM_DC; - break; - case 0x09: - break; - case 0x0a: - break; - case 0x0b: - read_key = 24; - break; - case 0x0c: - read_key = 1; - break; - case 0x0d: - read_key = 5; - break; - case 0x0e: - read_key = 3; - break; - case 0x17: - read_key = '\e'; - break; - default: - break; - } - } + if (key.scan_code == 0) + read_key = key.unicode_char; + else if (key.scan_code < ARRAY_SIZE (efi_codes)) + read_key = efi_codes[key.scan_code]; return read_key; } diff --git a/term/terminfo.c b/term/terminfo.c index ff54e5dba..9030c2580 100644 --- a/term/terminfo.c +++ b/term/terminfo.c @@ -402,34 +402,34 @@ grub_terminfo_readkey (int *keys, int *len, int (*readkey) (void)) static struct { char key; - char ascii; + unsigned ascii; } three_code_table[] = { - {'4', GRUB_TERM_DC}, - {'A', GRUB_TERM_UP}, - {'B', GRUB_TERM_DOWN}, - {'C', GRUB_TERM_RIGHT}, - {'D', GRUB_TERM_LEFT}, - {'F', GRUB_TERM_END}, - {'H', GRUB_TERM_HOME}, - {'K', GRUB_TERM_END}, - {'P', GRUB_TERM_DC}, - {'?', GRUB_TERM_PPAGE}, - {'/', GRUB_TERM_NPAGE} + {'4', GRUB_TERM_KEY_DC}, + {'A', GRUB_TERM_KEY_UP}, + {'B', GRUB_TERM_KEY_DOWN}, + {'C', GRUB_TERM_KEY_RIGHT}, + {'D', GRUB_TERM_KEY_LEFT}, + {'F', GRUB_TERM_KEY_END}, + {'H', GRUB_TERM_KEY_HOME}, + {'K', GRUB_TERM_KEY_END}, + {'P', GRUB_TERM_KEY_DC}, + {'?', GRUB_TERM_KEY_PPAGE}, + {'/', GRUB_TERM_KEY_NPAGE} }; static struct { char key; - char ascii; + unsigned ascii; } four_code_table[] = { - {'1', GRUB_TERM_HOME}, - {'3', GRUB_TERM_DC}, - {'5', GRUB_TERM_PPAGE}, - {'6', GRUB_TERM_NPAGE} + {'1', GRUB_TERM_KEY_HOME}, + {'3', GRUB_TERM_KEY_DC}, + {'5', GRUB_TERM_KEY_PPAGE}, + {'6', GRUB_TERM_KEY_NPAGE} }; unsigned i; diff --git a/term/usb_keyboard.c b/term/usb_keyboard.c index ba67e2b85..e18f205e8 100644 --- a/term/usb_keyboard.c +++ b/term/usb_keyboard.c @@ -27,7 +27,7 @@ #include -static int keyboard_map[128] = +static unsigned keyboard_map[128] = { '\0', '\0', '\0', '\0', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', @@ -36,13 +36,17 @@ static int keyboard_map[128] = '3', '4', '5', '6', '7', '8', '9', '0', '\n', GRUB_TERM_ESC, GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, ' ', '-', '=', '[', ']', '\\', '#', ';', '\'', '`', ',', '.', - '/', '\0', '\0', '\0', '\0', '\0', '\0', '\0', - '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', - '\0', '\0', GRUB_TERM_KEY_HOME, GRUB_TERM_KEY_PPAGE, GRUB_TERM_KEY_DC, GRUB_TERM_KEY_END, GRUB_TERM_KEY_NPAGE, GRUB_TERM_KEY_RIGHT, - GRUB_TERM_KEY_LEFT, GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_UP + '/', '\0', GRUB_TERM_KEY_F1, GRUB_TERM_KEY_F2, + GRUB_TERM_KEY_F3, GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5, GRUB_TERM_KEY_F6, + GRUB_TERM_KEY_F7, GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9, GRUB_TERM_KEY_F10, + GRUB_TERM_KEY_F11, GRUB_TERM_KEY_F12, '\0', '\0', + '\0', GRUB_TERM_KEY_INSERT, GRUB_TERM_KEY_HOME, GRUB_TERM_KEY_PPAGE, + GRUB_TERM_KEY_DC, GRUB_TERM_KEY_END, GRUB_TERM_KEY_NPAGE, GRUB_TERM_KEY_RIGHT, + GRUB_TERM_KEY_LEFT, GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_UP, + [0x64] = GRUB_TERM_KEY_102 }; -static char keyboard_map_shift[128] = +static unsigned keyboard_map_shift[128] = { '\0', '\0', '\0', '\0', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', @@ -51,7 +55,8 @@ static char keyboard_map_shift[128] = '#', '$', '%', '^', '&', '*', '(', ')', '\n', '\0', '\0', '\0', ' ', '_', '+', '{', '}', '|', '#', ':', '"', '`', '<', '>', - '?' + '?', + [0x64] = GRUB_TERM_KEY_SHIFT_102 }; static grub_usb_device_t usbdev; @@ -157,8 +162,9 @@ grub_usb_keyboard_checkkey (struct grub_term_input *term __attribute__ ((unused) #define GRUB_USB_KEYBOARD_RIGHT_ALT 0x40 /* Check if the Shift key was pressed. */ - if (data[0] & GRUB_USB_KEYBOARD_LEFT_SHIFT - || data[0] & GRUB_USB_KEYBOARD_RIGHT_SHIFT) + if ((data[0] & GRUB_USB_KEYBOARD_LEFT_SHIFT + || data[0] & GRUB_USB_KEYBOARD_RIGHT_SHIFT) + && keyboard_map_shift[data[2]]) key = keyboard_map_shift[data[2]]; else key = keyboard_map[data[2]]; From b6f7b4ba03559d7340a811bfe03a1a47b49f8dc6 Mon Sep 17 00:00:00 2001 From: Carles Pina i Estany Date: Thu, 19 Aug 2010 02:15:29 +0200 Subject: [PATCH 015/214] Reimported heavily modified version of cpina's grub-mklayout --- ChangeLog.keyboard_layouts | 7 + conf/common.rmk | 4 + include/grub/at_keyboard.h | 15 +- include/grub/keyboard_layouts.h | 28 ++++ include/grub/term.h | 4 +- term/at_keyboard.c | 13 +- util/grub-mklayouts.c | 279 ++++++++++++++++++++++++++++++++ 7 files changed, 335 insertions(+), 15 deletions(-) create mode 100644 ChangeLog.keyboard_layouts create mode 100644 include/grub/keyboard_layouts.h create mode 100644 util/grub-mklayouts.c diff --git a/ChangeLog.keyboard_layouts b/ChangeLog.keyboard_layouts new file mode 100644 index 000000000..65af097ff --- /dev/null +++ b/ChangeLog.keyboard_layouts @@ -0,0 +1,7 @@ +2010-01-18 Carles Pina i Estany + + Adds keyboard layouts support. + + * conf/common.rmk (bin_UTILITIES): Add grub-mklayouts rules. + * include/grub/keyboard_layouts.h: New file. + * util/grub-mklayouts.c: New file. diff --git a/conf/common.rmk b/conf/common.rmk index ee6b94032..745b1837e 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -80,6 +80,10 @@ endif bin_UTILITIES += grub-mkrelpath grub_mkrelpath_SOURCES = gnulib/progname.c util/grub-mkrelpath.c util/misc.c kern/emu/misc.c +# For grub-mklayouts. +bin_UTILITIES += grub-mklayouts +grub_mklayouts_SOURCES = gnulib/progname.c util/grub-mklayouts.c util/misc.c kern/emu/misc.c + bin_UTILITIES += grub-bin2h grub_bin2h_SOURCES = gnulib/progname.c util/bin2h.c diff --git a/include/grub/at_keyboard.h b/include/grub/at_keyboard.h index 3f72fa879..8bb090d2a 100644 --- a/include/grub/at_keyboard.h +++ b/include/grub/at_keyboard.h @@ -52,7 +52,7 @@ #endif #define GRUB_AT_KEY_KEYBOARD_MAP(name) \ -static const int name[128] = \ +static const unsigned name[128] = \ { \ '\0', GRUB_TERM_ESC, '1', '2', '3', '4', '5', '6', \ '7', '8', '9', '0', '-', '=', GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, \ @@ -75,4 +75,17 @@ static const int name[128] = \ OLPC_RIGHT \ } +#define GRUB_AT_KEY_KEYBOARD_MAP_SHIFT(name) \ +static unsigned name[128] = \ +{ \ + '\0', '\0', '!', '@', '#', '$', '%', '^', \ + '&', '*', '(', ')', '_', '+', '\0', '\0', \ + 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', \ + 'O', 'P', '{', '}', '\n', '\0', 'A', 'S', \ + 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', \ + '\"', '~', '\0', '|', 'Z', 'X', 'C', 'V', \ + 'B', 'N', 'M', '<', '>', '?', \ + [0x56] = GRUB_TERM_KEY_SHIFT_102 \ +} + #endif diff --git a/include/grub/keyboard_layouts.h b/include/grub/keyboard_layouts.h new file mode 100644 index 000000000..1d263e268 --- /dev/null +++ b/include/grub/keyboard_layouts.h @@ -0,0 +1,28 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_KEYBOARD_LAYOUTS_H +#define GRUB_KEYBOARD_LAYOUTS_H 1 + +#define GRUB_KEYBOARD_LAYOUTS_FILEMAGIC "GRUBLAYO" +#define GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE (sizeof(GRUB_KEYBOARD_LAYOUTS_FILEMAGIC) - 1) +#define GRUB_KEYBOARD_LAYOUTS_VERSION 2 + +#define GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE 256 + +#endif /* GRUB_KEYBOARD_LAYOUTS */ diff --git a/include/grub/term.h b/include/grub/term.h index dbafef0e1..fa813d1b5 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -53,8 +53,8 @@ #define GRUB_TERM_KEY_INSERT (GRUB_TERM_EXTENDED | 22) /* Used by keylayouts code. Never returned in grub_getkey. */ -#define GRUB_TERM_KEY_102 (GRUB_TERM_EXTENDED | 23) -#define GRUB_TERM_KEY_SHIFT_102 (GRUB_TERM_EXTENDED | 24) +#define GRUB_TERM_KEY_102 0x80 +#define GRUB_TERM_KEY_SHIFT_102 0x81 #define GRUB_TERM_ESC '\e' #define GRUB_TERM_TAB '\t' diff --git a/term/at_keyboard.c b/term/at_keyboard.c index e89f3bf5b..4c9c2a23a 100644 --- a/term/at_keyboard.c +++ b/term/at_keyboard.c @@ -42,18 +42,7 @@ static grub_uint8_t led_status; #define KEYBOARD_LED_CAPS (1 << 2) GRUB_AT_KEY_KEYBOARD_MAP (keyboard_map); - -static int keyboard_map_shift[128] = -{ - '\0', '\0', '!', '@', '#', '$', '%', '^', - '&', '*', '(', ')', '_', '+', '\0', '\0', - 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', - 'O', 'P', '{', '}', '\n', '\0', 'A', 'S', - 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', - '\"', '~', '\0', '|', 'Z', 'X', 'C', 'V', - 'B', 'N', 'M', '<', '>', '?', - [0x56] = GRUB_TERM_KEY_SHIFT_102 -}; +GRUB_AT_KEY_KEYBOARD_MAP_SHIFT (keyboard_map_shift); static grub_uint8_t grub_keyboard_controller_orig; diff --git a/util/grub-mklayouts.c b/util/grub-mklayouts.c new file mode 100644 index 000000000..48b17e798 --- /dev/null +++ b/util/grub-mklayouts.c @@ -0,0 +1,279 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "progname.h" + +#define CKBCOMP "ckbcomp" + +static struct option options[] = { + {"output", required_argument, 0, 'o'}, + {"help", no_argument, 0, 'h'}, + {"version", no_argument, 0, 'V'}, + {"verbose", no_argument, 0, 'v'}, + {0, 0, 0, 0} +}; + +struct console_grub_equivalence +{ + char *layout; + grub_uint32_t grub; +}; + +static struct console_grub_equivalence console_grub_equivalences[] = { + {"KP_1", '1'}, + {"KP_2", '2'}, + {"KP_3", '3'}, + {"KP_4", '4'}, + {"KP_5", '5'}, + {"KP_6", '6'}, + {"KP_7", '7'}, + {"KP_8", '8'}, + {"KP_9", '9'}, + + {"KP_Multiply", '*'}, + {"KP_Substract", '-'}, + {"KP_Add", '+'}, + {"KP_Divide", '/'}, + + {"KP_Enter", '\n'}, + {"Return", '\n'}, + {"", '\0'} +}; + +GRUB_AT_KEY_KEYBOARD_MAP (us_keyboard_map); +GRUB_AT_KEY_KEYBOARD_MAP_SHIFT (us_keyboard_map_shifted); + +static void +usage (int status) +{ + if (status) + fprintf (stderr, "Try `%s --help' for more information.\n", program_name); + else + printf ("\ +Usage: %s [OPTIONS] LAYOUT\n\ + -o, --output set output base name file. Default is LAYOUT.gkb\n\ + -h, --help display this message and exit.\n\ + -V, --version print version information and exit.\n\ + -v, --verbose print verbose messages.\n\ +\n\ +Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT); + + exit (status); +} + +char +lookup (char *code) +{ + int i; + + for (i = 0; console_grub_equivalences[i].grub != '\0'; i++) + if (strcmp (code, console_grub_equivalences[i].layout) == 0) + return console_grub_equivalences[i].grub; + + return '\0'; +} + +unsigned int +get_grub_code (char *layout_code) +{ + unsigned int code; + + if (strncmp (layout_code, "U+", sizeof ("U+") - 1) == 0) + sscanf (layout_code, "U+%x", &code); + else if (strncmp (layout_code, "+U+", sizeof ("+U+") - 1) == 0) + sscanf (layout_code, "+U+%x", &code); + else + code = lookup (layout_code); + return code; +} + +void +write_file (char* filename, grub_uint32_t *keyboard_map) +{ + FILE *fp_output; + grub_uint32_t version; + unsigned i; + + version = grub_cpu_to_le32 (GRUB_KEYBOARD_LAYOUTS_VERSION); + + for (i = 0; i < GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE; i++) + keyboard_map[i] = grub_cpu_to_le32 (keyboard_map[i]); + + fp_output = fopen (filename, "w"); + + if (!fp_output) + { + grub_util_error ("cannot open `%s'", filename); + exit (1); + } + + fwrite (GRUB_KEYBOARD_LAYOUTS_FILEMAGIC, 1, + GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE, fp_output); + fwrite (&version, sizeof (version), 1, fp_output); + fwrite (keyboard_map, sizeof (keyboard_map[0]), + GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE, fp_output); + fclose (fp_output); +} + +void +write_keymaps (char *keymap, char *file_basename) +{ + grub_uint32_t keyboard_map[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; + + char line[2048]; + pid_t pid; + int pipe_communication[2]; + int ok; + + FILE *fp_pipe; + + if (pipe (pipe_communication) == -1) + { + grub_util_error ("cannot prepare the pipe"); + exit (2); + } + + pid = fork (); + if (pid < 0) + { + grub_util_error ("cannot fork"); + exit (2); + } + else if (pid == 0) + { + close (1); + dup (pipe_communication[1]); + close (pipe_communication[0]); + execlp (CKBCOMP, CKBCOMP, keymap, NULL); + grub_util_error ("%s %s cannot be executed", CKBCOMP, keymap); + exit (3); + } + close (pipe_communication[1]); + fp_pipe = fdopen (pipe_communication[0], "r"); + + memset (keyboard_map, 0, sizeof (keyboard_map)); + + /* Process the ckbcomp output and prepare the layouts. */ + ok = 0; + while (fgets (line, sizeof (line), fp_pipe)) + { + if (strncmp (line, "keycode", sizeof ("keycode") - 1) == 0) + { + unsigned keycode; + char normal[64]; + char shift[64]; + sscanf (line, "keycode %u = %60s %60s", &keycode, normal, shift); + if (keycode < ARRAY_SIZE (us_keyboard_map) + && us_keyboard_map[keycode] < ARRAY_SIZE (keyboard_map)) + { + keyboard_map[us_keyboard_map[keycode]] = get_grub_code (normal); + ok = 1; + } + if (keycode < ARRAY_SIZE (us_keyboard_map_shifted) + && us_keyboard_map_shifted[keycode] < ARRAY_SIZE (keyboard_map)) + { + keyboard_map[us_keyboard_map_shifted[keycode]] + = get_grub_code (shift); + ok = 1; + } + } + } + + if (ok == 0) + { + fprintf (stderr, "ERROR: no keycodes found. Check output of %s %s.\n", + CKBCOMP, keymap); + exit (1); + } + + write_file (file_basename, keyboard_map); +} + +int +main (int argc, char *argv[]) +{ + int verbosity; + char *file_basename = NULL; + + set_program_name (argv[0]); + + verbosity = 0; + + /* Check for options. */ + while (1) + { + int c = getopt_long (argc, argv, "o:hVv", options, 0); + + if (c == -1) + break; + else + switch (c) + { + case 'h': + usage (0); + break; + + case 'o': + file_basename = optarg; + break; + + case 'V': + printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, + PACKAGE_VERSION); + return 0; + + case 'v': + verbosity++; + break; + + default: + usage (1); + break; + } + } + + /* Obtain LAYOUT. */ + if (optind >= argc) + { + fprintf (stderr, "No layout is specified.\n"); + usage (1); + } + + if (file_basename == NULL) + { + file_basename = xasprintf ("%s.gkb", argv[optind]); + write_keymaps (argv[optind], file_basename); + free (file_basename); + } + else + write_keymaps (argv[optind], file_basename); + + return 0; +} From 211144767584a29193a70172b134ee2f4ea0e6c9 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 19 Aug 2010 02:21:36 +0200 Subject: [PATCH 016/214] Add new flag SHIFT --- include/grub/term.h | 6 ++++-- term/at_keyboard.c | 12 ++++++++---- term/usb_keyboard.c | 10 +++++++--- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/include/grub/term.h b/include/grub/term.h index fa813d1b5..1f64bebc7 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -20,6 +20,8 @@ #define GRUB_TERM_HEADER 1 /* Internal codes used by GRUB to represent terminal input. */ +/* Only for keys otherwise not having shifted modification. */ +#define GRUB_TERM_SHIFT 0x01000000 #define GRUB_TERM_CTRL 0x02000000 #define GRUB_TERM_ALT 0x04000000 /* Used by keylayouts code. Never returned in grub_getkey. */ @@ -27,8 +29,8 @@ #define GRUB_TERM_CAPS 0x10000000 /* Keys without associated character. */ -#define GRUB_TERM_EXTENDED 0x1000000 -#define GRUB_TERM_KEY_MASK 0x1ffffff +#define GRUB_TERM_EXTENDED 0x00800000 +#define GRUB_TERM_KEY_MASK 0x00ffffff #define GRUB_TERM_KEY_LEFT (GRUB_TERM_EXTENDED | 1) #define GRUB_TERM_KEY_RIGHT (GRUB_TERM_EXTENDED | 2) #define GRUB_TERM_KEY_UP (GRUB_TERM_EXTENDED | 3) diff --git a/term/at_keyboard.c b/term/at_keyboard.c index 4c9c2a23a..cc0c69e22 100644 --- a/term/at_keyboard.c +++ b/term/at_keyboard.c @@ -187,10 +187,14 @@ grub_at_keyboard_getkey_noblock (void) key = -1; break; default: - if ((at_keyboard_status & (KEYBOARD_STATUS_SHIFT_L - | KEYBOARD_STATUS_SHIFT_R)) - && keyboard_map_shift[code]) - key = keyboard_map_shift[code]; + if (at_keyboard_status & (KEYBOARD_STATUS_SHIFT_L + | KEYBOARD_STATUS_SHIFT_R)) + { + if (keyboard_map_shift[code]) + key = keyboard_map_shift[code]; + else + key = keyboard_map[code] | GRUB_TERM_SHIFT; + } else key = keyboard_map[code]; diff --git a/term/usb_keyboard.c b/term/usb_keyboard.c index e18f205e8..9e1ce5e60 100644 --- a/term/usb_keyboard.c +++ b/term/usb_keyboard.c @@ -162,10 +162,14 @@ grub_usb_keyboard_checkkey (struct grub_term_input *term __attribute__ ((unused) #define GRUB_USB_KEYBOARD_RIGHT_ALT 0x40 /* Check if the Shift key was pressed. */ - if ((data[0] & GRUB_USB_KEYBOARD_LEFT_SHIFT + if (data[0] & GRUB_USB_KEYBOARD_LEFT_SHIFT || data[0] & GRUB_USB_KEYBOARD_RIGHT_SHIFT) - && keyboard_map_shift[data[2]]) - key = keyboard_map_shift[data[2]]; + { + if (keyboard_map_shift[data[2]]) + key = keyboard_map_shift[data[2]]; + else + key = keyboard_map[data[2]] | GRUB_TERM_SHIFT; + } else key = keyboard_map[data[2]]; From d90aa78482dfa4eebcf226484a386c0c6c3581a6 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 19 Aug 2010 02:57:05 +0200 Subject: [PATCH 017/214] KEyboard layout support --- commands/keylayouts.c | 112 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 103 insertions(+), 9 deletions(-) diff --git a/commands/keylayouts.c b/commands/keylayouts.c index 58baabe67..05595f8d1 100644 --- a/commands/keylayouts.c +++ b/commands/keylayouts.c @@ -24,6 +24,10 @@ #include #include #include +#include +#include +#include +#include GRUB_AT_KEY_KEYBOARD_MAP (keyboard_map); @@ -73,20 +77,21 @@ get_abstract_code (grub_term_input_t term, int in) } } +static grub_uint32_t mapping[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; + static int -map (grub_term_input_t term, int in) +map (grub_term_input_t term __attribute__ ((unused)), int in) { - /* No match with AltGr. Interpret it as Alt rather than as L3 modifier then. - */ + /* AltGr isn't supported yet. */ if (in & GRUB_TERM_ALT_GR) - return map (term, in & ~GRUB_TERM_ALT_GR) | GRUB_TERM_ALT_GR; + in = (in & ~GRUB_TERM_ALT_GR) | GRUB_TERM_ALT_GR; - if (in == GRUB_TERM_KEY_102) - return '\\'; - if (in == GRUB_TERM_KEY_SHIFT_102) - return '|'; + if ((in & GRUB_TERM_EXTENDED) || (in & GRUB_TERM_KEY_MASK) == '\b' + || (in & GRUB_TERM_KEY_MASK) == '\t' || (in & GRUB_TERM_KEY_MASK) == '\e' + || (in & GRUB_TERM_KEY_MASK) >= ARRAY_SIZE (mapping)) + return in; - return in; + return mapping[in & GRUB_TERM_KEY_MASK] | (in & ~GRUB_TERM_KEY_MASK); } static int @@ -152,15 +157,104 @@ grub_checkkey (void) return -1; } +static grub_err_t +grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + char *filename; + grub_file_t file; + grub_uint32_t version; + grub_uint8_t magic[GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE]; + grub_uint32_t newmapping[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; + unsigned i; + + if (argc < 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "file or layout name required"); + if (argv[0][0] != '(' && argv[0][0] != '/' && argv[0][0] != '+') + { + const char *prefix = grub_env_get ("prefix"); + if (!prefix) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "No prefix set"); + filename = grub_xasprintf ("%s/layouts/%s.gkb", prefix, argv[0]); + if (!filename) + return grub_errno; + } + else + filename = argv[0]; + + file = grub_gzfile_open (filename, 1); + if (! file) + goto fail; + + if (grub_file_read (file, magic, sizeof (magic)) != sizeof (magic)) + { + if (!grub_errno) + grub_error (GRUB_ERR_BAD_ARGUMENT, "file is too short"); + goto fail; + } + + if (grub_memcmp (magic, GRUB_KEYBOARD_LAYOUTS_FILEMAGIC, + GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE) != 0) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid magic"); + goto fail; + } + + if (grub_file_read (file, &version, sizeof (version)) != sizeof (version)) + { + if (!grub_errno) + grub_error (GRUB_ERR_BAD_ARGUMENT, "file is too short"); + goto fail; + } + + if (grub_le_to_cpu32 (version) != GRUB_KEYBOARD_LAYOUTS_VERSION) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid version"); + goto fail; + } + + if (grub_file_read (file, newmapping, sizeof (newmapping)) + != sizeof (newmapping)) + { + if (!grub_errno) + grub_error (GRUB_ERR_BAD_ARGUMENT, "file is too short"); + goto fail; + } + + for (i = 0; i < ARRAY_SIZE (mapping); i++) + mapping[i] = grub_le_to_cpu32(newmapping[i]); + + return GRUB_ERR_NONE; + + fail: + if (filename != argv[0]) + grub_free (filename); + if (file) + grub_file_close (file); + return grub_errno; +} + static int (*grub_getkey_saved) (void); +static grub_command_t cmd; + GRUB_MOD_INIT(keylayouts) { + unsigned i; + for (i = 0; i < ARRAY_SIZE (mapping); i++) + mapping[i] = i; + mapping[GRUB_TERM_KEY_102] = '\\'; + mapping[GRUB_TERM_KEY_SHIFT_102] = '|'; + grub_getkey_saved = grub_getkey; grub_getkey = grub_getkey_smart; + + cmd = grub_register_command ("keymap", grub_cmd_keymap, + 0, N_("Load a keyboard layout.")); } GRUB_MOD_FINI(keylayouts) { grub_getkey = grub_getkey_saved; + grub_unregister_command (cmd); } From 7ea82054f562055adb3d5c44ca402ec894cd89d4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 19 Aug 2010 04:13:32 +0200 Subject: [PATCH 018/214] Solve keypad-related issues --- commands/keylayouts.c | 44 ++++++++++++++++++++++-------- include/grub/at_keyboard.h | 56 +++++++++++++++++++++++--------------- include/grub/term.h | 6 ++-- 3 files changed, 70 insertions(+), 36 deletions(-) diff --git a/commands/keylayouts.c b/commands/keylayouts.c index 05595f8d1..419cdf45a 100644 --- a/commands/keylayouts.c +++ b/commands/keylayouts.c @@ -55,6 +55,11 @@ get_abstract_code (grub_term_input_t term, int in) if ((0x5600 | '|') == (in & 0xffff)) return GRUB_TERM_KEY_SHIFT_102 | flags; + if ((in & 0xff00) == 0x3500 || (in & 0xff00) == 0x3700 + || (in & 0xff00) == 0x4500 + || ((in & 0xff00) >= 0x4700 && (in & 0xff00) <= 0x5300)) + flags |= GRUB_TERM_KEYPAD; + /* Detect CTRL'ed keys. */ if ((in & 0xff) > 0 && (in & 0xff) < 0x20 && ((in & 0xffff) != (0x0100 | '\e')) @@ -79,19 +84,33 @@ get_abstract_code (grub_term_input_t term, int in) static grub_uint32_t mapping[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; -static int -map (grub_term_input_t term __attribute__ ((unused)), int in) +static unsigned +clear_internal_flags (unsigned in) { + if (in & GRUB_TERM_ALT_GR) + in = (in & ~GRUB_TERM_ALT_GR) | GRUB_TERM_ALT; + return in & ~GRUB_TERM_CAPS & ~GRUB_TERM_KEYPAD; +} + +static unsigned +map (grub_term_input_t term __attribute__ ((unused)), unsigned in) +{ + if (in & GRUB_TERM_KEYPAD) + return clear_internal_flags (in); + /* AltGr isn't supported yet. */ if (in & GRUB_TERM_ALT_GR) - in = (in & ~GRUB_TERM_ALT_GR) | GRUB_TERM_ALT_GR; + in = (in & ~GRUB_TERM_ALT_GR) | GRUB_TERM_ALT; if ((in & GRUB_TERM_EXTENDED) || (in & GRUB_TERM_KEY_MASK) == '\b' + || (in & GRUB_TERM_KEY_MASK) == '\n' || (in & GRUB_TERM_KEY_MASK) == ' ' || (in & GRUB_TERM_KEY_MASK) == '\t' || (in & GRUB_TERM_KEY_MASK) == '\e' + || (in & GRUB_TERM_KEY_MASK) == '\r' || (in & GRUB_TERM_KEY_MASK) >= ARRAY_SIZE (mapping)) - return in; + return clear_internal_flags (in); - return mapping[in & GRUB_TERM_KEY_MASK] | (in & ~GRUB_TERM_KEY_MASK); + return mapping[in & GRUB_TERM_KEY_MASK] + | clear_internal_flags (in & ~GRUB_TERM_KEY_MASK); } static int @@ -99,14 +118,15 @@ translate (grub_term_input_t term, int in) { int code, flags; code = get_abstract_code (term, in); - if ((code & GRUB_TERM_CAPS) && (code & 0xff) >= 'a' && (code & 0xff) <= 'z') - code = (code & 0xff) + 'A' - 'a'; - else if ((code & GRUB_TERM_CAPS) && (code & 0xff) >= 'A' - && (code & 0xff) <= 'Z') - code = (code & 0xff) + 'a' - 'A'; + if ((code & GRUB_TERM_CAPS) && (code & GRUB_TERM_KEY_MASK) >= 'a' + && (code & GRUB_TERM_KEY_MASK) <= 'z') + code = (code & GRUB_TERM_KEY_MASK) + 'A' - 'a'; + else if ((code & GRUB_TERM_CAPS) && (code & GRUB_TERM_KEY_MASK) >= 'A' + && (code & GRUB_TERM_KEY_MASK) <= 'Z') + code = (code & GRUB_TERM_KEY_MASK) + 'a' - 'A'; - flags = code & ~(GRUB_TERM_KEY_MASK | GRUB_TERM_ALT_GR); - code &= (GRUB_TERM_KEY_MASK | GRUB_TERM_ALT_GR); + flags = code & ~(GRUB_TERM_KEY_MASK | GRUB_TERM_ALT_GR | GRUB_TERM_KEYPAD); + code &= (GRUB_TERM_KEY_MASK | GRUB_TERM_ALT_GR | GRUB_TERM_KEYPAD); code = map (term, code); /* Transform unconsumed AltGr into Alt. */ if (code & GRUB_TERM_ALT_GR) diff --git a/include/grub/at_keyboard.h b/include/grub/at_keyboard.h index 8bb090d2a..e8289d672 100644 --- a/include/grub/at_keyboard.h +++ b/include/grub/at_keyboard.h @@ -51,28 +51,40 @@ #define OLPC_RIGHT '\0' #endif -#define GRUB_AT_KEY_KEYBOARD_MAP(name) \ -static const unsigned name[128] = \ -{ \ - '\0', GRUB_TERM_ESC, '1', '2', '3', '4', '5', '6', \ - '7', '8', '9', '0', '-', '=', GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, \ - 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', \ - 'o', 'p', '[', ']', '\n', '\0', 'a', 's', \ - 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', \ - '\'', '`', '\0', '\\', 'z', 'x', 'c', 'v', \ - 'b', 'n', 'm', ',', '.', '/', '\0', '*', \ - '\0', ' ', '\0', GRUB_TERM_KEY_F1, \ - GRUB_TERM_KEY_F2, GRUB_TERM_KEY_F3, GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5, \ - GRUB_TERM_KEY_F6, GRUB_TERM_KEY_F7, GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9, \ - GRUB_TERM_KEY_F10, '\0', '\0', GRUB_TERM_KEY_HOME, \ - GRUB_TERM_KEY_UP, GRUB_TERM_KEY_NPAGE, '-', GRUB_TERM_KEY_LEFT, \ - '\0', GRUB_TERM_KEY_RIGHT, '+', GRUB_TERM_KEY_END, \ - GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_PPAGE, \ - GRUB_TERM_KEY_INSERT, GRUB_TERM_KEY_DC, \ - '\0', '\0', GRUB_TERM_KEY_102, GRUB_TERM_KEY_F11, \ - GRUB_TERM_KEY_F12, '\0', '\0', '\0', '\0', '\0', '\0', '\0', \ - '\0', '\0', '\0', '\0', '\0', OLPC_UP, OLPC_DOWN, OLPC_LEFT, \ - OLPC_RIGHT \ +#define GRUB_AT_KEY_KEYBOARD_MAP(name) \ +static const unsigned name[128] = \ +{ \ + /* 0x00 */ '\0', GRUB_TERM_ESC, '1', '2', '3', '4', '5', '6', \ + /* 0x08 */ '7', '8', '9', '0', \ + /* 0x0c */ '-', '=', GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, \ + /* 0x10 */ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', \ + /* 0x18 */ 'o', 'p', '[', ']', '\n', '\0', 'a', 's', \ + /* 0x20 */ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', \ + /* 0x28 */ '\'', '`', '\0', '\\', 'z', 'x', 'c', 'v', \ + /* 0x30 */ 'b', 'n', 'm', ',', '.', '/', '\0', '*' | GRUB_TERM_KEYPAD, \ + /* 0x38 */ '\0', ' ', '\0', GRUB_TERM_KEY_F1, \ + /* 0x3c */ GRUB_TERM_KEY_F2, GRUB_TERM_KEY_F3, \ + /* 0x3e */ GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5, \ + /* 0x40 */ GRUB_TERM_KEY_F6, GRUB_TERM_KEY_F7, \ + /* 0x42 */ GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9, \ + /* 0x44 */ GRUB_TERM_KEY_F10, '\0', \ + /* 0x46 */ '\0', GRUB_TERM_KEY_HOME, \ + /* 0x48 */ GRUB_TERM_KEY_UP, \ + /* 0x49 */ GRUB_TERM_KEY_NPAGE, \ + /* 0x4a */ '-' | GRUB_TERM_KEYPAD, \ + /* 0x4b */ GRUB_TERM_KEY_LEFT, \ + /* 0x4c */ GRUB_TERM_KEY_CENTER | GRUB_TERM_KEYPAD, \ + /* 0x4d */ GRUB_TERM_KEY_RIGHT, \ + /* 0x4e */ '+' | GRUB_TERM_KEYPAD, \ + /* 0x4f */ GRUB_TERM_KEY_END, \ + /* 0x50 */ GRUB_TERM_KEY_DOWN, \ + /* 0x51 */ GRUB_TERM_KEY_PPAGE, \ + /* 0x52 */ GRUB_TERM_KEY_INSERT, \ + /* 0x53 */ GRUB_TERM_KEY_DC, \ + /* 0x54 */ '\0', '\0', GRUB_TERM_KEY_102, GRUB_TERM_KEY_F11, \ + /* 0x58 */ GRUB_TERM_KEY_F12, '\0', '\0', '\0', '\0', '\0', '\0', '\0', \ + /* 0x60 */ '\0', '\0', '\0', '\0', '\0', OLPC_UP, OLPC_DOWN, OLPC_LEFT, \ + /* 0x68 */ OLPC_RIGHT \ } #define GRUB_AT_KEY_KEYBOARD_MAP_SHIFT(name) \ diff --git a/include/grub/term.h b/include/grub/term.h index 1f64bebc7..f2f80152f 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -25,8 +25,9 @@ #define GRUB_TERM_CTRL 0x02000000 #define GRUB_TERM_ALT 0x04000000 /* Used by keylayouts code. Never returned in grub_getkey. */ -#define GRUB_TERM_ALT_GR 0x08000000 -#define GRUB_TERM_CAPS 0x10000000 +#define GRUB_TERM_ALT_GR 0x08000000 +#define GRUB_TERM_CAPS 0x10000000 +#define GRUB_TERM_KEYPAD 0x20000000 /* Keys without associated character. */ #define GRUB_TERM_EXTENDED 0x00800000 @@ -53,6 +54,7 @@ #define GRUB_TERM_KEY_F11 (GRUB_TERM_EXTENDED | 20) #define GRUB_TERM_KEY_F12 (GRUB_TERM_EXTENDED | 21) #define GRUB_TERM_KEY_INSERT (GRUB_TERM_EXTENDED | 22) +#define GRUB_TERM_KEY_CENTER (GRUB_TERM_EXTENDED | 23) /* Used by keylayouts code. Never returned in grub_getkey. */ #define GRUB_TERM_KEY_102 0x80 From eb628338dbd4198d517c91090207b0a651d8088a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 19 Aug 2010 11:44:49 +0200 Subject: [PATCH 019/214] AltGr support --- commands/keylayouts.c | 54 ++++++++++++++++++++++----------- include/grub/keyboard_layouts.h | 2 +- term/at_keyboard.c | 45 +++++++++++++++------------ util/grub-mklayouts.c | 21 +++++++++++-- 4 files changed, 82 insertions(+), 40 deletions(-) diff --git a/commands/keylayouts.c b/commands/keylayouts.c index 419cdf45a..25a117560 100644 --- a/commands/keylayouts.c +++ b/commands/keylayouts.c @@ -73,6 +73,18 @@ get_abstract_code (grub_term_input_t term, int in) if (((in & 0xff) == 0) && keyboard_map[(in & 0xff00) >> 8] >= 'a' && keyboard_map[(in & 0xff00) >> 8] <= 'z') return keyboard_map[(in & 0xff00) >> 8] | flags | GRUB_TERM_ALT_GR; + if ((in & 0xff) == 0 && (in & 0xff00) >= 0x7800 + && (in & 0xff00) <= 0x8000) + return (((in & 0xff00) >> 8) - 0x78 + '1') | flags | GRUB_TERM_ALT_GR; + + if ((in & 0xff00) == 0x8100) + return '0' | flags | GRUB_TERM_ALT_GR; + + if ((in & 0xffff) == 0x8200) + return '-' | flags | GRUB_TERM_ALT_GR; + + if ((in & 0xffff) == 0x8300) + return '+' | flags | GRUB_TERM_ALT_GR; if ((in & 0xff) == 0) return keyboard_map[(in & 0xff00) >> 8] | flags; @@ -83,34 +95,25 @@ get_abstract_code (grub_term_input_t term, int in) } static grub_uint32_t mapping[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; - -static unsigned -clear_internal_flags (unsigned in) -{ - if (in & GRUB_TERM_ALT_GR) - in = (in & ~GRUB_TERM_ALT_GR) | GRUB_TERM_ALT; - return in & ~GRUB_TERM_CAPS & ~GRUB_TERM_KEYPAD; -} +static grub_uint32_t mapping_alt[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; static unsigned map (grub_term_input_t term __attribute__ ((unused)), unsigned in) { if (in & GRUB_TERM_KEYPAD) - return clear_internal_flags (in); - - /* AltGr isn't supported yet. */ - if (in & GRUB_TERM_ALT_GR) - in = (in & ~GRUB_TERM_ALT_GR) | GRUB_TERM_ALT; + return in; if ((in & GRUB_TERM_EXTENDED) || (in & GRUB_TERM_KEY_MASK) == '\b' || (in & GRUB_TERM_KEY_MASK) == '\n' || (in & GRUB_TERM_KEY_MASK) == ' ' || (in & GRUB_TERM_KEY_MASK) == '\t' || (in & GRUB_TERM_KEY_MASK) == '\e' || (in & GRUB_TERM_KEY_MASK) == '\r' || (in & GRUB_TERM_KEY_MASK) >= ARRAY_SIZE (mapping)) - return clear_internal_flags (in); + return in; - return mapping[in & GRUB_TERM_KEY_MASK] - | clear_internal_flags (in & ~GRUB_TERM_KEY_MASK); + if ((in & GRUB_TERM_ALT_GR) && mapping_alt[in & GRUB_TERM_KEY_MASK]) + return mapping_alt[in & GRUB_TERM_KEY_MASK] | (in & ~GRUB_TERM_KEY_MASK & ~GRUB_TERM_ALT_GR); + + return mapping[in & GRUB_TERM_KEY_MASK] | (in & ~GRUB_TERM_KEY_MASK); } static int @@ -118,6 +121,9 @@ translate (grub_term_input_t term, int in) { int code, flags; code = get_abstract_code (term, in); + + flags = code & ~(GRUB_TERM_KEY_MASK | GRUB_TERM_ALT_GR | GRUB_TERM_KEYPAD | GRUB_TERM_CAPS); + if ((code & GRUB_TERM_CAPS) && (code & GRUB_TERM_KEY_MASK) >= 'a' && (code & GRUB_TERM_KEY_MASK) <= 'z') code = (code & GRUB_TERM_KEY_MASK) + 'A' - 'a'; @@ -125,7 +131,6 @@ translate (grub_term_input_t term, int in) && (code & GRUB_TERM_KEY_MASK) <= 'Z') code = (code & GRUB_TERM_KEY_MASK) + 'a' - 'A'; - flags = code & ~(GRUB_TERM_KEY_MASK | GRUB_TERM_ALT_GR | GRUB_TERM_KEYPAD); code &= (GRUB_TERM_KEY_MASK | GRUB_TERM_ALT_GR | GRUB_TERM_KEYPAD); code = map (term, code); /* Transform unconsumed AltGr into Alt. */ @@ -134,6 +139,8 @@ translate (grub_term_input_t term, int in) flags |= GRUB_TERM_ALT; code &= ~GRUB_TERM_ALT_GR; } + code &= ~GRUB_TERM_KEYPAD; + if ((flags & GRUB_TERM_CAPS) && code >= 'a' && code <= 'z') code += 'A' - 'a'; else if ((flags & GRUB_TERM_CAPS) && code >= 'A' @@ -186,6 +193,7 @@ grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)), grub_uint32_t version; grub_uint8_t magic[GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE]; grub_uint32_t newmapping[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; + grub_uint32_t newmapping_alt[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; unsigned i; if (argc < 1) @@ -241,9 +249,20 @@ grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)), goto fail; } + if (grub_file_read (file, newmapping_alt, sizeof (newmapping_alt)) + != sizeof (newmapping_alt)) + { + if (!grub_errno) + grub_error (GRUB_ERR_BAD_ARGUMENT, "file is too short"); + goto fail; + } + for (i = 0; i < ARRAY_SIZE (mapping); i++) mapping[i] = grub_le_to_cpu32(newmapping[i]); + for (i = 0; i < ARRAY_SIZE (mapping_alt); i++) + mapping_alt[i] = grub_le_to_cpu32(newmapping_alt[i]); + return GRUB_ERR_NONE; fail: @@ -263,6 +282,7 @@ GRUB_MOD_INIT(keylayouts) unsigned i; for (i = 0; i < ARRAY_SIZE (mapping); i++) mapping[i] = i; + grub_memset (mapping_alt, 0, sizeof (mapping_alt)); mapping[GRUB_TERM_KEY_102] = '\\'; mapping[GRUB_TERM_KEY_SHIFT_102] = '|'; diff --git a/include/grub/keyboard_layouts.h b/include/grub/keyboard_layouts.h index 1d263e268..081e9ca98 100644 --- a/include/grub/keyboard_layouts.h +++ b/include/grub/keyboard_layouts.h @@ -21,7 +21,7 @@ #define GRUB_KEYBOARD_LAYOUTS_FILEMAGIC "GRUBLAYO" #define GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE (sizeof(GRUB_KEYBOARD_LAYOUTS_FILEMAGIC) - 1) -#define GRUB_KEYBOARD_LAYOUTS_VERSION 2 +#define GRUB_KEYBOARD_LAYOUTS_VERSION 3 #define GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE 256 diff --git a/term/at_keyboard.c b/term/at_keyboard.c index cc0c69e22..5adc8b4da 100644 --- a/term/at_keyboard.c +++ b/term/at_keyboard.c @@ -34,6 +34,7 @@ static int pending_key = -1; #define KEYBOARD_STATUS_CTRL_R (1 << 5) #define KEYBOARD_STATUS_CAPS_LOCK (1 << 6) #define KEYBOARD_STATUS_NUM_LOCK (1 << 7) +#define KEYBOARD_STATUS_EXTENDED (1 << 8) static grub_uint8_t led_status; @@ -80,12 +81,10 @@ keyboard_controller_led (grub_uint8_t leds) /* FIXME: This should become an interrupt service routine. For now it's just used to catch events from control keys. */ static void -grub_keyboard_isr (char key) +grub_keyboard_isr (grub_uint8_t key) { - char is_make = KEYBOARD_ISMAKE (key); - key = KEYBOARD_SCANCODE (key); - if (is_make) - switch (key) + if (KEYBOARD_ISMAKE (key)) + switch (KEYBOARD_SCANCODE (key)) { case SHIFT_L: at_keyboard_status |= KEYBOARD_STATUS_SHIFT_L; @@ -97,14 +96,14 @@ grub_keyboard_isr (char key) at_keyboard_status |= KEYBOARD_STATUS_CTRL_L; break; case ALT: - at_keyboard_status |= KEYBOARD_STATUS_ALT_L; + if (at_keyboard_status & KEYBOARD_STATUS_EXTENDED) + at_keyboard_status |= KEYBOARD_STATUS_ALT_R; + else + at_keyboard_status |= KEYBOARD_STATUS_ALT_L; break; - default: - /* Skip grub_dprintf. */ - return; } else - switch (key) + switch (KEYBOARD_SCANCODE (key)) { case SHIFT_L: at_keyboard_status &= ~KEYBOARD_STATUS_SHIFT_L; @@ -116,15 +115,17 @@ grub_keyboard_isr (char key) at_keyboard_status &= ~KEYBOARD_STATUS_CTRL_L; break; case ALT: - at_keyboard_status &= ~KEYBOARD_STATUS_ALT_L; + if (at_keyboard_status & KEYBOARD_STATUS_EXTENDED) + at_keyboard_status &= ~KEYBOARD_STATUS_ALT_R; + else + at_keyboard_status &= ~KEYBOARD_STATUS_ALT_L; break; - default: - /* Skip grub_dprintf. */ - return; } -#ifdef DEBUG_AT_KEYBOARD - grub_dprintf ("atkeyb", "Control key 0x%0x was %s\n", key, is_make ? "pressed" : "unpressed"); -#endif + if (key == 0xe0) + at_keyboard_status |= KEYBOARD_STATUS_EXTENDED; + else + at_keyboard_status &= ~KEYBOARD_STATUS_EXTENDED; + } /* If there is a raw key pending, return it; otherwise return -1. */ @@ -210,9 +211,15 @@ grub_at_keyboard_getkey_noblock (void) } if (at_keyboard_status & KEYBOARD_STATUS_ALT_L) - key |= GRUB_TERM_ALT; + { + key |= GRUB_TERM_ALT; + grub_printf ("AltL"); + } if (at_keyboard_status & KEYBOARD_STATUS_ALT_R) - key |= GRUB_TERM_ALT_GR; + { + key |= GRUB_TERM_ALT_GR; + grub_printf ("AltGr"); + } if (at_keyboard_status & (KEYBOARD_STATUS_CTRL_L | KEYBOARD_STATUS_CTRL_R)) key |= GRUB_TERM_CTRL; diff --git a/util/grub-mklayouts.c b/util/grub-mklayouts.c index 48b17e798..434f9f4f8 100644 --- a/util/grub-mklayouts.c +++ b/util/grub-mklayouts.c @@ -115,7 +115,8 @@ get_grub_code (char *layout_code) } void -write_file (char* filename, grub_uint32_t *keyboard_map) +write_file (char* filename, grub_uint32_t *keyboard_map, + grub_uint32_t *keyboard_map_alt) { FILE *fp_output; grub_uint32_t version; @@ -126,6 +127,9 @@ write_file (char* filename, grub_uint32_t *keyboard_map) for (i = 0; i < GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE; i++) keyboard_map[i] = grub_cpu_to_le32 (keyboard_map[i]); + for (i = 0; i < GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE; i++) + keyboard_map_alt[i] = grub_cpu_to_le32 (keyboard_map_alt[i]); + fp_output = fopen (filename, "w"); if (!fp_output) @@ -139,6 +143,8 @@ write_file (char* filename, grub_uint32_t *keyboard_map) fwrite (&version, sizeof (version), 1, fp_output); fwrite (keyboard_map, sizeof (keyboard_map[0]), GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE, fp_output); + fwrite (keyboard_map_alt, sizeof (keyboard_map_alt[0]), + GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE, fp_output); fclose (fp_output); } @@ -146,6 +152,7 @@ void write_keymaps (char *keymap, char *file_basename) { grub_uint32_t keyboard_map[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; + grub_uint32_t keyboard_map_alt[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; char line[2048]; pid_t pid; @@ -189,11 +196,17 @@ write_keymaps (char *keymap, char *file_basename) unsigned keycode; char normal[64]; char shift[64]; - sscanf (line, "keycode %u = %60s %60s", &keycode, normal, shift); + char normalalt[64]; + char shiftalt[64]; + + sscanf (line, "keycode %u = %60s %60s %60s %60s", &keycode, + normal, shift, normalalt, shiftalt); if (keycode < ARRAY_SIZE (us_keyboard_map) && us_keyboard_map[keycode] < ARRAY_SIZE (keyboard_map)) { keyboard_map[us_keyboard_map[keycode]] = get_grub_code (normal); + keyboard_map_alt[us_keyboard_map[keycode]] + = get_grub_code (normalalt); ok = 1; } if (keycode < ARRAY_SIZE (us_keyboard_map_shifted) @@ -201,6 +214,8 @@ write_keymaps (char *keymap, char *file_basename) { keyboard_map[us_keyboard_map_shifted[keycode]] = get_grub_code (shift); + keyboard_map_alt[us_keyboard_map_shifted[keycode]] + = get_grub_code (shiftalt); ok = 1; } } @@ -213,7 +228,7 @@ write_keymaps (char *keymap, char *file_basename) exit (1); } - write_file (file_basename, keyboard_map); + write_file (file_basename, keyboard_map, keyboard_map_alt); } int From ed19677fe3e6a1217260186d9e1a2494b9ff6cd2 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 19 Aug 2010 13:32:36 +0200 Subject: [PATCH 020/214] Revert all parts done for BIOS keymap translation --- commands/keylayouts.c | 204 ++++---------------------------- include/grub/at_keyboard.h | 49 -------- include/grub/i386/pc/console.h | 13 -- include/grub/keyboard_layouts.h | 24 +++- include/grub/term.h | 63 ++++------ kern/i386/pc/startup.S | 34 +++++- kern/term.c | 23 +++- term/at_keyboard.c | 55 ++++++--- term/i386/pc/console.c | 3 +- term/usb_keyboard.c | 7 +- util/grub-fstest.c | 6 +- util/grub-mklayouts.c | 20 ---- util/grub-probe.c | 6 +- util/i386/pc/grub-setup.c | 6 +- 14 files changed, 166 insertions(+), 347 deletions(-) diff --git a/commands/keylayouts.c b/commands/keylayouts.c index 25a117560..bfe30d2ab 100644 --- a/commands/keylayouts.c +++ b/commands/keylayouts.c @@ -23,167 +23,11 @@ #include #include #include -#include #include #include #include #include -GRUB_AT_KEY_KEYBOARD_MAP (keyboard_map); - -static int -get_abstract_code (grub_term_input_t term, int in) -{ - switch (term->flags & GRUB_TERM_INPUT_FLAGS_TYPE_MASK) - { - case GRUB_TERM_INPUT_FLAGS_TYPE_TERMCODES: - default: - return in; - case GRUB_TERM_INPUT_FLAGS_TYPE_BIOS: - { - unsigned status = 0; - unsigned flags = 0; - - if (term->getkeystatus) - status = term->getkeystatus (term); - if (status & GRUB_TERM_CAPS) - flags |= GRUB_TERM_CAPS; - - if ((0x5600 | '\\') == (in & 0xffff)) - return GRUB_TERM_KEY_102 | flags; - - if ((0x5600 | '|') == (in & 0xffff)) - return GRUB_TERM_KEY_SHIFT_102 | flags; - - if ((in & 0xff00) == 0x3500 || (in & 0xff00) == 0x3700 - || (in & 0xff00) == 0x4500 - || ((in & 0xff00) >= 0x4700 && (in & 0xff00) <= 0x5300)) - flags |= GRUB_TERM_KEYPAD; - - /* Detect CTRL'ed keys. */ - if ((in & 0xff) > 0 && (in & 0xff) < 0x20 - && ((in & 0xffff) != (0x0100 | '\e')) - && ((in & 0xffff) != (0x0f00 | '\t')) - && ((in & 0xffff) != (0x0e00 | '\b')) - && ((in & 0xffff) != (0x1c00 | '\r')) - && ((in & 0xffff) != (0x1c00 | '\n'))) - return ((in & 0xff) - 1 + 'a') | flags | GRUB_TERM_CTRL; - /* Detect ALT'ed keys. */ - /* XXX no way to distinguish left and right ALT. */ - if (((in & 0xff) == 0) && keyboard_map[(in & 0xff00) >> 8] >= 'a' - && keyboard_map[(in & 0xff00) >> 8] <= 'z') - return keyboard_map[(in & 0xff00) >> 8] | flags | GRUB_TERM_ALT_GR; - if ((in & 0xff) == 0 && (in & 0xff00) >= 0x7800 - && (in & 0xff00) <= 0x8000) - return (((in & 0xff00) >> 8) - 0x78 + '1') | flags | GRUB_TERM_ALT_GR; - - if ((in & 0xff00) == 0x8100) - return '0' | flags | GRUB_TERM_ALT_GR; - - if ((in & 0xffff) == 0x8200) - return '-' | flags | GRUB_TERM_ALT_GR; - - if ((in & 0xffff) == 0x8300) - return '+' | flags | GRUB_TERM_ALT_GR; - - if ((in & 0xff) == 0) - return keyboard_map[(in & 0xff00) >> 8] | flags; - - return (in & 0xff) | flags; - } - } -} - -static grub_uint32_t mapping[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; -static grub_uint32_t mapping_alt[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; - -static unsigned -map (grub_term_input_t term __attribute__ ((unused)), unsigned in) -{ - if (in & GRUB_TERM_KEYPAD) - return in; - - if ((in & GRUB_TERM_EXTENDED) || (in & GRUB_TERM_KEY_MASK) == '\b' - || (in & GRUB_TERM_KEY_MASK) == '\n' || (in & GRUB_TERM_KEY_MASK) == ' ' - || (in & GRUB_TERM_KEY_MASK) == '\t' || (in & GRUB_TERM_KEY_MASK) == '\e' - || (in & GRUB_TERM_KEY_MASK) == '\r' - || (in & GRUB_TERM_KEY_MASK) >= ARRAY_SIZE (mapping)) - return in; - - if ((in & GRUB_TERM_ALT_GR) && mapping_alt[in & GRUB_TERM_KEY_MASK]) - return mapping_alt[in & GRUB_TERM_KEY_MASK] | (in & ~GRUB_TERM_KEY_MASK & ~GRUB_TERM_ALT_GR); - - return mapping[in & GRUB_TERM_KEY_MASK] | (in & ~GRUB_TERM_KEY_MASK); -} - -static int -translate (grub_term_input_t term, int in) -{ - int code, flags; - code = get_abstract_code (term, in); - - flags = code & ~(GRUB_TERM_KEY_MASK | GRUB_TERM_ALT_GR | GRUB_TERM_KEYPAD | GRUB_TERM_CAPS); - - if ((code & GRUB_TERM_CAPS) && (code & GRUB_TERM_KEY_MASK) >= 'a' - && (code & GRUB_TERM_KEY_MASK) <= 'z') - code = (code & GRUB_TERM_KEY_MASK) + 'A' - 'a'; - else if ((code & GRUB_TERM_CAPS) && (code & GRUB_TERM_KEY_MASK) >= 'A' - && (code & GRUB_TERM_KEY_MASK) <= 'Z') - code = (code & GRUB_TERM_KEY_MASK) + 'a' - 'A'; - - code &= (GRUB_TERM_KEY_MASK | GRUB_TERM_ALT_GR | GRUB_TERM_KEYPAD); - code = map (term, code); - /* Transform unconsumed AltGr into Alt. */ - if (code & GRUB_TERM_ALT_GR) - { - flags |= GRUB_TERM_ALT; - code &= ~GRUB_TERM_ALT_GR; - } - code &= ~GRUB_TERM_KEYPAD; - - if ((flags & GRUB_TERM_CAPS) && code >= 'a' && code <= 'z') - code += 'A' - 'a'; - else if ((flags & GRUB_TERM_CAPS) && code >= 'A' - && code <= 'Z') - code += 'a' - 'A'; - return code | flags; -} - -static int -grub_getkey_smart (void) -{ - grub_term_input_t term; - - grub_refresh (); - - while (1) - { - FOR_ACTIVE_TERM_INPUTS(term) - { - int key = term->checkkey (term); - if (key != -1) - return translate (term, term->getkey (term)); - } - - grub_cpu_idle (); - } -} - -int -grub_checkkey (void) -{ - grub_term_input_t term; - - FOR_ACTIVE_TERM_INPUTS(term) - { - int key = term->checkkey (term); - if (key != -1) - return translate (term, key); - } - - return -1; -} - static grub_err_t grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)), int argc, char *argv[]) @@ -192,8 +36,7 @@ grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)), grub_file_t file; grub_uint32_t version; grub_uint8_t magic[GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE]; - grub_uint32_t newmapping[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; - grub_uint32_t newmapping_alt[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; + struct grub_keyboard_layout *newmap = NULL; unsigned i; if (argc < 1) @@ -241,60 +84,53 @@ grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)), goto fail; } - if (grub_file_read (file, newmapping, sizeof (newmapping)) - != sizeof (newmapping)) + newmap = grub_malloc (sizeof (*newmap)); + if (!newmap) + goto fail; + + if (grub_file_read (file, newmap, sizeof (*newmap)) != sizeof (*newmap)) { if (!grub_errno) grub_error (GRUB_ERR_BAD_ARGUMENT, "file is too short"); goto fail; } - if (grub_file_read (file, newmapping_alt, sizeof (newmapping_alt)) - != sizeof (newmapping_alt)) - { - if (!grub_errno) - grub_error (GRUB_ERR_BAD_ARGUMENT, "file is too short"); - goto fail; - } + for (i = 0; i < ARRAY_SIZE (newmap->at.keyboard_map); i++) + newmap->at.keyboard_map[i] = grub_le_to_cpu32(newmap->at.keyboard_map[i]); - for (i = 0; i < ARRAY_SIZE (mapping); i++) - mapping[i] = grub_le_to_cpu32(newmapping[i]); + for (i = 0; i < ARRAY_SIZE (newmap->at.keyboard_map_shift); i++) + newmap->at.keyboard_map_shift[i] + = grub_le_to_cpu32(newmap->at.keyboard_map_shift[i]); - for (i = 0; i < ARRAY_SIZE (mapping_alt); i++) - mapping_alt[i] = grub_le_to_cpu32(newmapping_alt[i]); + for (i = 0; i < ARRAY_SIZE (newmap->at.keyboard_map_l3); i++) + newmap->at.keyboard_map_l3[i] + = grub_le_to_cpu32(newmap->at.keyboard_map_l3[i]); + + for (i = 0; i < ARRAY_SIZE (newmap->at.keyboard_map_shift_l3); i++) + newmap->at.keyboard_map_shift_l3[i] + = grub_le_to_cpu32(newmap->at.keyboard_map_shift_l3[i]); return GRUB_ERR_NONE; fail: if (filename != argv[0]) grub_free (filename); + grub_free (newmap); if (file) grub_file_close (file); return grub_errno; } -static int (*grub_getkey_saved) (void); - static grub_command_t cmd; GRUB_MOD_INIT(keylayouts) { - unsigned i; - for (i = 0; i < ARRAY_SIZE (mapping); i++) - mapping[i] = i; - grub_memset (mapping_alt, 0, sizeof (mapping_alt)); - mapping[GRUB_TERM_KEY_102] = '\\'; - mapping[GRUB_TERM_KEY_SHIFT_102] = '|'; - - grub_getkey_saved = grub_getkey; - grub_getkey = grub_getkey_smart; - cmd = grub_register_command ("keymap", grub_cmd_keymap, 0, N_("Load a keyboard layout.")); } GRUB_MOD_FINI(keylayouts) { - grub_getkey = grub_getkey_saved; + grub_current_layout = NULL; grub_unregister_command (cmd); } diff --git a/include/grub/at_keyboard.h b/include/grub/at_keyboard.h index e8289d672..10421540a 100644 --- a/include/grub/at_keyboard.h +++ b/include/grub/at_keyboard.h @@ -51,53 +51,4 @@ #define OLPC_RIGHT '\0' #endif -#define GRUB_AT_KEY_KEYBOARD_MAP(name) \ -static const unsigned name[128] = \ -{ \ - /* 0x00 */ '\0', GRUB_TERM_ESC, '1', '2', '3', '4', '5', '6', \ - /* 0x08 */ '7', '8', '9', '0', \ - /* 0x0c */ '-', '=', GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, \ - /* 0x10 */ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', \ - /* 0x18 */ 'o', 'p', '[', ']', '\n', '\0', 'a', 's', \ - /* 0x20 */ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', \ - /* 0x28 */ '\'', '`', '\0', '\\', 'z', 'x', 'c', 'v', \ - /* 0x30 */ 'b', 'n', 'm', ',', '.', '/', '\0', '*' | GRUB_TERM_KEYPAD, \ - /* 0x38 */ '\0', ' ', '\0', GRUB_TERM_KEY_F1, \ - /* 0x3c */ GRUB_TERM_KEY_F2, GRUB_TERM_KEY_F3, \ - /* 0x3e */ GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5, \ - /* 0x40 */ GRUB_TERM_KEY_F6, GRUB_TERM_KEY_F7, \ - /* 0x42 */ GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9, \ - /* 0x44 */ GRUB_TERM_KEY_F10, '\0', \ - /* 0x46 */ '\0', GRUB_TERM_KEY_HOME, \ - /* 0x48 */ GRUB_TERM_KEY_UP, \ - /* 0x49 */ GRUB_TERM_KEY_NPAGE, \ - /* 0x4a */ '-' | GRUB_TERM_KEYPAD, \ - /* 0x4b */ GRUB_TERM_KEY_LEFT, \ - /* 0x4c */ GRUB_TERM_KEY_CENTER | GRUB_TERM_KEYPAD, \ - /* 0x4d */ GRUB_TERM_KEY_RIGHT, \ - /* 0x4e */ '+' | GRUB_TERM_KEYPAD, \ - /* 0x4f */ GRUB_TERM_KEY_END, \ - /* 0x50 */ GRUB_TERM_KEY_DOWN, \ - /* 0x51 */ GRUB_TERM_KEY_PPAGE, \ - /* 0x52 */ GRUB_TERM_KEY_INSERT, \ - /* 0x53 */ GRUB_TERM_KEY_DC, \ - /* 0x54 */ '\0', '\0', GRUB_TERM_KEY_102, GRUB_TERM_KEY_F11, \ - /* 0x58 */ GRUB_TERM_KEY_F12, '\0', '\0', '\0', '\0', '\0', '\0', '\0', \ - /* 0x60 */ '\0', '\0', '\0', '\0', '\0', OLPC_UP, OLPC_DOWN, OLPC_LEFT, \ - /* 0x68 */ OLPC_RIGHT \ -} - -#define GRUB_AT_KEY_KEYBOARD_MAP_SHIFT(name) \ -static unsigned name[128] = \ -{ \ - '\0', '\0', '!', '@', '#', '$', '%', '^', \ - '&', '*', '(', ')', '_', '+', '\0', '\0', \ - 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', \ - 'O', 'P', '{', '}', '\n', '\0', 'A', 'S', \ - 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', \ - '\"', '~', '\0', '|', 'Z', 'X', 'C', 'V', \ - 'B', 'N', 'M', '<', '>', '?', \ - [0x56] = GRUB_TERM_KEY_SHIFT_102 \ -} - #endif diff --git a/include/grub/i386/pc/console.h b/include/grub/i386/pc/console.h index 7f58344ec..fabb13d5c 100644 --- a/include/grub/i386/pc/console.h +++ b/include/grub/i386/pc/console.h @@ -19,19 +19,6 @@ #ifndef GRUB_CONSOLE_MACHINE_HEADER #define GRUB_CONSOLE_MACHINE_HEADER 1 -/* Define scan codes. */ -#define GRUB_CONSOLE_KEY_LEFT 0x4B00 -#define GRUB_CONSOLE_KEY_RIGHT 0x4D00 -#define GRUB_CONSOLE_KEY_UP 0x4800 -#define GRUB_CONSOLE_KEY_DOWN 0x5000 -#define GRUB_CONSOLE_KEY_IC 0x5200 -#define GRUB_CONSOLE_KEY_DC 0x5300 -#define GRUB_CONSOLE_KEY_BACKSPACE 0x0008 -#define GRUB_CONSOLE_KEY_HOME 0x4700 -#define GRUB_CONSOLE_KEY_END 0x4F00 -#define GRUB_CONSOLE_KEY_NPAGE 0x5100 -#define GRUB_CONSOLE_KEY_PPAGE 0x4900 - #ifndef ASM_FILE #include diff --git a/include/grub/keyboard_layouts.h b/include/grub/keyboard_layouts.h index 081e9ca98..2d6e3d54c 100644 --- a/include/grub/keyboard_layouts.h +++ b/include/grub/keyboard_layouts.h @@ -21,8 +21,28 @@ #define GRUB_KEYBOARD_LAYOUTS_FILEMAGIC "GRUBLAYO" #define GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE (sizeof(GRUB_KEYBOARD_LAYOUTS_FILEMAGIC) - 1) -#define GRUB_KEYBOARD_LAYOUTS_VERSION 3 +#define GRUB_KEYBOARD_LAYOUTS_VERSION 4 -#define GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE 256 +#define GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE 128 + +struct grub_keyboard_layout +{ + struct + { + grub_uint32_t keyboard_map[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; + grub_uint32_t keyboard_map_shift[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; + grub_uint32_t keyboard_map_l3[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; + grub_uint32_t keyboard_map_shift_l3[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; + } at; + struct + { + grub_uint32_t keyboard_map[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; + grub_uint32_t keyboard_map_shift[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; + grub_uint32_t keyboard_map_l3[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; + grub_uint32_t keyboard_map_shift_l3[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; + } usb; +}; + +struct grub_keyboard_layout *EXPORT_VAR (grub_current_layout); #endif /* GRUB_KEYBOARD_LAYOUTS */ diff --git a/include/grub/term.h b/include/grub/term.h index f2f80152f..036e8caaa 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -24,41 +24,34 @@ #define GRUB_TERM_SHIFT 0x01000000 #define GRUB_TERM_CTRL 0x02000000 #define GRUB_TERM_ALT 0x04000000 -/* Used by keylayouts code. Never returned in grub_getkey. */ -#define GRUB_TERM_ALT_GR 0x08000000 -#define GRUB_TERM_CAPS 0x10000000 -#define GRUB_TERM_KEYPAD 0x20000000 /* Keys without associated character. */ #define GRUB_TERM_EXTENDED 0x00800000 #define GRUB_TERM_KEY_MASK 0x00ffffff -#define GRUB_TERM_KEY_LEFT (GRUB_TERM_EXTENDED | 1) -#define GRUB_TERM_KEY_RIGHT (GRUB_TERM_EXTENDED | 2) -#define GRUB_TERM_KEY_UP (GRUB_TERM_EXTENDED | 3) -#define GRUB_TERM_KEY_DOWN (GRUB_TERM_EXTENDED | 4) -#define GRUB_TERM_KEY_HOME (GRUB_TERM_EXTENDED | 5) -#define GRUB_TERM_KEY_END (GRUB_TERM_EXTENDED | 6) -#define GRUB_TERM_KEY_DC (GRUB_TERM_EXTENDED | 7) -#define GRUB_TERM_KEY_PPAGE (GRUB_TERM_EXTENDED | 8) -#define GRUB_TERM_KEY_NPAGE (GRUB_TERM_EXTENDED | 9) -#define GRUB_TERM_KEY_F1 (GRUB_TERM_EXTENDED | 10) -#define GRUB_TERM_KEY_F2 (GRUB_TERM_EXTENDED | 11) -#define GRUB_TERM_KEY_F3 (GRUB_TERM_EXTENDED | 12) -#define GRUB_TERM_KEY_F4 (GRUB_TERM_EXTENDED | 13) -#define GRUB_TERM_KEY_F5 (GRUB_TERM_EXTENDED | 14) -#define GRUB_TERM_KEY_F6 (GRUB_TERM_EXTENDED | 15) -#define GRUB_TERM_KEY_F7 (GRUB_TERM_EXTENDED | 16) -#define GRUB_TERM_KEY_F8 (GRUB_TERM_EXTENDED | 17) -#define GRUB_TERM_KEY_F9 (GRUB_TERM_EXTENDED | 18) -#define GRUB_TERM_KEY_F10 (GRUB_TERM_EXTENDED | 19) -#define GRUB_TERM_KEY_F11 (GRUB_TERM_EXTENDED | 20) -#define GRUB_TERM_KEY_F12 (GRUB_TERM_EXTENDED | 21) -#define GRUB_TERM_KEY_INSERT (GRUB_TERM_EXTENDED | 22) -#define GRUB_TERM_KEY_CENTER (GRUB_TERM_EXTENDED | 23) -/* Used by keylayouts code. Never returned in grub_getkey. */ -#define GRUB_TERM_KEY_102 0x80 -#define GRUB_TERM_KEY_SHIFT_102 0x81 +#define GRUB_TERM_KEY_LEFT (GRUB_TERM_EXTENDED | 0x4b) +#define GRUB_TERM_KEY_RIGHT (GRUB_TERM_EXTENDED | 0x4d) +#define GRUB_TERM_KEY_UP (GRUB_TERM_EXTENDED | 0x48) +#define GRUB_TERM_KEY_DOWN (GRUB_TERM_EXTENDED | 0x50) +#define GRUB_TERM_KEY_HOME (GRUB_TERM_EXTENDED | 0x47) +#define GRUB_TERM_KEY_END (GRUB_TERM_EXTENDED | 0x4f) +#define GRUB_TERM_KEY_DC (GRUB_TERM_EXTENDED | 0x53) +#define GRUB_TERM_KEY_PPAGE (GRUB_TERM_EXTENDED | 0x49) +#define GRUB_TERM_KEY_NPAGE (GRUB_TERM_EXTENDED | 0x51) +#define GRUB_TERM_KEY_F1 (GRUB_TERM_EXTENDED | 0x3b) +#define GRUB_TERM_KEY_F2 (GRUB_TERM_EXTENDED | 0x3c) +#define GRUB_TERM_KEY_F3 (GRUB_TERM_EXTENDED | 0x3d) +#define GRUB_TERM_KEY_F4 (GRUB_TERM_EXTENDED | 0x3e) +#define GRUB_TERM_KEY_F5 (GRUB_TERM_EXTENDED | 0x3f) +#define GRUB_TERM_KEY_F6 (GRUB_TERM_EXTENDED | 0x40) +#define GRUB_TERM_KEY_F7 (GRUB_TERM_EXTENDED | 0x41) +#define GRUB_TERM_KEY_F8 (GRUB_TERM_EXTENDED | 0x42) +#define GRUB_TERM_KEY_F9 (GRUB_TERM_EXTENDED | 0x43) +#define GRUB_TERM_KEY_F10 (GRUB_TERM_EXTENDED | 0x44) +#define GRUB_TERM_KEY_F11 (GRUB_TERM_EXTENDED | 0x57) +#define GRUB_TERM_KEY_F12 (GRUB_TERM_EXTENDED | 0x58) +#define GRUB_TERM_KEY_INSERT (GRUB_TERM_EXTENDED | 0x52) +#define GRUB_TERM_KEY_CENTER (GRUB_TERM_EXTENDED | 0x4c) #define GRUB_TERM_ESC '\e' #define GRUB_TERM_TAB '\t' @@ -168,16 +161,10 @@ struct grub_term_input /* Get keyboard modifier status. */ int (*getkeystatus) (struct grub_term_input *term); - grub_uint32_t flags; - void *data; }; typedef struct grub_term_input *grub_term_input_t; -#define GRUB_TERM_INPUT_FLAGS_TYPE_MASK 0xf -#define GRUB_TERM_INPUT_FLAGS_TYPE_TERMCODES 0x0 -#define GRUB_TERM_INPUT_FLAGS_TYPE_BIOS 0x1 - struct grub_term_output { /* The next terminal. */ @@ -314,8 +301,8 @@ grub_term_unregister_output (grub_term_output_t term) #define FOR_DISABLED_TERM_OUTPUTS(var) FOR_LIST_ELEMENTS((var), (grub_term_outputs_disabled)) void grub_putcode (grub_uint32_t code, struct grub_term_output *term); -extern int (*EXPORT_VAR(grub_getkey)) (void); -int grub_checkkey (void); +int EXPORT_FUNC(grub_getkey) (void); +int EXPORT_FUNC(grub_checkkey) (void); void grub_cls (void); void EXPORT_FUNC(grub_refresh) (void); void grub_puts_terminal (const char *str, struct grub_term_output *term); diff --git a/kern/i386/pc/startup.S b/kern/i386/pc/startup.S index cbc4c5cfb..ef5904bb2 100644 --- a/kern/i386/pc/startup.S +++ b/kern/i386/pc/startup.S @@ -1147,6 +1147,11 @@ FUNCTION(grub_console_putchar) ret +LOCAL(bypass_table): + .word 0x0100 | '\e',0x0f00 | '\t', 0x0e00 | '\b', 0x1c00 | '\r' + .word 0x1c00 | '\n' +LOCAL(bypass_table_end): + /* * int grub_console_getkey (void) * BIOS call "INT 16H Function 00H" to read character from keyboard @@ -1180,17 +1185,39 @@ FUNCTION(grub_console_getkey) movb $0, %ah int $0x16 + xorl %edx, %edx movw %ax, %dx /* real_to_prot uses %eax */ DATA32 call real_to_prot .code32 - movw %dx, %ax + movl $0xff, %eax + testl %eax, %edx + jz 1f + + andl %edx, %eax + cmp %eax, 0x20 + ja 2f + movl %edx, %eax + leal LOCAL(bypass_table), %esi + movl $((LOCAL(bypass_table_end) - LOCAL(bypass_table)) / 2), %ecx + repne cmpsw + jz 3f + + addl $('a' - 1 | GRUB_TERM_CTRL), %eax + jmp 2f +3: + andl $0xff, %eax + jmp 2f + +1: movl %edx, %eax + shrl $8, %eax + orl $GRUB_TERM_EXTENDED, %eax +2: popl %ebp ret - /* * int grub_console_checkkey (void) * if there is a character pending, return it; otherwise return -1 @@ -1216,6 +1243,7 @@ FUNCTION(grub_console_checkkey) jz notpending + xorl %edx, %edx movw %ax, %dx DATA32 jmp pending @@ -1226,8 +1254,6 @@ pending: DATA32 call real_to_prot .code32 - movl %edx, %eax - popl %ebp ret diff --git a/kern/term.c b/kern/term.c index d582dbb68..04d20364a 100644 --- a/kern/term.c +++ b/kern/term.c @@ -22,11 +22,13 @@ #include #include #include +#include struct grub_term_output *grub_term_outputs_disabled; struct grub_term_input *grub_term_inputs_disabled; struct grub_term_output *grub_term_outputs; struct grub_term_input *grub_term_inputs; +struct grub_keyboard_layout *grub_current_layout; /* Put a Unicode character. */ static void @@ -76,8 +78,8 @@ grub_xputs_dumb (const char *str) void (*grub_xputs) (const char *str) = grub_xputs_dumb; -static int -grub_getkey_dumb (void) +int +grub_getkey (void) { grub_term_input_t term; @@ -89,14 +91,27 @@ grub_getkey_dumb (void) { int key = term->checkkey (term); if (key != -1) - return term->getkey (term) & 0xff; + return term->getkey (term); } grub_cpu_idle (); } } -int (*grub_getkey) (void) = grub_getkey_dumb; +int +grub_checkkey (void) +{ + grub_term_input_t term; + + FOR_ACTIVE_TERM_INPUTS(term) + { + int key = term->checkkey (term); + if (key != -1) + return key; + } + + return -1; +} void grub_refresh (void) diff --git a/term/at_keyboard.c b/term/at_keyboard.c index 5adc8b4da..492075115 100644 --- a/term/at_keyboard.c +++ b/term/at_keyboard.c @@ -42,8 +42,43 @@ static grub_uint8_t led_status; #define KEYBOARD_LED_NUM (1 << 1) #define KEYBOARD_LED_CAPS (1 << 2) -GRUB_AT_KEY_KEYBOARD_MAP (keyboard_map); -GRUB_AT_KEY_KEYBOARD_MAP_SHIFT (keyboard_map_shift); +static const unsigned keyboard_map[128] = +{ + /* 0x00 */ '\0', GRUB_TERM_ESC, '1', '2', '3', '4', '5', '6', + /* 0x08 */ '7', '8', '9', '0', '-', '=', GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, + /* 0x10 */ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', + /* 0x18 */ 'o', 'p', '[', ']', '\n', '\0', 'a', 's', + /* 0x20 */ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', + /* 0x28 */ '\'', '`', '\0', '\\', 'z', 'x', 'c', 'v', + /* 0x30 */ 'b', 'n', 'm', ',', '.', '/', '\0', '*', + /* 0x38 */ '\0', ' ', '\0', GRUB_TERM_KEY_F1, + /* 0x3c */ GRUB_TERM_KEY_F2, GRUB_TERM_KEY_F3, + /* 0x3e */ GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5, + /* 0x40 */ GRUB_TERM_KEY_F6, GRUB_TERM_KEY_F7, + /* 0x42 */ GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9, + /* 0x44 */ GRUB_TERM_KEY_F10, '\0', '\0', GRUB_TERM_KEY_HOME, + /* 0x48 */ GRUB_TERM_KEY_UP, GRUB_TERM_KEY_NPAGE, '-', GRUB_TERM_KEY_LEFT, + /* 0x4c */ GRUB_TERM_KEY_CENTER, GRUB_TERM_KEY_RIGHT, '+', GRUB_TERM_KEY_END, + /* 0x50 */ GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_PPAGE, + /* 0x52 */ GRUB_TERM_KEY_INSERT, GRUB_TERM_KEY_DC, + /* 0x54 */ '\0', '\0', '\\', GRUB_TERM_KEY_F11, + /* 0x58 */ GRUB_TERM_KEY_F12, '\0', '\0', '\0', '\0', '\0', '\0', '\0', + /* 0x60 */ '\0', '\0', '\0', '\0', + /* 0x64 */ '\0', GRUB_TERM_KEY_UP, GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_LEFT, + /* 0x68 */ GRUB_TERM_KEY_RIGHT +}; + +static unsigned keyboard_map_shift[128] = +{ + '\0', '\0', '!', '@', '#', '$', '%', '^', + '&', '*', '(', ')', '_', '+', '\0', '\0', + 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', + 'O', 'P', '{', '}', '\n', '\0', 'A', 'S', + 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', + '\"', '~', '\0', '|', 'Z', 'X', 'C', 'V', + 'B', 'N', 'M', '<', '>', '?', + [0x56] = '|' +}; static grub_uint8_t grub_keyboard_controller_orig; @@ -211,21 +246,12 @@ grub_at_keyboard_getkey_noblock (void) } if (at_keyboard_status & KEYBOARD_STATUS_ALT_L) - { - key |= GRUB_TERM_ALT; - grub_printf ("AltL"); - } + key |= GRUB_TERM_ALT; if (at_keyboard_status & KEYBOARD_STATUS_ALT_R) - { - key |= GRUB_TERM_ALT_GR; - grub_printf ("AltGr"); - } + key |= GRUB_TERM_ALT; if (at_keyboard_status & (KEYBOARD_STATUS_CTRL_L | KEYBOARD_STATUS_CTRL_R)) key |= GRUB_TERM_CTRL; - - if (at_keyboard_status & KEYBOARD_STATUS_CAPS_LOCK) - key |= GRUB_TERM_CAPS; } return key; } @@ -284,8 +310,7 @@ static struct grub_term_input grub_at_keyboard_term = .init = grub_keyboard_controller_init, .fini = grub_keyboard_controller_fini, .checkkey = grub_at_keyboard_checkkey, - .getkey = grub_at_keyboard_getkey, - .flags = GRUB_TERM_INPUT_FLAGS_TYPE_TERMCODES + .getkey = grub_at_keyboard_getkey }; GRUB_MOD_INIT(at_keyboard) diff --git a/term/i386/pc/console.c b/term/i386/pc/console.c index 1bf954874..74df4c27f 100644 --- a/term/i386/pc/console.c +++ b/term/i386/pc/console.c @@ -50,8 +50,7 @@ static struct grub_term_input grub_console_term_input = .name = "console", .checkkey = grub_console_checkkey, .getkey = grub_console_getkey, - .getkeystatus = grub_console_getkeystatus, - .flags = GRUB_TERM_INPUT_FLAGS_TYPE_BIOS + .getkeystatus = grub_console_getkeystatus }; static struct grub_term_output grub_console_term_output = diff --git a/term/usb_keyboard.c b/term/usb_keyboard.c index 9e1ce5e60..3432f700c 100644 --- a/term/usb_keyboard.c +++ b/term/usb_keyboard.c @@ -43,7 +43,7 @@ static unsigned keyboard_map[128] = '\0', GRUB_TERM_KEY_INSERT, GRUB_TERM_KEY_HOME, GRUB_TERM_KEY_PPAGE, GRUB_TERM_KEY_DC, GRUB_TERM_KEY_END, GRUB_TERM_KEY_NPAGE, GRUB_TERM_KEY_RIGHT, GRUB_TERM_KEY_LEFT, GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_UP, - [0x64] = GRUB_TERM_KEY_102 + [0x64] = '\\' }; static unsigned keyboard_map_shift[128] = @@ -56,7 +56,7 @@ static unsigned keyboard_map_shift[128] = '\n', '\0', '\0', '\0', ' ', '_', '+', '{', '}', '|', '#', ':', '"', '`', '<', '>', '?', - [0x64] = GRUB_TERM_KEY_SHIFT_102 + [0x64] = '|' }; static grub_usb_device_t usbdev; @@ -186,7 +186,7 @@ grub_usb_keyboard_checkkey (struct grub_term_input *term __attribute__ ((unused) key |= GRUB_TERM_ALT; if (data[0] & GRUB_USB_KEYBOARD_RIGHT_ALT) - key |= GRUB_TERM_ALT_GR; + key |= GRUB_TERM_ALT; #if 0 /* Wait until the key is released. */ @@ -341,7 +341,6 @@ static struct grub_term_input grub_usb_keyboard_term = .checkkey = grub_usb_keyboard_checkkey, .getkey = grub_usb_keyboard_getkey, .getkeystatus = grub_usb_keyboard_getkeystatus, - .flags = GRUB_TERM_INPUT_FLAGS_TYPE_TERMCODES, .next = 0 }; diff --git a/util/grub-fstest.c b/util/grub-fstest.c index 715dfe2dd..2c80b964c 100644 --- a/util/grub-fstest.c +++ b/util/grub-fstest.c @@ -51,14 +51,12 @@ grub_xputs_real (const char *str) void (*grub_xputs) (const char *str) = grub_xputs_real; -static int -grub_getkey_real (void) +int +grub_getkey (void) { return -1; } -int (*grub_getkey) (void) = grub_getkey_real; - void grub_refresh (void) { diff --git a/util/grub-mklayouts.c b/util/grub-mklayouts.c index 434f9f4f8..9aca88cb1 100644 --- a/util/grub-mklayouts.c +++ b/util/grub-mklayouts.c @@ -67,9 +67,6 @@ static struct console_grub_equivalence console_grub_equivalences[] = { {"", '\0'} }; -GRUB_AT_KEY_KEYBOARD_MAP (us_keyboard_map); -GRUB_AT_KEY_KEYBOARD_MAP_SHIFT (us_keyboard_map_shifted); - static void usage (int status) { @@ -201,23 +198,6 @@ write_keymaps (char *keymap, char *file_basename) sscanf (line, "keycode %u = %60s %60s %60s %60s", &keycode, normal, shift, normalalt, shiftalt); - if (keycode < ARRAY_SIZE (us_keyboard_map) - && us_keyboard_map[keycode] < ARRAY_SIZE (keyboard_map)) - { - keyboard_map[us_keyboard_map[keycode]] = get_grub_code (normal); - keyboard_map_alt[us_keyboard_map[keycode]] - = get_grub_code (normalalt); - ok = 1; - } - if (keycode < ARRAY_SIZE (us_keyboard_map_shifted) - && us_keyboard_map_shifted[keycode] < ARRAY_SIZE (keyboard_map)) - { - keyboard_map[us_keyboard_map_shifted[keycode]] - = get_grub_code (shift); - keyboard_map_alt[us_keyboard_map_shifted[keycode]] - = get_grub_code (shiftalt); - ok = 1; - } } } diff --git a/util/grub-probe.c b/util/grub-probe.c index e4d3f2906..56cbc5592 100644 --- a/util/grub-probe.c +++ b/util/grub-probe.c @@ -68,14 +68,12 @@ grub_xputs_real (const char *str) void (*grub_xputs) (const char *str) = grub_xputs_real; -static int -grub_getkey_real (void) +int +grub_getkey (void) { return -1; } -int (*grub_getkey) (void) = grub_getkey_real; - void grub_refresh (void) { diff --git a/util/i386/pc/grub-setup.c b/util/i386/pc/grub-setup.c index 4e3980965..524572fad 100644 --- a/util/i386/pc/grub-setup.c +++ b/util/i386/pc/grub-setup.c @@ -72,14 +72,12 @@ grub_xputs_real (const char *str) void (*grub_xputs) (const char *str) = grub_xputs_real; -static int -grub_getkey_real (void) +int +grub_getkey (void) { return -1; } -int (*grub_getkey) (void) = grub_getkey_real; - void grub_refresh (void) { From e55e09628d0f67ecf87b0d3b0bdad140bd48bdce Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 19 Aug 2010 15:00:31 +0200 Subject: [PATCH 021/214] Hook AT keyboard mapping --- commands/keylayouts.c | 127 ++++++++++++++++++++++++++++++- commands/keystatus.c | 6 +- include/grub/keyboard_layouts.h | 30 ++++---- include/grub/term.h | 12 ++- kern/term.c | 2 - term/at_keyboard.c | 129 ++++++-------------------------- term/i386/pc/console.c | 18 +---- term/usb_keyboard.c | 20 +++-- util/grub-mklayouts.c | 119 ++++++++++++++++++++++++----- 9 files changed, 290 insertions(+), 173 deletions(-) diff --git a/commands/keylayouts.c b/commands/keylayouts.c index bfe30d2ab..b7aee7fab 100644 --- a/commands/keylayouts.c +++ b/commands/keylayouts.c @@ -28,6 +28,115 @@ #include #include +static struct grub_keyboard_layout layout_us = { + .at = { + .keyboard_map = { + /* 0x00 */ '\0', GRUB_TERM_ESC, '1', '2', '3', '4', '5', '6', + /* 0x08 */ '7', '8', '9', '0', + /* 0x0c */ '-', '=', GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, + /* 0x10 */ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', + /* 0x18 */ 'o', 'p', '[', ']', '\n', '\0', 'a', 's', + /* 0x20 */ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', + /* 0x28 */ '\'', '`', '\0', '\\', 'z', 'x', 'c', 'v', + /* 0x30 */ 'b', 'n', 'm', ',', '.', '/', '\0', '*', + /* 0x38 */ '\0', ' ', '\0', GRUB_TERM_KEY_F1, + /* 0x3c */ GRUB_TERM_KEY_F2, GRUB_TERM_KEY_F3, + /* 0x3e */ GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5, + /* 0x40 */ GRUB_TERM_KEY_F6, GRUB_TERM_KEY_F7, + /* 0x42 */ GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9, + /* 0x44 */ GRUB_TERM_KEY_F10, '\0', '\0', GRUB_TERM_KEY_HOME, + /* 0x48 */ GRUB_TERM_KEY_UP, GRUB_TERM_KEY_NPAGE, '-', GRUB_TERM_KEY_LEFT, + /* 0x4c */ GRUB_TERM_KEY_CENTER, GRUB_TERM_KEY_RIGHT, + /* 0x4e */ '+', GRUB_TERM_KEY_END, + /* 0x50 */ GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_PPAGE, + /* 0x52 */ GRUB_TERM_KEY_INSERT, GRUB_TERM_KEY_DC, + /* 0x54 */ '\0', '\0', '\\', GRUB_TERM_KEY_F11, + /* 0x58 */ GRUB_TERM_KEY_F12, '\0', '\0', '\0', '\0', '\0', '\0', '\0', + /* 0x60 */ '\0', '\0', '\0', '\0', + /* 0x64 */ '\0', GRUB_TERM_KEY_UP, GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_LEFT, + /* 0x68 */ GRUB_TERM_KEY_RIGHT + }, + .keyboard_map_shift = { + '\0', '\0', '!', '@', '#', '$', '%', '^', + '&', '*', '(', ')', '_', '+', '\0', '\0', + 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', + 'O', 'P', '{', '}', '\n', '\0', 'A', 'S', + 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', + '\"', '~', '\0', '|', 'Z', 'X', 'C', 'V', + 'B', 'N', 'M', '<', '>', '?', + [0x56] = '|' + } + } +}; + +static struct grub_keyboard_layout *grub_current_layout = &layout_us; + +static int +map_key_core (int code, int status, int *alt_gr_consumed) +{ + *alt_gr_consumed = 0; + + if (status & GRUB_TERM_STATUS_RALT) + { + if (status & (GRUB_TERM_STATUS_LSHIFT | GRUB_TERM_STATUS_RSHIFT)) + { + if (grub_current_layout->at.keyboard_map_shift_l3[code]) + { + *alt_gr_consumed = 1; + return grub_current_layout->at.keyboard_map_shift_l3[code]; + } + else if (grub_current_layout->at.keyboard_map_shift[code]) + { + *alt_gr_consumed = 1; + return grub_current_layout->at.keyboard_map_l3[code] + | GRUB_TERM_SHIFT; + } + } + else if (grub_current_layout->at.keyboard_map_shift[code]) + { + *alt_gr_consumed = 1; + return grub_current_layout->at.keyboard_map_l3[code]; + } + } + if (status & (GRUB_TERM_STATUS_LSHIFT | GRUB_TERM_STATUS_RSHIFT)) + { + if (grub_current_layout->at.keyboard_map_shift[code]) + return grub_current_layout->at.keyboard_map_shift[code]; + else + return grub_current_layout->at.keyboard_map[code] | GRUB_TERM_SHIFT; + } + else + return grub_current_layout->at.keyboard_map[code]; +} + +unsigned +grub_term_map_key (int code, int status) +{ + int alt_gr_consumed; + int key; + + key = map_key_core (code, status, &alt_gr_consumed); + + if (key == 0 || key == GRUB_TERM_SHIFT) + grub_dprintf ("atkeyb", "Unknown key 0x%x detected\n", code); + + if (status & GRUB_TERM_STATUS_CAPS) + { + if ((key >= 'a') && (key <= 'z')) + key += 'A' - 'a'; + else if ((key >= 'A') && (key <= 'Z')) + key += 'a' - 'A'; + } + + if ((status & GRUB_TERM_STATUS_LALT) || + ((status & GRUB_TERM_STATUS_RALT) && !alt_gr_consumed)) + key |= GRUB_TERM_ALT; + if (status & (GRUB_TERM_STATUS_LCTRL | GRUB_TERM_STATUS_RCTRL)) + key |= GRUB_TERM_CTRL; + + return key; +} + static grub_err_t grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)), int argc, char *argv[]) @@ -110,6 +219,23 @@ grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)), newmap->at.keyboard_map_shift_l3[i] = grub_le_to_cpu32(newmap->at.keyboard_map_shift_l3[i]); + for (i = 0; i < ARRAY_SIZE (newmap->usb.keyboard_map); i++) + newmap->usb.keyboard_map[i] = grub_le_to_cpu32(newmap->usb.keyboard_map[i]); + + for (i = 0; i < ARRAY_SIZE (newmap->usb.keyboard_map_shift); i++) + newmap->usb.keyboard_map_shift[i] + = grub_le_to_cpu32(newmap->usb.keyboard_map_shift[i]); + + for (i = 0; i < ARRAY_SIZE (newmap->usb.keyboard_map_l3); i++) + newmap->usb.keyboard_map_l3[i] + = grub_le_to_cpu32(newmap->usb.keyboard_map_l3[i]); + + for (i = 0; i < ARRAY_SIZE (newmap->usb.keyboard_map_shift_l3); i++) + newmap->usb.keyboard_map_shift_l3[i] + = grub_le_to_cpu32(newmap->usb.keyboard_map_shift_l3[i]); + + grub_current_layout = newmap; + return GRUB_ERR_NONE; fail: @@ -131,6 +257,5 @@ GRUB_MOD_INIT(keylayouts) GRUB_MOD_FINI(keylayouts) { - grub_current_layout = NULL; grub_unregister_command (cmd); } diff --git a/commands/keystatus.c b/commands/keystatus.c index 9db92b942..9c7ab84b0 100644 --- a/commands/keystatus.c +++ b/commands/keystatus.c @@ -56,11 +56,11 @@ grub_cmd_keystatus (grub_extcmd_t cmd, int mods; if (state[0].set) - expect_mods |= GRUB_TERM_STATUS_SHIFT; + expect_mods |= (GRUB_TERM_STATUS_LSHIFT | GRUB_TERM_STATUS_RSHIFT); if (state[1].set) - expect_mods |= GRUB_TERM_STATUS_CTRL; + expect_mods |= (GRUB_TERM_STATUS_LCTRL | GRUB_TERM_STATUS_RCTRL); if (state[2].set) - expect_mods |= GRUB_TERM_STATUS_ALT; + expect_mods |= (GRUB_TERM_STATUS_LALT | GRUB_TERM_STATUS_RALT); grub_dprintf ("keystatus", "expect_mods: %d\n", expect_mods); diff --git a/include/grub/keyboard_layouts.h b/include/grub/keyboard_layouts.h index 2d6e3d54c..6d4b620c2 100644 --- a/include/grub/keyboard_layouts.h +++ b/include/grub/keyboard_layouts.h @@ -21,28 +21,24 @@ #define GRUB_KEYBOARD_LAYOUTS_FILEMAGIC "GRUBLAYO" #define GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE (sizeof(GRUB_KEYBOARD_LAYOUTS_FILEMAGIC) - 1) -#define GRUB_KEYBOARD_LAYOUTS_VERSION 4 +#define GRUB_KEYBOARD_LAYOUTS_VERSION 5 #define GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE 128 -struct grub_keyboard_layout +struct grub_keyboard_layout_kbd { - struct - { - grub_uint32_t keyboard_map[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; - grub_uint32_t keyboard_map_shift[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; - grub_uint32_t keyboard_map_l3[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; - grub_uint32_t keyboard_map_shift_l3[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; - } at; - struct - { - grub_uint32_t keyboard_map[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; - grub_uint32_t keyboard_map_shift[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; - grub_uint32_t keyboard_map_l3[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; - grub_uint32_t keyboard_map_shift_l3[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; - } usb; + grub_uint32_t keyboard_map[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; + grub_uint32_t keyboard_map_shift[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; + grub_uint32_t keyboard_map_l3[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; + grub_uint32_t keyboard_map_shift_l3[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; }; -struct grub_keyboard_layout *EXPORT_VAR (grub_current_layout); +struct grub_keyboard_layout +{ + struct grub_keyboard_layout_kbd at; + struct grub_keyboard_layout_kbd usb; +}; + +unsigned grub_term_map_key (int code, int status); #endif /* GRUB_KEYBOARD_LAYOUTS */ diff --git a/include/grub/term.h b/include/grub/term.h index 036e8caaa..de430d66f 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -110,9 +110,15 @@ grub_term_color_state; /* Bitmasks for modifier keys returned by grub_getkeystatus. */ -#define GRUB_TERM_STATUS_SHIFT (1 << 0) -#define GRUB_TERM_STATUS_CTRL (1 << 1) -#define GRUB_TERM_STATUS_ALT (1 << 2) +#define GRUB_TERM_STATUS_RSHIFT (1 << 0) +#define GRUB_TERM_STATUS_LSHIFT (1 << 1) +#define GRUB_TERM_STATUS_RCTRL (1 << 2) +#define GRUB_TERM_STATUS_RALT (1 << 3) +#define GRUB_TERM_STATUS_SCROLL (1 << 4) +#define GRUB_TERM_STATUS_NUM (1 << 5) +#define GRUB_TERM_STATUS_CAPS (1 << 6) +#define GRUB_TERM_STATUS_LCTRL (1 << 8) +#define GRUB_TERM_STATUS_LALT (1 << 9) /* Menu-related geometrical constants. */ diff --git a/kern/term.c b/kern/term.c index 04d20364a..6ddf63208 100644 --- a/kern/term.c +++ b/kern/term.c @@ -22,13 +22,11 @@ #include #include #include -#include struct grub_term_output *grub_term_outputs_disabled; struct grub_term_input *grub_term_inputs_disabled; struct grub_term_output *grub_term_outputs; struct grub_term_input *grub_term_inputs; -struct grub_keyboard_layout *grub_current_layout; /* Put a Unicode character. */ static void diff --git a/term/at_keyboard.c b/term/at_keyboard.c index 492075115..054dc9805 100644 --- a/term/at_keyboard.c +++ b/term/at_keyboard.c @@ -22,64 +22,18 @@ #include #include #include +#include static short at_keyboard_status = 0; +static int extended_pending = 0; static int pending_key = -1; -#define KEYBOARD_STATUS_SHIFT_L (1 << 0) -#define KEYBOARD_STATUS_SHIFT_R (1 << 1) -#define KEYBOARD_STATUS_ALT_L (1 << 2) -#define KEYBOARD_STATUS_ALT_R (1 << 3) -#define KEYBOARD_STATUS_CTRL_L (1 << 4) -#define KEYBOARD_STATUS_CTRL_R (1 << 5) -#define KEYBOARD_STATUS_CAPS_LOCK (1 << 6) -#define KEYBOARD_STATUS_NUM_LOCK (1 << 7) -#define KEYBOARD_STATUS_EXTENDED (1 << 8) - static grub_uint8_t led_status; #define KEYBOARD_LED_SCROLL (1 << 0) #define KEYBOARD_LED_NUM (1 << 1) #define KEYBOARD_LED_CAPS (1 << 2) -static const unsigned keyboard_map[128] = -{ - /* 0x00 */ '\0', GRUB_TERM_ESC, '1', '2', '3', '4', '5', '6', - /* 0x08 */ '7', '8', '9', '0', '-', '=', GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, - /* 0x10 */ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', - /* 0x18 */ 'o', 'p', '[', ']', '\n', '\0', 'a', 's', - /* 0x20 */ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', - /* 0x28 */ '\'', '`', '\0', '\\', 'z', 'x', 'c', 'v', - /* 0x30 */ 'b', 'n', 'm', ',', '.', '/', '\0', '*', - /* 0x38 */ '\0', ' ', '\0', GRUB_TERM_KEY_F1, - /* 0x3c */ GRUB_TERM_KEY_F2, GRUB_TERM_KEY_F3, - /* 0x3e */ GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5, - /* 0x40 */ GRUB_TERM_KEY_F6, GRUB_TERM_KEY_F7, - /* 0x42 */ GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9, - /* 0x44 */ GRUB_TERM_KEY_F10, '\0', '\0', GRUB_TERM_KEY_HOME, - /* 0x48 */ GRUB_TERM_KEY_UP, GRUB_TERM_KEY_NPAGE, '-', GRUB_TERM_KEY_LEFT, - /* 0x4c */ GRUB_TERM_KEY_CENTER, GRUB_TERM_KEY_RIGHT, '+', GRUB_TERM_KEY_END, - /* 0x50 */ GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_PPAGE, - /* 0x52 */ GRUB_TERM_KEY_INSERT, GRUB_TERM_KEY_DC, - /* 0x54 */ '\0', '\0', '\\', GRUB_TERM_KEY_F11, - /* 0x58 */ GRUB_TERM_KEY_F12, '\0', '\0', '\0', '\0', '\0', '\0', '\0', - /* 0x60 */ '\0', '\0', '\0', '\0', - /* 0x64 */ '\0', GRUB_TERM_KEY_UP, GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_LEFT, - /* 0x68 */ GRUB_TERM_KEY_RIGHT -}; - -static unsigned keyboard_map_shift[128] = -{ - '\0', '\0', '!', '@', '#', '$', '%', '^', - '&', '*', '(', ')', '_', '+', '\0', '\0', - 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', - 'O', 'P', '{', '}', '\n', '\0', 'A', 'S', - 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', - '\"', '~', '\0', '|', 'Z', 'X', 'C', 'V', - 'B', 'N', 'M', '<', '>', '?', - [0x56] = '|' -}; - static grub_uint8_t grub_keyboard_controller_orig; static void @@ -122,45 +76,41 @@ grub_keyboard_isr (grub_uint8_t key) switch (KEYBOARD_SCANCODE (key)) { case SHIFT_L: - at_keyboard_status |= KEYBOARD_STATUS_SHIFT_L; + at_keyboard_status |= GRUB_TERM_STATUS_LSHIFT; break; case SHIFT_R: - at_keyboard_status |= KEYBOARD_STATUS_SHIFT_R; + at_keyboard_status |= GRUB_TERM_STATUS_RSHIFT; break; case CTRL: - at_keyboard_status |= KEYBOARD_STATUS_CTRL_L; + at_keyboard_status |= GRUB_TERM_STATUS_LCTRL; break; case ALT: - if (at_keyboard_status & KEYBOARD_STATUS_EXTENDED) - at_keyboard_status |= KEYBOARD_STATUS_ALT_R; + if (extended_pending) + at_keyboard_status |= GRUB_TERM_STATUS_RALT; else - at_keyboard_status |= KEYBOARD_STATUS_ALT_L; + at_keyboard_status |= GRUB_TERM_STATUS_LALT; break; } else switch (KEYBOARD_SCANCODE (key)) { case SHIFT_L: - at_keyboard_status &= ~KEYBOARD_STATUS_SHIFT_L; + at_keyboard_status &= ~GRUB_TERM_STATUS_LSHIFT; break; case SHIFT_R: - at_keyboard_status &= ~KEYBOARD_STATUS_SHIFT_R; + at_keyboard_status &= ~GRUB_TERM_STATUS_RSHIFT; break; case CTRL: - at_keyboard_status &= ~KEYBOARD_STATUS_CTRL_L; + at_keyboard_status &= ~GRUB_TERM_STATUS_LCTRL; break; case ALT: - if (at_keyboard_status & KEYBOARD_STATUS_EXTENDED) - at_keyboard_status &= ~KEYBOARD_STATUS_ALT_R; + if (extended_pending) + at_keyboard_status &= ~GRUB_TERM_STATUS_RALT; else - at_keyboard_status &= ~KEYBOARD_STATUS_ALT_L; + at_keyboard_status &= ~GRUB_TERM_STATUS_LALT; break; } - if (key == 0xe0) - at_keyboard_status |= KEYBOARD_STATUS_EXTENDED; - else - at_keyboard_status &= ~KEYBOARD_STATUS_EXTENDED; - + extended_pending = (key == 0xe0); } /* If there is a raw key pending, return it; otherwise return -1. */ @@ -177,11 +127,12 @@ grub_keyboard_getkey (void) return (KEYBOARD_SCANCODE (key)); } + /* If there is a character pending, return it; otherwise return -1. */ static int grub_at_keyboard_getkey_noblock (void) { - int code, key; + int code; code = grub_keyboard_getkey (); if (code == -1) return -1; @@ -194,66 +145,34 @@ grub_at_keyboard_getkey_noblock (void) /* Caps lock sends scan code twice. Get the second one and discard it. */ while (grub_keyboard_getkey () == -1); - at_keyboard_status ^= KEYBOARD_STATUS_CAPS_LOCK; + at_keyboard_status ^= GRUB_TERM_STATUS_CAPS; led_status ^= KEYBOARD_LED_CAPS; keyboard_controller_led (led_status); #ifdef DEBUG_AT_KEYBOARD grub_dprintf ("atkeyb", "caps_lock = %d\n", !!(at_keyboard_status & KEYBOARD_STATUS_CAPS_LOCK)); #endif - key = -1; - break; + return -1; case NUM_LOCK: /* Num lock sends scan code twice. Get the second one and discard it. */ while (grub_keyboard_getkey () == -1); - at_keyboard_status ^= KEYBOARD_STATUS_NUM_LOCK; + at_keyboard_status ^= GRUB_TERM_STATUS_NUM; led_status ^= KEYBOARD_LED_NUM; keyboard_controller_led (led_status); #ifdef DEBUG_AT_KEYBOARD grub_dprintf ("atkeyb", "num_lock = %d\n", !!(at_keyboard_status & KEYBOARD_STATUS_NUM_LOCK)); #endif - key = -1; - break; + return -1; case SCROLL_LOCK: - /* For scroll lock we don't keep track of status. Only update its led. */ + at_keyboard_status ^= GRUB_TERM_STATUS_SCROLL; led_status ^= KEYBOARD_LED_SCROLL; keyboard_controller_led (led_status); - key = -1; - break; + return -1; default: - if (at_keyboard_status & (KEYBOARD_STATUS_SHIFT_L - | KEYBOARD_STATUS_SHIFT_R)) - { - if (keyboard_map_shift[code]) - key = keyboard_map_shift[code]; - else - key = keyboard_map[code] | GRUB_TERM_SHIFT; - } - else - key = keyboard_map[code]; - - if (key == 0) - grub_dprintf ("atkeyb", "Unknown key 0x%x detected\n", code); - - if (at_keyboard_status & KEYBOARD_STATUS_CAPS_LOCK) - { - if ((key >= 'a') && (key <= 'z')) - key += 'A' - 'a'; - else if ((key >= 'A') && (key <= 'Z')) - key += 'a' - 'A'; - } - - if (at_keyboard_status & KEYBOARD_STATUS_ALT_L) - key |= GRUB_TERM_ALT; - if (at_keyboard_status & KEYBOARD_STATUS_ALT_R) - key |= GRUB_TERM_ALT; - if (at_keyboard_status & (KEYBOARD_STATUS_CTRL_L - | KEYBOARD_STATUS_CTRL_R)) - key |= GRUB_TERM_CTRL; + return grub_term_map_key (code, at_keyboard_status); } - return key; } static int diff --git a/term/i386/pc/console.c b/term/i386/pc/console.c index 74df4c27f..009647c4c 100644 --- a/term/i386/pc/console.c +++ b/term/i386/pc/console.c @@ -24,25 +24,11 @@ static const struct grub_machine_bios_data_area *bios_data_area = (struct grub_machine_bios_data_area *) GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR; -#define KEYBOARD_LEFT_SHIFT (1 << 0) -#define KEYBOARD_RIGHT_SHIFT (1 << 1) -#define KEYBOARD_CTRL (1 << 2) -#define KEYBOARD_ALT (1 << 3) - static int grub_console_getkeystatus (struct grub_term_input *term __attribute__ ((unused))) { - grub_uint8_t status = bios_data_area->keyboard_flag_lower; - int mods = 0; - - if (status & (KEYBOARD_LEFT_SHIFT | KEYBOARD_RIGHT_SHIFT)) - mods |= GRUB_TERM_STATUS_SHIFT; - if (status & KEYBOARD_CTRL) - mods |= GRUB_TERM_STATUS_CTRL; - if (status & KEYBOARD_ALT) - mods |= GRUB_TERM_STATUS_ALT; - - return mods; + /* conveniently GRUB keystatus is modelled after BIOS one. */ + return bios_data_area->keyboard_flag_lower & ~0x80; } static struct grub_term_input grub_console_term_input = diff --git a/term/usb_keyboard.c b/term/usb_keyboard.c index 3432f700c..f35cc4b65 100644 --- a/term/usb_keyboard.c +++ b/term/usb_keyboard.c @@ -163,7 +163,7 @@ grub_usb_keyboard_checkkey (struct grub_term_input *term __attribute__ ((unused) /* Check if the Shift key was pressed. */ if (data[0] & GRUB_USB_KEYBOARD_LEFT_SHIFT - || data[0] & GRUB_USB_KEYBOARD_RIGHT_SHIFT) + || data[0] & GRUB_USB_KEYBOARD_RIGHT_SHIFT) { if (keyboard_map_shift[data[2]]) key = keyboard_map_shift[data[2]]; @@ -323,12 +323,18 @@ grub_usb_keyboard_getkeystatus (struct grub_term_input *term __attribute__ ((unu data[4], data[5], data[6], data[7]); /* Check Shift, Control, and Alt status. */ - if (data[0] & 0x02 || data[0] & 0x20) - mods |= GRUB_TERM_STATUS_SHIFT; - if (data[0] & 0x01 || data[0] & 0x10) - mods |= GRUB_TERM_STATUS_CTRL; - if (data[0] & 0x04 || data[0] & 0x40) - mods |= GRUB_TERM_STATUS_ALT; + if (data[0] & GRUB_USB_KEYBOARD_LEFT_SHIFT) + mods |= GRUB_TERM_STATUS_LSHIFT; + if (data[0] & GRUB_USB_KEYBOARD_RIGHT_SHIFT) + mods |= GRUB_TERM_STATUS_RSHIFT; + if (data[0] & GRUB_USB_KEYBOARD_LEFT_CTRL) + mods |= GRUB_TERM_STATUS_LCTRL; + if (data[0] & GRUB_USB_KEYBOARD_RIGHT_CTRL) + mods |= GRUB_TERM_STATUS_RCTRL; + if (data[0] & GRUB_USB_KEYBOARD_LEFT_ALT) + mods |= GRUB_TERM_STATUS_LALT; + if (data[0] & GRUB_USB_KEYBOARD_RIGHT_ALT) + mods |= GRUB_TERM_STATUS_RALT; grub_errno = GRUB_ERR_NONE; diff --git a/util/grub-mklayouts.c b/util/grub-mklayouts.c index 9aca88cb1..43aa745a5 100644 --- a/util/grub-mklayouts.c +++ b/util/grub-mklayouts.c @@ -46,6 +46,26 @@ struct console_grub_equivalence grub_uint32_t grub; }; +static int at_to_usb_map[128] = +{ + 0, 41, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 45, 46, 42, 43, + 20, 26, 8, 21, 23, 28, 24, 12, + 18, 19, 47, 48, 40, 0, 4, 22, + 7, 9, 10, 11, 13, 14, 15, 51, + 52, 53, 0, 49, 29, 27, 6, 25, + 5, 17, 16, 54, 55, 56, 0, 0, + 0, 44, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 74, + 82, 78, 45, 80, 0, 79, 0, 77, + 81, 75, 0, 76, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + static struct console_grub_equivalence console_grub_equivalences[] = { {"KP_1", '1'}, {"KP_2", '2'}, @@ -85,7 +105,26 @@ Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT); exit (status); } -char +void +add_special_keys (struct grub_keyboard_layout *layout) +{ + layout->at.keyboard_map[71] = GRUB_TERM_KEY_HOME; + layout->at.keyboard_map[72] = GRUB_TERM_KEY_UP; + layout->at.keyboard_map[73] = GRUB_TERM_KEY_NPAGE; + layout->at.keyboard_map[75] = GRUB_TERM_KEY_LEFT; + layout->at.keyboard_map[77] = GRUB_TERM_KEY_RIGHT; + layout->at.keyboard_map[79] = GRUB_TERM_KEY_END; + layout->at.keyboard_map[80] = GRUB_TERM_KEY_DOWN; + layout->at.keyboard_map[81] = GRUB_TERM_KEY_PPAGE; + layout->at.keyboard_map[83] = GRUB_TERM_KEY_DC; + + layout->at.keyboard_map[101] = GRUB_TERM_KEY_UP; + layout->at.keyboard_map[102] = GRUB_TERM_KEY_DOWN; + layout->at.keyboard_map[103] = GRUB_TERM_KEY_LEFT; + layout->at.keyboard_map[104] = GRUB_TERM_KEY_RIGHT; +} + +static char lookup (char *code) { int i; @@ -97,7 +136,7 @@ lookup (char *code) return '\0'; } -unsigned int +static unsigned int get_grub_code (char *layout_code) { unsigned int code; @@ -111,9 +150,8 @@ get_grub_code (char *layout_code) return code; } -void -write_file (char* filename, grub_uint32_t *keyboard_map, - grub_uint32_t *keyboard_map_alt) +static void +write_file (char* filename, struct grub_keyboard_layout *layout) { FILE *fp_output; grub_uint32_t version; @@ -121,11 +159,35 @@ write_file (char* filename, grub_uint32_t *keyboard_map, version = grub_cpu_to_le32 (GRUB_KEYBOARD_LAYOUTS_VERSION); - for (i = 0; i < GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE; i++) - keyboard_map[i] = grub_cpu_to_le32 (keyboard_map[i]); + for (i = 0; i < ARRAY_SIZE (layout->at.keyboard_map); i++) + layout->at.keyboard_map[i] = grub_cpu_to_le32(layout->at.keyboard_map[i]); - for (i = 0; i < GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE; i++) - keyboard_map_alt[i] = grub_cpu_to_le32 (keyboard_map_alt[i]); + for (i = 0; i < ARRAY_SIZE (layout->at.keyboard_map_shift); i++) + layout->at.keyboard_map_shift[i] + = grub_cpu_to_le32(layout->at.keyboard_map_shift[i]); + + for (i = 0; i < ARRAY_SIZE (layout->at.keyboard_map_l3); i++) + layout->at.keyboard_map_l3[i] + = grub_cpu_to_le32(layout->at.keyboard_map_l3[i]); + + for (i = 0; i < ARRAY_SIZE (layout->at.keyboard_map_shift_l3); i++) + layout->at.keyboard_map_shift_l3[i] + = grub_cpu_to_le32(layout->at.keyboard_map_shift_l3[i]); + + for (i = 0; i < ARRAY_SIZE (layout->usb.keyboard_map); i++) + layout->usb.keyboard_map[i] = grub_cpu_to_le32(layout->usb.keyboard_map[i]); + + for (i = 0; i < ARRAY_SIZE (layout->usb.keyboard_map_shift); i++) + layout->usb.keyboard_map_shift[i] + = grub_cpu_to_le32(layout->usb.keyboard_map_shift[i]); + + for (i = 0; i < ARRAY_SIZE (layout->usb.keyboard_map_l3); i++) + layout->usb.keyboard_map_l3[i] + = grub_cpu_to_le32(layout->usb.keyboard_map_l3[i]); + + for (i = 0; i < ARRAY_SIZE (layout->usb.keyboard_map_shift_l3); i++) + layout->usb.keyboard_map_shift_l3[i] + = grub_cpu_to_le32(layout->usb.keyboard_map_shift_l3[i]); fp_output = fopen (filename, "w"); @@ -138,23 +200,19 @@ write_file (char* filename, grub_uint32_t *keyboard_map, fwrite (GRUB_KEYBOARD_LAYOUTS_FILEMAGIC, 1, GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE, fp_output); fwrite (&version, sizeof (version), 1, fp_output); - fwrite (keyboard_map, sizeof (keyboard_map[0]), - GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE, fp_output); - fwrite (keyboard_map_alt, sizeof (keyboard_map_alt[0]), - GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE, fp_output); + fwrite (layout, 1, sizeof (*layout), fp_output); fclose (fp_output); } -void +static void write_keymaps (char *keymap, char *file_basename) { - grub_uint32_t keyboard_map[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; - grub_uint32_t keyboard_map_alt[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; - + struct grub_keyboard_layout layout; char line[2048]; pid_t pid; int pipe_communication[2]; int ok; + unsigned i; FILE *fp_pipe; @@ -182,7 +240,7 @@ write_keymaps (char *keymap, char *file_basename) close (pipe_communication[1]); fp_pipe = fdopen (pipe_communication[0], "r"); - memset (keyboard_map, 0, sizeof (keyboard_map)); + memset (&layout, 0, sizeof (layout)); /* Process the ckbcomp output and prepare the layouts. */ ok = 0; @@ -198,9 +256,30 @@ write_keymaps (char *keymap, char *file_basename) sscanf (line, "keycode %u = %60s %60s %60s %60s", &keycode, normal, shift, normalalt, shiftalt); + if (keycode < GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE) + { + layout.at.keyboard_map[keycode] = get_grub_code (normal); + layout.at.keyboard_map_shift[keycode] = get_grub_code (shift); + layout.at.keyboard_map_l3[keycode] = get_grub_code (normalalt); + layout.at.keyboard_map_shift_l3[keycode] + = get_grub_code (shiftalt); + ok = 1; + } } } + for (i = 0; i < GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE; i++) + { + layout.usb.keyboard_map[at_to_usb_map[i]] = layout.at.keyboard_map[i]; + layout.usb.keyboard_map_shift[at_to_usb_map[i]] + = layout.at.keyboard_map_shift[i]; + layout.usb.keyboard_map_l3[at_to_usb_map[i]] + = layout.at.keyboard_map_l3[i]; + layout.usb.keyboard_map_shift_l3[at_to_usb_map[i]] + = layout.at.keyboard_map_shift_l3[i]; + } + + if (ok == 0) { fprintf (stderr, "ERROR: no keycodes found. Check output of %s %s.\n", @@ -208,7 +287,9 @@ write_keymaps (char *keymap, char *file_basename) exit (1); } - write_file (file_basename, keyboard_map, keyboard_map_alt); + add_special_keys (&layout); + + write_file (file_basename, &layout); } int From 5ef4e08416445b1b4245b09bc80725d4aca45f82 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 19 Aug 2010 15:32:43 +0200 Subject: [PATCH 022/214] add usb keymap support --- commands/keylayouts.c | 128 ++++++++++++--------------- include/grub/keyboard_layouts.h | 10 +-- term/usb_keyboard.c | 151 +++++++++++++++----------------- util/grub-mklayouts.c | 103 ++++++---------------- 4 files changed, 157 insertions(+), 235 deletions(-) diff --git a/commands/keylayouts.c b/commands/keylayouts.c index b7aee7fab..df8b95e02 100644 --- a/commands/keylayouts.c +++ b/commands/keylayouts.c @@ -29,43 +29,40 @@ #include static struct grub_keyboard_layout layout_us = { - .at = { - .keyboard_map = { - /* 0x00 */ '\0', GRUB_TERM_ESC, '1', '2', '3', '4', '5', '6', - /* 0x08 */ '7', '8', '9', '0', - /* 0x0c */ '-', '=', GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, - /* 0x10 */ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', - /* 0x18 */ 'o', 'p', '[', ']', '\n', '\0', 'a', 's', - /* 0x20 */ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', - /* 0x28 */ '\'', '`', '\0', '\\', 'z', 'x', 'c', 'v', - /* 0x30 */ 'b', 'n', 'm', ',', '.', '/', '\0', '*', - /* 0x38 */ '\0', ' ', '\0', GRUB_TERM_KEY_F1, - /* 0x3c */ GRUB_TERM_KEY_F2, GRUB_TERM_KEY_F3, - /* 0x3e */ GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5, - /* 0x40 */ GRUB_TERM_KEY_F6, GRUB_TERM_KEY_F7, - /* 0x42 */ GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9, - /* 0x44 */ GRUB_TERM_KEY_F10, '\0', '\0', GRUB_TERM_KEY_HOME, - /* 0x48 */ GRUB_TERM_KEY_UP, GRUB_TERM_KEY_NPAGE, '-', GRUB_TERM_KEY_LEFT, - /* 0x4c */ GRUB_TERM_KEY_CENTER, GRUB_TERM_KEY_RIGHT, - /* 0x4e */ '+', GRUB_TERM_KEY_END, - /* 0x50 */ GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_PPAGE, - /* 0x52 */ GRUB_TERM_KEY_INSERT, GRUB_TERM_KEY_DC, - /* 0x54 */ '\0', '\0', '\\', GRUB_TERM_KEY_F11, - /* 0x58 */ GRUB_TERM_KEY_F12, '\0', '\0', '\0', '\0', '\0', '\0', '\0', - /* 0x60 */ '\0', '\0', '\0', '\0', - /* 0x64 */ '\0', GRUB_TERM_KEY_UP, GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_LEFT, - /* 0x68 */ GRUB_TERM_KEY_RIGHT - }, - .keyboard_map_shift = { - '\0', '\0', '!', '@', '#', '$', '%', '^', - '&', '*', '(', ')', '_', '+', '\0', '\0', - 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', - 'O', 'P', '{', '}', '\n', '\0', 'A', 'S', - 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', - '\"', '~', '\0', '|', 'Z', 'X', 'C', 'V', - 'B', 'N', 'M', '<', '>', '?', - [0x56] = '|' - } + .keyboard_map = { + /* 0x00 */ '\0', GRUB_TERM_ESC, '1', '2', '3', '4', '5', '6', + /* 0x08 */ '7', '8', '9', '0', '-', '=', GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, + /* 0x10 */ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', + /* 0x18 */ 'o', 'p', '[', ']', '\n', '\0', 'a', 's', + /* 0x20 */ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', + /* 0x28 */ '\'', '`', '\0', '\\', 'z', 'x', 'c', 'v', + /* 0x30 */ 'b', 'n', 'm', ',', '.', '/', '\0', '*', + /* 0x38 */ '\0', ' ', '\0', GRUB_TERM_KEY_F1, + /* 0x3c */ GRUB_TERM_KEY_F2, GRUB_TERM_KEY_F3, + /* 0x3e */ GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5, + /* 0x40 */ GRUB_TERM_KEY_F6, GRUB_TERM_KEY_F7, + /* 0x42 */ GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9, + /* 0x44 */ GRUB_TERM_KEY_F10, '\0', '\0', GRUB_TERM_KEY_HOME, + /* 0x48 */ GRUB_TERM_KEY_UP, GRUB_TERM_KEY_NPAGE, '-', GRUB_TERM_KEY_LEFT, + /* 0x4c */ GRUB_TERM_KEY_CENTER, GRUB_TERM_KEY_RIGHT, + /* 0x4e */ '+', GRUB_TERM_KEY_END, + /* 0x50 */ GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_PPAGE, + /* 0x52 */ GRUB_TERM_KEY_INSERT, GRUB_TERM_KEY_DC, + /* 0x54 */ '\0', '\0', '\\', GRUB_TERM_KEY_F11, + /* 0x58 */ GRUB_TERM_KEY_F12, '\0', '\0', '\0', '\0', '\0', '\0', '\0', + /* 0x60 */ '\0', '\0', '\0', '\0', + /* 0x64 */ '\0', GRUB_TERM_KEY_UP, GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_LEFT, + /* 0x68 */ GRUB_TERM_KEY_RIGHT + }, + .keyboard_map_shift = { + '\0', '\0', '!', '@', '#', '$', '%', '^', + '&', '*', '(', ')', '_', '+', '\0', '\0', + 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', + 'O', 'P', '{', '}', '\n', '\0', 'A', 'S', + 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', + '\"', '~', '\0', '|', 'Z', 'X', 'C', 'V', + 'B', 'N', 'M', '<', '>', '?', + [0x56] = '|' } }; @@ -80,33 +77,33 @@ map_key_core (int code, int status, int *alt_gr_consumed) { if (status & (GRUB_TERM_STATUS_LSHIFT | GRUB_TERM_STATUS_RSHIFT)) { - if (grub_current_layout->at.keyboard_map_shift_l3[code]) + if (grub_current_layout->keyboard_map_shift_l3[code]) { *alt_gr_consumed = 1; - return grub_current_layout->at.keyboard_map_shift_l3[code]; + return grub_current_layout->keyboard_map_shift_l3[code]; } - else if (grub_current_layout->at.keyboard_map_shift[code]) + else if (grub_current_layout->keyboard_map_shift[code]) { *alt_gr_consumed = 1; - return grub_current_layout->at.keyboard_map_l3[code] + return grub_current_layout->keyboard_map_l3[code] | GRUB_TERM_SHIFT; } } - else if (grub_current_layout->at.keyboard_map_shift[code]) + else if (grub_current_layout->keyboard_map_shift[code]) { *alt_gr_consumed = 1; - return grub_current_layout->at.keyboard_map_l3[code]; + return grub_current_layout->keyboard_map_l3[code]; } } if (status & (GRUB_TERM_STATUS_LSHIFT | GRUB_TERM_STATUS_RSHIFT)) { - if (grub_current_layout->at.keyboard_map_shift[code]) - return grub_current_layout->at.keyboard_map_shift[code]; + if (grub_current_layout->keyboard_map_shift[code]) + return grub_current_layout->keyboard_map_shift[code]; else - return grub_current_layout->at.keyboard_map[code] | GRUB_TERM_SHIFT; + return grub_current_layout->keyboard_map[code] | GRUB_TERM_SHIFT; } else - return grub_current_layout->at.keyboard_map[code]; + return grub_current_layout->keyboard_map[code]; } unsigned @@ -204,35 +201,20 @@ grub_cmd_keymap (struct grub_command *cmd __attribute__ ((unused)), goto fail; } - for (i = 0; i < ARRAY_SIZE (newmap->at.keyboard_map); i++) - newmap->at.keyboard_map[i] = grub_le_to_cpu32(newmap->at.keyboard_map[i]); + for (i = 0; i < ARRAY_SIZE (newmap->keyboard_map); i++) + newmap->keyboard_map[i] = grub_le_to_cpu32(newmap->keyboard_map[i]); - for (i = 0; i < ARRAY_SIZE (newmap->at.keyboard_map_shift); i++) - newmap->at.keyboard_map_shift[i] - = grub_le_to_cpu32(newmap->at.keyboard_map_shift[i]); + for (i = 0; i < ARRAY_SIZE (newmap->keyboard_map_shift); i++) + newmap->keyboard_map_shift[i] + = grub_le_to_cpu32(newmap->keyboard_map_shift[i]); - for (i = 0; i < ARRAY_SIZE (newmap->at.keyboard_map_l3); i++) - newmap->at.keyboard_map_l3[i] - = grub_le_to_cpu32(newmap->at.keyboard_map_l3[i]); + for (i = 0; i < ARRAY_SIZE (newmap->keyboard_map_l3); i++) + newmap->keyboard_map_l3[i] + = grub_le_to_cpu32(newmap->keyboard_map_l3[i]); - for (i = 0; i < ARRAY_SIZE (newmap->at.keyboard_map_shift_l3); i++) - newmap->at.keyboard_map_shift_l3[i] - = grub_le_to_cpu32(newmap->at.keyboard_map_shift_l3[i]); - - for (i = 0; i < ARRAY_SIZE (newmap->usb.keyboard_map); i++) - newmap->usb.keyboard_map[i] = grub_le_to_cpu32(newmap->usb.keyboard_map[i]); - - for (i = 0; i < ARRAY_SIZE (newmap->usb.keyboard_map_shift); i++) - newmap->usb.keyboard_map_shift[i] - = grub_le_to_cpu32(newmap->usb.keyboard_map_shift[i]); - - for (i = 0; i < ARRAY_SIZE (newmap->usb.keyboard_map_l3); i++) - newmap->usb.keyboard_map_l3[i] - = grub_le_to_cpu32(newmap->usb.keyboard_map_l3[i]); - - for (i = 0; i < ARRAY_SIZE (newmap->usb.keyboard_map_shift_l3); i++) - newmap->usb.keyboard_map_shift_l3[i] - = grub_le_to_cpu32(newmap->usb.keyboard_map_shift_l3[i]); + for (i = 0; i < ARRAY_SIZE (newmap->keyboard_map_shift_l3); i++) + newmap->keyboard_map_shift_l3[i] + = grub_le_to_cpu32(newmap->keyboard_map_shift_l3[i]); grub_current_layout = newmap; diff --git a/include/grub/keyboard_layouts.h b/include/grub/keyboard_layouts.h index 6d4b620c2..1920b8887 100644 --- a/include/grub/keyboard_layouts.h +++ b/include/grub/keyboard_layouts.h @@ -21,11 +21,11 @@ #define GRUB_KEYBOARD_LAYOUTS_FILEMAGIC "GRUBLAYO" #define GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE (sizeof(GRUB_KEYBOARD_LAYOUTS_FILEMAGIC) - 1) -#define GRUB_KEYBOARD_LAYOUTS_VERSION 5 +#define GRUB_KEYBOARD_LAYOUTS_VERSION 6 #define GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE 128 -struct grub_keyboard_layout_kbd +struct grub_keyboard_layout { grub_uint32_t keyboard_map[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; grub_uint32_t keyboard_map_shift[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; @@ -33,12 +33,6 @@ struct grub_keyboard_layout_kbd grub_uint32_t keyboard_map_shift_l3[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; }; -struct grub_keyboard_layout -{ - struct grub_keyboard_layout_kbd at; - struct grub_keyboard_layout_kbd usb; -}; - unsigned grub_term_map_key (int code, int status); #endif /* GRUB_KEYBOARD_LAYOUTS */ diff --git a/term/usb_keyboard.c b/term/usb_keyboard.c index f35cc4b65..6f1e1a9e8 100644 --- a/term/usb_keyboard.c +++ b/term/usb_keyboard.c @@ -25,39 +25,45 @@ #include #include #include +#include -static unsigned keyboard_map[128] = - { - '\0', '\0', '\0', '\0', 'a', 'b', 'c', 'd', - 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', - 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', - 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', - '3', '4', '5', '6', '7', '8', '9', '0', - '\n', GRUB_TERM_ESC, GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, ' ', '-', '=', '[', - ']', '\\', '#', ';', '\'', '`', ',', '.', - '/', '\0', GRUB_TERM_KEY_F1, GRUB_TERM_KEY_F2, - GRUB_TERM_KEY_F3, GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5, GRUB_TERM_KEY_F6, - GRUB_TERM_KEY_F7, GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9, GRUB_TERM_KEY_F10, - GRUB_TERM_KEY_F11, GRUB_TERM_KEY_F12, '\0', '\0', - '\0', GRUB_TERM_KEY_INSERT, GRUB_TERM_KEY_HOME, GRUB_TERM_KEY_PPAGE, - GRUB_TERM_KEY_DC, GRUB_TERM_KEY_END, GRUB_TERM_KEY_NPAGE, GRUB_TERM_KEY_RIGHT, - GRUB_TERM_KEY_LEFT, GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_UP, - [0x64] = '\\' - }; -static unsigned keyboard_map_shift[128] = - { - '\0', '\0', '\0', '\0', 'A', 'B', 'C', 'D', - 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', - 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', - 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@', - '#', '$', '%', '^', '&', '*', '(', ')', - '\n', '\0', '\0', '\0', ' ', '_', '+', '{', - '}', '|', '#', ':', '"', '`', '<', '>', - '?', - [0x64] = '|' - }; +static grub_uint8_t usb_to_at_map[128] = +{ + /* 0x00 */ 0x00, 0x00, 0x00, 0x00, + /* 0x04 */ 0x1e /* a */, 0x30 /* b */, 0x2e /* c */, 0x20 /* d */, + /* 0x08 */ 0x12 /* e */, 0x21 /* f */, 0x22 /* g */, 0x23 /* h */, + /* 0x0c */ 0x17 /* i */, 0x24 /* j */, 0x25 /* k */, 0x26 /* l */, + /* 0x10 */ 0x32 /* m */, 0x31 /* n */, 0x18 /* o */, 0x19 /* p */, + /* 0x14 */ 0x10 /* q */, 0x13 /* r */, 0x1f /* s */, 0x14 /* t */, + /* 0x18 */ 0x16 /* u */, 0x2f /* v */, 0x11 /* w */, 0x2d /* x */, + /* 0x1c */ 0x15 /* y */, 0x2c /* z */, 0x02 /* 1 */, 0x03 /* 2 */, + /* 0x20 */ 0x04 /* 3 */, 0x05 /* 4 */, 0x06 /* 5 */, 0x07 /* 6 */, + /* 0x24 */ 0x08 /* 7 */, 0x09 /* 8 */, 0x0a /* 9 */, 0x0b /* 0 */, + /* 0x28 */ 0x1c /* Enter */, 0x01 /* Escape */, 0x0e /* \b */, 0x0f /* \t */, + /* 0x2c */ 0x39 /* Space */, 0x4a /* - */, 0x0d /* = */, 0x1a /* [ */, + /* 0x30 */ 0x1b /* ] */, 0x2b /* \ */, 0x00, 0x27 /* ; */, + /* 0x34 */ 0x28 /* " */, 0x29 /* ` */, 0x33 /* , */, 0x34 /* . */, + /* 0x38 */ 0x35 /* / */, 0x00, 0x00, 0x00, + /* 0x3c */ 0x00, 0x00, 0x00, 0x00, + /* 0x40 */ 0x00, 0x00, 0x00, 0x00, + /* 0x44 */ 0x00, 0x00, 0x00, 0x00, + /* 0x48 */ 0x00, 0x00, 0x47 /* HOME */, 0x51 /* PPAGE */, + /* 0x4c */ 0x53 /* DC */, 0x4f /* END */, 0x49 /* NPAGE */, 0x4d /* RIGHT */, + /* 0x50 */ 0x4b /* LEFT */, 0x50 /* DOWN */, 0x48 /* UP */, 0x00, + /* 0x54 */ 0x00, 0x00, 0x00, 0x00, + /* 0x58 */ 0x00, 0x00, 0x00, 0x00, + /* 0x5c */ 0x00, 0x00, 0x00, 0x00, + /* 0x60 */ 0x00, 0x00, 0x00, 0x00, + /* 0x64 */ 0x56 /* 102nd key. */, 0x00, 0x00, 0x00, + /* 0x68 */ 0x00, 0x00, 0x00, 0x00, + /* 0x6c */ 0x00, 0x00, 0x00, 0x00, + /* 0x70 */ 0x00, 0x00, 0x00, 0x00, + /* 0x74 */ 0x00, 0x00, 0x00, 0x00, + /* 0x78 */ 0x00, 0x00, 0x00, 0x00, + /* 0x7c */ 0x00, 0x00, 0x00, 0x00, +}; static grub_usb_device_t usbdev; @@ -74,6 +80,35 @@ static grub_usb_device_t usbdev; #define USB_HID_SET_IDLE 0x0A #define USB_HID_SET_PROTOCOL 0x0B +#define GRUB_USB_KEYBOARD_LEFT_CTRL 0x01 +#define GRUB_USB_KEYBOARD_LEFT_SHIFT 0x02 +#define GRUB_USB_KEYBOARD_LEFT_ALT 0x04 +#define GRUB_USB_KEYBOARD_RIGHT_CTRL 0x10 +#define GRUB_USB_KEYBOARD_RIGHT_SHIFT 0x20 +#define GRUB_USB_KEYBOARD_RIGHT_ALT 0x40 + +static int +interpret_status (grub_uint8_t data0) +{ + int mods = 0; + + /* Check Shift, Control, and Alt status. */ + if (data0 & GRUB_USB_KEYBOARD_LEFT_SHIFT) + mods |= GRUB_TERM_STATUS_LSHIFT; + if (data0 & GRUB_USB_KEYBOARD_RIGHT_SHIFT) + mods |= GRUB_TERM_STATUS_RSHIFT; + if (data0 & GRUB_USB_KEYBOARD_LEFT_CTRL) + mods |= GRUB_TERM_STATUS_LCTRL; + if (data0 & GRUB_USB_KEYBOARD_RIGHT_CTRL) + mods |= GRUB_TERM_STATUS_RCTRL; + if (data0 & GRUB_USB_KEYBOARD_LEFT_ALT) + mods |= GRUB_TERM_STATUS_LALT; + if (data0 & GRUB_USB_KEYBOARD_RIGHT_ALT) + mods |= GRUB_TERM_STATUS_RALT; + + return mods; +} + static void grub_usb_hid (void) { @@ -127,7 +162,7 @@ static int grub_usb_keyboard_checkkey (struct grub_term_input *term __attribute__ ((unused))) { grub_uint8_t data[8]; - int key; + int key = 0; grub_err_t err; grub_uint64_t currtime; int timeout = 50; @@ -154,39 +189,14 @@ grub_usb_keyboard_checkkey (struct grub_term_input *term __attribute__ ((unused) data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]); -#define GRUB_USB_KEYBOARD_LEFT_CTRL 0x01 -#define GRUB_USB_KEYBOARD_LEFT_SHIFT 0x02 -#define GRUB_USB_KEYBOARD_LEFT_ALT 0x04 -#define GRUB_USB_KEYBOARD_RIGHT_CTRL 0x10 -#define GRUB_USB_KEYBOARD_RIGHT_SHIFT 0x20 -#define GRUB_USB_KEYBOARD_RIGHT_ALT 0x40 - - /* Check if the Shift key was pressed. */ - if (data[0] & GRUB_USB_KEYBOARD_LEFT_SHIFT - || data[0] & GRUB_USB_KEYBOARD_RIGHT_SHIFT) - { - if (keyboard_map_shift[data[2]]) - key = keyboard_map_shift[data[2]]; - else - key = keyboard_map[data[2]] | GRUB_TERM_SHIFT; - } - else - key = keyboard_map[data[2]]; - - if (key == 0) + if (usb_to_at_map[data[2]] == 0) grub_printf ("Unknown key 0x%x detected\n", data[2]); + else + key = grub_term_map_key (usb_to_at_map[data[2]], interpret_status (data[0])); - /* Check if the Ctrl key was pressed. */ - if (data[0] & GRUB_USB_KEYBOARD_LEFT_CTRL - || data[0] & GRUB_USB_KEYBOARD_RIGHT_CTRL) - key |= GRUB_TERM_CTRL; + grub_errno = GRUB_ERR_NONE; - /* Check if the Alt key was pressed. */ - if (data[0] & GRUB_USB_KEYBOARD_LEFT_ALT) - key |= GRUB_TERM_ALT; - - if (data[0] & GRUB_USB_KEYBOARD_RIGHT_ALT) - key |= GRUB_TERM_ALT; + return key; #if 0 /* Wait until the key is released. */ @@ -203,8 +213,6 @@ grub_usb_keyboard_checkkey (struct grub_term_input *term __attribute__ ((unused) } #endif - grub_errno = GRUB_ERR_NONE; - return key; } @@ -284,7 +292,6 @@ static int grub_usb_keyboard_getkeystatus (struct grub_term_input *term __attribute__ ((unused))) { grub_uint8_t data[8]; - int mods = 0; grub_err_t err; grub_uint64_t currtime; int timeout = 50; @@ -322,23 +329,9 @@ grub_usb_keyboard_getkeystatus (struct grub_term_input *term __attribute__ ((unu data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]); - /* Check Shift, Control, and Alt status. */ - if (data[0] & GRUB_USB_KEYBOARD_LEFT_SHIFT) - mods |= GRUB_TERM_STATUS_LSHIFT; - if (data[0] & GRUB_USB_KEYBOARD_RIGHT_SHIFT) - mods |= GRUB_TERM_STATUS_RSHIFT; - if (data[0] & GRUB_USB_KEYBOARD_LEFT_CTRL) - mods |= GRUB_TERM_STATUS_LCTRL; - if (data[0] & GRUB_USB_KEYBOARD_RIGHT_CTRL) - mods |= GRUB_TERM_STATUS_RCTRL; - if (data[0] & GRUB_USB_KEYBOARD_LEFT_ALT) - mods |= GRUB_TERM_STATUS_LALT; - if (data[0] & GRUB_USB_KEYBOARD_RIGHT_ALT) - mods |= GRUB_TERM_STATUS_RALT; - grub_errno = GRUB_ERR_NONE; - return mods; + return interpret_status (data[0]); } static struct grub_term_input grub_usb_keyboard_term = diff --git a/util/grub-mklayouts.c b/util/grub-mklayouts.c index 43aa745a5..6a51a9a76 100644 --- a/util/grub-mklayouts.c +++ b/util/grub-mklayouts.c @@ -46,26 +46,6 @@ struct console_grub_equivalence grub_uint32_t grub; }; -static int at_to_usb_map[128] = -{ - 0, 41, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 45, 46, 42, 43, - 20, 26, 8, 21, 23, 28, 24, 12, - 18, 19, 47, 48, 40, 0, 4, 22, - 7, 9, 10, 11, 13, 14, 15, 51, - 52, 53, 0, 49, 29, 27, 6, 25, - 5, 17, 16, 54, 55, 56, 0, 0, - 0, 44, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 74, - 82, 78, 45, 80, 0, 79, 0, 77, - 81, 75, 0, 76, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 -}; - static struct console_grub_equivalence console_grub_equivalences[] = { {"KP_1", '1'}, {"KP_2", '2'}, @@ -108,20 +88,20 @@ Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT); void add_special_keys (struct grub_keyboard_layout *layout) { - layout->at.keyboard_map[71] = GRUB_TERM_KEY_HOME; - layout->at.keyboard_map[72] = GRUB_TERM_KEY_UP; - layout->at.keyboard_map[73] = GRUB_TERM_KEY_NPAGE; - layout->at.keyboard_map[75] = GRUB_TERM_KEY_LEFT; - layout->at.keyboard_map[77] = GRUB_TERM_KEY_RIGHT; - layout->at.keyboard_map[79] = GRUB_TERM_KEY_END; - layout->at.keyboard_map[80] = GRUB_TERM_KEY_DOWN; - layout->at.keyboard_map[81] = GRUB_TERM_KEY_PPAGE; - layout->at.keyboard_map[83] = GRUB_TERM_KEY_DC; + layout->keyboard_map[71] = GRUB_TERM_KEY_HOME; + layout->keyboard_map[72] = GRUB_TERM_KEY_UP; + layout->keyboard_map[73] = GRUB_TERM_KEY_NPAGE; + layout->keyboard_map[75] = GRUB_TERM_KEY_LEFT; + layout->keyboard_map[77] = GRUB_TERM_KEY_RIGHT; + layout->keyboard_map[79] = GRUB_TERM_KEY_END; + layout->keyboard_map[80] = GRUB_TERM_KEY_DOWN; + layout->keyboard_map[81] = GRUB_TERM_KEY_PPAGE; + layout->keyboard_map[83] = GRUB_TERM_KEY_DC; - layout->at.keyboard_map[101] = GRUB_TERM_KEY_UP; - layout->at.keyboard_map[102] = GRUB_TERM_KEY_DOWN; - layout->at.keyboard_map[103] = GRUB_TERM_KEY_LEFT; - layout->at.keyboard_map[104] = GRUB_TERM_KEY_RIGHT; + layout->keyboard_map[101] = GRUB_TERM_KEY_UP; + layout->keyboard_map[102] = GRUB_TERM_KEY_DOWN; + layout->keyboard_map[103] = GRUB_TERM_KEY_LEFT; + layout->keyboard_map[104] = GRUB_TERM_KEY_RIGHT; } static char @@ -159,35 +139,20 @@ write_file (char* filename, struct grub_keyboard_layout *layout) version = grub_cpu_to_le32 (GRUB_KEYBOARD_LAYOUTS_VERSION); - for (i = 0; i < ARRAY_SIZE (layout->at.keyboard_map); i++) - layout->at.keyboard_map[i] = grub_cpu_to_le32(layout->at.keyboard_map[i]); + for (i = 0; i < ARRAY_SIZE (layout->keyboard_map); i++) + layout->keyboard_map[i] = grub_cpu_to_le32(layout->keyboard_map[i]); - for (i = 0; i < ARRAY_SIZE (layout->at.keyboard_map_shift); i++) - layout->at.keyboard_map_shift[i] - = grub_cpu_to_le32(layout->at.keyboard_map_shift[i]); + for (i = 0; i < ARRAY_SIZE (layout->keyboard_map_shift); i++) + layout->keyboard_map_shift[i] + = grub_cpu_to_le32(layout->keyboard_map_shift[i]); - for (i = 0; i < ARRAY_SIZE (layout->at.keyboard_map_l3); i++) - layout->at.keyboard_map_l3[i] - = grub_cpu_to_le32(layout->at.keyboard_map_l3[i]); + for (i = 0; i < ARRAY_SIZE (layout->keyboard_map_l3); i++) + layout->keyboard_map_l3[i] + = grub_cpu_to_le32(layout->keyboard_map_l3[i]); - for (i = 0; i < ARRAY_SIZE (layout->at.keyboard_map_shift_l3); i++) - layout->at.keyboard_map_shift_l3[i] - = grub_cpu_to_le32(layout->at.keyboard_map_shift_l3[i]); - - for (i = 0; i < ARRAY_SIZE (layout->usb.keyboard_map); i++) - layout->usb.keyboard_map[i] = grub_cpu_to_le32(layout->usb.keyboard_map[i]); - - for (i = 0; i < ARRAY_SIZE (layout->usb.keyboard_map_shift); i++) - layout->usb.keyboard_map_shift[i] - = grub_cpu_to_le32(layout->usb.keyboard_map_shift[i]); - - for (i = 0; i < ARRAY_SIZE (layout->usb.keyboard_map_l3); i++) - layout->usb.keyboard_map_l3[i] - = grub_cpu_to_le32(layout->usb.keyboard_map_l3[i]); - - for (i = 0; i < ARRAY_SIZE (layout->usb.keyboard_map_shift_l3); i++) - layout->usb.keyboard_map_shift_l3[i] - = grub_cpu_to_le32(layout->usb.keyboard_map_shift_l3[i]); + for (i = 0; i < ARRAY_SIZE (layout->keyboard_map_shift_l3); i++) + layout->keyboard_map_shift_l3[i] + = grub_cpu_to_le32(layout->keyboard_map_shift_l3[i]); fp_output = fopen (filename, "w"); @@ -258,28 +223,16 @@ write_keymaps (char *keymap, char *file_basename) normal, shift, normalalt, shiftalt); if (keycode < GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE) { - layout.at.keyboard_map[keycode] = get_grub_code (normal); - layout.at.keyboard_map_shift[keycode] = get_grub_code (shift); - layout.at.keyboard_map_l3[keycode] = get_grub_code (normalalt); - layout.at.keyboard_map_shift_l3[keycode] + layout.keyboard_map[keycode] = get_grub_code (normal); + layout.keyboard_map_shift[keycode] = get_grub_code (shift); + layout.keyboard_map_l3[keycode] = get_grub_code (normalalt); + layout.keyboard_map_shift_l3[keycode] = get_grub_code (shiftalt); ok = 1; } } } - for (i = 0; i < GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE; i++) - { - layout.usb.keyboard_map[at_to_usb_map[i]] = layout.at.keyboard_map[i]; - layout.usb.keyboard_map_shift[at_to_usb_map[i]] - = layout.at.keyboard_map_shift[i]; - layout.usb.keyboard_map_l3[at_to_usb_map[i]] - = layout.at.keyboard_map_l3[i]; - layout.usb.keyboard_map_shift_l3[at_to_usb_map[i]] - = layout.at.keyboard_map_shift_l3[i]; - } - - if (ok == 0) { fprintf (stderr, "ERROR: no keycodes found. Check output of %s %s.\n", From b09634f02706eb412f9becf9d1d4084bcad97112 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 19 Aug 2010 16:12:18 +0200 Subject: [PATCH 023/214] Added missing values and indented USB table --- term/usb_keyboard.c | 96 ++++++++++++++++++++++++++++--------------- util/grub-mklayouts.c | 4 ++ 2 files changed, 68 insertions(+), 32 deletions(-) diff --git a/term/usb_keyboard.c b/term/usb_keyboard.c index 6f1e1a9e8..ede71bb5f 100644 --- a/term/usb_keyboard.c +++ b/term/usb_keyboard.c @@ -31,38 +31,70 @@ static grub_uint8_t usb_to_at_map[128] = { - /* 0x00 */ 0x00, 0x00, 0x00, 0x00, - /* 0x04 */ 0x1e /* a */, 0x30 /* b */, 0x2e /* c */, 0x20 /* d */, - /* 0x08 */ 0x12 /* e */, 0x21 /* f */, 0x22 /* g */, 0x23 /* h */, - /* 0x0c */ 0x17 /* i */, 0x24 /* j */, 0x25 /* k */, 0x26 /* l */, - /* 0x10 */ 0x32 /* m */, 0x31 /* n */, 0x18 /* o */, 0x19 /* p */, - /* 0x14 */ 0x10 /* q */, 0x13 /* r */, 0x1f /* s */, 0x14 /* t */, - /* 0x18 */ 0x16 /* u */, 0x2f /* v */, 0x11 /* w */, 0x2d /* x */, - /* 0x1c */ 0x15 /* y */, 0x2c /* z */, 0x02 /* 1 */, 0x03 /* 2 */, - /* 0x20 */ 0x04 /* 3 */, 0x05 /* 4 */, 0x06 /* 5 */, 0x07 /* 6 */, - /* 0x24 */ 0x08 /* 7 */, 0x09 /* 8 */, 0x0a /* 9 */, 0x0b /* 0 */, - /* 0x28 */ 0x1c /* Enter */, 0x01 /* Escape */, 0x0e /* \b */, 0x0f /* \t */, - /* 0x2c */ 0x39 /* Space */, 0x4a /* - */, 0x0d /* = */, 0x1a /* [ */, - /* 0x30 */ 0x1b /* ] */, 0x2b /* \ */, 0x00, 0x27 /* ; */, - /* 0x34 */ 0x28 /* " */, 0x29 /* ` */, 0x33 /* , */, 0x34 /* . */, - /* 0x38 */ 0x35 /* / */, 0x00, 0x00, 0x00, - /* 0x3c */ 0x00, 0x00, 0x00, 0x00, - /* 0x40 */ 0x00, 0x00, 0x00, 0x00, - /* 0x44 */ 0x00, 0x00, 0x00, 0x00, - /* 0x48 */ 0x00, 0x00, 0x47 /* HOME */, 0x51 /* PPAGE */, - /* 0x4c */ 0x53 /* DC */, 0x4f /* END */, 0x49 /* NPAGE */, 0x4d /* RIGHT */, - /* 0x50 */ 0x4b /* LEFT */, 0x50 /* DOWN */, 0x48 /* UP */, 0x00, - /* 0x54 */ 0x00, 0x00, 0x00, 0x00, - /* 0x58 */ 0x00, 0x00, 0x00, 0x00, - /* 0x5c */ 0x00, 0x00, 0x00, 0x00, - /* 0x60 */ 0x00, 0x00, 0x00, 0x00, - /* 0x64 */ 0x56 /* 102nd key. */, 0x00, 0x00, 0x00, - /* 0x68 */ 0x00, 0x00, 0x00, 0x00, - /* 0x6c */ 0x00, 0x00, 0x00, 0x00, - /* 0x70 */ 0x00, 0x00, 0x00, 0x00, - /* 0x74 */ 0x00, 0x00, 0x00, 0x00, - /* 0x78 */ 0x00, 0x00, 0x00, 0x00, - /* 0x7c */ 0x00, 0x00, 0x00, 0x00, + /* 0x00 */ 0x00, 0x00, + /* 0x02 */ 0x00, 0x00, + /* 0x04 */ 0x1e /* a */, 0x30 /* b */, + /* 0x06 */ 0x2e /* c */, 0x20 /* d */, + /* 0x08 */ 0x12 /* e */, 0x21 /* f */, + /* 0x0a */ 0x22 /* g */, 0x23 /* h */, + /* 0x0c */ 0x17 /* i */, 0x24 /* j */, + /* 0x0e */ 0x25 /* k */, 0x26 /* l */, + /* 0x10 */ 0x32 /* m */, 0x31 /* n */, + /* 0x12 */ 0x18 /* o */, 0x19 /* p */, + /* 0x14 */ 0x10 /* q */, 0x13 /* r */, + /* 0x16 */ 0x1f /* s */, 0x14 /* t */, + /* 0x18 */ 0x16 /* u */, 0x2f /* v */, + /* 0x1a */ 0x11 /* w */, 0x2d /* x */, + /* 0x1c */ 0x15 /* y */, 0x2c /* z */, + /* 0x1e */ 0x02 /* 1 */, 0x03 /* 2 */, + /* 0x20 */ 0x04 /* 3 */, 0x05 /* 4 */, + /* 0x22 */ 0x06 /* 5 */, 0x07 /* 6 */, + /* 0x24 */ 0x08 /* 7 */, 0x09 /* 8 */, + /* 0x26 */ 0x0a /* 9 */, 0x0b /* 0 */, + /* 0x28 */ 0x1c /* Enter */, 0x01 /* Escape */, + /* 0x2a */ 0x0e /* \b */, 0x0f /* \t */, + /* 0x2c */ 0x39 /* Space */, 0x0c /* - */, + /* 0x2e */ 0x0d /* = */, 0x1a /* [ */, + /* 0x30 */ 0x1b /* ] */, 0x2b /* \ */, + /* 0x32 */ 0x00, 0x27 /* ; */, + /* 0x34 */ 0x28 /* " */, 0x29 /* ` */, + /* 0x36 */ 0x33 /* , */, 0x34 /* . */, + /* 0x38 */ 0x35 /* / */, 0x00, + /* 0x3a */ 0x3b /* F1 */, 0x3c /* F2 */, + /* 0x3c */ 0x3d /* F3 */, 0x3e /* F4 */, + /* 0x3e */ 0x3f /* F5 */, 0x40 /* F6 */, + /* 0x40 */ 0x41 /* F7 */, 0x42 /* F8 */, + /* 0x42 */ 0x43 /* F9 */, 0x44 /* F10 */, + /* 0x44 */ 0x57 /* F11 */, 0x58 /* F12 */, + /* 0x46 */ 0x00, 0x00, + /* 0x48 */ 0x00, 0x00, + /* 0x4a */ 0x47 /* HOME */, 0x51 /* PPAGE */, + /* 0x4c */ 0x53 /* DC */, 0x4f /* END */, + /* 0x4e */ 0x49 /* NPAGE */, 0x4d /* RIGHT */, + /* 0x50 */ 0x4b /* LEFT */, 0x50 /* DOWN */, + /* 0x52 */ 0x48 /* UP */, 0x00, + /* 0x54 */ 0x00, 0x00, + /* 0x56 */ 0x00, 0x00, + /* 0x58 */ 0x00, 0x00, + /* 0x5a */ 0x00, 0x00, + /* 0x5c */ 0x00, 0x00, + /* 0x5e */ 0x00, 0x00, + /* 0x60 */ 0x00, 0x00, + /* 0x62 */ 0x00, 0x00, + /* 0x64 */ 0x56 /* 102nd key. */, 0x00, + /* 0x66 */ 0x00, 0x00, + /* 0x68 */ 0x00, 0x00, + /* 0x6a */ 0x00, 0x00, + /* 0x6c */ 0x00, 0x00, + /* 0x6e */ 0x00, 0x00, + /* 0x70 */ 0x00, 0x00, + /* 0x72 */ 0x00, 0x00, + /* 0x74 */ 0x00, 0x00, + /* 0x76 */ 0x00, 0x00, + /* 0x78 */ 0x00, 0x00, + /* 0x7a */ 0x00, 0x00, + /* 0x7c */ 0x00, 0x00, + /* 0x7e */ 0x00, 0x00, }; static grub_usb_device_t usbdev; diff --git a/util/grub-mklayouts.c b/util/grub-mklayouts.c index 6a51a9a76..dde2383e2 100644 --- a/util/grub-mklayouts.c +++ b/util/grub-mklayouts.c @@ -47,6 +47,10 @@ struct console_grub_equivalence }; static struct console_grub_equivalence console_grub_equivalences[] = { + {"Escape", GRUB_TERM_ESC}, + {"Tab", GRUB_TERM_TAB}, + {"Delete", GRUB_TERM_BACKSPACE}, + {"KP_1", '1'}, {"KP_2", '2'}, {"KP_3", '3'}, From b17520411991170f09751a50093760dc8dbf4d31 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 19 Aug 2010 19:17:36 +0200 Subject: [PATCH 024/214] Add missing keys to grub-mklayouts --- util/grub-mklayouts.c | 174 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 143 insertions(+), 31 deletions(-) diff --git a/util/grub-mklayouts.c b/util/grub-mklayouts.c index dde2383e2..49ad6be97 100644 --- a/util/grub-mklayouts.c +++ b/util/grub-mklayouts.c @@ -51,24 +51,136 @@ static struct console_grub_equivalence console_grub_equivalences[] = { {"Tab", GRUB_TERM_TAB}, {"Delete", GRUB_TERM_BACKSPACE}, - {"KP_1", '1'}, - {"KP_2", '2'}, - {"KP_3", '3'}, - {"KP_4", '4'}, - {"KP_5", '5'}, - {"KP_6", '6'}, - {"KP_7", '7'}, - {"KP_8", '8'}, - {"KP_9", '9'}, - {"KP_Multiply", '*'}, - {"KP_Substract", '-'}, + {"KP_Subtract", '-'}, {"KP_Add", '+'}, {"KP_Divide", '/'}, {"KP_Enter", '\n'}, {"Return", '\n'}, - {"", '\0'} + + {"F1", GRUB_TERM_KEY_F1}, + {"F2", GRUB_TERM_KEY_F2}, + {"F3", GRUB_TERM_KEY_F3}, + {"F4", GRUB_TERM_KEY_F4}, + {"F5", GRUB_TERM_KEY_F5}, + {"F6", GRUB_TERM_KEY_F6}, + {"F7", GRUB_TERM_KEY_F7}, + {"F8", GRUB_TERM_KEY_F8}, + {"F9", GRUB_TERM_KEY_F9}, + {"F10", GRUB_TERM_KEY_F10}, + {"F11", GRUB_TERM_KEY_F11}, + {"F12", GRUB_TERM_KEY_F12}, + {"F13", GRUB_TERM_KEY_F1 | GRUB_TERM_SHIFT}, + {"F14", GRUB_TERM_KEY_F2 | GRUB_TERM_SHIFT}, + {"F15", GRUB_TERM_KEY_F3 | GRUB_TERM_SHIFT}, + {"F16", GRUB_TERM_KEY_F4 | GRUB_TERM_SHIFT}, + {"F17", GRUB_TERM_KEY_F5 | GRUB_TERM_SHIFT}, + {"F18", GRUB_TERM_KEY_F6 | GRUB_TERM_SHIFT}, + {"F19", GRUB_TERM_KEY_F7 | GRUB_TERM_SHIFT}, + {"F20", GRUB_TERM_KEY_F8 | GRUB_TERM_SHIFT}, + {"F21", GRUB_TERM_KEY_F9 | GRUB_TERM_SHIFT}, + {"F22", GRUB_TERM_KEY_F10 | GRUB_TERM_SHIFT}, + {"F23", GRUB_TERM_KEY_F11 | GRUB_TERM_SHIFT}, + {"F24", GRUB_TERM_KEY_F12 | GRUB_TERM_SHIFT}, + {"Console_13", GRUB_TERM_KEY_F1 | GRUB_TERM_ALT}, + {"Console_14", GRUB_TERM_KEY_F2 | GRUB_TERM_ALT}, + {"Console_15", GRUB_TERM_KEY_F3 | GRUB_TERM_ALT}, + {"Console_16", GRUB_TERM_KEY_F4 | GRUB_TERM_ALT}, + {"Console_17", GRUB_TERM_KEY_F5 | GRUB_TERM_ALT}, + {"Console_18", GRUB_TERM_KEY_F6 | GRUB_TERM_ALT}, + {"Console_19", GRUB_TERM_KEY_F7 | GRUB_TERM_ALT}, + {"Console_20", GRUB_TERM_KEY_F8 | GRUB_TERM_ALT}, + {"Console_21", GRUB_TERM_KEY_F9 | GRUB_TERM_ALT}, + {"Console_22", GRUB_TERM_KEY_F10 | GRUB_TERM_ALT}, + {"Console_23", GRUB_TERM_KEY_F11 | GRUB_TERM_ALT}, + {"Console_24", GRUB_TERM_KEY_F12 | GRUB_TERM_ALT}, + {"Console_25", GRUB_TERM_KEY_F1 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_26", GRUB_TERM_KEY_F2 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_27", GRUB_TERM_KEY_F3 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_28", GRUB_TERM_KEY_F4 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_29", GRUB_TERM_KEY_F5 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_30", GRUB_TERM_KEY_F6 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_31", GRUB_TERM_KEY_F7 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_32", GRUB_TERM_KEY_F8 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_33", GRUB_TERM_KEY_F9 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_34", GRUB_TERM_KEY_F10 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_35", GRUB_TERM_KEY_F11 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + {"Console_36", GRUB_TERM_KEY_F12 | GRUB_TERM_SHIFT | GRUB_TERM_ALT}, + + {"Insert", GRUB_TERM_KEY_INSERT}, + {"Down", GRUB_TERM_KEY_DOWN}, + {"Up", GRUB_TERM_KEY_UP}, + {"Home", GRUB_TERM_KEY_HOME}, + {"End", GRUB_TERM_KEY_END}, + {"Right", GRUB_TERM_KEY_RIGHT}, + {"Left", GRUB_TERM_KEY_LEFT}, + {"VoidSymbol", 0}, + + /* "Undead" keys since no dead key support in GRUB. */ + {"dead_acute", '\''}, + {"dead_circumflex", '^'}, + {"dead_grave", '`'}, + {"dead_tilde", '~'}, + {"dead_diaeresis", '"'}, + + /* Following ones don't provide any useful symbols for shell. */ + {"dead_cedilla", 0}, + {"dead_ogonek", 0}, + {"dead_caron", 0}, + {"dead_breve", 0}, + {"dead_doubleacute", 0}, + + /* NumLock not supported yet. */ + {"KP_0", GRUB_TERM_KEY_INSERT}, + {"KP_1", GRUB_TERM_KEY_END}, + {"KP_2", GRUB_TERM_KEY_DOWN}, + {"KP_3", GRUB_TERM_KEY_NPAGE}, + {"KP_4", GRUB_TERM_KEY_LEFT}, + {"KP_5", 0}, + {"KP_6", GRUB_TERM_KEY_RIGHT}, + {"KP_7", GRUB_TERM_KEY_HOME}, + {"KP_8", GRUB_TERM_KEY_UP}, + {"KP_9", GRUB_TERM_KEY_PPAGE}, + {"KP_Period", GRUB_TERM_KEY_DC}, + + /* Unused in GRUB. */ + {"Pause", 0}, + {"Remove", 0}, + {"Next", 0}, + {"Prior", 0}, + {"Scroll_Forward", 0}, + {"Scroll_Backward", 0}, + {"Hex_0", 0}, + {"Hex_1", 0}, + {"Hex_2", 0}, + {"Hex_3", 0}, + {"Hex_4", 0}, + {"Hex_5", 0}, + {"Hex_6", 0}, + {"Hex_7", 0}, + {"Hex_8", 0}, + {"Hex_9", 0}, + {"Hex_A", 0}, + {"Hex_B", 0}, + {"Hex_C", 0}, + {"Hex_D", 0}, + {"Hex_E", 0}, + {"Hex_F", 0}, + {"Scroll_Lock", 0}, + {"Show_Memory", 0}, + {"Show_Registers", 0}, + {"Control_backslash", 0}, + + /* Keys currently not remappable. */ + {"CtrlL_Lock", 0}, + {"Num_Lock", 0}, + {"Alt", 0}, + {"AltGr", 0}, + {"Control", 0}, + {"Shift", 0}, + + {NULL, '\0'} }; static void @@ -92,16 +204,7 @@ Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT); void add_special_keys (struct grub_keyboard_layout *layout) { - layout->keyboard_map[71] = GRUB_TERM_KEY_HOME; - layout->keyboard_map[72] = GRUB_TERM_KEY_UP; - layout->keyboard_map[73] = GRUB_TERM_KEY_NPAGE; - layout->keyboard_map[75] = GRUB_TERM_KEY_LEFT; - layout->keyboard_map[77] = GRUB_TERM_KEY_RIGHT; - layout->keyboard_map[79] = GRUB_TERM_KEY_END; - layout->keyboard_map[80] = GRUB_TERM_KEY_DOWN; - layout->keyboard_map[81] = GRUB_TERM_KEY_PPAGE; - layout->keyboard_map[83] = GRUB_TERM_KEY_DC; - + /* OLPC keys. */ layout->keyboard_map[101] = GRUB_TERM_KEY_UP; layout->keyboard_map[102] = GRUB_TERM_KEY_DOWN; layout->keyboard_map[103] = GRUB_TERM_KEY_LEFT; @@ -113,10 +216,12 @@ lookup (char *code) { int i; - for (i = 0; console_grub_equivalences[i].grub != '\0'; i++) + for (i = 0; console_grub_equivalences[i].layout != NULL; i++) if (strcmp (code, console_grub_equivalences[i].layout) == 0) return console_grub_equivalences[i].grub; + printf ("Unknown key %s\n", code); + return '\0'; } @@ -174,14 +279,13 @@ write_file (char* filename, struct grub_keyboard_layout *layout) } static void -write_keymaps (char *keymap, char *file_basename) +write_keymaps (char *argv[], int argc, char *file_basename) { struct grub_keyboard_layout layout; char line[2048]; pid_t pid; int pipe_communication[2]; int ok; - unsigned i; FILE *fp_pipe; @@ -199,11 +303,19 @@ write_keymaps (char *keymap, char *file_basename) } else if (pid == 0) { + char **args; + int j; close (1); dup (pipe_communication[1]); close (pipe_communication[0]); - execlp (CKBCOMP, CKBCOMP, keymap, NULL); - grub_util_error ("%s %s cannot be executed", CKBCOMP, keymap); + args = xmalloc (sizeof (args[0]) * (argc + 2)); + args[0] = CKBCOMP; + for (j = 0; j < argc; j++) + args[j + 1] = argv[j]; + args[argc + 1] = NULL; + execvp (CKBCOMP, args); + grub_util_error ("%s cannot be executed", CKBCOMP); + free (args); exit (3); } close (pipe_communication[1]); @@ -239,8 +351,8 @@ write_keymaps (char *keymap, char *file_basename) if (ok == 0) { - fprintf (stderr, "ERROR: no keycodes found. Check output of %s %s.\n", - CKBCOMP, keymap); + fprintf (stderr, "ERROR: no keycodes found. Check output of %s.\n", + CKBCOMP); exit (1); } @@ -302,11 +414,11 @@ main (int argc, char *argv[]) if (file_basename == NULL) { file_basename = xasprintf ("%s.gkb", argv[optind]); - write_keymaps (argv[optind], file_basename); + write_keymaps (argv + optind, argc - optind, file_basename); free (file_basename); } else - write_keymaps (argv[optind], file_basename); + write_keymaps (argv + optind, argc - optind, file_basename); return 0; } From 5a3e99b388eaecaaa615300b5eb738fcdd780f7e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 19 Aug 2010 20:43:40 +0200 Subject: [PATCH 025/214] MAke grub-mklayouts do only one thing rather than doing all the piping --- util/grub-mklayouts.c | 109 ++++++++++++++++-------------------------- 1 file changed, 41 insertions(+), 68 deletions(-) diff --git a/util/grub-mklayouts.c b/util/grub-mklayouts.c index 49ad6be97..8fdee8590 100644 --- a/util/grub-mklayouts.c +++ b/util/grub-mklayouts.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "progname.h" @@ -240,9 +241,8 @@ get_grub_code (char *layout_code) } static void -write_file (char* filename, struct grub_keyboard_layout *layout) +write_file (FILE *out, struct grub_keyboard_layout *layout) { - FILE *fp_output; grub_uint32_t version; unsigned i; @@ -263,69 +263,24 @@ write_file (char* filename, struct grub_keyboard_layout *layout) layout->keyboard_map_shift_l3[i] = grub_cpu_to_le32(layout->keyboard_map_shift_l3[i]); - fp_output = fopen (filename, "w"); - - if (!fp_output) - { - grub_util_error ("cannot open `%s'", filename); - exit (1); - } - fwrite (GRUB_KEYBOARD_LAYOUTS_FILEMAGIC, 1, - GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE, fp_output); - fwrite (&version, sizeof (version), 1, fp_output); - fwrite (layout, 1, sizeof (*layout), fp_output); - fclose (fp_output); + GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE, out); + fwrite (&version, sizeof (version), 1, out); + fwrite (layout, 1, sizeof (*layout), out); } static void -write_keymaps (char *argv[], int argc, char *file_basename) +write_keymaps (FILE *in, FILE *out) { struct grub_keyboard_layout layout; char line[2048]; - pid_t pid; - int pipe_communication[2]; int ok; - FILE *fp_pipe; - - if (pipe (pipe_communication) == -1) - { - grub_util_error ("cannot prepare the pipe"); - exit (2); - } - - pid = fork (); - if (pid < 0) - { - grub_util_error ("cannot fork"); - exit (2); - } - else if (pid == 0) - { - char **args; - int j; - close (1); - dup (pipe_communication[1]); - close (pipe_communication[0]); - args = xmalloc (sizeof (args[0]) * (argc + 2)); - args[0] = CKBCOMP; - for (j = 0; j < argc; j++) - args[j + 1] = argv[j]; - args[argc + 1] = NULL; - execvp (CKBCOMP, args); - grub_util_error ("%s cannot be executed", CKBCOMP); - free (args); - exit (3); - } - close (pipe_communication[1]); - fp_pipe = fdopen (pipe_communication[0], "r"); - memset (&layout, 0, sizeof (layout)); /* Process the ckbcomp output and prepare the layouts. */ ok = 0; - while (fgets (line, sizeof (line), fp_pipe)) + while (fgets (line, sizeof (line), in)) { if (strncmp (line, "keycode", sizeof ("keycode") - 1) == 0) { @@ -358,14 +313,16 @@ write_keymaps (char *argv[], int argc, char *file_basename) add_special_keys (&layout); - write_file (file_basename, &layout); + write_file (out, &layout); } int main (int argc, char *argv[]) { int verbosity; - char *file_basename = NULL; + char *infile_name = NULL; + char *outfile_name = NULL; + FILE *in, *out; set_program_name (argv[0]); @@ -374,7 +331,7 @@ main (int argc, char *argv[]) /* Check for options. */ while (1) { - int c = getopt_long (argc, argv, "o:hVv", options, 0); + int c = getopt_long (argc, argv, "o:i:hVv", options, 0); if (c == -1) break; @@ -385,8 +342,12 @@ main (int argc, char *argv[]) usage (0); break; + case 'i': + infile_name = optarg; + break; + case 'o': - file_basename = optarg; + outfile_name = optarg; break; case 'V': @@ -404,21 +365,33 @@ main (int argc, char *argv[]) } } - /* Obtain LAYOUT. */ - if (optind >= argc) + if (infile_name) + in = fopen (infile_name, "r"); + else + in = stdin; + + if (!in) + grub_util_error ("Couldn't open input file: %s\n", strerror (errno)); + + if (outfile_name) + out = fopen (outfile_name, "r"); + else + out = stdout; + + if (!out) { - fprintf (stderr, "No layout is specified.\n"); - usage (1); + if (in != stdin) + fclose (in); + grub_util_error ("Couldn't open input file: %s\n", strerror (errno)); } - if (file_basename == NULL) - { - file_basename = xasprintf ("%s.gkb", argv[optind]); - write_keymaps (argv + optind, argc - optind, file_basename); - free (file_basename); - } - else - write_keymaps (argv + optind, argc - optind, file_basename); + write_keymaps (in, out); + + if (in != stdin) + fclose (in); + + if (out != stdout) + fclose (out); return 0; } From 9c9ec877cb6ab2d39b7f57525cb31b4acb47e5cb Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 19 Aug 2010 20:47:08 +0200 Subject: [PATCH 026/214] Rename grub-mklayouts to grub-mklayout --- conf/common.rmk | 6 +++--- util/{grub-mklayouts.c => grub-mklayout.c} | 0 2 files changed, 3 insertions(+), 3 deletions(-) rename util/{grub-mklayouts.c => grub-mklayout.c} (100%) diff --git a/conf/common.rmk b/conf/common.rmk index 745b1837e..82edc0aa0 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -80,9 +80,9 @@ endif bin_UTILITIES += grub-mkrelpath grub_mkrelpath_SOURCES = gnulib/progname.c util/grub-mkrelpath.c util/misc.c kern/emu/misc.c -# For grub-mklayouts. -bin_UTILITIES += grub-mklayouts -grub_mklayouts_SOURCES = gnulib/progname.c util/grub-mklayouts.c util/misc.c kern/emu/misc.c +# For grub-mklayout. +bin_UTILITIES += grub-mklayout +grub_mklayout_SOURCES = gnulib/progname.c util/grub-mklayout.c util/misc.c kern/emu/misc.c bin_UTILITIES += grub-bin2h grub_bin2h_SOURCES = gnulib/progname.c util/bin2h.c diff --git a/util/grub-mklayouts.c b/util/grub-mklayout.c similarity index 100% rename from util/grub-mklayouts.c rename to util/grub-mklayout.c From 88e543b519d930457462d6931d2c9cb55ea94ba5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 19 Aug 2010 20:48:31 +0200 Subject: [PATCH 027/214] Add grub-kbdcomp --- conf/common.rmk | 7 +++++++ util/grub-kbdcomp.in | 6 ++++++ 2 files changed, 13 insertions(+) create mode 100644 util/grub-kbdcomp.in diff --git a/conf/common.rmk b/conf/common.rmk index 82edc0aa0..e21c693b0 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -180,6 +180,13 @@ CLEANFILES += grub-pe2elf grub_macho2img_SOURCES = util/grub-macho2img.c CLEANFILES += grub-macho2img +# For grub-kbdcomp +grub-kbdcomp: util/grub-kbdcomp.in config.status + ./config.status --file=$@:$< + chmod +x $@ +sbin_SCRIPTS += grub-kbdcomp +CLEANFILES += grub-kbdcomp + # For grub-mkconfig grub-mkconfig: util/grub-mkconfig.in config.status ./config.status --file=$@:$< diff --git a/util/grub-kbdcomp.in b/util/grub-kbdcomp.in new file mode 100644 index 000000000..87b24bcdf --- /dev/null +++ b/util/grub-kbdcomp.in @@ -0,0 +1,6 @@ +#!/bin/sh + +grub_mklayout=${bindir}/`echo grub-mklayout | sed ${transform}` + +ckbcomp "$@" | $grub_mklayout -o "$1".gkb + From 8bb7e81637ba2f457daf8ce4c137e9851ab10960 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 20 Aug 2010 01:23:33 +0200 Subject: [PATCH 028/214] Fix printf bug --- util/grub-mklayout.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/util/grub-mklayout.c b/util/grub-mklayout.c index 8fdee8590..210ad646a 100644 --- a/util/grub-mklayout.c +++ b/util/grub-mklayout.c @@ -172,9 +172,12 @@ static struct console_grub_equivalence console_grub_equivalences[] = { {"Show_Memory", 0}, {"Show_Registers", 0}, {"Control_backslash", 0}, + {"Compose", 0}, /* Keys currently not remappable. */ {"CtrlL_Lock", 0}, + {"Caps_Lock", 0}, + {"ShiftL", 0}, {"Num_Lock", 0}, {"Alt", 0}, {"AltGr", 0}, @@ -221,7 +224,7 @@ lookup (char *code) if (strcmp (code, console_grub_equivalences[i].layout) == 0) return console_grub_equivalences[i].grub; - printf ("Unknown key %s\n", code); + fprintf (stderr, "Unknown key %s\n", code); return '\0'; } @@ -374,7 +377,7 @@ main (int argc, char *argv[]) grub_util_error ("Couldn't open input file: %s\n", strerror (errno)); if (outfile_name) - out = fopen (outfile_name, "r"); + out = fopen (outfile_name, "wb"); else out = stdout; @@ -382,7 +385,7 @@ main (int argc, char *argv[]) { if (in != stdin) fclose (in); - grub_util_error ("Couldn't open input file: %s\n", strerror (errno)); + grub_util_error ("Couldn't open output file: %s\n", strerror (errno)); } write_keymaps (in, out); From 0b335a9797e188032ccca7fba48ed80fa10cc738 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 20 Aug 2010 23:33:41 +0200 Subject: [PATCH 029/214] Fix cutting bits by implicit conversion to char --- util/grub-mklayout.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/grub-mklayout.c b/util/grub-mklayout.c index 210ad646a..91dea87a6 100644 --- a/util/grub-mklayout.c +++ b/util/grub-mklayout.c @@ -215,7 +215,7 @@ add_special_keys (struct grub_keyboard_layout *layout) layout->keyboard_map[104] = GRUB_TERM_KEY_RIGHT; } -static char +static unsigned lookup (char *code) { int i; From d9a8a9736e2c9e66a6f989c2acb8071c257aa4e6 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 21 Aug 2010 00:05:39 +0200 Subject: [PATCH 030/214] Add missing insert and \ codes --- term/usb_keyboard.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/term/usb_keyboard.c b/term/usb_keyboard.c index f5bd1d601..6b8891716 100644 --- a/term/usb_keyboard.c +++ b/term/usb_keyboard.c @@ -55,8 +55,10 @@ static grub_uint8_t usb_to_at_map[128] = /* 0x2a */ 0x0e /* \b */, 0x0f /* \t */, /* 0x2c */ 0x39 /* Space */, 0x0c /* - */, /* 0x2e */ 0x0d /* = */, 0x1a /* [ */, - /* 0x30 */ 0x1b /* ] */, 0x2b /* \ */, - /* 0x32 */ 0x00, 0x27 /* ; */, + /* According to usage table 0x31 should be remapped to 0x2b + but testing with real keyboard shows that 0x32 is remapped to 0x2b. */ + /* 0x30 */ 0x1b /* ] */, 0x00, + /* 0x32 */ 0x2b /* \ */, 0x27 /* ; */, /* 0x34 */ 0x28 /* " */, 0x29 /* ` */, /* 0x36 */ 0x33 /* , */, 0x34 /* . */, /* 0x38 */ 0x35 /* / */, 0x00, @@ -67,7 +69,7 @@ static grub_uint8_t usb_to_at_map[128] = /* 0x42 */ 0x43 /* F9 */, 0x44 /* F10 */, /* 0x44 */ 0x57 /* F11 */, 0x58 /* F12 */, /* 0x46 */ 0x00, 0x00, - /* 0x48 */ 0x00, 0x00, + /* 0x48 */ 0x00, 0x52 /* Insert */, /* 0x4a */ 0x47 /* HOME */, 0x51 /* PPAGE */, /* 0x4c */ 0x53 /* DC */, 0x4f /* END */, /* 0x4e */ 0x49 /* NPAGE */, 0x4d /* RIGHT */, From 735e864757e9dd158bacbf6a5c902442f65890f5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 21 Aug 2010 00:29:57 +0200 Subject: [PATCH 031/214] Implement CapsLock --- term/usb_keyboard.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/term/usb_keyboard.c b/term/usb_keyboard.c index 6b8891716..7b67c6e96 100644 --- a/term/usb_keyboard.c +++ b/term/usb_keyboard.c @@ -99,6 +99,8 @@ static grub_uint8_t usb_to_at_map[128] = /* 0x7e */ 0x00, 0x00, }; +#define CAPS_LOCK 0x39 +#define CAPS_LOCK_LED 0x02 /* Valid values for bRequest. See HID definition version 1.11 section 7.2. */ #define USB_HID_GET_REPORT 0x01 @@ -122,7 +124,9 @@ struct grub_usb_keyboard_data { grub_usb_device_t usbdev; grub_uint8_t status; + grub_uint16_t mods; int key; + int interfno; struct grub_usb_desc_endp *endp; }; @@ -237,6 +241,7 @@ grub_usb_keyboard_attach (grub_usb_device_t usbdev, int configno, int interfno) } data->usbdev = usbdev; + data->interfno = interfno; data->endp = endp; /* Place the device in boot mode. */ @@ -278,6 +283,8 @@ grub_usb_keyboard_attach (grub_usb_device_t usbdev, int configno, int interfno) } } + data->mods = 0; + grub_term_register_input_active ("usb_keyboard", &grub_usb_keyboards[curnum]); return 1; @@ -285,6 +292,19 @@ grub_usb_keyboard_attach (grub_usb_device_t usbdev, int configno, int interfno) +static void +send_leds (struct grub_usb_keyboard_data *termdata) +{ + char report[1]; + report[0] = 0; + if (termdata->mods & GRUB_TERM_STATUS_CAPS) + report[0] |= CAPS_LOCK_LED; + grub_usb_control_msg (termdata->usbdev, GRUB_USB_REQTYPE_CLASS_INTERFACE_OUT, + USB_HID_SET_REPORT, 0x0200, termdata->interfno, + sizeof (report), (char *) report); + grub_errno = GRUB_ERR_NONE; +} + static int grub_usb_keyboard_checkkey (struct grub_term_input *term) { @@ -309,6 +329,13 @@ grub_usb_keyboard_checkkey (struct grub_term_input *term) if (actual < 3 || !data[2]) return -1; + if (data[2] == CAPS_LOCK) + { + termdata->mods ^= GRUB_TERM_STATUS_CAPS; + send_leds (termdata); + return -1; + } + grub_dprintf ("usb_keyboard", "report: 0x%02x 0x%02x 0x%02x 0x%02x" " 0x%02x 0x%02x 0x%02x 0x%02x\n", @@ -320,7 +347,8 @@ grub_usb_keyboard_checkkey (struct grub_term_input *term) else termdata->key = grub_term_map_key (usb_to_at_map[data[2]], - interpret_status (data[0])); + interpret_status (data[0]) + | termdata->mods); grub_errno = GRUB_ERR_NONE; @@ -348,7 +376,7 @@ grub_usb_keyboard_getkeystatus (struct grub_term_input *term) { struct grub_usb_keyboard_data *termdata = term->data; - return interpret_status (termdata->status); + return interpret_status (termdata->status) | termdata->mods; } struct grub_usb_attach_desc attach_hook = From d10d149667bd650414dcc4ce5ba055cbc4ed8d0f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 21 Aug 2010 13:54:10 +0200 Subject: [PATCH 032/214] Return USB_ERR_INTERNAL instead of grub_errno when appropriate --- bus/usb/usbtrans.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bus/usb/usbtrans.c b/bus/usb/usbtrans.c index db2ec097a..4a2e112bf 100644 --- a/bus/usb/usbtrans.c +++ b/bus/usb/usbtrans.c @@ -209,7 +209,7 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, if (! transfer) { grub_dma_free (data_chunk); - return grub_errno; + return GRUB_USB_ERR_INTERNAL; } datablocks = ((size + max - 1) / max); @@ -229,7 +229,7 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, { grub_free (transfer); grub_dma_free (data_chunk); - return grub_errno; + return GRUB_USB_ERR_INTERNAL; } /* Set up all transfers. */ From 12cbb3ccd0876ef7731c10f22b0a426464cd064d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 21 Aug 2010 13:55:06 +0200 Subject: [PATCH 033/214] Don't retire active transaction on a NAK --- bus/usb/uhci.c | 51 +++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/bus/usb/uhci.c b/bus/usb/uhci.c index 0bba24b54..d0416d7e2 100644 --- a/bus/usb/uhci.c +++ b/bus/usb/uhci.c @@ -519,32 +519,35 @@ grub_uhci_transfer (grub_usb_controller_t dev, grub_dprintf ("uhci", "t status=0x%02x\n", errtd->ctrl_status); - /* Check if the endpoint is stalled. */ - if (errtd->ctrl_status & (1 << 22)) - err = GRUB_USB_ERR_STALL; + if (!(errtd->ctrl_status & (1 << 23))) + { + /* Check if the endpoint is stalled. */ + if (errtd->ctrl_status & (1 << 22)) + err = GRUB_USB_ERR_STALL; - /* Check if an error related to the data buffer occurred. */ - if (errtd->ctrl_status & (1 << 21)) - err = GRUB_USB_ERR_DATA; + /* Check if an error related to the data buffer occurred. */ + if (errtd->ctrl_status & (1 << 21)) + err = GRUB_USB_ERR_DATA; - /* Check if a babble error occurred. */ - if (errtd->ctrl_status & (1 << 20)) - err = GRUB_USB_ERR_BABBLE; + /* Check if a babble error occurred. */ + if (errtd->ctrl_status & (1 << 20)) + err = GRUB_USB_ERR_BABBLE; - /* Check if a NAK occurred. */ - if (errtd->ctrl_status & (1 << 19)) - err = GRUB_USB_ERR_NAK; + /* Check if a NAK occurred. */ + if (errtd->ctrl_status & (1 << 19)) + err = GRUB_USB_ERR_NAK; - /* Check if a timeout occurred. */ - if (errtd->ctrl_status & (1 << 18)) - err = GRUB_USB_ERR_TIMEOUT; + /* Check if a timeout occurred. */ + if (errtd->ctrl_status & (1 << 18)) + err = GRUB_USB_ERR_TIMEOUT; - /* Check if a bitstuff error occurred. */ - if (errtd->ctrl_status & (1 << 17)) - err = GRUB_USB_ERR_BITSTUFF; + /* Check if a bitstuff error occurred. */ + if (errtd->ctrl_status & (1 << 17)) + err = GRUB_USB_ERR_BITSTUFF; - if (err) - goto fail; + if (err) + break; + } /* Fall through, no errors occurred, so the QH might be updated. */ @@ -554,17 +557,15 @@ grub_uhci_transfer (grub_usb_controller_t dev, { err = GRUB_USB_ERR_STALL; grub_dprintf ("uhci", "transaction timed out\n"); - goto fail; + break; } grub_cpu_idle (); } - grub_dprintf ("uhci", "transaction complete\n"); - - fail: - if (err != GRUB_USB_ERR_NONE) grub_dprintf ("uhci", "transaction failed\n"); + else + grub_dprintf ("uhci", "transaction complete\n"); /* Place the QH back in the free list and deallocate the associated TDs. */ From bcfa613bc4a54b5910489057231dc2fae1eacf01 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 21 Aug 2010 13:56:55 +0200 Subject: [PATCH 034/214] correctly pass interfno and don't use GetReport --- term/usb_keyboard.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/term/usb_keyboard.c b/term/usb_keyboard.c index d875ac00a..adb84fa94 100644 --- a/term/usb_keyboard.c +++ b/term/usb_keyboard.c @@ -167,11 +167,11 @@ grub_usb_keyboard_attach (grub_usb_device_t usbdev, int configno, int interfno) /* Place the device in boot mode. */ grub_usb_control_msg (usbdev, GRUB_USB_REQTYPE_CLASS_INTERFACE_OUT, - USB_HID_SET_PROTOCOL, 0, 0, 0, 0); + USB_HID_SET_PROTOCOL, 0, interfno, 0, 0); /* Reports every time an event occurs and not more often than that. */ grub_usb_control_msg (usbdev, GRUB_USB_REQTYPE_CLASS_INTERFACE_OUT, - USB_HID_SET_IDLE, 0<<8, 0, 0, 0); + USB_HID_SET_IDLE, 0<<8, interfno, 0, 0); grub_memcpy (&grub_usb_keyboards[curnum], &grub_usb_keyboard_term, sizeof (grub_usb_keyboards[curnum])); @@ -185,12 +185,18 @@ grub_usb_keyboard_attach (grub_usb_device_t usbdev, int configno, int interfno) return 0; } + /* Test showed that getting report may make the keyboard go nuts. + Moreover since we're reattaching keyboard it usually sends + an initial message on interrupt pipe and so we retrieve + the same keystatus. + */ +#if 0 { grub_uint8_t report[8]; grub_usb_err_t err; grub_memset (report, 0, sizeof (report)); err = grub_usb_control_msg (usbdev, GRUB_USB_REQTYPE_CLASS_INTERFACE_IN, - USB_HID_GET_REPORT, 0x0000, interfno, + USB_HID_GET_REPORT, 0x0100, interfno, sizeof (report), (char *) report); if (err) { @@ -203,6 +209,10 @@ grub_usb_keyboard_attach (grub_usb_device_t usbdev, int configno, int interfno) data->key = report[2] ? : -1; } } +#else + data->status = 0; + data->key = -1; +#endif grub_term_register_input_active ("usb_keyboard", &grub_usb_keyboards[curnum]); @@ -279,6 +289,8 @@ grub_usb_keyboard_getkeystatus (struct grub_term_input *term) struct grub_usb_keyboard_data *termdata = term->data; int mods = 0; + grub_usb_keyboard_checkkey (term); + /* Check Shift, Control, and Alt status. */ if (termdata->status & 0x02 || termdata->status & 0x20) mods |= GRUB_TERM_STATUS_SHIFT; From 3ee4474e8dc092c7da7d7cb920d0a86bf1e15bd7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 21 Aug 2010 16:09:43 +0200 Subject: [PATCH 035/214] Prepare infrastructure for background USB transfers --- bus/usb/ohci.c | 794 ++++++++++++++++++++++------------------ bus/usb/uhci.c | 205 +++++++---- bus/usb/usb.c | 2 +- bus/usb/usbtrans.c | 40 +- include/grub/usb.h | 14 +- include/grub/usbtrans.h | 2 + 6 files changed, 606 insertions(+), 451 deletions(-) diff --git a/bus/usb/ohci.c b/bus/usb/ohci.c index 7f757485c..ba723996a 100644 --- a/bus/usb/ohci.c +++ b/bus/usb/ohci.c @@ -652,36 +652,32 @@ grub_ohci_transaction (grub_ohci_td_t td, td->next_td = 0; } +struct grub_ohci_transfer_controller_data +{ + grub_uint32_t tderr_phys; + grub_uint32_t td_last_phys; + grub_ohci_ed_t ed_virt; + grub_ohci_td_t td_current_virt; + grub_ohci_td_t td_head_virt; + grub_uint64_t bad_OHCI_delay; +}; + static grub_usb_err_t -grub_ohci_transfer (grub_usb_controller_t dev, - grub_usb_transfer_t transfer, int timeout, - grub_size_t *actual) +grub_ohci_setup_transfer (grub_usb_controller_t dev, + grub_usb_transfer_t transfer) { struct grub_ohci *o = (struct grub_ohci *) dev->data; - grub_ohci_ed_t ed_virt; int bulk = 0; - grub_ohci_td_t td_head_virt; - grub_ohci_td_t td_current_virt; grub_ohci_td_t td_next_virt; - grub_ohci_td_t tderr_virt = NULL; grub_uint32_t target; grub_uint32_t td_head_phys; grub_uint32_t td_tail_phys; - grub_uint32_t td_last_phys; - grub_uint32_t tderr_phys = 0; - grub_uint32_t status; - grub_uint32_t control; - grub_uint8_t errcode = 0; - grub_usb_err_t err = GRUB_USB_ERR_NONE; int i; - grub_uint64_t maxtime; - grub_uint64_t bad_OHCI_delay = 0; - int err_halt = 0; - int err_timeout = 0; - int err_unrec = 0; - grub_uint32_t intstatus; + struct grub_ohci_transfer_controller_data *cdata; - *actual = 0; + cdata = grub_zalloc (sizeof (*cdata)); + if (!cdata) + return GRUB_USB_ERR_INTERNAL; /* Pre-set target for ED - we need it to find proper ED */ /* Set the device address. */ @@ -703,21 +699,23 @@ grub_ohci_transfer (grub_usb_controller_t dev, case GRUB_USB_TRANSACTION_TYPE_CONTROL: break; - default : + default: + grub_free (cdata); return GRUB_USB_ERR_INTERNAL; } /* Find proper ED or add new ED */ - ed_virt = grub_ohci_find_ed (o, bulk, target); - if (!ed_virt) + cdata->ed_virt = grub_ohci_find_ed (o, bulk, target); + if (!cdata->ed_virt) { grub_dprintf ("ohci","Fatal: No free ED !\n"); + grub_free (cdata); return GRUB_USB_ERR_INTERNAL; } /* Take pointer to first TD from ED */ - td_head_phys = grub_le_to_cpu32 (ed_virt->td_head) & ~0xf; - td_tail_phys = grub_le_to_cpu32 (ed_virt->td_tail) & ~0xf; + td_head_phys = grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xf; + td_tail_phys = grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xf; /* Sanity check - td_head should be equal to td_tail */ if (td_head_phys != td_tail_phys) /* Should never happen ! */ @@ -726,6 +724,7 @@ grub_ohci_transfer (grub_usb_controller_t dev, grub_dprintf ("ohci", "HEAD = 0x%02x, TAIL = 0x%02x\n", td_head_phys, td_tail_phys); /* XXX: Fix: What to do ? */ + grub_free (cdata); return GRUB_USB_ERR_INTERNAL; } @@ -733,65 +732,64 @@ grub_ohci_transfer (grub_usb_controller_t dev, * we must allocate the first TD. */ if (!td_head_phys) { - td_head_virt = grub_ohci_alloc_td (o); - if (!td_head_virt) + cdata->td_head_virt = grub_ohci_alloc_td (o); + if (!cdata->td_head_virt) return GRUB_USB_ERR_INTERNAL; /* We don't need de-allocate ED */ /* We can set td_head only when ED is not active, i.e. * when it is newly allocated. */ - ed_virt->td_head = grub_cpu_to_le32 ( grub_ohci_td_virt2phys (o, - td_head_virt) ); - ed_virt->td_tail = ed_virt->td_head; + cdata->ed_virt->td_head + = grub_cpu_to_le32 (grub_ohci_td_virt2phys (o, cdata->td_head_virt)); + cdata->ed_virt->td_tail = cdata->ed_virt->td_head; } else - td_head_virt = grub_ohci_td_phys2virt ( o, td_head_phys ); + cdata->td_head_virt = grub_ohci_td_phys2virt ( o, td_head_phys ); /* Set TDs */ - td_last_phys = td_head_phys; /* initial value to make compiler happy... */ - for (i = 0, td_current_virt = td_head_virt; + cdata->td_last_phys = td_head_phys; /* initial value to make compiler happy... */ + for (i = 0, cdata->td_current_virt = cdata->td_head_virt; i < transfer->transcnt; i++) { grub_usb_transaction_t tr = &transfer->transactions[i]; - grub_ohci_transaction (td_current_virt, tr->pid, tr->toggle, + grub_ohci_transaction (cdata->td_current_virt, tr->pid, tr->toggle, tr->size, tr->data); /* Set index of TD in transfer */ - td_current_virt->tr_index = (grub_uint32_t) i; + cdata->td_current_virt->tr_index = (grub_uint32_t) i; /* No IRQ request in TD if bad_OHCI set */ if (o->bad_OHCI) - td_current_virt->token |= grub_cpu_to_le32 ( 7 << 21); + cdata->td_current_virt->token |= grub_cpu_to_le32 ( 7 << 21); /* Remember last used (processed) TD phys. addr. */ - td_last_phys = grub_ohci_td_virt2phys (o, td_current_virt); + cdata->td_last_phys = grub_ohci_td_virt2phys (o, cdata->td_current_virt); /* Allocate next TD */ td_next_virt = grub_ohci_alloc_td (o); if (!td_next_virt) /* No free TD, cancel transfer and free TDs except head TD */ { if (i) /* if i==0 we have nothing to free... */ - grub_ohci_free_tds (o, - grub_ohci_td_phys2virt(o, - grub_le_to_cpu32 (td_head_virt->next_td) ) ); + grub_ohci_free_tds (o, grub_ohci_td_phys2virt(o, + grub_le_to_cpu32 (cdata->td_head_virt->next_td))); /* Reset head TD */ - grub_memset ( (void*)td_head_virt, 0, + grub_memset ( (void*)cdata->td_head_virt, 0, sizeof(struct grub_ohci_td) ); grub_dprintf ("ohci", "Fatal: No free TD !"); + grub_free (cdata); return GRUB_USB_ERR_INTERNAL; } /* Chain TDs */ - td_current_virt->link_td = (grub_uint32_t) td_next_virt; - td_current_virt->next_td = grub_cpu_to_le32 ( - grub_ohci_td_virt2phys (o, - td_next_virt) ); - td_next_virt->prev_td_phys = grub_ohci_td_virt2phys (o, - td_current_virt); - td_current_virt = td_next_virt; + cdata->td_current_virt->link_td = (grub_uint32_t) td_next_virt; + cdata->td_current_virt->next_td + = grub_cpu_to_le32 (grub_ohci_td_virt2phys (o, td_next_virt)); + td_next_virt->prev_td_phys + = grub_ohci_td_virt2phys (o, cdata->td_current_virt); + cdata->td_current_virt = td_next_virt; } grub_dprintf ("ohci", "Tail TD (not processed) = %p\n", - td_current_virt); + cdata->td_current_virt); /* Setup the Endpoint Descriptor for transfer. */ /* First set necessary fields in TARGET but keep (or set) skip bit */ @@ -799,12 +797,12 @@ grub_ohci_transfer (grub_usb_controller_t dev, * size never change after first allocation of ED. * But unfortunately max. packet size may change during initial * setup sequence and we must handle it. */ - ed_virt->target = grub_cpu_to_le32 (target | (1 << 14)); + cdata->ed_virt->target = grub_cpu_to_le32 (target | (1 << 14)); /* Set td_tail */ - ed_virt->td_tail - = grub_cpu_to_le32 (grub_ohci_td_virt2phys (o, td_current_virt)); + cdata->ed_virt->td_tail + = grub_cpu_to_le32 (grub_ohci_td_virt2phys (o, cdata->td_current_virt)); /* Now reset skip bit */ - ed_virt->target = grub_cpu_to_le32 (target); + cdata->ed_virt->target = grub_cpu_to_le32 (target); /* ed_virt->td_head = grub_cpu_to_le32 (td_head); Must not be changed, it is maintained by OHCI */ /* ed_virt->next_ed = grub_cpu_to_le32 (0); Handled by grub_ohci_find_ed, do not change ! */ @@ -834,93 +832,19 @@ grub_ohci_transfer (grub_usb_controller_t dev, } } - /* Safety measure to avoid a hang. */ - maxtime = grub_get_time_ms () + timeout; - - /* Wait until the transfer is completed or STALLs. */ - do - { - /* Check transfer status */ - intstatus = grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); - if (!o->bad_OHCI && (intstatus & 0x2) != 0) - { - /* Remember last successful TD */ - tderr_phys = grub_le_to_cpu32 (o->hcca->donehead) & ~0xf; - /* Reset DoneHead */ - o->hcca->donehead = 0; - grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1)); - /* Read back of register should ensure it is really written */ - grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); - /* if TD is last, finish */ - if (tderr_phys == td_last_phys) - { - if (grub_le_to_cpu32 (ed_virt->td_head) & 1) - err_halt = 1; - break; - } - continue; - } + return GRUB_USB_ERR_NONE; +} - if ((intstatus & 0x10) != 0) - { /* Unrecoverable error - only reset can help...! */ - err_unrec = 1; - break; - } - - /* Detected a HALT. */ - if (err_halt || (grub_le_to_cpu32 (ed_virt->td_head) & 1)) - { - err_halt = 1; - /* ED is halted, but donehead event can happened in the meantime */ - intstatus = grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); - if (!o->bad_OHCI && (intstatus & 0x2) != 0) - /* Don't break loop now, first do donehead action(s) */ - continue; - break; - } - - /* bad OHCI handling */ - if ( (grub_le_to_cpu32 (ed_virt->td_head) & ~0xf) == - (grub_le_to_cpu32 (ed_virt->td_tail) & ~0xf) ) /* Empty ED */ - { - if (o->bad_OHCI) /* Bad OHCI detected previously */ - { - /* Try get last successful TD. */ - tderr_phys = grub_le_to_cpu32 (o->hcca->donehead) & ~0xf; - if (tderr_phys)/* Reset DoneHead if we were successful */ - { - o->hcca->donehead = 0; - grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1)); - /* Read back of register should ensure it is really written */ - grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); - } - /* Check the HALT bit */ - if (grub_le_to_cpu32 (ed_virt->td_head) & 1) - err_halt = 1; - break; - } - else /* Detection of bad OHCI */ - /* We should wait short time (~2ms) before we say that - * it is bad OHCI to prevent some hazard - - * donehead can react in the meantime. This waiting is done - * only once per OHCI driver "live cycle". */ - if (!bad_OHCI_delay) /* Set delay time */ - bad_OHCI_delay = grub_get_time_ms () + 2; - else if (grub_get_time_ms () >= bad_OHCI_delay) - o->bad_OHCI = 1; - continue; - } - - /* Timeout ? */ - if (grub_get_time_ms () > maxtime) - { - err_timeout = 1; - break; - } - - grub_cpu_idle (); - } - while (1); +static void +pre_finish_transfer (grub_usb_controller_t dev, + grub_usb_transfer_t transfer) +{ + struct grub_ohci *o = dev->data; + struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data; + grub_uint32_t target; + grub_uint32_t status; + grub_uint32_t control; + grub_uint32_t intstatus; /* There are many ways how the loop above can finish: * - normally without any error via INTSTATUS WDH bit @@ -952,8 +876,8 @@ grub_ohci_transfer (grub_usb_controller_t dev, /* Remember target for debug and set skip flag in ED */ /* It should be normaly not necessary but we need it at least * in case of timeout */ - target = grub_le_to_cpu32 ( ed_virt->target ); - ed_virt->target = grub_cpu_to_le32 (target | (1 << 14)); + target = grub_le_to_cpu32 ( cdata->ed_virt->target ); + cdata->ed_virt->target = grub_cpu_to_le32 (target | (1 << 14)); /* Read registers for debug - they should be read now because * debug prints case unwanted delays, so something can happen * in the meantime... */ @@ -964,224 +888,23 @@ grub_ohci_transfer (grub_usb_controller_t dev, grub_dprintf ("ohci", "loop finished: control=0x%02x status=0x%02x\n", control, status); grub_dprintf ("ohci", "intstatus=0x%02x \n\t\t tderr_phys=0x%02x, td_last_phys=0x%02x\n", - intstatus, tderr_phys, td_last_phys); - grub_dprintf ("ohci", "err_unrec=%d, err_timeout=%d \n\t\t err_halt=%d, bad_OHCI=%d\n", - err_unrec, err_timeout, err_halt, o->bad_OHCI); + intstatus, cdata->tderr_phys, cdata->td_last_phys); grub_dprintf ("ohci", "TARGET=0x%02x, HEAD=0x%02x, TAIL=0x%02x\n", target, - grub_le_to_cpu32 (ed_virt->td_head), - grub_le_to_cpu32 (ed_virt->td_tail) ); + grub_le_to_cpu32 (cdata->ed_virt->td_head), + grub_le_to_cpu32 (cdata->ed_virt->td_tail) ); - if (!err_halt && !err_unrec && !err_timeout) /* normal finish */ - { - /* Simple workaround if donehead is not working */ - if (o->bad_OHCI && - ( !tderr_phys || (tderr_phys != td_last_phys) ) ) - { - grub_dprintf ("ohci", "normal finish, but tderr_phys corrected\n"); - tderr_phys = td_last_phys; - /* I hope we can do it as transfer (most probably) finished OK */ - } - /* Prepare pointer to last processed TD */ - tderr_virt = grub_ohci_td_phys2virt (o, tderr_phys); - /* Set index of last processed TD */ - if (tderr_virt) - transfer->last_trans = tderr_virt->tr_index; - else - transfer->last_trans = -1; - *actual = transfer->size + 1; - } +} - else if (err_halt) /* error, ED is halted by OHCI, i.e. can be modified */ - { - /* First we must get proper tderr_phys value */ - if (o->bad_OHCI) /* In case of bad_OHCI tderr_phys can be wrong */ - { - if ( tderr_phys ) /* check if tderr_phys points to TD with error */ - errcode = grub_le_to_cpu32 ( grub_ohci_td_phys2virt (o, - tderr_phys)->token ) - >> 28; - if ( !tderr_phys || !errcode ) /* tderr_phys not valid or points to wrong TD */ - { /* Retired TD with error should be previous TD to ED->td_head */ - tderr_phys = grub_ohci_td_phys2virt (o, - grub_le_to_cpu32 ( ed_virt->td_head) & ~0xf ) - ->prev_td_phys; - } - } - - /* Even if we have "good" OHCI, in some cases - * tderr_phys can be zero, check it */ - else if ( !tderr_phys ) - { /* Retired TD with error should be previous TD to ED->td_head */ - tderr_phys = grub_ohci_td_phys2virt (o, - grub_le_to_cpu32 ( ed_virt->td_head) & ~0xf ) - ->prev_td_phys; - } - - /* Prepare pointer to last processed TD and get error code */ - tderr_virt = grub_ohci_td_phys2virt (o, tderr_phys); - /* Set index of last processed TD */ - if (tderr_virt) - { - errcode = grub_le_to_cpu32 ( tderr_virt->token ) >> 28; - transfer->last_trans = tderr_virt->tr_index; - } - else - transfer->last_trans = -1; - - /* Evaluation of error code */ - grub_dprintf ("ohci", "OHCI tderr_phys=0x%02x, errcode=0x%02x\n", - tderr_phys, errcode); - switch (errcode) - { - case 0: - /* XXX: Should not happen! */ - grub_error (GRUB_ERR_IO, "OHCI failed without reporting the reason"); - err = GRUB_USB_ERR_INTERNAL; - break; - - case 1: - /* XXX: CRC error. */ - err = GRUB_USB_ERR_TIMEOUT; - break; - - case 2: - err = GRUB_USB_ERR_BITSTUFF; - break; - - case 3: - /* XXX: Data Toggle error. */ - err = GRUB_USB_ERR_DATA; - break; - - case 4: - err = GRUB_USB_ERR_STALL; - break; - - case 5: - /* XXX: Not responding. */ - err = GRUB_USB_ERR_TIMEOUT; - break; - - case 6: - /* XXX: PID Check bits failed. */ - err = GRUB_USB_ERR_BABBLE; - break; - - case 7: - /* XXX: PID unexpected failed. */ - err = GRUB_USB_ERR_BABBLE; - break; - - case 8: - /* XXX: Data overrun error. */ - err = GRUB_USB_ERR_DATA; - grub_dprintf ("ohci", "Overrun, failed TD address: %p, index: %d\n", - tderr_virt, tderr_virt->tr_index); - break; - - case 9: - /* XXX: Data underrun error. */ - grub_dprintf ("ohci", "Underrun, failed TD address: %p, index: %d\n", - tderr_virt, tderr_virt->tr_index); - if (transfer->last_trans == -1) - break; - *actual = transfer->transactions[transfer->last_trans].size - - (grub_le_to_cpu32 (tderr_virt->buffer_end) - - grub_le_to_cpu32 (tderr_virt->buffer)) - + transfer->transactions[transfer->last_trans].preceding; - break; - - case 10: - /* XXX: Reserved. */ - err = GRUB_USB_ERR_NAK; - break; - - case 11: - /* XXX: Reserved. */ - err = GRUB_USB_ERR_NAK; - break; - - case 12: - /* XXX: Buffer overrun. */ - err = GRUB_USB_ERR_DATA; - break; - - case 13: - /* XXX: Buffer underrun. */ - err = GRUB_USB_ERR_DATA; - break; - - default: - err = GRUB_USB_ERR_NAK; - break; - } - - } - - else if (err_unrec) - { - /* Don't try to get error code and last processed TD for proper - * toggle bit value - anything can be invalid */ - err = GRUB_USB_ERR_UNRECOVERABLE; - grub_dprintf("ohci", "Unrecoverable error!"); - - /* Do OHCI reset in case of unrecoverable error - maybe we will need - * do more - re-enumerate bus etc. (?) */ - - /* Suspend the OHCI by issuing a reset. */ - grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, 1); /* XXX: Magic. */ - /* Read back of register should ensure it is really written */ - grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS); - grub_millisleep (1); - grub_dprintf ("ohci", "Unrecoverable error - OHCI reset\n"); - - /* Misc. resets. */ - o->hcca->donehead = 0; - grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, 0x7f); /* Clears everything */ - grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD, o->ed_ctrl_addr); - grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLCURR, 0); - grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, o->ed_bulk_addr); - grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKCURR, 0); - /* Read back of register should ensure it is really written */ - grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); - - /* Enable the OHCI. */ - grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, - (2 << 6) - | GRUB_OHCI_REG_CONTROL_CONTROL_ENABLE - | GRUB_OHCI_REG_CONTROL_BULK_ENABLE ); - } - - else if (err_timeout) - { - /* In case of timeout do not detect error from TD */ - err = GRUB_ERR_TIMEOUT; - grub_dprintf("ohci", "Timeout !\n"); - - /* We should wait for next SOF to be sure that ED is unaccessed - * by OHCI */ - /* SF bit reset. (SF bit indicates Start Of Frame (SOF) packet) */ - grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1<<2)); - /* Wait for new SOF */ - while ((grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS) & 0x4) == 0); - - /* Now we must find last processed TD if bad_OHCI == TRUE */ - if (o->bad_OHCI) - { /* Retired TD with error should be previous TD to ED->td_head */ - tderr_phys = grub_ohci_td_phys2virt (o, - grub_le_to_cpu32 ( ed_virt->td_head) & ~0xf) - ->prev_td_phys; - } - tderr_virt = grub_ohci_td_phys2virt (o, tderr_phys); - if (tderr_virt) - transfer->last_trans = tderr_virt->tr_index; - else - transfer->last_trans = -1; - } +static void +finish_transfer (grub_usb_controller_t dev, + grub_usb_transfer_t transfer) +{ + struct grub_ohci *o = dev->data; + struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data; /* Set empty ED - set HEAD = TAIL = last (not processed) TD */ - ed_virt->td_head = grub_cpu_to_le32 (grub_le_to_cpu32 (ed_virt->td_tail) & ~0xf); + cdata->ed_virt->td_head = grub_cpu_to_le32 (grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xf); /* At this point always should be: * ED has skip bit set and halted or empty or after next SOF, @@ -1195,23 +918,368 @@ grub_ohci_transfer (grub_usb_controller_t dev, grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); /* Un-chainig of last TD */ - if (td_current_virt->prev_td_phys) + if (cdata->td_current_virt->prev_td_phys) { grub_ohci_td_t td_prev_virt - = grub_ohci_td_phys2virt (o, td_current_virt->prev_td_phys); - - td_next_virt = (grub_ohci_td_t) td_prev_virt->link_td; - if (td_current_virt == td_next_virt) + = grub_ohci_td_phys2virt (o, cdata->td_current_virt->prev_td_phys); + + if (cdata->td_current_virt == (grub_ohci_td_t) td_prev_virt->link_td) td_prev_virt->link_td = 0; } - grub_dprintf ("ohci", "OHCI finished, freeing, err=0x%02x, errcode=0x%02x\n", - err, errcode); - grub_ohci_free_tds (o, td_head_virt); + grub_dprintf ("ohci", "OHCI finished, freeing\n"); + grub_ohci_free_tds (o, cdata->td_head_virt); +} + +static grub_usb_err_t +parse_halt (grub_usb_controller_t dev, + grub_usb_transfer_t transfer, + grub_size_t *actual) +{ + struct grub_ohci *o = dev->data; + struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data; + grub_uint8_t errcode = 0; + grub_usb_err_t err = GRUB_USB_ERR_NAK; + grub_ohci_td_t tderr_virt = NULL; + + *actual = 0; + + pre_finish_transfer (dev, transfer); + + /* First we must get proper tderr_phys value */ + if (o->bad_OHCI) /* In case of bad_OHCI tderr_phys can be wrong */ + { + if (cdata->tderr_phys) /* check if tderr_phys points to TD with error */ + errcode = grub_le_to_cpu32 (grub_ohci_td_phys2virt (o, + cdata->tderr_phys)->token) + >> 28; + if ( !cdata->tderr_phys || !errcode ) /* tderr_phys not valid or points to wrong TD */ + { /* Retired TD with error should be previous TD to ED->td_head */ + cdata->tderr_phys = grub_ohci_td_phys2virt (o, + grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xf ) + ->prev_td_phys; + } + } + /* Even if we have "good" OHCI, in some cases + * tderr_phys can be zero, check it */ + else if (!cdata->tderr_phys) + /* Retired TD with error should be previous TD to ED->td_head */ + cdata->tderr_phys + = grub_ohci_td_phys2virt (o, + grub_le_to_cpu32 (cdata->ed_virt->td_head) + & ~0xf)->prev_td_phys; + + + /* Prepare pointer to last processed TD and get error code */ + tderr_virt = grub_ohci_td_phys2virt (o, cdata->tderr_phys); + /* Set index of last processed TD */ + if (tderr_virt) + { + errcode = grub_le_to_cpu32 (tderr_virt->token) >> 28; + transfer->last_trans = tderr_virt->tr_index; + } + else + transfer->last_trans = -1; + + /* Evaluation of error code */ + grub_dprintf ("ohci", "OHCI tderr_phys=0x%02x, errcode=0x%02x\n", + cdata->tderr_phys, errcode); + switch (errcode) + { + case 0: + /* XXX: Should not happen! */ + grub_error (GRUB_ERR_IO, "OHCI failed without reporting the reason"); + err = GRUB_USB_ERR_INTERNAL; + break; + + case 1: + /* XXX: CRC error. */ + err = GRUB_USB_ERR_TIMEOUT; + break; + + case 2: + err = GRUB_USB_ERR_BITSTUFF; + break; + + case 3: + /* XXX: Data Toggle error. */ + err = GRUB_USB_ERR_DATA; + break; + + case 4: + err = GRUB_USB_ERR_STALL; + break; + + case 5: + /* XXX: Not responding. */ + err = GRUB_USB_ERR_TIMEOUT; + break; + + case 6: + /* XXX: PID Check bits failed. */ + err = GRUB_USB_ERR_BABBLE; + break; + + case 7: + /* XXX: PID unexpected failed. */ + err = GRUB_USB_ERR_BABBLE; + break; + + case 8: + /* XXX: Data overrun error. */ + err = GRUB_USB_ERR_DATA; + grub_dprintf ("ohci", "Overrun, failed TD address: %p, index: %d\n", + tderr_virt, tderr_virt->tr_index); + break; + + case 9: + /* XXX: Data underrun error. */ + grub_dprintf ("ohci", "Underrun, failed TD address: %p, index: %d\n", + tderr_virt, tderr_virt->tr_index); + if (transfer->last_trans == -1) + break; + *actual = transfer->transactions[transfer->last_trans].size + - (grub_le_to_cpu32 (tderr_virt->buffer_end) + - grub_le_to_cpu32 (tderr_virt->buffer)) + + transfer->transactions[transfer->last_trans].preceding; + err = GRUB_USB_ERR_NONE; + break; + + case 10: + /* XXX: Reserved. */ + err = GRUB_USB_ERR_NAK; + break; + + case 11: + /* XXX: Reserved. */ + err = GRUB_USB_ERR_NAK; + break; + + case 12: + /* XXX: Buffer overrun. */ + err = GRUB_USB_ERR_DATA; + break; + + case 13: + /* XXX: Buffer underrun. */ + err = GRUB_USB_ERR_DATA; + break; + + default: + err = GRUB_USB_ERR_NAK; + break; + } + + finish_transfer (dev, transfer); return err; } +static grub_usb_err_t +parse_success (grub_usb_controller_t dev, + grub_usb_transfer_t transfer, + grub_size_t *actual) +{ + struct grub_ohci *o = dev->data; + struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data; + grub_ohci_td_t tderr_virt = NULL; + + pre_finish_transfer (dev, transfer); + + /* Simple workaround if donehead is not working */ + if (o->bad_OHCI && + (!cdata->tderr_phys || (cdata->tderr_phys != cdata->td_last_phys))) + { + grub_dprintf ("ohci", "normal finish, but tderr_phys corrected\n"); + cdata->tderr_phys = cdata->td_last_phys; + /* I hope we can do it as transfer (most probably) finished OK */ + } + /* Prepare pointer to last processed TD */ + tderr_virt = grub_ohci_td_phys2virt (o, cdata->tderr_phys); + /* Set index of last processed TD */ + if (tderr_virt) + transfer->last_trans = tderr_virt->tr_index; + else + transfer->last_trans = -1; + *actual = transfer->size + 1; + + finish_transfer (dev, transfer); + + return GRUB_USB_ERR_NONE; +} + +static grub_usb_err_t +parse_unrec (grub_usb_controller_t dev, + grub_usb_transfer_t transfer, + grub_size_t *actual) +{ + struct grub_ohci *o = dev->data; + + *actual = 0; + + pre_finish_transfer (dev, transfer); + + /* Don't try to get error code and last processed TD for proper + * toggle bit value - anything can be invalid */ + grub_dprintf("ohci", "Unrecoverable error!"); + + /* Do OHCI reset in case of unrecoverable error - maybe we will need + * do more - re-enumerate bus etc. (?) */ + + /* Suspend the OHCI by issuing a reset. */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_CMDSTATUS, 1); /* XXX: Magic. */ + /* Read back of register should ensure it is really written */ + grub_ohci_readreg32 (o, GRUB_OHCI_REG_CMDSTATUS); + grub_millisleep (1); + grub_dprintf ("ohci", "Unrecoverable error - OHCI reset\n"); + + /* Misc. resets. */ + o->hcca->donehead = 0; + grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, 0x7f); /* Clears everything */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLHEAD, o->ed_ctrl_addr); + grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROLCURR, 0); + grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKHEAD, o->ed_bulk_addr); + grub_ohci_writereg32 (o, GRUB_OHCI_REG_BULKCURR, 0); + /* Read back of register should ensure it is really written */ + grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); + + /* Enable the OHCI. */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_CONTROL, + (2 << 6) + | GRUB_OHCI_REG_CONTROL_CONTROL_ENABLE + | GRUB_OHCI_REG_CONTROL_BULK_ENABLE ); + finish_transfer (dev, transfer); + + return GRUB_USB_ERR_UNRECOVERABLE; +} + +static grub_usb_err_t +grub_ohci_check_transfer (grub_usb_controller_t dev, + grub_usb_transfer_t transfer, + grub_size_t *actual) +{ + struct grub_ohci *o = dev->data; + struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data; + grub_uint32_t intstatus; + + /* Check transfer status */ + intstatus = grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); + if (!o->bad_OHCI && (intstatus & 0x2) != 0) + { + /* Remember last successful TD */ + cdata->tderr_phys = grub_le_to_cpu32 (o->hcca->donehead) & ~0xf; + /* Reset DoneHead */ + o->hcca->donehead = 0; + grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1)); + /* Read back of register should ensure it is really written */ + grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); + /* if TD is last, finish */ + if (cdata->tderr_phys == cdata->td_last_phys) + { + if (grub_le_to_cpu32 (cdata->ed_virt->td_head) & 1) + return parse_halt (dev, transfer, actual); + else + return parse_success (dev, transfer, actual); + } + return GRUB_USB_ERR_WAIT; + } + + if ((intstatus & 0x10) != 0) + /* Unrecoverable error - only reset can help...! */ + return parse_unrec (dev, transfer, actual); + + /* Detected a HALT. */ + if ((grub_le_to_cpu32 (cdata->ed_virt->td_head) & 1)) + { + /* ED is halted, but donehead event can happened in the meantime */ + intstatus = grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); + if (!o->bad_OHCI && (intstatus & 0x2) != 0) + { + /* Remember last successful TD */ + cdata->tderr_phys = grub_le_to_cpu32 (o->hcca->donehead) & ~0xf; + /* Reset DoneHead */ + o->hcca->donehead = 0; + grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1)); + /* Read back of register should ensure it is really written */ + grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); + /* if TD is last, finish */ + } + return parse_halt (dev, transfer, actual); + } + + /* bad OHCI handling */ + if ( (grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xf) == + (grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xf) ) /* Empty ED */ + { + if (o->bad_OHCI) /* Bad OHCI detected previously */ + { + /* Try get last successful TD. */ + cdata->tderr_phys = grub_le_to_cpu32 (o->hcca->donehead) & ~0xf; + if (cdata->tderr_phys)/* Reset DoneHead if we were successful */ + { + o->hcca->donehead = 0; + grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1)); + /* Read back of register should ensure it is really written */ + grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); + } + /* Check the HALT bit */ + if (grub_le_to_cpu32 (cdata->ed_virt->td_head) & 1) + return parse_halt (dev, transfer, actual); + else + return parse_success (dev, transfer, actual); + } + else /* Detection of bad OHCI */ + /* We should wait short time (~2ms) before we say that + * it is bad OHCI to prevent some hazard - + * donehead can react in the meantime. This waiting is done + * only once per OHCI driver "live cycle". */ + if (!cdata->bad_OHCI_delay) /* Set delay time */ + cdata->bad_OHCI_delay = grub_get_time_ms () + 2; + else if (grub_get_time_ms () >= cdata->bad_OHCI_delay) + o->bad_OHCI = 1; + return GRUB_USB_ERR_WAIT; + } + + return GRUB_USB_ERR_WAIT; +} + +static grub_usb_err_t +grub_ohci_cancel_transfer (grub_usb_controller_t dev, + grub_usb_transfer_t transfer) +{ + struct grub_ohci *o = dev->data; + struct grub_ohci_transfer_controller_data *cdata = transfer->controller_data; + grub_ohci_td_t tderr_virt = NULL; + + pre_finish_transfer (dev, transfer); + + grub_dprintf("ohci", "Timeout !\n"); + + /* We should wait for next SOF to be sure that ED is unaccessed + * by OHCI */ + /* SF bit reset. (SF bit indicates Start Of Frame (SOF) packet) */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1<<2)); + /* Wait for new SOF */ + while ((grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS) & 0x4) == 0); + + /* Now we must find last processed TD if bad_OHCI == TRUE */ + if (o->bad_OHCI) + /* Retired TD with error should be previous TD to ED->td_head */ + cdata->tderr_phys + = grub_ohci_td_phys2virt (o, grub_le_to_cpu32 (cdata->ed_virt->td_head) + & ~0xf)->prev_td_phys; + + tderr_virt = grub_ohci_td_phys2virt (o,cdata-> tderr_phys); + if (tderr_virt) + transfer->last_trans = tderr_virt->tr_index; + else + transfer->last_trans = -1; + + finish_transfer (dev, transfer); + + return GRUB_USB_ERR_NONE; +} + static grub_err_t grub_ohci_portstatus (grub_usb_controller_t dev, unsigned int port, unsigned int enable) @@ -1398,7 +1466,9 @@ static struct grub_usb_controller_dev usb_controller = { .name = "ohci", .iterate = grub_ohci_iterate, - .transfer = grub_ohci_transfer, + .setup_transfer = grub_ohci_setup_transfer, + .check_transfer = grub_ohci_check_transfer, + .cancel_transfer = grub_ohci_cancel_transfer, .hubports = grub_ohci_hubports, .portstatus = grub_ohci_portstatus, .detect_dev = grub_ohci_detect_dev diff --git a/bus/usb/uhci.c b/bus/usb/uhci.c index d0416d7e2..4792f961a 100644 --- a/bus/usb/uhci.c +++ b/bus/usb/uhci.c @@ -438,26 +438,35 @@ grub_uhci_transaction (struct grub_uhci *u, unsigned int endp, return td; } +struct grub_uhci_transfer_controller_data +{ + grub_uhci_qh_t qh; + grub_uhci_td_t td_first; +}; + static grub_usb_err_t -grub_uhci_transfer (grub_usb_controller_t dev, - grub_usb_transfer_t transfer, - int timeout, grub_size_t *actual) +grub_uhci_setup_transfer (grub_usb_controller_t dev, + grub_usb_transfer_t transfer) { struct grub_uhci *u = (struct grub_uhci *) dev->data; - grub_uhci_qh_t qh; grub_uhci_td_t td; - grub_uhci_td_t td_first = NULL; grub_uhci_td_t td_prev = NULL; - grub_usb_err_t err = GRUB_USB_ERR_NONE; int i; - grub_uint64_t endtime; + struct grub_uhci_transfer_controller_data *cdata; - *actual = 0; + cdata = grub_malloc (sizeof (*cdata)); + if (!cdata) + return GRUB_USB_ERR_INTERNAL; + + cdata->td_first = NULL; /* Allocate a queue head for the transfer queue. */ - qh = grub_alloc_qh (u, GRUB_USB_TRANSACTION_TYPE_CONTROL); - if (! qh) - return GRUB_USB_ERR_INTERNAL; + cdata->qh = grub_alloc_qh (u, GRUB_USB_TRANSACTION_TYPE_CONTROL); + if (! cdata->qh) + { + grub_free (cdata); + return GRUB_USB_ERR_INTERNAL; + } grub_dprintf ("uhci", "transfer, iobase:%08x\n", u->iobase); @@ -470,18 +479,20 @@ grub_uhci_transfer (grub_usb_controller_t dev, tr->size, tr->data); if (! td) { + grub_size_t actual = 0; /* Terminate and free. */ td_prev->linkptr2 = 0; td_prev->linkptr = 1; - if (td_first) - grub_free_queue (u, td_first, NULL, actual); + if (cdata->td_first) + grub_free_queue (u, cdata->td_first, NULL, &actual); + grub_free (cdata); return GRUB_USB_ERR_INTERNAL; } - if (! td_first) - td_first = td; + if (! cdata->td_first) + cdata->td_first = td; else { td_prev->linkptr2 = (grub_uint32_t) td; @@ -497,82 +508,112 @@ grub_uhci_transfer (grub_usb_controller_t dev, /* Link it into the queue and terminate. Now the transaction can take place. */ - qh->elinkptr = (grub_uint32_t) td_first; + cdata->qh->elinkptr = (grub_uint32_t) cdata->td_first; grub_dprintf ("uhci", "initiate transaction\n"); - /* Wait until either the transaction completed or an error - occurred. */ - endtime = grub_get_time_ms () + timeout; - for (;;) + transfer->controller_data = cdata; + + return GRUB_USB_ERR_NONE; +} + +static grub_usb_err_t +grub_uhci_check_transfer (grub_usb_controller_t dev, + grub_usb_transfer_t transfer, + grub_size_t *actual) +{ + struct grub_uhci *u = (struct grub_uhci *) dev->data; + grub_uhci_td_t errtd; + struct grub_uhci_transfer_controller_data *cdata = transfer->controller_data; + + *actual = 0; + + errtd = (grub_uhci_td_t) (cdata->qh->elinkptr & ~0x0f); + + grub_dprintf ("uhci", ">t status=0x%02x data=0x%02x td=%p\n", + errtd->ctrl_status, errtd->buffer & (~15), errtd); + + /* Check if the transaction completed. */ + if (cdata->qh->elinkptr & 1) { - grub_uhci_td_t errtd; + grub_dprintf ("uhci", "transaction complete\n"); - errtd = (grub_uhci_td_t) (qh->elinkptr & ~0x0f); - - grub_dprintf ("uhci", ">t status=0x%02x data=0x%02x td=%p\n", - errtd->ctrl_status, errtd->buffer & (~15), errtd); - - /* Check if the transaction completed. */ - if (qh->elinkptr & 1) - break; - - grub_dprintf ("uhci", "t status=0x%02x\n", errtd->ctrl_status); - - if (!(errtd->ctrl_status & (1 << 23))) - { - /* Check if the endpoint is stalled. */ - if (errtd->ctrl_status & (1 << 22)) - err = GRUB_USB_ERR_STALL; - - /* Check if an error related to the data buffer occurred. */ - if (errtd->ctrl_status & (1 << 21)) - err = GRUB_USB_ERR_DATA; - - /* Check if a babble error occurred. */ - if (errtd->ctrl_status & (1 << 20)) - err = GRUB_USB_ERR_BABBLE; - - /* Check if a NAK occurred. */ - if (errtd->ctrl_status & (1 << 19)) - err = GRUB_USB_ERR_NAK; - - /* Check if a timeout occurred. */ - if (errtd->ctrl_status & (1 << 18)) - err = GRUB_USB_ERR_TIMEOUT; - - /* Check if a bitstuff error occurred. */ - if (errtd->ctrl_status & (1 << 17)) - err = GRUB_USB_ERR_BITSTUFF; - - if (err) - break; - } - - /* Fall through, no errors occurred, so the QH might be - updated. */ - grub_dprintf ("uhci", "transaction fallthrough\n"); - - if (grub_get_time_ms () > endtime) - { - err = GRUB_USB_ERR_STALL; - grub_dprintf ("uhci", "transaction timed out\n"); - break; - } - grub_cpu_idle (); + /* Place the QH back in the free list and deallocate the associated + TDs. */ + cdata->qh->elinkptr = 1; + grub_free_queue (u, cdata->td_first, transfer, actual); + grub_free (cdata); + return GRUB_USB_ERR_NONE; } - if (err != GRUB_USB_ERR_NONE) - grub_dprintf ("uhci", "transaction failed\n"); - else - grub_dprintf ("uhci", "transaction complete\n"); + grub_dprintf ("uhci", "t status=0x%02x\n", errtd->ctrl_status); + + if (!(errtd->ctrl_status & (1 << 23))) + { + grub_usb_err_t err = GRUB_USB_ERR_NONE; + + /* Check if the endpoint is stalled. */ + if (errtd->ctrl_status & (1 << 22)) + err = GRUB_USB_ERR_STALL; + + /* Check if an error related to the data buffer occurred. */ + if (errtd->ctrl_status & (1 << 21)) + err = GRUB_USB_ERR_DATA; + + /* Check if a babble error occurred. */ + if (errtd->ctrl_status & (1 << 20)) + err = GRUB_USB_ERR_BABBLE; + + /* Check if a NAK occurred. */ + if (errtd->ctrl_status & (1 << 19)) + err = GRUB_USB_ERR_NAK; + + /* Check if a timeout occurred. */ + if (errtd->ctrl_status & (1 << 18)) + err = GRUB_USB_ERR_TIMEOUT; + + /* Check if a bitstuff error occurred. */ + if (errtd->ctrl_status & (1 << 17)) + err = GRUB_USB_ERR_BITSTUFF; + + if (err) + { + grub_dprintf ("uhci", "transaction failed\n"); + + /* Place the QH back in the free list and deallocate the associated + TDs. */ + cdata->qh->elinkptr = 1; + grub_free_queue (u, cdata->td_first, transfer, actual); + grub_free (cdata); + + return err; + } + } + + /* Fall through, no errors occurred, so the QH might be + updated. */ + grub_dprintf ("uhci", "transaction fallthrough\n"); + + return GRUB_USB_ERR_WAIT; +} + +static grub_usb_err_t +grub_uhci_cancel_transfer (grub_usb_controller_t dev, + grub_usb_transfer_t transfer) +{ + struct grub_uhci *u = (struct grub_uhci *) dev->data; + grub_size_t actual; + struct grub_uhci_transfer_controller_data *cdata = transfer->controller_data; + + grub_dprintf ("uhci", "transaction cancel\n"); /* Place the QH back in the free list and deallocate the associated TDs. */ - qh->elinkptr = 1; - grub_free_queue (u, td_first, transfer, actual); + cdata->qh->elinkptr = 1; + grub_free_queue (u, cdata->td_first, transfer, &actual); + grub_free (cdata); - return err; + return GRUB_USB_ERR_NONE; } static int @@ -706,7 +747,9 @@ static struct grub_usb_controller_dev usb_controller = { .name = "uhci", .iterate = grub_uhci_iterate, - .transfer = grub_uhci_transfer, + .setup_transfer = grub_uhci_setup_transfer, + .check_transfer = grub_uhci_check_transfer, + .cancel_transfer = grub_uhci_cancel_transfer, .hubports = grub_uhci_hubports, .portstatus = grub_uhci_portstatus, .detect_dev = grub_uhci_detect_dev diff --git a/bus/usb/usb.c b/bus/usb/usb.c index 2bd805ef2..80d386c8d 100644 --- a/bus/usb/usb.c +++ b/bus/usb/usb.c @@ -338,7 +338,7 @@ grub_usb_unregister_attach_hook_class (struct grub_usb_attach_desc *desc) GRUB_MOD_INIT(usb) { - grub_term_poll_usb = grub_usb_poll_devices; + // grub_term_poll_usb = grub_usb_poll_devices; } GRUB_MOD_FINI(usb) diff --git a/bus/usb/usbtrans.c b/bus/usb/usbtrans.c index 4a2e112bf..27377a3a5 100644 --- a/bus/usb/usbtrans.c +++ b/bus/usb/usbtrans.c @@ -23,6 +23,39 @@ #include #include #include +#include + +static grub_usb_err_t +grub_usb_execute_and_wait_transfer (grub_usb_device_t dev, + grub_usb_transfer_t transfer, + int timeout, grub_size_t *actual) +{ + grub_usb_err_t err; + grub_uint64_t endtime; + + endtime = grub_get_time_ms () + timeout; + err = dev->controller.dev->setup_transfer (&dev->controller, transfer); + if (err) + return err; + while (1) + { + err = dev->controller.dev->check_transfer (&dev->controller, transfer, + actual); + if (!err) + return GRUB_USB_ERR_NONE; + if (err != GRUB_USB_ERR_WAIT) + return err; + if (grub_get_time_ms () > endtime) + { + err = dev->controller.dev->cancel_transfer (&dev->controller, + transfer); + if (err) + return err; + return GRUB_USB_ERR_TIMEOUT; + } + grub_cpu_idle (); + } +} grub_usb_err_t grub_usb_control_msg (grub_usb_device_t dev, @@ -147,8 +180,8 @@ grub_usb_control_msg (grub_usb_device_t dev, transfer->transactions[datablocks + 1].toggle = 1; - err = dev->controller.dev->transfer (&dev->controller, transfer, - 1000, &actual); + err = grub_usb_execute_and_wait_transfer (dev, transfer, 1000, &actual); + grub_dprintf ("usb", "control: err=%d\n", err); grub_free (transfer->transactions); @@ -248,8 +281,7 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, size -= tr->size; } - err = dev->controller.dev->transfer (&dev->controller, transfer, timeout, - actual); + err = grub_usb_execute_and_wait_transfer (dev, transfer, timeout, actual); /* We must remember proper toggle value even if some transactions * were not processed - correct value should be inversion of last * processed transaction (TD). */ diff --git a/include/grub/usb.h b/include/grub/usb.h index bb3336580..e7d119646 100644 --- a/include/grub/usb.h +++ b/include/grub/usb.h @@ -30,6 +30,7 @@ typedef struct grub_usb_controller_dev *grub_usb_controller_dev_t; typedef enum { GRUB_USB_ERR_NONE, + GRUB_USB_ERR_WAIT, GRUB_USB_ERR_INTERNAL, GRUB_USB_ERR_STALL, GRUB_USB_ERR_DATA, @@ -97,6 +98,7 @@ grub_usb_err_t grub_usb_root_hub (grub_usb_controller_t controller); + /* XXX: All handled by libusb for now. */ struct grub_usb_controller_dev { @@ -105,9 +107,15 @@ struct grub_usb_controller_dev int (*iterate) (int (*hook) (grub_usb_controller_t dev)); - grub_usb_err_t (*transfer) (grub_usb_controller_t dev, - grub_usb_transfer_t transfer, - int timeout, grub_size_t *actual); + grub_usb_err_t (*setup_transfer) (grub_usb_controller_t dev, + grub_usb_transfer_t transfer); + + grub_usb_err_t (*check_transfer) (grub_usb_controller_t dev, + grub_usb_transfer_t transfer, + grub_size_t *actual); + + grub_usb_err_t (*cancel_transfer) (grub_usb_controller_t dev, + grub_usb_transfer_t transfer); int (*hubports) (grub_usb_controller_t dev); diff --git a/include/grub/usbtrans.h b/include/grub/usbtrans.h index a5bb2e8b2..486e83f40 100644 --- a/include/grub/usbtrans.h +++ b/include/grub/usbtrans.h @@ -62,6 +62,8 @@ struct grub_usb_transfer int last_trans; /* Index of last processed transaction in OHCI/UHCI driver. */ + + void *controller_data; }; typedef struct grub_usb_transfer *grub_usb_transfer_t; From e959937cfd6fca6f85da92c9b5b7f0153b276102 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 21 Aug 2010 17:12:51 +0200 Subject: [PATCH 036/214] Use background transfers for usb_keyboard --- bus/usb/usbtrans.c | 97 +++++++++++++++++++++++++++++++++-------- include/grub/usb.h | 5 +++ include/grub/usbtrans.h | 6 +++ term/usb_keyboard.c | 41 ++++++++++++++--- 4 files changed, 127 insertions(+), 22 deletions(-) diff --git a/bus/usb/usbtrans.c b/bus/usb/usbtrans.c index 27377a3a5..5d6966ecc 100644 --- a/bus/usb/usbtrans.c +++ b/bus/usb/usbtrans.c @@ -195,29 +195,27 @@ grub_usb_control_msg (grub_usb_device_t dev, return err; } -static grub_usb_err_t -grub_usb_bulk_readwrite (grub_usb_device_t dev, - int endpoint, grub_size_t size0, char *data_in, - grub_transfer_type_t type, int timeout, - grub_size_t *actual) +static grub_usb_transfer_t +grub_usb_bulk_setup_readwrite (grub_usb_device_t dev, + int endpoint, grub_size_t size0, char *data_in, + grub_transfer_type_t type) { int i; grub_usb_transfer_t transfer; int datablocks; unsigned int max; - grub_usb_err_t err; - int toggle = dev->toggle[endpoint]; volatile char *data; grub_uint32_t data_addr; struct grub_pci_dma_chunk *data_chunk; grub_size_t size = size0; + int toggle = dev->toggle[endpoint]; grub_dprintf ("usb", "bulk: size=0x%02x type=%d\n", size, type); /* FIXME: avoid allocation any kind of buffer in a first place. */ data_chunk = grub_memalign_dma32 (128, size); if (!data_chunk) - return GRUB_USB_ERR_INTERNAL; + return NULL; data = grub_dma_get_virt (data_chunk); data_addr = grub_dma_get_phys (data_chunk); if (type == GRUB_USB_TRANSFER_TYPE_OUT) @@ -242,7 +240,7 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, if (! transfer) { grub_dma_free (data_chunk); - return GRUB_USB_ERR_INTERNAL; + return NULL; } datablocks = ((size + max - 1) / max); @@ -251,9 +249,12 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, transfer->endpoint = endpoint & 15; transfer->devaddr = dev->addr; transfer->type = GRUB_USB_TRANSACTION_TYPE_BULK; + transfer->dir = type; transfer->max = max; transfer->dev = dev; transfer->last_trans = -1; /* Reset index of last processed transaction (TD) */ + transfer->data_chunk = data_chunk; + transfer->data = data_in; /* Allocate an array of transfer data structures. */ transfer->transactions = grub_malloc (transfer->transcnt @@ -262,7 +263,7 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, { grub_free (transfer); grub_dma_free (data_chunk); - return GRUB_USB_ERR_INTERNAL; + return NULL; } /* Set up all transfers. */ @@ -280,24 +281,51 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev, tr->preceding = i * max; size -= tr->size; } + return transfer; +} + +static void +grub_usb_bulk_finish_readwrite (grub_usb_transfer_t transfer) +{ + grub_usb_device_t dev = transfer->dev; + int toggle = dev->toggle[transfer->endpoint]; - err = grub_usb_execute_and_wait_transfer (dev, transfer, timeout, actual); /* We must remember proper toggle value even if some transactions * were not processed - correct value should be inversion of last * processed transaction (TD). */ if (transfer->last_trans >= 0) toggle = transfer->transactions[transfer->last_trans].toggle ? 0 : 1; else - toggle = dev->toggle[endpoint]; /* Nothing done, take original */ - grub_dprintf ("usb", "bulk: err=%d, toggle=%d\n", err, toggle); - dev->toggle[endpoint] = toggle; + toggle = dev->toggle[transfer->endpoint]; /* Nothing done, take original */ + grub_dprintf ("usb", "bulk: toggle=%d\n", toggle); + dev->toggle[transfer->endpoint] = toggle; + + if (transfer->dir == GRUB_USB_TRANSFER_TYPE_IN) + grub_memcpy (transfer->data, (void *) + grub_dma_get_virt (transfer->data_chunk), + transfer->size + 1); grub_free (transfer->transactions); grub_free (transfer); - grub_dma_free (data_chunk); + grub_dma_free (transfer->data_chunk); +} - if (type == GRUB_USB_TRANSFER_TYPE_IN) - grub_memcpy (data_in, (char *) data, size0); +static grub_usb_err_t +grub_usb_bulk_readwrite (grub_usb_device_t dev, + int endpoint, grub_size_t size0, char *data_in, + grub_transfer_type_t type, int timeout, + grub_size_t *actual) +{ + grub_usb_err_t err; + grub_usb_transfer_t transfer; + + transfer = grub_usb_bulk_setup_readwrite (dev, endpoint, size0, + data_in, type); + if (!transfer) + return GRUB_USB_ERR_INTERNAL; + err = grub_usb_execute_and_wait_transfer (dev, transfer, timeout, actual); + + grub_usb_bulk_finish_readwrite (transfer); return err; } @@ -329,6 +357,41 @@ grub_usb_bulk_read (grub_usb_device_t dev, return err; } +grub_usb_err_t +grub_usb_check_transfer (grub_usb_transfer_t transfer, grub_size_t *actual) +{ + grub_usb_err_t err; + grub_usb_device_t dev = transfer->dev; + + err = dev->controller.dev->check_transfer (&dev->controller, transfer, + actual); + if (err == GRUB_USB_ERR_WAIT) + return err; + + grub_usb_bulk_finish_readwrite (transfer); + + return err; +} + +grub_usb_transfer_t +grub_usb_bulk_read_background (grub_usb_device_t dev, + int endpoint, grub_size_t size, void *data) +{ + grub_usb_err_t err; + grub_usb_transfer_t transfer; + + transfer = grub_usb_bulk_setup_readwrite (dev, endpoint, size, + data, GRUB_USB_TRANSFER_TYPE_IN); + if (!transfer) + return NULL; + + err = dev->controller.dev->setup_transfer (&dev->controller, transfer); + if (err) + return NULL; + + return transfer; +} + grub_usb_err_t grub_usb_bulk_read_extended (grub_usb_device_t dev, int endpoint, grub_size_t size, char *data, diff --git a/include/grub/usb.h b/include/grub/usb.h index e7d119646..768ec2f66 100644 --- a/include/grub/usb.h +++ b/include/grub/usb.h @@ -274,5 +274,10 @@ grub_usb_err_t grub_usb_bulk_read_extended (grub_usb_device_t dev, int endpoint, grub_size_t size, char *data, int timeout, grub_size_t *actual); +grub_usb_transfer_t +grub_usb_bulk_read_background (grub_usb_device_t dev, + int endpoint, grub_size_t size, void *data); +grub_usb_err_t +grub_usb_check_transfer (grub_usb_transfer_t trans, grub_size_t *actual); #endif /* GRUB_USB_H */ diff --git a/include/grub/usbtrans.h b/include/grub/usbtrans.h index 486e83f40..a8aca3119 100644 --- a/include/grub/usbtrans.h +++ b/include/grub/usbtrans.h @@ -56,6 +56,8 @@ struct grub_usb_transfer grub_transaction_type_t type; + grub_transfer_type_t dir; + struct grub_usb_device *dev; struct grub_usb_transaction *transactions; @@ -64,6 +66,10 @@ struct grub_usb_transfer /* Index of last processed transaction in OHCI/UHCI driver. */ void *controller_data; + + /* Used when finishing transfer to copy data back. */ + struct grub_pci_dma_chunk *data_chunk; + void *data; }; typedef struct grub_usb_transfer *grub_usb_transfer_t; diff --git a/term/usb_keyboard.c b/term/usb_keyboard.c index adb84fa94..1a486b53d 100644 --- a/term/usb_keyboard.c +++ b/term/usb_keyboard.c @@ -84,6 +84,9 @@ struct grub_usb_keyboard_data grub_uint8_t status; int key; struct grub_usb_desc_endp *endp; + grub_usb_transfer_t transfer; + grub_uint8_t report[8]; + int dead; }; static struct grub_term_input grub_usb_keyboards[16]; @@ -214,8 +217,20 @@ grub_usb_keyboard_attach (grub_usb_device_t usbdev, int configno, int interfno) data->key = -1; #endif + data->transfer = grub_usb_bulk_read_background (usbdev, + data->endp->endp_addr, + sizeof (data->report), + (char *) data->report); + if (!data->transfer) + { + grub_print_error (); + return 0; + } + grub_term_register_input_active ("usb_keyboard", &grub_usb_keyboards[curnum]); + data->dead = 0; + return 1; } @@ -224,19 +239,35 @@ grub_usb_keyboard_attach (grub_usb_device_t usbdev, int configno, int interfno) static int grub_usb_keyboard_checkkey (struct grub_term_input *term) { - grub_uint8_t data[8]; grub_usb_err_t err; struct grub_usb_keyboard_data *termdata = term->data; + grub_uint8_t data[sizeof (termdata->report)]; grub_size_t actual; if (termdata->key != -1) return termdata->key; - data[2] = 0; + if (termdata->dead) + return -1; + /* Poll interrupt pipe. */ - err = grub_usb_bulk_read_extended (termdata->usbdev, - termdata->endp->endp_addr, sizeof (data), - (char *) data, 10, &actual); + err = grub_usb_check_transfer (termdata->transfer, &actual); + + if (err == GRUB_USB_ERR_WAIT) + return -1; + + grub_memcpy (data, termdata->report, sizeof (data)); + + termdata->transfer = grub_usb_bulk_read_background (termdata->usbdev, + termdata->endp->endp_addr, + sizeof (termdata->report), + (char *) termdata->report); + if (!termdata->transfer) + { + grub_printf ("%s failed. Stopped\n", term->name); + termdata->dead = 1; + } + if (err || actual < 1) return -1; From 2eb310be7981acf9284ae68857711da29b59ceb7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 21 Aug 2010 18:24:09 +0200 Subject: [PATCH 037/214] Enable usb device polling again --- bus/usb/usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bus/usb/usb.c b/bus/usb/usb.c index 80d386c8d..2bd805ef2 100644 --- a/bus/usb/usb.c +++ b/bus/usb/usb.c @@ -338,7 +338,7 @@ grub_usb_unregister_attach_hook_class (struct grub_usb_attach_desc *desc) GRUB_MOD_INIT(usb) { - // grub_term_poll_usb = grub_usb_poll_devices; + grub_term_poll_usb = grub_usb_poll_devices; } GRUB_MOD_FINI(usb) From 0aaf4938c785b06e611351bb927d9c1689355629 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 21 Aug 2010 19:41:37 +0200 Subject: [PATCH 038/214] Fix incorrect toggle calculation --- bus/usb/uhci.c | 2 +- bus/usb/usbtrans.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bus/usb/uhci.c b/bus/usb/uhci.c index 4792f961a..addfb41e8 100644 --- a/bus/usb/uhci.c +++ b/bus/usb/uhci.c @@ -474,7 +474,7 @@ grub_uhci_setup_transfer (grub_usb_controller_t dev, { grub_usb_transaction_t tr = &transfer->transactions[i]; - td = grub_uhci_transaction (u, transfer->endpoint, tr->pid, + td = grub_uhci_transaction (u, transfer->endpoint & 15, tr->pid, transfer->devaddr, tr->toggle, tr->size, tr->data); if (! td) diff --git a/bus/usb/usbtrans.c b/bus/usb/usbtrans.c index 5d6966ecc..7e6840083 100644 --- a/bus/usb/usbtrans.c +++ b/bus/usb/usbtrans.c @@ -246,7 +246,7 @@ grub_usb_bulk_setup_readwrite (grub_usb_device_t dev, datablocks = ((size + max - 1) / max); transfer->transcnt = datablocks; transfer->size = size - 1; - transfer->endpoint = endpoint & 15; + transfer->endpoint = endpoint; transfer->devaddr = dev->addr; transfer->type = GRUB_USB_TRANSACTION_TYPE_BULK; transfer->dir = type; From 5a2823c1913acbb22d06191b1057e7651f5936db Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 21 Aug 2010 19:42:31 +0200 Subject: [PATCH 039/214] Give better debug message in usb_keyboard_checkkey --- term/usb_keyboard.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/term/usb_keyboard.c b/term/usb_keyboard.c index 1a486b53d..e9be331cf 100644 --- a/term/usb_keyboard.c +++ b/term/usb_keyboard.c @@ -258,6 +258,13 @@ grub_usb_keyboard_checkkey (struct grub_term_input *term) grub_memcpy (data, termdata->report, sizeof (data)); + grub_dprintf ("usb_keyboard", + "err = %d, actual = %d report: 0x%02x 0x%02x 0x%02x 0x%02x" + " 0x%02x 0x%02x 0x%02x 0x%02x\n", + err, actual, + data[0], data[1], data[2], data[3], + data[4], data[5], data[6], data[7]); + termdata->transfer = grub_usb_bulk_read_background (termdata->usbdev, termdata->endp->endp_addr, sizeof (termdata->report), @@ -276,12 +283,6 @@ grub_usb_keyboard_checkkey (struct grub_term_input *term) if (actual < 3 || !data[2]) return -1; - grub_dprintf ("usb_keyboard", - "report: 0x%02x 0x%02x 0x%02x 0x%02x" - " 0x%02x 0x%02x 0x%02x 0x%02x\n", - data[0], data[1], data[2], data[3], - data[4], data[5], data[6], data[7]); - /* Check if the Control or Shift key was pressed. */ if (data[0] & 0x01 || data[0] & 0x10) termdata->key = keyboard_map[data[2]] - 'a' + 1; From b481fe847a3cc1642085940f541c8fda8a5f878d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 21 Aug 2010 20:54:20 +0200 Subject: [PATCH 040/214] really set controller_data in ohci --- bus/usb/ohci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bus/usb/ohci.c b/bus/usb/ohci.c index ba723996a..66b7c0855 100644 --- a/bus/usb/ohci.c +++ b/bus/usb/ohci.c @@ -832,6 +832,8 @@ grub_ohci_setup_transfer (grub_usb_controller_t dev, } } + transfer->controller_data = cdata; + return GRUB_USB_ERR_NONE; } From 3593f89bf3cebb02a5881ee71ac09cb61f5195da Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 21 Aug 2010 21:39:15 +0200 Subject: [PATCH 041/214] clear port status change afte polling it --- bus/usb/ohci.c | 12 ++++++++++-- bus/usb/uhci.c | 24 ++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/bus/usb/ohci.c b/bus/usb/ohci.c index 66b7c0855..e3cd490ac 100644 --- a/bus/usb/ohci.c +++ b/bus/usb/ohci.c @@ -1349,8 +1349,16 @@ grub_ohci_detect_dev (grub_usb_controller_t dev, int port, int *changed) grub_dprintf ("ohci", "detect_dev status=0x%02x\n", status); - /* Connect Status Change bit - it detects change of connection */ - *changed = ((status & GRUB_OHCI_RESET_CONNECT_CHANGE) != 0); + /* Connect Status Change bit - it detects change of connection */ + if (status & GRUB_OHCI_RESET_CONNECT_CHANGE) + { + *changed = 1; + /* Reset bit Connect Status Change */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, + GRUB_OHCI_RESET_CONNECT_CHANGE); + } + else + *changed = 0; if (! (status & 1)) return GRUB_USB_SPEED_NONE; diff --git a/bus/usb/uhci.c b/bus/usb/uhci.c index addfb41e8..472a7054e 100644 --- a/bus/usb/uhci.c +++ b/bus/usb/uhci.c @@ -39,6 +39,18 @@ typedef enum #define GRUB_UHCI_LINK_TERMINATE 1 #define GRUB_UHCI_LINK_QUEUE_HEAD 2 +enum + { + GRUB_UHCI_REG_PORTSC_CONNECT_CHANGED = 0x0002, + GRUB_UHCI_REG_PORTSC_PORT_ENABLED = 0x0004, + GRUB_UHCI_REG_PORTSC_RESUME = 0x0040, + GRUB_UHCI_REG_PORTSC_RESET = 0x0200, + GRUB_UHCI_REG_PORTSC_SUSPEND = 0x1000, + GRUB_UHCI_REG_PORTSC_RW = GRUB_UHCI_REG_PORTSC_PORT_ENABLED + | GRUB_UHCI_REG_PORTSC_RESUME | GRUB_UHCI_REG_PORTSC_RESET + | GRUB_UHCI_REG_PORTSC_SUSPEND + }; + /* UHCI Queue Head. */ struct grub_uhci_qh @@ -693,7 +705,7 @@ grub_uhci_portstatus (grub_usb_controller_t dev, return grub_error (GRUB_ERR_IO, "UHCI Timed out"); /* Reset bit Connect Status Change */ - grub_uhci_writereg16 (u, reg, status | (1 << 1)); + grub_uhci_writereg16 (u, reg, status | GRUB_UHCI_REG_PORTSC_CONNECT_CHANGED); /* Read final port status */ status = grub_uhci_readreg16 (u, reg); @@ -725,7 +737,15 @@ grub_uhci_detect_dev (grub_usb_controller_t dev, int port, int *changed) grub_dprintf ("uhci", "detect=0x%02x port=%d\n", status, port); /* Connect Status Change bit - it detects change of connection */ - *changed = ((status & (1 << 1)) != 0); + if (status & (1 << 1)) + { + *changed = 1; + /* Reset bit Connect Status Change */ + grub_uhci_writereg16 (u, reg, (status & GRUB_UHCI_REG_PORTSC_RW) + | GRUB_UHCI_REG_PORTSC_CONNECT_CHANGED); + } + else + *changed = 0; if (! (status & 1)) return GRUB_USB_SPEED_NONE; From f609c84a7fc5ae8b4729a39bcad8c90325c1aa85 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 21 Aug 2010 21:55:24 +0200 Subject: [PATCH 042/214] MAke an enum out of reqtype --- include/grub/usb.h | 8 -------- include/grub/usbtrans.h | 28 +++++++++++++++++++--------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/include/grub/usb.h b/include/grub/usb.h index 768ec2f66..315ae9455 100644 --- a/include/grub/usb.h +++ b/include/grub/usb.h @@ -49,14 +49,6 @@ typedef enum GRUB_USB_SPEED_HIGH } grub_usb_speed_t; -enum - { - GRUB_USB_REQTYPE_CLASS_INTERFACE_OUT = 0x21, - GRUB_USB_REQTYPE_VENDOR_OUT = 0x40, - GRUB_USB_REQTYPE_CLASS_INTERFACE_IN = 0xa1, - GRUB_USB_REQTYPE_VENDOR_IN = 0xc0 - }; - /* Call HOOK with each device, until HOOK returns non-zero. */ int grub_usb_iterate (int (*hook) (grub_usb_device_t dev)); diff --git a/include/grub/usbtrans.h b/include/grub/usbtrans.h index a8aca3119..ae2fd1bc4 100644 --- a/include/grub/usbtrans.h +++ b/include/grub/usbtrans.h @@ -74,15 +74,25 @@ struct grub_usb_transfer typedef struct grub_usb_transfer *grub_usb_transfer_t; -#define GRUB_USB_REQTYPE_IN (1 << 7) -#define GRUB_USB_REQTYPE_OUT (0 << 7) -#define GRUB_USB_REQTYPE_STANDARD (0 << 5) -#define GRUB_USB_REQTYPE_CLASS (1 << 5) -#define GRUB_USB_REQTYPE_VENDOR (2 << 5) -#define GRUB_USB_REQTYPE_TARGET_DEV (0 << 0) -#define GRUB_USB_REQTYPE_TARGET_INTERF (1 << 0) -#define GRUB_USB_REQTYPE_TARGET_ENDP (2 << 0) -#define GRUB_USB_REQTYPE_TARGET_OTHER (3 << 0) + +enum + { + GRUB_USB_REQTYPE_TARGET_DEV = (0 << 0), + GRUB_USB_REQTYPE_TARGET_INTERF = (1 << 0), + GRUB_USB_REQTYPE_TARGET_ENDP = (2 << 0), + GRUB_USB_REQTYPE_TARGET_OTHER = (3 << 0), + GRUB_USB_REQTYPE_STANDARD = (0 << 5), + GRUB_USB_REQTYPE_CLASS = (1 << 5), + GRUB_USB_REQTYPE_VENDOR = (2 << 5), + GRUB_USB_REQTYPE_OUT = (0 << 7), + GRUB_USB_REQTYPE_IN = (1 << 7), + GRUB_USB_REQTYPE_CLASS_INTERFACE_OUT = GRUB_USB_REQTYPE_TARGET_INTERF + | GRUB_USB_REQTYPE_CLASS | GRUB_USB_REQTYPE_OUT, + GRUB_USB_REQTYPE_VENDOR_OUT = GRUB_USB_REQTYPE_VENDOR | GRUB_USB_REQTYPE_OUT, + GRUB_USB_REQTYPE_CLASS_INTERFACE_IN = GRUB_USB_REQTYPE_TARGET_INTERF + | GRUB_USB_REQTYPE_CLASS | GRUB_USB_REQTYPE_IN, + GRUB_USB_REQTYPE_VENDOR_IN = GRUB_USB_REQTYPE_VENDOR | GRUB_USB_REQTYPE_IN + }; #define GRUB_USB_REQ_GET_STATUS 0x00 #define GRUB_USB_REQ_CLEAR_FEATURE 0x01 From ff62c48f5a8f2b35ab73eca078e5c5aed4755eb6 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 21 Aug 2010 23:09:37 +0200 Subject: [PATCH 043/214] Use status change pipe for hub hotplug detection --- bus/usb/usbhub.c | 112 +++++++++++++++++++++++++++++++++++----- bus/usb/usbtrans.c | 8 +++ include/grub/usb.h | 10 ++++ include/grub/usbtrans.h | 57 +++++++++++++------- term/usb_keyboard.c | 12 +++++ 5 files changed, 167 insertions(+), 32 deletions(-) diff --git a/bus/usb/usbhub.c b/bus/usb/usbhub.c index 7f2c8d24b..111a2495e 100644 --- a/bus/usb/usbhub.c +++ b/bus/usb/usbhub.c @@ -177,16 +177,16 @@ grub_usb_add_hub (grub_usb_device_t dev) grub_dprintf ("usb", "Hub port %d status: 0x%02x\n", i, status); /* If connected, reset and enable the port. */ - if (status & GRUB_USB_HUB_STATUS_CONNECTED) + if (status & GRUB_USB_HUB_STATUS_PORT_CONNECTED) { grub_usb_speed_t speed; /* Determine the device speed. */ - if (status & GRUB_USB_HUB_STATUS_LOWSPEED) + if (status & GRUB_USB_HUB_STATUS_PORT_LOWSPEED) speed = GRUB_USB_SPEED_LOW; else { - if (status & GRUB_USB_HUB_STATUS_HIGHSPEED) + if (status & GRUB_USB_HUB_STATUS_PORT_HIGHSPEED) speed = GRUB_USB_SPEED_HIGH; else speed = GRUB_USB_SPEED_FULL; @@ -231,7 +231,7 @@ grub_usb_add_hub (grub_usb_device_t dev) | GRUB_USB_REQTYPE_CLASS | GRUB_USB_REQTYPE_TARGET_OTHER), GRUB_USB_REQ_CLEAR_FEATURE, - GRUB_USB_HUB_FEATURE_C_CONNECTED, + GRUB_USB_HUB_FEATURE_C_PORT_CONNECTED, i, 0, 0); /* Just ignore the device if the Hub reports some error */ if (err) @@ -252,6 +252,25 @@ grub_usb_add_hub (grub_usb_device_t dev) } } + for (i = 0; i < dev->config[0].interf[0].descif->endpointcnt; + i++) + { + struct grub_usb_desc_endp *endp = NULL; + endp = &dev->config[0].interf[0].descendp[i]; + + if ((endp->endp_addr & 128) && grub_usb_get_ep_type(endp) + == GRUB_USB_EP_INTERRUPT) + { + dev->hub_endpoint = endp; + dev->hub_transfer + = grub_usb_bulk_read_background (dev, endp->endp_addr, + grub_min (endp->maxpacket, + sizeof (dev->statuschange)), + (char *) &dev->statuschange); + break; + } + } + return GRUB_ERR_NONE; } @@ -341,6 +360,9 @@ detach_device (grub_usb_device_t dev) return; if (dev->descdev.class == GRUB_USB_CLASS_HUB) { + if (dev->hub_transfer) + grub_usb_cancel_transfer (dev->hub_transfer); + for (i = 0; i < dev->nports; i++) detach_device (dev->children[i]); grub_free (dev->children); @@ -364,41 +386,105 @@ poll_nonroot_hub (grub_usb_device_t dev) grub_uint64_t timeout; grub_usb_device_t next_dev; grub_usb_device_t *attached_devices = dev->children; - + grub_uint8_t changed; + grub_size_t actual; + + if (!dev->hub_transfer) + return; + + err = grub_usb_check_transfer (dev->hub_transfer, &actual); + + if (err == GRUB_USB_ERR_WAIT) + return; + + changed = dev->statuschange; + + dev->hub_transfer + = grub_usb_bulk_read_background (dev, dev->hub_endpoint->endp_addr, + grub_min (dev->hub_endpoint->maxpacket, + sizeof (dev->statuschange)), + (char *) &dev->statuschange); + + if (err || actual == 0 || changed == 0) + return; + + grub_dprintf ("usb", "statuschanged = %02x, err = %d, actual = %d\n", + changed, err, actual); + /* Iterate over the Hub ports. */ for (i = 1; i <= dev->nports; i++) { grub_uint32_t status; + if (!(changed & (1 << i))) + continue; + /* Get the port status. */ err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN | GRUB_USB_REQTYPE_CLASS | GRUB_USB_REQTYPE_TARGET_OTHER), GRUB_USB_REQ_GET_STATUS, 0, i, sizeof (status), (char *) &status); - /* Just ignore the device if the Hub does not report the - status. */ + if (err) continue; - if (status & GRUB_USB_HUB_STATUS_C_CONNECTED) + /* FIXME: properly handle these conditions. */ + if (status & GRUB_USB_HUB_STATUS_C_PORT_RESET) + grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_CLEAR_FEATURE, + GRUB_USB_HUB_FEATURE_C_PORT_RESET, i, 0, 0); + + if (status & GRUB_USB_HUB_STATUS_C_PORT_ENABLED) + grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_CLEAR_FEATURE, + GRUB_USB_HUB_FEATURE_C_PORT_ENABLED, i, 0, 0); + + if (status & GRUB_USB_HUB_STATUS_C_PORT_SUSPEND) + grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_CLEAR_FEATURE, + GRUB_USB_HUB_FEATURE_C_PORT_SUSPEND, i, 0, 0); + + if (status & GRUB_USB_HUB_STATUS_C_PORT_OVERCURRENT) + grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_CLEAR_FEATURE, + GRUB_USB_HUB_FEATURE_C_PORT_OVERCURRENT, i, 0, 0); + + if (!(status & GRUB_USB_HUB_STATUS_C_PORT_CONNECTED)) + continue; + + grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_CLEAR_FEATURE, + GRUB_USB_HUB_FEATURE_C_PORT_CONNECTED, i, 0, 0); + + if (status & GRUB_USB_HUB_STATUS_C_PORT_CONNECTED) { detach_device (attached_devices[i-1]); attached_devices[i - 1] = NULL; } /* Connected and status of connection changed ? */ - if ((status & GRUB_USB_HUB_STATUS_CONNECTED) - && (status & GRUB_USB_HUB_STATUS_C_CONNECTED)) + if ((status & GRUB_USB_HUB_STATUS_PORT_CONNECTED) + && (status & GRUB_USB_HUB_STATUS_C_PORT_CONNECTED)) { grub_usb_speed_t speed; /* Determine the device speed. */ - if (status & GRUB_USB_HUB_STATUS_LOWSPEED) + if (status & GRUB_USB_HUB_STATUS_PORT_LOWSPEED) speed = GRUB_USB_SPEED_LOW; else { - if (status & GRUB_USB_HUB_STATUS_HIGHSPEED) + if (status & GRUB_USB_HUB_STATUS_PORT_HIGHSPEED) speed = GRUB_USB_SPEED_HIGH; else speed = GRUB_USB_SPEED_FULL; @@ -442,7 +528,7 @@ poll_nonroot_hub (grub_usb_device_t dev) | GRUB_USB_REQTYPE_CLASS | GRUB_USB_REQTYPE_TARGET_OTHER), GRUB_USB_REQ_CLEAR_FEATURE, - GRUB_USB_HUB_FEATURE_C_CONNECTED, + GRUB_USB_HUB_FEATURE_C_PORT_CONNECTED, i, 0, 0); /* Just ignore the device if the Hub reports some error */ if (err) diff --git a/bus/usb/usbtrans.c b/bus/usb/usbtrans.c index 7e6840083..fe55114c7 100644 --- a/bus/usb/usbtrans.c +++ b/bus/usb/usbtrans.c @@ -392,6 +392,14 @@ grub_usb_bulk_read_background (grub_usb_device_t dev, return transfer; } +void +grub_usb_cancel_transfer (grub_usb_transfer_t transfer) +{ + grub_usb_device_t dev = transfer->dev; + dev->controller.dev->cancel_transfer (&dev->controller, transfer); + grub_errno = GRUB_ERR_NONE; +} + grub_usb_err_t grub_usb_bulk_read_extended (grub_usb_device_t dev, int endpoint, grub_size_t size, char *data, diff --git a/include/grub/usb.h b/include/grub/usb.h index 315ae9455..f9cdb2765 100644 --- a/include/grub/usb.h +++ b/include/grub/usb.h @@ -181,11 +181,19 @@ struct grub_usb_device /* Used by libusb wrapper. Schedulded for removal. */ void *data; + /* Hub information. */ + /* Array of children for a hub. */ grub_usb_device_t *children; /* Number of hub ports. */ unsigned nports; + + grub_usb_transfer_t hub_transfer; + + grub_uint32_t statuschange; + + struct grub_usb_desc_endp *hub_endpoint; }; @@ -271,5 +279,7 @@ grub_usb_bulk_read_background (grub_usb_device_t dev, int endpoint, grub_size_t size, void *data); grub_usb_err_t grub_usb_check_transfer (grub_usb_transfer_t trans, grub_size_t *actual); +void +grub_usb_cancel_transfer (grub_usb_transfer_t trans); #endif /* GRUB_USB_H */ diff --git a/include/grub/usbtrans.h b/include/grub/usbtrans.h index ae2fd1bc4..9e9d75e5d 100644 --- a/include/grub/usbtrans.h +++ b/include/grub/usbtrans.h @@ -94,31 +94,50 @@ enum GRUB_USB_REQTYPE_VENDOR_IN = GRUB_USB_REQTYPE_VENDOR | GRUB_USB_REQTYPE_IN }; -#define GRUB_USB_REQ_GET_STATUS 0x00 -#define GRUB_USB_REQ_CLEAR_FEATURE 0x01 -#define GRUB_USB_REQ_SET_FEATURE 0x03 -#define GRUB_USB_REQ_SET_ADDRESS 0x05 -#define GRUB_USB_REQ_GET_DESCRIPTOR 0x06 -#define GRUB_USB_REQ_SET_DESCRIPTOR 0x07 -#define GRUB_USB_REQ_GET_CONFIGURATION 0x08 -#define GRUB_USB_REQ_SET_CONFIGURATION 0x09 -#define GRUB_USB_REQ_GET_INTERFACE 0x0A -#define GRUB_USB_REQ_SET_INTERFACE 0x0B -#define GRUB_USB_REQ_SYNC_FRAME 0x0C +enum + { + GRUB_USB_REQ_GET_STATUS = 0x00, + GRUB_USB_REQ_CLEAR_FEATURE = 0x01, + GRUB_USB_REQ_SET_FEATURE = 0x03, + GRUB_USB_REQ_SET_ADDRESS = 0x05, + GRUB_USB_REQ_GET_DESCRIPTOR = 0x06, + GRUB_USB_REQ_SET_DESCRIPTOR = 0x07, + GRUB_USB_REQ_GET_CONFIGURATION = 0x08, + GRUB_USB_REQ_SET_CONFIGURATION = 0x09, + GRUB_USB_REQ_GET_INTERFACE = 0x0A, + GRUB_USB_REQ_SET_INTERFACE = 0x0B, + GRUB_USB_REQ_SYNC_FRAME = 0x0C + }; #define GRUB_USB_FEATURE_ENDP_HALT 0x00 #define GRUB_USB_FEATURE_DEV_REMOTE_WU 0x01 #define GRUB_USB_FEATURE_TEST_MODE 0x02 -#define GRUB_USB_HUB_FEATURE_PORT_RESET 0x04 -#define GRUB_USB_HUB_FEATURE_PORT_POWER 0x08 -#define GRUB_USB_HUB_FEATURE_C_CONNECTED 0x10 +enum + { + GRUB_USB_HUB_FEATURE_PORT_RESET = 0x04, + GRUB_USB_HUB_FEATURE_PORT_POWER = 0x08, + GRUB_USB_HUB_FEATURE_C_PORT_CONNECTED = 0x10, + GRUB_USB_HUB_FEATURE_C_PORT_ENABLED = 0x11, + GRUB_USB_HUB_FEATURE_C_PORT_SUSPEND = 0x12, + GRUB_USB_HUB_FEATURE_C_PORT_OVERCURRENT = 0x13, + GRUB_USB_HUB_FEATURE_C_PORT_RESET = 0x14 + }; -#define GRUB_USB_HUB_STATUS_CONNECTED (1 << 0) -#define GRUB_USB_HUB_STATUS_LOWSPEED (1 << 9) -#define GRUB_USB_HUB_STATUS_HIGHSPEED (1 << 10) -#define GRUB_USB_HUB_STATUS_C_CONNECTED (1 << 16) -#define GRUB_USB_HUB_STATUS_C_PORT_RESET (1 << 20) +enum + { + GRUB_USB_HUB_STATUS_PORT_CONNECTED = (1 << 0), + GRUB_USB_HUB_STATUS_PORT_ENABLED = (1 << 1), + GRUB_USB_HUB_STATUS_PORT_SUSPEND = (1 << 2), + GRUB_USB_HUB_STATUS_PORT_OVERCURRENT = (1 << 3), + GRUB_USB_HUB_STATUS_PORT_LOWSPEED = (1 << 9), + GRUB_USB_HUB_STATUS_PORT_HIGHSPEED = (1 << 10), + GRUB_USB_HUB_STATUS_C_PORT_CONNECTED = (1 << 16), + GRUB_USB_HUB_STATUS_C_PORT_ENABLED = (1 << 17), + GRUB_USB_HUB_STATUS_C_PORT_SUSPEND = (1 << 18), + GRUB_USB_HUB_STATUS_C_PORT_OVERCURRENT = (1 << 19), + GRUB_USB_HUB_STATUS_C_PORT_RESET = (1 << 20) + }; struct grub_usb_packet_setup { diff --git a/term/usb_keyboard.c b/term/usb_keyboard.c index e9be331cf..ea13418e0 100644 --- a/term/usb_keyboard.c +++ b/term/usb_keyboard.c @@ -107,6 +107,9 @@ grub_usb_keyboard_detach (grub_usb_device_t usbdev, if (data->usbdev != usbdev) continue; + if (data->transfer) + grub_usb_cancel_transfer (data->transfer); + grub_term_unregister_input (&grub_usb_keyboards[i]); grub_free ((char *) grub_usb_keyboards[i].name); grub_usb_keyboards[i].name = NULL; @@ -351,9 +354,18 @@ GRUB_MOD_FINI(usb_keyboard) for (i = 0; i < ARRAY_SIZE (grub_usb_keyboards); i++) if (grub_usb_keyboards[i].data) { + struct grub_usb_keyboard_data *data = grub_usb_keyboards[i].data; + + if (!data) + continue; + + if (data->transfer) + grub_usb_cancel_transfer (data->transfer); + grub_term_unregister_input (&grub_usb_keyboards[i]); grub_free ((char *) grub_usb_keyboards[i].name); grub_usb_keyboards[i].name = NULL; + grub_free (grub_usb_keyboards[i].data); grub_usb_keyboards[i].data = 0; } grub_usb_unregister_attach_hook_class (&attach_hook); From ab247a453f02a2eb0f02d35b6950d26cf6eb327b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 22 Aug 2010 00:01:21 +0200 Subject: [PATCH 044/214] Ignore keyboard errors and track numlock status --- term/usb_keyboard.c | 40 +++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/term/usb_keyboard.c b/term/usb_keyboard.c index fc1435c05..759b3eb7d 100644 --- a/term/usb_keyboard.c +++ b/term/usb_keyboard.c @@ -99,8 +99,21 @@ static grub_uint8_t usb_to_at_map[128] = /* 0x7e */ 0x00, 0x00, }; -#define CAPS_LOCK 0x39 -#define CAPS_LOCK_LED 0x02 +enum + { + KEY_NO_KEY = 0x00, + KEY_ERR_BUFFER = 0x01, + KEY_ERR_POST = 0x02, + KEY_ERR_UNDEF = 0x03, + KEY_CAPS_LOCK = 0x39, + KEY_NUM_LOCK = 0x53, + }; + +enum + { + LED_NUM_LOCK = 0x01, + LED_CAPS_LOCK = 0x02 + }; /* Valid values for bRequest. See HID definition version 1.11 section 7.2. */ #define USB_HID_GET_REPORT 0x01 @@ -328,7 +341,9 @@ send_leds (struct grub_usb_keyboard_data *termdata) char report[1]; report[0] = 0; if (termdata->mods & GRUB_TERM_STATUS_CAPS) - report[0] |= CAPS_LOCK_LED; + report[0] |= LED_CAPS_LOCK; + if (termdata->mods & GRUB_TERM_STATUS_NUM) + report[0] |= LED_NUM_LOCK; grub_usb_control_msg (termdata->usbdev, GRUB_USB_REQTYPE_CLASS_INTERFACE_OUT, USB_HID_SET_REPORT, 0x0200, termdata->interfno, sizeof (report), (char *) report); @@ -380,18 +395,29 @@ grub_usb_keyboard_checkkey (struct grub_term_input *term) termdata->status = data[0]; - if (actual < 3 || !data[2]) + if (actual < 3) return -1; - if (data[2] == CAPS_LOCK) + if (data[2] == KEY_NO_KEY || data[2] == KEY_ERR_BUFFER + || data[2] == KEY_ERR_POST || data[2] == KEY_ERR_UNDEF) + return -1; + + if (data[2] == KEY_CAPS_LOCK) { termdata->mods ^= GRUB_TERM_STATUS_CAPS; send_leds (termdata); return -1; } - if (usb_to_at_map[data[2]] == 0) - grub_printf ("Unknown key 0x%x detected\n", data[2]); + if (data[2] == KEY_NUM_LOCK) + { + termdata->mods ^= GRUB_TERM_STATUS_NUM; + send_leds (termdata); + return -1; + } + + if (data[2] > ARRAY_SIZE (usb_to_at_map) || usb_to_at_map[data[2]] == 0) + grub_printf ("Unknown key 0x%02x detected\n", data[2]); else termdata->key = grub_term_map_key (usb_to_at_map[data[2]], interpret_status (data[0]) From 7e6975d7ea371b0cb6986fb028b21d2da5c93d35 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 22 Aug 2010 00:29:34 +0200 Subject: [PATCH 045/214] Support USB key repeat --- include/grub/term.h | 3 +++ term/usb_keyboard.c | 24 ++++++++++++++++++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/include/grub/term.h b/include/grub/term.h index 009258f6e..9956398da 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -490,6 +490,9 @@ grub_print_spaces (struct grub_term_output *term, int number_spaces) extern void (*EXPORT_VAR (grub_term_poll_usb)) (void); +#define GRUB_TERM_REPEAT_PRE_INTERVAL 100 +#define GRUB_TERM_REPEAT_INTERVAL 50 + #endif /* ! ASM_FILE */ #endif /* ! GRUB_TERM_HEADER */ diff --git a/term/usb_keyboard.c b/term/usb_keyboard.c index 759b3eb7d..c3af1694b 100644 --- a/term/usb_keyboard.c +++ b/term/usb_keyboard.c @@ -144,6 +144,8 @@ struct grub_usb_keyboard_data grub_usb_transfer_t transfer; grub_uint8_t report[8]; int dead; + int last_key; + grub_uint64_t repeat_time; }; static struct grub_term_input grub_usb_keyboards[16]; @@ -368,7 +370,16 @@ grub_usb_keyboard_checkkey (struct grub_term_input *term) err = grub_usb_check_transfer (termdata->transfer, &actual); if (err == GRUB_USB_ERR_WAIT) - return -1; + { + if (termdata->last_key != -1 + && grub_get_time_ms () > termdata->repeat_time) + { + termdata->key = termdata->last_key; + termdata->repeat_time = grub_get_time_ms () + + GRUB_TERM_REPEAT_INTERVAL; + } + return termdata->key; + } grub_memcpy (data, termdata->report, sizeof (data)); @@ -382,6 +393,7 @@ grub_usb_keyboard_checkkey (struct grub_term_input *term) termdata->dead = 1; } + termdata->last_key = -1; grub_dprintf ("usb_keyboard", "err = %d, actual = %d report: 0x%02x 0x%02x 0x%02x 0x%02x" @@ -419,9 +431,13 @@ grub_usb_keyboard_checkkey (struct grub_term_input *term) if (data[2] > ARRAY_SIZE (usb_to_at_map) || usb_to_at_map[data[2]] == 0) grub_printf ("Unknown key 0x%02x detected\n", data[2]); else - termdata->key = grub_term_map_key (usb_to_at_map[data[2]], - interpret_status (data[0]) - | termdata->mods); + { + termdata->last_key = termdata->key + = grub_term_map_key (usb_to_at_map[data[2]], + interpret_status (data[0]) | termdata->mods); + termdata->repeat_time = grub_get_time_ms () + + GRUB_TERM_REPEAT_PRE_INTERVAL; + } grub_errno = GRUB_ERR_NONE; From 7209c54e91d35c69789e774bc29b597cdd37f93e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 22 Aug 2010 00:31:43 +0200 Subject: [PATCH 046/214] Set last_key to -1 at init time --- term/usb_keyboard.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/term/usb_keyboard.c b/term/usb_keyboard.c index c3af1694b..3dfe5331b 100644 --- a/term/usb_keyboard.c +++ b/term/usb_keyboard.c @@ -326,12 +326,12 @@ grub_usb_keyboard_attach (grub_usb_device_t usbdev, int configno, int interfno) return 0; } + data->last_key = -1; data->mods = 0; + data->dead = 0; grub_term_register_input_active ("usb_keyboard", &grub_usb_keyboards[curnum]); - data->dead = 0; - return 1; } From c2994de1349f7135118853b2250fccd9a867b9bc Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 22 Aug 2010 00:57:04 +0200 Subject: [PATCH 047/214] Add back accidently removed mov --- kern/i386/pc/startup.S | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/kern/i386/pc/startup.S b/kern/i386/pc/startup.S index ef5904bb2..f78fb5baa 100644 --- a/kern/i386/pc/startup.S +++ b/kern/i386/pc/startup.S @@ -1214,7 +1214,6 @@ FUNCTION(grub_console_getkey) shrl $8, %eax orl $GRUB_TERM_EXTENDED, %eax 2: - popl %ebp ret @@ -1248,12 +1247,15 @@ FUNCTION(grub_console_checkkey) DATA32 jmp pending notpending: + xorl %edx, %edx decl %edx pending: DATA32 call real_to_prot .code32 + movl %edx, %eax + popl %ebp ret From 96157c5378112658d062a1b654fd008d7edce9ce Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 22 Aug 2010 01:01:31 +0200 Subject: [PATCH 048/214] Increase pre-repeat usb keyboad interval --- include/grub/term.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/grub/term.h b/include/grub/term.h index 9956398da..bfe1c8f9b 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -490,7 +490,7 @@ grub_print_spaces (struct grub_term_output *term, int number_spaces) extern void (*EXPORT_VAR (grub_term_poll_usb)) (void); -#define GRUB_TERM_REPEAT_PRE_INTERVAL 100 +#define GRUB_TERM_REPEAT_PRE_INTERVAL 400 #define GRUB_TERM_REPEAT_INTERVAL 50 #endif /* ! ASM_FILE */ From 49c822bc42eb215d168ee87cc1644a8a625b173a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 22 Aug 2010 02:17:14 +0200 Subject: [PATCH 049/214] Support numpad --- commands/keylayouts.c | 52 +++++++++++++++++++++++++++++++++++++++++-- term/at_keyboard.c | 8 +++++-- term/usb_keyboard.c | 30 ++++++++++++------------- 3 files changed, 71 insertions(+), 19 deletions(-) diff --git a/commands/keylayouts.c b/commands/keylayouts.c index d2cb0e1e7..3442d42e7 100644 --- a/commands/keylayouts.c +++ b/commands/keylayouts.c @@ -106,13 +106,61 @@ map_key_core (int code, int status, int *alt_gr_consumed) return grub_current_layout->keyboard_map[code]; } +static int +map_high_key (int code, int status) +{ + int ret = 0; + if (status & (GRUB_TERM_STATUS_RSHIFT | GRUB_TERM_STATUS_LSHIFT)) + ret |= GRUB_TERM_SHIFT; + + if (code == 0xb5) + return '/'; + + if (code == 0xb7) + return '*'; + + if (code == 0x9c) + return '\n'; + + if (code < 0xc7 || code > 0xd3 || code == 0xca || code == 0xce + || code == 0xcc) + return ret; + /* GRUB keyboard codes are conveniently similar to AT codes. */ + return ret | GRUB_TERM_EXTENDED | (code & ~0x80); +} + +static int +map_num_key (int code, int state) +{ + const int map_arrows[] + = { GRUB_TERM_KEY_HOME, GRUB_TERM_KEY_UP, GRUB_TERM_KEY_PPAGE, + '-', GRUB_TERM_KEY_LEFT, GRUB_TERM_KEY_CENTER, GRUB_TERM_KEY_RIGHT, '+', + GRUB_TERM_KEY_END, GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_NPAGE, + GRUB_TERM_KEY_INSERT, GRUB_TERM_KEY_DC }; + const int map_nums[] + = { '7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', '.'}; + + if (((state & GRUB_TERM_STATUS_NUM) + && !(state & (GRUB_TERM_STATUS_RSHIFT | GRUB_TERM_STATUS_LSHIFT))) + || ((state & GRUB_TERM_STATUS_NUM) + && !(state & (GRUB_TERM_STATUS_RSHIFT | GRUB_TERM_STATUS_LSHIFT)))) + return map_nums [code - 0x47]; + else + return map_arrows [code - 0x47]; +} + unsigned grub_term_map_key (int code, int status) { - int alt_gr_consumed; + int alt_gr_consumed = 0; int key; - key = map_key_core (code, status, &alt_gr_consumed); + if (code >= 0x47 && code <= 0x53) + key = map_num_key (code, status); + else if (code & 0x80) + key = map_high_key (code, status); + else + key = map_key_core (code, status, &alt_gr_consumed); if (key == 0 || key == GRUB_TERM_SHIFT) grub_dprintf ("atkeyb", "Unknown key 0x%x detected\n", code); diff --git a/term/at_keyboard.c b/term/at_keyboard.c index 054dc9805..c98fc8255 100644 --- a/term/at_keyboard.c +++ b/term/at_keyboard.c @@ -110,7 +110,6 @@ grub_keyboard_isr (grub_uint8_t key) at_keyboard_status &= ~GRUB_TERM_STATUS_LALT; break; } - extended_pending = (key == 0xe0); } /* If there is a raw key pending, return it; otherwise return -1. */ @@ -118,13 +117,18 @@ static int grub_keyboard_getkey (void) { grub_uint8_t key; + grub_uint8_t ret; if (! KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS))) return -1; key = grub_inb (KEYBOARD_REG_DATA); /* FIXME */ grub_keyboard_isr (key); + ret = KEYBOARD_SCANCODE (key); + if (extended_pending) + ret |= 0x80; + extended_pending = (key == 0xe0); if (! KEYBOARD_ISMAKE (key)) return -1; - return (KEYBOARD_SCANCODE (key)); + return ret; } diff --git a/term/usb_keyboard.c b/term/usb_keyboard.c index 3dfe5331b..1082e62d0 100644 --- a/term/usb_keyboard.c +++ b/term/usb_keyboard.c @@ -69,20 +69,20 @@ static grub_uint8_t usb_to_at_map[128] = /* 0x42 */ 0x43 /* F9 */, 0x44 /* F10 */, /* 0x44 */ 0x57 /* F11 */, 0x58 /* F12 */, /* 0x46 */ 0x00, 0x00, - /* 0x48 */ 0x00, 0x52 /* Insert */, - /* 0x4a */ 0x47 /* HOME */, 0x51 /* PPAGE */, - /* 0x4c */ 0x53 /* DC */, 0x4f /* END */, - /* 0x4e */ 0x49 /* NPAGE */, 0x4d /* RIGHT */, - /* 0x50 */ 0x4b /* LEFT */, 0x50 /* DOWN */, - /* 0x52 */ 0x48 /* UP */, 0x00, - /* 0x54 */ 0x00, 0x00, - /* 0x56 */ 0x00, 0x00, - /* 0x58 */ 0x00, 0x00, - /* 0x5a */ 0x00, 0x00, - /* 0x5c */ 0x00, 0x00, - /* 0x5e */ 0x00, 0x00, - /* 0x60 */ 0x00, 0x00, - /* 0x62 */ 0x00, 0x00, + /* 0x48 */ 0x00, 0xd2 /* Insert */, + /* 0x4a */ 0xc7 /* HOME */, 0xd1 /* PPAGE */, + /* 0x4c */ 0xd3 /* DC */, 0xcf /* END */, + /* 0x4e */ 0xc9 /* NPAGE */, 0xcd /* RIGHT */, + /* 0x50 */ 0xcb /* LEFT */, 0xd0 /* DOWN */, + /* 0x52 */ 0xc8 /* UP */, 0x00, + /* 0x54 */ 0xb5 /* Num / */, 0xb7 /* Num * */, + /* 0x56 */ 0x4a /* Num - */, 0x4e /* Num + */, + /* 0x58 */ 0x9c /* Num \n */, 0x4f /* Num 1 */, + /* 0x5a */ 0x50 /* Num 2 */, 0x51 /* Num 3 */, + /* 0x5c */ 0x4b /* Num 4 */, 0x4c /* Num 5 */, + /* 0x5e */ 0x4d /* Num 6 */, 0x47 /* Num 7 */, + /* 0x60 */ 0x48 /* Num 8 */, 0x49 /* Num 9 */, + /* 0x62 */ 0x52 /* Num 0 */, 0x53 /* Num . */, /* 0x64 */ 0x56 /* 102nd key. */, 0x00, /* 0x66 */ 0x00, 0x00, /* 0x68 */ 0x00, 0x00, @@ -428,7 +428,7 @@ grub_usb_keyboard_checkkey (struct grub_term_input *term) return -1; } - if (data[2] > ARRAY_SIZE (usb_to_at_map) || usb_to_at_map[data[2]] == 0) + if (data[2] >= ARRAY_SIZE (usb_to_at_map) || usb_to_at_map[data[2]] == 0) grub_printf ("Unknown key 0x%02x detected\n", data[2]); else { From c32f26bce85ec1ba5bc3a2c01ced4b2f10f00705 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 22 Aug 2010 16:06:09 +0200 Subject: [PATCH 050/214] Make USB the main keylayout for simplicity --- commands/keylayouts.c | 194 ++++++++++++++++---------------- include/grub/at_keyboard.h | 12 -- include/grub/atkeymap.h | 111 ++++++++++++++++++ include/grub/keyboard_layouts.h | 2 +- term/at_keyboard.c | 6 +- term/usb_keyboard.c | 83 +------------- util/grub-mklayout.c | 152 ++++++++++++++++--------- 7 files changed, 321 insertions(+), 239 deletions(-) create mode 100644 include/grub/atkeymap.h diff --git a/commands/keylayouts.c b/commands/keylayouts.c index 3442d42e7..c68919aef 100644 --- a/commands/keylayouts.c +++ b/commands/keylayouts.c @@ -30,39 +30,96 @@ static struct grub_keyboard_layout layout_us = { .keyboard_map = { - /* 0x00 */ '\0', GRUB_TERM_ESC, '1', '2', '3', '4', '5', '6', - /* 0x08 */ '7', '8', '9', '0', '-', '=', GRUB_TERM_BACKSPACE, GRUB_TERM_TAB, - /* 0x10 */ 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', - /* 0x18 */ 'o', 'p', '[', ']', '\n', '\0', 'a', 's', - /* 0x20 */ 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', - /* 0x28 */ '\'', '`', '\0', '\\', 'z', 'x', 'c', 'v', - /* 0x30 */ 'b', 'n', 'm', ',', '.', '/', '\0', '*', - /* 0x38 */ '\0', ' ', '\0', GRUB_TERM_KEY_F1, - /* 0x3c */ GRUB_TERM_KEY_F2, GRUB_TERM_KEY_F3, - /* 0x3e */ GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5, - /* 0x40 */ GRUB_TERM_KEY_F6, GRUB_TERM_KEY_F7, - /* 0x42 */ GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9, - /* 0x44 */ GRUB_TERM_KEY_F10, '\0', '\0', GRUB_TERM_KEY_HOME, - /* 0x48 */ GRUB_TERM_KEY_UP, GRUB_TERM_KEY_NPAGE, '-', GRUB_TERM_KEY_LEFT, - /* 0x4c */ GRUB_TERM_KEY_CENTER, GRUB_TERM_KEY_RIGHT, - /* 0x4e */ '+', GRUB_TERM_KEY_END, - /* 0x50 */ GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_PPAGE, - /* 0x52 */ GRUB_TERM_KEY_INSERT, GRUB_TERM_KEY_DC, - /* 0x54 */ '\0', '\0', '\\', GRUB_TERM_KEY_F11, - /* 0x58 */ GRUB_TERM_KEY_F12, '\0', '\0', '\0', '\0', '\0', '\0', '\0', - /* 0x60 */ '\0', '\0', '\0', '\0', - /* 0x64 */ '\0', GRUB_TERM_KEY_UP, GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_LEFT, - /* 0x68 */ GRUB_TERM_KEY_RIGHT + /* Keyboard errors. Handled by driver. */ + /* 0x00 */ 0, 0, 0, 0, + + /* 0x04 */ 'a', 'b', 'c', 'd', + /* 0x08 */ 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', + /* 0x10 */ 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', + /* 0x18 */ 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', + /* 0x20 */ '3', '4', '5', '6', '7', '8', '9', '0', + /* 0x28 */ '\n', '\e', '\b', '\t', ' ', '-', '=', '[', + /* According to usage table 0x31 should be mapped to '/' + but testing with real keyboard shows that 0x32 is remapped to '/'. + Map 0x31 to 0. + */ + /* 0x30 */ ']', 0, '\\', ';', '\'', '`', ',', '.', + /* 0x39 is CapsLock. Handled by driver. */ + /* 0x38 */ '/', 0, GRUB_TERM_KEY_F1, GRUB_TERM_KEY_F2, + /* 0x3c */ GRUB_TERM_KEY_F3, GRUB_TERM_KEY_F4, + /* 0x3e */ GRUB_TERM_KEY_F5, GRUB_TERM_KEY_F6, + /* 0x40 */ GRUB_TERM_KEY_F7, GRUB_TERM_KEY_F8, + /* 0x42 */ GRUB_TERM_KEY_F9, GRUB_TERM_KEY_F10, + /* 0x44 */ GRUB_TERM_KEY_F11, GRUB_TERM_KEY_F12, + /* PrtScr and ScrollLock. Not handled yet. */ + /* 0x46 */ 0, 0, + /* 0x48 is Pause. Not handled yet. */ + /* 0x48 */ 0, GRUB_TERM_KEY_INSERT, + /* 0x4a */ GRUB_TERM_KEY_HOME, GRUB_TERM_KEY_PPAGE, + /* 0x4c */ GRUB_TERM_KEY_DC, GRUB_TERM_KEY_END, + /* 0x4e */ GRUB_TERM_KEY_NPAGE, GRUB_TERM_KEY_RIGHT, + /* 0x50 */ GRUB_TERM_KEY_LEFT, GRUB_TERM_KEY_DOWN, + /* 0x53 is NumLock. Handled by driver. */ + /* 0x52 */ GRUB_TERM_KEY_UP, 0, + /* 0x54 */ '/', '*', + /* 0x56 */ '-', '+', + /* 0x58 */ '\n', GRUB_TERM_KEY_END, + /* 0x5a */ GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_NPAGE, + /* 0x5c */ GRUB_TERM_KEY_LEFT, GRUB_TERM_KEY_CENTER, + /* 0x5e */ GRUB_TERM_KEY_RIGHT, GRUB_TERM_KEY_HOME, + /* 0x60 */ GRUB_TERM_KEY_UP, GRUB_TERM_KEY_PPAGE, + /* 0x62 */ GRUB_TERM_KEY_INSERT, GRUB_TERM_KEY_DC, + /* 0x64 */ '\\' }, .keyboard_map_shift = { - '\0', '\0', '!', '@', '#', '$', '%', '^', - '&', '*', '(', ')', '_', '+', '\0', '\0', - 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', - 'O', 'P', '{', '}', '\n', '\0', 'A', 'S', - 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', - '\"', '~', '\0', '|', 'Z', 'X', 'C', 'V', - 'B', 'N', 'M', '<', '>', '?', - [0x56] = '|' + /* Keyboard errors. Handled by driver. */ + /* 0x00 */ 0, 0, 0, 0, + + /* 0x04 */ 'A', 'B', 'C', 'D', + /* 0x08 */ 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', + /* 0x10 */ 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', + /* 0x18 */ 'U', 'V', 'W', 'X', 'Y', 'Z', '!', '@', + /* 0x20 */ '#', '$', '%', '^', '&', '*', '(', ')', + /* 0x28 */ '\n' | GRUB_TERM_SHIFT, '\e' | GRUB_TERM_SHIFT, + /* 0x2a */ '\b' | GRUB_TERM_SHIFT, '\t' | GRUB_TERM_SHIFT, + /* 0x2c */ ' ' | GRUB_TERM_SHIFT, '_', '+', '{', + /* According to usage table 0x31 should be mapped to '/' + but testing with real keyboard shows that 0x32 is remapped to '/'. + Map 0x31 to 0. + */ + /* 0x30 */ '}', 0, '|', ':', '"', '~', '<', '>', + /* 0x39 is CapsLock. Handled by driver. */ + /* 0x38 */ '?', 0, + /* 0x3a */ GRUB_TERM_KEY_F1 | GRUB_TERM_SHIFT, + /* 0x3b */ GRUB_TERM_KEY_F2 | GRUB_TERM_SHIFT, + /* 0x3c */ GRUB_TERM_KEY_F3 | GRUB_TERM_SHIFT, + /* 0x3d */ GRUB_TERM_KEY_F4 | GRUB_TERM_SHIFT, + /* 0x3e */ GRUB_TERM_KEY_F5 | GRUB_TERM_SHIFT, + /* 0x3f */ GRUB_TERM_KEY_F6 | GRUB_TERM_SHIFT, + /* 0x40 */ GRUB_TERM_KEY_F7 | GRUB_TERM_SHIFT, + /* 0x41 */ GRUB_TERM_KEY_F8 | GRUB_TERM_SHIFT, + /* 0x42 */ GRUB_TERM_KEY_F9 | GRUB_TERM_SHIFT, + /* 0x43 */ GRUB_TERM_KEY_F10 | GRUB_TERM_SHIFT, + /* 0x44 */ GRUB_TERM_KEY_F11 | GRUB_TERM_SHIFT, + /* 0x45 */ GRUB_TERM_KEY_F12 | GRUB_TERM_SHIFT, + /* PrtScr and ScrollLock. Not handled yet. */ + /* 0x46 */ 0, 0, + /* 0x48 is Pause. Not handled yet. */ + /* 0x48 */ 0, GRUB_TERM_KEY_INSERT | GRUB_TERM_SHIFT, + /* 0x4a */ GRUB_TERM_KEY_HOME | GRUB_TERM_SHIFT, + /* 0x4b */ GRUB_TERM_KEY_PPAGE | GRUB_TERM_SHIFT, + /* 0x4c */ GRUB_TERM_KEY_DC | GRUB_TERM_SHIFT, + /* 0x4d */ GRUB_TERM_KEY_END | GRUB_TERM_SHIFT, + /* 0x4e */ GRUB_TERM_KEY_NPAGE | GRUB_TERM_SHIFT, + /* 0x4f */ GRUB_TERM_KEY_RIGHT | GRUB_TERM_SHIFT, + /* 0x50 */ GRUB_TERM_KEY_LEFT | GRUB_TERM_SHIFT, + /* 0x51 */ GRUB_TERM_KEY_DOWN | GRUB_TERM_SHIFT, + /* 0x53 is NumLock. Handled by driver. */ + /* 0x52 */ GRUB_TERM_KEY_UP | GRUB_TERM_SHIFT, 0, + /* 0x54 */ '/', '*', + /* 0x56 */ '-', '+', + /* 0x58 */ '\n' | GRUB_TERM_SHIFT, '1', '2', '3', '4', '5','6', '7', + /* 0x60 */ '8', '9', '0', '.', '|' } }; @@ -82,88 +139,37 @@ map_key_core (int code, int status, int *alt_gr_consumed) *alt_gr_consumed = 1; return grub_current_layout->keyboard_map_shift_l3[code]; } - else if (grub_current_layout->keyboard_map_shift[code]) - { - *alt_gr_consumed = 1; - return grub_current_layout->keyboard_map_l3[code] - | GRUB_TERM_SHIFT; - } } - else if (grub_current_layout->keyboard_map_shift[code]) + else if (grub_current_layout->keyboard_map_l3[code]) { *alt_gr_consumed = 1; return grub_current_layout->keyboard_map_l3[code]; } } if (status & (GRUB_TERM_STATUS_LSHIFT | GRUB_TERM_STATUS_RSHIFT)) - { - if (grub_current_layout->keyboard_map_shift[code]) - return grub_current_layout->keyboard_map_shift[code]; - else - return grub_current_layout->keyboard_map[code] | GRUB_TERM_SHIFT; - } + return grub_current_layout->keyboard_map_shift[code]; else return grub_current_layout->keyboard_map[code]; } -static int -map_high_key (int code, int status) -{ - int ret = 0; - if (status & (GRUB_TERM_STATUS_RSHIFT | GRUB_TERM_STATUS_LSHIFT)) - ret |= GRUB_TERM_SHIFT; - - if (code == 0xb5) - return '/'; - - if (code == 0xb7) - return '*'; - - if (code == 0x9c) - return '\n'; - - if (code < 0xc7 || code > 0xd3 || code == 0xca || code == 0xce - || code == 0xcc) - return ret; - /* GRUB keyboard codes are conveniently similar to AT codes. */ - return ret | GRUB_TERM_EXTENDED | (code & ~0x80); -} - -static int -map_num_key (int code, int state) -{ - const int map_arrows[] - = { GRUB_TERM_KEY_HOME, GRUB_TERM_KEY_UP, GRUB_TERM_KEY_PPAGE, - '-', GRUB_TERM_KEY_LEFT, GRUB_TERM_KEY_CENTER, GRUB_TERM_KEY_RIGHT, '+', - GRUB_TERM_KEY_END, GRUB_TERM_KEY_DOWN, GRUB_TERM_KEY_NPAGE, - GRUB_TERM_KEY_INSERT, GRUB_TERM_KEY_DC }; - const int map_nums[] - = { '7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', '.'}; - - if (((state & GRUB_TERM_STATUS_NUM) - && !(state & (GRUB_TERM_STATUS_RSHIFT | GRUB_TERM_STATUS_LSHIFT))) - || ((state & GRUB_TERM_STATUS_NUM) - && !(state & (GRUB_TERM_STATUS_RSHIFT | GRUB_TERM_STATUS_LSHIFT)))) - return map_nums [code - 0x47]; - else - return map_arrows [code - 0x47]; -} - unsigned grub_term_map_key (int code, int status) { int alt_gr_consumed = 0; int key; - if (code >= 0x47 && code <= 0x53) - key = map_num_key (code, status); - else if (code & 0x80) - key = map_high_key (code, status); - else - key = map_key_core (code, status, &alt_gr_consumed); + if (code >= 0x59 && code <= 0x63 && (status & GRUB_TERM_STATUS_NUM)) + { + if (status & (GRUB_TERM_STATUS_RSHIFT | GRUB_TERM_STATUS_LSHIFT)) + status &= ~(GRUB_TERM_STATUS_RSHIFT | GRUB_TERM_STATUS_LSHIFT); + else + status |= GRUB_TERM_STATUS_RSHIFT; + } + + key = map_key_core (code, status, &alt_gr_consumed); if (key == 0 || key == GRUB_TERM_SHIFT) - grub_dprintf ("atkeyb", "Unknown key 0x%x detected\n", code); + grub_printf ("Unknown key 0x%x detected\n", code); if (status & GRUB_TERM_STATUS_CAPS) { diff --git a/include/grub/at_keyboard.h b/include/grub/at_keyboard.h index 10421540a..350ce3bf9 100644 --- a/include/grub/at_keyboard.h +++ b/include/grub/at_keyboard.h @@ -39,16 +39,4 @@ #define KEYBOARD_ISREADY(x) ((x) & 0x01) #define KEYBOARD_SCANCODE(x) ((x) & 0x7f) -#ifdef GRUB_MACHINE_IEEE1275 -#define OLPC_UP GRUB_TERM_UP -#define OLPC_DOWN GRUB_TERM_DOWN -#define OLPC_LEFT GRUB_TERM_LEFT -#define OLPC_RIGHT GRUB_TERM_RIGHT -#else -#define OLPC_UP '\0' -#define OLPC_DOWN '\0' -#define OLPC_LEFT '\0' -#define OLPC_RIGHT '\0' -#endif - #endif diff --git a/include/grub/atkeymap.h b/include/grub/atkeymap.h new file mode 100644 index 000000000..a8b9140ff --- /dev/null +++ b/include/grub/atkeymap.h @@ -0,0 +1,111 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_AT_KEYMAP_HEADER +#define GRUB_AT_KEYMAP_HEADER 1 + +static inline int +grub_at_map_to_usb (grub_uint8_t keycode) +{ + /* Modifier keys (ctrl, alt, shift, capslock, numlock and scrolllock + are handled by driver and hence here are mapped to 0)*/ + + static const grub_uint8_t at_to_usb_map[] = + { + /* 0x00 */ 0x00 /* Unused */, 0x29 /* Escape */, + /* 0x02 */ 0x1e /* 1 */, 0x1f /* 2 */, + /* 0x04 */ 0x20 /* 3 */, 0x21 /* 4 */, + /* 0x06 */ 0x22 /* 5 */, 0x23 /* 6 */, + /* 0x08 */ 0x24 /* 7 */, 0x25 /* 8 */, + /* 0x0a */ 0x26 /* 9 */, 0x27 /* 0 */, + /* 0x0c */ 0x2d /* - */, 0x2e /* = */, + /* 0x0e */ 0x2a /* \b */, 0x2b /* \t */, + /* 0x10 */ 0x14 /* q */, 0x1a /* w */, + /* 0x12 */ 0x08 /* e */, 0x15 /* r */, + /* 0x14 */ 0x17 /* t */, 0x1c /* y */, + /* 0x16 */ 0x18 /* u */, 0x0c /* i */, + /* 0x18 */ 0x12 /* o */, 0x13 /* p */, + /* 0x1a */ 0x2f /* [ */, 0x30 /* ] */, + /* 0x1c */ 0x28 /* Enter */, 0x00 /* Left CTRL */, + /* 0x1e */ 0x04 /* a */, 0x16 /* s */, + /* 0x20 */ 0x07 /* d */, 0x09 /* f */, + /* 0x22 */ 0x0a /* g */, 0x0b /* h */, + /* 0x24 */ 0x0d /* j */, 0x0e /* k */, + /* 0x26 */ 0x0f /* l */, 0x33 /* ; */, + /* 0x28 */ 0x34 /* " */, 0x35 /* ` */, + /* 0x2a */ 0x00 /* Left Shift */, 0x32 /* \ */, + /* 0x2c */ 0x1d /* z */, 0x1b /* x */, + /* 0x2e */ 0x06 /* c */, 0x19 /* v */, + /* 0x30 */ 0x05 /* b */, 0x11 /* n */, + /* 0x32 */ 0x10 /* m */, 0x36 /* , */, + /* 0x34 */ 0x37 /* . */, 0x38 /* / */, + /* 0x36 */ 0x00 /* Right Shift */, 0x55 /* Num * */, + /* 0x38 */ 0x00 /* Left ALT */, 0x2c /* Space */, + /* 0x3a */ 0x39 /* Caps Lock */, 0x3a /* F1 */, + /* 0x3c */ 0x3b /* F2 */, 0x3c /* F3 */, + /* 0x3e */ 0x3d /* F4 */, 0x3e /* F5 */, + /* 0x40 */ 0x3f /* F6 */, 0x40 /* F7 */, + /* 0x42 */ 0x41 /* F8 */, 0x42 /* F9 */, + /* 0x44 */ 0x43 /* F10 */, 0x53 /* NumLock */, + /* 0x46 */ 0x47 /* Scroll Lock */, 0x5f /* Num 7 */, + /* 0x48 */ 0x60 /* Num 8 */, 0x61 /* Num 9 */, + /* 0x4a */ 0x56 /* Num - */, 0x5c /* Num 4 */, + /* 0x4c */ 0x5d /* Num 5 */, 0x5e /* Num 6 */, + /* 0x4e */ 0x57 /* Num + */, 0x59 /* Num 1 */, + /* 0x50 */ 0x5a /* Num 2 */, 0x5b /* Num 3 */, + /* 0x52 */ 0x62 /* Num 0 */, 0x63 /* Num . */, + /* 0x54 */ 0x00, 0x00, + /* 0x56 */ 0x64 /* 102nd key. */, 0x44 /* F11 */, + /* 0x58 */ 0x45 /* F12 */, 0x00 + }; + + static const struct + { + grub_uint8_t from, to; + } at_to_usb_extended[] = + { + /* OLPC keys. Just mapped to normal keys. */ + {0x65, 0x52 /* Up */ }, + {0x66, 0x51 /* Down */ }, + {0x67, 0x50 /* Left */ }, + {0x68, 0x4f /* Right */ }, + + {0x9c, 0x58 /* Num \n */}, + {0xb5, 0x54 /* Num / */ }, + {0xc7, 0x4a /* Home */ }, + {0xc8, 0x52 /* Up */ }, + {0xc9, 0x4e /* NPage */ }, + {0xcb, 0x50 /* Left */ }, + {0xcd, 0x4f /* Right */ }, + {0xcf, 0x4d /* End */ }, + {0xd0, 0x51 /* Down */ }, + {0xd1, 0x4b /* PPage */ }, + {0xd2, 0x49 /* Insert */}, + {0xd3, 0x4c /* DC */ }, + }; + if (keycode >= ARRAY_SIZE (at_to_usb_map)) + { + unsigned i; + for (i = 0; i < ARRAY_SIZE (at_to_usb_extended); i++) + if (at_to_usb_extended[i].from == keycode) + return at_to_usb_extended[i].to; + return 0; + } + return at_to_usb_map[keycode]; +} +#endif diff --git a/include/grub/keyboard_layouts.h b/include/grub/keyboard_layouts.h index f1d2fb282..b562d671e 100644 --- a/include/grub/keyboard_layouts.h +++ b/include/grub/keyboard_layouts.h @@ -21,7 +21,7 @@ #define GRUB_KEYBOARD_LAYOUTS_FILEMAGIC "GRUBLAYO" #define GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE (sizeof(GRUB_KEYBOARD_LAYOUTS_FILEMAGIC) - 1) -#define GRUB_KEYBOARD_LAYOUTS_VERSION 6 +#define GRUB_KEYBOARD_LAYOUTS_VERSION 7 #define GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE 128 diff --git a/term/at_keyboard.c b/term/at_keyboard.c index c98fc8255..f8595a41a 100644 --- a/term/at_keyboard.c +++ b/term/at_keyboard.c @@ -23,6 +23,7 @@ #include #include #include +#include static short at_keyboard_status = 0; static int extended_pending = 0; @@ -123,6 +124,8 @@ grub_keyboard_getkey (void) key = grub_inb (KEYBOARD_REG_DATA); /* FIXME */ grub_keyboard_isr (key); ret = KEYBOARD_SCANCODE (key); + if (ret == SHIFT_L || ret == SHIFT_R || ret == ALT || ret == CTRL) + return -1; if (extended_pending) ret |= 0x80; extended_pending = (key == 0xe0); @@ -175,7 +178,8 @@ grub_at_keyboard_getkey_noblock (void) keyboard_controller_led (led_status); return -1; default: - return grub_term_map_key (code, at_keyboard_status); + return grub_term_map_key (grub_at_map_to_usb (code), + at_keyboard_status); } } diff --git a/term/usb_keyboard.c b/term/usb_keyboard.c index 1082e62d0..b57b171f8 100644 --- a/term/usb_keyboard.c +++ b/term/usb_keyboard.c @@ -29,76 +29,6 @@ -static grub_uint8_t usb_to_at_map[128] = -{ - /* 0x00 */ 0x00, 0x00, - /* 0x02 */ 0x00, 0x00, - /* 0x04 */ 0x1e /* a */, 0x30 /* b */, - /* 0x06 */ 0x2e /* c */, 0x20 /* d */, - /* 0x08 */ 0x12 /* e */, 0x21 /* f */, - /* 0x0a */ 0x22 /* g */, 0x23 /* h */, - /* 0x0c */ 0x17 /* i */, 0x24 /* j */, - /* 0x0e */ 0x25 /* k */, 0x26 /* l */, - /* 0x10 */ 0x32 /* m */, 0x31 /* n */, - /* 0x12 */ 0x18 /* o */, 0x19 /* p */, - /* 0x14 */ 0x10 /* q */, 0x13 /* r */, - /* 0x16 */ 0x1f /* s */, 0x14 /* t */, - /* 0x18 */ 0x16 /* u */, 0x2f /* v */, - /* 0x1a */ 0x11 /* w */, 0x2d /* x */, - /* 0x1c */ 0x15 /* y */, 0x2c /* z */, - /* 0x1e */ 0x02 /* 1 */, 0x03 /* 2 */, - /* 0x20 */ 0x04 /* 3 */, 0x05 /* 4 */, - /* 0x22 */ 0x06 /* 5 */, 0x07 /* 6 */, - /* 0x24 */ 0x08 /* 7 */, 0x09 /* 8 */, - /* 0x26 */ 0x0a /* 9 */, 0x0b /* 0 */, - /* 0x28 */ 0x1c /* Enter */, 0x01 /* Escape */, - /* 0x2a */ 0x0e /* \b */, 0x0f /* \t */, - /* 0x2c */ 0x39 /* Space */, 0x0c /* - */, - /* 0x2e */ 0x0d /* = */, 0x1a /* [ */, - /* According to usage table 0x31 should be remapped to 0x2b - but testing with real keyboard shows that 0x32 is remapped to 0x2b. */ - /* 0x30 */ 0x1b /* ] */, 0x00, - /* 0x32 */ 0x2b /* \ */, 0x27 /* ; */, - /* 0x34 */ 0x28 /* " */, 0x29 /* ` */, - /* 0x36 */ 0x33 /* , */, 0x34 /* . */, - /* 0x38 */ 0x35 /* / */, 0x00, - /* 0x3a */ 0x3b /* F1 */, 0x3c /* F2 */, - /* 0x3c */ 0x3d /* F3 */, 0x3e /* F4 */, - /* 0x3e */ 0x3f /* F5 */, 0x40 /* F6 */, - /* 0x40 */ 0x41 /* F7 */, 0x42 /* F8 */, - /* 0x42 */ 0x43 /* F9 */, 0x44 /* F10 */, - /* 0x44 */ 0x57 /* F11 */, 0x58 /* F12 */, - /* 0x46 */ 0x00, 0x00, - /* 0x48 */ 0x00, 0xd2 /* Insert */, - /* 0x4a */ 0xc7 /* HOME */, 0xd1 /* PPAGE */, - /* 0x4c */ 0xd3 /* DC */, 0xcf /* END */, - /* 0x4e */ 0xc9 /* NPAGE */, 0xcd /* RIGHT */, - /* 0x50 */ 0xcb /* LEFT */, 0xd0 /* DOWN */, - /* 0x52 */ 0xc8 /* UP */, 0x00, - /* 0x54 */ 0xb5 /* Num / */, 0xb7 /* Num * */, - /* 0x56 */ 0x4a /* Num - */, 0x4e /* Num + */, - /* 0x58 */ 0x9c /* Num \n */, 0x4f /* Num 1 */, - /* 0x5a */ 0x50 /* Num 2 */, 0x51 /* Num 3 */, - /* 0x5c */ 0x4b /* Num 4 */, 0x4c /* Num 5 */, - /* 0x5e */ 0x4d /* Num 6 */, 0x47 /* Num 7 */, - /* 0x60 */ 0x48 /* Num 8 */, 0x49 /* Num 9 */, - /* 0x62 */ 0x52 /* Num 0 */, 0x53 /* Num . */, - /* 0x64 */ 0x56 /* 102nd key. */, 0x00, - /* 0x66 */ 0x00, 0x00, - /* 0x68 */ 0x00, 0x00, - /* 0x6a */ 0x00, 0x00, - /* 0x6c */ 0x00, 0x00, - /* 0x6e */ 0x00, 0x00, - /* 0x70 */ 0x00, 0x00, - /* 0x72 */ 0x00, 0x00, - /* 0x74 */ 0x00, 0x00, - /* 0x76 */ 0x00, 0x00, - /* 0x78 */ 0x00, 0x00, - /* 0x7a */ 0x00, 0x00, - /* 0x7c */ 0x00, 0x00, - /* 0x7e */ 0x00, 0x00, -}; - enum { KEY_NO_KEY = 0x00, @@ -428,16 +358,9 @@ grub_usb_keyboard_checkkey (struct grub_term_input *term) return -1; } - if (data[2] >= ARRAY_SIZE (usb_to_at_map) || usb_to_at_map[data[2]] == 0) - grub_printf ("Unknown key 0x%02x detected\n", data[2]); - else - { - termdata->last_key = termdata->key - = grub_term_map_key (usb_to_at_map[data[2]], - interpret_status (data[0]) | termdata->mods); - termdata->repeat_time = grub_get_time_ms () - + GRUB_TERM_REPEAT_PRE_INTERVAL; - } + termdata->last_key = termdata->key + = grub_term_map_key (data[2], interpret_status (data[0]) | termdata->mods); + termdata->repeat_time = grub_get_time_ms () + GRUB_TERM_REPEAT_PRE_INTERVAL; grub_errno = GRUB_ERR_NONE; diff --git a/util/grub-mklayout.c b/util/grub-mklayout.c index 91dea87a6..3aafd8837 100644 --- a/util/grub-mklayout.c +++ b/util/grub-mklayout.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include @@ -47,19 +47,47 @@ struct console_grub_equivalence grub_uint32_t grub; }; -static struct console_grub_equivalence console_grub_equivalences[] = { +static struct console_grub_equivalence console_grub_equivalences_shift[] = { + {"KP_0", '0'}, + {"KP_1", '1'}, + {"KP_2", '2'}, + {"KP_3", '3'}, + {"KP_4", '4'}, + {"KP_5", '5'}, + {"KP_6", '6'}, + {"KP_7", '7'}, + {"KP_8", '8'}, + {"KP_9", '9'}, + {"KP_Period", '.'}, +}; + +static struct console_grub_equivalence console_grub_equivalences_unshift[] = { + {"KP_0", GRUB_TERM_KEY_INSERT}, + {"KP_1", GRUB_TERM_KEY_END}, + {"KP_2", GRUB_TERM_KEY_DOWN}, + {"KP_3", GRUB_TERM_KEY_NPAGE}, + {"KP_4", GRUB_TERM_KEY_LEFT}, + {"KP_5", GRUB_TERM_KEY_CENTER}, + {"KP_6", GRUB_TERM_KEY_RIGHT}, + {"KP_7", GRUB_TERM_KEY_HOME}, + {"KP_8", GRUB_TERM_KEY_UP}, + {"KP_9", GRUB_TERM_KEY_PPAGE}, + {"KP_Period", GRUB_TERM_KEY_DC}, +}; + +static struct console_grub_equivalence console_grub_equivalences_common[] = { {"Escape", GRUB_TERM_ESC}, {"Tab", GRUB_TERM_TAB}, {"Delete", GRUB_TERM_BACKSPACE}, + {"KP_Enter", '\n'}, + {"Return", '\n'}, + {"KP_Multiply", '*'}, {"KP_Subtract", '-'}, {"KP_Add", '+'}, {"KP_Divide", '/'}, - {"KP_Enter", '\n'}, - {"Return", '\n'}, - {"F1", GRUB_TERM_KEY_F1}, {"F2", GRUB_TERM_KEY_F2}, {"F3", GRUB_TERM_KEY_F3}, @@ -116,6 +144,9 @@ static struct console_grub_equivalence console_grub_equivalences[] = { {"End", GRUB_TERM_KEY_END}, {"Right", GRUB_TERM_KEY_RIGHT}, {"Left", GRUB_TERM_KEY_LEFT}, + {"Next", GRUB_TERM_KEY_NPAGE}, + {"Prior", GRUB_TERM_KEY_PPAGE}, + {"Remove", GRUB_TERM_KEY_DC}, {"VoidSymbol", 0}, /* "Undead" keys since no dead key support in GRUB. */ @@ -132,24 +163,8 @@ static struct console_grub_equivalence console_grub_equivalences[] = { {"dead_breve", 0}, {"dead_doubleacute", 0}, - /* NumLock not supported yet. */ - {"KP_0", GRUB_TERM_KEY_INSERT}, - {"KP_1", GRUB_TERM_KEY_END}, - {"KP_2", GRUB_TERM_KEY_DOWN}, - {"KP_3", GRUB_TERM_KEY_NPAGE}, - {"KP_4", GRUB_TERM_KEY_LEFT}, - {"KP_5", 0}, - {"KP_6", GRUB_TERM_KEY_RIGHT}, - {"KP_7", GRUB_TERM_KEY_HOME}, - {"KP_8", GRUB_TERM_KEY_UP}, - {"KP_9", GRUB_TERM_KEY_PPAGE}, - {"KP_Period", GRUB_TERM_KEY_DC}, - /* Unused in GRUB. */ {"Pause", 0}, - {"Remove", 0}, - {"Next", 0}, - {"Prior", 0}, {"Scroll_Forward", 0}, {"Scroll_Backward", 0}, {"Hex_0", 0}, @@ -174,16 +189,6 @@ static struct console_grub_equivalence console_grub_equivalences[] = { {"Control_backslash", 0}, {"Compose", 0}, - /* Keys currently not remappable. */ - {"CtrlL_Lock", 0}, - {"Caps_Lock", 0}, - {"ShiftL", 0}, - {"Num_Lock", 0}, - {"Alt", 0}, - {"AltGr", 0}, - {"Control", 0}, - {"Shift", 0}, - {NULL, '\0'} }; @@ -205,24 +210,30 @@ Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT); exit (status); } -void +static void add_special_keys (struct grub_keyboard_layout *layout) { - /* OLPC keys. */ - layout->keyboard_map[101] = GRUB_TERM_KEY_UP; - layout->keyboard_map[102] = GRUB_TERM_KEY_DOWN; - layout->keyboard_map[103] = GRUB_TERM_KEY_LEFT; - layout->keyboard_map[104] = GRUB_TERM_KEY_RIGHT; + (void) layout; } static unsigned -lookup (char *code) +lookup (char *code, int shift) { int i; + struct console_grub_equivalence *pr; - for (i = 0; console_grub_equivalences[i].layout != NULL; i++) - if (strcmp (code, console_grub_equivalences[i].layout) == 0) - return console_grub_equivalences[i].grub; + if (shift) + pr = console_grub_equivalences_shift; + else + pr = console_grub_equivalences_unshift; + + for (i = 0; pr[i].layout != NULL; i++) + if (strcmp (code, pr[i].layout) == 0) + return pr[i].grub; + + for (i = 0; console_grub_equivalences_common[i].layout != NULL; i++) + if (strcmp (code, console_grub_equivalences_common[i].layout) == 0) + return console_grub_equivalences_common[i].grub; fprintf (stderr, "Unknown key %s\n", code); @@ -230,7 +241,7 @@ lookup (char *code) } static unsigned int -get_grub_code (char *layout_code) +get_grub_code (char *layout_code, int shift) { unsigned int code; @@ -239,7 +250,7 @@ get_grub_code (char *layout_code) else if (strncmp (layout_code, "+U+", sizeof ("+U+") - 1) == 0) sscanf (layout_code, "+U+%x", &code); else - code = lookup (layout_code); + code = lookup (layout_code, shift); return code; } @@ -287,21 +298,60 @@ write_keymaps (FILE *in, FILE *out) { if (strncmp (line, "keycode", sizeof ("keycode") - 1) == 0) { - unsigned keycode; + unsigned keycode_at, orig; + unsigned keycode_usb; char normal[64]; char shift[64]; char normalalt[64]; char shiftalt[64]; + static grub_uint8_t e0_remap[] = { + 0x9c /* Num \n */, 0x9d /* Right CTRL */, 0xb5 /* Num / */, + 0, 0xb8 /* Right ALT */, 0, + 0xc7 /* Home */, 0xc8 /* Up */, 0xc9 /* NPage*/, 0xcb /* Left */, + 0xcd /* Right */, 0xcf /* End */, 0xd0 /* Down */, 0xd1 /* PPage */, + 0xd2 /* Insert */, 0xd3 /* Delete */ + }; - sscanf (line, "keycode %u = %60s %60s %60s %60s", &keycode, + sscanf (line, "keycode %u = %60s %60s %60s %60s", &keycode_at, normal, shift, normalalt, shiftalt); - if (keycode < GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE) + orig = keycode_at; + + /* Not used. */ + if (keycode_at == 0x77 /* Pause */ + /* Some obscure keys */ + || keycode_at == 0x63 || keycode_at == 0x7d || keycode_at == 0x7e) + continue; + + if (keycode_at >= 96 && keycode_at < 96 + ARRAY_SIZE (e0_remap)) + keycode_at = e0_remap[keycode_at - 96]; + + /* Not remappable. */ + if (keycode_at == 0x1d /* Left CTRL */ + || keycode_at == 0x9d /* Right CTRL */ + || keycode_at == 0x2a /* Left Shift. */ + || keycode_at == 0x36 /* Right Shift. */ + || keycode_at == 0x38 /* Left ALT. */ + || keycode_at == 0xb8 /* Right ALT. */ + || keycode_at == 0x3a /* CapsLock. */ + || keycode_at == 0x45 /* NumLock. */ + || keycode_at == 0x46 /* ScrollLock. */) + continue; + + keycode_usb = grub_at_map_to_usb (keycode_at); + if (keycode_usb == 0 + || keycode_usb >= GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE) { - layout.keyboard_map[keycode] = get_grub_code (normal); - layout.keyboard_map_shift[keycode] = get_grub_code (shift); - layout.keyboard_map_l3[keycode] = get_grub_code (normalalt); - layout.keyboard_map_shift_l3[keycode] - = get_grub_code (shiftalt); + fprintf (stderr, "Unknown keycode 0x%02x\n", orig); + continue; + } + if (keycode_usb < GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE) + { + layout.keyboard_map[keycode_usb] = get_grub_code (normal, 0); + layout.keyboard_map_shift[keycode_usb] = get_grub_code (shift, 1); + layout.keyboard_map_l3[keycode_usb] + = get_grub_code (normalalt, 0); + layout.keyboard_map_shift_l3[keycode_usb] + = get_grub_code (shiftalt, 1); ok = 1; } } From 6e05e7f0f869af96ecb95b6d021b46f7e15c28c9 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 22 Aug 2010 17:44:03 +0200 Subject: [PATCH 051/214] Properly handle extended_pending --- term/at_keyboard.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/term/at_keyboard.c b/term/at_keyboard.c index 2b7dd9bee..4213b29db 100644 --- a/term/at_keyboard.c +++ b/term/at_keyboard.c @@ -122,13 +122,21 @@ grub_keyboard_getkey (void) if (! KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS))) return -1; key = grub_inb (KEYBOARD_REG_DATA); + if (key == 0xe0) + { + extended_pending = 1; + return -1; + } /* FIXME */ grub_keyboard_isr (key); ret = KEYBOARD_SCANCODE (key); if (ret == SHIFT_L || ret == SHIFT_R || ret == ALT || ret == CTRL) - return -1; + { + extended_pending = 0; + return -1; + } if (extended_pending) ret |= 0x80; - extended_pending = (key == 0xe0); + extended_pending = 0; if (! KEYBOARD_ISMAKE (key)) return -1; return ret; From f582367ecff67c616b5631331812d87ed5e67fdf Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 22 Aug 2010 18:15:27 +0200 Subject: [PATCH 052/214] Set the leds and drain the input buffer in at_keyboard initialisation --- term/at_keyboard.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/term/at_keyboard.c b/term/at_keyboard.c index 4213b29db..06d545d74 100644 --- a/term/at_keyboard.c +++ b/term/at_keyboard.c @@ -223,6 +223,11 @@ grub_keyboard_controller_init (struct grub_term_input *term __attribute__ ((unus at_keyboard_status = 0; grub_keyboard_controller_orig = grub_keyboard_controller_read (); grub_keyboard_controller_write (grub_keyboard_controller_orig | KEYBOARD_SCANCODE_SET1); + keyboard_controller_led (led_status); + /* Drain input buffer. */ + while (KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS))) + grub_inb (KEYBOARD_REG_DATA); + return GRUB_ERR_NONE; } From efc3e75f4d7006767be912b82761674f0814b08c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 22 Aug 2010 18:16:16 +0200 Subject: [PATCH 053/214] Bump keylayouts version --- include/grub/keyboard_layouts.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/grub/keyboard_layouts.h b/include/grub/keyboard_layouts.h index b562d671e..2f352a752 100644 --- a/include/grub/keyboard_layouts.h +++ b/include/grub/keyboard_layouts.h @@ -21,7 +21,7 @@ #define GRUB_KEYBOARD_LAYOUTS_FILEMAGIC "GRUBLAYO" #define GRUB_KEYBOARD_LAYOUTS_FILEMAGIC_SIZE (sizeof(GRUB_KEYBOARD_LAYOUTS_FILEMAGIC) - 1) -#define GRUB_KEYBOARD_LAYOUTS_VERSION 7 +#define GRUB_KEYBOARD_LAYOUTS_VERSION 8 #define GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE 128 From 5ea70ca5fabac085dc19caa490efd718882878ee Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 22 Aug 2010 22:53:31 +0200 Subject: [PATCH 054/214] Support scancode set 2 --- include/grub/at_keyboard.h | 10 +- include/grub/atkeymap.h | 111 --------- include/grub/keyboard_layouts.h | 15 +- term/at_keyboard.c | 386 ++++++++++++++++++++++++++------ util/grub-mklayout.c | 102 ++++++--- 5 files changed, 410 insertions(+), 214 deletions(-) delete mode 100644 include/grub/atkeymap.h diff --git a/include/grub/at_keyboard.h b/include/grub/at_keyboard.h index 350ce3bf9..6e0806bdb 100644 --- a/include/grub/at_keyboard.h +++ b/include/grub/at_keyboard.h @@ -19,21 +19,13 @@ #ifndef GRUB_AT_KEYBOARD_HEADER #define GRUB_AT_KEYBOARD_HEADER 1 -#define SHIFT_L 0x2a -#define SHIFT_R 0x36 -#define CTRL 0x1d -#define ALT 0x38 -#define CAPS_LOCK 0x3a -#define NUM_LOCK 0x45 -#define SCROLL_LOCK 0x46 - /* Used for sending commands to the controller. */ #define KEYBOARD_COMMAND_ISREADY(x) !((x) & 0x02) #define KEYBOARD_COMMAND_READ 0x20 #define KEYBOARD_COMMAND_WRITE 0x60 #define KEYBOARD_COMMAND_REBOOT 0xfe -#define KEYBOARD_SCANCODE_SET1 0x40 +#define KEYBOARD_AT_TRANSLATE 0x40 #define KEYBOARD_ISMAKE(x) !((x) & 0x80) #define KEYBOARD_ISREADY(x) ((x) & 0x01) diff --git a/include/grub/atkeymap.h b/include/grub/atkeymap.h deleted file mode 100644 index a8b9140ff..000000000 --- a/include/grub/atkeymap.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2010 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GRUB. If not, see . - */ - -#ifndef GRUB_AT_KEYMAP_HEADER -#define GRUB_AT_KEYMAP_HEADER 1 - -static inline int -grub_at_map_to_usb (grub_uint8_t keycode) -{ - /* Modifier keys (ctrl, alt, shift, capslock, numlock and scrolllock - are handled by driver and hence here are mapped to 0)*/ - - static const grub_uint8_t at_to_usb_map[] = - { - /* 0x00 */ 0x00 /* Unused */, 0x29 /* Escape */, - /* 0x02 */ 0x1e /* 1 */, 0x1f /* 2 */, - /* 0x04 */ 0x20 /* 3 */, 0x21 /* 4 */, - /* 0x06 */ 0x22 /* 5 */, 0x23 /* 6 */, - /* 0x08 */ 0x24 /* 7 */, 0x25 /* 8 */, - /* 0x0a */ 0x26 /* 9 */, 0x27 /* 0 */, - /* 0x0c */ 0x2d /* - */, 0x2e /* = */, - /* 0x0e */ 0x2a /* \b */, 0x2b /* \t */, - /* 0x10 */ 0x14 /* q */, 0x1a /* w */, - /* 0x12 */ 0x08 /* e */, 0x15 /* r */, - /* 0x14 */ 0x17 /* t */, 0x1c /* y */, - /* 0x16 */ 0x18 /* u */, 0x0c /* i */, - /* 0x18 */ 0x12 /* o */, 0x13 /* p */, - /* 0x1a */ 0x2f /* [ */, 0x30 /* ] */, - /* 0x1c */ 0x28 /* Enter */, 0x00 /* Left CTRL */, - /* 0x1e */ 0x04 /* a */, 0x16 /* s */, - /* 0x20 */ 0x07 /* d */, 0x09 /* f */, - /* 0x22 */ 0x0a /* g */, 0x0b /* h */, - /* 0x24 */ 0x0d /* j */, 0x0e /* k */, - /* 0x26 */ 0x0f /* l */, 0x33 /* ; */, - /* 0x28 */ 0x34 /* " */, 0x35 /* ` */, - /* 0x2a */ 0x00 /* Left Shift */, 0x32 /* \ */, - /* 0x2c */ 0x1d /* z */, 0x1b /* x */, - /* 0x2e */ 0x06 /* c */, 0x19 /* v */, - /* 0x30 */ 0x05 /* b */, 0x11 /* n */, - /* 0x32 */ 0x10 /* m */, 0x36 /* , */, - /* 0x34 */ 0x37 /* . */, 0x38 /* / */, - /* 0x36 */ 0x00 /* Right Shift */, 0x55 /* Num * */, - /* 0x38 */ 0x00 /* Left ALT */, 0x2c /* Space */, - /* 0x3a */ 0x39 /* Caps Lock */, 0x3a /* F1 */, - /* 0x3c */ 0x3b /* F2 */, 0x3c /* F3 */, - /* 0x3e */ 0x3d /* F4 */, 0x3e /* F5 */, - /* 0x40 */ 0x3f /* F6 */, 0x40 /* F7 */, - /* 0x42 */ 0x41 /* F8 */, 0x42 /* F9 */, - /* 0x44 */ 0x43 /* F10 */, 0x53 /* NumLock */, - /* 0x46 */ 0x47 /* Scroll Lock */, 0x5f /* Num 7 */, - /* 0x48 */ 0x60 /* Num 8 */, 0x61 /* Num 9 */, - /* 0x4a */ 0x56 /* Num - */, 0x5c /* Num 4 */, - /* 0x4c */ 0x5d /* Num 5 */, 0x5e /* Num 6 */, - /* 0x4e */ 0x57 /* Num + */, 0x59 /* Num 1 */, - /* 0x50 */ 0x5a /* Num 2 */, 0x5b /* Num 3 */, - /* 0x52 */ 0x62 /* Num 0 */, 0x63 /* Num . */, - /* 0x54 */ 0x00, 0x00, - /* 0x56 */ 0x64 /* 102nd key. */, 0x44 /* F11 */, - /* 0x58 */ 0x45 /* F12 */, 0x00 - }; - - static const struct - { - grub_uint8_t from, to; - } at_to_usb_extended[] = - { - /* OLPC keys. Just mapped to normal keys. */ - {0x65, 0x52 /* Up */ }, - {0x66, 0x51 /* Down */ }, - {0x67, 0x50 /* Left */ }, - {0x68, 0x4f /* Right */ }, - - {0x9c, 0x58 /* Num \n */}, - {0xb5, 0x54 /* Num / */ }, - {0xc7, 0x4a /* Home */ }, - {0xc8, 0x52 /* Up */ }, - {0xc9, 0x4e /* NPage */ }, - {0xcb, 0x50 /* Left */ }, - {0xcd, 0x4f /* Right */ }, - {0xcf, 0x4d /* End */ }, - {0xd0, 0x51 /* Down */ }, - {0xd1, 0x4b /* PPage */ }, - {0xd2, 0x49 /* Insert */}, - {0xd3, 0x4c /* DC */ }, - }; - if (keycode >= ARRAY_SIZE (at_to_usb_map)) - { - unsigned i; - for (i = 0; i < ARRAY_SIZE (at_to_usb_extended); i++) - if (at_to_usb_extended[i].from == keycode) - return at_to_usb_extended[i].to; - return 0; - } - return at_to_usb_map[keycode]; -} -#endif diff --git a/include/grub/keyboard_layouts.h b/include/grub/keyboard_layouts.h index 2f352a752..dd6631a51 100644 --- a/include/grub/keyboard_layouts.h +++ b/include/grub/keyboard_layouts.h @@ -33,6 +33,19 @@ struct grub_keyboard_layout grub_uint32_t keyboard_map_shift_l3[GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE]; }; -unsigned EXPORT_FUNC(grub_term_map_key) (int code, int status); +typedef enum grub_keyboard_key + { + GRUB_KEYBOARD_KEY_CAPS_LOCK = 0x39, + GRUB_KEYBOARD_KEY_SCROLL_LOCK = 0x47, + GRUB_KEYBOARD_KEY_NUM_LOCK = 0x53, + GRUB_KEYBOARD_KEY_LEFT_CTRL = 0xe0, + GRUB_KEYBOARD_KEY_LEFT_SHIFT = 0xe1, + GRUB_KEYBOARD_KEY_LEFT_ALT = 0xe2, + GRUB_KEYBOARD_KEY_RIGHT_CTRL = 0xe4, + GRUB_KEYBOARD_KEY_RIGHT_SHIFT = 0xe5, + GRUB_KEYBOARD_KEY_RIGHT_ALT = 0xe6, + } grub_keyboard_key_t; + +unsigned EXPORT_FUNC(grub_term_map_key) (grub_keyboard_key_t code, int status); #endif /* GRUB_KEYBOARD_LAYOUTS */ diff --git a/term/at_keyboard.c b/term/at_keyboard.c index 06d545d74..00c6cef83 100644 --- a/term/at_keyboard.c +++ b/term/at_keyboard.c @@ -23,10 +23,10 @@ #include #include #include -#include static short at_keyboard_status = 0; -static int extended_pending = 0; +static int e0_received = 0; +static int f0_received = 0; static int pending_key = -1; static grub_uint8_t led_status; @@ -36,6 +36,145 @@ static grub_uint8_t led_status; #define KEYBOARD_LED_CAPS (1 << 2) static grub_uint8_t grub_keyboard_controller_orig; +static grub_uint8_t grub_keyboard_orig_set; +static grub_uint8_t current_set; + +static const grub_uint8_t set1_mapping[128] = + { + /* 0x00 */ 0x00 /* Unused */, 0x29 /* Escape */, + /* 0x02 */ 0x1e /* 1 */, 0x1f /* 2 */, + /* 0x04 */ 0x20 /* 3 */, 0x21 /* 4 */, + /* 0x06 */ 0x22 /* 5 */, 0x23 /* 6 */, + /* 0x08 */ 0x24 /* 7 */, 0x25 /* 8 */, + /* 0x0a */ 0x26 /* 9 */, 0x27 /* 0 */, + /* 0x0c */ 0x2d /* - */, 0x2e /* = */, + /* 0x0e */ 0x2a /* \b */, 0x2b /* \t */, + /* 0x10 */ 0x14 /* q */, 0x1a /* w */, + /* 0x12 */ 0x08 /* e */, 0x15 /* r */, + /* 0x14 */ 0x17 /* t */, 0x1c /* y */, + /* 0x16 */ 0x18 /* u */, 0x0c /* i */, + /* 0x18 */ 0x12 /* o */, 0x13 /* p */, + /* 0x1a */ 0x2f /* [ */, 0x30 /* ] */, + /* 0x1c */ 0x28 /* Enter */, 0xe0 /* Left CTRL */, + /* 0x1e */ 0x04 /* a */, 0x16 /* s */, + /* 0x20 */ 0x07 /* d */, 0x09 /* f */, + /* 0x22 */ 0x0a /* g */, 0x0b /* h */, + /* 0x24 */ 0x0d /* j */, 0x0e /* k */, + /* 0x26 */ 0x0f /* l */, 0x33 /* ; */, + /* 0x28 */ 0x34 /* " */, 0x35 /* ` */, + /* 0x2a */ 0xe1 /* Left Shift */, 0x32 /* \ */, + /* 0x2c */ 0x1d /* z */, 0x1b /* x */, + /* 0x2e */ 0x06 /* c */, 0x19 /* v */, + /* 0x30 */ 0x05 /* b */, 0x11 /* n */, + /* 0x32 */ 0x10 /* m */, 0x36 /* , */, + /* 0x34 */ 0x37 /* . */, 0x38 /* / */, + /* 0x36 */ 0xe5 /* Right Shift */, 0x55 /* Num * */, + /* 0x38 */ 0xe2 /* Left ALT */, 0x2c /* Space */, + /* 0x3a */ 0x39 /* Caps Lock */, 0x3a /* F1 */, + /* 0x3c */ 0x3b /* F2 */, 0x3c /* F3 */, + /* 0x3e */ 0x3d /* F4 */, 0x3e /* F5 */, + /* 0x40 */ 0x3f /* F6 */, 0x40 /* F7 */, + /* 0x42 */ 0x41 /* F8 */, 0x42 /* F9 */, + /* 0x44 */ 0x43 /* F10 */, 0x53 /* NumLock */, + /* 0x46 */ 0x47 /* Scroll Lock */, 0x5f /* Num 7 */, + /* 0x48 */ 0x60 /* Num 8 */, 0x61 /* Num 9 */, + /* 0x4a */ 0x56 /* Num - */, 0x5c /* Num 4 */, + /* 0x4c */ 0x5d /* Num 5 */, 0x5e /* Num 6 */, + /* 0x4e */ 0x57 /* Num + */, 0x59 /* Num 1 */, + /* 0x50 */ 0x5a /* Num 2 */, 0x5b /* Num 3 */, + /* 0x52 */ 0x62 /* Num 0 */, 0x63 /* Num . */, + /* 0x54 */ 0x00, 0x00, + /* 0x56 */ 0x64 /* 102nd key. */, 0x44 /* F11 */, + /* 0x58 */ 0x45 /* F12 */, 0x00, + /* 0x5a */ 0x00, 0x00, + /* 0x5c */ 0x00, 0x00, + /* 0x5e */ 0x00, 0x00, + /* 0x60 */ 0x00, 0x00, + /* 0x62 */ 0x00, 0x00, + /* OLPC keys. Just mapped to normal keys. */ + /* 0x64 */ 0x00, 0x52 /* Up */, + /* 0x66 */ 0x51 /* Down */, 0x50 /* Left */, + /* 0x68 */ 0x4f /* Right */ + }; + +static const struct +{ + grub_uint8_t from, to; +} set1_e0_mapping[] = + { + {0x1c, 0x58 /* Num \n */}, + {0x1d, 0xe4 /* Right CTRL */}, + {0x35, 0x54 /* Num / */ }, + {0x38, 0xe6 /* Right ALT */}, + {0x47, 0x4a /* Home */ }, + {0x48, 0x52 /* Up */ }, + {0x49, 0x4e /* NPage */ }, + {0x4b, 0x50 /* Left */ }, + {0x4d, 0x4f /* Right */ }, + {0x4f, 0x4d /* End */ }, + {0x50, 0x51 /* Down */ }, + {0x51, 0x4b /* PPage */ }, + {0x52, 0x49 /* Insert */}, + {0x53, 0x4c /* DC */ }, + }; + +static const grub_uint8_t set2_mapping[256] = + { + /* 0x00 */ 0x00, 0x42 /* F9 */, 0x00, 0x3e /* F5 */, + /* 0x04 */ 0x3c /* F3 */, 0x3a /* F1 */, 0x3b /* F2 */, 0x45 /* F12 */, + /* 0x08 */ 0x00, 0x43 /* F10 */, 0x41 /* F8 */, 0x3f /* F6 */, + /* 0x0c */ 0x3d /* F4 */, 0x2b /* \t */, 0x35 /* ` */, 0x00, + /* 0x10 */ 0x00, GRUB_KEYBOARD_KEY_LEFT_ALT, GRUB_KEYBOARD_KEY_LEFT_SHIFT, 0x00, + /* 0x14 */ GRUB_KEYBOARD_KEY_LEFT_CTRL, 0x14 /* q */, 0x1e /* 1 */, 0x00, + /* 0x18 */ 0x00, 0x00, 0x1d /* s */, 0x16 /* s */, + /* 0x1c */ 0x04 /* a */, 0x1a /* w */, 0x1f /* 2 */, 0x00, + /* 0x20 */ 0x00, 0x06 /* c */, 0x1b /* x */, 0x07 /* d */, + /* 0x24 */ 0x08 /* e */, 0x21 /* 4 */, 0x20 /* 3 */, 0x00, + /* 0x28 */ 0x00, 0x2c /* Space */, 0x19 /* v */, 0x09 /* f */, + /* 0x2c */ 0x17 /* t */, 0x15 /* r */, 0x22 /* 5 */, 0x00, + /* 0x30 */ 0x00, 0x11 /* n */, 0x05 /* b */, 0x0b /* h */, + /* 0x34 */ 0x0a /* g */, 0x1c /* y */, 0x23 /* 6 */, 0x00, + /* 0x38 */ 0x00, 0x00, 0x10 /* m */, 0x0d /* j */, + /* 0x3c */ 0x18 /* u */, 0x24 /* 7 */, 0x25 /* 8 */, 0x00, + /* 0x40 */ 0x00, 0x37 /* . */, 0x0e /* k */, 0x0c /* i */, + /* 0x44 */ 0x12 /* o */, 0x27 /* 0 */, 0x26 /* 9 */, 0x00, + /* 0x48 */ 0x00, 0x36 /* , */, 0x38 /* / */, 0x0f /* l */, + /* 0x4c */ 0x33 /* ; */, 0x13 /* p */, 0x2d /* - */, 0x00, + /* 0x50 */ 0x00, 0x00, 0x34 /* ' */, 0x00, + /* 0x54 */ 0x2f /* [ */, 0x2e /* = */, 0x00, 0x00, + /* 0x58 */ GRUB_KEYBOARD_KEY_CAPS_LOCK, GRUB_KEYBOARD_KEY_RIGHT_SHIFT, 0x28 /* \n */,0x30 /* ] */, + /* 0x5c */ 0x00, 0x32 /* \ */, 0x00, 0x00, + /* 0x60 */ 0x00, 0x64 /* 102nd key. */, 0x00, 0x00, + /* 0x64 */ 0x00, 0x00, 0x2a /* \b */, 0x00, + /* 0x68 */ 0x00, 0x59 /* Num 1 */, 0x00, 0x5c /* Num 4 */, + /* 0x6c */ 0x5f /* Num 7 */, 0x00, 0x00, 0x00, + /* 0x70 */ 0x62 /* Num 0 */, 0x63 /* Num 0 */, 0x5a /* Num 2 */, 0x5d /* Num 5 */, + /* 0x74 */ 0x5e /* Num 6 */, 0x60 /* Num 8 */, 0x29 /* \e */, 0x53 /* NumLock */, + /* 0x78 */ 0x44 /* F11 */, 0x57 /* Num + */, 0x5b /* Num 3 */, 0x56 /* Num - */, + /* 0x7c */ 0x55 /* Num * */, 0x61 /* Num 9 */, 0x47 /* ScrollLock */, 0x00, + /* 0x80 */ 0x00, 0x00, 0x00, 0x40 /* F7 */, + }; + +static const struct +{ + grub_uint8_t from, to; +} set2_e0_mapping[] = + { + {0x11, GRUB_KEYBOARD_KEY_RIGHT_ALT}, + {0x14, GRUB_KEYBOARD_KEY_RIGHT_CTRL}, + {0x4a, 0x54}, /* Num / */ + {0x5a, 0x58}, /* Num enter */ + {0x69, 0x4d}, /* End */ + {0x6b, 0x50}, /* Left */ + {0x6c, 0x4a}, /* Home */ + {0x70, 0x49}, /* Insert */ + {0x71, 0x4c}, /* Delete */ + {0x72, 0x51}, /* Down */ + {0x74, 0x4f}, /* Right */ + {0x75, 0x52}, /* Up */ + {0x7a, 0x4e}, /* PageDown */ + {0x7d, 0x4b}, /* PageUp */ + }; static void keyboard_controller_wait_until_ready (void) @@ -51,6 +190,55 @@ grub_keyboard_controller_write (grub_uint8_t c) grub_outb (c, KEYBOARD_REG_DATA); } +static grub_uint8_t +query_mode (int mode) +{ + keyboard_controller_wait_until_ready (); + grub_outb (0xf0, KEYBOARD_REG_DATA); + keyboard_controller_wait_until_ready (); + grub_inb (KEYBOARD_REG_DATA); + keyboard_controller_wait_until_ready (); + grub_outb (mode, KEYBOARD_REG_DATA); + + keyboard_controller_wait_until_ready (); + + return grub_inb (KEYBOARD_REG_DATA); +} + +/* QEMU translates the set even in no-translate mode. */ +static inline int +recover_mode (grub_uint8_t report) +{ + if (report == 0x43 || report == 1) + return 1; + if (report == 0x41 || report == 2) + return 2; + if (report == 0x3f || report == 3) + return 3; + return -1; +} + +static void +set_scancodes (void) +{ + grub_keyboard_controller_write (grub_keyboard_controller_orig + & ~KEYBOARD_AT_TRANSLATE); + grub_keyboard_orig_set = recover_mode (query_mode (0)); + + query_mode (2); + current_set = query_mode (0); + current_set = recover_mode (current_set); + if (current_set == 2) + return; + + query_mode (1); + current_set = query_mode (0); + current_set = recover_mode (current_set); + if (current_set == 1) + return; + grub_printf ("No supported scancode set found\n"); +} + static grub_uint8_t grub_keyboard_controller_read (void) { @@ -68,48 +256,126 @@ keyboard_controller_led (grub_uint8_t leds) grub_outb (leds & 0x7, KEYBOARD_REG_DATA); } +static int +fetch_key (int *is_break) +{ + int was_ext = 0; + grub_uint8_t at_key; + int ret = 0; + + if (! KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS))) + return -1; + at_key = grub_inb (KEYBOARD_REG_DATA); + if (at_key == 0xe0) + { + e0_received = 1; + return -1; + } + + was_ext = e0_received; + e0_received = 0; + + switch (current_set) + { + case 1: + *is_break = !!(at_key & 0x80); + if (!was_ext) + ret = set1_mapping[at_key & 0x7f]; + else + { + unsigned i; + for (i = 0; i < ARRAY_SIZE (set1_e0_mapping); i++) + if (set1_e0_mapping[i].from == (at_key & 0x80)) + { + ret = set1_e0_mapping[i].to; + break; + } + } + break; + case 2: + if (at_key == 0xf0) + { + f0_received = 1; + return -1; + } + *is_break = f0_received; + f0_received = 0; + if (!was_ext) + ret = set2_mapping[at_key]; + else + { + unsigned i; + for (i = 0; i < ARRAY_SIZE (set1_e0_mapping); i++) + if (set1_e0_mapping[i].from == (at_key & 0x80)) + { + ret = set1_e0_mapping[i].to; + break; + } + } + break; + default: + return -1; + } + if (!ret) + { + grub_printf ("Unknown key 0x%02x from set %d\n\n", at_key, current_set); + return -1; + } + return ret; +} + /* FIXME: This should become an interrupt service routine. For now it's just used to catch events from control keys. */ -static void -grub_keyboard_isr (grub_uint8_t key) +static int +grub_keyboard_isr (grub_keyboard_key_t key, int is_break) { - if (KEYBOARD_ISMAKE (key)) - switch (KEYBOARD_SCANCODE (key)) + if (!is_break) + switch (key) { - case SHIFT_L: - at_keyboard_status |= GRUB_TERM_STATUS_LSHIFT; - break; - case SHIFT_R: - at_keyboard_status |= GRUB_TERM_STATUS_RSHIFT; - break; - case CTRL: - at_keyboard_status |= GRUB_TERM_STATUS_LCTRL; - break; - case ALT: - if (extended_pending) - at_keyboard_status |= GRUB_TERM_STATUS_RALT; - else - at_keyboard_status |= GRUB_TERM_STATUS_LALT; - break; + case GRUB_KEYBOARD_KEY_LEFT_SHIFT: + at_keyboard_status |= GRUB_TERM_STATUS_LSHIFT; + return 1; + case GRUB_KEYBOARD_KEY_RIGHT_SHIFT: + at_keyboard_status |= GRUB_TERM_STATUS_RSHIFT; + return 1; + case GRUB_KEYBOARD_KEY_LEFT_CTRL: + at_keyboard_status |= GRUB_TERM_STATUS_LCTRL; + return 1; + case GRUB_KEYBOARD_KEY_RIGHT_CTRL: + at_keyboard_status |= GRUB_TERM_STATUS_RCTRL; + return 1; + case GRUB_KEYBOARD_KEY_RIGHT_ALT: + at_keyboard_status |= GRUB_TERM_STATUS_RALT; + return 1; + case GRUB_KEYBOARD_KEY_LEFT_ALT: + at_keyboard_status |= GRUB_TERM_STATUS_LALT; + return 1; + default: + return 0; } else switch (KEYBOARD_SCANCODE (key)) { - case SHIFT_L: - at_keyboard_status &= ~GRUB_TERM_STATUS_LSHIFT; - break; - case SHIFT_R: - at_keyboard_status &= ~GRUB_TERM_STATUS_RSHIFT; - break; - case CTRL: - at_keyboard_status &= ~GRUB_TERM_STATUS_LCTRL; - break; - case ALT: - if (extended_pending) - at_keyboard_status &= ~GRUB_TERM_STATUS_RALT; - else - at_keyboard_status &= ~GRUB_TERM_STATUS_LALT; - break; + case GRUB_KEYBOARD_KEY_LEFT_SHIFT: + at_keyboard_status &= ~GRUB_TERM_STATUS_LSHIFT; + return 1; + case GRUB_KEYBOARD_KEY_RIGHT_SHIFT: + at_keyboard_status &= ~GRUB_TERM_STATUS_RSHIFT; + return 1; + case GRUB_KEYBOARD_KEY_LEFT_CTRL: + at_keyboard_status &= ~GRUB_TERM_STATUS_LCTRL; + return 1; + case GRUB_KEYBOARD_KEY_RIGHT_CTRL: + at_keyboard_status &= ~GRUB_TERM_STATUS_RCTRL; + return 1; + case GRUB_KEYBOARD_KEY_RIGHT_ALT: + at_keyboard_status &= ~GRUB_TERM_STATUS_RALT; + return 1; + case GRUB_KEYBOARD_KEY_LEFT_ALT: + at_keyboard_status &= ~GRUB_TERM_STATUS_LALT; + return 1; + default: + return 0; } } @@ -117,31 +383,19 @@ grub_keyboard_isr (grub_uint8_t key) static int grub_keyboard_getkey (void) { - grub_uint8_t key; - grub_uint8_t ret; - if (! KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS))) - return -1; - key = grub_inb (KEYBOARD_REG_DATA); - if (key == 0xe0) - { - extended_pending = 1; - return -1; - } - /* FIXME */ grub_keyboard_isr (key); - ret = KEYBOARD_SCANCODE (key); - if (ret == SHIFT_L || ret == SHIFT_R || ret == ALT || ret == CTRL) - { - extended_pending = 0; - return -1; - } - if (extended_pending) - ret |= 0x80; - extended_pending = 0; - if (! KEYBOARD_ISMAKE (key)) - return -1; - return ret; -} + int key; + int is_break; + key = fetch_key (&is_break); + if (key == -1) + return -1; + + if (grub_keyboard_isr (key, is_break)) + return -1; + if (is_break) + return -1; + return key; +} /* If there is a character pending, return it; otherwise return -1. */ static int @@ -156,7 +410,7 @@ grub_at_keyboard_getkey_noblock (void) #endif switch (code) { - case CAPS_LOCK: + case GRUB_KEYBOARD_KEY_CAPS_LOCK: at_keyboard_status ^= GRUB_TERM_STATUS_CAPS; led_status ^= KEYBOARD_LED_CAPS; keyboard_controller_led (led_status); @@ -165,7 +419,7 @@ grub_at_keyboard_getkey_noblock (void) grub_dprintf ("atkeyb", "caps_lock = %d\n", !!(at_keyboard_status & KEYBOARD_STATUS_CAPS_LOCK)); #endif return -1; - case NUM_LOCK: + case GRUB_KEYBOARD_KEY_NUM_LOCK: at_keyboard_status ^= GRUB_TERM_STATUS_NUM; led_status ^= KEYBOARD_LED_NUM; keyboard_controller_led (led_status); @@ -174,14 +428,13 @@ grub_at_keyboard_getkey_noblock (void) grub_dprintf ("atkeyb", "num_lock = %d\n", !!(at_keyboard_status & KEYBOARD_STATUS_NUM_LOCK)); #endif return -1; - case SCROLL_LOCK: + case GRUB_KEYBOARD_KEY_SCROLL_LOCK: at_keyboard_status ^= GRUB_TERM_STATUS_SCROLL; led_status ^= KEYBOARD_LED_SCROLL; keyboard_controller_led (led_status); return -1; default: - return grub_term_map_key (grub_at_map_to_usb (code), - at_keyboard_status); + return grub_term_map_key (code, at_keyboard_status); } } @@ -222,7 +475,7 @@ grub_keyboard_controller_init (struct grub_term_input *term __attribute__ ((unus pending_key = -1; at_keyboard_status = 0; grub_keyboard_controller_orig = grub_keyboard_controller_read (); - grub_keyboard_controller_write (grub_keyboard_controller_orig | KEYBOARD_SCANCODE_SET1); + set_scancodes (); keyboard_controller_led (led_status); /* Drain input buffer. */ while (KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS))) @@ -234,6 +487,7 @@ grub_keyboard_controller_init (struct grub_term_input *term __attribute__ ((unus static grub_err_t grub_keyboard_controller_fini (struct grub_term_input *term __attribute__ ((unused))) { + query_mode (grub_keyboard_orig_set); grub_keyboard_controller_write (grub_keyboard_controller_orig); return GRUB_ERR_NONE; } diff --git a/util/grub-mklayout.c b/util/grub-mklayout.c index 3aafd8837..fc8ffb67a 100644 --- a/util/grub-mklayout.c +++ b/util/grub-mklayout.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include @@ -192,6 +191,65 @@ static struct console_grub_equivalence console_grub_equivalences_common[] = { {NULL, '\0'} }; +static grub_uint8_t linux_to_usb_map[128] = { + /* 0x00 */ 0x00 /* Unused */, 0x29 /* Escape */, + /* 0x02 */ 0x1e /* 1 */, 0x1f /* 2 */, + /* 0x04 */ 0x20 /* 3 */, 0x21 /* 4 */, + /* 0x06 */ 0x22 /* 5 */, 0x23 /* 6 */, + /* 0x08 */ 0x24 /* 7 */, 0x25 /* 8 */, + /* 0x0a */ 0x26 /* 9 */, 0x27 /* 0 */, + /* 0x0c */ 0x2d /* - */, 0x2e /* = */, + /* 0x0e */ 0x2a /* \b */, 0x2b /* \t */, + /* 0x10 */ 0x14 /* q */, 0x1a /* w */, + /* 0x12 */ 0x08 /* e */, 0x15 /* r */, + /* 0x14 */ 0x17 /* t */, 0x1c /* y */, + /* 0x16 */ 0x18 /* u */, 0x0c /* i */, + /* 0x18 */ 0x12 /* o */, 0x13 /* p */, + /* 0x1a */ 0x2f /* [ */, 0x30 /* ] */, + /* 0x1c */ 0x28 /* Enter */, 0x00 /* Left CTRL */, + /* 0x1e */ 0x04 /* a */, 0x16 /* s */, + /* 0x20 */ 0x07 /* d */, 0x09 /* f */, + /* 0x22 */ 0x0a /* g */, 0x0b /* h */, + /* 0x24 */ 0x0d /* j */, 0x0e /* k */, + /* 0x26 */ 0x0f /* l */, 0x33 /* ; */, + /* 0x28 */ 0x34 /* " */, 0x35 /* ` */, + /* 0x2a */ 0x00 /* Left Shift */, 0x32 /* \ */, + /* 0x2c */ 0x1d /* z */, 0x1b /* x */, + /* 0x2e */ 0x06 /* c */, 0x19 /* v */, + /* 0x30 */ 0x05 /* b */, 0x11 /* n */, + /* 0x32 */ 0x10 /* m */, 0x36 /* , */, + /* 0x34 */ 0x37 /* . */, 0x38 /* / */, + /* 0x36 */ 0x00 /* Right Shift */, 0x55 /* Num * */, + /* 0x38 */ 0x00 /* Left ALT */, 0x2c /* Space */, + /* 0x3a */ 0x39 /* Caps Lock */, 0x3a /* F1 */, + /* 0x3c */ 0x3b /* F2 */, 0x3c /* F3 */, + /* 0x3e */ 0x3d /* F4 */, 0x3e /* F5 */, + /* 0x40 */ 0x3f /* F6 */, 0x40 /* F7 */, + /* 0x42 */ 0x41 /* F8 */, 0x42 /* F9 */, + /* 0x44 */ 0x43 /* F10 */, 0x53 /* NumLock */, + /* 0x46 */ 0x47 /* Scroll Lock */, 0x5f /* Num 7 */, + /* 0x48 */ 0x60 /* Num 8 */, 0x61 /* Num 9 */, + /* 0x4a */ 0x56 /* Num - */, 0x5c /* Num 4 */, + /* 0x4c */ 0x5d /* Num 5 */, 0x5e /* Num 6 */, + /* 0x4e */ 0x57 /* Num + */, 0x59 /* Num 1 */, + /* 0x50 */ 0x5a /* Num 2 */, 0x5b /* Num 3 */, + /* 0x52 */ 0x62 /* Num 0 */, 0x63 /* Num . */, + /* 0x54 */ 0x00, 0x00, + /* 0x56 */ 0x64 /* 102nd key. */, 0x44 /* F11 */, + /* 0x58 */ 0x45 /* F12 */, 0x00, + /* 0x5a */ 0x00, 0x00, + /* 0x5c */ 0x00, 0x00, + /* 0x5e */ 0x00, 0x00, + /* 0x60 */ 0x58 /* Num \n */, 0x00 /* Right CTRL */, + /* 0x62 */ 0x54 /* Num / */, 0x00, + /* 0x64 */ 0x00 /* Right ALT */, 0x00, + /* 0x66 */ 0x4a /* Home */, 0x52 /* Up */, + /* 0x68 */ 0x4e /* NPage */, 0x50 /* Left */, + /* 0x6a */ 0x4f /* Right */, 0x4d /* End */, + /* 0x6c */ 0x51 /* Down */, 0x4b /* PPage */, + /* 0x6e */ 0x49 /* Insert */, 0x4c /* DC */ +}; + static void usage (int status) { @@ -298,50 +356,40 @@ write_keymaps (FILE *in, FILE *out) { if (strncmp (line, "keycode", sizeof ("keycode") - 1) == 0) { - unsigned keycode_at, orig; + unsigned keycode_linux; unsigned keycode_usb; char normal[64]; char shift[64]; char normalalt[64]; char shiftalt[64]; - static grub_uint8_t e0_remap[] = { - 0x9c /* Num \n */, 0x9d /* Right CTRL */, 0xb5 /* Num / */, - 0, 0xb8 /* Right ALT */, 0, - 0xc7 /* Home */, 0xc8 /* Up */, 0xc9 /* NPage*/, 0xcb /* Left */, - 0xcd /* Right */, 0xcf /* End */, 0xd0 /* Down */, 0xd1 /* PPage */, - 0xd2 /* Insert */, 0xd3 /* Delete */ - }; - sscanf (line, "keycode %u = %60s %60s %60s %60s", &keycode_at, + sscanf (line, "keycode %u = %60s %60s %60s %60s", &keycode_linux, normal, shift, normalalt, shiftalt); - orig = keycode_at; /* Not used. */ - if (keycode_at == 0x77 /* Pause */ + if (keycode_linux == 0x77 /* Pause */ /* Some obscure keys */ - || keycode_at == 0x63 || keycode_at == 0x7d || keycode_at == 0x7e) + || keycode_linux == 0x63 || keycode_linux == 0x7d + || keycode_linux == 0x7e) continue; - if (keycode_at >= 96 && keycode_at < 96 + ARRAY_SIZE (e0_remap)) - keycode_at = e0_remap[keycode_at - 96]; - /* Not remappable. */ - if (keycode_at == 0x1d /* Left CTRL */ - || keycode_at == 0x9d /* Right CTRL */ - || keycode_at == 0x2a /* Left Shift. */ - || keycode_at == 0x36 /* Right Shift. */ - || keycode_at == 0x38 /* Left ALT. */ - || keycode_at == 0xb8 /* Right ALT. */ - || keycode_at == 0x3a /* CapsLock. */ - || keycode_at == 0x45 /* NumLock. */ - || keycode_at == 0x46 /* ScrollLock. */) + if (keycode_linux == 0x1d /* Left CTRL */ + || keycode_linux == 0x9d /* Right CTRL */ + || keycode_linux == 0x2a /* Left Shift. */ + || keycode_linux == 0x36 /* Right Shift. */ + || keycode_linux == 0x38 /* Left ALT. */ + || keycode_linux == 0xb8 /* Right ALT. */ + || keycode_linux == 0x3a /* CapsLock. */ + || keycode_linux == 0x45 /* NumLock. */ + || keycode_linux == 0x46 /* ScrollLock. */) continue; - keycode_usb = grub_at_map_to_usb (keycode_at); + keycode_usb = linux_to_usb_map[keycode_linux]; if (keycode_usb == 0 || keycode_usb >= GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE) { - fprintf (stderr, "Unknown keycode 0x%02x\n", orig); + fprintf (stderr, "Unknown keycode 0x%02x\n", keycode_linux); continue; } if (keycode_usb < GRUB_KEYBOARD_LAYOUTS_ARRAY_SIZE) From 09206dc3d09f29c8dcb2af30b1001ba56e0b9bf4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 22 Aug 2010 23:56:41 +0200 Subject: [PATCH 055/214] Macroify key constants --- include/grub/keyboard_layouts.h | 99 +++++++++++- term/at_keyboard.c | 257 ++++++++++++++++++-------------- util/grub-mklayout.c | 112 +++++++------- 3 files changed, 296 insertions(+), 172 deletions(-) diff --git a/include/grub/keyboard_layouts.h b/include/grub/keyboard_layouts.h index dd6631a51..24d4880af 100644 --- a/include/grub/keyboard_layouts.h +++ b/include/grub/keyboard_layouts.h @@ -35,15 +35,106 @@ struct grub_keyboard_layout typedef enum grub_keyboard_key { + GRUB_KEYBOARD_KEY_A = 0x04, + GRUB_KEYBOARD_KEY_B = 0x05, + GRUB_KEYBOARD_KEY_C = 0x06, + GRUB_KEYBOARD_KEY_D = 0x07, + GRUB_KEYBOARD_KEY_E = 0x08, + GRUB_KEYBOARD_KEY_F = 0x09, + GRUB_KEYBOARD_KEY_G = 0x0a, + GRUB_KEYBOARD_KEY_H = 0x0b, + GRUB_KEYBOARD_KEY_I = 0x0c, + GRUB_KEYBOARD_KEY_J = 0x0d, + GRUB_KEYBOARD_KEY_K = 0x0e, + GRUB_KEYBOARD_KEY_L = 0x0f, + GRUB_KEYBOARD_KEY_M = 0x10, + GRUB_KEYBOARD_KEY_N = 0x11, + GRUB_KEYBOARD_KEY_O = 0x12, + GRUB_KEYBOARD_KEY_P = 0x13, + GRUB_KEYBOARD_KEY_Q = 0x14, + GRUB_KEYBOARD_KEY_R = 0x15, + GRUB_KEYBOARD_KEY_S = 0x16, + GRUB_KEYBOARD_KEY_T = 0x17, + GRUB_KEYBOARD_KEY_U = 0x18, + GRUB_KEYBOARD_KEY_V = 0x19, + GRUB_KEYBOARD_KEY_W = 0x1a, + GRUB_KEYBOARD_KEY_X = 0x1b, + GRUB_KEYBOARD_KEY_Y = 0x1c, + GRUB_KEYBOARD_KEY_Z = 0x1d, + GRUB_KEYBOARD_KEY_1 = 0x1e, + GRUB_KEYBOARD_KEY_2 = 0x1f, + GRUB_KEYBOARD_KEY_3 = 0x20, + GRUB_KEYBOARD_KEY_4 = 0x21, + GRUB_KEYBOARD_KEY_5 = 0x22, + GRUB_KEYBOARD_KEY_6 = 0x23, + GRUB_KEYBOARD_KEY_7 = 0x24, + GRUB_KEYBOARD_KEY_8 = 0x25, + GRUB_KEYBOARD_KEY_9 = 0x26, + GRUB_KEYBOARD_KEY_0 = 0x27, + GRUB_KEYBOARD_KEY_ENTER = 0x28, + GRUB_KEYBOARD_KEY_ESCAPE = 0x29, + GRUB_KEYBOARD_KEY_BACKSPACE = 0x2a, + GRUB_KEYBOARD_KEY_TAB = 0x2b, + GRUB_KEYBOARD_KEY_SPACE = 0x2c, + GRUB_KEYBOARD_KEY_DASH = 0x2d, + GRUB_KEYBOARD_KEY_EQUAL = 0x2e, + GRUB_KEYBOARD_KEY_LBRACKET = 0x2f, + GRUB_KEYBOARD_KEY_RBRACKET = 0x30, + GRUB_KEYBOARD_KEY_BACKSLASH = 0x32, + GRUB_KEYBOARD_KEY_SEMICOLON = 0x33, + GRUB_KEYBOARD_KEY_DQUOTE = 0x34, + GRUB_KEYBOARD_KEY_RQUOTE = 0x35, + GRUB_KEYBOARD_KEY_COMMA = 0x36, + GRUB_KEYBOARD_KEY_DOT = 0x37, + GRUB_KEYBOARD_KEY_SLASH = 0x38, GRUB_KEYBOARD_KEY_CAPS_LOCK = 0x39, + GRUB_KEYBOARD_KEY_F1 = 0x3a, + GRUB_KEYBOARD_KEY_F2 = 0x3b, + GRUB_KEYBOARD_KEY_F3 = 0x3c, + GRUB_KEYBOARD_KEY_F4 = 0x3d, + GRUB_KEYBOARD_KEY_F5 = 0x3e, + GRUB_KEYBOARD_KEY_F6 = 0x3f, + GRUB_KEYBOARD_KEY_F7 = 0x40, + GRUB_KEYBOARD_KEY_F8 = 0x41, + GRUB_KEYBOARD_KEY_F9 = 0x42, + GRUB_KEYBOARD_KEY_F10 = 0x43, + GRUB_KEYBOARD_KEY_F11 = 0x44, + GRUB_KEYBOARD_KEY_F12 = 0x45, GRUB_KEYBOARD_KEY_SCROLL_LOCK = 0x47, - GRUB_KEYBOARD_KEY_NUM_LOCK = 0x53, - GRUB_KEYBOARD_KEY_LEFT_CTRL = 0xe0, + GRUB_KEYBOARD_KEY_INSERT = 0x49, + GRUB_KEYBOARD_KEY_HOME = 0x4a, + GRUB_KEYBOARD_KEY_PPAGE = 0x4b, + GRUB_KEYBOARD_KEY_DELETE = 0x4c, + GRUB_KEYBOARD_KEY_END = 0x4d, + GRUB_KEYBOARD_KEY_NPAGE = 0x4e, + GRUB_KEYBOARD_KEY_RIGHT = 0x4f, + GRUB_KEYBOARD_KEY_LEFT = 0x50, + GRUB_KEYBOARD_KEY_DOWN = 0x51, + GRUB_KEYBOARD_KEY_UP = 0x52, + GRUB_KEYBOARD_KEY_NUM_LOCK = 0x53, + GRUB_KEYBOARD_KEY_NUMSLASH = 0x54, + GRUB_KEYBOARD_KEY_NUMMUL = 0x55, + GRUB_KEYBOARD_KEY_NUMMINUS = 0x56, + GRUB_KEYBOARD_KEY_NUMPLUS = 0x57, + GRUB_KEYBOARD_KEY_NUMENTER = 0x58, + GRUB_KEYBOARD_KEY_NUM1 = 0x59, + GRUB_KEYBOARD_KEY_NUM2 = 0x5a, + GRUB_KEYBOARD_KEY_NUM3 = 0x5b, + GRUB_KEYBOARD_KEY_NUM4 = 0x5c, + GRUB_KEYBOARD_KEY_NUM5 = 0x5d, + GRUB_KEYBOARD_KEY_NUM6 = 0x5e, + GRUB_KEYBOARD_KEY_NUM7 = 0x5f, + GRUB_KEYBOARD_KEY_NUM8 = 0x60, + GRUB_KEYBOARD_KEY_NUM9 = 0x61, + GRUB_KEYBOARD_KEY_NUM0 = 0x62, + GRUB_KEYBOARD_KEY_NUMDOT = 0x63, + GRUB_KEYBOARD_KEY_102ND = 0x64, + GRUB_KEYBOARD_KEY_LEFT_CTRL = 0xe0, GRUB_KEYBOARD_KEY_LEFT_SHIFT = 0xe1, - GRUB_KEYBOARD_KEY_LEFT_ALT = 0xe2, + GRUB_KEYBOARD_KEY_LEFT_ALT = 0xe2, GRUB_KEYBOARD_KEY_RIGHT_CTRL = 0xe4, GRUB_KEYBOARD_KEY_RIGHT_SHIFT = 0xe5, - GRUB_KEYBOARD_KEY_RIGHT_ALT = 0xe6, + GRUB_KEYBOARD_KEY_RIGHT_ALT = 0xe6, } grub_keyboard_key_t; unsigned EXPORT_FUNC(grub_term_map_key) (grub_keyboard_key_t code, int status); diff --git a/term/at_keyboard.c b/term/at_keyboard.c index 00c6cef83..c515a3971 100644 --- a/term/at_keyboard.c +++ b/term/at_keyboard.c @@ -41,60 +41,60 @@ static grub_uint8_t current_set; static const grub_uint8_t set1_mapping[128] = { - /* 0x00 */ 0x00 /* Unused */, 0x29 /* Escape */, - /* 0x02 */ 0x1e /* 1 */, 0x1f /* 2 */, - /* 0x04 */ 0x20 /* 3 */, 0x21 /* 4 */, - /* 0x06 */ 0x22 /* 5 */, 0x23 /* 6 */, - /* 0x08 */ 0x24 /* 7 */, 0x25 /* 8 */, - /* 0x0a */ 0x26 /* 9 */, 0x27 /* 0 */, - /* 0x0c */ 0x2d /* - */, 0x2e /* = */, - /* 0x0e */ 0x2a /* \b */, 0x2b /* \t */, - /* 0x10 */ 0x14 /* q */, 0x1a /* w */, - /* 0x12 */ 0x08 /* e */, 0x15 /* r */, - /* 0x14 */ 0x17 /* t */, 0x1c /* y */, - /* 0x16 */ 0x18 /* u */, 0x0c /* i */, - /* 0x18 */ 0x12 /* o */, 0x13 /* p */, - /* 0x1a */ 0x2f /* [ */, 0x30 /* ] */, - /* 0x1c */ 0x28 /* Enter */, 0xe0 /* Left CTRL */, - /* 0x1e */ 0x04 /* a */, 0x16 /* s */, - /* 0x20 */ 0x07 /* d */, 0x09 /* f */, - /* 0x22 */ 0x0a /* g */, 0x0b /* h */, - /* 0x24 */ 0x0d /* j */, 0x0e /* k */, - /* 0x26 */ 0x0f /* l */, 0x33 /* ; */, - /* 0x28 */ 0x34 /* " */, 0x35 /* ` */, - /* 0x2a */ 0xe1 /* Left Shift */, 0x32 /* \ */, - /* 0x2c */ 0x1d /* z */, 0x1b /* x */, - /* 0x2e */ 0x06 /* c */, 0x19 /* v */, - /* 0x30 */ 0x05 /* b */, 0x11 /* n */, - /* 0x32 */ 0x10 /* m */, 0x36 /* , */, - /* 0x34 */ 0x37 /* . */, 0x38 /* / */, - /* 0x36 */ 0xe5 /* Right Shift */, 0x55 /* Num * */, - /* 0x38 */ 0xe2 /* Left ALT */, 0x2c /* Space */, - /* 0x3a */ 0x39 /* Caps Lock */, 0x3a /* F1 */, - /* 0x3c */ 0x3b /* F2 */, 0x3c /* F3 */, - /* 0x3e */ 0x3d /* F4 */, 0x3e /* F5 */, - /* 0x40 */ 0x3f /* F6 */, 0x40 /* F7 */, - /* 0x42 */ 0x41 /* F8 */, 0x42 /* F9 */, - /* 0x44 */ 0x43 /* F10 */, 0x53 /* NumLock */, - /* 0x46 */ 0x47 /* Scroll Lock */, 0x5f /* Num 7 */, - /* 0x48 */ 0x60 /* Num 8 */, 0x61 /* Num 9 */, - /* 0x4a */ 0x56 /* Num - */, 0x5c /* Num 4 */, - /* 0x4c */ 0x5d /* Num 5 */, 0x5e /* Num 6 */, - /* 0x4e */ 0x57 /* Num + */, 0x59 /* Num 1 */, - /* 0x50 */ 0x5a /* Num 2 */, 0x5b /* Num 3 */, - /* 0x52 */ 0x62 /* Num 0 */, 0x63 /* Num . */, - /* 0x54 */ 0x00, 0x00, - /* 0x56 */ 0x64 /* 102nd key. */, 0x44 /* F11 */, - /* 0x58 */ 0x45 /* F12 */, 0x00, - /* 0x5a */ 0x00, 0x00, - /* 0x5c */ 0x00, 0x00, - /* 0x5e */ 0x00, 0x00, - /* 0x60 */ 0x00, 0x00, - /* 0x62 */ 0x00, 0x00, + /* 0x00 */ 0 /* Unused */, GRUB_KEYBOARD_KEY_ESCAPE, + /* 0x02 */ GRUB_KEYBOARD_KEY_1, GRUB_KEYBOARD_KEY_2, + /* 0x04 */ GRUB_KEYBOARD_KEY_3, GRUB_KEYBOARD_KEY_4, + /* 0x06 */ GRUB_KEYBOARD_KEY_5, GRUB_KEYBOARD_KEY_6, + /* 0x08 */ GRUB_KEYBOARD_KEY_7, GRUB_KEYBOARD_KEY_8, + /* 0x0a */ GRUB_KEYBOARD_KEY_9, GRUB_KEYBOARD_KEY_0, + /* 0x0c */ GRUB_KEYBOARD_KEY_DASH, GRUB_KEYBOARD_KEY_EQUAL, + /* 0x0e */ GRUB_KEYBOARD_KEY_BACKSPACE, GRUB_KEYBOARD_KEY_TAB, + /* 0x10 */ GRUB_KEYBOARD_KEY_Q, GRUB_KEYBOARD_KEY_W, + /* 0x12 */ GRUB_KEYBOARD_KEY_E, GRUB_KEYBOARD_KEY_R, + /* 0x14 */ GRUB_KEYBOARD_KEY_T, GRUB_KEYBOARD_KEY_Y, + /* 0x16 */ GRUB_KEYBOARD_KEY_U, GRUB_KEYBOARD_KEY_I, + /* 0x18 */ GRUB_KEYBOARD_KEY_O, GRUB_KEYBOARD_KEY_P, + /* 0x1a */ GRUB_KEYBOARD_KEY_LBRACKET, GRUB_KEYBOARD_KEY_RBRACKET, + /* 0x1c */ GRUB_KEYBOARD_KEY_ENTER, GRUB_KEYBOARD_KEY_LEFT_CTRL, + /* 0x1e */ GRUB_KEYBOARD_KEY_A, GRUB_KEYBOARD_KEY_S, + /* 0x20 */ GRUB_KEYBOARD_KEY_D, GRUB_KEYBOARD_KEY_F, + /* 0x22 */ GRUB_KEYBOARD_KEY_G, GRUB_KEYBOARD_KEY_H, + /* 0x24 */ GRUB_KEYBOARD_KEY_J, GRUB_KEYBOARD_KEY_K, + /* 0x26 */ GRUB_KEYBOARD_KEY_L, GRUB_KEYBOARD_KEY_SEMICOLON, + /* 0x28 */ GRUB_KEYBOARD_KEY_DQUOTE, GRUB_KEYBOARD_KEY_RQUOTE, + /* 0x2a */ GRUB_KEYBOARD_KEY_LEFT_SHIFT, GRUB_KEYBOARD_KEY_BACKSLASH, + /* 0x2c */ GRUB_KEYBOARD_KEY_Z, GRUB_KEYBOARD_KEY_X, + /* 0x2e */ GRUB_KEYBOARD_KEY_C, GRUB_KEYBOARD_KEY_V, + /* 0x30 */ GRUB_KEYBOARD_KEY_B, GRUB_KEYBOARD_KEY_N, + /* 0x32 */ GRUB_KEYBOARD_KEY_M, GRUB_KEYBOARD_KEY_COMMA, + /* 0x34 */ GRUB_KEYBOARD_KEY_DOT, GRUB_KEYBOARD_KEY_SLASH, + /* 0x36 */ GRUB_KEYBOARD_KEY_RIGHT_SHIFT, GRUB_KEYBOARD_KEY_NUMMUL, + /* 0x38 */ GRUB_KEYBOARD_KEY_LEFT_ALT, GRUB_KEYBOARD_KEY_SPACE, + /* 0x3a */ GRUB_KEYBOARD_KEY_CAPS_LOCK, GRUB_KEYBOARD_KEY_F1, + /* 0x3c */ GRUB_KEYBOARD_KEY_F2, GRUB_KEYBOARD_KEY_F3, + /* 0x3e */ GRUB_KEYBOARD_KEY_F4, GRUB_KEYBOARD_KEY_F5, + /* 0x40 */ GRUB_KEYBOARD_KEY_F6, GRUB_KEYBOARD_KEY_F7, + /* 0x42 */ GRUB_KEYBOARD_KEY_F8, GRUB_KEYBOARD_KEY_F9, + /* 0x44 */ GRUB_KEYBOARD_KEY_F10, GRUB_KEYBOARD_KEY_NUM_LOCK, + /* 0x46 */ GRUB_KEYBOARD_KEY_SCROLL_LOCK, GRUB_KEYBOARD_KEY_NUM7, + /* 0x48 */ GRUB_KEYBOARD_KEY_NUM8, GRUB_KEYBOARD_KEY_NUM9, + /* 0x4a */ GRUB_KEYBOARD_KEY_NUMMINUS, GRUB_KEYBOARD_KEY_NUM4, + /* 0x4c */ GRUB_KEYBOARD_KEY_NUM5, GRUB_KEYBOARD_KEY_NUM6, + /* 0x4e */ GRUB_KEYBOARD_KEY_NUMPLUS, GRUB_KEYBOARD_KEY_NUM1, + /* 0x50 */ GRUB_KEYBOARD_KEY_NUM2, GRUB_KEYBOARD_KEY_NUM3, + /* 0x52 */ GRUB_KEYBOARD_KEY_NUMDOT, GRUB_KEYBOARD_KEY_NUMDOT, + /* 0x54 */ 0, 0, + /* 0x56 */ GRUB_KEYBOARD_KEY_102ND, GRUB_KEYBOARD_KEY_F11, + /* 0x58 */ GRUB_KEYBOARD_KEY_F12, 0, + /* 0x5a */ 0, 0, + /* 0x5c */ 0, 0, + /* 0x5e */ 0, 0, + /* 0x60 */ 0, 0, + /* 0x62 */ 0, 0, /* OLPC keys. Just mapped to normal keys. */ - /* 0x64 */ 0x00, 0x52 /* Up */, - /* 0x66 */ 0x51 /* Down */, 0x50 /* Left */, - /* 0x68 */ 0x4f /* Right */ + /* 0x64 */ 0, GRUB_KEYBOARD_KEY_UP, + /* 0x66 */ GRUB_KEYBOARD_KEY_DOWN, GRUB_KEYBOARD_KEY_LEFT, + /* 0x68 */ GRUB_KEYBOARD_KEY_RIGHT }; static const struct @@ -102,57 +102,90 @@ static const struct grub_uint8_t from, to; } set1_e0_mapping[] = { - {0x1c, 0x58 /* Num \n */}, - {0x1d, 0xe4 /* Right CTRL */}, - {0x35, 0x54 /* Num / */ }, - {0x38, 0xe6 /* Right ALT */}, - {0x47, 0x4a /* Home */ }, - {0x48, 0x52 /* Up */ }, - {0x49, 0x4e /* NPage */ }, - {0x4b, 0x50 /* Left */ }, - {0x4d, 0x4f /* Right */ }, - {0x4f, 0x4d /* End */ }, - {0x50, 0x51 /* Down */ }, - {0x51, 0x4b /* PPage */ }, - {0x52, 0x49 /* Insert */}, - {0x53, 0x4c /* DC */ }, + {0x1c, GRUB_KEYBOARD_KEY_NUMENTER}, + {0x1d, GRUB_KEYBOARD_KEY_RIGHT_CTRL}, + {0x35, GRUB_KEYBOARD_KEY_NUMSLASH }, + {0x38, GRUB_KEYBOARD_KEY_RIGHT_ALT}, + {0x47, GRUB_KEYBOARD_KEY_HOME}, + {0x48, GRUB_KEYBOARD_KEY_UP}, + {0x49, GRUB_KEYBOARD_KEY_NPAGE}, + {0x4b, GRUB_KEYBOARD_KEY_LEFT}, + {0x4d, GRUB_KEYBOARD_KEY_RIGHT}, + {0x4f, GRUB_KEYBOARD_KEY_END}, + {0x50, GRUB_KEYBOARD_KEY_DOWN}, + {0x51, GRUB_KEYBOARD_KEY_PPAGE}, + {0x52, GRUB_KEYBOARD_KEY_INSERT}, + {0x53, GRUB_KEYBOARD_KEY_DELETE}, }; static const grub_uint8_t set2_mapping[256] = { - /* 0x00 */ 0x00, 0x42 /* F9 */, 0x00, 0x3e /* F5 */, - /* 0x04 */ 0x3c /* F3 */, 0x3a /* F1 */, 0x3b /* F2 */, 0x45 /* F12 */, - /* 0x08 */ 0x00, 0x43 /* F10 */, 0x41 /* F8 */, 0x3f /* F6 */, - /* 0x0c */ 0x3d /* F4 */, 0x2b /* \t */, 0x35 /* ` */, 0x00, - /* 0x10 */ 0x00, GRUB_KEYBOARD_KEY_LEFT_ALT, GRUB_KEYBOARD_KEY_LEFT_SHIFT, 0x00, - /* 0x14 */ GRUB_KEYBOARD_KEY_LEFT_CTRL, 0x14 /* q */, 0x1e /* 1 */, 0x00, - /* 0x18 */ 0x00, 0x00, 0x1d /* s */, 0x16 /* s */, - /* 0x1c */ 0x04 /* a */, 0x1a /* w */, 0x1f /* 2 */, 0x00, - /* 0x20 */ 0x00, 0x06 /* c */, 0x1b /* x */, 0x07 /* d */, - /* 0x24 */ 0x08 /* e */, 0x21 /* 4 */, 0x20 /* 3 */, 0x00, - /* 0x28 */ 0x00, 0x2c /* Space */, 0x19 /* v */, 0x09 /* f */, - /* 0x2c */ 0x17 /* t */, 0x15 /* r */, 0x22 /* 5 */, 0x00, - /* 0x30 */ 0x00, 0x11 /* n */, 0x05 /* b */, 0x0b /* h */, - /* 0x34 */ 0x0a /* g */, 0x1c /* y */, 0x23 /* 6 */, 0x00, - /* 0x38 */ 0x00, 0x00, 0x10 /* m */, 0x0d /* j */, - /* 0x3c */ 0x18 /* u */, 0x24 /* 7 */, 0x25 /* 8 */, 0x00, - /* 0x40 */ 0x00, 0x37 /* . */, 0x0e /* k */, 0x0c /* i */, - /* 0x44 */ 0x12 /* o */, 0x27 /* 0 */, 0x26 /* 9 */, 0x00, - /* 0x48 */ 0x00, 0x36 /* , */, 0x38 /* / */, 0x0f /* l */, - /* 0x4c */ 0x33 /* ; */, 0x13 /* p */, 0x2d /* - */, 0x00, - /* 0x50 */ 0x00, 0x00, 0x34 /* ' */, 0x00, - /* 0x54 */ 0x2f /* [ */, 0x2e /* = */, 0x00, 0x00, - /* 0x58 */ GRUB_KEYBOARD_KEY_CAPS_LOCK, GRUB_KEYBOARD_KEY_RIGHT_SHIFT, 0x28 /* \n */,0x30 /* ] */, - /* 0x5c */ 0x00, 0x32 /* \ */, 0x00, 0x00, - /* 0x60 */ 0x00, 0x64 /* 102nd key. */, 0x00, 0x00, - /* 0x64 */ 0x00, 0x00, 0x2a /* \b */, 0x00, - /* 0x68 */ 0x00, 0x59 /* Num 1 */, 0x00, 0x5c /* Num 4 */, - /* 0x6c */ 0x5f /* Num 7 */, 0x00, 0x00, 0x00, - /* 0x70 */ 0x62 /* Num 0 */, 0x63 /* Num 0 */, 0x5a /* Num 2 */, 0x5d /* Num 5 */, - /* 0x74 */ 0x5e /* Num 6 */, 0x60 /* Num 8 */, 0x29 /* \e */, 0x53 /* NumLock */, - /* 0x78 */ 0x44 /* F11 */, 0x57 /* Num + */, 0x5b /* Num 3 */, 0x56 /* Num - */, - /* 0x7c */ 0x55 /* Num * */, 0x61 /* Num 9 */, 0x47 /* ScrollLock */, 0x00, - /* 0x80 */ 0x00, 0x00, 0x00, 0x40 /* F7 */, + /* 0x00 */ 0, GRUB_KEYBOARD_KEY_F9, + /* 0x02 */ 0, GRUB_KEYBOARD_KEY_F5, + /* 0x04 */ GRUB_KEYBOARD_KEY_F3, GRUB_KEYBOARD_KEY_F1, + /* 0x06 */ GRUB_KEYBOARD_KEY_F2, GRUB_KEYBOARD_KEY_F12, + /* 0x08 */ 0, GRUB_KEYBOARD_KEY_F10, + /* 0x0a */ GRUB_KEYBOARD_KEY_F8, GRUB_KEYBOARD_KEY_F6, + /* 0x0c */ GRUB_KEYBOARD_KEY_F4, GRUB_KEYBOARD_KEY_TAB, + /* 0x0e */ GRUB_KEYBOARD_KEY_RQUOTE, 0, + /* 0x10 */ 0, GRUB_KEYBOARD_KEY_LEFT_ALT, + /* 0x12 */ GRUB_KEYBOARD_KEY_LEFT_SHIFT, 0, + /* 0x14 */ GRUB_KEYBOARD_KEY_LEFT_CTRL, GRUB_KEYBOARD_KEY_Q, + /* 0x16 */ GRUB_KEYBOARD_KEY_1, 0, + /* 0x18 */ 0, 0, + /* 0x1a */ GRUB_KEYBOARD_KEY_Z, GRUB_KEYBOARD_KEY_S, + /* 0x1c */ GRUB_KEYBOARD_KEY_A, GRUB_KEYBOARD_KEY_W, + /* 0x1e */ GRUB_KEYBOARD_KEY_2, 0, + /* 0x20 */ 0, GRUB_KEYBOARD_KEY_C, + /* 0x22 */ GRUB_KEYBOARD_KEY_X, GRUB_KEYBOARD_KEY_D, + /* 0x24 */ GRUB_KEYBOARD_KEY_E, GRUB_KEYBOARD_KEY_4, + /* 0x26 */ GRUB_KEYBOARD_KEY_3, 0, + /* 0x28 */ 0, GRUB_KEYBOARD_KEY_SPACE, + /* 0x2a */ GRUB_KEYBOARD_KEY_V, GRUB_KEYBOARD_KEY_F, + /* 0x2c */ GRUB_KEYBOARD_KEY_T, GRUB_KEYBOARD_KEY_R, + /* 0x2e */ GRUB_KEYBOARD_KEY_5, 0, + /* 0x30 */ 0, GRUB_KEYBOARD_KEY_N, + /* 0x32 */ GRUB_KEYBOARD_KEY_B, GRUB_KEYBOARD_KEY_H, + /* 0x34 */ GRUB_KEYBOARD_KEY_G, GRUB_KEYBOARD_KEY_Y, + /* 0x36 */ GRUB_KEYBOARD_KEY_6, 0, + /* 0x38 */ 0, 0, + /* 0x3a */ GRUB_KEYBOARD_KEY_M, GRUB_KEYBOARD_KEY_J, + /* 0x3c */ GRUB_KEYBOARD_KEY_U, GRUB_KEYBOARD_KEY_7, + /* 0x3e */ GRUB_KEYBOARD_KEY_8, 0, + /* 0x40 */ 0, GRUB_KEYBOARD_KEY_DOT, + /* 0x42 */ GRUB_KEYBOARD_KEY_K, GRUB_KEYBOARD_KEY_I, + /* 0x44 */ GRUB_KEYBOARD_KEY_O, GRUB_KEYBOARD_KEY_0, + /* 0x46 */ GRUB_KEYBOARD_KEY_9, 0, + /* 0x48 */ 0, GRUB_KEYBOARD_KEY_COMMA, + /* 0x4a */ GRUB_KEYBOARD_KEY_SLASH, GRUB_KEYBOARD_KEY_L, + /* 0x4c */ GRUB_KEYBOARD_KEY_SEMICOLON, GRUB_KEYBOARD_KEY_P, + /* 0x4e */ GRUB_KEYBOARD_KEY_DASH, 0, + /* 0x50 */ 0, 0, + /* 0x52 */ GRUB_KEYBOARD_KEY_DQUOTE, 0, + /* 0x54 */ GRUB_KEYBOARD_KEY_LBRACKET, GRUB_KEYBOARD_KEY_EQUAL, + /* 0x56 */ 0, 0, + /* 0x58 */ GRUB_KEYBOARD_KEY_CAPS_LOCK, GRUB_KEYBOARD_KEY_RIGHT_SHIFT, + /* 0x5a */ GRUB_KEYBOARD_KEY_ENTER, GRUB_KEYBOARD_KEY_RBRACKET, + /* 0x5c */ 0, GRUB_KEYBOARD_KEY_BACKSLASH, + /* 0x5e */ 0, 0, + /* 0x60 */ 0, GRUB_KEYBOARD_KEY_102ND, + /* 0x62 */ 0, 0, + /* 0x64 */ 0, 0, + /* 0x66 */ GRUB_KEYBOARD_KEY_BACKSPACE, 0, + /* 0x68 */ 0, GRUB_KEYBOARD_KEY_NUM1, + /* 0x6a */ 0, GRUB_KEYBOARD_KEY_NUM4, + /* 0x6c */ GRUB_KEYBOARD_KEY_NUM7, 0, + /* 0x6e */ 0, 0, + /* 0x70 */ GRUB_KEYBOARD_KEY_NUMDOT, GRUB_KEYBOARD_KEY_NUM0, + /* 0x72 */ GRUB_KEYBOARD_KEY_NUM2, GRUB_KEYBOARD_KEY_NUM5, + /* 0x74 */ GRUB_KEYBOARD_KEY_NUM6, GRUB_KEYBOARD_KEY_NUM8, + /* 0x76 */ GRUB_KEYBOARD_KEY_ESCAPE, GRUB_KEYBOARD_KEY_NUM_LOCK, + /* 0x78 */ GRUB_KEYBOARD_KEY_F11, GRUB_KEYBOARD_KEY_NUMPLUS, + /* 0x7a */ GRUB_KEYBOARD_KEY_NUM3, GRUB_KEYBOARD_KEY_NUMMINUS, + /* 0x7c */ GRUB_KEYBOARD_KEY_NUMMUL, GRUB_KEYBOARD_KEY_NUM9, + /* 0x7e */ GRUB_KEYBOARD_KEY_SCROLL_LOCK, 0, + /* 0x80 */ 0, 0, + /* 0x82 */ 0, GRUB_KEYBOARD_KEY_F7, }; static const struct @@ -162,18 +195,18 @@ static const struct { {0x11, GRUB_KEYBOARD_KEY_RIGHT_ALT}, {0x14, GRUB_KEYBOARD_KEY_RIGHT_CTRL}, - {0x4a, 0x54}, /* Num / */ - {0x5a, 0x58}, /* Num enter */ - {0x69, 0x4d}, /* End */ - {0x6b, 0x50}, /* Left */ - {0x6c, 0x4a}, /* Home */ - {0x70, 0x49}, /* Insert */ - {0x71, 0x4c}, /* Delete */ - {0x72, 0x51}, /* Down */ - {0x74, 0x4f}, /* Right */ - {0x75, 0x52}, /* Up */ - {0x7a, 0x4e}, /* PageDown */ - {0x7d, 0x4b}, /* PageUp */ + {0x4a, GRUB_KEYBOARD_KEY_NUMSLASH}, + {0x5a, GRUB_KEYBOARD_KEY_NUMENTER}, + {0x69, GRUB_KEYBOARD_KEY_END}, + {0x6b, GRUB_KEYBOARD_KEY_LEFT}, + {0x6c, GRUB_KEYBOARD_KEY_HOME}, + {0x70, GRUB_KEYBOARD_KEY_INSERT}, + {0x71, GRUB_KEYBOARD_KEY_DELETE}, + {0x72, GRUB_KEYBOARD_KEY_DOWN}, + {0x74, GRUB_KEYBOARD_KEY_RIGHT}, + {0x75, GRUB_KEYBOARD_KEY_UP}, + {0x7a, GRUB_KEYBOARD_KEY_NPAGE}, + {0x7d, GRUB_KEYBOARD_KEY_PPAGE}, }; static void diff --git a/util/grub-mklayout.c b/util/grub-mklayout.c index fc8ffb67a..e22888fc5 100644 --- a/util/grub-mklayout.c +++ b/util/grub-mklayout.c @@ -192,62 +192,62 @@ static struct console_grub_equivalence console_grub_equivalences_common[] = { }; static grub_uint8_t linux_to_usb_map[128] = { - /* 0x00 */ 0x00 /* Unused */, 0x29 /* Escape */, - /* 0x02 */ 0x1e /* 1 */, 0x1f /* 2 */, - /* 0x04 */ 0x20 /* 3 */, 0x21 /* 4 */, - /* 0x06 */ 0x22 /* 5 */, 0x23 /* 6 */, - /* 0x08 */ 0x24 /* 7 */, 0x25 /* 8 */, - /* 0x0a */ 0x26 /* 9 */, 0x27 /* 0 */, - /* 0x0c */ 0x2d /* - */, 0x2e /* = */, - /* 0x0e */ 0x2a /* \b */, 0x2b /* \t */, - /* 0x10 */ 0x14 /* q */, 0x1a /* w */, - /* 0x12 */ 0x08 /* e */, 0x15 /* r */, - /* 0x14 */ 0x17 /* t */, 0x1c /* y */, - /* 0x16 */ 0x18 /* u */, 0x0c /* i */, - /* 0x18 */ 0x12 /* o */, 0x13 /* p */, - /* 0x1a */ 0x2f /* [ */, 0x30 /* ] */, - /* 0x1c */ 0x28 /* Enter */, 0x00 /* Left CTRL */, - /* 0x1e */ 0x04 /* a */, 0x16 /* s */, - /* 0x20 */ 0x07 /* d */, 0x09 /* f */, - /* 0x22 */ 0x0a /* g */, 0x0b /* h */, - /* 0x24 */ 0x0d /* j */, 0x0e /* k */, - /* 0x26 */ 0x0f /* l */, 0x33 /* ; */, - /* 0x28 */ 0x34 /* " */, 0x35 /* ` */, - /* 0x2a */ 0x00 /* Left Shift */, 0x32 /* \ */, - /* 0x2c */ 0x1d /* z */, 0x1b /* x */, - /* 0x2e */ 0x06 /* c */, 0x19 /* v */, - /* 0x30 */ 0x05 /* b */, 0x11 /* n */, - /* 0x32 */ 0x10 /* m */, 0x36 /* , */, - /* 0x34 */ 0x37 /* . */, 0x38 /* / */, - /* 0x36 */ 0x00 /* Right Shift */, 0x55 /* Num * */, - /* 0x38 */ 0x00 /* Left ALT */, 0x2c /* Space */, - /* 0x3a */ 0x39 /* Caps Lock */, 0x3a /* F1 */, - /* 0x3c */ 0x3b /* F2 */, 0x3c /* F3 */, - /* 0x3e */ 0x3d /* F4 */, 0x3e /* F5 */, - /* 0x40 */ 0x3f /* F6 */, 0x40 /* F7 */, - /* 0x42 */ 0x41 /* F8 */, 0x42 /* F9 */, - /* 0x44 */ 0x43 /* F10 */, 0x53 /* NumLock */, - /* 0x46 */ 0x47 /* Scroll Lock */, 0x5f /* Num 7 */, - /* 0x48 */ 0x60 /* Num 8 */, 0x61 /* Num 9 */, - /* 0x4a */ 0x56 /* Num - */, 0x5c /* Num 4 */, - /* 0x4c */ 0x5d /* Num 5 */, 0x5e /* Num 6 */, - /* 0x4e */ 0x57 /* Num + */, 0x59 /* Num 1 */, - /* 0x50 */ 0x5a /* Num 2 */, 0x5b /* Num 3 */, - /* 0x52 */ 0x62 /* Num 0 */, 0x63 /* Num . */, - /* 0x54 */ 0x00, 0x00, - /* 0x56 */ 0x64 /* 102nd key. */, 0x44 /* F11 */, - /* 0x58 */ 0x45 /* F12 */, 0x00, - /* 0x5a */ 0x00, 0x00, - /* 0x5c */ 0x00, 0x00, - /* 0x5e */ 0x00, 0x00, - /* 0x60 */ 0x58 /* Num \n */, 0x00 /* Right CTRL */, - /* 0x62 */ 0x54 /* Num / */, 0x00, - /* 0x64 */ 0x00 /* Right ALT */, 0x00, - /* 0x66 */ 0x4a /* Home */, 0x52 /* Up */, - /* 0x68 */ 0x4e /* NPage */, 0x50 /* Left */, - /* 0x6a */ 0x4f /* Right */, 0x4d /* End */, - /* 0x6c */ 0x51 /* Down */, 0x4b /* PPage */, - /* 0x6e */ 0x49 /* Insert */, 0x4c /* DC */ + /* 0x00 */ 0 /* Unused */, GRUB_KEYBOARD_KEY_ESCAPE, + /* 0x02 */ GRUB_KEYBOARD_KEY_1, GRUB_KEYBOARD_KEY_2, + /* 0x04 */ GRUB_KEYBOARD_KEY_3, GRUB_KEYBOARD_KEY_4, + /* 0x06 */ GRUB_KEYBOARD_KEY_5, GRUB_KEYBOARD_KEY_6, + /* 0x08 */ GRUB_KEYBOARD_KEY_7, GRUB_KEYBOARD_KEY_8, + /* 0x0a */ GRUB_KEYBOARD_KEY_9, GRUB_KEYBOARD_KEY_0, + /* 0x0c */ GRUB_KEYBOARD_KEY_DASH, GRUB_KEYBOARD_KEY_EQUAL, + /* 0x0e */ GRUB_KEYBOARD_KEY_BACKSPACE, GRUB_KEYBOARD_KEY_TAB, + /* 0x10 */ GRUB_KEYBOARD_KEY_Q, GRUB_KEYBOARD_KEY_W, + /* 0x12 */ GRUB_KEYBOARD_KEY_E, GRUB_KEYBOARD_KEY_R, + /* 0x14 */ GRUB_KEYBOARD_KEY_T, GRUB_KEYBOARD_KEY_Y, + /* 0x16 */ GRUB_KEYBOARD_KEY_U, GRUB_KEYBOARD_KEY_I, + /* 0x18 */ GRUB_KEYBOARD_KEY_O, GRUB_KEYBOARD_KEY_P, + /* 0x1a */ GRUB_KEYBOARD_KEY_LBRACKET, GRUB_KEYBOARD_KEY_RBRACKET, + /* 0x1c */ GRUB_KEYBOARD_KEY_ENTER, GRUB_KEYBOARD_KEY_LEFT_CTRL, + /* 0x1e */ GRUB_KEYBOARD_KEY_A, GRUB_KEYBOARD_KEY_S, + /* 0x20 */ GRUB_KEYBOARD_KEY_D, GRUB_KEYBOARD_KEY_F, + /* 0x22 */ GRUB_KEYBOARD_KEY_G, GRUB_KEYBOARD_KEY_H, + /* 0x24 */ GRUB_KEYBOARD_KEY_J, GRUB_KEYBOARD_KEY_K, + /* 0x26 */ GRUB_KEYBOARD_KEY_L, GRUB_KEYBOARD_KEY_SEMICOLON, + /* 0x28 */ GRUB_KEYBOARD_KEY_DQUOTE, GRUB_KEYBOARD_KEY_RQUOTE, + /* 0x2a */ GRUB_KEYBOARD_KEY_LEFT_SHIFT, GRUB_KEYBOARD_KEY_BACKSLASH, + /* 0x2c */ GRUB_KEYBOARD_KEY_Z, GRUB_KEYBOARD_KEY_X, + /* 0x2e */ GRUB_KEYBOARD_KEY_C, GRUB_KEYBOARD_KEY_V, + /* 0x30 */ GRUB_KEYBOARD_KEY_B, GRUB_KEYBOARD_KEY_N, + /* 0x32 */ GRUB_KEYBOARD_KEY_M, GRUB_KEYBOARD_KEY_COMMA, + /* 0x34 */ GRUB_KEYBOARD_KEY_DOT, GRUB_KEYBOARD_KEY_SLASH, + /* 0x36 */ GRUB_KEYBOARD_KEY_RIGHT_SHIFT, GRUB_KEYBOARD_KEY_NUMMUL, + /* 0x38 */ GRUB_KEYBOARD_KEY_LEFT_ALT, GRUB_KEYBOARD_KEY_SPACE, + /* 0x3a */ GRUB_KEYBOARD_KEY_CAPS_LOCK, GRUB_KEYBOARD_KEY_F1, + /* 0x3c */ GRUB_KEYBOARD_KEY_F2, GRUB_KEYBOARD_KEY_F3, + /* 0x3e */ GRUB_KEYBOARD_KEY_F4, GRUB_KEYBOARD_KEY_F5, + /* 0x40 */ GRUB_KEYBOARD_KEY_F6, GRUB_KEYBOARD_KEY_F7, + /* 0x42 */ GRUB_KEYBOARD_KEY_F8, GRUB_KEYBOARD_KEY_F9, + /* 0x44 */ GRUB_KEYBOARD_KEY_F10, GRUB_KEYBOARD_KEY_NUM_LOCK, + /* 0x46 */ GRUB_KEYBOARD_KEY_SCROLL_LOCK, GRUB_KEYBOARD_KEY_NUM7, + /* 0x48 */ GRUB_KEYBOARD_KEY_NUM8, GRUB_KEYBOARD_KEY_NUM9, + /* 0x4a */ GRUB_KEYBOARD_KEY_NUMMINUS, GRUB_KEYBOARD_KEY_NUM4, + /* 0x4c */ GRUB_KEYBOARD_KEY_NUM5, GRUB_KEYBOARD_KEY_NUM6, + /* 0x4e */ GRUB_KEYBOARD_KEY_NUMPLUS, GRUB_KEYBOARD_KEY_NUM1, + /* 0x50 */ GRUB_KEYBOARD_KEY_NUM2, GRUB_KEYBOARD_KEY_NUM3, + /* 0x52 */ GRUB_KEYBOARD_KEY_NUMDOT, GRUB_KEYBOARD_KEY_NUMDOT, + /* 0x54 */ 0, 0, + /* 0x56 */ GRUB_KEYBOARD_KEY_102ND, GRUB_KEYBOARD_KEY_F11, + /* 0x58 */ GRUB_KEYBOARD_KEY_F12, 0, + /* 0x5a */ 0, 0, + /* 0x5c */ 0, 0, + /* 0x5e */ 0, 0, + /* 0x60 */ GRUB_KEYBOARD_KEY_NUMENTER, GRUB_KEYBOARD_KEY_RIGHT_CTRL, + /* 0x62 */ GRUB_KEYBOARD_KEY_NUMSLASH, 0, + /* 0x64 */ GRUB_KEYBOARD_KEY_RIGHT_ALT, 0, + /* 0x66 */ GRUB_KEYBOARD_KEY_HOME, GRUB_KEYBOARD_KEY_UP, + /* 0x68 */ GRUB_KEYBOARD_KEY_NPAGE, GRUB_KEYBOARD_KEY_LEFT, + /* 0x6a */ GRUB_KEYBOARD_KEY_RIGHT, GRUB_KEYBOARD_KEY_END, + /* 0x6c */ GRUB_KEYBOARD_KEY_DOWN, GRUB_KEYBOARD_KEY_PPAGE, + /* 0x6e */ GRUB_KEYBOARD_KEY_INSERT, GRUB_KEYBOARD_KEY_DELETE }; static void From 9e91bd9d9ae3c89f89b235b2f3976fb2e4cdce2e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 23 Aug 2010 01:13:54 +0200 Subject: [PATCH 056/214] Fix multiple issues with set 2 --- commands/keylayouts.c | 2 +- term/at_keyboard.c | 113 +++++++++++++++++++++++++++--------------- 2 files changed, 74 insertions(+), 41 deletions(-) diff --git a/commands/keylayouts.c b/commands/keylayouts.c index c68919aef..deb482a85 100644 --- a/commands/keylayouts.c +++ b/commands/keylayouts.c @@ -153,7 +153,7 @@ map_key_core (int code, int status, int *alt_gr_consumed) } unsigned -grub_term_map_key (int code, int status) +grub_term_map_key (grub_keyboard_key_t code, int status) { int alt_gr_consumed = 0; int key; diff --git a/term/at_keyboard.c b/term/at_keyboard.c index c515a3971..b8df4cbf3 100644 --- a/term/at_keyboard.c +++ b/term/at_keyboard.c @@ -152,11 +152,11 @@ static const grub_uint8_t set2_mapping[256] = /* 0x3a */ GRUB_KEYBOARD_KEY_M, GRUB_KEYBOARD_KEY_J, /* 0x3c */ GRUB_KEYBOARD_KEY_U, GRUB_KEYBOARD_KEY_7, /* 0x3e */ GRUB_KEYBOARD_KEY_8, 0, - /* 0x40 */ 0, GRUB_KEYBOARD_KEY_DOT, + /* 0x40 */ 0, GRUB_KEYBOARD_KEY_COMMA, /* 0x42 */ GRUB_KEYBOARD_KEY_K, GRUB_KEYBOARD_KEY_I, /* 0x44 */ GRUB_KEYBOARD_KEY_O, GRUB_KEYBOARD_KEY_0, /* 0x46 */ GRUB_KEYBOARD_KEY_9, 0, - /* 0x48 */ 0, GRUB_KEYBOARD_KEY_COMMA, + /* 0x48 */ 0, GRUB_KEYBOARD_KEY_DOT, /* 0x4a */ GRUB_KEYBOARD_KEY_SLASH, GRUB_KEYBOARD_KEY_L, /* 0x4c */ GRUB_KEYBOARD_KEY_SEMICOLON, GRUB_KEYBOARD_KEY_P, /* 0x4e */ GRUB_KEYBOARD_KEY_DASH, 0, @@ -220,53 +220,75 @@ grub_keyboard_controller_write (grub_uint8_t c) { keyboard_controller_wait_until_ready (); grub_outb (KEYBOARD_COMMAND_WRITE, KEYBOARD_REG_STATUS); + keyboard_controller_wait_until_ready (); grub_outb (c, KEYBOARD_REG_DATA); } -static grub_uint8_t -query_mode (int mode) +static int +write_mode (int mode) { + grub_uint8_t ack; keyboard_controller_wait_until_ready (); grub_outb (0xf0, KEYBOARD_REG_DATA); keyboard_controller_wait_until_ready (); - grub_inb (KEYBOARD_REG_DATA); - keyboard_controller_wait_until_ready (); grub_outb (mode, KEYBOARD_REG_DATA); + keyboard_controller_wait_until_ready (); + ack = grub_inb (KEYBOARD_REG_DATA); + if (ack != 0xfa) + return 0; + + return 1; +} + +static int +query_mode (void) +{ + grub_uint8_t ret; + int e; + + e = write_mode (0); + if (!e) + return 0; keyboard_controller_wait_until_ready (); - return grub_inb (KEYBOARD_REG_DATA); + do + ret = grub_inb (KEYBOARD_REG_DATA); + while (ret == 0xfa); + + /* QEMU translates the set even in no-translate mode. */ + if (ret == 0x43 || ret == 1) + return 1; + if (ret == 0x41 || ret == 2) + return 2; + if (ret == 0x3f || ret == 3) + return 3; + return 0; } -/* QEMU translates the set even in no-translate mode. */ -static inline int -recover_mode (grub_uint8_t report) -{ - if (report == 0x43 || report == 1) - return 1; - if (report == 0x41 || report == 2) - return 2; - if (report == 0x3f || report == 3) - return 3; - return -1; -} static void set_scancodes (void) { + grub_keyboard_orig_set = query_mode (); + /* You must have visited computer museum. Keyboard without scancode set + knowledge. Assume XT. */ + if (!grub_keyboard_orig_set) + { + current_set = 1; + return; + } + grub_keyboard_controller_write (grub_keyboard_controller_orig & ~KEYBOARD_AT_TRANSLATE); - grub_keyboard_orig_set = recover_mode (query_mode (0)); - query_mode (2); - current_set = query_mode (0); - current_set = recover_mode (current_set); + write_mode (2); + current_set = query_mode (); if (current_set == 2) return; - query_mode (1); - current_set = query_mode (0); - current_set = recover_mode (current_set); + write_mode (1); + current_set = query_mode (); if (current_set == 1) return; grub_printf ("No supported scancode set found\n"); @@ -305,6 +327,16 @@ fetch_key (int *is_break) return -1; } + if ((current_set == 2 || current_set == 3) && at_key == 0xf0) + { + f0_received = 1; + return -1; + } + + /* Setting LEDs may generate ACKs. */ + if (at_key == 0xfa) + return -1; + was_ext = e0_received; e0_received = 0; @@ -326,11 +358,6 @@ fetch_key (int *is_break) } break; case 2: - if (at_key == 0xf0) - { - f0_received = 1; - return -1; - } *is_break = f0_received; f0_received = 0; if (!was_ext) @@ -338,10 +365,10 @@ fetch_key (int *is_break) else { unsigned i; - for (i = 0; i < ARRAY_SIZE (set1_e0_mapping); i++) - if (set1_e0_mapping[i].from == (at_key & 0x80)) + for (i = 0; i < ARRAY_SIZE (set2_e0_mapping); i++) + if (set2_e0_mapping[i].from == at_key) { - ret = set1_e0_mapping[i].to; + ret = set2_e0_mapping[i].to; break; } } @@ -351,7 +378,12 @@ fetch_key (int *is_break) } if (!ret) { - grub_printf ("Unknown key 0x%02x from set %d\n\n", at_key, current_set); + if (was_ext) + grub_printf ("Unknown key 0xe0+0x%02x from set %d\n", + at_key, current_set); + else + grub_printf ("Unknown key 0x%02x from set %d\n", + at_key, current_set); return -1; } return ret; @@ -387,7 +419,7 @@ grub_keyboard_isr (grub_keyboard_key_t key, int is_break) return 0; } else - switch (KEYBOARD_SCANCODE (key)) + switch (key) { case GRUB_KEYBOARD_KEY_LEFT_SHIFT: at_keyboard_status &= ~GRUB_TERM_STATUS_LSHIFT; @@ -507,12 +539,12 @@ grub_keyboard_controller_init (struct grub_term_input *term __attribute__ ((unus { pending_key = -1; at_keyboard_status = 0; - grub_keyboard_controller_orig = grub_keyboard_controller_read (); - set_scancodes (); - keyboard_controller_led (led_status); /* Drain input buffer. */ while (KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS))) grub_inb (KEYBOARD_REG_DATA); + grub_keyboard_controller_orig = grub_keyboard_controller_read (); + set_scancodes (); + keyboard_controller_led (led_status); return GRUB_ERR_NONE; } @@ -520,7 +552,8 @@ grub_keyboard_controller_init (struct grub_term_input *term __attribute__ ((unus static grub_err_t grub_keyboard_controller_fini (struct grub_term_input *term __attribute__ ((unused))) { - query_mode (grub_keyboard_orig_set); + if (grub_keyboard_orig_set) + write_mode (grub_keyboard_orig_set); grub_keyboard_controller_write (grub_keyboard_controller_orig); return GRUB_ERR_NONE; } From b88904ca7fab60afec987ed39d95589d33e8bc1f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 23 Aug 2010 01:44:54 +0200 Subject: [PATCH 057/214] Fix ignoring of set1 extended sequences --- term/at_keyboard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/term/at_keyboard.c b/term/at_keyboard.c index b8df4cbf3..ff9f713c6 100644 --- a/term/at_keyboard.c +++ b/term/at_keyboard.c @@ -350,7 +350,7 @@ fetch_key (int *is_break) { unsigned i; for (i = 0; i < ARRAY_SIZE (set1_e0_mapping); i++) - if (set1_e0_mapping[i].from == (at_key & 0x80)) + if (set1_e0_mapping[i].from == (at_key & 0x7f)) { ret = set1_e0_mapping[i].to; break; From 7ae3eb623250b80737e227c6efd0ca7740eb01ab Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 23 Aug 2010 11:26:28 +0200 Subject: [PATCH 058/214] Wait for ACKs when setting the mode --- include/grub/at_keyboard.h | 2 ++ term/at_keyboard.c | 38 +++++++++++++++++++++++++++++--------- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/include/grub/at_keyboard.h b/include/grub/at_keyboard.h index 6e0806bdb..3dfa0da80 100644 --- a/include/grub/at_keyboard.h +++ b/include/grub/at_keyboard.h @@ -27,6 +27,8 @@ #define KEYBOARD_AT_TRANSLATE 0x40 +#define GRUB_AT_ACK 0xfa + #define KEYBOARD_ISMAKE(x) !((x) & 0x80) #define KEYBOARD_ISREADY(x) ((x) & 0x01) #define KEYBOARD_SCANCODE(x) ((x) & 0x7f) diff --git a/term/at_keyboard.c b/term/at_keyboard.c index ff9f713c6..e9db7834a 100644 --- a/term/at_keyboard.c +++ b/term/at_keyboard.c @@ -23,6 +23,7 @@ #include #include #include +#include static short at_keyboard_status = 0; static int e0_received = 0; @@ -225,19 +226,29 @@ grub_keyboard_controller_write (grub_uint8_t c) } static int -write_mode (int mode) +wait_ack (void) { grub_uint8_t ack; + grub_uint64_t endtime = grub_get_time_ms () + 20; + do + { + ack = grub_inb (KEYBOARD_REG_DATA); + } + while (ack != GRUB_AT_ACK && grub_get_time_ms () < endtime); + grub_dprintf ("atkeyb", "Ack 0x%02x\n", ack); + return ack == GRUB_AT_ACK; +} + +static int +write_mode (int mode) +{ keyboard_controller_wait_until_ready (); grub_outb (0xf0, KEYBOARD_REG_DATA); keyboard_controller_wait_until_ready (); grub_outb (mode, KEYBOARD_REG_DATA); keyboard_controller_wait_until_ready (); - ack = grub_inb (KEYBOARD_REG_DATA); - if (ack != 0xfa) - return 0; - return 1; + return wait_ack (); } static int @@ -254,7 +265,7 @@ query_mode (void) do ret = grub_inb (KEYBOARD_REG_DATA); - while (ret == 0xfa); + while (ret == GRUB_AT_ACK); /* QEMU translates the set even in no-translate mode. */ if (ret == 0x43 || ret == 1) @@ -275,6 +286,7 @@ set_scancodes (void) knowledge. Assume XT. */ if (!grub_keyboard_orig_set) { + grub_dprintf ("atkeyb", "No sets support assumed\n"); current_set = 1; return; } @@ -284,11 +296,13 @@ set_scancodes (void) write_mode (2); current_set = query_mode (); + grub_dprintf ("atkeyb", "returned set %d\n", current_set); if (current_set == 2) return; write_mode (1); current_set = query_mode (); + grub_dprintf ("atkeyb", "returned set %d\n", current_set); if (current_set == 1) return; grub_printf ("No supported scancode set found\n"); @@ -334,7 +348,7 @@ fetch_key (int *is_break) } /* Setting LEDs may generate ACKs. */ - if (at_key == 0xfa) + if (at_key == GRUB_AT_ACK) return -1; was_ext = e0_received; @@ -540,8 +554,14 @@ grub_keyboard_controller_init (struct grub_term_input *term __attribute__ ((unus pending_key = -1; at_keyboard_status = 0; /* Drain input buffer. */ - while (KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS))) - grub_inb (KEYBOARD_REG_DATA); + while (1) + { + keyboard_controller_wait_until_ready (); + if (! KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS))) + break; + keyboard_controller_wait_until_ready (); + grub_inb (KEYBOARD_REG_DATA); + } grub_keyboard_controller_orig = grub_keyboard_controller_read (); set_scancodes (); keyboard_controller_led (led_status); From df2174ddedad2a1ae8d404476ae90069c3573adb Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 23 Aug 2010 12:07:49 +0200 Subject: [PATCH 059/214] Remove checkkey on term level --- include/grub/i386/pc/console.h | 1 - include/grub/term.h | 5 +-- include/grub/terminfo.h | 1 - kern/emu/console.c | 40 +++-------------------- kern/i386/pc/startup.S | 58 ++++++++-------------------------- kern/term.c | 21 +++++++++--- term/at_keyboard.c | 36 +-------------------- term/efi/console.c | 48 +++------------------------- term/i386/pc/console.c | 1 - term/ieee1275/ofconsole.c | 1 - term/serial.c | 1 - term/terminfo.c | 43 ++++++++++--------------- term/usb_keyboard.c | 49 +++++----------------------- 13 files changed, 65 insertions(+), 240 deletions(-) diff --git a/include/grub/i386/pc/console.h b/include/grub/i386/pc/console.h index fabb13d5c..1631a40ad 100644 --- a/include/grub/i386/pc/console.h +++ b/include/grub/i386/pc/console.h @@ -27,7 +27,6 @@ #include /* These are global to share code between C and asm. */ -int grub_console_checkkey (struct grub_term_input *term); int grub_console_getkey (struct grub_term_input *term); grub_uint16_t grub_console_getxy (struct grub_term_output *term); void grub_console_gotoxy (struct grub_term_output *term, diff --git a/include/grub/term.h b/include/grub/term.h index bfe1c8f9b..428978142 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -158,10 +158,7 @@ struct grub_term_input /* Clean up the terminal. */ grub_err_t (*fini) (struct grub_term_input *term); - /* Check if any input character is available. */ - int (*checkkey) (struct grub_term_input *term); - - /* Get a character. */ + /* Get a character if any input character is available. Otherwise return -1 */ int (*getkey) (struct grub_term_input *term); /* Get keyboard modifier status. */ diff --git a/include/grub/terminfo.h b/include/grub/terminfo.h index 85ddb5779..1962c71b7 100644 --- a/include/grub/terminfo.h +++ b/include/grub/terminfo.h @@ -64,7 +64,6 @@ void EXPORT_FUNC (grub_terminfo_setcolorstate) (struct grub_term_output *term, const grub_term_color_state state); -int EXPORT_FUNC (grub_terminfo_checkkey) (struct grub_term_input *term); grub_err_t EXPORT_FUNC (grub_terminfo_input_init) (struct grub_term_input *term); int EXPORT_FUNC (grub_terminfo_getkey) (struct grub_term_input *term); void EXPORT_FUNC (grub_terminfo_putchar) (struct grub_term_output *term, diff --git a/kern/emu/console.c b/kern/emu/console.c index f6b13b19b..0bf1e05f9 100644 --- a/kern/emu/console.c +++ b/kern/emu/console.c @@ -102,49 +102,18 @@ grub_ncurses_setcolorstate (struct grub_term_output *term, } } -static int saved_char = ERR; - -static int -grub_ncurses_checkkey (struct grub_term_input *term __attribute__ ((unused))) -{ - int c; - - /* Check for SAVED_CHAR. This should not be true, because this - means checkkey is called twice continuously. */ - if (saved_char != ERR) - return saved_char; - - wtimeout (stdscr, 100); - c = getch (); - /* If C is not ERR, then put it back in the input queue. */ - if (c != ERR) - { - saved_char = c; - return c; - } - - return -1; -} - static int grub_ncurses_getkey (struct grub_term_input *term __attribute__ ((unused))) { int c; - /* If checkkey has already got a character, then return it. */ - if (saved_char != ERR) - { - c = saved_char; - saved_char = ERR; - } - else - { - wtimeout (stdscr, -1); - c = getch (); - } + wtimeout (stdscr, 100); + c = getch (); switch (c) { + case ERR: + return -1; case KEY_LEFT: c = GRUB_TERM_LEFT; break; @@ -288,7 +257,6 @@ grub_ncurses_fini (struct grub_term_output *term __attribute__ ((unused))) static struct grub_term_input grub_ncurses_term_input = { .name = "console", - .checkkey = grub_ncurses_checkkey, .getkey = grub_ncurses_getkey, }; diff --git a/kern/i386/pc/startup.S b/kern/i386/pc/startup.S index f78fb5baa..2d7264156 100644 --- a/kern/i386/pc/startup.S +++ b/kern/i386/pc/startup.S @@ -1154,6 +1154,16 @@ LOCAL(bypass_table_end): /* * int grub_console_getkey (void) + * if there is a character pending, return it; otherwise return -1 + * BIOS call "INT 16H Function 01H" to check whether a character is pending + * Call with %ah = 0x1 + * Return: + * If key waiting to be input: + * %ah = keyboard scan code + * %al = ASCII character + * Zero flag = clear + * else + * Zero flag = set * BIOS call "INT 16H Function 00H" to read character from keyboard * Call with %ah = 0x0 * Return: %ah = keyboard scan code @@ -1173,14 +1183,9 @@ FUNCTION(grub_console_getkey) * INT 16/AH = 1 before calling INT 16/AH = 0. */ -1: movb $1, %ah int $0x16 - jnz 2f - hlt - jmp 1b - -2: + jz notpending movb $0, %ah int $0x16 @@ -1217,47 +1222,12 @@ FUNCTION(grub_console_getkey) popl %ebp ret -/* - * int grub_console_checkkey (void) - * if there is a character pending, return it; otherwise return -1 - * BIOS call "INT 16H Function 01H" to check whether a character is pending - * Call with %ah = 0x1 - * Return: - * If key waiting to be input: - * %ah = keyboard scan code - * %al = ASCII character - * Zero flag = clear - * else - * Zero flag = set - */ -FUNCTION(grub_console_checkkey) - pushl %ebp - xorl %edx, %edx - - call prot_to_real /* enter real mode */ +notpending: .code16 - - movb $0x1, %ah - int $0x16 - - jz notpending - - xorl %edx, %edx - movw %ax, %dx - DATA32 jmp pending - -notpending: - xorl %edx, %edx - decl %edx - -pending: DATA32 call real_to_prot .code32 - - movl %edx, %eax - - popl %ebp - ret + decl %eax + jmp 2b /* diff --git a/kern/term.c b/kern/term.c index 185626d36..a05325346 100644 --- a/kern/term.c +++ b/kern/term.c @@ -78,6 +78,8 @@ grub_xputs_dumb (const char *str) void (*grub_xputs) (const char *str) = grub_xputs_dumb; +static int pending_key = -1; + int grub_getkey (void) { @@ -85,6 +87,12 @@ grub_getkey (void) grub_refresh (); + if (pending_key != -1) + { + pending_key = -1; + return pending_key; + } + while (1) { if (grub_term_poll_usb) @@ -92,9 +100,9 @@ grub_getkey (void) FOR_ACTIVE_TERM_INPUTS(term) { - int key = term->checkkey (term); + int key = term->getkey (term); if (key != -1) - return term->getkey (term); + return key; } grub_cpu_idle (); @@ -106,14 +114,17 @@ grub_checkkey (void) { grub_term_input_t term; + if (pending_key != -1) + return pending_key; + if (grub_term_poll_usb) grub_term_poll_usb (); FOR_ACTIVE_TERM_INPUTS(term) { - int key = term->checkkey (term); - if (key != -1) - return key; + pending_key = term->getkey (term); + if (pending_key != -1) + return pending_key; } return -1; diff --git a/term/at_keyboard.c b/term/at_keyboard.c index e9db7834a..6ea908a2b 100644 --- a/term/at_keyboard.c +++ b/term/at_keyboard.c @@ -28,7 +28,6 @@ static short at_keyboard_status = 0; static int e0_received = 0; static int f0_received = 0; -static int pending_key = -1; static grub_uint8_t led_status; @@ -478,7 +477,7 @@ grub_keyboard_getkey (void) /* If there is a character pending, return it; otherwise return -1. */ static int -grub_at_keyboard_getkey_noblock (void) +grub_at_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused))) { int code; code = grub_keyboard_getkey (); @@ -517,41 +516,9 @@ grub_at_keyboard_getkey_noblock (void) } } -static int -grub_at_keyboard_checkkey (struct grub_term_input *term __attribute__ ((unused))) -{ - if (pending_key != -1) - return 1; - - pending_key = grub_at_keyboard_getkey_noblock (); - - if (pending_key != -1) - return 1; - - return -1; -} - -static int -grub_at_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused))) -{ - int key; - if (pending_key != -1) - { - key = pending_key; - pending_key = -1; - return key; - } - do - { - key = grub_at_keyboard_getkey_noblock (); - } while (key == -1); - return key; -} - static grub_err_t grub_keyboard_controller_init (struct grub_term_input *term __attribute__ ((unused))) { - pending_key = -1; at_keyboard_status = 0; /* Drain input buffer. */ while (1) @@ -583,7 +550,6 @@ static struct grub_term_input grub_at_keyboard_term = .name = "at_keyboard", .init = grub_keyboard_controller_init, .fini = grub_keyboard_controller_fini, - .checkkey = grub_at_keyboard_checkkey, .getkey = grub_at_keyboard_getkey }; diff --git a/term/efi/console.c b/term/efi/console.c index f47263ee4..97fefd981 100644 --- a/term/efi/console.c +++ b/term/efi/console.c @@ -28,8 +28,6 @@ static const grub_uint8_t grub_console_standard_color = GRUB_EFI_TEXT_ATTR (GRUB_EFI_YELLOW, GRUB_EFI_BACKGROUND_BLACK); -static int read_key = -1; - static grub_uint32_t map_char (grub_uint32_t c) { @@ -112,15 +110,12 @@ const unsigned efi_codes[] = static int -grub_console_checkkey (struct grub_term_input *term __attribute__ ((unused))) +grub_console_getkey (struct grub_term_input *term __attribute__ ((unused))) { grub_efi_simple_input_interface_t *i; grub_efi_input_key_t key; grub_efi_status_t status; - if (read_key >= 0) - return 1; - i = grub_efi_system_table->con_in; status = efi_call_2 (i->read_key_stroke, i, &key); @@ -128,45 +123,11 @@ grub_console_checkkey (struct grub_term_input *term __attribute__ ((unused))) return -1; if (key.scan_code == 0) - read_key = key.unicode_char; + return key.unicode_char; else if (key.scan_code < ARRAY_SIZE (efi_codes)) - read_key = efi_codes[key.scan_code]; + return efi_codes[key.scan_code]; - return read_key; -} - -static int -grub_console_getkey (struct grub_term_input *term) -{ - grub_efi_simple_input_interface_t *i; - grub_efi_boot_services_t *b; - grub_efi_uintn_t index; - grub_efi_status_t status; - int key; - - if (read_key >= 0) - { - key = read_key; - read_key = -1; - return key; - } - - i = grub_efi_system_table->con_in; - b = grub_efi_system_table->boot_services; - - do - { - status = efi_call_3 (b->wait_for_event, 1, &(i->wait_for_key), &index); - if (status != GRUB_EFI_SUCCESS) - return -1; - - grub_console_checkkey (term); - } - while (read_key < 0); - - key = read_key; - read_key = -1; - return key; + return -1; } static grub_uint16_t @@ -268,7 +229,6 @@ grub_efi_console_fini (struct grub_term_output *term) static struct grub_term_input grub_console_term_input = { .name = "console", - .checkkey = grub_console_checkkey, .getkey = grub_console_getkey, }; diff --git a/term/i386/pc/console.c b/term/i386/pc/console.c index 009647c4c..0efeafe4e 100644 --- a/term/i386/pc/console.c +++ b/term/i386/pc/console.c @@ -34,7 +34,6 @@ grub_console_getkeystatus (struct grub_term_input *term __attribute__ ((unused)) static struct grub_term_input grub_console_term_input = { .name = "console", - .checkkey = grub_console_checkkey, .getkey = grub_console_getkey, .getkeystatus = grub_console_getkeystatus }; diff --git a/term/ieee1275/ofconsole.c b/term/ieee1275/ofconsole.c index 604906ceb..e6550254f 100644 --- a/term/ieee1275/ofconsole.c +++ b/term/ieee1275/ofconsole.c @@ -189,7 +189,6 @@ static struct grub_term_input grub_ofconsole_term_input = { .name = "ofconsole", .init = grub_ofconsole_init_input, - .checkkey = grub_terminfo_checkkey, .getkey = grub_terminfo_getkey, .data = &grub_ofconsole_terminfo_input }; diff --git a/term/serial.c b/term/serial.c index 2268788af..f435a7bc5 100644 --- a/term/serial.c +++ b/term/serial.c @@ -99,7 +99,6 @@ static struct grub_term_input grub_serial_term_input = { .name = "serial", .init = grub_terminfo_input_init, - .checkkey = grub_terminfo_checkkey, .getkey = grub_terminfo_getkey, .data = &grub_serial_terminfo_input }; diff --git a/term/terminfo.c b/term/terminfo.c index 5379aac0c..d2d821449 100644 --- a/term/terminfo.c +++ b/term/terminfo.c @@ -467,39 +467,30 @@ grub_terminfo_readkey (struct grub_term_input *term, int *keys, int *len, #undef CONTINUE_READ } -/* The terminfo version of checkkey. */ -int -grub_terminfo_checkkey (struct grub_term_input *termi) -{ - struct grub_terminfo_input_state *data - = (struct grub_terminfo_input_state *) (termi->data); - if (data->npending) - return data->input_buf[0]; - - grub_terminfo_readkey (termi, data->input_buf, - &data->npending, data->readkey); - - if (data->npending) - return data->input_buf[0]; - - return -1; -} - /* The terminfo version of getkey. */ int grub_terminfo_getkey (struct grub_term_input *termi) { struct grub_terminfo_input_state *data = (struct grub_terminfo_input_state *) (termi->data); - int ret; - while (! data->npending) - grub_terminfo_readkey (termi, data->input_buf, &data->npending, - data->readkey); + if (data->npending) + { + data->npending--; + grub_memmove (data->input_buf, data->input_buf + 1, data->npending); + return data->input_buf[0]; + } - ret = data->input_buf[0]; - data->npending--; - grub_memmove (data->input_buf, data->input_buf + 1, data->npending); - return ret; + grub_terminfo_readkey (termi, data->input_buf, + &data->npending, data->readkey); + + if (data->npending) + { + data->npending--; + grub_memmove (data->input_buf, data->input_buf + 1, data->npending); + return data->input_buf[0]; + } + + return -1; } grub_err_t diff --git a/term/usb_keyboard.c b/term/usb_keyboard.c index b57b171f8..ca3a81179 100644 --- a/term/usb_keyboard.c +++ b/term/usb_keyboard.c @@ -68,7 +68,6 @@ struct grub_usb_keyboard_data grub_usb_device_t usbdev; grub_uint8_t status; grub_uint16_t mods; - int key; int interfno; struct grub_usb_desc_endp *endp; grub_usb_transfer_t transfer; @@ -78,15 +77,11 @@ struct grub_usb_keyboard_data grub_uint64_t repeat_time; }; -static struct grub_term_input grub_usb_keyboards[16]; - -static int grub_usb_keyboard_checkkey (struct grub_term_input *term); static int grub_usb_keyboard_getkey (struct grub_term_input *term); static int grub_usb_keyboard_getkeystatus (struct grub_term_input *term); static struct grub_term_input grub_usb_keyboard_term = { - .checkkey = grub_usb_keyboard_checkkey, .getkey = grub_usb_keyboard_getkey, .getkeystatus = grub_usb_keyboard_getkeystatus, .next = 0 @@ -231,19 +226,12 @@ grub_usb_keyboard_attach (grub_usb_device_t usbdev, int configno, int interfno) USB_HID_GET_REPORT, 0x0100, interfno, sizeof (report), (char *) report); if (err) - { - data->status = 0; - data->key = -1; - } + data->status = 0; else - { - data->status = report[0]; - data->key = report[2] ? : -1; - } + data->status = report[0]; } #else data->status = 0; - data->key = -1; #endif data->transfer = grub_usb_bulk_read_background (usbdev, @@ -283,16 +271,13 @@ send_leds (struct grub_usb_keyboard_data *termdata) } static int -grub_usb_keyboard_checkkey (struct grub_term_input *term) +grub_usb_keyboard_getkey (struct grub_term_input *term) { grub_usb_err_t err; struct grub_usb_keyboard_data *termdata = term->data; grub_uint8_t data[sizeof (termdata->report)]; grub_size_t actual; - if (termdata->key != -1) - return termdata->key; - if (termdata->dead) return -1; @@ -304,11 +289,11 @@ grub_usb_keyboard_checkkey (struct grub_term_input *term) if (termdata->last_key != -1 && grub_get_time_ms () > termdata->repeat_time) { - termdata->key = termdata->last_key; termdata->repeat_time = grub_get_time_ms () + GRUB_TERM_REPEAT_INTERVAL; + return termdata->last_key; } - return termdata->key; + return -1; } grub_memcpy (data, termdata->report, sizeof (data)); @@ -358,29 +343,13 @@ grub_usb_keyboard_checkkey (struct grub_term_input *term) return -1; } - termdata->last_key = termdata->key - = grub_term_map_key (data[2], interpret_status (data[0]) | termdata->mods); + termdata->last_key = grub_term_map_key (data[2], interpret_status (data[0]) + | termdata->mods); termdata->repeat_time = grub_get_time_ms () + GRUB_TERM_REPEAT_PRE_INTERVAL; grub_errno = GRUB_ERR_NONE; - return termdata->key; -} - -static int -grub_usb_keyboard_getkey (struct grub_term_input *term) -{ - int ret; - struct grub_usb_keyboard_data *termdata = term->data; - - while (termdata->key == -1) - grub_usb_keyboard_checkkey (term); - - ret = termdata->key; - - termdata->key = -1; - - return ret; + return termdata->last_key; } static int @@ -388,8 +357,6 @@ grub_usb_keyboard_getkeystatus (struct grub_term_input *term) { struct grub_usb_keyboard_data *termdata = term->data; - grub_usb_keyboard_checkkey (term); - return interpret_status (termdata->status) | termdata->mods; } From 9518e2a12bab434d0ba96df15773487f6adf0608 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 23 Aug 2010 12:53:42 +0200 Subject: [PATCH 060/214] Macroify GRUB_TERM_NO_KEY and use grub_checkkey in grub_getkey --- include/grub/term.h | 2 ++ kern/i386/pc/startup.S | 3 +++ kern/term.c | 50 +++++++++++++++--------------------------- term/at_keyboard.c | 11 +++++----- term/efi/console.c | 4 ++-- term/terminfo.c | 2 +- term/usb_keyboard.c | 14 ++++++------ 7 files changed, 39 insertions(+), 47 deletions(-) diff --git a/include/grub/term.h b/include/grub/term.h index 428978142..81c18365c 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -19,6 +19,8 @@ #ifndef GRUB_TERM_HEADER #define GRUB_TERM_HEADER 1 +#define GRUB_TERM_NO_KEY -1 + /* Internal codes used by GRUB to represent terminal input. */ /* Only for keys otherwise not having shifted modification. */ #define GRUB_TERM_SHIFT 0x01000000 diff --git a/kern/i386/pc/startup.S b/kern/i386/pc/startup.S index 2d7264156..5a6934dee 100644 --- a/kern/i386/pc/startup.S +++ b/kern/i386/pc/startup.S @@ -1226,6 +1226,9 @@ notpending: .code16 DATA32 call real_to_prot .code32 +#if GRUB_TERM_NO_KEY != -1 +#error Fix this asm code +#endif decl %eax jmp 2b diff --git a/kern/term.c b/kern/term.c index a05325346..9d23b4f91 100644 --- a/kern/term.c +++ b/kern/term.c @@ -78,43 +78,14 @@ grub_xputs_dumb (const char *str) void (*grub_xputs) (const char *str) = grub_xputs_dumb; -static int pending_key = -1; - -int -grub_getkey (void) -{ - grub_term_input_t term; - - grub_refresh (); - - if (pending_key != -1) - { - pending_key = -1; - return pending_key; - } - - while (1) - { - if (grub_term_poll_usb) - grub_term_poll_usb (); - - FOR_ACTIVE_TERM_INPUTS(term) - { - int key = term->getkey (term); - if (key != -1) - return key; - } - - grub_cpu_idle (); - } -} +static int pending_key = GRUB_TERM_NO_KEY; int grub_checkkey (void) { grub_term_input_t term; - if (pending_key != -1) + if (pending_key != GRUB_TERM_NO_KEY) return pending_key; if (grub_term_poll_usb) @@ -123,13 +94,28 @@ grub_checkkey (void) FOR_ACTIVE_TERM_INPUTS(term) { pending_key = term->getkey (term); - if (pending_key != -1) + if (pending_key != GRUB_TERM_NO_KEY) return pending_key; } return -1; } +int +grub_getkey (void) +{ + grub_refresh (); + + while (pending_key != GRUB_TERM_NO_KEY) + { + grub_cpu_idle (); + grub_checkkey (); + } + pending_key = GRUB_TERM_NO_KEY; + return pending_key; +} + + void grub_refresh (void) { diff --git a/term/at_keyboard.c b/term/at_keyboard.c index 6ea908a2b..681dd3ef9 100644 --- a/term/at_keyboard.c +++ b/term/at_keyboard.c @@ -475,14 +475,15 @@ grub_keyboard_getkey (void) return key; } -/* If there is a character pending, return it; otherwise return -1. */ +/* If there is a character pending, return it; + otherwise return GRUB_TERM_NO_KEY. */ static int grub_at_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused))) { int code; code = grub_keyboard_getkey (); if (code == -1) - return -1; + return GRUB_TERM_NO_KEY; #ifdef DEBUG_AT_KEYBOARD grub_dprintf ("atkeyb", "Detected key 0x%x\n", key); #endif @@ -496,7 +497,7 @@ grub_at_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused))) #ifdef DEBUG_AT_KEYBOARD grub_dprintf ("atkeyb", "caps_lock = %d\n", !!(at_keyboard_status & KEYBOARD_STATUS_CAPS_LOCK)); #endif - return -1; + return GRUB_TERM_NO_KEY; case GRUB_KEYBOARD_KEY_NUM_LOCK: at_keyboard_status ^= GRUB_TERM_STATUS_NUM; led_status ^= KEYBOARD_LED_NUM; @@ -505,12 +506,12 @@ grub_at_keyboard_getkey (struct grub_term_input *term __attribute__ ((unused))) #ifdef DEBUG_AT_KEYBOARD grub_dprintf ("atkeyb", "num_lock = %d\n", !!(at_keyboard_status & KEYBOARD_STATUS_NUM_LOCK)); #endif - return -1; + return GRUB_TERM_NO_KEY; case GRUB_KEYBOARD_KEY_SCROLL_LOCK: at_keyboard_status ^= GRUB_TERM_STATUS_SCROLL; led_status ^= KEYBOARD_LED_SCROLL; keyboard_controller_led (led_status); - return -1; + return GRUB_TERM_NO_KEY; default: return grub_term_map_key (code, at_keyboard_status); } diff --git a/term/efi/console.c b/term/efi/console.c index 97fefd981..1667bcd4f 100644 --- a/term/efi/console.c +++ b/term/efi/console.c @@ -120,14 +120,14 @@ grub_console_getkey (struct grub_term_input *term __attribute__ ((unused))) status = efi_call_2 (i->read_key_stroke, i, &key); if (status != GRUB_EFI_SUCCESS) - return -1; + return GRUB_TERM_NO_KEY; if (key.scan_code == 0) return key.unicode_char; else if (key.scan_code < ARRAY_SIZE (efi_codes)) return efi_codes[key.scan_code]; - return -1; + return GRUB_TERM_NO_KEY; } static grub_uint16_t diff --git a/term/terminfo.c b/term/terminfo.c index d2d821449..8dea7aea1 100644 --- a/term/terminfo.c +++ b/term/terminfo.c @@ -490,7 +490,7 @@ grub_terminfo_getkey (struct grub_term_input *termi) return data->input_buf[0]; } - return -1; + return GRUB_TERM_NO_KEY; } grub_err_t diff --git a/term/usb_keyboard.c b/term/usb_keyboard.c index ca3a81179..6b1485e96 100644 --- a/term/usb_keyboard.c +++ b/term/usb_keyboard.c @@ -279,7 +279,7 @@ grub_usb_keyboard_getkey (struct grub_term_input *term) grub_size_t actual; if (termdata->dead) - return -1; + return GRUB_TERM_NO_KEY; /* Poll interrupt pipe. */ err = grub_usb_check_transfer (termdata->transfer, &actual); @@ -293,7 +293,7 @@ grub_usb_keyboard_getkey (struct grub_term_input *term) + GRUB_TERM_REPEAT_INTERVAL; return termdata->last_key; } - return -1; + return GRUB_TERM_NO_KEY; } grub_memcpy (data, termdata->report, sizeof (data)); @@ -318,29 +318,29 @@ grub_usb_keyboard_getkey (struct grub_term_input *term) data[4], data[5], data[6], data[7]); if (err || actual < 1) - return -1; + return GRUB_TERM_NO_KEY; termdata->status = data[0]; if (actual < 3) - return -1; + return GRUB_TERM_NO_KEY; if (data[2] == KEY_NO_KEY || data[2] == KEY_ERR_BUFFER || data[2] == KEY_ERR_POST || data[2] == KEY_ERR_UNDEF) - return -1; + return GRUB_TERM_NO_KEY; if (data[2] == KEY_CAPS_LOCK) { termdata->mods ^= GRUB_TERM_STATUS_CAPS; send_leds (termdata); - return -1; + return GRUB_TERM_NO_KEY; } if (data[2] == KEY_NUM_LOCK) { termdata->mods ^= GRUB_TERM_STATUS_NUM; send_leds (termdata); - return -1; + return GRUB_TERM_NO_KEY; } termdata->last_key = grub_term_map_key (data[2], interpret_status (data[0]) From 071b673a7b50b59754841cf1c1f888c51d0a670e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 23 Aug 2010 13:12:29 +0200 Subject: [PATCH 061/214] Fix bugs in grub_getkey introduced in previous commit --- kern/term.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/kern/term.c b/kern/term.c index 9d23b4f91..7b3593161 100644 --- a/kern/term.c +++ b/kern/term.c @@ -104,15 +104,19 @@ grub_checkkey (void) int grub_getkey (void) { + int ret; + grub_refresh (); - while (pending_key != GRUB_TERM_NO_KEY) + grub_checkkey (); + while (pending_key == GRUB_TERM_NO_KEY) { grub_cpu_idle (); grub_checkkey (); } + ret = pending_key; pending_key = GRUB_TERM_NO_KEY; - return pending_key; + return ret; } From 9f5a5ad55a2593e89bb2278101fcaea8a35e61c1 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 23 Aug 2010 13:21:26 +0200 Subject: [PATCH 062/214] Fix RCTRL and RALT linux scancodes --- util/grub-mklayout.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/util/grub-mklayout.c b/util/grub-mklayout.c index e22888fc5..c07869eae 100644 --- a/util/grub-mklayout.c +++ b/util/grub-mklayout.c @@ -375,11 +375,11 @@ write_keymaps (FILE *in, FILE *out) /* Not remappable. */ if (keycode_linux == 0x1d /* Left CTRL */ - || keycode_linux == 0x9d /* Right CTRL */ + || keycode_linux == 0x61 /* Right CTRL */ || keycode_linux == 0x2a /* Left Shift. */ || keycode_linux == 0x36 /* Right Shift. */ || keycode_linux == 0x38 /* Left ALT. */ - || keycode_linux == 0xb8 /* Right ALT. */ + || keycode_linux == 0x64 /* Right ALT. */ || keycode_linux == 0x3a /* CapsLock. */ || keycode_linux == 0x45 /* NumLock. */ || keycode_linux == 0x46 /* ScrollLock. */) From 3ba3c4567e1edcb0a45e543f86e0683ec5b7057c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 23 Aug 2010 13:21:53 +0200 Subject: [PATCH 063/214] Change GRUB_TERM_NO_KEY to 0 --- include/grub/term.h | 2 +- kern/i386/pc/startup.S | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/include/grub/term.h b/include/grub/term.h index 81c18365c..dbcb2f52c 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -19,7 +19,7 @@ #ifndef GRUB_TERM_HEADER #define GRUB_TERM_HEADER 1 -#define GRUB_TERM_NO_KEY -1 +#define GRUB_TERM_NO_KEY 0 /* Internal codes used by GRUB to represent terminal input. */ /* Only for keys otherwise not having shifted modification. */ diff --git a/kern/i386/pc/startup.S b/kern/i386/pc/startup.S index 5a6934dee..f7a924fa8 100644 --- a/kern/i386/pc/startup.S +++ b/kern/i386/pc/startup.S @@ -1226,10 +1226,9 @@ notpending: .code16 DATA32 call real_to_prot .code32 -#if GRUB_TERM_NO_KEY != -1 +#if GRUB_TERM_NO_KEY != 0 #error Fix this asm code #endif - decl %eax jmp 2b From 400ef90dba295d1f3ed38c10020d34b3365bbcb1 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 23 Aug 2010 20:40:06 +0200 Subject: [PATCH 064/214] Fix reversal of NPAGE and PPAGE when handling Linux keymaps --- util/grub-mklayout.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/util/grub-mklayout.c b/util/grub-mklayout.c index c07869eae..ac59981c7 100644 --- a/util/grub-mklayout.c +++ b/util/grub-mklayout.c @@ -244,9 +244,9 @@ static grub_uint8_t linux_to_usb_map[128] = { /* 0x62 */ GRUB_KEYBOARD_KEY_NUMSLASH, 0, /* 0x64 */ GRUB_KEYBOARD_KEY_RIGHT_ALT, 0, /* 0x66 */ GRUB_KEYBOARD_KEY_HOME, GRUB_KEYBOARD_KEY_UP, - /* 0x68 */ GRUB_KEYBOARD_KEY_NPAGE, GRUB_KEYBOARD_KEY_LEFT, + /* 0x68 */ GRUB_KEYBOARD_KEY_PPAGE, GRUB_KEYBOARD_KEY_LEFT, /* 0x6a */ GRUB_KEYBOARD_KEY_RIGHT, GRUB_KEYBOARD_KEY_END, - /* 0x6c */ GRUB_KEYBOARD_KEY_DOWN, GRUB_KEYBOARD_KEY_PPAGE, + /* 0x6c */ GRUB_KEYBOARD_KEY_DOWN, GRUB_KEYBOARD_KEY_NPAGE, /* 0x6e */ GRUB_KEYBOARD_KEY_INSERT, GRUB_KEYBOARD_KEY_DELETE }; From f0b02c9c86daa78b3580e1de60986d1eea65f9d0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 23 Aug 2010 20:43:44 +0200 Subject: [PATCH 065/214] Handle ACKs, NACKs and restore state on booting --- include/grub/at_keyboard.h | 2 + term/at_keyboard.c | 115 +++++++++++++++++++++++++++---------- 2 files changed, 88 insertions(+), 29 deletions(-) diff --git a/include/grub/at_keyboard.h b/include/grub/at_keyboard.h index 3dfa0da80..65cf8a2a2 100644 --- a/include/grub/at_keyboard.h +++ b/include/grub/at_keyboard.h @@ -28,6 +28,8 @@ #define KEYBOARD_AT_TRANSLATE 0x40 #define GRUB_AT_ACK 0xfa +#define GRUB_AT_NACK 0xfe +#define GRUB_AT_TRIES 5 #define KEYBOARD_ISMAKE(x) !((x) & 0x80) #define KEYBOARD_ISREADY(x) ((x) & 0x01) diff --git a/term/at_keyboard.c b/term/at_keyboard.c index 681dd3ef9..1b130bd62 100644 --- a/term/at_keyboard.c +++ b/term/at_keyboard.c @@ -24,6 +24,7 @@ #include #include #include +#include static short at_keyboard_status = 0; static int e0_received = 0; @@ -215,39 +216,76 @@ keyboard_controller_wait_until_ready (void) while (! KEYBOARD_COMMAND_ISREADY (grub_inb (KEYBOARD_REG_STATUS))); } +static grub_uint8_t +wait_ack (void) +{ + grub_uint64_t endtime; + grub_uint8_t ack; + + endtime = grub_get_time_ms () + 20; + do + ack = grub_inb (KEYBOARD_REG_DATA); + while (ack != GRUB_AT_ACK && ack != GRUB_AT_NACK + && grub_get_time_ms () < endtime); + return ack; +} + +static int +at_command (grub_uint8_t data) +{ + unsigned i; + for (i = 0; i < GRUB_AT_TRIES; i++) + { + grub_uint8_t ack; + keyboard_controller_wait_until_ready (); + grub_outb (data, KEYBOARD_REG_STATUS); + ack = wait_ack (); + if (ack == GRUB_AT_NACK) + continue; + if (ack == GRUB_AT_ACK) + break; + return 0; + } + return (i != GRUB_AT_TRIES); +} + static void grub_keyboard_controller_write (grub_uint8_t c) { - keyboard_controller_wait_until_ready (); - grub_outb (KEYBOARD_COMMAND_WRITE, KEYBOARD_REG_STATUS); + at_command (KEYBOARD_COMMAND_WRITE); keyboard_controller_wait_until_ready (); grub_outb (c, KEYBOARD_REG_DATA); } -static int -wait_ack (void) +static grub_uint8_t +grub_keyboard_controller_read (void) { - grub_uint8_t ack; - grub_uint64_t endtime = grub_get_time_ms () + 20; - do - { - ack = grub_inb (KEYBOARD_REG_DATA); - } - while (ack != GRUB_AT_ACK && grub_get_time_ms () < endtime); - grub_dprintf ("atkeyb", "Ack 0x%02x\n", ack); - return ack == GRUB_AT_ACK; + at_command (KEYBOARD_COMMAND_READ); + keyboard_controller_wait_until_ready (); + return grub_inb (KEYBOARD_REG_DATA); } static int write_mode (int mode) { - keyboard_controller_wait_until_ready (); - grub_outb (0xf0, KEYBOARD_REG_DATA); - keyboard_controller_wait_until_ready (); - grub_outb (mode, KEYBOARD_REG_DATA); - keyboard_controller_wait_until_ready (); + unsigned i; + for (i = 0; i < GRUB_AT_TRIES; i++) + { + grub_uint8_t ack; + keyboard_controller_wait_until_ready (); + grub_outb (0xf0, KEYBOARD_REG_DATA); + keyboard_controller_wait_until_ready (); + grub_outb (mode, KEYBOARD_REG_DATA); + keyboard_controller_wait_until_ready (); + ack = wait_ack (); + if (ack == GRUB_AT_NACK) + continue; + if (ack == GRUB_AT_ACK) + break; + return 0; + } - return wait_ack (); + return (i != GRUB_AT_TRIES); } static int @@ -276,11 +314,9 @@ query_mode (void) return 0; } - static void set_scancodes (void) { - grub_keyboard_orig_set = query_mode (); /* You must have visited computer museum. Keyboard without scancode set knowledge. Assume XT. */ if (!grub_keyboard_orig_set) @@ -307,14 +343,6 @@ set_scancodes (void) grub_printf ("No supported scancode set found\n"); } -static grub_uint8_t -grub_keyboard_controller_read (void) -{ - keyboard_controller_wait_until_ready (); - grub_outb (KEYBOARD_COMMAND_READ, KEYBOARD_REG_STATUS); - return grub_inb (KEYBOARD_REG_DATA); -} - static void keyboard_controller_led (grub_uint8_t leds) { @@ -531,6 +559,7 @@ grub_keyboard_controller_init (struct grub_term_input *term __attribute__ ((unus grub_inb (KEYBOARD_REG_DATA); } grub_keyboard_controller_orig = grub_keyboard_controller_read (); + grub_keyboard_orig_set = query_mode (); set_scancodes (); keyboard_controller_led (led_status); @@ -546,6 +575,31 @@ grub_keyboard_controller_fini (struct grub_term_input *term __attribute__ ((unus return GRUB_ERR_NONE; } +static grub_err_t +grub_at_fini_hw (int noreturn __attribute__ ((unused))) +{ + return grub_keyboard_controller_fini (NULL); +} + +static grub_err_t +grub_at_restore_hw (void) +{ + /* Drain input buffer. */ + while (1) + { + keyboard_controller_wait_until_ready (); + if (! KEYBOARD_ISREADY (grub_inb (KEYBOARD_REG_STATUS))) + break; + keyboard_controller_wait_until_ready (); + grub_inb (KEYBOARD_REG_DATA); + } + set_scancodes (); + keyboard_controller_led (led_status); + + return GRUB_ERR_NONE; +} + + static struct grub_term_input grub_at_keyboard_term = { .name = "at_keyboard", @@ -557,9 +611,12 @@ static struct grub_term_input grub_at_keyboard_term = GRUB_MOD_INIT(at_keyboard) { grub_term_register_input ("at_keyboard", &grub_at_keyboard_term); + grub_loader_register_preboot_hook (grub_at_fini_hw, grub_at_restore_hw, + GRUB_LOADER_PREBOOT_HOOK_PRIO_CONSOLE); } GRUB_MOD_FINI(at_keyboard) { + grub_keyboard_controller_fini (NULL); grub_term_unregister_input (&grub_at_keyboard_term); } From 7c4425061d365271aee7c90aadbd2356b63cd73a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 23 Aug 2010 23:27:59 +0200 Subject: [PATCH 066/214] Don't reuse finished but not reclaimed QH --- bus/usb/uhci.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/bus/usb/uhci.c b/bus/usb/uhci.c index 472a7054e..b719051d6 100644 --- a/bus/usb/uhci.c +++ b/bus/usb/uhci.c @@ -28,6 +28,8 @@ #define GRUB_UHCI_IOMASK (0x7FF << 5) +#define N_QH 256 + typedef enum { GRUB_UHCI_REG_USBCMD = 0x00, @@ -99,7 +101,7 @@ struct grub_uhci int iobase; grub_uint32_t *framelist; - /* 256 Queue Heads. */ + /* N_QH Queue Heads. */ grub_uhci_qh_t qh; /* 256 Transfer Descriptors. */ @@ -108,6 +110,8 @@ struct grub_uhci /* Free Transfer Descriptors. */ grub_uhci_td_t tdfree; + int qh_busy[N_QH]; + struct grub_uhci *next; }; @@ -260,7 +264,7 @@ grub_uhci_pci_iter (grub_pci_device_t dev, (grub_uint32_t) u->framelist); /* Make the Queue Heads point to each other. */ - for (i = 0; i < 256; i++) + for (i = 0; i < N_QH; i++) { /* Point to the next QH. */ u->qh[i].linkptr = (grub_uint32_t) (&u->qh[i + 1]) & (~15); @@ -273,9 +277,8 @@ grub_uhci_pci_iter (grub_pci_device_t dev, u->qh[i].elinkptr = 1; } - /* The last Queue Head should terminate. 256 are too many QHs so - just use 50. */ - u->qh[50 - 1].linkptr = 1; + /* The last Queue Head should terminate. */ + u->qh[N_QH - 1].linkptr = 1; /* Enable UHCI again. */ grub_uhci_writereg16 (u, GRUB_UHCI_REG_USBCMD, 1 | (1 << 7)); @@ -344,11 +347,13 @@ grub_free_td (struct grub_uhci *u, grub_uhci_td_t td) } static void -grub_free_queue (struct grub_uhci *u, grub_uhci_td_t td, +grub_free_queue (struct grub_uhci *u, grub_uhci_qh_t qh, grub_uhci_td_t td, grub_usb_transfer_t transfer, grub_size_t *actual) { int i; /* Index of TD in transfer */ + u->qh_busy[qh - u->qh] = 0; + *actual = 0; /* Free the TDs in this queue and set last_trans. */ @@ -387,19 +392,21 @@ grub_alloc_qh (struct grub_uhci *u, #endif i = 1; - for (; i < 255; i++) + for (; i < N_QH; i++) { - if (u->qh[i].elinkptr & 1) + if (!u->qh_busy[i]) break; } qh = &u->qh[i]; - if (! (qh->elinkptr & 1)) + if (i == N_QH) { grub_error (GRUB_ERR_OUT_OF_MEMORY, "no free queue heads available"); return NULL; } + u->qh_busy[qh - u->qh] = 1; + return qh; } @@ -497,7 +504,7 @@ grub_uhci_setup_transfer (grub_usb_controller_t dev, td_prev->linkptr = 1; if (cdata->td_first) - grub_free_queue (u, cdata->td_first, NULL, &actual); + grub_free_queue (u, cdata->qh, cdata->td_first, NULL, &actual); grub_free (cdata); return GRUB_USB_ERR_INTERNAL; @@ -553,7 +560,7 @@ grub_uhci_check_transfer (grub_usb_controller_t dev, /* Place the QH back in the free list and deallocate the associated TDs. */ cdata->qh->elinkptr = 1; - grub_free_queue (u, cdata->td_first, transfer, actual); + grub_free_queue (u, cdata->qh, cdata->td_first, transfer, actual); grub_free (cdata); return GRUB_USB_ERR_NONE; } @@ -595,7 +602,7 @@ grub_uhci_check_transfer (grub_usb_controller_t dev, /* Place the QH back in the free list and deallocate the associated TDs. */ cdata->qh->elinkptr = 1; - grub_free_queue (u, cdata->td_first, transfer, actual); + grub_free_queue (u, cdata->qh, cdata->td_first, transfer, actual); grub_free (cdata); return err; @@ -622,7 +629,7 @@ grub_uhci_cancel_transfer (grub_usb_controller_t dev, /* Place the QH back in the free list and deallocate the associated TDs. */ cdata->qh->elinkptr = 1; - grub_free_queue (u, cdata->td_first, transfer, &actual); + grub_free_queue (u, cdata->qh, cdata->td_first, transfer, &actual); grub_free (cdata); return GRUB_USB_ERR_NONE; From a98f88ecfeee316f6cdcb4df1002d66029103886 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 23 Aug 2010 23:28:33 +0200 Subject: [PATCH 067/214] Add pot powered flag declaration --- include/grub/usbtrans.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/grub/usbtrans.h b/include/grub/usbtrans.h index 9e9d75e5d..5ee276d26 100644 --- a/include/grub/usbtrans.h +++ b/include/grub/usbtrans.h @@ -130,6 +130,7 @@ enum GRUB_USB_HUB_STATUS_PORT_ENABLED = (1 << 1), GRUB_USB_HUB_STATUS_PORT_SUSPEND = (1 << 2), GRUB_USB_HUB_STATUS_PORT_OVERCURRENT = (1 << 3), + GRUB_USB_HUB_STATUS_PORT_POWERED = (1 << 8), GRUB_USB_HUB_STATUS_PORT_LOWSPEED = (1 << 9), GRUB_USB_HUB_STATUS_PORT_HIGHSPEED = (1 << 10), GRUB_USB_HUB_STATUS_C_PORT_CONNECTED = (1 << 16), From ea9ed87faa8d90d112b2e648046c5a2b0cd27a00 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 27 Aug 2010 18:52:17 +0200 Subject: [PATCH 068/214] add help descriptions to legacy commands --- commands/legacycfg.c | 168 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 137 insertions(+), 31 deletions(-) diff --git a/commands/legacycfg.c b/commands/legacycfg.c index 8077497f3..10e897226 100644 --- a/commands/legacycfg.c +++ b/commands/legacycfg.c @@ -48,65 +48,166 @@ struct legacy_command enum { FLAG_IGNORE_REST = 1 } flags; + const char *shortdesc; + const char *longdesc; }; struct legacy_command legacy_commands[] = { - {"blocklist", "blocklist '%s'\n", 1, {TYPE_FILE}, 0}, - {"boot", "boot\n", 0, {}, 0}, + {"blocklist", "blocklist '%s'\n", 1, {TYPE_FILE}, 0, "FILE", + "Print the blocklist notation of the file FILE." + }, + {"boot", "boot\n", 0, {}, 0, 0, + "Boot the OS/chain-loader which has been loaded."}, /* bootp unsupported. */ - {"cat", "cat '%s'\n", 1, {TYPE_FILE}, 0}, + {"cat", "cat '%s'\n", 1, {TYPE_FILE}, 0, "FILE", + "Print the contents of the file FILE."}, {"chainloader", "chainloader %s '%s'\n", 2, {TYPE_FORCE_OPTION, TYPE_FILE}, - 0}, - {"cmp", "cmp '%s' '%s'\n", 2, {TYPE_FILE, TYPE_FILE}, FLAG_IGNORE_REST}, + 0, "[--force] FILE", + "Load the chain-loader FILE. If --force is specified, then load it" + " forcibly, whether the boot loader signature is present or not."}, + {"cmp", "cmp '%s' '%s'\n", 2, {TYPE_FILE, TYPE_FILE}, FLAG_IGNORE_REST, + "FILE1 FILE2", + "Compare the file FILE1 with the FILE2 and inform the different values" + " if any."}, /* FIXME: Implement command. */ {"color", "legacy_color '%s' '%s'\n", 2, {TYPE_VERBATIM, TYPE_VERBATIM}, - FLAG_IGNORE_REST}, - {"configfile", "legacy_configfile '%s'\n", 1, {TYPE_FILE}, 0}, + FLAG_IGNORE_REST, "NORMAL [HIGHLIGHT]", + "Change the menu colors. The color NORMAL is used for most" + " lines in the menu, and the color HIGHLIGHT is used to highlight the" + " line where the cursor points. If you omit HIGHLIGHT, then the" + " inverted color of NORMAL is used for the highlighted line." + " The format of a color is \"FG/BG\". FG and BG are symbolic color names." + " A symbolic color name must be one of these: black, blue, green," + " cyan, red, magenta, brown, light-gray, dark-gray, light-blue," + " light-green, light-cyan, light-red, light-magenta, yellow and white." + " But only the first eight names can be used for BG. You can prefix" + " \"blink-\" to FG if you want a blinking foreground color."}, + {"configfile", "legacy_configfile '%s'\n", 1, {TYPE_FILE}, 0, "FILE", + "Load FILE as the configuration file."}, {"debug", "if [ -z \"$debug\" ]; then set debug=all; else set debug=; fi\n", - 0, {}, 0}, - {"default", "set default='%s'; if [ x\"$default\" = xsaved ]; then load_env; set default=\"$saved_entry\"; fi\n", 1, {TYPE_VERBATIM}, 0}, + 0, {}, 0, 0, "Turn on/off the debug mode."}, + {"default", + "set default='%s'; if [ x\"$default\" = xsaved ]; then load_env; " + "set default=\"$saved_entry\"; fi\n", 1, {TYPE_VERBATIM}, 0, + "[NUM | `saved']", + "Set the default entry to entry number NUM (if not specified, it is" + " 0, the first entry) or the entry number saved by savedefault."}, /* dhcp unsupported. */ /* displayapm unsupported. */ - {"displaymem", "lsmmap\n", 0, {}, 0}, + {"displaymem", "lsmmap\n", 0, {}, 0, 0, + "Display what GRUB thinks the system address space map of the" + " machine is, including all regions of physical RAM installed."}, /* embed unsupported. */ - {"fallback", "set fallback='%s'\n", 1, {TYPE_VERBATIM}, 0}, - {"find", "search -f '%s'\n", 1, {TYPE_FILE}, 0}, + {"fallback", "set fallback='%s'\n", 1, {TYPE_VERBATIM}, 0, "NUM...", + "Go into unattended boot mode: if the default boot entry has any" + " errors, instead of waiting for the user to do anything, it" + " immediately starts over using the NUM entry (same numbering as the" + " `default' command). This obviously won't help if the machine" + " was rebooted by a kernel that GRUB loaded."}, + {"find", "search -f '%s'\n", 1, {TYPE_FILE}, 0, "FILENAME", + "Search for the filename FILENAME in all of partitions and print the list of" + " the devices which contain the file."}, /* fstest unsupported. */ /* geometry unsupported. */ - {"halt", "halt %s\n", 1, {TYPE_NOAPM_OPTION}, 0}, + {"halt", "halt %s\n", 1, {TYPE_NOAPM_OPTION}, 0, "[--no-apm]", + "Halt your system. If APM is available on it, turn off the power using" + " the APM BIOS, unless you specify the option `--no-apm'."}, /* help unsupported. */ /* NUL_TERMINATE */ /* hiddenmenu unsupported. */ - {"hide", "parttool '%s' hidden+\n", 1, {TYPE_PARTITION}, 0}, + {"hide", "parttool '%s' hidden+\n", 1, {TYPE_PARTITION}, 0, "PARTITION", + "Hide PARTITION by setting the \"hidden\" bit in" + " its partition type code."}, /* ifconfig unsupported. */ /* impsprobe unsupported. */ /* FIXME: Implement command. */ - {"initrd", "legacy_initrd '%s'\n", 1, {TYPE_FILE}, 0}, + {"initrd", "legacy_initrd '%s' %s\n", 2, {TYPE_FILE, TYPE_REST_VERBATIM}, 0, + "FILE [ARG ...]", + "Load an initial ramdisk FILE for a Linux format boot image and set the" + " appropriate parameters in the Linux setup area in memory."}, /* install unsupported. */ /* ioprobe unsupported. */ /* FIXME: implement command. */ - {"kernel", "legacy_kernel %s '%s' %s\n", 3, {TYPE_TYPE_OPTION, TYPE_FILE, - TYPE_REST_VERBATIM}, 0}, + {"kernel", "legacy_kernel %s '%s' %s\n", 4, {TYPE_TYPE_OR_NOMEM_OPTION, + TYPE_TYPE_OR_NOMEM_OPTION, + TYPE_FILE, + TYPE_REST_VERBATIM}, 0, + "[--no-mem-option] [--type=TYPE] FILE [ARG ...]", + "Attempt to load the primary boot image from FILE. The rest of the" + " line is passed verbatim as the \"kernel command line\". Any modules" + " must be reloaded after using this command. The option --type is used" + " to suggest what type of kernel to be loaded. TYPE must be either of" + " \"netbsd\", \"freebsd\", \"openbsd\", \"linux\", \"biglinux\" and" + " \"multiboot\". The option --no-mem-option tells GRUB not to pass a" + " Linux's mem option automatically."}, /* lock is handled separately. */ - {"makeactive", "parttool \"$root\" boot+\n", 0, {}, 0}, + {"makeactive", "parttool \"$root\" boot+\n", 0, {}, 0, 0 + "Set the active partition on the root disk to GRUB's root device." + " This command is limited to _primary_ PC partitions on a hard disk."}, {"map", "drivemap '%s' '%s'\n", 2, {TYPE_PARTITION, TYPE_PARTITION}, - FLAG_IGNORE_REST}, + FLAG_IGNORE_REST, "TO_DRIVE FROM_DRIVE", + "Map the drive FROM_DRIVE to the drive TO_DRIVE. This is necessary" + " when you chain-load some operating systems, such as DOS, if such an" + " OS resides at a non-first drive."}, /* md5crypt unsupported. */ - {"module", "legacy_initrd '%s'\n", 1, {TYPE_FILE}, 0}, + {"module", "legacy_initrd '%s' %s\n", 1, {TYPE_FILE, TYPE_REST_VERBATIM}, 0, + "FILE [ARG ...]", + "Load a boot module FILE for a Multiboot format boot image (no" + " interpretation of the file contents is made, so users of this" + " command must know what the kernel in question expects). The" + " rest of the line is passed as the \"module command line\", like" + " the `kernel' command."}, /* modulenounzip unsupported. */ - {"pager", "set pager=%d\n", 1, {TYPE_BOOL}, 0}, + /* FIXME: allow toggle. */ + {"pager", "set pager=%d\n", 1, {TYPE_BOOL}, 0, "[FLAG]", + "Toggle pager mode with no argument. If FLAG is given and its value" + " is `on', turn on the mode. If FLAG is `off', turn off the mode."}, /* partnew unsupported. */ - {"parttype", "parttool '%s' type=%s\n", 2, {TYPE_PARTITION, TYPE_INT}, 0}, + {"parttype", "parttool '%s' type=%s\n", 2, {TYPE_PARTITION, TYPE_INT}, 0, + "PART TYPE", "Change the type of the partition PART to TYPE."}, /* password unsupported. */ /* NUL_TERMINATE */ /* pause unsupported. */ /* rarp unsupported. */ - {"read", "read_dword %s\n", 1, {TYPE_INT}, 0}, - {"reboot", "reboot\n", 0, {}, 0}, - {"root", "set root='%s'\n", 1, {TYPE_PARTITION}, 0}, - {"rootnoverify", "set root='%s'\n", 1, {TYPE_PARTITION}, 0}, - {"savedefault", "saved_entry=${chosen}; save_env saved_entry\n", 0, {}, 0}, - {"serial", "serial %s\n", 1, {TYPE_REST_VERBATIM}, 0}, + {"read", "read_dword %s\n", 1, {TYPE_INT}, 0, "ADDR", + "Read a 32-bit value from memory at address ADDR and" + " display it in hex format."}, + {"reboot", "reboot\n", 0, {}, 0, 0, "Reboot your system."}, + /* FIXME: Support HDBIAS. */ + {"root", "set root='%s'\n", 1, {TYPE_PARTITION}, 0, "[DEVICE [HDBIAS]]", + "Set the current \"root device\" to the device DEVICE, then" + " attempt to mount it to get the partition size (for passing the" + " partition descriptor in `ES:ESI', used by some chain-loaded" + " bootloaders), the BSD drive-type (for booting BSD kernels using" + " their native boot format), and correctly determine " + " the PC partition where a BSD sub-partition is located. The" + " optional HDBIAS parameter is a number to tell a BSD kernel" + " how many BIOS drive numbers are on controllers before the current" + " one. For example, if there is an IDE disk and a SCSI disk, and your" + " FreeBSD root partition is on the SCSI disk, then use a `1' for HDBIAS."}, + {"rootnoverify", "set root='%s'\n", 1, {TYPE_PARTITION}, 0, + "[DEVICE [HDBIAS]]", + "Similar to `root', but don't attempt to mount the partition. This" + " is useful for when an OS is outside of the area of the disk that" + " GRUB can read, but setting the correct root device is still" + " desired. Note that the items mentioned in `root' which" + " derived from attempting the mount will NOT work correctly."}, + /* FIXME: support arguments. */ + {"savedefault", "saved_entry=${chosen}; save_env saved_entry\n", 0, {}, 0, + "[NUM | `fallback']", + "Save the current entry as the default boot entry if no argument is" + " specified. If a number is specified, this number is saved. If" + " `fallback' is used, next fallback entry is saved."}, + {"serial", "serial %s\n", 1, {TYPE_REST_VERBATIM}, 0, + "[--unit=UNIT] [--port=PORT] [--speed=SPEED] [--word=WORD] " + "[--parity=PARITY] [--stop=STOP] [--device=DEV]", + "Initialize a serial device. UNIT is a digit that specifies which serial" + " device is used (e.g. 0 == COM1). If you need to specify the port number," + " set it by --port. SPEED is the DTE-DTE speed. WORD is the word length," + " PARITY is the type of parity, which is one of `no', `odd' and `even'." + " STOP is the length of stop bit(s). The option --device can be used only" + " in the grub shell, which specifies the file name of a tty device. The" + " default values are COM1, 9600, 8N1."}, /* setkey unsupported. */ /* NUL_TERMINATE */ /* setup unsupported. */ /* terminal unsupported. */ /* NUL_TERMINATE */ @@ -114,11 +215,16 @@ struct legacy_command legacy_commands[] = /* testload unsupported. */ /* testvbe unsupported. */ /* tftpserver unsupported. */ - {"timeout", "set timeout=%s\n", 1, {TYPE_INT}, 0}, + {"timeout", "set timeout=%s\n", 1, {TYPE_INT}, 0, "SEC", + "Set a timeout, in SEC seconds, before automatically booting the" + " default entry (normally the first entry defined)."}, /* title is handled separately. */ - {"unhide", "parttool '%s' hidden-\n", 1, {TYPE_PARTITION}, 0}, + {"unhide", "parttool '%s' hidden-\n", 1, {TYPE_PARTITION}, 0, "PARTITION", + "Unhide PARTITION by clearing the \"hidden\" bit in its" + " partition type code."}, /* uppermem unsupported. */ - {"uuid", "search -u '%s'\n", 1, {TYPE_VERBATIM}, 0}, + {"uuid", "search -u '%s'\n", 1, {TYPE_VERBATIM}, 0, "UUID", + "Find root by UUID"}, /* vbeprobe unsupported. */ }; From fff175c77f6490ace62df776660c7c75ea526775 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 27 Aug 2010 20:04:49 +0200 Subject: [PATCH 069/214] Implement grub-menulst2cfg and fix many bugs in legacy_parser --- Makefile.util.def | 9 + grub-core/Makefile.core.def | 3 +- grub-core/commands/legacycfg.c | 470 +------------------------------ grub-core/lib/legacy_parse.c | 496 +++++++++++++++++++++++++++++++++ include/grub/legacy_parse.h | 27 ++ util/grub-menulst2cfg.c | 99 +++++++ 6 files changed, 636 insertions(+), 468 deletions(-) create mode 100644 grub-core/lib/legacy_parse.c create mode 100644 include/grub/legacy_parse.h create mode 100644 util/grub-menulst2cfg.c diff --git a/Makefile.util.def b/Makefile.util.def index fd3428e76..b4f9fc60e 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -508,3 +508,12 @@ program = { ldadd = libgrub.a; ldflags = '$(LIBDEVMAPPER)'; }; + +program = { + name = grub-menulst2cfg; + mansection = 1; + common = util/grub-menulst2cfg.c; + common = grub-core/lib/legacy_parse.c; + ldadd = libgrub.a; + ldflags = '$(LIBDEVMAPPER)'; +}; diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 5ddb99fa6..0ca28eb19 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1407,5 +1407,6 @@ module = { module = { name = legacycfg; common = commands/legacycfg.c; + common = lib/legacy_parse.c; enable = i386_pc; -}; \ No newline at end of file +}; diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c index 772f48c15..4207531ec 100644 --- a/grub-core/commands/legacycfg.c +++ b/grub-core/commands/legacycfg.c @@ -28,472 +28,7 @@ #include #include #include - -struct legacy_command -{ - const char *name; - const char *map; - unsigned argc; - enum arg_type { - TYPE_VERBATIM, - TYPE_FORCE_OPTION, - TYPE_NOAPM_OPTION, - TYPE_TYPE_OR_NOMEM_OPTION, - TYPE_FILE, - TYPE_PARTITION, - TYPE_BOOL, - TYPE_INT, - TYPE_REST_VERBATIM - } argt[4]; - enum { - FLAG_IGNORE_REST = 1 - } flags; - const char *shortdesc; - const char *longdesc; -}; - -struct legacy_command legacy_commands[] = - { - {"blocklist", "blocklist '%s'\n", 1, {TYPE_FILE}, 0, "FILE", - "Print the blocklist notation of the file FILE." - }, - {"boot", "boot\n", 0, {}, 0, 0, - "Boot the OS/chain-loader which has been loaded."}, - /* bootp unsupported. */ - {"cat", "cat '%s'\n", 1, {TYPE_FILE}, 0, "FILE", - "Print the contents of the file FILE."}, - {"chainloader", "chainloader %s '%s'\n", 2, {TYPE_FORCE_OPTION, TYPE_FILE}, - 0, "[--force] FILE", - "Load the chain-loader FILE. If --force is specified, then load it" - " forcibly, whether the boot loader signature is present or not."}, - {"cmp", "cmp '%s' '%s'\n", 2, {TYPE_FILE, TYPE_FILE}, FLAG_IGNORE_REST, - "FILE1 FILE2", - "Compare the file FILE1 with the FILE2 and inform the different values" - " if any."}, - /* FIXME: Implement command. */ - {"color", "legacy_color '%s' '%s'\n", 2, {TYPE_VERBATIM, TYPE_VERBATIM}, - FLAG_IGNORE_REST, "NORMAL [HIGHLIGHT]", - "Change the menu colors. The color NORMAL is used for most" - " lines in the menu, and the color HIGHLIGHT is used to highlight the" - " line where the cursor points. If you omit HIGHLIGHT, then the" - " inverted color of NORMAL is used for the highlighted line." - " The format of a color is \"FG/BG\". FG and BG are symbolic color names." - " A symbolic color name must be one of these: black, blue, green," - " cyan, red, magenta, brown, light-gray, dark-gray, light-blue," - " light-green, light-cyan, light-red, light-magenta, yellow and white." - " But only the first eight names can be used for BG. You can prefix" - " \"blink-\" to FG if you want a blinking foreground color."}, - {"configfile", "legacy_configfile '%s'\n", 1, {TYPE_FILE}, 0, "FILE", - "Load FILE as the configuration file."}, - {"debug", - "if [ -z \"$debug\" ]; then set debug=all; else set debug=; fi\n", - 0, {}, 0, 0, "Turn on/off the debug mode."}, - {"default", - "set default='%s'; if [ x\"$default\" = xsaved ]; then load_env; " - "set default=\"$saved_entry\"; fi\n", 1, {TYPE_VERBATIM}, 0, - "[NUM | `saved']", - "Set the default entry to entry number NUM (if not specified, it is" - " 0, the first entry) or the entry number saved by savedefault."}, - /* dhcp unsupported. */ - /* displayapm unsupported. */ - {"displaymem", "lsmmap\n", 0, {}, 0, 0, - "Display what GRUB thinks the system address space map of the" - " machine is, including all regions of physical RAM installed."}, - /* embed unsupported. */ - {"fallback", "set fallback='%s'\n", 1, {TYPE_VERBATIM}, 0, "NUM...", - "Go into unattended boot mode: if the default boot entry has any" - " errors, instead of waiting for the user to do anything, it" - " immediately starts over using the NUM entry (same numbering as the" - " `default' command). This obviously won't help if the machine" - " was rebooted by a kernel that GRUB loaded."}, - {"find", "search -f '%s'\n", 1, {TYPE_FILE}, 0, "FILENAME", - "Search for the filename FILENAME in all of partitions and print the list of" - " the devices which contain the file."}, - /* fstest unsupported. */ - /* geometry unsupported. */ - {"halt", "halt %s\n", 1, {TYPE_NOAPM_OPTION}, 0, "[--no-apm]", - "Halt your system. If APM is available on it, turn off the power using" - " the APM BIOS, unless you specify the option `--no-apm'."}, - /* help unsupported. */ /* NUL_TERMINATE */ - /* hiddenmenu unsupported. */ - {"hide", "parttool '%s' hidden+\n", 1, {TYPE_PARTITION}, 0, "PARTITION", - "Hide PARTITION by setting the \"hidden\" bit in" - " its partition type code."}, - /* ifconfig unsupported. */ - /* impsprobe unsupported. */ - /* FIXME: Implement command. */ - {"initrd", "legacy_initrd '%s' %s\n", 2, {TYPE_FILE, TYPE_REST_VERBATIM}, 0, - "FILE [ARG ...]", - "Load an initial ramdisk FILE for a Linux format boot image and set the" - " appropriate parameters in the Linux setup area in memory."}, - /* install unsupported. */ - /* ioprobe unsupported. */ - /* FIXME: implement command. */ - {"kernel", "legacy_kernel %s '%s' %s\n", 4, {TYPE_TYPE_OR_NOMEM_OPTION, - TYPE_TYPE_OR_NOMEM_OPTION, - TYPE_FILE, - TYPE_REST_VERBATIM}, 0, - "[--no-mem-option] [--type=TYPE] FILE [ARG ...]", - "Attempt to load the primary boot image from FILE. The rest of the" - " line is passed verbatim as the \"kernel command line\". Any modules" - " must be reloaded after using this command. The option --type is used" - " to suggest what type of kernel to be loaded. TYPE must be either of" - " \"netbsd\", \"freebsd\", \"openbsd\", \"linux\", \"biglinux\" and" - " \"multiboot\". The option --no-mem-option tells GRUB not to pass a" - " Linux's mem option automatically."}, - /* lock is handled separately. */ - {"makeactive", "parttool \"$root\" boot+\n", 0, {}, 0, 0, - "Set the active partition on the root disk to GRUB's root device." - " This command is limited to _primary_ PC partitions on a hard disk."}, - {"map", "drivemap '%s' '%s'\n", 2, {TYPE_PARTITION, TYPE_PARTITION}, - FLAG_IGNORE_REST, "TO_DRIVE FROM_DRIVE", - "Map the drive FROM_DRIVE to the drive TO_DRIVE. This is necessary" - " when you chain-load some operating systems, such as DOS, if such an" - " OS resides at a non-first drive."}, - /* md5crypt unsupported. */ - {"module", "legacy_initrd '%s' %s\n", 1, {TYPE_FILE, TYPE_REST_VERBATIM}, 0, - "FILE [ARG ...]", - "Load a boot module FILE for a Multiboot format boot image (no" - " interpretation of the file contents is made, so users of this" - " command must know what the kernel in question expects). The" - " rest of the line is passed as the \"module command line\", like" - " the `kernel' command."}, - /* modulenounzip unsupported. */ - /* FIXME: allow toggle. */ - {"pager", "set pager=%d\n", 1, {TYPE_BOOL}, 0, "[FLAG]", - "Toggle pager mode with no argument. If FLAG is given and its value" - " is `on', turn on the mode. If FLAG is `off', turn off the mode."}, - /* partnew unsupported. */ - {"parttype", "parttool '%s' type=%s\n", 2, {TYPE_PARTITION, TYPE_INT}, 0, - "PART TYPE", "Change the type of the partition PART to TYPE."}, - /* password unsupported. */ /* NUL_TERMINATE */ - /* pause unsupported. */ - /* rarp unsupported. */ - {"read", "read_dword %s\n", 1, {TYPE_INT}, 0, "ADDR", - "Read a 32-bit value from memory at address ADDR and" - " display it in hex format."}, - {"reboot", "reboot\n", 0, {}, 0, 0, "Reboot your system."}, - /* FIXME: Support HDBIAS. */ - {"root", "set root='%s'\n", 1, {TYPE_PARTITION}, 0, "[DEVICE [HDBIAS]]", - "Set the current \"root device\" to the device DEVICE, then" - " attempt to mount it to get the partition size (for passing the" - " partition descriptor in `ES:ESI', used by some chain-loaded" - " bootloaders), the BSD drive-type (for booting BSD kernels using" - " their native boot format), and correctly determine " - " the PC partition where a BSD sub-partition is located. The" - " optional HDBIAS parameter is a number to tell a BSD kernel" - " how many BIOS drive numbers are on controllers before the current" - " one. For example, if there is an IDE disk and a SCSI disk, and your" - " FreeBSD root partition is on the SCSI disk, then use a `1' for HDBIAS."}, - {"rootnoverify", "set root='%s'\n", 1, {TYPE_PARTITION}, 0, - "[DEVICE [HDBIAS]]", - "Similar to `root', but don't attempt to mount the partition. This" - " is useful for when an OS is outside of the area of the disk that" - " GRUB can read, but setting the correct root device is still" - " desired. Note that the items mentioned in `root' which" - " derived from attempting the mount will NOT work correctly."}, - /* FIXME: support arguments. */ - {"savedefault", "saved_entry=${chosen}; save_env saved_entry\n", 0, {}, 0, - "[NUM | `fallback']", - "Save the current entry as the default boot entry if no argument is" - " specified. If a number is specified, this number is saved. If" - " `fallback' is used, next fallback entry is saved."}, - {"serial", "serial %s\n", 1, {TYPE_REST_VERBATIM}, 0, - "[--unit=UNIT] [--port=PORT] [--speed=SPEED] [--word=WORD] " - "[--parity=PARITY] [--stop=STOP] [--device=DEV]", - "Initialize a serial device. UNIT is a digit that specifies which serial" - " device is used (e.g. 0 == COM1). If you need to specify the port number," - " set it by --port. SPEED is the DTE-DTE speed. WORD is the word length," - " PARITY is the type of parity, which is one of `no', `odd' and `even'." - " STOP is the length of stop bit(s). The option --device can be used only" - " in the grub shell, which specifies the file name of a tty device. The" - " default values are COM1, 9600, 8N1."}, - /* setkey unsupported. */ /* NUL_TERMINATE */ - /* setup unsupported. */ - /* terminal unsupported. */ /* NUL_TERMINATE */ - /* terminfo unsupported. */ /* NUL_TERMINATE */ - /* testload unsupported. */ - /* testvbe unsupported. */ - /* tftpserver unsupported. */ - {"timeout", "set timeout=%s\n", 1, {TYPE_INT}, 0, "SEC", - "Set a timeout, in SEC seconds, before automatically booting the" - " default entry (normally the first entry defined)."}, - /* title is handled separately. */ - {"unhide", "parttool '%s' hidden-\n", 1, {TYPE_PARTITION}, 0, "PARTITION", - "Unhide PARTITION by clearing the \"hidden\" bit in its" - " partition type code."}, - /* uppermem unsupported. */ - {"uuid", "search -u '%s'\n", 1, {TYPE_VERBATIM}, 0, "UUID", - "Find root by UUID"}, - /* vbeprobe unsupported. */ - }; - -static char * -escape (const char *in) -{ - const char *ptr; - char *ret, *outptr; - int overhead = 0; - for (ptr = in; *ptr; ptr++) - if (*ptr == '\'' || *ptr == '\\') - overhead++; - ret = grub_malloc (ptr - in + overhead); - if (!ret) - return NULL; - outptr = ret; - for (ptr = in; *ptr; ptr++) - { - if (*ptr == '\'' || *ptr == '\\') - *outptr++ = '\\'; - - *outptr++ = *ptr; - } - *outptr++ = 0; - return ret; -} - -static char * -adjust_file (const char *in) -{ - const char *comma, *ptr, *rest; - char *ret, *outptr; - int overhead = 0; - int part; - if (in[0] != '(') - return escape (in); - for (ptr = in + 1; *ptr && *ptr != ')' && *ptr != ','; ptr++) - if (*ptr == '\'' || *ptr == '\\') - overhead++; - comma = ptr; - if (*comma != ',') - return escape (in); - part = grub_strtoull (comma + 1, (char **) &rest, 0); - for (ptr = rest; *ptr; ptr++) - if (*ptr == '\'' || *ptr == '\\') - overhead++; - - /* 30 is enough for any number. */ - ret = grub_malloc (ptr - in + overhead + 30); - if (!ret) - return NULL; - - outptr = ret; - for (ptr = in; ptr <= comma; ptr++) - { - if (*ptr == '\'' || *ptr == '\\') - *outptr++ = '\\'; - - *outptr++ = *ptr; - } - grub_snprintf (outptr, 30, "%d", part + 1); - while (*outptr) - outptr++; - for (ptr = rest; ptr <= comma; ptr++) - { - if (*ptr == '\'' || *ptr == '\\') - *outptr++ = '\\'; - - *outptr++ = *ptr; - } - return ret; -} - -static int -is_option (enum arg_type opt, const char *curarg) -{ - switch (opt) - { - case TYPE_NOAPM_OPTION: - return grub_strcmp (curarg, "--no-apm") == 0; - case TYPE_FORCE_OPTION: - return grub_strcmp (curarg, "--force") == 0; - case TYPE_TYPE_OR_NOMEM_OPTION: - return grub_strcmp (curarg, "--type=netbsd") == 0 - || grub_strcmp (curarg, "--type=freebsd") == 0 - || grub_strcmp (curarg, "--type=openbsd") == 0 - || grub_strcmp (curarg, "--type=linux") == 0 - || grub_strcmp (curarg, "--type=biglinux") == 0 - || grub_strcmp (curarg, "--type=multiboot") == 0 - || grub_strcmp (curarg, "--no-mem-option") == 0; - default: - return 0; - } -} - -static char * -legacy_parse (char *buf, char **entryname) -{ - char *ptr; - char *cmdname; - unsigned i, cmdnum; - - for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++); - if ((!*ptr || *ptr == '#') && entryname && *entryname) - { - char *ret = grub_xasprintf ("%s\n", buf); - grub_free (buf); - return ret; - } - if (!*ptr || *ptr == '#') - { - grub_free (buf); - return NULL; - } - - cmdname = ptr; - for (ptr = buf; *ptr && !grub_isspace (*ptr) && *ptr != '='; ptr++); - - if (entryname && grub_strncmp ("title", cmdname, ptr - cmdname) == 0 - && ptr - cmdname == sizeof ("title") - 1) - { - for (; grub_isspace (*ptr) || *ptr == '='; ptr++); - *entryname = grub_strdup (ptr); - grub_free (buf); - return NULL; - } - - if (grub_strncmp ("lock", cmdname, ptr - cmdname) == 0 - && ptr - cmdname == sizeof ("lock") - 1) - { - /* FIXME */ - } - - for (cmdnum = 0; cmdnum < ARRAY_SIZE (legacy_commands); cmdnum++) - if (grub_strncmp (legacy_commands[cmdnum].name, cmdname, ptr - cmdname) == 0 - && legacy_commands[cmdnum].name[ptr - cmdname] == 0) - break; - if (cmdnum == ARRAY_SIZE (legacy_commands)) - return grub_xasprintf ("# Unsupported legacy command: %s\n", buf); - - for (; grub_isspace (*ptr) || *ptr == '='; ptr++); - - char *args[ARRAY_SIZE (legacy_commands[0].argt)]; - memset (args, 0, sizeof (args)); - - { - unsigned j = 0; - for (i = 0; i < legacy_commands[cmdnum].argc; i++) - { - char *curarg, *cptr = NULL, c = 0; - for (; grub_isspace (*ptr); ptr++); - curarg = ptr; - for (; !grub_isspace (*ptr); ptr++); - if (i != legacy_commands[cmdnum].argc - 1 - || (legacy_commands[cmdnum].flags & FLAG_IGNORE_REST)) - { - cptr = ptr; - c = *cptr; - *ptr = 0; - } - if (*ptr) - ptr++; - switch (legacy_commands[cmdnum].argt[i]) - { - case TYPE_PARTITION: - case TYPE_FILE: - args[j++] = adjust_file (curarg); - break; - - case TYPE_REST_VERBATIM: - { - char *outptr, *outptr0; - int overhead = 3; - ptr = curarg; - while (*ptr) - { - for (; grub_isspace (*ptr); ptr++); - for (; *ptr && !grub_isspace (*ptr); ptr++) - if (*ptr == '\\' || *ptr == '\'') - overhead++; - if (*ptr) - ptr++; - overhead += 3; - } - outptr0 = args[j++] = grub_malloc (overhead + (ptr - curarg)); - if (!outptr0) - { - grub_free (buf); - return NULL; - } - ptr = curarg; - outptr = outptr0; - while (*ptr) - { - for (; grub_isspace (*ptr); ptr++); - if (outptr != outptr0) - *outptr++ = ' '; - *outptr++ = '\''; - for (; *ptr && !grub_isspace (*ptr); ptr++) - { - if (*ptr == '\\' || *ptr == '\'') - *outptr++ = '\\'; - *outptr++ = *ptr; - } - *outptr++ = '\''; - if (*ptr) - ptr++; - overhead += 3; - } - *outptr++ = 0; - } - break; - - case TYPE_VERBATIM: - args[j++] = escape (curarg); - break; - case TYPE_FORCE_OPTION: - case TYPE_NOAPM_OPTION: - case TYPE_TYPE_OR_NOMEM_OPTION: - if (is_option (legacy_commands[cmdnum].argt[i], curarg)) - { - args[j++] = grub_strdup (curarg); - break; - } - if (cptr) - *cptr = c; - ptr = curarg; - args[j++] = ""; - break; - case TYPE_INT: - { - char *brk; - int base = 10; - brk = curarg; - if (brk[0] == '0' && brk[1] == 'x') - base = 16; - else if (brk[0] == '0') - base = 8; - for (; *brk; brk++) - { - if (base == 8 && (*brk == '8' || *brk == '9')) - break; - if (grub_isdigit (*brk)) - continue; - if (base != 16) - break; - if (!(*brk >= 'a' && *brk <= 'f') - && !(*brk >= 'A' && *brk <= 'F')) - break; - } - if (brk == curarg) - args[j++] = grub_strdup ("0"); - else - args[j++] = grub_strndup (curarg, brk - curarg); - } - break; - case TYPE_BOOL: - if (curarg[0] == 'o' && curarg[1] == 'n' - && (curarg[2] == 0 || grub_isspace (curarg[2]))) - args[j++] = grub_strdup ("1"); - else - args[j++] = grub_strdup ("0"); - break; - } - } - } - grub_free (buf); - return grub_xasprintf (legacy_commands[cmdnum].map, args[0], args[1], args[2]); -} +#include static grub_err_t legacy_file (const char *filename) @@ -534,7 +69,8 @@ legacy_file (const char *filename) char *oldname = NULL; oldname = entryname; - parsed = legacy_parse (buf, &entryname); + parsed = grub_legacy_parse (buf, &entryname); + grub_free (buf); if (oldname != entryname && oldname) { const char **args = grub_malloc (sizeof (args[0])); diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c new file mode 100644 index 000000000..0b30ef3b1 --- /dev/null +++ b/grub-core/lib/legacy_parse.c @@ -0,0 +1,496 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 1999,2000,2001,2002,2003,2004,2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include + +struct legacy_command +{ + const char *name; + const char *map; + unsigned argc; + enum arg_type { + TYPE_VERBATIM, + TYPE_FORCE_OPTION, + TYPE_NOAPM_OPTION, + TYPE_TYPE_OR_NOMEM_OPTION, + TYPE_FILE, + TYPE_PARTITION, + TYPE_BOOL, + TYPE_INT, + TYPE_REST_VERBATIM + } argt[4]; + enum { + FLAG_IGNORE_REST = 1 + } flags; + const char *shortdesc; + const char *longdesc; +}; + +struct legacy_command legacy_commands[] = + { + {"blocklist", "blocklist '%s'\n", 1, {TYPE_FILE}, 0, "FILE", + "Print the blocklist notation of the file FILE."}, + {"boot", "boot\n", 0, {}, 0, 0, + "Boot the OS/chain-loader which has been loaded."}, + /* bootp unsupported. */ + {"cat", "cat '%s'\n", 1, {TYPE_FILE}, 0, "FILE", + "Print the contents of the file FILE."}, + {"chainloader", "chainloader %s '%s'\n", 2, {TYPE_FORCE_OPTION, TYPE_FILE}, + 0, "[--force] FILE", + "Load the chain-loader FILE. If --force is specified, then load it" + " forcibly, whether the boot loader signature is present or not."}, + {"cmp", "cmp '%s' '%s'\n", 2, {TYPE_FILE, TYPE_FILE}, FLAG_IGNORE_REST, + "FILE1 FILE2", + "Compare the file FILE1 with the FILE2 and inform the different values" + " if any."}, + /* FIXME: Implement command. */ + {"color", "legacy_color '%s' '%s'\n", 2, {TYPE_VERBATIM, TYPE_VERBATIM}, + FLAG_IGNORE_REST, "NORMAL [HIGHLIGHT]", + "Change the menu colors. The color NORMAL is used for most" + " lines in the menu, and the color HIGHLIGHT is used to highlight the" + " line where the cursor points. If you omit HIGHLIGHT, then the" + " inverted color of NORMAL is used for the highlighted line." + " The format of a color is \"FG/BG\". FG and BG are symbolic color names." + " A symbolic color name must be one of these: black, blue, green," + " cyan, red, magenta, brown, light-gray, dark-gray, light-blue," + " light-green, light-cyan, light-red, light-magenta, yellow and white." + " But only the first eight names can be used for BG. You can prefix" + " \"blink-\" to FG if you want a blinking foreground color."}, + {"configfile", "legacy_configfile '%s'\n", 1, {TYPE_FILE}, 0, "FILE", + "Load FILE as the configuration file."}, + {"debug", + "if [ -z \"$debug\" ]; then set debug=all; else set debug=; fi\n", + 0, {}, 0, 0, "Turn on/off the debug mode."}, + {"default", + "set default='%s'; if [ x\"$default\" = xsaved ]; then load_env; " + "set default=\"$saved_entry\"; fi\n", 1, {TYPE_VERBATIM}, 0, + "[NUM | `saved']", + "Set the default entry to entry number NUM (if not specified, it is" + " 0, the first entry) or the entry number saved by savedefault."}, + /* dhcp unsupported. */ + /* displayapm unsupported. */ + {"displaymem", "lsmmap\n", 0, {}, 0, 0, + "Display what GRUB thinks the system address space map of the" + " machine is, including all regions of physical RAM installed."}, + /* embed unsupported. */ + {"fallback", "set fallback='%s'\n", 1, {TYPE_VERBATIM}, 0, "NUM...", + "Go into unattended boot mode: if the default boot entry has any" + " errors, instead of waiting for the user to do anything, it" + " immediately starts over using the NUM entry (same numbering as the" + " `default' command). This obviously won't help if the machine" + " was rebooted by a kernel that GRUB loaded."}, + {"find", "search -sf '%s'\n", 1, {TYPE_FILE}, 0, "FILENAME", + "Search for the filename FILENAME in all of partitions and print the list of" + " the devices which contain the file."}, + /* fstest unsupported. */ + /* geometry unsupported. */ + {"halt", "halt %s\n", 1, {TYPE_NOAPM_OPTION}, 0, "[--no-apm]", + "Halt your system. If APM is available on it, turn off the power using" + " the APM BIOS, unless you specify the option `--no-apm'."}, + /* help unsupported. */ /* NUL_TERMINATE */ + /* hiddenmenu unsupported. */ + {"hide", "parttool '%s' hidden+\n", 1, {TYPE_PARTITION}, 0, "PARTITION", + "Hide PARTITION by setting the \"hidden\" bit in" + " its partition type code."}, + /* ifconfig unsupported. */ + /* impsprobe unsupported. */ + /* FIXME: Implement command. */ + {"initrd", "legacy_initrd '%s' %s\n", 2, {TYPE_FILE, TYPE_REST_VERBATIM}, 0, + "FILE [ARG ...]", + "Load an initial ramdisk FILE for a Linux format boot image and set the" + " appropriate parameters in the Linux setup area in memory."}, + /* install unsupported. */ + /* ioprobe unsupported. */ + /* FIXME: implement command. */ + {"kernel", "legacy_kernel %s '%s' %s\n", 4, {TYPE_TYPE_OR_NOMEM_OPTION, + TYPE_TYPE_OR_NOMEM_OPTION, + TYPE_FILE, + TYPE_REST_VERBATIM}, 0, + "[--no-mem-option] [--type=TYPE] FILE [ARG ...]", + "Attempt to load the primary boot image from FILE. The rest of the" + " line is passed verbatim as the \"kernel command line\". Any modules" + " must be reloaded after using this command. The option --type is used" + " to suggest what type of kernel to be loaded. TYPE must be either of" + " \"netbsd\", \"freebsd\", \"openbsd\", \"linux\", \"biglinux\" and" + " \"multiboot\". The option --no-mem-option tells GRUB not to pass a" + " Linux's mem option automatically."}, + /* lock is handled separately. */ + {"makeactive", "parttool \"$root\" boot+\n", 0, {}, 0, 0, + "Set the active partition on the root disk to GRUB's root device." + " This command is limited to _primary_ PC partitions on a hard disk."}, + {"map", "drivemap '%s' '%s'\n", 2, {TYPE_PARTITION, TYPE_PARTITION}, + FLAG_IGNORE_REST, "TO_DRIVE FROM_DRIVE", + "Map the drive FROM_DRIVE to the drive TO_DRIVE. This is necessary" + " when you chain-load some operating systems, such as DOS, if such an" + " OS resides at a non-first drive."}, + /* md5crypt unsupported. */ + {"module", "legacy_initrd '%s' %s\n", 1, {TYPE_FILE, TYPE_REST_VERBATIM}, 0, + "FILE [ARG ...]", + "Load a boot module FILE for a Multiboot format boot image (no" + " interpretation of the file contents is made, so users of this" + " command must know what the kernel in question expects). The" + " rest of the line is passed as the \"module command line\", like" + " the `kernel' command."}, + /* modulenounzip unsupported. */ + /* FIXME: allow toggle. */ + {"pager", "set pager=%d\n", 1, {TYPE_BOOL}, 0, "[FLAG]", + "Toggle pager mode with no argument. If FLAG is given and its value" + " is `on', turn on the mode. If FLAG is `off', turn off the mode."}, + /* partnew unsupported. */ + {"parttype", "parttool '%s' type=%s\n", 2, {TYPE_PARTITION, TYPE_INT}, 0, + "PART TYPE", "Change the type of the partition PART to TYPE."}, + /* password unsupported. */ /* NUL_TERMINATE */ + /* pause unsupported. */ + /* rarp unsupported. */ + {"read", "read_dword %s\n", 1, {TYPE_INT}, 0, "ADDR", + "Read a 32-bit value from memory at address ADDR and" + " display it in hex format."}, + {"reboot", "reboot\n", 0, {}, 0, 0, "Reboot your system."}, + /* FIXME: Support HDBIAS. */ + /* FIXME: Support printing. */ + {"root", "set root='%s'\n", 1, {TYPE_PARTITION}, 0, "[DEVICE [HDBIAS]]", + "Set the current \"root device\" to the device DEVICE, then" + " attempt to mount it to get the partition size (for passing the" + " partition descriptor in `ES:ESI', used by some chain-loaded" + " bootloaders), the BSD drive-type (for booting BSD kernels using" + " their native boot format), and correctly determine " + " the PC partition where a BSD sub-partition is located. The" + " optional HDBIAS parameter is a number to tell a BSD kernel" + " how many BIOS drive numbers are on controllers before the current" + " one. For example, if there is an IDE disk and a SCSI disk, and your" + " FreeBSD root partition is on the SCSI disk, then use a `1' for HDBIAS."}, + {"rootnoverify", "set root='%s'\n", 1, {TYPE_PARTITION}, 0, + "[DEVICE [HDBIAS]]", + "Similar to `root', but don't attempt to mount the partition. This" + " is useful for when an OS is outside of the area of the disk that" + " GRUB can read, but setting the correct root device is still" + " desired. Note that the items mentioned in `root' which" + " derived from attempting the mount will NOT work correctly."}, + /* FIXME: support arguments. */ + {"savedefault", "saved_entry=${chosen}; save_env saved_entry\n", 0, {}, 0, + "[NUM | `fallback']", + "Save the current entry as the default boot entry if no argument is" + " specified. If a number is specified, this number is saved. If" + " `fallback' is used, next fallback entry is saved."}, + {"serial", "serial %s\n", 1, {TYPE_REST_VERBATIM}, 0, + "[--unit=UNIT] [--port=PORT] [--speed=SPEED] [--word=WORD] " + "[--parity=PARITY] [--stop=STOP] [--device=DEV]", + "Initialize a serial device. UNIT is a digit that specifies which serial" + " device is used (e.g. 0 == COM1). If you need to specify the port number," + " set it by --port. SPEED is the DTE-DTE speed. WORD is the word length," + " PARITY is the type of parity, which is one of `no', `odd' and `even'." + " STOP is the length of stop bit(s). The option --device can be used only" + " in the grub shell, which specifies the file name of a tty device. The" + " default values are COM1, 9600, 8N1."}, + /* setkey unsupported. */ /* NUL_TERMINATE */ + /* setup unsupported. */ + /* terminal unsupported. */ /* NUL_TERMINATE */ + /* terminfo unsupported. */ /* NUL_TERMINATE */ + /* testload unsupported. */ + /* testvbe unsupported. */ + /* tftpserver unsupported. */ + {"timeout", "set timeout=%s\n", 1, {TYPE_INT}, 0, "SEC", + "Set a timeout, in SEC seconds, before automatically booting the" + " default entry (normally the first entry defined)."}, + /* title is handled separately. */ + {"unhide", "parttool '%s' hidden-\n", 1, {TYPE_PARTITION}, 0, "PARTITION", + "Unhide PARTITION by clearing the \"hidden\" bit in its" + " partition type code."}, + /* uppermem unsupported. */ + {"uuid", "search -u '%s'\n", 1, {TYPE_VERBATIM}, 0, "UUID", + "Find root by UUID"}, + /* vbeprobe unsupported. */ + }; + +char * +grub_legacy_escape (const char *in, grub_size_t len) +{ + const char *ptr; + char *ret, *outptr; + int overhead = 0; + for (ptr = in; ptr < in + len && *ptr; ptr++) + if (*ptr == '\'' || *ptr == '\\') + overhead++; + ret = grub_malloc (ptr - in + overhead); + if (!ret) + return NULL; + outptr = ret; + for (ptr = in; ptr < in + len && *ptr; ptr++) + { + if (*ptr == '\'' || *ptr == '\\') + *outptr++ = '\\'; + + *outptr++ = *ptr; + } + *outptr++ = 0; + return ret; +} + +static char * +adjust_file (const char *in, grub_size_t len) +{ + const char *comma, *ptr, *rest; + char *ret, *outptr; + int overhead = 0; + int part; + if (in[0] != '(') + return grub_legacy_escape (in, len); + for (ptr = in + 1; ptr < in + len && *ptr && *ptr != ')' + && *ptr != ','; ptr++) + if (*ptr == '\'' || *ptr == '\\') + overhead++; + comma = ptr; + if (*comma != ',') + return grub_legacy_escape (in, len); + part = grub_strtoull (comma + 1, (char **) &rest, 0); + for (ptr = rest; ptr < in + len && *ptr; ptr++) + if (*ptr == '\'' || *ptr == '\\') + overhead++; + + /* 30 is enough for any number. */ + ret = grub_malloc (ptr - in + overhead + 30); + if (!ret) + return NULL; + + outptr = ret; + for (ptr = in; ptr < in + len && ptr <= comma; ptr++) + { + if (*ptr == '\'' || *ptr == '\\') + *outptr++ = '\\'; + + *outptr++ = *ptr; + } + grub_snprintf (outptr, 30, "%d", part + 1); + while (*outptr) + outptr++; + for (ptr = rest; ptr < in + len; ptr++) + { + if (*ptr == '\'' || *ptr == '\\') + *outptr++ = '\\'; + + *outptr++ = *ptr; + } + return ret; +} + +static int +check_option (const char *a, char *b, grub_size_t len) +{ + if (grub_strlen (b) != len) + return 0; + return grub_strncmp (a, b, len) == 0; +} + +static int +is_option (enum arg_type opt, const char *curarg, grub_size_t len) +{ + switch (opt) + { + case TYPE_NOAPM_OPTION: + return check_option (curarg, "--no-apm", len); + case TYPE_FORCE_OPTION: + return check_option (curarg, "--force", len); + case TYPE_TYPE_OR_NOMEM_OPTION: + return check_option (curarg, "--type=netbsd", len) + || check_option (curarg, "--type=freebsd", len) + || check_option (curarg, "--type=openbsd", len) + || check_option (curarg, "--type=linux", len) + || check_option (curarg, "--type=biglinux", len) + || check_option (curarg, "--type=multiboot", len) + || check_option (curarg, "--no-mem-option", len); + default: + return 0; + } +} + +char * +grub_legacy_parse (const char *buf, char **entryname) +{ + const char *ptr; + const char *cmdname; + unsigned i, cmdnum; + + for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++); + if (!*ptr || *ptr == '#') + return grub_strdup (buf); + + cmdname = ptr; + for (ptr = buf; *ptr && !grub_isspace (*ptr) && *ptr != '='; ptr++); + + if (entryname && grub_strncmp ("title", cmdname, ptr - cmdname) == 0 + && ptr - cmdname == sizeof ("title") - 1) + { + const char *ptr2; + for (; grub_isspace (*ptr) || *ptr == '='; ptr++); + ptr2 = ptr + grub_strlen (ptr); + while (ptr2 > ptr && grub_isspace (*(ptr2 - 1))) + ptr2--; + *entryname = grub_strndup (ptr, ptr2 - ptr); + return NULL; + } + + if (grub_strncmp ("lock", cmdname, ptr - cmdname) == 0 + && ptr - cmdname == sizeof ("lock") - 1) + { + /* FIXME */ + } + + for (cmdnum = 0; cmdnum < ARRAY_SIZE (legacy_commands); cmdnum++) + if (grub_strncmp (legacy_commands[cmdnum].name, cmdname, ptr - cmdname) == 0 + && legacy_commands[cmdnum].name[ptr - cmdname] == 0) + break; + if (cmdnum == ARRAY_SIZE (legacy_commands)) + return grub_xasprintf ("# Unsupported legacy command: %s\n", buf); + + for (; grub_isspace (*ptr) || *ptr == '='; ptr++); + + char *args[ARRAY_SIZE (legacy_commands[0].argt)]; + grub_memset (args, 0, sizeof (args)); + + { + unsigned j = 0; + int hold_arg = 0; + for (i = 0; i < legacy_commands[cmdnum].argc; i++) + { + const char *curarg; + grub_size_t curarglen; + if (hold_arg) + { + ptr = curarg; + hold_arg = 0; + } + for (; grub_isspace (*ptr); ptr++); + curarg = ptr; + for (; !grub_isspace (*ptr); ptr++); + if (i != legacy_commands[cmdnum].argc - 1 + || (legacy_commands[cmdnum].flags & FLAG_IGNORE_REST)) + curarglen = ptr - curarg; + else + { + curarglen = grub_strlen (curarg); + while (curarglen > 0 && grub_isspace (curarg[curarglen - 1])) + curarglen--; + } + if (*ptr) + ptr++; + switch (legacy_commands[cmdnum].argt[i]) + { + case TYPE_PARTITION: + case TYPE_FILE: + args[j++] = adjust_file (curarg, curarglen); + break; + + case TYPE_REST_VERBATIM: + { + char *outptr, *outptr0; + int overhead = 3; + ptr = curarg; + while (*ptr) + { + for (; grub_isspace (*ptr); ptr++); + for (; *ptr && !grub_isspace (*ptr); ptr++) + if (*ptr == '\\' || *ptr == '\'') + overhead++; + if (*ptr) + ptr++; + overhead += 3; + } + outptr0 = args[j++] = grub_malloc (overhead + (ptr - curarg)); + if (!outptr0) + return NULL; + ptr = curarg; + outptr = outptr0; + while (*ptr) + { + for (; grub_isspace (*ptr); ptr++); + if (outptr != outptr0) + *outptr++ = ' '; + *outptr++ = '\''; + for (; *ptr && !grub_isspace (*ptr); ptr++) + { + if (*ptr == '\\' || *ptr == '\'') + *outptr++ = '\\'; + *outptr++ = *ptr; + } + *outptr++ = '\''; + if (*ptr) + ptr++; + overhead += 3; + } + *outptr++ = 0; + } + break; + + case TYPE_VERBATIM: + args[j++] = grub_legacy_escape (curarg, curarglen); + break; + case TYPE_FORCE_OPTION: + case TYPE_NOAPM_OPTION: + case TYPE_TYPE_OR_NOMEM_OPTION: + if (is_option (legacy_commands[cmdnum].argt[i], curarg, curarglen)) + { + args[j++] = grub_strndup (curarg, curarglen); + break; + } + args[j++] = ""; + hold_arg = 1; + break; + case TYPE_INT: + { + const char *brk; + int base = 10; + brk = curarg; + if (curarglen < 1) + args[j++] = grub_strdup ("0"); + if (brk[0] == '0' && brk[1] == 'x') + base = 16; + else if (brk[0] == '0') + base = 8; + for (; *brk && brk < curarg + curarglen; brk++) + { + if (base == 8 && (*brk == '8' || *brk == '9')) + break; + if (grub_isdigit (*brk)) + continue; + if (base != 16) + break; + if (!(*brk >= 'a' && *brk <= 'f') + && !(*brk >= 'A' && *brk <= 'F')) + break; + } + if (brk == curarg) + args[j++] = grub_strdup ("0"); + else + args[j++] = grub_strndup (curarg, brk - curarg); + } + break; + case TYPE_BOOL: + if (curarglen == 2 && curarg[0] == 'o' && curarg[1] == 'n') + args[j++] = grub_strdup ("1"); + else + args[j++] = grub_strdup ("0"); + break; + } + } + } + return grub_xasprintf (legacy_commands[cmdnum].map, args[0], args[1], args[2]); +} diff --git a/include/grub/legacy_parse.h b/include/grub/legacy_parse.h new file mode 100644 index 000000000..fce4e3e40 --- /dev/null +++ b/include/grub/legacy_parse.h @@ -0,0 +1,27 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_LEGACY_PARSE_HEADER +#define GRUB_LEGACY_PARSE_HEADER 1 + +#include + +char *grub_legacy_parse (const char *buf, char **entryname); +char *grub_legacy_escape (const char *in, grub_size_t len); + +#endif diff --git a/util/grub-menulst2cfg.c b/util/grub-menulst2cfg.c new file mode 100644 index 000000000..fdbdda388 --- /dev/null +++ b/util/grub-menulst2cfg.c @@ -0,0 +1,99 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include + +int +main (int argc, char **argv) +{ + FILE *in, *out; + char *entryname = NULL; + char *buf = NULL; + size_t bufsize = 0; + + if (argc >= 2 && argv[1][0] == '-') + { + fprintf (stderr, "Usage: %s [INFILE [OUTFILE]]\n", argv[0]); + return 0; + } + + if (argc >= 2) + { + in = fopen (argv[1], "r"); + if (!in) + { + fprintf (stderr, "Couldn't open %s for reading: %s\n", + argv[1], strerror (errno)); + return 1; + } + } + else + in = stdin; + + if (argc >= 3) + { + out = fopen (argv[2], "w"); + if (!out) + { + if (in != stdin) + fclose (in); + fprintf (stderr, "Couldn't open %s for writing: %s\n", + argv[2], strerror (errno)); + return 1; + } + } + else + out = stdout; + + while (1) + { + char *parsed; + + if (getline (&buf, &bufsize, in) < 0) + break; + + { + char *oldname = NULL; + + oldname = entryname; + parsed = grub_legacy_parse (buf, &entryname); + if (oldname != entryname && oldname) + fprintf (out, "}\n\n"); + if (oldname != entryname) + fprintf (out, "menuentry \'%s\' {\n", + grub_legacy_escape (entryname, grub_strlen (entryname))); + } + + if (parsed) + fprintf (out, "%s%s", entryname ? " " : "", parsed); + } + + if (entryname) + fprintf (out, "}\n\n"); + + + if (in != stdin) + fclose (in); + if (out != stdout) + fclose (out); + + return 0; +} From 661cf422317447e70016ae99d222cc3601bb3e23 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 27 Aug 2010 20:23:39 +0200 Subject: [PATCH 070/214] Fix a problem with kernel command --- grub-core/lib/legacy_parse.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 0b30ef3b1..985a53733 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -121,7 +121,7 @@ struct legacy_command legacy_commands[] = /* install unsupported. */ /* ioprobe unsupported. */ /* FIXME: implement command. */ - {"kernel", "legacy_kernel %s '%s' %s\n", 4, {TYPE_TYPE_OR_NOMEM_OPTION, + {"kernel", "legacy_kernel %s %s '%s' %s\n", 4, {TYPE_TYPE_OR_NOMEM_OPTION, TYPE_TYPE_OR_NOMEM_OPTION, TYPE_FILE, TYPE_REST_VERBATIM}, 0, @@ -380,7 +380,7 @@ grub_legacy_parse (const char *buf, char **entryname) } for (; grub_isspace (*ptr); ptr++); curarg = ptr; - for (; !grub_isspace (*ptr); ptr++); + for (; *ptr && !grub_isspace (*ptr); ptr++); if (i != legacy_commands[cmdnum].argc - 1 || (legacy_commands[cmdnum].flags & FLAG_IGNORE_REST)) curarglen = ptr - curarg; @@ -406,7 +406,7 @@ grub_legacy_parse (const char *buf, char **entryname) ptr = curarg; while (*ptr) { - for (; grub_isspace (*ptr); ptr++); + for (; *ptr && grub_isspace (*ptr); ptr++); for (; *ptr && !grub_isspace (*ptr); ptr++) if (*ptr == '\\' || *ptr == '\'') overhead++; @@ -421,7 +421,7 @@ grub_legacy_parse (const char *buf, char **entryname) outptr = outptr0; while (*ptr) { - for (; grub_isspace (*ptr); ptr++); + for (; *ptr && grub_isspace (*ptr); ptr++); if (outptr != outptr0) *outptr++ = ' '; *outptr++ = '\''; @@ -434,7 +434,6 @@ grub_legacy_parse (const char *buf, char **entryname) *outptr++ = '\''; if (*ptr) ptr++; - overhead += 3; } *outptr++ = 0; } @@ -492,5 +491,7 @@ grub_legacy_parse (const char *buf, char **entryname) } } } - return grub_xasprintf (legacy_commands[cmdnum].map, args[0], args[1], args[2]); + + return grub_xasprintf (legacy_commands[cmdnum].map, args[0], args[1], args[2], + args[3]); } From 8fc6a271473ede7cdff29cbfab9558e9dbfd5597 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 27 Aug 2010 21:27:26 +0200 Subject: [PATCH 071/214] Implement legacy_kernel and legacy_initrd commands --- grub-core/commands/legacycfg.c | 190 ++++++++++++++++++++++++++++++++- grub-core/lib/legacy_parse.c | 8 +- 2 files changed, 194 insertions(+), 4 deletions(-) diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c index 4207531ec..ed02fd4f2 100644 --- a/grub-core/commands/legacycfg.c +++ b/grub-core/commands/legacycfg.c @@ -167,13 +167,199 @@ grub_cmd_legacy_configfile (struct grub_command *cmd __attribute__ ((unused)), return ret; } -static grub_command_t cmd_source, cmd_configfile; +static enum + { + GUESS_IT, LINUX, MULTIBOOT, KFREEBSD, KNETBSD, KOPENBSD + } kernel_type; + +static grub_err_t +grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), + int argc, char **args) +{ + int i; + int no_mem_option = 0; + struct grub_command *cmd; + for (i = 0; i < 2; i++) + { + /* FIXME: really support this. */ + if (argc >= 1 && grub_strcmp (args[0], "--no-mem-option") == 0) + { + no_mem_option = 1; + argc--; + args++; + continue; + } + + /* FIXME: what's the difference? */ + if (argc >= 1 && (grub_strcmp (args[0], "--type=linux") == 0 + || grub_strcmp (args[0], "--type=biglinux") == 0)) + { + kernel_type = LINUX; + argc--; + args++; + continue; + } + + if (argc >= 1 && grub_strcmp (args[0], "--type=multiboot") == 0) + { + kernel_type = MULTIBOOT; + argc--; + args++; + continue; + } + + if (argc >= 1 && grub_strcmp (args[0], "--type=freebsd") == 0) + { + kernel_type = KFREEBSD; + argc--; + args++; + continue; + } + + if (argc >= 1 && grub_strcmp (args[0], "--type=openbsd") == 0) + { + kernel_type = KOPENBSD; + argc--; + args++; + continue; + } + + if (argc >= 1 && grub_strcmp (args[0], "--type=netbsd") == 0) + { + kernel_type = KNETBSD; + argc--; + args++; + continue; + } + } + + if (!argc) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "filename required"); + + do + { + /* First try Linux. */ + if (kernel_type == GUESS_IT || kernel_type == LINUX) + { + cmd = grub_command_find ("linux16"); + if (cmd) + { + if (!(cmd->func) (cmd, argc, args)) + { + kernel_type = LINUX; + return GRUB_ERR_NONE; + } + } + grub_errno = GRUB_ERR_NONE; + } + + /* Then multiboot. */ + /* FIXME: dublicate multiboot filename. */ + if (kernel_type == GUESS_IT || kernel_type == MULTIBOOT) + { + cmd = grub_command_find ("multiboot"); + if (cmd) + { + if (!(cmd->func) (cmd, argc, args)) + { + kernel_type = MULTIBOOT; + return GRUB_ERR_NONE; + } + } + grub_errno = GRUB_ERR_NONE; + } + + /* k*BSD didn't really work well with grub-legacy. */ + if (kernel_type == GUESS_IT || kernel_type == KFREEBSD) + { + cmd = grub_command_find ("kfreebsd"); + if (cmd) + { + if (!(cmd->func) (cmd, argc, args)) + { + kernel_type = KFREEBSD; + return GRUB_ERR_NONE; + } + } + grub_errno = GRUB_ERR_NONE; + } + if (kernel_type == GUESS_IT || kernel_type == KNETBSD) + { + cmd = grub_command_find ("knetbsd"); + if (cmd) + { + if (!(cmd->func) (cmd, argc, args)) + { + kernel_type = KNETBSD; + return GRUB_ERR_NONE; + } + } + grub_errno = GRUB_ERR_NONE; + } + if (kernel_type == GUESS_IT || kernel_type == KOPENBSD) + { + cmd = grub_command_find ("kopenbsd"); + if (cmd) + { + if (!(cmd->func) (cmd, argc, args)) + { + kernel_type = KOPENBSD; + return GRUB_ERR_NONE; + } + } + grub_errno = GRUB_ERR_NONE; + } + } + while (0); + + return grub_error (GRUB_ERR_BAD_OS, "couldn't load file %s\n", + args[0]); +} + +static grub_err_t +grub_cmd_legacy_initrd (struct grub_command *mycmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_command *cmd; + + if (kernel_type == LINUX) + { + cmd = grub_command_find ("initrd16"); + if (!cmd) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "command initrd16 not found"); + + return cmd->func (cmd, argc, args); + } + if (kernel_type == MULTIBOOT) + { + /* FIXME: dublicate module filename. */ + cmd = grub_command_find ("module"); + if (!cmd) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "command module not found"); + + return cmd->func (cmd, argc, args); + } + + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "no kernel with module support is loaded in legacy way"); +} + +static grub_command_t cmd_source, cmd_configfile, cmd_kernel, cmd_initrd; GRUB_MOD_INIT(legacycfg) { cmd_source = grub_register_command ("legacy_source", grub_cmd_legacy_source, N_("FILE"), N_("Parse legacy config")); + cmd_kernel = grub_register_command ("legacy_kernel", + grub_cmd_legacy_kernel, + N_("[--no-mem-option] [--type=TYPE] FILE [ARG ...]"), + N_("Simulate grub-legacy kernel command")); + + cmd_initrd = grub_register_command ("legacy_initrd", + grub_cmd_legacy_initrd, + N_("FILE [ARG ...]"), + N_("Simulate grub-legacy initrd command")); cmd_configfile = grub_register_command ("legacy_configfile", grub_cmd_legacy_configfile, N_("FILE"), @@ -184,4 +370,6 @@ GRUB_MOD_FINI(legacycfg) { grub_unregister_command (cmd_source); grub_unregister_command (cmd_configfile); + grub_unregister_command (cmd_kernel); + grub_unregister_command (cmd_initrd); } diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 985a53733..61952d35d 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -113,14 +113,16 @@ struct legacy_command legacy_commands[] = " its partition type code."}, /* ifconfig unsupported. */ /* impsprobe unsupported. */ - /* FIXME: Implement command. */ + /* FIXME: dublicate multiboot filename. */ {"initrd", "legacy_initrd '%s' %s\n", 2, {TYPE_FILE, TYPE_REST_VERBATIM}, 0, "FILE [ARG ...]", "Load an initial ramdisk FILE for a Linux format boot image and set the" " appropriate parameters in the Linux setup area in memory."}, /* install unsupported. */ /* ioprobe unsupported. */ - /* FIXME: implement command. */ + /* FIXME: really support --no-mem-option. */ + /* FIXME: distinguish linux and biglinux. */ + /* FIXME: dublicate multiboot filename. */ {"kernel", "legacy_kernel %s %s '%s' %s\n", 4, {TYPE_TYPE_OR_NOMEM_OPTION, TYPE_TYPE_OR_NOMEM_OPTION, TYPE_FILE, @@ -133,7 +135,7 @@ struct legacy_command legacy_commands[] = " \"netbsd\", \"freebsd\", \"openbsd\", \"linux\", \"biglinux\" and" " \"multiboot\". The option --no-mem-option tells GRUB not to pass a" " Linux's mem option automatically."}, - /* lock is handled separately. */ + /* lock is unsupported. */ {"makeactive", "parttool \"$root\" boot+\n", 0, {}, 0, 0, "Set the active partition on the root disk to GRUB's root device." " This command is limited to _primary_ PC partitions on a hard disk."}, From 7ddbecf25fc97603da45d0783e5dec3372aa85b9 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 27 Aug 2010 22:09:09 +0200 Subject: [PATCH 072/214] implement legacy_color --- grub-core/commands/legacycfg.c | 39 ++++++++++++++++++++++++++++++++++ grub-core/lib/legacy_parse.c | 1 - 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c index ed02fd4f2..db53f2c92 100644 --- a/grub-core/commands/legacycfg.c +++ b/grub-core/commands/legacycfg.c @@ -344,7 +344,41 @@ grub_cmd_legacy_initrd (struct grub_command *mycmd __attribute__ ((unused)), "no kernel with module support is loaded in legacy way"); } +static grub_err_t +grub_cmd_legacy_color (struct grub_command *mycmd __attribute__ ((unused)), + int argc, char **args) +{ + if (argc < 1) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "color required"); + grub_env_set ("color_normal", args[0]); + if (argc >= 2) + grub_env_set ("color_highlight", args[1]); + else + { + char *slash = grub_strchr (args[0], '/'); + char *invert; + grub_size_t len; + + len = grub_strlen (args[0]); + if (!slash) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad color specification %s", + args[0]); + invert = grub_malloc (len + 1); + if (!invert) + return grub_errno; + grub_memcpy (invert, slash + 1, len - (slash - args[0]) - 1); + invert[len - (slash - args[0]) - 1] = '/'; + grub_memcpy (invert + len - (slash - args[0]), args[0], slash - args[0]); + invert[len] = 0; + grub_env_set ("color_highlight", invert); + grub_free (invert); + } + + return grub_errno; +} + static grub_command_t cmd_source, cmd_configfile, cmd_kernel, cmd_initrd; +static grub_command_t cmd_color; GRUB_MOD_INIT(legacycfg) { @@ -364,6 +398,10 @@ GRUB_MOD_INIT(legacycfg) grub_cmd_legacy_configfile, N_("FILE"), N_("Parse legacy config")); + cmd_color = grub_register_command ("legacy_color", + grub_cmd_legacy_color, + N_("NORMAL [HIGHLIGHT]"), + N_("Simulate grub-legacy color command")); } GRUB_MOD_FINI(legacycfg) @@ -372,4 +410,5 @@ GRUB_MOD_FINI(legacycfg) grub_unregister_command (cmd_configfile); grub_unregister_command (cmd_kernel); grub_unregister_command (cmd_initrd); + grub_unregister_command (cmd_color); } diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 61952d35d..1c502187d 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -62,7 +62,6 @@ struct legacy_command legacy_commands[] = "FILE1 FILE2", "Compare the file FILE1 with the FILE2 and inform the different values" " if any."}, - /* FIXME: Implement command. */ {"color", "legacy_color '%s' '%s'\n", 2, {TYPE_VERBATIM, TYPE_VERBATIM}, FLAG_IGNORE_REST, "NORMAL [HIGHLIGHT]", "Change the menu colors. The color NORMAL is used for most" From 2a87d7d1b6ebf745cedc9284419dd13b5ae29770 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 27 Aug 2010 22:34:25 +0200 Subject: [PATCH 073/214] Remove biglinux FIXME comment. It's a non-issue --- grub-core/commands/legacycfg.c | 2 +- grub-core/lib/legacy_parse.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c index db53f2c92..aca6d1e1f 100644 --- a/grub-core/commands/legacycfg.c +++ b/grub-core/commands/legacycfg.c @@ -190,7 +190,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), continue; } - /* FIXME: what's the difference? */ + /* linux16 handles both zImages and bzImages. */ if (argc >= 1 && (grub_strcmp (args[0], "--type=linux") == 0 || grub_strcmp (args[0], "--type=biglinux") == 0)) { diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 1c502187d..f2d3dec0a 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -120,7 +120,6 @@ struct legacy_command legacy_commands[] = /* install unsupported. */ /* ioprobe unsupported. */ /* FIXME: really support --no-mem-option. */ - /* FIXME: distinguish linux and biglinux. */ /* FIXME: dublicate multiboot filename. */ {"kernel", "legacy_kernel %s %s '%s' %s\n", 4, {TYPE_TYPE_OR_NOMEM_OPTION, TYPE_TYPE_OR_NOMEM_OPTION, From 69d6fc56036f18f3a9f69a78f24d6df8a40cfbb9 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 30 Aug 2010 01:04:07 +0200 Subject: [PATCH 074/214] Use interrupt endpoint for hubs --- bus/usb/usbhub.c | 290 +++++++++++++---------------------------------- 1 file changed, 81 insertions(+), 209 deletions(-) diff --git a/bus/usb/usbhub.c b/bus/usb/usbhub.c index 111a2495e..0ddba3255 100644 --- a/bus/usb/usbhub.c +++ b/bus/usb/usbhub.c @@ -28,6 +28,8 @@ /* USB Supports 127 devices, with device 0 as special case. */ static struct grub_usb_device *grub_usb_devs[GRUB_USBHUB_MAX_DEVICES]; +static int rescan = 0; + struct grub_usb_hub { struct grub_usb_hub *next; @@ -110,9 +112,6 @@ grub_usb_add_hub (grub_usb_device_t dev) struct grub_usb_usb_hubdesc hubdesc; grub_err_t err; int i; - grub_uint64_t timeout; - grub_usb_device_t next_dev; - grub_usb_device_t *attached_devices; err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN | GRUB_USB_REQTYPE_CLASS @@ -131,11 +130,9 @@ grub_usb_add_hub (grub_usb_device_t dev) grub_dprintf ("usb", "Hub set configuration\n"); grub_usb_set_configuration (dev, 1); - attached_devices = grub_zalloc (hubdesc.portcnt - * sizeof (attached_devices[0])); - if (!attached_devices) + dev->children = grub_zalloc (hubdesc.portcnt * sizeof (dev->children[0])); + if (!dev->children) return GRUB_USB_ERR_INTERNAL; - dev->children = attached_devices; dev->nports = hubdesc.portcnt; /* Power on all Hub ports. */ @@ -143,115 +140,15 @@ grub_usb_add_hub (grub_usb_device_t dev) { grub_dprintf ("usb", "Power on - port %d\n", i); /* Power on the port and wait for possible device connect */ - err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_OTHER), - GRUB_USB_REQ_SET_FEATURE, - GRUB_USB_HUB_FEATURE_PORT_POWER, - i, 0, NULL); - /* Just ignore the device if some error happened */ - if (err) - continue; - } - /* Wait for port power-on */ - if (hubdesc.pwdgood >= 50) - grub_millisleep (hubdesc.pwdgood * 2); - else - grub_millisleep (100); - - /* Iterate over the Hub ports. */ - for (i = 1; i <= hubdesc.portcnt; i++) - { - grub_uint32_t status; - - /* Get the port status. */ - err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_OTHER), - GRUB_USB_REQ_GET_STATUS, - 0, i, sizeof (status), (char *) &status); - /* Just ignore the device if the Hub does not report the - status. */ - if (err) - continue; - grub_dprintf ("usb", "Hub port %d status: 0x%02x\n", i, status); - - /* If connected, reset and enable the port. */ - if (status & GRUB_USB_HUB_STATUS_PORT_CONNECTED) - { - grub_usb_speed_t speed; - - /* Determine the device speed. */ - if (status & GRUB_USB_HUB_STATUS_PORT_LOWSPEED) - speed = GRUB_USB_SPEED_LOW; - else - { - if (status & GRUB_USB_HUB_STATUS_PORT_HIGHSPEED) - speed = GRUB_USB_SPEED_HIGH; - else - speed = GRUB_USB_SPEED_FULL; - } - - /* A device is actually connected to this port. - * Now do reset of port. */ - grub_dprintf ("usb", "Reset hub port - port %d\n", i); - err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_OTHER), - GRUB_USB_REQ_SET_FEATURE, - GRUB_USB_HUB_FEATURE_PORT_RESET, - i, 0, 0); - /* If the Hub does not cooperate for this port, just skip - the port. */ - if (err) - continue; - - /* Wait for reset procedure done */ - timeout = grub_get_time_ms () + 1000; - do - { - /* Get the port status. */ - err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_OTHER), - GRUB_USB_REQ_GET_STATUS, - 0, i, sizeof (status), (char *) &status); - } - while (!err && - !(status & GRUB_USB_HUB_STATUS_C_PORT_RESET) && - (grub_get_time_ms() < timeout) ); - if (err || !(status & GRUB_USB_HUB_STATUS_C_PORT_RESET) ) - continue; - - /* Wait a recovery time after reset, spec. says 10ms */ - grub_millisleep (10); - - /* Do reset of connection change bit */ - err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_OTHER), - GRUB_USB_REQ_CLEAR_FEATURE, - GRUB_USB_HUB_FEATURE_C_PORT_CONNECTED, - i, 0, 0); - /* Just ignore the device if the Hub reports some error */ - if (err) - continue; - grub_dprintf ("usb", "Hub port - cleared connection change\n"); - - /* Add the device and assign a device address to it. */ - grub_dprintf ("usb", "Call hub_add_dev - port %d\n", i); - next_dev = grub_usb_hub_add_dev (&dev->controller, speed); - if (! next_dev) - continue; - - attached_devices[i - 1] = next_dev; - - /* If the device is a Hub, scan it for more devices. */ - if (next_dev->descdev.class == 0x09) - grub_usb_add_hub (next_dev); - } + grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_SET_FEATURE, + GRUB_USB_HUB_FEATURE_PORT_POWER, + i, 0, NULL); } + /* Rest will be done on next usb poll. */ for (i = 0; i < dev->config[0].interf[0].descif->endpointcnt; i++) { @@ -271,6 +168,8 @@ grub_usb_add_hub (grub_usb_device_t dev) } } + rescan = 1; + return GRUB_ERR_NONE; } @@ -383,9 +282,6 @@ poll_nonroot_hub (grub_usb_device_t dev) { grub_err_t err; unsigned i; - grub_uint64_t timeout; - grub_usb_device_t next_dev; - grub_usb_device_t *attached_devices = dev->children; grub_uint8_t changed; grub_size_t actual; @@ -408,9 +304,6 @@ poll_nonroot_hub (grub_usb_device_t dev) if (err || actual == 0 || changed == 0) return; - grub_dprintf ("usb", "statuschanged = %02x, err = %d, actual = %d\n", - changed, err, actual); - /* Iterate over the Hub ports. */ for (i = 1; i <= dev->nports; i++) { @@ -426,17 +319,12 @@ poll_nonroot_hub (grub_usb_device_t dev) GRUB_USB_REQ_GET_STATUS, 0, i, sizeof (status), (char *) &status); + grub_printf ("i = %d, status = %08x\n", i, status); + if (err) continue; /* FIXME: properly handle these conditions. */ - if (status & GRUB_USB_HUB_STATUS_C_PORT_RESET) - grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_OTHER), - GRUB_USB_REQ_CLEAR_FEATURE, - GRUB_USB_HUB_FEATURE_C_PORT_RESET, i, 0, 0); - if (status & GRUB_USB_HUB_STATUS_C_PORT_ENABLED) grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT | GRUB_USB_REQTYPE_CLASS @@ -458,96 +346,72 @@ poll_nonroot_hub (grub_usb_device_t dev) GRUB_USB_REQ_CLEAR_FEATURE, GRUB_USB_HUB_FEATURE_C_PORT_OVERCURRENT, i, 0, 0); - if (!(status & GRUB_USB_HUB_STATUS_C_PORT_CONNECTED)) - continue; - - grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_OTHER), - GRUB_USB_REQ_CLEAR_FEATURE, - GRUB_USB_HUB_FEATURE_C_PORT_CONNECTED, i, 0, 0); - if (status & GRUB_USB_HUB_STATUS_C_PORT_CONNECTED) { - detach_device (attached_devices[i-1]); - attached_devices[i - 1] = NULL; - } + grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_CLEAR_FEATURE, + GRUB_USB_HUB_FEATURE_C_PORT_CONNECTED, i, 0, 0); + + detach_device (dev->children[i - 1]); + dev->children[i - 1] = NULL; - /* Connected and status of connection changed ? */ - if ((status & GRUB_USB_HUB_STATUS_PORT_CONNECTED) - && (status & GRUB_USB_HUB_STATUS_C_PORT_CONNECTED)) - { - grub_usb_speed_t speed; - - /* Determine the device speed. */ - if (status & GRUB_USB_HUB_STATUS_PORT_LOWSPEED) - speed = GRUB_USB_SPEED_LOW; - else + /* Connected and status of connection changed ? */ + if (status & GRUB_USB_HUB_STATUS_PORT_CONNECTED) { - if (status & GRUB_USB_HUB_STATUS_PORT_HIGHSPEED) - speed = GRUB_USB_SPEED_HIGH; - else - speed = GRUB_USB_SPEED_FULL; + /* A device is actually connected to this port. + * Now do reset of port. */ + grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_SET_FEATURE, + GRUB_USB_HUB_FEATURE_PORT_RESET, + i, 0, 0); + rescan = 1; } + } - /* A device is actually connected to this port. - * Now do reset of port. */ - err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_OTHER), - GRUB_USB_REQ_SET_FEATURE, - GRUB_USB_HUB_FEATURE_PORT_RESET, - i, 0, 0); - /* If the Hub does not cooperate for this port, just skip - the port. */ - if (err) - continue; + if (status & GRUB_USB_HUB_STATUS_C_PORT_RESET) + { + grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_CLEAR_FEATURE, + GRUB_USB_HUB_FEATURE_C_PORT_RESET, i, 0, 0); - /* Wait for reset procedure done */ - timeout = grub_get_time_ms () + 1000; - do - { - /* Get the port status. */ - err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_OTHER), - GRUB_USB_REQ_GET_STATUS, - 0, i, sizeof (status), (char *) &status); - } - while (!err && - !(status & GRUB_USB_HUB_STATUS_C_PORT_RESET) && - (grub_get_time_ms() < timeout) ); - if (err || !(status & GRUB_USB_HUB_STATUS_C_PORT_RESET) ) - continue; + if (status & GRUB_USB_HUB_STATUS_PORT_CONNECTED) + { + grub_usb_speed_t speed; + grub_usb_device_t next_dev; - /* Wait a recovery time after reset, spec. says 10ms */ - grub_millisleep (10); + /* Determine the device speed. */ + if (status & GRUB_USB_HUB_STATUS_PORT_LOWSPEED) + speed = GRUB_USB_SPEED_LOW; + else + { + if (status & GRUB_USB_HUB_STATUS_PORT_HIGHSPEED) + speed = GRUB_USB_SPEED_HIGH; + else + speed = GRUB_USB_SPEED_FULL; + } - /* Do reset of connection change bit */ - err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT - | GRUB_USB_REQTYPE_CLASS - | GRUB_USB_REQTYPE_TARGET_OTHER), - GRUB_USB_REQ_CLEAR_FEATURE, - GRUB_USB_HUB_FEATURE_C_PORT_CONNECTED, - i, 0, 0); - /* Just ignore the device if the Hub reports some error */ - if (err) - continue; + /* Wait a recovery time after reset, spec. says 10ms */ + grub_millisleep (10); - /* Add the device and assign a device address to it. */ - next_dev = grub_usb_hub_add_dev (&dev->controller, speed); - if (! next_dev) - continue; + /* Add the device and assign a device address to it. */ + next_dev = grub_usb_hub_add_dev (&dev->controller, speed); + if (! next_dev) + continue; - attached_devices[i - 1] = next_dev; + dev->children[i - 1] = next_dev; - /* If the device is a Hub, scan it for more devices. */ - if (next_dev->descdev.class == 0x09) - grub_usb_add_hub (next_dev); + /* If the device is a Hub, scan it for more devices. */ + if (next_dev->descdev.class == 0x09) + grub_usb_add_hub (next_dev); + } } } - - return; } void @@ -578,13 +442,21 @@ grub_usb_poll_devices (void) } } - /* We should check changes of non-root hubs too. */ - for (i = 0; i < GRUB_USBHUB_MAX_DEVICES; i++) + while (1) { - grub_usb_device_t dev = grub_usb_devs[i]; - - if (dev && dev->descdev.class == 0x09) - poll_nonroot_hub (dev); + rescan = 0; + + /* We should check changes of non-root hubs too. */ + for (i = 0; i < GRUB_USBHUB_MAX_DEVICES; i++) + { + grub_usb_device_t dev = grub_usb_devs[i]; + + if (dev && dev->descdev.class == 0x09) + poll_nonroot_hub (dev); + } + if (!rescan) + break; + grub_millisleep (50); } } From 8111f933ec1cf6d35488645680edd1d5b4a76730 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 30 Aug 2010 19:30:34 +0200 Subject: [PATCH 075/214] remove ieee1275/grub-install and adapt grub-install for ieee1275 --- Makefile.util.def | 4 +- util/grub-install.in | 86 ++++++++++- util/ieee1275/grub-install.in | 273 ---------------------------------- 3 files changed, 80 insertions(+), 283 deletions(-) delete mode 100644 util/ieee1275/grub-install.in diff --git a/Makefile.util.def b/Makefile.util.def index 9565dde65..0beae52ce 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -351,10 +351,10 @@ script = { i386_coreboot = util/grub-install.in; i386_multiboot = util/grub-install.in; sparc64_ieee1275 = util/grub-install.in; + i386_ieee1275 = util/grub-install.in; + powerpc_ieee1275 = util/grub-install.in; x86_efi = util/i386/efi/grub-install.in; - i386_ieee1275 = util/ieee1275/grub-install.in; - powerpc_ieee1275 = util/ieee1275/grub-install.in; enable = noemu; }; diff --git a/util/grub-install.in b/util/grub-install.in index 4a5b5a1c3..2502c7bf0 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -41,6 +41,7 @@ grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}` grub_probe=${sbindir}/`echo grub-probe | sed ${transform}` grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}` +grub_mkrelpath=${bindir}/`echo grub-mkrelpath | sed ${transform}` rootdir= grub_prefix=`echo /boot/grub | sed ${transform}` modules= @@ -52,6 +53,11 @@ recheck=no debug=no debug_image= +update_nvram=yes + +ofpathname=`which ofpathname` +nvsetenv=`which nvsetenv` + if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then disk_module=biosdisk elif [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then @@ -63,8 +69,16 @@ fi # Usage: usage # Print the usage. usage () { +if test "x$install_device" = x && test "${target_cpu}-${platform}" != "mips-yeeloong" && test "${target_cpu}-${platform}" != "i386-ieee1275" && test "${target_cpu}-${platform}" != "powerpc-ieee1275"; then cat <&2 usage exit 1 @@ -405,19 +433,61 @@ case "${target_cpu}-${platform}" in i386-pc) mkimage_target=i386-pc ;; sparc64-ieee1275) mkimage_target=sparc64-ieee1275-raw ;; mips-yeeloong) mkimage_target=mipsel-yeeloong-elf ;; - *) mkimage_target=i386-coreboot; + i386-coreboot) mkimage_target=i386-coreboot ;; + i386-multiboot) mkimage_target=i386-multiboot ;; + i386-qemu) mkimage_target=i386-multiboot ;; + i386-ieee1275) mkimage_target=i386-ieee1275 ;; + powerpc-ieee1275) mkimage_target=powerpc-ieee1275 ;; + *) echo "Unknown platform"; exit 1 ;; esac -if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then - $grub_mkimage ${config_opt} -O ${mkimage_target} --output=${grubdir}/core.img --prefix=${prefix_drive}${relative_grubdir} $modules || exit 1 +$grub_mkimage ${config_opt} -O ${mkimage_target} --output=${grubdir}/core.img --prefix=${prefix_drive}${relative_grubdir} $modules || exit 1 +# Copy to traditional location for compatibility +if [ "${target_cpu}-${platform}" = "mips-yeeloong" ]; then + cp ${grubdir}/core.img /boot/grub.elf +elif [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${platform}" = "powerpc-ieee1275" ]; then + cp ${grubdir}/core.img /boot/grub +fi + +if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then # Now perform the installation. $grub_setup ${setup_verbose} ${setup_force} --directory=${grubdir} --device-map=${device_map} \ ${install_device} || exit 1 -elif [ "${target_cpu}-${platform}" = "mips-yeeloong" ] ; then - $grub_mkimage ${config_opt} -f ${font} -d ${pkglibdir} -O ${mkimage_target} --output=/boot/grub.elf --prefix=${prefix_drive}${relative_grubdir} $modules || exit 1 -else - $grub_mkimage -O ${mkimage_target} ${config_opt} -d ${pkglibdir} --output=/boot/multiboot.img --prefix=${prefix_drive}${relative_grubdir} $modules || exit 1 +elif [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${platform}" = "powerpc-ieee1275" ]; then + if [ x"$update_nvram" = xyes ]; then + set $ofpathname dummy + if test -f "$1"; then + : + else + echo "$1: Not found." 1>&2 + exit 1 + fi + set $nvsetenv dummy + if test -f "$1"; then + : + else + echo "$1: Not found." 1>&2 + exit 1 + fi + # Get the Open Firmware device tree path translation. + dev=`echo $grub_device | sed -e 's/\/dev\///' -e 's/[0-9]\+//'` + partno=`echo $grub_device | sed -e 's/.*[^0-9]\([0-9]\+\)$/\1/'` + ofpath=`$ofpathname $dev` || { + echo "Couldn't find Open Firmware device tree path for $dev." + echo "You will have to set boot-device manually." + exit 1 + } + + # Point boot-device at the new grub install + boot_device="$ofpath:$partno,"`grub-mkrelpath ${grubdir}/core.img | sed 's,/,\\,g'` + "$nvsetenv" boot-device "$boot_device" || { + echo "$nvsetenv failed." + echo "You will have to set boot-device manually. At the Open Firmware prompt, type:" + echo " setenv boot-device $boot_device" + exit 1 + } + fi fi echo "Installation finished. No error reported." diff --git a/util/ieee1275/grub-install.in b/util/ieee1275/grub-install.in deleted file mode 100644 index 98de5f348..000000000 --- a/util/ieee1275/grub-install.in +++ /dev/null @@ -1,273 +0,0 @@ -#! /bin/sh - -# Install GRUB on your drive. -# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008 Free Software Foundation, Inc. -# -# GRUB is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# GRUB is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GRUB. If not, see . - -# This script uses `ofpathname', which is downloadable from -# http://ppc64-utils.ozlabs.org . - -# Initialize some variables. -transform="@program_transform_name@" - -prefix=@prefix@ -exec_prefix=@exec_prefix@ -sbindir=@sbindir@ -bindir=@bindir@ -libdir=@libdir@ -PACKAGE_NAME=@PACKAGE_NAME@ -PACKAGE_TARNAME=@PACKAGE_TARNAME@ -PACKAGE_VERSION=@PACKAGE_VERSION@ -target_cpu=@target_cpu@ -platform=@platform@ -pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}` - -self=`basename $0` - -grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` -grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}` -grub_probe=${sbindir}/`echo grub-probe | sed ${transform}` -grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}` -rootdir= -grub_prefix=`echo /boot/grub | sed ${transform}` -modules= - -install_device= -debug=no -update_nvram=yes - -ofpathname=`which ofpathname` -nvsetenv=`which nvsetenv` - -# Usage: usage -# Print the usage. -usage () { - cat <. -EOF -} - -argument () { - opt=$1 - shift - - if test $# -eq 0; then - echo "$0: option requires an argument -- '$opt'" 1>&2 - exit 1 - fi - echo $1 -} - -# Check the arguments. -while test $# -gt 0 -do - option=$1 - shift - - case "$option" in - -h | --help) - usage - exit 0 ;; - -v | --version) - echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" - exit 0 ;; - - --modules) - modules=`argument $option "$@"`; shift ;; - --modules=*) - modules=`echo "$option" | sed 's/--modules=//'` ;; - - --root-directory) - rootdir=`argument $option "$@"`; shift ;; - --root-directory=*) - rootdir=`echo "$option" | sed 's/--root-directory=//'` ;; - - --grub-mkdevicemap) - grub_mkdevicemap=`argument $option "$@"`; shift ;; - --grub-mkdevicemap=*) - grub_mkdevicemap=`echo "$option" | sed 's/--grub-mkdevicemap=//'` ;; - - --grub-mkimage) - grub_mkimage=`argument $option "$@"`; shift ;; - --grub-mkimage=*) - grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;; - - --grub-probe) - grub_probe=`argument $option "$@"`; shift ;; - --grub-probe=*) - grub_probe=`echo "$option" | sed 's/--grub-probe=//'` ;; - - --no-nvram) - update_nvram=no ;; - # This is an undocumented feature... - --debug) - debug=yes ;; - -*) - echo "Unrecognized option \`$option'" 1>&2 - usage - exit 1 - ;; - *) - if test "x$install_device" != x; then - echo "More than one install_devices?" 1>&2 - usage - exit 1 - fi - install_device="${option}" ;; - esac -done - -# If the debugging feature is enabled, print commands. -if test $debug = yes; then - set -x -fi - -# Initialize these directories here, since ROOTDIR was initialized. -bootdir=${rootdir}/boot -grubdir=${bootdir}/`echo grub | sed ${transform}` -device_map=${grubdir}/device.map - -set $grub_mkimage dummy -if test -f "$1"; then - : -else - echo "$1: Not found." 1>&2 - exit 1 -fi - -# Find the partition at the right mount point. -install_device=`$grub_mkdevicemap --device-map=/dev/stdout | $grub_probe --target=device --device-map=/dev/stdin ${grubdir}` - -if test "x$install_device" = "x`$grub_mkdevicemap --device-map=/dev/stdout | $grub_probe --target=device --device-map=/dev/stdin ${bootdir}`"; then - echo "$grubdir must be a mount point." - exit 1 -fi -# XXX warn on firmware-unreadable filesystems? - -# Create the GRUB directory if it is not present. -mkdir -p "$grubdir" || exit 1 - -# Create the device map file if it is not present. -if test -f "$device_map"; then - : -else - # Create a safe temporary file. - test -n "$mklog" && log_file=`$mklog` - - $grub_mkdevicemap --device-map=$device_map $no_floppy || exit 1 -fi - -# Copy the GRUB images to the GRUB directory. -for file in ${grubdir}/*.mod ${grubdir}/*.lst ; do - if test -f $file; then - rm -f $file || exit 1 - fi -done -for file in ${pkglibdir}/*.mod ${pkglibdir}/*.lst ; do - cp -f $file ${grubdir} || exit 1 -done - -if ! test -f ${grubdir}/grubenv; then - $grub_editenv ${grubdir}/grubenv create -fi - -# Create the core image. First, auto-detect the filesystem module. -fs_module=`$grub_probe --target=fs --device-map=${device_map} ${grubdir}` -if test "x$fs_module" = x -a "x$modules" = x; then - echo "Auto-detection of a filesystem module failed." 1>&2 - echo "Please specify the module with the option \`--modules' explicitly." 1>&2 - exit 1 -fi - -# Then the partition map module. In order to support partition-less media, -# this command is allowed to fail (--target=fs already grants us that the -# filesystem will be accessible). -partmap_module= -for x in `$grub_probe --target=partmap --device-map=${device_map} ${grubdir} 2> /dev/null`; do - partmap_module="$partmap_module part_$x"; -done - -# Device abstraction module, if any (lvm, raid). -devabstraction_module=`$grub_probe --target=abstraction --device-map=${device_map} ${grubdir}` - -modules="$modules $fs_module $partmap_module $devabstraction_module" - -# Now perform the installation. -"$grub_mkimage" -O ${target_cpu}-ieee1275 --directory=${pkglibdir} --output=${grubdir}/grub $modules || exit 1 - -if test $update_nvram = yes; then - set $ofpathname dummy - if test -f "$1"; then - : - else - echo "$1: Not found." 1>&2 - exit 1 - fi - - set $nvsetenv dummy - if test -f "$1"; then - : - else - echo "$1: Not found." 1>&2 - exit 1 - fi - - # Get the Open Firmware device tree path translation. - dev=`echo $install_device | sed -e 's/\/dev\///' -e 's/[0-9]\+//'` - partno=`echo $install_device | sed -e 's/.*[^0-9]\([0-9]\+\)$/\1/'` - ofpath=`$ofpathname $dev` || { - echo "Couldn't find Open Firmware device tree path for $dev." - echo "You will have to set boot-device manually." - exit 1 - } - - # Point boot-device at the new grub install - boot_device="$ofpath:$partno,\\grub" - "$nvsetenv" boot-device "$boot_device" || { - echo "$nvsetenv failed." - echo "You will have to set boot-device manually. At the Open Firmware prompt, type:" - echo " setenv boot-device $boot_device" - exit 1 - } -fi - -# Prompt the user to check if the device map is correct. -echo "Installation finished. No error reported." -echo "This is the contents of the device map $device_map." -echo "Check if this is correct or not. If any of the lines is incorrect," -echo "fix it and re-run the script \`$self'." -echo - -cat $device_map - -# Bye. -exit 0 From 37837d4ecb1526799eb2ff0a733fcd4e22e9dd90 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 30 Aug 2010 19:48:10 +0200 Subject: [PATCH 076/214] Remove leftover embedding of font objects. * include/grub/kernel.h (OBJ_TYPE_FONT): Removed. * util/grub-install.in (font): Removed. * util/grub-mkimage.c (generate_image): Remove font support. All users updated. --- ChangeLog | 9 +++++++++ include/grub/kernel.h | 3 +-- util/grub-install.in | 13 ++++--------- util/grub-mkimage.c | 34 +++------------------------------- 4 files changed, 17 insertions(+), 42 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1a0085d9a..869bd420b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2010-08-30 Vladimir Serbinenko + + Remove leftover embedding of font objects. + + * include/grub/kernel.h (OBJ_TYPE_FONT): Removed. + * util/grub-install.in (font): Removed. + * util/grub-mkimage.c (generate_image): Remove font support. All users + updated. + 2010-08-30 Vladimir Serbinenko * docs/grub.texi (Network): Fix reference to pxe_blksize. diff --git a/include/grub/kernel.h b/include/grub/kernel.h index fed875db1..2ecc73df4 100644 --- a/include/grub/kernel.h +++ b/include/grub/kernel.h @@ -26,8 +26,7 @@ enum { OBJ_TYPE_ELF, OBJ_TYPE_MEMDISK, - OBJ_TYPE_CONFIG, - OBJ_TYPE_FONT + OBJ_TYPE_CONFIG }; /* The module header. */ diff --git a/util/grub-install.in b/util/grub-install.in index 4a5b5a1c3..e6521f069 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -30,7 +30,6 @@ PACKAGE_VERSION=@PACKAGE_VERSION@ target_cpu=@target_cpu@ platform=@platform@ host_os=@host_os@ -font=@datadir@/@PACKAGE_TARNAME@/ascii.pf2 pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}` localedir=@datadir@/locale @@ -84,11 +83,6 @@ if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then cat <type = grub_host_to_target32 (OBJ_TYPE_FONT); - header->size = grub_host_to_target32 (font_size + sizeof (*header)); - offset += sizeof (*header); - - grub_util_load_image (font_path, kernel_img + offset); - offset += font_size; - } - if (config_path) { struct grub_module_header *header; @@ -1241,7 +1221,6 @@ Make a bootable image of GRUB.\n\ -d, --directory=DIR use images and modules under DIR [default=%s/@platform@]\n\ -p, --prefix=DIR set grub_prefix directory [default=%s]\n\ -m, --memdisk=FILE embed FILE as a memdisk image\n\ - -f, --font=FILE embed FILE as a boot font\n\ -c, --config=FILE embed FILE as boot config\n\ -n, --note add NOTE segment for CHRP Open Firmware\n\ -o, --output=FILE output a generated image to FILE [default=stdout]\n\ @@ -1330,13 +1309,6 @@ main (int argc, char *argv[]) prefix = xstrdup ("(memdisk)/boot/grub"); break; - case 'f': - if (font) - free (font); - - font = xstrdup (optarg); - break; - case 'c': if (config) free (config); @@ -1401,7 +1373,7 @@ main (int argc, char *argv[]) } generate_image (dir, prefix ? : DEFAULT_DIRECTORY, fp, - argv + optind, memdisk, font, config, + argv + optind, memdisk, config, image_target, note); fclose (fp); From 6c2111e96cfc3eb7ee09b460e9d62ab4fe86aa41 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 30 Aug 2010 20:27:59 +0200 Subject: [PATCH 077/214] Adapt common grub-install for efi and use it --- Makefile.util.def | 12 +- util/grub-install.in | 33 +++-- util/i386/efi/grub-install.in | 261 ---------------------------------- 3 files changed, 20 insertions(+), 286 deletions(-) delete mode 100644 util/i386/efi/grub-install.in diff --git a/Makefile.util.def b/Makefile.util.def index 0beae52ce..532ff65b7 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -345,17 +345,7 @@ script = { installdir = sbin; name = grub-install; - mips = util/grub-install.in; - i386_pc = util/grub-install.in; - i386_qemu = util/grub-install.in; - i386_coreboot = util/grub-install.in; - i386_multiboot = util/grub-install.in; - sparc64_ieee1275 = util/grub-install.in; - i386_ieee1275 = util/grub-install.in; - powerpc_ieee1275 = util/grub-install.in; - - x86_efi = util/i386/efi/grub-install.in; - + common = util/grub-install.in; enable = noemu; }; diff --git a/util/grub-install.in b/util/grub-install.in index 7511522c7..910549d30 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -425,30 +425,35 @@ else fi case "${target_cpu}-${platform}" in - i386-pc) mkimage_target=i386-pc ;; sparc64-ieee1275) mkimage_target=sparc64-ieee1275-raw ;; mips-yeeloong) mkimage_target=mipsel-yeeloong-elf ;; - i386-coreboot) mkimage_target=i386-coreboot ;; - i386-multiboot) mkimage_target=i386-multiboot ;; - i386-qemu) mkimage_target=i386-multiboot ;; - i386-ieee1275) mkimage_target=i386-ieee1275 ;; - powerpc-ieee1275) mkimage_target=powerpc-ieee1275 ;; - *) echo "Unknown platform"; exit 1 ;; + *) mkimage_target="${target_cpu}-${platform}" ;; esac -$grub_mkimage ${config_opt} -O ${mkimage_target} --output=${grubdir}/core.img --prefix=${prefix_drive}${relative_grubdir} $modules || exit 1 +case "${target_cpu}-${platform}" in + i386-efi | x86_64-efi) imgext=efi ;; + mips-yeeloong | i386-coreboot | i386-multiboot | i386-ieee1275 \ + | powerpc-ieeee1275) imgext=elf ;; + *) imgext=img ;; +esac -# Copy to traditional location for compatibility + +$grub_mkimage ${config_opt} -O ${mkimage_target} --output=${grubdir}/core.${imgext} --prefix=${prefix_drive}${relative_grubdir} $modules || exit 1 + +# Backward-compatibility kludges if [ "${target_cpu}-${platform}" = "mips-yeeloong" ]; then - cp ${grubdir}/core.img /boot/grub.elf + cp ${grubdir}/core.${imgext} /boot/grub.elf elif [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${platform}" = "powerpc-ieee1275" ]; then - cp ${grubdir}/core.img /boot/grub + cp ${grubdir}/core.${imgext} /boot/grub +elif [ "${target_cpu}-${platform}" = "i386-efi" ] || [ "${target_cpu}-${platform}" = "x86_64-efi" ]; then + $grub_mkimage ${config_opt} -O ${mkimage_target} --output=${grubdir}/grub.efi --prefix="" $modules || exit 1 fi +# Perform the platform-dependent install if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then # Now perform the installation. - $grub_setup ${setup_verbose} ${setup_force} --directory=${grubdir} --device-map=${device_map} \ - ${install_device} || exit 1 + $grub_setup ${setup_verbose} ${setup_force} --directory=${grubdir} \ + --device-map=${device_map} ${install_device} || exit 1 elif [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${platform}" = "powerpc-ieee1275" ]; then if [ x"$update_nvram" = xyes ]; then set $ofpathname dummy @@ -475,7 +480,7 @@ elif [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${pla } # Point boot-device at the new grub install - boot_device="$ofpath:$partno,"`grub-mkrelpath ${grubdir}/core.img | sed 's,/,\\,g'` + boot_device="$ofpath:$partno,"`grub-mkrelpath ${grubdir}/core.${imgext} | sed 's,/,\\,g'` "$nvsetenv" boot-device "$boot_device" || { echo "$nvsetenv failed." echo "You will have to set boot-device manually. At the Open Firmware prompt, type:" diff --git a/util/i386/efi/grub-install.in b/util/i386/efi/grub-install.in deleted file mode 100644 index d8554a328..000000000 --- a/util/i386/efi/grub-install.in +++ /dev/null @@ -1,261 +0,0 @@ -#! /bin/sh - -# Install GRUB on your EFI partition. -# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008 Free Software Foundation, Inc. -# -# GRUB is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# GRUB is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with GRUB. If not, see . - -# Initialize some variables. -transform="@program_transform_name@" - -prefix=@prefix@ -exec_prefix=@exec_prefix@ -sbindir=@sbindir@ -bindir=@bindir@ -libdir=@libdir@ -PACKAGE_NAME=@PACKAGE_NAME@ -PACKAGE_TARNAME=@PACKAGE_TARNAME@ -PACKAGE_VERSION=@PACKAGE_VERSION@ -target_cpu=@target_cpu@ -platform=@platform@ -host_os=@host_os@ -pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}` -localedir=@datadir@/locale - -self=`basename $0` - -grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` -grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}` -grub_probe=${sbindir}/`echo grub-probe | sed ${transform}` -grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}` -rootdir= -grub_prefix=`echo /boot/grub | sed ${transform}` -modules= - -no_floppy= -force_lba= -recheck=no -debug=no - -# Usage: usage -# Print the usage. -usage () { - cat <. -EOF -} - -argument () { - opt=$1 - shift - - if test $# -eq 0; then - echo "$0: option requires an argument -- '$opt'" 1>&2 - exit 1 - fi - echo $1 -} - -# Check the arguments. -while test $# -gt 0 -do - option=$1 - shift - - case "$option" in - -h | --help) - usage - exit 0 ;; - -v | --version) - echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" - exit 0 ;; - - --modules) - modules=`argument $option "$@"`; shift ;; - --modules=*) - modules=`echo "$option" | sed 's/--modules=//'` ;; - - --root-directory) - rootdir=`argument $option "$@"`; shift ;; - --root-directory=*) - rootdir=`echo "$option" | sed 's/--root-directory=//'` ;; - - --grub-mkimage) - grub_mkimage=`argument $option "$@"`; shift ;; - --grub-mkimage=*) - grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;; - - --grub-mkdevicemap) - grub_mkdevicemap=`argument $option "$@"`; shift ;; - --grub-mkdevicemap=*) - grub_mkdevicemap=`echo "$option" | sed 's/--grub-mkdevicemap=//'` ;; - - --grub-probe) - grub_probe=`argument $option "$@"`; shift ;; - --grub-probe=*) - grub_probe=`echo "$option" | sed 's/--grub-probe=//'` ;; - - --no-floppy) - no_floppy="--no-floppy" ;; - --recheck) - recheck=yes ;; - # This is an undocumented feature... - --debug) - debug=yes ;; - *) - echo "Unrecognized option \`$option'" 1>&2 - usage - exit 1 - ;; - esac -done - -# If the debugging feature is enabled, print commands. -if test $debug = yes; then - set -x -fi - -# Initialize these directories here, since ROOTDIR was initialized. -case "$host_os" in -netbsd* | openbsd*) - # Because /boot is used for the boot block in NetBSD and OpenBSD, use /grub - # instead of /boot/grub. - grub_prefix=`echo /grub | sed ${transform}` - bootdir=${rootdir} - ;; -*) - # Use /boot/grub by default. - bootdir=${rootdir}/boot - ;; -esac - -grubdir=${bootdir}/`echo grub | sed ${transform}` -device_map=${grubdir}/device.map - -# Check if GRUB is installed. -set $grub_mkimage dummy -if test -f "$1"; then - : -else - echo "$1: Not found." 1>&2 - exit 1 -fi - -set $grub_mkdevicemap dummy -if test -f "$1"; then - : -else - echo "$1: Not found." 1>&2 - exit 1 -fi - -# Create the GRUB directory if it is not present. -mkdir -p "$grubdir" || exit 1 - -# If --recheck is specified, remove the device map, if present. -if test $recheck = yes; then - rm -f $device_map -fi - -# Create the device map file if it is not present. -if test -f "$device_map"; then - : -else - # Create a safe temporary file. - test -n "$mklog" && log_file=`$mklog` - - $grub_mkdevicemap --device-map=$device_map $no_floppy || exit 1 -fi - -# Make sure that there is no duplicated entry. -tmp=`sed -n '/^([fh]d[0-9]*)/s/\(^(.*)\).*/\1/p' $device_map \ - | sort | uniq -d | sed -n 1p` -if test -n "$tmp"; then - echo "The drive $tmp is defined multiple times in the device map $device_map" 1>&2 - exit 1 -fi - -# Copy the GRUB images to the GRUB directory. -for file in ${grubdir}/*.mod ${grubdir}/*.lst; do - if test -f $file && [ "`basename $file`" != menu.lst ]; then - rm -f $file || exit 1 - fi -done -for file in ${pkglibdir}/*.mod ${pkglibdir}/*.lst; do - cp -f $file ${grubdir} || exit 1 -done - -# Copy gettext files -mkdir -p ${grubdir}/locale/ -for dir in ${localedir}/*; do - if test -f "$dir/LC_MESSAGES/grub.mo"; then - cp -f "$dir/LC_MESSAGES/grub.mo" "${grubdir}/locale/${dir##*/}.mo" - fi -done - -if ! test -f ${grubdir}/grubenv; then - $grub_editenv ${grubdir}/grubenv create -fi - -# Create the core image. First, auto-detect the filesystem module. -fs_module=`$grub_probe --target=fs --device-map=${device_map} ${grubdir}` -if test "x$fs_module" = xfat; then :; else - echo "${grubdir} doesn't look like an EFI partition." 1>&2 - exit 1 -fi - -# Then the partition map module. In order to support partition-less media, -# this command is allowed to fail (--target=fs already grants us that the -# filesystem will be accessible). -partmap_module= -for x in `$grub_probe --target=partmap --device-map=${device_map} ${grubdir} 2> /dev/null`; do - partmap_module="$partmap_module part_$x"; -done - -# Device abstraction module, if any (lvm, raid). -devabstraction_module=`$grub_probe --target=abstraction --device-map=${device_map} ${grubdir}` - -# The order in this list is critical. Be careful when modifying it. -modules="$modules $fs_module $partmap_module $devabstraction_module" - -$grub_mkimage -p "" -O ${target_cpu}-efi --output=${grubdir}/grub.efi $modules || exit 1 - -# Prompt the user to check if the device map is correct. -echo "Installation finished. No error reported." -echo "This is the contents of the device map $device_map." -echo "Check if this is correct or not. If any of the lines is incorrect," -echo "fix it and re-run the script \`$self'." -echo - -cat $device_map - -# Bye. -exit 0 From 861d5b5c72578b3f95987c9f4d89a83f0da0f61d Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Mon, 30 Aug 2010 21:00:48 +0200 Subject: [PATCH 078/214] Import EFI patch by cjwatson --- util/grub-install.in | 132 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) diff --git a/util/grub-install.in b/util/grub-install.in index 910549d30..4ce451d11 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -24,6 +24,7 @@ exec_prefix=@exec_prefix@ sbindir=@sbindir@ bindir=@bindir@ libdir=@libdir@ +sysconfdir=@sysconfdir@ PACKAGE_NAME=@PACKAGE_NAME@ PACKAGE_TARNAME=@PACKAGE_TARNAME@ PACKAGE_VERSION=@PACKAGE_VERSION@ @@ -56,6 +57,9 @@ update_nvram=yes ofpathname=`which ofpathname` nvsetenv=`which nvsetenv` +efibootmgr=`which efibootmgr 2>/dev/null || true` +removable=no +efi_quiet= if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then disk_module=biosdisk @@ -103,6 +107,11 @@ if [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${platf cat <&2 + efidir= + fi + fi + + if test -n "$efidir"; then + # The EFI specification requires that an EFI System Partition must + # contain an "EFI" subdirectory, and that OS loaders are stored in + # subdirectories below EFI. Vendors are expected to pick names that do + # not collide with other vendors. To minimise collisions, we use the + # name of our distributor if possible. + if test $removable = yes; then + # The specification makes stricter requirements of removable + # devices, in order that only one image can be automatically loaded + # from them. The image must always reside under /EFI/BOOT, and it + # must have a specific file name depending on the architecture. + efi_distributor=BOOT + case "$target_cpu" in + i386) + efi_file=BOOTIA32.EFI ;; + x86-64) + efi_file=BOOTX64.EFI ;; + # GRUB does not yet support these architectures, but they're defined + # by the specification so we include them here to ease future + # expansion. + ia64) + efi_file=BOOTIA64.EFI ;; + esac + else + efi_distributor="$(echo "$GRUB_DISTRIBUTOR" | tr '[A-Z]' '[a-z]' | cut -d' ' -f1)" + if test -z "$efi_distributor"; then + efi_distributor=grub + fi + # It is convenient for each architecture to have a different + # efi_file, so that different versions can be installed in parallel. + case "$target_cpu" in + i386) + efi_file=grubia32.efi ;; + x86-64) + efi_file=grubx64.efi ;; + # GRUB does not yet support these architectures, but they're defined + # by the specification so we include them here to ease future + # expansion. + ia64) + efi_file=grubia64.efi ;; + *) + efi_file=grub.efi ;; + esac + # TODO: We should also use efibootmgr, if available, to add a Boot + # entry for ourselves. + fi + efidir="$efidir/EFI/$efi_distributor" + mkdir -p "$efidir" || exit 1 + else + # We don't know what's going on. Fall back to traditional + # (non-specification-compliant) behaviour. + efidir="$grubdir" + efi_distributor= + efi_file=grub.efi + fi + cp ${grubdir}/core.${imgext} ${efidir}/${efi_file} + # Try to make this image bootable using the EFI Boot Manager, if available. + if test "$removable" = no && test -n "$efi_distributor" && \ + test -n "$efibootmgr"; then + # On Linux, we need the efivars kernel modules. + case "$host_os" in + linux*) + modprobe -q efivars 2>/dev/null || true ;; + esac + + # Delete old entries from the same distributor. + for bootnum in `efibootmgr | grep '^Boot[0-9]' | \ + fgrep " $efi_distributor" | cut -b5-8`; do + efibootmgr $efi_quiet -b "$bootnum" -B + done + + # Add a new entry for the image we just created. efibootmgr needs to be + # given the disk device and partition number separately, so we have to + # fiddle about with grub-probe to get hold of this reasonably reliably. + # Use fresh device map text to avoid any problems with stale data, since + # all we need here is a one-to-one mapping. + clean_devmap="$($grub_mkdevicemap --device-map=/dev/stdout)" + efidir_drive="$(echo "$clean_devmap" | $grub_probe --target=drive --device-map=/dev/stdin "$efidir")" + if test -z "$efidir_drive"; then + echo "Can't find GRUB drive for $efidir; unable to create EFI Boot Manager entry." >&2 + else + efidir_disk="$(echo "$clean_devmap" | grep "^$(echo "$efidir_drive" | sed 's/,[^)]*//')" | cut -f2)" + efidir_part="$(echo "$efidir_drive" | sed 's/^([^,]*,[^0-9]*//; s/[^0-9].*//')" + efibootmgr $efi_quiet -c -d "$efidir_disk" -p "$efidir_part" -w \ + -L "$GRUB_DISTRIBUTOR" -l "\\EFI\\$efi_distributor\\$efi_file" + fi + fi + fi echo "Installation finished. No error reported." From 1782b135e50c7bf98b348ef4e02d9833d738ae2b Mon Sep 17 00:00:00 2001 From: Tristan Gingold Date: Wed, 1 Sep 2010 01:05:32 +0200 Subject: [PATCH 079/214] * commands/lsacpi.c: New file. * grub-core/Makefile.core.def (lsacpi): New module. * include/grub/acpi.h (GRUB_ACPI_FADT_SIGNATURE): New definition. (GRUB_ACPI_MADT_SIGNATURE): Likewise. (grub_acpi_madt_entry_header): New struct. (grub_acpi_madt): Likewise. (grub_acpi_madt_entry_interrupt_override): Likewise. (grub_acpi_madt_entry_sapic): Likewise. (grub_acpi_madt_entry_lsapic): Likewise. (grub_acpi_madt_entry_platform_int_source): Likewise. * include/grub/types.h (PRIxGRUB_UINT32_T): New definition. (PRIuGRUB_UINT32_T): Likewise. (PRIxGRUB_UINT64_T): Likewise. Also-By: Robert Millan Also-By: Vladimir Serbinenko --- ChangeLog.gingold1 | 17 +++ grub-core/Makefile.core.def | 13 +- grub-core/commands/acpi.c | 4 +- grub-core/commands/lsacpi.c | 250 ++++++++++++++++++++++++++++++++++++ include/grub/acpi.h | 73 +++++++++++ include/grub/types.h | 4 + 6 files changed, 358 insertions(+), 3 deletions(-) create mode 100644 ChangeLog.gingold1 create mode 100644 grub-core/commands/lsacpi.c diff --git a/ChangeLog.gingold1 b/ChangeLog.gingold1 new file mode 100644 index 000000000..b2bef5d0c --- /dev/null +++ b/ChangeLog.gingold1 @@ -0,0 +1,17 @@ +2008-01-28 Tristan Gingold +2010-01-18 Robert Millan +2010-08-31 Vladimir Serbinenko + + * commands/lsacpi.c: New file. + * grub-core/Makefile.core.def (lsacpi): New module. + * include/grub/acpi.h (GRUB_ACPI_FADT_SIGNATURE): New definition. + (GRUB_ACPI_MADT_SIGNATURE): Likewise. + (grub_acpi_madt_entry_header): New struct. + (grub_acpi_madt): Likewise. + (grub_acpi_madt_entry_interrupt_override): Likewise. + (grub_acpi_madt_entry_sapic): Likewise. + (grub_acpi_madt_entry_lsapic): Likewise. + (grub_acpi_madt_entry_platform_int_source): Likewise. + * include/grub/types.h (PRIxGRUB_UINT32_T): New definition. + (PRIuGRUB_UINT32_T): Likewise. + (PRIxGRUB_UINT64_T): Likewise. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 353b9d123..6f116770e 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -402,7 +402,7 @@ module = { module = { name = acpi; - x86 = commands/acpi.c; + common = commands/acpi.c; x86_efi = commands/efi/acpi.c; i386_pc = commands/i386/pc/acpi.c; i386_coreboot = commands/i386/pc/acpi.c; @@ -414,6 +414,17 @@ module = { enable = i386_multiboot; }; +module = { + name = lsacpi; + + common = commands/lsacpi.c; + + enable = x86_efi; + enable = i386_pc; + enable = i386_coreboot; + enable = i386_multiboot; +}; + module = { name = blocklist; common = commands/blocklist.c; diff --git a/grub-core/commands/acpi.c b/grub-core/commands/acpi.c index 884ddf000..016e6fd9c 100644 --- a/grub-core/commands/acpi.c +++ b/grub-core/commands/acpi.c @@ -325,7 +325,7 @@ setup_common_tables (void) /* If it's FADT correct DSDT and FACS addresses. */ fadt = (struct grub_acpi_fadt *) cur->addr; - if (grub_memcmp (fadt->hdr.signature, "FACP", + if (grub_memcmp (fadt->hdr.signature, GRUB_ACPI_FADT_SIGNATURE, sizeof (fadt->hdr.signature)) == 0) { fadt->dsdt_addr = PTR_TO_UINT32 (table_dsdt); @@ -529,7 +529,7 @@ grub_cmd_acpi (struct grub_extcmd *cmd, struct grub_acpi_fadt *fadt = (struct grub_acpi_fadt *) curtable; /* Set root header variables to the same values - as FACP by default. */ + as FADT by default. */ grub_memcpy (&root_oemid, &(fadt->hdr.oemid), sizeof (root_oemid)); grub_memcpy (&root_oemtable, &(fadt->hdr.oemtable), diff --git a/grub-core/commands/lsacpi.c b/grub-core/commands/lsacpi.c new file mode 100644 index 000000000..d20b80fed --- /dev/null +++ b/grub-core/commands/lsacpi.c @@ -0,0 +1,250 @@ +/* acpi.c - Display acpi tables. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ +#include +#include +#include +#include +#include +#include +#include +#include + +static void +print_strn (grub_uint8_t *str, grub_size_t len) +{ + for (; *str && len; str++, len--) + grub_printf ("%c", *str); + for (len++; len; len--) + grub_printf (" "); +} + +#define print_field(x) print_strn(x, sizeof (x)) + +static void +disp_acpi_table (struct grub_acpi_table_header *t) +{ + print_field (t->signature); + grub_printf ("%4" PRIuGRUB_UINT32_T "B rev=%u OEM=", t->length, t->revision); + print_field (t->oemid); + print_field (t->oemtable); + grub_printf ("OEMrev=%08" PRIxGRUB_UINT32_T " ", t->oemrev); + print_field (t->creator_id); + grub_printf (" %08" PRIxGRUB_UINT32_T "\n", t->creator_rev); +} + +static void +disp_madt_table (struct grub_acpi_madt *t) +{ + struct grub_acpi_madt_entry_header *d; + grub_uint32_t len; + + disp_acpi_table (&t->hdr); + grub_printf ("Local APIC=%08" PRIxGRUB_UINT32_T " Flags=%08" + PRIxGRUB_UINT32_T "\n", + t->lapic_addr, t->flags); + len = t->hdr.length - sizeof (struct grub_acpi_madt); + d = t->entries; + for (;len > 0; len -= d->len, d = (void *) ((grub_uint8_t *) d + d->len)) + { + grub_printf (" type=%x l=%u ", d->type, d->len); + + switch (d->type) + { + case GRUB_ACPI_MADT_ENTRY_TYPE_INTERRUPT_OVERRIDE: + { + struct grub_acpi_madt_entry_interrupt_override *dt = (void *) d; + grub_printf ("Int Override bus=%x src=%x GSI=%08x Flags=%04x\n", + dt->bus, dt->source, dt->global_sys_interrupt, + dt->flags); + } + break; + case GRUB_ACPI_MADT_ENTRY_TYPE_SAPIC: + { + struct grub_acpi_madt_entry_sapic *dt = (void *) d; + grub_printf ("IOSAPIC Id=%02x GSI=%08x Addr=%016" PRIxGRUB_UINT64_T + "\n", + dt->id, dt->global_sys_interrupt_base, + dt->addr); + } + break; + case GRUB_ACPI_MADT_ENTRY_TYPE_LSAPIC: + { + struct grub_acpi_madt_entry_lsapic *dt = (void *) d; + grub_printf ("LSAPIC ProcId=%02x ID=%02x EID=%02x Flags=%x", + dt->cpu_id, dt->id, dt->eid, dt->flags); + if (dt->flags & GRUB_ACPI_MADT_ENTRY_SAPIC_FLAGS_ENABLED) + grub_printf (" Enabled\n"); + else + grub_printf (" Disabled\n"); + if (d->len > sizeof (struct grub_acpi_madt_entry_sapic)) + grub_printf (" UID val=%08x, Str=%s\n", dt->cpu_uid, + dt->cpu_uid_str); + } + break; + case GRUB_ACPI_MADT_ENTRY_TYPE_PLATFORM_INT_SOURCE: + { + struct grub_acpi_madt_entry_platform_int_source *dt = (void *) d; + static const char * const platint_type[] = + {"Nul", "PMI", "INIT", "CPEI"}; + + grub_printf ("Platform INT flags=%04x type=%02x (%s)" + " ID=%02x EID=%02x\n", + dt->flags, dt->inttype, + (dt->inttype < ARRAY_SIZE (platint_type)) + ? platint_type[dt->inttype] : "??", dt->cpu_id, + dt->cpu_eid); + grub_printf (" IOSAPIC Vec=%02x GSI=%08x source flags=%08x\n", + dt->sapic_vector, dt->global_sys_int, dt->src_flags); + } + break; + default: + grub_printf (" ??\n"); + } + } +} + +static void +disp_acpi_xsdt_table (struct grub_acpi_table_header *t) +{ + grub_uint32_t len; + grub_uint64_t *desc; + + disp_acpi_table (t); + len = t->length - sizeof (*t); + desc = (grub_uint64_t *) (t + 1); + for (; len > 0; desc++, len -= sizeof (*desc)) + { + if (sizeof (grub_addr_t) == 4 && *desc >= (1ULL << 32)) + { + grub_printf ("Unreachable table\n"); + continue; + } + t = (struct grub_acpi_table_header *) (grub_addr_t) *desc; + + if (t == NULL) + continue; + + if (grub_memcmp (t->signature, GRUB_ACPI_MADT_SIGNATURE, + sizeof (t->signature)) == 0) + disp_madt_table ((struct grub_acpi_madt *) t); + else + disp_acpi_table (t); + } +} + +static void +disp_acpi_rsdt_table (struct grub_acpi_table_header *t) +{ + grub_uint32_t len; + grub_uint32_t *desc; + + disp_acpi_table (t); + len = t->length - sizeof (*t); + desc = (grub_uint32_t *) (t + 1); + for (; len > 0; desc++, len -= sizeof (*desc)) + { + t = (struct grub_acpi_table_header *) (grub_addr_t) *desc; + + if (t == NULL) + continue; + + if (grub_memcmp (t->signature, GRUB_ACPI_MADT_SIGNATURE, + sizeof (t->signature)) == 0) + disp_madt_table ((struct grub_acpi_madt *) t); + else + disp_acpi_table (t); + } +} + +static void +disp_acpi_rsdpv1 (struct grub_acpi_rsdp_v10 *rsdp) +{ + print_field (rsdp->signature); + grub_printf ("chksum:%02x, OEM-ID: ", rsdp->checksum); + print_field (rsdp->oemid); + grub_printf ("rev=%d\n", rsdp->revision); + grub_printf ("RSDT=%08" PRIxGRUB_UINT32_T "\n", rsdp->rsdt_addr); +} + +static void +disp_acpi_rsdpv2 (struct grub_acpi_rsdp_v20 *rsdp) +{ + disp_acpi_rsdpv1 (&rsdp->rsdpv1); + grub_printf ("len=%d XSDT=%016" PRIxGRUB_UINT64_T "\n", rsdp->length, + rsdp->xsdt_addr); +} + +static const struct grub_arg_option options[] = { + {"v1", '1', 0, N_("Show v1 tables only."), 0, ARG_TYPE_NONE}, + {"v2", '2', 0, N_("Show v2 and v3 tablesv only."), 0, ARG_TYPE_NONE} +}; + +static grub_err_t +grub_cmd_lsacpi (struct grub_extcmd *cmd, int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + if (!cmd->state[1].set) + { + struct grub_acpi_rsdp_v10 *rsdp1 = grub_acpi_get_rsdpv1 (); + if (!rsdp1) + grub_printf ("No RSDPv1\n"); + else + { + grub_printf ("RSDPv1 signature:"); + disp_acpi_rsdpv1 (rsdp1); + disp_acpi_rsdt_table ((void *) (grub_addr_t) rsdp1->rsdt_addr); + } + } + + if (!cmd->state[0].set) + { + struct grub_acpi_rsdp_v20 *rsdp2 = grub_acpi_get_rsdpv2 (); + if (!rsdp2) + grub_printf ("No RSDPv2\n"); + else + { + if (sizeof (grub_addr_t) == 4 && rsdp2->xsdt_addr >= (1ULL << 32)) + grub_printf ("Unreachable RSDPv2\n"); + else + { + grub_printf ("RSDPv2 signature:"); + disp_acpi_rsdpv2 (rsdp2); + disp_acpi_xsdt_table ((void *) (grub_addr_t) rsdp2->xsdt_addr); + grub_printf ("\n"); + } + } + } + return GRUB_ERR_NONE; +} + +static grub_extcmd_t cmd; + +GRUB_MOD_INIT(lsapi) +{ + cmd = grub_register_extcmd ("lsacpi", grub_cmd_lsacpi, GRUB_COMMAND_FLAG_BOTH, + N_("[-1|-2]"), + N_("Show ACPI information."), options); +} + +GRUB_MOD_FINI(lsacpi) +{ + grub_unregister_extcmd (cmd); +} + + diff --git a/include/grub/acpi.h b/include/grub/acpi.h index 7933db824..17ffd7686 100644 --- a/include/grub/acpi.h +++ b/include/grub/acpi.h @@ -53,6 +53,8 @@ struct grub_acpi_table_header grub_uint32_t creator_rev; } __attribute__ ((packed)); +#define GRUB_ACPI_FADT_SIGNATURE "FACP" + struct grub_acpi_fadt { struct grub_acpi_table_header hdr; @@ -64,6 +66,77 @@ struct grub_acpi_fadt grub_uint8_t somefields2[96]; } __attribute__ ((packed)); +#define GRUB_ACPI_MADT_SIGNATURE "APIC" + +struct grub_acpi_madt_entry_header +{ + grub_uint8_t type; + grub_uint8_t len; +}; + +struct grub_acpi_madt +{ + struct grub_acpi_table_header hdr; + grub_uint32_t lapic_addr; + grub_uint32_t flags; + struct grub_acpi_madt_entry_header entries[0]; +}; + +enum + { + GRUB_ACPI_MADT_ENTRY_TYPE_INTERRUPT_OVERRIDE = 2, + GRUB_ACPI_MADT_ENTRY_TYPE_SAPIC = 6, + GRUB_ACPI_MADT_ENTRY_TYPE_LSAPIC = 7, + GRUB_ACPI_MADT_ENTRY_TYPE_PLATFORM_INT_SOURCE = 8 + }; + +struct grub_acpi_madt_entry_interrupt_override +{ + struct grub_acpi_madt_entry_header hdr; + grub_uint8_t bus; + grub_uint8_t source; + grub_uint32_t global_sys_interrupt; + grub_uint16_t flags; +}; + +struct grub_acpi_madt_entry_sapic +{ + struct grub_acpi_madt_entry_header hdr; + grub_uint8_t id; + grub_uint8_t pad; + grub_uint32_t global_sys_interrupt_base; + grub_uint64_t addr; +}; + +struct grub_acpi_madt_entry_lsapic +{ + struct grub_acpi_madt_entry_header hdr; + grub_uint8_t cpu_id; + grub_uint8_t id; + grub_uint8_t eid; + grub_uint8_t pad[3]; + grub_uint32_t flags; + grub_uint32_t cpu_uid; + grub_uint8_t cpu_uid_str[0]; +}; + +struct grub_acpi_madt_entry_platform_int_source +{ + struct grub_acpi_madt_entry_header hdr; + grub_uint16_t flags; + grub_uint8_t inttype; + grub_uint8_t cpu_id; + grub_uint8_t cpu_eid; + grub_uint8_t sapic_vector; + grub_uint32_t global_sys_int; + grub_uint32_t src_flags; +}; + +enum + { + GRUB_ACPI_MADT_ENTRY_SAPIC_FLAGS_ENABLED = 1 + }; + struct grub_acpi_rsdp_v10 *grub_acpi_get_rsdpv1 (void); struct grub_acpi_rsdp_v20 *grub_acpi_get_rsdpv2 (void); struct grub_acpi_rsdp_v10 *grub_machine_acpi_get_rsdpv1 (void); diff --git a/include/grub/types.h b/include/grub/types.h index 4499e4538..1cabc2ecf 100644 --- a/include/grub/types.h +++ b/include/grub/types.h @@ -69,10 +69,14 @@ typedef long long grub_int64_t; typedef unsigned char grub_uint8_t; typedef unsigned short grub_uint16_t; typedef unsigned grub_uint32_t; +# define PRIxGRUB_UINT32_T "x" +# define PRIuGRUB_UINT32_T "u" #if GRUB_CPU_SIZEOF_LONG == 8 typedef unsigned long grub_uint64_t; +# define PRIxGRUB_UINT64_T "lx" #else typedef unsigned long long grub_uint64_t; +# define PRIxGRUB_UINT64_T "llx" #endif /* Misc types. */ From 105de6a758c1015f7999d35a3afa484fa69906f1 Mon Sep 17 00:00:00 2001 From: Tristan Gingold Date: Wed, 1 Sep 2010 02:37:17 +0200 Subject: [PATCH 080/214] * grub-core/commands/efi/lsefisystab.c: New file. * grub-core/commands/efi/lssal.c: Likewise. * grub-core/Makefile.core.def (lsacpi): New module. (lsefisystab): Likewise. * include/grub/efi/api.h (GRUB_EFI_SAL_TABLE_GUID): New definition. (GRUB_EFI_HCDP_TABLE_GUID): Likewise. (grub_efi_sal_system_table): New struct. (grub_efi_sal_system_table_entrypoint_descriptor): Likewise. (grub_efi_sal_system_table_memory_descriptor): Likewise. (grub_efi_sal_system_table_platform_features): Likewise. (grub_efi_sal_system_table_translation_register_descriptor): Likewise. (grub_efi_sal_system_table_purge_translation_coherence): Likewise. (grub_efi_sal_system_table_ap_wakeup): Likewise. * include/grub/types.h (PRIuGRUB_UINT64_T): New definition. Also-By: Robert Millan Also-By: Vladimir Serbinenko --- ChangeLog.gingold2 | 18 +++ grub-core/Makefile.core.def | 16 +++ grub-core/commands/efi/lsefisystab.c | 106 ++++++++++++++++++ grub-core/commands/efi/lssal.c | 162 +++++++++++++++++++++++++++ include/grub/efi/api.h | 103 +++++++++++++++++ include/grub/types.h | 2 + 6 files changed, 407 insertions(+) create mode 100644 ChangeLog.gingold2 create mode 100644 grub-core/commands/efi/lsefisystab.c create mode 100644 grub-core/commands/efi/lssal.c diff --git a/ChangeLog.gingold2 b/ChangeLog.gingold2 new file mode 100644 index 000000000..517a2cce1 --- /dev/null +++ b/ChangeLog.gingold2 @@ -0,0 +1,18 @@ +2008-01-28 Tristan Gingold +2010-01-18 Robert Millan +2010-08-31 Vladimir Serbinenko + + * grub-core/commands/efi/lsefisystab.c: New file. + * grub-core/commands/efi/lssal.c: Likewise. + * grub-core/Makefile.core.def (lsacpi): New module. + (lsefisystab): Likewise. + * include/grub/efi/api.h (GRUB_EFI_SAL_TABLE_GUID): New definition. + (GRUB_EFI_HCDP_TABLE_GUID): Likewise. + (grub_efi_sal_system_table): New struct. + (grub_efi_sal_system_table_entrypoint_descriptor): Likewise. + (grub_efi_sal_system_table_memory_descriptor): Likewise. + (grub_efi_sal_system_table_platform_features): Likewise. + (grub_efi_sal_system_table_translation_register_descriptor): Likewise. + (grub_efi_sal_system_table_purge_translation_coherence): Likewise. + (grub_efi_sal_system_table_ap_wakeup): Likewise. + * include/grub/types.h (PRIuGRUB_UINT64_T): New definition. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 6f116770e..f9cf382f2 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -425,6 +425,22 @@ module = { enable = i386_multiboot; }; +module = { + name = lsefisystab; + + common = commands/efi/lsefisystab.c; + + enable = x86_efi; +}; + +module = { + name = lssal; + + common = commands/efi/lssal.c; + + enable = x86_efi; +}; + module = { name = blocklist; common = commands/blocklist.c; diff --git a/grub-core/commands/efi/lsefisystab.c b/grub-core/commands/efi/lsefisystab.c new file mode 100644 index 000000000..90f7bf0d1 --- /dev/null +++ b/grub-core/commands/efi/lsefisystab.c @@ -0,0 +1,106 @@ +/* systab.c - Display EFI systab. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ +#include +#include +#include +#include +#include +#include +#include + +struct guid_mapping +{ + grub_efi_guid_t guid; + const char *name; +}; + +static const struct guid_mapping guid_mappings[] = + { + { GRUB_EFI_ACPI_20_TABLE_GUID, "ACPI-2.0"}, + { GRUB_EFI_ACPI_TABLE_GUID, "ACPI-1.0"}, + { GRUB_EFI_SAL_TABLE_GUID, "SAL"}, + { GRUB_EFI_SMBIOS_TABLE_GUID, "SMBIOS"}, + { GRUB_EFI_MPS_TABLE_GUID, "MPS"}, + { GRUB_EFI_HCDP_TABLE_GUID, "HCDP"} + }; + +static grub_err_t +grub_cmd_lsefisystab (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + const grub_efi_system_table_t *st = grub_efi_system_table; + grub_efi_configuration_table_t *t; + unsigned int i; + + grub_printf ("Signature: %016" PRIxGRUB_UINT64_T " revision: %08x\n", + st->hdr.signature, st->hdr.revision); + { + char *vendor; + grub_uint16_t *vendor_utf16; + grub_printf ("Vendor: "); + + for (vendor_utf16 = st->firmware_vendor; *vendor_utf16; vendor_utf16++); + vendor = grub_malloc (4 * (vendor_utf16 - st->firmware_vendor) + 1); + if (!vendor) + return grub_errno; + *grub_utf16_to_utf8 ((grub_uint8_t *) vendor, st->firmware_vendor, + vendor_utf16 - st->firmware_vendor) = 0; + grub_printf ("%s", vendor); + } + + grub_printf (", Version=%x\n", st->firmware_revision); + + grub_printf ("%ld tables:\n", st->num_table_entries); + t = st->configuration_table; + for (i = 0; i < st->num_table_entries; i++) + { + unsigned int j; + + grub_printf ("%p ", t->vendor_table); + + grub_printf ("%08x-%04x-%04x-", + t->vendor_guid.data1, t->vendor_guid.data2, + t->vendor_guid.data3); + for (j = 0; j < 8; j++) + grub_printf ("%02x", t->vendor_guid.data4[j]); + + for (j = 0; j < ARRAY_SIZE (guid_mappings); j++) + if (grub_memcmp (&guid_mappings[j].guid, &t->vendor_guid, + sizeof (grub_efi_guid_t)) == 0) + grub_printf (" %s", guid_mappings[j].name); + + grub_printf ("\n"); + t++; + } + return GRUB_ERR_NONE; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(lsefisystab) +{ + cmd = grub_register_command ("lsefisystab", grub_cmd_lsefisystab, + "", "Display EFI system tables."); +} + +GRUB_MOD_FINI(lsefisystab) +{ + grub_unregister_command (cmd); +} diff --git a/grub-core/commands/efi/lssal.c b/grub-core/commands/efi/lssal.c new file mode 100644 index 000000000..245883f90 --- /dev/null +++ b/grub-core/commands/efi/lssal.c @@ -0,0 +1,162 @@ +/* systab.c - Display EFI systab. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2008 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ +#include +#include +#include +#include +#include +#include +#include + +static void +disp_sal (void *table) +{ + struct grub_efi_sal_system_table *t = table; + void *desc; + grub_uint32_t len, l; + + grub_printf ("SAL rev: %02x, signature: %x, len:%x\n", + t->sal_rev, t->signature, t->total_table_len); + grub_printf ("nbr entry: %d, chksum: %02x, SAL version A: %02x B: %02x\n", + t->entry_count, t->checksum, + t->sal_a_version, t->sal_b_version); + grub_printf ("OEM-ID: %-32s\n", t->oem_id); + grub_printf ("Product-ID: %-32s\n", t->product_id); + + desc = t->entries; + len = t->total_table_len - sizeof (struct grub_efi_sal_system_table); + while (len > 0) + { + switch (*(grub_uint8_t *) desc) + { + case GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_ENTRYPOINT_DESCRIPTOR: + { + struct grub_efi_sal_system_table_entrypoint_descriptor *c = desc; + l = sizeof (*c); + grub_printf (" Entry point: PAL=%016" PRIxGRUB_UINT64_T + " SAL=%016" PRIxGRUB_UINT64_T " GP=%016" + PRIxGRUB_UINT64_T "\n", + c->pal_proc_addr, c->sal_proc_addr, + c->global_data_ptr); + } + break; + case GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_MEMORY_DESCRIPTOR: + { + struct grub_efi_sal_system_table_memory_descriptor *c = desc; + l = sizeof (*c); + grub_printf (" Memory descriptor entry addr=%016" PRIxGRUB_UINT64_T + " len=%" PRIuGRUB_UINT64_T "KB\n", + c->addr, c->len * 4); + grub_printf (" sal_used=%d attr=%x AR=%x attr_mask=%x " + "type=%x usage=%x\n", + c->sal_used, c->attr, c->ar, c->attr_mask, c->mem_type, + c->usage); + } + break; + case GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_PLATFORM_FEATURES: + { + struct grub_efi_sal_system_table_platform_features *c = desc; + l = sizeof (*c); + grub_printf (" Platform features: %02x", c->flags); + if (c->flags & GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_BUSLOCK) + grub_printf (" BusLock"); + if (c->flags & GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_IRQREDIRECT) + grub_printf (" IrqRedirect"); + if (c->flags & GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_IPIREDIRECT) + + grub_printf (" IPIRedirect"); + if (c->flags & GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_ITCDRIFT) + + grub_printf (" ITCDrift"); + grub_printf ("\n"); + } + break; + case GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_TRANSLATION_REGISTER_DESCRIPTOR: + { + struct grub_efi_sal_system_table_translation_register_descriptor *c + = desc; + l = sizeof (*c); + grub_printf (" TR type=%d num=%d va=%016" PRIxGRUB_UINT64_T + " pte=%016" PRIxGRUB_UINT64_T "\n", + c->register_type, c->register_number, + c->addr, c->page_size); + } + break; + case GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_PURGE_TRANSLATION_COHERENCE: + { + struct grub_efi_sal_system_table_purge_translation_coherence *c + = desc; + l = sizeof (*c); + grub_printf (" PTC coherence nbr=%d addr=%016" PRIxGRUB_UINT64_T "\n", + c->ndomains, c->coherence); + } + break; + case GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_AP_WAKEUP: + { + struct grub_efi_sal_system_table_ap_wakeup *c = desc; + l = sizeof (*c); + grub_printf (" AP wake-up: mec=%d vect=%" PRIxGRUB_UINT64_T "\n", + c->mechanism, c->vector); + } + break; + default: + grub_printf (" unknown entry 0x%x\n", *(grub_uint8_t *)desc); + return; + } + desc = (grub_uint8_t *)desc + l; + len -= l; + } +} + +static grub_err_t +grub_cmd_lssal (struct grub_command *cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + const grub_efi_system_table_t *st = grub_efi_system_table; + grub_efi_configuration_table_t *t = st->configuration_table; + unsigned int i; + grub_efi_guid_t guid = GRUB_EFI_SAL_TABLE_GUID; + + for (i = 0; i < st->num_table_entries; i++) + { + if (grub_memcmp (&guid, &t->vendor_guid, + sizeof (grub_efi_guid_t)) == 0) + { + disp_sal (t->vendor_table); + return GRUB_ERR_NONE; + } + t++; + } + grub_printf ("SAL not found\n"); + return GRUB_ERR_NONE; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(lssal) +{ + cmd = grub_register_command ("lssal", grub_cmd_lssal, "", + "Display SAL system table."); +} + +GRUB_MOD_FINI(lssal) +{ + grub_unregister_command (cmd); +} diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h index 36363ae1e..5eededdc2 100644 --- a/include/grub/efi/api.h +++ b/include/grub/efi/api.h @@ -109,6 +109,109 @@ { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ } +#define GRUB_EFI_SAL_TABLE_GUID \ + { 0xeb9d2d32, 0x2d88, 0x11d3, \ + { 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +#define GRUB_EFI_HCDP_TABLE_GUID \ + { 0xf951938d, 0x620b, 0x42ef, \ + { 0x82, 0x79, 0xa8, 0x4b, 0x79, 0x61, 0x78, 0x98 } \ + } + +struct grub_efi_sal_system_table +{ + grub_uint32_t signature; + grub_uint32_t total_table_len; + grub_uint16_t sal_rev; + grub_uint16_t entry_count; + grub_uint8_t checksum; + grub_uint8_t reserved1[7]; + grub_uint16_t sal_a_version; + grub_uint16_t sal_b_version; + grub_uint8_t oem_id[32]; + grub_uint8_t product_id[32]; + grub_uint8_t reserved2[8]; + grub_uint8_t entries[0]; +}; + +enum + { + GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_ENTRYPOINT_DESCRIPTOR = 0, + GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_MEMORY_DESCRIPTOR = 1, + GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_PLATFORM_FEATURES = 2, + GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_TRANSLATION_REGISTER_DESCRIPTOR = 3, + GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_PURGE_TRANSLATION_COHERENCE = 4, + GRUB_EFI_SAL_SYSTEM_TABLE_TYPE_AP_WAKEUP = 5 + }; + +struct grub_efi_sal_system_table_entrypoint_descriptor +{ + grub_uint8_t type; + grub_uint8_t pad[7]; + grub_uint64_t pal_proc_addr; + grub_uint64_t sal_proc_addr; + grub_uint64_t global_data_ptr; + grub_uint64_t reserved[2]; +}; + +struct grub_efi_sal_system_table_memory_descriptor +{ + grub_uint8_t type; + grub_uint8_t sal_used; + grub_uint8_t attr; + grub_uint8_t ar; + grub_uint8_t attr_mask; + grub_uint8_t mem_type; + grub_uint8_t usage; + grub_uint8_t unknown; + grub_uint64_t addr; + grub_uint64_t len; + grub_uint64_t unknown2; +}; + +struct grub_efi_sal_system_table_platform_features +{ + grub_uint8_t type; + grub_uint8_t flags; + grub_uint8_t reserved[14]; +}; + +struct grub_efi_sal_system_table_translation_register_descriptor +{ + grub_uint8_t type; + grub_uint8_t register_type; + grub_uint8_t register_number; + grub_uint8_t reserved[5]; + grub_uint64_t addr; + grub_uint64_t page_size; + grub_uint64_t reserver; +}; + +struct grub_efi_sal_system_table_purge_translation_coherence +{ + grub_uint8_t type; + grub_uint8_t reserved[3]; + grub_uint32_t ndomains; + grub_uint64_t coherence; +}; + +struct grub_efi_sal_system_table_ap_wakeup +{ + grub_uint8_t type; + grub_uint8_t mechanism; + grub_uint8_t reserved[6]; + grub_uint64_t vector; +}; + +enum + { + GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_BUSLOCK = 1, + GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_IRQREDIRECT = 2, + GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_IPIREDIRECT = 4, + GRUB_EFI_SAL_SYSTEM_TABLE_PLATFORM_FEATURE_ITCDRIFT = 8, + }; + /* Enumerations. */ enum grub_efi_timer_delay { diff --git a/include/grub/types.h b/include/grub/types.h index 1cabc2ecf..766eddf07 100644 --- a/include/grub/types.h +++ b/include/grub/types.h @@ -74,9 +74,11 @@ typedef unsigned grub_uint32_t; #if GRUB_CPU_SIZEOF_LONG == 8 typedef unsigned long grub_uint64_t; # define PRIxGRUB_UINT64_T "lx" +# define PRIuGRUB_UINT64_T "lu" #else typedef unsigned long long grub_uint64_t; # define PRIxGRUB_UINT64_T "llx" +# define PRIuGRUB_UINT64_T "llu" #endif /* Misc types. */ From 48798b6a1e4553a0d19eb1df62c5ce6218377a17 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 1 Sep 2010 09:34:09 +0200 Subject: [PATCH 081/214] Fix memory leak --- grub-core/commands/efi/lsefisystab.c | 1 + 1 file changed, 1 insertion(+) diff --git a/grub-core/commands/efi/lsefisystab.c b/grub-core/commands/efi/lsefisystab.c index 90f7bf0d1..ac84fc426 100644 --- a/grub-core/commands/efi/lsefisystab.c +++ b/grub-core/commands/efi/lsefisystab.c @@ -63,6 +63,7 @@ grub_cmd_lsefisystab (struct grub_command *cmd __attribute__ ((unused)), *grub_utf16_to_utf8 ((grub_uint8_t *) vendor, st->firmware_vendor, vendor_utf16 - st->firmware_vendor) = 0; grub_printf ("%s", vendor); + grub_free (vendor); } grub_printf (", Version=%x\n", st->firmware_revision); From 8395034beca005a90c7c9fc870ab319860b6ae7c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 2 Sep 2010 17:15:53 +0200 Subject: [PATCH 082/214] Add i386-pc-pxe image target. * util/grub-mkimage.c (image_target_desc): New enum value IMAGE_I386_PC_PXE. (image_targets): New target i386-pc-pxe. (generate_image): Handle i386-pc-pxe image. --- ChangeLog.mknet | 7 ++ Makefile.util.def | 8 ++ tests/util/grub-shell.in | 24 +++- util/grub-mknetdir.in | 230 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 263 insertions(+), 6 deletions(-) create mode 100644 ChangeLog.mknet create mode 100644 util/grub-mknetdir.in diff --git a/ChangeLog.mknet b/ChangeLog.mknet new file mode 100644 index 000000000..92de7b2d4 --- /dev/null +++ b/ChangeLog.mknet @@ -0,0 +1,7 @@ +2010-09-02 Vladimir Serbinenko + + grub-mknetdir script. + + * Makefile.util.def (grub-mknetdir): New module. + * tests/util/grub-shell.in: Support boot=net + * util/grub-mknetdir.in: New file. diff --git a/Makefile.util.def b/Makefile.util.def index 35bcd81b2..747eb7837 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -360,6 +360,14 @@ script = { enable = noemu; }; +script = { + mansection = 8; + installdir = sbin; + name = grub-mknetdir; + + common = util/grub-mknetdir.in; +}; + script = { name = grub-mkconfig; common = util/grub-mkconfig.in; diff --git a/tests/util/grub-shell.in b/tests/util/grub-shell.in index e21cc95f4..a59714b44 100644 --- a/tests/util/grub-shell.in +++ b/tests/util/grub-shell.in @@ -28,6 +28,7 @@ PACKAGE_NAME=@PACKAGE_NAME@ PACKAGE_TARNAME=@PACKAGE_TARNAME@ PACKAGE_VERSION=@PACKAGE_VERSION@ target_cpu=@target_cpu@ +platform=@platform@ # Force build directory components PATH=${builddir}:$PATH @@ -42,7 +43,7 @@ Run GRUB script in a Qemu instance. -h, --help print this message and exit -v, --version print the version information and exit - --boot=[fd|hd|cd] boot method for Qemu instance + --boot=[fd|hd|cd|net] boot method for Qemu instance --modules=MODULES pre-load specified modules MODULES --qemu=FILE Name of qemu binary --qemu-opts=OPTIONS extra options to pass to Qemu instance @@ -83,6 +84,7 @@ for option in "$@"; do if [ "$dev" = "fd" ] ; then boot=fd; elif [ "$dev" = "hd" ] ; then boot=hd; elif [ "$dev" = "cd" ] ; then boot=cd; + elif [ "$dev" = "net" ] ; then boot=net; elif [ "$dev" = "qemu" ] ; then boot=qemu; elif [ "$dev" = "coreboot" ] ; then boot=coreboot; else @@ -134,10 +136,12 @@ halt EOF isofile=`mktemp` -sh @builddir@/grub-mkrescue --grub-mkimage=${builddir}/grub-mkimage --output=${isofile} --override-directory=${builddir}/grub-core \ - --rom-directory="${rom_directory}" \ - /boot/grub/grub.cfg=${cfgfile} /boot/grub/testcase.cfg=${source} \ - ${files} >/dev/null 2>&1 +if [ x$boot != xnet ]; then + sh @builddir@/grub-mkrescue --grub-mkimage=${builddir}/grub-mkimage --output=${isofile} --override-directory=${builddir}/grub-core \ + --rom-directory="${rom_directory}" \ + /boot/grub/grub.cfg=${cfgfile} /boot/grub/testcase.cfg=${source} \ + ${files} >/dev/null 2>&1 +fi if [ x$boot = xhd ]; then device=hda bootdev="-boot c" @@ -164,7 +168,15 @@ if [ x$boot = xcoreboot ]; then device=cdrom fi -${qemu} ${qemuopts} -nographic -serial file:/dev/stdout -monitor file:/dev/null -${device} ${isofile} ${bootdev} | cat | tr -d "\r" +if [ x$boot = xnet ]; then + netdir=`mktemp -d` + sh @builddir@/grub-mknetdir --grub-mkimage=${builddir}/grub-mkimage --override-directory=${builddir}/grub-core --net-directory=$netdir + cp ${cfgfile} $netdir/boot/grub/grub.cfg + cp ${source} $netdir/boot/grub/testcase.cfg + ${qemu} ${qemuopts} -nographic -serial file:/dev/stdout -monitor file:/dev/null -boot n -net user,tftp=$netdir,bootfile=/boot/grub/$target_cpu-$platform/core.0 -net nic | cat | tr -d "\r" +else + ${qemu} ${qemuopts} -nographic -serial file:/dev/stdout -monitor file:/dev/null -${device} ${isofile} ${bootdev} | cat | tr -d "\r" +fi rm -f "${isofile}" "${imgfile}" rm -rf "${rom_directory}" if [ x$boot = xcoreboot ]; then diff --git a/util/grub-mknetdir.in b/util/grub-mknetdir.in new file mode 100644 index 000000000..b353e98b9 --- /dev/null +++ b/util/grub-mknetdir.in @@ -0,0 +1,230 @@ +#! /bin/sh + +# Install GRUB on your drive. +# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc. +# +# GRUB is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# GRUB is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GRUB. If not, see . + +# Initialize some variables. +transform="@program_transform_name@" + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +sbindir=@sbindir@ +bindir=@bindir@ +libdir=@libdir@ +PACKAGE_NAME=@PACKAGE_NAME@ +PACKAGE_TARNAME=@PACKAGE_TARNAME@ +PACKAGE_VERSION=@PACKAGE_VERSION@ +target_cpu=@target_cpu@ +platform=@platform@ +host_os=@host_os@ +pkglibdir=${libdir}/`echo ${PACKAGE_TARNAME}/${target_cpu}-${platform} | sed ${transform}` +localedir=@datadir@/locale +native_platform=@platform@ +pkglib_DATA="moddep.lst command.lst fs.lst partmap.lst parttool.lst handler.lst video.lst crypto.lst terminal.lst" + +self=`basename $0` + +grub_mkimage=${bindir}/`echo grub-mkimage | sed ${transform}` +rootdir=/srv/tftp +grub_prefix=`echo /boot/grub | sed ${transform}` +modules= + +install_device= +no_floppy= +recheck=no +debug=no +debug_image= +subdir=`echo /boot/grub | sed ${transform}` +pc_dir=${libdir}/$(echo ${PACKAGE_TARNAME} | sed ${transform})/i386-pc + +# Usage: usage +# Print the usage. +usage () { + cat <. +EOF +} + +argument () { + opt=$1 + shift + + if test $# -eq 0; then + echo "$0: option requires an argument -- '$opt'" 1>&2 + exit 1 + fi + echo $1 +} + +# Check the arguments. +while test $# -gt 0 +do + option=$1 + shift + + case "$option" in + -h | --help) + usage + exit 0 ;; + -v | --version) + echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" + exit 0 ;; + + --modules) + modules=`argument $option "$@"`; shift;; + --modules=*) + modules=`echo "$option" | sed 's/--modules=//'` ;; + + --net-directory) + rootdir=`argument $option "$@"`; shift;; + --net-directory=*) + rootdir=`echo "$option" | sed 's/--net-directory=//'` ;; + + --subdir) + subdir=`argument $option "$@"`; shift;; + --subdir=*) + subdir=`echo "$option" | sed 's/--subdir=//'` ;; + + --grub-mkimage) + grub_mkimage=`argument $option "$@"`; shift;; + --grub-mkimage=*) + grub_mkimage=`echo "$option" | sed 's/--grub-mkimage=//'` ;; + + # This is an undocumented feature... + --debug) + debug=yes ;; + --debug-image) + debug_image=`argument $option "$@"`; shift;; + --debug-image=*) + debug_image=`echo "$option" | sed 's/--debug-image=//'` ;; + + # Intentionally undocumented + --override-directory) + override_dir=`argument $option "$@"` + shift + PATH=${override_dir}:$PATH + export PATH + ;; + --override-directory=*) + override_dir=`echo "${option}/" | sed 's/--override-directory=//'` + PATH=${override_dir}:$PATH + export PATH + ;; + + -*) + echo "Unrecognized option \`$option'" 1>&2 + usage + exit 1 + ;; + *) + if test "x$install_device" != x; then + echo "More than one install_devices?" 1>&2 + usage + exit 1 + fi + install_device="${option}" ;; + esac +done + +set $grub_mkimage dummy +if test -f "$1"; then + : +else + echo "$1: Not found." 1>&2 + exit 1 +fi + +# Create the GRUB directory if it is not present. +mkdir -p "${rootdir}/${subdir}" || exit 1 + +process_input_dir () +{ + input_dir="$1" + platform="$2" + grubdir="${rootdir}/${subdir}/${platform}" + config_opt= + mkdir -p "$grubdir" || exit 1 + + for file in ${grubdir}/*.mod ${grubdir}/*.lst ${grubdir}/*.img ${grubdir}/efiemu??.o; do + if test -f $file && [ "`basename $file`" != menu.lst ]; then + rm -f $file || exit 1 + fi + done + for file in ${input_dir}/*.mod; do + if test -f "$file"; then + cp -f "$file" "$grubdir/" + fi + done + for file in ${pkglib_DATA}; do + if test -f "${input_dir}/${file}"; then + cp -f "${input_dir}/${file}" "$grubdir/" + fi + done + + mkdir -p "$grubdir/locale" + for file in ${input_dir}/po/*.mo; do + if test -f "$file"; then + cp -f "$file" "$grubdir/locale/" + fi + done + + rm -f ${grubdir}/load.cfg + + if [ "x${debug_image}" != x ]; then + echo "set debug='${debug_image}'" >> ${grubdir}/load.cfg + config_opt="-c ${grubdir}/load.cfg " + fi + + case "${platform}" in + i386-pc) mkimage_target=i386-pc-pxe; + netmodules="pxe"; + prefix="(pxe)/${subdir}/${platform}"; + ext=0 ;; + *) echo Unsupported platform ${platform}; + exit 1;; + esac + + cat << EOF > ${grubdir}/grub.cfg +source ${subdir}/grub.cfg +EOF + + $grub_mkimage ${config_opt} -d "${input_dir}" -O ${mkimage_target} --output=${grubdir}/core.$ext --prefix=$prefix $modules $netmodules || exit 1 + echo "Netboot directory for ${platform} created. Configure your DHCP server to point to ${subdir}/${platform}/core.$ext" +} + +if [ "${override_dir}" = "" ] ; then + if test -e "${pc_dir}" ; then + process_input_dir ${pc_dir} i386-pc + fi +else + process_input_dir ${override_dir} ${target_cpu}-${native_platform} +fi + + +# Bye. +exit 0 From 540e2fe18579c7c63945f7a416c1a4de37fa9628 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 3 Sep 2010 21:19:22 +0200 Subject: [PATCH 083/214] Initial videoinfo implementation --- grub-core/Makefile.core.def | 5 + grub-core/commands/videoinfo.c | 101 ++++++++++++++++++ grub-core/video/i386/pc/vbe.c | 185 +++++++++++++++++++-------------- include/grub/video.h | 2 + 4 files changed, 216 insertions(+), 77 deletions(-) create mode 100644 grub-core/commands/videoinfo.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 353b9d123..cf497964d 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -676,6 +676,11 @@ module = { enable = i386_pc; }; +module = { + name = videoinfo; + common = commands/videoinfo.c; +}; + module = { name = vbetest; i386_pc = commands/i386/pc/vbetest.c; diff --git a/grub-core/commands/videoinfo.c b/grub-core/commands/videoinfo.c new file mode 100644 index 000000000..405c73774 --- /dev/null +++ b/grub-core/commands/videoinfo.c @@ -0,0 +1,101 @@ +/* videoinfo.c - command to list video modes. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2005,2007,2008,2009,2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +static int +hook (const struct grub_video_mode_info *info) +{ + grub_printf (" %4d x %4d x %2d ", info->height, info->width, info->bpp); + + /* Show mask and position details for direct color modes. */ + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_RGB) + grub_printf ("D, mask: %d/%d/%d/%d pos: %d/%d/%d/%d", + info->red_mask_size, + info->green_mask_size, + info->blue_mask_size, + info->reserved_mask_size, + info->red_field_pos, + info->green_field_pos, + info->blue_field_pos, + info->reserved_field_pos); + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) + grub_printf ("P"); + grub_printf ("\n"); + + return 0; +} + +static grub_err_t +grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) +{ + grub_video_adapter_t adapter; + grub_video_driver_id_t id = grub_video_get_driver_id (); + + grub_printf ("List of supported video modes:\n"); + grub_printf ("Legend: P=Packed pixel, D=Direct color, " + "mask/pos=R/G/B/reserved\n"); + + FOR_VIDEO_ADAPTERS (adapter) + { + if (adapter->id != id) + { + if (adapter->init ()) + { + grub_errno = GRUB_ERR_NONE; + continue; + } + } + + grub_printf ("Adapter '%s':\n", adapter->name); + adapter->iterate (hook); + + if (adapter->id != id) + { + if (adapter->fini ()) + { + grub_errno = GRUB_ERR_NONE; + continue; + } + } + } + return GRUB_ERR_NONE; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(videoinfo) +{ + cmd = grub_register_command ("videoinfo", grub_cmd_videoinfo, 0, + N_("List available video modes.")); +} + +GRUB_MOD_FINI(videoinfo) +{ + grub_unregister_command (cmd); +} + diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c index 3817b3f68..082c9bc84 100644 --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -33,7 +33,6 @@ static int vbe_detected = -1; static struct grub_vbe_info_block controller_info; -static struct grub_vbe_mode_info_block active_vbe_mode_info; /* Track last mode to support cards which fail on get_mode. */ static grub_uint32_t last_set_mode = 3; @@ -42,11 +41,7 @@ static struct { struct grub_video_mode_info mode_info; - unsigned int bytes_per_scan_line; - unsigned int bytes_per_pixel; - grub_uint32_t active_vbe_mode; grub_uint8_t *ptr; - int index_color_mode; } framebuffer; static grub_uint32_t initial_vbe_mode; @@ -332,21 +327,12 @@ grub_vbe_set_video_mode (grub_uint32_t vbe_mode, vbe_mode |= 1 << 14; /* Determine frame buffer pixel format. */ - switch (new_vbe_mode_info.memory_model) - { - case GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL: - framebuffer.index_color_mode = 1; - break; - - case GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR: - framebuffer.index_color_mode = 0; - break; - - default: - return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, - "unsupported pixel format 0x%x", - new_vbe_mode_info.memory_model); - } + if (new_vbe_mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL + && new_vbe_mode_info.memory_model + != GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "unsupported pixel format 0x%x", + new_vbe_mode_info.memory_model); } /* Get current mode. */ @@ -360,24 +346,14 @@ grub_vbe_set_video_mode (grub_uint32_t vbe_mode, return grub_error (GRUB_ERR_BAD_DEVICE, "cannot set VBE mode %x", vbe_mode); last_set_mode = vbe_mode; - /* Save information for later usage. */ - framebuffer.active_vbe_mode = vbe_mode; - grub_memcpy (&active_vbe_mode_info, &new_vbe_mode_info, sizeof (active_vbe_mode_info)); - if (vbe_mode < 0x100) { /* If this is not a VESA mode, guess address. */ framebuffer.ptr = (grub_uint8_t *) GRUB_MEMORY_MACHINE_VGA_ADDR; - framebuffer.index_color_mode = 1; } else { framebuffer.ptr = (grub_uint8_t *) new_vbe_mode_info.phys_base_addr; - - if (controller_info.version >= 0x300) - framebuffer.bytes_per_scan_line = new_vbe_mode_info.lin_bytes_per_scan_line; - else - framebuffer.bytes_per_scan_line = new_vbe_mode_info.bytes_per_scan_line; } /* Check whether mode is text mode or graphics mode. */ @@ -392,25 +368,9 @@ grub_vbe_set_video_mode (grub_uint32_t vbe_mode, { /* Graphics mode. */ - /* Calculate bytes_per_pixel value. */ - switch(new_vbe_mode_info.bits_per_pixel) - { - case 32: framebuffer.bytes_per_pixel = 4; break; - case 24: framebuffer.bytes_per_pixel = 3; break; - case 16: framebuffer.bytes_per_pixel = 2; break; - case 15: framebuffer.bytes_per_pixel = 2; break; - case 8: framebuffer.bytes_per_pixel = 1; break; - default: - grub_vbe_bios_set_mode (old_vbe_mode, 0); - last_set_mode = old_vbe_mode; - return grub_error (GRUB_ERR_BAD_DEVICE, - "cannot set VBE mode %x", - vbe_mode); - break; - } - /* If video mode is in indexed color, setup default VGA palette. */ - if (framebuffer.index_color_mode) + if (vbe_mode < 0x100 || new_vbe_mode_info.memory_model + == GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL) { struct grub_vbe_palette_data *palette = (struct grub_vbe_palette_data *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; @@ -548,10 +508,13 @@ grub_video_vbe_fini (void) grub_err_t err; /* Restore old video mode. */ - status = grub_vbe_bios_set_mode (initial_vbe_mode, 0); - if (status != GRUB_VBE_STATUS_OK) - /* TODO: Decide, is this something we want to do. */ - return grub_errno; + if (last_set_mode != initial_vbe_mode) + { + status = grub_vbe_bios_set_mode (initial_vbe_mode, 0); + if (status != GRUB_VBE_STATUS_OK) + /* TODO: Decide, is this something we want to do. */ + return grub_errno; + } last_set_mode = initial_vbe_mode; /* TODO: Free any resources allocated by driver. */ @@ -583,6 +546,86 @@ doublebuf_pageflipping_set_page (int page) return 0; } +static void +vbe2videoinfo (const struct grub_vbe_mode_info_block *vbeinfo, + struct grub_video_mode_info *mode_info) +{ + mode_info->width = vbeinfo->x_resolution; + mode_info->height = vbeinfo->y_resolution; + switch (vbeinfo->memory_model) + { + case GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL: + mode_info->mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; + break; + + case GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR: + mode_info->mode_type = GRUB_VIDEO_MODE_TYPE_RGB; + break; + } + + mode_info->bpp = vbeinfo->bits_per_pixel; + /* Calculate bytes_per_pixel value. */ + switch(vbeinfo->bits_per_pixel) + { + case 32: + mode_info->bytes_per_pixel = 4; + break; + case 24: + mode_info->bytes_per_pixel = 3; + break; + case 16: + mode_info->bytes_per_pixel = 2; + break; + case 15: + mode_info->bytes_per_pixel = 2; + break; + case 8: + mode_info->bytes_per_pixel = 1; + break; + } + + if (controller_info.version >= 0x300) + mode_info->pitch = vbeinfo->lin_bytes_per_scan_line; + else + mode_info->pitch = vbeinfo->bytes_per_scan_line; + + mode_info->number_of_colors = 256; /* TODO: fix me. */ + mode_info->red_mask_size = vbeinfo->red_mask_size; + mode_info->red_field_pos = vbeinfo->red_field_position; + mode_info->green_mask_size = vbeinfo->green_mask_size; + mode_info->green_field_pos = vbeinfo->green_field_position; + mode_info->blue_mask_size = vbeinfo->blue_mask_size; + mode_info->blue_field_pos = vbeinfo->blue_field_position; + mode_info->reserved_mask_size = vbeinfo->rsvd_mask_size; + mode_info->reserved_field_pos = vbeinfo->rsvd_field_position; + + mode_info->blit_format = grub_video_get_blit_format (mode_info); +} + +static int +grub_video_vbe_iterate (int (*hook) (const struct grub_video_mode_info *info)) +{ + grub_uint16_t *p; + struct grub_vbe_mode_info_block vbe_mode_info; + struct grub_video_mode_info mode_info; + + for (p = vbe_mode_list; *p != 0xFFFF; p++) + { + grub_vbe_get_video_mode_info (*p, &vbe_mode_info); + if (grub_errno != GRUB_ERR_NONE) + { + /* Could not retrieve mode info, retreat. */ + grub_errno = GRUB_ERR_NONE; + break; + } + + vbe2videoinfo (&vbe_mode_info, &mode_info); + if (hook (&mode_info)) + return 1; + } + return 0; +} + static grub_err_t grub_video_vbe_setup (unsigned int width, unsigned int height, unsigned int mode_type, unsigned int mode_mask) @@ -631,6 +674,14 @@ grub_video_vbe_setup (unsigned int width, unsigned int height, /* Not compatible memory model. */ continue; + if (vbe_mode_info.bits_per_pixel != 8 + && vbe_mode_info.bits_per_pixel != 15 + && vbe_mode_info.bits_per_pixel != 16 + && vbe_mode_info.bits_per_pixel != 24 + && vbe_mode_info.bits_per_pixel != 32) + /* Unsupported bitdepth . */ + continue; + if (((vbe_mode_info.x_resolution != width) || (vbe_mode_info.y_resolution != height)) && width != 0 && height != 0) /* Non matching resolution. */ @@ -676,36 +727,15 @@ grub_video_vbe_setup (unsigned int width, unsigned int height, if (best_vbe_mode != 0) { grub_err_t err; + static struct grub_vbe_mode_info_block active_vbe_mode_info; /* If this fails, then we have mode selection heuristics problem, or adapter failure. */ - /* grub_vbe_set_video_mode already sets active_vbe_mode_info. */ - grub_vbe_set_video_mode (best_vbe_mode, NULL); + grub_vbe_set_video_mode (best_vbe_mode, &active_vbe_mode_info); if (grub_errno != GRUB_ERR_NONE) return grub_errno; /* Fill mode info details. */ - framebuffer.mode_info.width = active_vbe_mode_info.x_resolution; - framebuffer.mode_info.height = active_vbe_mode_info.y_resolution; - - if (framebuffer.index_color_mode) - framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; - else - framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB; - - framebuffer.mode_info.bpp = active_vbe_mode_info.bits_per_pixel; - framebuffer.mode_info.bytes_per_pixel = framebuffer.bytes_per_pixel; - framebuffer.mode_info.pitch = framebuffer.bytes_per_scan_line; - framebuffer.mode_info.number_of_colors = 256; /* TODO: fix me. */ - framebuffer.mode_info.red_mask_size = active_vbe_mode_info.red_mask_size; - framebuffer.mode_info.red_field_pos = active_vbe_mode_info.red_field_position; - framebuffer.mode_info.green_mask_size = active_vbe_mode_info.green_mask_size; - framebuffer.mode_info.green_field_pos = active_vbe_mode_info.green_field_position; - framebuffer.mode_info.blue_mask_size = active_vbe_mode_info.blue_mask_size; - framebuffer.mode_info.blue_field_pos = active_vbe_mode_info.blue_field_position; - framebuffer.mode_info.reserved_mask_size = active_vbe_mode_info.rsvd_mask_size; - framebuffer.mode_info.reserved_field_pos = active_vbe_mode_info.rsvd_field_position; - - framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info); + vbe2videoinfo (&active_vbe_mode_info, &framebuffer.mode_info); { /* Get video RAM size in bytes. */ @@ -740,7 +770,7 @@ static grub_err_t grub_video_vbe_set_palette (unsigned int start, unsigned int count, struct grub_video_palette_data *palette_data) { - if (framebuffer.index_color_mode) + if (framebuffer.mode_info.mode_type == GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) { /* TODO: Implement setting indexed color mode palette to hardware. */ //status = grub_vbe_bios_set_palette_data (sizeof (vga_colors) @@ -793,6 +823,7 @@ static struct grub_video_adapter grub_video_vbe_adapter = .delete_render_target = grub_video_fb_delete_render_target, .set_active_render_target = grub_video_fb_set_active_render_target, .get_active_render_target = grub_video_fb_get_active_render_target, + .iterate = grub_video_vbe_iterate, .next = 0 }; diff --git a/include/grub/video.h b/include/grub/video.h index 24167281f..d530ab415 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -282,6 +282,8 @@ struct grub_video_adapter grub_err_t (*set_active_render_target) (struct grub_video_render_target *target); grub_err_t (*get_active_render_target) (struct grub_video_render_target **target); + + int (*iterate) (int (*hook) (const struct grub_video_mode_info *info)); }; typedef struct grub_video_adapter *grub_video_adapter_t; From 4787931fe0b44613c0758d34234f2510ac24e3cf Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 3 Sep 2010 21:40:40 +0200 Subject: [PATCH 084/214] Show mode id --- grub-core/commands/videoinfo.c | 10 +++++++--- grub-core/video/i386/pc/vbe.c | 10 +++++++--- include/grub/video.h | 3 +++ 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/grub-core/commands/videoinfo.c b/grub-core/commands/videoinfo.c index 405c73774..e03b3372d 100644 --- a/grub-core/commands/videoinfo.c +++ b/grub-core/commands/videoinfo.c @@ -28,11 +28,15 @@ static int hook (const struct grub_video_mode_info *info) { - grub_printf (" %4d x %4d x %2d ", info->height, info->width, info->bpp); + if (info->mode_number == GRUB_VIDEO_MODE_NUMBER_INVALID) + grub_printf (" "); + else + grub_printf (" 0x%03x ", info->mode_number); + grub_printf ("%4d x %4d x %2d ", info->height, info->width, info->bpp); /* Show mask and position details for direct color modes. */ if (info->mode_type & GRUB_VIDEO_MODE_TYPE_RGB) - grub_printf ("D, mask: %d/%d/%d/%d pos: %d/%d/%d/%d", + grub_printf ("Direct, mask: %d/%d/%d/%d pos: %d/%d/%d/%d", info->red_mask_size, info->green_mask_size, info->blue_mask_size, @@ -42,7 +46,7 @@ hook (const struct grub_video_mode_info *info) info->blue_field_pos, info->reserved_field_pos); if (info->mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) - grub_printf ("P"); + grub_printf ("Packed"); grub_printf ("\n"); return 0; diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c index 082c9bc84..6b089db04 100644 --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -547,9 +547,12 @@ doublebuf_pageflipping_set_page (int page) } static void -vbe2videoinfo (const struct grub_vbe_mode_info_block *vbeinfo, +vbe2videoinfo (grub_uint32_t mode, + const struct grub_vbe_mode_info_block *vbeinfo, struct grub_video_mode_info *mode_info) { + mode_info->mode_number = mode; + mode_info->width = vbeinfo->x_resolution; mode_info->height = vbeinfo->y_resolution; switch (vbeinfo->memory_model) @@ -619,7 +622,7 @@ grub_video_vbe_iterate (int (*hook) (const struct grub_video_mode_info *info)) break; } - vbe2videoinfo (&vbe_mode_info, &mode_info); + vbe2videoinfo (*p, &vbe_mode_info, &mode_info); if (hook (&mode_info)) return 1; } @@ -735,7 +738,8 @@ grub_video_vbe_setup (unsigned int width, unsigned int height, return grub_errno; /* Fill mode info details. */ - vbe2videoinfo (&active_vbe_mode_info, &framebuffer.mode_info); + vbe2videoinfo (best_vbe_mode, &active_vbe_mode_info, + &framebuffer.mode_info); { /* Get video RAM size in bytes. */ diff --git a/include/grub/video.h b/include/grub/video.h index d530ab415..40bd5e615 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -117,6 +117,9 @@ struct grub_video_mode_info /* In index color mode, number of colors. In RGB mode this is 256. */ unsigned int number_of_colors; + unsigned int mode_number; +#define GRUB_VIDEO_MODE_NUMBER_INVALID 0xffffffff + /* Optimization hint how binary data is coded. */ enum grub_video_blit_format blit_format; From 380c39cb25e2905d66cefda5638ddbf448430149 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 3 Sep 2010 22:11:22 +0200 Subject: [PATCH 085/214] Show adapter-specific info --- grub-core/commands/videoinfo.c | 13 ++++++++++++- grub-core/video/i386/pc/vbe.c | 15 +++++++++++++++ include/grub/video.h | 2 ++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/grub-core/commands/videoinfo.c b/grub-core/commands/videoinfo.c index e03b3372d..a9e8be745 100644 --- a/grub-core/commands/videoinfo.c +++ b/grub-core/commands/videoinfo.c @@ -66,16 +66,27 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), FOR_VIDEO_ADAPTERS (adapter) { + grub_printf ("Adapter '%s':\n", adapter->name); + + if (!adapter->iterate) + { + grub_printf (" No info available\n"); + continue; + } + if (adapter->id != id) { if (adapter->init ()) { + grub_printf (" Failed\n"); grub_errno = GRUB_ERR_NONE; continue; } } - grub_printf ("Adapter '%s':\n", adapter->name); + if (adapter->print_adapter_specific_info) + adapter->print_adapter_specific_info (); + adapter->iterate (hook); if (adapter->id != id) diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c index 6b089db04..1d2a9ac76 100644 --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -798,6 +798,20 @@ grub_video_vbe_get_info_and_fini (struct grub_video_mode_info *mode_info, return grub_video_fb_get_info_and_fini (mode_info, framebuf); } +static void +grub_video_vbe_print_adapter_specific_info (void) +{ + grub_printf (" VBE info: version: %d.%d OEM software rev: %d.%d\n", + controller_info.version >> 8, + controller_info.version & 0xFF, + controller_info.oem_software_rev >> 8, + controller_info.oem_software_rev & 0xFF); + + /* The total_memory field is in 64 KiB units. */ + grub_printf (" total memory: %d KiB\n", + (controller_info.total_memory << 16) / 1024); +} + static struct grub_video_adapter grub_video_vbe_adapter = { .name = "VESA BIOS Extension Video Driver", @@ -828,6 +842,7 @@ static struct grub_video_adapter grub_video_vbe_adapter = .set_active_render_target = grub_video_fb_set_active_render_target, .get_active_render_target = grub_video_fb_get_active_render_target, .iterate = grub_video_vbe_iterate, + .print_adapter_specific_info = grub_video_vbe_print_adapter_specific_info, .next = 0 }; diff --git a/include/grub/video.h b/include/grub/video.h index 40bd5e615..1c1bf16ab 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -287,6 +287,8 @@ struct grub_video_adapter grub_err_t (*get_active_render_target) (struct grub_video_render_target **target); int (*iterate) (int (*hook) (const struct grub_video_mode_info *info)); + + void (*print_adapter_specific_info) (void); }; typedef struct grub_video_adapter *grub_video_adapter_t; From 4ab5f27548ce1f443c3385d7c68821c7d5b415a9 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 3 Sep 2010 22:21:48 +0200 Subject: [PATCH 086/214] Remove vbetest and vbeinfo in favour of videotest and videoinfo --- grub-core/Makefile.core.def | 12 -- grub-core/commands/i386/pc/vbeinfo.c | 185 --------------------------- grub-core/commands/i386/pc/vbetest.c | 179 -------------------------- grub-core/commands/videoinfo.c | 19 ++- grub-core/commands/videotest.c | 15 +++ 5 files changed, 33 insertions(+), 377 deletions(-) delete mode 100644 grub-core/commands/i386/pc/vbeinfo.c delete mode 100644 grub-core/commands/i386/pc/vbetest.c diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index cf497964d..e8728e0da 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -670,23 +670,11 @@ module = { emu_condition = COND_GRUB_EMU_USB; }; -module = { - name = vbeinfo; - i386_pc = commands/i386/pc/vbeinfo.c; - enable = i386_pc; -}; - module = { name = videoinfo; common = commands/videoinfo.c; }; -module = { - name = vbetest; - i386_pc = commands/i386/pc/vbetest.c; - enable = i386_pc; -}; - module = { name = videotest; common = commands/videotest.c; diff --git a/grub-core/commands/i386/pc/vbeinfo.c b/grub-core/commands/i386/pc/vbeinfo.c deleted file mode 100644 index c266bbfcb..000000000 --- a/grub-core/commands/i386/pc/vbeinfo.c +++ /dev/null @@ -1,185 +0,0 @@ -/* vbeinfo.c - command to list compatible VBE video modes. */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2005,2007,2008,2009 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GRUB. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -static void * -real2pm (grub_vbe_farptr_t ptr) -{ - return (void *) ((((unsigned long) ptr & 0xFFFF0000) >> 12UL) - + ((unsigned long) ptr & 0x0000FFFF)); -} - -static grub_err_t -grub_cmd_vbeinfo (grub_command_t cmd __attribute__ ((unused)), - int argc __attribute__ ((unused)), - char **args __attribute__ ((unused))) -{ - struct grub_vbe_info_block controller_info; - struct grub_vbe_mode_info_block mode_info_tmp; - grub_uint32_t use_mode = GRUB_VBE_DEFAULT_VIDEO_MODE; - grub_uint16_t *video_mode_list; - grub_uint16_t *p; - grub_uint16_t *saved_video_mode_list; - grub_size_t video_mode_list_size; - grub_err_t err; - char *modevar; - - err = grub_vbe_probe (&controller_info); - if (err != GRUB_ERR_NONE) - return err; - - grub_printf ("VBE info: version: %d.%d OEM software rev: %d.%d\n", - controller_info.version >> 8, - controller_info.version & 0xFF, - controller_info.oem_software_rev >> 8, - controller_info.oem_software_rev & 0xFF); - - /* The total_memory field is in 64 KiB units. */ - grub_printf (" total memory: %d KiB\n", - (controller_info.total_memory << 16) / 1024); - - /* Because the information on video modes is stored in a temporary place, - it is better to copy it to somewhere safe. */ - p = video_mode_list = real2pm (controller_info.video_mode_ptr); - while (*p++ != 0xFFFF) - ; - - video_mode_list_size = (grub_addr_t) p - (grub_addr_t) video_mode_list; - saved_video_mode_list = grub_malloc (video_mode_list_size); - if (! saved_video_mode_list) - return grub_errno; - - grub_memcpy (saved_video_mode_list, video_mode_list, video_mode_list_size); - - grub_printf ("List of compatible video modes:\n"); - grub_printf ("Legend: P=Packed pixel, D=Direct color, " - "mask/pos=R/G/B/reserved\n"); - - /* Walk through all video modes listed. */ - for (p = saved_video_mode_list; *p != 0xFFFF; p++) - { - const char *memory_model = 0; - grub_uint32_t mode = (grub_uint32_t) *p; - - err = grub_vbe_get_video_mode_info (mode, &mode_info_tmp); - if (err != GRUB_ERR_NONE) - { - grub_errno = GRUB_ERR_NONE; - continue; - } - - if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_SUPPORTED) == 0) - /* If not available, skip it. */ - continue; - - if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_RESERVED_1) == 0) - /* Not enough information. */ - continue; - - if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_COLOR) == 0) - /* Monochrome is unusable. */ - continue; - - if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_LFB_AVAIL) == 0) - /* We support only linear frame buffer modes. */ - continue; - - if ((mode_info_tmp.mode_attributes & GRUB_VBE_MODEATTR_GRAPHICS) == 0) - /* We allow only graphical modes. */ - continue; - - switch (mode_info_tmp.memory_model) - { - case GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL: - memory_model = "Packed"; - break; - case GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR: - memory_model = "Direct"; - break; - - default: - break; - } - - if (! memory_model) - continue; - - grub_printf ("0x%03x: %4d x %4d x %2d %s", - mode, - mode_info_tmp.x_resolution, - mode_info_tmp.y_resolution, - mode_info_tmp.bits_per_pixel, - memory_model); - - /* Show mask and position details for direct color modes. */ - if (mode_info_tmp.memory_model == GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR) - grub_printf (", mask: %d/%d/%d/%d pos: %d/%d/%d/%d", - mode_info_tmp.red_mask_size, - mode_info_tmp.green_mask_size, - mode_info_tmp.blue_mask_size, - mode_info_tmp.rsvd_mask_size, - mode_info_tmp.red_field_position, - mode_info_tmp.green_field_position, - mode_info_tmp.blue_field_position, - mode_info_tmp.rsvd_field_position); - grub_printf ("\n"); - } - - grub_free (saved_video_mode_list); - - /* Check existence of vbe_mode environment variable. */ - modevar = grub_env_get ("vbe_mode"); - - if (modevar != 0) - { - unsigned long value; - - value = grub_strtoul (modevar, 0, 0); - if (grub_errno == GRUB_ERR_NONE) - use_mode = value; - else - grub_errno = GRUB_ERR_NONE; - } - - grub_printf ("Configured VBE mode (vbe_mode) = 0x%03x\n", use_mode); - - return 0; -} - -static grub_command_t cmd; - -GRUB_MOD_INIT(vbeinfo) -{ - cmd = - grub_register_command ("vbeinfo", grub_cmd_vbeinfo, 0, - N_("List compatible VESA BIOS extension video modes.")); -} - -GRUB_MOD_FINI(vbeinfo) -{ - grub_unregister_command (cmd); -} diff --git a/grub-core/commands/i386/pc/vbetest.c b/grub-core/commands/i386/pc/vbetest.c deleted file mode 100644 index d2921c09d..000000000 --- a/grub-core/commands/i386/pc/vbetest.c +++ /dev/null @@ -1,179 +0,0 @@ -/* vbetest.c - command to test VESA BIOS Extension 2.0+ support. */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2005,2007 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GRUB. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static grub_err_t -grub_cmd_vbetest (grub_command_t cmd __attribute__ ((unused)), - int argc __attribute__ ((unused)), - char **args __attribute__ ((unused))) -{ - grub_err_t err; - char *modevar; - struct grub_vbe_mode_info_block mode_info; - struct grub_vbe_info_block controller_info; - grub_uint32_t use_mode = GRUB_VBE_DEFAULT_VIDEO_MODE; - grub_uint32_t old_mode; - grub_uint8_t *framebuffer = 0; - grub_uint32_t bytes_per_scan_line = 0; - unsigned char *ptr; - int i; - - grub_printf ("Probing for VESA BIOS Extension ... "); - - /* Check if VESA BIOS exists. */ - err = grub_vbe_probe (&controller_info); - if (err != GRUB_ERR_NONE) - return err; - - grub_printf ("found!\n"); - - /* Dump out controller information. */ - grub_printf ("VBE signature = %c%c%c%c\n", - controller_info.signature[0], - controller_info.signature[1], - controller_info.signature[2], - controller_info.signature[3]); - - grub_printf ("VBE version = %d.%d\n", - controller_info.version >> 8, - controller_info.version & 0xFF); - grub_printf ("OEM string ptr = %08x\n", - controller_info.oem_string_ptr); - grub_printf ("Total memory = %d\n", - controller_info.total_memory); - - err = grub_vbe_get_video_mode (&old_mode); - grub_printf ("Get video mode err = %04x\n", err); - - if (err == GRUB_ERR_NONE) - grub_printf ("Old video mode = %04x\n", old_mode); - else - grub_errno = GRUB_ERR_NONE; - - /* Check existence of vbe_mode environment variable. */ - modevar = grub_env_get ("vbe_mode"); - if (modevar != 0) - { - unsigned long value; - - value = grub_strtoul (modevar, 0, 0); - if (grub_errno == GRUB_ERR_NONE) - use_mode = value; - else - grub_errno = GRUB_ERR_NONE; - } - - err = grub_vbe_get_video_mode_info (use_mode, &mode_info); - if (err != GRUB_ERR_NONE) - return err; - - /* Dump out details about the mode being tested. */ - grub_printf ("mode: 0x%03x\n", - use_mode); - grub_printf ("width : %d\n", - mode_info.x_resolution); - grub_printf ("height: %d\n", - mode_info.y_resolution); - grub_printf ("memory model: %02x\n", - mode_info.memory_model); - grub_printf ("bytes/scanline: %d\n", - mode_info.bytes_per_scan_line); - grub_printf ("bytes/scanline (lin): %d\n", - mode_info.lin_bytes_per_scan_line); - grub_printf ("base address: %08x\n", - mode_info.phys_base_addr); - grub_printf ("red mask/pos: %d/%d\n", - mode_info.red_mask_size, - mode_info.red_field_position); - grub_printf ("green mask/pos: %d/%d\n", - mode_info.green_mask_size, - mode_info.green_field_position); - grub_printf ("blue mask/pos: %d/%d\n", - mode_info.blue_mask_size, - mode_info.blue_field_position); - - grub_printf ("Press any key to continue.\n"); - - grub_getkey (); - - /* Setup GFX mode. */ - err = grub_vbe_set_video_mode (use_mode, &mode_info); - if (err != GRUB_ERR_NONE) - return err; - - /* Determine framebuffer address and how many bytes are in scan line. */ - framebuffer = (grub_uint8_t *) mode_info.phys_base_addr; - ptr = framebuffer; - - if (controller_info.version >= 0x300) - { - bytes_per_scan_line = mode_info.lin_bytes_per_scan_line; - } - else - { - bytes_per_scan_line = mode_info.bytes_per_scan_line; - } - - /* Draw some random data to screen. */ - for (i = 0; i < 256 * 256; i++) - { - ptr[i] = i & 0x0F; - } - - /* Draw white line to screen. */ - for (i = 0; i < 100; i++) - { - ptr[mode_info.bytes_per_scan_line * 50 + i] = 0x0F; - } - - /* Draw another white line to screen. */ - grub_memset (ptr + bytes_per_scan_line * 51, 0x0f, bytes_per_scan_line); - - grub_getkey (); - - grub_video_restore (); - - /* Restore old video mode. */ - grub_vbe_set_video_mode (old_mode, 0); - - return grub_errno; -} - -static grub_command_t cmd; - -GRUB_MOD_INIT(vbetest) -{ - cmd = grub_register_command ("vbetest", grub_cmd_vbetest, - 0, N_("Test VESA BIOS Extension 2.0+ support.")); -} - -GRUB_MOD_FINI(vbetest) -{ - grub_unregister_command (cmd); -} diff --git a/grub-core/commands/videoinfo.c b/grub-core/commands/videoinfo.c index a9e8be745..caa32c939 100644 --- a/grub-core/commands/videoinfo.c +++ b/grub-core/commands/videoinfo.c @@ -58,7 +58,14 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), char **args __attribute__ ((unused))) { grub_video_adapter_t adapter; - grub_video_driver_id_t id = grub_video_get_driver_id (); + grub_video_driver_id_t id; + +#ifdef GRUB_MACHINE_PCBIOS + if (grub_strcmp (cmd->name, "vbeinfo") == 0) + grub_dl_load ("vbe"); +#endif + + id = grub_video_get_driver_id (); grub_printf ("List of supported video modes:\n"); grub_printf ("Legend: P=Packed pixel, D=Direct color, " @@ -102,15 +109,25 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), } static grub_command_t cmd; +#ifdef GRUB_MACHINE_PCBIOS +static grub_command_t cmd_vbe; +#endif GRUB_MOD_INIT(videoinfo) { cmd = grub_register_command ("videoinfo", grub_cmd_videoinfo, 0, N_("List available video modes.")); +#ifdef GRUB_MACHINE_PCBIOS + cmd_vbe = grub_register_command ("vbeinfo", grub_cmd_videoinfo, 0, + N_("List available video modes.")); +#endif } GRUB_MOD_FINI(videoinfo) { grub_unregister_command (cmd); +#ifdef GRUB_MACHINE_PCBIOS + grub_unregister_command (cmd_vbe); +#endif } diff --git a/grub-core/commands/videotest.c b/grub-core/commands/videotest.c index c544d1839..22bd648d0 100644 --- a/grub-core/commands/videotest.c +++ b/grub-core/commands/videotest.c @@ -42,6 +42,11 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), struct grub_video_render_target *text_layer; grub_video_color_t palette[16]; +#ifdef GRUB_MACHINE_PCBIOS + if (grub_strcmp (cmd->name, "vbetest") == 0) + grub_dl_load ("vbe"); +#endif + err = grub_video_set_mode ("auto", GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0); if (err) return err; @@ -180,14 +185,24 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), } static grub_command_t cmd; +#ifdef GRUB_MACHINE_PCBIOS +static grub_command_t cmd_vbe; +#endif GRUB_MOD_INIT(videotest) { cmd = grub_register_command ("videotest", grub_cmd_videotest, 0, N_("Test video subsystem.")); +#ifdef GRUB_MACHINE_PCBIOS + cmd_vbe = grub_register_command ("vbetest", grub_cmd_videotest, + 0, N_("Test video subsystem.")); +#endif } GRUB_MOD_FINI(videotest) { grub_unregister_command (cmd); +#ifdef GRUB_MACHINE_PCBIOS + grub_unregister_command (cmd_vbe); +#endif } From 03199f1909e8f2181b60de2f45ea571fe4a8f75c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 3 Sep 2010 22:50:11 +0200 Subject: [PATCH 087/214] Fix order of dimensions in videoinfo --- grub-core/commands/videoinfo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/commands/videoinfo.c b/grub-core/commands/videoinfo.c index caa32c939..febb56aba 100644 --- a/grub-core/commands/videoinfo.c +++ b/grub-core/commands/videoinfo.c @@ -32,7 +32,7 @@ hook (const struct grub_video_mode_info *info) grub_printf (" "); else grub_printf (" 0x%03x ", info->mode_number); - grub_printf ("%4d x %4d x %2d ", info->height, info->width, info->bpp); + grub_printf ("%4d x %4d x %2d ", info->width, info->height, info->bpp); /* Show mask and position details for direct color modes. */ if (info->mode_type & GRUB_VIDEO_MODE_TYPE_RGB) From 30d71dbcedb44f7e13b9b8ebd38dfab2991c021b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Fri, 3 Sep 2010 22:50:27 +0200 Subject: [PATCH 088/214] dd GOP mode listing --- grub-core/video/efi_gop.c | 43 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/grub-core/video/efi_gop.c b/grub-core/video/efi_gop.c index 4e79b8521..cb04667eb 100644 --- a/grub-core/video/efi_gop.c +++ b/grub-core/video/efi_gop.c @@ -127,9 +127,11 @@ grub_video_gop_get_bitmask (grub_uint32_t mask, unsigned int *mask_size, } static grub_err_t -grub_video_gop_fill_mode_info (struct grub_efi_gop_mode_info *in, +grub_video_gop_fill_mode_info (unsigned mode, + struct grub_efi_gop_mode_info *in, struct grub_video_mode_info *out) { + out->mode_number = mode; out->number_of_colors = 256; out->width = in->width; out->height = in->height; @@ -183,6 +185,39 @@ grub_video_gop_fill_mode_info (struct grub_efi_gop_mode_info *in, return GRUB_ERR_NONE; } +static int +grub_video_gop_iterate (int (*hook) (const struct grub_video_mode_info *info)) +{ + unsigned mode; + + for (mode = 0; mode < gop->mode->max_mode; mode++) + { + grub_efi_uintn_t size; + grub_efi_status_t status; + struct grub_efi_gop_mode_info *info = NULL; + grub_err_t err; + struct grub_video_mode_info mode_info; + + status = efi_call_4 (gop->query_mode, gop, mode, &size, &info); + + if (status) + { + info = 0; + continue; + } + + err = grub_video_gop_fill_mode_info (mode, info, &mode_info); + if (err) + { + grub_errno = GRUB_ERR_NONE; + continue; + } + if (hook (&mode_info)) + return 1; + } + return 0; +} + static grub_err_t grub_video_gop_setup (unsigned int width, unsigned int height, unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused))) @@ -226,7 +261,7 @@ grub_video_gop_setup (unsigned int width, unsigned int height, if (status) { info = 0; - break; + continue; } grub_dprintf ("video", "GOP: mode %d: %dx%d\n", mode, info->width, @@ -281,7 +316,8 @@ grub_video_gop_setup (unsigned int width, unsigned int height, info = gop->mode->info; - err = grub_video_gop_fill_mode_info (info, &framebuffer.mode_info); + err = grub_video_gop_fill_mode_info (gop->mode->mode, info, + &framebuffer.mode_info); if (err) { grub_dprintf ("video", "GOP: couldn't fill mode info\n"); @@ -379,6 +415,7 @@ static struct grub_video_adapter grub_video_gop_adapter = .delete_render_target = grub_video_fb_delete_render_target, .set_active_render_target = grub_video_gop_set_active_render_target, .get_active_render_target = grub_video_fb_get_active_render_target, + .iterate = grub_video_gop_iterate, .next = 0 }; From 2550da89ecea329e6d2c01adc62b9f7b5b15ef56 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 4 Sep 2010 01:52:04 +0200 Subject: [PATCH 089/214] Add missing h2m --- docs/man/grub-mknetdir.h2m | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 docs/man/grub-mknetdir.h2m diff --git a/docs/man/grub-mknetdir.h2m b/docs/man/grub-mknetdir.h2m new file mode 100644 index 000000000..26defe876 --- /dev/null +++ b/docs/man/grub-mknetdir.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-mknetdir \- prepare a GRUB netboot directory. From df3df23d5cc5b2eb0598dc10b9378a64a0ebd956 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 4 Sep 2010 17:10:10 +0200 Subject: [PATCH 090/214] Reorganise memory map handling --- grub-core/Makefile.am | 9 +--- grub-core/boot/i386/qemu/boot.S | 1 + grub-core/commands/acpi.c | 9 ++-- grub-core/commands/i386/pc/drivemap.c | 5 +- grub-core/commands/lsmmap.c | 31 +++++++++--- grub-core/disk/i386/pc/biosdisk.c | 2 +- grub-core/efiemu/mm.c | 46 +++++++++--------- grub-core/kern/i386/coreboot/init.c | 9 ++-- grub-core/kern/i386/coreboot/mmap.c | 3 +- grub-core/kern/i386/coreboot/startup.S | 2 + grub-core/kern/i386/ieee1275/startup.S | 2 +- grub-core/kern/i386/multiboot_mmap.c | 15 +----- grub-core/kern/i386/pc/init.c | 8 +-- grub-core/kern/i386/pc/mmap.c | 27 ++++++++--- grub-core/kern/i386/qemu/mmap.c | 16 +++--- grub-core/kern/i386/qemu/startup.S | 2 + grub-core/kern/ieee1275/init.c | 35 ++------------ grub-core/kern/ieee1275/mmap.c | 6 +-- grub-core/kern/mips/qemu-mips/init.c | 7 +-- grub-core/kern/mips/yeeloong/init.c | 9 ++-- grub-core/lib/ieee1275/relocator.c | 10 ++-- grub-core/lib/relocator.c | 8 +-- grub-core/loader/i386/bsd.c | 25 ++++------ grub-core/loader/i386/linux.c | 34 ++++++------- grub-core/loader/i386/multiboot_mbi.c | 17 +++---- grub-core/loader/i386/pc/chainloader.c | 2 +- grub-core/loader/i386/pc/linux.c | 2 +- grub-core/loader/mips/linux.c | 2 +- grub-core/loader/multiboot.c | 3 +- grub-core/loader/multiboot_mbi2.c | 18 +++---- grub-core/loader/sparc64/ieee1275/linux.c | 7 ++- grub-core/mmap/efi/mmap.c | 39 ++++++++------- grub-core/mmap/i386/mmap.c | 7 +-- grub-core/mmap/i386/pc/mmap.c | 6 +-- grub-core/mmap/i386/uppermem.c | 22 +++++---- grub-core/mmap/mips/yeeloong/uppermem.c | 14 +++--- grub-core/mmap/mmap.c | 59 +++++++++-------------- grub-core/term/ns8250.c | 2 +- include/grub/autoefi.h | 16 ------ include/grub/efi/memory.h | 10 ---- include/grub/efiemu/efiemu.h | 5 -- include/grub/i386/coreboot/memory.h | 43 ++++++----------- include/grub/i386/ieee1275/memory.h | 2 +- include/grub/i386/memory.h | 8 +++ include/grub/i386/pc/memory.h | 42 ---------------- include/grub/i386/qemu/memory.h | 5 +- include/grub/memory.h | 31 ++++++++++-- include/grub/mips/qemu-mips/memory.h | 2 - include/grub/mips/yeeloong/memory.h | 7 --- include/grub/powerpc/ieee1275/memory.h | 26 ---------- include/grub/sparc64/ieee1275/memory.h | 26 ---------- 51 files changed, 301 insertions(+), 443 deletions(-) delete mode 100644 include/grub/powerpc/ieee1275/memory.h delete mode 100644 include/grub/sparc64/ieee1275/memory.h diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index 5d13d0313..135125f7a 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -74,9 +74,9 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/boot.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h if COND_i386_pc -KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/loader.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pxe.h @@ -92,24 +92,20 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h endif if COND_i386_coreboot -KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h endif if COND_i386_multiboot -KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h endif if COND_i386_qemu -KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h endif if COND_i386_ieee1275 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h -KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/terminfo.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/i386/pit.h endif @@ -123,7 +119,6 @@ endif if COND_mips_yeeloong KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/kernel.h -KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/cpu/cache.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bitmap.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/video.h @@ -135,7 +130,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/cs5536.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pci.h -KERNEL_HEADER_FILES += $(top_builddir)/include/grub/serial.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/serial.h endif if COND_powerpc_ieee1275 diff --git a/grub-core/boot/i386/qemu/boot.S b/grub-core/boot/i386/qemu/boot.S index fe14f0f06..97aeab9e6 100644 --- a/grub-core/boot/i386/qemu/boot.S +++ b/grub-core/boot/i386/qemu/boot.S @@ -18,6 +18,7 @@ #include #include +#include #include #include #include diff --git a/grub-core/commands/acpi.c b/grub-core/commands/acpi.c index 884ddf000..71d5fe812 100644 --- a/grub-core/commands/acpi.c +++ b/grub-core/commands/acpi.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include @@ -152,10 +151,10 @@ grub_acpi_create_ebda (void) auto int NESTED_FUNC_ATTR find_hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); int NESTED_FUNC_ATTR find_hook (grub_uint64_t start, grub_uint64_t size, - grub_uint32_t type) + grub_memory_type_t type) { grub_uint64_t end = start + size; - if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + if (type != GRUB_MEMORY_AVAILABLE) return 0; if (end > 0x100000) end = 0x100000; @@ -181,7 +180,7 @@ grub_acpi_create_ebda (void) "couldn't find space for the new EBDA"); mmapregion = grub_mmap_register (PTR_TO_UINT64 (targetebda), ebda_len, - GRUB_MACHINE_MEMORY_RESERVED); + GRUB_MEMORY_RESERVED); if (! mmapregion) return grub_errno; @@ -706,7 +705,7 @@ grub_cmd_acpi (struct grub_extcmd *cmd, playground = playground_ptr = grub_mmap_malign_and_register (1, playground_size, &mmapregion, - GRUB_MACHINE_MEMORY_ACPI, 0); + GRUB_MEMORY_ACPI, 0); if (! playground) { diff --git a/grub-core/commands/i386/pc/drivemap.c b/grub-core/commands/i386/pc/drivemap.c index 4afc43358..6a60671f8 100644 --- a/grub-core/commands/i386/pc/drivemap.c +++ b/grub-core/commands/i386/pc/drivemap.c @@ -24,9 +24,10 @@ #include #include #include -#include #include #include +#include +#include /* Real mode IVT slot (seg:off far pointer) for interrupt 0x13. */ @@ -306,7 +307,7 @@ install_int13_handler (int noret __attribute__ ((unused))) grub_dprintf ("drivemap", "Payload is %u bytes long\n", total_size); handler_base = grub_mmap_malign_and_register (16, total_size, &drivemap_mmap, - GRUB_MACHINE_MEMORY_RESERVED, + GRUB_MEMORY_RESERVED, GRUB_MMAP_MALLOC_LOW); if (! handler_base) return grub_error (GRUB_ERR_OUT_OF_MEMORY, "couldn't reserve " diff --git a/grub-core/commands/lsmmap.c b/grub-core/commands/lsmmap.c index 2755df9c4..657f81387 100644 --- a/grub-core/commands/lsmmap.c +++ b/grub-core/commands/lsmmap.c @@ -16,24 +16,39 @@ * along with GRUB. If not, see . */ -#ifndef GRUB_MACHINE_EMU -#include -#endif #include #include #include #include +#include + +static const char *names[] = + { + [GRUB_MEMORY_AVAILABLE] = "available", + [GRUB_MEMORY_RESERVED] = "reserved", + [GRUB_MEMORY_ACPI] = "ACPI reclamaible", + [GRUB_MEMORY_NVS] = "NVS", + [GRUB_MEMORY_BADRAM] = "BadRAM", + [GRUB_MEMORY_CODE] = "firmware code", + [GRUB_MEMORY_HOLE] = "hole" + }; static grub_err_t grub_cmd_lsmmap (grub_command_t cmd __attribute__ ((unused)), - int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) + int argc __attribute__ ((unused)), + char **args __attribute__ ((unused))) { - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); - int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_memory_type_t); + int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, + grub_memory_type_t type) { - grub_printf ("base_addr = 0x%llx, length = 0x%llx, type = 0x%x\n", - (long long) addr, (long long) size, type); + if (type < ARRAY_SIZE (names) && names[type]) + grub_printf ("base_addr = 0x%llx, length = 0x%llx, %s\n", + (long long) addr, (long long) size, names[type]); + else + grub_printf ("base_addr = 0x%llx, length = 0x%llx, type = 0x%x\n", + (long long) addr, (long long) size, type); return 0; } #ifndef GRUB_MACHINE_EMU diff --git a/grub-core/disk/i386/pc/biosdisk.c b/grub-core/disk/i386/pc/biosdisk.c index 17de0c1a1..934a4692a 100644 --- a/grub-core/disk/i386/pc/biosdisk.c +++ b/grub-core/disk/i386/pc/biosdisk.c @@ -17,8 +17,8 @@ */ #include -#include #include +#include #include #include #include diff --git a/grub-core/efiemu/mm.c b/grub-core/efiemu/mm.c index de7d309be..3c1dc2946 100644 --- a/grub-core/efiemu/mm.c +++ b/grub-core/efiemu/mm.c @@ -29,8 +29,8 @@ #include #include #include -#include #include +#include struct grub_efiemu_memrequest { @@ -269,10 +269,11 @@ static grub_err_t grub_efiemu_mmap_init (void) { auto int NESTED_FUNC_ATTR bounds_hook (grub_uint64_t, grub_uint64_t, - grub_uint32_t); + grub_memory_type_t); int NESTED_FUNC_ATTR bounds_hook (grub_uint64_t addr __attribute__ ((unused)), grub_uint64_t size __attribute__ ((unused)), - grub_uint32_t type __attribute__ ((unused))) + grub_memory_type_t type + __attribute__ ((unused))) { mmap_reserved_size++; return 0; @@ -382,32 +383,29 @@ grub_efiemu_mm_init (void) static grub_err_t grub_efiemu_mmap_fill (void) { - auto int NESTED_FUNC_ATTR fill_hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + auto int NESTED_FUNC_ATTR fill_hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); int NESTED_FUNC_ATTR fill_hook (grub_uint64_t addr, grub_uint64_t size, - grub_uint32_t type) + grub_memory_type_t type) { switch (type) { - case GRUB_MACHINE_MEMORY_AVAILABLE: + case GRUB_MEMORY_AVAILABLE: return grub_efiemu_add_to_mmap (addr, size, GRUB_EFI_CONVENTIONAL_MEMORY); -#ifdef GRUB_MACHINE_MEMORY_ACPI - case GRUB_MACHINE_MEMORY_ACPI: + case GRUB_MEMORY_ACPI: return grub_efiemu_add_to_mmap (addr, size, GRUB_EFI_ACPI_RECLAIM_MEMORY); -#endif -#ifdef GRUB_MACHINE_MEMORY_NVS - case GRUB_MACHINE_MEMORY_NVS: + case GRUB_MEMORY_NVS: return grub_efiemu_add_to_mmap (addr, size, GRUB_EFI_ACPI_MEMORY_NVS); -#endif default: - grub_printf ("Unknown memory type %d. Marking as unusable\n", type); - case GRUB_MACHINE_MEMORY_RESERVED: + grub_printf ("Unknown memory type %d. Assuming unusable\n", type); + case GRUB_MEMORY_RESERVED: return grub_efiemu_add_to_mmap (addr, size, GRUB_EFI_UNUSABLE_MEMORY); } @@ -421,9 +419,7 @@ grub_efiemu_mmap_fill (void) } grub_err_t -grub_efiemu_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, - grub_uint64_t, - grub_uint32_t)) +grub_efiemu_mmap_iterate (grub_memory_hook_t hook) { unsigned i; @@ -432,18 +428,22 @@ grub_efiemu_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, { case GRUB_EFI_RUNTIME_SERVICES_CODE: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_EFIEMU_MEMORY_CODE); + GRUB_MEMORY_CODE); + break; + + case GRUB_EFI_UNUSABLE_MEMORY: + hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, + GRUB_MEMORY_BADRAM); break; case GRUB_EFI_RESERVED_MEMORY_TYPE: case GRUB_EFI_RUNTIME_SERVICES_DATA: - case GRUB_EFI_UNUSABLE_MEMORY: case GRUB_EFI_MEMORY_MAPPED_IO: case GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE: case GRUB_EFI_PAL_CODE: case GRUB_EFI_MAX_MEMORY_TYPE: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_EFIEMU_MEMORY_RESERVED); + GRUB_MEMORY_RESERVED); break; case GRUB_EFI_LOADER_CODE: @@ -452,17 +452,17 @@ grub_efiemu_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, case GRUB_EFI_BOOT_SERVICES_DATA: case GRUB_EFI_CONVENTIONAL_MEMORY: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_EFIEMU_MEMORY_AVAILABLE); + GRUB_MEMORY_AVAILABLE); break; case GRUB_EFI_ACPI_RECLAIM_MEMORY: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_EFIEMU_MEMORY_ACPI); + GRUB_MEMORY_ACPI); break; case GRUB_EFI_ACPI_MEMORY_NVS: hook (efiemu_mmap[i].physical_start, efiemu_mmap[i].num_pages * 4096, - GRUB_EFIEMU_MEMORY_NVS); + GRUB_MEMORY_NVS); break; } diff --git a/grub-core/kern/i386/coreboot/init.c b/grub-core/kern/i386/coreboot/init.c index 75f385b56..434b9b5a8 100644 --- a/grub-core/kern/i386/coreboot/init.c +++ b/grub-core/kern/i386/coreboot/init.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -64,8 +65,10 @@ grub_machine_init (void) /* Initialize the console as early as possible. */ grub_vga_text_init (); - auto int NESTED_FUNC_ATTR heap_init (grub_uint64_t, grub_uint64_t, grub_uint32_t); - int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) + auto int NESTED_FUNC_ATTR heap_init (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); + int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t size, + grub_memory_type_t type) { #if GRUB_CPU_SIZEOF_VOID_P == 4 /* Restrict ourselves to 32-bit memory space. */ @@ -75,7 +78,7 @@ grub_machine_init (void) size = GRUB_ULONG_MAX - addr; #endif - if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + if (type != GRUB_MEMORY_AVAILABLE) return 0; /* Avoid the lower memory. */ diff --git a/grub-core/kern/i386/coreboot/mmap.c b/grub-core/kern/i386/coreboot/mmap.c index d06627a08..8b0b20265 100644 --- a/grub-core/kern/i386/coreboot/mmap.c +++ b/grub-core/kern/i386/coreboot/mmap.c @@ -17,6 +17,7 @@ */ #include +#include #include #include #include @@ -74,7 +75,7 @@ signature_found: } grub_err_t -grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { mem_region_t mem_region; diff --git a/grub-core/kern/i386/coreboot/startup.S b/grub-core/kern/i386/coreboot/startup.S index 592073776..cac023ddf 100644 --- a/grub-core/kern/i386/coreboot/startup.S +++ b/grub-core/kern/i386/coreboot/startup.S @@ -17,6 +17,8 @@ */ #include +/* For stack parameters. */ +#include #include #include #include diff --git a/grub-core/kern/i386/ieee1275/startup.S b/grub-core/kern/i386/ieee1275/startup.S index 3ecf09598..82087323b 100644 --- a/grub-core/kern/i386/ieee1275/startup.S +++ b/grub-core/kern/i386/ieee1275/startup.S @@ -17,7 +17,7 @@ */ #include -#include +#include #include #include #include diff --git a/grub-core/kern/i386/multiboot_mmap.c b/grub-core/kern/i386/multiboot_mmap.c index 73c82049f..7f4bc3b5c 100644 --- a/grub-core/kern/i386/multiboot_mmap.c +++ b/grub-core/kern/i386/multiboot_mmap.c @@ -22,8 +22,6 @@ #include #include -grub_size_t grub_lower_mem, grub_upper_mem; - /* A pointer to the MBI in its initial location. */ struct multiboot_info *startup_multiboot_info; @@ -56,21 +54,10 @@ grub_machine_mmap_init () } grub_memmove (mmap_entries, (void *) kern_multiboot_info.mmap_addr, kern_multiboot_info.mmap_length); kern_multiboot_info.mmap_addr = (grub_uint32_t) mmap_entries; - - if ((kern_multiboot_info.flags & MULTIBOOT_INFO_MEMORY) == 0) - { - grub_lower_mem = GRUB_MEMORY_MACHINE_LOWER_USABLE; - grub_upper_mem = 0; - } - else - { - grub_lower_mem = kern_multiboot_info.mem_lower * 1024; - grub_upper_mem = kern_multiboot_info.mem_upper * 1024; - } } grub_err_t -grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { struct multiboot_mmap_entry *entry = (void *) kern_multiboot_info.mmap_addr; diff --git a/grub-core/kern/i386/pc/init.c b/grub-core/kern/i386/pc/init.c index 57e33569e..815e8e7c7 100644 --- a/grub-core/kern/i386/pc/init.c +++ b/grub-core/kern/i386/pc/init.c @@ -186,8 +186,10 @@ grub_machine_init (void) grub_lower_mem - GRUB_MEMORY_MACHINE_RESERVED_END); #endif - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); - int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); + int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, + grub_memory_type_t type) { /* Avoid the lower memory. */ if (addr < 0x100000) @@ -200,7 +202,7 @@ grub_machine_init (void) } /* Ignore >4GB. */ - if (addr <= 0xFFFFFFFF && type == GRUB_MACHINE_MEMORY_AVAILABLE) + if (addr <= 0xFFFFFFFF && type == GRUB_MEMORY_AVAILABLE) { grub_size_t len; diff --git a/grub-core/kern/i386/pc/mmap.c b/grub-core/kern/i386/pc/mmap.c index b174bc441..798256fd8 100644 --- a/grub-core/kern/i386/pc/mmap.c +++ b/grub-core/kern/i386/pc/mmap.c @@ -23,6 +23,20 @@ #include #include +struct grub_machine_mmap_entry +{ + grub_uint32_t size; + grub_uint64_t addr; + grub_uint64_t len; +#define GRUB_MACHINE_MEMORY_AVAILABLE 1 +#define GRUB_MACHINE_MEMORY_RESERVED 2 +#define GRUB_MACHINE_MEMORY_ACPI 3 +#define GRUB_MACHINE_MEMORY_NVS 4 +#define GRUB_MACHINE_MEMORY_BADRAM 5 + grub_uint32_t type; +} __attribute__((packed)); + + /* * grub_get_ext_memsize() : return the extended memory size in KB. * BIOS call "INT 15H, AH=88H" to get extended memory size @@ -110,7 +124,7 @@ grub_get_mmap_entry (struct grub_machine_mmap_entry *entry, } grub_err_t -grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { grub_uint32_t cont; struct grub_machine_mmap_entry *entry @@ -125,9 +139,9 @@ grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uin do { if (hook (entry->addr, entry->len, - /* Multiboot mmaps have been defined to match with the E820 definition. + /* GRUB mmaps have been defined to match with the E820 definition. Therefore, we can just pass type through. */ - entry->type)) + ((entry->type <= GRUB_MACHINE_MEMORY_BADRAM) && (entry->type >= GRUB_MACHINE_MEMORY_AVAILABLE)) ? entry->type : GRUB_MEMORY_RESERVED)) break; if (! cont) @@ -144,11 +158,12 @@ grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uin if (eisa_mmap) { - if (hook (0x100000, (eisa_mmap & 0xFFFF) << 10, GRUB_MACHINE_MEMORY_AVAILABLE) == 0) - hook (0x1000000, eisa_mmap & ~0xFFFF, GRUB_MACHINE_MEMORY_AVAILABLE); + if (hook (0x100000, (eisa_mmap & 0xFFFF) << 10, + GRUB_MEMORY_AVAILABLE) == 0) + hook (0x1000000, eisa_mmap & ~0xFFFF, GRUB_MEMORY_AVAILABLE); } else - hook (0x100000, grub_get_ext_memsize () << 10, GRUB_MACHINE_MEMORY_AVAILABLE); + hook (0x100000, grub_get_ext_memsize () << 10, GRUB_MEMORY_AVAILABLE); } return 0; diff --git a/grub-core/kern/i386/qemu/mmap.c b/grub-core/kern/i386/qemu/mmap.c index f8b4b9b4f..208f36b7e 100644 --- a/grub-core/kern/i386/qemu/mmap.c +++ b/grub-core/kern/i386/qemu/mmap.c @@ -16,12 +16,14 @@ * along with GRUB. If not, see . */ +#include #include #include #include #include #include #include +#include #define QEMU_CMOS_MEMSIZE_HIGH 0x35 #define QEMU_CMOS_MEMSIZE_LOW 0x34 @@ -60,38 +62,38 @@ grub_machine_mmap_init () } grub_err_t -grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { if (hook (0x0, (grub_addr_t) _start, - GRUB_MACHINE_MEMORY_AVAILABLE)) + GRUB_MEMORY_AVAILABLE)) return 1; if (hook ((grub_addr_t) _end, 0xa0000 - (grub_addr_t) _end, - GRUB_MACHINE_MEMORY_AVAILABLE)) + GRUB_MEMORY_AVAILABLE)) return 1; if (hook (GRUB_MEMORY_MACHINE_UPPER, 0x100000 - GRUB_MEMORY_MACHINE_UPPER, - GRUB_MACHINE_MEMORY_RESERVED)) + GRUB_MEMORY_RESERVED)) return 1; /* Everything else is free. */ if (hook (0x100000, min (mem_size, (grub_uint32_t) -GRUB_BOOT_MACHINE_SIZE) - 0x100000, - GRUB_MACHINE_MEMORY_AVAILABLE)) + GRUB_MEMORY_AVAILABLE)) return 1; /* Protect boot.img, which contains the gdt. It is mapped at the top of memory (it is also mapped below 0x100000, but we already reserved that area). */ if (hook ((grub_uint32_t) -GRUB_BOOT_MACHINE_SIZE, GRUB_BOOT_MACHINE_SIZE, - GRUB_MACHINE_MEMORY_RESERVED)) + GRUB_MEMORY_RESERVED)) return 1; if (above_4g != 0 && hook (0x100000000ULL, above_4g, - GRUB_MACHINE_MEMORY_AVAILABLE)) + GRUB_MEMORY_AVAILABLE)) return 1; return 0; diff --git a/grub-core/kern/i386/qemu/startup.S b/grub-core/kern/i386/qemu/startup.S index 680de9dc4..7834d1df5 100644 --- a/grub-core/kern/i386/qemu/startup.S +++ b/grub-core/kern/i386/qemu/startup.S @@ -18,6 +18,8 @@ #include #include + +#include #include #include diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c index 99ce7179b..682a8b5a4 100644 --- a/grub-core/kern/ieee1275/init.c +++ b/grub-core/kern/ieee1275/init.c @@ -32,6 +32,7 @@ #include #include #include +#include /* The minimal heap size we can live with. */ #define HEAP_MIN_SIZE (unsigned long) (2 * 1024 * 1024) @@ -126,8 +127,10 @@ static void grub_claim_heap (void) { unsigned long total = 0; - auto int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type); - int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type) + auto int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t len, + grub_memory_type_t type); + int NESTED_FUNC_ATTR heap_init (grub_uint64_t addr, grub_uint64_t len, + grub_memory_type_t type) { if (type != 1) return 0; @@ -189,31 +192,6 @@ static void grub_claim_heap (void) grub_machine_mmap_iterate (heap_init); } -#ifdef __i386__ - -grub_uint32_t grub_upper_mem; - -/* We need to call this before grub_claim_memory. */ -static void -grub_get_extended_memory (void) -{ - auto int NESTED_FUNC_ATTR find_ext_mem (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type); - int NESTED_FUNC_ATTR find_ext_mem (grub_uint64_t addr, grub_uint64_t len, grub_uint32_t type) - { - if (type == 1 && addr == 0x100000) - { - grub_upper_mem = len; - return 1; - } - - return 0; - } - - grub_machine_mmap_iterate (find_ext_mem); -} - -#endif - static grub_uint64_t ieee1275_get_time_ms (void); void @@ -225,9 +203,6 @@ grub_machine_init (void) grub_ieee1275_init (); grub_console_init_early (); -#ifdef __i386__ - grub_get_extended_memory (); -#endif grub_claim_heap (); grub_console_init_lately (); grub_ofdisk_init (); diff --git a/grub-core/kern/ieee1275/mmap.c b/grub-core/kern/ieee1275/mmap.c index 6f0652770..942e5a354 100644 --- a/grub-core/kern/ieee1275/mmap.c +++ b/grub-core/kern/ieee1275/mmap.c @@ -16,12 +16,12 @@ * along with GRUB. If not, see . */ -#include +#include #include #include grub_err_t -grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { grub_ieee1275_phandle_t root; grub_ieee1275_phandle_t memory; @@ -66,7 +66,7 @@ grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uin if (size_cells == 2) size = (size << 32) | available[i++]; - if (hook (address, size, GRUB_MACHINE_MEMORY_AVAILABLE)) + if (hook (address, size, GRUB_MEMORY_AVAILABLE)) break; } diff --git a/grub-core/kern/mips/qemu-mips/init.c b/grub-core/kern/mips/qemu-mips/init.c index 866c7a82a..f2bb652a8 100644 --- a/grub-core/kern/mips/qemu-mips/init.c +++ b/grub-core/kern/mips/qemu-mips/init.c @@ -51,11 +51,8 @@ grub_reboot (void) } grub_err_t -grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, - grub_uint64_t, - grub_uint32_t)) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { - hook (0, RAMSIZE, - GRUB_MACHINE_MEMORY_AVAILABLE); + hook (0, RAMSIZE, GRUB_MEMORY_AVAILABLE); return GRUB_ERR_NONE; } diff --git a/grub-core/kern/mips/yeeloong/init.c b/grub-core/kern/mips/yeeloong/init.c index 523f90282..6b906d06e 100644 --- a/grub-core/kern/mips/yeeloong/init.c +++ b/grub-core/kern/mips/yeeloong/init.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -57,14 +58,12 @@ grub_get_rtc (void) } grub_err_t -grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, - grub_uint64_t, - grub_uint32_t)) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { hook (GRUB_ARCH_LOWMEMPSTART, grub_arch_memsize << 20, - GRUB_MACHINE_MEMORY_AVAILABLE); + GRUB_MEMORY_AVAILABLE); hook (GRUB_ARCH_HIGHMEMPSTART, grub_arch_highmemsize << 20, - GRUB_MACHINE_MEMORY_AVAILABLE); + GRUB_MEMORY_AVAILABLE); return GRUB_ERR_NONE; } diff --git a/grub-core/lib/ieee1275/relocator.c b/grub-core/lib/ieee1275/relocator.c index 947346d46..c09f1e9c5 100644 --- a/grub-core/lib/ieee1275/relocator.c +++ b/grub-core/lib/ieee1275/relocator.c @@ -27,10 +27,10 @@ grub_relocator_firmware_get_max_events (void) int counter = 0; auto int NESTED_FUNC_ATTR count (grub_uint64_t addr __attribute__ ((unused)), grub_uint64_t len __attribute__ ((unused)), - grub_uint32_t type __attribute__ ((unused))); + grub_memory_type_t type __attribute__ ((unused))); int NESTED_FUNC_ATTR count (grub_uint64_t addr __attribute__ ((unused)), grub_uint64_t len __attribute__ ((unused)), - grub_uint32_t type __attribute__ ((unused))) + grub_memory_type_t type __attribute__ ((unused))) { counter++; return 0; @@ -47,11 +47,11 @@ grub_relocator_firmware_fill_events (struct grub_relocator_mmap_event *events) { int counter = 0; auto int NESTED_FUNC_ATTR fill (grub_uint64_t addr, grub_uint64_t len, - grub_uint32_t type); + grub_memory_type_t type); int NESTED_FUNC_ATTR fill (grub_uint64_t addr, grub_uint64_t len, - grub_uint32_t type) + grub_memory_type_t type) { - if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + if (type != GRUB_MEMORY_AVAILABLE) return 0; if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM)) diff --git a/grub-core/lib/relocator.c b/grub-core/lib/relocator.c index 53acda52f..9a6941332 100644 --- a/grub-core/lib/relocator.c +++ b/grub-core/lib/relocator.c @@ -1379,11 +1379,13 @@ grub_relocator_alloc_chunk_align (struct grub_relocator *rel, { int found = 0; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); - int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t sz, grub_uint32_t type) + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); + int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t sz, + grub_memory_type_t type) { grub_uint64_t candidate; - if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + if (type != GRUB_MEMORY_AVAILABLE) return 0; candidate = ALIGN_UP (addr, align); if (candidate < min_addr) diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c index d72c8195a..b35b4258c 100644 --- a/grub-core/loader/i386/bsd.c +++ b/grub-core/loader/i386/bsd.c @@ -19,8 +19,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -262,37 +262,30 @@ generate_e820_mmap (grub_size_t *len, grub_size_t *cnt, void *buf) struct grub_e820_mmap *mmap = buf; struct grub_e820_mmap prev, cur; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, - grub_uint32_t type) + grub_memory_type_t type) { cur.addr = addr; cur.size = size; switch (type) { - case GRUB_MACHINE_MEMORY_AVAILABLE: + case GRUB_MEMORY_AVAILABLE: cur.type = GRUB_E820_RAM; break; -#ifdef GRUB_MACHINE_MEMORY_ACPI - case GRUB_MACHINE_MEMORY_ACPI: + case GRUB_MEMORY_ACPI: cur.type = GRUB_E820_ACPI; break; -#endif -#ifdef GRUB_MACHINE_MEMORY_NVS - case GRUB_MACHINE_MEMORY_NVS: + case GRUB_MEMORY_NVS: cur.type = GRUB_E820_NVS; break; -#endif default: -#ifdef GRUB_MACHINE_MEMORY_CODE - case GRUB_MACHINE_MEMORY_CODE: -#endif -#ifdef GRUB_MACHINE_MEMORY_RESERVED - case GRUB_MACHINE_MEMORY_RESERVED: -#endif + case GRUB_MEMORY_CODE: + case GRUB_MEMORY_RESERVED: cur.type = GRUB_E820_RESERVED; break; } diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c index 9cb26a0c2..99670d4e3 100644 --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -17,7 +17,6 @@ */ #include -#include #include #include #include @@ -312,10 +311,11 @@ find_mmap_size (void) { grub_size_t count = 0, mmap_size; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); int NESTED_FUNC_ATTR hook (grub_uint64_t addr __attribute__ ((unused)), grub_uint64_t size __attribute__ ((unused)), - grub_uint32_t type __attribute__ ((unused))) + grub_memory_type_t type __attribute__ ((unused))) { count++; return 0; @@ -379,12 +379,14 @@ allocate_pages (grub_size_t prot_size) /* FIXME: Should request low memory from the heap when this feature is implemented. */ - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); - int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); + int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, + grub_memory_type_t type) { /* We must put real mode code in the traditional space. */ - if (type == GRUB_MACHINE_MEMORY_AVAILABLE + if (type == GRUB_MEMORY_AVAILABLE && addr <= 0x90000) { if (addr < 0x10000) @@ -559,36 +561,32 @@ grub_linux_boot (void) grub_dprintf ("linux", "code32_start = %x\n", (unsigned) params->code32_start); - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); - int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); + int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, + grub_memory_type_t type) { switch (type) { - case GRUB_MACHINE_MEMORY_AVAILABLE: + case GRUB_MEMORY_AVAILABLE: grub_e820_add_region (params->e820_map, &e820_num, addr, size, GRUB_E820_RAM); break; -#ifdef GRUB_MACHINE_MEMORY_ACPI - case GRUB_MACHINE_MEMORY_ACPI: + case GRUB_MEMORY_ACPI: grub_e820_add_region (params->e820_map, &e820_num, addr, size, GRUB_E820_ACPI); break; -#endif -#ifdef GRUB_MACHINE_MEMORY_NVS - case GRUB_MACHINE_MEMORY_NVS: + case GRUB_MEMORY_NVS: grub_e820_add_region (params->e820_map, &e820_num, addr, size, GRUB_E820_NVS); break; -#endif -#ifdef GRUB_MACHINE_MEMORY_CODE - case GRUB_MACHINE_MEMORY_CODE: + case GRUB_MEMORY_CODE: grub_e820_add_region (params->e820_map, &e820_num, addr, size, GRUB_E820_EXEC_CODE); break; -#endif default: grub_e820_add_region (params->e820_map, &e820_num, diff --git a/grub-core/loader/i386/multiboot_mbi.c b/grub-core/loader/i386/multiboot_mbi.c index bf17863cf..10450d68e 100644 --- a/grub-core/loader/i386/multiboot_mbi.c +++ b/grub-core/loader/i386/multiboot_mbi.c @@ -16,7 +16,6 @@ * along with GRUB. If not, see . */ -#include #include #ifdef GRUB_MACHINE_PCBIOS #include @@ -203,28 +202,26 @@ grub_fill_multiboot_mmap (struct multiboot_mmap_entry *first_entry) { struct multiboot_mmap_entry *mmap_entry = (struct multiboot_mmap_entry *) first_entry; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); - int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); + int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, + grub_memory_type_t type) { mmap_entry->addr = addr; mmap_entry->len = size; switch (type) { - case GRUB_MACHINE_MEMORY_AVAILABLE: + case GRUB_MEMORY_AVAILABLE: mmap_entry->type = MULTIBOOT_MEMORY_AVAILABLE; break; -#ifdef GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE - case GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE: + case GRUB_MEMORY_ACPI: mmap_entry->type = MULTIBOOT_MEMORY_ACPI_RECLAIMABLE; break; -#endif -#ifdef GRUB_MACHINE_MEMORY_NVS - case GRUB_MACHINE_MEMORY_NVS: + case GRUB_MEMORY_NVS: mmap_entry->type = MULTIBOOT_MEMORY_NVS; break; -#endif default: mmap_entry->type = MULTIBOOT_MEMORY_RESERVED; diff --git a/grub-core/loader/i386/pc/chainloader.c b/grub-core/loader/i386/pc/chainloader.c index 502031d0e..e455e9e52 100644 --- a/grub-core/loader/i386/pc/chainloader.c +++ b/grub-core/loader/i386/pc/chainloader.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c index 0719cfb26..899545ccd 100644 --- a/grub-core/loader/i386/pc/linux.c +++ b/grub-core/loader/i386/pc/linux.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/grub-core/loader/mips/linux.c b/grub-core/loader/mips/linux.c index 018cfdcc5..78b7dd632 100644 --- a/grub-core/loader/mips/linux.c +++ b/grub-core/loader/mips/linux.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include /* For frequencies. */ diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c index 1de1def86..7c0fa1b77 100644 --- a/grub-core/loader/multiboot.c +++ b/grub-core/loader/multiboot.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -74,7 +73,7 @@ grub_get_multiboot_mmap_count (void) auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); int NESTED_FUNC_ATTR hook (grub_uint64_t addr __attribute__ ((unused)), grub_uint64_t size __attribute__ ((unused)), - grub_uint32_t type __attribute__ ((unused))) + grub_memory_type_t type __attribute__ ((unused))) { count++; return 0; diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c index f453dcc6a..8ef928b51 100644 --- a/grub-core/loader/multiboot_mbi2.c +++ b/grub-core/loader/multiboot_mbi2.c @@ -16,10 +16,10 @@ * along with GRUB. If not, see . */ -#include #include #ifdef GRUB_MACHINE_PCBIOS #include +#include #endif #include #include @@ -288,28 +288,26 @@ grub_fill_multiboot_mmap (struct multiboot_tag_mmap *tag) { struct multiboot_mmap_entry *mmap_entry = tag->entries; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); - int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, grub_uint32_t type) + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); + int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, + grub_memory_type_t type) { mmap_entry->addr = addr; mmap_entry->len = size; switch (type) { - case GRUB_MACHINE_MEMORY_AVAILABLE: + case GRUB_MEMORY_AVAILABLE: mmap_entry->type = MULTIBOOT_MEMORY_AVAILABLE; break; -#ifdef GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE - case GRUB_MACHINE_MEMORY_ACPI_RECLAIMABLE: + case GRUB_MEMORY_ACPI: mmap_entry->type = MULTIBOOT_MEMORY_ACPI_RECLAIMABLE; break; -#endif -#ifdef GRUB_MACHINE_MEMORY_NVS - case GRUB_MACHINE_MEMORY_NVS: + case GRUB_MEMORY_NVS: mmap_entry->type = MULTIBOOT_MEMORY_NVS; break; -#endif default: mmap_entry->type = MULTIBOOT_MEMORY_RESERVED; diff --git a/grub-core/loader/sparc64/ieee1275/linux.c b/grub-core/loader/sparc64/ieee1275/linux.c index 948729a5d..99051ea78 100644 --- a/grub-core/loader/sparc64/ieee1275/linux.c +++ b/grub-core/loader/sparc64/ieee1275/linux.c @@ -27,6 +27,7 @@ #include #include #include +#include static grub_dl_t my_mod; @@ -182,8 +183,10 @@ alloc_phys (grub_addr_t size) { grub_addr_t ret = (grub_addr_t) -1; - auto int NESTED_FUNC_ATTR choose (grub_uint64_t addr, grub_uint64_t len __attribute__((unused)), grub_uint32_t type); - int NESTED_FUNC_ATTR choose (grub_uint64_t addr, grub_uint64_t len __attribute__((unused)), grub_uint32_t type) + auto int NESTED_FUNC_ATTR choose (grub_uint64_t addr, grub_uint64_t len, + grub_memory_type_t type); + int NESTED_FUNC_ATTR choose (grub_uint64_t addr, grub_uint64_t len, + grub_memory_type_t type) { grub_addr_t end = addr + len; diff --git a/grub-core/mmap/efi/mmap.c b/grub-core/mmap/efi/mmap.c index 316c997c7..5b82a8717 100644 --- a/grub-core/mmap/efi/mmap.c +++ b/grub-core/mmap/efi/mmap.c @@ -29,9 +29,7 @@ ((grub_efi_memory_descriptor_t *) ((char *) (desc) + (size))) grub_err_t -grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, - grub_uint64_t, - grub_uint32_t)) +grub_machine_mmap_iterate (grub_memory_hook_t hook) { grub_efi_uintn_t mmap_size = 0; grub_efi_memory_descriptor_t *map_buf = 0; @@ -69,7 +67,12 @@ grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, { case GRUB_EFI_RUNTIME_SERVICES_CODE: hook (desc->physical_start, desc->num_pages * 4096, - GRUB_MACHINE_MEMORY_CODE); + GRUB_MEMORY_CODE); + break; + + case GRUB_EFI_UNUSABLE_MEMORY: + hook (desc->physical_start, desc->num_pages * 4096, + GRUB_MEMORY_BADRAM); break; default: @@ -78,12 +81,11 @@ grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, case GRUB_EFI_RESERVED_MEMORY_TYPE: case GRUB_EFI_RUNTIME_SERVICES_DATA: - case GRUB_EFI_UNUSABLE_MEMORY: case GRUB_EFI_MEMORY_MAPPED_IO: case GRUB_EFI_MEMORY_MAPPED_IO_PORT_SPACE: case GRUB_EFI_PAL_CODE: hook (desc->physical_start, desc->num_pages * 4096, - GRUB_MACHINE_MEMORY_RESERVED); + GRUB_MEMORY_RESERVED); break; case GRUB_EFI_LOADER_CODE: @@ -92,17 +94,17 @@ grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, case GRUB_EFI_BOOT_SERVICES_DATA: case GRUB_EFI_CONVENTIONAL_MEMORY: hook (desc->physical_start, desc->num_pages * 4096, - GRUB_MACHINE_MEMORY_AVAILABLE); + GRUB_MEMORY_AVAILABLE); break; case GRUB_EFI_ACPI_RECLAIM_MEMORY: hook (desc->physical_start, desc->num_pages * 4096, - GRUB_MACHINE_MEMORY_ACPI); + GRUB_MEMORY_ACPI); break; case GRUB_EFI_ACPI_MEMORY_NVS: hook (desc->physical_start, desc->num_pages * 4096, - GRUB_MACHINE_MEMORY_NVS); + GRUB_MEMORY_NVS); break; } } @@ -115,29 +117,26 @@ make_efi_memtype (int type) { switch (type) { - case GRUB_MACHINE_MEMORY_CODE: + case GRUB_MEMORY_CODE: return GRUB_EFI_RUNTIME_SERVICES_CODE; /* No way to remove a chunk of memory from EFI mmap. So mark it as unusable. */ - case GRUB_MACHINE_MEMORY_HOLE: - - default: - - case GRUB_MACHINE_MEMORY_RESERVED: + case GRUB_MEMORY_HOLE: + case GRUB_MEMORY_RESERVED: return GRUB_EFI_UNUSABLE_MEMORY; - case GRUB_MACHINE_MEMORY_AVAILABLE: + case GRUB_MEMORY_AVAILABLE: return GRUB_EFI_CONVENTIONAL_MEMORY; - case GRUB_MACHINE_MEMORY_ACPI: - return GRUB_EFI_ACPI_RECLAIM_MEMORY; - - case GRUB_MACHINE_MEMORY_NVS: + case GRUB_MEMORY_ACPI: return GRUB_EFI_ACPI_RECLAIM_MEMORY; + case GRUB_MEMORY_NVS: + return GRUB_EFI_ACPI_MEMORY_NVS; } + return GRUB_EFI_UNUSABLE_MEMORY; } struct overlay diff --git a/grub-core/mmap/i386/mmap.c b/grub-core/mmap/i386/mmap.c index f6e16129e..e9c030b7b 100644 --- a/grub-core/mmap/i386/mmap.c +++ b/grub-core/mmap/i386/mmap.c @@ -18,6 +18,7 @@ */ #include +#include #include #include #include @@ -33,12 +34,12 @@ grub_mmap_malign_and_register (grub_uint64_t align, grub_uint64_t size, grub_uint64_t highestlow = 0; auto int NESTED_FUNC_ATTR find_hook (grub_uint64_t, grub_uint64_t, - grub_uint32_t); + grub_memory_type_t); int NESTED_FUNC_ATTR find_hook (grub_uint64_t start, grub_uint64_t rangesize, - grub_uint32_t memtype) + grub_memory_type_t memtype) { grub_uint64_t end = start + rangesize; - if (memtype != GRUB_MACHINE_MEMORY_AVAILABLE) + if (memtype != GRUB_MEMORY_AVAILABLE) return 0; if (end > 0x100000) end = 0x100000; diff --git a/grub-core/mmap/i386/pc/mmap.c b/grub-core/mmap/i386/pc/mmap.c index 7d5a43fec..8dec083f8 100644 --- a/grub-core/mmap/i386/pc/mmap.c +++ b/grub-core/mmap/i386/pc/mmap.c @@ -57,7 +57,7 @@ preboot (int noreturn __attribute__ ((unused))) auto int NESTED_FUNC_ATTR fill_hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); int NESTED_FUNC_ATTR fill_hook (grub_uint64_t addr, grub_uint64_t size, - grub_uint32_t type) + grub_memory_type_t type) { grub_dprintf ("mmap", "mmap chunk %llx-%llx:%x\n", addr, addr + size, type); hookmmapcur->addr = addr; @@ -135,7 +135,7 @@ malloc_hook (void) grub_uint32_t); int NESTED_FUNC_ATTR count_hook (grub_uint64_t addr __attribute__ ((unused)), grub_uint64_t size __attribute__ ((unused)), - grub_uint32_t type __attribute__ ((unused))) + grub_memory_type_t type __attribute__ ((unused))) { regcount++; return 0; @@ -172,7 +172,7 @@ malloc_hook (void) reentry = 1; hooktarget = grub_mmap_malign_and_register (16, hooksize, &mmapregion, - GRUB_MACHINE_MEMORY_RESERVED, + GRUB_MEMORY_RESERVED, GRUB_MMAP_MALLOC_LOW); reentry = 0; diff --git a/grub-core/mmap/i386/uppermem.c b/grub-core/mmap/i386/uppermem.c index cd1a45239..2aa430155 100644 --- a/grub-core/mmap/i386/uppermem.c +++ b/grub-core/mmap/i386/uppermem.c @@ -18,6 +18,7 @@ */ #include +#include #include #include @@ -26,11 +27,12 @@ grub_mmap_get_lower (void) { grub_uint64_t lower = 0; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, - grub_uint32_t type) + grub_memory_type_t type) { - if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + if (type != GRUB_MEMORY_AVAILABLE) return 0; if (addr == 0) lower = size; @@ -48,11 +50,12 @@ grub_mmap_get_upper (void) { grub_uint64_t upper = 0; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, - grub_uint32_t type) + grub_memory_type_t type) { - if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + if (type != GRUB_MEMORY_AVAILABLE) return 0; if (addr <= 0x100000 && addr + size > 0x100000) upper = addr + size - 0x100000; @@ -69,11 +72,12 @@ grub_mmap_get_post64 (void) { grub_uint64_t post64 = 0; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, - grub_uint32_t type) + grub_memory_type_t type) { - if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + if (type != GRUB_MEMORY_AVAILABLE) return 0; if (addr <= 0x4000000 && addr + size > 0x4000000) post64 = addr + size - 0x4000000; diff --git a/grub-core/mmap/mips/yeeloong/uppermem.c b/grub-core/mmap/mips/yeeloong/uppermem.c index 3c5f814de..723b6a888 100644 --- a/grub-core/mmap/mips/yeeloong/uppermem.c +++ b/grub-core/mmap/mips/yeeloong/uppermem.c @@ -27,11 +27,12 @@ grub_mmap_get_lower (void) { grub_uint64_t lower = 0; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, - grub_uint32_t type) + grub_memory_type_t type) { - if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + if (type != GRUB_MEMORY_AVAILABLE) return 0; if (addr == 0) lower = size; @@ -49,11 +50,12 @@ grub_mmap_get_upper (void) { grub_uint64_t upper = 0; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, - grub_uint32_t type) + grub_memory_type_t type) { - if (type != GRUB_MACHINE_MEMORY_AVAILABLE) + if (type != GRUB_MEMORY_AVAILABLE) return 0; if (addr <= GRUB_ARCH_HIGHMEMPSTART && addr + size > GRUB_ARCH_HIGHMEMPSTART) diff --git a/grub-core/mmap/mmap.c b/grub-core/mmap/mmap.c index a1afc8b06..7c3430e9f 100644 --- a/grub-core/mmap/mmap.c +++ b/grub-core/mmap/mmap.c @@ -17,8 +17,8 @@ * along with GRUB. If not, see . */ -#include #include +#include #include #include #include @@ -34,8 +34,7 @@ static int curhandle = 1; #endif grub_err_t -grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, - grub_uint64_t, grub_uint32_t)) +grub_mmap_iterate (grub_memory_hook_t hook) { /* This function resolves overlapping regions and sorts the memory map. @@ -48,27 +47,17 @@ grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, 3 - unusable memory 4 - a range deliberately empty */ - int priority[GRUB_MACHINE_MEMORY_MAX_TYPE + 2] = + int priority[] = { -#ifdef GRUB_MACHINE_MEMORY_AVAILABLE - [GRUB_MACHINE_MEMORY_AVAILABLE] = 1, -#endif -#if defined (GRUB_MACHINE_MEMORY_RESERVED) && GRUB_MACHINE_MEMORY_RESERVED != GRUB_MACHINE_MEMORY_HOLE - [GRUB_MACHINE_MEMORY_RESERVED] = 3, -#endif -#ifdef GRUB_MACHINE_MEMORY_ACPI - [GRUB_MACHINE_MEMORY_ACPI] = 2, -#endif -#ifdef GRUB_MACHINE_MEMORY_CODE - [GRUB_MACHINE_MEMORY_CODE] = 3, -#endif -#ifdef GRUB_MACHINE_MEMORY_NVS - [GRUB_MACHINE_MEMORY_NVS] = 3, -#endif - [GRUB_MACHINE_MEMORY_HOLE] = 4, + [GRUB_MEMORY_AVAILABLE] = 1, + [GRUB_MEMORY_RESERVED] = 3, + [GRUB_MEMORY_ACPI] = 2, + [GRUB_MEMORY_CODE] = 3, + [GRUB_MEMORY_NVS] = 3, + [GRUB_MEMORY_HOLE] = 4, }; - int i, k, done; + int i, done; /* Scanline events. */ struct grub_mmap_scan @@ -89,7 +78,7 @@ grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, /* Current scanline event. */ int curtype; /* How many regions of given type overlap at current location? */ - int present[GRUB_MACHINE_MEMORY_MAX_TYPE + 2]; + int present[ARRAY_SIZE (priority)]; /* Number of mmap chunks. */ int mmap_num; @@ -101,7 +90,7 @@ grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint32_t); int NESTED_FUNC_ATTR count_hook (grub_uint64_t addr __attribute__ ((unused)), grub_uint64_t size __attribute__ ((unused)), - grub_uint32_t type __attribute__ ((unused))) + grub_memory_type_t type __attribute__ ((unused))) { mmap_num++; return 0; @@ -111,17 +100,17 @@ grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint32_t); int NESTED_FUNC_ATTR fill_hook (grub_uint64_t addr, grub_uint64_t size, - grub_uint32_t type) + grub_memory_type_t type) { scanline_events[i].pos = addr; scanline_events[i].type = 0; - if (type <= GRUB_MACHINE_MEMORY_MAX_TYPE && priority[type]) + if (type < ARRAY_SIZE (priority) && priority[type]) scanline_events[i].memtype = type; else { grub_dprintf ("mmap", "Unknown memory type %d. Assuming unusable\n", type); - scanline_events[i].memtype = GRUB_MACHINE_MEMORY_RESERVED; + scanline_events[i].memtype = GRUB_MEMORY_RESERVED; } i++; @@ -160,12 +149,10 @@ grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, { scanline_events[i].pos = cur->start; scanline_events[i].type = 0; - if (cur->type == GRUB_MACHINE_MEMORY_HOLE - || (cur->type >= 0 && cur->type <= GRUB_MACHINE_MEMORY_MAX_TYPE - && priority[cur->type])) + if (cur->type < ARRAY_SIZE (priority) && priority[cur->type]) scanline_events[i].memtype = cur->type; else - scanline_events[i].memtype = GRUB_MACHINE_MEMORY_RESERVED; + scanline_events[i].memtype = GRUB_MEMORY_RESERVED; i++; scanline_events[i].pos = cur->end; @@ -201,6 +188,7 @@ grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, lasttype = scanline_events[0].memtype; for (i = 0; i < 2 * mmap_num; i++) { + unsigned k; /* Process event. */ if (scanline_events[i].type) present[scanline_events[i].memtype]--; @@ -209,7 +197,7 @@ grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, /* Determine current region type. */ curtype = -1; - for (k = 0; k <= GRUB_MACHINE_MEMORY_MAX_TYPE + 1; k++) + for (k = 0; k < ARRAY_SIZE (priority); k++) if (present[k] && (curtype == -1 || priority[k] > priority[curtype])) curtype = k; @@ -217,7 +205,7 @@ grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, if ((curtype == -1 || curtype != lasttype) && lastaddr != scanline_events[i].pos && lasttype != -1 - && lasttype != GRUB_MACHINE_MEMORY_HOLE + && lasttype != GRUB_MEMORY_HOLE && hook (lastaddr, scanline_events[i].pos - lastaddr, lasttype)) { grub_free (scanline_events); @@ -324,10 +312,11 @@ grub_cmd_badram (grub_command_t cmd __attribute__ ((unused)), char * str; grub_uint64_t badaddr, badmask; - auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, grub_uint32_t); + auto int NESTED_FUNC_ATTR hook (grub_uint64_t, grub_uint64_t, + grub_memory_type_t); int NESTED_FUNC_ATTR hook (grub_uint64_t addr, grub_uint64_t size, - grub_uint32_t type __attribute__ ((unused))) + grub_memory_type_t type __attribute__ ((unused))) { grub_uint64_t iterator, low, high, cur; int tail, var; @@ -370,7 +359,7 @@ grub_cmd_badram (grub_command_t cmd __attribute__ ((unused)), { grub_dprintf ("badram", "%llx (size %llx) is a badram range\n", (unsigned long long) cur, (1ULL << tail)); - grub_mmap_register (cur, (1ULL << tail), GRUB_MACHINE_MEMORY_HOLE); + grub_mmap_register (cur, (1ULL << tail), GRUB_MEMORY_HOLE); } return 0; } diff --git a/grub-core/term/ns8250.c b/grub-core/term/ns8250.c index f3a804d53..550ee6341 100644 --- a/grub-core/term/ns8250.c +++ b/grub-core/term/ns8250.c @@ -16,7 +16,6 @@ * along with GRUB. If not, see . */ -#include #include #include #include @@ -26,6 +25,7 @@ #include #ifdef GRUB_MACHINE_PCBIOS +#include static const unsigned short *serial_hw_io_addr = (const unsigned short *) GRUB_MEMORY_MACHINE_BIOS_DATA_AREA_ADDR; #define GRUB_SERIAL_PORT_NUM 4 #else diff --git a/include/grub/autoefi.h b/include/grub/autoefi.h index 740be3249..b75591176 100644 --- a/include/grub/autoefi.h +++ b/include/grub/autoefi.h @@ -34,17 +34,6 @@ static inline grub_err_t grub_autoefi_prepare (void) { return GRUB_ERR_NONE; }; -# define GRUB_AUTOEFI_MEMORY_AVAILABLE GRUB_MACHINE_MEMORY_AVAILABLE -# define GRUB_AUTOEFI_MEMORY_RESERVED GRUB_MACHINE_MEMORY_RESERVED -# ifdef GRUB_MACHINE_MEMORY_ACPI -# define GRUB_AUTOEFI_MEMORY_ACPI GRUB_MACHINE_MEMORY_ACPI -# endif -# ifdef GRUB_MACHINE_MEMORY_NVS -# define GRUB_AUTOEFI_MEMORY_NVS GRUB_MACHINE_MEMORY_NVS -# endif -# ifdef GRUB_MACHINE_MEMORY_CODE -# define GRUB_AUTOEFI_MEMORY_CODE GRUB_MACHINE_MEMORY_CODE -# endif # define SYSTEM_TABLE_SIZEOF(x) (sizeof(grub_efi_system_table->x)) # define SYSTEM_TABLE_VAR(x) ((void *)&(grub_efi_system_table->x)) # define SYSTEM_TABLE_PTR(x) ((void *)(grub_efi_system_table->x)) @@ -61,11 +50,6 @@ static inline grub_err_t grub_autoefi_prepare (void) # define grub_autoefi_mmap_iterate grub_efiemu_mmap_iterate # define grub_autoefi_prepare grub_efiemu_prepare # define grub_autoefi_set_virtual_address_map grub_efiemu_set_virtual_address_map -# define GRUB_AUTOEFI_MEMORY_AVAILABLE GRUB_EFIEMU_MEMORY_AVAILABLE -# define GRUB_AUTOEFI_MEMORY_RESERVED GRUB_EFIEMU_MEMORY_RESERVED -# define GRUB_AUTOEFI_MEMORY_ACPI GRUB_EFIEMU_MEMORY_ACPI -# define GRUB_AUTOEFI_MEMORY_NVS GRUB_EFIEMU_MEMORY_NVS -# define GRUB_AUTOEFI_MEMORY_CODE GRUB_EFIEMU_MEMORY_CODE # define SYSTEM_TABLE_SIZEOF GRUB_EFIEMU_SYSTEM_TABLE_SIZEOF # define SYSTEM_TABLE_VAR GRUB_EFIEMU_SYSTEM_TABLE_VAR # define SYSTEM_TABLE_PTR GRUB_EFIEMU_SYSTEM_TABLE_PTR diff --git a/include/grub/efi/memory.h b/include/grub/efi/memory.h index 285be8359..133f9504c 100644 --- a/include/grub/efi/memory.h +++ b/include/grub/efi/memory.h @@ -24,16 +24,6 @@ #define GRUB_MMAP_REGISTER_BY_FIRMWARE 1 -#define GRUB_MACHINE_MEMORY_AVAILABLE 1 -#define GRUB_MACHINE_MEMORY_RESERVED 2 -#define GRUB_MACHINE_MEMORY_ACPI 3 -#define GRUB_MACHINE_MEMORY_NVS 4 -#define GRUB_MACHINE_MEMORY_CODE 5 -#define GRUB_MACHINE_MEMORY_MAX_TYPE 5 - /* This one is special: it's used internally but is never reported - by firmware. */ -#define GRUB_MACHINE_MEMORY_HOLE 6 - grub_err_t grub_machine_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); diff --git a/include/grub/efiemu/efiemu.h b/include/grub/efiemu/efiemu.h index 56d4ea8ee..8eee98b61 100644 --- a/include/grub/efiemu/efiemu.h +++ b/include/grub/efiemu/efiemu.h @@ -233,11 +233,6 @@ grub_efiemu_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, int grub_efiemu_sizeof_uintn_t (void); grub_err_t grub_efiemu_get_lower_upper_memory (grub_uint64_t *lower, grub_uint64_t *upper); -#define GRUB_EFIEMU_MEMORY_AVAILABLE 1 -#define GRUB_EFIEMU_MEMORY_RESERVED 2 -#define GRUB_EFIEMU_MEMORY_ACPI 3 -#define GRUB_EFIEMU_MEMORY_NVS 4 -#define GRUB_EFIEMU_MEMORY_CODE 5 /* efiemu main control definitions and functions*/ typedef enum {GRUB_EFIEMU_NOTLOADED, diff --git a/include/grub/i386/coreboot/memory.h b/include/grub/i386/coreboot/memory.h index 664086a81..0642280b9 100644 --- a/include/grub/i386/coreboot/memory.h +++ b/include/grub/i386/coreboot/memory.h @@ -21,11 +21,11 @@ #define _GRUB_MEMORY_MACHINE_LB_HEADER 1 #include -#include #ifndef ASM_FILE #include #include +#include #endif #define GRUB_MEMORY_MACHINE_LOWER_USABLE 0x9fc00 /* 640 kiB - 1 kiB */ @@ -35,36 +35,21 @@ #ifndef ASM_FILE -struct grub_linuxbios_table_header -{ - char signature[4]; - grub_uint32_t size; -}; -typedef struct grub_linuxbios_table_header *grub_linuxbios_table_header_t; - -struct grub_linuxbios_table_item -{ -#define GRUB_LINUXBIOS_MEMBER_UNUSED 0x00 -#define GRUB_LINUXBIOS_MEMBER_MEMORY 0x01 -#define GRUB_LINUXBIOS_MEMBER_LINK 0x11 - grub_uint32_t tag; - grub_uint32_t size; -}; -typedef struct grub_linuxbios_table_item *grub_linuxbios_table_item_t; - -struct grub_linuxbios_mem_region -{ - grub_uint64_t addr; - grub_uint64_t size; -#define GRUB_MACHINE_MEMORY_AVAILABLE 1 - grub_uint32_t type; -}; -typedef struct grub_linuxbios_mem_region *mem_region_t; - void grub_machine_mmap_init (void); -grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate) - (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); +static inline grub_err_t +grub_machine_mmap_register (grub_uint64_t start __attribute__ ((unused)), + grub_uint64_t size __attribute__ ((unused)), + int type __attribute__ ((unused)), + int handle __attribute__ ((unused))) +{ + return GRUB_ERR_NONE; +} +static inline grub_err_t +grub_machine_mmap_unregister (int handle __attribute__ ((unused))) +{ + return GRUB_ERR_NONE; +} #endif diff --git a/include/grub/i386/ieee1275/memory.h b/include/grub/i386/ieee1275/memory.h index 386ee4a05..8dd6f7c8c 100644 --- a/include/grub/i386/ieee1275/memory.h +++ b/include/grub/i386/ieee1275/memory.h @@ -1 +1 @@ -#include +#include diff --git a/include/grub/i386/memory.h b/include/grub/i386/memory.h index 4f9a3c916..582226eed 100644 --- a/include/grub/i386/memory.h +++ b/include/grub/i386/memory.h @@ -30,6 +30,14 @@ #ifndef ASM_FILE +#define GRUB_MMAP_MALLOC_LOW 1 + +#include + +grub_uint64_t grub_mmap_get_upper (void); +grub_uint64_t grub_mmap_get_lower (void); +grub_uint64_t grub_mmap_get_post64 (void); + typedef grub_addr_t grub_phys_addr_t; static inline grub_phys_addr_t diff --git a/include/grub/i386/pc/memory.h b/include/grub/i386/pc/memory.h index 68f5e8bc9..401c837fa 100644 --- a/include/grub/i386/pc/memory.h +++ b/include/grub/i386/pc/memory.h @@ -88,51 +88,9 @@ struct grub_machine_bios_data_area grub_uint8_t unused2[0xf0 - 0x18]; }; -struct grub_machine_mmap_entry -{ - grub_uint32_t size; - grub_uint64_t addr; - grub_uint64_t len; -#define GRUB_MACHINE_MEMORY_AVAILABLE 1 -#define GRUB_MACHINE_MEMORY_RESERVED 2 -#define GRUB_MACHINE_MEMORY_ACPI 3 -#define GRUB_MACHINE_MEMORY_NVS 4 -#define GRUB_MACHINE_MEMORY_MAX_TYPE 4 - /* This one is special: it's used internally but is never reported - by firmware. */ -#define GRUB_MACHINE_MEMORY_HOLE 5 - - grub_uint32_t type; -} __attribute__((packed)); - -grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate) - (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); - -grub_uint64_t grub_mmap_get_post64 (void); -grub_uint64_t grub_mmap_get_upper (void); -grub_uint64_t grub_mmap_get_lower (void); - -#define GRUB_MMAP_MALLOC_LOW 1 - -#ifdef GRUB_MACHINE_PCBIOS grub_err_t grub_machine_mmap_register (grub_uint64_t start, grub_uint64_t size, int type, int handle); grub_err_t grub_machine_mmap_unregister (int handle); -#else -static inline grub_err_t -grub_machine_mmap_register (grub_uint64_t start __attribute__ ((unused)), - grub_uint64_t size __attribute__ ((unused)), - int type __attribute__ ((unused)), - int handle __attribute__ ((unused))) -{ - return GRUB_ERR_NONE; -} -static inline grub_err_t -grub_machine_mmap_unregister (int handle __attribute__ ((unused))) -{ - return GRUB_ERR_NONE; -} -#endif #endif diff --git a/include/grub/i386/qemu/memory.h b/include/grub/i386/qemu/memory.h index de559443d..2003e4934 100644 --- a/include/grub/i386/qemu/memory.h +++ b/include/grub/i386/qemu/memory.h @@ -21,7 +21,7 @@ #define _GRUB_MEMORY_MACHINE_HEADER 1 #include -#include +#include #ifndef ASM_FILE #include @@ -37,9 +37,6 @@ void grub_machine_mmap_init (void); -grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate) - (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); - #endif #endif /* ! _GRUB_MEMORY_MACHINE_HEADER */ diff --git a/include/grub/memory.h b/include/grub/memory.h index 43f90e1dd..d98386565 100644 --- a/include/grub/memory.h +++ b/include/grub/memory.h @@ -22,11 +22,32 @@ #include #include -#include -grub_err_t grub_mmap_iterate (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, - grub_uint64_t, - grub_uint32_t)); +typedef enum grub_memory_type + { + GRUB_MEMORY_AVAILABLE = 1, + GRUB_MEMORY_RESERVED = 2, + GRUB_MEMORY_ACPI = 3, + GRUB_MEMORY_NVS = 4, + GRUB_MEMORY_BADRAM = 5, + GRUB_MEMORY_CODE = 20, + /* This one is special: it's used internally but is never reported + by firmware. */ + GRUB_MEMORY_HOLE = 21 + } grub_memory_type_t; + +typedef int NESTED_FUNC_ATTR (*grub_memory_hook_t) (grub_uint64_t, + grub_uint64_t, + grub_memory_type_t); + +grub_err_t grub_mmap_iterate (grub_memory_hook_t hook); + +#if !defined (GRUB_MACHINE_EMU) && !defined (GRUB_MACHINE_EFI) +grub_err_t EXPORT_FUNC(grub_machine_mmap_iterate) (grub_memory_hook_t hook); +#else +grub_err_t grub_machine_mmap_iterate (grub_memory_hook_t hook); +#endif + int grub_mmap_register (grub_uint64_t start, grub_uint64_t size, int type); grub_err_t grub_mmap_unregister (int handle); @@ -42,7 +63,7 @@ struct grub_mmap_region struct grub_mmap_region *next; grub_uint64_t start; grub_uint64_t end; - int type; + grub_memory_type_t type; int handle; }; diff --git a/include/grub/mips/qemu-mips/memory.h b/include/grub/mips/qemu-mips/memory.h index 87e68674e..99d9ef2be 100644 --- a/include/grub/mips/qemu-mips/memory.h +++ b/include/grub/mips/qemu-mips/memory.h @@ -28,8 +28,6 @@ #define GRUB_MACHINE_MEMORY_STACK_HIGH 0x80f00000 #define GRUB_MACHINE_MEMORY_USABLE 0x81000000 -#define GRUB_MACHINE_MEMORY_AVAILABLE 1 - #ifndef ASM_FILE grub_err_t EXPORT_FUNC (grub_machine_mmap_iterate) (int NESTED_FUNC_ATTR (*hook) (grub_uint64_t, grub_uint64_t, grub_uint32_t)); diff --git a/include/grub/mips/yeeloong/memory.h b/include/grub/mips/yeeloong/memory.h index e7e995283..9d53b5e0e 100644 --- a/include/grub/mips/yeeloong/memory.h +++ b/include/grub/mips/yeeloong/memory.h @@ -31,13 +31,6 @@ #define GRUB_ARCH_LOWMEMMAXSIZE 0x10000000 #define GRUB_ARCH_HIGHMEMPSTART 0x10000000 -#define GRUB_MACHINE_MEMORY_AVAILABLE 1 -#define GRUB_MACHINE_MEMORY_MAX_TYPE 1 - /* This one is special: it's used internally but is never reported - by firmware. */ -#define GRUB_MACHINE_MEMORY_HOLE 2 -#define GRUB_MACHINE_MEMORY_RESERVED GRUB_MACHINE_MEMORY_HOLE - #ifndef ASM_FILE typedef grub_addr_t grub_phys_addr_t; diff --git a/include/grub/powerpc/ieee1275/memory.h b/include/grub/powerpc/ieee1275/memory.h deleted file mode 100644 index f8f2ff08d..000000000 --- a/include/grub/powerpc/ieee1275/memory.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2008 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GRUB. If not, see . - */ - -#ifndef GRUB_MEMORY_MACHINE_HEADER -#define GRUB_MEMORY_MACHINE_HEADER 1 - -#include - -#define GRUB_MACHINE_MEMORY_AVAILABLE 1 - -#endif diff --git a/include/grub/sparc64/ieee1275/memory.h b/include/grub/sparc64/ieee1275/memory.h deleted file mode 100644 index 25e31002e..000000000 --- a/include/grub/sparc64/ieee1275/memory.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2009 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GRUB. If not, see . - */ - -#ifndef GRUB_MEMORY_MACHINE_HEADER -#define GRUB_MEMORY_MACHINE_HEADER 1 - -#include - -#define GRUB_MACHINE_MEMORY_AVAILABLE 1 - -#endif From 1bce65c7b14696a43ad795eb6b71c67f3d3fb9c8 Mon Sep 17 00:00:00 2001 From: BVK Chaitanya Date: Sun, 5 Sep 2010 14:57:28 +0530 Subject: [PATCH 091/214] not command (!) support --- Makefile.util.def | 6 ++++ grub-core/script/execute.c | 29 +++++++++++++++--- grub-core/script/yylex.l | 1 - tests/grub_script_not.in | 62 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+), 5 deletions(-) create mode 100644 tests/grub_script_not.in diff --git a/Makefile.util.def b/Makefile.util.def index dd38774fd..e0900c73f 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -531,6 +531,12 @@ script = { common = tests/grub_script_expansion.in; }; +script = { + testcase; + name = grub_script_not; + common = tests/grub_script_not.in; +}; + program = { testcase; name = example_unit_test; diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c index a7baee96c..b43ec85e1 100644 --- a/grub-core/script/execute.c +++ b/grub-core/script/execute.c @@ -547,13 +547,32 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd) grub_script_function_t func = 0; char errnobuf[18]; char *cmdname; + int argc; + char **args; + int invert; struct grub_script_argv argv = { 0, 0, 0 }; /* Lookup the command. */ if (grub_script_arglist_to_argv (cmdline->arglist, &argv) || ! argv.args[0]) return grub_errno; + invert = 0; + argc = argv.argc - 1; + args = argv.args + 1; cmdname = argv.args[0]; + if (grub_strcmp (cmdname, "!") == 0) + { + if (argv.argc < 2 || ! argv.args[1]) + { + grub_script_argv_free (&argv); + return grub_error (GRUB_ERR_BAD_ARGUMENT, "missing arguments"); + } + + invert = 1; + argc = argv.argc - 2; + args = argv.args + 2; + cmdname = argv.args[1]; + } grubcmd = grub_command_find (cmdname); if (! grubcmd) { @@ -594,13 +613,15 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd) { if ((grubcmd->flags & GRUB_COMMAND_FLAG_BLOCKS) && (grubcmd->flags & GRUB_COMMAND_FLAG_EXTCMD)) - ret = grub_extcmd_dispatcher (grubcmd, argv.argc - 1, argv.args + 1, - argv.script); + ret = grub_extcmd_dispatcher (grubcmd, argc, args, argv.script); else - ret = (grubcmd->func) (grubcmd, argv.argc - 1, argv.args + 1); + ret = (grubcmd->func) (grubcmd, argc, args); } else - ret = grub_script_function_call (func, argv.argc - 1, argv.args + 1); + ret = grub_script_function_call (func, argc, args); + + if (invert) + ret = ! ret; /* Free arguments. */ grub_script_argv_free (&argv); diff --git a/grub-core/script/yylex.l b/grub-core/script/yylex.l index d4cad8097..55620b6bd 100644 --- a/grub-core/script/yylex.l +++ b/grub-core/script/yylex.l @@ -155,7 +155,6 @@ MULTILINE {WORD}?((\"{DQCHR}*)|(\'{SQCHR}*)|(\\\n)) ">" { RECORD; return GRUB_PARSER_TOKEN_GT; } /* Reserved words */ -"!" { RECORD; return GRUB_PARSER_TOKEN_NOT; } "{" { RECORD; return GRUB_PARSER_TOKEN_LBR; } "}" { RECORD; return GRUB_PARSER_TOKEN_RBR; } "[[" { RECORD; return GRUB_PARSER_TOKEN_RSQBR2; } diff --git a/tests/grub_script_not.in b/tests/grub_script_not.in new file mode 100644 index 000000000..ff71039a6 --- /dev/null +++ b/tests/grub_script_not.in @@ -0,0 +1,62 @@ +#! @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 . + +true +echo $? + +! true +echo $? + +false +echo $? + +! false +echo $? + +# +# Negated forms (copied from grub_script_if.in) +# + +#basic if, execute +if ! true; then echo yes; fi + +#basic if, no execution +if ! false; then echo no; fi + +#if else, execute if path +if ! true; then echo yes; else echo no; fi + +#if else, execute else path +if ! false; then echo no; else echo yes; fi + +#if elif, execute elif +if ! false; then echo no; elif ! true; then echo yes; fi + +#if elif else, execute else +if ! false; then echo no; elif ! false; then echo no; else echo yes; fi + +#if elif(1) elif(2), execute elif(2) +if false; then echo no; elif ! false; then echo no; elif ! true; then echo yes; fi + +#if elif(1) elif(2) else, execute else +if false; then echo no; elif false; then echo no; elif ! false; then echo no; else echo yes; fi + +#if {if elif else}, execute elif +if true; then if false; then echo no; elif ! true; then echo yes; else echo no; fi; fi + +#if {if elif} else, execute elif. ofcourse no dangling-else problem due to "fi" +if true; then if ! false; then echo no; elif true; then echo yes; fi; else echo no; fi From 5cd837bd47208c9e51b214109d7a57758e045e76 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 5 Sep 2010 20:43:43 +0200 Subject: [PATCH 092/214] Add testload --- grub-core/lib/legacy_parse.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index f2d3dec0a..f350aaf09 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -205,7 +205,12 @@ struct legacy_command legacy_commands[] = /* setup unsupported. */ /* terminal unsupported. */ /* NUL_TERMINATE */ /* terminfo unsupported. */ /* NUL_TERMINATE */ - /* testload unsupported. */ + {"testload", "cat '%s'\n", 1, {TYPE_FILE}, 0, "FILE", + "Read the entire contents of FILE in several different ways and" + " compares them, to test the filesystem code. " + " If this test succeeds, then a good next" + " step is to try loading a kernel."}, + "Print the contents of the file FILE."}, /* testvbe unsupported. */ /* tftpserver unsupported. */ {"timeout", "set timeout=%s\n", 1, {TYPE_INT}, 0, "SEC", From 88ae2ce1604483663971083a0980b06d53afef84 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 6 Sep 2010 23:03:25 +0200 Subject: [PATCH 093/214] Fix several powerpc-ieee1275 issues and one EFI one while on it --- util/grub-install.in | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/util/grub-install.in b/util/grub-install.in index 4ce451d11..a47258a96 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -63,7 +63,7 @@ efi_quiet= if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then disk_module=biosdisk -elif [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then +elif [ "${platform}" = "ieee1275" ] || [ "${platform}" = "efi" ] ; then disk_module= else disk_module=ata @@ -445,7 +445,7 @@ esac case "${target_cpu}-${platform}" in i386-efi | x86_64-efi) imgext=efi ;; mips-yeeloong | i386-coreboot | i386-multiboot | i386-ieee1275 \ - | powerpc-ieeee1275) imgext=elf ;; + | powerpc-ieee1275) imgext=elf ;; *) imgext=img ;; esac @@ -456,7 +456,7 @@ $grub_mkimage ${config_opt} -O ${mkimage_target} --output=${grubdir}/core.${imge if [ "${target_cpu}-${platform}" = "mips-yeeloong" ]; then cp ${grubdir}/core.${imgext} /boot/grub.elf elif [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${platform}" = "powerpc-ieee1275" ]; then - cp ${grubdir}/core.${imgext} /boot/grub + cp ${grubdir}/core.${imgext} /boot/grub/grub elif [ "${target_cpu}-${platform}" = "i386-efi" ] || [ "${target_cpu}-${platform}" = "x86_64-efi" ]; then $grub_mkimage ${config_opt} -O ${mkimage_target} --output=${grubdir}/grub.efi --prefix="" $modules || exit 1 fi @@ -492,7 +492,7 @@ elif [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${pla } # Point boot-device at the new grub install - boot_device="$ofpath:$partno,"`grub-mkrelpath ${grubdir}/core.${imgext} | sed 's,/,\\,g'` + boot_device="$ofpath:$partno,"`grub-mkrelpath ${grubdir}/core.${imgext} | sed 's,/,\\\\,g'` "$nvsetenv" boot-device "$boot_device" || { echo "$nvsetenv failed." echo "You will have to set boot-device manually. At the Open Firmware prompt, type:" From b61d05ed19c4877bff2faf3103b72c5e034a379a Mon Sep 17 00:00:00 2001 From: "bvk.groups@gmail.com" <> Date: Tue, 7 Sep 2010 17:16:03 +0530 Subject: [PATCH 094/214] * grub-core/commands/wildcard.c (wildcard_expand): Fix wrong grub_free. --- ChangeLog | 4 ++++ grub-core/commands/wildcard.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 0f79aaa87..279668975 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2010-09-07 BVK Chaitanya + + * grub-core/commands/wildcard.c (wildcard_expand): Fix wrong grub_free. + 2010-09-07 BVK Chaitanya * docs/grub.texi (Shell-like scripting): Fix @dots to @dots{}. diff --git a/grub-core/commands/wildcard.c b/grub-core/commands/wildcard.c index cbe32e0ff..64e2e3a54 100644 --- a/grub-core/commands/wildcard.c +++ b/grub-core/commands/wildcard.c @@ -488,7 +488,7 @@ wildcard_expand (const char *s, char ***strs) for (i = 0; paths && paths[i]; i++) grub_free (paths[i]); - grub_free (paths[i]); + grub_free (paths); regfree (®exp); return grub_errno; } From a0b5f6bcb11da5d6383564c1e8fc78201be6f728 Mon Sep 17 00:00:00 2001 From: "bvk.groups@gmail.com" <> Date: Tue, 7 Sep 2010 21:46:04 +0530 Subject: [PATCH 095/214] update grub_errno as per the return value --- grub-core/script/execute.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c index b43ec85e1..87dd6581c 100644 --- a/grub-core/script/execute.c +++ b/grub-core/script/execute.c @@ -621,7 +621,17 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd) ret = grub_script_function_call (func, argc, args); if (invert) - ret = ! ret; + { + if (ret == GRUB_ERR_TEST_FAILURE) + grub_errno = ret = GRUB_ERR_NONE; + else if (ret == GRUB_ERR_NONE) + ret = grub_error (GRUB_ERR_TEST_FAILURE, "false"); + else + { + grub_print_error (); + grub_errno = ret = GRUB_ERR_NONE; + } + } /* Free arguments. */ grub_script_argv_free (&argv); From 420eae7e6cb7499ed41a3187d6de95854cef6719 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Wed, 8 Sep 2010 13:13:15 +0200 Subject: [PATCH 096/214] Remove conf/*.mk --- .bzrignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.bzrignore b/.bzrignore index cfdd069fd..411daae47 100644 --- a/.bzrignore +++ b/.bzrignore @@ -18,7 +18,6 @@ config.log config.status config.sub configure -conf/*.mk *.d DISTLIST docs/*.info From f438a5be5849137073732cca2ba2ebb113c342f0 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Wed, 8 Sep 2010 12:54:38 +0100 Subject: [PATCH 097/214] Set install_device for EFI before it's needed. --- util/grub-install.in | 177 ++++++++++++++++++++++--------------------- 1 file changed, 90 insertions(+), 87 deletions(-) diff --git a/util/grub-install.in b/util/grub-install.in index a47258a96..cf2a752ab 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -301,6 +301,95 @@ else exit 1 fi +if [ x"$platform" = xefi ]; then + # Get GRUB_DISTRIBUTOR. + if test -f ${sysconfdir}/default/grub ; then + . ${sysconfdir}/default/grub + fi + + # Find the EFI System Partition. + efidir= + if test -d ${bootdir}/efi; then + install_device=`$grub_mkdevicemap --device-map=/dev/stdout | $grub_probe --target=device --device-map=/dev/stdin ${bootdir}/efi` + # Is it a mount point? + if test "x$install_device" != "x`$grub_mkdevicemap --device-map=/dev/stdout | $grub_probe --target=device --device-map=/dev/stdin ${bootdir}`"; then + efidir=${bootdir}/efi + fi + elif test -n "$rootdir" && test "x$rootdir" != "x/"; then + # The EFI System Partition may have been given directly using + # --root-directory. + install_device=`$grub_mkdevicemap --device-map=/dev/stdout | $grub_probe --target=device --device-map=/dev/stdin ${rootdir}` + # Is it a mount point? + if test "x$install_device" != "x`$grub_mkdevicemap --device-map=/dev/stdout | $grub_probe --target=device --device-map=/dev/stdin ${rootdir}/..`"; then + efidir=${rootdir} + fi + fi + + if test -n "$efidir"; then + efi_fs=`$grub_probe --target=fs --device-map=${device_map} ${efidir}` + if test "x$efi_fs" = xfat; then :; else + echo "${efidir} doesn't look like an EFI partition." 1>&2 + efidir= + fi + fi + + if test -n "$efidir"; then + # The EFI specification requires that an EFI System Partition must + # contain an "EFI" subdirectory, and that OS loaders are stored in + # subdirectories below EFI. Vendors are expected to pick names that do + # not collide with other vendors. To minimise collisions, we use the + # name of our distributor if possible. + if test $removable = yes; then + # The specification makes stricter requirements of removable + # devices, in order that only one image can be automatically loaded + # from them. The image must always reside under /EFI/BOOT, and it + # must have a specific file name depending on the architecture. + efi_distributor=BOOT + case "$target_cpu" in + i386) + efi_file=BOOTIA32.EFI ;; + x86-64) + efi_file=BOOTX64.EFI ;; + # GRUB does not yet support these architectures, but they're defined + # by the specification so we include them here to ease future + # expansion. + ia64) + efi_file=BOOTIA64.EFI ;; + esac + else + efi_distributor="$(echo "$GRUB_DISTRIBUTOR" | tr '[A-Z]' '[a-z]' | cut -d' ' -f1)" + if test -z "$efi_distributor"; then + efi_distributor=grub + fi + # It is convenient for each architecture to have a different + # efi_file, so that different versions can be installed in parallel. + case "$target_cpu" in + i386) + efi_file=grubia32.efi ;; + x86-64) + efi_file=grubx64.efi ;; + # GRUB does not yet support these architectures, but they're defined + # by the specification so we include them here to ease future + # expansion. + ia64) + efi_file=grubia64.efi ;; + *) + efi_file=grub.efi ;; + esac + # TODO: We should also use efibootmgr, if available, to add a Boot + # entry for ourselves. + fi + efidir="$efidir/EFI/$efi_distributor" + mkdir -p "$efidir" || exit 1 + else + # We don't know what's going on. Fall back to traditional + # (non-specification-compliant) behaviour. + efidir="$grubdir" + efi_distributor= + efi_file=grub.efi + fi +fi + # Create the GRUB directory if it is not present. mkdir -p "$grubdir" || exit 1 @@ -501,93 +590,8 @@ elif [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${pla } fi elif [ x"$platform" = xefi ]; then - # Get GRUB_DISTRIBUTOR. - if test -f ${sysconfdir}/default/grub ; then - . ${sysconfdir}/default/grub - fi - - # Find the EFI System Partition. - efidir= - if test -d ${bootdir}/efi; then - install_device=`$grub_mkdevicemap --device-map=/dev/stdout | $grub_probe --target=device --device-map=/dev/stdin ${bootdir}/efi` - # Is it a mount point? - if test "x$install_device" != "x`$grub_mkdevicemap --device-map=/dev/stdout | $grub_probe --target=device --device-map=/dev/stdin ${bootdir}`"; then - efidir=${bootdir}/efi - fi - elif test -n "$rootdir" && test "x$rootdir" != "x/"; then - # The EFI System Partition may have been given directly using - # --root-directory. - install_device=`$grub_mkdevicemap --device-map=/dev/stdout | $grub_probe --target=device --device-map=/dev/stdin ${rootdir}` - # Is it a mount point? - if test "x$install_device" != "x`$grub_mkdevicemap --device-map=/dev/stdout | $grub_probe --target=device --device-map=/dev/stdin ${rootdir}/..`"; then - efidir=${rootdir} - fi - fi - - if test -n "$efidir"; then - efi_fs=`$grub_probe --target=fs --device-map=${device_map} ${efidir}` - if test "x$efi_fs" = xfat; then :; else - echo "${efidir} doesn't look like an EFI partition." 1>&2 - efidir= - fi - fi - - if test -n "$efidir"; then - # The EFI specification requires that an EFI System Partition must - # contain an "EFI" subdirectory, and that OS loaders are stored in - # subdirectories below EFI. Vendors are expected to pick names that do - # not collide with other vendors. To minimise collisions, we use the - # name of our distributor if possible. - if test $removable = yes; then - # The specification makes stricter requirements of removable - # devices, in order that only one image can be automatically loaded - # from them. The image must always reside under /EFI/BOOT, and it - # must have a specific file name depending on the architecture. - efi_distributor=BOOT - case "$target_cpu" in - i386) - efi_file=BOOTIA32.EFI ;; - x86-64) - efi_file=BOOTX64.EFI ;; - # GRUB does not yet support these architectures, but they're defined - # by the specification so we include them here to ease future - # expansion. - ia64) - efi_file=BOOTIA64.EFI ;; - esac - else - efi_distributor="$(echo "$GRUB_DISTRIBUTOR" | tr '[A-Z]' '[a-z]' | cut -d' ' -f1)" - if test -z "$efi_distributor"; then - efi_distributor=grub - fi - # It is convenient for each architecture to have a different - # efi_file, so that different versions can be installed in parallel. - case "$target_cpu" in - i386) - efi_file=grubia32.efi ;; - x86-64) - efi_file=grubx64.efi ;; - # GRUB does not yet support these architectures, but they're defined - # by the specification so we include them here to ease future - # expansion. - ia64) - efi_file=grubia64.efi ;; - *) - efi_file=grub.efi ;; - esac - # TODO: We should also use efibootmgr, if available, to add a Boot - # entry for ourselves. - fi - efidir="$efidir/EFI/$efi_distributor" - mkdir -p "$efidir" || exit 1 - else - # We don't know what's going on. Fall back to traditional - # (non-specification-compliant) behaviour. - efidir="$grubdir" - efi_distributor= - efi_file=grub.efi - fi cp ${grubdir}/core.${imgext} ${efidir}/${efi_file} + # Try to make this image bootable using the EFI Boot Manager, if available. if test "$removable" = no && test -n "$efi_distributor" && \ test -n "$efibootmgr"; then @@ -619,7 +623,6 @@ elif [ x"$platform" = xefi ]; then -L "$GRUB_DISTRIBUTOR" -l "\\EFI\\$efi_distributor\\$efi_file" fi fi - fi echo "Installation finished. No error reported." From dc3d901cde7e014fa1241a795cd946d07f961852 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Wed, 8 Sep 2010 13:07:21 +0100 Subject: [PATCH 098/214] Check for the EFI distributor case-insensitively, since efi_distributor is always forced to lower-case. Reported by: Mario Limonciello. --- util/grub-install.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/grub-install.in b/util/grub-install.in index cf2a752ab..b0823642a 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -603,7 +603,7 @@ elif [ x"$platform" = xefi ]; then # Delete old entries from the same distributor. for bootnum in `efibootmgr | grep '^Boot[0-9]' | \ - fgrep " $efi_distributor" | cut -b5-8`; do + fgrep -i " $efi_distributor" | cut -b5-8`; do efibootmgr $efi_quiet -b "$bootnum" -B done From 99fd620d5af6c9d3235adfb4210c881d82364400 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Wed, 8 Sep 2010 14:29:32 +0200 Subject: [PATCH 099/214] 2010-09-08 Robert Millan * util/grub-mkconfig.in: Pass `--device ${GRUB_DEVICE}' when initializing `GRUB_FS'. --- ChangeLog | 5 +++++ util/grub-mkconfig.in | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 73db891d4..0e1285c6f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2010-09-08 Robert Millan + + * util/grub-mkconfig.in: Pass `--device ${GRUB_DEVICE}' when + initializing `GRUB_FS'. + 2010-09-08 BVK Chaitanya Not command (!) support to GRUB script. diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in index 828b54bce..6f1d375a7 100644 --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in @@ -158,7 +158,7 @@ GRUB_DEVICE_BOOT_UUID="`${grub_probe} --device ${GRUB_DEVICE_BOOT} --target=fs_u # Filesystem for the device containing our userland. Used for stuff like # choosing Hurd filesystem module. -GRUB_FS="`${grub_probe} --target=fs / 2> /dev/null || echo unknown`" +GRUB_FS="`${grub_probe} --device ${GRUB_DEVICE} --target=fs 2> /dev/null || echo unknown`" if test -f ${sysconfdir}/default/grub ; then . ${sysconfdir}/default/grub From 92f2aef0458cebd1f095ca05fb8f0a70f45417fd Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Wed, 8 Sep 2010 14:37:19 +0200 Subject: [PATCH 100/214] 2010-09-08 Robert Millan * configure.ac: Remove `--enable-grub-fstest' option. * Makefile.util.def (grub-fstest): Remove COND_GRUB_FSTEST condition. * util/grub-mkconfig_lib.in (is_path_readable_by_grub): Use `grub-fstest' instead of `grub-probe' for readability verification. * util/grub-probe.c (probe): Remove readability verification kludge. --- ChangeLog | 9 +++++++++ Makefile.util.def | 1 - configure.ac | 19 ------------------- util/grub-mkconfig_lib.in | 10 ++++++++-- util/grub-probe.c | 36 +----------------------------------- 5 files changed, 18 insertions(+), 57 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0e1285c6f..7e2420c64 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2010-09-08 Robert Millan + + * configure.ac: Remove `--enable-grub-fstest' option. + * Makefile.util.def (grub-fstest): Remove COND_GRUB_FSTEST condition. + + * util/grub-mkconfig_lib.in (is_path_readable_by_grub): Use + `grub-fstest' instead of `grub-probe' for readability verification. + * util/grub-probe.c (probe): Remove readability verification kludge. + 2010-09-08 Robert Millan * util/grub-mkconfig.in: Pass `--device ${GRUB_DEVICE}' when diff --git a/Makefile.util.def b/Makefile.util.def index e0900c73f..c4872c7c3 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -183,7 +183,6 @@ program = { ldadd = libgrub.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER)'; - condition = COND_GRUB_FSTEST; }; program = { diff --git a/configure.ac b/configure.ac index d362f68a5..3a1a6da63 100644 --- a/configure.ac +++ b/configure.ac @@ -762,19 +762,6 @@ AC_SUBST([enable_grub_emu_usb]) AC_SUBST([enable_grub_emu_pci]) fi -AC_ARG_ENABLE([grub-fstest], - [AS_HELP_STRING([--enable-grub-fstest], - [build and install the `grub-fstest' debugging utility (default=guessed)])]) -if test x"$enable_grub_fstest" = xno ; then - grub_fstest_excuse="explicitly disabled" -fi -if test x"$grub_fstest_excuse" = x ; then -enable_grub_fstest=yes -else -enable_grub_fstest=no -fi -AC_SUBST([enable_grub_fstest]) - AC_ARG_ENABLE([grub-mkfont], [AS_HELP_STRING([--enable-grub-mkfont], [build and install the `grub-mkfont' utility (default=guessed)])]) @@ -905,7 +892,6 @@ AM_CONDITIONAL([COND_GRUB_EMU_SDL], [test x$enable_grub_emu_sdl = xyes]) AM_CONDITIONAL([COND_GRUB_EMU_PCI], [test x$enable_grub_emu_pci = xyes]) AM_CONDITIONAL([COND_GRUB_MKFONT], [test x$enable_grub_mkfont = xyes]) AM_CONDITIONAL([COND_HAVE_FONT_SOURCE], [test x$FONT_SOURCE != x]) -AM_CONDITIONAL([COND_GRUB_FSTEST], [test x$enable_grub_fstest = xyes]) AM_CONDITIONAL([COND_GRUB_PE2ELF], [test x$TARGET_OBJ2ELF != x]) AM_CONDITIONAL([COND_APPLE_CC], [test x$TARGET_APPLE_CC = x1]) AM_CONDITIONAL([COND_ENABLE_EFIEMU], [test x$enable_efiemu = xyes]) @@ -970,11 +956,6 @@ echo efiemu runtime: Yes else echo efiemu runtime: No "($efiemu_excuse)" fi -if [ x"$grub_fstest_excuse" = x ]; then -echo grub-fstest: Yes -else -echo grub-fstest: No "($grub_fstest_excuse)" -fi if [ x"$grub_mkfont_excuse" = x ]; then echo grub-mkfont: Yes else diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in index 9a77d1bdf..c6f79fb49 100644 --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in @@ -30,6 +30,9 @@ fi if test "x$grub_mkrelpath" = x; then grub_mkrelpath=${bindir}/`echo grub-mkrelpath | sed ${transform}` fi +if test "x$grub_fstest" = x; then + grub_fstest=${bindir}/`echo grub-fstest | sed ${transform}` +fi if $(which gettext >/dev/null 2>/dev/null) ; then gettext="gettext" @@ -56,8 +59,11 @@ is_path_readable_by_grub () return 1 fi - # abort if file is in a filesystem we can't read - if ${grub_probe} -t fs $path > /dev/null 2>&1 ; then : ; else + # abort if file read through GRUB doesn't match file read through system + # facilities + device=$(${grub_probe} --target=device $path) + relpath=$(${grub_mkrelpath} $path) + if ${grub_fstest} $device cmp $relpath $path > /dev/null 2>&1 ; then : ; else return 1 fi diff --git a/util/grub-probe.c b/util/grub-probe.c index f02d98589..4ee122713 100644 --- a/util/grub-probe.c +++ b/util/grub-probe.c @@ -226,43 +226,9 @@ probe (const char *path, char *device_name) if (print == PRINT_FS) { - if (path) - { - struct stat st; - - stat (path, &st); - - if (S_ISREG (st.st_mode)) - { - /* Regular file. Verify that we can read it properly. */ - - grub_file_t file; - char *rel_path; - grub_util_info ("reading %s via OS facilities", path); - filebuf_via_sys = grub_util_read_image (path); - - rel_path = grub_make_system_path_relative_to_its_root (path); - grub_path = xasprintf ("(%s)%s", drive_name, rel_path); - free (rel_path); - grub_util_info ("reading %s via GRUB facilities", grub_path); - grub_file_filter_disable_compression (); - file = grub_file_open (grub_path); - if (! file) - grub_util_error ("cannot open %s via GRUB facilities", grub_path); - filebuf_via_grub = xmalloc (file->size); - grub_file_read (file, filebuf_via_grub, file->size); - - grub_util_info ("comparing"); - - if (memcmp (filebuf_via_grub, filebuf_via_sys, file->size)) - grub_util_error ("files differ"); - } - } - printf ("%s\n", fs->name); } - - if (print == PRINT_FS_UUID) + else if (print == PRINT_FS_UUID) { char *uuid; if (! fs->uuid) From 6fa6d6751dd946e7acbfbe2c01516bdc17854329 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Wed, 8 Sep 2010 13:53:47 +0100 Subject: [PATCH 101/214] * grub-core/kern/efi/init.c (grub_efi_set_prefix): If the prefix starts with "(,", fill the drive containing the loaded image in between those two characters, but expect that a full partition specification including partition map names will follow. --- ChangeLog | 7 +++++++ grub-core/kern/efi/init.c | 29 ++++++++++++++++++++++++++--- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7e2420c64..0bb728b6b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2010-09-08 Colin Watson + + * grub-core/kern/efi/init.c (grub_efi_set_prefix): If the prefix + starts with "(,", fill the drive containing the loaded image in + between those two characters, but expect that a full partition + specification including partition map names will follow. + 2010-09-08 Robert Millan * configure.ac: Remove `--enable-grub-fstest' option. diff --git a/grub-core/kern/efi/init.c b/grub-core/kern/efi/init.c index c124aa292..1b0a872b4 100644 --- a/grub-core/kern/efi/init.c +++ b/grub-core/kern/efi/init.c @@ -66,10 +66,33 @@ grub_efi_set_prefix (void) path = grub_strdup (pptr); } - if (!device || !path) + if ((!device || device[0] == ',' || !device[0]) || !path) image = grub_efi_get_loaded_image (grub_efi_image_handle); - if (image && !device) - device = grub_efidisk_get_device_name (image->device_handle); + if (image) + { + if (!device) + device = grub_efidisk_get_device_name (image->device_handle); + else if (device[0] == ',' || !device[0]) + { + /* We have a partition, but still need to fill in the drive. */ + char *image_device, *comma, *new_device; + + image_device = grub_efidisk_get_device_name (image->device_handle); + comma = grub_strchr (image_device, ','); + if (comma) + { + char *drive = grub_strndup (image_device, comma - image_device); + new_device = grub_xasprintf ("%s%s", drive, device); + grub_free (drive); + } + else + new_device = grub_xasprintf ("%s%s", image_device, device); + + grub_free (image_device); + grub_free (device); + device = new_device; + } + } if (image && !path) { From fdff6f0be97ff0dcc7a0a74b21b98f6c8107de6b Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Wed, 8 Sep 2010 14:11:45 +0100 Subject: [PATCH 102/214] For EFI, hardcode the partition number in the core image's prefix. --- util/grub-install.in | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/util/grub-install.in b/util/grub-install.in index b0823642a..0956c0902 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -498,6 +498,7 @@ if [ "x${devabstraction_module}" = "x" ] ; then grub_drive="`$grub_probe --target=drive --device ${grub_device}`" || exit 1 # Strip partition number + grub_partition="`echo ${grub_drive} | sed -e 's/^[^,]*,//; s/)$//'`" grub_drive="`echo ${grub_drive} | sed -e s/,[a-z0-9,]*//g`" if [ "$disk_module" = ata ] ; then # generic method (used on coreboot and ata mod) @@ -520,6 +521,10 @@ if [ "x${devabstraction_module}" = "x" ] ; then echo 'set prefix=($root)'"${relative_grubdir}" >> ${grubdir}/load.cfg config_opt="-c ${grubdir}/load.cfg " modules="$modules search_fs_uuid" + elif [ "x$platform" = xefi ]; then + # No grub-setup, so we need to hardcode the partition number in the + # core image's prefix. + prefix_drive="(,$grub_partition)" fi else prefix_drive=`$grub_probe --target=drive --device ${grub_device}` || exit 1 From e55e8495e1c2ff55abea99784d91961ab86fb9ad Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 8 Sep 2010 16:15:57 +0200 Subject: [PATCH 103/214] * grub-core/kern/ieee1275/cmain.c (grub_ieee1275_find_options): Set GRUB_IEEE1275_FLAG_HAS_CURSORONOFF when appropriate. * grub-core/term/ieee1275/ofconsole.c (grub_ofconsole_setcursor): Use terminfo and don't use cursor-on/cursor-off unless it's known to work. * include/grub/ieee1275/ieee1275.h (grub_ieee1275_flag): New element GRUB_IEEE1275_FLAG_HAS_CURSORONOFF. --- ChangeLog | 10 ++++++++++ grub-core/kern/ieee1275/cmain.c | 9 +++++++-- include/grub/ieee1275/ieee1275.h | 3 +++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0bb728b6b..d8818585b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2010-09-08 Vladimir Serbinenko + + * grub-core/kern/ieee1275/cmain.c (grub_ieee1275_find_options): Set + GRUB_IEEE1275_FLAG_HAS_CURSORONOFF when appropriate. + * grub-core/term/ieee1275/ofconsole.c (grub_ofconsole_setcursor): + Use terminfo and don't use cursor-on/cursor-off unless it's known + to work. + * include/grub/ieee1275/ieee1275.h (grub_ieee1275_flag): New element + GRUB_IEEE1275_FLAG_HAS_CURSORONOFF. + 2010-09-08 Colin Watson * grub-core/kern/efi/init.c (grub_efi_set_prefix): If the prefix diff --git a/grub-core/kern/ieee1275/cmain.c b/grub-core/kern/ieee1275/cmain.c index d3c3a8d88..30eacbbdd 100644 --- a/grub-core/kern/ieee1275/cmain.c +++ b/grub-core/kern/ieee1275/cmain.c @@ -138,11 +138,16 @@ grub_ieee1275_find_options (void) */ grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY); + grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_HAS_CURSORONOFF); } if (is_qemu) - /* OpenFirmware hangs on qemu if one requests any memory below 1.5 MiB. */ - grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM); + { + /* OpenFirmware hangs on qemu if one requests any memory below 1.5 MiB. */ + grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM); + + grub_ieee1275_set_flag (GRUB_IEEE1275_FLAG_HAS_CURSORONOFF); + } if (! grub_ieee1275_finddevice ("/rom/boot-rom", &bootrom)) { diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h index b30909c68..6835b5abc 100644 --- a/include/grub/ieee1275/ieee1275.h +++ b/include/grub/ieee1275/ieee1275.h @@ -103,6 +103,9 @@ enum grub_ieee1275_flag /* OpenFirmware hangs on qemu if one requests any memory below 1.5 MiB. */ GRUB_IEEE1275_FLAG_NO_PRE1_5M_CLAIM, + + /* OLPC / XO firmware has the cursor ON/OFF routines. */ + GRUB_IEEE1275_FLAG_HAS_CURSORONOFF, }; extern int EXPORT_FUNC(grub_ieee1275_test_flag) (enum grub_ieee1275_flag flag); From d87aedff341566b900a62f3557a086772e01f51b Mon Sep 17 00:00:00 2001 From: Yves Blusseau Date: Wed, 8 Sep 2010 17:19:27 +0200 Subject: [PATCH 104/214] * configure.ac: Define some useful variables. --- ChangeLog | 4 ++++ configure.ac | 13 +++++++++++++ 2 files changed, 17 insertions(+) diff --git a/ChangeLog b/ChangeLog index d8818585b..8d87e9182 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2010-09-08 Yves Blusseau + + * configure.ac: Define some useful variables. + 2010-09-08 Vladimir Serbinenko * grub-core/kern/ieee1275/cmain.c (grub_ieee1275_find_options): Set diff --git a/configure.ac b/configure.ac index 3a1a6da63..57b9bb3ac 100644 --- a/configure.ac +++ b/configure.ac @@ -176,6 +176,19 @@ AC_SUBST(host_kernel) AC_SUBST(target_cpu) AC_SUBST(platform) +# Define default variables +case "$host_os" in + netbsd* | openbsd*) + # Because /boot is used for the boot block in NetBSD and OpenBSD, + bootdirname='' ;; + *) bootdirname='boot' ;; +esac +bootdirname=`echo "$bootdirname" | sed "$program_transform_name"` +AC_SUBST(bootdirname) + +grubdirname=`echo "$PACKAGE" | sed "$program_transform_name"` +AC_SUBST(grubdirname) + # # Checks for build programs. # From b9fe6ea2ead3028b08e166cbe0b4e4f32c914772 Mon Sep 17 00:00:00 2001 From: Yves Blusseau Date: Wed, 8 Sep 2010 17:21:32 +0200 Subject: [PATCH 105/214] * util/grub-mkconfig.in: Use new variable. --- ChangeLog | 4 ++++ util/grub-mkconfig.in | 16 +++------------- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8d87e9182..38b97ec8d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2010-09-08 Yves Blusseau + + * util/grub-mkconfig.in: Use new variable. + 2010-09-08 Yves Blusseau * configure.ac: Define some useful variables. diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in index 6f1d375a7..c3b4c3398 100644 --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in @@ -38,6 +38,8 @@ self=`basename $0` grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}` grub_probe=${sbindir}/`echo grub-probe | sed ${transform}` +GRUB_PREFIX=`echo '/@bootdirname@/@grubdirname@' | sed "s,//*,/,g"` + # Usage: usage # Print the usage. usage () { @@ -93,18 +95,6 @@ done . ${libdir}/grub/grub-mkconfig_lib -case "$host_os" in -netbsd* | openbsd*) - # Because /boot is used for the boot block in NetBSD and OpenBSD, use /grub - # instead of /boot/grub. - GRUB_PREFIX=`echo /grub | sed ${transform}` - ;; -*) - # Use /boot/grub by default. - GRUB_PREFIX=`echo /boot/grub | sed ${transform}` - ;; -esac - if [ "x$EUID" = "x" ] ; then EUID=`id -u` fi @@ -200,7 +190,7 @@ for x in ${GRUB_TERMINAL_OUTPUT}; do exit 1 fi else - for dir in ${pkgdatadir} /boot/grub /usr/share/grub ; do + for dir in ${pkgdatadir} ${GRUB_PREFIX} /usr/share/grub ; do for basename in unicode unifont ascii; do path="${dir}/${basename}.pf2" if is_path_readable_by_grub ${path} > /dev/null ; then From c0e53ea537b8ae2755426ac9953fec6591705e8e Mon Sep 17 00:00:00 2001 From: Yves Blusseau Date: Wed, 8 Sep 2010 17:25:29 +0200 Subject: [PATCH 106/214] Add new --boot-directory option to replace --root-directory * util/grub-install.in: Add new --boot-directory option * util/grub-reboot.in: Likewise. * util/grub-set-default.in: Likewise. --- ChangeLog | 8 +++++++ util/grub-install.in | 45 ++++++++++++++++++++-------------------- util/grub-reboot.in | 36 ++++++++++++++++++-------------- util/grub-set-default.in | 36 ++++++++++++++++++-------------- 4 files changed, 70 insertions(+), 55 deletions(-) diff --git a/ChangeLog b/ChangeLog index 38b97ec8d..998385fa2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2010-09-08 Yves Blusseau + + Add new --boot-directory option to replace --root-directory + + * util/grub-install.in: Add new --boot-directory option + * util/grub-reboot.in: Likewise. + * util/grub-set-default.in: Likewise. + 2010-09-08 Yves Blusseau * util/grub-mkconfig.in: Use new variable. diff --git a/util/grub-install.in b/util/grub-install.in index e6521f069..340a616aa 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -41,7 +41,8 @@ grub_mkdevicemap=${sbindir}/`echo grub-mkdevicemap | sed ${transform}` grub_probe=${sbindir}/`echo grub-probe | sed ${transform}` grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}` rootdir= -grub_prefix=`echo /boot/grub | sed ${transform}` +bootdir= +grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'` modules= install_device= @@ -69,8 +70,8 @@ Install GRUB on your drive. -h, --help print this message and exit -v, --version print the version information and exit --modules=MODULES pre-load specified modules MODULES - --root-directory=DIR install GRUB images under the directory DIR - instead of the root directory + --boot-directory=DIR install GRUB images under the directory DIR/@grubdirname@ + instead of the $grubdir directory --grub-setup=FILE use FILE as grub-setup --grub-mkimage=FILE use FILE as grub-mkimage --grub-mkdevicemap=FILE use FILE as grub-mkdevicemap @@ -88,11 +89,8 @@ fi INSTALL_DEVICE can be a GRUB device name or a system device filename. -$self copies GRUB images into /boot/grub (or /grub on NetBSD and -OpenBSD), and uses grub-setup to install grub into the boot sector. - -If the --root-directory option is used, then $self will copy -images into the operating system installation rooted at that directory. +$self copies GRUB images into $grubdir, and uses grub-setup +to install grub into the boot sector. Report bugs to . EOF @@ -134,11 +132,17 @@ do --font=*) ;; +# Accept for compatibility --root-directory) rootdir=`argument $option "$@"`; shift;; --root-directory=*) rootdir=`echo "$option" | sed 's/--root-directory=//'` ;; + --boot-directory) + bootdir=`argument $option "$@"`; shift;; + --boot-directory=*) + bootdir=`echo "$option" | sed 's/--boot-directory=//'` ;; + --grub-setup) grub_setup=`argument $option "$@"`; shift;; --grub-setup=*) @@ -215,23 +219,18 @@ if test $debug = yes; then setup_verbose="--verbose" fi -# Initialize these directories here, since ROOTDIR was initialized. -case "$host_os" in -netbsd* | openbsd*) - # Because /boot is used for the boot block in NetBSD and OpenBSD, use /grub - # instead of /boot/grub. - grub_prefix=`echo /grub | sed ${transform}` - bootdir=${rootdir} - ;; -*) - # Use /boot/grub by default. - bootdir=${rootdir}/boot - ;; -esac +if [ -z "$bootdir" ]; then + # Default bootdir if bootdir not initialized. + bootdir=/@bootdirname@ -grubdir=${bootdir}/`echo grub | sed ${transform}` + if [ -n "$rootdir" ] ; then + # Initialize bootdir if rootdir was initialized. + bootdir=${rootdir}/@bootdirname@ + fi +fi + +grubdir=`echo "${bootdir}/@grubdirname@" | sed 's,//*,/,g'` device_map=${grubdir}/device.map - grub_probe="${grub_probe} --device-map=${device_map}" # Check if GRUB is installed. diff --git a/util/grub-reboot.in b/util/grub-reboot.in index e7a41f68f..929cf5202 100644 --- a/util/grub-reboot.in +++ b/util/grub-reboot.in @@ -29,6 +29,8 @@ self=`basename $0` grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}` rootdir= +bootdir= +grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'` # Usage: usage # Print the usage. @@ -39,8 +41,8 @@ Set the default boot entry for GRUB, for the next boot only. -h, --help print this message and exit -v, --version print the version information and exit - --root-directory=DIR expect GRUB images under the directory DIR - instead of the root directory + --boot-directory=DIR expect GRUB images under the directory DIR/@grubdirname@ + instead of the $grubdir directory ENTRY is a number or a menu item title. @@ -73,11 +75,17 @@ do echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" exit 0 ;; +# Accept for compatibility --root-directory) rootdir=`argument $option "$@"`; shift ;; --root-directory=*) rootdir=`echo "$option" | sed 's/--root-directory=//'` ;; + --boot-directory) + bootdir=`argument $option "$@"`; shift;; + --boot-directory=*) + bootdir=`echo "$option" | sed 's/--boot-directory=//'` ;; + -*) echo "Unrecognized option \`$option'" 1>&2 usage @@ -99,21 +107,17 @@ if test "x$entry" = x; then exit 1 fi -# Initialize these directories here, since ROOTDIR was initialized. -case "$host_os" in -netbsd* | openbsd*) - # Because /boot is used for the boot block in NetBSD and OpenBSD, use /grub - # instead of /boot/grub. - grub_prefix=`echo /grub | sed ${transform}` - bootdir=${rootdir} - ;; -*) - # Use /boot/grub by default. - bootdir=${rootdir}/boot - ;; -esac +if [ -z "$bootdir" ]; then + # Default bootdir if bootdir not initialized. + bootdir=/@bootdirname@ -grubdir=${bootdir}/`echo grub | sed ${transform}` + if [ -n "$rootdir" ] ; then + # Initialize bootdir if rootdir was initialized. + bootdir=${rootdir}/@bootdirname@ + fi +fi + +grubdir=`echo "${bootdir}/@grubdirname@" | sed 's,//*,/,g'` prev_saved_entry=`$grub_editenv ${grubdir}/grubenv list | sed -n 's/^saved_entry=//p'` if [ "$prev_saved_entry" ]; then diff --git a/util/grub-set-default.in b/util/grub-set-default.in index 389c504c7..b09727de2 100644 --- a/util/grub-set-default.in +++ b/util/grub-set-default.in @@ -29,6 +29,8 @@ self=`basename $0` grub_editenv=${bindir}/`echo grub-editenv | sed ${transform}` rootdir= +bootdir= +grubdir=`echo "/@bootdirname@/@grubdirname@" | sed 's,//*,/,g'` # Usage: usage # Print the usage. @@ -39,8 +41,8 @@ Set the default boot entry for GRUB. -h, --help print this message and exit -v, --version print the version information and exit - --root-directory=DIR expect GRUB images under the directory DIR - instead of the root directory + --boot-directory=DIR expect GRUB images under the directory DIR/@grubdirname@ + instead of the $grubdir directory ENTRY is a number or a menu item title. @@ -73,11 +75,17 @@ do echo "$self (${PACKAGE_NAME}) ${PACKAGE_VERSION}" exit 0 ;; +# Accept for compatibility --root-directory) rootdir=`argument $option "$@"`; shift ;; --root-directory=*) rootdir=`echo "$option" | sed 's/--root-directory=//'` ;; + --boot-directory) + bootdir=`argument $option "$@"`; shift;; + --boot-directory=*) + bootdir=`echo "$option" | sed 's/--boot-directory=//'` ;; + -*) echo "Unrecognized option \`$option'" 1>&2 usage @@ -99,21 +107,17 @@ if test "x$entry" = x; then exit 1 fi -# Initialize these directories here, since ROOTDIR was initialized. -case "$host_os" in -netbsd* | openbsd*) - # Because /boot is used for the boot block in NetBSD and OpenBSD, use /grub - # instead of /boot/grub. - grub_prefix=`echo /grub | sed ${transform}` - bootdir=${rootdir} - ;; -*) - # Use /boot/grub by default. - bootdir=${rootdir}/boot - ;; -esac +if [ -z "$bootdir" ]; then + # Default bootdir if bootdir not initialized. + bootdir=/@bootdirname@ -grubdir=${bootdir}/`echo grub | sed ${transform}` + if [ -n "$rootdir" ] ; then + # Initialize bootdir if rootdir was initialized. + bootdir=${rootdir}/@bootdirname@ + fi +fi + +grubdir=`echo "${bootdir}/@grubdirname@" | sed 's,//*,/,g'` $grub_editenv ${grubdir}/grubenv unset prev_saved_entry $grub_editenv ${grubdir}/grubenv set saved_entry="$entry" From 5f7a44bf9219d0f5482ddcaf9f322ea6bcefe5cd Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 8 Sep 2010 19:09:07 +0200 Subject: [PATCH 107/214] Missing part of r2705 --- grub-core/term/ieee1275/ofconsole.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/grub-core/term/ieee1275/ofconsole.c b/grub-core/term/ieee1275/ofconsole.c index 9ec85631b..1e8fbd1ad 100644 --- a/grub-core/term/ieee1275/ofconsole.c +++ b/grub-core/term/ieee1275/ofconsole.c @@ -117,9 +117,14 @@ grub_ofconsole_getwh (struct grub_term_output *term __attribute__ ((unused))) } static void -grub_ofconsole_setcursor (struct grub_term_output *term __attribute__ ((unused)), +grub_ofconsole_setcursor (struct grub_term_output *term, int on) { + grub_terminfo_setcursor (term, on); + + if (!grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_HAS_CURSORONOFF)) + return; + /* Understood by the Open Firmware flavour in OLPC. */ if (on) grub_ieee1275_interpret ("cursor-on", 0); From b4a0c9154b05f59036920a9fc666ad0556ec7a73 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 8 Sep 2010 19:13:48 +0200 Subject: [PATCH 108/214] Split minix.mod into minix.mod and minix2.mod. * Makefile.util.def (libgrub.a): Add grub-core/fs/minix2.c. * grub-core/Makefile.core.def (minix2): New module. * grub-core/fs/minix.c: Use definitions instead of runtime version checking. * grub-core/fs/minix2.c: New file. --- Makefile.util.def | 1 + grub-core/Makefile.core.def | 5 ++ grub-core/fs/minix.c | 145 +++++++++++++++--------------------- grub-core/fs/minix2.c | 2 + 4 files changed, 69 insertions(+), 84 deletions(-) create mode 100644 grub-core/fs/minix2.c diff --git a/Makefile.util.def b/Makefile.util.def index c4872c7c3..05c4404a2 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -52,6 +52,7 @@ library = { common = grub-core/fs/iso9660.c; common = grub-core/fs/jfs.c; common = grub-core/fs/minix.c; + common = grub-core/fs/minix2.c; common = grub-core/fs/nilfs2.c; common = grub-core/fs/ntfs.c; common = grub-core/fs/ntfscomp.c; diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 59d99a326..04525bbab 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -880,6 +880,11 @@ module = { common = fs/minix.c; }; +module = { + name = minix2; + common = fs/minix2.c; +}; + module = { name = nilfs2; common = fs/nilfs2.c; diff --git a/grub-core/fs/minix.c b/grub-core/fs/minix.c index a856e38c4..aa5b9a0c9 100644 --- a/grub-core/fs/minix.c +++ b/grub-core/fs/minix.c @@ -25,10 +25,13 @@ #include #include +#ifdef MODE_MINIX2 +#define GRUB_MINIX_MAGIC 0x2468 +#define GRUB_MINIX_MAGIC_30 0x2478 +#else #define GRUB_MINIX_MAGIC 0x137F -#define GRUB_MINIX2_MAGIC 0x2468 #define GRUB_MINIX_MAGIC_30 0x138F -#define GRUB_MINIX2_MAGIC_30 0x2478 +#endif #define GRUB_MINIX_BSIZE 1024U #define GRUB_MINIX_LOG2_BSIZE 1 #define GRUB_MINIX_ROOT_INODE 1 @@ -38,20 +41,25 @@ #define GRUB_MINIX_IFDIR 0040000U #define GRUB_MINIX_IFLNK 0120000U -#define GRUB_MINIX_INODE(data,field) (data->version == 1 ? \ - data->inode. field : data->inode2. field) -#define GRUB_MINIX_INODE_ENDIAN(data,field,bits1,bits2) (data->version == 1 ? \ - grub_le_to_cpu##bits1 (data->inode.field) : \ - grub_le_to_cpu##bits2 (data->inode2.field)) -#define GRUB_MINIX_INODE_SIZE(data) GRUB_MINIX_INODE_ENDIAN (data,size,16,32) -#define GRUB_MINIX_INODE_MODE(data) GRUB_MINIX_INODE_ENDIAN (data,mode,16,16) -#define GRUB_MINIX_INODE_DIR_ZONES(data,blk) GRUB_MINIX_INODE_ENDIAN \ - (data,dir_zones[blk],16,32) -#define GRUB_MINIX_INODE_INDIR_ZONE(data) \ - GRUB_MINIX_INODE_ENDIAN (data,indir_zone,16,32) -#define GRUB_MINIX_INODE_DINDIR_ZONE(data) \ - GRUB_MINIX_INODE_ENDIAN (data,double_indir_zone,16,32) -#define GRUB_MINIX_INODE_BLKSZ(data) (data->version == 1 ? 2 : 4) +#ifdef MODE_MINIX2 +typedef grub_uint32_t grub_minix_uintn_t; +#define grub_minix_le_to_cpu_n grub_le_to_cpu32 +#else +typedef grub_uint16_t grub_minix_uintn_t; +#define grub_minix_le_to_cpu_n grub_le_to_cpu16 +#endif + +#define GRUB_MINIX_INODE_BLKSZ(data) sizeof (grub_minix_uintn_t) + +#define GRUB_MINIX_INODE_SIZE(data) (grub_minix_le_to_cpu_n (data->inode.size)) +#define GRUB_MINIX_INODE_MODE(data) (grub_le_to_cpu16 (data->inode.mode)) +#define GRUB_MINIX_INODE_DIR_ZONES(data,blk) (grub_minix_le_to_cpu_n \ + (data->inode.dir_zones[blk])) +#define GRUB_MINIX_INODE_INDIR_ZONE(data) (grub_minix_le_to_cpu_n \ + (data->inode.indir_zone)) +#define GRUB_MINIX_INODE_DINDIR_ZONE(data) (grub_minix_le_to_cpu_n \ + (data->inode.double_indir_zone)) + #define GRUB_MINIX_LOG2_ZONESZ (GRUB_MINIX_LOG2_BSIZE \ + grub_le_to_cpu16 (sblock->log2_zone_size)) #define GRUB_MINIX_ZONESZ (GRUB_MINIX_BSIZE \ @@ -69,6 +77,7 @@ struct grub_minix_sblock grub_uint16_t magic; }; +#ifndef MODE_MINIX2 struct grub_minix_inode { grub_uint16_t mode; @@ -82,7 +91,9 @@ struct grub_minix_inode grub_uint16_t double_indir_zone; }; -struct grub_minix2_inode +#else + +struct grub_minix_inode { grub_uint16_t mode; grub_uint16_t nlinks; @@ -99,16 +110,16 @@ struct grub_minix2_inode }; +#endif + /* Information about a "mounted" minix filesystem. */ struct grub_minix_data { struct grub_minix_sblock sblock; struct grub_minix_inode inode; - struct grub_minix2_inode inode2; int ino; int linknest; grub_disk_t disk; - int version; int filename_size; }; @@ -128,24 +139,12 @@ grub_minix_get_file_block (struct grub_minix_data *data, unsigned int blk) /* Read the block pointer in ZONE, on the offset NUM. */ int grub_get_indir (int zone, int num) { - if (data->version == 1) - { - grub_uint16_t indir16; - grub_disk_read (data->disk, - zone << GRUB_MINIX_LOG2_ZONESZ, - sizeof (grub_uint16_t) * num, - sizeof (grub_uint16_t), (char *) &indir16); - return grub_le_to_cpu16 (indir16); - } - else - { - grub_uint32_t indir32; - grub_disk_read (data->disk, - zone << GRUB_MINIX_LOG2_ZONESZ, - sizeof (grub_uint32_t) * num, - sizeof (grub_uint32_t), (char *) &indir32); - return grub_le_to_cpu32 (indir32); - } + grub_minix_uintn_t indirn; + grub_disk_read (data->disk, + zone << GRUB_MINIX_LOG2_ZONESZ, + sizeof (grub_minix_uintn_t) * num, + sizeof (grub_minix_uintn_t), (char *) &indirn); + return grub_minix_le_to_cpu_n (indirn); } /* Direct block. */ @@ -259,27 +258,13 @@ grub_minix_read_inode (struct grub_minix_data *data, int ino) + grub_le_to_cpu16 (sblock->zone_bmap_size)) << GRUB_MINIX_LOG2_BSIZE); - if (data->version == 1) - { - block += ino / (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode)); - int offs = (ino % (GRUB_DISK_SECTOR_SIZE - / sizeof (struct grub_minix_inode)) - * sizeof (struct grub_minix_inode)); - - grub_disk_read (data->disk, block, offs, - sizeof (struct grub_minix_inode), &data->inode); - } - else - { - block += ino / (GRUB_DISK_SECTOR_SIZE - / sizeof (struct grub_minix2_inode)); - int offs = (ino - % (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix2_inode)) - * sizeof (struct grub_minix2_inode)); - - grub_disk_read (data->disk, block, offs, - sizeof (struct grub_minix2_inode),&data->inode2); - } + block += ino / (GRUB_DISK_SECTOR_SIZE / sizeof (struct grub_minix_inode)); + int offs = (ino % (GRUB_DISK_SECTOR_SIZE + / sizeof (struct grub_minix_inode)) + * sizeof (struct grub_minix_inode)); + + grub_disk_read (data->disk, block, offs, + sizeof (struct grub_minix_inode), &data->inode); return GRUB_ERR_NONE; } @@ -424,25 +409,9 @@ grub_minix_mount (grub_disk_t disk) goto fail; if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX_MAGIC) - { - data->version = 1; - data->filename_size = 14; - } - else if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX2_MAGIC) - { - data->version = 2; - data->filename_size = 14; - } + data->filename_size = 14; else if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX_MAGIC_30) - { - data->version = 1; - data->filename_size = 30; - } - else if (grub_le_to_cpu16 (data->sblock.magic) == GRUB_MINIX2_MAGIC_30) - { - data->version = 2; - data->filename_size = 30; - } + data->filename_size = 30; else goto fail; @@ -453,7 +422,11 @@ grub_minix_mount (grub_disk_t disk) fail: grub_free (data); +#ifdef MODE_MINIX2 + grub_error (GRUB_ERR_BAD_FS, "not a minix2 filesystem"); +#else grub_error (GRUB_ERR_BAD_FS, "not a minix filesystem"); +#endif return 0; } @@ -583,32 +556,36 @@ grub_minix_close (grub_file_t file) } -static grub_err_t -grub_minix_label (grub_device_t device __attribute ((unused)), - char **label __attribute ((unused))) -{ - return GRUB_ERR_NONE; -} - static struct grub_fs grub_minix_fs = { +#ifdef MODE_MINIX2 + .name = "minix2", +#else .name = "minix", +#endif .dir = grub_minix_dir, .open = grub_minix_open, .read = grub_minix_read, .close = grub_minix_close, - .label = grub_minix_label, .next = 0 }; +#ifdef MODE_MINIX2 +GRUB_MOD_INIT(minix2) +#else GRUB_MOD_INIT(minix) +#endif { grub_fs_register (&grub_minix_fs); my_mod = mod; } +#ifdef MODE_MINIX2 +GRUB_MOD_FINI(minix2) +#else GRUB_MOD_FINI(minix) +#endif { grub_fs_unregister (&grub_minix_fs); } diff --git a/grub-core/fs/minix2.c b/grub-core/fs/minix2.c new file mode 100644 index 000000000..0fcd4b139 --- /dev/null +++ b/grub-core/fs/minix2.c @@ -0,0 +1,2 @@ +#define MODE_MINIX2 1 +#include "minix.c" From 27f21a8bb614d70b0db45d123a98bafa932098a5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 8 Sep 2010 21:01:20 +0200 Subject: [PATCH 109/214] Add forgotten commit part --- ChangeLog | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ChangeLog b/ChangeLog index 998385fa2..09fa2e60b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2010-09-08 Vladimir Serbinenko + + Split minix.mod into minix.mod and minix2.mod. + + * Makefile.util.def (libgrub.a): Add grub-core/fs/minix2.c. + * grub-core/Makefile.core.def (minix2): New module. + * grub-core/fs/minix.c: Use definitions instead of runtime version + checking. + * grub-core/fs/minix2.c: New file. + 2010-09-08 Yves Blusseau Add new --boot-directory option to replace --root-directory From 6b8e78aee3538c8e44721c2697673652b8986c97 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Wed, 8 Sep 2010 23:35:53 +0200 Subject: [PATCH 110/214] 2010-09-08 Robert Millan * util/grub-mkconfig_lib.in (is_path_readable_by_grub): Improve with (optional) parameters to specify device and relative path. * util/grub-install.in: Use is_path_readable_by_grub() to verify readability of a few critical files. * util/grub-mkconfig.in: Use is_path_readable_by_grub() to verify readability of grub.cfg.new. --- ChangeLog | 9 +++++++++ util/grub-install.in | 13 ++++++++++--- util/grub-mkconfig.in | 6 ++++++ util/grub-mkconfig_lib.in | 11 +++++++++-- 4 files changed, 34 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 09fa2e60b..ae534fa7f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2010-09-08 Robert Millan + + * util/grub-mkconfig_lib.in (is_path_readable_by_grub): Improve + with (optional) parameters to specify device and relative path. + * util/grub-install.in: Use is_path_readable_by_grub() to + verify readability of a few critical files. + * util/grub-mkconfig.in: Use is_path_readable_by_grub() to + verify readability of grub.cfg.new. + 2010-09-08 Vladimir Serbinenko Split minix.mod into minix.mod and minix2.mod. diff --git a/util/grub-install.in b/util/grub-install.in index 340a616aa..4de5dbc4a 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -1,7 +1,7 @@ #! /bin/sh # Install GRUB on your drive. -# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc. +# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc. # # GRUB is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -327,8 +327,7 @@ if test "x$fs_module" = x -a "x$modules" = x; then fi # Then the partition map module. In order to support partition-less media, -# this command is allowed to fail (--target=fs already grants us that the -# filesystem will be accessible). +# this command is allowed to fail. partmap_module= for x in `$grub_probe --target=partmap --device ${grub_device} 2> /dev/null`; do partmap_module="$partmap_module part_$x"; @@ -402,6 +401,14 @@ case "${target_cpu}-${platform}" in *) mkimage_target=i386-coreboot; esac +# Verify readability of a few critical files +for file in grubenv core.${imgext} normal.mod ; do + if is_path_readable_by_grub ${grubdir}/${file} ${grub_device} ${relative_grubdir}/${file} ; then : ; else + echo "GRUB is unable to read ${grubdir}/${file}" >&2 + exit 1 + fi +done + if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then $grub_mkimage ${config_opt} -O ${mkimage_target} --output=${grubdir}/core.img --prefix=${prefix_drive}${relative_grubdir} $modules || exit 1 diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in index c3b4c3398..f0f134b3d 100644 --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in @@ -303,6 +303,12 @@ for i in ${grub_mkconfig_dir}/* ; do esac done +# Verify readability of ${grub_cfg}.new +if is_path_readable_by_grub ${grub_cfg}.new ; then : ; else + echo "GRUB is unable to read ${grubdir}/${file}" >&2 + exit 1 +fi + if test "x${grub_cfg}" != "x" ; then # none of the children aborted with error, install the new grub.cfg mv -f ${grub_cfg}.new ${grub_cfg} diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in index c6f79fb49..6d4f9f3bb 100644 --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in @@ -53,16 +53,23 @@ make_system_path_relative_to_its_root () is_path_readable_by_grub () { path=$1 + device=$2 + relpath=$3 # abort if path doesn't exist if test -e $path ; then : ;else return 1 fi + if [ "${device}" = "" ] ; then + device=$(${grub_probe} --target=device $path) + fi + if [ "${relpath}" = "" ] ; then + relpath=$(${grub_mkrelpath} $path) + fi + # abort if file read through GRUB doesn't match file read through system # facilities - device=$(${grub_probe} --target=device $path) - relpath=$(${grub_mkrelpath} $path) if ${grub_fstest} $device cmp $relpath $path > /dev/null 2>&1 ; then : ; else return 1 fi From f637773235f4439e5493969c2012ddcf7143156e Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Wed, 8 Sep 2010 23:41:27 +0200 Subject: [PATCH 111/214] 2010-09-08 Robert Millan * util/grub-mkconfig_lib.in (is_path_readable_by_grub): Improve with (optional) parameters to specify device and relative path. * util/grub-install.in: Use is_path_readable_by_grub() to verify readability of a few critical files. * util/grub-mkconfig.in: Use is_path_readable_by_grub() to verify readability of grub.cfg.new. --- ChangeLog | 9 +++++++++ util/grub-install.in | 13 ++++++++++--- util/grub-mkconfig.in | 6 ++++++ util/grub-mkconfig_lib.in | 11 +++++++++-- 4 files changed, 34 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2acf132ee..eef306cc9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2010-09-08 Robert Millan + + * util/grub-mkconfig_lib.in (is_path_readable_by_grub): Improve + with (optional) parameters to specify device and relative path. + * util/grub-install.in: Use is_path_readable_by_grub() to + verify readability of a few critical files. + * util/grub-mkconfig.in: Use is_path_readable_by_grub() to + verify readability of grub.cfg.new. + 2010-09-08 Colin Watson * grub-core/kern/efi/init.c (grub_efi_set_prefix): If the prefix diff --git a/util/grub-install.in b/util/grub-install.in index 0956c0902..eb7ef48b6 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -1,7 +1,7 @@ #! /bin/sh # Install GRUB on your drive. -# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc. +# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc. # # GRUB is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -457,8 +457,7 @@ if test "x$fs_module" = x -a "x$modules" = x; then fi # Then the partition map module. In order to support partition-less media, -# this command is allowed to fail (--target=fs already grants us that the -# filesystem will be accessible). +# this command is allowed to fail. partmap_module= for x in `$grub_probe --target=partmap --device ${grub_device} 2> /dev/null`; do partmap_module="$partmap_module part_$x"; @@ -555,6 +554,14 @@ elif [ "${target_cpu}-${platform}" = "i386-efi" ] || [ "${target_cpu}-${platform $grub_mkimage ${config_opt} -O ${mkimage_target} --output=${grubdir}/grub.efi --prefix="" $modules || exit 1 fi +# Verify readability of a few critical files +for file in grubenv core.${imgext} normal.mod ; do + if is_path_readable_by_grub ${grubdir}/${file} ${grub_device} ${relative_grubdir}/${file} ; then : ; else + echo "GRUB is unable to read ${grubdir}/${file}" >&2 + exit 1 + fi +done + # Perform the platform-dependent install if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then # Now perform the installation. diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in index 6f1d375a7..9ea01e8f6 100644 --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in @@ -313,6 +313,12 @@ for i in ${grub_mkconfig_dir}/* ; do esac done +# Verify readability of ${grub_cfg}.new +if is_path_readable_by_grub ${grub_cfg}.new ; then : ; else + echo "GRUB is unable to read ${grubdir}/${file}" >&2 + exit 1 +fi + if test "x${grub_cfg}" != "x" ; then # none of the children aborted with error, install the new grub.cfg mv -f ${grub_cfg}.new ${grub_cfg} diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in index c6f79fb49..6d4f9f3bb 100644 --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in @@ -53,16 +53,23 @@ make_system_path_relative_to_its_root () is_path_readable_by_grub () { path=$1 + device=$2 + relpath=$3 # abort if path doesn't exist if test -e $path ; then : ;else return 1 fi + if [ "${device}" = "" ] ; then + device=$(${grub_probe} --target=device $path) + fi + if [ "${relpath}" = "" ] ; then + relpath=$(${grub_mkrelpath} $path) + fi + # abort if file read through GRUB doesn't match file read through system # facilities - device=$(${grub_probe} --target=device $path) - relpath=$(${grub_mkrelpath} $path) if ${grub_fstest} $device cmp $relpath $path > /dev/null 2>&1 ; then : ; else return 1 fi From 4dfbc57428c2639b388fb1b08409dbd158b7f2de Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Thu, 9 Sep 2010 01:12:10 +0200 Subject: [PATCH 112/214] 2010-09-09 Robert Millan Basic Btrfs support (detection and UUID). * grub-core/fs/btrfs.c: New file. * Makefile.util.def (library): Register btrfs.c. * grub-core/Makefile.core.def: Likewise. --- ChangeLog | 8 +++ Makefile.util.def | 1 + grub-core/Makefile.core.def | 5 ++ grub-core/fs/btrfs.c | 132 ++++++++++++++++++++++++++++++++++++ 4 files changed, 146 insertions(+) create mode 100644 grub-core/fs/btrfs.c diff --git a/ChangeLog b/ChangeLog index ae534fa7f..0593c7731 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2010-09-09 Robert Millan + + Basic Btrfs support (detection and UUID). + + * grub-core/fs/btrfs.c: New file. + * Makefile.util.def (library): Register btrfs.c. + * grub-core/Makefile.core.def: Likewise. + 2010-09-08 Robert Millan * util/grub-mkconfig_lib.in (is_path_readable_by_grub): Improve diff --git a/Makefile.util.def b/Makefile.util.def index 05c4404a2..413c7eed8 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -43,6 +43,7 @@ library = { common = grub-core/fs/afs.c; common = grub-core/fs/befs_be.c; common = grub-core/fs/befs.c; + common = grub-core/fs/btrfs.c; common = grub-core/fs/cpio.c; common = grub-core/fs/ext2.c; common = grub-core/fs/fat.c; diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 04525bbab..000ccaa2a 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -835,6 +835,11 @@ module = { common = fs/befs_be.c; }; +module = { + name = btrfs; + common = fs/btrfs.c; +}; + module = { name = cpio; common = fs/cpio.c; diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c new file mode 100644 index 000000000..a50bae000 --- /dev/null +++ b/grub-core/fs/btrfs.c @@ -0,0 +1,132 @@ +/* btrfs.c - B-tree file system. */ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +#define BTRFS_SIGNATURE "_BHRfS_M" + +struct btrfs_superblock +{ + grub_uint8_t dummy1[32]; + grub_uint16_t uuid[8]; + grub_uint8_t dummy2[16]; + grub_uint8_t signature[sizeof (BTRFS_SIGNATURE) - 1]; +} __attribute__ ((packed)); + +struct grub_btrfs_data +{ + struct btrfs_superblock sblock; +}; + +static struct grub_btrfs_data * +grub_btrfs_mount (grub_disk_t disk) +{ + struct grub_btrfs_data *data = grub_malloc (sizeof (*data)); + if (! data) + return NULL; + + if (grub_disk_read (disk, 128, 0, sizeof (data->sblock), + &data->sblock) != GRUB_ERR_NONE) + goto fail; + + if (grub_strncmp ((char *) data->sblock.signature, BTRFS_SIGNATURE, sizeof (BTRFS_SIGNATURE) - 1)) + { + grub_error (GRUB_ERR_BAD_FS, "not a Btrfs filesystem"); + goto fail; + } + + return data; + + fail: + grub_free (data); + return NULL; +} + +static grub_err_t +grub_btrfs_open (struct grub_file *file __attribute__ ((unused)), + const char *name __attribute__ ((unused))) +{ + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "only detection is supported for Btrfs"); +} + +static grub_err_t +grub_btrfs_dir (grub_device_t device, + const char *path __attribute__ ((unused)), + int (*hook) (const char *filename, + const struct grub_dirhook_info *info) + __attribute__ ((unused))) +{ + struct grub_btrfs_data *data = grub_btrfs_mount (device->disk); + if (grub_errno) + return grub_errno; + + grub_free (data); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_btrfs_uuid (grub_device_t device, char **uuid) +{ + struct grub_btrfs_data *data; + + *uuid = NULL; + + data = grub_btrfs_mount (device->disk); + if (! data) + return grub_errno; + + *uuid = grub_xasprintf ("%04x%04x-%04x-%04x-%04x-%04x%04x%04x", + grub_be_to_cpu16 (data->sblock.uuid[0]), + grub_be_to_cpu16 (data->sblock.uuid[1]), + grub_be_to_cpu16 (data->sblock.uuid[2]), + grub_be_to_cpu16 (data->sblock.uuid[3]), + grub_be_to_cpu16 (data->sblock.uuid[4]), + grub_be_to_cpu16 (data->sblock.uuid[5]), + grub_be_to_cpu16 (data->sblock.uuid[6]), + grub_be_to_cpu16 (data->sblock.uuid[7])); + + grub_free (data); + + return grub_errno; +} + +static struct grub_fs grub_btrfs_fs = + { + .name = "btrfs", + .dir = grub_btrfs_dir, + .open = grub_btrfs_open, + .uuid = grub_btrfs_uuid, + }; + +GRUB_MOD_INIT(btrfs) +{ + grub_fs_register (&grub_btrfs_fs); +} + +GRUB_MOD_FINI(btrfs) +{ + grub_fs_unregister (&grub_btrfs_fs); +} From 7bf45fdd318944cfcbb75a359e58d8658fddef14 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Thu, 9 Sep 2010 01:16:05 +0200 Subject: [PATCH 113/214] 2010-09-09 Robert Millan * util/grub-probe.c (probe): Fix a pair of unhandled error conditions. --- ChangeLog | 5 +++++ util/grub-probe.c | 6 ++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0593c7731..b0354a4fc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2010-09-09 Robert Millan + + * util/grub-probe.c (probe): Fix a pair of unhandled error + conditions. + 2010-09-09 Robert Millan Basic Btrfs support (detection and UUID). diff --git a/util/grub-probe.c b/util/grub-probe.c index 4ee122713..9f8a443c8 100644 --- a/util/grub-probe.c +++ b/util/grub-probe.c @@ -234,7 +234,8 @@ probe (const char *path, char *device_name) if (! fs->uuid) grub_util_error ("%s does not support UUIDs", fs->name); - fs->uuid (dev, &uuid); + if (fs->uuid (dev, &uuid) != GRUB_ERR_NONE) + grub_util_error ("%s", grub_errmsg); printf ("%s\n", uuid); } @@ -244,7 +245,8 @@ probe (const char *path, char *device_name) if (! fs->label) grub_util_error ("%s does not support labels", fs->name); - fs->label (dev, &label); + if (fs->label (dev, &label) != GRUB_ERR_NONE) + grub_util_error ("%s", grub_errmsg); printf ("%s\n", label); } From 56672f4a8bff852ba92a5e95b331c74521d98b5e Mon Sep 17 00:00:00 2001 From: "bvk.groups@gmail.com" <> Date: Thu, 9 Sep 2010 21:10:17 +0530 Subject: [PATCH 114/214] added new partmaps test --- Makefile.util.def | 6 + tests/partmap_test.in | 259 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 265 insertions(+) create mode 100644 tests/partmap_test.in diff --git a/Makefile.util.def b/Makefile.util.def index 413c7eed8..b9901ad66 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -538,6 +538,12 @@ script = { common = tests/grub_script_not.in; }; +script = { + testcase; + name = partmap_test; + common = tests/partmap_test.in; +}; + program = { testcase; name = example_unit_test; diff --git a/tests/partmap_test.in b/tests/partmap_test.in new file mode 100644 index 000000000..80b38e58b --- /dev/null +++ b/tests/partmap_test.in @@ -0,0 +1,259 @@ +#! /bin/sh -e + +parted=/sbin/parted +grubshell=@builddir@/grub-shell + +create_disk_image () { + name=$1 + size=$2 + qemu-img create ${name} ${size} >/dev/null +} + +check_output () { + outfile=$1 + shift + + for disk in $@; do + if ! grep "($disk)" ${outfile} >/dev/null + then + echo "($disk): disk/partiton not found" + exit 1 + fi + done +} + +list_parts () { + mod=$1; + shift; + imgfile=$1 + shift + outfile=$1 + shift + + echo ls | ${grubshell} --boot=cd --qemu-opts="-hda ${imgfile}" \ + --modules=$mod | tr -d "\n\r" > ${outfile} + cat ${outfile} + echo +} + +imgfile=`mktemp` +outfile=`mktemp` + +# +# MSDOS partition types +# + +echo "Checking MSDOS partition types..." + +# 0 primary +create_disk_image ${imgfile} 64M +${parted} -a none -s ${imgfile} mklabel msdos +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 + +# 1 primary +create_disk_image ${imgfile} 64M +${parted} -a none -s ${imgfile} mklabel msdos mkpart primary 0 10M +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,msdos1 + +# 2 primary +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel msdos mkpart primary 0 10M mkpart primary 10M 20M +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,msdos1 hd0,msdos2 + +# 3 primary +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel msdos mkpart primary 0 10M mkpart primary 10M 20M mkpart primary 20M 30M +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,msdos1 hd0,msdos2 hd0,msdos3 + +# 4 primary +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel msdos mkpart primary 0 10M mkpart primary 10M 20M mkpart primary 20M 30M mkpart primary 30M 40M +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,msdos1 hd0,msdos2 hd0,msdos3 hd0,msdos4 + +# 1 primary, 1 extended +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel msdos mkpart primary 0 10M mkpart primary 10M 20M mkpart extended 20M 100% +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,msdos1 + +# 1 primary, 1 extended, 1 logical +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel msdos mkpart primary 0 10M mkpart primary 10M 20M mkpart extended 20M 100% mkpart logical 20M 30M +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,msdos1 hd0,msdos5 + +# 1 primary, 1 extended, 2 logical +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel msdos mkpart primary 0 10M mkpart primary 10M 20M mkpart extended 20M 100% mkpart logical 20M 30M mkpart logical 30M 40M +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,msdos1 hd0,msdos5 hd0,msdos6 + +# 1 primary, 1 extended, 3 logical +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel msdos mkpart primary 0 10M mkpart primary 10M 20M mkpart extended 20M 100% mkpart logical 20M 30M mkpart logical 30M 40M mkpart logical 40M 50M +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,msdos1 hd0,msdos5 hd0,msdos6 hd0,msdos7 + +# 1 primary, 1 extended, 4 logical +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel msdos mkpart primary 0 10M mkpart primary 10M 20M mkpart extended 20M 100% mkpart logical 20M 30M mkpart logical 30M 40M mkpart logical 40M 50M mkpart logical 50M 60M +list_parts part_msdos ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,msdos1 hd0,msdos5 hd0,msdos6 hd0,msdos7 hd0,msdos8 + + +# +# GPT partition types +# + +echo "Checking GPT partition types..." + +# 0 parts +create_disk_image ${imgfile} 64M +${parted} -a none -s ${imgfile} mklabel gpt +list_parts part_gpt ${imgfile} ${outfile} +check_output ${outfile} hd0 + +# 1 parts +create_disk_image ${imgfile} 64M +${parted} -a none -s ${imgfile} mklabel gpt mkpart 1 0 10M +list_parts part_gpt ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,gpt1 + +# 2 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel gpt mkpart 1 0 10M mkpart 2 10M 20M +list_parts part_gpt ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,gpt1 hd0,gpt2 + +# 3 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel gpt mkpart 1 0 10M mkpart 2 10M 20M mkpart 3 20M 30M +list_parts part_gpt ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,gpt1 hd0,gpt2 hd0,gpt3 + +# 4 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel gpt mkpart 1 0 10M mkpart 2 10M 20M mkpart 4 20M 30M mkpart 5 30M 40M +list_parts part_gpt ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,gpt1 hd0,gpt2 hd0,gpt3 hd0,gpt4 + +# 5 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel gpt mkpart 1 0 10M mkpart 2 10M 20M mkpart 3 20M 30M mkpart 4 30M 40M mkpart 5 40M 50M +list_parts part_gpt ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,gpt1 hd0,gpt2 hd0,gpt3 hd0,gpt4 hd0,gpt5 + +# 6 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel gpt mkpart 1 0 10M mkpart 2 10M 20M mkpart 3 20M 30M mkpart 4 30M 40M mkpart 5 40M 50M mkpart 6 50M 60M +list_parts part_gpt ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,gpt1 hd0,gpt2 hd0,gpt3 hd0,gpt4 hd0,gpt5 hd0,gpt6 + + +# +# SUN partition types +# +# It seems partition #3 is reserved for whole disk by parted. +# + +echo "Checking SUN partition types..." + +# 0 parts +create_disk_image ${imgfile} 64M +${parted} -a none -s ${imgfile} mklabel sun +list_parts part_sun ${imgfile} ${outfile} +check_output ${outfile} hd0 + +# 1 parts +create_disk_image ${imgfile} 64M +${parted} -a none -s ${imgfile} mklabel sun mkpart 0 10M +list_parts part_sun ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,sun1 + +# 2 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel sun mkpart 0 10M mkpart 10M 20M +list_parts part_sun ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,sun1 hd0,sun2 + +# 3 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel sun mkpart 0 10M mkpart 10M 20M mkpart 20M 30M +list_parts part_sun ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,sun1 hd0,sun2 hd0,sun4 + +# 4 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel sun mkpart 0 10M mkpart 10M 20M mkpart 20M 30M mkpart 30M 40M +list_parts part_sun ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,sun1 hd0,sun2 hd0,sun4 hd0,sun5 + +# 5 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel sun mkpart 0 10M mkpart 10M 20M mkpart 20M 30M mkpart 30M 40M mkpart 40M 50M +list_parts part_sun ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,sun1 hd0,sun2 hd0,sun4 hd0,sun5 hd0,sun6 + +# 6 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel sun mkpart 0 10M mkpart 10M 20M mkpart 20M 30M mkpart 30M 40M mkpart 40M 50M mkpart 50M 60M +list_parts part_sun ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,sun1 hd0,sun2 hd0,sun4 hd0,sun5 hd0,sun6 hd0,sun7 + + +# +# Apple partition types +# +# Partition table itself is part of some partition, so there is always +# a partition by default. But I don't understand why GRUB displays +# two partitions by default :-( +# + +echo "Checking APPLE partition types..." + +# 0 parts +create_disk_image ${imgfile} 64M +${parted} -a none -s ${imgfile} mklabel mac +list_parts part_apple ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,apple1 hd0,apple2 + +# 1 parts +create_disk_image ${imgfile} 64M +${parted} -a none -s ${imgfile} mklabel mac mkpart a 1M 10M +list_parts part_apple ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,apple1 hd0,apple2 hd0,apple3 + +# 2 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel mac mkpart a 1M 10M mkpart b 10M 20M +list_parts part_apple ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,apple1 hd0,apple2 hd0,apple3 hd0,apple4 + +# 3 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel mac mkpart a 1M 10M mkpart b 10M 20M mkpart c 20M 30M +list_parts part_apple ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,apple1 hd0,apple2 hd0,apple4 hd0,apple5 + +# 4 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel mac mkpart a 1M 10M mkpart b 10M 20M mkpart c 20M 30M mkpart d 30M 40M +list_parts part_apple ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,apple1 hd0,apple2 hd0,apple4 hd0,apple5 hd0,apple6 + +# 5 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel mac mkpart a 1M 10M mkpart b 10M 20M mkpart c 20M 30M mkpart d 30M 40M mkpart e 40M 50M +list_parts part_apple ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,apple1 hd0,apple2 hd0,apple4 hd0,apple5 hd0,apple6 hd0,apple7 + +# 6 parts +create_disk_image ${imgfile} 128M +${parted} -a none -s ${imgfile} mklabel mac mkpart a 1M 10M mkpart b 10M 20M mkpart c 20M 30M mkpart d 30M 40M mkpart e 40M 50M mkpart f 50M 60M +list_parts part_apple ${imgfile} ${outfile} +check_output ${outfile} hd0 hd0,apple1 hd0,apple2 hd0,apple4 hd0,apple5 hd0,apple6 hd0,apple7 hd0,apple8 From b6a690eeb8567f4841e3518a41932086d556fc43 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Thu, 9 Sep 2010 17:17:45 +0100 Subject: [PATCH 115/214] * Makefile.util.def (libgrub.a): Move grub-core/kern/emu/hostfs.c and grub-core/disk/host.c to ... (grub-fstest): ... here. Having the host disk implementation present confuses grub-probe and other utility programs. * util/grub-mkconfig.in: Only verify readability of grub.cfg.new when writing to a file, not when writing to stdout. --- ChangeLog | 10 ++++++++++ Makefile.util.def | 4 ++-- util/grub-mkconfig.in | 8 +++++--- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index cd53ca445..a51619eef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2010-09-09 Colin Watson + + * Makefile.util.def (libgrub.a): Move grub-core/kern/emu/hostfs.c + and grub-core/disk/host.c to ... + (grub-fstest): ... here. Having the host disk implementation + present confuses grub-probe and other utility programs. + + * util/grub-mkconfig.in: Only verify readability of grub.cfg.new + when writing to a file, not when writing to stdout. + 2010-09-09 BVK Chaitanya * tests/partmap_test.in: New test for partitions. diff --git a/Makefile.util.def b/Makefile.util.def index b9901ad66..5ef33c5db 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -23,7 +23,6 @@ library = { common = grub-core/kern/misc.c; common = grub-core/kern/emu/mm.c; common = grub-core/kern/emu/misc.c; - common = grub-core/kern/emu/hostfs.c; common = grub-core/kern/emu/getroot.c; common = grub-core/kern/emu/hostdisk.c; @@ -31,7 +30,6 @@ library = { common = grub-core/commands/extcmd.c; common = grub-core/commands/ls.c; common = grub-core/disk/dmraid_nvidia.c; - common = grub-core/disk/host.c; common = grub-core/disk/loopback.c; common = grub-core/disk/lvm.c; common = grub-core/disk/mdraid_linux.c; @@ -182,6 +180,8 @@ program = { name = grub-fstest; mansection = 1; common = util/grub-fstest.c; + common = grub-core/kern/emu/hostfs.c; + common = grub-core/disk/host.c; ldadd = libgrub.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER)'; diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in index f0f134b3d..fa84c63d1 100644 --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in @@ -304,9 +304,11 @@ for i in ${grub_mkconfig_dir}/* ; do done # Verify readability of ${grub_cfg}.new -if is_path_readable_by_grub ${grub_cfg}.new ; then : ; else - echo "GRUB is unable to read ${grubdir}/${file}" >&2 - exit 1 +if test "x${grub_cfg}" != "x"; then + if is_path_readable_by_grub ${grub_cfg}.new ; then : ; else + echo "GRUB is unable to read ${grubdir}/${file}" >&2 + exit 1 + fi fi if test "x${grub_cfg}" != "x" ; then From 66d4bea5ccec6a33eea9e9d95af597a8b6499401 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Fri, 10 Sep 2010 13:35:23 +0200 Subject: [PATCH 116/214] 2010-09-10 Robert Millan * util/grub.d/10_kfreebsd.in: Fix ${kfreebsd_device} initialization on ZFS. Now non-main filesystems are supported as / too. --- ChangeLog | 5 +++++ util/grub.d/10_kfreebsd.in | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index a51619eef..fb6b19bef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2010-09-10 Robert Millan + + * util/grub.d/10_kfreebsd.in: Fix ${kfreebsd_device} initialization + on ZFS. Now non-main filesystems are supported as / too. + 2010-09-09 Colin Watson * Makefile.util.def (libgrub.a): Move grub-core/kern/emu/hostfs.c diff --git a/util/grub.d/10_kfreebsd.in b/util/grub.d/10_kfreebsd.in index 40ac240c7..e39423999 100644 --- a/util/grub.d/10_kfreebsd.in +++ b/util/grub.d/10_kfreebsd.in @@ -138,7 +138,12 @@ while [ "x$list" != "x" ] ; do esac case ${GRUB_FS} in - zfs) kfreebsd_device=$(grub-probe -t fs_label --device ${GRUB_DEVICE}) ;; + zfs) + # zpool name + kfreebsd_device=$(grub-probe -t fs_label --device ${GRUB_DEVICE}) + # filesystem name (empty string for the main filesystem) + kfreebsd_device="${kfreebsd_device}$(grub-mkrelpath / | sed -e "s,/*@$,,")" + ;; *) kfreebsd_device=${GRUB_DEVICE} ;; esac From fb90b54648993ce72f91d7557f0c4e4f6b635511 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Fri, 10 Sep 2010 14:02:54 +0200 Subject: [PATCH 117/214] 2010-09-10 Robert Millan * configure.ac: Check for `struct statfs.f_fstypename' and `struct statfs.f_mntfromname'. * grub-core/kern/emu/misc.c (grub_find_zpool_from_dir): Conditionalize kFreeBSD-specific code. --- ChangeLog | 8 ++++++++ configure.ac | 8 ++++++++ grub-core/kern/emu/misc.c | 20 ++++++++++++++------ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index fb6b19bef..f2b1e9dcd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2010-09-10 Robert Millan + + * configure.ac: Check for `struct statfs.f_fstypename' and + `struct statfs.f_mntfromname'. + + * grub-core/kern/emu/misc.c (grub_find_zpool_from_dir): Conditionalize + kFreeBSD-specific code. + 2010-09-10 Robert Millan * util/grub.d/10_kfreebsd.in: Fix ${kfreebsd_device} initialization diff --git a/configure.ac b/configure.ac index 57b9bb3ac..ec1ea8d88 100644 --- a/configure.ac +++ b/configure.ac @@ -280,6 +280,14 @@ fi AC_CHECK_FUNCS(posix_memalign memalign asprintf vasprintf) AC_CHECK_HEADERS(libzfs.h libnvpair.h sys/param.h sys/mount.h) +AC_CHECK_MEMBERS([struct statfs.f_fstypename],,,[$ac_includes_default +#include +#include ]) + +AC_CHECK_MEMBERS([struct statfs.f_mntfromname],,,[$ac_includes_default +#include +#include ]) + # For opendisk() and getrawpartition() on NetBSD. # Used in util/deviceiter.c and in util/hostdisk.c. AC_CHECK_HEADER([util.h], [ diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c index 82f579616..db89f0ece 100644 --- a/grub-core/kern/emu/misc.c +++ b/grub-core/kern/emu/misc.c @@ -282,18 +282,26 @@ grub_get_libzfs_handle (void) 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 defined(HAVE_STRUCT_STATFS_F_FSTYPENAME) && defined(HAVE_STRUCT_STATFS_F_MNTFROMNAME) + /* FreeBSD and GNU/kFreeBSD. */ + { + struct statfs mnt; - if (strcmp (mnt.f_fstypename, "zfs") != 0) - return; + if (statfs (dir, &mnt) != 0) + return; - *poolname = xstrdup (mnt.f_mntfromname); + if (strcmp (mnt.f_fstypename, "zfs") != 0) + return; + + *poolname = xstrdup (mnt.f_mntfromname); + } +#else + return; +#endif slash = strchr (*poolname, '/'); if (slash) From 905f7773e596bf110ec8f3dd81e9436289d08b2a Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 10 Sep 2010 13:20:21 +0100 Subject: [PATCH 118/214] grub-fstest needs the host and hostfs modules while other utilities actively require those modules to be absent, so grub-fstest needs its own initialisation and finalisation code. * Makefile.am (grub_fstest.pp): New target. (grub_fstest_init.lst): Likewise. (grub_fstest_init.c): Likewise. * Makefile.util.def (grub-fstest): Add grub_fstest_init.c. --- ChangeLog | 11 +++++++++++ Makefile.am | 14 ++++++++++++++ Makefile.util.def | 1 + 3 files changed, 26 insertions(+) diff --git a/ChangeLog b/ChangeLog index f2b1e9dcd..c5d0760a6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2010-09-10 Colin Watson + + grub-fstest needs the host and hostfs modules while other utilities + actively require those modules to be absent, so grub-fstest needs + its own initialisation and finalisation code. + + * Makefile.am (grub_fstest.pp): New target. + (grub_fstest_init.lst): Likewise. + (grub_fstest_init.c): Likewise. + * Makefile.util.def (grub-fstest): Add grub_fstest_init.c. + 2010-09-10 Robert Millan * configure.ac: Check for `struct statfs.f_fstypename' and diff --git a/Makefile.am b/Makefile.am index 1cf2297bd..e0f2f013f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -44,6 +44,20 @@ libgrub_a_init.c: libgrub_a_init.lst $(top_srcdir)/geninit.sh sh $(top_srcdir)/geninit.sh `cat $<` > $@ || (rm -f $@; exit 1) CLEANFILES += libgrub_a_init.c +# For grub-fstest +grub_fstest.pp: $(grub_fstest_SOURCES) + $(CPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(grub_fstest_CPPFLAGS) $(CPPFLAGS) \ + -D'GRUB_MOD_INIT(x)=@MARKER@x@' $^ > $@ || (rm -f $@; exit 1) +CLEANFILES += grub_fstest.pp + +grub_fstest_init.lst: libgrub.pp grub_fstest.pp + cat $^ | grep '@MARKER@' | sed 's/@MARKER@\(.*\)@/\1/g' | sort -u > $@ || (rm -f $@; exit 1) +CLEANFILES += grub_fstest_init.lst + +grub_fstest_init.c: grub_fstest_init.lst $(top_srcdir)/geninit.sh + sh $(top_srcdir)/geninit.sh `cat $<` > $@ || (rm -f $@; exit 1) +CLEANFILES += grub_fstest_init.c + if COND_GRUB_MKFONT if COND_HAVE_FONT_SOURCE grubdata_DATA = unicode.pf2 ascii.pf2 ascii.h widthspec.h diff --git a/Makefile.util.def b/Makefile.util.def index 5ef33c5db..5d4724b8f 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -179,6 +179,7 @@ program = { program = { name = grub-fstest; mansection = 1; + common_nodist = grub_fstest_init.c; common = util/grub-fstest.c; common = grub-core/kern/emu/hostfs.c; common = grub-core/disk/host.c; From c38fe9f48e9b9fadf390ce310821f16bc9944a6c Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Fri, 10 Sep 2010 14:32:28 +0200 Subject: [PATCH 119/214] 2010-09-10 Robert Millan Solaris support in grub_find_zpool_from_dir(). Thanks Seth Goldberg for referring to getextmntent() facility. * configure.ac: Check for getextmntent(), `sys/mnttab.h' and `sys/mkdev.h'. * grub-core/kern/emu/misc.c [HAVE_SYS_MNTTAB_H]: Include `'. [HAVE_SYS_MKDEV_H]: Include `'. [HAVE_GETEXTMNTENT] (grub_find_zpool_from_dir): Add getextmntent() method for finding zpool name. --- ChangeLog | 13 +++++++++++++ configure.ac | 4 ++-- grub-core/kern/emu/misc.c | 39 +++++++++++++++++++++++++++++++++++++-- 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index c5d0760a6..1abd19556 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2010-09-10 Robert Millan + + Solaris support in grub_find_zpool_from_dir(). Thanks + Seth Goldberg for referring to getextmntent() facility. + + * configure.ac: Check for getextmntent(), `sys/mnttab.h' and + `sys/mkdev.h'. + * grub-core/kern/emu/misc.c [HAVE_SYS_MNTTAB_H]: Include + `'. + [HAVE_SYS_MKDEV_H]: Include `'. + [HAVE_GETEXTMNTENT] (grub_find_zpool_from_dir): Add getextmntent() + method for finding zpool name. + 2010-09-10 Colin Watson grub-fstest needs the host and hostfs modules while other utilities diff --git a/configure.ac b/configure.ac index ec1ea8d88..d50dfe6dd 100644 --- a/configure.ac +++ b/configure.ac @@ -277,8 +277,8 @@ else fi # Check for functions and headers. -AC_CHECK_FUNCS(posix_memalign memalign asprintf vasprintf) -AC_CHECK_HEADERS(libzfs.h libnvpair.h sys/param.h sys/mount.h) +AC_CHECK_FUNCS(posix_memalign memalign asprintf vasprintf getextmntent) +AC_CHECK_HEADERS(libzfs.h libnvpair.h sys/param.h sys/mount.h sys/mnttab.h sys/mkdev.h) AC_CHECK_MEMBERS([struct statfs.f_fstypename],,,[$ac_includes_default #include diff --git a/grub-core/kern/emu/misc.c b/grub-core/kern/emu/misc.c index db89f0ece..c710777ea 100644 --- a/grub-core/kern/emu/misc.c +++ b/grub-core/kern/emu/misc.c @@ -61,6 +61,15 @@ # include #endif +#ifdef HAVE_SYS_MNTTAB_H +# include /* Needed by sys/mnttab.h. */ +# include +#endif + +#ifdef HAVE_SYS_MKDEV_H +# include /* makedev */ +#endif + int verbosity; void @@ -299,10 +308,36 @@ grub_find_zpool_from_dir (const char *dir, char **poolname, char **poolfs) *poolname = xstrdup (mnt.f_mntfromname); } -#else - return; +#elif defined(HAVE_GETEXTMNTENT) + /* Solaris. */ + { + struct stat st; + struct extmnttab mnt; + + if (stat (dir, &st) != 0) + return; + + FILE *mnttab = fopen ("/etc/mnttab", "r"); + if (! mnttab) + return; + + while (getextmntent (mnttab, &mnt, sizeof (mnt)) == 0) + { + if (makedev (mnt.mnt_major, mnt.mnt_minor) == st.st_dev + && !strcmp (mnt.mnt_fstype, "zfs")) + { + *poolname = xstrdup (mnt.mnt_special); + break; + } + } + + fclose (mnttab); + } #endif + if (! *poolname) + return; + slash = strchr (*poolname, '/'); if (slash) { From c452fa66dd9ebb75142dc4afed8371ca11511bd2 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 10 Sep 2010 13:47:16 +0100 Subject: [PATCH 120/214] * util/grub-install.in: ${imgext} won't be defined here until the install branch is merged. For the meantime, only verify core.img on i386-pc and sparc64-ieee1275 platforms. --- ChangeLog | 6 ++++++ util/grub-install.in | 9 ++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 1abd19556..3a7a75e20 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2010-09-10 Colin Watson + + * util/grub-install.in: ${imgext} won't be defined here until the + install branch is merged. For the meantime, only verify core.img on + i386-pc and sparc64-ieee1275 platforms. + 2010-09-10 Robert Millan Solaris support in grub_find_zpool_from_dir(). Thanks diff --git a/util/grub-install.in b/util/grub-install.in index 4de5dbc4a..c30f900db 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -402,7 +402,14 @@ case "${target_cpu}-${platform}" in esac # Verify readability of a few critical files -for file in grubenv core.${imgext} normal.mod ; do +# verify_files is a temporary workaround; drop this once the install branch +# is merged. +verify_files=grubenv +if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ]; then + verify_files="$verify_files core.img" +fi +verify_files="$verify_files normal.mod" +for file in $verify_files ; do if is_path_readable_by_grub ${grubdir}/${file} ${grub_device} ${relative_grubdir}/${file} ; then : ; else echo "GRUB is unable to read ${grubdir}/${file}" >&2 exit 1 From 90367e043da1a9328eaf1edecf2809db41c8ebc5 Mon Sep 17 00:00:00 2001 From: Robert Millan Date: Fri, 10 Sep 2010 15:11:54 +0200 Subject: [PATCH 121/214] 2010-09-10 Robert Millan * util/grub.d/10_hurd.in: Add misc readability checks. * util/grub.d/10_kfreebsd.in: Likewise. * util/grub.d/10_linux.in: Likewise. --- ChangeLog | 6 ++++++ util/grub.d/10_hurd.in | 8 ++++++++ util/grub.d/10_kfreebsd.in | 17 +++++++++++++++-- util/grub.d/10_linux.in | 9 +++++++++ 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3a7a75e20..9f6c66e81 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2010-09-10 Robert Millan + + * util/grub.d/10_hurd.in: Add misc readability checks. + * util/grub.d/10_kfreebsd.in: Likewise. + * util/grub.d/10_linux.in: Likewise. + 2010-09-10 Colin Watson * util/grub-install.in: ${imgext} won't be defined here until the diff --git a/util/grub.d/10_hurd.in b/util/grub.d/10_hurd.in index 350eb30a8..d8cc7aea4 100644 --- a/util/grub.d/10_hurd.in +++ b/util/grub.d/10_hurd.in @@ -41,6 +41,14 @@ for i in /boot/gnumach* ; do basename=`basename $i` dirname=`dirname $i` rel_dirname=`make_system_path_relative_to_its_root $dirname` + + if ! is_path_readable_by_grub ${dirname}/${basename} \ + ${GRUB_DEVICE_BOOT} \ + ${rel_dirname}/${basename} ; then + echo "${dirname}/${basename} is not readable by GRUB" >&2 + exit 1 + fi + echo "Found GNU Mach: $i" >&2 kernels="${kernels} ${rel_dirname}/${basename}" at_least_one=true diff --git a/util/grub.d/10_kfreebsd.in b/util/grub.d/10_kfreebsd.in index e39423999..bf1632bd6 100644 --- a/util/grub.d/10_kfreebsd.in +++ b/util/grub.d/10_kfreebsd.in @@ -44,7 +44,7 @@ load_kfreebsd_module () mod="$1" allow_fail="$2" - if ! test -e "${module_dir}/${mod}.ko" ; then + if ! is_path_readable_by_grub "${module_dir}/${mod}.ko" ; then if [ "${allow_fail}" = "true" ] ; then # Return silently return @@ -77,6 +77,13 @@ kfreebsd_entry () prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")" fi + if ! is_path_readable_by_grub ${dirname}/${basename} \ + ${GRUB_DEVICE_BOOT} \ + ${rel_dirname}/${basename} ; then + echo "${dirname}/${basename} is not readable by GRUB" >&2 + exit 1 + fi + printf '%s\n' "${prepare_boot_cache}" cat << EOF echo '$(printf "$(gettext_quoted "Loading kernel of FreeBSD %s ...")" ${version})' @@ -95,7 +102,13 @@ EOF zfs) load_kfreebsd_module opensolaris false - ls "${dirname}/zfs/zpool.cache" > /dev/null + if ! is_path_readable_by_grub ${dirname}/zfs/zpool.cache \ + ${GRUB_DEVICE_BOOT} \ + ${rel_dirname}/zfs/zpool.cache ; then + echo "${dirname}/zfs/zpool.cache is not readable by GRUB" >&2 + exit 1 + fi + printf '%s\n' "${prepare_boot_cache}" cat << EOF kfreebsd_module ${rel_dirname}/zfs/zpool.cache type=/boot/zfs/zpool.cache diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in index 14b85c7f1..765a7fab6 100644 --- a/util/grub.d/10_linux.in +++ b/util/grub.d/10_linux.in @@ -83,6 +83,15 @@ EOF EOF fi + for i in ${basename} ${initrd} ; do + if ! is_path_readable_by_grub ${dirname}/${i} \ + ${GRUB_DEVICE_BOOT} \ + ${rel_dirname}/${i} ; then + echo "${dirname}/${i} is not readable by GRUB" >&2 + exit 1 + fi + done + if [ -z "${prepare_boot_cache}" ]; then prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")" fi From 5ed7d816b406f191a8f787dbac888ab0d69729ca Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 10 Sep 2010 23:15:56 +0100 Subject: [PATCH 122/214] * util/grub-install.in: Don't try to verify core.img until after running grub-mkimage to create it. --- ChangeLog | 5 +++++ util/grub-install.in | 16 ++++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9f6c66e81..8b5a2b99c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2010-09-10 Colin Watson + + * util/grub-install.in: Don't try to verify core.img until after + running grub-mkimage to create it. + 2010-09-10 Robert Millan * util/grub.d/10_hurd.in: Add misc readability checks. diff --git a/util/grub-install.in b/util/grub-install.in index c30f900db..3ac7f677f 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -402,14 +402,7 @@ case "${target_cpu}-${platform}" in esac # Verify readability of a few critical files -# verify_files is a temporary workaround; drop this once the install branch -# is merged. -verify_files=grubenv -if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ]; then - verify_files="$verify_files core.img" -fi -verify_files="$verify_files normal.mod" -for file in $verify_files ; do +for file in grubenv normal.mod ; do if is_path_readable_by_grub ${grubdir}/${file} ${grub_device} ${relative_grubdir}/${file} ; then : ; else echo "GRUB is unable to read ${grubdir}/${file}" >&2 exit 1 @@ -419,6 +412,13 @@ done if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then $grub_mkimage ${config_opt} -O ${mkimage_target} --output=${grubdir}/core.img --prefix=${prefix_drive}${relative_grubdir} $modules || exit 1 + # This is a temporary workaround; it can be merged back into the check + # above once the install branch is merged. + if is_path_readable_by_grub ${grubdir}/core.img ${grub_device} ${relative_grubdir}/core.img ; then : ; else + echo "GRUB is unable to read ${grubdir}/core.img" >&2 + exit 1 + fi + # Now perform the installation. $grub_setup ${setup_verbose} ${setup_force} --directory=${grubdir} --device-map=${device_map} \ ${install_device} || exit 1 From 638f5f7ea1758160f4b79a0301d25b7c02c604c2 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Sep 2010 16:37:00 +0200 Subject: [PATCH 123/214] Implement --bootloader-id --- util/grub-install.in | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/util/grub-install.in b/util/grub-install.in index eb7ef48b6..5b49adcf8 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -61,6 +61,16 @@ efibootmgr=`which efibootmgr 2>/dev/null || true` removable=no efi_quiet= +# Get GRUB_DISTRIBUTOR. +if test -f ${sysconfdir}/default/grub ; then + . ${sysconfdir}/default/grub +fi + +bootloader_id="$(echo "$GRUB_DISTRIBUTOR" | tr '[A-Z]' '[a-z]' | cut -d' ' -f1)" +if test -z "$bootloader_id"; then + bootloader_id=grub +fi + if [ "${target_cpu}-${platform}" = "i386-pc" ] ; then disk_module=biosdisk elif [ "${platform}" = "ieee1275" ] || [ "${platform}" = "efi" ] ; then @@ -111,6 +121,7 @@ fi if [ "${platform}" = "efi" ]; then cat < Date: Sat, 11 Sep 2010 16:58:06 +0200 Subject: [PATCH 124/214] Fix emu on mipsel. * conf/Makefile.common (CFLAGS_PLATFORM): Add -mflush-func =grub_cpu_flush_cache on all mips and not only yeeloong. * configure.ac (COND_mips): New conditional. * grub-core/Makefile.am (KERNEL_HEADER_FILES): Add libgcc on all platforms. * grub-core/kern/emu/cache.S (__mips__): Use _flush_cache. * grub-core/kern/emu/full.c (grub_arch_dl_init_linker) [GRUB_LINKER_HAVE_INIT]: New function. (grub_emu_post_init): Likewise. * grub-core/kern/emu/lite.c (grub_emu_post_init): Likewise. * grub-core/kern/emu/main.c: Use grub_emu_post_init. * include/grub/cache.h (_mips): Include mips/cache.h. * include/grub/disk.h [GRUB_UTIL || GRUB_MACHINE_EMU]: Add missing LVM and RAID prototypes. * include/grub/emu/misc.h (grub_emu_post_init): New proto. * include/grub/mips/time.h (grub_cpu_idle) [GRUB_MACHINE_EMU]: New function. --- ChangeLog | 22 ++++++++++++++++++++++ conf/Makefile.common | 17 +++++++++++------ configure.ac | 1 + grub-core/Makefile.am | 4 +--- grub-core/kern/emu/cache.S | 15 ++++++++++++++- grub-core/kern/emu/full.c | 19 +++++++++++++++++++ grub-core/kern/emu/lite.c | 5 +++++ grub-core/kern/emu/main.c | 7 +------ include/grub/cache.h | 4 ++++ include/grub/disk.h | 9 +++++++++ include/grub/emu/misc.h | 1 + include/grub/mips/time.h | 6 ++++++ 12 files changed, 94 insertions(+), 16 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8b5a2b99c..e80ccad9e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2010-09-11 Vladimir Serbinenko + + Fix emu on mipsel. + + * conf/Makefile.common (CFLAGS_PLATFORM): Add -mflush-func + =grub_cpu_flush_cache on all mips and not only yeeloong. + * configure.ac (COND_mips): New conditional. + * grub-core/Makefile.am (KERNEL_HEADER_FILES): Add libgcc on all + platforms. + * grub-core/kern/emu/cache.S (__mips__): Use _flush_cache. + * grub-core/kern/emu/full.c (grub_arch_dl_init_linker) + [GRUB_LINKER_HAVE_INIT]: New function. + (grub_emu_post_init): Likewise. + * grub-core/kern/emu/lite.c (grub_emu_post_init): Likewise. + * grub-core/kern/emu/main.c: Use grub_emu_post_init. + * include/grub/cache.h (_mips): Include mips/cache.h. + * include/grub/disk.h [GRUB_UTIL || GRUB_MACHINE_EMU]: Add missing + LVM and RAID prototypes. + * include/grub/emu/misc.h (grub_emu_post_init): New proto. + * include/grub/mips/time.h (grub_cpu_idle) [GRUB_MACHINE_EMU]: New + function. + 2010-09-10 Colin Watson * util/grub-install.in: Don't try to verify core.img until after diff --git a/conf/Makefile.common b/conf/Makefile.common index fca0f67ae..afa57b986 100644 --- a/conf/Makefile.common +++ b/conf/Makefile.common @@ -1,8 +1,10 @@ # -*- makefile -*- +CFLAGS_PLATFORM= + # Platform specific options if COND_i386_pc - CFLAGS_PLATFORM = -mrtd -mregparm=3 + CFLAGS_PLATFORM += -mrtd -mregparm=3 endif if COND_i386_efi LDFLAGS_PLATFORM = -melf_i386 @@ -11,21 +13,24 @@ if COND_x86_64_efi LDFLAGS_PLATFORM = -melf_x86_64 endif if COND_i386_qemu - CFLAGS_PLATFORM = -mrtd -mregparm=3 + CFLAGS_PLATFORM += -mrtd -mregparm=3 endif if COND_i386_coreboot - CFLAGS_PLATFORM = -mrtd -mregparm=3 + CFLAGS_PLATFORM += -mrtd -mregparm=3 endif if COND_i386_ieee1275 - CFLAGS_PLATFORM = -mrtd -mregparm=3 + CFLAGS_PLATFORM += -mrtd -mregparm=3 endif if COND_mips_yeeloong - CFLAGS_PLATFORM = -march=mips3 -mexplicit-relocs -mflush-func=grub_cpu_flush_cache + CFLAGS_PLATFORM += -march=mips3 -mexplicit-relocs CPPFLAGS_PLATFORM = -DUSE_ASCII_FAILBACK CCASFLAGS_PLATFORM = -march=mips3 endif +if COND_mips + CFLAGS_PLATFORM += -mflush-func=grub_cpu_flush_cache +endif if COND_sparc64_ieee1275 - CFLAGS_PLATFORM = -mno-app-regs + CFLAGS_PLATFORM += -mno-app-regs LDFLAGS_PLATFORM = -melf64_sparc -mno-relax endif diff --git a/configure.ac b/configure.ac index d50dfe6dd..9578f6518 100644 --- a/configure.ac +++ b/configure.ac @@ -900,6 +900,7 @@ AM_CONDITIONAL([COND_mips_yeeloong], [test x$target_cpu = xmips -a x$platform = AM_CONDITIONAL([COND_mips_qemu_mips], [test x$target_cpu = xmips -a x$platform = xqemu_mips]) AM_CONDITIONAL([COND_sparc64_ieee1275], [test x$target_cpu = xsparc64 -a x$platform = xieee1275]) AM_CONDITIONAL([COND_powerpc_ieee1275], [test x$target_cpu = xpowerpc -a x$platform = xieee1275]) +AM_CONDITIONAL([COND_mips], [test x$target_cpu = xmips]) AM_CONDITIONAL([COND_HOST_HURD], [test x$host_kernel = xhurd]) AM_CONDITIONAL([COND_HOST_LINUX], [test x$host_kernel = xlinux]) diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index 5d13d0313..7fa00b744 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -74,6 +74,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/boot.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h if COND_i386_pc KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/memory.h @@ -132,7 +133,6 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/font.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bitmap_scale.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/bufio.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/pci.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/cs5536.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pci.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/serial.h @@ -140,11 +140,9 @@ endif if COND_powerpc_ieee1275 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h endif if COND_sparc64_ieee1275 -KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/ieee1275/ieee1275.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sparc64/ieee1275/ieee1275.h endif diff --git a/grub-core/kern/emu/cache.S b/grub-core/kern/emu/cache.S index 90a5b5396..abd81c910 100644 --- a/grub-core/kern/emu/cache.S +++ b/grub-core/kern/emu/cache.S @@ -7,7 +7,20 @@ #elif defined(__sparc__) #include "../sparc64/cache.S" #elif defined(__mips__) -#include "../mips/cache.S" +/* On MIPS we must go through standard functions. */ +#include + +FUNCTION (grub_cpu_flush_cache) +FUNCTION (grub_arch_sync_caches) + .set nomacro + .set noreorder + lui $t0, %hi(_flush_cache) + addui $t0, $t0, %lo(_flush_cache) + move $a3, $zero + jr $t0 + nop + .set reorder + .set macro #elif defined(__powerpc__) #include "../powerpc/cache.S" #else diff --git a/grub-core/kern/emu/full.c b/grub-core/kern/emu/full.c index 0bd33337f..a5801db2f 100644 --- a/grub-core/kern/emu/full.c +++ b/grub-core/kern/emu/full.c @@ -22,6 +22,7 @@ #include #include #include +#include void grub_register_exported_symbols (void) @@ -48,3 +49,21 @@ grub_emu_init (void) { grub_no_autoload = 1; } + +#ifdef GRUB_LINKER_HAVE_INIT +void +grub_arch_dl_init_linker (void) +{ +} +#endif + +void +grub_emu_post_init (void) +{ + grub_lvm_fini (); + grub_mdraid_fini (); + grub_raid_fini (); + grub_raid_init (); + grub_mdraid_init (); + grub_lvm_init (); +} diff --git a/grub-core/kern/emu/lite.c b/grub-core/kern/emu/lite.c index 9b3728717..32e12a079 100644 --- a/grub-core/kern/emu/lite.c +++ b/grub-core/kern/emu/lite.c @@ -38,3 +38,8 @@ grub_emu_init (void) { return; } + +void +grub_emu_post_init (void) +{ +} diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c index 8867f6101..23b8516f1 100644 --- a/grub-core/kern/emu/main.c +++ b/grub-core/kern/emu/main.c @@ -197,12 +197,7 @@ main (int argc, char *argv[]) grub_init_all (); - grub_lvm_fini (); - grub_mdraid_fini (); - grub_raid_fini (); - grub_raid_init (); - grub_mdraid_init (); - grub_lvm_init (); + grub_emu_post_init (); /* Make sure that there is a root device. */ if (! root_dev) diff --git a/include/grub/cache.h b/include/grub/cache.h index 27e44f0a2..4f913f5c8 100644 --- a/include/grub/cache.h +++ b/include/grub/cache.h @@ -23,6 +23,10 @@ #include #include +#ifdef _mips +#include +#endif + #if defined (__i386__) || defined (__x86_64__) static inline void grub_arch_sync_caches (void *address __attribute__ ((unused)), diff --git a/include/grub/disk.h b/include/grub/disk.h index e7f807e0e..b41f89b38 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -177,4 +177,13 @@ struct grub_disk_ata_pass_through_parms extern grub_err_t (* EXPORT_VAR(grub_disk_ata_pass_through)) (grub_disk_t, struct grub_disk_ata_pass_through_parms *); +#if defined (GRUB_UTIL) || defined (GRUB_MACHINE_EMU) +void grub_lvm_init (void); +void grub_mdraid_init (void); +void grub_raid_init (void); +void grub_lvm_fini (void); +void grub_mdraid_fini (void); +void grub_raid_fini (void); +#endif + #endif /* ! GRUB_DISK_HEADER */ diff --git a/include/grub/emu/misc.h b/include/grub/emu/misc.h index e9038c916..972bc4efc 100644 --- a/include/grub/emu/misc.h +++ b/include/grub/emu/misc.h @@ -45,6 +45,7 @@ extern const char *program_name; void grub_emu_init (void); void grub_init_all (void); void grub_fini_all (void); +void grub_emu_post_init (void); void grub_find_zpool_from_dir (const char *dir, char **poolname, char **poolfs); diff --git a/include/grub/mips/time.h b/include/grub/mips/time.h index e69de29bb..b143a48e0 100644 --- a/include/grub/mips/time.h +++ b/include/grub/mips/time.h @@ -0,0 +1,6 @@ +#ifdef GRUB_MACHINE_EMU +static inline void +grub_cpu_idle(void) +{ +} +#endif From 25761e13eed9fa02ee56c088dbeffa450b6b4326 Mon Sep 17 00:00:00 2001 From: Vladimir Serbinenko Date: Sat, 11 Sep 2010 17:21:48 +0200 Subject: [PATCH 125/214] * util/grub-install.in (grub_partition): New variable. Set prefix_drive on EFI and PC to (,$grub_partition) as last resort. * util/i386/pc/grub-setup.c (setup): Don't touch prefix. Fixes a bug reported by Yves Blusseau. --- ChangeLog | 8 ++++++++ util/grub-install.in | 4 ++++ util/i386/pc/grub-setup.c | 19 ------------------- 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/ChangeLog b/ChangeLog index e80ccad9e..02cbb91cf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2010-09-11 Vladimir Serbinenko +2010-09-11 Colin Watson + + * util/grub-install.in (grub_partition): New variable. + Set prefix_drive on EFI and PC to (,$grub_partition) as last resort. + * util/i386/pc/grub-setup.c (setup): Don't touch prefix. + Fixes a bug reported by Yves Blusseau. + 2010-09-11 Vladimir Serbinenko Fix emu on mipsel. diff --git a/util/grub-install.in b/util/grub-install.in index 3ac7f677f..ef1778b2a 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -367,6 +367,7 @@ if [ "x${devabstraction_module}" = "x" ] ; then grub_drive="`$grub_probe --target=drive --device ${grub_device}`" || exit 1 # Strip partition number + grub_partition="`echo ${grub_drive} | sed -e 's/^[^,]*,//; s/)$//'`" grub_drive="`echo ${grub_drive} | sed -e s/,[a-z0-9,]*//g`" if [ "$disk_module" = ata ] ; then # generic method (used on coreboot and ata mod) @@ -389,6 +390,9 @@ if [ "x${devabstraction_module}" = "x" ] ; then echo 'set prefix=($root)'"${relative_grubdir}" >> ${grubdir}/load.cfg config_opt="-c ${grubdir}/load.cfg " modules="$modules search_fs_uuid" + elif [ "x$platform" = xefi ] || [ "x$platform" = xpc ]; then + # we need to hardcode the partition number in the core image's prefix. + prefix_drive="(,$grub_partition)" fi else prefix_drive=`$grub_probe --target=drive --device ${grub_device}` || exit 1 diff --git a/util/i386/pc/grub-setup.c b/util/i386/pc/grub-setup.c index ff5aeda40..987e2d05a 100644 --- a/util/i386/pc/grub-setup.c +++ b/util/i386/pc/grub-setup.c @@ -81,8 +81,6 @@ setup (const char *dir, struct grub_boot_blocklist *first_block, *block; grub_int32_t *install_dos_part, *install_bsd_part; grub_int32_t dos_part, bsd_part; - char *install_prefix; - char *prefix = NULL; char *tmp_img; int i; grub_disk_addr_t first_sector; @@ -214,8 +212,6 @@ setup (const char *dir, + GRUB_KERNEL_MACHINE_INSTALL_DOS_PART); install_bsd_part = (grub_int32_t *) (core_img + GRUB_DISK_SECTOR_SIZE + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART); - install_prefix = (char *) (core_img + GRUB_DISK_SECTOR_SIZE + - GRUB_KERNEL_MACHINE_PREFIX); /* Open the root device and the destination device. */ root_dev = grub_device_open (root); @@ -291,16 +287,6 @@ setup (const char *dir, dos_part = root_dev->disk->partition->number; bsd_part = -1; } - - if (install_prefix[0] != '(') - { - char *root_part_name; - - root_part_name = - grub_partition_get_name (root_dev->disk->partition); - prefix = xasprintf ("(,%s)%s", root_part_name, install_prefix); - free (root_part_name); - } } else dos_part = bsd_part = -1; @@ -389,8 +375,6 @@ setup (const char *dir, *install_dos_part = grub_cpu_to_le32 (dos_part); *install_bsd_part = grub_cpu_to_le32 (bsd_part); - if (prefix) - strcpy (install_prefix, prefix); /* The first blocklist contains the whole sectors. */ first_block->start = grub_cpu_to_le64 (embed_region.start + 1); @@ -553,8 +537,6 @@ unable_to_embed: *install_dos_part = grub_cpu_to_le32 (dos_part); *install_bsd_part = grub_cpu_to_le32 (bsd_part); - if (prefix) - strcpy (install_prefix, prefix); /* Write the first two sectors of the core image onto the disk. */ grub_util_info ("opening the core image `%s'", core_path); @@ -574,7 +556,6 @@ unable_to_embed: /* Sync is a Good Thing. */ sync (); - free (prefix); free (core_path); free (core_img); free (boot_img); From 1aa4fe882236d4f14a38dd00c514365b70e3363c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Sep 2010 17:41:56 +0200 Subject: [PATCH 126/214] Implement loading palette on ieee1275_fb. * grub-core/video/ieee1275.c (stdout_ihandle): New variable. (have_setcolors): Likewise. (grub_video_ieee1275_init): Fill stdout_ihandle and have_setcolors. (grub_video_ieee1275_setup): Use grub_video_ieee1275_set_palette. (grub_video_ieee1275_set_palette): Implement. --- ChangeLog | 10 ++++++++++ grub-core/video/ieee1275.c | 38 +++++++++++++++++++++++++------------- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 02cbb91cf..57b11981f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2010-09-11 Vladimir Serbinenko + + Implement loading palette on ieee1275_fb. + + * grub-core/video/ieee1275.c (stdout_ihandle): New variable. + (have_setcolors): Likewise. + (grub_video_ieee1275_init): Fill stdout_ihandle and have_setcolors. + (grub_video_ieee1275_setup): Use grub_video_ieee1275_set_palette. + (grub_video_ieee1275_set_palette): Implement. + 2010-09-11 Vladimir Serbinenko 2010-09-11 Colin Watson diff --git a/grub-core/video/ieee1275.c b/grub-core/video/ieee1275.c index 9c9477c2b..501ba7c2f 100644 --- a/grub-core/video/ieee1275.c +++ b/grub-core/video/ieee1275.c @@ -32,6 +32,8 @@ static unsigned old_width, old_height; static int restore_needed; static char *display; +static grub_ieee1275_ihandle_t stdout_ihandle; +static int have_setcolors = 0; static struct { @@ -72,7 +74,17 @@ find_display (void) static grub_err_t grub_video_ieee1275_init (void) { + grub_ssize_t actual; + grub_memset (&framebuffer, 0, sizeof(framebuffer)); + + if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_CANNOT_SET_COLORS) + && !grub_ieee1275_get_integer_property (grub_ieee1275_chosen, + "stdout", &stdout_ihandle, + sizeof (stdout_ihandle), &actual) + && actual == sizeof (stdout_ihandle)) + have_setcolors = 1; + return grub_video_fb_init (); } @@ -169,9 +181,6 @@ grub_video_ieee1275_setup (unsigned int width, unsigned int height, /* For some reason sparc64 uses 32-bit pointer too. */ framebuffer.ptr = (void *) (grub_addr_t) address; - grub_video_ieee1275_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, - grub_video_fbstd_colors); - grub_dprintf ("video", "IEEE1275: initialising FB @ %p %dx%dx%d\n", framebuffer.ptr, framebuffer.mode_info.width, framebuffer.mode_info.height, framebuffer.mode_info.bpp); @@ -192,15 +201,10 @@ grub_video_ieee1275_setup (unsigned int width, unsigned int height, grub_dprintf ("video", "IEEE1275: Couldn't set FB target\n"); return err; } - - err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, - grub_video_fbstd_colors); - if (err) - grub_dprintf ("video", "IEEE1275: Couldn't set palette\n"); - else - grub_dprintf ("video", "IEEE1275: Success\n"); - + grub_video_ieee1275_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, + grub_video_fbstd_colors); + return err; } @@ -243,9 +247,17 @@ grub_video_ieee1275_set_palette (unsigned int start, unsigned int count, if (err) return err; - grub_video_fb_get_palette (0, 256, fb_palette_data); + grub_video_fb_get_palette (0, ARRAY_SIZE (fb_palette_data), fb_palette_data); - /* TODO. */ + /* Set colors. */ + if (have_setcolors) + { + unsigned col; + for (col = 0; col < ARRAY_SIZE (fb_palette_data); col++) + grub_ieee1275_set_color (stdout_ihandle, col, fb_palette_data[col].r, + fb_palette_data[col].g, + fb_palette_data[col].b); + } return GRUB_ERR_NONE; } From 3c70f225b2d7d4da2c1333c582a54fcb253ff359 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Sat, 11 Sep 2010 20:08:37 +0200 Subject: [PATCH 127/214] * grub-core/commands/lsacpi.c (grub_cmd_lsacpi): Fix prototype. --- ChangeLog | 4 ++++ grub-core/commands/lsacpi.c | 7 ++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index b2164f905..330656cc3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2010-09-11 Szymon Janc + + * grub-core/commands/lsacpi.c (grub_cmd_lsacpi): Fix prototype. + 2010-09-11 Vladimir Serbinenko Shutdown using ACPI. diff --git a/grub-core/commands/lsacpi.c b/grub-core/commands/lsacpi.c index d20b80fed..149de6b79 100644 --- a/grub-core/commands/lsacpi.c +++ b/grub-core/commands/lsacpi.c @@ -196,10 +196,11 @@ static const struct grub_arg_option options[] = { }; static grub_err_t -grub_cmd_lsacpi (struct grub_extcmd *cmd, int argc __attribute__ ((unused)), +grub_cmd_lsacpi (struct grub_extcmd_context *ctxt, + int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) { - if (!cmd->state[1].set) + if (!ctxt->state[1].set) { struct grub_acpi_rsdp_v10 *rsdp1 = grub_acpi_get_rsdpv1 (); if (!rsdp1) @@ -212,7 +213,7 @@ grub_cmd_lsacpi (struct grub_extcmd *cmd, int argc __attribute__ ((unused)), } } - if (!cmd->state[0].set) + if (!ctxt->state[0].set) { struct grub_acpi_rsdp_v20 *rsdp2 = grub_acpi_get_rsdpv2 (); if (!rsdp2) From 09695ab80c5f602c15c1897a9497870307f19362 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Sep 2010 22:18:06 +0200 Subject: [PATCH 128/214] Fix few compile errors --- docs/man/grub-menulst2cfg.h2m | 3 +++ util/grub-menulst2cfg.c | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 docs/man/grub-menulst2cfg.h2m diff --git a/docs/man/grub-menulst2cfg.h2m b/docs/man/grub-menulst2cfg.h2m new file mode 100644 index 000000000..0c0570f27 --- /dev/null +++ b/docs/man/grub-menulst2cfg.h2m @@ -0,0 +1,3 @@ +[NAME] +grub-menulst2cfg \- transform legacy menu.lst into grub.cfg + diff --git a/util/grub-menulst2cfg.c b/util/grub-menulst2cfg.c index fdbdda388..89b792e9a 100644 --- a/util/grub-menulst2cfg.c +++ b/util/grub-menulst2cfg.c @@ -31,7 +31,7 @@ main (int argc, char **argv) if (argc >= 2 && argv[1][0] == '-') { - fprintf (stderr, "Usage: %s [INFILE [OUTFILE]]\n", argv[0]); + fprintf (stdout, "Usage: %s [INFILE [OUTFILE]]\n", argv[0]); return 0; } @@ -79,7 +79,7 @@ main (int argc, char **argv) fprintf (out, "}\n\n"); if (oldname != entryname) fprintf (out, "menuentry \'%s\' {\n", - grub_legacy_escape (entryname, grub_strlen (entryname))); + grub_legacy_escape (entryname, strlen (entryname))); } if (parsed) From 9fb175ed9a48102543867f8006842628cc41217c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Sep 2010 22:18:41 +0200 Subject: [PATCH 129/214] Implement multiboot filename duplication in legacy parser --- grub-core/commands/legacycfg.c | 17 ++++++++++++----- grub-core/lib/legacy_parse.c | 16 ++++++++++------ 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c index aca6d1e1f..100464e69 100644 --- a/grub-core/commands/legacycfg.c +++ b/grub-core/commands/legacycfg.c @@ -179,6 +179,8 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), int i; int no_mem_option = 0; struct grub_command *cmd; + char **cutargs; + int cutargc; for (i = 0; i < 2; i++) { /* FIXME: really support this. */ @@ -233,9 +235,14 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), } } - if (!argc) + if (argc < 2) return grub_error (GRUB_ERR_BAD_ARGUMENT, "filename required"); + cutargs = grub_malloc (sizeof (cutargsp[0]) * (argc - 1)); + cutargc = argc - 1; + grub_memcpy (cutargs + 1, args + 2, sizeof (cutargsp[0]) * (argc - 2)); + cutargs[0] = args[0]; + do { /* First try Linux. */ @@ -244,7 +251,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), cmd = grub_command_find ("linux16"); if (cmd) { - if (!(cmd->func) (cmd, argc, args)) + if (!(cmd->func) (cmd, cutargc, cutargs)) { kernel_type = LINUX; return GRUB_ERR_NONE; @@ -275,7 +282,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), cmd = grub_command_find ("kfreebsd"); if (cmd) { - if (!(cmd->func) (cmd, argc, args)) + if (!(cmd->func) (cmd, cutargc, cutargs)) { kernel_type = KFREEBSD; return GRUB_ERR_NONE; @@ -288,7 +295,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), cmd = grub_command_find ("knetbsd"); if (cmd) { - if (!(cmd->func) (cmd, argc, args)) + if (!(cmd->func) (cmd, cutargc, cutargs)) { kernel_type = KNETBSD; return GRUB_ERR_NONE; @@ -301,7 +308,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), cmd = grub_command_find ("kopenbsd"); if (cmd) { - if (!(cmd->func) (cmd, argc, args)) + if (!(cmd->func) (cmd, cutargc, cutargs)) { kernel_type = KOPENBSD; return GRUB_ERR_NONE; diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index f350aaf09..694de097b 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -33,6 +33,7 @@ struct legacy_command TYPE_NOAPM_OPTION, TYPE_TYPE_OR_NOMEM_OPTION, TYPE_FILE, + TYPE_FILE_NO_CONSUME, TYPE_PARTITION, TYPE_BOOL, TYPE_INT, @@ -113,7 +114,8 @@ struct legacy_command legacy_commands[] = /* ifconfig unsupported. */ /* impsprobe unsupported. */ /* FIXME: dublicate multiboot filename. */ - {"initrd", "legacy_initrd '%s' %s\n", 2, {TYPE_FILE, TYPE_REST_VERBATIM}, 0, + {"initrd", "legacy_initrd '%s' %s\n", 2, {TYPE_FILE_NO_CONSUME, + TYPE_REST_VERBATIM}, 0, "FILE [ARG ...]", "Load an initial ramdisk FILE for a Linux format boot image and set the" " appropriate parameters in the Linux setup area in memory."}, @@ -122,9 +124,9 @@ struct legacy_command legacy_commands[] = /* FIXME: really support --no-mem-option. */ /* FIXME: dublicate multiboot filename. */ {"kernel", "legacy_kernel %s %s '%s' %s\n", 4, {TYPE_TYPE_OR_NOMEM_OPTION, - TYPE_TYPE_OR_NOMEM_OPTION, - TYPE_FILE, - TYPE_REST_VERBATIM}, 0, + TYPE_TYPE_OR_NOMEM_OPTION, + TYPE_FILE_NO_CONSUME, + TYPE_REST_VERBATIM}, 0, "[--no-mem-option] [--type=TYPE] FILE [ARG ...]", "Attempt to load the primary boot image from FILE. The rest of the" " line is passed verbatim as the \"kernel command line\". Any modules" @@ -143,7 +145,8 @@ struct legacy_command legacy_commands[] = " when you chain-load some operating systems, such as DOS, if such an" " OS resides at a non-first drive."}, /* md5crypt unsupported. */ - {"module", "legacy_initrd '%s' %s\n", 1, {TYPE_FILE, TYPE_REST_VERBATIM}, 0, + {"module", "legacy_initrd '%s' %s\n", 1, {TYPE_FILE_NO_CONSUME, + TYPE_REST_VERBATIM}, 0, "FILE [ARG ...]", "Load a boot module FILE for a Multiboot format boot image (no" " interpretation of the file contents is made, so users of this" @@ -210,7 +213,6 @@ struct legacy_command legacy_commands[] = " compares them, to test the filesystem code. " " If this test succeeds, then a good next" " step is to try loading a kernel."}, - "Print the contents of the file FILE."}, /* testvbe unsupported. */ /* tftpserver unsupported. */ {"timeout", "set timeout=%s\n", 1, {TYPE_INT}, 0, "SEC", @@ -399,6 +401,8 @@ grub_legacy_parse (const char *buf, char **entryname) ptr++; switch (legacy_commands[cmdnum].argt[i]) { + case TYPE_FILE_NO_CONSUME: + hold_arg = 1; case TYPE_PARTITION: case TYPE_FILE: args[j++] = adjust_file (curarg, curarglen); From 8bc402fbda9048e0a5b2a8509a3427a8842d09c4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 11 Sep 2010 22:47:49 +0200 Subject: [PATCH 130/214] Remove obsolete FIXME comments --- grub-core/commands/legacycfg.c | 2 -- grub-core/lib/legacy_parse.c | 2 -- 2 files changed, 4 deletions(-) diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c index b0253e707..6c0caad98 100644 --- a/grub-core/commands/legacycfg.c +++ b/grub-core/commands/legacycfg.c @@ -261,7 +261,6 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), } /* Then multiboot. */ - /* FIXME: dublicate multiboot filename. */ if (kernel_type == GUESS_IT || kernel_type == MULTIBOOT) { cmd = grub_command_find ("multiboot"); @@ -339,7 +338,6 @@ grub_cmd_legacy_initrd (struct grub_command *mycmd __attribute__ ((unused)), } if (kernel_type == MULTIBOOT) { - /* FIXME: dublicate module filename. */ cmd = grub_command_find ("module"); if (!cmd) return grub_error (GRUB_ERR_BAD_ARGUMENT, "command module not found"); diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 832b6cd1a..585c91b22 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -113,7 +113,6 @@ struct legacy_command legacy_commands[] = " its partition type code."}, /* ifconfig unsupported. */ /* impsprobe unsupported. */ - /* FIXME: dublicate multiboot filename. */ {"initrd", "legacy_initrd '%s' %s\n", 2, {TYPE_FILE_NO_CONSUME, TYPE_REST_VERBATIM}, 0, "FILE [ARG ...]", @@ -122,7 +121,6 @@ struct legacy_command legacy_commands[] = /* install unsupported. */ /* ioprobe unsupported. */ /* FIXME: really support --no-mem-option. */ - /* FIXME: dublicate multiboot filename. */ {"kernel", "legacy_kernel %s %s '%s' %s\n", 4, {TYPE_TYPE_OR_NOMEM_OPTION, TYPE_TYPE_OR_NOMEM_OPTION, TYPE_FILE_NO_CONSUME, From a37376e72a3c2e4d449d308e38f571a84f732550 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Sep 2010 01:07:41 +0200 Subject: [PATCH 131/214] legacy_password implementation --- grub-core/commands/legacycfg.c | 193 ++++++++++++++++++++++++++++++++- grub-core/commands/password.c | 23 ++-- grub-core/lib/legacy_parse.c | 20 +++- include/grub/normal.h | 3 + 4 files changed, 226 insertions(+), 13 deletions(-) diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c index 6c0caad98..f8e91b876 100644 --- a/grub-core/commands/legacycfg.c +++ b/grub-core/commands/legacycfg.c @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2010 Free Software Foundation, Inc. + * Copyright (C) 2000, 2001, 2010 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,6 +28,8 @@ #include #include #include +#include +#include static grub_err_t legacy_file (const char *filename) @@ -351,7 +353,7 @@ grub_cmd_legacy_initrd (struct grub_command *mycmd __attribute__ ((unused)), static grub_err_t grub_cmd_legacy_color (struct grub_command *mycmd __attribute__ ((unused)), - int argc, char **args) + int argc, char **args) { if (argc < 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "color required"); @@ -382,8 +384,188 @@ grub_cmd_legacy_color (struct grub_command *mycmd __attribute__ ((unused)), return grub_errno; } +static grub_err_t +check_password_deny (const char *user __attribute__ ((unused)), + const char *entered __attribute__ ((unused)), + void *password __attribute__ ((unused))) +{ + return GRUB_ACCESS_DENIED; +} + +#define MD5_HASHLEN 16 + +struct legacy_md5_password +{ + grub_uint8_t *salt; + int saltlen; + grub_uint8_t hash[MD5_HASHLEN]; +}; + +static int +check_password_md5_real (const char *entered, + struct legacy_md5_password *pw) +{ + int enteredlen = grub_strlen (entered); + unsigned char alt_result[MD5_HASHLEN]; + unsigned char *digest; + grub_uint8_t ctx[GRUB_MD_MD5->contextsize]; + int i; + + GRUB_MD_MD5->init (ctx); + GRUB_MD_MD5->write (ctx, entered, enteredlen); + GRUB_MD_MD5->write (ctx, pw->salt + 3, pw->saltlen - 3); + GRUB_MD_MD5->write (ctx, entered, enteredlen); + digest = GRUB_MD_MD5->read (ctx); + GRUB_MD_MD5->final (ctx); + memcpy (alt_result, digest, MD5_HASHLEN); + + GRUB_MD_MD5->init (ctx); + GRUB_MD_MD5->write (ctx, entered, enteredlen); + GRUB_MD_MD5->write (ctx, pw->salt, pw->saltlen); /* include the $1$ header */ + for (i = enteredlen; i > 16; i -= 16) + GRUB_MD_MD5->write (ctx, alt_result, 16); + GRUB_MD_MD5->write (ctx, alt_result, i); + + for (i = enteredlen; i > 0; i >>= 1) + GRUB_MD_MD5->write (ctx, entered + ((i & 1) ? enteredlen : 0), 1); + digest = GRUB_MD_MD5->read (ctx); + GRUB_MD_MD5->final (ctx); + + for (i = 0; i < 1000; i++) + { + memcpy (alt_result, digest, 16); + + GRUB_MD_MD5->init (ctx); + if ((i & 1) != 0) + GRUB_MD_MD5->write (ctx, entered, enteredlen); + else + GRUB_MD_MD5->write (ctx, alt_result, 16); + + if (i % 3 != 0) + GRUB_MD_MD5->write (ctx, pw->salt + 3, pw->saltlen - 3); + + if (i % 7 != 0) + GRUB_MD_MD5->write (ctx, entered, enteredlen); + + if ((i & 1) != 0) + GRUB_MD_MD5->write (ctx, alt_result, 16); + else + GRUB_MD_MD5->write (ctx, entered, enteredlen); + digest = GRUB_MD_MD5->read (ctx); + GRUB_MD_MD5->final (ctx); + } + + return (grub_crypto_memcmp (digest, pw->hash, MD5_HASHLEN) == 0); +} + +static grub_err_t +check_password_md5 (const char *user, + const char *entered, + void *password) +{ + if (!check_password_md5_real (entered, password)) + return GRUB_ACCESS_DENIED; + + grub_auth_authenticate (user); + + return GRUB_ERR_NONE; +} + +static inline int +ib64t (char c) +{ + if (c == '.') + return 0; + if (c == '/') + return 1; + if (c >= '0' && c <= '9') + return c - '0' + 2; + if (c >= 'A' && c <= 'Z') + return c - 'A' + 12; + if (c >= 'a' && c <= 'z') + return c - 'a' + 38; + return -1; +} + +static grub_err_t +grub_cmd_legacy_password (struct grub_command *mycmd __attribute__ ((unused)), + int argc, char **args) +{ + const char *salt, *saltend; + const char *p; + struct legacy_md5_password *pw = NULL; + int i; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments expected"); + if (args[0][0] != '-' || args[0][1] != '-') + return grub_normal_set_password ("legacy", args[0]); + if (grub_memcmp (args[0], "--md5", sizeof ("--md5")) != 0) + goto fail; + if (argc == 1) + goto fail; + if (grub_strlen(args[1]) <= 3) + goto fail; + salt = args[1]; + saltend = grub_strchr (salt + 3, '$'); + if (!saltend) + goto fail; + pw = grub_malloc (sizeof (*pw)); + if (!pw) + goto fail; + + p = saltend + 1; + for (i = 0; i < 5; i++) + { + int n; + grub_uint32_t w = 0; + + for (n = 0; n < 4; n++) + { + int ww = ib64t(*p++); + if (ww == -1) + goto fail; + w |= ww << (n * 6); + } + pw->hash[i == 4 ? 5 : 12+i] = w & 0xff; + pw->hash[6+i] = (w >> 8) & 0xff; + pw->hash[i] = (w >> 16) & 0xff; + } + { + int n; + grub_uint32_t w = 0; + for (n = 0; n < 2; n++) + { + int ww = ib64t(*p++); + if (ww == -1) + goto fail; + w |= ww << (6 * n); + } + if (w >= 0x100) + goto fail; + pw->hash[11] = w; + } + + pw->saltlen = saltend - salt; + pw->salt = (grub_uint8_t *) grub_strndup (salt, pw->saltlen); + if (!pw->salt) + goto fail; + + return grub_auth_register_authentication ("legacy", check_password_md5, pw); + + fail: + grub_free (pw); + /* This is to imitate minor difference between grub-legacy in GRUB2. + If 2 password commands are executed in a row and second one fails + on GRUB2 the password of first one is used, whereas in grub-legacy + authenthication is denied. In case of no password command was executed + early both versions deny any access. */ + return grub_auth_register_authentication ("legacy", check_password_deny, + NULL); +} + static grub_command_t cmd_source, cmd_configfile, cmd_kernel, cmd_initrd; -static grub_command_t cmd_color; +static grub_command_t cmd_color, cmd_password; GRUB_MOD_INIT(legacycfg) { @@ -407,6 +589,10 @@ GRUB_MOD_INIT(legacycfg) grub_cmd_legacy_color, N_("NORMAL [HIGHLIGHT]"), N_("Simulate grub-legacy color command")); + cmd_password = grub_register_command ("legacy_password", + grub_cmd_legacy_password, + N_("[--md5] PASSWD [FILE]"), + N_("Simulate grub-legacy password command")); } GRUB_MOD_FINI(legacycfg) @@ -416,4 +602,5 @@ GRUB_MOD_FINI(legacycfg) grub_unregister_command (cmd_kernel); grub_unregister_command (cmd_initrd); grub_unregister_command (cmd_color); + grub_unregister_command (cmd_password); } diff --git a/grub-core/commands/password.c b/grub-core/commands/password.c index 04285254e..db5951cbb 100644 --- a/grub-core/commands/password.c +++ b/grub-core/commands/password.c @@ -40,26 +40,22 @@ check_password (const char *user, const char *entered, return GRUB_ERR_NONE; } -static grub_err_t -grub_cmd_password (grub_command_t cmd __attribute__ ((unused)), - int argc, char **args) +grub_err_t +grub_normal_set_password (const char *user, const char *password) { grub_err_t err; char *pass; int copylen; - if (argc != 2) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "two arguments expected"); - pass = grub_zalloc (GRUB_AUTH_MAX_PASSLEN); if (!pass) return grub_errno; - copylen = grub_strlen (args[1]); + copylen = grub_strlen (password); if (copylen >= GRUB_AUTH_MAX_PASSLEN) copylen = GRUB_AUTH_MAX_PASSLEN - 1; - grub_memcpy (pass, args[1], copylen); + grub_memcpy (pass, password, copylen); - err = grub_auth_register_authentication (args[0], check_password, pass); + err = grub_auth_register_authentication (user, check_password, pass); if (err) { grub_free (pass); @@ -69,6 +65,15 @@ grub_cmd_password (grub_command_t cmd __attribute__ ((unused)), return GRUB_ERR_NONE; } +static grub_err_t +grub_cmd_password (grub_command_t cmd __attribute__ ((unused)), + int argc, char **args) +{ + if (argc != 2) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "two arguments expected"); + return grub_normal_set_password (args[0], args[1]); +} + static grub_command_t cmd; GRUB_MOD_INIT(password) diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 585c91b22..34ebd19c5 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -32,6 +32,7 @@ struct legacy_command TYPE_FORCE_OPTION, TYPE_NOAPM_OPTION, TYPE_TYPE_OR_NOMEM_OPTION, + TYPE_OPTION, TYPE_FILE, TYPE_FILE_NO_CONSUME, TYPE_PARTITION, @@ -159,7 +160,21 @@ struct legacy_command legacy_commands[] = /* partnew unsupported. */ {"parttype", "parttool '%s' type=%s\n", 2, {TYPE_PARTITION, TYPE_INT}, 0, "PART TYPE", "Change the type of the partition PART to TYPE."}, - /* password unsupported. */ /* NUL_TERMINATE */ + /* FIXME: support config file reloading. */ + /* FIXME: support usage in menuentry. */ + {"password", "if [ \"$superusers\" = "" ]; then superusers=legacy; fi; " + "legacy_password %s '%s' %s", 3, {TYPE_OPTION, TYPE_VERBATIM, + TYPE_FILE}, FLAG_IGNORE_REST, + "[--md5] PASSWD [FILE]", + "If used in the first section of a menu file, disable all" + " interactive editing control (menu entry editor and" + " command line). If the password PASSWD is entered, it loads the" + " FILE as a new config file and restarts the GRUB Stage 2. If you" + " omit the argument FILE, then GRUB just unlocks privileged" + " instructions. You can also use it in the script section, in" + " which case it will ask for the password, before continuing." + " The option --md5 tells GRUB that PASSWD is encrypted with" + " md5crypt."}, /* pause unsupported. */ /* rarp unsupported. */ {"read", "read_dword %s\n", 1, {TYPE_INT}, 0, "ADDR", @@ -323,6 +338,8 @@ is_option (enum arg_type opt, const char *curarg, grub_size_t len) || check_option (curarg, "--type=biglinux", len) || check_option (curarg, "--type=multiboot", len) || check_option (curarg, "--no-mem-option", len); + case TYPE_OPTION: + return (len >= 2 && curarg[0] == '-' && curarg[1] == '-'); default: return 0; } @@ -453,6 +470,7 @@ grub_legacy_parse (const char *buf, char **entryname) case TYPE_FORCE_OPTION: case TYPE_NOAPM_OPTION: case TYPE_TYPE_OR_NOMEM_OPTION: + case TYPE_OPTION: if (is_option (legacy_commands[cmdnum].argt[i], curarg, curarglen)) { args[j++] = grub_strndup (curarg, curarglen); diff --git a/include/grub/normal.h b/include/grub/normal.h index df7f70142..417560d9f 100644 --- a/include/grub/normal.h +++ b/include/grub/normal.h @@ -120,4 +120,7 @@ grub_normal_add_menu_entry (int argc, const char **args, char **classes, const char *users, const char *hotkey, const char *prefix, const char *sourcecode); +grub_err_t +grub_normal_set_password (const char *user, const char *password); + #endif /* ! GRUB_NORMAL_HEADER */ From d2467d2361cef8465b4483d1756fb9831b0b12b4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Sep 2010 01:45:58 +0200 Subject: [PATCH 132/214] Add Hercules, Planar and YUV to videoinfo (not tested) --- grub-core/commands/videoinfo.c | 15 +++++++++++++- grub-core/video/i386/pc/vbe.c | 36 ++++++++++++++++++++++++++++++---- include/grub/video.h | 4 ++++ 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/grub-core/commands/videoinfo.c b/grub-core/commands/videoinfo.c index febb56aba..9ee3f1af5 100644 --- a/grub-core/commands/videoinfo.c +++ b/grub-core/commands/videoinfo.c @@ -34,6 +34,8 @@ hook (const struct grub_video_mode_info *info) grub_printf (" 0x%03x ", info->mode_number); grub_printf ("%4d x %4d x %2d ", info->width, info->height, info->bpp); + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PURE_TEXT) + grub_printf ("Text-only "); /* Show mask and position details for direct color modes. */ if (info->mode_type & GRUB_VIDEO_MODE_TYPE_RGB) grub_printf ("Direct, mask: %d/%d/%d/%d pos: %d/%d/%d/%d", @@ -46,7 +48,18 @@ hook (const struct grub_video_mode_info *info) info->blue_field_pos, info->reserved_field_pos); if (info->mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) - grub_printf ("Packed"); + grub_printf ("Packed "); + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_YUV) + grub_printf ("YUV "); + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_PLANAR) + grub_printf ("Planar "); + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_HERCULES) + grub_printf ("Hercules "); + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) + grub_printf ("Monochrome "); + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_UNKNOWN) + grub_printf ("Unknown "); + grub_printf ("\n"); return 0; diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c index 1d2a9ac76..be266d238 100644 --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -555,14 +555,39 @@ vbe2videoinfo (grub_uint32_t mode, mode_info->width = vbeinfo->x_resolution; mode_info->height = vbeinfo->y_resolution; + mode_info->mode_type = 0; switch (vbeinfo->memory_model) { - case GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL: - mode_info->mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; + case GRUB_VBE_MEMORY_MODEL_TEXT: + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_PURE_TEXT; break; - + + /* CGA is basically 4-bit packed pixel. */ + case GRUB_VBE_MEMORY_MODEL_CGA: + case GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL: + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; + break; + + case GRUB_VBE_MEMORY_MODEL_HERCULES: + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_HERCULES + | GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP; + break; + + /* Non chain 4 is a special case of planar. */ + case GRUB_VBE_MEMORY_MODEL_NONCHAIN4_256: + case GRUB_VBE_MEMORY_MODEL_PLANAR: + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_PLANAR; + break; + + case GRUB_VBE_MEMORY_MODEL_YUV: + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_YUV; + break; + case GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR: - mode_info->mode_type = GRUB_VIDEO_MODE_TYPE_RGB; + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_RGB; + break; + default: + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_UNKNOWN; break; } @@ -585,6 +610,9 @@ vbe2videoinfo (grub_uint32_t mode, case 8: mode_info->bytes_per_pixel = 1; break; + case 4: + mode_info->bytes_per_pixel = 0; + break; } if (controller_info.version >= 0x300) diff --git a/include/grub/video.h b/include/grub/video.h index 1c1bf16ab..6381efe64 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -38,6 +38,10 @@ struct grub_video_bitmap; /* If following is set render target contains currenly displayed image after swapping buffers (otherwise it contains previously displayed image). */ +#define GRUB_VIDEO_MODE_TYPE_YUV 0x00000800 +#define GRUB_VIDEO_MODE_TYPE_PLANAR 0x00000400 +#define GRUB_VIDEO_MODE_TYPE_HERCULES 0x00000200 +#define GRUB_VIDEO_MODE_TYPE_UNKNOWN 0x00000100 #define GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP 0x00000080 #define GRUB_VIDEO_MODE_TYPE_PURE_TEXT 0x00000040 #define GRUB_VIDEO_MODE_TYPE_ALPHA 0x00000020 From 4dd58a6edd36d933c690bcb6f538afb684de489b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Sep 2010 02:09:09 +0200 Subject: [PATCH 133/214] Change video_mode_type to an enum, fix collisions and add a bit more info --- grub-core/commands/videoinfo.c | 4 +++ grub-core/video/i386/pc/vbe.c | 5 +++- include/grub/video.h | 51 +++++++++++++++++++++------------- 3 files changed, 39 insertions(+), 21 deletions(-) diff --git a/grub-core/commands/videoinfo.c b/grub-core/commands/videoinfo.c index 9ee3f1af5..15f677e14 100644 --- a/grub-core/commands/videoinfo.c +++ b/grub-core/commands/videoinfo.c @@ -55,6 +55,10 @@ hook (const struct grub_video_mode_info *info) grub_printf ("Planar "); if (info->mode_type & GRUB_VIDEO_MODE_TYPE_HERCULES) grub_printf ("Hercules "); + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_CGA) + grub_printf ("CGA "); + if (info->mode_type & GRUB_VIDEO_MODE_TYPE_NONCHAIN4) + grub_printf ("Non-chain 4 "); if (info->mode_type & GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) grub_printf ("Monochrome "); if (info->mode_type & GRUB_VIDEO_MODE_TYPE_UNKNOWN) diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c index be266d238..4bb46e4cd 100644 --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -564,6 +564,7 @@ vbe2videoinfo (grub_uint32_t mode, /* CGA is basically 4-bit packed pixel. */ case GRUB_VBE_MEMORY_MODEL_CGA: + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_CGA; case GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL: mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; break; @@ -575,8 +576,10 @@ vbe2videoinfo (grub_uint32_t mode, /* Non chain 4 is a special case of planar. */ case GRUB_VBE_MEMORY_MODEL_NONCHAIN4_256: + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_NONCHAIN4; case GRUB_VBE_MEMORY_MODEL_PLANAR: - mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_PLANAR; + mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_PLANAR + | GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; break; case GRUB_VBE_MEMORY_MODEL_YUV: diff --git a/include/grub/video.h b/include/grub/video.h index 6381efe64..5350d87eb 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -38,24 +38,33 @@ struct grub_video_bitmap; /* If following is set render target contains currenly displayed image after swapping buffers (otherwise it contains previously displayed image). */ -#define GRUB_VIDEO_MODE_TYPE_YUV 0x00000800 -#define GRUB_VIDEO_MODE_TYPE_PLANAR 0x00000400 -#define GRUB_VIDEO_MODE_TYPE_HERCULES 0x00000200 -#define GRUB_VIDEO_MODE_TYPE_UNKNOWN 0x00000100 -#define GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP 0x00000080 -#define GRUB_VIDEO_MODE_TYPE_PURE_TEXT 0x00000040 -#define GRUB_VIDEO_MODE_TYPE_ALPHA 0x00000020 -#define GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED 0x00000010 -#define GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP 0x00000004 -#define GRUB_VIDEO_MODE_TYPE_INDEX_COLOR 0x00000002 -#define GRUB_VIDEO_MODE_TYPE_RGB 0x00000001 +typedef enum grub_video_mode_type + { + GRUB_VIDEO_MODE_TYPE_RGB = 0x00000001, + GRUB_VIDEO_MODE_TYPE_INDEX_COLOR = 0x00000002, + GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP = 0x00000004, + GRUB_VIDEO_MODE_TYPE_YUV = 0x00000008, -/* Defines used to mask flags. */ -#define GRUB_VIDEO_MODE_TYPE_COLOR_MASK 0x0000000F + /* Defines used to mask flags. */ + GRUB_VIDEO_MODE_TYPE_COLOR_MASK = 0x0000000F, -/* Defines used to specify requested bit depth. */ -#define GRUB_VIDEO_MODE_TYPE_DEPTH_MASK 0x0000ff00 -#define GRUB_VIDEO_MODE_TYPE_DEPTH_POS 8 + GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED = 0x00000010, + GRUB_VIDEO_MODE_TYPE_ALPHA = 0x00000020, + GRUB_VIDEO_MODE_TYPE_PURE_TEXT = 0x00000040, + GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP = 0x00000080, + GRUB_VIDEO_MODE_TYPE_OPERATIONAL_MASK = 0x000000F0, + + /* Defines used to specify requested bit depth. */ + GRUB_VIDEO_MODE_TYPE_DEPTH_MASK = 0x0000FF00, +#define GRUB_VIDEO_MODE_TYPE_DEPTH_POS 8 + + GRUB_VIDEO_MODE_TYPE_UNKNOWN = 0x00010000, + GRUB_VIDEO_MODE_TYPE_HERCULES = 0x00020000, + GRUB_VIDEO_MODE_TYPE_PLANAR = 0x00040000, + GRUB_VIDEO_MODE_TYPE_NONCHAIN4 = 0x00080000, + GRUB_VIDEO_MODE_TYPE_CGA = 0x00100000, + GRUB_VIDEO_MODE_TYPE_INFO_MASK = 0x00FF0000, + } grub_video_mode_type_t; /* The basic render target representing the whole display. This always renders to the back buffer when double-buffering is in use. */ @@ -107,7 +116,7 @@ struct grub_video_mode_info /* Mode type bitmask. Contains information like is it Index color or RGB mode. */ - unsigned int mode_type; + grub_video_mode_type_t mode_type; /* Bits per pixel. */ unsigned int bpp; @@ -232,7 +241,8 @@ struct grub_video_adapter grub_err_t (*fini) (void); grub_err_t (*setup) (unsigned int width, unsigned int height, - unsigned int mode_type, unsigned int mode_mask); + grub_video_mode_type_t mode_type, + grub_video_mode_type_t mode_mask); grub_err_t (*get_info) (struct grub_video_mode_info *mode_info); @@ -409,8 +419,9 @@ grub_err_t EXPORT_FUNC (grub_video_set_mode) (const char *modestring, unsigned int modevalue); static inline int -grub_video_check_mode_flag (unsigned int flags, unsigned int mask, - unsigned int flag, int def) +grub_video_check_mode_flag (grub_video_mode_type_t flags, + grub_video_mode_type_t mask, + grub_video_mode_type_t flag, int def) { return (flag & mask) ? !! (flags & flag) : def; } From b062152c2ae490fa41938b23cc288c1aff4da2a2 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Sep 2010 02:18:14 +0200 Subject: [PATCH 134/214] Allow specifying video mode --- grub-core/commands/videotest.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/grub-core/commands/videotest.c b/grub-core/commands/videotest.c index 22bd648d0..435ac2937 100644 --- a/grub-core/commands/videotest.c +++ b/grub-core/commands/videotest.c @@ -26,11 +26,11 @@ #include #include #include +#include static grub_err_t grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), - int argc __attribute__ ((unused)), - char **args __attribute__ ((unused))) + int argc, char **args) { grub_err_t err; grub_video_color_t color; @@ -41,13 +41,20 @@ grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)), int i; struct grub_video_render_target *text_layer; grub_video_color_t palette[16]; + const char *mode = NULL; #ifdef GRUB_MACHINE_PCBIOS if (grub_strcmp (cmd->name, "vbetest") == 0) grub_dl_load ("vbe"); #endif - err = grub_video_set_mode ("auto", GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0); + mode = grub_env_get ("gfxmode"); + if (argc) + mode = args[0]; + if (!mode) + mode = "auto"; + + err = grub_video_set_mode (mode, GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0); if (err) return err; @@ -192,7 +199,8 @@ static grub_command_t cmd_vbe; GRUB_MOD_INIT(videotest) { cmd = grub_register_command ("videotest", grub_cmd_videotest, - 0, N_("Test video subsystem.")); + "[WxH]", + N_("Test video subsystem in mode WxH.")); #ifdef GRUB_MACHINE_PCBIOS cmd_vbe = grub_register_command ("vbetest", grub_cmd_videotest, 0, N_("Test video subsystem.")); From 237a43b1c191211d4d64e749ba52c5ede622fce6 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Sep 2010 02:30:48 +0200 Subject: [PATCH 135/214] Support few more legacy commands --- grub-core/commands/legacycfg.c | 44 +++++++++++++++++++++++++- grub-core/lib/legacy_parse.c | 56 +++++++++++++++++++--------------- 2 files changed, 75 insertions(+), 25 deletions(-) diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c index f8e91b876..aeff78b8a 100644 --- a/grub-core/commands/legacycfg.c +++ b/grub-core/commands/legacycfg.c @@ -351,6 +351,42 @@ grub_cmd_legacy_initrd (struct grub_command *mycmd __attribute__ ((unused)), "no kernel with module support is loaded in legacy way"); } +static grub_err_t +grub_cmd_legacy_initrdnounzip (struct grub_command *mycmd __attribute__ ((unused)), + int argc, char **args) +{ + struct grub_command *cmd; + + if (kernel_type == LINUX) + { + cmd = grub_command_find ("initrd16"); + if (!cmd) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "command initrd16 not found"); + + return cmd->func (cmd, argc, args); + } + if (kernel_type == MULTIBOOT) + { + char **newargs; + grub_err_t err; + newargs = grub_malloc ((argc + 1) * sizeof (newargs[0])); + if (!newargs) + return grub_errno; + grub_memcpy (newargs + 1, args, argc * sizeof (newargs[0])); + newargs[0] = "--nounzip"; + cmd = grub_command_find ("module"); + if (!cmd) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "command module not found"); + + err = cmd->func (cmd, argc + 1, newargs); + grub_free (newargs); + return err; + } + + return grub_error (GRUB_ERR_BAD_ARGUMENT, + "no kernel with module support is loaded in legacy way"); +} + static grub_err_t grub_cmd_legacy_color (struct grub_command *mycmd __attribute__ ((unused)), int argc, char **args) @@ -565,7 +601,7 @@ grub_cmd_legacy_password (struct grub_command *mycmd __attribute__ ((unused)), } static grub_command_t cmd_source, cmd_configfile, cmd_kernel, cmd_initrd; -static grub_command_t cmd_color, cmd_password; +static grub_command_t cmd_color, cmd_password, cmd_initrdnounzip; GRUB_MOD_INIT(legacycfg) { @@ -581,6 +617,11 @@ GRUB_MOD_INIT(legacycfg) grub_cmd_legacy_initrd, N_("FILE [ARG ...]"), N_("Simulate grub-legacy initrd command")); + cmd_initrdnounzip = grub_register_command ("legacy_initrd_nounzip", + grub_cmd_legacy_initrdnounzip, + N_("FILE [ARG ...]"), + N_("Simulate grub-legacy modulenounzip command")); + cmd_configfile = grub_register_command ("legacy_configfile", grub_cmd_legacy_configfile, N_("FILE"), @@ -601,6 +642,7 @@ GRUB_MOD_FINI(legacycfg) grub_unregister_command (cmd_configfile); grub_unregister_command (cmd_kernel); grub_unregister_command (cmd_initrd); + grub_unregister_command (cmd_initrdnounzip); grub_unregister_command (cmd_color); grub_unregister_command (cmd_password); } diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 34ebd19c5..671d0f3f8 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -53,7 +53,7 @@ struct legacy_command legacy_commands[] = "Print the blocklist notation of the file FILE."}, {"boot", "boot\n", 0, {}, 0, 0, "Boot the OS/chain-loader which has been loaded."}, - /* bootp unsupported. */ + /* FIXME: bootp unsupported. */ {"cat", "cat '%s'\n", 1, {TYPE_FILE}, 0, "FILE", "Print the contents of the file FILE."}, {"chainloader", "chainloader %s '%s'\n", 2, {TYPE_FORCE_OPTION, TYPE_FILE}, @@ -87,8 +87,8 @@ struct legacy_command legacy_commands[] = "[NUM | `saved']", "Set the default entry to entry number NUM (if not specified, it is" " 0, the first entry) or the entry number saved by savedefault."}, - /* dhcp unsupported. */ - /* displayapm unsupported. */ + /* FIXME: dhcp unsupported. */ + /* FIXME: displayapm unsupported. */ {"displaymem", "lsmmap\n", 0, {}, 0, 0, "Display what GRUB thinks the system address space map of the" " machine is, including all regions of physical RAM installed."}, @@ -102,25 +102,25 @@ struct legacy_command legacy_commands[] = {"find", "search -sf '%s'\n", 1, {TYPE_FILE}, 0, "FILENAME", "Search for the filename FILENAME in all of partitions and print the list of" " the devices which contain the file."}, - /* fstest unsupported. */ - /* geometry unsupported. */ + /* FIXME: fstest unsupported. */ + /* FIXME: geometry unsupported. */ {"halt", "halt %s\n", 1, {TYPE_NOAPM_OPTION}, 0, "[--no-apm]", "Halt your system. If APM is available on it, turn off the power using" " the APM BIOS, unless you specify the option `--no-apm'."}, - /* help unsupported. */ /* NUL_TERMINATE */ - /* hiddenmenu unsupported. */ + /* FIXME: help unsupported. */ /* NUL_TERMINATE */ + /* FIXME: hiddenmenu unsupported. */ {"hide", "parttool '%s' hidden+\n", 1, {TYPE_PARTITION}, 0, "PARTITION", "Hide PARTITION by setting the \"hidden\" bit in" " its partition type code."}, - /* ifconfig unsupported. */ - /* impsprobe unsupported. */ + /* FIXME: ifconfig unsupported. */ + /* FIXME: impsprobe unsupported. */ {"initrd", "legacy_initrd '%s' %s\n", 2, {TYPE_FILE_NO_CONSUME, TYPE_REST_VERBATIM}, 0, "FILE [ARG ...]", "Load an initial ramdisk FILE for a Linux format boot image and set the" " appropriate parameters in the Linux setup area in memory."}, /* install unsupported. */ - /* ioprobe unsupported. */ + /* FIXME: ioprobe unsupported. */ /* FIXME: really support --no-mem-option. */ {"kernel", "legacy_kernel %s %s '%s' %s\n", 4, {TYPE_TYPE_OR_NOMEM_OPTION, TYPE_TYPE_OR_NOMEM_OPTION, @@ -134,7 +134,7 @@ struct legacy_command legacy_commands[] = " \"netbsd\", \"freebsd\", \"openbsd\", \"linux\", \"biglinux\" and" " \"multiboot\". The option --no-mem-option tells GRUB not to pass a" " Linux's mem option automatically."}, - /* lock is unsupported. */ + /* FIXME: lock is unsupported. */ {"makeactive", "parttool \"$root\" boot+\n", 0, {}, 0, 0, "Set the active partition on the root disk to GRUB's root device." " This command is limited to _primary_ PC partitions on a hard disk."}, @@ -143,7 +143,8 @@ struct legacy_command legacy_commands[] = "Map the drive FROM_DRIVE to the drive TO_DRIVE. This is necessary" " when you chain-load some operating systems, such as DOS, if such an" " OS resides at a non-first drive."}, - /* md5crypt unsupported. */ + /* md5crypt unsupported since GRUB has not enough entropy and this + hash shouldn't be used anymore. */ {"module", "legacy_initrd '%s' %s\n", 1, {TYPE_FILE_NO_CONSUME, TYPE_REST_VERBATIM}, 0, "FILE [ARG ...]", @@ -152,12 +153,16 @@ struct legacy_command legacy_commands[] = " command must know what the kernel in question expects). The" " rest of the line is passed as the \"module command line\", like" " the `kernel' command."}, - /* modulenounzip unsupported. */ + {"modulenounzip", "legacy_initrd_nounzip '%s' %s\n", 1, + {TYPE_FILE_NO_CONSUME, TYPE_REST_VERBATIM}, 0, + "FILE [ARG ...]", + "The same as `module', except that automatic decompression is" + " disabled."}, /* FIXME: allow toggle. */ {"pager", "set pager=%d\n", 1, {TYPE_BOOL}, 0, "[FLAG]", "Toggle pager mode with no argument. If FLAG is given and its value" " is `on', turn on the mode. If FLAG is `off', turn off the mode."}, - /* partnew unsupported. */ + /* FIXME: partnew unsupported. */ {"parttype", "parttool '%s' type=%s\n", 2, {TYPE_PARTITION, TYPE_INT}, 0, "PART TYPE", "Change the type of the partition PART to TYPE."}, /* FIXME: support config file reloading. */ @@ -175,8 +180,8 @@ struct legacy_command legacy_commands[] = " which case it will ask for the password, before continuing." " The option --md5 tells GRUB that PASSWD is encrypted with" " md5crypt."}, - /* pause unsupported. */ - /* rarp unsupported. */ + /* FIXME: pause unsupported. */ + /* FIXME: rarp unsupported. */ {"read", "read_dword %s\n", 1, {TYPE_INT}, 0, "ADDR", "Read a 32-bit value from memory at address ADDR and" " display it in hex format."}, @@ -217,17 +222,17 @@ struct legacy_command legacy_commands[] = " STOP is the length of stop bit(s). The option --device can be used only" " in the grub shell, which specifies the file name of a tty device. The" " default values are COM1, 9600, 8N1."}, - /* setkey unsupported. */ /* NUL_TERMINATE */ - /* setup unsupported. */ - /* terminal unsupported. */ /* NUL_TERMINATE */ - /* terminfo unsupported. */ /* NUL_TERMINATE */ + /* FIXME: setkey unsupported. */ /* NUL_TERMINATE */ + /* FIXME: setup unsupported. */ + /* FIXME: terminal unsupported. */ /* NUL_TERMINATE */ + /* FIXME: terminfo unsupported. */ /* NUL_TERMINATE */ {"testload", "cat '%s'\n", 1, {TYPE_FILE}, 0, "FILE", "Read the entire contents of FILE in several different ways and" " compares them, to test the filesystem code. " " If this test succeeds, then a good next" " step is to try loading a kernel."}, - /* testvbe unsupported. */ - /* tftpserver unsupported. */ + /* FIXME: testvbe unsupported. */ + /* FIXME: tftpserver unsupported. */ {"timeout", "set timeout=%s\n", 1, {TYPE_INT}, 0, "SEC", "Set a timeout, in SEC seconds, before automatically booting the" " default entry (normally the first entry defined)."}, @@ -235,10 +240,13 @@ struct legacy_command legacy_commands[] = {"unhide", "parttool '%s' hidden-\n", 1, {TYPE_PARTITION}, 0, "PARTITION", "Unhide PARTITION by clearing the \"hidden\" bit in its" " partition type code."}, - /* uppermem unsupported. */ + /* FIXME: uppermem unsupported. */ {"uuid", "search -u '%s'\n", 1, {TYPE_VERBATIM}, 0, "UUID", "Find root by UUID"}, - /* vbeprobe unsupported. */ + /* FIXME: support MODE. */ + {"vbeprobe", "vbeinfo", 0, {}, 0, "[MODE]", + "Probe VBE information. If the mode number MODE is specified, show only" + " the information about only the mode."} }; char * From 6c6850ae13bff8975c9682aa59db0c09ad1edde8 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Sep 2010 02:55:24 +0200 Subject: [PATCH 136/214] Implement hiddenmenu (not tested) --- grub-core/commands/legacycfg.c | 48 ++++++++++++++++++++++++++++------ grub-core/lib/legacy_parse.c | 12 ++++++--- include/grub/legacy_parse.h | 2 +- util/grub-menulst2cfg.c | 13 ++++++++- 4 files changed, 62 insertions(+), 13 deletions(-) diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c index aeff78b8a..82901b0e7 100644 --- a/grub-core/commands/legacycfg.c +++ b/grub-core/commands/legacycfg.c @@ -37,6 +37,18 @@ legacy_file (const char *filename) grub_file_t file; char *entryname = NULL, *entrysrc = NULL; grub_menu_t menu; + char *suffix = grub_strdup (""); + + auto grub_err_t getline (char **line, int cont); + grub_err_t getline (char **line, + int cont __attribute__ ((unused))) + { + *line = 0; + return GRUB_ERR_NONE; + } + + if (!suffix) + return grub_errno; file = grub_file_open (filename); if (! file) @@ -68,10 +80,32 @@ legacy_file (const char *filename) { char *oldname = NULL; + int is_suffix; oldname = entryname; - parsed = grub_legacy_parse (buf, &entryname); + parsed = grub_legacy_parse (buf, &entryname, &is_suffix); grub_free (buf); + if (is_suffix) + { + char *t; + + t = suffix; + suffix = grub_realloc (suffix, grub_strlen (suffix) + + grub_strlen (parsed) + 1); + if (!suffix) + { + grub_free (t); + grub_free (entrysrc); + grub_free (parsed); + grub_free (suffix); + return grub_errno; + } + grub_memcpy (entrysrc + grub_strlen (entrysrc), parsed, + grub_strlen (parsed) + 1); + grub_free (parsed); + parsed = NULL; + continue; + } if (oldname != entryname && oldname) { const char **args = grub_malloc (sizeof (args[0])); @@ -88,13 +122,6 @@ legacy_file (const char *filename) if (parsed && !entryname) { - auto grub_err_t getline (char **line, int cont); - grub_err_t getline (char **line __attribute__ ((unused)), - int cont __attribute__ ((unused))) - { - return GRUB_ERR_NONE; - } - grub_normal_parse_line (parsed, getline); grub_print_error (); grub_free (parsed); @@ -114,6 +141,7 @@ legacy_file (const char *filename) { grub_free (t); grub_free (parsed); + grub_free (suffix); return grub_errno; } grub_memcpy (entrysrc + grub_strlen (entrysrc), parsed, @@ -137,6 +165,10 @@ legacy_file (const char *filename) grub_normal_add_menu_entry (1, args, NULL, NULL, NULL, NULL, entrysrc); } + grub_normal_parse_line (suffix, getline); + grub_print_error (); + grub_free (suffix); + if (menu && menu->size) grub_show_menu (menu, 1); diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 671d0f3f8..3800d6ca5 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -41,7 +41,8 @@ struct legacy_command TYPE_REST_VERBATIM } argt[4]; enum { - FLAG_IGNORE_REST = 1 + FLAG_IGNORE_REST = 1, + FLAG_SUFFIX = 2 } flags; const char *shortdesc; const char *longdesc; @@ -108,7 +109,8 @@ struct legacy_command legacy_commands[] = "Halt your system. If APM is available on it, turn off the power using" " the APM BIOS, unless you specify the option `--no-apm'."}, /* FIXME: help unsupported. */ /* NUL_TERMINATE */ - /* FIXME: hiddenmenu unsupported. */ + {"hiddenmenu", "if sleep -i $timeout; then timeout=0; else timeout=-1; fi\n", + 0, {}, FLAG_SUFFIX, "", "Hide the menu."}, {"hide", "parttool '%s' hidden+\n", 1, {TYPE_PARTITION}, 0, "PARTITION", "Hide PARTITION by setting the \"hidden\" bit in" " its partition type code."}, @@ -354,12 +356,14 @@ is_option (enum arg_type opt, const char *curarg, grub_size_t len) } char * -grub_legacy_parse (const char *buf, char **entryname) +grub_legacy_parse (const char *buf, char **entryname, int *suffix) { const char *ptr; const char *cmdname; unsigned i, cmdnum; + *suffix = 0; + for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++); if (!*ptr || *ptr == '#') return grub_strdup (buf); @@ -392,6 +396,8 @@ grub_legacy_parse (const char *buf, char **entryname) if (cmdnum == ARRAY_SIZE (legacy_commands)) return grub_xasprintf ("# Unsupported legacy command: %s\n", buf); + *suffix = !!(legacy_commands[cmdnum].flags & FLAG_SUFFIX); + for (; grub_isspace (*ptr) || *ptr == '='; ptr++); char *args[ARRAY_SIZE (legacy_commands[0].argt)]; diff --git a/include/grub/legacy_parse.h b/include/grub/legacy_parse.h index fce4e3e40..a6394496f 100644 --- a/include/grub/legacy_parse.h +++ b/include/grub/legacy_parse.h @@ -21,7 +21,7 @@ #include -char *grub_legacy_parse (const char *buf, char **entryname); +char *grub_legacy_parse (const char *buf, char **entryname, int *suffix); char *grub_legacy_escape (const char *in, grub_size_t len); #endif diff --git a/util/grub-menulst2cfg.c b/util/grub-menulst2cfg.c index 89b792e9a..0184b3fe3 100644 --- a/util/grub-menulst2cfg.c +++ b/util/grub-menulst2cfg.c @@ -28,6 +28,9 @@ main (int argc, char **argv) char *entryname = NULL; char *buf = NULL; size_t bufsize = 0; + char *suffix = xstrdup (""); + int suffixlen = 0; + int is_suffix = 0; if (argc >= 2 && argv[1][0] == '-') { @@ -74,7 +77,14 @@ main (int argc, char **argv) char *oldname = NULL; oldname = entryname; - parsed = grub_legacy_parse (buf, &entryname); + parsed = grub_legacy_parse (buf, &entryname, &is_suffix); + if (is_suffix) + { + suffixlen += strlen (parsed); + suffix = xrealloc (suffix, suffixlen + 1); + strcat (suffix, parsed); + continue; + } if (oldname != entryname && oldname) fprintf (out, "}\n\n"); if (oldname != entryname) @@ -89,6 +99,7 @@ main (int argc, char **argv) if (entryname) fprintf (out, "}\n\n"); + fwrite (out, 1, suffixlen, suffix); if (in != stdin) fclose (in); From 07473cf9175f5fc0d0b78b71f5bc3e3fe703820d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Sep 2010 03:05:19 +0200 Subject: [PATCH 137/214] Support pause --- grub-core/lib/legacy_parse.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 3800d6ca5..4e038807c 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -93,7 +93,7 @@ struct legacy_command legacy_commands[] = {"displaymem", "lsmmap\n", 0, {}, 0, 0, "Display what GRUB thinks the system address space map of the" " machine is, including all regions of physical RAM installed."}, - /* embed unsupported. */ + /* NOTE: embed unsupported. */ {"fallback", "set fallback='%s'\n", 1, {TYPE_VERBATIM}, 0, "NUM...", "Go into unattended boot mode: if the default boot entry has any" " errors, instead of waiting for the user to do anything, it" @@ -121,7 +121,7 @@ struct legacy_command legacy_commands[] = "FILE [ARG ...]", "Load an initial ramdisk FILE for a Linux format boot image and set the" " appropriate parameters in the Linux setup area in memory."}, - /* install unsupported. */ + /* NOTE: install unsupported. */ /* FIXME: ioprobe unsupported. */ /* FIXME: really support --no-mem-option. */ {"kernel", "legacy_kernel %s %s '%s' %s\n", 4, {TYPE_TYPE_OR_NOMEM_OPTION, @@ -145,7 +145,7 @@ struct legacy_command legacy_commands[] = "Map the drive FROM_DRIVE to the drive TO_DRIVE. This is necessary" " when you chain-load some operating systems, such as DOS, if such an" " OS resides at a non-first drive."}, - /* md5crypt unsupported since GRUB has not enough entropy and this + /* NOTE: md5crypt unsupported since GRUB has not enough entropy and this hash shouldn't be used anymore. */ {"module", "legacy_initrd '%s' %s\n", 1, {TYPE_FILE_NO_CONSUME, TYPE_REST_VERBATIM}, 0, @@ -182,7 +182,12 @@ struct legacy_command legacy_commands[] = " which case it will ask for the password, before continuing." " The option --md5 tells GRUB that PASSWD is encrypted with" " md5crypt."}, - /* FIXME: pause unsupported. */ + /* NOTE: GRUB2 has a design principle of not eternally waiting for user + input. 60 seconds should be enough. + */ + {"pause", "echo %s; if ! sleep -i 60; then return; fi", 1, + {TYPE_REST_VERBATIM}, 0, + "[MESSAGE ...]", "Print MESSAGE, then wait until a key is pressed."}, /* FIXME: rarp unsupported. */ {"read", "read_dword %s\n", 1, {TYPE_INT}, 0, "ADDR", "Read a 32-bit value from memory at address ADDR and" @@ -208,7 +213,7 @@ struct legacy_command legacy_commands[] = " GRUB can read, but setting the correct root device is still" " desired. Note that the items mentioned in `root' which" " derived from attempting the mount will NOT work correctly."}, - /* FIXME: support arguments. */ + /* FIXME: support saving NUM and fallback. */ {"savedefault", "saved_entry=${chosen}; save_env saved_entry\n", 0, {}, 0, "[NUM | `fallback']", "Save the current entry as the default boot entry if no argument is" From 43cce9e0955c22cda56eef3d3054aedb1b4892bf Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Sep 2010 11:01:21 +0200 Subject: [PATCH 138/214] Fix uninitialised usage of curarg --- grub-core/lib/legacy_parse.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 4e038807c..797594c15 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -411,10 +411,10 @@ grub_legacy_parse (const char *buf, char **entryname, int *suffix) { unsigned j = 0; int hold_arg = 0; + const char *curarg = NULL; for (i = 0; i < legacy_commands[cmdnum].argc; i++) { - const char *curarg; - grub_size_t curarglen; + grub_size_t curarglen; if (hold_arg) { ptr = curarg; From 966446589259f507b5f327f3bb7ede0deab4b4db Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Sep 2010 11:09:01 +0200 Subject: [PATCH 139/214] Add missing newlines --- grub-core/lib/legacy_parse.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 797594c15..dabc497be 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -169,7 +169,7 @@ struct legacy_command legacy_commands[] = "PART TYPE", "Change the type of the partition PART to TYPE."}, /* FIXME: support config file reloading. */ /* FIXME: support usage in menuentry. */ - {"password", "if [ \"$superusers\" = "" ]; then superusers=legacy; fi; " + {"password", "if [ \"$superusers\" = "" ]; then superusers=legacy; fi;\n" "legacy_password %s '%s' %s", 3, {TYPE_OPTION, TYPE_VERBATIM, TYPE_FILE}, FLAG_IGNORE_REST, "[--md5] PASSWD [FILE]", @@ -185,7 +185,7 @@ struct legacy_command legacy_commands[] = /* NOTE: GRUB2 has a design principle of not eternally waiting for user input. 60 seconds should be enough. */ - {"pause", "echo %s; if ! sleep -i 60; then return; fi", 1, + {"pause", "echo %s; if ! sleep -i 60; then return; fi\n", 1, {TYPE_REST_VERBATIM}, 0, "[MESSAGE ...]", "Print MESSAGE, then wait until a key is pressed."}, /* FIXME: rarp unsupported. */ @@ -251,7 +251,7 @@ struct legacy_command legacy_commands[] = {"uuid", "search -u '%s'\n", 1, {TYPE_VERBATIM}, 0, "UUID", "Find root by UUID"}, /* FIXME: support MODE. */ - {"vbeprobe", "vbeinfo", 0, {}, 0, "[MODE]", + {"vbeprobe", "vbeinfo\n", 0, {}, 0, "[MODE]", "Probe VBE information. If the mode number MODE is specified, show only" " the information about only the mode."} }; From 788f1f3a85e3b369124cc698f7979b73819a656b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Sep 2010 13:50:24 +0200 Subject: [PATCH 140/214] * grub-core/lib/xzembed/xz_dec_stream.c (xz_dec_reset): Preserve context pointer. --- ChangeLog | 5 +++++ grub-core/lib/xzembed/xz_dec_stream.c | 11 +++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 330656cc3..f82f12467 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2010-09-11 Vladimir Serbinenko + + * grub-core/lib/xzembed/xz_dec_stream.c (xz_dec_reset): Preserve context + pointer. + 2010-09-11 Szymon Janc * grub-core/commands/lsacpi.c (grub_cmd_lsacpi): Fix prototype. diff --git a/grub-core/lib/xzembed/xz_dec_stream.c b/grub-core/lib/xzembed/xz_dec_stream.c index 642492483..ff26f5119 100644 --- a/grub-core/lib/xzembed/xz_dec_stream.c +++ b/grub-core/lib/xzembed/xz_dec_stream.c @@ -830,8 +830,15 @@ void xz_dec_reset(struct xz_dec *s) s->allow_buf_error = false; s->pos = 0; - memzero(&s->block, sizeof(s->block)); - memzero(&s->index, sizeof(s->index)); + { + uint8_t *t; + t = s->block.hash.crc32_context; + memzero(&s->block, sizeof(s->block)); + s->block.hash.crc32_context = t; + t = s->index.hash.crc32_context; + memzero(&s->index, sizeof(s->index)); + s->index.hash.crc32_context = t; + } s->temp.pos = 0; s->temp.size = STREAM_HEADER_SIZE; From faca6bec3b87b5973998ed44bbc42e7273e491ab Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Sep 2010 13:53:12 +0200 Subject: [PATCH 141/214] * grub-core/commands/menuentry.c (append_menu_entry): Don't rely on args ending with NULL. --- ChangeLog | 7 ++++++- grub-core/commands/menuentry.c | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index f82f12467..79fd79556 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,9 @@ -2010-09-11 Vladimir Serbinenko +2010-09-12 Vladimir Serbinenko + + * grub-core/commands/menuentry.c (append_menu_entry): Don't rely on + args ending with NULL. + +2010-09-12 Vladimir Serbinenko * grub-core/lib/xzembed/xz_dec_stream.c (xz_dec_reset): Preserve context pointer. diff --git a/grub-core/commands/menuentry.c b/grub-core/commands/menuentry.c index fc1ae71c7..c28c6ef6f 100644 --- a/grub-core/commands/menuentry.c +++ b/grub-core/commands/menuentry.c @@ -128,7 +128,7 @@ append_menu_entry (int argc, const char **args, char **classes, if (! menu_args) goto fail; - for (i = 0; args[i]; i++) + for (i = 0; i < argc; i++) { menu_args[i] = grub_strdup (args[i]); if (! menu_args[i]) From 4870900f8fa000335070852a917c85c68aae664a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Sep 2010 13:55:52 +0200 Subject: [PATCH 142/214] * grub-core/kern/emu/main.c (main): Call hostfs_init only after init_all. --- ChangeLog | 4 ++++ grub-core/kern/emu/main.c | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 79fd79556..436c0980b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2010-09-12 Vladimir Serbinenko + + * grub-core/kern/emu/main.c (main): Call hostfs_init only after init_all. + 2010-09-12 Vladimir Serbinenko * grub-core/commands/menuentry.c (append_menu_entry): Don't rely on diff --git a/grub-core/kern/emu/main.c b/grub-core/kern/emu/main.c index 23b8516f1..c575beb4b 100644 --- a/grub-core/kern/emu/main.c +++ b/grub-core/kern/emu/main.c @@ -190,13 +190,14 @@ main (int argc, char *argv[]) grub_emu_init (); grub_console_init (); grub_host_init (); - grub_hostfs_init (); /* XXX: This is a bit unportable. */ grub_util_biosdisk_init (dev_map); grub_init_all (); + grub_hostfs_init (); + grub_emu_post_init (); /* Make sure that there is a root device. */ From abda0cade5a5d6af5017a9b06bf27614909b8255 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Sep 2010 13:58:18 +0200 Subject: [PATCH 143/214] Enable legacy_parser on emu --- grub-core/Makefile.core.def | 1 + 1 file changed, 1 insertion(+) diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index cbc5b7438..36a6e6564 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1411,6 +1411,7 @@ module = { common = commands/legacycfg.c; common = lib/legacy_parse.c; enable = i386_pc; + enable = emu; }; module = { From 768ec2e2adef102e74e1739b8ffdacf50ab57552 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Sep 2010 14:00:44 +0200 Subject: [PATCH 144/214] * grub-core/kern/misc.c (grub_vprintf): Use va_copy when necessary. (grub_xvasprintf): Likewise. --- ChangeLog | 5 +++++ grub-core/kern/misc.c | 8 ++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 436c0980b..46f430bdc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2010-09-12 Vladimir Serbinenko + + * grub-core/kern/misc.c (grub_vprintf): Use va_copy when necessary. + (grub_xvasprintf): Likewise. + 2010-09-12 Vladimir Serbinenko * grub-core/kern/emu/main.c (main): Call hostfs_init only after init_all. diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c index 0bfa08992..6e0eaf6a4 100644 --- a/grub-core/kern/misc.c +++ b/grub-core/kern/misc.c @@ -196,6 +196,8 @@ grub_vprintf (const char *fmt, va_list args) grub_size_t s; static char buf[PREALLOC_SIZE + 1]; char *curbuf = buf; + va_list ap2; + va_copy (ap2, args); s = grub_vsnprintf_real (buf, PREALLOC_SIZE, fmt, args); if (s > PREALLOC_SIZE) @@ -210,7 +212,7 @@ grub_vprintf (const char *fmt, va_list args) buf[PREALLOC_SIZE] = 0; } else - s = grub_vsnprintf_real (curbuf, s, fmt, args); + s = grub_vsnprintf_real (curbuf, s, fmt, ap2); } grub_xputs (curbuf); @@ -947,11 +949,13 @@ grub_xvasprintf (const char *fmt, va_list ap) while (1) { + va_list ap2; + va_copy (ap2, ap); ret = grub_malloc (as + 1); if (!ret) return NULL; - s = grub_vsnprintf_real (ret, as, fmt, ap); + s = grub_vsnprintf_real (ret, as, fmt, ap2); if (s <= as) return ret; From 64ad6157ae4f9d68be1b96ad7882544241a3e0f4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Sep 2010 14:01:02 +0200 Subject: [PATCH 145/214] Fix bunch of memory problems and implement hdbias --- grub-core/commands/legacycfg.c | 147 +++++++++++++++++++++++++-------- grub-core/lib/legacy_parse.c | 36 ++++++-- util/grub-menulst2cfg.c | 14 +++- 3 files changed, 153 insertions(+), 44 deletions(-) diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c index 82901b0e7..e42ca5878 100644 --- a/grub-core/commands/legacycfg.c +++ b/grub-core/commands/legacycfg.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include static grub_err_t legacy_file (const char *filename) @@ -67,7 +69,7 @@ legacy_file (const char *filename) while (1) { char *buf = grub_file_getline (file); - char *parsed; + char *parsed = NULL; if (!buf && grub_errno) { @@ -84,7 +86,7 @@ legacy_file (const char *filename) oldname = entryname; parsed = grub_legacy_parse (buf, &entryname, &is_suffix); - grub_free (buf); + buf = NULL; if (is_suffix) { char *t; @@ -100,7 +102,7 @@ legacy_file (const char *filename) grub_free (suffix); return grub_errno; } - grub_memcpy (entrysrc + grub_strlen (entrysrc), parsed, + grub_memcpy (suffix + grub_strlen (suffix), parsed, grub_strlen (parsed) + 1); grub_free (parsed); parsed = NULL; @@ -117,6 +119,9 @@ legacy_file (const char *filename) args[0] = oldname; grub_normal_add_menu_entry (1, args, NULL, NULL, NULL, NULL, entrysrc); + grub_free (args); + entrysrc[0] = 0; + grub_free (oldname); } } @@ -125,6 +130,7 @@ legacy_file (const char *filename) grub_normal_parse_line (parsed, getline); grub_print_error (); grub_free (parsed); + parsed = NULL; } else if (parsed) { @@ -163,11 +169,13 @@ legacy_file (const char *filename) } args[0] = entryname; grub_normal_add_menu_entry (1, args, NULL, NULL, NULL, NULL, entrysrc); + grub_free (args); } grub_normal_parse_line (suffix, getline); grub_print_error (); grub_free (suffix); + grub_free (entrysrc); if (menu && menu->size) grub_show_menu (menu, 1); @@ -215,6 +223,7 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), struct grub_command *cmd; char **cutargs; int cutargc; + for (i = 0; i < 2; i++) { /* FIXME: really support this. */ @@ -309,46 +318,118 @@ grub_cmd_legacy_kernel (struct grub_command *mycmd __attribute__ ((unused)), grub_errno = GRUB_ERR_NONE; } - /* k*BSD didn't really work well with grub-legacy. */ - if (kernel_type == GUESS_IT || kernel_type == KFREEBSD) + { + int bsd_device = -1; + int bsd_slice = -1; + int bsd_part = -1; { - cmd = grub_command_find ("kfreebsd"); - if (cmd) + grub_device_t dev; + char *hdbiasstr; + int hdbias = 0; + hdbiasstr = grub_env_get ("legacy_hdbias"); + if (hdbiasstr) { - if (!(cmd->func) (cmd, cutargc, cutargs)) - { - kernel_type = KFREEBSD; - return GRUB_ERR_NONE; - } + hdbias = grub_strtoul (hdbiasstr, 0, 0); + grub_errno = GRUB_ERR_NONE; + } + dev = grub_device_open (0); + if (dev && dev->disk + && dev->disk->dev->id == GRUB_DISK_DEVICE_BIOSDISK_ID + && dev->disk->dev->id >= 0x80 && dev->disk->dev->id <= 0x90) + { + struct grub_partition *part = dev->disk->partition; + bsd_device = dev->disk->id - 0x80 - hdbias; + if (part && (grub_strcmp (part->partmap->name, "netbsd") == 0 + || grub_strcmp (part->partmap->name, "openbsd") == 0 + || grub_strcmp (part->partmap->name, "bsd") == 0)) + { + bsd_part = part->number; + part = part->parent; + } + if (part && grub_strcmp (part->partmap->name, "msdos") == 0) + bsd_slice = part->number; } - grub_errno = GRUB_ERR_NONE; } - if (kernel_type == GUESS_IT || kernel_type == KNETBSD) + + /* k*BSD didn't really work well with grub-legacy. */ + if (kernel_type == GUESS_IT || kernel_type == KFREEBSD) + { + char buf[sizeof("adXXXXXXXXXXXXsXXXXXXXXXXXXYYY")]; + if (bsd_device != -1) + { + if (bsd_slice != -1 && bsd_part != -1) + grub_snprintf(buf, sizeof(buf), "ad%ds%d%c", bsd_device, + bsd_slice, 'a' + bsd_part); + else if (bsd_slice != -1) + grub_snprintf(buf, sizeof(buf), "ad%ds%d", bsd_device, + bsd_slice); + else + grub_snprintf(buf, sizeof(buf), "ad%d", bsd_device); + grub_env_set ("kFreeBSD.vfs.root.mountfrom", buf); + } + else + grub_env_unset ("kFreeBSD.vfs.root.mountfrom"); + cmd = grub_command_find ("kfreebsd"); + if (cmd) + { + if (!(cmd->func) (cmd, cutargc, cutargs)) + { + kernel_type = KFREEBSD; + return GRUB_ERR_NONE; + } + } + grub_errno = GRUB_ERR_NONE; + } { - cmd = grub_command_find ("knetbsd"); - if (cmd) + char **bsdargs; + int bsdargc; + char bsddevname[sizeof ("wdXXXXXXXXXXXXY")]; + if (bsd_device == -1) { - if (!(cmd->func) (cmd, cutargc, cutargs)) - { - kernel_type = KNETBSD; - return GRUB_ERR_NONE; - } + bsdargs = cutargs; + bsdargc = cutargc; } - grub_errno = GRUB_ERR_NONE; - } - if (kernel_type == GUESS_IT || kernel_type == KOPENBSD) - { - cmd = grub_command_find ("kopenbsd"); - if (cmd) + else { - if (!(cmd->func) (cmd, cutargc, cutargs)) - { - kernel_type = KOPENBSD; - return GRUB_ERR_NONE; - } + bsdargc = cutargc + 2; + bsdargs = grub_malloc (sizeof (bsdargs[0]) * bsdargc); + grub_memcpy (bsdargs, args, argc * sizeof (bsdargs[0])); + bsdargs[argc] = "-r"; + bsdargs[argc + 1] = bsddevname; + grub_snprintf (bsddevname, sizeof (bsddevname), + "wd%d%c", bsd_device, + bsd_part != -1 ? bsd_part + 'a' : 'c'); } - grub_errno = GRUB_ERR_NONE; + if (kernel_type == GUESS_IT || kernel_type == KNETBSD) + { + cmd = grub_command_find ("knetbsd"); + if (cmd) + { + if (!(cmd->func) (cmd, bsdargc, bsdargs)) + { + kernel_type = KNETBSD; + return GRUB_ERR_NONE; + } + } + grub_errno = GRUB_ERR_NONE; + } + if (kernel_type == GUESS_IT || kernel_type == KOPENBSD) + { + cmd = grub_command_find ("kopenbsd"); + if (cmd) + { + if (!(cmd->func) (cmd, bsdargc, bsdargs)) + { + kernel_type = KOPENBSD; + return GRUB_ERR_NONE; + } + } + grub_errno = GRUB_ERR_NONE; + } + if (bsdargs != cutargs) + grub_free (bsdargs); } + } } while (0); diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index dabc497be..01b836087 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -195,7 +195,9 @@ struct legacy_command legacy_commands[] = {"reboot", "reboot\n", 0, {}, 0, 0, "Reboot your system."}, /* FIXME: Support HDBIAS. */ /* FIXME: Support printing. */ - {"root", "set root='%s'\n", 1, {TYPE_PARTITION}, 0, "[DEVICE [HDBIAS]]", + {"root", "set root='%s'; set legacy_hdbias='%s'\n", + 2, {TYPE_PARTITION, TYPE_INT}, 0, + "[DEVICE [HDBIAS]]", "Set the current \"root device\" to the device DEVICE, then" " attempt to mount it to get the partition size (for passing the" " partition descriptor in `ES:ESI', used by some chain-loaded" @@ -206,7 +208,8 @@ struct legacy_command legacy_commands[] = " how many BIOS drive numbers are on controllers before the current" " one. For example, if there is an IDE disk and a SCSI disk, and your" " FreeBSD root partition is on the SCSI disk, then use a `1' for HDBIAS."}, - {"rootnoverify", "set root='%s'\n", 1, {TYPE_PARTITION}, 0, + {"rootnoverify", "set root='%s'; set legacy_hdbias='%s'\n", + 2, {TYPE_PARTITION, TYPE_INT}, 0, "[DEVICE [HDBIAS]]", "Similar to `root', but don't attempt to mount the partition. This" " is useful for when an OS is outside of the area of the disk that" @@ -265,7 +268,7 @@ grub_legacy_escape (const char *in, grub_size_t len) for (ptr = in; ptr < in + len && *ptr; ptr++) if (*ptr == '\'' || *ptr == '\\') overhead++; - ret = grub_malloc (ptr - in + overhead); + ret = grub_malloc (ptr - in + overhead + 1); if (!ret) return NULL; outptr = ret; @@ -371,7 +374,15 @@ grub_legacy_parse (const char *buf, char **entryname, int *suffix) for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++); if (!*ptr || *ptr == '#') - return grub_strdup (buf); + { + char *ret; + int len = grub_strlen (buf); + ret = grub_malloc (len + 2); + grub_memcpy (ret, buf, len); + ret[len] = '\n'; + ret[len + 1] = 0; + return ret; + } cmdname = ptr; for (ptr = buf; *ptr && !grub_isspace (*ptr) && *ptr != '='; ptr++); @@ -412,7 +423,7 @@ grub_legacy_parse (const char *buf, char **entryname, int *suffix) unsigned j = 0; int hold_arg = 0; const char *curarg = NULL; - for (i = 0; i < legacy_commands[cmdnum].argc; i++) + for (i = 0; i < legacy_commands[cmdnum].argc + hold_arg; i++) { grub_size_t curarglen; if (hold_arg) @@ -495,7 +506,7 @@ grub_legacy_parse (const char *buf, char **entryname, int *suffix) args[j++] = grub_strndup (curarg, curarglen); break; } - args[j++] = ""; + args[j++] = grub_strdup (""); hold_arg = 1; break; case TYPE_INT: @@ -536,7 +547,14 @@ grub_legacy_parse (const char *buf, char **entryname, int *suffix) } } } - - return grub_xasprintf (legacy_commands[cmdnum].map, args[0], args[1], args[2], - args[3]); + + { + char *ret = grub_xasprintf (legacy_commands[cmdnum].map, args[0], args[1], + args[2], args[3]); + grub_free (args[0]); + grub_free (args[1]); + grub_free (args[2]); + grub_free (args[3]); + return ret; + } } diff --git a/util/grub-menulst2cfg.c b/util/grub-menulst2cfg.c index 0184b3fe3..38a906c0a 100644 --- a/util/grub-menulst2cfg.c +++ b/util/grub-menulst2cfg.c @@ -88,12 +88,18 @@ main (int argc, char **argv) if (oldname != entryname && oldname) fprintf (out, "}\n\n"); if (oldname != entryname) - fprintf (out, "menuentry \'%s\' {\n", - grub_legacy_escape (entryname, strlen (entryname))); + { + char *escaped = grub_legacy_escape (entryname, strlen (entryname)); + fprintf (out, "menuentry \'%s\' {\n", escaped); + grub_free (escaped); + grub_free (oldname); + } } if (parsed) fprintf (out, "%s%s", entryname ? " " : "", parsed); + grub_free (parsed); + parsed = NULL; } if (entryname) @@ -101,6 +107,10 @@ main (int argc, char **argv) fwrite (out, 1, suffixlen, suffix); + grub_free (buf); + grub_free (suffix); + grub_free (entryname); + if (in != stdin) fclose (in); if (out != stdout) From b2b260b9eb009126690c700e00b902d5ba1b7ba8 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Sep 2010 14:04:10 +0200 Subject: [PATCH 146/214] REmove obsolete FIXME --- grub-core/lib/legacy_parse.c | 1 - 1 file changed, 1 deletion(-) diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 01b836087..44dc31d81 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -193,7 +193,6 @@ struct legacy_command legacy_commands[] = "Read a 32-bit value from memory at address ADDR and" " display it in hex format."}, {"reboot", "reboot\n", 0, {}, 0, 0, "Reboot your system."}, - /* FIXME: Support HDBIAS. */ /* FIXME: Support printing. */ {"root", "set root='%s'; set legacy_hdbias='%s'\n", 2, {TYPE_PARTITION, TYPE_INT}, 0, From 21d7be66125b6cfe48dbc9110e42a7e436548138 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Sep 2010 14:18:39 +0200 Subject: [PATCH 147/214] Support (hd0,1,a legacy partition specification --- grub-core/lib/legacy_parse.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 44dc31d81..2bf372de3 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -288,7 +288,7 @@ adjust_file (const char *in, grub_size_t len) const char *comma, *ptr, *rest; char *ret, *outptr; int overhead = 0; - int part; + int part = -1, subpart = -1; if (in[0] != '(') return grub_legacy_escape (in, len); for (ptr = in + 1; ptr < in + len && *ptr && *ptr != ')' @@ -299,12 +299,17 @@ adjust_file (const char *in, grub_size_t len) if (*comma != ',') return grub_legacy_escape (in, len); part = grub_strtoull (comma + 1, (char **) &rest, 0); + if (rest[0] == ',' && rest[1] >= 'a' && rest[1] <= 'z') + { + subpart = rest[1] - 'a'; + rest += 2; + } for (ptr = rest; ptr < in + len && *ptr; ptr++) if (*ptr == '\'' || *ptr == '\\') overhead++; - /* 30 is enough for any number. */ - ret = grub_malloc (ptr - in + overhead + 30); + /* 35 is enough for any 2 numbers. */ + ret = grub_malloc (ptr - in + overhead + 35); if (!ret) return NULL; @@ -316,7 +321,10 @@ adjust_file (const char *in, grub_size_t len) *outptr++ = *ptr; } - grub_snprintf (outptr, 30, "%d", part + 1); + if (subpart != -1) + grub_snprintf (outptr, 35, "%d,%d", part + 1, subpart + 1); + else + grub_snprintf (outptr, 35, "%d", part + 1); while (*outptr) outptr++; for (ptr = rest; ptr < in + len; ptr++) @@ -378,8 +386,13 @@ grub_legacy_parse (const char *buf, char **entryname, int *suffix) int len = grub_strlen (buf); ret = grub_malloc (len + 2); grub_memcpy (ret, buf, len); - ret[len] = '\n'; - ret[len + 1] = 0; + if (len && ret[len - 1] == '\n') + ret[len] = 0; + else + { + ret[len] = '\n'; + ret[len + 1] = 0; + } return ret; } From 281d690594631f846ea76585fe154aa79f4d8beb Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Sep 2010 15:26:38 +0200 Subject: [PATCH 148/214] Add no-argument version of commands and remove legacy_color --- grub-core/commands/legacycfg.c | 49 ++-------------- grub-core/lib/legacy_parse.c | 102 ++++++++++++++++++++++++++------- 2 files changed, 88 insertions(+), 63 deletions(-) diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c index e42ca5878..ca69a7817 100644 --- a/grub-core/commands/legacycfg.c +++ b/grub-core/commands/legacycfg.c @@ -500,39 +500,6 @@ grub_cmd_legacy_initrdnounzip (struct grub_command *mycmd __attribute__ ((unused "no kernel with module support is loaded in legacy way"); } -static grub_err_t -grub_cmd_legacy_color (struct grub_command *mycmd __attribute__ ((unused)), - int argc, char **args) -{ - if (argc < 1) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "color required"); - grub_env_set ("color_normal", args[0]); - if (argc >= 2) - grub_env_set ("color_highlight", args[1]); - else - { - char *slash = grub_strchr (args[0], '/'); - char *invert; - grub_size_t len; - - len = grub_strlen (args[0]); - if (!slash) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "bad color specification %s", - args[0]); - invert = grub_malloc (len + 1); - if (!invert) - return grub_errno; - grub_memcpy (invert, slash + 1, len - (slash - args[0]) - 1); - invert[len - (slash - args[0]) - 1] = '/'; - grub_memcpy (invert + len - (slash - args[0]), args[0], slash - args[0]); - invert[len] = 0; - grub_env_set ("color_highlight", invert); - grub_free (invert); - } - - return grub_errno; -} - static grub_err_t check_password_deny (const char *user __attribute__ ((unused)), const char *entered __attribute__ ((unused)), @@ -714,13 +681,18 @@ grub_cmd_legacy_password (struct grub_command *mycmd __attribute__ ((unused)), } static grub_command_t cmd_source, cmd_configfile, cmd_kernel, cmd_initrd; -static grub_command_t cmd_color, cmd_password, cmd_initrdnounzip; +static grub_command_t cmd_password, cmd_initrdnounzip; GRUB_MOD_INIT(legacycfg) { cmd_source = grub_register_command ("legacy_source", grub_cmd_legacy_source, N_("FILE"), N_("Parse legacy config")); + cmd_configfile = grub_register_command ("legacy_configfile", + grub_cmd_legacy_configfile, + N_("FILE"), + N_("Parse legacy config")); + cmd_kernel = grub_register_command ("legacy_kernel", grub_cmd_legacy_kernel, N_("[--no-mem-option] [--type=TYPE] FILE [ARG ...]"), @@ -735,14 +707,6 @@ GRUB_MOD_INIT(legacycfg) N_("FILE [ARG ...]"), N_("Simulate grub-legacy modulenounzip command")); - cmd_configfile = grub_register_command ("legacy_configfile", - grub_cmd_legacy_configfile, - N_("FILE"), - N_("Parse legacy config")); - cmd_color = grub_register_command ("legacy_color", - grub_cmd_legacy_color, - N_("NORMAL [HIGHLIGHT]"), - N_("Simulate grub-legacy color command")); cmd_password = grub_register_command ("legacy_password", grub_cmd_legacy_password, N_("[--md5] PASSWD [FILE]"), @@ -756,6 +720,5 @@ GRUB_MOD_FINI(legacycfg) grub_unregister_command (cmd_kernel); grub_unregister_command (cmd_initrd); grub_unregister_command (cmd_initrdnounzip); - grub_unregister_command (cmd_color); grub_unregister_command (cmd_password); } diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 2bf372de3..096975434 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -41,8 +41,11 @@ struct legacy_command TYPE_REST_VERBATIM } argt[4]; enum { - FLAG_IGNORE_REST = 1, - FLAG_SUFFIX = 2 + FLAG_IGNORE_REST = 1, + FLAG_SUFFIX = 2, + FLAG_FALLBACK_AVAILABLE = 4, + FLAG_FALLBACK = 8, + FLAG_COLOR_INVERT = 16, } flags; const char *shortdesc; const char *longdesc; @@ -65,8 +68,9 @@ struct legacy_command legacy_commands[] = "FILE1 FILE2", "Compare the file FILE1 with the FILE2 and inform the different values" " if any."}, - {"color", "legacy_color '%s' '%s'\n", 2, {TYPE_VERBATIM, TYPE_VERBATIM}, - FLAG_IGNORE_REST, "NORMAL [HIGHLIGHT]", + {"color", "set color_normal='%s'; set color_highlight='%s'\n", + 2, {TYPE_VERBATIM, TYPE_VERBATIM}, + FLAG_IGNORE_REST | FLAG_FALLBACK_AVAILABLE, "NORMAL [HIGHLIGHT]", "Change the menu colors. The color NORMAL is used for most" " lines in the menu, and the color HIGHLIGHT is used to highlight the" " line where the cursor points. If you omit HIGHLIGHT, then the" @@ -77,6 +81,9 @@ struct legacy_command legacy_commands[] = " light-green, light-cyan, light-red, light-magenta, yellow and white." " But only the first eight names can be used for BG. You can prefix" " \"blink-\" to FG if you want a blinking foreground color."}, + {"color", "set color_normal='%s'; set color_highlight='%s'\n", + 1, {TYPE_VERBATIM}, + FLAG_IGNORE_REST | FLAG_FALLBACK | FLAG_COLOR_INVERT, NULL, NULL}, {"configfile", "legacy_configfile '%s'\n", 1, {TYPE_FILE}, 0, "FILE", "Load FILE as the configuration file."}, {"debug", @@ -160,10 +167,15 @@ struct legacy_command legacy_commands[] = "FILE [ARG ...]", "The same as `module', except that automatic decompression is" " disabled."}, - /* FIXME: allow toggle. */ - {"pager", "set pager=%d\n", 1, {TYPE_BOOL}, 0, "[FLAG]", + {"pager", "set pager=%s; if [ \"$pager\" = 0 ]; then " + " echo Internal pager is now off; else echo Internal pager is now on; fi\n", + 1, {TYPE_BOOL}, FLAG_FALLBACK_AVAILABLE, "[FLAG]", "Toggle pager mode with no argument. If FLAG is given and its value" " is `on', turn on the mode. If FLAG is `off', turn off the mode."}, + {"pager", + "if [ \"$pager\" = 1 ]; then pager=0; echo Internal pager is now off;" + "else pager=1; echo Internal pager is now on; fi\n", 0, {}, + FLAG_FALLBACK, NULL, NULL}, /* FIXME: partnew unsupported. */ {"parttype", "parttool '%s' type=%s\n", 2, {TYPE_PARTITION, TYPE_INT}, 0, "PART TYPE", "Change the type of the partition PART to TYPE."}, @@ -193,9 +205,8 @@ struct legacy_command legacy_commands[] = "Read a 32-bit value from memory at address ADDR and" " display it in hex format."}, {"reboot", "reboot\n", 0, {}, 0, 0, "Reboot your system."}, - /* FIXME: Support printing. */ {"root", "set root='%s'; set legacy_hdbias='%s'\n", - 2, {TYPE_PARTITION, TYPE_INT}, 0, + 2, {TYPE_PARTITION, TYPE_INT}, FLAG_FALLBACK_AVAILABLE, "[DEVICE [HDBIAS]]", "Set the current \"root device\" to the device DEVICE, then" " attempt to mount it to get the partition size (for passing the" @@ -207,6 +218,7 @@ struct legacy_command legacy_commands[] = " how many BIOS drive numbers are on controllers before the current" " one. For example, if there is an IDE disk and a SCSI disk, and your" " FreeBSD root partition is on the SCSI disk, then use a `1' for HDBIAS."}, + {"root", "echo \"$root\"\n", 0, {}, FLAG_FALLBACK, NULL, NULL}, {"rootnoverify", "set root='%s'; set legacy_hdbias='%s'\n", 2, {TYPE_PARTITION, TYPE_INT}, 0, "[DEVICE [HDBIAS]]", @@ -215,6 +227,7 @@ struct legacy_command legacy_commands[] = " GRUB can read, but setting the correct root device is still" " desired. Note that the items mentioned in `root' which" " derived from attempting the mount will NOT work correctly."}, + {"rootnoverify", "echo \"$root\"\n", 0, {}, FLAG_FALLBACK, NULL, NULL}, /* FIXME: support saving NUM and fallback. */ {"savedefault", "saved_entry=${chosen}; save_env saved_entry\n", 0, {}, 0, "[NUM | `fallback']", @@ -432,7 +445,6 @@ grub_legacy_parse (const char *buf, char **entryname, int *suffix) grub_memset (args, 0, sizeof (args)); { - unsigned j = 0; int hold_arg = 0; const char *curarg = NULL; for (i = 0; i < legacy_commands[cmdnum].argc + hold_arg; i++) @@ -445,6 +457,8 @@ grub_legacy_parse (const char *buf, char **entryname, int *suffix) } for (; grub_isspace (*ptr); ptr++); curarg = ptr; + if (!*curarg) + break; for (; *ptr && !grub_isspace (*ptr); ptr++); if (i != legacy_commands[cmdnum].argc - 1 || (legacy_commands[cmdnum].flags & FLAG_IGNORE_REST)) @@ -463,7 +477,7 @@ grub_legacy_parse (const char *buf, char **entryname, int *suffix) hold_arg = 1; case TYPE_PARTITION: case TYPE_FILE: - args[j++] = adjust_file (curarg, curarglen); + args[i] = adjust_file (curarg, curarglen); break; case TYPE_REST_VERBATIM: @@ -481,7 +495,7 @@ grub_legacy_parse (const char *buf, char **entryname, int *suffix) ptr++; overhead += 3; } - outptr0 = args[j++] = grub_malloc (overhead + (ptr - curarg)); + outptr0 = args[i] = grub_malloc (overhead + (ptr - curarg)); if (!outptr0) return NULL; ptr = curarg; @@ -507,7 +521,7 @@ grub_legacy_parse (const char *buf, char **entryname, int *suffix) break; case TYPE_VERBATIM: - args[j++] = grub_legacy_escape (curarg, curarglen); + args[i] = grub_legacy_escape (curarg, curarglen); break; case TYPE_FORCE_OPTION: case TYPE_NOAPM_OPTION: @@ -515,10 +529,10 @@ grub_legacy_parse (const char *buf, char **entryname, int *suffix) case TYPE_OPTION: if (is_option (legacy_commands[cmdnum].argt[i], curarg, curarglen)) { - args[j++] = grub_strndup (curarg, curarglen); + args[i] = grub_strndup (curarg, curarglen); break; } - args[j++] = grub_strdup (""); + args[i] = grub_strdup (""); hold_arg = 1; break; case TYPE_INT: @@ -526,8 +540,6 @@ grub_legacy_parse (const char *buf, char **entryname, int *suffix) const char *brk; int base = 10; brk = curarg; - if (curarglen < 1) - args[j++] = grub_strdup ("0"); if (brk[0] == '0' && brk[1] == 'x') base = 16; else if (brk[0] == '0') @@ -545,21 +557,71 @@ grub_legacy_parse (const char *buf, char **entryname, int *suffix) break; } if (brk == curarg) - args[j++] = grub_strdup ("0"); + args[i] = grub_strdup ("0"); else - args[j++] = grub_strndup (curarg, brk - curarg); + args[i] = grub_strndup (curarg, brk - curarg); } break; case TYPE_BOOL: if (curarglen == 2 && curarg[0] == 'o' && curarg[1] == 'n') - args[j++] = grub_strdup ("1"); + args[i] = grub_strdup ("1"); else - args[j++] = grub_strdup ("0"); + args[i] = grub_strdup ("0"); break; } } } + while (legacy_commands[cmdnum].argc > 0 + && args[legacy_commands[cmdnum].argc - 1] == NULL + && (legacy_commands[cmdnum].flags & FLAG_FALLBACK_AVAILABLE) + && args[legacy_commands[cmdnum + 1].argc] == NULL) + cmdnum++; + + for (; i < legacy_commands[cmdnum].argc; i++) + switch (legacy_commands[cmdnum].argt[i]) + { + case TYPE_FILE_NO_CONSUME: + case TYPE_PARTITION: + case TYPE_FILE: + case TYPE_REST_VERBATIM: + case TYPE_VERBATIM: + case TYPE_FORCE_OPTION: + case TYPE_NOAPM_OPTION: + case TYPE_TYPE_OR_NOMEM_OPTION: + case TYPE_OPTION: + args[i] = grub_strdup (""); + break; + case TYPE_BOOL: + case TYPE_INT: + args[i] = grub_strdup ("0"); + break; + } + + if (legacy_commands[cmdnum].flags & FLAG_COLOR_INVERT) + { + char *corig = args[legacy_commands[cmdnum].argc - 1]; + char *slash = grub_strchr (corig, '/'); + char *invert; + grub_size_t len; + + len = grub_strlen (corig); + if (!slash) + { + grub_error (GRUB_ERR_BAD_ARGUMENT, "bad color specification %s", + args[0]); + return NULL; + } + invert = grub_malloc (len + 1); + if (!invert) + return NULL; + grub_memcpy (invert, slash + 1, len - (slash - corig) - 1); + invert[len - (slash - args[0]) - 1] = '/'; + grub_memcpy (invert + len - (slash - corig), corig, slash - corig); + invert[len] = 0; + args[legacy_commands[cmdnum].argc] = invert; + } + { char *ret = grub_xasprintf (legacy_commands[cmdnum].map, args[0], args[1], args[2], args[3]); From e64334df29ed3394b9c5f3cb7ad46d06d3160b36 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Sep 2010 15:50:52 +0200 Subject: [PATCH 149/214] Support mixed inline and suffix commands --- grub-core/commands/legacycfg.c | 18 ++--- grub-core/lib/legacy_parse.c | 128 ++++++++++++++++++--------------- include/grub/legacy_parse.h | 2 +- util/grub-menulst2cfg.c | 26 +++---- 4 files changed, 94 insertions(+), 80 deletions(-) diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c index ca69a7817..bea608b9e 100644 --- a/grub-core/commands/legacycfg.c +++ b/grub-core/commands/legacycfg.c @@ -82,31 +82,31 @@ legacy_file (const char *filename) { char *oldname = NULL; - int is_suffix; + char *newsuffix; oldname = entryname; - parsed = grub_legacy_parse (buf, &entryname, &is_suffix); + parsed = grub_legacy_parse (buf, &entryname, &newsuffix); buf = NULL; - if (is_suffix) + if (newsuffix) { char *t; t = suffix; suffix = grub_realloc (suffix, grub_strlen (suffix) - + grub_strlen (parsed) + 1); + + grub_strlen (newsuffix) + 1); if (!suffix) { grub_free (t); grub_free (entrysrc); grub_free (parsed); + grub_free (newsuffix); grub_free (suffix); return grub_errno; } - grub_memcpy (suffix + grub_strlen (suffix), parsed, - grub_strlen (parsed) + 1); - grub_free (parsed); - parsed = NULL; - continue; + grub_memcpy (suffix + grub_strlen (suffix), newsuffix, + grub_strlen (newsuffix) + 1); + grub_free (newsuffix); + newsuffix = NULL; } if (oldname != entryname && oldname) { diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 096975434..692b1b7d4 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -26,6 +26,8 @@ struct legacy_command { const char *name; const char *map; + const char *suffix; + unsigned suffixarg; unsigned argc; enum arg_type { TYPE_VERBATIM, @@ -42,7 +44,6 @@ struct legacy_command } argt[4]; enum { FLAG_IGNORE_REST = 1, - FLAG_SUFFIX = 2, FLAG_FALLBACK_AVAILABLE = 4, FLAG_FALLBACK = 8, FLAG_COLOR_INVERT = 16, @@ -53,22 +54,22 @@ struct legacy_command struct legacy_command legacy_commands[] = { - {"blocklist", "blocklist '%s'\n", 1, {TYPE_FILE}, 0, "FILE", + {"blocklist", "blocklist '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILE", "Print the blocklist notation of the file FILE."}, - {"boot", "boot\n", 0, {}, 0, 0, + {"boot", "boot\n", NULL, 0, 0, {}, 0, 0, "Boot the OS/chain-loader which has been loaded."}, /* FIXME: bootp unsupported. */ - {"cat", "cat '%s'\n", 1, {TYPE_FILE}, 0, "FILE", + {"cat", "cat '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILE", "Print the contents of the file FILE."}, - {"chainloader", "chainloader %s '%s'\n", 2, {TYPE_FORCE_OPTION, TYPE_FILE}, - 0, "[--force] FILE", + {"chainloader", "chainloader %s '%s'\n", NULL, 0, + 2, {TYPE_FORCE_OPTION, TYPE_FILE}, 0, "[--force] FILE", "Load the chain-loader FILE. If --force is specified, then load it" " forcibly, whether the boot loader signature is present or not."}, - {"cmp", "cmp '%s' '%s'\n", 2, {TYPE_FILE, TYPE_FILE}, FLAG_IGNORE_REST, - "FILE1 FILE2", + {"cmp", "cmp '%s' '%s'\n", NULL, 0, + 2, {TYPE_FILE, TYPE_FILE}, FLAG_IGNORE_REST, "FILE1 FILE2", "Compare the file FILE1 with the FILE2 and inform the different values" " if any."}, - {"color", "set color_normal='%s'; set color_highlight='%s'\n", + {"color", "set color_normal='%s'; set color_highlight='%s'\n", NULL, 0, 2, {TYPE_VERBATIM, TYPE_VERBATIM}, FLAG_IGNORE_REST | FLAG_FALLBACK_AVAILABLE, "NORMAL [HIGHLIGHT]", "Change the menu colors. The color NORMAL is used for most" @@ -81,60 +82,62 @@ struct legacy_command legacy_commands[] = " light-green, light-cyan, light-red, light-magenta, yellow and white." " But only the first eight names can be used for BG. You can prefix" " \"blink-\" to FG if you want a blinking foreground color."}, - {"color", "set color_normal='%s'; set color_highlight='%s'\n", + {"color", "set color_normal='%s'; set color_highlight='%s'\n", NULL, 0, 1, {TYPE_VERBATIM}, FLAG_IGNORE_REST | FLAG_FALLBACK | FLAG_COLOR_INVERT, NULL, NULL}, - {"configfile", "legacy_configfile '%s'\n", 1, {TYPE_FILE}, 0, "FILE", - "Load FILE as the configuration file."}, + {"configfile", "legacy_configfile '%s'\n", NULL, 0, 1, {TYPE_FILE}, + 0, "FILE", "Load FILE as the configuration file."}, {"debug", - "if [ -z \"$debug\" ]; then set debug=all; else set debug=; fi\n", + "if [ -z \"$debug\" ]; then set debug=all; else set debug=; fi\n", NULL, 0, 0, {}, 0, 0, "Turn on/off the debug mode."}, {"default", "set default='%s'; if [ x\"$default\" = xsaved ]; then load_env; " - "set default=\"$saved_entry\"; fi\n", 1, {TYPE_VERBATIM}, 0, + "set default=\"$saved_entry\"; fi\n", NULL, 0, 1, {TYPE_VERBATIM}, 0, "[NUM | `saved']", "Set the default entry to entry number NUM (if not specified, it is" " 0, the first entry) or the entry number saved by savedefault."}, /* FIXME: dhcp unsupported. */ /* FIXME: displayapm unsupported. */ - {"displaymem", "lsmmap\n", 0, {}, 0, 0, + {"displaymem", "lsmmap\n", NULL, 0, 0, {}, 0, 0, "Display what GRUB thinks the system address space map of the" " machine is, including all regions of physical RAM installed."}, /* NOTE: embed unsupported. */ - {"fallback", "set fallback='%s'\n", 1, {TYPE_VERBATIM}, 0, "NUM...", + {"fallback", "set fallback='%s'\n", NULL, 0, + 1, {TYPE_VERBATIM}, 0, "NUM...", "Go into unattended boot mode: if the default boot entry has any" " errors, instead of waiting for the user to do anything, it" " immediately starts over using the NUM entry (same numbering as the" " `default' command). This obviously won't help if the machine" " was rebooted by a kernel that GRUB loaded."}, - {"find", "search -sf '%s'\n", 1, {TYPE_FILE}, 0, "FILENAME", + {"find", "search -sf '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILENAME", "Search for the filename FILENAME in all of partitions and print the list of" " the devices which contain the file."}, /* FIXME: fstest unsupported. */ /* FIXME: geometry unsupported. */ - {"halt", "halt %s\n", 1, {TYPE_NOAPM_OPTION}, 0, "[--no-apm]", + {"halt", "halt %s\n", NULL, 0, 1, {TYPE_NOAPM_OPTION}, 0, "[--no-apm]", "Halt your system. If APM is available on it, turn off the power using" " the APM BIOS, unless you specify the option `--no-apm'."}, /* FIXME: help unsupported. */ /* NUL_TERMINATE */ - {"hiddenmenu", "if sleep -i $timeout; then timeout=0; else timeout=-1; fi\n", - 0, {}, FLAG_SUFFIX, "", "Hide the menu."}, - {"hide", "parttool '%s' hidden+\n", 1, {TYPE_PARTITION}, 0, "PARTITION", + {"hiddenmenu", NULL, + "if sleep -i $timeout; then timeout=0; else timeout=-1; fi\n", 0, + 0, {}, 0, "", "Hide the menu."}, + {"hide", "parttool '%s' hidden+\n", NULL, 0, 1, {TYPE_PARTITION}, + 0, "PARTITION", "Hide PARTITION by setting the \"hidden\" bit in" " its partition type code."}, /* FIXME: ifconfig unsupported. */ /* FIXME: impsprobe unsupported. */ - {"initrd", "legacy_initrd '%s' %s\n", 2, {TYPE_FILE_NO_CONSUME, - TYPE_REST_VERBATIM}, 0, + {"initrd", "legacy_initrd '%s' %s\n", NULL, 0, 2, {TYPE_FILE_NO_CONSUME, + TYPE_REST_VERBATIM}, 0, "FILE [ARG ...]", "Load an initial ramdisk FILE for a Linux format boot image and set the" " appropriate parameters in the Linux setup area in memory."}, /* NOTE: install unsupported. */ /* FIXME: ioprobe unsupported. */ /* FIXME: really support --no-mem-option. */ - {"kernel", "legacy_kernel %s %s '%s' %s\n", 4, {TYPE_TYPE_OR_NOMEM_OPTION, - TYPE_TYPE_OR_NOMEM_OPTION, - TYPE_FILE_NO_CONSUME, - TYPE_REST_VERBATIM}, 0, + {"kernel", "legacy_kernel %s %s '%s' %s\n", NULL, 0, + 4, {TYPE_TYPE_OR_NOMEM_OPTION, TYPE_TYPE_OR_NOMEM_OPTION, + TYPE_FILE_NO_CONSUME, TYPE_REST_VERBATIM}, 0, "[--no-mem-option] [--type=TYPE] FILE [ARG ...]", "Attempt to load the primary boot image from FILE. The rest of the" " line is passed verbatim as the \"kernel command line\". Any modules" @@ -144,46 +147,49 @@ struct legacy_command legacy_commands[] = " \"multiboot\". The option --no-mem-option tells GRUB not to pass a" " Linux's mem option automatically."}, /* FIXME: lock is unsupported. */ - {"makeactive", "parttool \"$root\" boot+\n", 0, {}, 0, 0, + {"makeactive", "parttool \"$root\" boot+\n", NULL, 0, 0, {}, 0, 0, "Set the active partition on the root disk to GRUB's root device." " This command is limited to _primary_ PC partitions on a hard disk."}, - {"map", "drivemap '%s' '%s'\n", 2, {TYPE_PARTITION, TYPE_PARTITION}, + {"map", "drivemap '%s' '%s'\n", NULL, 0, + 2, {TYPE_PARTITION, TYPE_PARTITION}, FLAG_IGNORE_REST, "TO_DRIVE FROM_DRIVE", "Map the drive FROM_DRIVE to the drive TO_DRIVE. This is necessary" " when you chain-load some operating systems, such as DOS, if such an" " OS resides at a non-first drive."}, /* NOTE: md5crypt unsupported since GRUB has not enough entropy and this hash shouldn't be used anymore. */ - {"module", "legacy_initrd '%s' %s\n", 1, {TYPE_FILE_NO_CONSUME, - TYPE_REST_VERBATIM}, 0, + {"module", "legacy_initrd '%s' %s\n", NULL, 0, 2, {TYPE_FILE_NO_CONSUME, + TYPE_REST_VERBATIM}, 0, "FILE [ARG ...]", "Load a boot module FILE for a Multiboot format boot image (no" " interpretation of the file contents is made, so users of this" " command must know what the kernel in question expects). The" " rest of the line is passed as the \"module command line\", like" " the `kernel' command."}, - {"modulenounzip", "legacy_initrd_nounzip '%s' %s\n", 1, + {"modulenounzip", "legacy_initrd_nounzip '%s' %s\n", NULL, 0, 2, {TYPE_FILE_NO_CONSUME, TYPE_REST_VERBATIM}, 0, "FILE [ARG ...]", "The same as `module', except that automatic decompression is" " disabled."}, {"pager", "set pager=%s; if [ \"$pager\" = 0 ]; then " - " echo Internal pager is now off; else echo Internal pager is now on; fi\n", + " echo Internal pager is now off; else " + "echo Internal pager is now on; fi\n", NULL, 0, 1, {TYPE_BOOL}, FLAG_FALLBACK_AVAILABLE, "[FLAG]", "Toggle pager mode with no argument. If FLAG is given and its value" " is `on', turn on the mode. If FLAG is `off', turn off the mode."}, {"pager", "if [ \"$pager\" = 1 ]; then pager=0; echo Internal pager is now off;" - "else pager=1; echo Internal pager is now on; fi\n", 0, {}, + "else pager=1; echo Internal pager is now on; fi\n", NULL, 0, 0, {}, FLAG_FALLBACK, NULL, NULL}, /* FIXME: partnew unsupported. */ - {"parttype", "parttool '%s' type=%s\n", 2, {TYPE_PARTITION, TYPE_INT}, 0, + {"parttype", "parttool '%s' type=%s\n", NULL, 0, + 2, {TYPE_PARTITION, TYPE_INT}, 0, "PART TYPE", "Change the type of the partition PART to TYPE."}, /* FIXME: support config file reloading. */ /* FIXME: support usage in menuentry. */ {"password", "if [ \"$superusers\" = "" ]; then superusers=legacy; fi;\n" - "legacy_password %s '%s' %s", 3, {TYPE_OPTION, TYPE_VERBATIM, - TYPE_FILE}, FLAG_IGNORE_REST, + "legacy_password %s '%s' %s", NULL, 0, 3, {TYPE_OPTION, TYPE_VERBATIM, + TYPE_FILE}, FLAG_IGNORE_REST, "[--md5] PASSWD [FILE]", "If used in the first section of a menu file, disable all" " interactive editing control (menu entry editor and" @@ -197,15 +203,15 @@ struct legacy_command legacy_commands[] = /* NOTE: GRUB2 has a design principle of not eternally waiting for user input. 60 seconds should be enough. */ - {"pause", "echo %s; if ! sleep -i 60; then return; fi\n", 1, + {"pause", "echo %s; if ! sleep -i 60; then return; fi\n", NULL, 0, 1, {TYPE_REST_VERBATIM}, 0, "[MESSAGE ...]", "Print MESSAGE, then wait until a key is pressed."}, /* FIXME: rarp unsupported. */ - {"read", "read_dword %s\n", 1, {TYPE_INT}, 0, "ADDR", + {"read", "read_dword %s\n", NULL, 0, 1, {TYPE_INT}, 0, "ADDR", "Read a 32-bit value from memory at address ADDR and" " display it in hex format."}, - {"reboot", "reboot\n", 0, {}, 0, 0, "Reboot your system."}, - {"root", "set root='%s'; set legacy_hdbias='%s'\n", + {"reboot", "reboot\n", NULL, 0, 0, {}, 0, 0, "Reboot your system."}, + {"root", "set root='%s'; set legacy_hdbias='%s'\n", NULL, 0, 2, {TYPE_PARTITION, TYPE_INT}, FLAG_FALLBACK_AVAILABLE, "[DEVICE [HDBIAS]]", "Set the current \"root device\" to the device DEVICE, then" @@ -218,8 +224,8 @@ struct legacy_command legacy_commands[] = " how many BIOS drive numbers are on controllers before the current" " one. For example, if there is an IDE disk and a SCSI disk, and your" " FreeBSD root partition is on the SCSI disk, then use a `1' for HDBIAS."}, - {"root", "echo \"$root\"\n", 0, {}, FLAG_FALLBACK, NULL, NULL}, - {"rootnoverify", "set root='%s'; set legacy_hdbias='%s'\n", + {"root", "echo \"$root\"\n", NULL, 0, 0, {}, FLAG_FALLBACK, NULL, NULL}, + {"rootnoverify", "set root='%s'; set legacy_hdbias='%s'\n", NULL, 0, 2, {TYPE_PARTITION, TYPE_INT}, 0, "[DEVICE [HDBIAS]]", "Similar to `root', but don't attempt to mount the partition. This" @@ -227,14 +233,15 @@ struct legacy_command legacy_commands[] = " GRUB can read, but setting the correct root device is still" " desired. Note that the items mentioned in `root' which" " derived from attempting the mount will NOT work correctly."}, - {"rootnoverify", "echo \"$root\"\n", 0, {}, FLAG_FALLBACK, NULL, NULL}, + {"rootnoverify", "echo \"$root\"\n", NULL, 0, + 0, {}, FLAG_FALLBACK, NULL, NULL}, /* FIXME: support saving NUM and fallback. */ - {"savedefault", "saved_entry=${chosen}; save_env saved_entry\n", 0, {}, 0, - "[NUM | `fallback']", + {"savedefault", "saved_entry=${chosen}; save_env saved_entry\n", NULL, 0, + 0, {}, 0, "[NUM | `fallback']", "Save the current entry as the default boot entry if no argument is" " specified. If a number is specified, this number is saved. If" " `fallback' is used, next fallback entry is saved."}, - {"serial", "serial %s\n", 1, {TYPE_REST_VERBATIM}, 0, + {"serial", "serial %s\n", NULL, 0, 1, {TYPE_REST_VERBATIM}, 0, "[--unit=UNIT] [--port=PORT] [--speed=SPEED] [--word=WORD] " "[--parity=PARITY] [--stop=STOP] [--device=DEV]", "Initialize a serial device. UNIT is a digit that specifies which serial" @@ -248,25 +255,26 @@ struct legacy_command legacy_commands[] = /* FIXME: setup unsupported. */ /* FIXME: terminal unsupported. */ /* NUL_TERMINATE */ /* FIXME: terminfo unsupported. */ /* NUL_TERMINATE */ - {"testload", "cat '%s'\n", 1, {TYPE_FILE}, 0, "FILE", + {"testload", "cat '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILE", "Read the entire contents of FILE in several different ways and" " compares them, to test the filesystem code. " " If this test succeeds, then a good next" " step is to try loading a kernel."}, /* FIXME: testvbe unsupported. */ /* FIXME: tftpserver unsupported. */ - {"timeout", "set timeout=%s\n", 1, {TYPE_INT}, 0, "SEC", + {"timeout", "set timeout=%s\n", NULL, 0, 1, {TYPE_INT}, 0, "SEC", "Set a timeout, in SEC seconds, before automatically booting the" " default entry (normally the first entry defined)."}, /* title is handled separately. */ - {"unhide", "parttool '%s' hidden-\n", 1, {TYPE_PARTITION}, 0, "PARTITION", + {"unhide", "parttool '%s' hidden-\n", NULL, 0, + 1, {TYPE_PARTITION}, 0, "PARTITION", "Unhide PARTITION by clearing the \"hidden\" bit in its" " partition type code."}, /* FIXME: uppermem unsupported. */ - {"uuid", "search -u '%s'\n", 1, {TYPE_VERBATIM}, 0, "UUID", + {"uuid", "search -u '%s'\n", NULL, 0, 1, {TYPE_VERBATIM}, 0, "UUID", "Find root by UUID"}, /* FIXME: support MODE. */ - {"vbeprobe", "vbeinfo\n", 0, {}, 0, "[MODE]", + {"vbeprobe", "vbeinfo\n", NULL, 0, 0, {}, 0, "[MODE]", "Probe VBE information. If the mode number MODE is specified, show only" " the information about only the mode."} }; @@ -384,13 +392,13 @@ is_option (enum arg_type opt, const char *curarg, grub_size_t len) } char * -grub_legacy_parse (const char *buf, char **entryname, int *suffix) +grub_legacy_parse (const char *buf, char **entryname, char **suffix) { const char *ptr; const char *cmdname; unsigned i, cmdnum; - *suffix = 0; + *suffix = NULL; for (ptr = buf; *ptr && grub_isspace (*ptr); ptr++); if (!*ptr || *ptr == '#') @@ -437,8 +445,6 @@ grub_legacy_parse (const char *buf, char **entryname, int *suffix) if (cmdnum == ARRAY_SIZE (legacy_commands)) return grub_xasprintf ("# Unsupported legacy command: %s\n", buf); - *suffix = !!(legacy_commands[cmdnum].flags & FLAG_SUFFIX); - for (; grub_isspace (*ptr) || *ptr == '='; ptr++); char *args[ARRAY_SIZE (legacy_commands[0].argt)]; @@ -447,7 +453,7 @@ grub_legacy_parse (const char *buf, char **entryname, int *suffix) { int hold_arg = 0; const char *curarg = NULL; - for (i = 0; i < legacy_commands[cmdnum].argc + hold_arg; i++) + for (i = 0; i < legacy_commands[cmdnum].argc; i++) { grub_size_t curarglen; if (hold_arg) @@ -622,6 +628,14 @@ grub_legacy_parse (const char *buf, char **entryname, int *suffix) args[legacy_commands[cmdnum].argc] = invert; } + if (legacy_commands[cmdnum].suffix) + { + *suffix = grub_xasprintf (legacy_commands[cmdnum].suffix, + args[legacy_commands[cmdnum].suffixarg]); + if (*suffix) + return NULL; + } + { char *ret = grub_xasprintf (legacy_commands[cmdnum].map, args[0], args[1], args[2], args[3]); diff --git a/include/grub/legacy_parse.h b/include/grub/legacy_parse.h index a6394496f..a5e67a071 100644 --- a/include/grub/legacy_parse.h +++ b/include/grub/legacy_parse.h @@ -21,7 +21,7 @@ #include -char *grub_legacy_parse (const char *buf, char **entryname, int *suffix); +char *grub_legacy_parse (const char *buf, char **entryname, char **suffix); char *grub_legacy_escape (const char *in, grub_size_t len); #endif diff --git a/util/grub-menulst2cfg.c b/util/grub-menulst2cfg.c index 38a906c0a..512239e89 100644 --- a/util/grub-menulst2cfg.c +++ b/util/grub-menulst2cfg.c @@ -20,6 +20,7 @@ #include #include #include +#include int main (int argc, char **argv) @@ -30,7 +31,6 @@ main (int argc, char **argv) size_t bufsize = 0; char *suffix = xstrdup (""); int suffixlen = 0; - int is_suffix = 0; if (argc >= 2 && argv[1][0] == '-') { @@ -75,15 +75,15 @@ main (int argc, char **argv) { char *oldname = NULL; + char *newsuffix; oldname = entryname; - parsed = grub_legacy_parse (buf, &entryname, &is_suffix); - if (is_suffix) + parsed = grub_legacy_parse (buf, &entryname, &newsuffix); + if (newsuffix) { - suffixlen += strlen (parsed); + suffixlen += strlen (newsuffix); suffix = xrealloc (suffix, suffixlen + 1); - strcat (suffix, parsed); - continue; + strcat (suffix, newsuffix); } if (oldname != entryname && oldname) fprintf (out, "}\n\n"); @@ -91,25 +91,25 @@ main (int argc, char **argv) { char *escaped = grub_legacy_escape (entryname, strlen (entryname)); fprintf (out, "menuentry \'%s\' {\n", escaped); - grub_free (escaped); - grub_free (oldname); + free (escaped); + free (oldname); } } if (parsed) fprintf (out, "%s%s", entryname ? " " : "", parsed); - grub_free (parsed); + free (parsed); parsed = NULL; } if (entryname) fprintf (out, "}\n\n"); - fwrite (out, 1, suffixlen, suffix); + fwrite (suffix, 1, suffixlen, out); - grub_free (buf); - grub_free (suffix); - grub_free (entryname); + free (buf); + free (suffix); + free (entryname); if (in != stdin) fclose (in); From 6492c85a42ce35b170e4477243834cf969048916 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Sep 2010 15:54:39 +0200 Subject: [PATCH 150/214] Support config file reloading (not tested) --- grub-core/lib/legacy_parse.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 692b1b7d4..3f28544b3 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -185,12 +185,12 @@ struct legacy_command legacy_commands[] = {"parttype", "parttool '%s' type=%s\n", NULL, 0, 2, {TYPE_PARTITION, TYPE_INT}, 0, "PART TYPE", "Change the type of the partition PART to TYPE."}, - /* FIXME: support config file reloading. */ /* FIXME: support usage in menuentry. */ {"password", "if [ \"$superusers\" = "" ]; then superusers=legacy; fi;\n" - "legacy_password %s '%s' %s", NULL, 0, 3, {TYPE_OPTION, TYPE_VERBATIM, - TYPE_FILE}, FLAG_IGNORE_REST, - "[--md5] PASSWD [FILE]", + "legacy_password %s '%s'", + "menuentry \"Superuser menu\" --users \"legacy\" { configfile '%s'; }\n", + 2, 3, {TYPE_OPTION, TYPE_VERBATIM, TYPE_FILE}, + FLAG_IGNORE_REST | FLAG_FALLBACK_AVAILABLE, "[--md5] PASSWD [FILE]", "If used in the first section of a menu file, disable all" " interactive editing control (menu entry editor and" " command line). If the password PASSWD is entered, it loads the" @@ -200,6 +200,9 @@ struct legacy_command legacy_commands[] = " which case it will ask for the password, before continuing." " The option --md5 tells GRUB that PASSWD is encrypted with" " md5crypt."}, + {"password", "if [ \"$superusers\" = "" ]; then superusers=legacy; fi;\n" + "legacy_password %s '%s'", NULL, 0, 2, {TYPE_OPTION, TYPE_VERBATIM}, + FLAG_IGNORE_REST | FLAG_FALLBACK, NULL, NULL}, /* NOTE: GRUB2 has a design principle of not eternally waiting for user input. 60 seconds should be enough. */ From df8957929d631ffd298de7c2ab717c245934fe23 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Sep 2010 16:11:41 +0200 Subject: [PATCH 151/214] lock support (not tested) --- grub-core/lib/legacy_parse.c | 9 ++------- grub-core/normal/auth.c | 24 ++++++++++++++++++++++++ grub-core/normal/main.c | 2 ++ include/grub/normal.h | 3 +++ 4 files changed, 31 insertions(+), 7 deletions(-) diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 3f28544b3..868eab4ab 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -146,7 +146,8 @@ struct legacy_command legacy_commands[] = " \"netbsd\", \"freebsd\", \"openbsd\", \"linux\", \"biglinux\" and" " \"multiboot\". The option --no-mem-option tells GRUB not to pass a" " Linux's mem option automatically."}, - /* FIXME: lock is unsupported. */ + {"lock", "if ! authenticate legacy; then return; fi", NULL, 0, 0, {}, 0, + 0, "Break a command execution unless the user is authenticated."}, {"makeactive", "parttool \"$root\" boot+\n", NULL, 0, 0, {}, 0, 0, "Set the active partition on the root disk to GRUB's root device." " This command is limited to _primary_ PC partitions on a hard disk."}, @@ -435,12 +436,6 @@ grub_legacy_parse (const char *buf, char **entryname, char **suffix) return NULL; } - if (grub_strncmp ("lock", cmdname, ptr - cmdname) == 0 - && ptr - cmdname == sizeof ("lock") - 1) - { - /* FIXME */ - } - for (cmdnum = 0; cmdnum < ARRAY_SIZE (legacy_commands); cmdnum++) if (grub_strncmp (legacy_commands[cmdnum].name, cmdname, ptr - cmdname) == 0 && legacy_commands[cmdnum].name[ptr - cmdname] == 0) diff --git a/grub-core/normal/auth.c b/grub-core/normal/auth.c index bf1efbfdd..e5216da8c 100644 --- a/grub-core/normal/auth.c +++ b/grub-core/normal/auth.c @@ -248,3 +248,27 @@ grub_auth_check_authentication (const char *userlist) return GRUB_ACCESS_DENIED; } + +static grub_err_t +grub_cmd_authenticate (struct grub_command *cmd __attribute__ ((unused)), + int argc, char **args) +{ + return grub_auth_check_authentication ((argc >= 1) ? args[0] : ""); +} + +static grub_command_t cmd; + +void +grub_normal_auth_init (void) +{ + cmd = grub_register_command ("authenticate", + grub_cmd_authenticate, + N_("[USERLIST]"), N_("Authenticate users")); + +} + +void +grub_normal_auth_fini (void) +{ + grub_unregister_command (cmd); +} diff --git a/grub-core/normal/main.c b/grub-core/normal/main.c index c7e83fba0..f2e5eaf51 100644 --- a/grub-core/normal/main.c +++ b/grub-core/normal/main.c @@ -477,6 +477,7 @@ GRUB_MOD_INIT(normal) /* Previously many modules depended on gzio. Be nice to user and load it. */ grub_dl_load ("gzio"); + grub_normal_auth_init (); grub_context_init (); grub_script_init (); grub_menu_init (); @@ -520,6 +521,7 @@ GRUB_MOD_FINI(normal) grub_context_fini (); grub_script_fini (); grub_menu_fini (); + grub_normal_auth_fini (); grub_xputs = grub_xputs_saved; diff --git a/include/grub/normal.h b/include/grub/normal.h index 417560d9f..72912e524 100644 --- a/include/grub/normal.h +++ b/include/grub/normal.h @@ -123,4 +123,7 @@ grub_normal_add_menu_entry (int argc, const char **args, char **classes, grub_err_t grub_normal_set_password (const char *user, const char *password); +void grub_normal_auth_init (void); +void grub_normal_auth_fini (void); + #endif /* ! GRUB_NORMAL_HEADER */ From 898330b0973d88db9aebd15b08705485a1f433d1 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Sep 2010 16:15:40 +0200 Subject: [PATCH 152/214] MArk setup as not to be implemented --- grub-core/lib/legacy_parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 868eab4ab..5b5b4d6e2 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -256,7 +256,7 @@ struct legacy_command legacy_commands[] = " in the grub shell, which specifies the file name of a tty device. The" " default values are COM1, 9600, 8N1."}, /* FIXME: setkey unsupported. */ /* NUL_TERMINATE */ - /* FIXME: setup unsupported. */ + /* NOTE: setup unsupported. */ /* FIXME: terminal unsupported. */ /* NUL_TERMINATE */ /* FIXME: terminfo unsupported. */ /* NUL_TERMINATE */ {"testload", "cat '%s'\n", NULL, 0, 1, {TYPE_FILE}, 0, "FILE", From 84fb3b3d73b4a1d594cb750033930db640da084a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Sep 2010 20:12:16 +0200 Subject: [PATCH 153/214] * grub-core/commands/ls.c (grub_cmd_ls): Accept multiple files. --- ChangeLog | 4 ++++ grub-core/commands/ls.c | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 46f430bdc..72959e665 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2010-09-12 Vladimir Serbinenko + + * grub-core/commands/ls.c (grub_cmd_ls): Accept multiple files. + 2010-09-12 Vladimir Serbinenko * grub-core/kern/misc.c (grub_vprintf): Use va_copy when necessary. diff --git a/grub-core/commands/ls.c b/grub-core/commands/ls.c index 02915bac4..ed8afd4ae 100644 --- a/grub-core/commands/ls.c +++ b/grub-core/commands/ls.c @@ -253,12 +253,14 @@ static grub_err_t grub_cmd_ls (grub_extcmd_context_t ctxt, int argc, char **args) { struct grub_arg_list *state = ctxt->state; + int i; if (argc == 0) grub_ls_list_devices (state[0].set); else - grub_ls_list_files (args[0], state[0].set, state[2].set, - state[1].set); + for (i = 0; i < argc; i++) + grub_ls_list_files (args[i], state[0].set, state[2].set, + state[1].set); return 0; } From d8a84076eaa7c0cbc27644760bddf3054832ae53 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Sep 2010 20:15:30 +0200 Subject: [PATCH 154/214] * grub-core/commands/wildcard.c (make_regex): Escape brackets. --- ChangeLog | 4 ++++ grub-core/commands/wildcard.c | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 72959e665..2eaee5571 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2010-09-12 Vladimir Serbinenko + + * grub-core/commands/wildcard.c (make_regex): Escape brackets. + 2010-09-12 Vladimir Serbinenko * grub-core/commands/ls.c (grub_cmd_ls): Accept multiple files. diff --git a/grub-core/commands/wildcard.c b/grub-core/commands/wildcard.c index 64e2e3a54..6eab333b3 100644 --- a/grub-core/commands/wildcard.c +++ b/grub-core/commands/wildcard.c @@ -137,8 +137,10 @@ make_regex (const char *start, const char *end, regex_t *regexp) break; case '.': + case '(': + case ')': buffer[i++] = '\\'; - buffer[i++] = '.'; + buffer[i++] = ch; break; case '*': @@ -152,6 +154,7 @@ make_regex (const char *start, const char *end, regex_t *regexp) } buffer[i++] = '$'; buffer[i] = '\0'; + grub_dprintf ("expand", "Regexp is %s\n", buffer); if (regcomp (regexp, buffer, RE_SYNTAX_GNU_AWK)) { @@ -224,6 +227,7 @@ match_devices (const regex_t *regexp, int noparts) grub_dprintf ("expand", "matching: %s\n", buffer); if (regexec (regexp, buffer, 0, 0, 0)) { + grub_dprintf ("expand", "not matched\n"); grub_free (buffer); return 0; } From 2fc8ccb97fbfae43301a36b17d48c7560f18e537 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Sep 2010 20:18:50 +0200 Subject: [PATCH 155/214] * grub-core/normal/misc.c (grub_normal_print_device_info): Show partition size and offset. --- ChangeLog | 5 +++++ grub-core/normal/misc.c | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/ChangeLog b/ChangeLog index 2eaee5571..7d957c5cf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2010-09-12 Vladimir Serbinenko + + * grub-core/normal/misc.c (grub_normal_print_device_info): Show + partition size and offset. + 2010-09-12 Vladimir Serbinenko * grub-core/commands/wildcard.c (make_regex): Escape brackets. diff --git a/grub-core/normal/misc.c b/grub-core/normal/misc.c index 2b84b1c82..ad408074b 100644 --- a/grub-core/normal/misc.c +++ b/grub-core/normal/misc.c @@ -26,6 +26,7 @@ #include #include #include +#include /* Print the information on the device NAME. */ grub_err_t @@ -112,6 +113,16 @@ grub_normal_print_device_info (const char *name) else grub_printf ("%s", _("Partition table")); + if (dev->disk->partition) + grub_printf (_(" - Partition start at %u"), + grub_partition_get_start (dev->disk->partition)); + if (grub_disk_get_size (dev->disk) == GRUB_DISK_SIZE_UNKNOWN) + grub_printf (_(" - Total size unknown"), + grub_disk_get_size (dev->disk)); + else + grub_printf (_(" - Total size %u sectors"), + grub_disk_get_size (dev->disk)); + grub_device_close (dev); } From d547dc281c2a383917ce473860a8de04e29886b7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 12 Sep 2010 22:05:27 +0200 Subject: [PATCH 156/214] * grub-core/normal/term.c (put_glyphs_terminal): Correct sign. (print_backlog): set backlog_ucs4 and backlog_glyphs. Reported by: Yves Blusseau. --- ChangeLog | 6 ++++++ grub-core/normal/term.c | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 7d957c5cf..3e8ccf4eb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2010-09-12 Vladimir Serbinenko + + * grub-core/normal/term.c (put_glyphs_terminal): Correct sign. + (print_backlog): set backlog_ucs4 and backlog_glyphs. + Reported by: Yves Blusseau. + 2010-09-12 Vladimir Serbinenko * grub-core/normal/misc.c (grub_normal_print_device_info): Show diff --git a/grub-core/normal/term.c b/grub-core/normal/term.c index b55c0f06a..760900e86 100644 --- a/grub-core/normal/term.c +++ b/grub-core/normal/term.c @@ -657,7 +657,7 @@ put_glyphs_terminal (const struct grub_unicode_glyph *visual, >= (grub_ssize_t) grub_term_height (term) - 2) { state->backlog_glyphs = visual_ptr + 1; - state->backlog_len = visual_len - (visual - visual_ptr) - 1; + state->backlog_len = visual_len - (visual_ptr - visual) - 1; return 1; } @@ -688,6 +688,7 @@ print_backlog (struct grub_term_output *term, grub_free (state->free); state->free = NULL; state->backlog_len = 0; + state->backlog_ucs4 = 0; } return ret; } @@ -703,6 +704,7 @@ print_backlog (struct grub_term_output *term, grub_free (state->free); state->free = NULL; state->backlog_len = 0; + state->backlog_glyphs = 0; } return ret; } From b23ffd70eb42ef0a42ef30be6eada058f0bb8d47 Mon Sep 17 00:00:00 2001 From: Yves Blusseau Date: Mon, 13 Sep 2010 10:29:18 +0200 Subject: [PATCH 157/214] Bash completion script for util commands * Makefile.am: Add util/bash-completion.d directory * configure.ac: Likewise. * util/bash-completion.d/Makefile.am: New file. * util/bash-completion.d/grub-completion.bash.in: Likewise. --- ChangeLog | 9 + Makefile.am | 2 +- configure.ac | 1 + util/bash-completion.d/Makefile.am | 13 + .../bash-completion.d/grub-completion.bash.in | 467 ++++++++++++++++++ 5 files changed, 491 insertions(+), 1 deletion(-) create mode 100644 util/bash-completion.d/Makefile.am create mode 100644 util/bash-completion.d/grub-completion.bash.in diff --git a/ChangeLog b/ChangeLog index 3e8ccf4eb..53cf3501c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2010-09-13 Yves Blusseau + + Bash completion script for util commands + + * Makefile.am: Add util/bash-completion.d directory + * configure.ac: Likewise. + * util/bash-completion.d/Makefile.am: New file. + * util/bash-completion.d/grub-completion.bash.in: Likewise. + 2010-09-12 Vladimir Serbinenko * grub-core/normal/term.c (put_glyphs_terminal): Correct sign. diff --git a/Makefile.am b/Makefile.am index e0f2f013f..93d1e37fd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,7 @@ AUTOMAKE_OPTIONS = subdir-objects DEPDIR = .deps-util -SUBDIRS = . grub-core po docs +SUBDIRS = . grub-core po docs util/bash-completion.d include $(top_srcdir)/conf/Makefile.common include $(top_srcdir)/conf/Makefile.extra-dist diff --git a/configure.ac b/configure.ac index 9578f6518..e3116ee7e 100644 --- a/configure.ac +++ b/configure.ac @@ -939,6 +939,7 @@ AC_CONFIG_FILES([Makefile]) AC_CONFIG_FILES([grub-core/Makefile]) AC_CONFIG_FILES([po/Makefile]) AC_CONFIG_FILES([docs/Makefile]) +AC_CONFIG_FILES([util/bash-completion.d/Makefile]) AC_CONFIG_FILES([stamp-h], [echo timestamp > stamp-h]) AC_OUTPUT diff --git a/util/bash-completion.d/Makefile.am b/util/bash-completion.d/Makefile.am new file mode 100644 index 000000000..58171988d --- /dev/null +++ b/util/bash-completion.d/Makefile.am @@ -0,0 +1,13 @@ + +bash_completion_source = grub-completion.bash.in +bash_completion_script = grub + +EXTRA_DIST = $(bash_completion_source) + +CLEANFILES = $(bash_completion_script) + +bashcompletiondir = $(sysconfdir)/bash_completion.d +bashcompletion_DATA = $(bash_completion_script) + +$(bash_completion_script): $(bash_completion_source) $(top_builddir)/config.status + $(top_builddir)/config.status --file=$@:$< diff --git a/util/bash-completion.d/grub-completion.bash.in b/util/bash-completion.d/grub-completion.bash.in new file mode 100644 index 000000000..abba0df78 --- /dev/null +++ b/util/bash-completion.d/grub-completion.bash.in @@ -0,0 +1,467 @@ +# +# Bash completion for grub +# +# 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 . +# bash completion for grub + +__grub_dir() { + local i c=1 boot_dir + + for (( c=1; c <= ${#COMP_WORDS[@]}; c++ )); do + i="${COMP_WORDS[c]}" + case "$i" in + --boot-directory) + c=$((++c)) + i="${COMP_WORDS[c]}" + boot_dir="${i##*=}"; + break + ;; + esac + done + boot_dir=${boot_dir-/@bootdirname@} + echo "${boot_dir%/}/@grubdirname@" +} + + +# This function generates completion reply with compgen +# - arg: accepts 1, 2, 3, or 4 arguments +# $1 wordlist separate by space, tab or newline +# $2 (optional) prefix to add +# $3 (optional) current word to complete +# $4 (optional) suffix to add +__grubcomp () { + local cur="${COMP_WORDS[COMP_CWORD]}" + if [ $# -gt 2 ]; then + cur="$3" + fi + case "$cur" in + --*=) + COMPREPLY=() + ;; + *) + local IFS=' '$'\t'$'\n' + COMPREPLY=($(compgen -P "${2-}" -W "${1-}" -S "${4-}" -- "$cur")) + ;; + esac +} + +# Function that return long options from the help +# - arg: $1 (optional) command to get the long options from +__grub_get_options_from_help () { + local prog + + if [ $# -ge 1 ]; then + prog="$1" + else + prog="${COMP_WORDS[0]}" + fi + + local i IFS=" "$'\t'$'\n' + for i in $($prog --help) + do + case $i in + --*) echo "${i%=*}";; + esac + done +} + +__grub_get_last_option () { + local i + for (( i=$COMP_CWORD-1; i > 0; i-- )); do + if [[ "${COMP_WORDS[i]}" == -* ]]; then + echo "${COMP_WORDS[i]}" + break; + fi + done +} + +__grub_list_menuentries () { + local cur="${COMP_WORDS[COMP_CWORD]}" + local config_file=$(__grub_dir)/grub.cfg + + if [ -f "$config_file" ];then + local IFS=$'\n' + COMPREPLY=( $(compgen \ + -W "$( awk -F "[\"']" '/menuentry/ { print $2 }' $config_file )" \ + -- "$cur" )) #'# Help emacs syntax highlighting + fi +} + +__grub_list_modules () { + local grub_dir=$(__grub_dir) + local IFS=$'\n' + COMPREPLY=( $( compgen -f -X '!*/*.mod' -- "${grub_dir}/$cur" | { + while read -r tmp; do + [ -n $tmp ] && { + tmp=${tmp##*/} + printf '%s\n' ${tmp%.mod} + } + done + } + )) +} + +# +# grub-set-default & grub-reboot +# +_grub_set_entry () { + local cur prev split=false + + COMPREPLY=() + cur=`_get_cword` + prev=${COMP_WORDS[COMP_CWORD-1]} + + _split_longopt && split=true + + case "$prev" in + --boot-directory) + _filedir -d + return + ;; + esac + + $split && return 0 + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + # Default complete with a menuentry + __grub_list_menuentries + fi +} + +__grub_set_default_program=$( echo grub-set-default | sed "@program_transform_name@" ) +have ${__grub_set_default_program} && \ + complete -F _grub_set_entry -o filenames ${__grub_set_default_program} +unset __grub_set_default_program + +__grub_reboot_program=$( echo grub-reboot | sed "@program_transform_name@" ) +have ${__grub_reboot_program} && \ + complete -F _grub_set_entry -o filenames ${__grub_reboot_program} +unset __grub_reboot_program + + +# +# grub-editenv +# +_grub_editenv () { + local cur prev + + COMPREPLY=() + cur=`_get_cword` + prev=${COMP_WORDS[COMP_CWORD-1]} + + case "$prev" in + create|list|set|unset) + COMPREPLY=( "" ) + return + ;; + esac + + __grubcomp "$(__grub_get_options_from_help) + create list set unset" +} + +__grub_editenv_program=$( echo grub-editenv | sed "@program_transform_name@" ) +have ${__grub_editenv_program} && \ + complete -F _grub_editenv -o filenames ${__grub_editenv_program} +unset __grub_editenv_program + + +# +# grub-mkconfig +# +_grub_mkconfig () { + local cur prev + + COMPREPLY=() + cur=`_get_cword` + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + _filedir + fi +} +__grub_mkconfig_program=$( echo grub-mkconfig | sed "@program_transform_name@" ) +have ${__grub_mkconfig_program} && \ + complete -F _grub_mkconfig -o filenames ${__grub_mkconfig_program} +unset __grub_mkconfig_program + + +# +# grub-setup +# +_grub_setup () { + local cur prev split=false + + COMPREPLY=() + cur=`_get_cword` + prev=${COMP_WORDS[COMP_CWORD-1]} + + _split_longopt && split=true + + case "$prev" in + -d|--directory) + _filedir -d + return + ;; + esac + + $split && return 0 + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + # Default complete with a filename + _filedir + fi +} +__grub_setup_program=$( echo grub-setup | sed "@program_transform_name@" ) +have ${__grub_setup_program} && \ + complete -F _grub_setup -o filenames ${__grub_setup_program} +unset __grub_setup_program + + +# +# grub-install +# +_grub_install () { + local cur prev last split=false + + COMPREPLY=() + cur=`_get_cword` + prev=${COMP_WORDS[COMP_CWORD-1]} + last=$(__grub_get_last_option) + + _split_longopt && split=true + + case "$prev" in + --boot-directory) + _filedir -d + return + ;; + --disk-module) + __grubcomp "biosdisk ata" + return + ;; + esac + + $split && return 0 + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + case "$last" in + --modules) + __grub_list_modules + return + ;; + esac + + # Default complete with a filename + _filedir + fi +} +__grub_install_program=$( echo grub-install | sed "@program_transform_name@" ) +have ${__grub_install_program} && \ + complete -F _grub_install -o filenames ${__grub_install_program} +unset __grub_install_program + + +# +# grub-mkfont +# +_grub_mkfont () { + local cur + + COMPREPLY=() + cur=`_get_cword` + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + # Default complete with a filename + _filedir + fi +} +__grub_mkfont_program=$( echo grub-mkfont | sed "@program_transform_name@" ) +have ${__grub_mkfont_program} && \ + complete -F _grub_mkfont -o filenames ${__grub_mkfont_program} +unset __grub_mkfont_program + + +# +# grub-mkrescue +# +_grub_mkrescue () { + local cur prev last + + COMPREPLY=() + cur=`_get_cword` + prev=${COMP_WORDS[COMP_CWORD-1]} + last=$(__grub_get_last_option) + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + case "$last" in + --modules) + __grub_list_modules + return + ;; + esac + + # Default complete with a filename + _filedir + fi +} +__grub_mkrescue_program=$( echo grub-mkrescue | sed "@program_transform_name@" ) +have ${__grub_mkrescue_program} && \ + complete -F _grub_mkrescue -o filenames ${__grub_mkrescue_program} +unset __grub_mkrescue_program + + +# +# grub-mkimage +# +_grub_mkimage () { + local cur prev split=false + + COMPREPLY=() + cur=`_get_cword` + prev=${COMP_WORDS[COMP_CWORD-1]} + + _split_longopt && split=true + + case "$prev" in + -d|--directory|-p|--prefix) + _filedir -d + return + ;; + -O|--format) + # Get available format from help + local prog=${COMP_WORDS[0]} + __grubcomp "$($prog --help | \ + awk -F ":" '/available formats/ { print $2 }' | \ + sed 's/, / /g')" + return + ;; + esac + + $split && return 0 + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + # Default complete with a filename + _filedir + fi +} +__grub_mkimage_program=$( echo grub-mkimage | sed "@program_transform_name@" ) +have ${__grub_mkimage_program} && \ + complete -F _grub_mkimage -o filenames ${__grub_mkimage_program} +unset __grub_mkimage_program + + +# +# grub-mkpasswd-pbkdf2 +# +_grub_mkpasswd-pbkdf2 () { + local cur + + COMPREPLY=() + cur=`_get_cword` + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + # Default complete with a filename + _filedir + fi +} +__grub_mkpasswd_pbkdf2_program=$( echo grub-mkpasswd-pbkdf2 | sed "@program_transform_name@" ) +have ${__grub_mkpasswd_pbkdf2_program} && \ + complete -F _grub_mkpasswd-pbkdf2 -o filenames ${__grub_mkpasswd_pbkdf2_program} +unset __grub_mkpasswd_pbkdf2_program + + +# +# grub-probe +# +_grub_probe () { + local cur prev split=false + + COMPREPLY=() + cur=`_get_cword` + prev=${COMP_WORDS[COMP_CWORD-1]} + + _split_longopt && split=true + + case "$prev" in + -t|--target) + # Get target type from help + local prog=${COMP_WORDS[0]} + __grubcomp "$($prog --help | \ + awk -F "[()]" '/--target=/ { print $2 }' | \ + sed 's/|/ /g')" + return + ;; + esac + + $split && return 0 + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + # Default complete with a filename + _filedir + fi +} +__grub_probe_program=$( echo grub-probe | sed "@program_transform_name@" ) +have ${__grub_probe_program} && \ + complete -F _grub_probe -o filenames ${__grub_probe_program} +unset __grub_probe_program + + +# +# grub-script-check +# +_grub_script-check () { + local cur + + COMPREPLY=() + cur=`_get_cword` + + if [[ "$cur" == -* ]]; then + __grubcomp "$(__grub_get_options_from_help)" + else + # Default complete with a filename + _filedir + fi +} +__grub_script_check_program=$( echo grub-script-check | sed "@program_transform_name@" ) +have ${__grub_script_check_program} && \ + complete -F _grub_script-check -o filenames ${__grub_script_check_program} + + +# Local variables: +# mode: shell-script +# sh-basic-offset: 4 +# sh-indent-comment: t +# indent-tabs-mode: nil +# End: +# ex: ts=4 sw=4 et filetype=sh From 53d4ca1afcb194cf67426e9c423476497d393c80 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 13 Sep 2010 11:48:01 +0200 Subject: [PATCH 158/214] Change from direct arguments to --hint --- grub-core/commands/search_wrap.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/grub-core/commands/search_wrap.c b/grub-core/commands/search_wrap.c index 14028bec7..68497fa0d 100644 --- a/grub-core/commands/search_wrap.c +++ b/grub-core/commands/search_wrap.c @@ -37,6 +37,8 @@ static const struct grub_arg_option options[] = {"set", 's', GRUB_ARG_OPTION_OPTIONAL, N_("Set a variable to the first device found."), "VAR", ARG_TYPE_STRING}, {"no-floppy", 'n', 0, N_("Do not probe any floppy drive."), 0, 0}, + {"hint", 'h', GRUB_ARG_OPTION_REPEATABLE, + N_("First try the device HINT"), N_("HINT"), ARG_TYPE_STRING}, {0, 0, 0, 0, 0, 0} }; @@ -47,6 +49,7 @@ enum options SEARCH_FS_UUID, SEARCH_SET, SEARCH_NO_FLOPPY, + SEARCH_HINT }; static grub_err_t @@ -54,6 +57,11 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args) { struct grub_arg_list *state = ctxt->state; const char *var = 0; + int nhints = 0; + + if (state[SEARCH_HINT].set) + while (state[SEARCH_HINT].args[nhints]) + nhints++; if (argc == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, "no argument specified"); @@ -63,13 +71,13 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args) if (state[SEARCH_LABEL].set) grub_search_label (args[0], var, state[SEARCH_NO_FLOPPY].set, - (const char **) (args + 1), argc - 1); + (const char **) state[SEARCH_HINT].args, nhints); else if (state[SEARCH_FS_UUID].set) grub_search_fs_uuid (args[0], var, state[SEARCH_NO_FLOPPY].set, - (const char **) (args + 1), argc - 1); + (const char **) state[SEARCH_HINT].args, nhints); else if (state[SEARCH_FILE].set) grub_search_fs_file (args[0], var, state[SEARCH_NO_FLOPPY].set, - (const char **) (args + 1), argc - 1); + (const char **) state[SEARCH_HINT].args, nhints); else return grub_error (GRUB_ERR_INVALID_COMMAND, "unspecified search type"); @@ -83,7 +91,8 @@ GRUB_MOD_INIT(search) cmd = grub_register_extcmd ("search", grub_cmd_search, GRUB_COMMAND_FLAG_BOTH, - N_("[-f|-l|-u|-s|-n] NAME [HINTS]"), + N_("[-f|-l|-u|-s|-n] [--hint HINT [--hint HINT] ...]" + " NAME"), N_("Search devices by file, filesystem label" " or filesystem UUID." " If --set is specified, the first device found is" From 1f1dd48a1748e8bff5b5d7cb293d30468d403ed7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 13 Sep 2010 12:16:22 +0200 Subject: [PATCH 159/214] support subpartition hints --- grub-core/commands/search.c | 64 ++++++++++++++++++++++++++++++-- grub-core/commands/search_wrap.c | 9 +++-- include/grub/search.h | 6 +-- 3 files changed, 68 insertions(+), 11 deletions(-) diff --git a/grub-core/commands/search.c b/grub-core/commands/search.c index 9b693e76f..f265f86d6 100644 --- a/grub-core/commands/search.c +++ b/grub-core/commands/search.c @@ -28,10 +28,12 @@ #include #include #include +#include +#include void FUNC_NAME (const char *key, const char *var, int no_floppy, - const char **hints, unsigned nhints) + char **hints, unsigned nhints) { int count = 0; grub_fs_autoload_hook_t saved_autoload; @@ -115,13 +117,67 @@ FUNC_NAME (const char *key, const char *var, int no_floppy, return (found && var); } + auto int part_hook (grub_disk_t disk, const grub_partition_t partition); + int part_hook (grub_disk_t disk, const grub_partition_t partition) + { + char *partition_name, *devname; + int ret; + + partition_name = grub_partition_get_name (partition); + if (! partition_name) + return 1; + + devname = grub_xasprintf ("%s,%s", disk->name, partition_name); + grub_free (partition_name); + if (!devname) + return 1; + ret = iterate_device (devname); + grub_free (devname); + + return ret; + } + auto void try (void); void try (void) { unsigned i; for (i = 0; i < nhints; i++) - if (iterate_device (hints[i])) - return; + { + char *end; + if (!hints[i][0]) + continue; + end = hints[i] + grub_strlen (hints[i]) - 1; + if (*end == ',') + *end = 0; + if (iterate_device (hints[i])) + { + if (!*end) + *end = ','; + return; + } + if (!*end) + { + grub_device_t dev; + int ret; + dev = grub_device_open (hints[i]); + if (!dev) + { + *end = ','; + continue; + } + if (!dev->disk) + { + grub_device_close (dev); + *end = ','; + continue; + } + ret = grub_partition_iterate (dev->disk, part_hook); + *end = ','; + grub_device_close (dev); + if (ret) + return; + } + } grub_device_iterate (iterate_device); } @@ -153,7 +209,7 @@ grub_cmd_do_search (grub_command_t cmd __attribute__ ((unused)), int argc, if (argc == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, "no argument specified"); - FUNC_NAME (args[0], argc == 1 ? 0 : args[1], 0, (const char **) (args + 2), + FUNC_NAME (args[0], argc == 1 ? 0 : args[1], 0, (args + 2), argc > 2 ? argc - 2 : 0); return grub_errno; diff --git a/grub-core/commands/search_wrap.c b/grub-core/commands/search_wrap.c index 68497fa0d..61eb78203 100644 --- a/grub-core/commands/search_wrap.c +++ b/grub-core/commands/search_wrap.c @@ -38,7 +38,8 @@ static const struct grub_arg_option options[] = N_("Set a variable to the first device found."), "VAR", ARG_TYPE_STRING}, {"no-floppy", 'n', 0, N_("Do not probe any floppy drive."), 0, 0}, {"hint", 'h', GRUB_ARG_OPTION_REPEATABLE, - N_("First try the device HINT"), N_("HINT"), ARG_TYPE_STRING}, + N_("First try the device HINT. If HINT ends in comma, " + "also try subpartitions"), N_("HINT"), ARG_TYPE_STRING}, {0, 0, 0, 0, 0, 0} }; @@ -71,13 +72,13 @@ grub_cmd_search (grub_extcmd_context_t ctxt, int argc, char **args) if (state[SEARCH_LABEL].set) grub_search_label (args[0], var, state[SEARCH_NO_FLOPPY].set, - (const char **) state[SEARCH_HINT].args, nhints); + state[SEARCH_HINT].args, nhints); else if (state[SEARCH_FS_UUID].set) grub_search_fs_uuid (args[0], var, state[SEARCH_NO_FLOPPY].set, - (const char **) state[SEARCH_HINT].args, nhints); + state[SEARCH_HINT].args, nhints); else if (state[SEARCH_FILE].set) grub_search_fs_file (args[0], var, state[SEARCH_NO_FLOPPY].set, - (const char **) state[SEARCH_HINT].args, nhints); + state[SEARCH_HINT].args, nhints); else return grub_error (GRUB_ERR_INVALID_COMMAND, "unspecified search type"); diff --git a/include/grub/search.h b/include/grub/search.h index 3c56f0305..d80347df3 100644 --- a/include/grub/search.h +++ b/include/grub/search.h @@ -20,10 +20,10 @@ #define GRUB_SEARCH_HEADER 1 void grub_search_fs_file (const char *key, const char *var, int no_floppy, - const char **hints, unsigned nhints); + char **hints, unsigned nhints); void grub_search_fs_uuid (const char *key, const char *var, int no_floppy, - const char **hints, unsigned nhints); + char **hints, unsigned nhints); void grub_search_label (const char *key, const char *var, int no_floppy, - const char **hints, unsigned nhints); + char **hints, unsigned nhints); #endif From 0fd75223cca283694ffec2f74b2635604e1a3d5d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 13 Sep 2010 12:17:22 +0200 Subject: [PATCH 160/214] Add missing ChangeLog --- ChangeLog.hints | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 ChangeLog.hints diff --git a/ChangeLog.hints b/ChangeLog.hints new file mode 100644 index 000000000..16ae1cc90 --- /dev/null +++ b/ChangeLog.hints @@ -0,0 +1,6 @@ +2009-12-28 Vladimir Serbinenko + + Search hints support. + + * commands/search.c (FUNC_NAME): New arguments hints and nhints. + All users updated. From cf9827de73597be19869a6cdab1153baeb9af797 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 13 Sep 2010 13:09:58 +0200 Subject: [PATCH 161/214] Support explicit user claim that a device is BIOS-visible. * grub-core/kern/emu/getroot.c (grub_util_get_dev_abstraction): Return GRUB_DEV_ABSTRACTION_NONE if device is in device.map. * grub-core/kern/emu/hostdisk.c (convert_system_partition_to_system_disk): Support mdX. (find_system_device): New parameter add. All users updated. (grub_util_biosdisk_is_present): New function. * include/grub/emu/hostdisk.h (grub_util_biosdisk_is_present): New proto. --- ChangeLog | 13 +++++++++++++ grub-core/kern/emu/getroot.c | 4 ++++ grub-core/kern/emu/hostdisk.c | 28 ++++++++++++++++++++++++++-- include/grub/emu/hostdisk.h | 1 + 4 files changed, 44 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index c0b77d906..f6678af06 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2010-09-13 Vladimir Serbinenko + + Support explicit user claim that a device is BIOS-visible. + + * grub-core/kern/emu/getroot.c (grub_util_get_dev_abstraction): + Return GRUB_DEV_ABSTRACTION_NONE if device is in device.map. + * grub-core/kern/emu/hostdisk.c + (convert_system_partition_to_system_disk): Support mdX. + (find_system_device): New parameter add. All users updated. + (grub_util_biosdisk_is_present): New function. + * include/grub/emu/hostdisk.h (grub_util_biosdisk_is_present): New + proto. + 2010-09-13 Vladimir Serbinenko Search hints support. diff --git a/grub-core/kern/emu/getroot.c b/grub-core/kern/emu/getroot.c index c0a10d22b..32dcb49ca 100644 --- a/grub-core/kern/emu/getroot.c +++ b/grub-core/kern/emu/getroot.c @@ -572,6 +572,10 @@ int grub_util_get_dev_abstraction (const char *os_dev __attribute__((unused))) { #ifdef __linux__ + /* User explicitly claims that this drive is visible by BIOS. */ + if (grub_util_biosdisk_is_present (os_dev)) + return GRUB_DEV_ABSTRACTION_NONE; + /* Check for LVM. */ if (!strncmp (os_dev, "/dev/mapper/", 12) && ! grub_util_is_dmraid (os_dev) diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index 2cdf449e2..1eb6cb9d8 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -1117,6 +1117,16 @@ convert_system_partition_to_system_disk (const char *os_dev, struct stat *st) return path; } + if (strncmp ("md", p, 2) == 0 + && p[2] >= '0' && p[2] <= '9') + { + char *ptr = p + 2; + while (*ptr >= '0' && *ptr <= '9') + ptr++; + *ptr = 0; + return path; + } + /* If this is an IDE, SCSI or Virtio disk. */ if (strncmp ("vdisk", p, 5) == 0 && p[5] >= 'a' && p[5] <= 'z') @@ -1334,7 +1344,7 @@ device_is_wholedisk (const char *os_dev) #endif /* defined(__NetBSD__) */ static int -find_system_device (const char *os_dev, struct stat *st) +find_system_device (const char *os_dev, struct stat *st, int add) { unsigned int i; char *os_disk; @@ -1352,6 +1362,9 @@ find_system_device (const char *os_dev, struct stat *st) return i; } + if (!add) + return -1; + if (i == ARRAY_SIZE (map)) grub_util_error (_("device count exceeds limit")); @@ -1361,6 +1374,17 @@ find_system_device (const char *os_dev, struct stat *st) return i; } +int +grub_util_biosdisk_is_present (const char *os_dev) +{ + struct stat st; + + if (stat (os_dev, &st) < 0) + return 0; + + return find_system_device (os_dev, &st, 0) != -1; +} + char * grub_util_biosdisk_get_grub_dev (const char *os_dev) { @@ -1373,7 +1397,7 @@ grub_util_biosdisk_get_grub_dev (const char *os_dev) return 0; } - drive = find_system_device (os_dev, &st); + drive = find_system_device (os_dev, &st, 1); if (drive < 0) { grub_error (GRUB_ERR_UNKNOWN_DEVICE, diff --git a/include/grub/emu/hostdisk.h b/include/grub/emu/hostdisk.h index 246046ee0..5873aa440 100644 --- a/include/grub/emu/hostdisk.h +++ b/include/grub/emu/hostdisk.h @@ -26,5 +26,6 @@ void grub_util_biosdisk_init (const char *dev_map); void grub_util_biosdisk_fini (void); char *grub_util_biosdisk_get_grub_dev (const char *os_dev); const char *grub_util_biosdisk_get_osdev (grub_disk_t disk); +int grub_util_biosdisk_is_present (const char *name); #endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */ From f452b0404823d6b338ccc08bb2f355f4d9955080 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 13 Sep 2010 14:26:55 +0200 Subject: [PATCH 162/214] * grub-core/normal/completion.c (complete_file): Handle device containing slash. Fix based on patch by Doug Nazar. --- ChangeLog | 6 ++++++ grub-core/normal/completion.c | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 4a6fefc15..8a51142a9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2010-09-13 Vladimir Serbinenko + + * grub-core/normal/completion.c (complete_file): Handle device + containing slash. + Fix based on patch by Doug Nazar. + 2010-09-13 Vladimir Serbinenko grub-mknetdir script. diff --git a/grub-core/normal/completion.c b/grub-core/normal/completion.c index 1b51dab3a..a1e86adb0 100644 --- a/grub-core/normal/completion.c +++ b/grub-core/normal/completion.c @@ -247,7 +247,8 @@ complete_file (void) goto fail; } - dir = grub_strchr (current_word, '/'); + dir = grub_strchr (current_word + (device ? 2 + grub_strlen (device) : 0), + '/'); last_dir = grub_strrchr (current_word, '/'); if (dir) { From fb53b340aab6f2d3b4a9093080f8230fb37c6131 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 13 Sep 2010 16:49:50 +0200 Subject: [PATCH 163/214] Fix sparc64. * configure.ac (GRUB_KERNEL_MACHINE_LINK_ADDR): Removed. * grub-core/Makefile.core.def (kernel): Make ldflags just use the right address. Add sparc64_ieee1275_ldflags. * grub-core/loader/sparc64/ieee1275/linux.c: Remove leftover include. * util/grub-mkimagexx.c (locate_sections): Correct grub_host_to_target32 to grub_host_to_target_addr (load_image): Likewise. --- ChangeLog | 12 ++++++++++++ configure.ac | 12 ------------ grub-core/Makefile.core.def | 16 ++++++++-------- grub-core/loader/sparc64/ieee1275/linux.c | 1 - util/grub-mkimagexx.c | 8 ++++---- 5 files changed, 24 insertions(+), 25 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8a51142a9..96e2ebcf8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2010-09-13 Vladimir Serbinenko + + Fix sparc64. + + * configure.ac (GRUB_KERNEL_MACHINE_LINK_ADDR): Removed. + * grub-core/Makefile.core.def (kernel): Make ldflags just use the + right address. Add sparc64_ieee1275_ldflags. + * grub-core/loader/sparc64/ieee1275/linux.c: Remove leftover include. + * util/grub-mkimagexx.c (locate_sections): Correct grub_host_to_target32 + to grub_host_to_target_addr + (load_image): Likewise. + 2010-09-13 Vladimir Serbinenko * grub-core/normal/completion.c (complete_file): Handle device diff --git a/configure.ac b/configure.ac index e3116ee7e..e519fdd1a 100644 --- a/configure.ac +++ b/configure.ac @@ -867,20 +867,8 @@ pkglibrootdir='$(libdir)'/`echo $PACKAGE | sed "$program_transform_name"` AC_SUBST(pkglibrootdir) AC_SUBST([FONT_SOURCE]) -AS_IF([test x$target_cpu = xi386 -a x$platform = xpc], - [AC_SUBST([GRUB_KERNEL_MACHINE_LINK_ADDR], 0x8200)]) -AS_IF([test x$target_cpu = xi386 -a x$platform = xcoreboot], - [AC_SUBST([GRUB_KERNEL_MACHINE_LINK_ADDR], 0x8200)]) -AS_IF([test x$target_cpu = xi386 -a x$platform = xmultiboot], - [AC_SUBST([GRUB_KERNEL_MACHINE_LINK_ADDR], 0x8200)]) -AS_IF([test x$target_cpu = xmips -a x$platform = xyeeloong], - [AC_SUBST([GRUB_KERNEL_MACHINE_LINK_ADDR], 0x80200000)]) -AS_IF([test x$target_cpu = xpowerpc -a x$platform = xieee1275], - [AC_SUBST([GRUB_KERNEL_MACHINE_LINK_ADDR], 0x200000)]) AS_IF([test x$target_cpu = xi386 -a x$platform = xqemu], [AC_SUBST([GRUB_BOOT_MACHINE_LINK_ADDR], 0xffe00)]) -AS_IF([test x$target_cpu = xi386 -a x$platform = xieee1275], - [AC_SUBST([GRUB_KERNEL_MACHINE_LINK_ADDR], 0x10000)]) AS_IF([test x$TARGET_APPLE_CC = x1], [AC_SUBST([USE_APPLE_CC_FIXES], yes)]) diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 9100c6033..902ab48a8 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -10,20 +10,20 @@ kernel = { x86_efi_stripflags = '--strip-unneeded -K start -R .note -R .comment'; i386_pc_ldflags = '$(TARGET_IMG_LDFLAGS)'; - i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),$(GRUB_KERNEL_MACHINE_LINK_ADDR)'; + i386_pc_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200'; i386_qemu_ldflags = '$(TARGET_IMG_LDFLAGS)'; - i386_qemu_ldflags = '$(TARGET_IMG_BASE_LDOPT),$(GRUB_KERNEL_MACHINE_LINK_ADDR)'; + i386_qemu_ldflags = '$(TARGET_IMG_BASE_LDOPT),0x8200'; - i386_coreboot_ldflags = '-Wl,-Ttext=$(GRUB_KERNEL_MACHINE_LINK_ADDR)'; - i386_multiboot_ldflags = '-Wl,-Ttext=$(GRUB_KERNEL_MACHINE_LINK_ADDR)'; - i386_ieee1275_ldflags = '-Wl,-Ttext=$(GRUB_KERNEL_MACHINE_LINK_ADDR)'; - mips_yeeloong_ldflags = '-Wl,-Ttext,$(GRUB_KERNEL_MACHINE_LINK_ADDR)'; - powerpc_ieee1275_ldflags = '-Wl,-Ttext,$(GRUB_KERNEL_MACHINE_LINK_ADDR)'; + i386_coreboot_ldflags = '-Wl,-Ttext=0x8200'; + i386_multiboot_ldflags = '-Wl,-Ttext=0x8200'; + i386_ieee1275_ldflags = '-Wl,-Ttext=0x10000'; + mips_yeeloong_ldflags = '-Wl,-Ttext,0x80200000'; + powerpc_ieee1275_ldflags = '-Wl,-Ttext,0x200000'; + sparc64_ieee1275_ldflags = '-Wl,-Ttext,0x4400'; mips_yeeloong_cppflags = '-DUSE_ASCII_FAILBACK'; i386_qemu_cppflags = '-DGRUB_BOOT_MACHINE_LINK_ADDR=$(GRUB_BOOT_MACHINE_LINK_ADDR)'; - i386_qemu_ccasflags = '-DGRUB_KERNEL_MACHINE_LINK_ADDR=$(GRUB_KERNEL_MACHINE_LINK_ADDR)'; emu_cflags = '$(CFLAGS_GNULIB)'; emu_cppflags = '$(CPPFLAGS_GNULIB)'; diff --git a/grub-core/loader/sparc64/ieee1275/linux.c b/grub-core/loader/sparc64/ieee1275/linux.c index 177a6976e..010353dc5 100644 --- a/grub-core/loader/sparc64/ieee1275/linux.c +++ b/grub-core/loader/sparc64/ieee1275/linux.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include diff --git a/util/grub-mkimagexx.c b/util/grub-mkimagexx.c index 4a257e329..ce51f2fbc 100644 --- a/util/grub-mkimagexx.c +++ b/util/grub-mkimagexx.c @@ -555,7 +555,7 @@ SUFFIX (locate_sections) (Elf_Shdr *sections, Elf_Half section_entsize, i++, s = (Elf_Shdr *) ((char *) s + section_entsize)) if (SUFFIX (is_text_section) (s, image_target)) { - Elf_Word align = grub_host_to_target32 (s->sh_addralign); + Elf_Word align = grub_host_to_target_addr (s->sh_addralign); const char *name = strtab + grub_host_to_target32 (s->sh_name); if (align) current_address = ALIGN_UP (current_address + image_target->vaddr_offset, @@ -577,7 +577,7 @@ SUFFIX (locate_sections) (Elf_Shdr *sections, Elf_Half section_entsize, i++, s = (Elf_Shdr *) ((char *) s + section_entsize)) if (SUFFIX (is_data_section) (s, image_target)) { - Elf_Word align = grub_host_to_target32 (s->sh_addralign); + Elf_Word align = grub_host_to_target_addr (s->sh_addralign); const char *name = strtab + grub_host_to_target32 (s->sh_name); if (align) @@ -641,7 +641,7 @@ SUFFIX (load_image) (const char *kernel_path, grub_size_t *exec_size, /* Relocate sections then symbols in the virtual address space. */ s = (Elf_Shdr *) ((char *) sections + grub_host_to_target16 (e->e_shstrndx) * section_entsize); - strtab = (char *) e + grub_host_to_target32 (s->sh_offset); + strtab = (char *) e + grub_host_to_target_addr (s->sh_offset); section_addresses = SUFFIX (locate_sections) (sections, section_entsize, num_sections, strtab, @@ -662,7 +662,7 @@ SUFFIX (load_image) (const char *kernel_path, grub_size_t *exec_size, i++, s = (Elf_Shdr *) ((char *) s + section_entsize)) if (grub_target_to_host32 (s->sh_type) == SHT_NOBITS) { - Elf_Word align = grub_host_to_target32 (s->sh_addralign); + Elf_Word align = grub_host_to_target_addr (s->sh_addralign); const char *name = strtab + grub_host_to_target32 (s->sh_name); if (align) From b2a30ac5e46131c647d660d6c67ff7e60e4db178 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 13 Sep 2010 19:17:29 +0200 Subject: [PATCH 164/214] Filter devaliases and never open same device twice. * grub-core/disk/ieee1275/ofdisk.c (last_devpath): New variable. (last_ihandle): Likewise. (ofdisk_hash_ent): New member shortest. (ofdisk_hash_add): Add canonical path too. (scan): New function. (grub_ofdisk_iterate): Iterate over hashed entries. (compute_dev_path): Don't add :0. (grub_ofdisk_open): Don't really open the disk. (grub_ofdisk_close): Avoid closing unrelated disk. (grub_ofdisk_read): Implement reopen logic. * grub-core/kern/ieee1275/openfw.c (grub_ieee1275_canonicalise_devname): New function. * include/grub/ieee1275/ieee1275.h (grub_ieee1275_canonicalise_devname): New proto. --- ChangeLog | 19 +++ grub-core/disk/ieee1275/ofdisk.c | 248 ++++++++++++++++++++----------- grub-core/kern/ieee1275/openfw.c | 44 ++++++ include/grub/ieee1275/ieee1275.h | 2 + 4 files changed, 227 insertions(+), 86 deletions(-) diff --git a/ChangeLog b/ChangeLog index 96e2ebcf8..8751b8daf 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2010-09-13 Vladimir Serbinenko + + Filter devaliases and never open same device twice. + + * grub-core/disk/ieee1275/ofdisk.c (last_devpath): New variable. + (last_ihandle): Likewise. + (ofdisk_hash_ent): New member shortest. + (ofdisk_hash_add): Add canonical path too. + (scan): New function. + (grub_ofdisk_iterate): Iterate over hashed entries. + (compute_dev_path): Don't add :0. + (grub_ofdisk_open): Don't really open the disk. + (grub_ofdisk_close): Avoid closing unrelated disk. + (grub_ofdisk_read): Implement reopen logic. + * grub-core/kern/ieee1275/openfw.c (grub_ieee1275_canonicalise_devname): + New function. + * include/grub/ieee1275/ieee1275.h (grub_ieee1275_canonicalise_devname): + New proto. + 2010-09-13 Vladimir Serbinenko Fix sparc64. diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c index d0d9e894f..3d9976257 100644 --- a/grub-core/disk/ieee1275/ofdisk.c +++ b/grub-core/disk/ieee1275/ofdisk.c @@ -23,9 +23,15 @@ #include #include +static char *last_devpath; +static grub_ieee1275_ihandle_t last_ihandle; + struct ofdisk_hash_ent { char *devpath; + /* Pointer to shortest available name on nodes representing canonical names, + otherwise NULL. */ + const char *shortest; struct ofdisk_hash_ent *next; }; @@ -59,60 +65,125 @@ static struct ofdisk_hash_ent * ofdisk_hash_add (char *devpath) { struct ofdisk_hash_ent **head = &ofdisk_hash[ofdisk_hash_fn(devpath)]; - struct ofdisk_hash_ent *p = grub_malloc(sizeof (*p)); + struct ofdisk_hash_ent *p, *pcan; + char *curcan; - if (p) + p = grub_malloc(sizeof (*p)); + if (!p) + return NULL; + + p->devpath = devpath; + p->next = *head; + p->shortest = 0; + *head = p; + + curcan = grub_ieee1275_canonicalise_devname (devpath); + if (!curcan) { - p->devpath = devpath; - p->next = *head; - *head = p; + grub_errno = GRUB_ERR_NONE; + return p; } + + pcan = ofdisk_hash_find (curcan); + if (!pcan) + pcan = ofdisk_hash_add (curcan); + else + grub_free (curcan); + + if (!pcan) + grub_errno = GRUB_ERR_NONE; + else + { + if (!pcan->shortest + || grub_strlen (pcan->shortest) > grub_strlen (devpath)) + pcan->shortest = devpath; + } + return p; } -static int -grub_ofdisk_iterate (int (*hook) (const char *name)) +static void +scan (void) { auto int dev_iterate (struct grub_ieee1275_devalias *alias); int dev_iterate (struct grub_ieee1275_devalias *alias) { - int ret = 0; + struct ofdisk_hash_ent *op; + + grub_dprintf ("disk", "device name = %s type = %s\n", alias->name, + alias->type); + + if (grub_strcmp (alias->type, "block") != 0) + return 0; grub_dprintf ("disk", "disk name = %s\n", alias->name); - if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY)) + op = ofdisk_hash_find (alias->path); + if (!op) { - grub_ieee1275_phandle_t dev; - char tmp[8]; - - if (grub_ieee1275_finddevice (alias->path, &dev)) + char *name = grub_strdup (alias->name); + if (!name) { - grub_dprintf ("disk", "finddevice (%s) failed\n", alias->path); - return 0; - } - - if (grub_ieee1275_get_property (dev, "iconname", tmp, - sizeof tmp, 0)) - { - grub_dprintf ("disk", "get iconname failed\n"); - return 0; - } - - if (grub_strcmp (tmp, "sdmmc")) - { - grub_dprintf ("disk", "device is not an SD card\n"); + grub_errno = GRUB_ERR_NONE; return 0; } + op = ofdisk_hash_add (name); } - - if (! grub_strcmp (alias->type, "block") && - grub_strncmp (alias->name, "cdrom", 5)) - ret = hook (alias->name); - return ret; + return 0; } - return grub_devalias_iterate (dev_iterate); + grub_devalias_iterate (dev_iterate); + grub_ieee1275_devices_iterate (dev_iterate); +} + +static int +grub_ofdisk_iterate (int (*hook) (const char *name)) +{ + unsigned i; + scan (); + + for (i = 0; i < ARRAY_SIZE (ofdisk_hash); i++) + { + static struct ofdisk_hash_ent *ent; + for (ent = ofdisk_hash[i]; ent; ent = ent->next) + { + if (!ent->shortest) + continue; + if (grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_OFDISK_SDCARD_ONLY)) + { + grub_ieee1275_phandle_t dev; + char tmp[8]; + + if (grub_ieee1275_finddevice (ent->devpath, &dev)) + { + grub_dprintf ("disk", "finddevice (%s) failed\n", + ent->devpath); + continue; + } + + if (grub_ieee1275_get_property (dev, "iconname", tmp, + sizeof tmp, 0)) + { + grub_dprintf ("disk", "get iconname failed\n"); + continue; + } + + if (grub_strcmp (tmp, "sdmmc") != 0) + { + grub_dprintf ("disk", "device is not an SD card\n"); + continue; + } + } + + if (grub_strncmp (ent->shortest, "cdrom", 5) == 0) + continue; + + if (hook (ent->shortest)) + return 1; + } + } + return 0; } static char * @@ -137,11 +208,6 @@ compute_dev_path (const char *name) *p++ = c; } - if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0)) - { - *p++ = ':'; - *p++ = '0'; - } *p++ = '\0'; return devpath; @@ -151,8 +217,6 @@ static grub_err_t grub_ofdisk_open (const char *name, grub_disk_t disk) { grub_ieee1275_phandle_t dev; - grub_ieee1275_ihandle_t dev_ihandle = 0; - struct ofdisk_hash_ent *op; char *devpath; /* XXX: This should be large enough for any possible case. */ char prop[64]; @@ -162,69 +226,52 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) if (! devpath) return grub_errno; - op = ofdisk_hash_find (devpath); - if (!op) - op = ofdisk_hash_add (devpath); + grub_dprintf ("disk", "Opening `%s'.\n", devpath); - grub_free (devpath); - if (!op) - return grub_errno; - - grub_dprintf ("disk", "Opening `%s'.\n", op->devpath); - - if (grub_ieee1275_finddevice (op->devpath, &dev)) - { - grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read device properties"); - goto fail; - } + if (grub_ieee1275_finddevice (devpath, &dev)) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read device properties"); if (grub_ieee1275_get_property (dev, "device_type", prop, sizeof (prop), &actual)) - { - grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read the device type"); - goto fail; - } + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't read the device type"); if (grub_strcmp (prop, "block")) - { - grub_error (GRUB_ERR_BAD_DEVICE, "not a block device"); - goto fail; - } - - grub_ieee1275_open (op->devpath, &dev_ihandle); - if (! dev_ihandle) - { - grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); - goto fail; - } - - grub_dprintf ("disk", "Opened `%s' as handle %p.\n", op->devpath, - (void *) (unsigned long) dev_ihandle); + return grub_error (GRUB_ERR_BAD_DEVICE, "not a block device"); /* XXX: There is no property to read the number of blocks. There should be a property `#blocks', but it is not there. Perhaps it is possible to use seek for this. */ disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN; - disk->id = (unsigned long) op; + { + struct ofdisk_hash_ent *op; + op = ofdisk_hash_find (devpath); + if (!op) + op = ofdisk_hash_add (devpath); + else + grub_free (devpath); + if (!op) + return grub_errno; + disk->id = (unsigned long) op; + disk->data = op->devpath; + } /* XXX: Read this, somehow. */ disk->has_partitions = 1; - disk->data = (void *) (unsigned long) dev_ihandle; return 0; - - fail: - if (dev_ihandle) - grub_ieee1275_close (dev_ihandle); - return grub_errno; } static void grub_ofdisk_close (grub_disk_t disk) { - grub_dprintf ("disk", "Closing handle %p.\n", - (void *) disk->data); - grub_ieee1275_close ((grub_ieee1275_ihandle_t) (unsigned long) disk->data); + if (disk->data == last_devpath) + { + if (last_ihandle) + grub_ieee1275_close (last_ihandle); + last_ihandle = 0; + last_devpath = NULL; + } + disk->data = 0; } static grub_err_t @@ -234,16 +281,40 @@ grub_ofdisk_read (grub_disk_t disk, grub_disk_addr_t sector, grub_ssize_t status, actual; unsigned long long pos; + if (disk->data != last_devpath) + { + if (last_ihandle) + grub_ieee1275_close (last_ihandle); + last_ihandle = 0; + last_devpath = NULL; + + if (! grub_ieee1275_test_flag (GRUB_IEEE1275_FLAG_NO_PARTITION_0)) + { + char name2[grub_strlen (disk->data) + 3]; + char *p; + + grub_strcpy (name2, disk->data); + p = name2 + grub_strlen (name2); + *p++ = ':'; + *p++ = '0'; + *p = 0; + grub_ieee1275_open (name2, &last_ihandle); + } + else + grub_ieee1275_open (disk->data, &last_ihandle); + if (! last_ihandle) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "can't open device"); + last_devpath = disk->data; + } + pos = sector * 512UL; - grub_ieee1275_seek ((grub_ieee1275_ihandle_t) (unsigned long) disk->data, - pos, &status); + grub_ieee1275_seek (last_ihandle, pos, &status); if (status < 0) return grub_error (GRUB_ERR_READ_ERROR, "seek error, can't seek block %llu", (long long) sector); - grub_ieee1275_read ((grub_ieee1275_ihandle_t) (unsigned long) disk->data, - buf, size * 512UL, &actual); + grub_ieee1275_read (last_ihandle, buf, size * 512UL, &actual); if (actual != (grub_ssize_t) (size * 512UL)) return grub_error (GRUB_ERR_READ_ERROR, "read error on block: %llu", (long long) sector); @@ -281,5 +352,10 @@ grub_ofdisk_init (void) void grub_ofdisk_fini (void) { + if (last_ihandle) + grub_ieee1275_close (last_ihandle); + last_ihandle = 0; + last_devpath = NULL; + grub_disk_dev_unregister (&grub_ofdisk_dev); } diff --git a/grub-core/kern/ieee1275/openfw.c b/grub-core/kern/ieee1275/openfw.c index fcd43f617..f5dc8efb1 100644 --- a/grub-core/kern/ieee1275/openfw.c +++ b/grub-core/kern/ieee1275/openfw.c @@ -423,3 +423,47 @@ grub_reboot (void) for (;;) ; } #endif + +/* Resolve aliases. */ +char * +grub_ieee1275_canonicalise_devname (const char *path) +{ + struct canon_args + { + struct grub_ieee1275_common_hdr common; + grub_ieee1275_cell_t path; + grub_ieee1275_cell_t buf; + grub_ieee1275_cell_t inlen; + grub_ieee1275_cell_t outlen; + } + args; + char *buf = NULL; + grub_size_t bufsize = 64; + int i; + + for (i = 0; i < 2; i++) + { + grub_free (buf); + + buf = grub_malloc (bufsize); + if (!buf) + return NULL; + + INIT_IEEE1275_COMMON (&args.common, "canon", 3, 1); + args.path = (grub_ieee1275_cell_t) path; + args.buf = (grub_ieee1275_cell_t) buf; + args.inlen = (grub_ieee1275_cell_t) (bufsize - 1); + + if (IEEE1275_CALL_ENTRY_FN (&args) == -1) + return 0; + if (args.outlen > bufsize - 1) + { + bufsize = args.outlen + 2; + continue; + } + return buf; + } + /* Shouldn't reach here. */ + grub_free (buf); + return NULL; +} diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h index 6835b5abc..2592dd348 100644 --- a/include/grub/ieee1275/ieee1275.h +++ b/include/grub/ieee1275/ieee1275.h @@ -190,4 +190,6 @@ int EXPORT_FUNC(grub_ieee1275_devices_iterate) (int (*hook) (struct grub_ieee1275_devalias * alias)); +char *EXPORT_FUNC(grub_ieee1275_canonicalise_devname) (const char *path); + #endif /* ! GRUB_IEEE1275_HEADER */ From 54ac3cd189cc3f4c19ad28beca715bbf059ab614 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 13 Sep 2010 20:10:41 +0200 Subject: [PATCH 165/214] * grub-core/video/efi_gop.c: Fix over-80-chars line. * grub-core/video/efi_uga.c: Likewise. --- ChangeLog | 5 +++++ grub-core/video/efi_gop.c | 3 ++- grub-core/video/efi_uga.c | 3 ++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8751b8daf..58fbf36cc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2010-09-13 Vladimir Serbinenko + + * grub-core/video/efi_gop.c: Fix over-80-chars line. + * grub-core/video/efi_uga.c: Likewise. + 2010-09-13 Vladimir Serbinenko Filter devaliases and never open same device twice. diff --git a/grub-core/video/efi_gop.c b/grub-core/video/efi_gop.c index cb04667eb..f02dc9cb6 100644 --- a/grub-core/video/efi_gop.c +++ b/grub-core/video/efi_gop.c @@ -220,7 +220,8 @@ grub_video_gop_iterate (int (*hook) (const struct grub_video_mode_info *info)) static grub_err_t grub_video_gop_setup (unsigned int width, unsigned int height, - unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused))) + unsigned int mode_type, + unsigned int mode_mask __attribute__ ((unused))) { unsigned int depth; struct grub_efi_gop_mode_info *info = NULL; diff --git a/grub-core/video/efi_uga.c b/grub-core/video/efi_uga.c index 6352d4342..a8f70edea 100644 --- a/grub-core/video/efi_uga.c +++ b/grub-core/video/efi_uga.c @@ -198,7 +198,8 @@ grub_video_uga_fini (void) static grub_err_t grub_video_uga_setup (unsigned int width, unsigned int height, - unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused))) + unsigned int mode_type, + unsigned int mode_mask __attribute__ ((unused))) { unsigned int depth; int found = 0; From 0575c7c3eccef42e03b21633d5647387a6596e73 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 13 Sep 2010 20:16:51 +0200 Subject: [PATCH 166/214] * grub-core/commands/iorw.c (grub_cmd_read): Declare buf in smallest context. --- ChangeLog | 5 +++++ grub-core/commands/iorw.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 58fbf36cc..8b959c0f4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2010-09-13 Vladimir Serbinenko + + * grub-core/commands/iorw.c (grub_cmd_read): Declare buf in smallest + context. + 2010-09-13 Vladimir Serbinenko * grub-core/video/efi_gop.c: Fix over-80-chars line. diff --git a/grub-core/commands/iorw.c b/grub-core/commands/iorw.c index bd0183794..5157ebd4c 100644 --- a/grub-core/commands/iorw.c +++ b/grub-core/commands/iorw.c @@ -40,7 +40,6 @@ grub_cmd_read (grub_extcmd_context_t ctxt, int argc, char **argv) { grub_target_addr_t addr; grub_uint32_t value = 0; - char buf[sizeof ("XXXXXXXX")]; if (argc != 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid number of arguments"); @@ -63,6 +62,7 @@ grub_cmd_read (grub_extcmd_context_t ctxt, int argc, char **argv) if (ctxt->state[0].set) { + char buf[sizeof ("XXXXXXXX")]; grub_snprintf (buf, sizeof (buf), "%x", value); grub_env_set (ctxt->state[0].arg, buf); } From 2419f17a09037635044ef7f2eea7ae2089c81be5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 13 Sep 2010 20:29:15 +0200 Subject: [PATCH 167/214] Enable acpi shutdown on all ACPI platforms. * grub-core/Makefile.core.def (halt): Inlude commands/acpihalt.c on coreboo, multiboot and EFI. * grub-core/commands/acpihalt.c (get_sleep_type): Add missing casts. (grub_acpi_halt): Likewise. * grub-core/commands/i386/pc/halt.c (grub_halt): Call grub_acpi_halt. (grub_cmd_halt): Don't call grub_acpi_halt directly. * grub-core/lib/efi/halt.c (grub_halt): Call grub_acpi_halt. * grub-core/lib/i386/halt.c (grub_halt) [GRUB_MACHINE_COREBOOT || GRUB_MACHINE_MULTIBOOT]: Likewise. --- ChangeLog | 14 ++++++++++++++ grub-core/Makefile.core.def | 3 +++ grub-core/commands/acpihalt.c | 12 ++++++------ grub-core/commands/i386/pc/halt.c | 4 ++-- grub-core/lib/efi/halt.c | 2 ++ grub-core/lib/i386/halt.c | 5 +++++ 6 files changed, 32 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8b959c0f4..555ed7711 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2010-09-13 Vladimir Serbinenko + + Enable acpi shutdown on all ACPI platforms. + + * grub-core/Makefile.core.def (halt): Inlude commands/acpihalt.c + on coreboo, multiboot and EFI. + * grub-core/commands/acpihalt.c (get_sleep_type): Add missing casts. + (grub_acpi_halt): Likewise. + * grub-core/commands/i386/pc/halt.c (grub_halt): Call grub_acpi_halt. + (grub_cmd_halt): Don't call grub_acpi_halt directly. + * grub-core/lib/efi/halt.c (grub_halt): Call grub_acpi_halt. + * grub-core/lib/i386/halt.c (grub_halt) + [GRUB_MACHINE_COREBOOT || GRUB_MACHINE_MULTIBOOT]: Likewise. + 2010-09-13 Vladimir Serbinenko * grub-core/commands/iorw.c (grub_cmd_read): Declare buf in smallest diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 902ab48a8..05890d248 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -521,6 +521,9 @@ module = { nopc = commands/halt.c; i386_pc = commands/i386/pc/halt.c; i386_pc = commands/acpihalt.c; + i386_coreboot = commands/acpihalt.c; + i386_multiboot = commands/acpihalt.c; + x86_efi = commands/acpihalt.c; i386_multiboot = lib/i386/halt.c; i386_coreboot = lib/i386/halt.c; i386_qemu = lib/i386/halt.c; diff --git a/grub-core/commands/acpihalt.c b/grub-core/commands/acpihalt.c index 2ba15468b..0cd32f389 100644 --- a/grub-core/commands/acpihalt.c +++ b/grub-core/commands/acpihalt.c @@ -144,8 +144,8 @@ get_sleep_type (grub_uint8_t *table, grub_uint8_t *end) { int add; prev = ptr; - grub_dprintf ("acpi", "Opcode %x\n", *ptr); - grub_dprintf ("acpi", "Tell %x\n", ptr - table); + grub_dprintf ("acpi", "Opcode 0x%x\n", *ptr); + grub_dprintf ("acpi", "Tell %x\n", (unsigned) (ptr - table)); switch (*ptr) { case GRUB_ACPI_OPCODE_EXTOP: @@ -225,19 +225,19 @@ grub_acpi_halt (void) if (!rsdp1) return; - rsdt = (struct grub_acpi_table_header *) rsdp1->rsdt_addr; + rsdt = (struct grub_acpi_table_header *) (grub_addr_t) rsdp1->rsdt_addr; for (entry_ptr = (grub_uint32_t *) (rsdt + 1); entry_ptr < (grub_uint32_t *) (((grub_uint8_t *) rsdt) + rsdt->length); entry_ptr++) { - if (grub_memcmp ((void *)*entry_ptr, "FACP", 4) == 0) + if (grub_memcmp ((void *) (grub_addr_t) *entry_ptr, "FACP", 4) == 0) { grub_uint32_t port; struct grub_acpi_fadt *fadt - = ((struct grub_acpi_fadt *) *entry_ptr); + = ((struct grub_acpi_fadt *) (grub_addr_t) *entry_ptr); struct grub_acpi_table_header *dsdt - = (struct grub_acpi_table_header *) fadt->dsdt_addr; + = (struct grub_acpi_table_header *) (grub_addr_t) fadt->dsdt_addr; int sleep_type = -1; port = fadt->pm1a; diff --git a/grub-core/commands/i386/pc/halt.c b/grub-core/commands/i386/pc/halt.c index 8afae8eb7..44a88bb05 100644 --- a/grub-core/commands/i386/pc/halt.c +++ b/grub-core/commands/i386/pc/halt.c @@ -47,6 +47,8 @@ grub_halt (int no_apm) { struct grub_bios_int_registers regs; + grub_acpi_halt (); + if (no_apm) stop (); @@ -102,8 +104,6 @@ grub_cmd_halt (grub_extcmd_context_t ctxt, struct grub_arg_list *state = ctxt->state; int no_apm = 0; - grub_acpi_halt (); - if (state[0].set) no_apm = 1; grub_halt (no_apm); diff --git a/grub-core/lib/efi/halt.c b/grub-core/lib/efi/halt.c index ed3e1e1c0..c19536897 100644 --- a/grub-core/lib/efi/halt.c +++ b/grub-core/lib/efi/halt.c @@ -22,11 +22,13 @@ #include #include #include +#include void grub_halt (void) { grub_machine_fini (); + grub_acpi_halt (); efi_call_4 (grub_efi_system_table->runtime_services->reset_system, GRUB_EFI_RESET_SHUTDOWN, GRUB_EFI_SUCCESS, 0, NULL); diff --git a/grub-core/lib/i386/halt.c b/grub-core/lib/i386/halt.c index 74e0c7301..15c4ba0d6 100644 --- a/grub-core/lib/i386/halt.c +++ b/grub-core/lib/i386/halt.c @@ -18,6 +18,7 @@ #include #include +#include const char bochs_shutdown[] = "Shutdown"; @@ -40,6 +41,10 @@ grub_halt (void) { unsigned int i; +#if defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_MULTIBOOT) + grub_acpi_halt (); +#endif + /* Disable interrupts. */ __asm__ __volatile__ ("cli"); From 3352800b992c9ad152cb6a1fc1d9c053c87ccbca Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 13 Sep 2010 22:18:03 +0200 Subject: [PATCH 168/214] Remove readability checks (too many false negatives). * util/grub-install.in: Remove readability checks. * util/grub-mkconfig.in: Likewise. * util/grub.d/10_hurd.in: Likewise. * util/grub.d/10_kfreebsd.in: Likewise. * util/grub.d/10_linux.in: Likewise. * util/grub-mkconfig_lib.in (is_path_readable_by_grub): Revert to old way. --- ChangeLog | 12 ++++++++++++ util/grub-install.in | 20 +++----------------- util/grub-mkconfig.in | 8 -------- util/grub-mkconfig_lib.in | 17 ++--------------- util/grub.d/10_hurd.in | 8 -------- util/grub.d/10_kfreebsd.in | 17 ++--------------- util/grub.d/10_linux.in | 9 --------- 7 files changed, 19 insertions(+), 72 deletions(-) diff --git a/ChangeLog b/ChangeLog index 555ed7711..10ba63029 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2010-09-13 Vladimir Serbinenko + + Remove readability checks (too many false negatives). + + * util/grub-install.in: Remove readability checks. + * util/grub-mkconfig.in: Likewise. + * util/grub.d/10_hurd.in: Likewise. + * util/grub.d/10_kfreebsd.in: Likewise. + * util/grub.d/10_linux.in: Likewise. + * util/grub-mkconfig_lib.in (is_path_readable_by_grub): Revert to old + way. + 2010-09-13 Vladimir Serbinenko Enable acpi shutdown on all ACPI platforms. diff --git a/util/grub-install.in b/util/grub-install.in index ef1778b2a..92271a15a 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -1,7 +1,7 @@ #! /bin/sh # Install GRUB on your drive. -# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc. +# Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software Foundation, Inc. # # GRUB is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -327,7 +327,8 @@ if test "x$fs_module" = x -a "x$modules" = x; then fi # Then the partition map module. In order to support partition-less media, -# this command is allowed to fail. +# this command is allowed to fail (--target=fs already grants us that the +# filesystem will be accessible). partmap_module= for x in `$grub_probe --target=partmap --device ${grub_device} 2> /dev/null`; do partmap_module="$partmap_module part_$x"; @@ -405,24 +406,9 @@ case "${target_cpu}-${platform}" in *) mkimage_target=i386-coreboot; esac -# Verify readability of a few critical files -for file in grubenv normal.mod ; do - if is_path_readable_by_grub ${grubdir}/${file} ${grub_device} ${relative_grubdir}/${file} ; then : ; else - echo "GRUB is unable to read ${grubdir}/${file}" >&2 - exit 1 - fi -done - if [ "${target_cpu}-${platform}" = "i386-pc" ] || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ] ; then $grub_mkimage ${config_opt} -O ${mkimage_target} --output=${grubdir}/core.img --prefix=${prefix_drive}${relative_grubdir} $modules || exit 1 - # This is a temporary workaround; it can be merged back into the check - # above once the install branch is merged. - if is_path_readable_by_grub ${grubdir}/core.img ${grub_device} ${relative_grubdir}/core.img ; then : ; else - echo "GRUB is unable to read ${grubdir}/core.img" >&2 - exit 1 - fi - # Now perform the installation. $grub_setup ${setup_verbose} ${setup_force} --directory=${grubdir} --device-map=${device_map} \ ${install_device} || exit 1 diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in index fa84c63d1..c3b4c3398 100644 --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in @@ -303,14 +303,6 @@ for i in ${grub_mkconfig_dir}/* ; do esac done -# Verify readability of ${grub_cfg}.new -if test "x${grub_cfg}" != "x"; then - if is_path_readable_by_grub ${grub_cfg}.new ; then : ; else - echo "GRUB is unable to read ${grubdir}/${file}" >&2 - exit 1 - fi -fi - if test "x${grub_cfg}" != "x" ; then # none of the children aborted with error, install the new grub.cfg mv -f ${grub_cfg}.new ${grub_cfg} diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in index 6d4f9f3bb..9a77d1bdf 100644 --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in @@ -30,9 +30,6 @@ fi if test "x$grub_mkrelpath" = x; then grub_mkrelpath=${bindir}/`echo grub-mkrelpath | sed ${transform}` fi -if test "x$grub_fstest" = x; then - grub_fstest=${bindir}/`echo grub-fstest | sed ${transform}` -fi if $(which gettext >/dev/null 2>/dev/null) ; then gettext="gettext" @@ -53,24 +50,14 @@ make_system_path_relative_to_its_root () is_path_readable_by_grub () { path=$1 - device=$2 - relpath=$3 # abort if path doesn't exist if test -e $path ; then : ;else return 1 fi - if [ "${device}" = "" ] ; then - device=$(${grub_probe} --target=device $path) - fi - if [ "${relpath}" = "" ] ; then - relpath=$(${grub_mkrelpath} $path) - fi - - # abort if file read through GRUB doesn't match file read through system - # facilities - if ${grub_fstest} $device cmp $relpath $path > /dev/null 2>&1 ; then : ; else + # abort if file is in a filesystem we can't read + if ${grub_probe} -t fs $path > /dev/null 2>&1 ; then : ; else return 1 fi diff --git a/util/grub.d/10_hurd.in b/util/grub.d/10_hurd.in index d8cc7aea4..350eb30a8 100644 --- a/util/grub.d/10_hurd.in +++ b/util/grub.d/10_hurd.in @@ -41,14 +41,6 @@ for i in /boot/gnumach* ; do basename=`basename $i` dirname=`dirname $i` rel_dirname=`make_system_path_relative_to_its_root $dirname` - - if ! is_path_readable_by_grub ${dirname}/${basename} \ - ${GRUB_DEVICE_BOOT} \ - ${rel_dirname}/${basename} ; then - echo "${dirname}/${basename} is not readable by GRUB" >&2 - exit 1 - fi - echo "Found GNU Mach: $i" >&2 kernels="${kernels} ${rel_dirname}/${basename}" at_least_one=true diff --git a/util/grub.d/10_kfreebsd.in b/util/grub.d/10_kfreebsd.in index bf1632bd6..e39423999 100644 --- a/util/grub.d/10_kfreebsd.in +++ b/util/grub.d/10_kfreebsd.in @@ -44,7 +44,7 @@ load_kfreebsd_module () mod="$1" allow_fail="$2" - if ! is_path_readable_by_grub "${module_dir}/${mod}.ko" ; then + if ! test -e "${module_dir}/${mod}.ko" ; then if [ "${allow_fail}" = "true" ] ; then # Return silently return @@ -77,13 +77,6 @@ kfreebsd_entry () prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")" fi - if ! is_path_readable_by_grub ${dirname}/${basename} \ - ${GRUB_DEVICE_BOOT} \ - ${rel_dirname}/${basename} ; then - echo "${dirname}/${basename} is not readable by GRUB" >&2 - exit 1 - fi - printf '%s\n' "${prepare_boot_cache}" cat << EOF echo '$(printf "$(gettext_quoted "Loading kernel of FreeBSD %s ...")" ${version})' @@ -102,13 +95,7 @@ EOF zfs) load_kfreebsd_module opensolaris false - if ! is_path_readable_by_grub ${dirname}/zfs/zpool.cache \ - ${GRUB_DEVICE_BOOT} \ - ${rel_dirname}/zfs/zpool.cache ; then - echo "${dirname}/zfs/zpool.cache is not readable by GRUB" >&2 - exit 1 - fi - + ls "${dirname}/zfs/zpool.cache" > /dev/null printf '%s\n' "${prepare_boot_cache}" cat << EOF kfreebsd_module ${rel_dirname}/zfs/zpool.cache type=/boot/zfs/zpool.cache diff --git a/util/grub.d/10_linux.in b/util/grub.d/10_linux.in index 765a7fab6..14b85c7f1 100644 --- a/util/grub.d/10_linux.in +++ b/util/grub.d/10_linux.in @@ -83,15 +83,6 @@ EOF EOF fi - for i in ${basename} ${initrd} ; do - if ! is_path_readable_by_grub ${dirname}/${i} \ - ${GRUB_DEVICE_BOOT} \ - ${rel_dirname}/${i} ; then - echo "${dirname}/${i} is not readable by GRUB" >&2 - exit 1 - fi - done - if [ -z "${prepare_boot_cache}" ]; then prepare_boot_cache="$(prepare_grub_to_access_device ${GRUB_DEVICE_BOOT} | sed -e "s/^/\t/")" fi From 94564f81a822111ab1f96fbe063ded55f7f77da0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Mon, 13 Sep 2010 23:59:22 +0200 Subject: [PATCH 169/214] * include/grub/disk.h (grub_disk): Remove has_partitions. All users updated. * disk/loopback.c (grub_loopback): Remove has_partitions. All users updated. (options): Remove partitions. All users updated. * util/grub-fstest.c (fstest): Don't pass "-p" to loopback. * util/i386/pc/grub-setup.c (setup): copy partition table only when actual partition table is found. --- ChangeLog | 11 +++++++++++ grub-core/disk/ata.c | 1 - grub-core/disk/efi/efidisk.c | 4 ---- grub-core/disk/host.c | 1 - grub-core/disk/i386/pc/biosdisk.c | 1 - grub-core/disk/ieee1275/nand.c | 1 - grub-core/disk/ieee1275/ofdisk.c | 2 -- grub-core/disk/loopback.c | 9 --------- grub-core/disk/lvm.c | 9 +++++++-- grub-core/disk/memdisk.c | 1 - grub-core/disk/raid.c | 1 - grub-core/disk/scsi.c | 6 ------ grub-core/fs/i386/pc/pxe.c | 1 - grub-core/kern/device.c | 2 +- grub-core/kern/disk.c | 6 ------ grub-core/kern/emu/hostdisk.c | 1 - grub-core/normal/completion.c | 17 +++++++++++++---- grub-core/normal/misc.c | 4 +--- include/grub/disk.h | 3 --- util/grub-fstest.c | 17 ++++++++--------- util/i386/pc/grub-setup.c | 22 ++++++++-------------- 21 files changed, 49 insertions(+), 71 deletions(-) diff --git a/ChangeLog b/ChangeLog index 10ba63029..6e29c939e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2010-09-13 Vladimir Serbinenko + + * include/grub/disk.h (grub_disk): Remove has_partitions. + All users updated. + * disk/loopback.c (grub_loopback): Remove has_partitions. + All users updated. + (options): Remove partitions. All users updated. + * util/grub-fstest.c (fstest): Don't pass "-p" to loopback. + * util/i386/pc/grub-setup.c (setup): copy partition table only when + actual partition table is found. + 2010-09-13 Vladimir Serbinenko Remove readability checks (too many false negatives). diff --git a/grub-core/disk/ata.c b/grub-core/disk/ata.c index cfd58a6d5..fe677e2a0 100644 --- a/grub-core/disk/ata.c +++ b/grub-core/disk/ata.c @@ -723,7 +723,6 @@ grub_ata_open (const char *name, grub_disk_t disk) disk->id = (unsigned long) dev; - disk->has_partitions = 1; disk->data = dev; return 0; diff --git a/grub-core/disk/efi/efidisk.c b/grub-core/disk/efi/efidisk.c index f9c6f3153..7aec1efe8 100644 --- a/grub-core/disk/efi/efidisk.c +++ b/grub-core/disk/efi/efidisk.c @@ -514,16 +514,12 @@ grub_efidisk_open (const char *name, struct grub_disk *disk) switch (name[0]) { case 'f': - disk->has_partitions = 0; d = get_device (fd_devices, num); break; case 'c': - /* FIXME: a CDROM should have partitions, but not implemented yet. */ - disk->has_partitions = 0; d = get_device (cd_devices, num); break; case 'h': - disk->has_partitions = 1; d = get_device (hd_devices, num); break; default: diff --git a/grub-core/disk/host.c b/grub-core/disk/host.c index c4f3e7150..c51966293 100644 --- a/grub-core/disk/host.c +++ b/grub-core/disk/host.c @@ -43,7 +43,6 @@ grub_host_open (const char *name, grub_disk_t disk) disk->total_sectors = 0; disk->id = (unsigned long) "host"; - disk->has_partitions = 0; disk->data = 0; return GRUB_ERR_NONE; diff --git a/grub-core/disk/i386/pc/biosdisk.c b/grub-core/disk/i386/pc/biosdisk.c index 9c0209693..f69626455 100644 --- a/grub-core/disk/i386/pc/biosdisk.c +++ b/grub-core/disk/i386/pc/biosdisk.c @@ -327,7 +327,6 @@ grub_biosdisk_open (const char *name, grub_disk_t disk) if (drive < 0) return grub_errno; - disk->has_partitions = 1; disk->id = drive; data = (struct grub_biosdisk_data *) grub_zalloc (sizeof (*data)); diff --git a/grub-core/disk/ieee1275/nand.c b/grub-core/disk/ieee1275/nand.c index df2ee81f3..a2c717cdb 100644 --- a/grub-core/disk/ieee1275/nand.c +++ b/grub-core/disk/ieee1275/nand.c @@ -113,7 +113,6 @@ grub_nand_open (const char *name, grub_disk_t disk) disk->id = dev_ihandle; - disk->has_partitions = 0; disk->data = data; return 0; diff --git a/grub-core/disk/ieee1275/ofdisk.c b/grub-core/disk/ieee1275/ofdisk.c index 3d9976257..85c34609e 100644 --- a/grub-core/disk/ieee1275/ofdisk.c +++ b/grub-core/disk/ieee1275/ofdisk.c @@ -256,8 +256,6 @@ grub_ofdisk_open (const char *name, grub_disk_t disk) disk->data = op->devpath; } - /* XXX: Read this, somehow. */ - disk->has_partitions = 1; return 0; } diff --git a/grub-core/disk/loopback.c b/grub-core/disk/loopback.c index 878369e5f..c8ee52580 100644 --- a/grub-core/disk/loopback.c +++ b/grub-core/disk/loopback.c @@ -29,7 +29,6 @@ struct grub_loopback { char *devname; grub_file_t file; - int has_partitions; struct grub_loopback *next; }; @@ -38,7 +37,6 @@ static struct grub_loopback *loopback_list; static const struct grub_arg_option options[] = { {"delete", 'd', 0, N_("Delete the loopback device entry."), 0, 0}, - {"partitions", 'p', 0, N_("Simulate a hard drive with partitions."), 0, 0}, {0, 0, 0, 0, 0, 0} }; @@ -106,9 +104,6 @@ grub_cmd_loopback (grub_extcmd_context_t ctxt, int argc, char **args) grub_file_close (newdev->file); newdev->file = file; - /* Set has_partitions when `--partitions' was used. */ - newdev->has_partitions = state[1].set; - return 0; } @@ -126,9 +121,6 @@ grub_cmd_loopback (grub_extcmd_context_t ctxt, int argc, char **args) newdev->file = file; - /* Set has_partitions when `--partitions' was used. */ - newdev->has_partitions = state[1].set; - /* Add the new entry to the list. */ newdev->next = loopback_list; loopback_list = newdev; @@ -174,7 +166,6 @@ grub_loopback_open (const char *name, grub_disk_t disk) disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN; disk->id = (unsigned long) dev; - disk->has_partitions = dev->has_partitions; disk->data = dev->file; return 0; diff --git a/grub-core/disk/lvm.c b/grub-core/disk/lvm.c index 3981d9811..94cf9a1aa 100644 --- a/grub-core/disk/lvm.c +++ b/grub-core/disk/lvm.c @@ -150,7 +150,6 @@ grub_lvm_open (const char *name, grub_disk_t disk) if (! lv) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown LVM device %s", name); - disk->has_partitions = 0; disk->id = lv->number; disk->data = lv; disk->total_sectors = lv->size; @@ -280,7 +279,11 @@ grub_lvm_scan_device (const char *name) disk = grub_disk_open (name); if (!disk) - return 0; + { + if (grub_errno == GRUB_ERR_OUT_OF_RANGE) + grub_errno = GRUB_ERR_NONE; + return 0; + } /* Search for label. */ for (i = 0; i < GRUB_LVM_LABEL_SCAN_SECTORS; i++) @@ -725,6 +728,8 @@ grub_lvm_scan_device (const char *name) grub_free (metadatabuf); fail: grub_disk_close (disk); + if (grub_errno == GRUB_ERR_OUT_OF_RANGE) + grub_errno = GRUB_ERR_NONE; return 0; } diff --git a/grub-core/disk/memdisk.c b/grub-core/disk/memdisk.c index 2e8885020..e00280dd7 100644 --- a/grub-core/disk/memdisk.c +++ b/grub-core/disk/memdisk.c @@ -41,7 +41,6 @@ grub_memdisk_open (const char *name, grub_disk_t disk) disk->total_sectors = memdisk_size / GRUB_DISK_SECTOR_SIZE; disk->id = (unsigned long) "mdsk"; - disk->has_partitions = 0; return GRUB_ERR_NONE; } diff --git a/grub-core/disk/raid.c b/grub-core/disk/raid.c index 51a4b00e2..2fd6aa9de 100644 --- a/grub-core/disk/raid.c +++ b/grub-core/disk/raid.c @@ -126,7 +126,6 @@ grub_raid_open (const char *name, grub_disk_t disk) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown RAID device %s", name); - disk->has_partitions = 1; disk->id = array->number; disk->data = array; diff --git a/grub-core/disk/scsi.c b/grub-core/disk/scsi.c index 60192bef5..902ab12c3 100644 --- a/grub-core/disk/scsi.c +++ b/grub-core/disk/scsi.c @@ -431,12 +431,6 @@ grub_scsi_open (const char *name, grub_disk_t disk) "unknown SCSI device"); } - if (scsi->devtype == grub_scsi_devtype_cdrom) - disk->has_partitions = 0; - else - disk->has_partitions = 1; - - /* According to USB MS tests specification, issue Test Unit Ready * until OK */ maxtime = grub_get_time_ms () + 5000; /* It is safer value */ diff --git a/grub-core/fs/i386/pc/pxe.c b/grub-core/fs/i386/pc/pxe.c index baaff0ffc..cbb3c7d87 100644 --- a/grub-core/fs/i386/pc/pxe.c +++ b/grub-core/fs/i386/pc/pxe.c @@ -176,7 +176,6 @@ grub_pxe_open (const char *name, grub_disk_t disk) disk->total_sectors = 0; disk->id = (unsigned long) data; - disk->has_partitions = 0; disk->data = data; return GRUB_ERR_NONE; diff --git a/grub-core/kern/device.c b/grub-core/kern/device.c index 4273fedfe..9554ca76a 100644 --- a/grub-core/kern/device.c +++ b/grub-core/kern/device.c @@ -103,7 +103,7 @@ grub_device_iterate (int (*hook) (const char *name)) return 0; } - if (dev->disk && dev->disk->has_partitions) + if (dev->disk) { struct part_ent *p; int ret = 0; diff --git a/grub-core/kern/disk.c b/grub-core/kern/disk.c index ccd5f200f..7cf29ae7c 100644 --- a/grub-core/kern/disk.c +++ b/grub-core/kern/disk.c @@ -281,12 +281,6 @@ grub_disk_open (const char *name) goto fail; } - if (p && ! disk->has_partitions) - { - grub_error (GRUB_ERR_BAD_DEVICE, "no partition on this disk"); - goto fail; - } - disk->dev = dev; if (p) diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index 1eb6cb9d8..142e93fe2 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -221,7 +221,6 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk) return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no mapping exists for `%s'", name); - disk->has_partitions = 1; disk->id = drive; disk->data = data = xmalloc (sizeof (struct grub_util_biosdisk_data)); data->dev = NULL; diff --git a/grub-core/normal/completion.c b/grub-core/normal/completion.c index a1e86adb0..f19919d1d 100644 --- a/grub-core/normal/completion.c +++ b/grub-core/normal/completion.c @@ -160,14 +160,23 @@ iterate_dev (const char *devname) if (dev) { - if (dev->disk && dev->disk->has_partitions) + char tmp[grub_strlen (devname) + sizeof (",")]; + + grub_memcpy (tmp, devname, grub_strlen (devname)); + + if (grub_strcmp (devname, current_word) == 0) { - if (add_completion (devname, ",", GRUB_COMPLETION_TYPE_DEVICE)) + if (add_completion (devname, ")", GRUB_COMPLETION_TYPE_PARTITION)) return 1; + + if (dev->disk) + if (grub_partition_iterate (dev->disk, iterate_partition)) + return 1; } else { - if (add_completion (devname, ")", GRUB_COMPLETION_TYPE_DEVICE)) + grub_memcpy (tmp + grub_strlen (devname), "", sizeof ("")); + if (add_completion (tmp, "", GRUB_COMPLETION_TYPE_DEVICE)) return 1; } } @@ -200,7 +209,7 @@ complete_device (void) if (dev) { - if (dev->disk && dev->disk->has_partitions) + if (dev->disk) { if (grub_partition_iterate (dev->disk, iterate_partition)) { diff --git a/grub-core/normal/misc.c b/grub-core/normal/misc.c index ad408074b..d81b6d26f 100644 --- a/grub-core/normal/misc.c +++ b/grub-core/normal/misc.c @@ -108,10 +108,8 @@ grub_normal_print_device_info (const char *name) grub_errno = GRUB_ERR_NONE; } } - else if (! dev->disk->has_partitions || dev->disk->partition) - grub_printf ("%s", _("Unknown filesystem")); else - grub_printf ("%s", _("Partition table")); + grub_printf ("%s", _("Not a known filesystem")); if (dev->disk->partition) grub_printf (_(" - Partition start at %u"), diff --git a/include/grub/disk.h b/include/grub/disk.h index b41f89b38..e3a0160c4 100644 --- a/include/grub/disk.h +++ b/include/grub/disk.h @@ -99,9 +99,6 @@ struct grub_disk /* The total number of sectors. */ grub_uint64_t total_sectors; - /* If partitions can be stored. */ - int has_partitions; - /* The id used by the disk cache manager. */ unsigned long id; diff --git a/util/grub-fstest.c b/util/grub-fstest.c index 3935ce08b..eb7981d3a 100644 --- a/util/grub-fstest.c +++ b/util/grub-fstest.c @@ -259,13 +259,11 @@ fstest (char **images, int num_disks, int cmd, int n, char **args) { char *host_file; char *loop_name; - char *argv[3]; int i; - argv[0] = "-p"; - for (i = 0; i < num_disks; i++) { + char *argv[2]; loop_name = grub_xasprintf ("loop%d", i); if (!loop_name) grub_util_error (grub_errmsg); @@ -274,10 +272,10 @@ fstest (char **images, int num_disks, int cmd, int n, char **args) if (!host_file) grub_util_error (grub_errmsg); - argv[1] = loop_name; - argv[2] = host_file; + argv[0] = loop_name; + argv[1] = host_file; - if (execute_command ("loopback", 3, argv)) + if (execute_command ("loopback", 2, argv)) grub_util_error ("loopback command fails"); grub_free (loop_name); @@ -312,15 +310,16 @@ fstest (char **images, int num_disks, int cmd, int n, char **args) execute_command ("blocklist", n, args); grub_printf ("\n"); } - - argv[0] = "-d"; - + for (i = 0; i < num_disks; i++) { + char *argv[2]; + loop_name = grub_xasprintf ("loop%d", i); if (!loop_name) grub_util_error (grub_errmsg); + argv[0] = "-d"; argv[1] = loop_name; execute_command ("loopback", 2, argv); diff --git a/util/i386/pc/grub-setup.c b/util/i386/pc/grub-setup.c index 987e2d05a..b9abfb0c6 100644 --- a/util/i386/pc/grub-setup.c +++ b/util/i386/pc/grub-setup.c @@ -252,14 +252,6 @@ setup (const char *dir, tmp_img + GRUB_BOOT_MACHINE_BPB_START, GRUB_BOOT_MACHINE_BPB_END - GRUB_BOOT_MACHINE_BPB_START); - /* Copy the possible partition table. */ - if (dest_dev->disk->has_partitions) - memcpy (boot_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC, - tmp_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC, - GRUB_BOOT_MACHINE_PART_END - GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC); - - free (tmp_img); - /* If DEST_DRIVE is a hard disk, enable the workaround, which is for buggy BIOSes which don't pass boot drive correctly. Instead, they pass 0x00 or 0x01 even when booted from 0x80. */ @@ -300,12 +292,6 @@ setup (const char *dir, grub_util_info ("dos partition is %d, bsd partition is %d", dos_part, bsd_part); - if (! dest_dev->disk->has_partitions) - { - grub_util_warn (_("Attempting to install GRUB to a partitionless disk. This is a BAD idea.")); - goto unable_to_embed; - } - if (dest_dev->disk->partition) { grub_util_warn (_("Attempting to install GRUB to a partition instead of the MBR. This is a BAD idea.")); @@ -345,6 +331,14 @@ setup (const char *dir, goto unable_to_embed; } + /* Copy the partition table. */ + if (dest_partmap) + memcpy (boot_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC, + tmp_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC, + GRUB_BOOT_MACHINE_PART_END - GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC); + + free (tmp_img); + if (strcmp (dest_partmap, "msdos") == 0) grub_partition_iterate (dest_dev->disk, find_usable_region_msdos); else if (strcmp (dest_partmap, "gpt") == 0) From 608e43b102999e3db863bcb1a24f1ac4c426714f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 14 Sep 2010 00:08:07 +0200 Subject: [PATCH 170/214] Disable usbserial on grub-emu since our libusb code isn't good enough yet. * grub-core/Makefile.core.def (usbserial_common): Disable on emu. (usbserial_pl2303): Likewise. (usbserial_ftdi): Likewise. --- ChangeLog | 9 +++++++++ grub-core/Makefile.core.def | 6 ------ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index 6e29c939e..3a6905800 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2010-09-13 Vladimir Serbinenko + + Disable usbserial on grub-emu since our libusb code isn't good enough + yet. + + * grub-core/Makefile.core.def (usbserial_common): Disable on emu. + (usbserial_pl2303): Likewise. + (usbserial_ftdi): Likewise. + 2010-09-13 Vladimir Serbinenko * include/grub/disk.h (grub_disk): Remove has_partitions. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 05890d248..54ffdccf2 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -319,25 +319,19 @@ module = { module = { name = usbserial_common; common = bus/usb/serial/common.c; - enable = emu; enable = usb; - emu_condition = COND_GRUB_EMU_USB; }; module = { name = usbserial_pl2303; common = bus/usb/serial/pl2303.c; - enable = emu; enable = usb; - emu_condition = COND_GRUB_EMU_USB; }; module = { name = usbserial_ftdi; common = bus/usb/serial/ftdi.c; - enable = emu; enable = usb; - emu_condition = COND_GRUB_EMU_USB; }; module = { From 62a747cb00cfd78eb3ccf7f35d43b58a8b0fc89e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 14 Sep 2010 00:21:52 +0200 Subject: [PATCH 171/214] * configure.ac: Disable emu-usb by default to prevent inadvertent device takeover. --- ChangeLog | 5 +++++ configure.ac | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3a6905800..574c849d9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2010-09-14 Vladimir Serbinenko + + * configure.ac: Disable emu-usb by default to prevent inadvertent + device takeover. + 2010-09-13 Vladimir Serbinenko Disable usbserial on grub-emu since our libusb code isn't good enough diff --git a/configure.ac b/configure.ac index e519fdd1a..10723987b 100644 --- a/configure.ac +++ b/configure.ac @@ -698,8 +698,8 @@ if test x"$missing_ncurses" = xtrue ; then AC_MSG_ERROR([grub-emu can't be compiled without ncurses]) fi -if test x"$enable_grub_emu_usb" = xno ; then - grub_emu_usb_excuse="explicitly disabled" +if test x"$enable_grub_emu_usb" != xyes ; then + grub_emu_usb_excuse="not enabled" fi if test x"$enable_grub_emu_pci" = xyes ; then From a5dbb1f10daf2de825d5dab16e6cacc4b2dee8e7 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 14 Sep 2010 00:49:02 +0200 Subject: [PATCH 172/214] Create euro.pf2 which supports most European languages. * Makefile.am (grubdata_DATA): Add euro.pf2. (euro.pf2): New target. (CLEANFILES): Add euro.pf2. --- ChangeLog | 8 ++++++++ Makefile.am | 6 +++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 574c849d9..c3d7a6f0d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2010-09-14 Vladimir Serbinenko + + Create euro.pf2 which supports most European languages. + + * Makefile.am (grubdata_DATA): Add euro.pf2. + (euro.pf2): New target. + (CLEANFILES): Add euro.pf2. + 2010-09-14 Vladimir Serbinenko * configure.ac: Disable emu-usb by default to prevent inadvertent diff --git a/Makefile.am b/Makefile.am index 93d1e37fd..9ef8feaac 100644 --- a/Makefile.am +++ b/Makefile.am @@ -60,7 +60,7 @@ CLEANFILES += grub_fstest_init.c if COND_GRUB_MKFONT if COND_HAVE_FONT_SOURCE -grubdata_DATA = unicode.pf2 ascii.pf2 ascii.h widthspec.h +grubdata_DATA = unicode.pf2 ascii.pf2 euro.pf2 ascii.h widthspec.h endif endif @@ -76,6 +76,10 @@ ascii.pf2: $(FONT_SOURCE) grub-mkfont $(builddir)/grub-mkfont -o $@ $(FONT_SOURCE) -r 0x0-0x7f,$(UNICODE_ARROWS),$(UNICODE_LINES) CLEANFILES += ascii.pf2 +euro.pf2: $(FONT_SOURCE) grub-mkfont + $(builddir)/grub-mkfont -o $@ $(FONT_SOURCE) -r 0x0-0x4ff,0x1e00-0x1fff,$(UNICODE_ARROWS),$(UNICODE_LINES) +CLEANFILES += euro.pf2 + ascii.bitmaps: $(FONT_SOURCE) grub-mkfont $(builddir)/grub-mkfont --ascii-bitmaps -o $@ $(FONT_SOURCE) CLEANFILES += ascii.bitmaps From 275433e64227ad96921e5de8f72169a1403df29f Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 14 Sep 2010 01:08:24 +0200 Subject: [PATCH 173/214] Don't export grub_gate_a20. * grub-core/kern/i386/pc/init.c: Remove leftovers. * grub-core/kern/i386/pc/startup.S (FUNCTION(grub_gate_a20)): Rename to ... (grub_gate_a20): ... this. All users updated. * include/grub/i386/pc/init.h: Removed. All users updated. --- ChangeLog | 10 +++++++++ grub-core/kern/i386/pc/init.c | 7 +----- grub-core/kern/i386/pc/mmap.c | 3 +-- grub-core/kern/i386/pc/startup.S | 6 +++--- grub-core/loader/i386/pc/chainloader.c | 2 +- grub-core/loader/i386/pc/linux.c | 1 - include/grub/i386/pc/init.h | 30 -------------------------- 7 files changed, 16 insertions(+), 43 deletions(-) delete mode 100644 include/grub/i386/pc/init.h diff --git a/ChangeLog b/ChangeLog index c3d7a6f0d..e622b6da5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2010-09-14 Vladimir Serbinenko + + Don't export grub_gate_a20. + + * grub-core/kern/i386/pc/init.c: Remove leftovers. + * grub-core/kern/i386/pc/startup.S (FUNCTION(grub_gate_a20)): Rename + to ... + (grub_gate_a20): ... this. All users updated. + * include/grub/i386/pc/init.h: Removed. All users updated. + 2010-09-14 Vladimir Serbinenko Create euro.pf2 which supports most European languages. diff --git a/grub-core/kern/i386/pc/init.c b/grub-core/kern/i386/pc/init.c index 57e33569e..fc247a0d0 100644 --- a/grub-core/kern/i386/pc/init.c +++ b/grub-core/kern/i386/pc/init.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include @@ -171,11 +171,6 @@ grub_machine_init (void) if (grub_lower_mem < GRUB_MEMORY_MACHINE_RESERVED_END) grub_fatal ("too small memory"); -#if 0 - /* Turn on Gate A20 to access >1MB. */ - grub_gate_a20 (1); -#endif - /* FIXME: This prevents loader/i386/linux.c from using low memory. When our heap implements support for requesting a chunk in low memory, this should no longer be a problem. */ diff --git a/grub-core/kern/i386/pc/mmap.c b/grub-core/kern/i386/pc/mmap.c index b174bc441..dba69bbcb 100644 --- a/grub-core/kern/i386/pc/mmap.c +++ b/grub-core/kern/i386/pc/mmap.c @@ -16,9 +16,8 @@ * along with GRUB. If not, see . */ -#include -#include #include +#include #include #include #include diff --git a/grub-core/kern/i386/pc/startup.S b/grub-core/kern/i386/pc/startup.S index 9b53deeb2..2a78bc76f 100644 --- a/grub-core/kern/i386/pc/startup.S +++ b/grub-core/kern/i386/pc/startup.S @@ -202,7 +202,7 @@ LOCAL (codestart): .code32 incl %eax - call EXT_C(grub_gate_a20) + call grub_gate_a20 #ifdef ENABLE_LZMA movl $GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR, %edi @@ -292,7 +292,7 @@ VARIABLE(grub_boot_drive) * It also eats any keystrokes in the keyboard buffer. :-( */ -FUNCTION(grub_gate_a20) +grub_gate_a20: movl %eax, %edx gate_a20_test_current_state: @@ -478,7 +478,7 @@ FUNCTION(grub_chainloader_real_boot) /* Turn off Gate A20 */ xorl %eax, %eax - call EXT_C(grub_gate_a20) + call grub_gate_a20 /* set up to pass boot drive */ popl %edx diff --git a/grub-core/loader/i386/pc/chainloader.c b/grub-core/loader/i386/pc/chainloader.c index e76f84f08..0ae94eaf8 100644 --- a/grub-core/loader/i386/pc/chainloader.c +++ b/grub-core/loader/i386/pc/chainloader.c @@ -26,13 +26,13 @@ #include #include #include -#include #include #include #include #include #include #include +#include #include #include #include diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c index 2f5dfec70..8e9a1b630 100644 --- a/grub-core/loader/i386/pc/linux.c +++ b/grub-core/loader/i386/pc/linux.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include diff --git a/include/grub/i386/pc/init.h b/include/grub/i386/pc/init.h deleted file mode 100644 index 4005a1772..000000000 --- a/include/grub/i386/pc/init.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 2002,2004,2005,2007,2008 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GRUB. If not, see . - */ - -#ifndef GRUB_INIT_MACHINE_HEADER -#define GRUB_INIT_MACHINE_HEADER 1 - -#include -#include -#include -#include - -/* Turn on/off Gate A20. */ -void grub_gate_a20 (int on); - -#endif /* ! GRUB_INIT_MACHINE_HEADER */ From b71c3faedb3aad10e9a422310a9f90551c028230 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 14 Sep 2010 20:59:00 +0200 Subject: [PATCH 174/214] * grub-core/kern/sparc64/ieee1275/crt0.S: Align stack. --- ChangeLog | 4 ++++ grub-core/kern/sparc64/ieee1275/crt0.S | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index e622b6da5..907a489de 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2010-09-14 Vladimir Serbinenko + + * grub-core/kern/sparc64/ieee1275/crt0.S: Align stack. + 2010-09-14 Vladimir Serbinenko Don't export grub_gate_a20. diff --git a/grub-core/kern/sparc64/ieee1275/crt0.S b/grub-core/kern/sparc64/ieee1275/crt0.S index f178f5d3c..cebdca2b6 100644 --- a/grub-core/kern/sparc64/ieee1275/crt0.S +++ b/grub-core/kern/sparc64/ieee1275/crt0.S @@ -61,9 +61,11 @@ codestart: /* Save ieee1275 stack for future use by booter. */ mov %o6, %o1 /* Our future stack. */ - sethi %hi(GRUB_KERNEL_MACHINE_STACK_SIZE - 2047), %o5 - or %o5, %lo(GRUB_KERNEL_MACHINE_STACK_SIZE - 2047), %o5 + sethi %hi(GRUB_KERNEL_MACHINE_STACK_SIZE), %o5 + or %o5, %lo(GRUB_KERNEL_MACHINE_STACK_SIZE), %o5 add %o3, %o5, %o6 + and %o6, ~0xff, %o6 + sub %o6, 2047, %o6 sub %o2, 4, %o2 sub %o3, 4, %o3 From 3c3b5040cdf52b7c04be95a49ada241006d453ef Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 14 Sep 2010 21:04:08 +0200 Subject: [PATCH 175/214] * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Add explicit root argument to set to prevent UUID to be interpreted as argument to set. --- ChangeLog | 6 ++++++ util/grub-mkconfig_lib.in | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 907a489de..f300c84ab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2010-09-14 Vladimir Serbinenko + + * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Add + explicit root argument to set to prevent UUID to be interpreted as + argument to set. + 2010-09-14 Vladimir Serbinenko * grub-core/kern/sparc64/ieee1275/crt0.S: Align stack. diff --git a/util/grub-mkconfig_lib.in b/util/grub-mkconfig_lib.in index 9a77d1bdf..41359975e 100644 --- a/util/grub-mkconfig_lib.in +++ b/util/grub-mkconfig_lib.in @@ -119,7 +119,7 @@ prepare_grub_to_access_device () # otherwise set root as per value in device.map. echo "set root='`${grub_probe} --device ${device} --target=drive`'" if fs_uuid="`${grub_probe} --device ${device} --target=fs_uuid 2> /dev/null`" ; then - echo "search --no-floppy --fs-uuid --set ${fs_uuid}" + echo "search --no-floppy --fs-uuid --set=root ${fs_uuid}" fi } From d2ea45514111f866432b8acabdabd1277ee19f98 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 14 Sep 2010 21:07:39 +0200 Subject: [PATCH 176/214] * grub-core/partmap/sun.c (sun_partition_map_iterate): Don't needlesly allocate p. --- ChangeLog | 5 + Makefile.util.def | 9 +- grub-core/fs/ext2.c | 19 +- grub-core/partmap/sun.c | 35 +- include/grub/sparc64/ieee1275/boot.h | 9 + util/{i386/pc => }/grub-setup.c | 690 ++++++++++++++++----------- util/sparc64/ieee1275/grub-setup.c | 644 ------------------------- 7 files changed, 450 insertions(+), 961 deletions(-) rename util/{i386/pc => }/grub-setup.c (60%) delete mode 100644 util/sparc64/ieee1275/grub-setup.c diff --git a/ChangeLog b/ChangeLog index f300c84ab..d3e7c31c0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2010-09-14 Vladimir Serbinenko + + * grub-core/partmap/sun.c (sun_partition_map_iterate): Don't needlesly + allocate p. + 2010-09-14 Vladimir Serbinenko * util/grub-mkconfig_lib.in (prepare_grub_to_access_device): Add diff --git a/Makefile.util.def b/Makefile.util.def index 4bbcd2b07..f56eab339 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -232,14 +232,11 @@ program = { name = grub-setup; installdir = sbin; mansection = 8; - i386_pc = util/i386/pc/grub-setup.c; - i386_pc = util/raid.c; - i386_pc = util/lvm.c; + common = util/grub-setup.c; + common = util/raid.c; + common = util/lvm.c; sparc64_ieee1275 = util/ieee1275/ofpath.c; - sparc64_ieee1275 = util/sparc64/ieee1275/grub-setup.c; - sparc64_ieee1275 = util/raid.c; - sparc64_ieee1275 = util/lvm.c; ldadd = libgrub.a; ldadd = '$(LIBINTL) $(LIBDEVMAPPER) $(LIBUTIL)'; diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c index f2fec828a..dfc75c625 100644 --- a/grub-core/fs/ext2.c +++ b/grub-core/fs/ext2.c @@ -728,22 +728,27 @@ grub_ext2_open (struct grub_file *file, const char *name) { struct grub_ext2_data *data; struct grub_fshelp_node *fdiro = 0; + grub_err_t err; grub_dl_ref (my_mod); data = grub_ext2_mount (file->device->disk); if (! data) - goto fail; + { + err = grub_errno; + goto fail; + } - grub_fshelp_find_file (name, &data->diropen, &fdiro, grub_ext2_iterate_dir, - grub_ext2_read_symlink, GRUB_FSHELP_REG); - if (grub_errno) + err = grub_fshelp_find_file (name, &data->diropen, &fdiro, + grub_ext2_iterate_dir, + grub_ext2_read_symlink, GRUB_FSHELP_REG); + if (err) goto fail; if (! fdiro->inode_read) { - grub_ext2_read_inode (data, fdiro->ino, &fdiro->inode); - if (grub_errno) + err = grub_ext2_read_inode (data, fdiro->ino, &fdiro->inode); + if (err) goto fail; } @@ -763,7 +768,7 @@ grub_ext2_open (struct grub_file *file, const char *name) grub_dl_unref (my_mod); - return grub_errno; + return err; } static grub_err_t diff --git a/grub-core/partmap/sun.c b/grub-core/partmap/sun.c index 7a7eaef27..7af95c939 100644 --- a/grub-core/partmap/sun.c +++ b/grub-core/partmap/sun.c @@ -87,36 +87,23 @@ sun_partition_map_iterate (grub_disk_t disk, int (*hook) (grub_disk_t disk, const grub_partition_t partition)) { - grub_partition_t p; + struct grub_partition p; struct grub_sun_block block; int partnum; grub_err_t err; - p = (grub_partition_t) grub_zalloc (sizeof (struct grub_partition)); - if (! p) - return grub_errno; - - p->partmap = &grub_sun_partition_map; + p.partmap = &grub_sun_partition_map; err = grub_disk_read (disk, 0, 0, sizeof (struct grub_sun_block), &block); if (err) - { - grub_free (p); - return err; - } + return err; if (GRUB_PARTMAP_SUN_MAGIC != grub_be_to_cpu16 (block.magic)) - { - grub_free (p); - return grub_error (GRUB_ERR_BAD_PART_TABLE, "not a sun partition table"); - } + return grub_error (GRUB_ERR_BAD_PART_TABLE, "not a sun partition table"); if (! grub_sun_is_valid (&block)) - { - grub_free (p); return grub_error (GRUB_ERR_BAD_PART_TABLE, "invalid checksum"); - } - + /* Maybe another error value would be better, because partition table _is_ recognized but invalid. */ for (partnum = 0; partnum < GRUB_PARTMAP_SUN_MAX_PARTS; partnum++) @@ -128,20 +115,18 @@ sun_partition_map_iterate (grub_disk_t disk, continue; desc = &block.partitions[partnum]; - p->start = ((grub_uint64_t) grub_be_to_cpu32 (desc->start_cylinder) + p.start = ((grub_uint64_t) grub_be_to_cpu32 (desc->start_cylinder) * grub_be_to_cpu16 (block.ntrks) * grub_be_to_cpu16 (block.nsect)); - p->len = grub_be_to_cpu32 (desc->num_sectors); - p->number = p->index = partnum; - if (p->len) + p.len = grub_be_to_cpu32 (desc->num_sectors); + p.number = p.index = partnum; + if (p.len) { - if (hook (disk, p)) + if (hook (disk, &p)) partnum = GRUB_PARTMAP_SUN_MAX_PARTS; } } - grub_free (p); - return grub_errno; } diff --git a/include/grub/sparc64/ieee1275/boot.h b/include/grub/sparc64/ieee1275/boot.h index bd0a7bf3c..112d19bc7 100644 --- a/include/grub/sparc64/ieee1275/boot.h +++ b/include/grub/sparc64/ieee1275/boot.h @@ -52,4 +52,13 @@ #define GRUB_BOOT_MACHINE_KERNEL_ADDR 0x4200 +#ifndef ASM_FILE +/* This is the blocklist used in the diskboot image. */ +struct grub_boot_blocklist +{ + grub_uint64_t start; + grub_uint32_t len; +} __attribute__ ((packed)); +#endif + #endif /* ! BOOT_MACHINE_HEADER */ diff --git a/util/i386/pc/grub-setup.c b/util/grub-setup.c similarity index 60% rename from util/i386/pc/grub-setup.c rename to util/grub-setup.c index b9abfb0c6..55d740f09 100644 --- a/util/i386/pc/grub-setup.c +++ b/util/grub-setup.c @@ -36,9 +36,9 @@ #include #include #include -#include - -static const grub_gpt_part_type_t grub_gpt_partition_type_bios_boot = GRUB_GPT_PARTITION_TYPE_BIOS_BOOT; +#ifdef GRUB_MACHINE_IEEE1275 +#include +#endif #include #include @@ -48,59 +48,312 @@ static const grub_gpt_part_type_t grub_gpt_partition_type_bios_boot = GRUB_GPT_P #include #include #include +#include #include "progname.h" #define _GNU_SOURCE 1 #include +/* On SPARC this program fills in various fields inside of the 'boot' and 'core' + * image files. + * + * The 'boot' image needs to know the OBP path name of the root + * device. It also needs to know the initial block number of + * 'core' (which is 'diskboot' concatenated with 'kernel' and + * all the modules, this is created by grub-mkimage). This resulting + * 'boot' image is 512 bytes in size and is placed in the second block + * of a partition. + * + * The initial 'diskboot' block acts as a loader for the actual GRUB + * kernel. It contains the loading code and then a block list. + * + * The block list of 'core' starts at the end of the 'diskboot' image + * and works it's way backwards towards the end of the code of 'diskboot'. + * + * We patch up the images with the necessary values and write out the + * result. + */ + +#ifdef GRUB_MACHINE_PCBIOS +static const grub_gpt_part_type_t grub_gpt_partition_type_bios_boot = GRUB_GPT_PARTITION_TYPE_BIOS_BOOT; +#endif + #define DEFAULT_BOOT_FILE "boot.img" #define DEFAULT_CORE_FILE "core.img" +#ifdef GRUB_MACHINE_SPARC64 +#define grub_target_to_host16(x) grub_be_to_cpu16(x) +#define grub_target_to_host32(x) grub_be_to_cpu32(x) +#define grub_target_to_host64(x) grub_be_to_cpu64(x) +#define grub_host_to_target16(x) grub_cpu_to_be16(x) +#define grub_host_to_target32(x) grub_cpu_to_be32(x) +#define grub_host_to_target64(x) grub_cpu_to_be64(x) +#elif defined (GRUB_MACHINE_PCBIOS) #define grub_target_to_host16(x) grub_le_to_cpu16(x) #define grub_target_to_host32(x) grub_le_to_cpu32(x) #define grub_target_to_host64(x) grub_le_to_cpu64(x) #define grub_host_to_target16(x) grub_cpu_to_le16(x) #define grub_host_to_target32(x) grub_cpu_to_le32(x) #define grub_host_to_target64(x) grub_cpu_to_le64(x) +#else +#error Complete this +#endif + +static void +write_rootdev (char *core_img, grub_device_t root_dev, + char *boot_img, grub_uint64_t first_sector) +{ +#ifdef GRUB_MACHINE_PCBIOS + { + grub_int32_t *install_dos_part, *install_bsd_part; + grub_int32_t dos_part, bsd_part; + grub_uint8_t *boot_drive; + grub_disk_addr_t *kernel_sector; + boot_drive = (grub_uint8_t *) (boot_img + GRUB_BOOT_MACHINE_BOOT_DRIVE); + kernel_sector = (grub_disk_addr_t *) (boot_img + + GRUB_BOOT_MACHINE_KERNEL_SECTOR); + + + install_dos_part = (grub_int32_t *) (core_img + GRUB_DISK_SECTOR_SIZE + + GRUB_KERNEL_MACHINE_INSTALL_DOS_PART); + install_bsd_part = (grub_int32_t *) (core_img + GRUB_DISK_SECTOR_SIZE + + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART); + + /* If we hardcoded drive as part of prefix, we don't want to + override the current setting. */ + if (*install_dos_part != -2) + { + /* Embed information about the installed location. */ + if (root_dev->disk->partition) + { + if (root_dev->disk->partition->parent) + { + if (root_dev->disk->partition->parent->parent) + grub_util_error ("Installing on doubly nested partitions is " + "not supported"); + dos_part = root_dev->disk->partition->parent->number; + bsd_part = root_dev->disk->partition->number; + } + else + { + dos_part = root_dev->disk->partition->number; + bsd_part = -1; + } + } + else + dos_part = bsd_part = -1; + } + else + { + dos_part = grub_le_to_cpu32 (*install_dos_part); + bsd_part = grub_le_to_cpu32 (*install_bsd_part); + } + + grub_util_info ("dos partition is %d, bsd partition is %d", + dos_part, bsd_part); + + *install_dos_part = grub_cpu_to_le32 (dos_part); + *install_bsd_part = grub_cpu_to_le32 (bsd_part); + + /* FIXME: can this be skipped? */ + *boot_drive = 0xFF; + + *kernel_sector = grub_cpu_to_le64 (first_sector); + } +#endif +#ifdef GRUB_MACHINE_IEEE1275 + { + grub_disk_addr_t *kernel_byte; + kernel_byte = (grub_disk_addr_t *) (boot_img + + GRUB_BOOT_AOUT_HEADER_SIZE + + GRUB_BOOT_MACHINE_KERNEL_BYTE); + *kernel_byte = grub_cpu_to_be64 (first_sector << GRUB_DISK_SECTOR_BITS); + } +#endif +} + +#ifdef GRUB_MACHINE_IEEE1275 +#define BOOT_SECTOR 1 +#else +#define BOOT_SECTOR 0 +#endif static void setup (const char *dir, const char *boot_file, const char *core_file, - const char *root, const char *dest, int must_embed, int force, int fs_probe) + const char *root, const char *dest, int must_embed, int force, + int fs_probe) { char *boot_path, *core_path, *core_path_dev, *core_path_dev_full; char *boot_img, *core_img; size_t boot_size, core_size; grub_uint16_t core_sectors; grub_device_t root_dev, dest_dev; - const char *dest_partmap; - int multiple_partmaps; - grub_uint8_t *boot_drive; - grub_disk_addr_t *kernel_sector; - grub_uint16_t *boot_drive_check; struct grub_boot_blocklist *first_block, *block; - grub_int32_t *install_dos_part, *install_bsd_part; - grub_int32_t dos_part, bsd_part; char *tmp_img; int i; grub_disk_addr_t first_sector; +#ifdef GRUB_MACHINE_PCBIOS grub_uint16_t current_segment = GRUB_BOOT_MACHINE_KERNEL_SEG + (GRUB_DISK_SECTOR_SIZE >> 4); +#endif grub_uint16_t last_length = GRUB_DISK_SECTOR_SIZE; grub_file_t file; FILE *fp; struct { grub_uint64_t start; grub_uint64_t end; } embed_region; embed_region.start = embed_region.end = ~0UL; - auto void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, unsigned offset, - unsigned length); - auto void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, unsigned offset, - unsigned length); + auto void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, + unsigned offset, + unsigned length); + auto void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, + unsigned offset, + unsigned length); - auto int NESTED_FUNC_ATTR find_usable_region_msdos (grub_disk_t disk, - const grub_partition_t p); - int NESTED_FUNC_ATTR find_usable_region_msdos (grub_disk_t disk __attribute__ ((unused)), - const grub_partition_t p) + void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, + unsigned offset, + unsigned length) + { + grub_util_info ("the first sector is <%llu,%u,%u>", + sector, offset, length); + + if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE) + grub_util_error (_("the first sector of the core file is not sector-aligned")); + + first_sector = sector; + } + + void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, + unsigned offset, + unsigned length) + { + struct grub_boot_blocklist *prev = block + 1; + + grub_util_info ("saving <%llu,%u,%u>", sector, offset, length); + + if (offset != 0 || last_length != GRUB_DISK_SECTOR_SIZE) + grub_util_error (_("non-sector-aligned data is found in the core file")); + + if (block != first_block + && (grub_target_to_host64 (prev->start) + + grub_target_to_host16 (prev->len)) == sector) + prev->len = grub_host_to_target16 (grub_target_to_host16 (prev->len) + 1); + else + { + block->start = grub_host_to_target64 (sector); + block->len = grub_host_to_target16 (1); +#ifdef GRUB_MACHINE_PCBIOS + block->segment = grub_host_to_target16 (current_segment); +#endif + + block--; + if (block->len) + grub_util_error (_("the sectors of the core file are too fragmented")); + } + + last_length = length; +#ifdef GRUB_MACHINE_PCBIOS + current_segment += GRUB_DISK_SECTOR_SIZE >> 4; +#endif + } + + /* Read the boot image by the OS service. */ + boot_path = grub_util_get_path (dir, boot_file); + boot_size = grub_util_get_image_size (boot_path); + if (boot_size != GRUB_DISK_SECTOR_SIZE) + grub_util_error (_("the size of `%s' is not %u"), + boot_path, GRUB_DISK_SECTOR_SIZE); + boot_img = grub_util_read_image (boot_path); + free (boot_path); + + core_path = grub_util_get_path (dir, core_file); + core_size = grub_util_get_image_size (core_path); + core_sectors = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) + >> GRUB_DISK_SECTOR_BITS); + if (core_size < GRUB_DISK_SECTOR_SIZE) + grub_util_error (_("the size of `%s' is too small"), core_path); +#ifdef GRUB_MACHINE_PCBIOS + if (core_size > 0xFFFF * GRUB_DISK_SECTOR_SIZE) + grub_util_error (_("the size of `%s' is too large"), core_path); +#endif + + core_img = grub_util_read_image (core_path); + + /* Have FIRST_BLOCK to point to the first blocklist. */ + first_block = (struct grub_boot_blocklist *) (core_img + + GRUB_DISK_SECTOR_SIZE + - sizeof (*block)); + + grub_util_info ("root is `%s', dest is `%s'", root, dest); + + /* Open the root device and the destination device. */ + grub_util_info ("Opening root"); + root_dev = grub_device_open (root); + if (! root_dev) + grub_util_error ("%s", grub_errmsg); + + grub_util_info ("Opening dest"); + dest_dev = grub_device_open (dest); + if (! dest_dev) + grub_util_error ("%s", grub_errmsg); + + grub_util_info ("setting the root device to `%s'", root); + if (grub_env_set ("root", root) != GRUB_ERR_NONE) + grub_util_error ("%s", grub_errmsg); + +#ifdef GRUB_MACHINE_PCBIOS + /* Read the original sector from the disk. */ + tmp_img = xmalloc (GRUB_DISK_SECTOR_SIZE); + if (grub_disk_read (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, tmp_img)) + grub_util_error ("%s", grub_errmsg); +#endif + +#ifdef GRUB_MACHINE_PCBIOS + if (dest_dev->disk->partition && fs_probe) + { + grub_fs_t fs; + fs = grub_fs_probe (dest_dev); + if (! fs) + grub_util_error (_("unable to identify a filesystem in %s; safety check can't be performed"), + dest_dev->disk->name); + + if (! fs->reserved_first_sector) + grub_util_error (_("%s appears to contain a %s filesystem which isn't known to " + "reserve space for DOS-style boot. Installing GRUB there could " + "result in FILESYSTEM DESTRUCTION if valuable data is overwritten " + "by grub-setup (--skip-fs-probe disables this " + "check, use at your own risk)"), dest_dev->disk->name, fs->name); + } +#endif + +#ifdef GRUB_MACHINE_PCBIOS + { + grub_uint16_t *boot_drive_check; + boot_drive_check = (grub_uint16_t *) (boot_img + + GRUB_BOOT_MACHINE_DRIVE_CHECK); + /* Copy the possible DOS BPB. */ + memcpy (boot_img + GRUB_BOOT_MACHINE_BPB_START, + tmp_img + GRUB_BOOT_MACHINE_BPB_START, + GRUB_BOOT_MACHINE_BPB_END - GRUB_BOOT_MACHINE_BPB_START); + + /* If DEST_DRIVE is a hard disk, enable the workaround, which is + for buggy BIOSes which don't pass boot drive correctly. Instead, + they pass 0x00 or 0x01 even when booted from 0x80. */ + if (dest_dev->disk->id & 0x80) + /* Replace the jmp (2 bytes) with double nop's. */ + *boot_drive_check = 0x9090; + } +#endif + +#ifdef GRUB_MACHINE_PCBIOS + { + const char *dest_partmap; + int multiple_partmaps; + + auto int NESTED_FUNC_ATTR find_usable_region_msdos (grub_disk_t disk, + const grub_partition_t p); + int NESTED_FUNC_ATTR find_usable_region_msdos (grub_disk_t disk __attribute__ ((unused)), + const grub_partition_t p) { /* There's always an embed region, and it starts right after the MBR. */ embed_region.start = 1; @@ -111,10 +364,10 @@ setup (const char *dir, return 0; } - auto int NESTED_FUNC_ATTR find_usable_region_gpt (grub_disk_t disk, - const grub_partition_t p); - int NESTED_FUNC_ATTR find_usable_region_gpt (grub_disk_t disk __attribute__ ((unused)), - const grub_partition_t p) + auto int NESTED_FUNC_ATTR find_usable_region_gpt (grub_disk_t disk, + const grub_partition_t p); + int NESTED_FUNC_ATTR find_usable_region_gpt (grub_disk_t disk __attribute__ ((unused)), + const grub_partition_t p) { struct grub_gpt_partentry gptdata; @@ -134,176 +387,18 @@ setup (const char *dir, return 0; } - void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, unsigned offset, - unsigned length) - { - grub_util_info ("the first sector is <%llu,%u,%u>", - sector, offset, length); + if (dest_dev->disk->partition) + { + grub_util_warn (_("Attempting to install GRUB to a partition instead of the MBR. This is a BAD idea.")); + goto unable_to_embed; + } - if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("the first sector of the core file is not sector-aligned")); - - first_sector = sector; - } - - void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, unsigned offset, - unsigned length) - { - struct grub_boot_blocklist *prev = block + 1; - - grub_util_info ("saving <%llu,%u,%u> with the segment 0x%x", - sector, offset, length, (unsigned) current_segment); - - if (offset != 0 || last_length != GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("non-sector-aligned data is found in the core file")); - - if (block != first_block - && (grub_le_to_cpu64 (prev->start) - + grub_le_to_cpu16 (prev->len)) == sector) - prev->len = grub_cpu_to_le16 (grub_le_to_cpu16 (prev->len) + 1); - else - { - block->start = grub_cpu_to_le64 (sector); - block->len = grub_cpu_to_le16 (1); - block->segment = grub_cpu_to_le16 (current_segment); - - block--; - if (block->len) - grub_util_error (_("the sectors of the core file are too fragmented")); - } - - last_length = length; - current_segment += GRUB_DISK_SECTOR_SIZE >> 4; - } - - /* Read the boot image by the OS service. */ - boot_path = grub_util_get_path (dir, boot_file); - boot_size = grub_util_get_image_size (boot_path); - if (boot_size != GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("the size of `%s' is not %u"), - boot_path, GRUB_DISK_SECTOR_SIZE); - boot_img = grub_util_read_image (boot_path); - free (boot_path); - - /* Set the addresses of variables in the boot image. */ - boot_drive = (grub_uint8_t *) (boot_img + GRUB_BOOT_MACHINE_BOOT_DRIVE); - kernel_sector = (grub_disk_addr_t *) (boot_img - + GRUB_BOOT_MACHINE_KERNEL_SECTOR); - boot_drive_check = (grub_uint16_t *) (boot_img - + GRUB_BOOT_MACHINE_DRIVE_CHECK); - - core_path = grub_util_get_path (dir, core_file); - core_size = grub_util_get_image_size (core_path); - core_sectors = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) - >> GRUB_DISK_SECTOR_BITS); - if (core_size < GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("the size of `%s' is too small"), core_path); - else if (core_size > 0xFFFF * GRUB_DISK_SECTOR_SIZE) - grub_util_error (_("the size of `%s' is too large"), core_path); - - core_img = grub_util_read_image (core_path); - - /* Have FIRST_BLOCK to point to the first blocklist. */ - first_block = (struct grub_boot_blocklist *) (core_img - + GRUB_DISK_SECTOR_SIZE - - sizeof (*block)); - - install_dos_part = (grub_int32_t *) (core_img + GRUB_DISK_SECTOR_SIZE - + GRUB_KERNEL_MACHINE_INSTALL_DOS_PART); - install_bsd_part = (grub_int32_t *) (core_img + GRUB_DISK_SECTOR_SIZE - + GRUB_KERNEL_MACHINE_INSTALL_BSD_PART); - - /* Open the root device and the destination device. */ - root_dev = grub_device_open (root); - if (! root_dev) - grub_util_error ("%s", grub_errmsg); - - dest_dev = grub_device_open (dest); - if (! dest_dev) - grub_util_error ("%s", grub_errmsg); - - grub_util_info ("setting the root device to `%s'", root); - if (grub_env_set ("root", root) != GRUB_ERR_NONE) - grub_util_error ("%s", grub_errmsg); - - /* Read the original sector from the disk. */ - tmp_img = xmalloc (GRUB_DISK_SECTOR_SIZE); - if (grub_disk_read (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, tmp_img)) - grub_util_error ("%s", grub_errmsg); - - if (dest_dev->disk->partition && fs_probe) - { - grub_fs_t fs; - fs = grub_fs_probe (dest_dev); - if (! fs) - grub_util_error (_("unable to identify a filesystem in %s; safety check can't be performed"), - dest_dev->disk->name); - - if (! fs->reserved_first_sector) - grub_util_error (_("%s appears to contain a %s filesystem which isn't known to " - "reserve space for DOS-style boot. Installing GRUB there could " - "result in FILESYSTEM DESTRUCTION if valuable data is overwritten " - "by grub-setup (--skip-fs-probe disables this " - "check, use at your own risk)"), dest_dev->disk->name, fs->name); - } - - /* Copy the possible DOS BPB. */ - memcpy (boot_img + GRUB_BOOT_MACHINE_BPB_START, - tmp_img + GRUB_BOOT_MACHINE_BPB_START, - GRUB_BOOT_MACHINE_BPB_END - GRUB_BOOT_MACHINE_BPB_START); - - /* If DEST_DRIVE is a hard disk, enable the workaround, which is - for buggy BIOSes which don't pass boot drive correctly. Instead, - they pass 0x00 or 0x01 even when booted from 0x80. */ - if (dest_dev->disk->id & 0x80) - /* Replace the jmp (2 bytes) with double nop's. */ - *boot_drive_check = 0x9090; - - /* If we hardcoded drive as part of prefix, we don't want to - override the current setting. */ - if (*install_dos_part != -2) - { - /* Embed information about the installed location. */ - if (root_dev->disk->partition) - { - if (root_dev->disk->partition->parent) - { - if (root_dev->disk->partition->parent->parent) - grub_util_error ("Installing on doubly nested partitions is " - "not supported"); - dos_part = root_dev->disk->partition->parent->number; - bsd_part = root_dev->disk->partition->number; - } - else - { - dos_part = root_dev->disk->partition->number; - bsd_part = -1; - } - } - else - dos_part = bsd_part = -1; - } - else - { - dos_part = grub_le_to_cpu32 (*install_dos_part); - bsd_part = grub_le_to_cpu32 (*install_bsd_part); - } - - grub_util_info ("dos partition is %d, bsd partition is %d", - dos_part, bsd_part); - - if (dest_dev->disk->partition) - { - grub_util_warn (_("Attempting to install GRUB to a partition instead of the MBR. This is a BAD idea.")); - goto unable_to_embed; - } - - /* Unlike root_dev, with dest_dev we're interested in the partition map even - if dest_dev itself is a whole disk. */ - auto int NESTED_FUNC_ATTR identify_partmap (grub_disk_t disk, - const grub_partition_t p); - int NESTED_FUNC_ATTR identify_partmap (grub_disk_t disk __attribute__ ((unused)), - const grub_partition_t p) + /* Unlike root_dev, with dest_dev we're interested in the partition map even + if dest_dev itself is a whole disk. */ + auto int NESTED_FUNC_ATTR identify_partmap (grub_disk_t disk, + const grub_partition_t p); + int NESTED_FUNC_ATTR identify_partmap (grub_disk_t disk __attribute__ ((unused)), + const grub_partition_t p) { if (p->parent) return 0; @@ -316,89 +411,85 @@ setup (const char *dir, } return 0; } - dest_partmap = 0; - multiple_partmaps = 0; - grub_partition_iterate (dest_dev->disk, identify_partmap); + dest_partmap = 0; + multiple_partmaps = 0; + grub_partition_iterate (dest_dev->disk, identify_partmap); - if (! dest_partmap) - { - grub_util_warn (_("Attempting to install GRUB to a partitionless disk. This is a BAD idea.")); - goto unable_to_embed; - } - if (multiple_partmaps) - { - grub_util_warn (_("Attempting to install GRUB to a disk with multiple partition labels. This is not supported yet.")); - goto unable_to_embed; - } + if (! dest_partmap) + { + grub_util_warn (_("Attempting to install GRUB to a partitionless disk. This is a BAD idea.")); + goto unable_to_embed; + } + if (multiple_partmaps) + { + grub_util_warn (_("Attempting to install GRUB to a disk with multiple partition labels. This is not supported yet.")); + goto unable_to_embed; + } - /* Copy the partition table. */ - if (dest_partmap) - memcpy (boot_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC, - tmp_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC, - GRUB_BOOT_MACHINE_PART_END - GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC); + /* Copy the partition table. */ + if (dest_partmap) + memcpy (boot_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC, + tmp_img + GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC, + GRUB_BOOT_MACHINE_PART_END - GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC); - free (tmp_img); + free (tmp_img); - if (strcmp (dest_partmap, "msdos") == 0) - grub_partition_iterate (dest_dev->disk, find_usable_region_msdos); - else if (strcmp (dest_partmap, "gpt") == 0) - grub_partition_iterate (dest_dev->disk, find_usable_region_gpt); - else - grub_util_error (_("No DOS-style partitions found")); + if (strcmp (dest_partmap, "msdos") == 0) + grub_partition_iterate (dest_dev->disk, find_usable_region_msdos); + else if (strcmp (dest_partmap, "gpt") == 0) + grub_partition_iterate (dest_dev->disk, find_usable_region_gpt); + else + grub_util_error (_("No DOS-style partitions found")); - if (embed_region.end <= embed_region.start) - { - if (! strcmp (dest_partmap, "msdos")) - grub_util_warn (_("This msdos-style partition label has no post-MBR gap; embedding won't be possible!")); - else - grub_util_warn (_("This GPT partition label has no BIOS Boot Partition; embedding won't be possible!")); - goto unable_to_embed; - } + if (embed_region.end <= embed_region.start) + { + if (! strcmp (dest_partmap, "msdos")) + grub_util_warn (_("This msdos-style partition label has no post-MBR gap; embedding won't be possible!")); + else + grub_util_warn (_("This GPT partition label has no BIOS Boot Partition; embedding won't be possible!")); + goto unable_to_embed; + } - if ((unsigned long) core_sectors > embed_region.end - embed_region.start) - { - if (core_sectors > 62) - grub_util_warn (_("Your core.img is unusually large. It won't fit in the embedding area.")); - else /* embed_region.end - embed_region.start < 62 */ - grub_util_warn (_("Your embedding area is unusually small. core.img won't fit in it.")); - goto unable_to_embed; - } + if ((unsigned long) core_sectors > embed_region.end - embed_region.start) + { + if (core_sectors > 62) + grub_util_warn (_("Your core.img is unusually large. It won't fit in the embedding area.")); + else /* embed_region.end - embed_region.start < 62 */ + grub_util_warn (_("Your embedding area is unusually small. core.img won't fit in it.")); + goto unable_to_embed; + } + write_rootdev (core_img, root_dev, + boot_img, embed_region.start); - grub_util_info ("the core image will be embedded at sector 0x%llx", embed_region.start); + grub_util_info ("the core image will be embedded at sector 0x%llx", embed_region.start); - *install_dos_part = grub_cpu_to_le32 (dos_part); - *install_bsd_part = grub_cpu_to_le32 (bsd_part); + /* The first blocklist contains the whole sectors. */ + first_block->start = grub_cpu_to_le64 (embed_region.start + 1); - /* The first blocklist contains the whole sectors. */ - first_block->start = grub_cpu_to_le64 (embed_region.start + 1); + /* These are filled elsewhere. Verify them just in case. */ + assert (first_block->len == grub_host_to_target16 (core_sectors - 1)); + assert (first_block->segment == grub_host_to_target16 (GRUB_BOOT_MACHINE_KERNEL_SEG + + (GRUB_DISK_SECTOR_SIZE >> 4))); - /* These are filled elsewhere. Verify them just in case. */ - assert (first_block->len == grub_host_to_target16 (core_sectors - 1)); - assert (first_block->segment == grub_host_to_target16 (GRUB_BOOT_MACHINE_KERNEL_SEG - + (GRUB_DISK_SECTOR_SIZE >> 4))); + /* Make sure that the second blocklist is a terminator. */ + block = first_block - 1; + block->start = 0; + block->len = 0; + block->segment = 0; - /* Make sure that the second blocklist is a terminator. */ - block = first_block - 1; - block->start = 0; - block->len = 0; - block->segment = 0; + /* Write the core image onto the disk. */ + if (grub_disk_write (dest_dev->disk, embed_region.start, 0, core_size, core_img)) + grub_util_error ("%s", grub_errmsg); - /* Write the core image onto the disk. */ - if (grub_disk_write (dest_dev->disk, embed_region.start, 0, core_size, core_img)) - grub_util_error ("%s", grub_errmsg); + /* Write the boot image onto the disk. */ + if (grub_disk_write (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, + boot_img)) + grub_util_error ("%s", grub_errmsg); - /* FIXME: can this be skipped? */ - *boot_drive = 0xFF; - - *kernel_sector = grub_cpu_to_le64 (embed_region.start); - - /* Write the boot image onto the disk. */ - if (grub_disk_write (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, - boot_img)) - grub_util_error ("%s", grub_errmsg); - - goto finish; + goto finish; + } +#endif unable_to_embed: @@ -412,6 +503,9 @@ unable_to_embed: if (! force) grub_util_error (_("if you really want blocklists, use --force")); + /* The core image must be put on a filesystem unfortunately. */ + grub_util_info ("will leave the core image on the filesystem"); + /* Make sure that GRUB reads the identical image as the OS. */ tmp_img = xmalloc (core_size); core_path_dev_full = grub_util_get_path (dir, core_file); @@ -494,7 +588,9 @@ unable_to_embed: { block->start = 0; block->len = 0; +#ifdef GRUB_MACHINE_PCBIOS block->segment = 0; +#endif block--; @@ -519,18 +615,39 @@ unable_to_embed: != (grub_ssize_t) core_size - GRUB_DISK_SECTOR_SIZE) grub_util_error (_("failed to read the rest sectors of the core image")); +#ifdef GRUB_MACHINE_IEEE1275 + { + char *boot_devpath; + boot_devpath = (char *) (boot_img + + GRUB_BOOT_AOUT_HEADER_SIZE + + GRUB_BOOT_MACHINE_BOOT_DEVPATH); + if (file->device->disk->id != dest_dev->disk->id) + { + const char *dest_ofpath; + dest_ofpath + = grub_util_devname_to_ofpath (grub_util_biosdisk_get_osdev (file->device->disk)); + grub_util_info ("dest_ofpath is `%s'", dest_ofpath); + strncpy (boot_devpath, dest_ofpath, GRUB_BOOT_MACHINE_BOOT_DEVPATH_END + - GRUB_BOOT_MACHINE_BOOT_DEVPATH - 1); + boot_devpath[GRUB_BOOT_MACHINE_BOOT_DEVPATH_END + - GRUB_BOOT_MACHINE_BOOT_DEVPATH - 1] = 0; + } + else + { + grub_util_info ("non cross-disk install"); + memset (boot_devpath, 0, GRUB_BOOT_MACHINE_BOOT_DEVPATH_END + - GRUB_BOOT_MACHINE_BOOT_DEVPATH); + } + grub_util_info ("boot device path %s", boot_devpath); + } +#endif + grub_file_close (file); free (core_path_dev); free (tmp_img); - *kernel_sector = grub_cpu_to_le64 (first_sector); - - /* FIXME: can this be skipped? */ - *boot_drive = 0xFF; - - *install_dos_part = grub_cpu_to_le32 (dos_part); - *install_bsd_part = grub_cpu_to_le32 (bsd_part); + write_rootdev (core_img, root_dev, boot_img, first_sector); /* Write the first two sectors of the core image onto the disk. */ grub_util_info ("opening the core image `%s'", core_path); @@ -542,7 +659,8 @@ unable_to_embed: fclose (fp); /* Write the boot image onto the disk. */ - if (grub_disk_write (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, boot_img)) + if (grub_disk_write (dest_dev->disk, BOOT_SECTOR, + 0, GRUB_DISK_SECTOR_SIZE, boot_img)) grub_util_error ("%s", grub_errmsg); finish: @@ -621,14 +739,18 @@ get_device_name (char *dev) int main (int argc, char *argv[]) { - char *boot_file = 0; - char *core_file = 0; - char *dir = 0; - char *dev_map = 0; - char *root_dev = 0; - char *dest_dev; + char *boot_file = NULL; + char *core_file = NULL; + char *dir = NULL; + char *dev_map = NULL; + char *root_dev = NULL; + char *dest_dev = NULL; int must_embed = 0, force = 0, fs_probe = 1; +#ifdef GRUB_MACHINE_IEEE1275 + force = 1; +#endif + set_program_name (argv[0]); grub_util_init_nls (); @@ -743,10 +865,15 @@ main (int argc, char *argv[]) fprintf (stderr, _("Invalid device `%s'.\n"), argv[optind]); usage (1); } + grub_util_info ("transformed OS device `%s' into GRUB device `%s'", + argv[optind], dest_dev); } else - /* For simplicity. */ - dest_dev = xstrdup (dest_dev); + { + /* For simplicity. */ + dest_dev = xstrdup (dest_dev); + grub_util_info ("Using `%s' as GRUB device", dest_dev); + } if (root_dev) { @@ -761,13 +888,18 @@ main (int argc, char *argv[]) } else { - root_dev = grub_util_get_grub_dev (grub_guess_root_device (dir ? : DEFAULT_DIRECTORY)); + char *root_device = grub_guess_root_device (dir ? : DEFAULT_DIRECTORY); + + root_dev = grub_util_get_grub_dev (root_device); if (! root_dev) { grub_util_info ("guessing the root device failed, because of `%s'", grub_errmsg); grub_util_error (_("cannot guess the root device. Specify the option `--root-device'")); } + grub_util_info ("guessed root device `%s' and root_dev `%s' from " + "dir `%s'", root_device, root_dev, + dir ? : DEFAULT_DIRECTORY); } #ifdef __linux__ @@ -799,7 +931,7 @@ main (int argc, char *argv[]) } else #endif - /* Do the real work. */ + /* Do the real work. */ setup (dir ? : DEFAULT_DIRECTORY, boot_file ? : DEFAULT_BOOT_FILE, core_file ? : DEFAULT_CORE_FILE, diff --git a/util/sparc64/ieee1275/grub-setup.c b/util/sparc64/ieee1275/grub-setup.c deleted file mode 100644 index 1b1a80911..000000000 --- a/util/sparc64/ieee1275/grub-setup.c +++ /dev/null @@ -1,644 +0,0 @@ -/* grub-setup.c - make GRUB usable */ -/* - * GRUB -- GRand Unified Bootloader - * Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008,2009,2010 Free Software Foundation, Inc. - * - * GRUB is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GRUB is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GRUB. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#define _GNU_SOURCE 1 -#include - -#include "progname.h" - -/* This program fills in various fields inside of the 'boot' and 'core' - * image files. - * - * The 'boot' image needs to know the OBP path name of the root - * device. It also needs to know the initial block number of - * 'core' (which is 'diskboot' concatenated with 'kernel' and - * all the modules, this is created by grub-mkimage). This resulting - * 'boot' image is 512 bytes in size and is placed in the second block - * of a partition. - * - * The initial 'diskboot' block acts as a loader for the actual GRUB - * kernel. It contains the loading code and then a block list. - * - * The block list of 'core' starts at the end of the 'diskboot' image - * and works it's way backwards towards the end of the code of 'diskboot'. - * - * We patch up the images with the necessary values and write out the - * result. - */ - -#define DEFAULT_BOOT_FILE "boot.img" -#define DEFAULT_CORE_FILE "core.img" - -#define grub_target_to_host16(x) grub_be_to_cpu16(x) -#define grub_target_to_host32(x) grub_be_to_cpu32(x) -#define grub_target_to_host64(x) grub_be_to_cpu64(x) -#define grub_host_to_target16(x) grub_cpu_to_be16(x) -#define grub_host_to_target32(x) grub_cpu_to_be32(x) -#define grub_host_to_target64(x) grub_cpu_to_be64(x) - -/* This is the blocklist used in the diskboot image. */ -struct boot_blocklist -{ - grub_uint64_t start; - grub_uint32_t len; -} __attribute__ ((packed)); - -static void -setup (const char *prefix, const char *dir, - const char *boot_file, const char *core_file, - const char *root, const char *dest) -{ - char *boot_path, *core_path; - char *boot_img, *core_img; - size_t boot_size, core_size; - grub_uint16_t core_sectors; - grub_device_t root_dev, dest_dev; - char *boot_devpath; - grub_disk_addr_t *kernel_byte; - struct boot_blocklist *first_block, *block; - char *tmp_img; - int i; - grub_disk_addr_t first_sector; - grub_uint16_t last_length = GRUB_DISK_SECTOR_SIZE; - grub_file_t file; - FILE *fp; - struct { grub_uint64_t start; grub_uint64_t end; } embed_region; - embed_region.start = embed_region.end = ~0UL; - - auto void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, - unsigned int offset, - unsigned int length); - auto void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, - unsigned int offset, - unsigned int length); - - void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, - unsigned int offset, - unsigned int length) - { - grub_util_info ("first sector is <%llu,%u,%u>", sector, offset, length); - - if (offset != 0 || length != GRUB_DISK_SECTOR_SIZE) - grub_util_error ("the first sector of the core file " - "is not sector-aligned"); - - first_sector = sector; - } - - void NESTED_FUNC_ATTR save_blocklists (grub_disk_addr_t sector, - unsigned int offset, - unsigned int length) - { - struct boot_blocklist *prev = block + 1; - - grub_util_info ("saving <%llu,%u,%u>", sector, offset, length); - - if (offset != 0 || last_length != GRUB_DISK_SECTOR_SIZE) - grub_util_error ("non-sector-aligned data is found in the core file"); - - if (block != first_block - && (grub_be_to_cpu64 (prev->start) - + grub_be_to_cpu16 (prev->len)) == sector) - prev->len = grub_cpu_to_be16 (grub_be_to_cpu16 (prev->len) + 1); - else - { - block->start = grub_cpu_to_be64 (sector); - block->len = grub_cpu_to_be16 (1); - - block--; - if (block->len) - grub_util_error ("the sectors of the core file are too fragmented"); - } - - last_length = length; - } - - /* Read the boot image by the OS service. */ - boot_path = grub_util_get_path (dir, boot_file); - boot_size = grub_util_get_image_size (boot_path); - if (boot_size != GRUB_DISK_SECTOR_SIZE) - grub_util_error ("the size of `%s' is not %d", - boot_path, GRUB_DISK_SECTOR_SIZE); - boot_img = grub_util_read_image (boot_path); - free (boot_path); - - /* Set the addresses of variables in the boot image. */ - boot_devpath = (char *) (boot_img - + GRUB_BOOT_AOUT_HEADER_SIZE - + GRUB_BOOT_MACHINE_BOOT_DEVPATH); - kernel_byte = (grub_disk_addr_t *) (boot_img - + GRUB_BOOT_AOUT_HEADER_SIZE - + GRUB_BOOT_MACHINE_KERNEL_BYTE); - - core_path = grub_util_get_path (dir, core_file); - core_size = grub_util_get_image_size (core_path); - core_sectors = ((core_size + GRUB_DISK_SECTOR_SIZE - 1) - >> GRUB_DISK_SECTOR_BITS); - if (core_size < GRUB_DISK_SECTOR_SIZE) - grub_util_error ("the size of `%s' is too small", core_path); - - core_img = grub_util_read_image (core_path); - free (core_path); - - /* Have FIRST_BLOCK to point to the first blocklist. */ - first_block = (struct boot_blocklist *) (core_img - + GRUB_DISK_SECTOR_SIZE - - sizeof (*block)); - - grub_util_info ("root is `%s', dest is `%s'", root, dest); - - /* Open the root device and the destination device. */ - grub_util_info ("Opening root"); - root_dev = grub_device_open (root); - if (! root_dev) - grub_util_error ("%s", grub_errmsg); - - grub_util_info ("Opening dest"); - dest_dev = grub_device_open (dest); - if (! dest_dev) - grub_util_error ("%s", grub_errmsg); - - grub_util_info ("setting the root device to `%s'", root); - if (grub_env_set ("root", root) != GRUB_ERR_NONE) - grub_util_error ("%s", grub_errmsg); - - /* The core image must be put on a filesystem unfortunately. */ - grub_util_info ("will leave the core image on the filesystem"); - - /* Make sure that GRUB reads the identical image as the OS. */ - tmp_img = xmalloc (core_size); - core_path = grub_util_get_path (prefix, core_file); - - /* It is a Good Thing to sync two times. */ - sync (); - sync (); - -#define MAX_TRIES 5 - - for (i = 0; i < MAX_TRIES; i++) - { - grub_util_info ("attempting to read the core image `%s' from GRUB%s", - core_path, (i == 0) ? "" : " again"); - - grub_disk_cache_invalidate_all (); - - grub_file_filter_disable_compression (); - file = grub_file_open (core_path); - if (file) - { - if (grub_file_size (file) != core_size) - grub_util_info ("succeeded in opening the core image but the size is different (%d != %d)", - (int) grub_file_size (file), (int) core_size); - else if (grub_file_read (file, tmp_img, core_size) - != (grub_ssize_t) core_size) - grub_util_info ("succeeded in opening the core image but cannot read %d bytes", - (int) core_size); - else if (memcmp (core_img, tmp_img, core_size) != 0) - { -#if 0 - FILE *dump; - FILE *dump2; - - dump = fopen ("dump.img", "wb"); - if (dump) - { - fwrite (tmp_img, 1, core_size, dump); - fclose (dump); - } - - dump2 = fopen ("dump2.img", "wb"); - if (dump2) - { - fwrite (core_img, 1, core_size, dump2); - fclose (dump2); - } - -#endif - grub_util_info ("succeeded in opening the core image but the data is different"); - } - else - { - grub_file_close (file); - break; - } - - grub_file_close (file); - } - else - grub_util_info ("couldn't open the core image"); - - if (grub_errno) - grub_util_info ("error message = %s", grub_errmsg); - - grub_errno = GRUB_ERR_NONE; - sync (); - sleep (1); - } - - if (i == MAX_TRIES) - grub_util_error ("cannot read `%s' correctly", core_path); - - /* Clean out the blocklists. */ - block = first_block; - while (block->len) - { - block->start = 0; - block->len = 0; - - block--; - - if ((char *) block <= core_img) - grub_util_error ("no terminator in the core image"); - } - - /* Now read the core image to determine where the sectors are. */ - grub_file_filter_disable_compression (); - file = grub_file_open (core_path); - if (! file) - grub_util_error ("%s", grub_errmsg); - - file->read_hook = save_first_sector; - if (grub_file_read (file, tmp_img, GRUB_DISK_SECTOR_SIZE) - != GRUB_DISK_SECTOR_SIZE) - grub_util_error ("failed to read the first sector of the core image"); - - block = first_block; - file->read_hook = save_blocklists; - if (grub_file_read (file, tmp_img, core_size - GRUB_DISK_SECTOR_SIZE) - != (grub_ssize_t) core_size - GRUB_DISK_SECTOR_SIZE) - grub_util_error ("failed to read the rest sectors of the core image"); - - if (file->device->disk->id != dest_dev->disk->id) - { - const char *dest_ofpath; - dest_ofpath - = grub_util_devname_to_ofpath (grub_util_biosdisk_get_osdev (file->device->disk)); - grub_util_info ("dest_ofpath is `%s'", dest_ofpath); - strncpy (boot_devpath, dest_ofpath, GRUB_BOOT_MACHINE_BOOT_DEVPATH_END - - GRUB_BOOT_MACHINE_BOOT_DEVPATH - 1); - boot_devpath[GRUB_BOOT_MACHINE_BOOT_DEVPATH_END - - GRUB_BOOT_MACHINE_BOOT_DEVPATH - 1] = 0; - } - else - { - grub_util_info ("non cross-disk install"); - memset (boot_devpath, 0, GRUB_BOOT_MACHINE_BOOT_DEVPATH_END - - GRUB_BOOT_MACHINE_BOOT_DEVPATH); - } - - grub_file_close (file); - - free (core_path); - free (tmp_img); - - *kernel_byte = grub_cpu_to_be64 (first_sector << GRUB_DISK_SECTOR_BITS); - - grub_util_info ("boot device path %s, prefix is %s, dest is %s", - boot_devpath, prefix, dest); - - /* Write the first two sectors of the core image onto the disk. */ - core_path = grub_util_get_path (dir, core_file); - grub_util_info ("opening the core image `%s'", core_path); - fp = fopen (core_path, "r+b"); - if (! fp) - grub_util_error ("cannot open `%s'", core_path); - - grub_util_write_image (core_img, GRUB_DISK_SECTOR_SIZE, fp); - fclose (fp); - free (core_path); - - /* Write the boot image onto the disk. */ - if (grub_disk_write (dest_dev->disk, 1, 0, GRUB_DISK_SECTOR_SIZE, boot_img)) - grub_util_error ("%s", grub_errmsg); - - /* Sync is a Good Thing. */ - sync (); - - free (core_img); - free (boot_img); - grub_device_close (dest_dev); - grub_device_close (root_dev); -} - -static struct option options[] = - { - {"boot-image", required_argument, 0, 'b'}, - {"core-image", required_argument, 0, 'c'}, - {"directory", required_argument, 0, 'd'}, - {"device-map", required_argument, 0, 'm'}, - {"root-device", required_argument, 0, 'r'}, - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'V'}, - {"verbose", no_argument, 0, 'v'}, - {0, 0, 0, 0} - }; - -static void -usage (int status) -{ - if (status) - fprintf (stderr, "Try `%s --help' for more information.\n", program_name); - else - printf ("\ -Usage: %s [OPTION]... DEVICE\n\ -\n\ -Set up images to boot from DEVICE.\n\ -DEVICE must be a GRUB device (e.g. `(hd0,1)').\n\ -\n\ -You should not normally run %s directly. Use grub-install instead.\n\ -\n\ - -b, --boot-image=FILE use FILE as the boot image [default=%s]\n\ - -c, --core-image=FILE use FILE as the core image [default=%s]\n\ - -d, --directory=DIR use GRUB files in the directory DIR [default=%s]\n\ - -m, --device-map=FILE use FILE as the device map [default=%s]\n\ - -r, --root-device=DEV use DEV as the root device [default=guessed]\n\ - -h, --help display this message and exit\n\ - -V, --version print version information and exit\n\ - -v, --verbose print verbose messages\n\ -\n\ -Report bugs to <%s>.\n\ -", program_name, program_name, - DEFAULT_BOOT_FILE, DEFAULT_CORE_FILE, DEFAULT_DIRECTORY, - DEFAULT_DEVICE_MAP, PACKAGE_BUGREPORT); - - exit (status); -} - -struct grub_setup_info -{ - char *boot_file; - char *core_file; - char *dir; - char *dev_map; - char *root_dev; - char *prefix; - char *dest_dev; -}; - -static void -init_info (struct grub_setup_info *gp) -{ - gp->boot_file = NULL; - gp->core_file = NULL; - gp->dir = NULL; - gp->dev_map = NULL; - gp->root_dev = NULL; - gp->prefix = NULL; - gp->dest_dev = NULL; -} - -static int -parse_options (struct grub_setup_info *gp, int argc, char *argv[]) -{ - while (1) - { - int c = getopt_long (argc, argv, "b:c:d:m:r:hVv", options, 0); - - if (c == -1) - break; - else - switch (c) - { - case 'b': - if (gp->boot_file) - free (gp->boot_file); - - gp->boot_file = xstrdup (optarg); - break; - - case 'c': - if (gp->core_file) - free (gp->core_file); - - gp->core_file = xstrdup (optarg); - break; - - case 'd': - if (gp->dir) - free (gp->dir); - - gp->dir = xstrdup (optarg); - break; - - case 'm': - if (gp->dev_map) - free (gp->dev_map); - - gp->dev_map = xstrdup (optarg); - break; - - case 'r': - if (gp->root_dev) - free (gp->root_dev); - - gp->root_dev = xstrdup (optarg); - break; - - case 'h': - usage (0); - break; - - case 'V': - printf ("%s (%s) %s\n", program_name, PACKAGE_NAME, PACKAGE_VERSION); - return 0; - - case 'v': - verbosity++; - break; - - default: - usage (1); - break; - } - } - - if (verbosity > 1) - grub_env_set ("debug", "all"); - - if (optind >= argc) - { - fprintf (stderr, "No device is specified.\n"); - usage (1); - } - - if (optind + 1 != argc) - { - fprintf (stderr, "Unknown extra argument `%s'.\n", argv[optind + 1]); - usage (1); - } - return 1; -} - -static char * -get_device_name (char *dev) -{ - size_t len = strlen (dev); - - if (dev[0] != '(' || dev[len - 1] != ')') - return 0; - - dev[len - 1] = '\0'; - return dev + 1; -} - -static void -find_dest_dev (struct grub_setup_info *gp, char *argv[]) -{ - gp->dest_dev = get_device_name (argv[optind]); - if (! gp->dest_dev) - { - /* Possibly, the user specified an OS device file. */ - gp->dest_dev = grub_util_get_grub_dev (argv[optind]); - if (! gp->dest_dev) - { - fprintf (stderr, "Invalid device `%s'.\n", argv[optind]); - usage (1); - } - grub_util_info ("transformed OS device `%s' into GRUB device `%s'", - argv[optind], gp->dest_dev); - } - else - { - /* For simplicity. */ - gp->dest_dev = xstrdup (gp->dest_dev); - grub_util_info ("Using `%s' as GRUB device", gp->dest_dev); - } -} - -static void -check_root_dev (struct grub_setup_info *gp) -{ - if (gp->root_dev) - { - char *tmp = get_device_name (gp->root_dev); - - if (! tmp) - grub_util_error ("invalid root device `%s'", gp->root_dev); - - tmp = xstrdup (tmp); - free (gp->root_dev); - gp->root_dev = tmp; - } - else - { - char *dir = gp->dir ? gp->dir : DEFAULT_DIRECTORY; - char *root_device = grub_guess_root_device (dir); - - gp->root_dev = grub_util_get_grub_dev (root_device); - if (! gp->root_dev) - { - grub_util_info ("guessing the root device failed, because of `%s'", - grub_errmsg); - grub_util_error ("cannot guess the root device. " - "Specify the option `--root-device'"); - } - grub_util_info ("guessed root device `%s' and root_dev `%s' from " - "dir `%s'", root_device, gp->root_dev, dir); - } -} - -static void -free_memory (struct grub_setup_info *gp) -{ - free (gp->boot_file); - free (gp->core_file); - free (gp->dir); - free (gp->dev_map); - free (gp->root_dev); - free (gp->prefix); - free (gp->dest_dev); -} - -int -main (int argc, char *argv[]) -{ - struct grub_setup_info ginfo; - - set_program_name (argv[0]); - - grub_util_init_nls (); - - init_info (&ginfo); - if (!parse_options (&ginfo, argc, argv)) - return 0; - - /* Initialize the emulated biosdisk driver. */ - grub_util_biosdisk_init (ginfo.dev_map ? ginfo.dev_map : DEFAULT_DEVICE_MAP); - - /* Initialize all modules. */ - grub_init_all (); - - grub_lvm_fini (); - grub_mdraid_fini (); - grub_raid_fini (); - grub_raid_init (); - grub_mdraid_init (); - grub_lvm_init (); - - find_dest_dev (&ginfo, argv); - - ginfo.prefix = grub_make_system_path_relative_to_its_root (ginfo.dir ? - : DEFAULT_DIRECTORY); - - check_root_dev (&ginfo); - - /* Do the real work. */ - setup (ginfo.prefix, - ginfo.dir ? ginfo.dir : DEFAULT_DIRECTORY, - ginfo.boot_file ? ginfo.boot_file : DEFAULT_BOOT_FILE, - ginfo.core_file ? ginfo.core_file : DEFAULT_CORE_FILE, - ginfo.root_dev, ginfo.dest_dev); - - /* Free resources. */ - grub_fini_all (); - - free_memory (&ginfo); - - return 0; -} From 6c1a338ca5ff2685320f06022cd1bbad547e7423 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 14 Sep 2010 21:15:35 +0200 Subject: [PATCH 177/214] * util/i386/pc/grub-setup.c: Merge this ... * util/sparc64/ieee1275/grub-setup.c: ... and this ... * util/grub-setup.c: ... into this. * include/grub/sparc64/ieee1275/boot.h (grub_boot_blocklist) [ASM_FILE]: New struct. * grub-core/fs/ext2.c (grub_ext2_open): Use return error value when possible. --- ChangeLog | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/ChangeLog b/ChangeLog index d3e7c31c0..68ada05ec 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2010-09-14 Vladimir Serbinenko + + * util/i386/pc/grub-setup.c: Merge this ... + * util/sparc64/ieee1275/grub-setup.c: ... and this ... + * util/grub-setup.c: ... into this. + * include/grub/sparc64/ieee1275/boot.h (grub_boot_blocklist) [ASM_FILE]: + New struct. + +2010-09-14 Vladimir Serbinenko + + * grub-core/fs/ext2.c (grub_ext2_open): Use return error value when + possible. + 2010-09-14 Vladimir Serbinenko * grub-core/partmap/sun.c (sun_partition_map_iterate): Don't needlesly From 58db070de1b123274790d32489b39161acc93175 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 14 Sep 2010 21:18:57 +0200 Subject: [PATCH 178/214] Remove now empty util/i386/pc From 545b752f881be2cb5aff919a439de7e53f1eff9e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 14 Sep 2010 22:21:35 +0200 Subject: [PATCH 179/214] Remove deprecated root command. * grub-core/commands/minicmd.c (grub_mini_cmd_root): Removed. All users updated. --- ChangeLog | 7 +++++++ grub-core/commands/minicmd.c | 40 +----------------------------------- 2 files changed, 8 insertions(+), 39 deletions(-) diff --git a/ChangeLog b/ChangeLog index 68ada05ec..5e3d86177 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2010-09-14 Vladimir Serbinenko + + Remove deprecated root command. + + * grub-core/commands/minicmd.c (grub_mini_cmd_root): Removed. All users + updated. + 2010-09-14 Vladimir Serbinenko * util/i386/pc/grub-setup.c: Merge this ... diff --git a/grub-core/commands/minicmd.c b/grub-core/commands/minicmd.c index 3d5f59719..5cf109fde 100644 --- a/grub-core/commands/minicmd.c +++ b/grub-core/commands/minicmd.c @@ -108,40 +108,6 @@ grub_rescue_cmd_info (void) } #endif -/* root [DEVICE] */ -static grub_err_t -grub_mini_cmd_root (struct grub_command *cmd __attribute__ ((unused)), - int argc, char *argv[]) -{ - grub_device_t dev; - grub_fs_t fs; - - if (argc > 0) - { - char *device_name = grub_file_get_device_name (argv[0]); - if (! device_name) - return grub_errno; - - grub_env_set ("root", device_name); - grub_free (device_name); - } - - dev = grub_device_open (0); - if (! dev) - return grub_errno; - - fs = grub_fs_probe (dev); - if (grub_errno == GRUB_ERR_UNKNOWN_FS) - grub_errno = GRUB_ERR_NONE; - - grub_printf ("(%s): Filesystem is %s.\n", - grub_env_get ("root"), fs ? fs->name : "unknown"); - - grub_device_close (dev); - - return 0; -} - /* dump ADDRESS [SIZE] */ static grub_err_t grub_mini_cmd_dump (struct grub_command *cmd __attribute__ ((unused)), @@ -226,7 +192,7 @@ grub_mini_cmd_exit (struct grub_command *cmd __attribute__ ((unused)), return 0; } -static grub_command_t cmd_cat, cmd_help, cmd_root; +static grub_command_t cmd_cat, cmd_help; static grub_command_t cmd_dump, cmd_rmmod, cmd_lsmod, cmd_exit; GRUB_MOD_INIT(minicmd) @@ -237,9 +203,6 @@ GRUB_MOD_INIT(minicmd) cmd_help = grub_register_command ("help", grub_mini_cmd_help, 0, N_("Show this message.")); - cmd_root = - grub_register_command ("root", grub_mini_cmd_root, - N_("[DEVICE]"), N_("Set the root device.")); cmd_dump = grub_register_command ("dump", grub_mini_cmd_dump, N_("ADDR"), N_("Dump memory.")); @@ -258,7 +221,6 @@ GRUB_MOD_FINI(minicmd) { grub_unregister_command (cmd_cat); grub_unregister_command (cmd_help); - grub_unregister_command (cmd_root); grub_unregister_command (cmd_dump); grub_unregister_command (cmd_rmmod); grub_unregister_command (cmd_lsmod); From 5fe7620a4e9622566166f894f3451801d6c3aba2 Mon Sep 17 00:00:00 2001 From: Seth Goldberg Date: Tue, 14 Sep 2010 22:32:33 +0200 Subject: [PATCH 180/214] Fix solaris compilation. * grub-core/Makefile.core.def (kernel): Include gnulib/error.c on emu. (grub-emu): Add LIBZFS and LIBNVPAIR to ldadd. (grub-emu-list): Likewise. --- ChangeLog | 8 ++++++++ grub-core/Makefile.core.def | 5 +++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5e3d86177..8b8f7db26 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2010-09-14 Seth Goldberg + + Fix solaris compilation. + + * grub-core/Makefile.core.def (kernel): Include gnulib/error.c on emu. + (grub-emu): Add LIBZFS and LIBNVPAIR to ldadd. + (grub-emu-list): Likewise. + 2010-09-14 Vladimir Serbinenko Remove deprecated root command. diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 54ffdccf2..2fca91430 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -150,6 +150,7 @@ kernel = { emu = disk/host.c; emu = gnulib/progname.c; + emu = gnulib/error.c; emu = kern/emu/console.c; emu = kern/emu/getroot.c; emu = kern/emu/hostdisk.c; @@ -187,7 +188,7 @@ program = { ldadd = 'kernel.img$(EXEEXT)'; ldadd = '$(MODULE_FILES)'; - ldadd = '$(LIBUTIL) $(LIBCURSES) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER)'; + ldadd = '$(LIBUTIL) $(LIBCURSES) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)'; enable = emu; }; @@ -200,7 +201,7 @@ program = { emu_nodist = symlist.c; ldadd = 'kernel.img$(EXEEXT)'; - ldadd = '$(LIBUTIL) $(LIBCURSES) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER)'; + ldadd = '$(LIBUTIL) $(LIBCURSES) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR)'; enable = emu; }; From ed80f7d586ad4608828a346052505a82459fda20 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 14 Sep 2010 23:06:01 +0200 Subject: [PATCH 181/214] * include/grub/command.h (GRUB_COMMAND_FLAG_CMDLINE): Removed. All users updated. (GRUB_COMMAND_FLAG_MENU): Likewise. (GRUB_COMMAND_FLAG_BOTH): Likewise. (GRUB_COMMAND_FLAG_TITLE): Removed. (GRUB_COMMAND_FLAG_NO_ECHO): Likewise. (GRUB_COMMAND_FLAG_EXTCMD): Moved into enum. (GRUB_COMMAND_FLAG_DYNCMD): Likewise. (GRUB_COMMAND_FLAG_BLOCKS): Likewise. (grub_command_flags_t): New enum. All users updated. --- ChangeLog | 13 +++++++++++++ grub-core/commands/acpi.c | 3 +-- grub-core/commands/cat.c | 2 +- grub-core/commands/echo.c | 2 +- grub-core/commands/extcmd.c | 4 ++-- grub-core/commands/hashsum.c | 12 ++++-------- grub-core/commands/hdparm.c | 3 +-- grub-core/commands/help.c | 6 ++---- grub-core/commands/hexdump.c | 3 +-- grub-core/commands/i386/cpuid.c | 2 +- grub-core/commands/i386/pc/drivemap.c | 3 +-- grub-core/commands/i386/pc/halt.c | 3 +-- grub-core/commands/i386/pc/sendkey.c | 3 +-- grub-core/commands/iorw.c | 6 +++--- grub-core/commands/keystatus.c | 3 +-- grub-core/commands/loadenv.c | 11 +++-------- grub-core/commands/ls.c | 2 +- grub-core/commands/lsacpi.c | 3 +-- grub-core/commands/lspci.c | 4 ++-- grub-core/commands/memrw.c | 6 +++--- grub-core/commands/menuentry.c | 2 +- grub-core/commands/probe.c | 3 +-- grub-core/commands/regexp.c | 3 +-- grub-core/commands/search_wrap.c | 3 +-- grub-core/commands/setpci.c | 2 +- grub-core/commands/sleep.c | 2 +- grub-core/disk/loopback.c | 3 +-- grub-core/hello/hello.c | 4 ++-- grub-core/kern/command.c | 2 +- grub-core/loader/i386/bsd.c | 9 +++------ grub-core/loader/xnu.c | 3 +-- grub-core/normal/completion.c | 7 ++----- grub-core/normal/dyncmd.c | 1 - grub-core/term/gfxterm.c | 3 +-- grub-core/term/serial.c | 3 +-- grub-core/tests/lib/functional_test.c | 3 +-- grub-core/tests/test_blockarg.c | 2 +- include/grub/command.h | 27 ++++++++++----------------- include/grub/extcmd.h | 4 ++-- 39 files changed, 76 insertions(+), 104 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8b8f7db26..4bb294fab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2010-09-14 Vladimir Serbinenko + + * include/grub/command.h (GRUB_COMMAND_FLAG_CMDLINE): Removed. All + users updated. + (GRUB_COMMAND_FLAG_MENU): Likewise. + (GRUB_COMMAND_FLAG_BOTH): Likewise. + (GRUB_COMMAND_FLAG_TITLE): Removed. + (GRUB_COMMAND_FLAG_NO_ECHO): Likewise. + (GRUB_COMMAND_FLAG_EXTCMD): Moved into enum. + (GRUB_COMMAND_FLAG_DYNCMD): Likewise. + (GRUB_COMMAND_FLAG_BLOCKS): Likewise. + (grub_command_flags_t): New enum. All users updated. + 2010-09-14 Seth Goldberg Fix solaris compilation. diff --git a/grub-core/commands/acpi.c b/grub-core/commands/acpi.c index 9d5e93495..931b2e39d 100644 --- a/grub-core/commands/acpi.c +++ b/grub-core/commands/acpi.c @@ -758,8 +758,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(acpi) { - cmd = grub_register_extcmd ("acpi", grub_cmd_acpi, - GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("acpi", grub_cmd_acpi, 0, N_("[-1|-2] [--exclude=TABLE1,TABLE2|" "--load-only=table1,table2] FILE1" " [FILE2] [...]"), diff --git a/grub-core/commands/cat.c b/grub-core/commands/cat.c index 68ca83c5d..f3d08e960 100644 --- a/grub-core/commands/cat.c +++ b/grub-core/commands/cat.c @@ -91,7 +91,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(cat) { - cmd = grub_register_extcmd ("cat", grub_cmd_cat, GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("cat", grub_cmd_cat, 0, N_("FILE"), N_("Show the contents of a file."), options); } diff --git a/grub-core/commands/echo.c b/grub-core/commands/echo.c index 6bc00eae8..6d69bc3f0 100644 --- a/grub-core/commands/echo.c +++ b/grub-core/commands/echo.c @@ -113,7 +113,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(echo) { - cmd = grub_register_extcmd ("echo", grub_cmd_echo, GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("echo", grub_cmd_echo, 0, N_("[-e|-n] STRING"), N_("Display a line of text."), options); } diff --git a/grub-core/commands/extcmd.c b/grub-core/commands/extcmd.c index 44a4b6cfd..e9274fbab 100644 --- a/grub-core/commands/extcmd.c +++ b/grub-core/commands/extcmd.c @@ -66,7 +66,7 @@ grub_extcmd_dispatch (struct grub_command *cmd, int argc, char **args) grub_extcmd_t grub_register_extcmd_prio (const char *name, grub_extcmd_func_t func, - unsigned flags, const char *summary, + grub_command_flags_t flags, const char *summary, const char *description, const struct grub_arg_option *parser, int prio) @@ -99,7 +99,7 @@ grub_register_extcmd_prio (const char *name, grub_extcmd_func_t func, grub_extcmd_t grub_register_extcmd (const char *name, grub_extcmd_func_t func, - unsigned flags, const char *summary, + grub_command_flags_t flags, const char *summary, const char *description, const struct grub_arg_option *parser) { diff --git a/grub-core/commands/hashsum.c b/grub-core/commands/hashsum.c index 6f65b4ab3..e926c0435 100644 --- a/grub-core/commands/hashsum.c +++ b/grub-core/commands/hashsum.c @@ -252,26 +252,22 @@ static grub_extcmd_t cmd, cmd_md5, cmd_sha256, cmd_sha512; GRUB_MOD_INIT(hashsum) { - cmd = grub_register_extcmd ("hashsum", grub_cmd_hashsum, - GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("hashsum", grub_cmd_hashsum, 0, "hashsum -h HASH [-c FILE [-p PREFIX]] " "[FILE1 [FILE2 ...]]", "Compute or check hash checksum.", options); - cmd_md5 = grub_register_extcmd ("md5sum", grub_cmd_hashsum, - GRUB_COMMAND_FLAG_BOTH, + cmd_md5 = grub_register_extcmd ("md5sum", grub_cmd_hashsum, 0, N_("[-c FILE [-p PREFIX]] " "[FILE1 [FILE2 ...]]"), N_("Compute or check hash checksum."), options); - cmd_sha256 = grub_register_extcmd ("sha256sum", grub_cmd_hashsum, - GRUB_COMMAND_FLAG_BOTH, + cmd_sha256 = grub_register_extcmd ("sha256sum", grub_cmd_hashsum, 0, N_("[-c FILE [-p PREFIX]] " "[FILE1 [FILE2 ...]]"), "Compute or check hash checksum.", options); - cmd_sha512 = grub_register_extcmd ("sha512sum", grub_cmd_hashsum, - GRUB_COMMAND_FLAG_BOTH, + cmd_sha512 = grub_register_extcmd ("sha512sum", grub_cmd_hashsum, 0, N_("[-c FILE [-p PREFIX]] " "[FILE1 [FILE2 ...]]"), N_("Compute or check hash checksum."), diff --git a/grub-core/commands/hdparm.c b/grub-core/commands/hdparm.c index 54724077d..b6ab78755 100644 --- a/grub-core/commands/hdparm.c +++ b/grub-core/commands/hdparm.c @@ -409,8 +409,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(hdparm) { - cmd = grub_register_extcmd ("hdparm", grub_cmd_hdparm, - GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("hdparm", grub_cmd_hdparm, 0, N_("[OPTIONS] DISK"), N_("Get/set ATA disk parameters."), options); } diff --git a/grub-core/commands/help.c b/grub-core/commands/help.c index 1ca46aa7e..ff6d7ed2e 100644 --- a/grub-core/commands/help.c +++ b/grub-core/commands/help.c @@ -38,8 +38,7 @@ grub_cmd_help (grub_extcmd_context_t ctxt __attribute__ ((unused)), int argc, grub_command_t cmd; FOR_COMMANDS(cmd) { - if ((cmd->prio & GRUB_PRIO_LIST_FLAG_ACTIVE) && - (cmd->flags & GRUB_COMMAND_FLAG_CMDLINE)) + if ((cmd->prio & GRUB_PRIO_LIST_FLAG_ACTIVE)) { struct grub_term_output *term; const char *summary_translated = _(cmd->summary); @@ -131,8 +130,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(help) { - cmd = grub_register_extcmd ("help", grub_cmd_help, - GRUB_COMMAND_FLAG_CMDLINE, + cmd = grub_register_extcmd ("help", grub_cmd_help, 0, N_("[PATTERN ...]"), N_("Show a help message."), 0); } diff --git a/grub-core/commands/hexdump.c b/grub-core/commands/hexdump.c index 08a94eb64..629f2a069 100644 --- a/grub-core/commands/hexdump.c +++ b/grub-core/commands/hexdump.c @@ -119,8 +119,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT (hexdump) { - cmd = grub_register_extcmd ("hexdump", grub_cmd_hexdump, - GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("hexdump", grub_cmd_hexdump, 0, N_("[OPTIONS] FILE_OR_DEVICE"), N_("Dump the contents of a file or memory."), options); diff --git a/grub-core/commands/i386/cpuid.c b/grub-core/commands/i386/cpuid.c index 412b284d0..f5f0f15a8 100644 --- a/grub-core/commands/i386/cpuid.c +++ b/grub-core/commands/i386/cpuid.c @@ -88,7 +88,7 @@ GRUB_MOD_INIT(cpuid) done: #endif - cmd = grub_register_extcmd ("cpuid", grub_cmd_cpuid, GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("cpuid", grub_cmd_cpuid, 0, "[-l]", N_("Check for CPU features."), options); } diff --git a/grub-core/commands/i386/pc/drivemap.c b/grub-core/commands/i386/pc/drivemap.c index 7ecfe7454..d4871de52 100644 --- a/grub-core/commands/i386/pc/drivemap.c +++ b/grub-core/commands/i386/pc/drivemap.c @@ -401,8 +401,7 @@ GRUB_MOD_INIT (drivemap) { grub_get_root_biosnumber_saved = grub_get_root_biosnumber; grub_get_root_biosnumber = grub_get_root_biosnumber_drivemap; - cmd = grub_register_extcmd ("drivemap", grub_cmd_drivemap, - GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("drivemap", grub_cmd_drivemap, 0, N_("-l | -r | [-s] grubdev osdisk."), N_("Manage the BIOS drive mappings."), options); diff --git a/grub-core/commands/i386/pc/halt.c b/grub-core/commands/i386/pc/halt.c index 44a88bb05..81eb6a1bb 100644 --- a/grub-core/commands/i386/pc/halt.c +++ b/grub-core/commands/i386/pc/halt.c @@ -114,8 +114,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(halt) { - cmd = grub_register_extcmd ("halt", grub_cmd_halt, GRUB_COMMAND_FLAG_BOTH, - "[-n]", + cmd = grub_register_extcmd ("halt", grub_cmd_halt, 0, "[-n]", N_("Halt the system, if possible using APM."), options); } diff --git a/grub-core/commands/i386/pc/sendkey.c b/grub-core/commands/i386/pc/sendkey.c index 1f506b3cd..c777ea60a 100644 --- a/grub-core/commands/i386/pc/sendkey.c +++ b/grub-core/commands/i386/pc/sendkey.c @@ -366,8 +366,7 @@ static void *preboot_hook; GRUB_MOD_INIT (sendkey) { - cmd = grub_register_extcmd ("sendkey", grub_cmd_sendkey, - GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("sendkey", grub_cmd_sendkey, 0, "sendkey [KEYSTROKE1] [KEYSTROKE2] ...", "Emulate a keystroke", options); diff --git a/grub-core/commands/iorw.c b/grub-core/commands/iorw.c index 5157ebd4c..20d203e92 100644 --- a/grub-core/commands/iorw.c +++ b/grub-core/commands/iorw.c @@ -117,13 +117,13 @@ grub_cmd_write (grub_command_t cmd, int argc, char **argv) GRUB_MOD_INIT(memrw) { cmd_read_byte = - grub_register_extcmd ("inb", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH, + grub_register_extcmd ("inb", grub_cmd_read, 0, N_("PORT"), N_("Read byte from PORT."), options); cmd_read_word = - grub_register_extcmd ("inw", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH, + grub_register_extcmd ("inw", grub_cmd_read, 0, N_("PORT"), N_("Read word from PORT."), options); cmd_read_dword = - grub_register_extcmd ("inl", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH, + grub_register_extcmd ("inl", grub_cmd_read, 0, N_("PORT"), N_("Read dword from PORT."), options); cmd_write_byte = grub_register_command ("outb", grub_cmd_write, diff --git a/grub-core/commands/keystatus.c b/grub-core/commands/keystatus.c index c83c00560..64e5a08d7 100644 --- a/grub-core/commands/keystatus.c +++ b/grub-core/commands/keystatus.c @@ -80,8 +80,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(keystatus) { - cmd = grub_register_extcmd ("keystatus", grub_cmd_keystatus, - GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("keystatus", grub_cmd_keystatus, 0, N_("[--shift] [--ctrl] [--alt]"), N_("Check key modifier status."), options); diff --git a/grub-core/commands/loadenv.c b/grub-core/commands/loadenv.c index 9a1873ba9..38b3a84c6 100644 --- a/grub-core/commands/loadenv.c +++ b/grub-core/commands/loadenv.c @@ -375,20 +375,15 @@ static grub_extcmd_t cmd_load, cmd_list, cmd_save; GRUB_MOD_INIT(loadenv) { cmd_load = - grub_register_extcmd ("load_env", grub_cmd_load_env, - GRUB_COMMAND_FLAG_BOTH, - N_("[-f FILE]"), + grub_register_extcmd ("load_env", grub_cmd_load_env, 0, N_("[-f FILE]"), N_("Load variables from environment block file."), options); cmd_list = - grub_register_extcmd ("list_env", grub_cmd_list_env, - GRUB_COMMAND_FLAG_BOTH, - N_("[-f FILE]"), + grub_register_extcmd ("list_env", grub_cmd_list_env, 0, N_("[-f FILE]"), N_("List variables from environment block file."), options); cmd_save = - grub_register_extcmd ("save_env", grub_cmd_save_env, - GRUB_COMMAND_FLAG_BOTH, + grub_register_extcmd ("save_env", grub_cmd_save_env, 0, N_("[-f FILE] variable_name [...]"), N_("Save variables to environment block file."), options); diff --git a/grub-core/commands/ls.c b/grub-core/commands/ls.c index ed8afd4ae..3bd6607be 100644 --- a/grub-core/commands/ls.c +++ b/grub-core/commands/ls.c @@ -269,7 +269,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(ls) { - cmd = grub_register_extcmd ("ls", grub_cmd_ls, GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("ls", grub_cmd_ls, 0, N_("[-l|-h|-a] [FILE]"), N_("List devices and files."), options); } diff --git a/grub-core/commands/lsacpi.c b/grub-core/commands/lsacpi.c index 149de6b79..64b559665 100644 --- a/grub-core/commands/lsacpi.c +++ b/grub-core/commands/lsacpi.c @@ -238,8 +238,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(lsapi) { - cmd = grub_register_extcmd ("lsacpi", grub_cmd_lsacpi, GRUB_COMMAND_FLAG_BOTH, - N_("[-1|-2]"), + cmd = grub_register_extcmd ("lsacpi", grub_cmd_lsacpi, 0, N_("[-1|-2]"), N_("Show ACPI information."), options); } diff --git a/grub-core/commands/lspci.c b/grub-core/commands/lspci.c index bc52e060a..fd2d4eaf2 100644 --- a/grub-core/commands/lspci.c +++ b/grub-core/commands/lspci.c @@ -224,8 +224,8 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(lspci) { - cmd = grub_register_extcmd ("lspci", grub_cmd_lspci, GRUB_COMMAND_FLAG_BOTH, - "[-i]", N_("List PCI devices."), options); + cmd = grub_register_extcmd ("lspci", grub_cmd_lspci, 0, "[-i]", + N_("List PCI devices."), options); } GRUB_MOD_FINI(lspci) diff --git a/grub-core/commands/memrw.c b/grub-core/commands/memrw.c index d28f45ec1..28aac7d81 100644 --- a/grub-core/commands/memrw.c +++ b/grub-core/commands/memrw.c @@ -119,13 +119,13 @@ grub_cmd_write (grub_command_t cmd, int argc, char **argv) GRUB_MOD_INIT(memrw) { cmd_read_byte = - grub_register_extcmd ("read_byte", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH, + grub_register_extcmd ("read_byte", grub_cmd_read, 0, N_("ADDR"), N_("Read byte from ADDR."), options); cmd_read_word = - grub_register_extcmd ("read_word", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH, + grub_register_extcmd ("read_word", grub_cmd_read, 0, N_("ADDR"), N_("Read word from ADDR."), options); cmd_read_dword = - grub_register_extcmd ("read_dword", grub_cmd_read, GRUB_COMMAND_FLAG_BOTH, + grub_register_extcmd ("read_dword", grub_cmd_read, 0, N_("ADDR"), N_("Read dword from ADDR."), options); cmd_write_byte = grub_register_command ("write_byte", grub_cmd_write, diff --git a/grub-core/commands/menuentry.c b/grub-core/commands/menuentry.c index c28c6ef6f..9c4139d7d 100644 --- a/grub-core/commands/menuentry.c +++ b/grub-core/commands/menuentry.c @@ -274,7 +274,7 @@ void grub_menu_init (void) { cmd = grub_register_extcmd ("menuentry", grub_cmd_menuentry, - GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_BLOCKS, + GRUB_COMMAND_FLAG_BLOCKS, N_("BLOCK"), N_("Define a menuentry."), options); } diff --git a/grub-core/commands/probe.c b/grub-core/commands/probe.c index f3941e029..abe84895d 100644 --- a/grub-core/commands/probe.c +++ b/grub-core/commands/probe.c @@ -150,8 +150,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT (probe) { - cmd = grub_register_extcmd ("probe", grub_cmd_probe, GRUB_COMMAND_FLAG_BOTH, - N_("[DEVICE]"), + cmd = grub_register_extcmd ("probe", grub_cmd_probe, 0, N_("[DEVICE]"), N_("Retrieve device info."), options); } diff --git a/grub-core/commands/regexp.c b/grub-core/commands/regexp.c index 4329483af..f27a147af 100644 --- a/grub-core/commands/regexp.c +++ b/grub-core/commands/regexp.c @@ -136,8 +136,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(regexp) { - cmd = grub_register_extcmd ("regexp", grub_cmd_regexp, - GRUB_COMMAND_FLAG_BOTH, N_("REGEXP STRING"), + cmd = grub_register_extcmd ("regexp", grub_cmd_regexp, 0, N_("REGEXP STRING"), N_("Test if REGEXP matches STRING."), options); /* Setup GRUB script wildcard translator. */ diff --git a/grub-core/commands/search_wrap.c b/grub-core/commands/search_wrap.c index 61eb78203..402421f65 100644 --- a/grub-core/commands/search_wrap.c +++ b/grub-core/commands/search_wrap.c @@ -90,8 +90,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(search) { cmd = - grub_register_extcmd ("search", grub_cmd_search, - GRUB_COMMAND_FLAG_BOTH, + grub_register_extcmd ("search", grub_cmd_search, 0, N_("[-f|-l|-u|-s|-n] [--hint HINT [--hint HINT] ...]" " NAME"), N_("Search devices by file, filesystem label" diff --git a/grub-core/commands/setpci.c b/grub-core/commands/setpci.c index 5e947cd7d..7b194ed17 100644 --- a/grub-core/commands/setpci.c +++ b/grub-core/commands/setpci.c @@ -329,7 +329,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(setpci) { - cmd = grub_register_extcmd ("setpci", grub_cmd_setpci, GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("setpci", grub_cmd_setpci, 0, N_("[-s POSITION] [-d DEVICE] [-v VAR] " "[REGISTER][=VALUE[:MASK]]"), N_("Manipulate PCI devices."), options); diff --git a/grub-core/commands/sleep.c b/grub-core/commands/sleep.c index ee0875cf7..da9937548 100644 --- a/grub-core/commands/sleep.c +++ b/grub-core/commands/sleep.c @@ -101,7 +101,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(sleep) { - cmd = grub_register_extcmd ("sleep", grub_cmd_sleep, GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("sleep", grub_cmd_sleep, 0, N_("NUMBER_OF_SECONDS"), N_("Wait for a specified number of seconds."), options); diff --git a/grub-core/disk/loopback.c b/grub-core/disk/loopback.c index c8ee52580..ae4cb9a9c 100644 --- a/grub-core/disk/loopback.c +++ b/grub-core/disk/loopback.c @@ -221,8 +221,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(loopback) { - cmd = grub_register_extcmd ("loopback", grub_cmd_loopback, - GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("loopback", grub_cmd_loopback, 0, N_("[-d|-p] DEVICENAME FILE."), N_("Make a device of a file."), options); grub_disk_dev_register (&grub_loopback_dev); diff --git a/grub-core/hello/hello.c b/grub-core/hello/hello.c index 183ee7798..77c4c96b1 100644 --- a/grub-core/hello/hello.c +++ b/grub-core/hello/hello.c @@ -39,8 +39,8 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(hello) { - cmd = grub_register_extcmd ("hello", grub_cmd_hello, GRUB_COMMAND_FLAG_BOTH, - 0, N_("Say \"Hello World\"."), 0); + cmd = grub_register_extcmd ("hello", grub_cmd_hello, 0, 0, + N_("Say \"Hello World\"."), 0); } GRUB_MOD_FINI(hello) diff --git a/grub-core/kern/command.c b/grub-core/kern/command.c index 477240d57..7f353b653 100644 --- a/grub-core/kern/command.c +++ b/grub-core/kern/command.c @@ -40,7 +40,7 @@ grub_register_command_prio (const char *name, cmd->summary = (summary) ? summary : ""; cmd->description = description; - cmd->flags = GRUB_COMMAND_FLAG_BOTH; + cmd->flags = 0; cmd->prio = prio; grub_prio_list_insert (GRUB_AS_PRIO_LIST_P (&grub_command_list), diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c index 2e92bc42f..16dfc731c 100644 --- a/grub-core/loader/i386/bsd.c +++ b/grub-core/loader/i386/bsd.c @@ -1942,16 +1942,13 @@ GRUB_MOD_INIT (bsd) /* Net and OpenBSD kernels are often compressed. */ grub_dl_load ("gzio"); - cmd_freebsd = grub_register_extcmd ("kfreebsd", grub_cmd_freebsd, - GRUB_COMMAND_FLAG_BOTH, + cmd_freebsd = grub_register_extcmd ("kfreebsd", grub_cmd_freebsd, 0, N_("FILE"), N_("Load kernel of FreeBSD."), freebsd_opts); - cmd_openbsd = grub_register_extcmd ("kopenbsd", grub_cmd_openbsd, - GRUB_COMMAND_FLAG_BOTH, + cmd_openbsd = grub_register_extcmd ("kopenbsd", grub_cmd_openbsd, 0, N_("FILE"), N_("Load kernel of OpenBSD."), openbsd_opts); - cmd_netbsd = grub_register_extcmd ("knetbsd", grub_cmd_netbsd, - GRUB_COMMAND_FLAG_BOTH, + cmd_netbsd = grub_register_extcmd ("knetbsd", grub_cmd_netbsd, 0, N_("FILE"), N_("Load kernel of NetBSD."), netbsd_opts); cmd_freebsd_loadenv = diff --git a/grub-core/loader/xnu.c b/grub-core/loader/xnu.c index ece65611a..d0b32dc6f 100644 --- a/grub-core/loader/xnu.c +++ b/grub-core/loader/xnu.c @@ -1434,8 +1434,7 @@ GRUB_MOD_INIT(xnu) "Load XNU ramdisk. " "It will be seen as md0."); cmd_splash = grub_register_extcmd ("xnu_splash", - grub_cmd_xnu_splash, - GRUB_COMMAND_FLAG_BOTH, 0, + grub_cmd_xnu_splash, 0, 0, N_("Load a splash image for XNU."), xnu_splash_cmd_options); diff --git a/grub-core/normal/completion.c b/grub-core/normal/completion.c index f19919d1d..197cb1145 100644 --- a/grub-core/normal/completion.c +++ b/grub-core/normal/completion.c @@ -429,11 +429,8 @@ grub_normal_do_completion (char *buf, int *restore, { if (cmd->prio & GRUB_PRIO_LIST_FLAG_ACTIVE) { - if (cmd->flags & GRUB_COMMAND_FLAG_CMDLINE) - { - if (add_completion (cmd->name, " ", GRUB_COMPLETION_TYPE_COMMAND)) - goto fail; - } + if (add_completion (cmd->name, " ", GRUB_COMPLETION_TYPE_COMMAND)) + goto fail; } } } diff --git a/grub-core/normal/dyncmd.c b/grub-core/normal/dyncmd.c index 3519253f6..ed98855eb 100644 --- a/grub-core/normal/dyncmd.c +++ b/grub-core/normal/dyncmd.c @@ -155,7 +155,6 @@ read_command_list (const char *prefix) grub_dyncmd_dispatcher, GRUB_COMMAND_FLAG_BLOCKS | GRUB_COMMAND_FLAG_EXTCMD - | GRUB_COMMAND_FLAG_CMDLINE | GRUB_COMMAND_FLAG_DYNCMD, 0, N_("not loaded"), 0, prio); diff --git a/grub-core/term/gfxterm.c b/grub-core/term/gfxterm.c index 3616eb453..9a10d47b0 100644 --- a/grub-core/term/gfxterm.c +++ b/grub-core/term/gfxterm.c @@ -1207,8 +1207,7 @@ GRUB_MOD_INIT(gfxterm) grub_term_register_output ("gfxterm", &grub_video_term); background_image_cmd_handle = grub_register_extcmd ("background_image", - grub_gfxterm_background_image_cmd, - GRUB_COMMAND_FLAG_BOTH, + grub_gfxterm_background_image_cmd, 0, N_("[-m (stretch|normal)] FILE"), N_("Load background image for active terminal."), background_image_cmd_options); diff --git a/grub-core/term/serial.c b/grub-core/term/serial.c index 394fc1576..6c8a87225 100644 --- a/grub-core/term/serial.c +++ b/grub-core/term/serial.c @@ -341,8 +341,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(serial) { - cmd = grub_register_extcmd ("serial", grub_cmd_serial, - GRUB_COMMAND_FLAG_BOTH, + cmd = grub_register_extcmd ("serial", grub_cmd_serial, 0, N_("[OPTIONS...]"), N_("Configure serial port."), options); #ifndef GRUB_MACHINE_EMU diff --git a/grub-core/tests/lib/functional_test.c b/grub-core/tests/lib/functional_test.c index 82bf372c0..521f4ad22 100644 --- a/grub-core/tests/lib/functional_test.c +++ b/grub-core/tests/lib/functional_test.c @@ -37,8 +37,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT (functional_test) { - cmd = grub_register_extcmd ("functional_test", grub_functional_test, - GRUB_COMMAND_FLAG_CMDLINE, 0, + cmd = grub_register_extcmd ("functional_test", grub_functional_test, 0, 0, "Run all functional tests.", 0); } diff --git a/grub-core/tests/test_blockarg.c b/grub-core/tests/test_blockarg.c index bb6f3c3f0..41460fb7e 100644 --- a/grub-core/tests/test_blockarg.c +++ b/grub-core/tests/test_blockarg.c @@ -40,7 +40,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(test_blockarg) { cmd = grub_register_extcmd ("test_blockarg", test_blockarg, - GRUB_COMMAND_FLAG_BOTH | GRUB_COMMAND_FLAG_BLOCKS, + GRUB_COMMAND_FLAG_BLOCKS, N_("BLOCK"), N_("Print and execute block argument."), 0); } diff --git a/include/grub/command.h b/include/grub/command.h index 599b99437..31b639548 100644 --- a/include/grub/command.h +++ b/include/grub/command.h @@ -23,22 +23,15 @@ #include #include -/* Can be run in the command-line. */ -#define GRUB_COMMAND_FLAG_CMDLINE 0x1 -/* Can be run in the menu. */ -#define GRUB_COMMAND_FLAG_MENU 0x2 -/* Can be run in both interfaces. */ -#define GRUB_COMMAND_FLAG_BOTH 0x3 -/* Only for the command title. */ -#define GRUB_COMMAND_FLAG_TITLE 0x4 -/* Don't print the command on booting. */ -#define GRUB_COMMAND_FLAG_NO_ECHO 0x8 -/* This is an extended command. */ -#define GRUB_COMMAND_FLAG_EXTCMD 0x10 -/* This is an dynamic command. */ -#define GRUB_COMMAND_FLAG_DYNCMD 0x20 -/* This command accepts block arguments. */ -#define GRUB_COMMAND_FLAG_BLOCKS 0x40 +typedef enum grub_command_flags + { + /* This is an extended command. */ + GRUB_COMMAND_FLAG_EXTCMD = 0x10, + /* This is an dynamic command. */ + GRUB_COMMAND_FLAG_DYNCMD = 0x20, + /* This command accepts block arguments. */ + GRUB_COMMAND_FLAG_BLOCKS = 0x40 + } grub_command_flags_t; struct grub_command; @@ -61,7 +54,7 @@ struct grub_command grub_command_func_t func; /* The flags. */ - unsigned flags; + grub_command_flags_t flags; /* The summary of the command usage. */ const char *summary; diff --git a/include/grub/extcmd.h b/include/grub/extcmd.h index 773e47854..c34a1df66 100644 --- a/include/grub/extcmd.h +++ b/include/grub/extcmd.h @@ -57,14 +57,14 @@ typedef struct grub_extcmd_context *grub_extcmd_context_t; grub_extcmd_t grub_register_extcmd (const char *name, grub_extcmd_func_t func, - unsigned flags, + grub_command_flags_t flags, const char *summary, const char *description, const struct grub_arg_option *parser); grub_extcmd_t grub_register_extcmd_prio (const char *name, grub_extcmd_func_t func, - unsigned flags, + grub_command_flags_t flags, const char *summary, const char *description, const struct grub_arg_option *parser, From 79c4eeb919217a21c52e8693a4ea0e570701dc0b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 14 Sep 2010 23:30:06 +0200 Subject: [PATCH 182/214] Fix incorrect echo options handling. Reported by: Yves Blusseau. * include/grub/command.h (grub_command_flags_t): New flags GRUB_COMMAND_ACCEPT_DASH and GRUB_COMMAND_OPTIONS_AT_START. * grub-core/lib/arg.c (grub_arg_parse): Handle new flags. * grub-core/commands/echo.c (GRUB_MOD_INIT): Use new flags. --- ChangeLog | 10 ++++++++++ grub-core/commands/echo.c | 4 +++- grub-core/lib/arg.c | 36 ++++++++++++++++++++++++++++++------ include/grub/command.h | 6 +++++- 4 files changed, 48 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4bb294fab..0ec383b3a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2010-09-14 Vladimir Serbinenko + + Fix incorrect echo options handling. + Reported by: Yves Blusseau. + + * include/grub/command.h (grub_command_flags_t): New flags + GRUB_COMMAND_ACCEPT_DASH and GRUB_COMMAND_OPTIONS_AT_START. + * grub-core/lib/arg.c (grub_arg_parse): Handle new flags. + * grub-core/commands/echo.c (GRUB_MOD_INIT): Use new flags. + 2010-09-14 Vladimir Serbinenko * include/grub/command.h (GRUB_COMMAND_FLAG_CMDLINE): Removed. All diff --git a/grub-core/commands/echo.c b/grub-core/commands/echo.c index 6d69bc3f0..13bc1c3fd 100644 --- a/grub-core/commands/echo.c +++ b/grub-core/commands/echo.c @@ -113,7 +113,9 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(echo) { - cmd = grub_register_extcmd ("echo", grub_cmd_echo, 0, + cmd = grub_register_extcmd ("echo", grub_cmd_echo, + GRUB_COMMAND_ACCEPT_DASH + | GRUB_COMMAND_OPTIONS_AT_START, N_("[-e|-n] STRING"), N_("Display a line of text."), options); } diff --git a/grub-core/lib/arg.c b/grub-core/lib/arg.c index f3352520b..f487de7ad 100644 --- a/grub-core/lib/arg.c +++ b/grub-core/lib/arg.c @@ -231,7 +231,6 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, { int curarg; int arglen; - int complete = 0; char **argl = 0; int num = 0; auto grub_err_t add_arg (char *s); @@ -258,7 +257,8 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, char *option = 0; /* No option is used. */ - if (arg[0] != '-' || grub_strlen (arg) == 1) + if ((num && GRUB_COMMAND_OPTIONS_AT_START) + || arg[0] != '-' || grub_strlen (arg) == 1) { if (add_arg (arg) != 0) goto fail; @@ -269,11 +269,28 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, /* One or more short options. */ if (arg[1] != '-') { - char *curshort = arg + 1; + char *curshort; + + if (cmd->cmd->flags & GRUB_COMMAND_ACCEPT_DASH) + { + for (curshort = arg + 1; *curshort; curshort++) + if (!find_short (cmd->options, *curshort)) + break; + + if (*curshort) + { + if (add_arg (arg) != 0) + goto fail; + continue; + } + } + + curshort = arg + 1; while (1) { opt = find_short (cmd->options, *curshort); + if (! opt) { grub_error (GRUB_ERR_BAD_ARGUMENT, @@ -330,6 +347,14 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, } opt = find_long (cmd->options, arg + 2, arglen); + + if (!opt && (cmd->cmd->flags & GRUB_COMMAND_ACCEPT_DASH)) + { + if (add_arg (arg) != 0) + goto fail; + continue; + } + if (! opt) { grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown argument `%s'", arg); @@ -398,13 +423,12 @@ grub_arg_parse (grub_extcmd_t cmd, int argc, char **argv, } } - complete = 1; - *args = argl; *argnum = num; + return 1; fail: - return complete; + return 0; } struct grub_arg_list* diff --git a/include/grub/command.h b/include/grub/command.h index 31b639548..3b7bf0a10 100644 --- a/include/grub/command.h +++ b/include/grub/command.h @@ -30,7 +30,11 @@ typedef enum grub_command_flags /* This is an dynamic command. */ GRUB_COMMAND_FLAG_DYNCMD = 0x20, /* This command accepts block arguments. */ - GRUB_COMMAND_FLAG_BLOCKS = 0x40 + GRUB_COMMAND_FLAG_BLOCKS = 0x40, + /* This command accepts unknown arguments as direct parameters. */ + GRUB_COMMAND_ACCEPT_DASH = 0x80, + /* This command accepts only options preceding direct arguments. */ + GRUB_COMMAND_OPTIONS_AT_START = 0x100, } grub_command_flags_t; struct grub_command; From dd521a4afb805c995108c1aba844c47b8c50e7d0 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 15 Sep 2010 00:13:09 +0200 Subject: [PATCH 183/214] * grub-core/lib/xzembed/xz_dec_stream.c (xz_dec_end): Fix memory leak. --- ChangeLog | 4 ++++ grub-core/lib/xzembed/xz_dec_stream.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/ChangeLog b/ChangeLog index 0ec383b3a..0b043ccd5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2010-09-15 Szymon Janc + + * grub-core/lib/xzembed/xz_dec_stream.c (xz_dec_end): Fix memory leak. + 2010-09-14 Vladimir Serbinenko Fix incorrect echo options handling. diff --git a/grub-core/lib/xzembed/xz_dec_stream.c b/grub-core/lib/xzembed/xz_dec_stream.c index ff26f5119..071ca8deb 100644 --- a/grub-core/lib/xzembed/xz_dec_stream.c +++ b/grub-core/lib/xzembed/xz_dec_stream.c @@ -853,6 +853,10 @@ void xz_dec_end(struct xz_dec *s) { if (s != NULL) { xz_dec_lzma2_end(s->lzma2); + kfree(s->index.hash.crc32_context); + kfree(s->block.hash.crc32_context); + kfree(s->crc32_context); + #ifdef XZ_DEC_BCJ xz_dec_bcj_end(s->bcj); #endif From 014f47b74fa375f313ef3b91a8047ccf8f2f7531 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Wed, 15 Sep 2010 00:39:49 +0200 Subject: [PATCH 184/214] * grub-core/lib/xzembed/xz_dec_stream.c (dec_main): Fix index and block CRC calculations and validity checks. * grub-core/lib/xzembed/xz_dec_stream.c (dec_index): Fix index CRC calculations. --- ChangeLog | 7 +++++++ grub-core/lib/xzembed/xz_dec_stream.c | 17 ++++++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0b043ccd5..0a85dbbcc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2010-09-15 Szymon Janc + + * grub-core/lib/xzembed/xz_dec_stream.c (dec_main): Fix index and block + CRC calculations and validity checks. + * grub-core/lib/xzembed/xz_dec_stream.c (dec_index): Fix index CRC + calculations. + 2010-09-15 Szymon Janc * grub-core/lib/xzembed/xz_dec_stream.c (xz_dec_end): Fix memory leak. diff --git a/grub-core/lib/xzembed/xz_dec_stream.c b/grub-core/lib/xzembed/xz_dec_stream.c index 071ca8deb..273041edb 100644 --- a/grub-core/lib/xzembed/xz_dec_stream.c +++ b/grub-core/lib/xzembed/xz_dec_stream.c @@ -270,7 +270,7 @@ static enum xz_ret dec_block(struct xz_dec *s, struct xz_buf *b) s->block.hash.uncompressed += s->block.uncompressed; GRUB_MD_CRC32->write(s->block.hash.crc32_context, - (const uint8_t *)&s->block.hash, sizeof(s->block.hash)); + (const uint8_t *)&s->block.hash, 2 * sizeof(vli_type)); ++s->block.count; } @@ -329,8 +329,7 @@ static enum xz_ret dec_index(struct xz_dec *s, struct xz_buf *b) s->index.hash.uncompressed += s->vli; GRUB_MD_CRC32->write(s->index.hash.crc32_context, - (const uint8_t *)&s->index.hash, - sizeof(s->index.hash)); + (const uint8_t *)&s->index.hash, 2 * sizeof(vli_type)); --s->index.count; s->index.sequence = SEQ_INDEX_UNPADDED; @@ -671,8 +670,17 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) index_update(s, b); /* Compare the hashes to validate the Index field. */ - if (! memeq(&s->block.hash, &s->index.hash, sizeof(s->block.hash))) + GRUB_MD_CRC32->final(s->block.hash.crc32_context); + GRUB_MD_CRC32->final(s->index.hash.crc32_context); + uint32_t block_crc = *(uint32_t*)GRUB_MD_CRC32->read(s->block.hash.crc32_context); + uint32_t index_crc = *(uint32_t*)GRUB_MD_CRC32->read(s->index.hash.crc32_context); + + if (s->block.hash.unpadded != s->index.hash.unpadded + || s->block.hash.uncompressed != s->index.hash.uncompressed + || block_crc != index_crc) + { return XZ_DATA_ERROR; + } s->sequence = SEQ_INDEX_CRC32; @@ -856,7 +864,6 @@ void xz_dec_end(struct xz_dec *s) kfree(s->index.hash.crc32_context); kfree(s->block.hash.crc32_context); kfree(s->crc32_context); - #ifdef XZ_DEC_BCJ xz_dec_bcj_end(s->bcj); #endif From 44224d3948d9952cb2928571f8aa914ebf6f040a Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 15 Sep 2010 02:16:12 +0200 Subject: [PATCH 185/214] Fix UUID command. Reported by: Jordan Uggla --- grub-core/lib/legacy_parse.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 5b5b4d6e2..7ecd1c74f 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -275,8 +275,8 @@ struct legacy_command legacy_commands[] = "Unhide PARTITION by clearing the \"hidden\" bit in its" " partition type code."}, /* FIXME: uppermem unsupported. */ - {"uuid", "search -u '%s'\n", NULL, 0, 1, {TYPE_VERBATIM}, 0, "UUID", - "Find root by UUID"}, + {"uuid", "search --set=root --fs-uuid '%s'\n", NULL, 0, 1, {TYPE_VERBATIM}, + 0, "UUID", "Find root by UUID"}, /* FIXME: support MODE. */ {"vbeprobe", "vbeinfo\n", NULL, 0, 0, {}, 0, "[MODE]", "Probe VBE information. If the mode number MODE is specified, show only" From 5dcdf93ad6771ef6bf61c73072efe3d0f5878d3e Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 15 Sep 2010 11:31:02 +0200 Subject: [PATCH 186/214] * grub-core/gnulib/error.c: Resynced. * grub-core/gnulib/getopt.c: Likewise. * grub-core/gnulib/getopt_int.h: Likewise. * grub-core/gnulib/regex.h: Likewise. * grub-core/gnulib/regex_internal.c: Likewise. * grub-core/gnulib/regex_internal.h: Likewise. --- ChangeLog | 9 ++++ grub-core/gnulib/error.c | 32 +++++++++++++- grub-core/gnulib/getopt.c | 39 ++++++++++------- grub-core/gnulib/getopt_int.h | 69 ++++++++++++++++--------------- grub-core/gnulib/regex.h | 20 ++++----- grub-core/gnulib/regex_internal.c | 4 +- grub-core/gnulib/regex_internal.h | 2 + 7 files changed, 113 insertions(+), 62 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0a85dbbcc..5dfe4b7bd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2010-09-15 Vladimir Serbinenko + + * grub-core/gnulib/error.c: Resynced. + * grub-core/gnulib/getopt.c: Likewise. + * grub-core/gnulib/getopt_int.h: Likewise. + * grub-core/gnulib/regex.h: Likewise. + * grub-core/gnulib/regex_internal.c: Likewise. + * grub-core/gnulib/regex_internal.h: Likewise. + 2010-09-15 Szymon Janc * grub-core/lib/xzembed/xz_dec_stream.c (dec_main): Fix index and block diff --git a/grub-core/gnulib/error.c b/grub-core/gnulib/error.c index c79e8d42c..ed9dba0d2 100644 --- a/grub-core/gnulib/error.c +++ b/grub-core/gnulib/error.c @@ -88,6 +88,15 @@ extern void __error_at_line (int status, int errnum, const char *file_name, # include # include +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ +/* Get declarations of the Win32 API functions. */ +# define WIN32_LEAN_AND_MEAN +# include +# endif + +/* The gnulib override of fcntl is not needed in this file. */ +# undef fcntl + # if !HAVE_DECL_STRERROR_R && STRERROR_R_CHAR_P # ifndef HAVE_DECL_STRERROR_R "this configure-time declaration test was not run" @@ -104,10 +113,29 @@ extern char *program_name; # endif /* HAVE_STRERROR_R || defined strerror_r */ #endif /* not _LIBC */ +#if !_LIBC +/* Return non-zero if FD is open. */ +static inline int +is_open (int fd) +{ +# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ + /* On Win32: The initial state of unassigned standard file descriptors is + that they are open but point to an INVALID_HANDLE_VALUE. There is no + fcntl, and the gnulib replacement fcntl does not support F_GETFL. */ + return (HANDLE) _get_osfhandle (fd) != INVALID_HANDLE_VALUE; +# else +# ifndef F_GETFL +# error Please port fcntl to your platform +# endif + return 0 <= fcntl (fd, F_GETFL); +# endif +} +#endif + static inline void flush_stdout (void) { -#if !_LIBC && defined F_GETFL +#if !_LIBC int stdout_fd; # if GNULIB_FREOPEN_SAFER @@ -124,7 +152,7 @@ flush_stdout (void) /* POSIX states that fflush (stdout) after fclose is unspecified; it is safe in glibc, but not on all other platforms. fflush (NULL) is always defined, but too draconian. */ - if (0 <= stdout_fd && 0 <= fcntl (stdout_fd, F_GETFL)) + if (0 <= stdout_fd && is_open (stdout_fd)) #endif fflush (stdout); } diff --git a/grub-core/gnulib/getopt.c b/grub-core/gnulib/getopt.c index aaabc8d19..3791f1293 100644 --- a/grub-core/gnulib/getopt.c +++ b/grub-core/gnulib/getopt.c @@ -348,8 +348,6 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, int long_only, struct _getopt_data *d, int posixly_correct) { int print_errors = d->opterr; - if (optstring[0] == ':') - print_errors = 0; if (argc < 1) return -1; @@ -364,6 +362,10 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, posixly_correct); d->__initialized = 1; } + else if (optstring[0] == '-' || optstring[0] == '+') + optstring++; + if (optstring[0] == ':') + print_errors = 0; /* Test whether ARGV[optind] points to a non-option argument. Either it does not have option syntax, or there is an environment flag @@ -633,8 +635,8 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, char *buf; if (__asprintf (&buf, _("\ -%s: option '%s' requires an argument\n"), - argv[0], argv[d->optind - 1]) >= 0) +%s: option '--%s' requires an argument\n"), + argv[0], pfound->name) >= 0) { _IO_flockfile (stderr); @@ -651,8 +653,8 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, } #else fprintf (stderr, - _("%s: option '%s' requires an argument\n"), - argv[0], argv[d->optind - 1]); + _("%s: option '--%s' requires an argument\n"), + argv[0], pfound->name); #endif } d->__nextchar += strlen (d->__nextchar); @@ -736,13 +738,13 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, { char c = *d->__nextchar++; - char *temp = strchr (optstring, c); + const char *temp = strchr (optstring, c); /* Increment `optind' when we start to process its last character. */ if (*d->__nextchar == '\0') ++d->optind; - if (temp == NULL || c == ':') + if (temp == NULL || c == ':' || c == ';') { if (print_errors) { @@ -864,7 +866,10 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, pfound = p; indfound = option_index; } - else + else if (long_only + || pfound->has_arg != p->has_arg + || pfound->flag != p->flag + || pfound->val != p->val) /* Second or later nonexact match found. */ ambig = 1; } @@ -876,7 +881,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, char *buf; if (__asprintf (&buf, _("%s: option '-W %s' is ambiguous\n"), - argv[0], argv[d->optind]) >= 0) + argv[0], d->optarg) >= 0) { _IO_flockfile (stderr); @@ -892,7 +897,7 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, } #else fprintf (stderr, _("%s: option '-W %s' is ambiguous\n"), - argv[0], argv[d->optind]); + argv[0], d->optarg); #endif } d->__nextchar += strlen (d->__nextchar); @@ -955,8 +960,8 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, char *buf; if (__asprintf (&buf, _("\ -%s: option '%s' requires an argument\n"), - argv[0], argv[d->optind - 1]) >= 0) +%s: option '-W %s' requires an argument\n"), + argv[0], pfound->name) >= 0) { _IO_flockfile (stderr); @@ -972,15 +977,17 @@ _getopt_internal_r (int argc, char **argv, const char *optstring, free (buf); } #else - fprintf (stderr, - _("%s: option '%s' requires an argument\n"), - argv[0], argv[d->optind - 1]); + fprintf (stderr, _("\ +%s: option '-W %s' requires an argument\n"), + argv[0], pfound->name); #endif } d->__nextchar += strlen (d->__nextchar); return optstring[0] == ':' ? ':' : '?'; } } + else + d->optarg = NULL; d->__nextchar += strlen (d->__nextchar); if (longind != NULL) *longind = option_index; diff --git a/grub-core/gnulib/getopt_int.h b/grub-core/gnulib/getopt_int.h index 169def5b2..980b7507f 100644 --- a/grub-core/gnulib/getopt_int.h +++ b/grub-core/gnulib/getopt_int.h @@ -30,6 +30,40 @@ extern int _getopt_internal (int ___argc, char **___argv, /* Reentrant versions which can handle parsing multiple argument vectors at the same time. */ +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters, or by calling getopt. + + PERMUTE is the default. We permute the contents of ARGV as we + scan, so that eventually all the non-options are at the end. + This allows options to be given in any order, even with programs + that were not written to expect this. + + RETURN_IN_ORDER is an option available to programs that were + written to expect options and other ARGV-elements in any order + and that care about the ordering of the two. We describe each + non-option ARGV-element as if it were the argument of an option + with character code 1. Using `-' as the first character of the + list of option characters selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return -1 with `optind' != ARGC. */ + +enum __ord + { + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER + }; + /* Data type for reentrant functions. */ struct _getopt_data { @@ -54,39 +88,8 @@ struct _getopt_data by advancing to the next ARGV-element. */ char *__nextchar; - /* Describe how to deal with options that follow non-option ARGV-elements. - - If the caller did not specify anything, - the default is REQUIRE_ORDER if the environment variable - POSIXLY_CORRECT is defined, PERMUTE otherwise. - - REQUIRE_ORDER means don't recognize them as options; - stop option processing when the first non-option is seen. - This is what Unix does. - This mode of operation is selected by either setting the environment - variable POSIXLY_CORRECT, or using `+' as the first character - of the list of option characters, or by calling getopt. - - PERMUTE is the default. We permute the contents of ARGV as we - scan, so that eventually all the non-options are at the end. - This allows options to be given in any order, even with programs - that were not written to expect this. - - RETURN_IN_ORDER is an option available to programs that were - written to expect options and other ARGV-elements in any order - and that care about the ordering of the two. We describe each - non-option ARGV-element as if it were the argument of an option - with character code 1. Using `-' as the first character of the - list of option characters selects this mode of operation. - - The special argument `--' forces an end of option-scanning regardless - of the value of `ordering'. In the case of RETURN_IN_ORDER, only - `--' can cause `getopt' to return -1 with `optind' != ARGC. */ - - enum - { - REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER - } __ordering; + /* See __ord above. */ + enum __ord __ordering; /* If the POSIXLY_CORRECT environment variable is set or getopt was called. */ diff --git a/grub-core/gnulib/regex.h b/grub-core/gnulib/regex.h index 594d5e6aa..89a8143d4 100644 --- a/grub-core/gnulib/regex.h +++ b/grub-core/gnulib/regex.h @@ -114,10 +114,10 @@ typedef unsigned long int reg_syntax_t; /* If this bit is set, then ^ and $ are always anchors (outside bracket expressions, of course). If this bit is not set, then it depends: - ^ is an anchor if it is at the beginning of a regular - expression or after an open-group or an alternation operator; - $ is an anchor if it is at the end of a regular expression, or - before a close-group or an alternation operator. + ^ is an anchor if it is at the beginning of a regular + expression or after an open-group or an alternation operator; + $ is an anchor if it is at the end of a regular expression, or + before a close-group or an alternation operator. This bit could be (re)combined with RE_CONTEXT_INDEP_OPS, because POSIX draft 11.2 says that * etc. in leading positions is undefined. @@ -219,8 +219,8 @@ typedef unsigned long int reg_syntax_t; whether ^ should be special. */ # define RE_CARET_ANCHORS_HERE (RE_ICASE << 1) -/* If this bit is set, then \{ cannot be first in an bre or - immediately after an alternation or begin-group operator. */ +/* If this bit is set, then \{ cannot be first in a regex or + immediately after an alternation, open-group or \} operator. */ # define RE_CONTEXT_INVALID_DUP (RE_CARET_ANCHORS_HERE << 1) /* If this bit is set, then no_sub will be set to 1 during @@ -495,8 +495,8 @@ struct re_pattern_buffer #endif unsigned int _REG_RE_NAME (regs_allocated) : 2; - /* Set to zero when `regex_compile' compiles a pattern; set to one - by `re_compile_fastmap' if it updates the fastmap. */ + /* Set to zero when `re_compile_pattern' compiles a pattern; set to + one by `re_compile_fastmap' if it updates the fastmap. */ unsigned int _REG_RE_NAME (fastmap_accurate) : 1; /* If set, `re_match_2' does not return information about @@ -610,8 +610,8 @@ extern regoff_t re_match_2 (struct re_pattern_buffer *__buffer, register data. Unless this function is called, the first search or match using - PATTERN_BUFFER will allocate its own register data, without - freeing the old data. */ + BUFFER will allocate its own register data, without freeing the old + data. */ extern void re_set_registers (struct re_pattern_buffer *__buffer, struct re_registers *__regs, __re_size_t __num_regs, diff --git a/grub-core/gnulib/regex_internal.c b/grub-core/gnulib/regex_internal.c index 378b767d8..787a3a627 100644 --- a/grub-core/gnulib/regex_internal.c +++ b/grub-core/gnulib/regex_internal.c @@ -733,15 +733,17 @@ re_string_reconstruct (re_string_t *pstr, Idx idx, int eflags) mbstate_t cur_state; wchar_t wc2; Idx mlen = raw + pstr->len - p; - unsigned char buf[6]; size_t mbclen; +#if 0 /* dead code: buf is set but never used */ + unsigned char buf[6]; if (BE (pstr->trans != NULL, 0)) { int i = mlen < 6 ? mlen : 6; while (--i >= 0) buf[i] = pstr->trans[p[i]]; } +#endif /* XXX Don't use mbrtowc, we know which conversion to use (UTF-8 -> UCS4). */ memset (&cur_state, 0, sizeof (cur_state)); diff --git a/grub-core/gnulib/regex_internal.h b/grub-core/gnulib/regex_internal.h index e1b4c61b3..dc94e2cbc 100644 --- a/grub-core/gnulib/regex_internal.h +++ b/grub-core/gnulib/regex_internal.h @@ -467,6 +467,8 @@ static unsigned int re_string_context_at (const re_string_t *input, Idx idx, # else /* alloca is implemented with malloc, so just use malloc. */ # define __libc_use_alloca(n) 0 +# undef alloca +# define alloca(n) malloc (n) # endif #endif From 2e04a0068595e6623e175164e762875003f17a9b Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 15 Sep 2010 11:34:29 +0200 Subject: [PATCH 187/214] * grub-core/gnulib/basename-lgpl.c: Imported. * grub-core/gnulib/basename.c: Likewise. * grub-core/gnulib/dirname-lgpl.c: Likewise. * grub-core/gnulib/dirname.c: Likewise. * grub-core/gnulib/dirname.h: Likewise. * grub-core/gnulib/stripslash.c: Likewise. --- ChangeLog | 9 ++++ grub-core/gnulib/basename-lgpl.c | 75 ++++++++++++++++++++++++++++ grub-core/gnulib/basename.c | 58 +++++++++++++++++++++ grub-core/gnulib/dirname-lgpl.c | 86 ++++++++++++++++++++++++++++++++ grub-core/gnulib/dirname.c | 38 ++++++++++++++ grub-core/gnulib/dirname.h | 74 +++++++++++++++++++++++++++ grub-core/gnulib/stripslash.c | 45 +++++++++++++++++ 7 files changed, 385 insertions(+) create mode 100644 grub-core/gnulib/basename-lgpl.c create mode 100644 grub-core/gnulib/basename.c create mode 100644 grub-core/gnulib/dirname-lgpl.c create mode 100644 grub-core/gnulib/dirname.c create mode 100644 grub-core/gnulib/dirname.h create mode 100644 grub-core/gnulib/stripslash.c diff --git a/ChangeLog b/ChangeLog index 5dfe4b7bd..c525fe369 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2010-09-15 Vladimir Serbinenko + + * grub-core/gnulib/basename-lgpl.c: Imported. + * grub-core/gnulib/basename.c: Likewise. + * grub-core/gnulib/dirname-lgpl.c: Likewise. + * grub-core/gnulib/dirname.c: Likewise. + * grub-core/gnulib/dirname.h: Likewise. + * grub-core/gnulib/stripslash.c: Likewise. + 2010-09-15 Vladimir Serbinenko * grub-core/gnulib/error.c: Resynced. diff --git a/grub-core/gnulib/basename-lgpl.c b/grub-core/gnulib/basename-lgpl.c new file mode 100644 index 000000000..a35ff01c2 --- /dev/null +++ b/grub-core/gnulib/basename-lgpl.c @@ -0,0 +1,75 @@ +/* basename.c -- return the last element in a file name + + Copyright (C) 1990, 1998-2001, 2003-2006, 2009-2010 Free Software + Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 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, see . */ + +#include + +#include "dirname.h" + +#include + +/* Return the address of the last file name component of NAME. If + NAME has no relative file name components because it is a file + system root, return the empty string. */ + +char * +last_component (char const *name) +{ + char const *base = name + FILE_SYSTEM_PREFIX_LEN (name); + char const *p; + bool saw_slash = false; + + while (ISSLASH (*base)) + base++; + + for (p = base; *p; p++) + { + if (ISSLASH (*p)) + saw_slash = true; + else if (saw_slash) + { + base = p; + saw_slash = false; + } + } + + return (char *) base; +} + +/* Return the length of the basename NAME. Typically NAME is the + value returned by base_name or last_component. Act like strlen + (NAME), except omit all trailing slashes. */ + +size_t +base_len (char const *name) +{ + size_t len; + size_t prefix_len = FILE_SYSTEM_PREFIX_LEN (name); + + for (len = strlen (name); 1 < len && ISSLASH (name[len - 1]); len--) + continue; + + if (DOUBLE_SLASH_IS_DISTINCT_ROOT && len == 1 + && ISSLASH (name[0]) && ISSLASH (name[1]) && ! name[2]) + return 2; + + if (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE && prefix_len + && len == prefix_len && ISSLASH (name[prefix_len])) + return prefix_len + 1; + + return len; +} diff --git a/grub-core/gnulib/basename.c b/grub-core/gnulib/basename.c new file mode 100644 index 000000000..24da93ac4 --- /dev/null +++ b/grub-core/gnulib/basename.c @@ -0,0 +1,58 @@ +/* basename.c -- return the last element in a file name + + Copyright (C) 1990, 1998-2001, 2003-2006, 2009-2010 Free Software + Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 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, see . */ + +#include + +#include "dirname.h" + +#include +#include "xalloc.h" +#include "xstrndup.h" + +char * +base_name (char const *name) +{ + char const *base = last_component (name); + size_t length; + + /* If there is no last component, then name is a file system root or the + empty string. */ + if (! *base) + return xstrndup (name, base_len (name)); + + /* Collapse a sequence of trailing slashes into one. */ + length = base_len (base); + if (ISSLASH (base[length])) + length++; + + /* On systems with drive letters, `a/b:c' must return `./b:c' rather + than `b:c' to avoid confusion with a drive letter. On systems + with pure POSIX semantics, this is not an issue. */ + if (FILE_SYSTEM_PREFIX_LEN (base)) + { + char *p = xmalloc (length + 3); + p[0] = '.'; + p[1] = '/'; + memcpy (p + 2, base, length); + p[length + 2] = '\0'; + return p; + } + + /* Finally, copy the basename. */ + return xstrndup (base, length); +} diff --git a/grub-core/gnulib/dirname-lgpl.c b/grub-core/gnulib/dirname-lgpl.c new file mode 100644 index 000000000..d4506e060 --- /dev/null +++ b/grub-core/gnulib/dirname-lgpl.c @@ -0,0 +1,86 @@ +/* dirname.c -- return all but the last element in a file name + + Copyright (C) 1990, 1998, 2000-2001, 2003-2006, 2009-2010 Free Software + Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 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, see . */ + +#include + +#include "dirname.h" + +#include +#include + +/* Return the length of the prefix of FILE that will be used by + dir_name. If FILE is in the working directory, this returns zero + even though `dir_name (FILE)' will return ".". Works properly even + if there are trailing slashes (by effectively ignoring them). */ + +size_t +dir_len (char const *file) +{ + size_t prefix_length = FILE_SYSTEM_PREFIX_LEN (file); + size_t length; + + /* Advance prefix_length beyond important leading slashes. */ + prefix_length += (prefix_length != 0 + ? (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE + && ISSLASH (file[prefix_length])) + : (ISSLASH (file[0]) + ? ((DOUBLE_SLASH_IS_DISTINCT_ROOT + && ISSLASH (file[1]) && ! ISSLASH (file[2]) + ? 2 : 1)) + : 0)); + + /* Strip the basename and any redundant slashes before it. */ + for (length = last_component (file) - file; + prefix_length < length; length--) + if (! ISSLASH (file[length - 1])) + break; + return length; +} + + +/* In general, we can't use the builtin `dirname' function if available, + since it has different meanings in different environments. + In some environments the builtin `dirname' modifies its argument. + + Return the leading directories part of FILE, allocated with malloc. + Works properly even if there are trailing slashes (by effectively + ignoring them). Return NULL on failure. + + If lstat (FILE) would succeed, then { chdir (dir_name (FILE)); + lstat (base_name (FILE)); } will access the same file. Likewise, + if the sequence { chdir (dir_name (FILE)); + rename (base_name (FILE), "foo"); } succeeds, you have renamed FILE + to "foo" in the same directory FILE was in. */ + +char * +mdir_name (char const *file) +{ + size_t length = dir_len (file); + bool append_dot = (length == 0 + || (FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE + && length == FILE_SYSTEM_PREFIX_LEN (file) + && file[2] != '\0' && ! ISSLASH (file[2]))); + char *dir = malloc (length + append_dot + 1); + if (!dir) + return NULL; + memcpy (dir, file, length); + if (append_dot) + dir[length++] = '.'; + dir[length] = '\0'; + return dir; +} diff --git a/grub-core/gnulib/dirname.c b/grub-core/gnulib/dirname.c new file mode 100644 index 000000000..953a9acc3 --- /dev/null +++ b/grub-core/gnulib/dirname.c @@ -0,0 +1,38 @@ +/* dirname.c -- return all but the last element in a file name + + Copyright (C) 1990, 1998, 2000-2001, 2003-2006, 2009-2010 Free Software + Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 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, see . */ + +#include + +#include "dirname.h" + +#include +#include +#include "xalloc.h" + +/* Just like mdir_name (dirname-lgpl.c), except, rather than + returning NULL upon malloc failure, here, we report the + "memory exhausted" condition and exit. */ + +char * +dir_name (char const *file) +{ + char *result = mdir_name (file); + if (!result) + xalloc_die (); + return result; +} diff --git a/grub-core/gnulib/dirname.h b/grub-core/gnulib/dirname.h new file mode 100644 index 000000000..fb19508f7 --- /dev/null +++ b/grub-core/gnulib/dirname.h @@ -0,0 +1,74 @@ +/* Take file names apart into directory and base names. + + Copyright (C) 1998, 2001, 2003-2006, 2009-2010 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 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, see . */ + +#ifndef DIRNAME_H_ +# define DIRNAME_H_ 1 + +# include +# include + +# ifndef DIRECTORY_SEPARATOR +# define DIRECTORY_SEPARATOR '/' +# endif + +# ifndef ISSLASH +# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR) +# endif + +# ifndef FILE_SYSTEM_PREFIX_LEN +# if FILE_SYSTEM_ACCEPTS_DRIVE_LETTER_PREFIX + /* This internal macro assumes ASCII, but all hosts that support drive + letters use ASCII. */ +# define _IS_DRIVE_LETTER(c) (((unsigned int) (c) | ('a' - 'A')) - 'a' \ + <= 'z' - 'a') +# define FILE_SYSTEM_PREFIX_LEN(Filename) \ + (_IS_DRIVE_LETTER ((Filename)[0]) && (Filename)[1] == ':' ? 2 : 0) +# else +# define FILE_SYSTEM_PREFIX_LEN(Filename) 0 +# endif +# endif + +# ifndef FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE +# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0 +# endif + +# ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT +# define DOUBLE_SLASH_IS_DISTINCT_ROOT 0 +# endif + +# if FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE +# define IS_ABSOLUTE_FILE_NAME(F) ISSLASH ((F)[FILE_SYSTEM_PREFIX_LEN (F)]) +# else +# define IS_ABSOLUTE_FILE_NAME(F) \ + (ISSLASH ((F)[0]) || 0 < FILE_SYSTEM_PREFIX_LEN (F)) +# endif +# define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F)) + +# if GNULIB_DIRNAME +char *base_name (char const *file); +char *dir_name (char const *file); +# endif + +char *mdir_name (char const *file); +size_t base_len (char const *file); +size_t dir_len (char const *file); +char *last_component (char const *file); + +bool strip_trailing_slashes (char *file); + +#endif /* not DIRNAME_H_ */ diff --git a/grub-core/gnulib/stripslash.c b/grub-core/gnulib/stripslash.c new file mode 100644 index 000000000..3a5996fd9 --- /dev/null +++ b/grub-core/gnulib/stripslash.c @@ -0,0 +1,45 @@ +/* stripslash.c -- remove redundant trailing slashes from a file name + + Copyright (C) 1990, 2001, 2003-2006, 2009-2010 Free Software Foundation, + Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 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, see . */ + +#include + +#include "dirname.h" + +/* Remove trailing slashes from FILE. Return true if a trailing slash + was removed. This is useful when using file name completion from a + shell that adds a "/" after directory names (such as tcsh and + bash), because on symlinks to directories, several system calls + have different semantics according to whether a trailing slash is + present. */ + +bool +strip_trailing_slashes (char *file) +{ + char *base = last_component (file); + char *base_lim; + bool had_slash; + + /* last_component returns "" for file system roots, but we need to turn + `///' into `/'. */ + if (! *base) + base = file; + base_lim = base + base_len (base); + had_slash = (*base_lim != '\0'); + *base_lim = '\0'; + return had_slash; +} From e31bb619117766a74a7d5c7f6b87bdcaea7c55c5 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 15 Sep 2010 11:39:53 +0200 Subject: [PATCH 188/214] Transform legacy mode numbers into resolution specification --- Makefile.util.def | 2 + grub-core/Makefile.core.def | 1 + grub-core/lib/i386/pc/vesa_modes_table.c | 127 +++++++++++++++ grub-core/lib/legacy_parse.c | 42 ++++- grub-core/loader/i386/linux.c | 190 ++--------------------- 5 files changed, 179 insertions(+), 183 deletions(-) create mode 100644 grub-core/lib/i386/pc/vesa_modes_table.c diff --git a/Makefile.util.def b/Makefile.util.def index febbfd0ed..54ec6ee8a 100644 --- a/Makefile.util.def +++ b/Makefile.util.def @@ -563,6 +563,8 @@ program = { mansection = 1; common = util/grub-menulst2cfg.c; common = grub-core/lib/legacy_parse.c; + common = grub-core/lib/i386/pc/vesa_modes_table.c; + ldadd = libgrub.a; ldflags = '$(LIBDEVMAPPER)'; }; diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 36a6e6564..03505ad5a 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1111,6 +1111,7 @@ module = { module = { name = linux; x86 = loader/i386/linux.c; + i386_pc = lib/i386/pc/vesa_modes_table.c; mips = loader/mips/linux.c; powerpc_ieee1275 = loader/powerpc/ieee1275/linux.c; sparc64_ieee1275 = loader/sparc64/ieee1275/linux.c; diff --git a/grub-core/lib/i386/pc/vesa_modes_table.c b/grub-core/lib/i386/pc/vesa_modes_table.c new file mode 100644 index 000000000..6dc4b7d8d --- /dev/null +++ b/grub-core/lib/i386/pc/vesa_modes_table.c @@ -0,0 +1,127 @@ + +#include + +/* This is the reverse of the table in [linux]/Documentation/fb/vesafb.txt + plus a few more modes based on the table in + http://en.wikipedia.org/wiki/VESA_BIOS_Extensions */ +struct grub_vesa_mode_table_entry +grub_vesa_mode_table[GRUB_VESA_MODE_TABLE_END + - GRUB_VESA_MODE_TABLE_START + 1] = + { + { 640, 400, 8 }, /* 0x300 */ + { 640, 480, 8 }, /* 0x301 */ + { 800, 600, 4 }, /* 0x302 */ + { 800, 600, 8 }, /* 0x303 */ + { 1024, 768, 4 }, /* 0x304 */ + { 1024, 768, 8 }, /* 0x305 */ + { 1280, 1024, 4 }, /* 0x306 */ + { 1280, 1024, 8 }, /* 0x307 */ + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 320, 200, 15 }, /* 0x30d */ + { 320, 200, 16 }, /* 0x30e */ + { 320, 200, 24 }, /* 0x30f */ + { 640, 480, 15 }, /* 0x310 */ + { 640, 480, 16 }, /* 0x311 */ + { 640, 480, 24 }, /* 0x312 */ + { 800, 600, 15 }, /* 0x313 */ + { 800, 600, 16 }, /* 0x314 */ + { 800, 600, 24 }, /* 0x315 */ + { 1024, 768, 15 }, /* 0x316 */ + { 1024, 768, 16 }, /* 0x317 */ + { 1024, 768, 24 }, /* 0x318 */ + { 1280, 1024, 15 }, /* 0x319 */ + { 1280, 1024, 16 }, /* 0x31a */ + { 1280, 1024, 24 }, /* 0x31b */ + { 1600, 1200, 8 }, /* 0x31c */ + { 1600, 1200, 15 }, /* 0x31d */ + { 1600, 1200, 16 }, /* 0x31e */ + { 1600, 1200, 24 }, /* 0x31f */ + { 0, 0, 0 }, + { 640, 400, 15 }, /* 0x321 */ + { 640, 400, 16 }, /* 0x322 */ + { 640, 400, 24 }, /* 0x323 */ + { 640, 400, 32 }, /* 0x324 */ + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 640, 480, 32 }, /* 0x329 */ + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 896, 672, 8 }, /* 0x32f */ + { 896, 672, 15 }, /* 0x330 */ + { 896, 672, 16 }, /* 0x331 */ + { 896, 672, 24 }, /* 0x332 */ + { 896, 672, 32 }, /* 0x333 */ + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 1600, 1200, 32 }, /* 0x342 */ + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 0, 0, 0 }, + { 1440, 900, 8 }, /* 0x360 */ + { 1440, 900, 15 }, /* 0x361 */ + { 1440, 900, 16 }, /* 0x362 */ + { 1440, 900, 24 }, /* 0x363 */ + { 1440, 900, 32 }, /* 0x364 */ + { 1152, 720, 8 }, /* 0x365 */ + { 1152, 720, 15 }, /* 0x366 */ + { 1152, 720, 16 }, /* 0x367 */ + { 1152, 720, 24 }, /* 0x368 */ + { 1152, 720, 32 }, /* 0x369 */ + { 1024, 640, 8 }, /* 0x36a */ + { 1024, 640, 15 }, /* 0x36b */ + { 1024, 640, 16 }, /* 0x36c */ + { 1024, 640, 24 }, /* 0x36d */ + { 1024, 640, 32 }, /* 0x36e */ + { 800, 500, 8 }, /* 0x36f */ + { 800, 500, 15 }, /* 0x370 */ + { 800, 500, 16 }, /* 0x371 */ + { 800, 500, 24 }, /* 0x372 */ + { 800, 500, 32 }, /* 0x373 */ + }; diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 7ecd1c74f..959d8367d 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -21,6 +21,7 @@ #include #include #include +#include struct legacy_command { @@ -40,7 +41,8 @@ struct legacy_command TYPE_PARTITION, TYPE_BOOL, TYPE_INT, - TYPE_REST_VERBATIM + TYPE_REST_VERBATIM, + TYPE_VBE_MODE } argt[4]; enum { FLAG_IGNORE_REST = 1, @@ -264,7 +266,8 @@ struct legacy_command legacy_commands[] = " compares them, to test the filesystem code. " " If this test succeeds, then a good next" " step is to try loading a kernel."}, - /* FIXME: testvbe unsupported. */ + {"testvbe", "insmod vbe; videotest '%s'\n", NULL, 0, 1, {TYPE_VBE_MODE}, 0, + "MODE", "Test the VBE mode MODE. Hit any key to return."}, /* FIXME: tftpserver unsupported. */ {"timeout", "set timeout=%s\n", NULL, 0, 1, {TYPE_INT}, 0, "SEC", "Set a timeout, in SEC seconds, before automatically booting the" @@ -278,7 +281,7 @@ struct legacy_command legacy_commands[] = {"uuid", "search --set=root --fs-uuid '%s'\n", NULL, 0, 1, {TYPE_VERBATIM}, 0, "UUID", "Find root by UUID"}, /* FIXME: support MODE. */ - {"vbeprobe", "vbeinfo\n", NULL, 0, 0, {}, 0, "[MODE]", + {"vbeprobe", "insmod vbe; videoinfo\n", NULL, 0, 0, {}, 0, "[MODE]", "Probe VBE information. If the mode number MODE is specified, show only" " the information about only the mode."} }; @@ -566,6 +569,34 @@ grub_legacy_parse (const char *buf, char **entryname, char **suffix) args[i] = grub_strndup (curarg, brk - curarg); } break; + case TYPE_VBE_MODE: + { + unsigned mod; + struct grub_vesa_mode_table_entry *modedesc; + + mod = grub_strtoul (curarg, 0, 0); + if (grub_errno) + { + mod = 0; + grub_errno = GRUB_ERR_NONE; + } + if (mod < GRUB_VESA_MODE_TABLE_START + || mod > GRUB_VESA_MODE_TABLE_END) + { + args[i] = grub_strdup ("auto"); + break; + } + modedesc = &grub_vesa_mode_table[mod - GRUB_VESA_MODE_TABLE_START]; + if (!modedesc->width) + { + args[i] = grub_strdup ("auto"); + break; + } + args[i] = grub_xasprintf ("%ux%ux%u", + modedesc->width, modedesc->height, + modedesc->depth); + break; + } case TYPE_BOOL: if (curarglen == 2 && curarg[0] == 'o' && curarg[1] == 'n') args[i] = grub_strdup ("1"); @@ -599,7 +630,10 @@ grub_legacy_parse (const char *buf, char **entryname, char **suffix) case TYPE_BOOL: case TYPE_INT: args[i] = grub_strdup ("0"); - break; + break; + case TYPE_VBE_MODE: + args[i] = grub_strdup ("auto"); + break; } if (legacy_commands[cmdnum].flags & FLAG_COLOR_INVERT) diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c index cc2d20af3..9d5b7b727 100644 --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -35,6 +35,10 @@ #include #include +#ifdef GRUB_MACHINE_PCBIOS +#include +#endif + #ifdef GRUB_MACHINE_EFI #include #define HAS_VGA_TEXT 0 @@ -89,175 +93,6 @@ static struct idt_descriptor idt_desc = }; #endif -#ifdef GRUB_MACHINE_PCBIOS -struct linux_vesafb_res -{ - grub_uint16_t width; - grub_uint16_t height; -}; - -struct linux_vesafb_mode -{ - grub_uint8_t res_index; - grub_uint8_t depth; -}; - -enum vga_modes - { - VGA_320_200, - VGA_640_400, - VGA_640_480, - VGA_800_500, - VGA_800_600, - VGA_896_672, - VGA_1024_640, - VGA_1024_768, - VGA_1152_720, - VGA_1280_1024, - VGA_1440_900, - VGA_1600_1200, - }; - -static struct linux_vesafb_res linux_vesafb_res[] = - { - { 320, 200 }, - { 640, 400 }, - { 640, 480 }, - { 800, 500 }, - { 800, 600 }, - { 896, 672 }, - { 1024, 640 }, - { 1024, 768 }, - { 1152, 720 }, - { 1280, 1024 }, - { 1440, 900 }, - { 1600, 1200 }, - }; - -/* This is the reverse of the table in [linux]/Documentation/fb/vesafb.txt - plus a few more modes based on the table in - http://en.wikipedia.org/wiki/VESA_BIOS_Extensions */ -struct linux_vesafb_mode linux_vesafb_modes[] = - { - { VGA_640_400, 8 }, /* 0x300 */ - { VGA_640_480, 8 }, /* 0x301 */ - { VGA_800_600, 4 }, /* 0x302 */ - { VGA_800_600, 8 }, /* 0x303 */ - { VGA_1024_768, 4 }, /* 0x304 */ - { VGA_1024_768, 8 }, /* 0x305 */ - { VGA_1280_1024, 4 }, /* 0x306 */ - { VGA_1280_1024, 8 }, /* 0x307 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { VGA_320_200, 15 }, /* 0x30d */ - { VGA_320_200, 16 }, /* 0x30e */ - { VGA_320_200, 24 }, /* 0x30f */ - { VGA_640_480, 15 }, /* 0x310 */ - { VGA_640_480, 16 }, /* 0x311 */ - { VGA_640_480, 24 }, /* 0x312 */ - { VGA_800_600, 15 }, /* 0x313 */ - { VGA_800_600, 16 }, /* 0x314 */ - { VGA_800_600, 24 }, /* 0x315 */ - { VGA_1024_768, 15 }, /* 0x316 */ - { VGA_1024_768, 16 }, /* 0x317 */ - { VGA_1024_768, 24 }, /* 0x318 */ - { VGA_1280_1024, 15 }, /* 0x319 */ - { VGA_1280_1024, 16 }, /* 0x31a */ - { VGA_1280_1024, 24 }, /* 0x31b */ - { VGA_1600_1200, 8 }, /* 0x31c */ - { VGA_1600_1200, 15 }, /* 0x31d */ - { VGA_1600_1200, 16 }, /* 0x31e */ - { VGA_1600_1200, 24 }, /* 0x31f */ - { 0, 0 }, - { VGA_640_400, 15 }, /* 0x321 */ - { VGA_640_400, 16 }, /* 0x322 */ - { VGA_640_400, 24 }, /* 0x323 */ - { VGA_640_400, 32 }, /* 0x324 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { VGA_640_480, 32 }, /* 0x329 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { VGA_896_672, 8 }, /* 0x32f */ - { VGA_896_672, 15 }, /* 0x330 */ - { VGA_896_672, 16 }, /* 0x331 */ - { VGA_896_672, 24 }, /* 0x332 */ - { VGA_896_672, 32 }, /* 0x333 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { VGA_1600_1200, 32 }, /* 0x342 */ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { VGA_1440_900, 8 }, /* 0x360 */ - { VGA_1440_900, 15 }, /* 0x361 */ - { VGA_1440_900, 16 }, /* 0x362 */ - { VGA_1440_900, 24 }, /* 0x363 */ - { VGA_1440_900, 32 }, /* 0x364 */ - { VGA_1152_720, 8 }, /* 0x365 */ - { VGA_1152_720, 15 }, /* 0x366 */ - { VGA_1152_720, 16 }, /* 0x367 */ - { VGA_1152_720, 24 }, /* 0x368 */ - { VGA_1152_720, 32 }, /* 0x369 */ - { VGA_1024_640, 8 }, /* 0x36a */ - { VGA_1024_640, 15 }, /* 0x36b */ - { VGA_1024_640, 16 }, /* 0x36c */ - { VGA_1024_640, 24 }, /* 0x36d */ - { VGA_1024_640, 32 }, /* 0x36e */ - { VGA_800_500, 8 }, /* 0x36f */ - { VGA_800_500, 15 }, /* 0x370 */ - { VGA_800_500, 16 }, /* 0x371 */ - { VGA_800_500, 24 }, /* 0x372 */ - { VGA_800_500, 32 }, /* 0x373 */ - }; -#endif - static inline grub_size_t page_align (grub_size_t size) { @@ -882,7 +717,7 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), /* Video mode selection support. */ char *val = argv[i] + 4; unsigned vid_mode = GRUB_LINUX_VID_MODE_NORMAL; - struct linux_vesafb_mode *linux_mode; + struct grub_vesa_mode_table_entry *linux_mode; grub_err_t err; char *buf; @@ -925,9 +760,8 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), break; default: /* Ignore invalid values. */ - if (vid_mode < GRUB_LINUX_VID_MODE_VESA_START || - vid_mode >= GRUB_LINUX_VID_MODE_VESA_START + - ARRAY_SIZE (linux_vesafb_modes)) + if (vid_mode < GRUB_VESA_MODE_TABLE_START || + vid_mode > GRUB_VESA_MODE_TABLE_END) { grub_env_set ("gfxpayload", "text"); grub_printf ("%s is deprecated. Mode %d isn't recognized. " @@ -941,15 +775,13 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), is built-in because `vga=' parameter was used. */ params->have_vga = GRUB_VIDEO_LINUX_TYPE_VESA; - linux_mode - = &linux_vesafb_modes[vid_mode - GRUB_LINUX_VID_MODE_VESA_START]; + linux_mode = &grub_vesa_mode_table[vid_mode + - GRUB_VESA_MODE_TABLE_START]; buf = grub_xasprintf ("%ux%ux%u,%ux%u", - linux_vesafb_res[linux_mode->res_index].width, - linux_vesafb_res[linux_mode->res_index].height, + linux_mode->width, linux_mode->height, linux_mode->depth, - linux_vesafb_res[linux_mode->res_index].width, - linux_vesafb_res[linux_mode->res_index].height); + linux_mode->width, linux_mode->height); if (! buf) goto fail; From 890c9fa5f2fd0177d1222c2871ca40510904e800 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 15 Sep 2010 11:42:18 +0200 Subject: [PATCH 189/214] Implement APM --- grub-core/Makefile.core.def | 6 ++ grub-core/commands/i386/pc/lsapm.c | 113 ++++++++++++++++++++++++ grub-core/lib/legacy_parse.c | 3 +- grub-core/loader/i386/multiboot_mbi.c | 27 +++++- grub-core/loader/multiboot.c | 2 - grub-core/loader/multiboot_mbi2.c | 29 +++++- include/grub/i386/pc/apm.h | 48 ++++++++++ include/grub/i386/pc/int.h | 1 + include/grub/i386/pc/vesa_modes_table.h | 19 ++++ include/multiboot.h | 14 +++ 10 files changed, 257 insertions(+), 5 deletions(-) create mode 100644 grub-core/commands/i386/pc/lsapm.c create mode 100644 include/grub/i386/pc/apm.h create mode 100644 include/grub/i386/pc/vesa_modes_table.h diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 03505ad5a..584b9754d 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -1433,3 +1433,9 @@ module = { name = testload; common = commands/testload.c; }; + +module = { + name = lsapm; + common = commands/i386/pc/lsapm.c; + enable = i386_pc; +}; diff --git a/grub-core/commands/i386/pc/lsapm.c b/grub-core/commands/i386/pc/lsapm.c new file mode 100644 index 000000000..30475d2ec --- /dev/null +++ b/grub-core/commands/i386/pc/lsapm.c @@ -0,0 +1,113 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#include +#include +#include +#include +#include + +int +grub_apm_get_info (struct grub_apm_info *info) +{ + struct grub_bios_int_registers regs; + + /* detect APM */ + regs.eax = 0x5300; + regs.ebx = 0; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x15, ®s); + + if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY) + return 0; + info->version = regs.eax & 0xffff; + info->flags = regs.ecx & 0xffff; + + /* disconnect APM first */ + regs.eax = 0x5304; + regs.ebx = 0; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x15, ®s); + + /* connect APM */ + regs.eax = 0x5303; + regs.ebx = 0; + regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT; + grub_bios_interrupt (0x15, ®s); + + if (regs.flags & GRUB_CPU_INT_FLAGS_CARRY) + return 0; + + info->cseg = regs.eax & 0xffff; + info->offset = regs.ebx; + info->cseg_16 = regs.ecx & 0xffff; + info->dseg = regs.edx & 0xffff; + info->cseg_len = regs.esi >> 16; + info->cseg_16_len = regs.esi & 0xffff; + info->dseg_len = regs.edi; + + return 1; +} + +static grub_err_t +grub_cmd_lsapm (grub_command_t cmd __attribute__ ((unused)), + int argc __attribute__ ((unused)), char **args __attribute__ ((unused))) +{ + struct grub_apm_info info; + if (!grub_apm_get_info (&info)) + return grub_error (GRUB_ERR_IO, "no APM found"); + + grub_printf ("Vesion %u.%u\n" + "32-bit CS = 0x%x, len = 0x%x, offset = 0x%x\n" + "16-bit CS = 0x%x, len = 0x%x\n" + "DS = 0x%x, len = 0x%x\n", + info.version >> 8, info.version & 0xff, + info.cseg, info.cseg_len, info.offset, + info.cseg_16, info.cseg_16_len, + info.dseg, info.dseg_len); + grub_xputs (info.flags & GRUB_APM_FLAGS_16BITPROTECTED_SUPPORTED + ? "16-bit protected interface supported\n" + : "16-bit protected interface unsupported\n"); + grub_xputs (info.flags & GRUB_APM_FLAGS_32BITPROTECTED_SUPPORTED + ? "32-bit protected interface supported\n" + : "32-bit protected interface unsupported\n"); + grub_xputs (info.flags & GRUB_APM_FLAGS_CPUIDLE_SLOWS_DOWN + ? "CPU Idle slows down processor\n" + : "CPU Idle doesn't slow down processor\n"); + grub_xputs (info.flags & GRUB_APM_FLAGS_DISABLED + ? "APM disabled\n" : "APM enabled\n"); + grub_xputs (info.flags & GRUB_APM_FLAGS_DISENGAGED + ? "APM disengaged\n" : "APM engaged\n"); + + return GRUB_ERR_NONE; +} + +static grub_command_t cmd; + +GRUB_MOD_INIT(lsapm) +{ + cmd = grub_register_command ("lsapm", grub_cmd_lsapm, 0, + N_("Show APM information.")); +} + +GRUB_MOD_FINI(lsapm) +{ + grub_unregister_command (cmd); +} + + diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 959d8367d..024d425e8 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -99,7 +99,8 @@ struct legacy_command legacy_commands[] = "Set the default entry to entry number NUM (if not specified, it is" " 0, the first entry) or the entry number saved by savedefault."}, /* FIXME: dhcp unsupported. */ - /* FIXME: displayapm unsupported. */ + {"displayapm", "lsapm\n", NULL, 0, 0, {}, 0, 0, + "Display APM BIOS information."}, {"displaymem", "lsmmap\n", NULL, 0, 0, {}, 0, 0, "Display what GRUB thinks the system address space map of the" " machine is, including all regions of physical RAM installed."}, diff --git a/grub-core/loader/i386/multiboot_mbi.c b/grub-core/loader/i386/multiboot_mbi.c index bf17863cf..2cce39746 100644 --- a/grub-core/loader/i386/multiboot_mbi.c +++ b/grub-core/loader/i386/multiboot_mbi.c @@ -20,6 +20,7 @@ #include #ifdef GRUB_MACHINE_PCBIOS #include +#include #endif #include #include @@ -194,7 +195,8 @@ grub_multiboot_get_mbi_size (void) + ALIGN_UP (sizeof(PACKAGE_STRING), 4) + grub_get_multiboot_mmap_count () * sizeof (struct multiboot_mmap_entry) + elf_sec_entsize * elf_sec_num - + 256 * sizeof (struct multiboot_color); + + 256 * sizeof (struct multiboot_color) + + ALIGN_UP (sizeof (struct multiboot_apm_info), 4); } /* Fill previously allocated Multiboot mmap. */ @@ -356,6 +358,29 @@ grub_multiboot_make_mbi (grub_uint32_t *target) ptrorig += ALIGN_UP (sizeof(PACKAGE_STRING), 4); ptrdest += ALIGN_UP (sizeof(PACKAGE_STRING), 4); +#ifdef GRUB_MACHINE_PCBIOS + { + struct grub_apm_info info; + if (grub_apm_get_info (&info)) + { + struct multiboot_apm_info *mbinfo = (void *) ptrorig; + + mbinfo->cseg = info.cseg; + mbinfo->offset = info.offset; + mbinfo->cseg_16 = info.cseg_16; + mbinfo->dseg = info.dseg; + mbinfo->flags = info.flags; + mbinfo->cseg_len = info.cseg_len; + mbinfo->dseg_len = info.dseg_len; + mbinfo->cseg_16_len = info.cseg_16_len; + mbinfo->version = info.version; + + ptrorig += ALIGN_UP (sizeof (struct multiboot_apm_info), 4); + ptrdest += ALIGN_UP (sizeof (struct multiboot_apm_info), 4); + } + } +#endif + if (modcnt) { mbi->flags |= MULTIBOOT_INFO_MODS; diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c index 8780ec061..d5cb42604 100644 --- a/grub-core/loader/multiboot.c +++ b/grub-core/loader/multiboot.c @@ -21,10 +21,8 @@ * FIXME: The following features from the Multiboot specification still * need to be implemented: * - VBE support - * - symbol table * - drives table * - ROM configuration table - * - APM table */ #include diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c index f453dcc6a..2e6801252 100644 --- a/grub-core/loader/multiboot_mbi2.c +++ b/grub-core/loader/multiboot_mbi2.c @@ -20,6 +20,7 @@ #include #ifdef GRUB_MACHINE_PCBIOS #include +#include #endif #include #include @@ -279,7 +280,8 @@ grub_multiboot_get_mbi_size (void) + elf_sec_entsize * elf_sec_num + (sizeof (struct multiboot_tag_mmap) + grub_get_multiboot_mmap_count () * sizeof (struct multiboot_mmap_entry)) - + sizeof (struct multiboot_tag_vbe) + MULTIBOOT_TAG_ALIGN - 1; + + sizeof (struct multiboot_tag_vbe) + MULTIBOOT_TAG_ALIGN - 1 + + sizeof (struct multiboot_tag_apm) + MULTIBOOT_TAG_ALIGN - 1; } /* Fill previously allocated Multiboot mmap. */ @@ -515,6 +517,31 @@ grub_multiboot_make_mbi (grub_uint32_t *target) ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); } +#ifdef GRUB_MACHINE_PCBIOS + { + struct grub_apm_info info; + if (grub_apm_get_info (&info)) + { + struct multiboot_tag_apm *tag = (struct multiboot_tag_apm *) ptrorig; + + tag->type = MULTIBOOT_TAG_TYPE_APM; + tag->size = sizeof (struct multiboot_tag_apm); + + tag->cseg = info.cseg; + tag->offset = info.offset; + tag->cseg_16 = info.cseg_16; + tag->dseg = info.dseg; + tag->flags = info.flags; + tag->cseg_len = info.cseg_len; + tag->dseg_len = info.dseg_len; + tag->cseg_16_len = info.cseg_16_len; + tag->version = info.version; + + ptrorig += ALIGN_UP (tag->size, MULTIBOOT_TAG_ALIGN); + } + } +#endif + { unsigned i; struct module *cur; diff --git a/include/grub/i386/pc/apm.h b/include/grub/i386/pc/apm.h new file mode 100644 index 000000000..6d9e8c61d --- /dev/null +++ b/include/grub/i386/pc/apm.h @@ -0,0 +1,48 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2010 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_APM_MACHINE_HEADER +#define GRUB_APM_MACHINE_HEADER 1 + +#include + +struct grub_apm_info +{ + grub_uint16_t cseg; + grub_uint32_t offset; + grub_uint16_t cseg_16; + grub_uint16_t dseg; + grub_uint16_t flags; + grub_uint16_t cseg_len; + grub_uint16_t cseg_16_len; + grub_uint16_t dseg_len; + grub_uint16_t version; +}; + +enum + { + GRUB_APM_FLAGS_16BITPROTECTED_SUPPORTED = 1, + GRUB_APM_FLAGS_32BITPROTECTED_SUPPORTED = 2, + GRUB_APM_FLAGS_CPUIDLE_SLOWS_DOWN = 4, + GRUB_APM_FLAGS_DISABLED = 8, + GRUB_APM_FLAGS_DISENGAGED = 16, + }; + +int grub_apm_get_info (struct grub_apm_info *info); + +#endif diff --git a/include/grub/i386/pc/int.h b/include/grub/i386/pc/int.h index e1c463925..de23775d0 100644 --- a/include/grub/i386/pc/int.h +++ b/include/grub/i386/pc/int.h @@ -20,6 +20,7 @@ #define GRUB_INTERRUPT_MACHINE_HEADER 1 #include +#include struct grub_bios_int_registers { diff --git a/include/grub/i386/pc/vesa_modes_table.h b/include/grub/i386/pc/vesa_modes_table.h new file mode 100644 index 000000000..376ca376b --- /dev/null +++ b/include/grub/i386/pc/vesa_modes_table.h @@ -0,0 +1,19 @@ +#ifndef GRUB_VESA_MODE_TABLE_HEADER +#define GRUB_VESA_MODE_TABLE_HEADER 1 + +#include + +#define GRUB_VESA_MODE_TABLE_START 0x300 +#define GRUB_VESA_MODE_TABLE_END 0x373 + +struct grub_vesa_mode_table_entry { + grub_uint16_t width; + grub_uint16_t height; + grub_uint8_t depth; +}; + +extern struct grub_vesa_mode_table_entry +grub_vesa_mode_table[GRUB_VESA_MODE_TABLE_END + - GRUB_VESA_MODE_TABLE_START + 1]; + +#endif diff --git a/include/multiboot.h b/include/multiboot.h index fda863e85..ed71e6b96 100644 --- a/include/multiboot.h +++ b/include/multiboot.h @@ -254,6 +254,20 @@ struct multiboot_mod_list }; typedef struct multiboot_mod_list multiboot_module_t; +/* APM BIOS info. */ +struct multiboot_apm_info +{ + grub_uint16_t version; + grub_uint16_t cseg; + grub_uint32_t offset; + grub_uint16_t cseg_16; + grub_uint16_t dseg; + grub_uint16_t flags; + grub_uint16_t cseg_len; + grub_uint16_t cseg_16_len; + grub_uint16_t dseg_len; +}; + #endif /* ! ASM_FILE */ #endif /* ! MULTIBOOT_HEADER */ From 2b94e3ff6e3f116256ed74b0552dd2a19eb91f48 Mon Sep 17 00:00:00 2001 From: Yves Blusseau Date: Wed, 15 Sep 2010 11:46:16 +0200 Subject: [PATCH 190/214] Add function to get completions from usage. * util/bash-completion.d/grub-completion.bash.in: Add function to get completions from usage. Use LC_ALL=C to get options properly. --- ChangeLog | 7 +++++ ChangeLog.completion-usage | 4 +++ .../bash-completion.d/grub-completion.bash.in | 30 ++++++++++++++++--- 3 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 ChangeLog.completion-usage diff --git a/ChangeLog b/ChangeLog index c525fe369..1113b8157 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2010-09-15 Yves Blusseau + + Add function to get completions from usage. + + * util/bash-completion.d/grub-completion.bash.in: Add function to get + completions from usage. Use LC_ALL=C to get options properly. + 2010-09-15 Vladimir Serbinenko * grub-core/gnulib/basename-lgpl.c: Imported. diff --git a/ChangeLog.completion-usage b/ChangeLog.completion-usage new file mode 100644 index 000000000..eee7b018f --- /dev/null +++ b/ChangeLog.completion-usage @@ -0,0 +1,4 @@ +2010-09-15 Yves Blusseau + + * util/bash-completion.d/grub-completion.bash.in: Add function to get + completions from usage. diff --git a/util/bash-completion.d/grub-completion.bash.in b/util/bash-completion.d/grub-completion.bash.in index abba0df78..65cbb80ee 100644 --- a/util/bash-completion.d/grub-completion.bash.in +++ b/util/bash-completion.d/grub-completion.bash.in @@ -58,7 +58,7 @@ __grubcomp () { esac } -# Function that return long options from the help +# Function that return long options from the help of the command # - arg: $1 (optional) command to get the long options from __grub_get_options_from_help () { local prog @@ -70,7 +70,7 @@ __grub_get_options_from_help () { fi local i IFS=" "$'\t'$'\n' - for i in $($prog --help) + for i in $(LC_ALL=C $prog --help) do case $i in --*) echo "${i%=*}";; @@ -78,6 +78,28 @@ __grub_get_options_from_help () { done } +# Function that return long options from the usage of the command +# - arg: $1 (optional) command to get the long options from +__grub_get_options_from_usage () { + local prog + + if [ $# -ge 1 ]; then + prog="$1" + else + prog="${COMP_WORDS[0]}" + fi + + local i IFS=" "$'\t'$'\n' + for i in $(LC_ALL=C $prog --usage) + do + case $i in + \[--*\]) i=${i#[} # Remove leading [ + echo ${i%%?(=*)]} # Remove optional value and trailing ] + ;; + esac + done +} + __grub_get_last_option () { local i for (( i=$COMP_CWORD-1; i > 0; i-- )); do @@ -355,7 +377,7 @@ _grub_mkimage () { -O|--format) # Get available format from help local prog=${COMP_WORDS[0]} - __grubcomp "$($prog --help | \ + __grubcomp "$(LC_ALL=C $prog --help | \ awk -F ":" '/available formats/ { print $2 }' | \ sed 's/, / /g')" return @@ -415,7 +437,7 @@ _grub_probe () { -t|--target) # Get target type from help local prog=${COMP_WORDS[0]} - __grubcomp "$($prog --help | \ + __grubcomp "$(LC_ALL=C $prog --help | \ awk -F "[()]" '/--target=/ { print $2 }' | \ sed 's/|/ /g')" return From e2830452f05001e1c24e718deec6c71b7dc39e70 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 15 Sep 2010 13:51:02 +0200 Subject: [PATCH 191/214] Support legacy_check_password --- grub-core/commands/legacycfg.c | 91 +++++++++++++++++++++++++++------- grub-core/lib/legacy_parse.c | 25 +++++++--- 2 files changed, 93 insertions(+), 23 deletions(-) diff --git a/grub-core/commands/legacycfg.c b/grub-core/commands/legacycfg.c index bea608b9e..463297810 100644 --- a/grub-core/commands/legacycfg.c +++ b/grub-core/commands/legacycfg.c @@ -603,19 +603,14 @@ ib64t (char c) return -1; } -static grub_err_t -grub_cmd_legacy_password (struct grub_command *mycmd __attribute__ ((unused)), - int argc, char **args) +static struct legacy_md5_password * +parse_legacy_md5 (int argc, char **args) { const char *salt, *saltend; - const char *p; struct legacy_md5_password *pw = NULL; int i; + const char *p; - if (argc == 0) - return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments expected"); - if (args[0][0] != '-' || args[0][1] != '-') - return grub_normal_set_password ("legacy", args[0]); if (grub_memcmp (args[0], "--md5", sizeof ("--md5")) != 0) goto fail; if (argc == 1) @@ -667,21 +662,76 @@ grub_cmd_legacy_password (struct grub_command *mycmd __attribute__ ((unused)), if (!pw->salt) goto fail; - return grub_auth_register_authentication ("legacy", check_password_md5, pw); + return pw; fail: grub_free (pw); - /* This is to imitate minor difference between grub-legacy in GRUB2. - If 2 password commands are executed in a row and second one fails - on GRUB2 the password of first one is used, whereas in grub-legacy - authenthication is denied. In case of no password command was executed - early both versions deny any access. */ - return grub_auth_register_authentication ("legacy", check_password_deny, - NULL); + return NULL; +} + +static grub_err_t +grub_cmd_legacy_password (struct grub_command *mycmd __attribute__ ((unused)), + int argc, char **args) +{ + struct legacy_md5_password *pw = NULL; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments expected"); + if (args[0][0] != '-' || args[0][1] != '-') + return grub_normal_set_password ("legacy", args[0]); + + pw = parse_legacy_md5 (argc, args); + + if (pw) + return grub_auth_register_authentication ("legacy", check_password_md5, pw); + else + /* This is to imitate minor difference between grub-legacy in GRUB2. + If 2 password commands are executed in a row and second one fails + on GRUB2 the password of first one is used, whereas in grub-legacy + authenthication is denied. In case of no password command was executed + early both versions deny any access. */ + return grub_auth_register_authentication ("legacy", check_password_deny, + NULL); +} + +static grub_err_t +grub_cmd_legacy_check_password (struct grub_command *mycmd __attribute__ ((unused)), + int argc, char **args) +{ + struct legacy_md5_password *pw = NULL; + char entered[GRUB_AUTH_MAX_PASSLEN]; + + if (argc == 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments expected"); + grub_printf ("Enter password:"); + if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN)) + return GRUB_ACCESS_DENIED; + + if (args[0][0] != '-' || args[0][1] != '-') + { + char correct[GRUB_AUTH_MAX_PASSLEN]; + + grub_memset (correct, 0, sizeof (correct)); + grub_strncpy (correct, args[0], sizeof (correct)); + + if (grub_crypto_memcmp (entered, correct, GRUB_AUTH_MAX_PASSLEN) != 0) + return GRUB_ACCESS_DENIED; + return GRUB_ERR_NONE; + } + + pw = parse_legacy_md5 (argc, args); + + if (!pw) + return GRUB_ACCESS_DENIED; + + if (!check_password_md5_real (entered, pw)) + return GRUB_ACCESS_DENIED; + + return GRUB_ERR_NONE; } static grub_command_t cmd_source, cmd_configfile, cmd_kernel, cmd_initrd; -static grub_command_t cmd_password, cmd_initrdnounzip; +static grub_command_t cmd_password, cmd_check_password, cmd_initrdnounzip; GRUB_MOD_INIT(legacycfg) { @@ -711,6 +761,12 @@ GRUB_MOD_INIT(legacycfg) grub_cmd_legacy_password, N_("[--md5] PASSWD [FILE]"), N_("Simulate grub-legacy password command")); + + cmd_check_password = grub_register_command ("legacy_check_password", + grub_cmd_legacy_check_password, + N_("[--md5] PASSWD [FILE]"), + N_("Simulate grub-legacy password command in menuentry mode")); + } GRUB_MOD_FINI(legacycfg) @@ -721,4 +777,5 @@ GRUB_MOD_FINI(legacycfg) grub_unregister_command (cmd_initrd); grub_unregister_command (cmd_initrdnounzip); grub_unregister_command (cmd_password); + grub_unregister_command (cmd_check_password); } diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index 024d425e8..e5014cdc7 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -49,6 +49,8 @@ struct legacy_command FLAG_FALLBACK_AVAILABLE = 4, FLAG_FALLBACK = 8, FLAG_COLOR_INVERT = 16, + FLAG_NO_MENUENTRY = 32, + FLAG_MENUENTRY_ONLY = 64, } flags; const char *shortdesc; const char *longdesc; @@ -189,12 +191,12 @@ struct legacy_command legacy_commands[] = {"parttype", "parttool '%s' type=%s\n", NULL, 0, 2, {TYPE_PARTITION, TYPE_INT}, 0, "PART TYPE", "Change the type of the partition PART to TYPE."}, - /* FIXME: support usage in menuentry. */ {"password", "if [ \"$superusers\" = "" ]; then superusers=legacy; fi;\n" - "legacy_password %s '%s'", + "legacy_password %s '%s'\n", "menuentry \"Superuser menu\" --users \"legacy\" { configfile '%s'; }\n", 2, 3, {TYPE_OPTION, TYPE_VERBATIM, TYPE_FILE}, - FLAG_IGNORE_REST | FLAG_FALLBACK_AVAILABLE, "[--md5] PASSWD [FILE]", + FLAG_IGNORE_REST | FLAG_FALLBACK_AVAILABLE | FLAG_NO_MENUENTRY, + "[--md5] PASSWD [FILE]", "If used in the first section of a menu file, disable all" " interactive editing control (menu entry editor and" " command line). If the password PASSWD is entered, it loads the" @@ -205,8 +207,15 @@ struct legacy_command legacy_commands[] = " The option --md5 tells GRUB that PASSWD is encrypted with" " md5crypt."}, {"password", "if [ \"$superusers\" = "" ]; then superusers=legacy; fi;\n" - "legacy_password %s '%s'", NULL, 0, 2, {TYPE_OPTION, TYPE_VERBATIM}, - FLAG_IGNORE_REST | FLAG_FALLBACK, NULL, NULL}, + "legacy_password %s '%s'\n", NULL, 0, 2, {TYPE_OPTION, TYPE_VERBATIM}, + FLAG_IGNORE_REST | FLAG_FALLBACK | FLAG_NO_MENUENTRY, NULL, NULL}, + {"password", "if legacy_check_password %s '%s'; then configfile '%s'; " + "else return; fi\n", NULL, 2, 3, {TYPE_OPTION, TYPE_VERBATIM, TYPE_FILE}, + FLAG_IGNORE_REST | FLAG_FALLBACK_AVAILABLE | FLAG_MENUENTRY_ONLY, + NULL, NULL}, + {"password", "if ! legacy_check_password %s '%s'; then return fi;\n", + NULL, 0, 2, {TYPE_OPTION, TYPE_VERBATIM}, + FLAG_IGNORE_REST | FLAG_FALLBACK | FLAG_MENUENTRY_ONLY, NULL, NULL}, /* NOTE: GRUB2 has a design principle of not eternally waiting for user input. 60 seconds should be enough. */ @@ -442,7 +451,11 @@ grub_legacy_parse (const char *buf, char **entryname, char **suffix) for (cmdnum = 0; cmdnum < ARRAY_SIZE (legacy_commands); cmdnum++) if (grub_strncmp (legacy_commands[cmdnum].name, cmdname, ptr - cmdname) == 0 - && legacy_commands[cmdnum].name[ptr - cmdname] == 0) + && legacy_commands[cmdnum].name[ptr - cmdname] == 0 + && (!(*entryname != NULL && (legacy_commands[cmdnum].flags + & FLAG_NO_MENUENTRY))) + && (!(*entryname == NULL && (legacy_commands[cmdnum].flags + & FLAG_MENUENTRY_ONLY)))) break; if (cmdnum == ARRAY_SIZE (legacy_commands)) return grub_xasprintf ("# Unsupported legacy command: %s\n", buf); From c99dead65448b083befbb9977f19d22c8ea14902 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 15 Sep 2010 14:11:08 +0200 Subject: [PATCH 192/214] Support geometry --- grub-core/lib/legacy_parse.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index e5014cdc7..a0be27d60 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -118,7 +118,9 @@ struct legacy_command legacy_commands[] = "Search for the filename FILENAME in all of partitions and print the list of" " the devices which contain the file."}, /* FIXME: fstest unsupported. */ - /* FIXME: geometry unsupported. */ + /* NOTE: The obsolete C/H/S geometry isn't shown anymore. */ + {"geometry", "insmod regexp; ls -l (%s*)\n", NULL, 0, 1, {TYPE_VERBATIM}, 0, "DRIVE", + "Print the information for a drive DRIVE. "}, {"halt", "halt %s\n", NULL, 0, 1, {TYPE_NOAPM_OPTION}, 0, "[--no-apm]", "Halt your system. If APM is available on it, turn off the power using" " the APM BIOS, unless you specify the option `--no-apm'."}, From 3f8fcb6a24414ab86f1ea37501ae6d608a2487b6 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 15 Sep 2010 14:37:28 +0200 Subject: [PATCH 193/214] Support vbeprobe MODE --- grub-core/commands/videoinfo.c | 46 +++++++++++++++++++++++++++++----- grub-core/lib/legacy_parse.c | 8 +++--- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/grub-core/commands/videoinfo.c b/grub-core/commands/videoinfo.c index 15f677e14..10f77915b 100644 --- a/grub-core/commands/videoinfo.c +++ b/grub-core/commands/videoinfo.c @@ -25,9 +25,17 @@ #include #include +static unsigned height, width, depth; + static int hook (const struct grub_video_mode_info *info) { + if (height && width && (info->width != width || info->height != height)) + return 0; + + if (depth && info->bpp != depth) + return 0; + if (info->mode_number == GRUB_VIDEO_MODE_NUMBER_INVALID) grub_printf (" "); else @@ -71,12 +79,34 @@ hook (const struct grub_video_mode_info *info) static grub_err_t grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)), - int argc __attribute__ ((unused)), - char **args __attribute__ ((unused))) + int argc, char **args) { grub_video_adapter_t adapter; grub_video_driver_id_t id; + height = width = depth = 0; + if (argc) + { + char *ptr; + ptr = args[0]; + width = grub_strtoul (ptr, &ptr, 0); + if (grub_errno) + return grub_errno; + if (*ptr != 'x') + return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid mode specification"); + ptr++; + height = grub_strtoul (ptr, &ptr, 0); + if (grub_errno) + return grub_errno; + if (*ptr == 'x') + { + ptr++; + depth = grub_strtoul (ptr, &ptr, 0); + if (grub_errno) + return grub_errno; + } + } + #ifdef GRUB_MACHINE_PCBIOS if (grub_strcmp (cmd->name, "vbeinfo") == 0) grub_dl_load ("vbe"); @@ -132,11 +162,15 @@ static grub_command_t cmd_vbe; GRUB_MOD_INIT(videoinfo) { - cmd = grub_register_command ("videoinfo", grub_cmd_videoinfo, 0, - N_("List available video modes.")); + cmd = grub_register_command ("videoinfo", grub_cmd_videoinfo, "[WxH[xD]]", + N_("List available video modes. If " + "resolution is given show only modes" + " matching it.")); #ifdef GRUB_MACHINE_PCBIOS - cmd_vbe = grub_register_command ("vbeinfo", grub_cmd_videoinfo, 0, - N_("List available video modes.")); + cmd_vbe = grub_register_command ("vbeinfo", grub_cmd_videoinfo, "[WxH[xD]]", + N_("List available video modes. If " + "resolution is given show only modes" + " matching it.")); #endif } diff --git a/grub-core/lib/legacy_parse.c b/grub-core/lib/legacy_parse.c index a0be27d60..6ad15dc49 100644 --- a/grub-core/lib/legacy_parse.c +++ b/grub-core/lib/legacy_parse.c @@ -292,10 +292,12 @@ struct legacy_command legacy_commands[] = /* FIXME: uppermem unsupported. */ {"uuid", "search --set=root --fs-uuid '%s'\n", NULL, 0, 1, {TYPE_VERBATIM}, 0, "UUID", "Find root by UUID"}, - /* FIXME: support MODE. */ - {"vbeprobe", "insmod vbe; videoinfo\n", NULL, 0, 0, {}, 0, "[MODE]", + {"vbeprobe", "insmod vbe; videoinfo '%s'\n", NULL, 0, 1, {TYPE_VBE_MODE}, + FLAG_FALLBACK_AVAILABLE, "[MODE]", "Probe VBE information. If the mode number MODE is specified, show only" - " the information about only the mode."} + " the information about only the mode."}, + {"vbeprobe", "insmod vbe; videoinfo\n", NULL, 0, 0, {}, + FLAG_FALLBACK, NULL, NULL} }; char * From 14437e800868c847980daad364a31a63029d9e8c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 15 Sep 2010 14:45:08 +0200 Subject: [PATCH 194/214] Allow install_device to be missing on non-pc and non-sparc --- util/grub-install.in | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/util/grub-install.in b/util/grub-install.in index ecdbfe179..344475b5c 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -83,7 +83,8 @@ fi # Usage: usage # Print the usage. usage () { -if test "x$install_device" = x && test "${target_cpu}-${platform}" != "mips-yeeloong" && test "${target_cpu}-${platform}" != "i386-ieee1275" && test "${target_cpu}-${platform}" != "powerpc-ieee1275"; then +if [ "${target_cpu}-${platform}" = "i386-pc" ] \ + || [ "${target_cpu}-${platform}" = "sparc64-ieee1275" ]; then cat <&2 usage exit 1 From f00478b7196526bfd3370c3d3acf8fdff7e92b78 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 15 Sep 2010 15:30:43 +0200 Subject: [PATCH 195/214] * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_is_floppy): New function. * include/grub/emu/hostdisk.h (grub_util_biosdisk_is_floppy): New proto. * util/grub-setup.c (setup): Use grub_util_biosdisk_is_floppy. --- ChangeLog | 7 +++++++ grub-core/kern/emu/hostdisk.c | 26 ++++++++++++++++++++++++++ include/grub/emu/hostdisk.h | 1 + util/grub-setup.c | 4 ++-- 4 files changed, 36 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1113b8157..b3f3c0e51 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2010-09-15 Vladimir Serbinenko + + * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_is_floppy): New + function. + * include/grub/emu/hostdisk.h (grub_util_biosdisk_is_floppy): New proto. + * util/grub-setup.c (setup): Use grub_util_biosdisk_is_floppy. + 2010-09-15 Yves Blusseau Add function to get completions from usage. diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index 142e93fe2..edf8dc219 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -1575,3 +1575,29 @@ grub_util_biosdisk_get_osdev (grub_disk_t disk) { return map[disk->id].device; } + +int +grub_util_biosdisk_is_floppy (grub_disk_t disk) +{ + struct stat st; + int fd; + + fd = open (map[disk->id].device, O_RDONLY); + /* Shouldn't happen. */ + if (fd == -1) + return 0; + + /* Shouldn't happen either. */ + if (fstat (fd, &st) < 0) + return 0; + +#if defined(__NetBSD__) + if (major(st.st_rdev) == RAW_FLOPPY_MAJOR) + return 1; +#endif + + if (major(st.st_rdev) == FLOPPY_MAJOR) + return 1; + + return 0; +} diff --git a/include/grub/emu/hostdisk.h b/include/grub/emu/hostdisk.h index 5873aa440..d8cc02e14 100644 --- a/include/grub/emu/hostdisk.h +++ b/include/grub/emu/hostdisk.h @@ -27,5 +27,6 @@ void grub_util_biosdisk_fini (void); char *grub_util_biosdisk_get_grub_dev (const char *os_dev); const char *grub_util_biosdisk_get_osdev (grub_disk_t disk); int grub_util_biosdisk_is_present (const char *name); +int grub_util_biosdisk_is_floppy (grub_disk_t disk); #endif /* ! GRUB_BIOSDISK_MACHINE_UTIL_HEADER */ diff --git a/util/grub-setup.c b/util/grub-setup.c index 55d740f09..a95f9b9d5 100644 --- a/util/grub-setup.c +++ b/util/grub-setup.c @@ -339,8 +339,8 @@ setup (const char *dir, /* If DEST_DRIVE is a hard disk, enable the workaround, which is for buggy BIOSes which don't pass boot drive correctly. Instead, they pass 0x00 or 0x01 even when booted from 0x80. */ - if (dest_dev->disk->id & 0x80) - /* Replace the jmp (2 bytes) with double nop's. */ + if (!grub_util_biosdisk_is_floppy (dest_dev->disk)) + /* Replace the jmp (2 bytes) with double nop's. */ *boot_drive_check = 0x9090; } #endif From e9fc4da271612c22fb98d104ea872ef848a95b5d Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 15 Sep 2010 16:14:38 +0200 Subject: [PATCH 196/214] Remove accidently merged file --- ChangeLog.completion-usage | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 ChangeLog.completion-usage diff --git a/ChangeLog.completion-usage b/ChangeLog.completion-usage deleted file mode 100644 index eee7b018f..000000000 --- a/ChangeLog.completion-usage +++ /dev/null @@ -1,4 +0,0 @@ -2010-09-15 Yves Blusseau - - * util/bash-completion.d/grub-completion.bash.in: Add function to get - completions from usage. From e50fca4a4c7ec7597456a5e2e0d166c20c719ecc Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 15 Sep 2010 21:36:57 +0200 Subject: [PATCH 197/214] Move embedding routines to partmap sources files. * grub-core/partmap/gpt.c (grub_gpt_partition_type_bios_boot) [GRUB_UTIL]: New variable. (gpt_partition_map_iterate): Set part.parent. (gpt_partition_map_embed) [GRUB_UTIL]: New function. (grub_gpt_partition_map) [GRUB_UTIL]: Set .embed. * grub-core/partmap/msdos.c (pc_partition_map_embed) [GRUB_UTIL]: New function. (grub_msdos_partition_map) [GRUB_UTIL]: Set .embed. * include/grub/partition.h (grub_embed_type_t) [GRUB_UTIL]: New type. (grub_partition_map) [GRUB_UTIL]: New field embed. * util/grub-setup.c (grub_gpt_partition_type_bios_boot): Removed. (setup): Use ->embed. --- ChangeLog | 17 ++++ grub-core/partmap/gpt.c | 66 +++++++++++++ grub-core/partmap/msdos.c | 116 ++++++++++++++++++++++ include/grub/partition.h | 12 +++ util/grub-setup.c | 196 ++++++++++++++++---------------------- 5 files changed, 295 insertions(+), 112 deletions(-) diff --git a/ChangeLog b/ChangeLog index b3f3c0e51..0c092d0b9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2010-09-15 Vladimir Serbinenko + + Move embedding routines to partmap sources files. + + * grub-core/partmap/gpt.c (grub_gpt_partition_type_bios_boot) + [GRUB_UTIL]: New variable. + (gpt_partition_map_iterate): Set part.parent. + (gpt_partition_map_embed) [GRUB_UTIL]: New function. + (grub_gpt_partition_map) [GRUB_UTIL]: Set .embed. + * grub-core/partmap/msdos.c (pc_partition_map_embed) [GRUB_UTIL]: + New function. + (grub_msdos_partition_map) [GRUB_UTIL]: Set .embed. + * include/grub/partition.h (grub_embed_type_t) [GRUB_UTIL]: New type. + (grub_partition_map) [GRUB_UTIL]: New field embed. + * util/grub-setup.c (grub_gpt_partition_type_bios_boot): Removed. + (setup): Use ->embed. + 2010-09-15 Vladimir Serbinenko * grub-core/kern/emu/hostdisk.c (grub_util_biosdisk_is_floppy): New diff --git a/grub-core/partmap/gpt.c b/grub-core/partmap/gpt.c index 0dd670cce..c9393d932 100644 --- a/grub-core/partmap/gpt.c +++ b/grub-core/partmap/gpt.c @@ -32,6 +32,10 @@ static grub_uint8_t grub_gpt_magic[8] = static const grub_gpt_part_type_t grub_gpt_partition_type_empty = GRUB_GPT_PARTITION_TYPE_EMPTY; +#ifdef GRUB_UTIL +static const grub_gpt_part_type_t grub_gpt_partition_type_bios_boot = GRUB_GPT_PARTITION_TYPE_BIOS_BOOT; +#endif + /* 512 << 7 = 65536 byte sectors. */ #define MAX_SECTOR_LOG 7 @@ -97,6 +101,7 @@ gpt_partition_map_iterate (grub_disk_t disk, part.number = i; part.index = last_offset; part.partmap = &grub_gpt_partition_map; + part.parent = disk->partition; grub_dprintf ("gpt", "GPT entry %d: start=%lld, length=%lld\n", i, (unsigned long long) part.start, @@ -117,12 +122,73 @@ gpt_partition_map_iterate (grub_disk_t disk, return GRUB_ERR_NONE; } +#ifdef GRUB_UTIL +static grub_err_t +gpt_partition_map_embed (struct grub_disk *disk, unsigned int nsectors, + grub_embed_type_t embed_type, + grub_disk_addr_t *sectors) +{ + grub_disk_addr_t start = 0, len = 0; + unsigned i; + grub_err_t err; + + auto int NESTED_FUNC_ATTR find_usable_region (grub_disk_t disk, + const grub_partition_t p); + int NESTED_FUNC_ATTR find_usable_region (grub_disk_t disk __attribute__ ((unused)), + const grub_partition_t p) + { + struct grub_gpt_partentry gptdata; + + disk->partition = p->parent; + if (grub_disk_read (disk, p->offset, p->index, + sizeof (gptdata), &gptdata)) + return 0; + + /* If there's an embed region, it is in a dedicated partition. */ + if (! grub_memcmp (&gptdata.type, &grub_gpt_partition_type_bios_boot, 16)) + { + start = p->start; + len = p->len; + return 1; + } + + return 0; + } + + if (embed_type != GRUB_EMBED_PCBIOS) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "GPT curently supports only PC-BIOS embedding"); + + err = gpt_partition_map_iterate (disk, find_usable_region); + if (err) + return err; + + if (len == 0) + return grub_error (GRUB_ERR_FILE_NOT_FOUND, + "This GPT partition label has no BIOS Boot Partition;" + " embedding won't be possible!"); + + if (len < nsectors) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "Your BIOS Boot Partition is too small;" + " embedding won't be possible!"); + + for (i = 0; i < nsectors; i++) + sectors[i] = start + i; + + return GRUB_ERR_NONE; +} +#endif + /* Partition map type. */ static struct grub_partition_map grub_gpt_partition_map = { .name = "gpt", .iterate = gpt_partition_map_iterate, +#ifdef GRUB_UTIL + .embed = gpt_partition_map_embed +#endif }; GRUB_MOD_INIT(part_gpt) diff --git a/grub-core/partmap/msdos.c b/grub-core/partmap/msdos.c index 3898d09fa..7dab4aa0f 100644 --- a/grub-core/partmap/msdos.c +++ b/grub-core/partmap/msdos.c @@ -133,12 +133,128 @@ pc_partition_map_iterate (grub_disk_t disk, return grub_errno; } +#ifdef GRUB_UTIL +static grub_err_t +pc_partition_map_embed (struct grub_disk *disk, unsigned int nsectors, + grub_embed_type_t embed_type, + grub_disk_addr_t *sectors) +{ + grub_disk_addr_t end = ~0ULL; + struct grub_msdos_partition_mbr mbr; + int labeln = 0; + /* Any value different than `p.offset' will satisfy the check during + first loop. */ + grub_disk_addr_t lastaddr = 1; + grub_disk_addr_t ext_offset = 0; + grub_disk_addr_t offset = 0; + + if (embed_type != GRUB_EMBED_PCBIOS) + return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, + "PC-style partitions curently support " + "only PC-BIOS embedding"); + + if (disk->partition) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "Embedding on MSDOS subpartition isn't supported"); + + while (1) + { + int i; + struct grub_msdos_partition_entry *e; + grub_err_t err; + + /* Read the MBR. */ + err = grub_disk_read (disk, offset, 0, sizeof (mbr), &mbr); + if (err) + return err; + + /* This is our loop-detection algorithm. It works the following way: + It saves last position which was a power of two. Then it compares the + saved value with a current one. This way it's guaranteed that the loop + will be broken by at most third walk. + */ + if (labeln && lastaddr == offset) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "loop detected"); + + labeln++; + if ((labeln & (labeln - 1)) == 0) + lastaddr = offset; + + /* Check if it is valid. */ + if (mbr.signature != grub_cpu_to_le16 (GRUB_PC_PARTITION_SIGNATURE)) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "no signature"); + + for (i = 0; i < 4; i++) + if (mbr.entries[i].flag & 0x7f) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "bad boot flag"); + + /* Analyze DOS partitions. */ + for (i = 0; i < 4; i++) + { + e = mbr.entries + i; + + if (!grub_msdos_partition_is_empty (e->type) + && end > offset + grub_le_to_cpu32 (e->start)) + end = offset + grub_le_to_cpu32 (e->start); + + /* If this is a GPT partition, this MBR is just a dummy. */ + if (e->type == GRUB_PC_PARTITION_TYPE_GPT_DISK && i == 0) + return grub_error (GRUB_ERR_BAD_PART_TABLE, "dummy mbr"); + } + + /* Find an extended partition. */ + for (i = 0; i < 4; i++) + { + e = mbr.entries + i; + + if (grub_msdos_partition_is_extended (e->type)) + { + offset = ext_offset + grub_le_to_cpu32 (e->start); + if (! ext_offset) + ext_offset = offset; + + break; + } + } + + /* If no extended partition, the end. */ + if (i == 4) + break; + } + + if (end >= nsectors + 1) + { + int i; + for (i = 0; i < nsectors; i++) + sectors[i] = 1 + i; + return GRUB_ERR_NONE; + } + + if (end <= 1) + return grub_error (GRUB_ERR_FILE_NOT_FOUND, + "This msdos-style partition label has no " + "post-MBR gap; embedding won't be possible!"); + + if (nsectors > 62) + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "Your core.img is unusually large. " + "It won't fit in the embedding area."); + + return grub_error (GRUB_ERR_OUT_OF_RANGE, + "Your embedding area is unusually small. " + "core.img won't fit in it."); +} +#endif + /* Partition map type. */ static struct grub_partition_map grub_msdos_partition_map = { .name = "msdos", .iterate = pc_partition_map_iterate, +#ifdef GRUB_UTIL + .embed = pc_partition_map_embed +#endif }; GRUB_MOD_INIT(part_msdos) diff --git a/include/grub/partition.h b/include/grub/partition.h index 20705c527..a29a3440d 100644 --- a/include/grub/partition.h +++ b/include/grub/partition.h @@ -26,6 +26,13 @@ struct grub_disk; typedef struct grub_partition *grub_partition_t; +#ifdef GRUB_UTIL +typedef enum +{ + GRUB_EMBED_PCBIOS +} grub_embed_type_t; +#endif + /* Partition map type. */ struct grub_partition_map { @@ -39,6 +46,11 @@ struct grub_partition_map grub_err_t (*iterate) (struct grub_disk *disk, int (*hook) (struct grub_disk *disk, const grub_partition_t partition)); +#ifdef GRUB_UTIL + /* Determine sectors available for embedding. */ + grub_err_t (*embed) (struct grub_disk *disk, unsigned int nsectors, + grub_embed_type_t embed_type, grub_disk_addr_t *sectors); +#endif }; typedef struct grub_partition_map *grub_partition_map_t; diff --git a/util/grub-setup.c b/util/grub-setup.c index a95f9b9d5..c9ab5cfdb 100644 --- a/util/grub-setup.c +++ b/util/grub-setup.c @@ -26,8 +26,6 @@ #include #include #include -#include -#include #include #include #include @@ -74,10 +72,6 @@ * result. */ -#ifdef GRUB_MACHINE_PCBIOS -static const grub_gpt_part_type_t grub_gpt_partition_type_bios_boot = GRUB_GPT_PARTITION_TYPE_BIOS_BOOT; -#endif - #define DEFAULT_BOOT_FILE "boot.img" #define DEFAULT_CORE_FILE "core.img" @@ -200,8 +194,6 @@ setup (const char *dir, grub_uint16_t last_length = GRUB_DISK_SECTOR_SIZE; grub_file_t file; FILE *fp; - struct { grub_uint64_t start; grub_uint64_t end; } embed_region; - embed_region.start = embed_region.end = ~0UL; auto void NESTED_FUNC_ATTR save_first_sector (grub_disk_addr_t sector, unsigned offset, @@ -283,7 +275,6 @@ setup (const char *dir, first_block = (struct grub_boot_blocklist *) (core_img + GRUB_DISK_SECTOR_SIZE - sizeof (*block)); - grub_util_info ("root is `%s', dest is `%s'", root, dest); /* Open the root device and the destination device. */ @@ -308,24 +299,6 @@ setup (const char *dir, grub_util_error ("%s", grub_errmsg); #endif -#ifdef GRUB_MACHINE_PCBIOS - if (dest_dev->disk->partition && fs_probe) - { - grub_fs_t fs; - fs = grub_fs_probe (dest_dev); - if (! fs) - grub_util_error (_("unable to identify a filesystem in %s; safety check can't be performed"), - dest_dev->disk->name); - - if (! fs->reserved_first_sector) - grub_util_error (_("%s appears to contain a %s filesystem which isn't known to " - "reserve space for DOS-style boot. Installing GRUB there could " - "result in FILESYSTEM DESTRUCTION if valuable data is overwritten " - "by grub-setup (--skip-fs-probe disables this " - "check, use at your own risk)"), dest_dev->disk->name, fs->name); - } -#endif - #ifdef GRUB_MACHINE_PCBIOS { grub_uint16_t *boot_drive_check; @@ -345,53 +318,27 @@ setup (const char *dir, } #endif + /* Clean out the blocklists. */ + block = first_block; + while (block->len) + { + grub_memset (block, 0, sizeof (block)); + + block--; + + if ((char *) block <= core_img) + grub_util_error ("No terminator in the core image"); + } + #ifdef GRUB_MACHINE_PCBIOS { - const char *dest_partmap; - int multiple_partmaps; - - auto int NESTED_FUNC_ATTR find_usable_region_msdos (grub_disk_t disk, - const grub_partition_t p); - int NESTED_FUNC_ATTR find_usable_region_msdos (grub_disk_t disk __attribute__ ((unused)), - const grub_partition_t p) - { - /* There's always an embed region, and it starts right after the MBR. */ - embed_region.start = 1; - - if (embed_region.end > grub_partition_get_start (p)) - embed_region.end = grub_partition_get_start (p); - - return 0; - } - - auto int NESTED_FUNC_ATTR find_usable_region_gpt (grub_disk_t disk, - const grub_partition_t p); - int NESTED_FUNC_ATTR find_usable_region_gpt (grub_disk_t disk __attribute__ ((unused)), - const grub_partition_t p) - { - struct grub_gpt_partentry gptdata; - - disk->partition = p->parent; - if (grub_disk_read (disk, p->offset, p->index, - sizeof (gptdata), &gptdata)) - return 0; - - /* If there's an embed region, it is in a dedicated partition. */ - if (! memcmp (&gptdata.type, &grub_gpt_partition_type_bios_boot, 16)) - { - embed_region.start = grub_partition_get_start (p); - embed_region.end = grub_partition_get_start (p) + grub_partition_get_len (p); - - return 1; - } - return 0; - } - - if (dest_dev->disk->partition) - { - grub_util_warn (_("Attempting to install GRUB to a partition instead of the MBR. This is a BAD idea.")); - goto unable_to_embed; - } + grub_partition_map_t dest_partmap = NULL; + grub_partition_map_t container = dest_dev->disk->partition; + int multiple_partmaps = 0; + grub_err_t err; + grub_disk_addr_t sectors[core_sectors]; + int i; + grub_fs_t fs; /* Unlike root_dev, with dest_dev we're interested in the partition map even if dest_dev itself is a whole disk. */ @@ -400,29 +347,60 @@ setup (const char *dir, int NESTED_FUNC_ATTR identify_partmap (grub_disk_t disk __attribute__ ((unused)), const grub_partition_t p) { - if (p->parent) + if (p->parent != container) return 0; if (dest_partmap == NULL) - dest_partmap = p->partmap->name; - else if (strcmp (dest_partmap, p->partmap->name) != 0) { - multiple_partmaps = 1; - return 1; + dest_partmap = p->partmap; + return 0; } - return 0; + if (dest_partmap == p->partmap) + return 0; + multiple_partmaps = 1; + return 1; } - dest_partmap = 0; - multiple_partmaps = 0; + grub_partition_iterate (dest_dev->disk, identify_partmap); + fs = grub_fs_probe (dest_dev); + if (!fs) + grub_errno = GRUB_ERR_NONE; + +#ifdef GRUB_MACHINE_PCBIOS + if (fs_probe) + { + if (!fs && !dest_partmap) + grub_util_error (_("unable to identify a filesystem in %s; safety check can't be performed"), + dest_dev->disk->name); + if (fs && !fs->reserved_first_sector) + grub_util_error (_("%s appears to contain a %s filesystem which isn't known to " + "reserve space for DOS-style boot. Installing GRUB there could " + "result in FILESYSTEM DESTRUCTION if valuable data is overwritten " + "by grub-setup (--skip-fs-probe disables this " + "check, use at your own risk)"), dest_dev->disk->name, fs->name); + + if (dest_partmap && strcmp (dest_partmap->name, "msdos") != 0 + && strcmp (dest_partmap->name, "gpt") != 0 + && strcmp (dest_partmap->name, "bsd") != 0 + && strcmp (dest_partmap->name, "netbsd") != 0 + && strcmp (dest_partmap->name, "openbsd") != 0 + && strcmp (dest_partmap->name, "sunpc") != 0) + grub_util_error (_("%s appears to contain a %s partition map which isn't known to " + "reserve space for DOS-style boot. Installing GRUB there could " + "result in FILESYSTEM DESTRUCTION if valuable data is overwritten " + "by grub-setup (--skip-fs-probe disables this " + "check, use at your own risk)"), dest_dev->disk->name, dest_partmap->name); + } +#endif + if (! dest_partmap) { grub_util_warn (_("Attempting to install GRUB to a partitionless disk. This is a BAD idea.")); goto unable_to_embed; } - if (multiple_partmaps) + if (multiple_partmaps || fs) { - grub_util_warn (_("Attempting to install GRUB to a disk with multiple partition labels. This is not supported yet.")); + grub_util_warn (_("Attempting to install GRUB to a disk with multiple partition labels or both partition label and filesystem. This is not supported yet.")); goto unable_to_embed; } @@ -433,44 +411,33 @@ setup (const char *dir, GRUB_BOOT_MACHINE_PART_END - GRUB_BOOT_MACHINE_WINDOWS_NT_MAGIC); free (tmp_img); - - if (strcmp (dest_partmap, "msdos") == 0) - grub_partition_iterate (dest_dev->disk, find_usable_region_msdos); - else if (strcmp (dest_partmap, "gpt") == 0) - grub_partition_iterate (dest_dev->disk, find_usable_region_gpt); - else - grub_util_error (_("No DOS-style partitions found")); - - if (embed_region.end <= embed_region.start) + + if (!dest_partmap->embed) { - if (! strcmp (dest_partmap, "msdos")) - grub_util_warn (_("This msdos-style partition label has no post-MBR gap; embedding won't be possible!")); - else - grub_util_warn (_("This GPT partition label has no BIOS Boot Partition; embedding won't be possible!")); + grub_util_warn ("Partition style '%s' doesn't support embeding", + dest_partmap->name); goto unable_to_embed; } - if ((unsigned long) core_sectors > embed_region.end - embed_region.start) + err = dest_partmap->embed (dest_dev->disk, core_sectors, + GRUB_EMBED_PCBIOS, sectors); + + if (err) { - if (core_sectors > 62) - grub_util_warn (_("Your core.img is unusually large. It won't fit in the embedding area.")); - else /* embed_region.end - embed_region.start < 62 */ - grub_util_warn (_("Your embedding area is unusually small. core.img won't fit in it.")); + grub_util_warn ("%s", grub_errmsg); + grub_errno = GRUB_ERR_NONE; goto unable_to_embed; } - write_rootdev (core_img, root_dev, - boot_img, embed_region.start); + save_first_sector (sectors[0] + grub_partition_get_start (container), + 0, GRUB_DISK_SECTOR_SIZE); - grub_util_info ("the core image will be embedded at sector 0x%llx", embed_region.start); + block = first_block; + for (i = 1; i < core_sectors; i++) + save_blocklists (sectors[i] + grub_partition_get_start (container), + 0, GRUB_DISK_SECTOR_SIZE); - /* The first blocklist contains the whole sectors. */ - first_block->start = grub_cpu_to_le64 (embed_region.start + 1); - - /* These are filled elsewhere. Verify them just in case. */ - assert (first_block->len == grub_host_to_target16 (core_sectors - 1)); - assert (first_block->segment == grub_host_to_target16 (GRUB_BOOT_MACHINE_KERNEL_SEG - + (GRUB_DISK_SECTOR_SIZE >> 4))); + write_rootdev (core_img, root_dev, boot_img, first_sector); /* Make sure that the second blocklist is a terminator. */ block = first_block - 1; @@ -479,8 +446,13 @@ setup (const char *dir, block->segment = 0; /* Write the core image onto the disk. */ - if (grub_disk_write (dest_dev->disk, embed_region.start, 0, core_size, core_img)) - grub_util_error ("%s", grub_errmsg); + for (i = 0; i < core_sectors; i++) + grub_disk_write (dest_dev->disk, sectors[i], 0, + (core_size - i * GRUB_DISK_SECTOR_SIZE + < GRUB_DISK_SECTOR_SIZE) ? core_size + - i * GRUB_DISK_SECTOR_SIZE + : GRUB_DISK_SECTOR_SIZE, + core_img + i * GRUB_DISK_SECTOR_SIZE); /* Write the boot image onto the disk. */ if (grub_disk_write (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, From 35139e8a5556a6fb6c79686e6545b80a7370bd4c Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Wed, 15 Sep 2010 21:48:24 +0200 Subject: [PATCH 198/214] * grub-core/commands/parttool.c (grub_cmd_parttool): Fix a variable misusage. Reported by: J. Nick Terry --- ChangeLog | 6 ++++++ grub-core/commands/parttool.c | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 0c092d0b9..0b3d7627c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2010-09-15 Vladimir Serbinenko + + * grub-core/commands/parttool.c (grub_cmd_parttool): Fix a variable + misusage. + Reported by: J. Nick Terry + 2010-09-15 Vladimir Serbinenko Move embedding routines to partmap sources files. diff --git a/grub-core/commands/parttool.c b/grub-core/commands/parttool.c index f2a62e581..31e768553 100644 --- a/grub-core/commands/parttool.c +++ b/grub-core/commands/parttool.c @@ -275,7 +275,7 @@ grub_cmd_parttool (grub_command_t cmd __attribute__ ((unused)), if (! parsed[j]) { for (curarg = ptool->args; curarg->name; curarg++) - if (grub_strncmp (curarg->name, args[i], + if (grub_strncmp (curarg->name, args[j], grub_strlen (curarg->name)) == 0 && ((curarg->type == GRUB_PARTTOOL_ARG_BOOL && (args[j][grub_strlen (curarg->name)] == '+' From cb731b5e81d006e367414a592f7ca7b2ccddadd4 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 16 Sep 2010 00:27:06 +0200 Subject: [PATCH 199/214] * util/grub-setup.c (setup): Fix incorrect container semantics. --- ChangeLog | 4 ++++ util/grub-setup.c | 10 +++------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0b3d7627c..0696c38b3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2010-09-15 Vladimir Serbinenko + + * util/grub-setup.c (setup): Fix incorrect container semantics. + 2010-09-15 Vladimir Serbinenko * grub-core/commands/parttool.c (grub_cmd_parttool): Fix a variable diff --git a/util/grub-setup.c b/util/grub-setup.c index c9ab5cfdb..1bf0d958d 100644 --- a/util/grub-setup.c +++ b/util/grub-setup.c @@ -333,7 +333,7 @@ setup (const char *dir, #ifdef GRUB_MACHINE_PCBIOS { grub_partition_map_t dest_partmap = NULL; - grub_partition_map_t container = dest_dev->disk->partition; + grub_partition_t container = dest_dev->disk->partition; int multiple_partmaps = 0; grub_err_t err; grub_disk_addr_t sectors[core_sectors]; @@ -454,11 +454,6 @@ setup (const char *dir, : GRUB_DISK_SECTOR_SIZE, core_img + i * GRUB_DISK_SECTOR_SIZE); - /* Write the boot image onto the disk. */ - if (grub_disk_write (dest_dev->disk, 0, 0, GRUB_DISK_SECTOR_SIZE, - boot_img)) - grub_util_error ("%s", grub_errmsg); - goto finish; } #endif @@ -630,12 +625,13 @@ unable_to_embed: grub_util_write_image (core_img, GRUB_DISK_SECTOR_SIZE * 2, fp); fclose (fp); + finish: + /* Write the boot image onto the disk. */ if (grub_disk_write (dest_dev->disk, BOOT_SECTOR, 0, GRUB_DISK_SECTOR_SIZE, boot_img)) grub_util_error ("%s", grub_errmsg); - finish: /* Sync is a Good Thing. */ sync (); From be458ae2643316ffb4df4b07028df0d9d5e99b8b Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Thu, 16 Sep 2010 14:09:37 +0100 Subject: [PATCH 200/214] * .bzrignore: Add *.1, *.8, grub-shell, grub-shell-tester, libgrub_a_init.c, and util/bash-completion.d/grub. --- .bzrignore | 6 ++++++ ChangeLog | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/.bzrignore b/.bzrignore index 411daae47..b5c9df6f2 100644 --- a/.bzrignore +++ b/.bzrignore @@ -4,6 +4,8 @@ 30_os-prober 40_custom 41_custom +*.1 +*.8 aclocal.m4 ascii.bitmaps ascii.h @@ -57,11 +59,14 @@ grub-set-default grub-setup grub_setup_init.c grub_setup_init.h +grub-shell +grub-shell-tester *.img include/grub/cpu include/grub/machine install-sh lib/libgcrypt-grub +libgrub_a_init.c *.lst Makefile *.mod @@ -98,3 +103,4 @@ grub-core/Makefile.gcry.am grub-core/Makefile.gcry.def grub-core/*.module grub-core/*.pp +util/bash-completion.d/grub diff --git a/ChangeLog b/ChangeLog index 0696c38b3..5cfe2fa9f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2010-09-16 Colin Watson + + * .bzrignore: Add *.1, *.8, grub-shell, grub-shell-tester, + libgrub_a_init.c, and util/bash-completion.d/grub. + 2010-09-15 Vladimir Serbinenko * util/grub-setup.c (setup): Fix incorrect container semantics. From e5bfc130a4e32a73120e017593b4259b1c3c0a30 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Thu, 16 Sep 2010 14:13:48 +0100 Subject: [PATCH 201/214] * docs/grub.texi (serial): Remove obsolete comment about GRUB needing to be compiled with serial support. (ls): Indicate that multiple files are accepted. * grub-core/commands/ls.c (GRUB_MOD_INIT): Update help text to indicate that multiple files are accepted. --- ChangeLog | 8 ++++++++ docs/grub.texi | 5 ++--- grub-core/commands/ls.c | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5cfe2fa9f..648d60f47 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2010-09-16 Colin Watson + + * docs/grub.texi (serial): Remove obsolete comment about GRUB + needing to be compiled with serial support. + (ls): Indicate that multiple files are accepted. + * grub-core/commands/ls.c (GRUB_MOD_INIT): Update help text to + indicate that multiple files are accepted. + 2010-09-16 Colin Watson * .bzrignore: Add *.1, *.8, grub-shell, grub-shell-tester, diff --git a/docs/grub.texi b/docs/grub.texi index af6d42ccb..076adfd6c 100644 --- a/docs/grub.texi +++ b/docs/grub.texi @@ -2415,8 +2415,7 @@ The serial port is not used as a communication channel unless the @command{terminal_input} or @command{terminal_output} command is used (@pxref{terminal_input}, @pxref{terminal_output}). -This command is only available if GRUB is compiled with serial -support. See also @ref{Serial terminal}. +See also @ref{Serial terminal}. @end deffn @@ -2907,7 +2906,7 @@ This command is only available on x86 systems. @node ls @subsection ls -@deffn Command ls [arg] +@deffn Command ls [arg @dots{}] List devices or files. With no arguments, print all devices known to GRUB. diff --git a/grub-core/commands/ls.c b/grub-core/commands/ls.c index 3bd6607be..481d17db0 100644 --- a/grub-core/commands/ls.c +++ b/grub-core/commands/ls.c @@ -270,7 +270,7 @@ static grub_extcmd_t cmd; GRUB_MOD_INIT(ls) { cmd = grub_register_extcmd ("ls", grub_cmd_ls, 0, - N_("[-l|-h|-a] [FILE]"), + N_("[-l|-h|-a] [FILE ...]"), N_("List devices and files."), options); } From c514c29712e89b5ef7a3423787820ddeb9a80154 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Thu, 16 Sep 2010 14:50:41 +0100 Subject: [PATCH 202/214] Explicitly pass -d ${pkglibdir} to grub-mkimage, to make it easier to run grub-install from the build directory. --- util/grub-install.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/util/grub-install.in b/util/grub-install.in index 0ef4cfe84..955bf0257 100644 --- a/util/grub-install.in +++ b/util/grub-install.in @@ -552,7 +552,7 @@ case "${target_cpu}-${platform}" in esac -$grub_mkimage ${config_opt} -O ${mkimage_target} --output=${grubdir}/core.${imgext} --prefix=${prefix_drive}${relative_grubdir} $modules || exit 1 +$grub_mkimage ${config_opt} -d ${pkglibdir} -O ${mkimage_target} --output=${grubdir}/core.${imgext} --prefix=${prefix_drive}${relative_grubdir} $modules || exit 1 # Backward-compatibility kludges if [ "${target_cpu}-${platform}" = "mips-yeeloong" ]; then @@ -560,7 +560,7 @@ if [ "${target_cpu}-${platform}" = "mips-yeeloong" ]; then elif [ "${target_cpu}-${platform}" = "i386-ieee1275" ] || [ "${target_cpu}-${platform}" = "powerpc-ieee1275" ]; then cp ${grubdir}/core.${imgext} /boot/grub/grub elif [ "${target_cpu}-${platform}" = "i386-efi" ] || [ "${target_cpu}-${platform}" = "x86_64-efi" ]; then - $grub_mkimage ${config_opt} -O ${mkimage_target} --output=${grubdir}/grub.efi --prefix="" $modules || exit 1 + $grub_mkimage ${config_opt} -d ${pkglibdir} -O ${mkimage_target} --output=${grubdir}/grub.efi --prefix="" $modules || exit 1 fi From 108538d8ffd7bd584b305ae51e125523eb8003b6 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Thu, 16 Sep 2010 14:55:28 +0100 Subject: [PATCH 203/214] Support RAID on virtio devices, and others. * grub-core/kern/emu/getroot.c [__MINGW32__] (find_root_device): Rename to ... [__MINGW32__] (grub_find_device): ... this. [! __MINGW32__ && ! __CYGWIN__] (find_root_device): Rename to ... [! __MINGW32__ && ! __CYGWIN__] (grub_find_device): ... this. Use a reasonable default if dir is NULL. [! __MINGW32__ && __CYGWIN__] (find_cygwin_root_device): Rename to ... [! __MINGW32__ && __CYGWIN__] (grub_find_device): ... this. (grub_guess_root_device): Update callers. * include/grub/emu/getroot.h (grub_find_device): Add prototype. * util/raid.c (grub_util_getdiskname): Remove. (grub_util_raid_getmembers): Use grub_find_device rather than grub_util_getdiskname. --- ChangeLog | 20 ++++++++++++++++++++ grub-core/kern/emu/getroot.c | 29 +++++++++++++++++++---------- include/grub/emu/getroot.h | 3 +++ util/raid.c | 28 ++++------------------------ 4 files changed, 46 insertions(+), 34 deletions(-) diff --git a/ChangeLog b/ChangeLog index 648d60f47..050b74a3f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2010-09-16 Colin Watson + + Support RAID on virtio devices, and others. + + * grub-core/kern/emu/getroot.c [__MINGW32__] (find_root_device): + Rename to ... + [__MINGW32__] (grub_find_device): ... this. + [! __MINGW32__ && ! __CYGWIN__] (find_root_device): Rename to ... + [! __MINGW32__ && ! __CYGWIN__] (grub_find_device): ... this. Use a + reasonable default if dir is NULL. + [! __MINGW32__ && __CYGWIN__] (find_cygwin_root_device): Rename to + ... + [! __MINGW32__ && __CYGWIN__] (grub_find_device): ... this. + (grub_guess_root_device): Update callers. + * include/grub/emu/getroot.h (grub_find_device): Add prototype. + + * util/raid.c (grub_util_getdiskname): Remove. + (grub_util_raid_getmembers): Use grub_find_device rather than + grub_util_getdiskname. + 2010-09-16 Colin Watson * docs/grub.texi (serial): Remove obsolete comment about GRUB diff --git a/grub-core/kern/emu/getroot.c b/grub-core/kern/emu/getroot.c index 32dcb49ca..003fe9333 100644 --- a/grub-core/kern/emu/getroot.c +++ b/grub-core/kern/emu/getroot.c @@ -228,8 +228,8 @@ find_root_device_from_libzfs (const char *dir) #ifdef __MINGW32__ -static char * -find_root_device (const char *dir __attribute__ ((unused)), +char * +grub_find_device (const char *dir __attribute__ ((unused)), dev_t dev __attribute__ ((unused))) { return 0; @@ -237,13 +237,22 @@ find_root_device (const char *dir __attribute__ ((unused)), #elif ! defined(__CYGWIN__) -static char * -find_root_device (const char *dir, dev_t dev) +char * +grub_find_device (const char *dir, dev_t dev) { DIR *dp; char *saved_cwd; struct dirent *ent; + if (! dir) + { +#ifdef __CYGWIN__ + return NULL; +#else + dir = "/dev"; +#endif + } + dp = opendir (dir); if (! dp) return 0; @@ -292,7 +301,7 @@ find_root_device (const char *dir, dev_t dev) /* Find it recursively. */ char *res; - res = find_root_device (ent->d_name, dev); + res = grub_find_device (ent->d_name, dev); if (res) { @@ -402,8 +411,8 @@ get_bootsec_serial (const char *os_dev, int mbr) return serial; } -static char * -find_cygwin_root_device (const char *path, dev_t dev) +char * +grub_find_device (const char *path, dev_t dev) { /* No root device for /cygdrive. */ if (dev == (DEV_CYGDRIVE_MAJOR << 16)) @@ -424,7 +433,7 @@ find_cygwin_root_device (const char *path, dev_t dev) /* Cygwin returns the partition serial number in stat.st_dev. This is never identical to the device number of the emulated - /dev/sdXN device, so above find_root_device () does not work. + /dev/sdXN device, so above grub_find_device () does not work. Search the partition with the same serial in boot sector instead. */ char devpath[sizeof ("/dev/sda15") + 13]; /* Size + Paranoia. */ int d; @@ -529,12 +538,12 @@ grub_guess_root_device (const char *dir) #ifdef __CYGWIN__ /* Cygwin specific function. */ - os_dev = find_cygwin_root_device (dir, st.st_dev); + os_dev = grub_find_device (dir, st.st_dev); #else /* This might be truly slow, but is there any better way? */ - os_dev = find_root_device ("/dev", st.st_dev); + os_dev = grub_find_device ("/dev", st.st_dev); #endif #endif /* !__GNU__ */ diff --git a/include/grub/emu/getroot.h b/include/grub/emu/getroot.h index 04a2805c8..581ea8056 100644 --- a/include/grub/emu/getroot.h +++ b/include/grub/emu/getroot.h @@ -19,12 +19,15 @@ #ifndef GRUB_UTIL_GETROOT_HEADER #define GRUB_UTIL_GETROOT_HEADER 1 +#include + enum grub_dev_abstraction_types { GRUB_DEV_ABSTRACTION_NONE, GRUB_DEV_ABSTRACTION_LVM, GRUB_DEV_ABSTRACTION_RAID, }; +char *grub_find_device (const char *dir, dev_t dev); char *grub_guess_root_device (const char *dir); int grub_util_get_dev_abstraction (const char *os_dev); char *grub_util_get_grub_dev (const char *os_dev); diff --git a/util/raid.c b/util/raid.c index edf865aa7..dac19a935 100644 --- a/util/raid.c +++ b/util/raid.c @@ -22,40 +22,19 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include #include -static char * -grub_util_getdiskname (int major, int minor) -{ - char *name = xmalloc (15); - - if (major == LOOP_MAJOR) - sprintf (name, "/dev/loop%d", minor); - else if (major == IDE0_MAJOR) - sprintf (name, "/dev/hd%c", 'a' + minor / 64); - else if (major == IDE1_MAJOR) - sprintf (name, "/dev/hd%c", 'c' + minor / 64); - else if (major == IDE2_MAJOR) - sprintf (name, "/dev/hd%c", 'e' + minor / 64); - else if (major == IDE3_MAJOR) - sprintf (name, "/dev/hd%c", 'g' + minor / 64); - else if (major == SCSI_DISK0_MAJOR) - sprintf (name, "/dev/sd%c", 'a' + minor / 16); - else - grub_util_error ("unknown device number: %d, %d", major, minor); - - return name; -} - char ** grub_util_raid_getmembers (char *name) { @@ -100,7 +79,8 @@ grub_util_raid_getmembers (char *name) if (disk.state & (1 << MD_DISK_ACTIVE)) { - devicelist[j] = grub_util_getdiskname (disk.major, disk.minor); + devicelist[j] = grub_find_device (NULL, + makedev (disk.major, disk.minor)); j++; } } From 10854d0d79ce5bf62f623f51ee9bb041031b21ba Mon Sep 17 00:00:00 2001 From: Yves Blusseau Date: Thu, 16 Sep 2010 17:07:42 +0200 Subject: [PATCH 204/214] * configure.ac: Avoid some annoying error messages if freetype-config program is not found. --- ChangeLog | 5 +++++ configure.ac | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index 050b74a3f..2d204338e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2010-09-16 Yves Blusseau + + * configure.ac: Avoid some annoying error messages if freetype-config + program is not found. + 2010-09-16 Colin Watson Support RAID on virtio devices, and others. diff --git a/configure.ac b/configure.ac index 10723987b..57df640b8 100644 --- a/configure.ac +++ b/configure.ac @@ -796,12 +796,12 @@ if test x"$grub_mkfont_excuse" = x ; then if test "x$FREETYPE" = x ; then grub_mkfont_excuse=["need freetype2 library"] fi - freetype_cflags=`freetype-config --cflags` - freetype_libs=`freetype-config --libs` fi if test x"$grub_mkfont_excuse" = x ; then # Check for freetype libraries. + freetype_cflags=`freetype-config --cflags` + freetype_libs=`freetype-config --libs` SAVED_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $freetype_cflags" AC_CHECK_HEADERS([ft2build.h], [], From 0f7ee3c969360f031f98c00305f0c345fa576645 Mon Sep 17 00:00:00 2001 From: Yves Blusseau Date: Fri, 17 Sep 2010 11:56:04 +0200 Subject: [PATCH 205/214] * .bzrignore: *.d removed (old rule), add *.image and symlist.h. --- .bzrignore | 3 ++- ChangeLog | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.bzrignore b/.bzrignore index b5c9df6f2..5c121e652 100644 --- a/.bzrignore +++ b/.bzrignore @@ -20,7 +20,6 @@ config.log config.status config.sub configure -*.d DISTLIST docs/*.info docs/stamp-vti @@ -62,6 +61,7 @@ grub_setup_init.h grub-shell grub-shell-tester *.img +*.image include/grub/cpu include/grub/machine install-sh @@ -80,6 +80,7 @@ stamp-h stamp-h1 stamp-h.in symlist.c +symlist.h trigtables.c update-grub_lib unidata.c diff --git a/ChangeLog b/ChangeLog index 2d204338e..885ae3be8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2010-09-17 Yves Blusseau + + * .bzrignore: *.d removed (old rule), add *.image and symlist.h. + 2010-09-16 Yves Blusseau * configure.ac: Avoid some annoying error messages if freetype-config From a939d135ec53026a4f0b15f00962a4e3a8908b7a Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 17 Sep 2010 11:00:37 +0100 Subject: [PATCH 206/214] Fix DM-RAID probing with recent versions of device-mapper udev rules. * grub-core/kern/emu/hostdisk.c (read_device_map): Don't canonicalise device paths under /dev/mapper/. (convert_system_partition_to_system_disk): Compare the uncanonicalised path to /dev/mapper/ rather than the canonicalised path, since device nodes under /dev/mapper/ are often symlinks. --- ChangeLog | 11 +++++++++++ grub-core/kern/emu/hostdisk.c | 21 +++++++++++++-------- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 885ae3be8..7f5ba2d44 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2010-09-17 Colin Watson + + Fix DM-RAID probing with recent versions of device-mapper udev + rules. + + * grub-core/kern/emu/hostdisk.c (read_device_map): Don't + canonicalise device paths under /dev/mapper/. + (convert_system_partition_to_system_disk): Compare the + uncanonicalised path to /dev/mapper/ rather than the canonicalised + path, since device nodes under /dev/mapper/ are often symlinks. + 2010-09-17 Yves Blusseau * .bzrignore: *.d removed (old rule), add *.image and symlist.h. diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index edf8dc219..69c5ed921 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -955,13 +955,16 @@ read_device_map (const char *dev_map) #ifdef __linux__ /* On Linux, the devfs uses symbolic links horribly, and that confuses the interface very much, so use realpath to expand - symbolic links. */ - map[drive].device = xmalloc (PATH_MAX); - if (! realpath (p, map[drive].device)) - grub_util_error ("cannot get the real path of `%s'", p); -#else - map[drive].device = xstrdup (p); + symbolic links. Leave /dev/mapper/ alone, though. */ + if (strncmp (p, "/dev/mapper/", 12) != 0) + { + map[drive].device = xmalloc (PATH_MAX); + if (! realpath (p, map[drive].device)) + grub_util_error ("cannot get the real path of `%s'", p); + } + else #endif + map[drive].device = xstrdup (p); } fclose (fp); @@ -1153,8 +1156,10 @@ convert_system_partition_to_system_disk (const char *os_dev, struct stat *st) } #ifdef HAVE_DEVICE_MAPPER - /* If this is a DM-RAID device. */ - if ((strncmp ("mapper/", p, 7) == 0)) + /* If this is a DM-RAID device. + Compare os_dev rather than path here, since nodes under + /dev/mapper/ are often symlinks. */ + if ((strncmp ("/dev/mapper/", os_dev, 12) == 0)) { static struct dm_tree *tree = NULL; uint32_t maj, min; From 9c0bad2e15331cc4035e022571cec2e004842083 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 17 Sep 2010 11:43:46 +0100 Subject: [PATCH 207/214] * grub-core/kern/emu/hostdisk.c (convert_system_partition_to_system_disk): Fix devmapper memory pool leak. Reported and based on patch by: Modestas Vainius. --- ChangeLog | 7 +++++++ grub-core/kern/emu/hostdisk.c | 36 ++++++++++++++++++----------------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7f5ba2d44..9638bc633 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2010-09-17 Colin Watson + + * grub-core/kern/emu/hostdisk.c + (convert_system_partition_to_system_disk): Fix devmapper memory pool + leak. + Reported and based on patch by: Modestas Vainius. + 2010-09-17 Colin Watson Fix DM-RAID probing with recent versions of device-mapper udev diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index 69c5ed921..a9b94e212 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -1161,19 +1161,17 @@ convert_system_partition_to_system_disk (const char *os_dev, struct stat *st) /dev/mapper/ are often symlinks. */ if ((strncmp ("/dev/mapper/", os_dev, 12) == 0)) { - static struct dm_tree *tree = NULL; + struct dm_tree *tree; uint32_t maj, min; struct dm_tree_node *node, *child; void *handle; - const char *node_uuid, *mapper_name, *child_uuid, *child_name; - - if (! tree) - tree = dm_tree_create (); + const char *node_uuid, *mapper_name = NULL, *child_uuid, *child_name; + tree = dm_tree_create (); if (! tree) { grub_dprintf ("hostdisk", "dm_tree_create failed\n"); - return NULL; + goto devmapper_out; } maj = major (st->st_rdev); @@ -1181,29 +1179,30 @@ convert_system_partition_to_system_disk (const char *os_dev, struct stat *st) if (! dm_tree_add_dev (tree, maj, min)) { grub_dprintf ("hostdisk", "dm_tree_add_dev failed\n"); - return NULL; + goto devmapper_out; } node = dm_tree_find_node (tree, maj, min); if (! node) { grub_dprintf ("hostdisk", "dm_tree_find_node failed\n"); - return NULL; + goto devmapper_out; } node_uuid = dm_tree_node_get_uuid (node); if (! node_uuid) { grub_dprintf ("hostdisk", "%s has no DM uuid\n", path); - return NULL; + node = NULL; + goto devmapper_out; } else if (strncmp (node_uuid, "DMRAID-", 7) != 0) { grub_dprintf ("hostdisk", "%s is not DM-RAID\n", path); - return NULL; + node = NULL; + goto devmapper_out; } handle = NULL; - mapper_name = NULL; /* Counter-intuitively, device-mapper refers to the disk-like device containing a DM-RAID partition device as a "child" of the partition device. */ @@ -1233,17 +1232,20 @@ convert_system_partition_to_system_disk (const char *os_dev, struct stat *st) mapper_name = child_name; devmapper_out: - if (! mapper_name) + if (! mapper_name && node) { /* This is a DM-RAID disk, not a partition. */ mapper_name = dm_tree_node_get_name (node); if (! mapper_name) - { - grub_dprintf ("hostdisk", "%s has no DM name\n", path); - return NULL; - } + grub_dprintf ("hostdisk", "%s has no DM name\n", path); } - return xasprintf ("/dev/mapper/%s", mapper_name); + if (tree) + dm_tree_free (tree); + free (path); + if (mapper_name) + return xasprintf ("/dev/mapper/%s", mapper_name); + else + return NULL; } #endif /* HAVE_DEVICE_MAPPER */ } From bf8d13388dfa31b8961280b027365ce062beafc6 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 17 Sep 2010 23:41:06 +0100 Subject: [PATCH 208/214] (convert_system_partition_to_system_disk): Initialise node. * grub-core/kern/emu/hostdisk.c --- ChangeLog | 5 +++++ grub-core/kern/emu/hostdisk.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 9638bc633..d34dbd201 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2010-09-17 Colin Watson + + * grub-core/kern/emu/hostdisk.c + (convert_system_partition_to_system_disk): Initialise node. + 2010-09-17 Colin Watson * grub-core/kern/emu/hostdisk.c diff --git a/grub-core/kern/emu/hostdisk.c b/grub-core/kern/emu/hostdisk.c index a9b94e212..7d9d1dac1 100644 --- a/grub-core/kern/emu/hostdisk.c +++ b/grub-core/kern/emu/hostdisk.c @@ -1163,7 +1163,7 @@ convert_system_partition_to_system_disk (const char *os_dev, struct stat *st) { struct dm_tree *tree; uint32_t maj, min; - struct dm_tree_node *node, *child; + struct dm_tree_node *node = NULL, *child; void *handle; const char *node_uuid, *mapper_name = NULL, *child_uuid, *child_name; From b9c7e9d400b7473006b988a08e19d6bfe76bb795 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1=20Nesrsta?= Date: Sat, 18 Sep 2010 10:56:52 +0200 Subject: [PATCH 209/214] Set UHCI low-speed flag --- grub-core/bus/usb/uhci.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/grub-core/bus/usb/uhci.c b/grub-core/bus/usb/uhci.c index 755ec70f7..d51aace8c 100644 --- a/grub-core/bus/usb/uhci.c +++ b/grub-core/bus/usb/uhci.c @@ -414,7 +414,7 @@ static grub_uhci_td_t grub_uhci_transaction (struct grub_uhci *u, unsigned int endp, grub_transfer_type_t type, unsigned int addr, unsigned int toggle, grub_size_t size, - grub_uint32_t data) + grub_uint32_t data, grub_usb_speed_t speed) { grub_uhci_td_t td; static const unsigned int tf[] = { 0x69, 0xE1, 0x2D }; @@ -439,7 +439,8 @@ grub_uhci_transaction (struct grub_uhci *u, unsigned int endp, td->linkptr = 1; /* Active! Only retry a transfer 3 times. */ - td->ctrl_status = (1 << 23) | (3 << 27); + td->ctrl_status = (1 << 23) | (3 << 27) | + ((speed == GRUB_USB_SPEED_LOW) ? (1 << 26) : 0); /* If zero bytes are transmitted, size is 0x7FF. Otherwise size is size-1. */ @@ -495,7 +496,8 @@ grub_uhci_setup_transfer (grub_usb_controller_t dev, td = grub_uhci_transaction (u, transfer->endpoint & 15, tr->pid, transfer->devaddr, tr->toggle, - tr->size, tr->data); + tr->size, tr->data, + transfer->dev->speed); if (! td) { grub_size_t actual = 0; From e70a1b9535ee1af0c84cab327e006948973d463d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1=20Nesrsta?= Date: Sat, 18 Sep 2010 13:49:15 +0200 Subject: [PATCH 210/214] Fix multiple USB issues --- grub-core/bus/usb/ohci.c | 194 ++++++++++++----------------------- grub-core/bus/usb/uhci.c | 48 +++++---- grub-core/bus/usb/usb.c | 2 +- grub-core/bus/usb/usbhub.c | 104 ++++++++++++++++--- grub-core/bus/usb/usbtrans.c | 4 +- include/grub/usb.h | 3 + 6 files changed, 195 insertions(+), 160 deletions(-) diff --git a/grub-core/bus/usb/ohci.c b/grub-core/bus/usb/ohci.c index 7c618a614..b07e30403 100644 --- a/grub-core/bus/usb/ohci.c +++ b/grub-core/bus/usb/ohci.c @@ -98,7 +98,6 @@ struct grub_ohci struct grub_pci_dma_chunk *td_chunk; struct grub_ohci *next; grub_ohci_td_t td_free; /* Pointer to first free TD */ - int bad_OHCI; }; static struct grub_ohci *ohci; @@ -149,8 +148,8 @@ typedef enum #define GRUB_OHCI_REG_CONTROL_CONTROL_ENABLE (1 << 4) #define GRUB_OHCI_RESET_CONNECT_CHANGE (1 << 16) -#define GRUB_OHCI_CTRL_EDS 16 -#define GRUB_OHCI_BULK_EDS 16 +#define GRUB_OHCI_CTRL_EDS 256 +#define GRUB_OHCI_BULK_EDS 510 #define GRUB_OHCI_TDS 256 #define GRUB_OHCI_ED_ADDR_MASK 0x7ff @@ -442,8 +441,10 @@ grub_ohci_pci_iter (grub_pci_device_t dev, (grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBA) & ~GRUB_OHCI_RHUB_PORT_POWER_MASK) | GRUB_OHCI_RHUB_PORT_ALL_POWERED); +#if 0 /* We don't need it at all, handled via hotplugging */ /* Now we have hot-plugging, we need to wait for stable power only */ grub_millisleep (100); +#endif /* Link to ohci now that initialisation is successful. */ o->next = ohci; @@ -623,7 +624,8 @@ grub_ohci_transaction (grub_ohci_td_t td, break; } - /* Set the token (Always generate interrupt - bits 21-23 = 0). */ + /* Set the token */ + token |= ( 7 << 21); /* Never generate interrupt */ token |= toggle << 24; token |= 1 << 25; @@ -659,7 +661,6 @@ struct grub_ohci_transfer_controller_data grub_ohci_ed_t ed_virt; grub_ohci_td_t td_current_virt; grub_ohci_td_t td_head_virt; - grub_uint64_t bad_OHCI_delay; }; static grub_usb_err_t @@ -756,10 +757,6 @@ grub_ohci_setup_transfer (grub_usb_controller_t dev, /* Set index of TD in transfer */ cdata->td_current_virt->tr_index = (grub_uint32_t) i; - - /* No IRQ request in TD if bad_OHCI set */ - if (o->bad_OHCI) - cdata->td_current_virt->token |= grub_cpu_to_le32 ( 7 << 21); /* Remember last used (processed) TD phys. addr. */ cdata->td_last_phys = grub_ohci_td_virt2phys (o, cdata->td_current_virt); @@ -891,8 +888,8 @@ pre_finish_transfer (grub_usb_controller_t dev, /* Now print debug values - to have full info what happened */ grub_dprintf ("ohci", "loop finished: control=0x%02x status=0x%02x\n", control, status); - grub_dprintf ("ohci", "intstatus=0x%02x \n\t\t tderr_phys=0x%02x, td_last_phys=0x%02x\n", - intstatus, cdata->tderr_phys, cdata->td_last_phys); + grub_dprintf ("ohci", "intstatus=0x%02x, td_last_phys=0x%02x\n", + intstatus, cdata->td_last_phys); grub_dprintf ("ohci", "TARGET=0x%02x, HEAD=0x%02x, TAIL=0x%02x\n", target, grub_le_to_cpu32 (cdata->ed_virt->td_head), @@ -915,12 +912,6 @@ finish_transfer (grub_usb_controller_t dev, * i.e. it is safe to free all TDs except last not processed * ED HEAD == TAIL == phys. addr. of td_current_virt */ - /* Reset DoneHead - sanity cleanup */ - o->hcca->donehead = 0; - grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1)); - /* Read back of register should ensure it is really written */ - grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); - /* Un-chainig of last TD */ if (cdata->td_current_virt->prev_td_phys) { @@ -929,10 +920,13 @@ finish_transfer (grub_usb_controller_t dev, if (cdata->td_current_virt == (grub_ohci_td_t) td_prev_virt->link_td) td_prev_virt->link_td = 0; + + cdata->td_current_virt->prev_td_phys = 0; } grub_dprintf ("ohci", "OHCI finished, freeing\n"); grub_ohci_free_tds (o, cdata->td_head_virt); + grub_free (cdata); } static grub_usb_err_t @@ -951,28 +945,10 @@ parse_halt (grub_usb_controller_t dev, pre_finish_transfer (dev, transfer); /* First we must get proper tderr_phys value */ - if (o->bad_OHCI) /* In case of bad_OHCI tderr_phys can be wrong */ - { - if (cdata->tderr_phys) /* check if tderr_phys points to TD with error */ - errcode = grub_le_to_cpu32 (grub_ohci_td_phys2virt (o, - cdata->tderr_phys)->token) - >> 28; - if ( !cdata->tderr_phys || !errcode ) /* tderr_phys not valid or points to wrong TD */ - { /* Retired TD with error should be previous TD to ED->td_head */ - cdata->tderr_phys = grub_ohci_td_phys2virt (o, - grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xf ) - ->prev_td_phys; - } - } - /* Even if we have "good" OHCI, in some cases - * tderr_phys can be zero, check it */ - else if (!cdata->tderr_phys) - /* Retired TD with error should be previous TD to ED->td_head */ - cdata->tderr_phys - = grub_ohci_td_phys2virt (o, - grub_le_to_cpu32 (cdata->ed_virt->td_head) - & ~0xf)->prev_td_phys; - + /* Retired TD with error should be previous TD to ED->td_head */ + cdata->tderr_phys = grub_ohci_td_phys2virt (o, + grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xf ) + ->prev_td_phys; /* Prepare pointer to last processed TD and get error code */ tderr_virt = grub_ohci_td_phys2virt (o, cdata->tderr_phys); @@ -1090,16 +1066,12 @@ parse_success (grub_usb_controller_t dev, pre_finish_transfer (dev, transfer); - /* Simple workaround if donehead is not working */ - if (o->bad_OHCI && - (!cdata->tderr_phys || (cdata->tderr_phys != cdata->td_last_phys))) - { - grub_dprintf ("ohci", "normal finish, but tderr_phys corrected\n"); - cdata->tderr_phys = cdata->td_last_phys; - /* I hope we can do it as transfer (most probably) finished OK */ - } + /* I hope we can do it as transfer (most probably) finished OK */ + cdata->tderr_phys = cdata->td_last_phys; + /* Prepare pointer to last processed TD */ tderr_virt = grub_ohci_td_phys2virt (o, cdata->tderr_phys); + /* Set index of last processed TD */ if (tderr_virt) transfer->last_trans = tderr_virt->tr_index; @@ -1168,25 +1140,6 @@ grub_ohci_check_transfer (grub_usb_controller_t dev, /* Check transfer status */ intstatus = grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); - if (!o->bad_OHCI && (intstatus & 0x2) != 0) - { - /* Remember last successful TD */ - cdata->tderr_phys = grub_le_to_cpu32 (o->hcca->donehead) & ~0xf; - /* Reset DoneHead */ - o->hcca->donehead = 0; - grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1)); - /* Read back of register should ensure it is really written */ - grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); - /* if TD is last, finish */ - if (cdata->tderr_phys == cdata->td_last_phys) - { - if (grub_le_to_cpu32 (cdata->ed_virt->td_head) & 1) - return parse_halt (dev, transfer, actual); - else - return parse_success (dev, transfer, actual); - } - return GRUB_USB_ERR_WAIT; - } if ((intstatus & 0x10) != 0) /* Unrecoverable error - only reset can help...! */ @@ -1194,54 +1147,20 @@ grub_ohci_check_transfer (grub_usb_controller_t dev, /* Detected a HALT. */ if ((grub_le_to_cpu32 (cdata->ed_virt->td_head) & 1)) - { - /* ED is halted, but donehead event can happened in the meantime */ - intstatus = grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); - if (!o->bad_OHCI && (intstatus & 0x2) != 0) - { - /* Remember last successful TD */ - cdata->tderr_phys = grub_le_to_cpu32 (o->hcca->donehead) & ~0xf; - /* Reset DoneHead */ - o->hcca->donehead = 0; - grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1)); - /* Read back of register should ensure it is really written */ - grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); - /* if TD is last, finish */ - } - return parse_halt (dev, transfer, actual); - } + return parse_halt (dev, transfer, actual); - /* bad OHCI handling */ + /* Finished ED detection */ if ( (grub_le_to_cpu32 (cdata->ed_virt->td_head) & ~0xf) == (grub_le_to_cpu32 (cdata->ed_virt->td_tail) & ~0xf) ) /* Empty ED */ { - if (o->bad_OHCI) /* Bad OHCI detected previously */ - { - /* Try get last successful TD. */ - cdata->tderr_phys = grub_le_to_cpu32 (o->hcca->donehead) & ~0xf; - if (cdata->tderr_phys)/* Reset DoneHead if we were successful */ - { - o->hcca->donehead = 0; - grub_ohci_writereg32 (o, GRUB_OHCI_REG_INTSTATUS, (1 << 1)); - /* Read back of register should ensure it is really written */ - grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS); - } - /* Check the HALT bit */ - if (grub_le_to_cpu32 (cdata->ed_virt->td_head) & 1) - return parse_halt (dev, transfer, actual); - else - return parse_success (dev, transfer, actual); - } - else /* Detection of bad OHCI */ - /* We should wait short time (~2ms) before we say that - * it is bad OHCI to prevent some hazard - - * donehead can react in the meantime. This waiting is done - * only once per OHCI driver "live cycle". */ - if (!cdata->bad_OHCI_delay) /* Set delay time */ - cdata->bad_OHCI_delay = grub_get_time_ms () + 2; - else if (grub_get_time_ms () >= cdata->bad_OHCI_delay) - o->bad_OHCI = 1; - return GRUB_USB_ERR_WAIT; + /* Check the HALT bit */ + /* It looks like nonsense - it was tested previously... + * but it can change because OHCI is working + * simultaneously via DMA... */ + if (grub_le_to_cpu32 (cdata->ed_virt->td_head) & 1) + return parse_halt (dev, transfer, actual); + else + return parse_success (dev, transfer, actual); } return GRUB_USB_ERR_WAIT; @@ -1266,14 +1185,16 @@ grub_ohci_cancel_transfer (grub_usb_controller_t dev, /* Wait for new SOF */ while ((grub_ohci_readreg32 (o, GRUB_OHCI_REG_INTSTATUS) & 0x4) == 0); - /* Now we must find last processed TD if bad_OHCI == TRUE */ - if (o->bad_OHCI) - /* Retired TD with error should be previous TD to ED->td_head */ - cdata->tderr_phys - = grub_ohci_td_phys2virt (o, grub_le_to_cpu32 (cdata->ed_virt->td_head) - & ~0xf)->prev_td_phys; + /* Possible retired TD with error should be previous TD to ED->td_head */ + cdata->tderr_phys + = grub_ohci_td_phys2virt (o, grub_le_to_cpu32 (cdata->ed_virt->td_head) + & ~0xf)->prev_td_phys; tderr_virt = grub_ohci_td_phys2virt (o,cdata-> tderr_phys); + + grub_dprintf ("ohci", "Cancel: tderr_phys=0x%08x, tderr_virt=0x%08x\n", + cdata->tderr_phys, (unsigned int)tderr_virt); + if (tderr_virt) transfer->last_trans = tderr_virt->tr_index; else @@ -1290,6 +1211,7 @@ grub_ohci_portstatus (grub_usb_controller_t dev, { struct grub_ohci *o = (struct grub_ohci *) dev->data; grub_uint64_t endtime; + int i; grub_dprintf ("ohci", "begin of portstatus=0x%02x\n", grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port)); @@ -1310,31 +1232,47 @@ grub_ohci_portstatus (grub_usb_controller_t dev, return GRUB_ERR_NONE; } - /* Reset the port */ - grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, - GRUB_OHCI_SET_PORT_RESET); - grub_millisleep (50); /* For root hub should be nominaly 50ms */ - - /* End the reset signaling. */ - grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, - GRUB_OHCI_SET_PORT_RESET_STATUS_CHANGE); - grub_millisleep (10); + /* OHCI does one reset signal 10ms long but USB spec. + * requests 50ms for root hub (no need to be continuous). + * So, we do reset 5 times... */ + for (i = 0; i < 5; i++) + { + /* Reset the port - timing of reset is done by OHCI */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, + GRUB_OHCI_SET_PORT_RESET); - /* Enable the port and wait for it. */ + /* Wait for reset completion */ + endtime = grub_get_time_ms () + 1000; + while (! (grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port) + & GRUB_OHCI_SET_PORT_RESET_STATUS_CHANGE)) + if (grub_get_time_ms () > endtime) + return grub_error (GRUB_ERR_IO, "OHCI Timed out - reset"); + + /* End the reset signaling - reset the reset status change */ + grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, + GRUB_OHCI_SET_PORT_RESET_STATUS_CHANGE); + grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port); + } + + /* Enable port */ grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, GRUB_OHCI_SET_PORT_ENABLE); + grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port); + + /* Wait for signal enabled */ endtime = grub_get_time_ms () + 1000; while (! (grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port) & (1 << 1))) if (grub_get_time_ms () > endtime) return grub_error (GRUB_ERR_IO, "OHCI Timed out - enable"); - grub_millisleep (10); - /* Reset bit Connect Status Change */ grub_ohci_writereg32 (o, GRUB_OHCI_REG_RHUBPORT + port, GRUB_OHCI_RESET_CONNECT_CHANGE); + /* "Reset recovery time" (USB spec.) */ + grub_millisleep (10); + grub_dprintf ("ohci", "end of portstatus=0x%02x\n", grub_ohci_readreg32 (o, GRUB_OHCI_REG_RHUBPORT + port)); diff --git a/grub-core/bus/usb/uhci.c b/grub-core/bus/usb/uhci.c index d51aace8c..2265ebed0 100644 --- a/grub-core/bus/usb/uhci.c +++ b/grub-core/bus/usb/uhci.c @@ -50,9 +50,12 @@ enum GRUB_UHCI_REG_PORTSC_SUSPEND = 0x1000, GRUB_UHCI_REG_PORTSC_RW = GRUB_UHCI_REG_PORTSC_PORT_ENABLED | GRUB_UHCI_REG_PORTSC_RESUME | GRUB_UHCI_REG_PORTSC_RESET - | GRUB_UHCI_REG_PORTSC_SUSPEND + | GRUB_UHCI_REG_PORTSC_SUSPEND, + /* These bits should not be written as 1 unless we really need it */ + GRUB_UHCI_PORTSC_RWC = ((1 << 1) | (1 << 3) | (1 << 11) | (3 << 13)) }; +#define /* UHCI Queue Head. */ struct grub_uhci_qh @@ -578,23 +581,23 @@ grub_uhci_check_transfer (grub_usb_controller_t dev, err = GRUB_USB_ERR_STALL; /* Check if an error related to the data buffer occurred. */ - if (errtd->ctrl_status & (1 << 21)) + else if (errtd->ctrl_status & (1 << 21)) err = GRUB_USB_ERR_DATA; /* Check if a babble error occurred. */ - if (errtd->ctrl_status & (1 << 20)) + else if (errtd->ctrl_status & (1 << 20)) err = GRUB_USB_ERR_BABBLE; /* Check if a NAK occurred. */ - if (errtd->ctrl_status & (1 << 19)) + else if (errtd->ctrl_status & (1 << 19)) err = GRUB_USB_ERR_NAK; /* Check if a timeout occurred. */ - if (errtd->ctrl_status & (1 << 18)) + else if (errtd->ctrl_status & (1 << 18)) err = GRUB_USB_ERR_TIMEOUT; /* Check if a bitstuff error occurred. */ - if (errtd->ctrl_status & (1 << 17)) + else if (errtd->ctrl_status & (1 << 17)) err = GRUB_USB_ERR_BITSTUFF; if (err) @@ -685,7 +688,7 @@ grub_uhci_portstatus (grub_usb_controller_t dev, endtime = grub_get_time_ms () + 1000; while ((grub_uhci_readreg16 (u, reg) & (1 << 2))) if (grub_get_time_ms () > endtime) - return grub_error (GRUB_ERR_IO, "UHCI Timed out"); + return grub_error (GRUB_ERR_IO, "UHCI Timed out - disable"); status = grub_uhci_readreg16 (u, reg); grub_dprintf ("uhci", ">3detect=0x%02x\n", status); @@ -693,28 +696,37 @@ grub_uhci_portstatus (grub_usb_controller_t dev, } /* Reset the port. */ - grub_uhci_writereg16 (u, reg, 1 << 9); + status = grub_uhci_readreg16 (u, reg) & ~GRUB_UHCI_PORTSC_RWC; + grub_uhci_writereg16 (u, reg, status | (1 << 9)); + grub_uhci_readreg16 (u, reg); /* Ensure it is writen... */ /* Wait for the reset to complete. XXX: How long exactly? */ grub_millisleep (50); /* For root hub should be nominaly 50ms */ - status = grub_uhci_readreg16 (u, reg); + status = grub_uhci_readreg16 (u, reg) & ~GRUB_UHCI_PORTSC_RWC; grub_uhci_writereg16 (u, reg, status & ~(1 << 9)); - grub_dprintf ("uhci", "reset completed\n"); - grub_millisleep (10); + grub_uhci_readreg16 (u, reg); /* Ensure it is writen... */ + + /* Note: some debug prints were removed because they affected reset/enable timing. */ + + grub_millisleep (1); /* Probably not needed at all or only few microsecs. */ + + /* Reset bits Connect & Enable Status Change */ + status = grub_uhci_readreg16 (u, reg) & ~GRUB_UHCI_PORTSC_RWC; + grub_uhci_writereg16 (u, reg, status | (1 << 3) | GRUB_UHCI_REG_PORTSC_CONNECT_CHANGED); + grub_uhci_readreg16 (u, reg); /* Ensure it is writen... */ /* Enable the port. */ - grub_uhci_writereg16 (u, reg, 1 << 2); - grub_millisleep (10); - - grub_dprintf ("uhci", "waiting for the port to be enabled\n"); + status = grub_uhci_readreg16 (u, reg) & ~GRUB_UHCI_PORTSC_RWC; + grub_uhci_writereg16 (u, reg, status | (1 << 2)); + grub_uhci_readreg16 (u, reg); /* Ensure it is writen... */ endtime = grub_get_time_ms () + 1000; while (! ((status = grub_uhci_readreg16 (u, reg)) & (1 << 2))) if (grub_get_time_ms () > endtime) - return grub_error (GRUB_ERR_IO, "UHCI Timed out"); + return grub_error (GRUB_ERR_IO, "UHCI Timed out - enable"); - /* Reset bit Connect Status Change */ - grub_uhci_writereg16 (u, reg, status | GRUB_UHCI_REG_PORTSC_CONNECT_CHANGED); + /* Reset recovery time */ + grub_millisleep (10); /* Read final port status */ status = grub_uhci_readreg16 (u, reg); diff --git a/grub-core/bus/usb/usb.c b/grub-core/bus/usb/usb.c index 2bd805ef2..e17bf0c9d 100644 --- a/grub-core/bus/usb/usb.c +++ b/grub-core/bus/usb/usb.c @@ -262,7 +262,7 @@ void grub_usb_device_attach (grub_usb_device_t dev) if (dev->config[0].interf[i].attached) continue; - + for (desc = attach_hooks; desc; desc = desc->next) if (interf->class == desc->class && desc->hook (dev, 0, i)) dev->config[0].interf[i].attached = 1; diff --git a/grub-core/bus/usb/usbhub.c b/grub-core/bus/usb/usbhub.c index 0ddba3255..73d233642 100644 --- a/grub-core/bus/usb/usbhub.c +++ b/grub-core/bus/usb/usbhub.c @@ -179,19 +179,45 @@ attach_root_port (struct grub_usb_hub *hub, int portno, { grub_usb_device_t dev; grub_err_t err; + int total, i; + grub_usb_speed_t current_speed = GRUB_USB_SPEED_NONE; + int changed=0; +#if 0 +/* Specification does not say about disabling of port when device + * connected. If disabling is really necessary for some devices, + * delete this #if 0 and related #endif */ /* Disable the port. XXX: Why? */ err = hub->controller->dev->portstatus (hub->controller, portno, 0); if (err) return; +#endif + /* Wait for completion of insertion and stable power (USB spec.) + * Should be at least 100ms, some devices requires more... + * There is also another thing - some devices have worse contacts + * and connected signal is unstable for some time - we should handle + * it - but prevent deadlock in case when device is too faulty... */ + for (total = i = 0; (i < 250) && (total < 2000); i++, total++) + { + grub_millisleep (1); + current_speed = hub->controller->dev->detect_dev + (hub->controller, portno, &changed); + if (current_speed == GRUB_USB_SPEED_NONE) + i = 0; + } + grub_dprintf ("usb", "total=%d\n", total); + if (total >= 2000) + return; /* Enable the port. */ err = hub->controller->dev->portstatus (hub->controller, portno, 1); if (err) return; + hub->controller->dev->pending_reset = grub_get_time_ms () + 5000; /* Enable the port and create a device. */ dev = grub_usb_hub_add_dev (hub->controller, speed); + hub->controller->dev->pending_reset = 0; if (! dev) return; @@ -238,11 +264,14 @@ grub_usb_root_hub (grub_usb_controller_t controller) for (i = 0; i < hub->nports; i++) { grub_usb_speed_t speed; - speed = controller->dev->detect_dev (hub->controller, i, - &changed); + if (!controller->dev->pending_reset) + { + speed = controller->dev->detect_dev (hub->controller, i, + &changed); - if (speed != GRUB_USB_SPEED_NONE) - attach_root_port (hub, i, speed); + if (speed != GRUB_USB_SPEED_NONE) + attach_root_port (hub, i, speed); + } } return GRUB_USB_ERR_NONE; @@ -284,6 +313,7 @@ poll_nonroot_hub (grub_usb_device_t dev) unsigned i; grub_uint8_t changed; grub_size_t actual; + int j, total; if (!dev->hub_transfer) return; @@ -308,6 +338,7 @@ poll_nonroot_hub (grub_usb_device_t dev) for (i = 1; i <= dev->nports; i++) { grub_uint32_t status; + grub_uint32_t current_status = 0; if (!(changed & (1 << i))) continue; @@ -319,7 +350,8 @@ poll_nonroot_hub (grub_usb_device_t dev) GRUB_USB_REQ_GET_STATUS, 0, i, sizeof (status), (char *) &status); - grub_printf ("i = %d, status = %08x\n", i, status); + grub_printf ("dev = 0x%0x, i = %d, status = %08x\n", + (unsigned int) dev, i, status); if (err) continue; @@ -346,7 +378,8 @@ poll_nonroot_hub (grub_usb_device_t dev) GRUB_USB_REQ_CLEAR_FEATURE, GRUB_USB_HUB_FEATURE_C_PORT_OVERCURRENT, i, 0, 0); - if (status & GRUB_USB_HUB_STATUS_C_PORT_CONNECTED) + if (!dev->controller.dev->pending_reset && + (status & GRUB_USB_HUB_STATUS_C_PORT_CONNECTED)) { grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT | GRUB_USB_REQTYPE_CLASS @@ -360,8 +393,36 @@ poll_nonroot_hub (grub_usb_device_t dev) /* Connected and status of connection changed ? */ if (status & GRUB_USB_HUB_STATUS_PORT_CONNECTED) { - /* A device is actually connected to this port. - * Now do reset of port. */ + /* A device is actually connected to this port. */ + /* Wait for completion of insertion and stable power (USB spec.) + * Should be at least 100ms, some devices requires more... + * There is also another thing - some devices have worse contacts + * and connected signal is unstable for some time - we should handle + * it - but prevent deadlock in case when device is too faulty... */ + for (total = j = 0; (j < 250) && (total < 2000); j++, total++) + { + grub_millisleep (1); + /* Get the port status. */ + err = grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_IN + | GRUB_USB_REQTYPE_CLASS + | GRUB_USB_REQTYPE_TARGET_OTHER), + GRUB_USB_REQ_GET_STATUS, + 0, i, + sizeof (current_status), + (char *) ¤t_status); + if (err) + { + total = 2000; + break; + } + if (!(current_status & GRUB_USB_HUB_STATUS_PORT_CONNECTED)) + j = 0; + } + grub_dprintf ("usb", "(non-root) total=%d\n", total); + if (total >= 2000) + continue; + + /* Now do reset of port. */ grub_usb_control_msg (dev, (GRUB_USB_REQTYPE_OUT | GRUB_USB_REQTYPE_CLASS | GRUB_USB_REQTYPE_TARGET_OTHER), @@ -369,6 +430,15 @@ poll_nonroot_hub (grub_usb_device_t dev) GRUB_USB_HUB_FEATURE_PORT_RESET, i, 0, 0); rescan = 1; + /* We cannot reset more than one device at the same time ! + * Resetting more devices together results in very bad + * situation: more than one device has default address 0 + * at the same time !!! + * Additionaly, we cannot perform another reset + * anywhere on the same OHCI controller until + * we will finish addressing of reseted device ! */ + dev->controller.dev->pending_reset = grub_get_time_ms () + 5000; + return; } } @@ -401,6 +471,7 @@ poll_nonroot_hub (grub_usb_device_t dev) /* Add the device and assign a device address to it. */ next_dev = grub_usb_hub_add_dev (&dev->controller, speed); + dev->controller.dev->pending_reset = 0; if (! next_dev) continue; @@ -426,12 +497,21 @@ grub_usb_poll_devices (void) /* No, it should be never changed, it should be constant. */ for (i = 0; i < hub->nports; i++) { - grub_usb_speed_t speed; + grub_usb_speed_t speed = GRUB_USB_SPEED_NONE; int changed = 0; - speed = hub->controller->dev->detect_dev (hub->controller, i, - &changed); - + if (!hub->controller->dev->pending_reset) + { + /* Check for possible timeout */ + if (grub_get_time_ms () > hub->controller->dev->pending_reset) + { + /* Something went wrong, reset device was not + * addressed properly, timeout happened */ + hub->controller->dev->pending_reset = 0; + speed = hub->controller->dev->detect_dev (hub->controller, + i, &changed); + } + } if (changed) { detach_device (hub->devices[i]); diff --git a/grub-core/bus/usb/usbtrans.c b/grub-core/bus/usb/usbtrans.c index 6b9b1a5b9..afd2eb0a5 100644 --- a/grub-core/bus/usb/usbtrans.c +++ b/grub-core/bus/usb/usbtrans.c @@ -33,10 +33,12 @@ grub_usb_execute_and_wait_transfer (grub_usb_device_t dev, grub_usb_err_t err; grub_uint64_t endtime; - endtime = grub_get_time_ms () + timeout; err = dev->controller.dev->setup_transfer (&dev->controller, transfer); if (err) return err; + /* endtime moved behind setup transfer to prevent false timeouts + * while debugging... */ + endtime = grub_get_time_ms () + timeout; while (1) { err = dev->controller.dev->check_transfer (&dev->controller, transfer, diff --git a/include/grub/usb.h b/include/grub/usb.h index f9cdb2765..6f838e4f9 100644 --- a/include/grub/usb.h +++ b/include/grub/usb.h @@ -116,6 +116,9 @@ struct grub_usb_controller_dev grub_usb_speed_t (*detect_dev) (grub_usb_controller_t dev, int port, int *changed); + /* Per controller flag - port reset pending, don't do another reset */ + grub_uint64_t pending_reset; + /* The next host controller. */ struct grub_usb_controller_dev *next; }; From 685475e59622cce56cc8a3d2b180241fc90e1d05 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 18 Sep 2010 13:49:39 +0200 Subject: [PATCH 211/214] Fix yeeloong compilation --- grub-core/Makefile.am | 1 + grub-core/Makefile.core.def | 3 +++ include/grub/loader.h | 12 ++++++------ 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am index 8b8d993b3..504bd4463 100644 --- a/grub-core/Makefile.am +++ b/grub-core/Makefile.am @@ -137,6 +137,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/libgcc.h KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/cs5536.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/machine/pci.h KERNEL_HEADER_FILES += $(top_builddir)/include/grub/serial.h +KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/loader.h endif if COND_powerpc_ieee1275 diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index c0a796ee0..f4a555ebe 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -173,6 +173,8 @@ kernel = { videoinkernel = video/fb/video_fb.c; videoinkernel = video/video.c; + videoinkernel = commands/boot.c; + extra_dist = kern/i386/realmode.S; extra_dist = kern/i386/pc/lzma_decode.S; extra_dist = kern/mips/cache_flush.S; @@ -424,6 +426,7 @@ module = { name = boot; common = commands/boot.c; i386_pc = lib/i386/pc/biosnum.c; + enable = videomodules; }; module = { diff --git a/include/grub/loader.h b/include/grub/loader.h index 319f3c551..c71e8dd10 100644 --- a/include/grub/loader.h +++ b/include/grub/loader.h @@ -26,16 +26,16 @@ #include /* Check if a loader is loaded. */ -int grub_loader_is_loaded (void); +int EXPORT_FUNC (grub_loader_is_loaded) (void); /* Set loader functions. NORETURN must be set to true, if BOOT won't return to the original state. */ -void grub_loader_set (grub_err_t (*boot) (void), - grub_err_t (*unload) (void), - int noreturn); +void EXPORT_FUNC (grub_loader_set) (grub_err_t (*boot) (void), + grub_err_t (*unload) (void), + int noreturn); /* Unset current loader, if any. */ -void grub_loader_unset (void); +void EXPORT_FUNC (grub_loader_unset) (void); /* Call the boot hook in current loader. This may or may not return, depending on the setting by grub_loader_set. */ @@ -56,7 +56,7 @@ typedef enum { } grub_loader_preboot_hook_prio_t; /* Register a preboot hook. */ -void *grub_loader_register_preboot_hook (grub_err_t (*preboot_func) (int noret), +void *EXPORT_FUNC(grub_loader_register_preboot_hook) (grub_err_t (*preboot_func) (int noret), grub_err_t (*preboot_rest_func) (void), grub_loader_preboot_hook_prio_t prio); From ab629d0c5de4ea6ba8e50300b271b33c2b945c49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1=20Nesrsta?= Date: Sun, 19 Sep 2010 00:34:25 +0200 Subject: [PATCH 212/214] Fix incorrect usb report interpretation --- grub-core/term/usb_keyboard.c | 134 ++++++++++++++++++++++++++-------- 1 file changed, 104 insertions(+), 30 deletions(-) diff --git a/grub-core/term/usb_keyboard.c b/grub-core/term/usb_keyboard.c index 6b1485e96..8a34ec552 100644 --- a/grub-core/term/usb_keyboard.c +++ b/grub-core/term/usb_keyboard.c @@ -75,6 +75,10 @@ struct grub_usb_keyboard_data int dead; int last_key; grub_uint64_t repeat_time; + grub_uint8_t current_report[8]; + grub_uint8_t last_report[8]; + int index; + int max_index; }; static int grub_usb_keyboard_getkey (struct grub_term_input *term); @@ -192,6 +196,9 @@ grub_usb_keyboard_attach (grub_usb_device_t usbdev, int configno, int interfno) data->interfno = interfno; data->endp = endp; + /* Configure device */ + grub_usb_set_configuration (usbdev, configno + 1); + /* Place the device in boot mode. */ grub_usb_control_msg (usbdev, GRUB_USB_REQTYPE_CLASS_INTERFACE_OUT, USB_HID_SET_PROTOCOL, 0, interfno, 0, 0); @@ -270,17 +277,96 @@ send_leds (struct grub_usb_keyboard_data *termdata) grub_errno = GRUB_ERR_NONE; } +static int +parse_keycode (struct grub_usb_keyboard_data *termdata) +{ + int index = termdata->index; + int i, keycode; + + /* Sanity check */ + if (index < 2) + index = 2; + + for ( ; index < termdata->max_index; index++) + { + keycode = termdata->current_report[index]; + + if (keycode == KEY_NO_KEY + || keycode == KEY_ERR_BUFFER + || keycode == KEY_ERR_POST + || keycode == KEY_ERR_UNDEF) + { + /* Don't parse (rest of) this report */ + termdata->index = 0; + if (keycode != KEY_NO_KEY) + /* Don't replace last report with current faulty report + * in future ! */ + grub_memcpy (termdata->current_report, + termdata->last_report, + sizeof (termdata->report)); + return GRUB_TERM_NO_KEY; + } + + /* Try to find current keycode in last report. */ + for (i = 2; i < 8; i++) + if (keycode == termdata->last_report[i]) + break; + if (i < 8) + /* Keycode is in last report, it means it was not released, + * ignore it. */ + continue; + + if (keycode == KEY_CAPS_LOCK) + { + termdata->mods ^= GRUB_TERM_STATUS_CAPS; + send_leds (termdata); + continue; + } + + if (keycode == KEY_NUM_LOCK) + { + termdata->mods ^= GRUB_TERM_STATUS_NUM; + send_leds (termdata); + continue; + } + + termdata->last_key = grub_term_map_key (keycode, + interpret_status (termdata->current_report[0]) + | termdata->mods); + termdata->repeat_time = grub_get_time_ms () + GRUB_TERM_REPEAT_PRE_INTERVAL; + + grub_errno = GRUB_ERR_NONE; + + index++; + if (index >= termdata->max_index) + termdata->index = 0; + else + termdata->index = index; + + return termdata->last_key; + } + + /* All keycodes parsed */ + termdata->index = 0; + return GRUB_TERM_NO_KEY; +} + static int grub_usb_keyboard_getkey (struct grub_term_input *term) { grub_usb_err_t err; struct grub_usb_keyboard_data *termdata = term->data; - grub_uint8_t data[sizeof (termdata->report)]; grub_size_t actual; + int keycode = GRUB_TERM_NO_KEY; if (termdata->dead) return GRUB_TERM_NO_KEY; + if (termdata->index) + keycode = parse_keycode (termdata); + if (keycode != GRUB_TERM_NO_KEY) + return keycode; + /* Poll interrupt pipe. */ err = grub_usb_check_transfer (termdata->transfer, &actual); @@ -296,7 +382,14 @@ grub_usb_keyboard_getkey (struct grub_term_input *term) return GRUB_TERM_NO_KEY; } - grub_memcpy (data, termdata->report, sizeof (data)); + if (!err && (actual >= 3)) + grub_memcpy (termdata->last_report, + termdata->current_report, + sizeof (termdata->report)); + + grub_memcpy (termdata->current_report, + termdata->report, + sizeof (termdata->report)); termdata->transfer = grub_usb_bulk_read_background (termdata->usbdev, termdata->endp->endp_addr, @@ -314,42 +407,23 @@ grub_usb_keyboard_getkey (struct grub_term_input *term) "err = %d, actual = %d report: 0x%02x 0x%02x 0x%02x 0x%02x" " 0x%02x 0x%02x 0x%02x 0x%02x\n", err, actual, - data[0], data[1], data[2], data[3], - data[4], data[5], data[6], data[7]); + termdata->current_report[0], termdata->current_report[1], + termdata->current_report[2], termdata->current_report[3], + termdata->current_report[4], termdata->current_report[5], + termdata->current_report[6], termdata->current_report[7]); if (err || actual < 1) return GRUB_TERM_NO_KEY; - termdata->status = data[0]; + termdata->status = termdata->current_report[0]; if (actual < 3) return GRUB_TERM_NO_KEY; - if (data[2] == KEY_NO_KEY || data[2] == KEY_ERR_BUFFER - || data[2] == KEY_ERR_POST || data[2] == KEY_ERR_UNDEF) - return GRUB_TERM_NO_KEY; - - if (data[2] == KEY_CAPS_LOCK) - { - termdata->mods ^= GRUB_TERM_STATUS_CAPS; - send_leds (termdata); - return GRUB_TERM_NO_KEY; - } - - if (data[2] == KEY_NUM_LOCK) - { - termdata->mods ^= GRUB_TERM_STATUS_NUM; - send_leds (termdata); - return GRUB_TERM_NO_KEY; - } - - termdata->last_key = grub_term_map_key (data[2], interpret_status (data[0]) - | termdata->mods); - termdata->repeat_time = grub_get_time_ms () + GRUB_TERM_REPEAT_PRE_INTERVAL; - - grub_errno = GRUB_ERR_NONE; - - return termdata->last_key; + termdata->index = 2; /* New data received. */ + termdata->max_index = actual; + + return parse_keycode (termdata); } static int From de0bd1d940653833558937f6b2c27e9a973bceab Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 19 Sep 2010 01:08:25 +0200 Subject: [PATCH 213/214] Add missing file of previous commit --- docs/man/grub-mklayout.h2m | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 docs/man/grub-mklayout.h2m diff --git a/docs/man/grub-mklayout.h2m b/docs/man/grub-mklayout.h2m new file mode 100644 index 000000000..e0ae9dedb --- /dev/null +++ b/docs/man/grub-mklayout.h2m @@ -0,0 +1,2 @@ +[NAME] +grub-mklayout \- generate a GRUB keyboard layout file From eaf41b25921efe7cad32a7a2dc62e38da1df0ac0 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sun, 19 Sep 2010 01:15:44 +0200 Subject: [PATCH 214/214] * grub-core/commands/i386/cmostest.c (+parse_args): New function. (grub_cmd_cmosclean): Likewise. (GRUB_MOD_INIT): Register command cmosclean. * util/grub-mkconfig.in: Export GRUB_BUTTON_CMOS_CLEAN. * util/grub.d/00_header.in: Handle GRUB_BUTTON_CMOS_CLEAN. --- ChangeLog | 8 ++++++ grub-core/commands/i386/cmostest.c | 43 +++++++++++++++++++++++++----- util/grub-mkconfig.in | 1 + util/grub.d/00_header.in | 6 +++++ 4 files changed, 52 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index e9eb142be..d1ca11650 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2010-09-19 Vladimir Serbinenko + + * grub-core/commands/i386/cmostest.c (+parse_args): New function. + (grub_cmd_cmosclean): Likewise. + (GRUB_MOD_INIT): Register command cmosclean. + * util/grub-mkconfig.in: Export GRUB_BUTTON_CMOS_CLEAN. + * util/grub.d/00_header.in: Handle GRUB_BUTTON_CMOS_CLEAN. + 2010-09-18 Carles Pina i Estany 2010-09-18 Aleš Nesrsta 2010-09-18 Vladimir Serbinenko diff --git a/grub-core/commands/i386/cmostest.c b/grub-core/commands/i386/cmostest.c index 36c35e6c4..994da11b0 100644 --- a/grub-core/commands/i386/cmostest.c +++ b/grub-core/commands/i386/cmostest.c @@ -22,20 +22,32 @@ #include static grub_err_t -grub_cmd_cmostest (struct grub_command *cmd __attribute__ ((unused)), - int argc, char *argv[]) +parse_args (int argc, char *argv[], int *byte, int *bit) { - int byte, bit; char *rest; if (argc != 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "Address required."); - byte = grub_strtoul (argv[0], &rest, 0); + *byte = grub_strtoul (argv[0], &rest, 0); if (*rest != ':') return grub_error (GRUB_ERR_BAD_ARGUMENT, "Address required."); - bit = grub_strtoul (rest + 1, 0, 0); + *bit = grub_strtoul (rest + 1, 0, 0); + + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_cmd_cmostest (struct grub_command *cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + int byte, bit; + grub_err_t err; + + err = parse_args (argc, argv, &byte, &bit); + if (err) + return err; if (grub_cmos_read (byte) & (1 << bit)) return GRUB_ERR_NONE; @@ -43,7 +55,22 @@ grub_cmd_cmostest (struct grub_command *cmd __attribute__ ((unused)), return grub_error (GRUB_ERR_TEST_FAILURE, "false"); } -static grub_command_t cmd; +static grub_err_t +grub_cmd_cmosclean (struct grub_command *cmd __attribute__ ((unused)), + int argc, char *argv[]) +{ + int byte, bit; + grub_err_t err; + + err = parse_args (argc, argv, &byte, &bit); + if (err) + return err; + + grub_cmos_write (byte, grub_cmos_read (byte) & (~(1 << bit))); + return GRUB_ERR_NONE; +} + +static grub_command_t cmd, cmd_clean; GRUB_MOD_INIT(cmostest) @@ -51,9 +78,13 @@ GRUB_MOD_INIT(cmostest) cmd = grub_register_command ("cmostest", grub_cmd_cmostest, "cmostest BYTE:BIT", "Test bit at BYTE:BIT in CMOS."); + cmd_clean = grub_register_command ("cmosclean", grub_cmd_cmosclean, + "cmosclean BYTE:BIT", + "Clean bit at BYTE:BIT in CMOS."); } GRUB_MOD_FINI(cmostest) { grub_unregister_command (cmd); + grub_unregister_command (cmd_clean); } diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in index c3b4c3398..3ba9cd63e 100644 --- a/util/grub-mkconfig.in +++ b/util/grub-mkconfig.in @@ -245,6 +245,7 @@ export GRUB_DEFAULT \ GRUB_HIDDEN_TIMEOUT_BUTTON \ GRUB_TIMEOUT_BUTTON \ GRUB_BUTTON_CMOS_ADDRESS \ + GRUB_BUTTON_CMOS_CLEAN \ GRUB_DISTRIBUTOR \ GRUB_CMDLINE_LINUX \ GRUB_CMDLINE_LINUX_DEFAULT \ diff --git a/util/grub.d/00_header.in b/util/grub.d/00_header.in index 2f39650e9..9ed3fc3a1 100644 --- a/util/grub.d/00_header.in +++ b/util/grub.d/00_header.in @@ -247,6 +247,12 @@ else make_timeout "${GRUB_HIDDEN_TIMEOUT}" "${GRUB_TIMEOUT}" fi +if [ "x$GRUB_BUTTON_CMOS_ADDRESS" != "x" ] && [ "x$GRUB_BUTTON_CMOS_CLEAN" = "xyes" ]; then + cat <