]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/grub-0.97/grub-0.97-splash.patch
HinzugefĆ¼gt:
[ipfire-2.x.git] / src / patches / grub-0.97 / grub-0.97-splash.patch
1 diff -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
28 diff -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)
64 diff -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)
369 diff -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,
416 diff -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 {
489 diff -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 }