I'm not the one that did these, but since you asked... ;-) The source RPM is available on: ftp://ftp.caldera.com/pub/eDesktop/Packages/SRPMS/grub-0.5.94-5.src.rpm and the relevant patches from that are attached. initrd1G - places the initrd below 1G so large mem machines will boot. nomeminfo - tries to help some broken BIOSes with mem detection splash - graphical menu (splash) screen, CD ioctl, etc. -- Tim Riker - http://rikers.org/ - short SIGs! <g> All I need to know I could have learned in Kindergarten ... if I'd just been paying attention.
--- grub-0.5.94/stage2/boot.c.orig Thu Feb 10 10:25:16 2000 +++ grub-0.5.94/stage2/boot.c Thu Feb 10 14:49:49 2000 @@ -544,7 +544,7 @@ return 0; } - moveto = ((mbi.mem_upper + 0x400) * 0x400 - len) & 0xfffff000; + moveto = ((mbi.mem_upper + 0x400) * 0x400 - len) & 0x3ffff000; memmove ((void *) RAW_ADDR (moveto), (void *) cur_addr, len); if (cls_hook_seg)
--- grub-0.5.94/stage2/boot.c Thu Feb 10 18:12:26 2000 +++ grub-0.5.94.new/stage2/boot.c Thu Feb 10 16:05:52 2000 @@ -261,17 +261,26 @@ /* copy command-line plus memory hack to staging area */ { char *src = arg; - char *dest = (char *) (CL_MY_LOCATION + 4); - - memmove ((char *) CL_MY_LOCATION, "mem=", 4); - - *((unsigned short *) CL_OFFSET) = CL_MY_LOCATION - CL_BASE_ADDR; - *((unsigned short *) CL_MAGIC_ADDR) = CL_MAGIC; - - dest = convert_to_ascii (dest, 'u', (mbi.mem_upper + 0x400)); - *(dest++) = 'K'; - *(dest++) = ' '; + char *dest = (char *) (CL_MY_LOCATION); + *((unsigned short *) CL_OFFSET) = CL_MY_LOCATION - CL_BASE_ADDR; + *((unsigned short *) CL_MAGIC_ADDR) = CL_MAGIC; + + /* Help Linux to find memory only if more than 64MB are present. + * Up to that amount it is fairly capable to find by itself, + * and at least newer Phoenix BIOSes are known to put a + * 10k hole just before 64MB, but report a proper total. + */ + if (mbi.mem_upper > 65535) /* might subtract 1MB lower mem here */ + { + memmove ((char *) CL_MY_LOCATION, "mem=", 4); + dest = (char *) (CL_MY_LOCATION + 4); + + dest = convert_to_ascii (dest, 'u', (mbi.mem_upper + 0x400)); + *(dest++) = 'K'; + *(dest++) = ' '; + } + while (*src && *src != ' ') src++;
diff -ur grub-0.5.94.orig/grub/asmstub.c grub-0.5.94/grub/asmstub.c --- grub-0.5.94.orig/grub/asmstub.c Wed Jan 19 12:58:36 2000 +++ grub-0.5.94/grub/asmstub.c Wed Jan 19 15:38:06 2000 @@ -43,6 +43,8 @@ #ifdef __linux__ # include <sys/ioctl.h> /* ioctl */ # include <linux/hdreg.h> /* HDIO_GETGEO */ +# include <linux/cdrom.h> /* CDROM_GET_CAPABILITY to identify CDs */ +# define SOME_CDROM_IOCTL CDROM_GET_CAPABILITY # if __GLIBC__ < 2 /* Maybe libc doesn't have large file support. */ # include <linux/unistd.h> /* _llseek */ @@ -56,6 +58,8 @@ #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) # include <sys/ioctl.h> /* ioctl */ # include <sys/disklabel.h> +# include <sys/cdio.h> /* CDIOCCLRDEBUG to identify CDs */ +# define SOME_CDROM_IOCTL CDIOCCLRDEBUG #endif /* __FreeBSD__ || __NetBSD__ || __OpenBSD__ */ #ifdef HAVE_OPENDISK @@ -83,6 +87,9 @@ unsigned long boot_drive = 0; char version_string[] = VERSION; char config_file[128] = "/boot/grub/menu.lst"; /* FIXME: arbitrary */ +char splashscreen_file[128]; + +unsigned short cls_hook_seg; /* Emulation requirements. */ char *grub_scratch_mem = 0; @@ -538,6 +545,11 @@ fclose (fp); return 0; } + + /* Make sure CD-ROMs don't get assigned a BIOS disk number + before SCSI disks ! */ + if (ioctl(fileno(fp), SOME_CDROM_IOCTL, 0) >= 0) + return 0; fclose (fp); return 1; diff -ur grub-0.5.94.orig/stage2/asm.S grub-0.5.94/stage2/asm.S --- grub-0.5.94.orig/stage2/asm.S Wed Jan 19 12:58:36 2000 +++ grub-0.5.94/stage2/asm.S Wed Jan 19 15:38:06 2000 @@ -1345,7 +1345,7 @@ movb %bl, %al movb $0xe, %ah - movw $1, %bx + movw $0x8f, %bx /* invert all planes */ int $0x10 DATA32 call EXT_C(real_to_prot) @@ -1688,24 +1688,45 @@ ENTRY(cls) - push %ebp - push %eax - push %ebx /* save EBX */ + pusha call EXT_C(prot_to_real) .code16 + movw EXT_C(cls_hook_seg), %ax + cmpw $0, %ax + je cls_self + + + mov %ds,%ax + push %ax + + mov %es,%ax + push %ax + + lcall (cls_hook) + + pop %ax + mov %ax,%es + + pop %ax + mov %ax,%ds + + jmp cls_ret + +cls_self: + movb $0xf, %ah int $0x10 /* Get Current Video mode */ xorb %ah, %ah + movw $0x0003, %ax /* hardcode 80x25 color XXX */ int $0x10 /* Set Video mode (clears screen) */ +cls_ret: DATA32 call EXT_C(real_to_prot) .code32 - pop %ebx - pop %eax - pop %ebp + popa ret @@ -1861,10 +1882,19 @@ call EXT_C(prot_to_real) .code16 + movw EXT_C(cls_hook_seg),%ax + cmpw $0, %ax + je sa_text + + movb $0xDB, %al + movw $0x8f, %bx /* invert all planes */ + jmp sa_common +sa_text: movb $0x8, %ah int $0x10 - movb $0x9, %ah movb %cl, %bl +sa_common: + movb $0x9, %ah movw $1, %cx int $0x10 @@ -2068,6 +2098,14 @@ protstack: .long PROTSTACKINIT + +cls_hook: + .word 0 /* offset -- hard-wired for now */ +VARIABLE(cls_hook_seg) + .word 0 + +VARIABLE(splashscreen_file) + .string "\0/boot/grub/splashscreenXXXXXXXXXXXXXXXXXX" VARIABLE(boot_drive) .long 0 diff -ur grub-0.5.94.orig/stage2/boot.c grub-0.5.94/stage2/boot.c --- grub-0.5.94.orig/stage2/boot.c Wed Jan 19 12:58:36 2000 +++ grub-0.5.94/stage2/boot.c Wed Jan 19 15:54:39 2000 @@ -209,8 +209,9 @@ return KERNEL_TYPE_NONE; } - printf (" [Linux-%s, setup=0x%x, size=0x%x]\n", - (big_linux ? "bzImage" : "zImage"), data_len, text_len); + if (!cls_hook_seg) + printf (" [Linux-%s, setup=0x%x, size=0x%x]\n", + (big_linux ? "bzImage" : "zImage"), data_len, text_len); if (mbi.mem_lower >= 608) { @@ -546,7 +547,8 @@ moveto = ((mbi.mem_upper + 0x400) * 0x400 - len) & 0xfffff000; memmove ((void *) RAW_ADDR (moveto), (void *) cur_addr, len); - printf (" [Linux-initrd @ 0x%x, 0x%x bytes]\n", moveto, len); + if (!cls_hook_seg) + printf (" [Linux-initrd @ 0x%x, 0x%x bytes]\n", moveto, len); ramdisk = (unsigned long *) (LINUX_SETUP + LINUX_SETUP_INITRD); ramdisk[0] = RAW_ADDR (moveto); diff -ur grub-0.5.94.orig/stage2/builtins.c grub-0.5.94/stage2/builtins.c --- grub-0.5.94.orig/stage2/builtins.c Wed Jan 19 12:58:36 2000 +++ grub-0.5.94/stage2/builtins.c Wed Jan 19 15:57:29 2000 @@ -168,6 +168,14 @@ if (kernel_type != KERNEL_TYPE_NONE) unset_int15_handler (); + if (kernel_type != KERNEL_TYPE_NONE && + kernel_type != KERNEL_TYPE_LINUX && + kernel_type != KERNEL_TYPE_BIG_LINUX) + { + cls_hook_seg = 0; + cls(); + } + switch (kernel_type) { case KERNEL_TYPE_FREEBSD: @@ -2022,7 +2030,8 @@ bootdev = set_bootdev (hdbias); /* Print the type of the filesystem. */ - print_fsys_type (); + if (!cls_hook_seg) + print_fsys_type (); return 0; } @@ -2524,6 +2533,28 @@ }; +/* spiffy splash screen */ +static int +splashscreen_func (char *arg, int flags) +{ + char * f = splashscreen_file; + char * p = arg; + while ((*f++ = *p++)) + ; + return 0; +} + +static struct builtin builtin_splashscreen = +{ + "splashscreen", + splashscreen_func, + BUILTIN_CMDLINE | BUILTIN_MENU, + "splashscreen FILE", + "Load file as splashscreen hook and call it each time " + "the screen is to be cleared" +}; + + /* testload */ static int testload_func (char *arg, int flags) @@ -2750,6 +2781,7 @@ &builtin_rootnoverify, &builtin_setkey, &builtin_setup, + &builtin_splashscreen, &builtin_testload, &builtin_timeout, &builtin_title, diff -ur grub-0.5.94.orig/stage2/char_io.c grub-0.5.94/stage2/char_io.c --- grub-0.5.94.orig/stage2/char_io.c Thu Nov 11 21:43:14 1999 +++ grub-0.5.94/stage2/char_io.c Wed Jan 19 15:38:06 2000 @@ -169,8 +169,9 @@ { cls (); - printf ("\n GRUB version %s (%dK lower / %dK upper memory)\n\n", - version_string, mbi.mem_lower, mbi.mem_upper); + if (!cls_hook_seg) + printf ("\n GRUB version %s (%dK lower / %dK upper memory)\n\n", + version_string, mbi.mem_lower, mbi.mem_upper); } /* The number of the history entries. */ diff -ur grub-0.5.94.orig/stage2/cmdline.c grub-0.5.94/stage2/cmdline.c --- grub-0.5.94.orig/stage2/cmdline.c Fri Nov 19 18:41:29 1999 +++ grub-0.5.94/stage2/cmdline.c Wed Jan 19 15:38:06 2000 @@ -182,7 +182,8 @@ ; grub_memmove (heap, old_entry, (int) cur_entry - (int) old_entry); - grub_printf ("%s\n", old_entry); + if (!cls_hook_seg) + grub_printf ("%s\n", old_entry); if (! *heap) { diff -ur grub-0.5.94.orig/stage2/shared.h grub-0.5.94/stage2/shared.h --- grub-0.5.94.orig/stage2/shared.h Wed Jan 19 12:58:36 2000 +++ grub-0.5.94/stage2/shared.h Wed Jan 19 15:38:06 2000 @@ -439,6 +439,18 @@ extern void assign_device_name (int drive, const char *device); #endif +extern char splashscreen_file[]; +/* the segment a loaded clear screen hook + * (splashscreen) resides in + */ +extern unsigned short +cls_hook_seg; + +/* The menu geometry */ +extern int menu_w, menu_h, morig_x, morig_y; + +extern int timeout_x, timeout_y; + #ifndef STAGE1_5 /* GUI interface variables. */ extern int fallback_entry; diff -ur grub-0.5.94.orig/stage2/stage2.c grub-0.5.94/stage2/stage2.c --- grub-0.5.94.orig/stage2/stage2.c Wed Jan 19 12:58:36 2000 +++ grub-0.5.94/stage2/stage2.c Wed Jan 19 15:38:06 2000 @@ -38,13 +38,15 @@ return list; } +/* The (default) menu geometry */ +int menu_w = 71, menu_h = 12, morig_x = 3, morig_y = 3; static void print_entries (int y, int size, int first, char *menu_entries) { int i; - gotoxy (77, y + 1); + gotoxy (morig_x+menu_w, y + 1); if (first) putchar (DISP_UP); @@ -57,11 +59,11 @@ { int j = 0; - gotoxy (3, y + i); + gotoxy (morig_x, y + i); while (*menu_entries) { - if (j < 71) + if (j < menu_w) { putchar (*menu_entries); j++; @@ -73,11 +75,11 @@ if (*(menu_entries - 1)) menu_entries++; - for (; j < 71; j++) + for (; j < menu_w; j++) putchar (' '); } - gotoxy (77, y + size); + gotoxy (morig_x+menu_w, y + size); if (*menu_entries) putchar (DISP_DOWN); @@ -91,6 +93,9 @@ { int i; + if (cls_hook_seg) + return; + #ifndef GRUB_UTIL /* Color the menu. The menu is 75 * 14 characters. */ for (i = 0; i < 14; i++) @@ -138,7 +143,7 @@ { int x; - for (x = 2; x < 75; x++) + for (x = morig_x-1; x < morig_x+menu_w+1; x++) { gotoxy (x, y); set_attrib (attr); @@ -167,11 +172,15 @@ #endif } +int timeout_x = 3, timeout_y = 22; +#define TIMEOUT_TEXT \ +"The highlighted entry will be booted automatically in %d seconds. " + static void run_menu (char *menu_entries, char *config_entries, int num_entries, char *heap, int entryno) { - int c, time1, time2 = -1, first_entry = 0; + int c, time1, time2 = -1, first_entry = 0, firsttimer=1; char *cur_entry; /* @@ -179,7 +188,7 @@ */ restart: - while (entryno > 11) + while (entryno > menu_h-1) { first_entry++; entryno--; @@ -190,8 +199,11 @@ nocursor (); #endif - print_border (3, 12); + print_border (morig_y, menu_h); + + if (!cls_hook_seg) + { #ifdef GRUB_UTIL grub_printf ("\n Use the up and down arrows for selecting which entry is highlighted.\n"); @@ -218,15 +230,16 @@ after (\'O\' for before) the selected line, \'d\' to remove the selected line, or escape to go back to the main menu."); } - - print_entries (3, 12, first_entry, menu_entries); + } + print_entries (morig_y, menu_h, first_entry, menu_entries); /* highlight initial line */ - set_line_highlight (4 + entryno); + set_line_highlight (morig_y+1 + entryno); /* XX using RT clock now, need to initialize value */ while ((time1 = getrtsecs()) == 0xFF); + firsttimer=1; while (1) { /* initilize to NULL just in case... */ @@ -237,14 +250,21 @@ if (grub_timeout <= 0) { grub_timeout = -1; + gotoxy (timeout_x, timeout_y); + printf (TIMEOUT_TEXT, 0); break; } /* else not booting yet! */ time2 = time1; - gotoxy (3, 22); - printf ("The highlighted entry will be booted automatically in %d seconds. ", grub_timeout); - gotoxy (74, 4 + entryno); + gotoxy (timeout_x, timeout_y); + if (!firsttimer) + printf (TIMEOUT_TEXT, grub_timeout+1); + else + firsttimer=0; + gotoxy (timeout_x, timeout_y); + printf (TIMEOUT_TEXT, grub_timeout); + gotoxy (morig_x+menu_w, morig_y+1 + entryno); grub_timeout--; } @@ -254,42 +274,48 @@ if (grub_timeout >= 0) { - gotoxy (3, 22); + gotoxy (timeout_x, timeout_y); + printf (TIMEOUT_TEXT, grub_timeout+1); + gotoxy (timeout_x, timeout_y); printf (" "); grub_timeout = -1; fallback_entry = -1; - gotoxy (74, 4 + entryno); + gotoxy (morig_x+menu_w, morig_y+1 + entryno); } if ((c == KEY_UP) || (ASCII_CHAR (c) == 16)) { if (entryno > 0) { - set_line_normal (4 + entryno); + set_line_normal (morig_y+1 + entryno); entryno--; - set_line_highlight (4 + entryno); + set_line_highlight (morig_y+1 + entryno); } else if (first_entry > 0) { + set_line_normal (morig_y+1); + print_entries (morig_y, menu_h, first_entry, menu_entries); first_entry--; - print_entries (3, 12, first_entry, menu_entries); - set_line_highlight (4); + print_entries (morig_y, menu_h, first_entry, menu_entries); + set_line_highlight (morig_y+1); } } if (((c == KEY_DOWN) || (ASCII_CHAR (c) == 14)) && (first_entry + entryno + 1) < num_entries) { - if (entryno < 11) + if (entryno < menu_h-1) { - set_line_normal (4 + entryno); + set_line_normal (morig_y+1 + entryno); entryno++; - set_line_highlight (4 + entryno); + set_line_highlight (morig_y+1 + entryno); } - else if (num_entries > 12 + first_entry) + else if (num_entries > menu_h + first_entry) { + set_line_normal (morig_y+menu_h); + print_entries (morig_y, menu_h, first_entry, menu_entries); first_entry++; - print_entries (3, 12, first_entry, menu_entries); - set_line_highlight (15); + print_entries (morig_y, menu_h, first_entry, menu_entries); + set_line_highlight (morig_y+menu_h); } } @@ -304,7 +330,8 @@ { if ((c == 'd') || (c == 'o') || (c == 'O')) { - set_line_normal (4 + entryno); + set_line_normal (morig_y+1 + entryno); + print_entries (morig_y, menu_h, first_entry, menu_entries); /* insert after is almost exactly like insert before */ if (c == 'o') @@ -342,12 +369,12 @@ if (entryno >= num_entries) entryno--; - if (first_entry && num_entries < 12 + first_entry) + if (first_entry && num_entries < menu_h + first_entry) first_entry--; } - print_entries (3, 12, first_entry, menu_entries); - set_line_highlight (4 + entryno); + print_entries (morig_y, menu_h, first_entry, menu_entries); + set_line_highlight (morig_y+1 + entryno); } cur_entry = menu_entries; @@ -401,6 +428,15 @@ int num_entries = 0, i = 0; char *new_heap; + morig_x = 3; + morig_y = 3; + menu_h = 12; + menu_w = 71; + timeout_x = 3; + timeout_y = 22; + cls_hook_seg = 0; + cls(); + if (config_entries) { new_heap = heap; @@ -496,12 +532,15 @@ { cls (); - if (config_entries) - printf (" Booting \'%s\'\n\n", - get_entry (menu_entries, first_entry + entryno, 0)); - else - printf (" Booting command-list\n\n"); - + if (!cls_hook_seg) + { + if (config_entries) + printf (" Booting \'%s\'\n\n", + get_entry (menu_entries, first_entry + entryno, 0)); + else + printf (" Booting command-list\n\n"); + } + if (! cur_entry) cur_entry = get_entry (config_entries, first_entry + entryno, 1); @@ -696,6 +735,36 @@ grub_close (); } + if (*splashscreen_file && grub_open (splashscreen_file) ) + { + if ( grub_read ((char *) RAW_ADDR (0x50000), -1) > 0 ) + { + cls_hook_seg = 0x5000; + + morig_x = 2; + morig_y = 6; + menu_h = 20; + menu_w = 51; + + timeout_x = 2; + timeout_y = 28; /* Grafix screen has 80x30 Chars */ + } + + /* grub_printf("would use splashscreen file %s\n", splashscreen_file); */ + + *splashscreen_file = '\0'; + grub_close (); + } + else + { + morig_x = 3; + morig_y = 3; + menu_h = 12; + menu_w = 71; + timeout_x = 3; + timeout_y = 22; + } + if (! num_entries) { /* If no acceptable config file, goto command-line, starting @@ -705,6 +774,7 @@ } else { + cls(); /* Run menu interface. */ run_menu (menu_entries, config_entries, num_entries, menu_entries + menu_len, default_entry); --- grub-0.5.94/stage2/boot.c.orig Thu Feb 10 21:16:20 2000 +++ grub-0.5.94/stage2/boot.c Mon Feb 14 19:29:56 2000 @@ -229,7 +229,7 @@ /* Handle special strings. */ if (substring ("normal", value) < 1) - vid_mode = LINUX_VID_MODE_NORMAL; + vid_mode = LINUX_VID_MODE_NORMAL, cls_hook_seg = 0; else if (substring ("ext", value) < 1) vid_mode = LINUX_VID_MODE_EXTENDED; else if (substring ("ask", value) < 1) @@ -326,7 +326,8 @@ mbi.syms.a.addr = 0; mbi.syms.a.pad = 0; - printf (" [%s-%s", str2, str); + if (!cls_hook_seg) + printf (" [%s-%s", str2, str); str = ""; @@ -489,7 +490,10 @@ } if (!errnum) - printf (", entry=0x%x]\n", (int) entry_addr); + { + if (!cls_hook_seg) + printf (", entry=0x%x]\n", (int) entry_addr); + } else { putchar ('\n');