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
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
12 @@ -2150,6 +2151,15 @@
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.
26 @subsection hiddenmenu
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
35 +/* graphical menu functions . */
37 +gfx_init (gfx_data_t *gfx_data)
43 +gfx_done (gfx_data_t *gfx_data)
49 +gfx_input (gfx_data_t *gfx_data, int *menu_entry)
55 +gfx_setup_menu (gfx_data_t *gfx_data)
61 /* low-level timing info */
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 @@
73 + * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
75 + * graphical menu functions
80 + * int gfx_init (gfx_data_t *gfx_data)
105 + call EXT_C(prot_to_real)
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
117 + /* basically just a lcall, but we need %edi */
120 + pushl gfx_ofs_jmp_table + 4 * 0 (%di)
122 + movl gfx_ofs_mem_align(%di),%edi
132 + DATA32 call EXT_C(real_to_prot)
141 + movl %ebx,gfx_ofs_ok(%edx)
152 + * int gfx_done (gfx_data_t *gfx_data)
154 + * shut down gfx things
158 + * sets gfx_data->ok
176 + call EXT_C(prot_to_real)
183 + lcall *gfx_ofs_jmp_table + 4 * 1 (%bx)
187 + DATA32 call EXT_C(real_to_prot)
194 + movl %eax,gfx_ofs_ok(%edx)
205 + * int gfx_input (gfx_data_t *gfx_data, int *menu_entry)
207 + * let user enter a command line
209 + * uses gfx_data->cmdline as buffer
214 + * menu_entry: selected entry
232 + call EXT_C(prot_to_real)
239 + movl gfx_ofs_cmdline(%bx),%edi
241 + movw gfx_ofs_cmdline_len(%bx),%cx
242 + movw gfx_ofs_timeout(%bx),%ax
246 + lcall *gfx_ofs_jmp_table + 4 * 2 (%bx)
252 + DATA32 call EXT_C(real_to_prot)
271 + * int gfx_setup_menu (gfx_data_t *gfx_data)
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
288 +ENTRY(gfx_setup_menu)
301 + call EXT_C(prot_to_real)
309 + subw $sizeof_menu_desc,%sp
312 + movl gfx_ofs_menu_entries(%bx),%eax
313 + movw %ax,menu_entries(%bp)
315 + movl gfx_ofs_menu_default_entry(%bx),%eax
317 + movw %ax,menu_default(%bp)
318 + movw %ds,menu_default+2(%bp)
320 + movl gfx_ofs_menu_list(%bx),%eax
322 + movw %ax,menu_ent_list(%bp)
323 + movw %ds,menu_ent_list+2(%bp)
325 + movl gfx_ofs_menu_entry_len(%bx),%eax
326 + movw %ax,menu_ent_size(%bp)
328 + movl gfx_ofs_args_list(%bx),%eax
330 + movw %ax,menu_arg_list(%bp)
331 + movw %ds,menu_arg_list+2(%bp)
333 + movl gfx_ofs_args_entry_len(%bx),%eax
334 + movw %ax,menu_arg_size(%bp)
340 + lcall %ds: *gfx_ofs_jmp_table + 4 * 3 (%bx)
342 + addw $sizeof_menu_desc,%sp
346 + DATA32 call EXT_C(real_to_prot)
361 + * end graphics stuff
363 + * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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
373 int fallback_entries[MAX_FALLBACK_ENTRIES];
374 /* The number of current entry. */
377 +char graphics_file[64];
378 /* The address for Multiboot command-line buffer. */
379 static char *mb_cmdline;
381 @@ -1331,6 +1333,26 @@
387 +gfxmenu_func (char *arg, int flags)
389 + memmove(graphics_file, arg, sizeof graphics_file - 1);
390 + graphics_file[sizeof graphics_file - 1] = 0;
395 +static struct builtin builtin_gfxmenu =
399 + BUILTIN_MENU | BUILTIN_HELP_LIST,
401 + "Use the graphical menu from FILE."
407 geometry_func (char *arg, int flags)
408 @@ -4837,6 +4859,7 @@
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
420 #endif /* WITHOUT_LIBC_STUBS */
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
446 * Below this should be ONLY defines and other constructs for C code.
448 extern int default_entry;
449 extern int current_entryno;
453 + * graphics menu stuff
455 + * Note: gfx_data and all data referred to in it must lie within a 64k area.
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;
476 +extern gfx_data_t *graphics_data;
478 +/* pointer to graphics image data */
479 +extern char graphics_file[64];
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);
486 /* The constants for password types. */
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
494 grub_jmp_buf restart_env;
496 +gfx_data_t *graphics_data;
498 #if defined(PRESET_MENU_STRING) || defined(SUPPORT_DISKLESS)
500 # if defined(PRESET_MENU_STRING)
503 if (! auth && password)
505 + if (*graphics_file)
508 + WARNING: graphical menu doesn\'t work\
509 + in conjunction with the password feature\n" );
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 @@
521 +static void hexdump(unsigned char *buf, unsigned len)
525 + unsigned addr = (unsigned) buf;
531 + s[j & 15] = (i >= 0x20 && i <= 0x7e) ? i : '.';
533 + printf("%x ", j + addr);
535 + if(!(j & 7) && (j & 15)) printf(" ");
536 + /* stupid grub_printf */
537 + printf("%x", (i >> 4) & 0x0f);
538 + printf("%x ", i & 0x0f);
540 + printf(" %s\n", s);
546 + if(!(j & 8)) printf(" ");
547 + i = 1 + 3 * (16 - (j & 15));
548 + while(i--) printf(" ");
555 + * Go through config entry and find kernel args, if any.
557 +static char *get_kernel_args(char *cfg)
562 + for(j = 0; ; j++) {
563 + s = get_entry(cfg, j, 0);
565 + if(!memcmp(s, "kernel", 6) && (s[6] == ' ' || s[6] == '\t')) {
567 + if(*t) t = skip_to(0, t);
577 + * Check header and return code start offset.
579 +static unsigned magic_ok(unsigned char *buf)
582 + *(unsigned *) buf == 0x0b2d97f00 && /* magic id */
583 + (buf[4] == 5 || buf[4] == 6) /* version 5 or 6 */
585 + return *(unsigned *) (buf + 8);
593 + * Search cpio archive for gfx file.
595 +static unsigned find_file(unsigned char *buf, unsigned len, unsigned *gfx_file_start)
597 + unsigned i, fname_len, flen, code_start = 0;
599 + *gfx_file_start = 0;
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;
612 + i = ((i + 1) & ~1);
624 + * Leave that much space on the heap. Everything else goes to the graphics
627 + * 0x2000 is _not_ enough
629 +#define MIN_HEAP_SIZE 0x4000
631 +/* gfx code needs at least this much free memory */
632 +#define MIN_GFX_FREE 0xc000
635 + * Does normally not return.
638 +run_graphics_menu (char *menu_entries, char *config_entries, int num_entries,
639 + char *heap, int entryno)
641 + unsigned char *buf;
642 + unsigned u, buf_size, code_start, file_start;
643 + char *s, *t, *cfg, *new_config;
646 + int selected_entry;
647 + gfx_data_t *gfx_data;
650 + * check gfx_data_t struct offsets for consistency; gcc will optimize away
654 + /* dummy function to make ld fail */
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();
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
679 + if(!num_entries) return;
681 + graphics_data = gfx_data = (gfx_data_t *) heap;
682 + heap += sizeof *gfx_data;
683 + memset(gfx_data, 0, sizeof *gfx_data);
685 + gfx_data->sys_cfg[0] = 2; /* bootloader: grub */
686 + gfx_data->timeout = grub_timeout >= 0 ? grub_timeout : 0;
689 + /* setup command line edit buffer */
691 + gfx_data->cmdline_len = 256;
693 + gfx_data->cmdline = heap;
694 + heap += gfx_data->cmdline_len;
695 + memset(gfx_data->cmdline, 0, gfx_data->cmdline_len);
698 + /* setup menu entries */
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;
705 + if(!max_len) return;
707 + gfx_data->menu_entry_len = max_len + 1;
708 + gfx_data->menu_entries = num_entries;
710 + gfx_data->menu_list = heap;
711 + heap += gfx_data->menu_entry_len * gfx_data->menu_entries;
713 + memset(gfx_data->menu_list, 0, gfx_data->menu_entry_len * gfx_data->menu_entries);
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));
719 + gfx_data->menu_default_entry = gfx_data->menu_list + entryno * gfx_data->menu_entry_len;
722 + /* setup list of kernel args */
724 + for(i = max_len = 0; i < num_entries; i++) {
725 + s = get_kernel_args(get_entry(config_entries, i, 1));
727 + if(j > max_len) max_len = j;
730 + gfx_data->args_entry_len = max_len + 1;
732 + gfx_data->args_list = heap;
733 + heap += gfx_data->args_entry_len * gfx_data->menu_entries;
735 + memset(gfx_data->args_list, 0, gfx_data->args_entry_len * gfx_data->menu_entries);
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)));
742 + /* go back here when we no longer need the graphics data */
746 + /* get memory area to be used by graphics functions */
748 + buf = (unsigned char *) (((unsigned) heap + 0xf) & ~0xf);
750 + buf_size = (unsigned char *) &buf - buf - MIN_HEAP_SIZE;
754 + if(buf_size < 0x10000) return;
756 + gfx_data->mem_start = (unsigned) buf;
757 + gfx_data->mem_max = gfx_data->mem_start + buf_size;
760 + printf("graphics menu\n");
762 + "heap = 0x%x, buf = 0x%x (0x%x bytes), graphics_file = %s\n",
763 + heap, gfx_data->mem_start, buf_size, graphics_file
771 + /* read the file */
773 + if(!grub_open(graphics_file)) {
774 + printf("graphics file \"%s\" missing, press a key to continue...\n", graphics_file);
779 + i = grub_read(buf, buf_size);
784 + printf("error reading \"%s\", press a key to continue...\n", graphics_file);
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);
796 + gfx_data->mem_cur = gfx_data->mem_start + ((i + 0x0f + 3) & ~3); /* align it */
799 + printf("image: %d bytes (%d bytes left)\n", i, gfx_data->mem_max - gfx_data->mem_cur);
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);
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;
817 + memcpy((void *) gfx_data->mem_align, (void *) gfx_data->mem_start, i);
820 + /* init interface to graphics functions */
822 + code_start += gfx_data->mem_file;
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
831 + gfx_data->code_seg = code_start >> 4;
834 + printf("code start = 0x%x, code_seg = 0x%x\n", code_start, gfx_data->code_seg);
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];
842 + for(i = 0; i < 12; i++) {
843 + printf("%d: 0x%x\n", i, gfx_data->jmp_table[i]);
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
853 + printf("def: >%s<\n", gfx_data->menu_default_entry);
857 + /* switch to graphics mode */
859 + if(gfx_init(gfx_data)) {
861 + printf("gfx_init failed\n");
867 + gfx_setup_menu(gfx_data);
869 + i = gfx_input(gfx_data, &selected_entry);
871 + /* ESC -> show text menu */
873 + gfx_done(gfx_data);
879 + gfx_done(gfx_data);
881 + heap = saved_heap; /* free most of the graphics data */
883 + // printf("cmdline: >%s<, entry = %d\n", gfx_data->cmdline, selected_entry);
885 + if(selected_entry < 0 || selected_entry > num_entries) return;
888 + /* create new config with modified kernel option */
890 + cfg = get_entry(config_entries, selected_entry, 1);
894 + for(i = 0; ; i++) {
895 + s = get_entry(cfg, i, 0);
897 + if(!i) *heap++ = 0;
901 + if(!memcmp(s, "kernel", 6) && (s[6] == ' ' || s[6] == '\t')) {
903 + if(*t) t = skip_to(0, t);
904 + memmove(heap, s, t - s);
907 + strcpy(heap, gfx_data->cmdline);
908 + heap += strlen(gfx_data->cmdline) + 1;
912 + heap += strlen(s) + 1;
918 + // hexdump(new_config, heap - new_config);
921 + run_script(new_config, heap);
926 get_line_from_config (char *cmdline, int maxlen, int read_from_file)
928 @@ -1059,9 +1474,12 @@
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)
937 + run_graphics_menu(menu_entries, config_entries, num_entries,menu_entries + menu_len, default_entry);
939 + /* Run menu interface. */
940 + run_menu (menu_entries, config_entries, num_entries, menu_entries + menu_len, default_entry);