]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/grub-0.97/grub-0.97-splash.patch
Anpassung der Pfadangaben für GRUB.
[ipfire-2.x.git] / src / patches / grub-0.97 / grub-0.97-splash.patch
CommitLineData
27996c53
MT
1diff -Nur grub-0.97-misc/docs/grub.texi grub-0.97-splash/docs/grub.texi
2--- grub-0.97-misc/docs/grub.texi 2005-08-21 20:22:18.000000000 +0300
3+++ grub-0.97-splash/docs/grub.texi 2005-08-21 20:29:22.000000000 +0300
4@@ -2118,6 +2118,7 @@
5 * default:: Set the default entry
6 * fallback:: Set the fallback entry
7 * hiddenmenu:: Hide the menu interface
8+* gfxmenu:: Use graphical menu interface
9 * timeout:: Set the timeout
10 * title:: Start a menu entry
11 @end menu
12@@ -2150,6 +2151,15 @@
13 @end deffn
14
15
16+@node gfxmenu
17+@subsection gfxmenu
18+
19+@deffn Command gfxmenu file
20+Use the graphical menu interface. The graphics data are taken from
21+@var{file} and must be created using 'mkbootmsg' from the gfxboot package.
22+@end deffn
23+
24+
25 @node hiddenmenu
26 @subsection hiddenmenu
27
28diff -Nur grub-0.97-misc/grub/asmstub.c grub-0.97-splash/grub/asmstub.c
29--- grub-0.97-misc/grub/asmstub.c 2005-08-21 20:22:18.000000000 +0300
30+++ grub-0.97-splash/grub/asmstub.c 2005-08-21 20:29:22.000000000 +0300
31@@ -480,6 +480,32 @@
32 return 0;
33 }
34
35+/* graphical menu functions . */
36+int
37+gfx_init (gfx_data_t *gfx_data)
38+{
39+ return 0;
40+}
41+
42+int
43+gfx_done (gfx_data_t *gfx_data)
44+{
45+ return 0;
46+}
47+
48+int
49+gfx_input (gfx_data_t *gfx_data, int *menu_entry)
50+{
51+ return 0;
52+}
53+
54+int
55+gfx_setup_menu (gfx_data_t *gfx_data)
56+{
57+ return 0;
58+}
59+
60+
61 /* low-level timing info */
62 int
63 getrtsecs (void)
64diff -Nur grub-0.97-misc/stage2/asm.S grub-0.97-splash/stage2/asm.S
65--- grub-0.97-misc/stage2/asm.S 2005-08-21 20:22:18.000000000 +0300
66+++ grub-0.97-splash/stage2/asm.S 2005-08-21 20:29:22.000000000 +0300
67@@ -1610,6 +1610,301 @@
68 popl %ebp
69 ret
70
71+
72+/*
73+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
74+ *
75+ * graphical menu functions
76+ *
77+ */
78+
79+/*
80+ * int gfx_init (gfx_data_t *gfx_data)
81+ *
82+ * init gfx things
83+ *
84+ * return vales:
85+ * 0: ok
86+ * 1: failed
87+ * sets gfx_data->ok
88+ */
89+
90+ENTRY(gfx_init)
91+ pushl %ebp
92+ movl %esp, %ebp
93+
94+ pushl %edi
95+ pushl %esi
96+ pushl %ebx
97+
98+ movl 8(%ebp),%edx
99+ movl %edx,%edi
100+ andl $0xf,%edi
101+ shrl $4,%edx
102+
103+ pushl %ebp
104+
105+ call EXT_C(prot_to_real)
106+ .code16
107+
108+ pushw %ds
109+
110+ movw %dx,%ds
111+ leal gfx_ofs_sys_cfg(%di),%esi
112+ movl gfx_ofs_mem_file(%di),%eax
113+ movl gfx_ofs_mem_cur(%di),%ebx
114+ movl gfx_ofs_mem_max(%di),%ecx
115+ movw %ds,%dx
116+
117+ /* basically just a lcall, but we need %edi */
118+ pushw %cs
119+ pushw $gfx_init_50
120+ pushl gfx_ofs_jmp_table + 4 * 0 (%di)
121+
122+ movl gfx_ofs_mem_align(%di),%edi
123+
124+ lret
125+
126+gfx_init_50:
127+ movl $0,%ebx
128+ adcl $0,%ebx
129+
130+ popw %ds
131+
132+ DATA32 call EXT_C(real_to_prot)
133+ .code32
134+
135+ popl %ebp
136+
137+ movl %ebx,%eax
138+ negl %ebx
139+ incl %ebx
140+ movl 8(%ebp),%edx
141+ movl %ebx,gfx_ofs_ok(%edx)
142+
143+ popl %ebx
144+ popl %esi
145+ popl %edi
146+
147+ popl %ebp
148+ ret
149+
150+
151+/*
152+ * int gfx_done (gfx_data_t *gfx_data)
153+ *
154+ * shut down gfx things
155+ *
156+ * return vales:
157+ * always 0
158+ * sets gfx_data->ok
159+ */
160+
161+ENTRY(gfx_done)
162+ pushl %ebp
163+ movl %esp, %ebp
164+
165+ pushl %edi
166+ pushl %esi
167+ pushl %ebx
168+
169+ movl 8(%ebp),%edx
170+ movl %edx,%ebx
171+ andl $0xf,%ebx
172+ shrl $4,%edx
173+
174+ pushl %ebp
175+
176+ call EXT_C(prot_to_real)
177+ .code16
178+
179+ pushw %ds
180+
181+ movw %dx,%ds
182+
183+ lcall *gfx_ofs_jmp_table + 4 * 1 (%bx)
184+
185+ popw %ds
186+
187+ DATA32 call EXT_C(real_to_prot)
188+ .code32
189+
190+ popl %ebp
191+
192+ xorl %eax,%eax
193+ movl 8(%ebp),%edx
194+ movl %eax,gfx_ofs_ok(%edx)
195+
196+ popl %ebx
197+ popl %esi
198+ popl %edi
199+
200+ popl %ebp
201+ ret
202+
203+
204+/*
205+ * int gfx_input (gfx_data_t *gfx_data, int *menu_entry)
206+ *
207+ * let user enter a command line
208+ *
209+ * uses gfx_data->cmdline as buffer
210+ *
211+ * return values:
212+ * 1: abort
213+ * 2: boot
214+ * menu_entry: selected entry
215+ */
216+
217+ENTRY(gfx_input)
218+ pushl %ebp
219+ movl %esp, %ebp
220+
221+ pushl %edi
222+ pushl %esi
223+ pushl %ebx
224+
225+ movl 8(%ebp),%edx
226+ movl %edx,%ebx
227+ andl $0xf,%ebx
228+ shrl $4,%edx
229+
230+ pushl %ebp
231+
232+ call EXT_C(prot_to_real)
233+ .code16
234+
235+ pushw %ds
236+
237+ movw %dx,%ds
238+ shll $4,%edx
239+ movl gfx_ofs_cmdline(%bx),%edi
240+ subl %edx,%edi
241+ movw gfx_ofs_cmdline_len(%bx),%cx
242+ movw gfx_ofs_timeout(%bx),%ax
243+ imulw $18,%ax
244+
245+ pushl %ebp
246+ lcall *gfx_ofs_jmp_table + 4 * 2 (%bx)
247+ popl %ebp
248+ movl %eax,%ecx
249+
250+ popw %ds
251+
252+ DATA32 call EXT_C(real_to_prot)
253+ .code32
254+
255+ popl %ebp
256+
257+ movl 12(%ebp),%edx
258+ movl %ebx,(%edx)
259+
260+ movl %ecx,%eax
261+
262+ popl %ebx
263+ popl %esi
264+ popl %edi
265+
266+ popl %ebp
267+ ret
268+
269+
270+/*
271+ * int gfx_setup_menu (gfx_data_t *gfx_data)
272+ *
273+ * draw boot menu
274+ *
275+ * return values:
276+ * always 0
277+ */
278+
279+/* menu entry descriptor */
280+#define menu_entries 0
281+#define menu_default 2 /* seg:ofs */
282+#define menu_ent_list 6 /* seg:ofs */
283+#define menu_ent_size 10
284+#define menu_arg_list 12 /* seg:ofs */
285+#define menu_arg_size 16
286+#define sizeof_menu_desc 18
287+
288+ENTRY(gfx_setup_menu)
289+ pushl %ebp
290+ movl %esp, %ebp
291+
292+ pushl %edi
293+ pushl %esi
294+ pushl %ebx
295+
296+ movl 8(%ebp),%edx
297+ movl %edx,%ebx
298+ andl $0xf,%ebx
299+ shrl $4,%edx
300+
301+ call EXT_C(prot_to_real)
302+ .code16
303+
304+ pushw %ds
305+
306+ movw %dx,%ds
307+ shll $4,%edx
308+
309+ subw $sizeof_menu_desc,%sp
310+ movw %sp,%bp
311+
312+ movl gfx_ofs_menu_entries(%bx),%eax
313+ movw %ax,menu_entries(%bp)
314+
315+ movl gfx_ofs_menu_default_entry(%bx),%eax
316+ subl %edx,%eax
317+ movw %ax,menu_default(%bp)
318+ movw %ds,menu_default+2(%bp)
319+
320+ movl gfx_ofs_menu_list(%bx),%eax
321+ subl %edx,%eax
322+ movw %ax,menu_ent_list(%bp)
323+ movw %ds,menu_ent_list+2(%bp)
324+
325+ movl gfx_ofs_menu_entry_len(%bx),%eax
326+ movw %ax,menu_ent_size(%bp)
327+
328+ movl gfx_ofs_args_list(%bx),%eax
329+ subl %edx,%eax
330+ movw %ax,menu_arg_list(%bp)
331+ movw %ds,menu_arg_list+2(%bp)
332+
333+ movl gfx_ofs_args_entry_len(%bx),%eax
334+ movw %ax,menu_arg_size(%bp)
335+
336+ movw %bp,%si
337+ pushw %ss
338+ popw %es
339+
340+ lcall %ds: *gfx_ofs_jmp_table + 4 * 3 (%bx)
341+
342+ addw $sizeof_menu_desc,%sp
343+
344+ popw %ds
345+
346+ DATA32 call EXT_C(real_to_prot)
347+ .code32
348+
349+ xorl %eax,%eax
350+
351+ popl %ebx
352+ popl %esi
353+ popl %edi
354+
355+ popl %ebp
356+ ret
357+
358+
359+/*
360+ *
361+ * end graphics stuff
362+ *
363+ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
364+ */
365+
366
367 /*
368 * gateA20(int linear)
369diff -Nur grub-0.97-misc/stage2/builtins.c grub-0.97-splash/stage2/builtins.c
370--- grub-0.97-misc/stage2/builtins.c 2005-08-21 20:22:30.000000000 +0300
371+++ grub-0.97-splash/stage2/builtins.c 2005-08-21 20:29:22.000000000 +0300
372@@ -63,6 +63,8 @@
373 int fallback_entries[MAX_FALLBACK_ENTRIES];
374 /* The number of current entry. */
375 int current_entryno;
376+/* graphics file */
377+char graphics_file[64];
378 /* The address for Multiboot command-line buffer. */
379 static char *mb_cmdline;
380 /* The password. */
381@@ -1331,6 +1333,26 @@
382 };
383
384 \f
385+/* graphics */
386+static int
387+gfxmenu_func (char *arg, int flags)
388+{
389+ memmove(graphics_file, arg, sizeof graphics_file - 1);
390+ graphics_file[sizeof graphics_file - 1] = 0;
391+
392+ return 0;
393+}
394+
395+static struct builtin builtin_gfxmenu =
396+{
397+ "gfxmenu",
398+ gfxmenu_func,
399+ BUILTIN_MENU | BUILTIN_HELP_LIST,
400+ "gfxmenu FILE",
401+ "Use the graphical menu from FILE."
402+};
403+
404+\f
405 /* geometry */
406 static int
407 geometry_func (char *arg, int flags)
408@@ -4837,6 +4859,7 @@
409 &builtin_find,
410 &builtin_fstest,
411 &builtin_geometry,
412+ &builtin_gfxmenu,
413 &builtin_halt,
414 &builtin_help,
415 &builtin_hiddenmenu,
416diff -Nur grub-0.97-misc/stage2/shared.h grub-0.97-splash/stage2/shared.h
417--- grub-0.97-misc/stage2/shared.h 2005-08-21 20:22:18.000000000 +0300
418+++ grub-0.97-splash/stage2/shared.h 2005-08-21 20:29:22.000000000 +0300
419@@ -374,6 +374,27 @@
420 #endif /* WITHOUT_LIBC_STUBS */
421
422
423+/* see typedef gfx_data_t below */
424+#define gfx_ofs_ok 0x00
425+#define gfx_ofs_mem_start 0x04
426+#define gfx_ofs_mem_cur 0x08
427+#define gfx_ofs_mem_max 0x0c
428+#define gfx_ofs_code_seg 0x10
429+#define gfx_ofs_jmp_table 0x14
430+#define gfx_ofs_sys_cfg 0x44
431+#define gfx_ofs_cmdline 0x64
432+#define gfx_ofs_cmdline_len 0x68
433+#define gfx_ofs_menu_list 0x6c
434+#define gfx_ofs_menu_default_entry 0x70
435+#define gfx_ofs_menu_entries 0x74
436+#define gfx_ofs_menu_entry_len 0x78
437+#define gfx_ofs_args_list 0x7c
438+#define gfx_ofs_args_entry_len 0x80
439+#define gfx_ofs_timeout 0x84
440+#define gfx_ofs_mem_file 0x88
441+#define gfx_ofs_mem_align 0x8c
442+
443+
444 #ifndef ASM_FILE
445 /*
446 * Below this should be ONLY defines and other constructs for C code.
447@@ -595,6 +616,41 @@
448 extern int default_entry;
449 extern int current_entryno;
450
451+
452+/*
453+ * graphics menu stuff
454+ *
455+ * Note: gfx_data and all data referred to in it must lie within a 64k area.
456+ */
457+typedef struct {
458+ unsigned ok; /* set while we're in graphics mode */
459+ unsigned mem_start, mem_cur, mem_max;
460+ unsigned code_seg; /* code segment of binary graphics code */
461+ unsigned jmp_table[12]; /* link to graphics functions */
462+ unsigned char sys_cfg[32]; /* sys_cfg[0]: identifies boot loader (grub == 2) */
463+ char *cmdline; /* command line returned by gfx_input() */
464+ unsigned cmdline_len; /* length of the above */
465+ char *menu_list; /* list of menu entries, each of fixed length (menu_entry_len) */
466+ char *menu_default_entry; /* the default entry */
467+ unsigned menu_entries; /* number of entries in menu_list */
468+ unsigned menu_entry_len; /* one entry */
469+ char *args_list; /* same structure as menu_list, menu_entries entries */
470+ unsigned args_entry_len; /* one entry */
471+ unsigned timeout; /* in seconds (0: no timeout) */
472+ unsigned mem_file; /* aligned gfx file start */
473+ unsigned mem_align; /* aligned cpio file start */
474+} __attribute__ ((packed)) gfx_data_t;
475+
476+extern gfx_data_t *graphics_data;
477+
478+/* pointer to graphics image data */
479+extern char graphics_file[64];
480+
481+int gfx_init(gfx_data_t *gfx_data);
482+int gfx_done(gfx_data_t *gfx_data);
483+int gfx_input(gfx_data_t *gfx_data, int *menu_entry);
484+int gfx_setup_menu(gfx_data_t *gfx_data);
485+
486 /* The constants for password types. */
487 typedef enum
488 {
489diff -Nur grub-0.97-misc/stage2/stage2.c grub-0.97-splash/stage2/stage2.c
490--- grub-0.97-misc/stage2/stage2.c 2005-08-21 20:22:18.000000000 +0300
491+++ grub-0.97-splash/stage2/stage2.c 2005-08-21 20:29:22.000000000 +0300
492@@ -22,6 +22,8 @@
493
494 grub_jmp_buf restart_env;
495
496+gfx_data_t *graphics_data;
497+
498 #if defined(PRESET_MENU_STRING) || defined(SUPPORT_DISKLESS)
499
500 # if defined(PRESET_MENU_STRING)
501@@ -310,6 +312,12 @@
502
503 if (! auth && password)
504 {
505+ if (*graphics_file)
506+ {
507+ printf ("\
508+ WARNING: graphical menu doesn\'t work\
509+ in conjunction with the password feature\n" );
510+ }
511 printf ("\
512 Press enter to boot the selected OS or \'p\' to enter a\n\
513 password to unlock the next set of features.");
514@@ -753,6 +761,413 @@
515 }
516
517
518+
519+#if 0
520+/* for debugging */
521+static void hexdump(unsigned char *buf, unsigned len)
522+{
523+ int i, j = 0;
524+ char s[17];
525+ unsigned addr = (unsigned) buf;
526+
527+ s[16] = 0;
528+ while(len--) {
529+ i = buf[j];
530+ i = i & 0xff;
531+ s[j & 15] = (i >= 0x20 && i <= 0x7e) ? i : '.';
532+ if(!(j & 15)) {
533+ printf("%x ", j + addr);
534+ }
535+ if(!(j & 7) && (j & 15)) printf(" ");
536+ /* stupid grub_printf */
537+ printf("%x", (i >> 4) & 0x0f);
538+ printf("%x ", i & 0x0f);
539+ if(!(++j & 15)) {
540+ printf(" %s\n", s);
541+ }
542+ }
543+
544+ if(j & 15) {
545+ s[j & 15] = 0;
546+ if(!(j & 8)) printf(" ");
547+ i = 1 + 3 * (16 - (j & 15));
548+ while(i--) printf(" ");
549+ printf("%s\n", s);
550+ }
551+}
552+#endif
553+
554+/*
555+ * Go through config entry and find kernel args, if any.
556+ */
557+static char *get_kernel_args(char *cfg)
558+{
559+ int j;
560+ char *s, *t = "";
561+
562+ for(j = 0; ; j++) {
563+ s = get_entry(cfg, j, 0);
564+ if(!*s) break;
565+ if(!memcmp(s, "kernel", 6) && (s[6] == ' ' || s[6] == '\t')) {
566+ t = skip_to(0, s);
567+ if(*t) t = skip_to(0, t);
568+ break;
569+ }
570+ }
571+
572+ return t;
573+}
574+
575+
576+/*
577+ * Check header and return code start offset.
578+ */
579+static unsigned magic_ok(unsigned char *buf)
580+{
581+ if(
582+ *(unsigned *) buf == 0x0b2d97f00 && /* magic id */
583+ (buf[4] == 5 || buf[4] == 6) /* version 5 or 6 */
584+ ) {
585+ return *(unsigned *) (buf + 8);
586+ }
587+
588+ return 0;
589+}
590+
591+
592+/*
593+ * Search cpio archive for gfx file.
594+ */
595+static unsigned find_file(unsigned char *buf, unsigned len, unsigned *gfx_file_start)
596+{
597+ unsigned i, fname_len, flen, code_start = 0;
598+
599+ *gfx_file_start = 0;
600+
601+ for(i = 0; i < len;) {
602+ if((len - i) >= 0x1a && (buf[i] + (buf[i + 1] << 8)) == 0x71c7) {
603+ fname_len = *(unsigned short *) (buf + i + 20);
604+ flen = *(unsigned short *) (buf + i + 24) + (*(unsigned short *) (buf + i + 22) << 16);
605+ i += 26 + fname_len;
606+ i = ((i + 1) & ~1);
607+ if((code_start = magic_ok(buf + i))) {
608+ *gfx_file_start = i;
609+ return code_start;
610+ }
611+ i += flen;
612+ i = ((i + 1) & ~1);
613+ }
614+ else {
615+ break;
616+ }
617+ }
618+
619+ return code_start;
620+}
621+
622+
623+/*
624+ * Leave that much space on the heap. Everything else goes to the graphics
625+ * functions.
626+ *
627+ * 0x2000 is _not_ enough
628+ */
629+#define MIN_HEAP_SIZE 0x4000
630+
631+/* gfx code needs at least this much free memory */
632+#define MIN_GFX_FREE 0xc000
633+
634+/*
635+ * Does normally not return.
636+ */
637+static void
638+run_graphics_menu (char *menu_entries, char *config_entries, int num_entries,
639+ char *heap, int entryno)
640+{
641+ unsigned char *buf;
642+ unsigned u, buf_size, code_start, file_start;
643+ char *s, *t, *cfg, *new_config;
644+ char *saved_heap;
645+ int i, j, max_len;
646+ int selected_entry;
647+ gfx_data_t *gfx_data;
648+
649+ /*
650+ * check gfx_data_t struct offsets for consistency; gcc will optimize away
651+ * the whole block
652+ */
653+
654+ /* dummy function to make ld fail */
655+ {
656+ extern void wrong_struct_size(void);
657+ #define gfx_ofs_check(a) if(gfx_ofs_##a != (char *) &gfx_data->a - (char *) gfx_data) wrong_struct_size();
658+ gfx_ofs_check(ok);
659+ gfx_ofs_check(mem_start);
660+ gfx_ofs_check(mem_cur);
661+ gfx_ofs_check(mem_max);
662+ gfx_ofs_check(code_seg);
663+ gfx_ofs_check(jmp_table);
664+ gfx_ofs_check(sys_cfg);
665+ gfx_ofs_check(cmdline);
666+ gfx_ofs_check(cmdline_len);
667+ gfx_ofs_check(menu_list);
668+ gfx_ofs_check(menu_default_entry);
669+ gfx_ofs_check(menu_entries);
670+ gfx_ofs_check(menu_entry_len);
671+ gfx_ofs_check(args_list);
672+ gfx_ofs_check(args_entry_len);
673+ gfx_ofs_check(timeout);
674+ gfx_ofs_check(mem_file);
675+ gfx_ofs_check(mem_align);
676+ #undef gfx_ofs_check
677+ }
678+
679+ if(!num_entries) return;
680+
681+ graphics_data = gfx_data = (gfx_data_t *) heap;
682+ heap += sizeof *gfx_data;
683+ memset(gfx_data, 0, sizeof *gfx_data);
684+
685+ gfx_data->sys_cfg[0] = 2; /* bootloader: grub */
686+ gfx_data->timeout = grub_timeout >= 0 ? grub_timeout : 0;
687+
688+
689+ /* setup command line edit buffer */
690+
691+ gfx_data->cmdline_len = 256;
692+
693+ gfx_data->cmdline = heap;
694+ heap += gfx_data->cmdline_len;
695+ memset(gfx_data->cmdline, 0, gfx_data->cmdline_len);
696+
697+
698+ /* setup menu entries */
699+
700+ for(i = max_len = 0; i < num_entries; i++) {
701+ j = strlen(get_entry(menu_entries, i, 0));
702+ if(j > max_len) max_len = j;
703+ }
704+
705+ if(!max_len) return;
706+
707+ gfx_data->menu_entry_len = max_len + 1;
708+ gfx_data->menu_entries = num_entries;
709+
710+ gfx_data->menu_list = heap;
711+ heap += gfx_data->menu_entry_len * gfx_data->menu_entries;
712+
713+ memset(gfx_data->menu_list, 0, gfx_data->menu_entry_len * gfx_data->menu_entries);
714+
715+ for(i = 0; i < (int) gfx_data->menu_entries; i++) {
716+ strcpy(gfx_data->menu_list + i * gfx_data->menu_entry_len, get_entry(menu_entries, i, 0));
717+ }
718+
719+ gfx_data->menu_default_entry = gfx_data->menu_list + entryno * gfx_data->menu_entry_len;
720+
721+
722+ /* setup list of kernel args */
723+
724+ for(i = max_len = 0; i < num_entries; i++) {
725+ s = get_kernel_args(get_entry(config_entries, i, 1));
726+ j = strlen(s);
727+ if(j > max_len) max_len = j;
728+ }
729+
730+ gfx_data->args_entry_len = max_len + 1;
731+
732+ gfx_data->args_list = heap;
733+ heap += gfx_data->args_entry_len * gfx_data->menu_entries;
734+
735+ memset(gfx_data->args_list, 0, gfx_data->args_entry_len * gfx_data->menu_entries);
736+
737+ for(i = 0; i < (int) gfx_data->menu_entries; i++) {
738+ strcpy(gfx_data->args_list + i* gfx_data->args_entry_len, get_kernel_args(get_entry(config_entries, i, 1)));
739+ }
740+
741+
742+ /* go back here when we no longer need the graphics data */
743+ saved_heap = heap;
744+
745+
746+ /* get memory area to be used by graphics functions */
747+
748+ buf = (unsigned char *) (((unsigned) heap + 0xf) & ~0xf);
749+
750+ buf_size = (unsigned char *) &buf - buf - MIN_HEAP_SIZE;
751+ buf_size &= ~0xf;
752+
753+ /* too small */
754+ if(buf_size < 0x10000) return;
755+
756+ gfx_data->mem_start = (unsigned) buf;
757+ gfx_data->mem_max = gfx_data->mem_start + buf_size;
758+
759+#if 0
760+ printf("graphics menu\n");
761+ printf(
762+ "heap = 0x%x, buf = 0x%x (0x%x bytes), graphics_file = %s\n",
763+ heap, gfx_data->mem_start, buf_size, graphics_file
764+ );
765+ getkey();
766+#endif
767+
768+ heap += buf_size;
769+
770+
771+ /* read the file */
772+
773+ if(!grub_open(graphics_file)) {
774+ printf("graphics file \"%s\" missing, press a key to continue...\n", graphics_file);
775+ getkey();
776+ return;
777+ }
778+
779+ i = grub_read(buf, buf_size);
780+
781+ grub_close();
782+
783+ if(i <= 0) {
784+ printf("error reading \"%s\", press a key to continue...\n", graphics_file);
785+ getkey();
786+ return;
787+ }
788+
789+ /* besides the file, we need some working memory, too */
790+ if(i + MIN_GFX_FREE + 0x0f >= (int) buf_size) {
791+ printf("file \"%s\" too large, press a key to continue...\n", graphics_file);
792+ getkey();
793+ return;
794+ }
795+
796+ gfx_data->mem_cur = gfx_data->mem_start + ((i + 0x0f + 3) & ~3); /* align it */
797+
798+#if 0
799+ printf("image: %d bytes (%d bytes left)\n", i, gfx_data->mem_max - gfx_data->mem_cur);
800+ getkey();
801+#endif
802+
803+
804+ /* locate file inside cpio archive */
805+ if(!(code_start = find_file(buf, i, &file_start))) {
806+ printf("\"%s\" has wrong format, press a key to continue...\n", graphics_file);
807+ getkey();
808+ return;
809+ }
810+
811+
812+ /* align it */
813+ u = (-(code_start + gfx_data->mem_start + file_start)) & 0x0f;
814+ gfx_data->mem_align = gfx_data->mem_start + u;
815+ gfx_data->mem_file = gfx_data->mem_align + file_start;
816+ if(u) {
817+ memcpy((void *) gfx_data->mem_align, (void *) gfx_data->mem_start, i);
818+ }
819+
820+ /* init interface to graphics functions */
821+
822+ code_start += gfx_data->mem_file;
823+
824+#if 0
825+ printf("code_start: 0x%x, file_start: 0x%x, mem_align = 0x%x, mem_file = 0x%x\n",
826+ code_start, file_start, gfx_data->mem_align, gfx_data->mem_file
827+ );
828+ getkey();
829+#endif
830+
831+ gfx_data->code_seg = code_start >> 4;
832+
833+#if 0
834+ printf("code start = 0x%x, code_seg = 0x%x\n", code_start, gfx_data->code_seg);
835+#endif
836+
837+ for(i = 0; (unsigned) i < sizeof gfx_data->jmp_table / sizeof *gfx_data->jmp_table; i++) {
838+ gfx_data->jmp_table[i] = (gfx_data->code_seg << 16) + ((unsigned short *) code_start)[i];
839+ }
840+
841+#if 0
842+ for(i = 0; i < 12; i++) {
843+ printf("%d: 0x%x\n", i, gfx_data->jmp_table[i]);
844+ }
845+
846+ for(i = 0; i < gfx_data->menu_entries; i++) {
847+ printf(">%s< - >%s<\n",
848+ gfx_data->menu_list + i * gfx_data->menu_entry_len,
849+ gfx_data->args_list + i * gfx_data->args_entry_len
850+ );
851+ }
852+
853+ printf("def: >%s<\n", gfx_data->menu_default_entry);
854+#endif
855+
856+
857+ /* switch to graphics mode */
858+
859+ if(gfx_init(gfx_data)) {
860+#if 0
861+ printf("gfx_init failed\n");
862+ getkey();
863+#endif
864+ return;
865+ }
866+
867+ gfx_setup_menu(gfx_data);
868+
869+ i = gfx_input(gfx_data, &selected_entry);
870+
871+ /* ESC -> show text menu */
872+ if(i == 1) {
873+ gfx_done(gfx_data);
874+ grub_timeout = -1;
875+
876+ return;
877+ }
878+
879+ gfx_done(gfx_data);
880+
881+ heap = saved_heap; /* free most of the graphics data */
882+
883+ // printf("cmdline: >%s<, entry = %d\n", gfx_data->cmdline, selected_entry);
884+
885+ if(selected_entry < 0 || selected_entry > num_entries) return;
886+
887+
888+ /* create new config with modified kernel option */
889+
890+ cfg = get_entry(config_entries, selected_entry, 1);
891+
892+ new_config = heap;
893+
894+ for(i = 0; ; i++) {
895+ s = get_entry(cfg, i, 0);
896+ if(!*s) {
897+ if(!i) *heap++ = 0;
898+ *heap++ = 0;
899+ break;
900+ }
901+ if(!memcmp(s, "kernel", 6) && (s[6] == ' ' || s[6] == '\t')) {
902+ t = skip_to(0, s);
903+ if(*t) t = skip_to(0, t);
904+ memmove(heap, s, t - s);
905+ heap += t - s;
906+ *heap++ = ' ';
907+ strcpy(heap, gfx_data->cmdline);
908+ heap += strlen(gfx_data->cmdline) + 1;
909+ }
910+ else {
911+ strcpy(heap, s);
912+ heap += strlen(s) + 1;
913+ }
914+ }
915+
916+ *heap++ = 0;
917+
918+ // hexdump(new_config, heap - new_config);
919+ // getkey();
920+
921+ run_script(new_config, heap);
922+}
923+
924+
925 static int
926 get_line_from_config (char *cmdline, int maxlen, int read_from_file)
927 {
928@@ -1059,9 +1474,12 @@
929 }
930 else
931 {
932- /* Run menu interface. */
933- run_menu (menu_entries, config_entries, num_entries,
934- menu_entries + menu_len, default_entry);
935+ if (*graphics_file && !password && show_menu && grub_timeout)
936+ {
937+ run_graphics_menu(menu_entries, config_entries, num_entries,menu_entries + menu_len, default_entry);
938+ }
939+ /* Run menu interface. */
940+ run_menu (menu_entries, config_entries, num_entries, menu_entries + menu_len, default_entry);
941 }
942 }
943 }