Files
bpfire/src/patches/SuSE10.2/grub-gfxmenu-v8.diff
casemaster 73276c912a Update des GFXBoot-Patches für GRUB aus SuSE 10.2 v8.
Startbild aktualisiert.

git-svn-id: http://svn.ipfire.org/svn/ipfire/trunk@285 ea5c0bd1-69bd-2848-81d8-4f18e57aeed8
2006-09-19 06:53:10 +00:00

995 lines
21 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
--- docs/grub.texi
+++ docs/grub.texi
@@ -2118,6 +2118,7 @@
* default:: Set the default entry
* fallback:: Set the fallback entry
* hiddenmenu:: Hide the menu interface
+* gfxmenu:: Use graphical menu interface
* timeout:: Set the timeout
* title:: Start a menu entry
@end menu
@@ -2150,6 +2151,15 @@
@end deffn
+@node gfxmenu
+@subsection gfxmenu
+
+@deffn Command gfxmenu file
+Use the graphical menu interface. The graphics data are taken from
+@var{file} and must be created using 'mkbootmsg' from the gfxboot package.
+@end deffn
+
+
@node hiddenmenu
@subsection hiddenmenu
--- grub/asmstub.c
+++ grub/asmstub.c
@@ -498,6 +498,32 @@
return 0;
}
+/* graphical menu functions . */
+int
+gfx_init (gfx_data_t *gfx_data)
+{
+ return 0;
+}
+
+int
+gfx_done (gfx_data_t *gfx_data)
+{
+ return 0;
+}
+
+int
+gfx_input (gfx_data_t *gfx_data, int *menu_entry)
+{
+ return 0;
+}
+
+int
+gfx_setup_menu (gfx_data_t *gfx_data)
+{
+ return 0;
+}
+
+
/* low-level timing info */
int
getrtsecs (void)
--- stage2/asm.S
+++ stage2/asm.S
@@ -1614,6 +1614,286 @@
popl %ebp
ret
+
+/*
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ *
+ * graphical menu functions
+ *
+ */
+
+/*
+ * int gfx_init (gfx_data_t *gfx_data)
+ *
+ * init gfx things
+ *
+ * return vales:
+ * 0: ok
+ * 1: failed
+ * sets gfx_data->ok
+ */
+
+ENTRY(gfx_init)
+ pushl %ebp
+ movl %esp, %ebp
+
+ pushl %edi
+ pushl %esi
+ pushl %ebx
+
+ movl 8(%ebp),%edx
+ movl %edx,%edi
+ leal gfx_ofs_sys_cfg(%edx),%esi
+ andl $0xf,%edi
+ shrl $4,%edx
+
+ pushl %ebp
+
+ call EXT_C(prot_to_real)
+ .code16
+
+ pushw %ds
+ movw %dx,%ds
+
+ lcall *gfx_ofs_jmp_table + 4 * 0 (%di)
+
+ sbbl %ebx,%ebx
+ negl %ebx
+
+ popw %ds
+
+ DATA32 call EXT_C(real_to_prot)
+ .code32
+
+ popl %ebp
+
+ movl %ebx,%eax
+ xorl $1,%ebx
+ movl 8(%ebp),%edx
+ movl %ebx,gfx_ofs_ok(%edx)
+
+ popl %ebx
+ popl %esi
+ popl %edi
+
+ popl %ebp
+ ret
+
+
+/*
+ * int gfx_done (gfx_data_t *gfx_data)
+ *
+ * shut down gfx things
+ *
+ * return vales:
+ * always 0
+ * sets gfx_data->ok
+ */
+
+ENTRY(gfx_done)
+ pushl %ebp
+ movl %esp, %ebp
+
+ pushl %edi
+ pushl %esi
+ pushl %ebx
+
+ movl 8(%ebp),%edx
+ movl %edx,%ebx
+ andl $0xf,%ebx
+ shrl $4,%edx
+
+ pushl %ebp
+
+ call EXT_C(prot_to_real)
+ .code16
+
+ pushw %ds
+
+ movw %dx,%ds
+
+ lcall *gfx_ofs_jmp_table + 4 * 1 (%bx)
+
+ popw %ds
+
+ DATA32 call EXT_C(real_to_prot)
+ .code32
+
+ popl %ebp
+
+ xorl %eax,%eax
+ movl 8(%ebp),%edx
+ movl %eax,gfx_ofs_ok(%edx)
+
+ popl %ebx
+ popl %esi
+ popl %edi
+
+ popl %ebp
+ ret
+
+
+/*
+ * int gfx_input (gfx_data_t *gfx_data, int *menu_entry)
+ *
+ * let user enter a command line
+ *
+ * uses gfx_data->cmdline as buffer
+ *
+ * return values:
+ * 1: abort
+ * 2: boot
+ * menu_entry: selected entry
+ */
+
+ENTRY(gfx_input)
+ pushl %ebp
+ movl %esp, %ebp
+
+ pushl %edi
+ pushl %esi
+ pushl %ebx
+
+ movl 8(%ebp),%edx
+ movl %edx,%ebx
+ leal gfx_ofs_sys_cfg(%edx),%esi
+ andl $0xf,%ebx
+ shrl $4,%edx
+
+ pushl %ebp
+
+ call EXT_C(prot_to_real)
+ .code16
+
+ pushw %ds
+
+ movw %dx,%ds
+
+ movl gfx_ofs_cmdline(%bx),%edi
+ movl gfx_ofs_cmdline_len(%bx),%ecx
+ movl gfx_ofs_timeout(%bx),%eax
+ imull $18,%eax
+
+ lcall *gfx_ofs_jmp_table + 4 * 2 (%bx)
+
+ movl %eax,%ecx
+
+ popw %ds
+
+ DATA32 call EXT_C(real_to_prot)
+ .code32
+
+ popl %ebp
+
+ movl 12(%ebp),%edx
+ movl %ebx,(%edx)
+
+ movl %ecx,%eax
+
+ popl %ebx
+ popl %esi
+ popl %edi
+
+ popl %ebp
+ ret
+
+
+/*
+ * int gfx_setup_menu (gfx_data_t *gfx_data)
+ *
+ * draw boot menu
+ *
+ * return values:
+ * always 0
+ */
+
+/* menu entry descriptor */
+#define menu_entries 0
+#define menu_default 2 /* seg:ofs */
+#define menu_ent_list 6 /* seg:ofs */
+#define menu_ent_size 10
+#define menu_arg_list 12 /* seg:ofs */
+#define menu_arg_size 16
+#define sizeof_menu_desc 18
+
+ENTRY(gfx_setup_menu)
+ pushl %ebp
+ movl %esp, %ebp
+
+ pushl %edi
+ pushl %esi
+ pushl %ebx
+
+ movl 8(%ebp),%edx
+ movl %edx,%ebx
+ andl $0xf,%ebx
+ shrl $4,%edx
+
+ call EXT_C(prot_to_real)
+ .code16
+
+ pushw %ds
+
+ movw %dx,%ds
+ shll $4,%edx
+
+ subw $sizeof_menu_desc,%sp
+ movw %esp,%ebp
+
+ movl gfx_ofs_menu_entries(%bx),%eax
+ movw %ax,menu_entries(%bp)
+
+ movl gfx_ofs_menu_default_entry(%bx),%eax
+ subl %edx,%eax
+ movw %ax,menu_default(%bp)
+ movw %ds,menu_default+2(%bp)
+
+ movl gfx_ofs_menu_list(%bx),%eax
+ subl %edx,%eax
+ movw %ax,menu_ent_list(%bp)
+ movw %ds,menu_ent_list+2(%bp)
+
+ movl gfx_ofs_menu_entry_len(%bx),%eax
+ movw %ax,menu_ent_size(%bp)
+
+ movl gfx_ofs_args_list(%bx),%eax
+ subl %edx,%eax
+ movw %ax,menu_arg_list(%bp)
+ movw %ds,menu_arg_list+2(%bp)
+
+ movl gfx_ofs_args_entry_len(%bx),%eax
+ movw %ax,menu_arg_size(%bp)
+
+ movl %ss,%esi
+ shll $4,%esi
+ addl %ebp,%esi
+
+ lcall %ds: *gfx_ofs_jmp_table + 4 * 3 (%bx)
+
+ addw $sizeof_menu_desc,%sp
+
+ popw %ds
+
+ DATA32 call EXT_C(real_to_prot)
+ .code32
+
+ xorl %eax,%eax
+
+ popl %ebx
+ popl %esi
+ popl %edi
+
+ popl %ebp
+ ret
+
+
+/*
+ *
+ * end graphics stuff
+ *
+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ */
+
/*
* gateA20(int linear)
--- stage2/builtins.c
+++ stage2/builtins.c
@@ -63,6 +63,8 @@
int fallback_entries[MAX_FALLBACK_ENTRIES];
/* The number of current entry. */
int current_entryno;
+/* graphics file */
+char graphics_file[64];
/* The address for Multiboot command-line buffer. */
static char *mb_cmdline;
/* The password. */
@@ -1351,6 +1353,26 @@
};
+/* graphics */
+static int
+gfxmenu_func (char *arg, int flags)
+{
+ memmove(graphics_file, arg, sizeof graphics_file - 1);
+ graphics_file[sizeof graphics_file - 1] = 0;
+
+ return 0;
+}
+
+static struct builtin builtin_gfxmenu =
+{
+ "gfxmenu",
+ gfxmenu_func,
+ BUILTIN_MENU | BUILTIN_HELP_LIST,
+ "gfxmenu FILE",
+ "Use the graphical menu from FILE."
+};
+
+
/* geometry */
static int
geometry_func (char *arg, int flags)
@@ -4874,6 +4896,7 @@
&builtin_find,
&builtin_fstest,
&builtin_geometry,
+ &builtin_gfxmenu,
&builtin_halt,
&builtin_help,
&builtin_hiddenmenu,
--- stage2/shared.h
+++ stage2/shared.h
@@ -374,6 +374,22 @@
#endif /* WITHOUT_LIBC_STUBS */
+/* see typedef gfx_data_t below */
+#define gfx_ofs_ok 0x00
+#define gfx_ofs_code_seg 0x04
+#define gfx_ofs_jmp_table 0x08
+#define gfx_ofs_sys_cfg 0x38
+#define gfx_ofs_cmdline 0x6c
+#define gfx_ofs_cmdline_len 0x70
+#define gfx_ofs_menu_list 0x74
+#define gfx_ofs_menu_default_entry 0x78
+#define gfx_ofs_menu_entries 0x7c
+#define gfx_ofs_menu_entry_len 0x80
+#define gfx_ofs_args_list 0x84
+#define gfx_ofs_args_entry_len 0x88
+#define gfx_ofs_timeout 0x8c
+
+
#ifndef ASM_FILE
/*
* Below this should be ONLY defines and other constructs for C code.
@@ -595,6 +611,38 @@
extern int default_entry;
extern int current_entryno;
+
+/*
+ * graphics menu stuff
+ *
+ * Note: gfx_data and all data referred to in it must lie within a 64k area.
+ */
+typedef struct {
+ unsigned ok; /* set while we're in graphics mode */
+ unsigned code_seg; /* code segment of binary graphics code */
+ unsigned jmp_table[12]; /* link to graphics functions */
+ unsigned char sys_cfg[52]; /* sys_cfg[0]: identifies boot loader (grub == 2) */
+ char *cmdline; /* command line returned by gfx_input() */
+ unsigned cmdline_len; /* length of the above */
+ char *menu_list; /* list of menu entries, each of fixed length (menu_entry_len) */
+ char *menu_default_entry; /* the default entry */
+ unsigned menu_entries; /* number of entries in menu_list */
+ unsigned menu_entry_len; /* one entry */
+ char *args_list; /* same structure as menu_list, menu_entries entries */
+ unsigned args_entry_len; /* one entry */
+ unsigned timeout; /* in seconds (0: no timeout) */
+} __attribute__ ((packed)) gfx_data_t;
+
+extern gfx_data_t *graphics_data;
+
+/* pointer to graphics image data */
+extern char graphics_file[64];
+
+int gfx_init(gfx_data_t *gfx_data);
+int gfx_done(gfx_data_t *gfx_data);
+int gfx_input(gfx_data_t *gfx_data, int *menu_entry);
+int gfx_setup_menu(gfx_data_t *gfx_data);
+
/* The constants for password types. */
typedef enum
{
--- stage2/stage2.c
+++ stage2/stage2.c
@@ -22,6 +22,8 @@
grub_jmp_buf restart_env;
+gfx_data_t *graphics_data;
+
#if defined(PRESET_MENU_STRING) || defined(SUPPORT_DISKLESS)
# if defined(PRESET_MENU_STRING)
@@ -310,6 +312,12 @@
if (! auth && password)
{
+ if (*graphics_file)
+ {
+ printf ("\
+ WARNING: graphical menu doesn\'t work\
+ in conjunction with the password feature\n" );
+ }
printf ("\
Press enter to boot the selected OS or \'p\' to enter a\n\
password to unlock the next set of features.");
@@ -753,6 +761,493 @@
}
+
+#if 0
+/* for debugging */
+static void hexdump(unsigned char *buf, unsigned len)
+{
+ int i, j = 0;
+ char s[17];
+ unsigned addr = (unsigned) buf;
+
+ s[16] = 0;
+ while(len--) {
+ i = buf[j];
+ i = i & 0xff;
+ s[j & 15] = (i >= 0x20 && i <= 0x7e) ? i : '.';
+ if(!(j & 15)) {
+ printf("%x ", j + addr);
+ }
+ if(!(j & 7) && (j & 15)) printf(" ");
+ /* stupid grub_printf */
+ printf("%x", (i >> 4) & 0x0f);
+ printf("%x ", i & 0x0f);
+ if(!(++j & 15)) {
+ printf(" %s\n", s);
+ }
+ }
+
+ if(j & 15) {
+ s[j & 15] = 0;
+ if(!(j & 8)) printf(" ");
+ i = 1 + 3 * (16 - (j & 15));
+ while(i--) printf(" ");
+ printf("%s\n", s);
+ }
+}
+#endif
+
+
+/* kernel + (grub-)module options */
+#define GFX_CMD_BUF_SIZE 512
+
+/* command line separator char */
+#define GFX_CMD_SEP 1
+
+/*
+ * Go through config entry and find kernel args, if any.
+ * Put things into buf and return it.
+ */
+static char *get_kernel_args(char *cfg, char *buf)
+{
+ int i, j;
+ char *s, *t = "", *p, *t2;
+
+ *(p = buf) = 0;
+
+ for(j = 0; ; j++) {
+ s = get_entry(cfg, j, 0);
+ if(!*s) break;
+ if(
+ (!memcmp(s, "kernel", 6) || !memcmp(s, "module", 6)) &&
+ (s[6] == ' ' || s[6] == '\t')
+ ) {
+ t = skip_to(0, s);
+ t2 = s[0] == 'm' ? strstr(t, "initrd") : NULL;
+ if(*t) t = skip_to(0, t);
+ if(t2 && t2 < t) break; /* module is likely a normal initrd -> skip */
+ i = strlen(t);
+ if(p - buf + i > GFX_CMD_BUF_SIZE - 2) break;
+ *p++ = GFX_CMD_SEP;
+ strcpy(p, t);
+ p += i;
+
+ continue;
+ }
+ }
+
+ if(*buf) buf++; /* skip initial separator char */
+
+ return buf;
+}
+
+
+/*
+ * Check header and return code start offset.
+ */
+static unsigned magic_ok(unsigned char *buf)
+{
+ if(
+ *(unsigned *) buf == 0x0b2d97f00 && /* magic id */
+ (buf[4] == 8) /* version 8 */
+ ) {
+ return *(unsigned *) (buf + 8);
+ }
+
+ return 0;
+}
+
+
+/*
+ * Search cpio archive for gfx file.
+ */
+static unsigned find_file(unsigned char *buf, unsigned len, unsigned *gfx_file_start, unsigned *file_len)
+{
+ unsigned i, fname_len, code_start = 0;
+
+ *gfx_file_start = 0;
+
+ for(i = 0; i < len;) {
+ if((len - i) >= 0x1a && (buf[i] + (buf[i + 1] << 8)) == 0x71c7) {
+ fname_len = *(unsigned short *) (buf + i + 20);
+ *file_len = *(unsigned short *) (buf + i + 24) + (*(unsigned short *) (buf + i + 22) << 16);
+ i += 26 + fname_len;
+ i = ((i + 1) & ~1);
+ if((code_start = magic_ok(buf + i))) {
+ *gfx_file_start = i;
+ return code_start;
+ }
+ i += *file_len;
+ i = ((i + 1) & ~1);
+ }
+ else {
+ break;
+ }
+ }
+
+ return code_start;
+}
+
+static inline unsigned char * stack_ptr(void)
+{
+ unsigned char * u;
+
+ asm("movl %%esp, %0" : "=r" (u));
+
+ return u;
+}
+
+static void sleep(int delay)
+{
+ int tick, last_tick = currticks();
+
+ delay *= 18;
+
+ while(delay--) {
+ while((tick = currticks()) == last_tick) { }
+ last_tick = tick;
+ }
+}
+
+static void wait_for_key()
+{
+ printf("Press a key to continue...");
+ getkey();
+ printf("\r \r");
+}
+
+
+/*
+ * Leave that much space on the heap. Everything else goes to the graphics
+ * functions.
+ *
+ * 0x2000 is _not_ enough
+ */
+#define MIN_HEAP_SIZE 0x4000
+#define MIN_GFX_FREE 0x1000
+
+#define SC_BOOTLOADER 0
+#define SC_FAILSAFE 3
+#define SC_SYSCONFIG_SIZE 4
+#define SC_BOOTLOADER_SEG 8
+#define SC_XMEM_0 24
+#define SC_XMEM_1 26
+#define SC_XMEM_2 28
+#define SC_XMEM_3 30
+#define SC_FILE 32
+#define SC_ARCHIVE_START 36
+#define SC_ARCHIVE_END 40
+#define SC_MEM0_START 44
+#define SC_MEM0_END 48
+
+/*
+ * Does normally not return.
+ */
+static void
+run_graphics_menu (char *menu_entries, char *config_entries, int num_entries,
+ char *heap, int entryno)
+{
+ unsigned char *buf, *buf_ext;
+ unsigned buf_size, buf_ext_size, code_start, file_start;
+ char *s, *t, *t2, *cfg, *new_config, *p;
+ char *saved_heap;
+ int i, j, max_len, gfx_file_size, verbose;
+ int selected_entry;
+ gfx_data_t *gfx_data;
+ char *cmd_buf;
+ unsigned mem0_start, mem0_end, file_len;
+
+ /*
+ * check gfx_data_t struct offsets for consistency; gcc will optimize away
+ * the whole block
+ */
+
+ /* dummy function to make ld fail */
+ {
+ extern void wrong_struct_size(void);
+ #define gfx_ofs_check(a) if(gfx_ofs_##a != (char *) &gfx_data->a - (char *) gfx_data) wrong_struct_size();
+ gfx_ofs_check(ok);
+ gfx_ofs_check(code_seg);
+ gfx_ofs_check(jmp_table);
+ gfx_ofs_check(sys_cfg);
+ gfx_ofs_check(cmdline);
+ gfx_ofs_check(cmdline_len);
+ gfx_ofs_check(menu_list);
+ gfx_ofs_check(menu_default_entry);
+ gfx_ofs_check(menu_entries);
+ gfx_ofs_check(menu_entry_len);
+ gfx_ofs_check(args_list);
+ gfx_ofs_check(args_entry_len);
+ gfx_ofs_check(timeout);
+ #undef gfx_ofs_check
+ }
+
+ if(!num_entries) return;
+
+ graphics_data = gfx_data = (gfx_data_t *) heap;
+ heap += sizeof *gfx_data;
+ memset(gfx_data, 0, sizeof *gfx_data);
+
+ gfx_data->sys_cfg[SC_BOOTLOADER] = 2; /* bootloader: grub */
+ gfx_data->sys_cfg[SC_SYSCONFIG_SIZE] = 52; /* config data size */
+ *(unsigned short *) (gfx_data->sys_cfg + SC_BOOTLOADER_SEG) = (unsigned) gfx_data >> 4; /* segment */
+ gfx_data->sys_cfg[SC_XMEM_0] = 0x21; /* 1MB @ 2MB */
+ gfx_data->sys_cfg[SC_XMEM_1] = 0x41; /* 1MB @ 4MB */
+ verbose = (*(unsigned char *) 0x417) & 3 ? 1 : 0; /* SHIFT pressed */
+ gfx_data->sys_cfg[SC_FAILSAFE] = verbose;
+
+ gfx_data->timeout = grub_timeout >= 0 ? grub_timeout : 0;
+
+
+ /* setup command line edit buffer */
+
+ gfx_data->cmdline_len = 256;
+
+ gfx_data->cmdline = heap;
+ heap += gfx_data->cmdline_len;
+ memset(gfx_data->cmdline, 0, gfx_data->cmdline_len);
+
+ cmd_buf = heap;
+ heap += GFX_CMD_BUF_SIZE;
+
+ /* setup menu entries */
+
+ for(i = max_len = 0; i < num_entries; i++) {
+ j = strlen(get_entry(menu_entries, i, 0));
+ if(j > max_len) max_len = j;
+ }
+
+ if(!max_len) return;
+
+ gfx_data->menu_entry_len = max_len + 1;
+ gfx_data->menu_entries = num_entries;
+
+ gfx_data->menu_list = heap;
+ heap += gfx_data->menu_entry_len * gfx_data->menu_entries;
+
+ memset(gfx_data->menu_list, 0, gfx_data->menu_entry_len * gfx_data->menu_entries);
+
+ for(i = 0; i < (int) gfx_data->menu_entries; i++) {
+ strcpy(gfx_data->menu_list + i * gfx_data->menu_entry_len, get_entry(menu_entries, i, 0));
+ }
+
+ gfx_data->menu_default_entry = gfx_data->menu_list + entryno * gfx_data->menu_entry_len;
+
+
+ /* setup list of kernel args */
+
+ for(i = max_len = 0; i < num_entries; i++) {
+ s = get_kernel_args(get_entry(config_entries, i, 1), cmd_buf);
+ j = strlen(s);
+ if(j > max_len) max_len = j;
+ }
+
+ gfx_data->args_entry_len = max_len + 1;
+
+ gfx_data->args_list = heap;
+ heap += gfx_data->args_entry_len * gfx_data->menu_entries;
+
+ memset(gfx_data->args_list, 0, gfx_data->args_entry_len * gfx_data->menu_entries);
+
+ for(i = 0; i < (int) gfx_data->menu_entries; i++) {
+ strcpy(gfx_data->args_list + i* gfx_data->args_entry_len, get_kernel_args(get_entry(config_entries, i, 1), cmd_buf));
+ }
+
+
+ /* go back here when we no longer need the graphics data */
+ saved_heap = heap;
+
+
+ /* get memory area to be used by graphics functions */
+
+ /* use 1MB starting at 2MB as file buffer */
+ buf_ext = (unsigned char *) (2 << 20);
+ buf_ext_size = 1 << 20;
+
+ /* must be 16-byte aligned */
+ buf = (unsigned char *) (((unsigned) heap + 0xf) & ~0xf);
+
+ buf_size = stack_ptr() - buf - MIN_HEAP_SIZE;
+ buf_size &= ~0xf;
+
+ mem0_start = (unsigned) buf;
+ mem0_end = mem0_start + buf_size;
+
+ if(verbose) {
+ printf("low memory 0x%x - 0x%x (%d bytes)\n", mem0_start, mem0_end, buf_size);
+ wait_for_key();
+ }
+
+ heap += buf_size;
+
+ /* read the file */
+
+ if(!grub_open(graphics_file)) {
+ printf("%s: file not found\n", graphics_file);
+ sleep(5);
+ heap = saved_heap;
+ return;
+ }
+
+ gfx_file_size = grub_read(buf_ext, buf_ext_size);
+
+ grub_close();
+
+ if(gfx_file_size <= 0) {
+ printf("%s: read error\n", graphics_file);
+ sleep(5);
+ heap = saved_heap;
+ return;
+ }
+
+ if(verbose) {
+ printf("%s: %d bytes (%d bytes left)\n", graphics_file, gfx_file_size, buf_ext_size - gfx_file_size);
+ wait_for_key();
+ }
+
+ /* locate file inside cpio archive */
+ if(!(code_start = find_file(buf_ext, gfx_file_size, &file_start, &file_len))) {
+ printf("%s: invalid file format\n", graphics_file);
+ sleep(5);
+ heap = saved_heap;
+ return;
+ }
+
+ if(verbose) {
+ printf("init: start 0x%x, len %d; code offset 0x%x\n", file_start, file_len, code_start);
+ wait_for_key();
+ }
+
+ if(file_len - code_start + MIN_GFX_FREE > buf_size) {
+ printf("not enough free memory: %d extra bytes need\n", file_len - code_start + MIN_GFX_FREE - buf_size);
+ sleep(5);
+ heap = saved_heap;
+ return;
+ }
+
+ memcpy((void *) buf, (void *) (buf_ext + file_start + code_start), file_len - code_start);
+
+ mem0_start += file_len - code_start;
+ mem0_start = (mem0_start + 3) & ~3; /* align */
+
+ /* init interface to graphics functions */
+
+ *(unsigned *) (gfx_data->sys_cfg + SC_FILE) = (unsigned) buf_ext + file_start;
+ *(unsigned *) (gfx_data->sys_cfg + SC_ARCHIVE_START) = (unsigned) buf_ext;
+ *(unsigned *) (gfx_data->sys_cfg + SC_ARCHIVE_END) = (unsigned) buf_ext + gfx_file_size;
+ *(unsigned *) (gfx_data->sys_cfg + SC_MEM0_START) = mem0_start;
+ *(unsigned *) (gfx_data->sys_cfg + SC_MEM0_END) = mem0_end;
+
+ gfx_data->code_seg = (unsigned) buf >> 4;
+
+ if(verbose) {
+ printf("init 0x%x, archive 0x%x - 0x%x, low mem 0x%x - 0x%x\ncode seg 0x%x\n",
+ (unsigned) buf_ext + file_start,
+ (unsigned) buf_ext, (unsigned) buf_ext + gfx_file_size,
+ mem0_start, mem0_end, gfx_data->code_seg
+ );
+ wait_for_key();
+ }
+
+ for(i = 0; (unsigned) i < sizeof gfx_data->jmp_table / sizeof *gfx_data->jmp_table; i++) {
+ gfx_data->jmp_table[i] = (gfx_data->code_seg << 16) + ((unsigned short *) buf)[i];
+ }
+
+ if(verbose) {
+ for(i = 0; i < 12; i++) {
+ printf("%d: 0x%x\n", i, gfx_data->jmp_table[i]);
+ }
+
+ for(i = 0; i < gfx_data->menu_entries; i++) {
+ printf("\"%s\" -- \"%s\"\n",
+ gfx_data->menu_list + i * gfx_data->menu_entry_len,
+ gfx_data->args_list + i * gfx_data->args_entry_len
+ );
+ }
+
+ printf("default: \"%s\"\n", gfx_data->menu_default_entry);
+ wait_for_key();
+ }
+
+ /* switch to graphics mode */
+
+ if(gfx_init(gfx_data)) {
+ printf("graphics initialization failed\n");
+ sleep(5);
+ heap = saved_heap;
+ return;
+ }
+
+ gfx_setup_menu(gfx_data);
+
+ i = gfx_input(gfx_data, &selected_entry);
+
+ /* ESC -> show text menu */
+ if(i == 1) {
+ gfx_done(gfx_data);
+ grub_timeout = -1;
+
+ heap = saved_heap;
+ return;
+ }
+
+ gfx_done(gfx_data);
+
+ heap = saved_heap; /* free most of the graphics data */
+
+ // printf("cmdline: >%s<, entry = %d\n", gfx_data->cmdline, selected_entry);
+
+ if(selected_entry < 0 || selected_entry > num_entries) return;
+
+
+ /* create new config with modified kernel option */
+
+ cfg = get_entry(config_entries, selected_entry, 1);
+
+ new_config = heap;
+
+ for(p = gfx_data->cmdline, i = 0; ; i++) {
+ s = get_entry(cfg, i, 0);
+ if(!*s) {
+ if(!i) *heap++ = 0;
+ *heap++ = 0;
+ break;
+ }
+ /* note: must match get_kernel_args() */
+ if(
+ (!memcmp(s, "kernel", 6) || !memcmp(s, "module", 6)) &&
+ (s[6] == ' ' || s[6] == '\t')
+ ) {
+ t = skip_to(0, s);
+ t2 = s[0] == 'm' ? strstr(t, "initrd") : NULL;
+ if(*t) t = skip_to(0, t);
+ if(t2 && t2 < t) { /* module is likely a normal initrd -> skip */
+ strcpy(heap, s);
+ heap += strlen(s) + 1;
+ continue;
+ }
+ memmove(heap, s, t - s);
+ heap += t - s;
+ *heap++ = ' ';
+ while(*p && *p != GFX_CMD_SEP) *heap++ = *p++;
+ *heap++ = 0;
+ if(*p == GFX_CMD_SEP) p++;
+ }
+ else {
+ strcpy(heap, s);
+ heap += strlen(s) + 1;
+ }
+ }
+
+ *heap++ = 0;
+
+ // hexdump(new_config, heap - new_config);
+ // getkey();
+
+ run_script(new_config, heap);
+}
+
+
static int
get_line_from_config (char *cmdline, int maxlen, int read_from_file)
{
@@ -1062,9 +1557,12 @@
}
else
{
- /* Run menu interface. */
- run_menu (menu_entries, config_entries, num_entries,
- menu_entries + menu_len, default_entry);
+ if (*graphics_file && !password && show_menu && grub_timeout)
+ {
+ run_graphics_menu(menu_entries, config_entries, num_entries,menu_entries + menu_len, default_entry);
+ }
+ /* Run menu interface. */
+ run_menu (menu_entries, config_entries, num_entries, menu_entries + menu_len, default_entry);
}
}
}