grub-0.95
Rudolf Weber
rfweber at tesionmail.de
Mon Oct 11 20:32:14 CEST 2004
Hallo,
I adaped the patch for grup for grub-0.95.
The grub in the Dresden CVS don't compile with gcc-3.3. and gcc-3.4.0
(as I tried it)
Grub2 is very promissing, but it don't find the symbol tyble (as I tried
it)
I think it is a good idea to put the Dresdner grub enhancement in the
official grub2.
Greetings
Rudolf Weber
P.S: My new Notebook boots now from the net and the grub have now
variables ...
P.P.S: I have worked on RACE http://www.infnet.verein.de/produkte/race/
and dream to map ACE/RACE on L4
--
--
---------------------------------------------------------------
Rudolf Weber
http://www.infnet.verein.de/~rw
E-Mail: rfweber at tesionmail.de
-------------- next part --------------
--- ./stage2/asm.S.voros 2004-05-23 18:22:23.000000000 +0200
+++ ./stage2/asm.S 2004-09-11 00:48:08.000000000 +0200
@@ -951,6 +951,8 @@
pushl %esi
pushl %ebx
+ pushl %ecx
+ pushl %edx
/* compute the address of disk_address_packet */
movl 0x10(%ebp), %eax
@@ -980,6 +982,8 @@
movb %dl, %al /* return value in %eax */
+ popl %edx
+ popl %ecx
popl %ebx
popl %esi
popl %ebp
@@ -1610,6 +1614,66 @@
ret
+ ENTRY(reset_vbe_mode)
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %ebx
+
+ call EXT_C(prot_to_real)
+ .code16
+
+ movw $0x0003, %ax
+ int $0x10
+
+ DATA32 call EXT_C(real_to_prot)
+ .code32
+
+ popl %ebx
+ popl %ebp
+ ret
+
+
+ ENTRY(get_vbe_pmif)
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %ebx
+ pushl %esi
+ pushl %edi
+
+ pushl %ebp
+
+ call EXT_C(prot_to_real)
+ .code16
+
+ movw $0x4F0A, %ax
+ xorw %bx,%bx
+ xorw %di,%di
+ int $0x10
+ xorl %ebx,%ebx
+ cmpw $0x004F,%ax
+ jnz nopm
+
+ movw %es,%bx
+ shll $16,%ebx
+ movw %di,%bx
+
+ nopm: DATA32 call EXT_C(real_to_prot)
+ .code32
+
+ popl %ebp
+
+ movl 0x8(%ebp),%eax
+ movl %ebx,(%eax)
+ movl 0xc(%ebp),%eax
+ andl $0xFFFF,%ecx
+ movl %ecx,(%eax)
+
+ popl %edi
+ popl %esi
+ popl %ebx
+ popl %ebp
+ ret
+
/*
* gateA20(int linear)
*
--- ./stage2/bios.c.voros 2004-03-27 17:34:04.000000000 +0100
+++ ./stage2/bios.c 2004-09-11 00:59:35.000000000 +0200
@@ -86,6 +86,10 @@
#ifndef NO_INT13_FALLBACK
if (err)
{
+ /* We can't switch to CHS mode */
+ if (geometry->cylinders == 0)
+ return err;
+
if (geometry->flags & BIOSDISK_FLAG_CDROM)
return err;
@@ -187,6 +191,7 @@
/* Clear the flags. */
geometry->flags = 0;
+ geometry->total_sectors = 0;
if (drive & 0x80)
{
--- ./stage2/boot.c.voros 2004-03-30 13:44:08.000000000 +0200
+++ ./stage2/boot.c 2004-09-11 01:06:31.000000000 +0200
@@ -769,6 +769,16 @@
if (!grub_open (module))
return 0;
+ if ((cur_addr + filemax) >= (1024*(1024+mbi.mem_upper)))
+ {
+ printf("Want to load module to 0x%x len 0x%x but only have 0x%x RAM\n",
+ cur_addr, filemax, 1024*(1024+mbi.mem_upper));
+ errnum = ERR_BADMODADDR;
+ grub_close ();
+ return 0;
+ }
+
+
len = grub_read ((char *) cur_addr, -1);
if (! len)
{
@@ -795,6 +805,36 @@
return 1;
}
+void
+create_vbe_module(void *ctrl_info, int ctrl_info_len,
+ void *mode_info, int mode_info_len,
+ int mode, int pmif, int pmif_len,
+ unsigned int version)
+{
+ /* if we are supposed to load on 4K boundaries */
+ cur_addr = (cur_addr + 0xFFF) & 0xFFFFF000;
+
+ printf (" [VESA %d.%d info @ 0x%x, 0x%x bytes]\n",
+ version >> 8, version & 0xFF,
+ cur_addr, ctrl_info_len + mode_info_len);
+
+ grub_memmove((char*)cur_addr, ctrl_info, ctrl_info_len);
+ mbi.vbe_control_info = (int)cur_addr;
+ cur_addr += ctrl_info_len;
+
+ grub_memmove((char*)cur_addr, mode_info, mode_info_len);
+ mbi.vbe_mode_info = (int)cur_addr;
+ cur_addr += mode_info_len;
+
+ mbi.flags |= MB_INFO_VIDEO_INFO;
+
+ mbi.vbe_mode = mode;
+ mbi.vbe_interface_seg = (pmif >> 16) & 0xFFFF;
+ mbi.vbe_interface_off = pmif & 0xFFFF;
+ mbi.vbe_interface_len = pmif_len;
+}
+
+
int
load_initrd (char *initrd)
{
@@ -854,6 +894,13 @@
}
+void
+set_load_addr (int addr)
+{
+ printf ("Setting module load address to 0x%x\n", addr);
+ cur_addr = addr;
+}
+
#ifdef GRUB_UTIL
/* Dummy function to fake the *BSD boot. */
static void
--- ./stage2/builtins.c.voros 2004-05-14 21:30:52.000000000 +0200
+++ ./stage2/builtins.c 2004-09-11 16:48:30.000000000 +0200
@@ -2542,6 +2542,40 @@
};
#endif /* USE_MD5_PASSWORDS */
+/* modaddr */
+static int
+modaddr_func (char *arg, int flags)
+{
+ int addr;
+
+ switch (kernel_type)
+ {
+ case KERNEL_TYPE_MULTIBOOT:
+ if (safe_parse_maxint(&arg, &addr))
+ {
+ set_load_addr(addr);
+ break;
+ }
+
+ /* else fallthrough */
+
+ default:
+ errnum = ERR_NEED_MB_KERNEL;
+ return 1;
+ }
+
+ return 0;
+}
+
+static struct builtin builtin_modaddr =
+{
+ "modaddr",
+ modaddr_func,
+ BUILTIN_CMDLINE | BUILTIN_HELP_LIST,
+ "modaddr ADDRESS",
+ "Set the load address for the next Multiboot module to ADDRESS"
+};
+
/* module */
static int
@@ -4664,6 +4698,1005 @@
" the information about only the mode."
};
+/* vbeset MODE */
+static int
+vbeset_func (char *arg, int flags)
+{
+#ifndef GRUB_UTIL
+ int mode_number;
+ int pmif_segoff, pmif_len;
+ struct vbe_controller controller;
+ struct vbe_mode mode;
+
+ if (kernel_type != KERNEL_TYPE_MULTIBOOT)
+ {
+ grub_printf("Multiboot kernel must be loaded before vbeset command\n");
+ errnum = MAX_ERR_NUM;
+ return 1;
+ }
+
+ if (! *arg)
+ {
+ reset_vbe_mode ();
+ return 0;
+ }
+
+ if (! safe_parse_maxint (&arg, &mode_number))
+ return 1;
+
+ /* Preset `VBE2'. */
+ grub_memmove (controller.signature, "VBE2", 4);
+
+ /* Detect VBE BIOS. */
+ if (get_vbe_controller_info (&controller) != 0x004F)
+ {
+ grub_printf (" VBE BIOS is not present.\n");
+ return 1;
+ }
+ if (controller.version < 0x0200)
+ {
+ grub_printf (" VBE version %d.%d is not supported.\n",
+ (int) (controller.version >> 8),
+ (int) (controller.version & 0xFF));
+ errnum = MAX_ERR_NUM;
+ return 1;
+ }
+
+ if (get_vbe_mode_info (mode_number, &mode) != 0x004F
+ || (mode.mode_attributes & 0x0091) != 0x0091)
+ {
+ grub_printf (" Mode 0x%x is not supported.\n", mode_number);
+ errnum = MAX_ERR_NUM;
+ return 1;
+ }
+
+ /* Now trip to the graphics mode. */
+ if (set_vbe_mode (mode_number | (1 << 14)) != 0x004F)
+ {
+ grub_printf (" Switching to Mode 0x%x failed.\n", mode_number);
+ errnum = MAX_ERR_NUM;
+ return 1;
+ }
+
+ get_vbe_pmif(&pmif_segoff, &pmif_len);
+ create_vbe_module(&controller, sizeof(struct vbe_controller),
+ &mode, sizeof(struct vbe_mode),
+ mode_number, pmif_segoff, pmif_len, controller.version);
+
+ /* mode setting was successful */
+ return 0;
+#else
+ errnum = ERR_BAD_ARGUMENT;
+ return 1;
+#endif
+}
+
+static struct builtin builtin_vbeset =
+{
+ "vbeset",
+ vbeset_func,
+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
+ "vbeset [MODE]",
+ "Set the VBE mode MODE. If no MODE is given, switch back to text mode."
+};
+
+
+#define VARIABLE_STORE_SIZE 1024
+char variable_store[VARIABLE_STORE_SIZE];
+unsigned int variable_store_actpos; /* Points to the next free entry */
+struct variable_list_struct {
+ char *name;
+ char *value;
+} variable_list[VARIABLES_MAX];
+
+static void var_show(void)
+{
+ int i = 0;
+
+ for (; i < VARIABLES_MAX; i++)
+ if (variable_list[i].name)
+ {
+ grub_printf("%s = %s\n",
+ variable_list[i].name,
+ variable_list[i].value);
+ }
+}
+
+static int var_get_index(char *var)
+{
+ int i = 0;
+
+ if (!*var)
+ return -1;
+
+ for (; i < VARIABLES_MAX; i++)
+ if (variable_list[i].name &&
+ grub_strcmp(variable_list[i].name, var) == 0)
+ return i;
+
+ return -1;
+}
+
+char *var_get(char *var)
+{
+ int i;
+
+ if ((i = var_get_index(var)) == -1)
+ return NULL;
+
+ return variable_list[i].value;
+}
+
+static char *var_alloc_mem(unsigned int len)
+{
+ if (VARIABLE_STORE_SIZE < variable_store_actpos + len
+ || !len)
+ return NULL;
+
+ variable_store_actpos += len;
+ return &variable_store[variable_store_actpos - len];
+}
+
+/* Maybe we're implementing "unset" later? */
+static int var_get_free_var(void)
+{
+ int i = 0;
+
+ for (; i < VARIABLES_MAX; i++)
+ if (variable_list[i].name == NULL)
+ return i;
+
+ return -1;
+}
+static inline char *skip_ws(char *s)
+{
+ while (isspace(*s))
+ s++;
+ return s;
+}
+
+static int var_sprint_once(char *buf, char *str)
+{
+ char *b = buf;
+
+ while (*str)
+ {
+ if (*str == '$' && *(str + 1) == '(')
+ {
+ /* Found start of variable */
+ char *end_var;
+ char *c = str + 2;
+
+ end_var = c;
+ while (*end_var && *end_var != ')')
+ end_var++;
+
+ if (*end_var == ')')
+ {
+ char *val;
+
+ /* Copy variable name into var */
+
+ str = end_var + 1;
+
+ *end_var = 0;
+ if ((val = var_get(c)))
+ {
+ /* All ok, we got it */
+ /* Copy to buf */
+ while (*val)
+ *b++ = *val++;
+
+ *end_var = ')';
+
+ continue;
+ }
+ /* else
+ grub_printf("Unknown variable: %var!\n", var); */
+
+ *end_var = ')';
+ }
+ }
+ *b++ = *str++;
+ }
+
+ *b = 0;
+
+ return b - buf;
+}
+
+int var_sprint(char *buf, char *str)
+{
+ int i = 10;
+ /* Waste some stack here... */
+ const int buffer_size = 1000;
+ char buffer[buffer_size];
+
+ grub_strcpy(buf, str);
+
+ /* We're not checking any return values here or any array overflows... :( */
+ do
+ {
+ if (grub_strlen(buf) > buffer_size)
+ {
+ grub_printf("Buffer overflow: %s(%d)\n", __FILE__, __LINE__);
+ while (1) {}
+ }
+
+ grub_strcpy(buffer, buf);
+
+ var_sprint_once(buf, buffer);
+ }
+ while (--i && grub_strcmp(buf, buffer));
+ if (!i)
+ {
+ grub_printf("Possible loop in var_sprintf!\n");
+ getkey();
+ }
+
+ return grub_strlen(buf);
+}
+
+/* Use our own buffer instead of a supplied one and
+ * return the pointer to the buffer and not the bytes
+ * processed. */
+/* We try to detect buffer overruns... */
+static char var_sprint_buffer[1500];
+static const long var_sprint_magic = 0x14233241;
+char *var_sprint_buf(char *str, int *bytes)
+{
+ *(long *)(var_sprint_buffer + sizeof(var_sprint_buffer) - sizeof(var_sprint_magic)) = var_sprint_magic;
+
+ *bytes = var_sprint(var_sprint_buffer, str);
+
+ if (*(long *)(var_sprint_buffer + sizeof(var_sprint_buffer) - sizeof(var_sprint_magic)) != var_sprint_magic)
+ {
+ grub_printf("Possible buffer overrun: %s(%d)\n", __FILE__, __LINE__);
+ while (1) {}
+ }
+ return var_sprint_buffer;
+}
+/* This function just updates the pointer to the value, this value has to
+ * be inside the variable_store */
+static int var_set_no_copy(char *name, char *val)
+{
+ int i;
+
+ if (val < variable_store || val >= (variable_store + VARIABLE_STORE_SIZE))
+ return 1;
+
+ i = var_get_index(name);
+
+ if (i == -1)
+ {
+ /* The variable doesn't exist yet, so we have a new variable */
+ char *a = name;
+
+ /* Some sanity check */
+ while (*a)
+ {
+ if (*a == '(' || *a == ')' || *a == ' ')
+ return 1;
+ a++;
+ }
+
+
+ if ((i = var_get_free_var()) == -1)
+ return 1;
+
+ if ((a = var_alloc_mem(grub_strlen(name) + 1)) == NULL)
+ return 1;
+
+ grub_strcpy(a, name);
+ variable_list[i].name = a;
+ }
+
+ variable_list[i].value = val;
+
+ return 0; /* Ok */
+}
+
+/* XXX: this is a bit code duplication with var_set_no_copy,
+ * so if someone has some free time, feel free to join this
+ */
+int var_set(char *name, char *value, int parse)
+{
+ int i;
+
+ if (parse)
+ value = var_sprint_buf(value, &i);
+
+ i = var_get_index(name);
+
+ if (i == -1)
+ {
+ /* The variable doesn't exist yet, so we have a new variable */
+ char *a = name;
+
+ /* Some sanity check */
+ while (*a)
+ {
+ if (*a == '(' || *a == ')' || *a == ' ')
+ return 1;
+ a++;
+ }
+
+ if ((i = var_get_free_var()) == -1)
+ return 1;
+
+ if ((a = var_alloc_mem(grub_strlen(name) + 1)) == NULL)
+ return 1;
+
+ grub_strcpy(a, name);
+ variable_list[i].name = a;
+
+ if ((a = var_alloc_mem(grub_strlen(value) + 1)) == NULL)
+ return 1;
+
+ grub_strcpy(a, value);
+ variable_list[i].value = a;
+ }
+ else
+ {
+ /* Variable already exists */
+ if (grub_strlen(variable_list[i].value) >= grub_strlen(value))
+ {
+ /* We can just replace the value but we're potentially
+ * loosing space */
+ grub_strcpy(variable_list[i].value, value);
+ }
+ else
+ {
+ /* New value is longer then the old one, we need to +
+ * allocate a new place and drop the old one (i.e. wasting it) */
+ char *a;
+ if ((a = var_alloc_mem(grub_strlen(value) + 1)) == NULL)
+ return 1;
+
+ grub_strcpy(a, value);
+
+ variable_list[i].value = a;
+ }
+ }
+
+ //grub_printf("Saved %s=\"%s\" in slot %d.\n", variable_list[i].name, variable_list[i].value, i + 1);
+ //getkey();
+
+ return 0; /* Ok */
+}
+
+
+static int
+set_func(char *arg, int flags)
+{
+ char *a = arg;
+ char *variable, *value;
+ char *end_variable, end_variable_val;
+ char *end_value, end_value_val;
+ char end_char;
+ int i = 0, parse = 0, emptysetonly = 0;
+
+ a = skip_ws(a);
+
+ if (!*a)
+ {
+ var_show();
+ return 0;
+ }
+
+ variable = a;
+ while (*a && *a != ':' && *a != '=' && *a != ' ')
+ a++;
+ end_variable_val = *a;
+ end_variable = a;
+ a = skip_ws(a);
+
+ if (*a == ':')
+ {
+ parse = 1;
+ a++;
+ }
+ if (*a == '?')
+ {
+ emptysetonly = 1;
+ a++;
+ }
+
+ if (*a != '=')
+ goto bad_arg;
+
+ a++;
+ a = skip_ws(a);
+
+ end_char = ' ';
+ if (*a == '"')
+ {
+ end_char = *a;
+ a++;
+ }
+ /* XXX: add/fix \" and \\ stuff */
+ value = a;
+ while (*a && *a != end_char)
+ a++;
+ end_value_val = *a;
+ end_value = a;
+
+ *end_value = *end_variable = 0;
+
+ if ((emptysetonly && var_get_index(variable) == -1) ||
+ !emptysetonly)
+ i = var_set(variable, value, parse);
+
+ *end_value = end_value_val;
+ *end_variable = end_variable_val;
+
+ return i;
+
+bad_arg:
+ grub_printf("%s: ERR_BAD_ARGUMENT\n", __func__);
+ getkey();
+ errnum = ERR_BAD_ARGUMENT;
+ return 1;
+}
+
+static struct builtin builtin_set =
+{
+ "set",
+ set_func,
+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
+ "set var=val",
+ "Set a variable to a value."
+};
+
+static int
+print_func(char *arg, int flags)
+{
+ grub_printf("%s\n", var_sprint_buf(arg, &flags));
+ return 0;
+}
+
+static struct builtin builtin_print =
+{
+ "print",
+ print_func,
+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
+ "print \"string with vars\"",
+ "Print a string which may contain variables. Variables are enclosed"
+ " in $( and ) (like \"make\")."
+};
+
+static struct builtin builtin_echo =
+{
+ "echo",
+ print_func,
+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
+ "echo \"string with vars\"",
+ "Alias for \"print\"."
+};
+
+
+
+
+#define TOGGLES 10
+#define MAX_BLOCKS 7
+#define MAX_VAR_PER_BLOCK 4
+
+struct toggle_data_struct {
+ int key; /* int because of F-keys !? */
+ int current_block;
+ char nr_blocks;
+ struct {
+ char nr_vars;
+ struct {
+ int var; /* index of variable_list */
+ char *value; /* pointer to value */
+ } var[MAX_VAR_PER_BLOCK];
+ } block[MAX_BLOCKS];
+} toggle_data[TOGGLES];
+int toggles_used = 0;
+
+char toggle_trigger_init_done;
+
+static int get_toggle_slot_for_key(int key)
+{
+ int i = 0;
+
+ for (; i < TOGGLES; i++)
+ if (toggle_data[i].key == key)
+ return i;
+
+ return -1;
+}
+
+int toggle_print_status(int x, int y)
+{
+ /* Basically print all variable which are on the left side on toggles */
+ int printed[VARIABLES_MAX];
+ int printed_something = 0;
+ int i, t, b, v, dummy;
+ const int ylines = 6;
+ int xpos[ylines];
+ int dy = 0;
+
+ for (i = 0; i < ylines; i++)
+ xpos[i] = x;
+ for (i = 0; i < VARIABLES_MAX; i++)
+ printed[i] = 0;
+
+ for (t = 0; t < toggles_used; t++)
+ {
+ for (b = 0; b < toggle_data[t].nr_blocks; b++)
+ {
+ for (v = 0; v < toggle_data[t].block[b].nr_vars; v++)
+ {
+ i = toggle_data[t].block[b].var[v].var;
+ if (!printed[i])
+ {
+ int len;
+ char *vals;
+
+ gotoxy(xpos[dy], y + dy);
+
+ /* don't use printf here since we need the lengths
+ * of the printed string and we don't want to use another
+ * buffer for sprintf
+ */
+ grub_putstr(variable_list[i].name);
+ grub_putchar('=');
+ len = grub_strlen(variable_list[i].name) + 1;
+
+ vals = var_sprint_buf(variable_list[i].value, &dummy);
+ grub_putstr(vals);
+ len += grub_strlen(vals);
+
+ xpos[dy] += len + 2;
+
+ if (++dy == ylines) {
+ dy = 0;
+ }
+
+ printed[i] = printed_something = 1;
+ }
+ }
+ }
+ }
+
+ return printed_something;
+}
+
+static int toggle_do_block(int slot, int block_nr)
+{
+ int v;
+
+ if (slot >= toggles_used || block_nr >= toggle_data[slot].nr_blocks)
+ return 0;
+
+ /* Set all variables in th block block_nr to their new values */
+ for (v = 0; v < toggle_data[slot].block[block_nr].nr_vars; v++)
+ {
+ int l = toggle_data[slot].block[block_nr].var[v].var;
+
+ var_set_no_copy(variable_list[l].name, toggle_data[slot].block[block_nr].var[v].value);
+ }
+
+ return 1; /* Ok */
+}
+static int toggle_find_slot(int key)
+{
+ int i = 0;
+
+ for (; i < toggles_used; i++)
+ if (toggle_data[i].key == key)
+ return i;
+
+ return -1;
+}
+
+int toggle_do_key(int key)
+{
+ int slot;
+
+ if ((slot = toggle_find_slot(key)) == -1)
+ return 0;
+
+ /* Proceed to the next block */
+ if (++toggle_data[slot].current_block == toggle_data[slot].nr_blocks)
+ toggle_data[slot].current_block = 0;
+
+ toggle_do_block(slot, toggle_data[slot].current_block);
+
+ return 1;
+}
+
+static int
+toggle_func(char *arg, int flags)
+{
+ int slot, key, block = 0, i;
+ char *a = arg, *eb;
+ int command;
+ enum {
+ COMMAND_SET,
+ COMMAND_SELECT,
+ COMMAND_TRIGGER,
+ };
+
+ static int process_var(int bl, int var, char *start, char *end)
+ {
+ char *p, origvar, *origvarp, origval, *v;
+
+ //grub_printf("VAR(%d, %d) %s [%d]\n", bl, var, start, end-start+1);
+
+ start = skip_ws(start);
+ p = start;
+ while (p < end && *p != '=' && !isspace(*p))
+ p++;
+
+ origvar = *p;
+ origvarp = p;
+
+ p = skip_ws(p);
+ if (*p != '=')
+ return 1;
+
+ p = skip_ws(p+1);
+
+ // value is now from p to end (both inclusive)
+
+ origval = *(end + 1);
+ *(end + 1) = 0;
+ *origvarp = 0;
+
+ /* See if we already have the same value in that toggle
+ * (in case we're entering a menu multiple time we would
+ * allocate memory multiple time) */
+
+ if (toggle_data[slot].block[bl].var[var].value &&
+ var_get_index(start) != -1 &&
+ !grub_strcmp(toggle_data[slot].block[bl].var[var].value, p))
+ {
+ }
+ else
+ {
+ /* Allocate space for the value and hang it in */
+ if ((v = var_alloc_mem(grub_strlen(p) + 1)) == NULL)
+ return 1;
+ grub_strcpy(v, p);
+
+ var_set_no_copy(start, v);
+
+ if ((toggle_data[slot].block[bl].var[var].var = var_get_index(start)) == -1)
+ return 1; /* internal error */
+ toggle_data[slot].block[bl].var[var].value = v;
+ }
+
+ *origvarp = origvar;
+ *(end + 1) = origval;
+
+ //grub_printf("slot=%d block=%d var=%d %d=%s\n", slot, bl, var, toggle_data[slot].block[bl].var[var].var, v);
+
+ if (var >= toggle_data[slot].block[bl].nr_vars)
+ toggle_data[slot].block[bl].nr_vars = var + 1;
+
+ return 0;
+ }
+
+ static int process_block(int bl, char *start, char *end)
+ {
+ char *p = start;
+ int var = 0;
+
+ //grub_printf("BL(%d) %s [%d]\n", bl, start, end-start+1);
+
+ while (p <= end)
+ {
+ if (*p == ',' || p == end)
+ {
+ if (var == MAX_VAR_PER_BLOCK)
+ return ERR_WONT_FIT;
+
+ if (process_var(bl, var, start, (p == end) ? p : (p-1)))
+ return ERR_BAD_ARGUMENT;
+
+ var++;
+ start = p + 1;
+ }
+ p++;
+ }
+
+ return 0;
+ }
+
+
+ /* parse args */
+ /* proceed to next arg */
+ while (*a && *a == ' ')
+ a++;
+
+ /* Get command */
+ {
+ eb = a;
+
+ while (!isspace(*eb))
+ eb++;
+
+ if (!isspace(*eb))
+ goto bad_arg;
+
+ //grub_printf("trigger: processing line: %s\n", a);
+
+ *eb = 0;
+
+ if (!grub_strcmp(a, "set"))
+ command = COMMAND_SET;
+ else if (!grub_strcmp(a, "select"))
+ command = COMMAND_SELECT;
+ else if (!grub_strcmp(a, "trigger"))
+ command = COMMAND_TRIGGER;
+ else
+ {
+ grub_printf("toggle: Unknown command!\n");
+ goto bad_arg;
+ }
+ *eb = ' ';
+ a = eb + 1;
+ }
+
+ a = skip_ws(a);
+
+ if (command == COMMAND_SET)
+ {
+
+ if (!*a || !*(a+1))
+ goto bad_arg;
+
+ key = *a;
+ a++;
+
+ //grub_printf("key: %c\n", key);
+
+ /* Find slot for key */
+ slot = get_toggle_slot_for_key(key);
+ if (slot == -1)
+ {
+ /* Get next free toggle_data slot */
+ slot = toggles_used;
+ if (slot == TOGGLES)
+ goto wont_fit;
+ toggle_data[slot].key = key;
+ toggles_used++;
+ }
+
+ /* Reset current slot */
+ toggle_data[slot].nr_blocks = toggle_data[slot].current_block = 0;
+ for (i = 0; i < MAX_VAR_PER_BLOCK; i++)
+ toggle_data[slot].block[i].nr_vars = 0;
+
+ while (*a)
+ {
+ int ret;
+
+ a = skip_ws(a);
+
+ if (*a != '{')
+ goto bad_arg;
+ /* find the correspondig '}' */
+ eb = a++;
+ while (*eb && *eb != '}')
+ eb++;
+ if (*eb != '}')
+ goto bad_arg;
+ /* Now we have the block between a and eb-1 */
+ ret = process_block(block, a, eb-1);
+ if (ret == ERR_WONT_FIT)
+ goto wont_fit;
+ if (ret)
+ goto bad_arg;
+
+ a = eb + 1;
+
+ block++;
+ if (*a) {
+ if (block == MAX_BLOCKS)
+ goto wont_fit;
+ }
+ }
+ toggle_data[slot].nr_blocks = block;
+
+ /* finally, set all vars from the first block */
+ toggle_do_block(slot, 0);
+ }
+ else if (command == COMMAND_SELECT)
+ {
+ while (*a)
+ {
+ int k, b, s;
+
+ /* there's something between a and eb-1 now*/
+ /* *a is a key and *(a+1) == '=' */
+ k = *a++;
+
+ if (*a++ != '=')
+ goto bad_arg;
+
+ if (!safe_parse_maxint(&a, &b))
+ goto bad_arg;
+
+ if ((s = toggle_find_slot(k)) == -1)
+ goto bad_arg;
+
+ if (!toggle_do_block(s, b))
+ goto bad_arg;
+
+ toggle_data[s].current_block = b;
+
+ toggle_data[s].current_block = b;
+
+ a = skip_ws(a);
+ }
+ }
+ else if (command == COMMAND_TRIGGER)
+ {
+ char *vr, *vre, *vl, *vle, *vrval;
+ char o;
+ int cmp;
+ // remaining a(rg) format: VAR==VAL "command"
+ //grub_printf("%s: trigger\n");
+
+ /* Find the '=' */
+ vr = a;
+ while (*a && *a != ' ' && *a != '=')
+ a++;
+
+ if (*a != '=' || *(a+1) != '=')
+ goto bad_arg;
+
+ vre = a;
+
+ if (vr == vre)
+ goto bad_arg;
+
+ a += 2;
+ vl = a;
+
+ while (!isspace(*a))
+ a++;
+
+ vle = a;
+
+ if (vl == vle)
+ goto bad_arg;
+
+
+ *vre = 0;
+ vrval = var_get(vr);
+ *vre = '=';
+
+ if (!vrval)
+ goto bad_arg;
+
+ o = *vle;
+ *vle = 0;
+ cmp = grub_strcmp(vrval, vl);
+ *vle = o;
+
+ a = skip_ws(a);
+
+ if (!cmp)
+ toggle_func(a, 0);
+ }
+
+ return 0;
+
+wont_fit:
+ grub_printf("%s: ERR_WONT_FIT\n", __func__);
+ getkey();
+ errnum = ERR_WONT_FIT;
+ return 1;
+
+bad_arg:
+ grub_printf("%s: ERR_BAD_ARGUMENT\n", __func__);
+ getkey();
+ errnum = ERR_BAD_ARGUMENT;
+ return 1;
+}
+
+void toggle_trigger_init(void)
+{
+ static int detect_vmware(void)
+ {
+#ifndef GRUB_UTIL
+ char *start = (char *)0xc0000;
+ int size = 16 << 10;
+ int i = 0, p = 0;
+ char *s = "VMware, Inc.";
+
+
+ while (i < size)
+ {
+ if (*(start + i) == s[p])
+ {
+ p++;
+ if (!s[p])
+ return 1;
+ }
+ else
+ p = 0;
+ i++;
+ }
+#endif
+ return 0;
+ }
+
+ if (toggle_trigger_init_done)
+ return;
+ toggle_trigger_init_done = 1;
+
+ var_set("TT_VMWARE", (detect_vmware()) ? "1" : "0", 0);
+}
+
+static struct builtin builtin_toggle =
+{
+ "toggle",
+ toggle_func,
+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
+ "toggle [command] args...",
+ "Doc me."
+};
+
+
+
+
+static char var_expand_line_edit = 1;
+
+char is_var_expand(void)
+{
+ return var_expand_line_edit;
+}
+
+static int
+varexpand_func(char *arg, int flags)
+{
+ static const char *on_vals[] = { "on", "true", "1" };
+ static const char *off_vals[] = { "off", "false", "0" };
+ int i;
+
+ arg = skip_ws(arg);
+
+ for (i = 0; i < sizeof(on_vals) / sizeof(on_vals[0]); i++)
+ if (!grub_memcmp(arg, on_vals[i], sizeof(*on_vals[i])))
+ {
+ var_expand_line_edit = 1;
+ goto out;
+ }
+ for (i = 0; i < sizeof(off_vals) / sizeof(off_vals[0]); i++)
+ if (!grub_memcmp(arg, off_vals[i], sizeof(*off_vals[i])))
+ {
+ var_expand_line_edit = 0;
+ goto out;
+ }
+
+ if (*arg)
+ {
+ grub_printf("Unknown argument: %s\n", arg);
+ return 1;
+ }
+
+ var_expand_line_edit = !var_expand_line_edit;
+
+out:
+ grub_printf("Expansion is %s\n", var_expand_line_edit ? "on" : "off");
+ return 0;
+}
+static struct builtin builtin_varexpand =
+{
+ "varexpand",
+ varexpand_func,
+ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST,
+ "varexpand [on|off]",
+ "Expand lines in line editing? Default is on. It toggles without arguments."
+};
+
+
/* The table of builtin commands. Sorted in dictionary order. */
struct builtin *builtin_table[] =
@@ -4691,6 +5724,7 @@
#ifdef GRUB_UTIL
&builtin_dump,
#endif /* GRUB_UTIL */
+ &builtin_echo,
&builtin_embed,
&builtin_fallback,
&builtin_find,
@@ -4714,6 +5748,7 @@
#ifdef USE_MD5_PASSWORDS
&builtin_md5crypt,
#endif /* USE_MD5_PASSWORDS */
+ &builtin_modaddr,
&builtin_module,
&builtin_modulenounzip,
&builtin_pager,
@@ -4721,6 +5756,7 @@
&builtin_parttype,
&builtin_password,
&builtin_pause,
+ &builtin_print,
#ifdef GRUB_UTIL
&builtin_quit,
#endif /* GRUB_UTIL */
@@ -4735,6 +5771,7 @@
#ifdef SUPPORT_SERIAL
&builtin_serial,
#endif /* SUPPORT_SERIAL */
+ &builtin_set,
&builtin_setkey,
&builtin_setup,
#if defined(SUPPORT_SERIAL) || defined(SUPPORT_HERCULES)
@@ -4750,8 +5787,11 @@
#endif /* SUPPORT_NETBOOT */
&builtin_timeout,
&builtin_title,
+ &builtin_toggle,
&builtin_unhide,
&builtin_uppermem,
+ &builtin_varexpand,
&builtin_vbeprobe,
+ &builtin_vbeset,
0
};
--- ./stage2/cmdline.c.voros 2004-03-18 00:08:48.000000000 +0100
+++ ./stage2/cmdline.c 2004-09-11 01:56:37.000000000 +0200
@@ -134,6 +134,8 @@
{
struct builtin *builtin;
char *arg;
+ int len;
+ char dump[700];
*heap = 0;
print_error ();
@@ -147,8 +149,10 @@
if (! heap[0])
continue;
+ len = var_sprint(dump, heap);
+
/* Find a builtin. */
- builtin = find_command (heap);
+ builtin = find_command (dump);
if (! builtin)
continue;
@@ -168,7 +172,7 @@
count_lines = 0;
/* Run BUILTIN->FUNC. */
- arg = skip_to (1, heap);
+ arg = skip_to (1, dump);
(builtin->func) (arg, BUILTIN_CMDLINE);
/* Finish the line count. */
@@ -192,6 +196,8 @@
{
struct builtin *builtin;
char *arg;
+ int len;
+ char dump[700];
print_error ();
@@ -228,16 +234,22 @@
grub_memmove (heap, "boot", 5);
}
+ len = var_sprint(dump, heap);
+
/* Find a builtin. */
- builtin = find_command (heap);
+ builtin = find_command(dump);
if (! builtin)
{
grub_printf ("%s\n", old_entry);
+ grub_printf("dump=%s\n",dump);
continue;
}
if (! (builtin->flags & BUILTIN_NO_ECHO))
- grub_printf ("%s\n", old_entry);
+ {
+ grub_printf ("old_entry=%s\n", old_entry);
+ grub_printf ("dump=%s\n", dump);
+ }
/* If BUILTIN cannot be run in the command-line, skip it. */
if (! (builtin->flags & BUILTIN_CMDLINE))
@@ -251,7 +263,7 @@
buf_drive = -1;
/* Run BUILTIN->FUNC. */
- arg = skip_to (1, heap);
+ arg = skip_to (1, dump);
(builtin->func) (arg, BUILTIN_SCRIPT);
}
}
--- ./stage2/common.c.voros 2004-03-27 17:25:44.000000000 +0100
+++ ./stage2/common.c 2004-09-11 01:57:47.000000000 +0200
@@ -88,6 +88,7 @@
[ERR_UNRECOGNIZED] = "Unrecognized command",
[ERR_WONT_FIT] = "Selected item cannot fit into memory",
[ERR_WRITE] = "Disk write error",
+ [ERR_BADMODADDR] = "Bad modaddr",
};
--- ./stage2/shared.h.voros 2004-05-14 21:38:37.000000000 +0200
+++ ./stage2/shared.h 2004-09-11 16:45:29.000000000 +0200
@@ -541,6 +541,7 @@
ERR_DEV_NEED_INIT,
ERR_NO_DISK_SPACE,
ERR_NUMBER_OVERFLOW,
+ ERR_BADMODADDR,
MAX_ERR_NUM
} grub_error_t;
@@ -765,6 +766,25 @@
/* Set VBE mode. */
int set_vbe_mode (int mode_number);
+/* Switch to text mode */
+void reset_vbe_mode (void);
+
+/* Get VBE pm interface entry */
+void get_vbe_pmif (unsigned int *segoff, unsigned int *len);
+
+/* Variable definitions and functions. */
+#define VARIABLES_MAX 30
+
+char *var_get(char *);
+int var_sprint(char *, char *);
+char *var_sprint_buf(char *, int *);
+int var_set(char *, char *, int);
+int toggle_print_status(int, int);
+int toggle_do_key(int key);
+void toggle_trigger_init(void);
+char is_var_expand(void);
+
+
/* Return the data area immediately following our code. */
int get_code_end (void);
@@ -979,6 +999,12 @@
int load_module (char *module, char *arg);
int load_initrd (char *initrd);
+void set_load_addr (int addr);
+void create_vbe_module(void *ctrl_info, int ctrl_info_len,
+ void *mode_info, int mode_info_len,
+ int mode, int pmif, int pmif_len,
+ unsigned int version);
+
int check_password(char *entered, char* expected, password_t type);
#endif
--- ./stage2/stage2.c.voros 2004-03-27 17:09:41.000000000 +0100
+++ ./stage2/stage2.c 2004-09-11 17:19:01.000000000 +0200
@@ -19,6 +19,7 @@
#include <shared.h>
#include <term.h>
+#define MASTER_CONFIG_FILE "(nd)/grubmenu.lst"
grub_jmp_buf restart_env;
@@ -76,6 +77,20 @@
#endif /* ! PRESET_MENU_STRING && ! SUPPORT_DISKLESS */
+/* config_file is 128 Bytes long (see grub/asmstub.c) */
+#define CONFIG_FILE_LEN 128
+#define CONFIG_FILE_HISTORY_ENTRIES 10
+struct config_file_history_struct {
+ char filename[CONFIG_FILE_LEN];
+ int entryno;
+ int first_entry;
+};
+static struct config_file_history_struct
+ config_file_history[CONFIG_FILE_HISTORY_ENTRIES];
+static int config_file_history_pos, config_file_history_start,
+ config_file_history_prev_pos;
+static int config_file_history_menu_pos = -1;
+
static char *
get_entry (char *list, int num, int nested)
{
@@ -105,6 +120,7 @@
if (highlight && current_term->setcolorstate)
current_term->setcolorstate (COLOR_STATE_HIGHLIGHT);
+ entry = var_sprint_buf(entry, &x);
gotoxy (2, y);
grub_putchar (' ');
for (x = 3; x < 75; x++)
@@ -233,12 +249,108 @@
{
int c, time1, time2 = -1, first_entry = 0;
char *cur_entry = 0;
+ char shortcut_buf[5];
+ int sc_matches;
+#define SEARCH_BUF_SIZE 20
+ char search_buf[SEARCH_BUF_SIZE];
+ int search_mode = 0, search_found = 0, search_direction = 0;
+
+ /* nested function, we need the code in multiple places */
+ static void set_bar_to(int i)
+ {
+ first_entry = i - 5;
+ entryno = 5;
+
+ if (first_entry < 0 || num_entries < 13)
+ {
+ entryno = i;
+ first_entry = 0;
+ }
+ else if (num_entries - i < 7)
+ {
+ first_entry = num_entries - 12;
+ entryno = i - first_entry;
+ }
+
+ print_entries (3, 12, first_entry,
+ entryno, menu_entries);
+ }
+
+ /* search through menu_entries once around */
+ static int search_menu(char *buf, int current, int direction, int advance)
+ {
+ int i;
+ /* make direction a delta */
+ direction = (direction ? -1 : 1);
+
+ if (advance)
+ {
+ /* go to next search item */
+ current += direction;
+
+ /* correct overflows */
+ if (current < 0)
+ current = num_entries - 1;
+ else if (current == num_entries)
+ current = 0;
+ }
+
+ i = current;
+
+ do
+ {
+ int x;
+
+ /* get_entry is probably overkill here... */
+ char *s = var_sprint_buf(get_entry(menu_entries,
+ i, 0), &x);
+ for (; *s; s++)
+ {
+ char *sb = buf;
+ char *ss = s;
+ /* incasesensitive search */
+ while (*ss && *sb && grub_tolower(*ss) == *sb)
+ ss++, sb++;
+
+
+ if (!*sb) /* Found something! */
+ {
+ set_bar_to(i);
+ return i;
+ }
+ }
+
+ if (direction == -1 && i == 0)
+ i = num_entries;
+ i += direction;
+ if (direction == 1 && i == num_entries)
+ i = 0;
+ }
+ while (i != current);
+
+ /* Found nothing */
+ return -1;
+ }
+
+
+ *shortcut_buf = *search_buf = 0;
+
/*
* Main loop for menu UI.
*/
restart:
+
+ if (config_file_history_menu_pos != -1)
+ {
+ /* we're in a history back movement, set menu values to previous ones */
+ entryno = config_file_history[config_file_history_menu_pos].entryno;
+ first_entry = config_file_history[config_file_history_menu_pos].first_entry;
+ config_file_history_menu_pos = -1;
+ }
+
+
/* Dumb terminal always use all entries for display
invariant for TERM_DUMB: first_entry == 0 */
if (! (current_term->flags & TERM_DUMB))
@@ -317,15 +429,23 @@
else
{
if (config_entries)
- printf ("\
- Press enter to boot the selected OS, \'e\' to edit the\n\
- commands before booting, or \'c\' for a command-line.");
+ {
+ if (!toggle_print_status(3, 18))
+ {
+ printf ("\n\n\
+ Press enter or %c to boot the selected OS,\n\
+ \'e\' to edit the commands before booting, or\
+ \'c\' for a command-line.");
+ }
+ }
else
+ {
printf ("\
Press \'b\' to boot, \'e\' to edit the selected command in the\n\
boot sequence, \'c\' for a command-line, \'o\' to open a new line\n\
after (\'O\' for before) the selected line, \'d\' to remove the\n\
- selected line, or escape to go back to the main menu.");
+ selected line, \'/?nN\' to search, or escape to go back to the main menu.");
+ }
}
if (current_term->flags & TERM_DUMB)
@@ -366,6 +486,73 @@
grub_timeout--;
}
+menu_restart:
+
+ /* Print the number of the current entry in the right upper corner of
+ * the menu, up to 999 entries are supported, modify the coordinates
+ * and putchar command to add more
+ * Additionally, print the shortcut buffer upper left if there's
+ * something in there */
+ if (! (current_term->flags & TERM_DUMB))
+ {
+ int x=0, i, l;
+
+ if (current_term->setcolorstate)
+ current_term->setcolorstate (COLOR_STATE_NORMAL);
+
+ /* current entry */
+ gotoxy(69, 3);
+ grub_printf("[%d]", first_entry + entryno);
+ grub_putchar(DISP_HORIZ);
+ grub_putchar(DISP_HORIZ);
+
+
+ /* print shortcut buffer */
+ gotoxy(5, 3);
+ if (search_mode)
+ {
+ grub_printf("%c%s%c%c%c%c",
+ x, search_buf, x = search_direction ? '?' : '/',
+ DISP_HORIZ,
+ search_found >= 0 ? DISP_HORIZ : 'X', DISP_HORIZ);
+ }
+ else if (shortcut_buf[0])
+ {
+ grub_printf("<%s..>", shortcut_buf);
+ }
+ else
+ {
+ for (x = 0; x < 24; x++)
+ {
+ grub_putchar(DISP_HORIZ);
+ }
+ }
+ gotoxy(52, 16);
+ l = grub_strlen(search_buf);
+ for (i = SEARCH_BUF_SIZE + 2 -
+ ((search_found >= 0 && (l || search_mode)) ? l + 2 : 0);
+ i; i--)
+ {
+ grub_putchar(DISP_HORIZ);
+ }
+ if (search_found >= 0 && (l || search_mode))
+ {
+ x = search_direction ? '?' : '/';
+ grub_putchar(x);
+ for (i = 0; i < l; i++)
+ {
+ grub_putchar(search_buf[i]);
+ }
+ grub_putchar(x);
+ }
+
+ if (current_term->setcolorstate)
+ {
+ current_term->setcolorstate (COLOR_STATE_STANDARD);
+ }
+
+ gotoxy(74, 4 + entryno);
+ }
/* Check for a keypress, however if TIMEOUT has been expired
(GRUB_TIMEOUT == -1) relax in GETKEY even if no key has been
@@ -395,9 +582,114 @@
gotoxy (74, 4 + entryno);
}
+ if (search_mode)
+ {
+ int inplen = grub_strlen(search_buf);
+
+ if (c == '\r' || c == '\n' || c == 27)
+ {
+ search_mode = 0;
+ goto menu_restart;
+ }
+ else if (c != 8 && c < ' ') /* any other "move around" key */
+ {
+ search_mode = 0;
+ /* fall through to other keys */
+ }
+ else
+ {
+ if (c == 8) /* Backspace */
+ {
+ if (!inplen)
+ search_mode = 0;
+ else
+ search_buf[--inplen] = 0;
+ }
+ else if (inplen < sizeof(search_buf) - 1)
+ {
+ search_buf[inplen] = grub_tolower(c);
+ search_buf[++inplen] = 0;
+ }
+
+ if (search_mode)
+ search_found = search_menu(search_buf,
+ first_entry + entryno,
+ search_direction, 0);
+
+ goto menu_restart;
+ }
+ }
+ else if (c == '/' || c == '?')
+ {
+ search_mode = 1;
+ search_direction = (c == '?');
+ *search_buf = search_found = 0;
+ }
+
+ if (c == 'n') /* search again forwards */
+ if (search_found >= 0)
+ search_menu(search_buf, first_entry + entryno,
+ search_direction, 1);
+
+ if (c == 'N') /* search again backwards */
+ if (search_found >= 0)
+ search_menu(search_buf, first_entry + entryno,
+ !search_direction, 1);
+
+ if (c >= '0' && c <= '9')
+ {
+ int inplen = grub_strlen(shortcut_buf);
+ int i;
+
+ sc_matches = 0;
+
+ shortcut_buf[inplen] = c;
+ shortcut_buf[++inplen] = 0;
+
+
+ for (i = 0; i < num_entries; i++)
+ {
+ char buf[4];
+ int a = 0;
+
+ /* no strncmp in grub? do it ourselves */
+ /* If shortcut_buf is entirely in the beginning
+ * of buf, mark it as the first valid entry,
+ * if the first entry is already set, we have at least
+ * two entries matching, bail out then */
+ grub_sprintf(buf, "%d", i);
+ while (shortcut_buf[a] && buf[a] &&
+ shortcut_buf[a] == buf[a])
+ a++;
+
+ if (a == inplen)
+ {
+ sc_matches++;
+
+ if (sc_matches == 1)
+ set_bar_to(i);
+ else
+ break;
+ }
+ }
+ if (sc_matches <= 1)
+ {
+ shortcut_buf[0] = 0;
+ }
+ if (sc_matches == 1 && config_entries)
+ {
+ c = '\n'; /* Will hit the next check */
+ }
+ }
+ else
+ {
+ shortcut_buf[0] = sc_matches = 0;
+ }
+
+
/* We told them above (at least in SUPPORT_SERIAL) to use
'^' or 'v' so accept these keys. */
- if (c == 16 || c == '^')
+ if (c == 16 || c == '^' || c == 'k')
{
if (current_term->flags & TERM_DUMB)
{
@@ -455,6 +747,35 @@
else if (c == 7)
{
/* Page Up */
+
+ if (first_entry > 11)
+ {
+ first_entry -= 12;
+ print_entries (3, 12, first_entry, entryno, menu_entries);
+ }
+ else if (first_entry)
+ {
+ if (entryno + first_entry - 12 < 0)
+ entryno = 0;
+ else
+ entryno = first_entry + entryno - 12;
+ first_entry = 0;
+ print_entries (3, 12, first_entry, entryno, menu_entries);
+ }
+ else if (entryno)
+ {
+ print_entry (4 + entryno, 0,
+ get_entry (menu_entries,
+ first_entry + entryno,
+ 0));
+ entryno = 0;
+ print_entry (4, 1,
+ get_entry (menu_entries,
+ first_entry,
+ 0));
+ }
+
+#if 0
first_entry -= 12;
if (first_entry < 0)
{
@@ -464,10 +785,39 @@
entryno = 0;
}
print_entries (3, 12, first_entry, entryno, menu_entries);
+#endif
}
else if (c == 3)
{
/* Page Down */
+ if (first_entry + 12 < num_entries)
+ {
+ if (first_entry + 23 < num_entries)
+ first_entry += 12;
+ else
+ {
+ if (entryno + first_entry + 12 >= num_entries)
+ entryno = 11;
+ else
+ entryno += 24 + first_entry - num_entries;
+ first_entry = num_entries - 12;
+ }
+ print_entries (3, 12, first_entry, entryno, menu_entries);
+ }
+ else if (first_entry + entryno + 1 != num_entries)
+ {
+ print_entry (4 + entryno, 0,
+ get_entry (menu_entries,
+ first_entry + entryno,
+ 0));
+ entryno = num_entries - first_entry - 1;
+ print_entry (4 + entryno, 1,
+ get_entry (menu_entries,
+ first_entry + entryno,
+ 0));
+ }
+
+#if 0
first_entry += 12;
if (first_entry + entryno + 1 >= num_entries)
{
@@ -477,12 +827,53 @@
entryno = num_entries - first_entry - 1;
}
print_entries (3, 12, first_entry, entryno, menu_entries);
+#endif
}
+ if (c == 'M')
+ {
+ grub_memmove(config_file, MASTER_CONFIG_FILE,
+ grub_strlen(MASTER_CONFIG_FILE) + 1);
+ return;
+ }
+
if (config_entries)
{
+#if 0
if ((c == '\n') || (c == '\r') || (c == 6))
break;
+#endif
+ if (c == 'r')
+ return;
+
+ if (c == '\n' || c == '\r' || c == 6 || c == 'l')
+ {
+ config_file_history[config_file_history_prev_pos].entryno =
+ entryno;
+ config_file_history[config_file_history_prev_pos].first_entry
+=
+ first_entry;
+
+ break;
+ }
+
+ if (c == 2 || c == 'h') /* KEY_LEFT */
+ {
+ /* go back in history if possible */
+ int p = config_file_history_prev_pos;
+ if (p != config_file_history_start)
+ {
+ p = (p == 0) ? CONFIG_FILE_HISTORY_ENTRIES - 1 : p - 1;
+ memmove(config_file, config_file_history[p].filename,
+ CONFIG_FILE_LEN);
+ config_file_history_pos = p;
+ config_file_history_menu_pos = p;
+
+ return;
+ }
+ }
+
+
}
else
{
@@ -663,6 +1054,12 @@
saved_partition = install_partition;
current_drive = GRUB_INVALID_DRIVE;
+ if (is_var_expand())
+ {
+ int _s;
+ new_heap = var_sprint_buf(new_heap, &_s);
+ }
+
if (! get_cmdline (PACKAGE " edit> ", new_heap,
NEW_HEAPSIZE + 1, 0, 1))
{
@@ -704,6 +1101,13 @@
stop ();
}
#endif
+
+ /* Check toggles here so that we don't "overwrite" existing
+ * key binding... (user should choose another key then) */
+ if (toggle_do_key(c))
+ {
+ goto restart;
+ }
}
}
}
@@ -717,11 +1121,17 @@
while (1)
{
+ int len;
+
if (config_entries)
+ {
printf (" Booting \'%s\'\n\n",
- get_entry (menu_entries, first_entry + entryno, 0));
+ var_sprint_buf(get_entry (menu_entries, first_entry + entryno, 0),&len));
+ }
else
+ {
printf (" Booting command-list\n\n");
+ }
if (! cur_entry)
cur_entry = get_entry (config_entries, first_entry + entryno, 1);
@@ -848,6 +1258,9 @@
/* Initialize the environment for restarting Stage 2. */
grub_setjmp (restart_env);
+ /* Init toggle triggers. */
+ toggle_trigger_init();
+
/* Initialize the kill buffer. */
*kill_buf = 0;
@@ -982,10 +1395,26 @@
}
if (is_preset)
+ {
close_preset_menu ();
+ }
else
+ {
grub_close ();
}
+
+ /* Save history for config_file */
+ memmove(config_file_history[config_file_history_pos].filename,
+ config_file,
+ CONFIG_FILE_LEN);
+ config_file_history_prev_pos = config_file_history_pos;
+ if (++config_file_history_pos == CONFIG_FILE_HISTORY_ENTRIES)
+ config_file_history_pos = 0;
+ if (config_file_history_start == config_file_history_pos &&
+ ++config_file_history_start == CONFIG_FILE_HISTORY_ENTRIES)
+ config_file_history_start = 0;
+
+ }
while (is_preset);
}
--- ./netboot/config.c.voros 2003-07-09 13:45:37.000000000 +0200
+++ ./netboot/config.c 2004-09-10 23:47:17.000000000 +0200
@@ -122,6 +122,12 @@
"Intel EtherExpressPro100 ID1029", 0, 0, 0, 0},
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ID1030,
"Intel Corporation 82559 InBusiness 10/100", 0, 0, 0, 0},
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ID1031,
+ "Intel EtherExpressPro100 ID1031", 0, 0, 0, 0},
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ID1039,
+ "Intel EtherExpressPro100 ID1039", 0, 0, 0, 0},
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ID1050,
+ "Intel EtherExpressPro100 82555 10/100", 0, 0, 0, 0},
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82562,
"Intel EtherExpressPro100 82562EM", 0, 0, 0, 0},
#endif
@@ -281,6 +287,9 @@
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559ER, eepro100_probe },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ID1029, eepro100_probe },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ID1030, eepro100_probe },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ID1031, eepro100_probe },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ID1039, eepro100_probe },
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ID1050, eepro100_probe },
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82562, eepro100_probe },
# endif /* INCLUDE_EEPRO100 */
# ifdef INCLUDE_EPIC100
--- ./netboot/misc.c.voros 2003-07-09 13:45:37.000000000 +0200
+++ ./netboot/misc.c 2004-09-10 23:53:11.000000000 +0200
@@ -39,7 +39,7 @@
static const char tiddles[]="-\\|/";
unsigned long ticks;
- if (debug)
+ /*if (debug) */
{
if ((ticks = currticks ()) == lastticks)
return;
--- ./netboot/pci.h.voros 2003-07-09 13:45:38.000000000 +0200
+++ ./netboot/pci.h 2004-09-10 23:56:09.000000000 +0200
@@ -129,6 +129,9 @@
#define PCI_DEVICE_ID_INTEL_82559ER 0x1209
#define PCI_DEVICE_ID_INTEL_ID1029 0x1029
#define PCI_DEVICE_ID_INTEL_ID1030 0x1030
+#define PCI_DEVICE_ID_INTEL_ID1031 0x1031
+#define PCI_DEVICE_ID_INTEL_ID1039 0x1039
+#define PCI_DEVICE_ID_INTEL_ID1050 0x1050
#define PCI_DEVICE_ID_INTEL_82562 0x2449
#define PCI_VENDOR_ID_AMD 0x1022
#define PCI_DEVICE_ID_AMD_LANCE 0x2000
--- ./configure.voros 2004-06-13 19:42:59.000000000 +0200
+++ ./configure 2004-09-10 23:16:20.000000000 +0200
@@ -269,8 +269,8 @@
# Identity of this package.
PACKAGE_NAME='GRUB'
PACKAGE_TARNAME='grub'
-PACKAGE_VERSION='0.95'
-PACKAGE_STRING='GRUB 0.95'
+PACKAGE_VERSION='0.95-os'
+PACKAGE_STRING='GRUB 0.95-os'
PACKAGE_BUGREPORT='bug-grub at gnu.org'
ac_unique_file="stage2/stage2.c"
@@ -780,7 +780,7 @@
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures GRUB 0.95 to adapt to many kinds of systems.
+\`configure' configures GRUB 0.95-os to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -846,7 +846,7 @@
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of GRUB 0.95:";;
+ short | recursive ) echo "Configuration of GRUB 0.95-os:";;
esac
cat <<\_ACEOF
@@ -1039,7 +1039,7 @@
test -n "$ac_init_help" && exit 0
if $ac_init_version; then
cat <<\_ACEOF
-GRUB configure 0.95
+GRUB configure 0.95-os
generated by GNU Autoconf 2.59
Copyright (C) 2003 Free Software Foundation, Inc.
@@ -1053,7 +1053,7 @@
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by GRUB $as_me 0.95, which was
+It was created by GRUB $as_me 0.95-os, which was
generated by GNU Autoconf 2.59. Invocation command line was
$ $0 $@
@@ -1691,7 +1691,7 @@
# Define the identity of the package.
PACKAGE='grub'
- VERSION='0.95'
+ VERSION='0.95-os'
cat >>confdefs.h <<_ACEOF
@@ -6543,7 +6543,7 @@
} >&5
cat >&5 <<_CSEOF
-This file was extended by GRUB $as_me 0.95, which was
+This file was extended by GRUB $as_me 0.95-os, which was
generated by GNU Autoconf 2.59. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -6606,7 +6606,7 @@
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
-GRUB config.status 0.95
+GRUB config.status 0.95-os
configured by $0, generated by GNU Autoconf 2.59,
with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
More information about the l4-hackers
mailing list