From: ms Date: Sat, 12 Aug 2006 15:16:04 +0000 (+0000) Subject: Hinzugefügt: X-Git-Tag: v2.3-beta1~1010 X-Git-Url: http://git.ipfire.org/?p=people%2Fpmueller%2Fipfire-2.x.git;a=commitdiff_plain;h=27996c53e756406da9bcf45c1ce7583c2412666c;ds=sidebyside Hinzugefügt: * GFXBoot - experimental git-svn-id: http://svn.ipfire.org/svn/ipfire/trunk@244 ea5c0bd1-69bd-2848-81d8-4f18e57aeed8 --- diff --git a/config/aboot/scsiaboot.conf b/config/aboot/scsiaboot.conf index b3f0fb3cd3..4915e41d63 100644 --- a/config/aboot/scsiaboot.conf +++ b/config/aboot/scsiaboot.conf @@ -1 +1 @@ -0:1/vmlinuz root=ROOT panic=10 initrd=ipcoprd.img init=/linuxrc rw +0:1/vmlinuz root=ROOT panic=10 initrd=ipfirerd.img init=/linuxrc rw diff --git a/config/grub/grub.conf b/config/grub/grub.conf index ff9af0b3c6..543f976552 100644 --- a/config/grub/grub.conf +++ b/config/grub/grub.conf @@ -1,45 +1,47 @@ -timeout 5 -default saved +timeout 10 +#default saved foreground = 16064e background = ffffff -splashimage (hd0,0)/grub/ipfire.xpm.gz +gfxmenu /grub/message +#hiddenmenu +#splashimage (hd0,0)/grub/ipfire.xpm.gz title IPFire (1024x768) root (hd0,0) kernel /vmlinuz root=ROOT panic=10 acpi=off vga=791 splash=silent ro initrd /initrd.splash - savedefault + #savedefault title IPFire (640x480) root (hd0,0) kernel /vmlinuz root=ROOT panic=10 acpi=off vga=785 splash=silent ro initrd /initrd.splash - savedefault + #savedefault title IPFire SMP (1024x768) root (hd0,0) kernel /vmlinuz-smp root=ROOT panic=10 acpi=off vga=791 splash=silent ro initrd /initrd.splash - savedefault + #savedefault title IPFire SMP (640x480) root (hd0,0) kernel /vmlinuz-smp root=ROOT panic=10 acpi=off vga=785 splash=silent ro initrd /initrd.splash - savedefault + #savedefault title IPFire (ACPI enabled) (1024x768) root (hd0,0) kernel /vmlinuz root=ROOT panic=10 vga=791 splash=silent ro initrd /initrd.splash - savedefault + #savedefault title IPFire (ACPI enabled) (640x480) root (hd0,0) kernel /vmlinuz root=ROOT panic=10 vga=785 splash=silent ro initrd /initrd.splash - savedefault + #savedefault title IPFire SMP (ACPI HT enabled) (1024x768) root (hd0,0) kernel /vmlinuz-smp root=ROOT panic=10 acpi=ht vga=791 splash=silent ro initrd /initrd.splash - savedefault + #savedefault title IPFire SMP (ACPI HT enabled) (640x480) root (hd0,0) kernel /vmlinuz-smp root=ROOT panic=10 acpi=ht vga=785 splash=silent ro initrd /initrd.splash - savedefault + #savedefault diff --git a/config/grub/message b/config/grub/message new file mode 100644 index 0000000000..6825ac916b Binary files /dev/null and b/config/grub/message differ diff --git a/config/grub/scsigrub.conf b/config/grub/scsigrub.conf index 13a850a183..9b20e03bd0 100644 --- a/config/grub/scsigrub.conf +++ b/config/grub/scsigrub.conf @@ -1,45 +1,47 @@ -timeout 5 -default saved +timeout 10 +#default saved foreground = 16064e background = ffffff -splashimage (hd0,0)/grub/ipfire.xpm.gz +gfxmenu /grub/message +#hiddenmenu +#splashimage (hd0,0)/grub/ipfire.xpm.gz title IPFire (1024x768) root (hd0,0) kernel /vmlinuz root=ROOT panic=10 init=/linuxrc acpi=off vga=791 splash=silent rw initrd /ipfirerd.img - savedefault + #savedefault title IPFire (640x480) root (hd0,0) kernel /vmlinuz root=ROOT panic=10 init=/linuxrc acpi=off vga=785 splash=silent rw initrd /ipfirerd.img - savedefault + #savedefault title IPFire SMP (1024x768) root (hd0,0) kernel /vmlinuz-smp root=ROOT panic=10 init=/linuxrc acpi=off vga=791 splash=silent rw initrd /ipfirerd-smp.img - savedefault + #savedefault title IPFire SMP (640x480) root (hd0,0) kernel /vmlinuz-smp root=ROOT panic=10 init=/linuxrc acpi=off vga=785 splash=silent rw initrd /ipfirerd-smp.img - savedefault + #savedefault title IPFire (ACPI enabled) (1024x768) root (hd0,0) kernel /vmlinuz root=ROOT panic=10 init=/linuxrc vga=791 splash=silent rw initrd /ipfirerd.img - savedefault + #savedefault title IPFire (ACPI enabled) (640x480) root (hd0,0) kernel /vmlinuz root=ROOT panic=10 init=/linuxrc vga=785 splash=silent rw initrd /ipfirerd.img - savedefault + #savedefault title IPFire SMP (ACPI HT enabled) (1024x768) root (hd0,0) kernel /vmlinuz-smp root=ROOT panic=10 init=/linuxrc acpi=ht vga=791 splash=silent rw initrd /ipfirerd-smp.img - savedefault + #savedefault title IPFire SMP (ACPI HT enabled) (640x480) root (hd0,0) kernel /vmlinuz-smp root=ROOT panic=10 init=/linuxrc acpi=ht vga=785 splash=silent rw initrd /ipfirerd-smp.img - savedefault + #savedefault diff --git a/doc/packages-list.txt b/doc/packages-list.txt index ab533270f8..caa14196b1 100644 --- a/doc/packages-list.txt +++ b/doc/packages-list.txt @@ -104,6 +104,7 @@ * grep-2.5.1 * groff-1.19 * grub-0.95 + * grub-0.97 * gzip-1.3.5 * hddtemp-0.3-beta14 * hdparm-6.3 diff --git a/lfs/grub b/lfs/grub index aa5dc69a00..d0800523e6 100644 --- a/lfs/grub +++ b/lfs/grub @@ -32,7 +32,7 @@ include Config -VER = 0.95 +VER = 0.97 THISAPP = grub-$(VER) DL_FILE = $(THISAPP).tar.gz @@ -50,7 +50,7 @@ objects = $(DL_FILE) $(DL_FILE) = $(DL_FROM)/$(DL_FILE) -$(DL_FILE)_MD5 = 4ca8e4363d5f1980f2c63b7f5cdbe0d1 +$(DL_FILE)_MD5 = cd3f3eb54446be6003156158d51f4884 install : $(TARGET) @@ -80,21 +80,45 @@ $(subst %,%_MD5,$(objects)) : $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects)) @$(PREBUILD) @rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar zxf $(DIR_DL)/$(DL_FILE) - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.93-configfile.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.90-symlinkmenulst.patch - cd $(DIR_APP) && patch -Np0 < $(DIR_SRC)/src/patches/grub-0.93-endedit.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.90-append.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.91-bootonce.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.93-graphics.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.91-splashimagehelp.patch - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.93-graphics-bootterm.patch + +# cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.93-configfile.patch +# cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.90-symlinkmenulst.patch +# cd $(DIR_APP) && patch -Np0 < $(DIR_SRC)/src/patches/grub-0.93-endedit.patch +# cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.90-append.patch +# cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.91-bootonce.patch +# cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.93-graphics.patch +# cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.91-splashimagehelp.patch +# cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.93-graphics-bootterm.patch +# cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.93-special-device-names.patch +# cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.94-i2o.patch +# cd $(DIR_APP)/netboot && patch -Np0 < $(DIR_SRC)/src/patches/grub-0.93-rtl8139.patch + + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97/grub-0.97-configfile.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97/grub-0.97-symlinkmenulst.patch +# cd $(DIR_APP) && patch -Np0 < $(DIR_SRC)/src/patches/grub-0.93-endedit.patch +# cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.90-append.patch +# cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.91-bootonce.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97/grub-0.97-misc.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97/grub-0.97-dirs.patch + +# cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.93-graphics.patch +# cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.91-splashimagehelp.patch +# cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.93-graphics-bootterm.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97/grub-0.97-splash.patch +# cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97/grub-0.97-wildcards.patch +# cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97/grub-0.96-PIC.patch +# cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97/grub-0.96-bounced-checks.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.93-special-device-names.patch +# cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97/grub-0.96-i2o-raid.patch cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.94-i2o.patch +# cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97/grub-0.96-nxstack.patch +# cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grub-0.97/grub-0.96-netboot-pic.patch cd $(DIR_APP)/netboot && patch -Np0 < $(DIR_SRC)/src/patches/grub-0.93-rtl8139.patch + cd $(DIR_APP) && autoreconf --install --force cd $(DIR_APP) && CFLAGS="-Os -fno-stack-protector" \ STAGE2_CFLAGS="-Os -fno-stack-protector" \ - ./configure --prefix=/usr \ + ./configure --prefix=/usr --datadir=/usr/share \ --enable-rtl8139 \ --enable-ne --enable-ne-scan=0x300 \ --disable-nls \ diff --git a/src/ROOTFILES.i386 b/src/ROOTFILES.i386 index 2ece52dec5..4eddbcdbd4 100644 --- a/src/ROOTFILES.i386 +++ b/src/ROOTFILES.i386 @@ -1267,6 +1267,7 @@ boot/grub/grub.conf boot/grub/grubbatch boot/grub/ipfire.xpm.gz boot/grub/scsigrub.conf +boot/grub/message #usr/bin/mbchk usr/sbin/grub usr/sbin/grub-install diff --git a/src/install+setup/install/grubbatch b/src/install+setup/install/grubbatch index 405baf2761..2893d63e46 100644 --- a/src/install+setup/install/grubbatch +++ b/src/install+setup/install/grubbatch @@ -1,6 +1,6 @@ #!/bin/sh /bin/cp -f /usr/share/grub/i386-pc/* /boot/grub -/usr/sbin/grub --no-floppy --batch < /dev/null 2> /dev/null +/usr/sbin/grub --no-floppy --batch < /dev/null 2> /dev/null device (hd0) DEVICE root (hd0,0) setup (hd0,0) diff --git a/src/patches/grub-0.97/README b/src/patches/grub-0.97/README new file mode 100644 index 0000000000..3fffda6c04 --- /dev/null +++ b/src/patches/grub-0.97/README @@ -0,0 +1,30 @@ +This file describes the patches in the patchsets: + +001_all_grub-0.97-misc.patch + Several simple fixes + +002_all_grub-0.97-splash.patch + Port of the SuSE's gfxboot patch + +003_all_grub-0.97-dirs.patch + FHS compilance + +004_all_grub-0.97-wildcards.patch + Port of the SuSE's wildcards patch with custom nice sorting addon + +005_all_grub-0.96-PIC.patch: + a patch to fix PIC issues by psm and Kevin F. Quinn in Gentoo bug #80693 + +010_all_grub-0.96-bounced-checks.patch: + Disables testing of FFS and UFS2 images (which always fail). See Gentoo bug + #71811 + +020_all_grub-0.96-i2o-raid.patch: + Support i2o RAID. See Gentoo bug #76143 + +040_all_grub-0.96-nxstack.patch: + Fix NX segfaulting on amd64 and x86_64. The patch is by Peter Jones. + See: http://lists.gnu.org/archive/html/bug-grub/2005-03/msg00011.html + +060_all_grub-0.96-netboot-pic.patch + Fix PIC issues in netboot code. See Gentoo bug #85566 diff --git a/src/patches/grub-0.97/grub-0.96-PIC.patch b/src/patches/grub-0.97/grub-0.96-PIC.patch new file mode 100644 index 0000000000..c69c0fa0e3 --- /dev/null +++ b/src/patches/grub-0.97/grub-0.96-PIC.patch @@ -0,0 +1,71 @@ +--- grub-0.96/stage2/char_io.c.orig 2005-02-18 09:12:39.163407496 +0100 ++++ grub-0.96/stage2/char_io.c 2005-02-18 09:13:11.431502000 +0100 +@@ -1202,37 +1202,62 @@ + } + #endif /* ! STAGE1_5 */ + ++#ifdef GRUB_UTIL ++# ifdef __PIC__ ++# if defined(HAVE_START_SYMBOL) && defined(HAVE_END_SYMBOL) ++ extern char start[]; ++ extern char end[]; ++# elif defined(HAVE_USCORE_START_SYMBOL) && defined (HAVE_USCORE_END_SYMBOL) ++ extern char _start[]; ++ extern char _end[]; ++# endif ++# endif ++#endif + int + memcheck (int addr, int len) + { + #ifdef GRUB_UTIL ++# ifdef __PIC__ ++# if defined(HAVE_START_SYMBOL) && defined(HAVE_END_SYMBOL) ++ if (start <= addr && end > addr + len) ++ return ! errnum; ++# elif defined(HAVE_USCORE_START_SYMBOL) && defined (HAVE_USCORE_END_SYMBOL) ++ if (_start <= addr && _end > addr + len) ++ return ! errnum; ++# endif ++# else /* __PIC__ */ + auto int start_addr (void); + auto int end_addr (void); + + auto int start_addr (void) + { + int ret; +-# if defined(HAVE_START_SYMBOL) ++# if defined(HAVE_START_SYMBOL) + asm volatile ("movl $start, %0" : "=a" (ret)); +-# elif defined(HAVE_USCORE_START_SYMBOL) ++# elif defined(HAVE_USCORE_START_SYMBOL) + asm volatile ("movl $_start, %0" : "=a" (ret)); +-# endif ++# else ++ erk! /* function would return undefined data in this case - barf */ ++# endif + return ret; + } + + auto int end_addr (void) + { + int ret; +-# if defined(HAVE_END_SYMBOL) ++# if defined(HAVE_END_SYMBOL) + asm volatile ("movl $end, %0" : "=a" (ret)); +-# elif defined(HAVE_USCORE_END_SYMBOL) ++# elif defined(HAVE_USCORE_END_SYMBOL) + asm volatile ("movl $_end, %0" : "=a" (ret)); +-# endif ++# else ++ erk! /* function would return undefined data in this case - barf */ ++# endif + return ret; + } + + if (start_addr () <= addr && end_addr () > addr + len) + return ! errnum; ++# endif /* __PIC__ */ + #endif /* GRUB_UTIL */ + + if ((addr < RAW_ADDR (0x1000)) diff --git a/src/patches/grub-0.97/grub-0.96-bounced-checks.patch b/src/patches/grub-0.97/grub-0.96-bounced-checks.patch new file mode 100644 index 0000000000..6ad2c82ee0 --- /dev/null +++ b/src/patches/grub-0.97/grub-0.96-bounced-checks.patch @@ -0,0 +1,19 @@ +Remove tests that the grub maintainers say can be ignored. + +http://lists.gnu.org/archive/html/bug-grub/2004-05/msg00076.html + +--- grub-0.96/stage2/size_test ++++ grub-0.96/stage2/size_test +@@ -36,9 +36,9 @@ + } + + # The bootloader area of a FFS partition is 14 sectors. +-check ffs_stage1_5 7168 +- +-check ufs2_stage1_5 7168 ++#check ffs_stage1_5 7168 ++# ++#check ufs2_stage1_5 7168 + + # Stage 1.5 can be installed in the sectors immediately after MBR in the + # first cylinder, so the size is (63 - 1) sectors. diff --git a/src/patches/grub-0.97/grub-0.96-i2o-raid.patch b/src/patches/grub-0.97/grub-0.96-i2o-raid.patch new file mode 100644 index 0000000000..5beec6f811 --- /dev/null +++ b/src/patches/grub-0.97/grub-0.96-i2o-raid.patch @@ -0,0 +1,61 @@ +diff -ru grub-0.96-orig/lib/device.c grub-0.96/lib/device.c +--- grub-0.96-orig/lib/device.c 2005-02-16 22:33:09.669384408 -0600 ++++ grub-0.96/lib/device.c 2005-02-17 00:47:05.127596672 -0600 +@@ -407,6 +407,12 @@ + { + sprintf (name, "/dev/ataraid/d%c", unit + '0'); + } ++ ++static void ++get_i2o_disk_name (char *name, int unit) ++{ ++ sprintf (name, "/dev/i2o/hd%c", unit + 'a'); ++} + #endif + + /* Check if DEVICE can be read. If an error occurs, return zero, +@@ -798,6 +804,26 @@ + } + } + } ++ ++ /* I2O disks. */ ++ for (i = 0; i < 8; i++) ++ { ++ char name[16]; ++ ++ get_i2o_disk_name (name, i); ++ if (check_device (name)) ++ { ++ (*map)[num_hd + 0x80] = strdup (name); ++ assert ((*map)[num_hd + 0x80]); ++ ++ /* If the device map file is opened, write the map. */ ++ if (fp) ++ fprintf (fp, "(hd%d)\t%s\n", num_hd, name); ++ ++ num_hd++; ++ } ++ } ++ + #endif /* __linux__ */ + + /* OK, close the device map file if opened. */ +@@ -858,8 +884,15 @@ + if (strcmp (dev + strlen(dev) - 5, "/disc") == 0) + strcpy (dev + strlen(dev) - 5, "/part"); + } +- sprintf (dev + strlen(dev), "%d", ((partition >> 16) & 0xFF) + 1); +- ++ sprintf (dev + strlen(dev), "%s%d", ++ /* Compaq smart and others */ ++ (strncmp(dev, "/dev/ida/", 9) == 0 || ++ strncmp(dev, "/dev/ataraid/", 13) == 0 || ++ strncmp(dev, "/dev/cciss/", 11) == 0 || ++ strncmp(dev, "/dev/rd/", 8) == 0 || ++ strncmp(dev, "/dev/i2o/", 9) == 0) ? "p" : "", ++ ((partition >> 16) & 0xFF) + 1); ++ + /* Open the partition. */ + fd = open (dev, O_RDWR); + if (fd < 0) diff --git a/src/patches/grub-0.97/grub-0.96-netboot-pic.patch b/src/patches/grub-0.97/grub-0.96-netboot-pic.patch new file mode 100644 index 0000000000..5cac692bb2 --- /dev/null +++ b/src/patches/grub-0.97/grub-0.96-netboot-pic.patch @@ -0,0 +1,15 @@ +Patch by the PaX Team to fix PIC/PIE problems. + +http://bugs.gentoo.org/show_bug.cgi?id=85566 + +--- netboot/main.c ++++ netboot/main.c +@@ -701,7 +701,7 @@ + "adcw %%ax,%0\n\t" /* add carry of previous iteration */ + "loop 1b\n\t" + "adcw $0,%0" /* add carry of last iteration */ +- : "=b" (*sum), "=S"(start), "=c"(len) ++ : "=r" (*sum), "=S"(start), "=c"(len) + : "0"(*sum), "1"(start), "2"(len) + : "ax", "cc" + ); diff --git a/src/patches/grub-0.97/grub-0.96-nxstack.patch b/src/patches/grub-0.97/grub-0.96-nxstack.patch new file mode 100644 index 0000000000..ebfa82b808 --- /dev/null +++ b/src/patches/grub-0.97/grub-0.96-nxstack.patch @@ -0,0 +1,617 @@ +--- grub-0.97/grub/asmstub.c ++++ grub-0.97/grub/asmstub.c +@@ -42,6 +42,7 @@ + #include + #include + #include ++#include + + #ifdef __linux__ + # include /* ioctl */ +@@ -79,7 +80,7 @@ + struct apm_info apm_bios_info; + + /* Emulation requirements. */ +-char *grub_scratch_mem = 0; ++void *grub_scratch_mem = 0; + + struct geometry *disks = 0; + +@@ -103,14 +104,62 @@ + static unsigned int serial_speed; + #endif /* SIMULATE_SLOWNESS_OF_SERIAL */ + ++/* This allocates page-aligned storage of the specified size, which must be ++ * a multiple of the page size as determined by calling sysconf(_SC_PAGESIZE) ++ */ ++#ifdef __linux__ ++static void * ++grub_mmap_alloc(size_t len) ++{ ++ int mmap_flags = MAP_ANONYMOUS|MAP_PRIVATE|MAP_EXECUTABLE; ++ ++#ifdef MAP_32BIT ++ mmap_flags |= MAP_32BIT; ++#endif ++ /* Mark the simulated stack executable, as GCC uses stack trampolines ++ * to implement nested functions. */ ++ return mmap(NULL, len, PROT_READ|PROT_WRITE|PROT_EXEC, mmap_flags, -1, 0); ++} ++#else /* !defined(__linux__) */ ++static void * ++grub_mmap_alloc(size_t len) ++{ ++ int fd = 0, offset = 0, ret = 0; ++ void *pa = MAP_FAILED; ++ char template[] = "/tmp/grub_mmap_alloc_XXXXXX"; ++ errno_t e; ++ ++ fd = mkstemp(template); ++ if (fd < 0) ++ return pa; ++ ++ unlink(template); ++ ++ ret = ftruncate(fd, len); ++ if (ret < 0) ++ return pa; ++ ++ /* Mark the simulated stack executable, as GCC uses stack trampolines ++ * to implement nested functions. */ ++ pa = mmap(NULL, len, PROT_READ|PROT_WRITE|PROT_EXEC, ++ MAP_PRIVATE|MAP_EXECUTABLE, fd, offset); ++ ++ e = errno; ++ close(fd); ++ errno = e; ++ return pa; ++} ++#endif /* defined(__linux__) */ ++ + /* The main entry point into this mess. */ + int + grub_stage2 (void) + { + /* These need to be static, because they survive our stack transitions. */ + static int status = 0; +- static char *realstack; +- char *scratch, *simstack; ++ static void *realstack; ++ void *simstack_alloc_base, *simstack; ++ size_t simstack_size, page_size; + int i; + + /* We need a nested function so that we get a clean stack frame, +@@ -140,9 +189,35 @@ + } + + assert (grub_scratch_mem == 0); +- scratch = malloc (0x100000 + EXTENDED_MEMSIZE + 15); +- assert (scratch); +- grub_scratch_mem = (char *) ((((int) scratch) >> 4) << 4); ++ ++ /* Allocate enough pages for 0x100000 + EXTENDED_SIZE + 15, and ++ * make sure the memory is aligned to a multiple of the system's ++ * page size */ ++ page_size = sysconf (_SC_PAGESIZE); ++ simstack_size = ( 0x100000 + EXTENDED_MEMSIZE + 15); ++ if (simstack_size % page_size) ++ { ++ /* If we're not on a page_size boundary, round up to the next one */ ++ simstack_size &= ~(page_size-1); ++ simstack_size += page_size; ++ } ++ ++ /* Add one for a PROT_NONE boundary page at each end. */ ++ simstack_size += 2 * page_size; ++ ++ simstack_alloc_base = grub_mmap_alloc(simstack_size); ++ assert (simstack_alloc_base != MAP_FAILED); ++ ++ /* mark pages above and below our simstack area as innaccessable. ++ * If the implementation we're using doesn't support that, then the ++ * new protection modes are undefined. It's safe to just ignore ++ * them, though. It'd be nice if we knew that we'd get a SEGV for ++ * touching the area, but that's all. it'd be nice to have. */ ++ mprotect (simstack_alloc_base, page_size, PROT_NONE); ++ mprotect ((void *)((unsigned long)simstack_alloc_base + ++ simstack_size - page_size), page_size, PROT_NONE); ++ ++ grub_scratch_mem = (void *)((unsigned long)simstack_alloc_base + page_size); + + /* FIXME: simulate the memory holes using mprot, if available. */ + +@@ -215,7 +290,7 @@ + device_map = 0; + free (disks); + disks = 0; +- free (scratch); ++ munmap(simstack_alloc_base, simstack_size); + grub_scratch_mem = 0; + + if (serial_device) +--- grub-0.97/stage2/builtins.c ++++ grub-0.97/stage2/builtins.c +@@ -131,63 +131,98 @@ + } + + ++/* blocklist_read_helper nee disk_read_blocklist_func was a nested ++ * function, to which pointers were taken and exposed globally. Even ++ * in the GNU-C nested functions extension, they have local linkage, ++ * and aren't guaranteed to be accessable *at all* outside of their ++ * containing scope. ++ * ++ * Above and beyond all of that, the variables within blocklist_func_context ++ * are originally local variables, with local (not even static) linkage, ++ * from within blocklist_func. These were each referenced by ++ * disk_read_blocklist_func, which is only called from other functions ++ * through a globally scoped pointer. ++ * ++ * The documentation in GCC actually uses the words "all hell will break ++ * loose" to describe this scenario. ++ * ++ * Also, "start_sector" was also used uninitialized, but gcc doesn't warn ++ * about it (possibly because of the scoping madness?) ++ */ ++ ++static struct { ++ int start_sector; ++ int num_sectors; ++ int num_entries; ++ int last_length; ++} blocklist_func_context = { ++ .start_sector = 0, ++ .num_sectors = 0, ++ .num_entries = 0, ++ .last_length = 0 ++}; ++ ++/* Collect contiguous blocks into one entry as many as possible, ++ and print the blocklist notation on the screen. */ ++static void ++blocklist_read_helper (int sector, int offset, int length) ++{ ++ int *start_sector = &blocklist_func_context.start_sector; ++ int *num_sectors = &blocklist_func_context.num_sectors; ++ int *num_entries = &blocklist_func_context.num_entries; ++ int *last_length = &blocklist_func_context.last_length; ++ ++ if (*num_sectors > 0) ++ { ++ if (*start_sector + *num_sectors == sector ++ && offset == 0 && *last_length == SECTOR_SIZE) ++ { ++ *num_sectors++; ++ *last_length = length; ++ return; ++ } ++ else ++ { ++ if (*last_length == SECTOR_SIZE) ++ grub_printf ("%s%d+%d", *num_entries ? "," : "", ++ *start_sector - part_start, *num_sectors); ++ else if (*num_sectors > 1) ++ grub_printf ("%s%d+%d,%d[0-%d]", *num_entries ? "," : "", ++ *start_sector - part_start, *num_sectors-1, ++ *start_sector + *num_sectors-1 - part_start, ++ *last_length); ++ else ++ grub_printf ("%s%d[0-%d]", *num_entries ? "," : "", ++ *start_sector - part_start, *last_length); ++ *num_entries++; ++ *num_sectors = 0; ++ } ++ } ++ ++ if (offset > 0) ++ { ++ grub_printf("%s%d[%d-%d]", *num_entries ? "," : "", ++ sector-part_start, offset, offset+length); ++ *num_entries++; ++ } ++ else ++ { ++ *start_sector = sector; ++ *num_sectors = 1; ++ *last_length = length; ++ } ++} ++ + /* blocklist */ + static int + blocklist_func (char *arg, int flags) + { + char *dummy = (char *) RAW_ADDR (0x100000); +- int start_sector; +- int num_sectors = 0; +- int num_entries = 0; +- int last_length = 0; +- +- auto void disk_read_blocklist_func (int sector, int offset, int length); +- +- /* Collect contiguous blocks into one entry as many as possible, +- and print the blocklist notation on the screen. */ +- auto void disk_read_blocklist_func (int sector, int offset, int length) +- { +- if (num_sectors > 0) +- { +- if (start_sector + num_sectors == sector +- && offset == 0 && last_length == SECTOR_SIZE) +- { +- num_sectors++; +- last_length = length; +- return; +- } +- else +- { +- if (last_length == SECTOR_SIZE) +- grub_printf ("%s%d+%d", num_entries ? "," : "", +- start_sector - part_start, num_sectors); +- else if (num_sectors > 1) +- grub_printf ("%s%d+%d,%d[0-%d]", num_entries ? "," : "", +- start_sector - part_start, num_sectors-1, +- start_sector + num_sectors-1 - part_start, +- last_length); +- else +- grub_printf ("%s%d[0-%d]", num_entries ? "," : "", +- start_sector - part_start, last_length); +- num_entries++; +- num_sectors = 0; +- } +- } +- +- if (offset > 0) +- { +- grub_printf("%s%d[%d-%d]", num_entries ? "," : "", +- sector-part_start, offset, offset+length); +- num_entries++; +- } +- else +- { +- start_sector = sector; +- num_sectors = 1; +- last_length = length; +- } +- } + ++ int *start_sector = &blocklist_func_context.start_sector; ++ int *num_sectors = &blocklist_func_context.num_sectors; ++ int *num_entries = &blocklist_func_context.num_entries; ++ + /* Open the file. */ + if (! grub_open (arg)) + return 1; +@@ -204,15 +241,15 @@ + grub_printf (")"); + + /* Read in the whole file to DUMMY. */ +- disk_read_hook = disk_read_blocklist_func; ++ disk_read_hook = blocklist_read_helper; + if (! grub_read (dummy, -1)) + goto fail; + + /* The last entry may not be printed yet. Don't check if it is a + * full sector, since it doesn't matter if we read too much. */ +- if (num_sectors > 0) +- grub_printf ("%s%d+%d", num_entries ? "," : "", +- start_sector - part_start, num_sectors); ++ if (*num_sectors > 0) ++ grub_printf ("%s%d+%d", *num_entries ? "," : "", ++ *start_sector - part_start, *num_sectors); + + grub_printf ("\n"); + +@@ -1868,6 +1905,77 @@ + + + /* install */ ++static struct { ++ int saved_sector; ++ int installaddr; ++ int installlist; ++ char *stage2_first_buffer; ++} install_func_context = { ++ .saved_sector = 0, ++ .installaddr = 0, ++ .installlist = 0, ++ .stage2_first_buffer = NULL, ++}; ++ ++/* Save the first sector of Stage2 in STAGE2_SECT. */ ++/* Formerly disk_read_savesect_func with local scope inside install_func */ ++static void ++install_savesect_helper(int sector, int offset, int length) ++{ ++ if (debug) ++ printf ("[%d]", sector); ++ ++ /* ReiserFS has files which sometimes contain data not aligned ++ on sector boundaries. Returning an error is better than ++ silently failing. */ ++ if (offset != 0 || length != SECTOR_SIZE) ++ errnum = ERR_UNALIGNED; ++ ++ install_func_context.saved_sector = sector; ++} ++ ++/* Write SECTOR to INSTALLLIST, and update INSTALLADDR and INSTALLSECT. */ ++/* Formerly disk_read_blocklist_func with local scope inside install_func */ ++static void ++install_blocklist_helper (int sector, int offset, int length) ++{ ++ int *installaddr = &install_func_context.installaddr; ++ int *installlist = &install_func_context.installlist; ++ char **stage2_first_buffer = &install_func_context.stage2_first_buffer; ++ /* Was the last sector full? */ ++ static int last_length = SECTOR_SIZE; ++ ++ if (debug) ++ printf("[%d]", sector); ++ ++ if (offset != 0 || last_length != SECTOR_SIZE) ++ { ++ /* We found a non-sector-aligned data block. */ ++ errnum = ERR_UNALIGNED; ++ return; ++ } ++ ++ last_length = length; ++ ++ if (*((unsigned long *) (*installlist - 4)) ++ + *((unsigned short *) *installlist) != sector ++ || *installlist == (int) *stage2_first_buffer + SECTOR_SIZE + 4) ++ { ++ *installlist -= 8; ++ ++ if (*((unsigned long *) (*installlist - 8))) ++ errnum = ERR_WONT_FIT; ++ else ++ { ++ *((unsigned short *) (*installlist + 2)) = (*installaddr >> 4); ++ *((unsigned long *) (*installlist - 4)) = sector; ++ } ++ } ++ ++ *((unsigned short *) *installlist) += 1; ++ *installaddr += 512; ++} ++ + static int + install_func (char *arg, int flags) + { +@@ -1875,8 +1983,12 @@ + char *stage1_buffer = (char *) RAW_ADDR (0x100000); + char *stage2_buffer = stage1_buffer + SECTOR_SIZE; + char *old_sect = stage2_buffer + SECTOR_SIZE; +- char *stage2_first_buffer = old_sect + SECTOR_SIZE; +- char *stage2_second_buffer = stage2_first_buffer + SECTOR_SIZE; ++ /* stage2_first_buffer used to be defined as: ++ * char *stage2_first_buffer = old_sect + SECTOR_SIZE; */ ++ char **stage2_first_buffer = &install_func_context.stage2_first_buffer; ++ /* and stage2_second_buffer was: ++ * char *stage2_second_buffer = stage2_first_buffer + SECTOR_SIZE; */ ++ char *stage2_second_buffer = old_sect + SECTOR_SIZE + SECTOR_SIZE; + /* XXX: Probably SECTOR_SIZE is reasonable. */ + char *config_filename = stage2_second_buffer + SECTOR_SIZE; + char *dummy = config_filename + SECTOR_SIZE; +@@ -1885,10 +1997,11 @@ + int src_drive, src_partition, src_part_start; + int i; + struct geometry dest_geom, src_geom; +- int saved_sector; ++ int *saved_sector = &install_func_context.saved_sector; + int stage2_first_sector, stage2_second_sector; + char *ptr; +- int installaddr, installlist; ++ int *installaddr = &install_func_context.installaddr; ++ int *installlist = &install_func_context.installlist; + /* Point to the location of the name of a configuration file in Stage 2. */ + char *config_file_location; + /* If FILE is a Stage 1.5? */ +@@ -1897,67 +2010,13 @@ + int is_open = 0; + /* If LBA is forced? */ + int is_force_lba = 0; +- /* Was the last sector full? */ +- int last_length = SECTOR_SIZE; +- ++ ++ *stage2_first_buffer = old_sect + SECTOR_SIZE; + #ifdef GRUB_UTIL + /* If the Stage 2 is in a partition mounted by an OS, this will store + the filename under the OS. */ + char *stage2_os_file = 0; + #endif /* GRUB_UTIL */ +- +- auto void disk_read_savesect_func (int sector, int offset, int length); +- auto void disk_read_blocklist_func (int sector, int offset, int length); +- +- /* Save the first sector of Stage2 in STAGE2_SECT. */ +- auto void disk_read_savesect_func (int sector, int offset, int length) +- { +- if (debug) +- printf ("[%d]", sector); +- +- /* ReiserFS has files which sometimes contain data not aligned +- on sector boundaries. Returning an error is better than +- silently failing. */ +- if (offset != 0 || length != SECTOR_SIZE) +- errnum = ERR_UNALIGNED; +- +- saved_sector = sector; +- } +- +- /* Write SECTOR to INSTALLLIST, and update INSTALLADDR and +- INSTALLSECT. */ +- auto void disk_read_blocklist_func (int sector, int offset, int length) +- { +- if (debug) +- printf("[%d]", sector); +- +- if (offset != 0 || last_length != SECTOR_SIZE) +- { +- /* We found a non-sector-aligned data block. */ +- errnum = ERR_UNALIGNED; +- return; +- } +- +- last_length = length; +- +- if (*((unsigned long *) (installlist - 4)) +- + *((unsigned short *) installlist) != sector +- || installlist == (int) stage2_first_buffer + SECTOR_SIZE + 4) +- { +- installlist -= 8; +- +- if (*((unsigned long *) (installlist - 8))) +- errnum = ERR_WONT_FIT; +- else +- { +- *((unsigned short *) (installlist + 2)) = (installaddr >> 4); +- *((unsigned long *) (installlist - 4)) = sector; +- } +- } +- +- *((unsigned short *) installlist) += 1; +- installaddr += 512; +- } + + /* First, check the GNU-style long option. */ + while (1) +@@ -1987,10 +2049,10 @@ + addr = skip_to (0, file); + + /* Get the installation address. */ +- if (! safe_parse_maxint (&addr, &installaddr)) ++ if (! safe_parse_maxint (&addr, installaddr)) + { + /* ADDR is not specified. */ +- installaddr = 0; ++ *installaddr = 0; + ptr = addr; + errnum = 0; + } +@@ -2084,17 +2146,17 @@ + = (dest_drive & BIOS_FLAG_FIXED_DISK); + + /* Read the first sector of Stage 2. */ +- disk_read_hook = disk_read_savesect_func; +- if (grub_read (stage2_first_buffer, SECTOR_SIZE) != SECTOR_SIZE) ++ disk_read_hook = install_savesect_helper; ++ if (grub_read (*stage2_first_buffer, SECTOR_SIZE) != SECTOR_SIZE) + goto fail; + +- stage2_first_sector = saved_sector; ++ stage2_first_sector = *saved_sector; + + /* Read the second sector of Stage 2. */ + if (grub_read (stage2_second_buffer, SECTOR_SIZE) != SECTOR_SIZE) + goto fail; + +- stage2_second_sector = saved_sector; ++ stage2_second_sector = *saved_sector; + + /* Check for the version of Stage 2. */ + if (*((short *) (stage2_second_buffer + STAGE2_VER_MAJ_OFFS)) +@@ -2110,27 +2172,27 @@ + + /* If INSTALLADDR is not specified explicitly in the command-line, + determine it by the Stage 2 id. */ +- if (! installaddr) ++ if (! *installaddr) + { + if (! is_stage1_5) + /* Stage 2. */ +- installaddr = 0x8000; ++ *installaddr = 0x8000; + else + /* Stage 1.5. */ +- installaddr = 0x2000; ++ *installaddr = 0x2000; + } + + *((unsigned long *) (stage1_buffer + STAGE1_STAGE2_SECTOR)) + = stage2_first_sector; + *((unsigned short *) (stage1_buffer + STAGE1_STAGE2_ADDRESS)) +- = installaddr; ++ = *installaddr; + *((unsigned short *) (stage1_buffer + STAGE1_STAGE2_SEGMENT)) +- = installaddr >> 4; ++ = *installaddr >> 4; + +- i = (int) stage2_first_buffer + SECTOR_SIZE - 4; ++ i = (int) *stage2_first_buffer + SECTOR_SIZE - 4; + while (*((unsigned long *) i)) + { +- if (i < (int) stage2_first_buffer ++ if (i < (int) *stage2_first_buffer + || (*((int *) (i - 4)) & 0x80000000) + || *((unsigned short *) i) >= 0xA00 + || *((short *) (i + 2)) == 0) +@@ -2144,13 +2206,13 @@ + i -= 8; + } + +- installlist = (int) stage2_first_buffer + SECTOR_SIZE + 4; +- installaddr += SECTOR_SIZE; ++ *installlist = (int) *stage2_first_buffer + SECTOR_SIZE + 4; ++ *installaddr += SECTOR_SIZE; + + /* Read the whole of Stage2 except for the first sector. */ + grub_seek (SECTOR_SIZE); + +- disk_read_hook = disk_read_blocklist_func; ++ disk_read_hook = install_blocklist_helper; + if (! grub_read (dummy, -1)) + goto fail; + +@@ -2233,7 +2295,7 @@ + /* Skip the first sector. */ + grub_seek (SECTOR_SIZE); + +- disk_read_hook = disk_read_savesect_func; ++ disk_read_hook = install_savesect_helper; + if (grub_read (stage2_buffer, SECTOR_SIZE) != SECTOR_SIZE) + goto fail; + +@@ -2303,7 +2365,7 @@ + else + #endif /* GRUB_UTIL */ + { +- if (! devwrite (saved_sector - part_start, 1, stage2_buffer)) ++ if (! devwrite (*saved_sector - part_start, 1, stage2_buffer)) + goto fail; + } + } +@@ -2325,7 +2387,7 @@ + goto fail; + } + +- if (fwrite (stage2_first_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE) ++ if (fwrite (*stage2_first_buffer, 1, SECTOR_SIZE, fp) != SECTOR_SIZE) + { + fclose (fp); + errnum = ERR_WRITE; +@@ -2352,7 +2414,7 @@ + goto fail; + + if (! devwrite (stage2_first_sector - src_part_start, 1, +- stage2_first_buffer)) ++ *stage2_first_buffer)) + goto fail; + + if (! devwrite (stage2_second_sector - src_part_start, 1, +--- grub-0.97/stage2/shared.h ++++ grub-0.97/stage2/shared.h +@@ -36,8 +36,8 @@ + + /* Maybe redirect memory requests through grub_scratch_mem. */ + #ifdef GRUB_UTIL +-extern char *grub_scratch_mem; +-# define RAW_ADDR(x) ((x) + (int) grub_scratch_mem) ++extern void *grub_scratch_mem; ++# define RAW_ADDR(x) ((x) + (unsigned long) grub_scratch_mem) + # define RAW_SEG(x) (RAW_ADDR ((x) << 4) >> 4) + #else + # define RAW_ADDR(x) (x) diff --git a/src/patches/grub-0.97/grub-0.97-configfile.patch b/src/patches/grub-0.97/grub-0.97-configfile.patch new file mode 100644 index 0000000000..4a0c32e501 --- /dev/null +++ b/src/patches/grub-0.97/grub-0.97-configfile.patch @@ -0,0 +1,80 @@ +diff -ru grub-0.97-old/docs/grub.8 grub-0.97/docs/grub.8 +--- grub-0.97-old/docs/grub.8 2005-05-08 02:48:56.000000000 +0000 ++++ grub-0.97/docs/grub.8 2006-08-05 13:17:07.868362408 +0000 +@@ -15,7 +15,7 @@ + specify stage2 boot_drive [default=0x0] + .TP + \fB\-\-config\-file\fR=\fIFILE\fR +-specify stage2 config_file [default=/boot/grub/menu.lst] ++specify stage2 config_file [default=/boot/grub/grub.conf] + .TP + \fB\-\-device\-map\fR=\fIFILE\fR + use the device map file FILE +diff -ru grub-0.97-old/docs/grub.texi grub-0.97/docs/grub.texi +--- grub-0.97-old/docs/grub.texi 2005-05-08 02:59:59.000000000 +0000 ++++ grub-0.97/docs/grub.texi 2006-08-05 13:17:07.875361344 +0000 +@@ -1265,7 +1265,7 @@ + keys) that will do everything to boot an OS. + + To enable the menu, you need a configuration file, +-@file{menu.lst} under the boot directory. We'll analyze an example ++@file{grub.conf} under the boot directory. We'll analyze an example + file. + + The file first contains some general settings, the menu interface +@@ -1882,8 +1882,8 @@ + + An absolute file name resembles a Unix absolute file name, using + @samp{/} for the directory separator (not @samp{\} as in DOS). One +-example is @samp{(hd0,0)/boot/grub/menu.lst}. This means the file +-@file{/boot/grub/menu.lst} in the first partition of the first hard ++example is @samp{(hd0,0)/boot/grub/grub.conf}. This means the file ++@file{/boot/grub/grub.conf} in the first partition of the first hard + disk. If you omit the device name in an absolute file name, GRUB uses + GRUB's @dfn{root device} implicitly. So if you set the root device to, + say, @samp{(hd1,0)} by the command @command{root} (@pxref{root}), then +@@ -3542,7 +3542,7 @@ + + @item --config-file=@var{file} + Read the configuration file @var{file} instead of +-@file{/boot/grub/menu.lst}. The format is the same as the normal GRUB ++@file{/boot/grub/grub.conf}. The format is the same as the normal GRUB + syntax. See @ref{Filesystem}, for more information. + + @item --boot-drive=@var{drive} +diff -ru grub-0.97-old/grub/asmstub.c grub-0.97/grub/asmstub.c +--- grub-0.97-old/grub/asmstub.c 2005-02-16 20:45:14.000000000 +0000 ++++ grub-0.97/grub/asmstub.c 2006-08-05 13:17:07.866362712 +0000 +@@ -71,7 +71,7 @@ + unsigned long boot_drive = 0; + int saved_entryno = 0; + char version_string[] = VERSION; +-char config_file[128] = "/boot/grub/menu.lst"; /* FIXME: arbitrary */ ++char config_file[128] = "/boot/grub/grub.conf"; /* FIXME: arbitrary */ + unsigned long linux_text_len = 0; + char *linux_data_tmp_addr = 0; + char *linux_data_real_addr = 0; +diff -ru grub-0.97-old/stage2/asm.S grub-0.97/stage2/asm.S +--- grub-0.97-old/stage2/asm.S 2004-06-19 16:55:22.000000000 +0000 ++++ grub-0.97/stage2/asm.S 2006-08-05 13:17:07.859363776 +0000 +@@ -98,7 +98,7 @@ + .string VERSION + VARIABLE(config_file) + #ifndef STAGE1_5 +- .string "/boot/grub/menu.lst" ++ .string "/boot/grub/grub.conf" + #else /* STAGE1_5 */ + .long 0xffffffff + .string "/boot/grub/stage2" +diff -ru grub-0.97-old/stage2/builtins.c grub-0.97/stage2/builtins.c +--- grub-0.97-old/stage2/builtins.c 2005-02-15 21:58:23.000000000 +0000 ++++ grub-0.97/stage2/builtins.c 2006-08-05 13:17:07.864363016 +0000 +@@ -3973,7 +3973,7 @@ + + /* The prefix was determined. */ + grub_sprintf (stage2, "%s%s", prefix, "/stage2"); +- grub_sprintf (config_filename, "%s%s", prefix, "/menu.lst"); ++ grub_sprintf (config_filename, "%s%s", prefix, "/grub.conf"); + *real_config_filename = 0; + + /* Check if stage2 exists. */ diff --git a/src/patches/grub-0.97/grub-0.97-dirs.patch b/src/patches/grub-0.97/grub-0.97-dirs.patch new file mode 100644 index 0000000000..79b532e3ee --- /dev/null +++ b/src/patches/grub-0.97/grub-0.97-dirs.patch @@ -0,0 +1,78 @@ +diff -Nur grub-0.97-splash/docs/grub.texi grub-0.97-dirs/docs/grub.texi +--- grub-0.97-splash/docs/grub.texi 2005-08-21 20:29:22.000000000 +0300 ++++ grub-0.97-dirs/docs/grub.texi 2005-08-21 20:31:12.000000000 +0300 +@@ -479,13 +479,13 @@ + if, by any chance, your hard drive becomes unusable (unbootable). + + GRUB comes with boot images, which are normally put in the directory +-@file{/usr/lib/grub/i386-pc}. If you do not use grub-install, then ++@file{/usr/share/grub/i386-pc}. If you do not use grub-install, then + you need to copy the files @file{stage1}, @file{stage2}, and + @file{*stage1_5} to the directory @file{/boot/grub}, and run the + @command{grub-set-default} (@pxref{Invoking grub-set-default}) if you + intend to use @samp{default saved} (@pxref{default}) in your + configuration file. Hereafter, the directory where GRUB images are +-initially placed (normally @file{/usr/lib/grub/i386-pc}) will be ++initially placed (normally @file{/usr/share/grub/i386-pc}) will be + called the @dfn{image directory}, and the directory where the boot + loader needs to find them (usually @file{/boot/grub}) will be called + the @dfn{boot directory}. +@@ -513,7 +513,7 @@ + + @example + @group +-# @kbd{cd /usr/lib/grub/i386-pc} ++# @kbd{cd /usr/share/grub/i386-pc} + # @kbd{dd if=stage1 of=/dev/fd0 bs=512 count=1} + 1+0 records in + 1+0 records out +@@ -707,7 +707,7 @@ + Copy the file @file{stage2_eltorito}: + + @example +-$ @kbd{cp /usr/lib/grub/i386-pc/stage2_eltorito iso/boot/grub} ++$ @kbd{cp /usr/share/grub/i386-pc/stage2_eltorito iso/boot/grub} + @end example + + If desired, make the config file @file{menu.lst} under @file{iso/boot/grub} +diff -Nur grub-0.97-splash/Makefile.am grub-0.97-dirs/Makefile.am +--- grub-0.97-splash/Makefile.am 2005-08-21 20:29:14.000000000 +0300 ++++ grub-0.97-dirs/Makefile.am 2005-08-21 20:31:12.000000000 +0300 +@@ -2,3 +2,4 @@ + AUTOMAKE_OPTIONS = 1.7 gnu + SUBDIRS = netboot stage2 stage1 lib grub util docs + EXTRA_DIST = BUGS MAINTENANCE ++pkgdatadir=$(datadir) +diff -Nur grub-0.97-splash/stage1/Makefile.am grub-0.97-dirs/stage1/Makefile.am +--- grub-0.97-splash/stage1/Makefile.am 2005-08-21 20:29:14.000000000 +0300 ++++ grub-0.97-dirs/stage1/Makefile.am 2005-08-21 20:31:12.000000000 +0300 +@@ -1,4 +1,4 @@ +-pkglibdir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor) ++pkglibdir = /usr/share/grub/i386-pc + nodist_pkglib_DATA = stage1 + + CLEANFILES = $(nodist_pkglib_DATA) +diff -Nur grub-0.97-splash/stage2/Makefile.am grub-0.97-dirs/stage2/Makefile.am +--- grub-0.97-splash/stage2/Makefile.am 2005-08-21 20:29:14.000000000 +0300 ++++ grub-0.97-dirs/stage2/Makefile.am 2005-08-21 20:31:12.000000000 +0300 +@@ -27,7 +27,7 @@ + -DUSE_MD5_PASSWORDS=1 -DSUPPORT_SERIAL=1 -DSUPPORT_HERCULES=1 + + # Stage 2 and Stage 1.5's. +-pkglibdir = $(libdir)/$(PACKAGE)/$(host_cpu)-$(host_vendor) ++pkglibdir = /usr/share/grub/i386-pc + + EXTRA_PROGRAMS = nbloader.exec pxeloader.exec diskless.exec + +diff -Nur grub-0.97-splash/util/grub-install.in grub-0.97-dirs/util/grub-install.in +--- grub-0.97-splash/util/grub-install.in 2005-08-21 20:29:14.000000000 +0300 ++++ grub-0.97-dirs/util/grub-install.in 2005-08-21 20:31:12.000000000 +0300 +@@ -27,7 +27,7 @@ + host_cpu=@host_cpu@ + host_os=@host_os@ + host_vendor=@host_vendor@ +-pkglibdir=${libdir}/${PACKAGE}/${host_cpu}-${host_vendor} ++pkglibdir=/usr/share/grub/i386-pc + + grub_shell=${sbindir}/grub + grub_set_default=${sbindir}/grub-set-default diff --git a/src/patches/grub-0.97/grub-0.97-misc.patch b/src/patches/grub-0.97/grub-0.97-misc.patch new file mode 100644 index 0000000000..9fa07af3e7 --- /dev/null +++ b/src/patches/grub-0.97/grub-0.97-misc.patch @@ -0,0 +1,94 @@ +diff -Nur grub-0.97-ori/lib/device.c grub-0.97-misc/lib/device.c +--- grub-0.97-ori/lib/device.c 2005-03-28 02:14:25.000000000 +0300 ++++ grub-0.97-misc/lib/device.c 2005-08-21 20:22:30.000000000 +0300 +@@ -831,9 +831,11 @@ + is_disk_device (char **map, int drive) + { + struct stat st; ++ int retval; + + assert (map[drive] != 0); +- assert (stat (map[drive], &st) == 0); ++ retval = stat (map[drive], &st); ++ assert (retval == 0); + /* For now, disk devices under Linux are all block devices. */ + return S_ISBLK (st.st_mode); + } +diff -Nur grub-0.97-ori/stage2/boot.c grub-0.97-misc/stage2/boot.c +--- grub-0.97-ori/stage2/boot.c 2004-03-30 14:44:08.000000000 +0300 ++++ grub-0.97-misc/stage2/boot.c 2005-08-21 20:22:30.000000000 +0300 +@@ -824,8 +824,11 @@ + moveto = (mbi.mem_upper + 0x400) << 10; + + moveto = (moveto - len) & 0xfffff000; +- max_addr = (lh->header == LINUX_MAGIC_SIGNATURE && lh->version >= 0x0203 +- ? lh->initrd_addr_max : LINUX_INITRD_MAX_ADDRESS); ++ max_addr = LINUX_INITRD_MAX_ADDRESS; ++ if (lh->header == LINUX_MAGIC_SIGNATURE && ++ lh->version >= 0x0203 && ++ lh->initrd_addr_max < max_addr) ++ max_addr = lh->initrd_addr_max; + if (moveto + len >= max_addr) + moveto = (max_addr - len) & 0xfffff000; + +diff -Nur grub-0.97-ori/stage2/builtins.c grub-0.97-misc/stage2/builtins.c +--- grub-0.97-ori/stage2/builtins.c 2005-02-15 23:58:23.000000000 +0200 ++++ grub-0.97-misc/stage2/builtins.c 2005-08-21 20:22:30.000000000 +0300 +@@ -1842,9 +1842,23 @@ + #ifdef GRUB_UTIL + else if (grub_memcmp ("--stage2=", arg, sizeof ("--stage2=") - 1) == 0) + { ++ int fd; + stage2_os_file = arg + sizeof ("--stage2=") - 1; + arg = skip_to (0, arg); + nul_terminate (stage2_os_file); ++ ++#if defined(__linux__) && defined (FSYS_REISERFS) ++ if ((fd=open(stage2_os_file, O_RDONLY)) >= 0) ++ { ++ struct statfs buf; ++ /* see if the file sits on a reiserfs, ++ and try do defragment it if so. */ ++ fstatfs(fd, &buf); ++ if (buf.f_type == REISERFS_SUPER_MAGIC) ++ ioctl (fd, REISERFS_IOC_UNPACK, 1); ++ } ++#endif /* __linux__ && FSYS_REISERFS */ ++ + } + #endif /* GRUB_UTIL */ + else +diff -Nur grub-0.97-ori/stage2/filesys.h grub-0.97-misc/stage2/filesys.h +--- grub-0.97-ori/stage2/filesys.h 2004-05-14 22:36:43.000000000 +0300 ++++ grub-0.97-misc/stage2/filesys.h 2005-08-21 20:22:30.000000000 +0300 +@@ -73,6 +73,16 @@ + int reiserfs_read (char *buf, int len); + int reiserfs_dir (char *dirname); + int reiserfs_embed (int *start_sector, int needed_sectors); ++#if defined(__linux__) && defined (GRUB_UTIL) ++#include ++#include ++#include ++#include ++#include ++/* from */ ++#define REISERFS_SUPER_MAGIC 0x52654973 ++#define REISERFS_IOC_UNPACK _IOW(0xCD,1,long) ++#endif + #else + #define FSYS_REISERFS_NUM 0 + #endif +diff -Nur grub-0.97-ori/util/mbchk.c grub-0.97-misc/util/mbchk.c +--- grub-0.97-ori/util/mbchk.c 2003-10-19 18:36:45.000000000 +0300 ++++ grub-0.97-misc/util/mbchk.c 2005-08-21 20:22:30.000000000 +0300 +@@ -59,7 +59,9 @@ + int i; + char buf[8192]; + +- if (fread (buf, 1, 8192, fp) < 0) ++ fread (buf, 1, 8192, fp); ++ ++ if (ferror(fp)) + { + fprintf (stderr, "%s: Read error.\n", filename); + return 0; diff --git a/src/patches/grub-0.97/grub-0.97-splash.patch b/src/patches/grub-0.97/grub-0.97-splash.patch new file mode 100644 index 0000000000..e7066e097d --- /dev/null +++ b/src/patches/grub-0.97/grub-0.97-splash.patch @@ -0,0 +1,943 @@ +diff -Nur grub-0.97-misc/docs/grub.texi grub-0.97-splash/docs/grub.texi +--- grub-0.97-misc/docs/grub.texi 2005-08-21 20:22:18.000000000 +0300 ++++ grub-0.97-splash/docs/grub.texi 2005-08-21 20:29:22.000000000 +0300 +@@ -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 + +diff -Nur grub-0.97-misc/grub/asmstub.c grub-0.97-splash/grub/asmstub.c +--- grub-0.97-misc/grub/asmstub.c 2005-08-21 20:22:18.000000000 +0300 ++++ grub-0.97-splash/grub/asmstub.c 2005-08-21 20:29:22.000000000 +0300 +@@ -480,6 +480,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) +diff -Nur grub-0.97-misc/stage2/asm.S grub-0.97-splash/stage2/asm.S +--- grub-0.97-misc/stage2/asm.S 2005-08-21 20:22:18.000000000 +0300 ++++ grub-0.97-splash/stage2/asm.S 2005-08-21 20:29:22.000000000 +0300 +@@ -1610,6 +1610,301 @@ + 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 ++ andl $0xf,%edi ++ shrl $4,%edx ++ ++ pushl %ebp ++ ++ call EXT_C(prot_to_real) ++ .code16 ++ ++ pushw %ds ++ ++ movw %dx,%ds ++ leal gfx_ofs_sys_cfg(%di),%esi ++ movl gfx_ofs_mem_file(%di),%eax ++ movl gfx_ofs_mem_cur(%di),%ebx ++ movl gfx_ofs_mem_max(%di),%ecx ++ movw %ds,%dx ++ ++ /* basically just a lcall, but we need %edi */ ++ pushw %cs ++ pushw $gfx_init_50 ++ pushl gfx_ofs_jmp_table + 4 * 0 (%di) ++ ++ movl gfx_ofs_mem_align(%di),%edi ++ ++ lret ++ ++gfx_init_50: ++ movl $0,%ebx ++ adcl $0,%ebx ++ ++ popw %ds ++ ++ DATA32 call EXT_C(real_to_prot) ++ .code32 ++ ++ popl %ebp ++ ++ movl %ebx,%eax ++ negl %ebx ++ incl %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 ++ andl $0xf,%ebx ++ shrl $4,%edx ++ ++ pushl %ebp ++ ++ call EXT_C(prot_to_real) ++ .code16 ++ ++ pushw %ds ++ ++ movw %dx,%ds ++ shll $4,%edx ++ movl gfx_ofs_cmdline(%bx),%edi ++ subl %edx,%edi ++ movw gfx_ofs_cmdline_len(%bx),%cx ++ movw gfx_ofs_timeout(%bx),%ax ++ imulw $18,%ax ++ ++ pushl %ebp ++ lcall *gfx_ofs_jmp_table + 4 * 2 (%bx) ++ popl %ebp ++ 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 %sp,%bp ++ ++ 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) ++ ++ movw %bp,%si ++ pushw %ss ++ popw %es ++ ++ 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) +diff -Nur grub-0.97-misc/stage2/builtins.c grub-0.97-splash/stage2/builtins.c +--- grub-0.97-misc/stage2/builtins.c 2005-08-21 20:22:30.000000000 +0300 ++++ grub-0.97-splash/stage2/builtins.c 2005-08-21 20:29:22.000000000 +0300 +@@ -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. */ +@@ -1331,6 +1333,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) +@@ -4837,6 +4859,7 @@ + &builtin_find, + &builtin_fstest, + &builtin_geometry, ++ &builtin_gfxmenu, + &builtin_halt, + &builtin_help, + &builtin_hiddenmenu, +diff -Nur grub-0.97-misc/stage2/shared.h grub-0.97-splash/stage2/shared.h +--- grub-0.97-misc/stage2/shared.h 2005-08-21 20:22:18.000000000 +0300 ++++ grub-0.97-splash/stage2/shared.h 2005-08-21 20:29:22.000000000 +0300 +@@ -374,6 +374,27 @@ + #endif /* WITHOUT_LIBC_STUBS */ + + ++/* see typedef gfx_data_t below */ ++#define gfx_ofs_ok 0x00 ++#define gfx_ofs_mem_start 0x04 ++#define gfx_ofs_mem_cur 0x08 ++#define gfx_ofs_mem_max 0x0c ++#define gfx_ofs_code_seg 0x10 ++#define gfx_ofs_jmp_table 0x14 ++#define gfx_ofs_sys_cfg 0x44 ++#define gfx_ofs_cmdline 0x64 ++#define gfx_ofs_cmdline_len 0x68 ++#define gfx_ofs_menu_list 0x6c ++#define gfx_ofs_menu_default_entry 0x70 ++#define gfx_ofs_menu_entries 0x74 ++#define gfx_ofs_menu_entry_len 0x78 ++#define gfx_ofs_args_list 0x7c ++#define gfx_ofs_args_entry_len 0x80 ++#define gfx_ofs_timeout 0x84 ++#define gfx_ofs_mem_file 0x88 ++#define gfx_ofs_mem_align 0x8c ++ ++ + #ifndef ASM_FILE + /* + * Below this should be ONLY defines and other constructs for C code. +@@ -595,6 +616,41 @@ + 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 mem_start, mem_cur, mem_max; ++ unsigned code_seg; /* code segment of binary graphics code */ ++ unsigned jmp_table[12]; /* link to graphics functions */ ++ unsigned char sys_cfg[32]; /* 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) */ ++ unsigned mem_file; /* aligned gfx file start */ ++ unsigned mem_align; /* aligned cpio file start */ ++} __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 + { +diff -Nur grub-0.97-misc/stage2/stage2.c grub-0.97-splash/stage2/stage2.c +--- grub-0.97-misc/stage2/stage2.c 2005-08-21 20:22:18.000000000 +0300 ++++ grub-0.97-splash/stage2/stage2.c 2005-08-21 20:29:22.000000000 +0300 +@@ -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,413 @@ + } + + ++ ++#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 ++ ++/* ++ * Go through config entry and find kernel args, if any. ++ */ ++static char *get_kernel_args(char *cfg) ++{ ++ int j; ++ char *s, *t = ""; ++ ++ for(j = 0; ; j++) { ++ s = get_entry(cfg, j, 0); ++ if(!*s) break; ++ if(!memcmp(s, "kernel", 6) && (s[6] == ' ' || s[6] == '\t')) { ++ t = skip_to(0, s); ++ if(*t) t = skip_to(0, t); ++ break; ++ } ++ } ++ ++ return t; ++} ++ ++ ++/* ++ * Check header and return code start offset. ++ */ ++static unsigned magic_ok(unsigned char *buf) ++{ ++ if( ++ *(unsigned *) buf == 0x0b2d97f00 && /* magic id */ ++ (buf[4] == 5 || buf[4] == 6) /* version 5 or 6 */ ++ ) { ++ 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 i, fname_len, flen, 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); ++ flen = *(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 += flen; ++ i = ((i + 1) & ~1); ++ } ++ else { ++ break; ++ } ++ } ++ ++ return code_start; ++} ++ ++ ++/* ++ * Leave that much space on the heap. Everything else goes to the graphics ++ * functions. ++ * ++ * 0x2000 is _not_ enough ++ */ ++#define MIN_HEAP_SIZE 0x4000 ++ ++/* gfx code needs at least this much free memory */ ++#define MIN_GFX_FREE 0xc000 ++ ++/* ++ * 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; ++ unsigned u, buf_size, code_start, file_start; ++ char *s, *t, *cfg, *new_config; ++ char *saved_heap; ++ int i, j, max_len; ++ int selected_entry; ++ gfx_data_t *gfx_data; ++ ++ /* ++ * 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(mem_start); ++ gfx_ofs_check(mem_cur); ++ gfx_ofs_check(mem_max); ++ 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); ++ gfx_ofs_check(mem_file); ++ gfx_ofs_check(mem_align); ++ #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[0] = 2; /* bootloader: grub */ ++ 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); ++ ++ ++ /* 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)); ++ 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))); ++ } ++ ++ ++ /* go back here when we no longer need the graphics data */ ++ saved_heap = heap; ++ ++ ++ /* get memory area to be used by graphics functions */ ++ ++ buf = (unsigned char *) (((unsigned) heap + 0xf) & ~0xf); ++ ++ buf_size = (unsigned char *) &buf - buf - MIN_HEAP_SIZE; ++ buf_size &= ~0xf; ++ ++ /* too small */ ++ if(buf_size < 0x10000) return; ++ ++ gfx_data->mem_start = (unsigned) buf; ++ gfx_data->mem_max = gfx_data->mem_start + buf_size; ++ ++#if 0 ++ printf("graphics menu\n"); ++ printf( ++ "heap = 0x%x, buf = 0x%x (0x%x bytes), graphics_file = %s\n", ++ heap, gfx_data->mem_start, buf_size, graphics_file ++ ); ++ getkey(); ++#endif ++ ++ heap += buf_size; ++ ++ ++ /* read the file */ ++ ++ if(!grub_open(graphics_file)) { ++ printf("graphics file \"%s\" missing, press a key to continue...\n", graphics_file); ++ getkey(); ++ return; ++ } ++ ++ i = grub_read(buf, buf_size); ++ ++ grub_close(); ++ ++ if(i <= 0) { ++ printf("error reading \"%s\", press a key to continue...\n", graphics_file); ++ getkey(); ++ return; ++ } ++ ++ /* besides the file, we need some working memory, too */ ++ if(i + MIN_GFX_FREE + 0x0f >= (int) buf_size) { ++ printf("file \"%s\" too large, press a key to continue...\n", graphics_file); ++ getkey(); ++ return; ++ } ++ ++ gfx_data->mem_cur = gfx_data->mem_start + ((i + 0x0f + 3) & ~3); /* align it */ ++ ++#if 0 ++ printf("image: %d bytes (%d bytes left)\n", i, gfx_data->mem_max - gfx_data->mem_cur); ++ getkey(); ++#endif ++ ++ ++ /* locate file inside cpio archive */ ++ if(!(code_start = find_file(buf, i, &file_start))) { ++ printf("\"%s\" has wrong format, press a key to continue...\n", graphics_file); ++ getkey(); ++ return; ++ } ++ ++ ++ /* align it */ ++ u = (-(code_start + gfx_data->mem_start + file_start)) & 0x0f; ++ gfx_data->mem_align = gfx_data->mem_start + u; ++ gfx_data->mem_file = gfx_data->mem_align + file_start; ++ if(u) { ++ memcpy((void *) gfx_data->mem_align, (void *) gfx_data->mem_start, i); ++ } ++ ++ /* init interface to graphics functions */ ++ ++ code_start += gfx_data->mem_file; ++ ++#if 0 ++ printf("code_start: 0x%x, file_start: 0x%x, mem_align = 0x%x, mem_file = 0x%x\n", ++ code_start, file_start, gfx_data->mem_align, gfx_data->mem_file ++ ); ++ getkey(); ++#endif ++ ++ gfx_data->code_seg = code_start >> 4; ++ ++#if 0 ++ printf("code start = 0x%x, code_seg = 0x%x\n", code_start, gfx_data->code_seg); ++#endif ++ ++ 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 *) code_start)[i]; ++ } ++ ++#if 0 ++ 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("def: >%s<\n", gfx_data->menu_default_entry); ++#endif ++ ++ ++ /* switch to graphics mode */ ++ ++ if(gfx_init(gfx_data)) { ++#if 0 ++ printf("gfx_init failed\n"); ++ getkey(); ++#endif ++ 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; ++ ++ 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(i = 0; ; i++) { ++ s = get_entry(cfg, i, 0); ++ if(!*s) { ++ if(!i) *heap++ = 0; ++ *heap++ = 0; ++ break; ++ } ++ if(!memcmp(s, "kernel", 6) && (s[6] == ' ' || s[6] == '\t')) { ++ t = skip_to(0, s); ++ if(*t) t = skip_to(0, t); ++ memmove(heap, s, t - s); ++ heap += t - s; ++ *heap++ = ' '; ++ strcpy(heap, gfx_data->cmdline); ++ heap += strlen(gfx_data->cmdline) + 1; ++ } ++ 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) + { +@@ -1059,9 +1474,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); + } + } + } diff --git a/src/patches/grub-0.97/grub-0.97-symlinkmenulst.patch b/src/patches/grub-0.97/grub-0.97-symlinkmenulst.patch new file mode 100644 index 0000000000..39b3f02b22 --- /dev/null +++ b/src/patches/grub-0.97/grub-0.97-symlinkmenulst.patch @@ -0,0 +1,14 @@ +diff -ur grub-0.97/util/grub-install.in grub-0.97-old/util/grub-install.in +--- grub-0.97/util/grub-install.in 2006-08-05 16:46:33.505226176 +0200 ++++ grub-0.97-old/util/grub-install.in 2004-07-24 20:57:31.000000000 +0200 +@@ -447,6 +447,10 @@ + rm -f $img_file + rm -f $log_file + ++if ! test -e ${grubdir}/grub.conf ; then ++ test -e ${grubdir}/menu.lst && ln -s ./menu.lst ${grubdir}/grub.conf ++fi ++ + # Create a safe temporary file. + test -n "$mklog" && log_file=`$mklog` + diff --git a/src/patches/grub-0.97/grub-0.97-wildcards.patch b/src/patches/grub-0.97/grub-0.97-wildcards.patch new file mode 100644 index 0000000000..a0789021aa --- /dev/null +++ b/src/patches/grub-0.97/grub-0.97-wildcards.patch @@ -0,0 +1,1188 @@ +diff -Nur grub-0.97-dirs/docs/grub.texi grub-0.97-wildcards/docs/grub.texi +--- grub-0.97-dirs/docs/grub.texi 2005-08-21 20:31:12.000000000 +0300 ++++ grub-0.97-wildcards/docs/grub.texi 2005-08-21 20:32:45.000000000 +0300 +@@ -2121,6 +2121,7 @@ + * gfxmenu:: Use graphical menu interface + * timeout:: Set the timeout + * title:: Start a menu entry ++* wildcard:: Define a wildcard boot entry + @end menu + + +@@ -2190,6 +2191,42 @@ + @end deffn + + ++@node wildcard ++@subsection wildcard ++ ++@deffn Command wildcard pathname ++Treat this boot entry as a wildcard entry: The ++wildcard, title, kernel, and initrd commands (see @ref{Menu-specific ++commands} and @ref{Command-line and menu entry commands}) each have an ++asterisk (*) in their value. A filename match is performed on the ++@var{pathname} of the wildcard command. For each match, the entire boot ++entry is duplicated. The part of the filename whcih matches the asterisk ++in the wildcard command replaces the asterisks in the title, kernel, and ++initrd commands. For example, with the files vmlinuz-2.6.5-1 and ++vmlinuz-2.6.8-8 below (hd0,7)/boot, the following entry in the stage 2 ++configuration file: ++ ++@example ++title Linux-* ++ wildcard (hd0,7)/boot/vmlinuz-* ++ kernel (hd0,7)/boot/vmlinuz-* root=/dev/hda8 ++ initrd (hd0,7)/boot/initrd-* ++@end example ++ ++would expand as follows: ++ ++@example ++title Linux-2.6.5-1 ++ wildcard (hd0,7)/boot/vmlinuz-2.6.5-1 ++ kernel (hd0,7)/boot/vmlinuz-2.6.5-1 root=/dev/hda8 ++ initrd (hd0,7)/boot/initrd-2.6.5-1 ++title Linux-2.6.8-8 ++ wildcard (hd0,7)/boot/vmlinuz-2.6.8-8 ++ kernel (hd0,7)/boot/vmlinuz-2.6.8-8 root=/dev/hda8 ++ initrd (hd0,7)/boot/initrd-2.6.8-8 ++@end example ++@end deffn ++ + @node General commands + @section The list of general commands + +diff -Nur grub-0.97-dirs/netboot/fsys_tftp.c grub-0.97-wildcards/netboot/fsys_tftp.c +--- grub-0.97-dirs/netboot/fsys_tftp.c 2005-08-21 20:31:02.000000000 +0300 ++++ grub-0.97-wildcards/netboot/fsys_tftp.c 2005-08-21 20:32:45.000000000 +0300 +@@ -409,7 +409,7 @@ + /* Check if the file DIRNAME really exists. Get the size and save it in + FILEMAX. */ + int +-tftp_dir (char *dirname) ++tftp_dir (char *dirname, void (*handle)(char *)) + { + int ch; + +@@ -418,7 +418,7 @@ + #endif + + /* In TFTP, there is no way to know what files exist. */ +- if (print_possibilities) ++ if (handle) + return 1; + + /* Don't know the size yet. */ +diff -Nur grub-0.97-dirs/stage2/builtins.c grub-0.97-wildcards/stage2/builtins.c +--- grub-0.97-dirs/stage2/builtins.c 2005-08-21 20:31:02.000000000 +0300 ++++ grub-0.97-wildcards/stage2/builtins.c 2005-08-21 20:32:45.000000000 +0300 +@@ -4828,6 +4828,49 @@ + }; + + ++/* wildcard */ ++ static int ++wildcard_func (char *arg, int flags) ++{ ++#ifdef DEBUG_WILDCARD ++ char *w = wildcard (arg); ++ ++ if (w) ++ { ++ while (*w) ++ { ++ grub_printf("%s ", w); ++ w += strlen (w) + 1; ++ } ++ grub_printf("\n"); ++ return 1; ++ } ++ else ++ print_error(); ++#endif ++ ++ /* This special command is interpreted in the config file parser. */ ++ return 0; ++} ++ ++static struct builtin builtin_wildcard = ++ { ++ "wildcard", ++ wildcard_func, ++#ifndef DEBUG_WILDCARD ++ BUILTIN_MENU, ++#else ++ BUILTIN_CMDLINE | BUILTIN_MENU | BUILTIN_HELP_LIST, ++ "wildcard GLOB", ++ "Declare this menu entry as a wildcard entry. GLOB is a path containing" ++ " one asterisk. All files matching this expression are looked up; the" ++ " menu entry is duplicated for each match with asterisks in other" ++ " commands replaced by the string matching the asterisk in the wildcard" ++ " command." ++#endif ++}; ++ ++ + /* The table of builtin commands. Sorted in dictionary order. */ + struct builtin *builtin_table[] = + { +@@ -4917,5 +4960,6 @@ + &builtin_unhide, + &builtin_uppermem, + &builtin_vbeprobe, ++ &builtin_wildcard, + 0 + }; +diff -Nur grub-0.97-dirs/stage2/disk_io.c grub-0.97-wildcards/stage2/disk_io.c +--- grub-0.97-dirs/stage2/disk_io.c 2005-08-21 20:31:02.000000000 +0300 ++++ grub-0.97-wildcards/stage2/disk_io.c 2005-08-21 20:32:45.000000000 +0300 +@@ -36,7 +36,6 @@ + void (*disk_read_func) (int, int, int) = NULL; + + #ifndef STAGE1_5 +-int print_possibilities; + + static int do_completion; + static int unique; +@@ -1479,7 +1478,7 @@ + if (! is_completion) + grub_printf (" Possible files are:"); + +- dir (buf); ++ dir (buf, print_a_completion); + + if (is_completion && *unique_string) + { +@@ -1498,7 +1497,7 @@ + *ptr = '/'; + *(ptr + 1) = 0; + +- dir (buf); ++ dir (buf, print_a_completion); + + /* Restore the original unique value. */ + unique = 1; +@@ -1626,12 +1625,7 @@ + if (!errnum && fsys_type == NUM_FSYS) + errnum = ERR_FSYS_MOUNT; + +-# ifndef STAGE1_5 +- /* set "dir" function to open a file */ +- print_possibilities = 0; +-# endif +- +- if (!errnum && (*(fsys_table[fsys_type].dir_func)) (filename)) ++ if (!errnum && (*(fsys_table[fsys_type].dir_func)) (filename, NULL)) + { + #ifndef NO_DECOMPRESSION + return gunzip_test_header (); +@@ -1752,7 +1746,7 @@ + } + + int +-dir (char *dirname) ++dir (char *dirname, void (*handle)(char *)) + { + #ifndef NO_DECOMPRESSION + compressed_file = 0; +@@ -1761,19 +1755,18 @@ + if (!(dirname = setup_part (dirname))) + return 0; + ++ errnum = 0; + if (*dirname != '/') + errnum = ERR_BAD_FILENAME; +- +- if (fsys_type == NUM_FSYS) ++ else if (fsys_type == NUM_FSYS) + errnum = ERR_FSYS_MOUNT; +- +- if (errnum) +- return 0; +- +- /* set "dir" function to list completions */ +- print_possibilities = 1; +- +- return (*(fsys_table[fsys_type].dir_func)) (dirname); ++ else ++ { ++ fsys_table[fsys_type].dir_func (dirname, handle); ++ if (errnum == ERR_FILE_NOT_FOUND) ++ errnum = 0; ++ } ++ return errnum == 0; + } + #endif /* STAGE1_5 */ + +diff -Nur grub-0.97-dirs/stage2/filesys.h grub-0.97-wildcards/stage2/filesys.h +--- grub-0.97-dirs/stage2/filesys.h 2005-08-21 20:31:02.000000000 +0300 ++++ grub-0.97-wildcards/stage2/filesys.h 2005-08-21 20:32:45.000000000 +0300 +@@ -24,7 +24,7 @@ + #define FSYS_FFS_NUM 1 + int ffs_mount (void); + int ffs_read (char *buf, int len); +-int ffs_dir (char *dirname); ++int ffs_dir (char *dirname, void (*handle)(char *)); + int ffs_embed (int *start_sector, int needed_sectors); + #else + #define FSYS_FFS_NUM 0 +@@ -34,7 +34,7 @@ + #define FSYS_UFS2_NUM 1 + int ufs2_mount (void); + int ufs2_read (char *buf, int len); +-int ufs2_dir (char *dirname); ++int ufs2_dir (char *dirname, void (*handle)(char *)); + int ufs2_embed (int *start_sector, int needed_sectors); + #else + #define FSYS_UFS2_NUM 0 +@@ -44,7 +44,7 @@ + #define FSYS_FAT_NUM 1 + int fat_mount (void); + int fat_read (char *buf, int len); +-int fat_dir (char *dirname); ++int fat_dir (char *dirname, void (*handle)(char *)); + #else + #define FSYS_FAT_NUM 0 + #endif +@@ -53,7 +53,7 @@ + #define FSYS_EXT2FS_NUM 1 + int ext2fs_mount (void); + int ext2fs_read (char *buf, int len); +-int ext2fs_dir (char *dirname); ++int ext2fs_dir (char *dirname, void (*handle)(char *)); + #else + #define FSYS_EXT2FS_NUM 0 + #endif +@@ -62,7 +62,7 @@ + #define FSYS_MINIX_NUM 1 + int minix_mount (void); + int minix_read (char *buf, int len); +-int minix_dir (char *dirname); ++int minix_dir (char *dirname, void (*handle)(char *)); + #else + #define FSYS_MINIX_NUM 0 + #endif +@@ -71,7 +71,7 @@ + #define FSYS_REISERFS_NUM 1 + int reiserfs_mount (void); + int reiserfs_read (char *buf, int len); +-int reiserfs_dir (char *dirname); ++int reiserfs_dir (char *dirname, void (*handle)(char *)); + int reiserfs_embed (int *start_sector, int needed_sectors); + #if defined(__linux__) && defined (GRUB_UTIL) + #include +@@ -91,7 +91,7 @@ + #define FSYS_VSTAFS_NUM 1 + int vstafs_mount (void); + int vstafs_read (char *buf, int len); +-int vstafs_dir (char *dirname); ++int vstafs_dir (char *dirname, void (*handle)(char *)); + #else + #define FSYS_VSTAFS_NUM 0 + #endif +@@ -100,7 +100,7 @@ + #define FSYS_JFS_NUM 1 + int jfs_mount (void); + int jfs_read (char *buf, int len); +-int jfs_dir (char *dirname); ++int jfs_dir (char *dirname, void (*handle)(char *)); + int jfs_embed (int *start_sector, int needed_sectors); + #else + #define FSYS_JFS_NUM 0 +@@ -110,7 +110,7 @@ + #define FSYS_XFS_NUM 1 + int xfs_mount (void); + int xfs_read (char *buf, int len); +-int xfs_dir (char *dirname); ++int xfs_dir (char *dirname, void (*handle)(char *)); + #else + #define FSYS_XFS_NUM 0 + #endif +@@ -119,7 +119,7 @@ + #define FSYS_TFTP_NUM 1 + int tftp_mount (void); + int tftp_read (char *buf, int len); +-int tftp_dir (char *dirname); ++int tftp_dir (char *dirname, void (*handle)(char *)); + void tftp_close (void); + #else + #define FSYS_TFTP_NUM 0 +@@ -129,7 +129,7 @@ + #define FSYS_ISO9660_NUM 1 + int iso9660_mount (void); + int iso9660_read (char *buf, int len); +-int iso9660_dir (char *dirname); ++int iso9660_dir (char *dirname, void (*handle)(char *)); + #else + #define FSYS_ISO9660_NUM 0 + #endif +@@ -160,16 +160,10 @@ + char *name; + int (*mount_func) (void); + int (*read_func) (char *buf, int len); +- int (*dir_func) (char *dirname); ++ int (*dir_func) (char *dirname, void (*print_one)(char *)); + void (*close_func) (void); + int (*embed_func) (int *start_sector, int needed_sectors); + }; + +-#ifdef STAGE1_5 +-# define print_possibilities 0 +-#else +-extern int print_possibilities; +-#endif +- + extern int fsmax; + extern struct fsys_entry fsys_table[NUM_FSYS + 1]; +diff -Nur grub-0.97-dirs/stage2/fsys_ext2fs.c grub-0.97-wildcards/stage2/fsys_ext2fs.c +--- grub-0.97-dirs/stage2/fsys_ext2fs.c 2005-08-21 20:31:02.000000000 +0300 ++++ grub-0.97-wildcards/stage2/fsys_ext2fs.c 2005-08-21 20:32:45.000000000 +0300 +@@ -495,7 +495,7 @@ + * side effects: messes up GROUP_DESC buffer area + */ + int +-ext2fs_dir (char *dirname) ++ext2fs_dir (char *dirname, void (*handle)(char *)) + { + int current_ino = EXT2_ROOT_INO; /* start at the root */ + int updir_ino = current_ino; /* the parent of the current directory */ +@@ -521,7 +521,6 @@ + #ifdef E2DEBUG + unsigned char *i; + #endif /* E2DEBUG */ +- + /* loop invariants: + current_ino = inode to lookup + dirname = pointer to filename component we are cur looking up within +@@ -713,18 +712,9 @@ + give up */ + if (loc >= INODE->i_size) + { +- if (print_possibilities < 0) +- { +-# if 0 +- putchar ('\n'); +-# endif +- } +- else +- { +- errnum = ERR_FILE_NOT_FOUND; +- *rest = ch; +- } +- return (print_possibilities < 0); ++ errnum = ERR_FILE_NOT_FOUND; ++ *rest = ch; ++ return 0; + } + + /* else, find the (logical) block component of our location */ +@@ -765,20 +755,15 @@ + str_chk = substring (dirname, dp->name); + + # ifndef STAGE1_5 +- if (print_possibilities && ch != '/' +- && (!*dirname || str_chk <= 0)) +- { +- if (print_possibilities > 0) +- print_possibilities = -print_possibilities; +- print_a_completion (dp->name); +- } ++ if (handle && ch != '/' && (!*dirname || str_chk <= 0)) ++ handle (dp->name); + # endif + + dp->name[dp->name_len] = saved_c; + } + + } +- while (!dp->inode || (str_chk || (print_possibilities && ch != '/'))); ++ while (!dp->inode || (str_chk || (handle && ch != '/'))); + + current_ino = dp->inode; + *(dirname = rest) = ch; +diff -Nur grub-0.97-dirs/stage2/fsys_fat.c grub-0.97-wildcards/stage2/fsys_fat.c +--- grub-0.97-dirs/stage2/fsys_fat.c 2005-08-21 20:31:02.000000000 +0300 ++++ grub-0.97-wildcards/stage2/fsys_fat.c 2005-08-21 20:32:45.000000000 +0300 +@@ -289,7 +289,7 @@ + } + + int +-fat_dir (char *dirname) ++fat_dir (char *dirname, void (*handle)(char *)) + { + char *rest, ch, dir_buf[FAT_DIRENTRY_LENGTH]; + char *filename = (char *) NAME_BUF; +@@ -345,7 +345,7 @@ + *rest = 0; + + # ifndef STAGE1_5 +- if (print_possibilities && ch != '/') ++ if (handle && ch != '/') + do_possibilities = 1; + # endif + +@@ -356,16 +356,6 @@ + { + if (!errnum) + { +-# ifndef STAGE1_5 +- if (print_possibilities < 0) +- { +-#if 0 +- putchar ('\n'); +-#endif +- return 1; +- } +-# endif /* STAGE1_5 */ +- + errnum = ERR_FILE_NOT_FOUND; + *rest = ch; + } +@@ -460,11 +450,7 @@ + { + print_filename: + if (substring (dirname, filename) <= 0) +- { +- if (print_possibilities > 0) +- print_possibilities = -print_possibilities; +- print_a_completion (filename); +- } ++ handle (filename); + continue; + } + # endif /* STAGE1_5 */ +diff -Nur grub-0.97-dirs/stage2/fsys_ffs.c grub-0.97-wildcards/stage2/fsys_ffs.c +--- grub-0.97-dirs/stage2/fsys_ffs.c 2005-08-21 20:31:02.000000000 +0300 ++++ grub-0.97-wildcards/stage2/fsys_ffs.c 2005-08-21 20:32:45.000000000 +0300 +@@ -180,7 +180,7 @@ + + + int +-ffs_dir (char *dirname) ++ffs_dir (char *dirname, void (*handle)(char *)) + { + char *rest, ch; + int block, off, loc, map, ino = ROOTINO; +@@ -236,13 +236,6 @@ + { + if (loc >= INODE->i_size) + { +-#if 0 +- putchar ('\n'); +-#endif +- +- if (print_possibilities < 0) +- return 1; +- + errnum = ERR_FILE_NOT_FOUND; + *rest = ch; + return 0; +@@ -267,18 +260,13 @@ + loc += dp->d_reclen; + + #ifndef STAGE1_5 +- if (dp->d_ino && print_possibilities && ch != '/' ++ if (dp->d_ino && handle && ch != '/' + && (!*dirname || substring (dirname, dp->d_name) <= 0)) +- { +- if (print_possibilities > 0) +- print_possibilities = -print_possibilities; +- +- print_a_completion (dp->d_name); +- } ++ handle (dp->d_name); + #endif /* STAGE1_5 */ + } + while (!dp->d_ino || (substring (dirname, dp->d_name) != 0 +- || (print_possibilities && ch != '/'))); ++ || (handle && ch != '/'))); + + /* only get here if we have a matching directory entry */ + +diff -Nur grub-0.97-dirs/stage2/fsys_iso9660.c grub-0.97-wildcards/stage2/fsys_iso9660.c +--- grub-0.97-dirs/stage2/fsys_iso9660.c 2005-08-21 20:31:02.000000000 +0300 ++++ grub-0.97-wildcards/stage2/fsys_iso9660.c 2005-08-21 20:32:45.000000000 +0300 +@@ -133,7 +133,7 @@ + } + + int +-iso9660_dir (char *dirname) ++iso9660_dir (char *dirname, void (*handle)(char *)) + { + struct iso_directory_record *idr; + RR_ptr_t rr_ptr; +@@ -346,7 +346,7 @@ + if (name_len >= pathlen + && !memcmp(name, dirname, pathlen)) + { +- if (dirname[pathlen] == '/' || !print_possibilities) ++ if (dirname[pathlen] == '/' || !handle) + { + /* + * DIRNAME is directory component of pathname, +@@ -377,11 +377,9 @@ + else /* Completion */ + { + #ifndef STAGE1_5 +- if (print_possibilities > 0) +- print_possibilities = -print_possibilities; + memcpy(NAME_BUF, name, name_len); + NAME_BUF[name_len] = '\0'; +- print_a_completion (NAME_BUF); ++ handle (NAME_BUF); + #endif + } + } +@@ -390,7 +388,7 @@ + size -= ISO_SECTOR_SIZE; + } /* size>0 */ + +- if (dirname[pathlen] == '/' || print_possibilities >= 0) ++ if (dirname[pathlen] == '/' || handle) + { + errnum = ERR_FILE_NOT_FOUND; + return 0; +diff -Nur grub-0.97-dirs/stage2/fsys_jfs.c grub-0.97-wildcards/stage2/fsys_jfs.c +--- grub-0.97-dirs/stage2/fsys_jfs.c 2005-08-21 20:31:02.000000000 +0300 ++++ grub-0.97-wildcards/stage2/fsys_jfs.c 2005-08-21 20:32:45.000000000 +0300 +@@ -270,7 +270,7 @@ + } + + int +-jfs_dir (char *dirname) ++jfs_dir (char *dirname, void (*handle)(char *)) + { + char *ptr, *rest, ch; + ldtentry_t *de; +@@ -357,12 +357,9 @@ + + cmp = (!*dirname) ? -1 : substring (dirname, namebuf); + #ifndef STAGE1_5 +- if (print_possibilities && ch != '/' +- && cmp <= 0) { +- if (print_possibilities > 0) +- print_possibilities = -print_possibilities; +- print_a_completion (namebuf); +- } else ++ if (handle && ch != '/' && cmp <= 0) ++ handle (namebuf); ++ else + #endif + if (cmp == 0) { + parent_inum = inum; +@@ -372,9 +369,6 @@ + } + de = next_dentry (); + if (de == NULL) { +- if (print_possibilities < 0) +- return 1; +- + errnum = ERR_FILE_NOT_FOUND; + *rest = ch; + return 0; +diff -Nur grub-0.97-dirs/stage2/fsys_minix.c grub-0.97-wildcards/stage2/fsys_minix.c +--- grub-0.97-dirs/stage2/fsys_minix.c 2005-08-21 20:31:02.000000000 +0300 ++++ grub-0.97-wildcards/stage2/fsys_minix.c 2005-08-21 20:32:45.000000000 +0300 +@@ -294,7 +294,7 @@ + inode of the file we were trying to look up + side effects: none yet */ + int +-minix_dir (char *dirname) ++minix_dir (char *dirname, void (*handle)(char *)) + { + int current_ino = MINIX_ROOT_INO; /* start at the root */ + int updir_ino = current_ino; /* the parent of the current directory */ +@@ -457,18 +457,9 @@ + give up */ + if (loc >= INODE->i_size) + { +- if (print_possibilities < 0) +- { +-#if 0 +- putchar ('\n'); +-#endif +- } +- else +- { +- errnum = ERR_FILE_NOT_FOUND; +- *rest = ch; +- } +- return (print_possibilities < 0); ++ errnum = ERR_FILE_NOT_FOUND; ++ *rest = ch; ++ return 0; + } + + /* else, find the (logical) block component of our location */ +@@ -510,20 +501,15 @@ + str_chk = substring (dirname, dp->name); + + # ifndef STAGE1_5 +- if (print_possibilities && ch != '/' +- && (!*dirname || str_chk <= 0)) +- { +- if (print_possibilities > 0) +- print_possibilities = -print_possibilities; +- print_a_completion (dp->name); +- } ++ if (handle && ch != '/' && (!*dirname || str_chk <= 0)) ++ handle (dp->name); + # endif + + dp->name[namelen] = saved_c; + } + + } +- while (!dp->inode || (str_chk || (print_possibilities && ch != '/'))); ++ while (!dp->inode || (str_chk || (handle && ch != '/'))); + + current_ino = dp->inode; + *(dirname = rest) = ch; +diff -Nur grub-0.97-dirs/stage2/fsys_reiserfs.c grub-0.97-wildcards/stage2/fsys_reiserfs.c +--- grub-0.97-dirs/stage2/fsys_reiserfs.c 2005-08-21 20:31:02.000000000 +0300 ++++ grub-0.97-wildcards/stage2/fsys_reiserfs.c 2005-08-21 20:32:45.000000000 +0300 +@@ -991,7 +991,7 @@ + * the size of the file. + */ + int +-reiserfs_dir (char *dirname) ++reiserfs_dir (char *dirname, void (*handle)(char *)) + { + struct reiserfs_de_head *de_head; + char *rest, ch; +@@ -1123,7 +1123,7 @@ + *rest = 0; + + # ifndef STAGE1_5 +- if (print_possibilities && ch != '/') ++ if (handle && ch != '/') + do_possibilities = 1; + # endif /* ! STAGE1_5 */ + +@@ -1170,10 +1170,8 @@ + { + if (cmp <= 0) + { +- if (print_possibilities > 0) +- print_possibilities = -print_possibilities; + *name_end = 0; +- print_a_completion (filename); ++ handle (filename); + *name_end = tmp; + } + } +@@ -1189,12 +1187,6 @@ + num_entries--; + } + } +- +-# ifndef STAGE1_5 +- if (print_possibilities < 0) +- return 1; +-# endif /* ! STAGE1_5 */ +- + errnum = ERR_FILE_NOT_FOUND; + *rest = ch; + return 0; +diff -Nur grub-0.97-dirs/stage2/fsys_ufs2.c grub-0.97-wildcards/stage2/fsys_ufs2.c +--- grub-0.97-dirs/stage2/fsys_ufs2.c 2005-08-21 20:31:02.000000000 +0300 ++++ grub-0.97-wildcards/stage2/fsys_ufs2.c 2005-08-21 20:32:45.000000000 +0300 +@@ -204,7 +204,7 @@ + } + + int +-ufs2_dir (char *dirname) ++ufs2_dir (char *dirname, void (*handle)(char *)) + { + char *rest, ch; + int block, off, loc, ino = ROOTINO; +@@ -261,9 +261,6 @@ + { + if (loc >= INODE_UFS2->di_size) + { +- if (print_possibilities < 0) +- return 1; +- + errnum = ERR_FILE_NOT_FOUND; + *rest = ch; + return 0; +@@ -288,18 +285,13 @@ + loc += dp->d_reclen; + + #ifndef STAGE1_5 +- if (dp->d_ino && print_possibilities && ch != '/' ++ if (dp->d_ino && handle && ch != '/' + && (!*dirname || substring (dirname, dp->d_name) <= 0)) +- { +- if (print_possibilities > 0) +- print_possibilities = -print_possibilities; +- +- print_a_completion (dp->d_name); +- } ++ handle (dp->d_name); + #endif /* STAGE1_5 */ + } + while (!dp->d_ino || (substring (dirname, dp->d_name) != 0 +- || (print_possibilities && ch != '/'))); ++ || (handle && ch != '/'))); + + /* only get here if we have a matching directory entry */ + +diff -Nur grub-0.97-dirs/stage2/fsys_vstafs.c grub-0.97-wildcards/stage2/fsys_vstafs.c +--- grub-0.97-dirs/stage2/fsys_vstafs.c 2005-08-21 20:31:02.000000000 +0300 ++++ grub-0.97-wildcards/stage2/fsys_vstafs.c 2005-08-21 20:32:45.000000000 +0300 +@@ -115,7 +115,7 @@ + } + + int +-vstafs_dir (char *dirname) ++vstafs_dir (char *dirname, void (*handle)(char *)) + { + char *fn, ch; + struct dir_entry *d; +@@ -146,14 +146,9 @@ + continue; + + #ifndef STAGE1_5 +- if (print_possibilities && ch != '/' ++ if (handle && ch != '/' + && (! *dirname || strcmp (dirname, d->name) <= 0)) +- { +- if (print_possibilities > 0) +- print_possibilities = -print_possibilities; +- +- printf (" %s", d->name); +- } ++ handle(d->name); + #endif + if (! grub_strcmp (dirname, d->name)) + { +@@ -168,12 +163,6 @@ + *(dirname = fn) = ch; + if (! d) + { +- if (print_possibilities < 0) +- { +- putchar ('\n'); +- return 1; +- } +- + errnum = ERR_FILE_NOT_FOUND; + return 0; + } +diff -Nur grub-0.97-dirs/stage2/fsys_xfs.c grub-0.97-wildcards/stage2/fsys_xfs.c +--- grub-0.97-dirs/stage2/fsys_xfs.c 2005-08-21 20:31:02.000000000 +0300 ++++ grub-0.97-wildcards/stage2/fsys_xfs.c 2005-08-21 20:32:45.000000000 +0300 +@@ -534,7 +534,7 @@ + } + + int +-xfs_dir (char *dirname) ++xfs_dir (char *dirname, void (*handle)(char *)) + { + xfs_ino_t ino, parent_ino, new_ino; + xfs_fsize_t di_size; +@@ -595,11 +595,9 @@ + for (;;) { + cmp = (!*dirname) ? -1 : substring (dirname, name); + #ifndef STAGE1_5 +- if (print_possibilities && ch != '/' && cmp <= 0) { +- if (print_possibilities > 0) +- print_possibilities = -print_possibilities; +- print_a_completion (name); +- } else ++ if (handle && ch != '/' && cmp <= 0) ++ handle (name); ++ else + #endif + if (cmp == 0) { + parent_ino = ino; +@@ -610,9 +608,6 @@ + } + name = next_dentry (&new_ino); + if (name == NULL) { +- if (print_possibilities < 0) +- return 1; +- + errnum = ERR_FILE_NOT_FOUND; + *rest = ch; + return 0; +diff -Nur grub-0.97-dirs/stage2/shared.h grub-0.97-wildcards/stage2/shared.h +--- grub-0.97-dirs/stage2/shared.h 2005-08-21 20:31:02.000000000 +0300 ++++ grub-0.97-wildcards/stage2/shared.h 2005-08-21 20:32:45.000000000 +0300 +@@ -1012,9 +1012,11 @@ + /* Close a file. */ + void grub_close (void); + +-/* List the contents of the directory that was opened with GRUB_OPEN, +- printing all completions. */ +-int dir (char *dirname); ++/* List the contents of DIRECTORY. */ ++int dir (char *dirname, void (*handle)(char *)); ++ ++/* Wildcard expand the last pathname component of GLOB. */ ++char *wildcard (char *glob, int *len); + + int set_bootdev (int hdbias); + +diff -Nur grub-0.97-dirs/stage2/stage2.c grub-0.97-wildcards/stage2/stage2.c +--- grub-0.97-dirs/stage2/stage2.c 2005-08-21 20:31:02.000000000 +0300 ++++ grub-0.97-wildcards/stage2/stage2.c 2005-08-21 20:33:24.000000000 +0300 +@@ -1243,6 +1243,230 @@ + } + + ++char *wildcard_prefix, *wildcard_suffix; ++char wildcard_matches[1024], *end_wildcard_matches; ++ ++static void wildcard_handler(char *name); ++ ++/* Match one directory entry against the current wildcard. If the entry ++ matches, store it in WILDCARD_MATCHES. Silently ignore entries that ++ don't fit into WILDCARD_MATCHES anymore. */ ++static void ++wildcard_handler(char *name) ++{ ++ char *n = name, *p = wildcard_prefix; ++ ++ while (*p && *p == *n) ++ { ++ p++; ++ n++; ++ } ++ if (*p) ++ return; /* prefix mismatch */ ++ ++ p = name + grub_strlen (name) - grub_strlen (wildcard_suffix); ++ /* [n .. p) is the part matching the asterisk */ ++ ++ if (p < n || grub_strcmp (p, wildcard_suffix) != 0) ++ return; /* suffix mismatch */ ++ ++ /* store this match */ ++ if (p - n + 1 > sizeof (wildcard_matches) - ++ (end_wildcard_matches - wildcard_matches)) ++ return; /* out of space */ ++ while (n < p) ++ *end_wildcard_matches++ = *n++; ++ *end_wildcard_matches++ = 0; ++} ++ ++/* Wildcard expand the GLOB argument. Return NULL upon failure, or ++ a list of 0-terminated expansions, terminated by a zero-length string. */ ++char * ++wildcard (char *glob, int *len) ++{ ++ char path[128], *p; ++ int ret; ++ ++ end_wildcard_matches = wildcard_matches; ++ if (grub_strlen (glob) + 1 > sizeof (path)) { ++ errnum = ERR_FILELENGTH; ++ return NULL; /* cannot handle pathnames this long */ ++ } ++ grub_strcpy (path, glob); ++ p = path; ++ while (*p) ++ p++; ++ wildcard_suffix = p; ++ while (p > path && *p != '/') ++ p--; ++ if (*p != '/') ++ { ++ errnum = ERR_BAD_FILETYPE; ++ return NULL; /* Cannot wildcard device names */ ++ } ++ *(++p) = 0; ++ wildcard_prefix = glob + (p - path); ++ for (p = wildcard_prefix;; p++) ++ { ++ if (*p == 0) ++ { ++ /* We cannot do exact matches: this cannot be represented in the ++ result list. */ ++ return NULL; ++ } ++ else if (*p == '*') ++ { ++ *p++ = 0; ++ wildcard_suffix = p; ++ break; ++ } ++ } ++ ++ ret = dir (path, wildcard_handler); ++ /* restore original argument */ ++ wildcard_prefix[grub_strlen (wildcard_prefix)] = '*'; ++ if (!ret) ++ return NULL; ++ *len = end_wildcard_matches - wildcard_matches; ++ return wildcard_matches; ++} ++ ++static int inplace_sort_nextint(char **p); ++ ++static int inplace_sort_nextint(char **p) ++{ ++ int i = 0; ++ ++ while (**p && **p < '0' && **p > '9') *p++; ++ if (!**p) return -1; ++ while (**p && **p >= '0' && **p <= '9') ++ { ++ i = i * 10 + **p - '0'; ++ *p++; ++ } ++ return i; ++} ++ ++static int inplace_sort_strcmp(char *l, char *r); ++ ++static int ++inplace_sort_strcmp(char *l, char *r) ++{ ++ char *lp = l; ++ char *rp = r; ++ int li, ri; ++ ++ do ++ { ++ li = inplace_sort_nextint(&lp); ++ ri = inplace_sort_nextint(&rp); ++ if (li > ri) return 1; ++ if (ri > li) return -1; ++ } ++ while (li != -1 || ri != -1); ++ return 0; ++} ++ ++#define skip(str) ((str) + grub_strlen (str) + 1) ++ ++static void inplace_sort (char *str, int len); ++ ++static void ++inplace_sort (char *str, int len) ++{ ++ int m, n = 0; ++ char *s, *t; ++ ++ /* we use x as temporary storage */ ++ char *x = str + len; ++ ++ for (s = str; s < x; s = skip (s)) ++ n++; ++ ++ for (; n >= 2; n--) ++ { ++ s = str; ++ t = skip (s); ++ ++ for (m = n; m >= 2; m--) ++ { ++ if (inplace_sort_strcmp (s, t) < 0) ++ { ++ int ls = skip (s) - s; ++ int lt = skip (t) - t; ++ ++ memcpy (x, s, ls); ++ grub_memmove (s + ls, s + lt, t - (s + ls)); ++ memcpy (s, t, lt); ++ t = t + lt - ls; ++ memcpy (t, x, ls); ++ } ++ s = t; ++ t = skip (t); ++ } ++ } ++} ++ ++#undef skip ++ ++static int this_config_len (const char *config); ++static int ++this_config_len (const char *config) ++{ ++ const char *c = config; ++ while (*c) ++ { ++ while (*c) ++ c++; ++ c++; ++ } ++ c++; ++ return c - config; ++} ++ ++static const char * expand_asterisks (const char *str, int *len, ++ const char *subst); ++ ++/* Expand all asterisks (*) in a menu entry or commands section with its ++ substitution. Use a backslash as escape character. */ ++static const char * ++expand_asterisks (const char *str, int *len, const char *subst) ++{ ++ static char buffer[1024]; ++ char *b = buffer, escaped = 0; ++ const char *end = str + *len; ++ ++ while (str < end) ++ { ++ if (*str == '*' && !escaped) ++ { ++ if (b - buffer + grub_strlen (subst) > sizeof (buffer)) ++ { ++ errnum = ERR_FILELENGTH; ++ return NULL; ++ } ++ grub_strcpy (b, subst); ++ b += grub_strlen (subst); ++ } ++ else if (*str == '\\' && !escaped) ++ escaped = 1; ++ else ++ { ++ escaped = 0; ++ if (b - buffer + 1 > sizeof (buffer)) ++ { ++ errnum = ERR_FILELENGTH; ++ return NULL; ++ } ++ *b++ = *str; ++ } ++ str++; ++ } ++ *len = b - buffer; ++ ++ return buffer; ++} ++ + /* This is the starting function in C. */ + void + cmain (void) +@@ -1262,6 +1486,97 @@ + menu_entries = (char *) MENU_BUF; + init_config (); + } ++ ++ auto void expand_wildcard_entries (void); ++ void expand_wildcard_entries (void) ++ { ++ char *config_entry = config_entries; ++ char *menu_entry = menu_entries; ++ ++ while (*menu_entry) ++ { ++ char *command = config_entry; ++ ++ do ++ { ++ char *c = command; ++ const char *w = "wildcard"; ++ ++ while (*w && *c == *w) ++ { ++ c++; ++ w++; ++ } ++ if (*w == 0 && (*c == ' ' || *c == '\t' || *c == '=')) ++ { ++ int len, wlen; ++ ++ /* This is a wildcard command. Advance to the argument. */ ++ while (*c == ' ' || *c == '\t' || *c == '=') ++ c++; ++ ++ /* Expand wildcard entry. */ ++ w = wildcard (c, &wlen); ++ if (w) ++ inplace_sort (w, wlen); ++ ++ /* Remove the wildcard command from the command section; ++ it has no meaning beyond the wildcard expansion just ++ performed. */ ++ len = grub_strlen (command) + 1; ++ grub_memmove (command, command + len, ++ config_len - (command - config_entries)); ++ config_len -= len; ++ ++ while (w && wlen) ++ { ++ /* Insert expansion before the wildcard entry in the ++ list of entry names. */ ++ len = grub_strlen (menu_entry) + 1; ++ const char *x = expand_asterisks (menu_entry, &len, w); ++ grub_memmove (menu_entry + len, menu_entry, ++ menu_len - (menu_entry - menu_entries)); ++ memcpy (menu_entry, x, len); ++ menu_entry += len; ++ menu_len += len; ++ ++ /* Insert expansion before the wildcard command section ++ in the list of command sections. */ ++ len = this_config_len (config_entry); ++ x = expand_asterisks (config_entry, &len, w); ++ grub_memmove (config_entry + len, config_entry, ++ config_len - (config_entry - ++ config_entries)); ++ memcpy (config_entry, x, len); ++ config_entry += len; ++ config_len += len; ++ ++ num_entries++; ++ wlen -= grub_strlen (w) + 1; ++ w += grub_strlen (w) + 1; ++ } ++ ++ /* Remove the wildcard command section; it has just ++ been expanded. */ ++ len = grub_strlen (menu_entry) + 1; ++ grub_memmove (menu_entry, menu_entry + len, ++ menu_len - (menu_entry - menu_entries)); ++ menu_len -= len; ++ ++ len = this_config_len(config_entry); ++ grub_memmove (config_entry, config_entry + len, ++ config_len - (config_entry - config_entries)); ++ config_len -= len; ++ ++ num_entries--; ++ } ++ command += grub_strlen (command) + 1; ++ } ++ while (*command); ++ menu_entry += grub_strlen (menu_entry) + 1; ++ config_entry += this_config_len(config_entry); ++ } ++ } + + /* Initialize the environment for restarting Stage 2. */ + grub_setjmp (restart_env); +@@ -1414,8 +1729,16 @@ + config_len = prev_config_len; + } + ++ if (is_preset) ++ close_preset_menu (); ++ else ++ grub_close (); ++ + menu_entries[menu_len++] = 0; + config_entries[config_len++] = 0; ++ ++ expand_wildcard_entries(); ++ + grub_memmove (config_entries + config_len, menu_entries, + menu_len); + menu_entries = config_entries + config_len; +@@ -1456,11 +1779,6 @@ + else + default_entry = 0; + } +- +- if (is_preset) +- close_preset_menu (); +- else +- grub_close (); + } + while (is_preset); + } diff --git a/src/rc.d/rc.halt b/src/rc.d/rc.halt index 5661959acb..5a05d7f522 100644 --- a/src/rc.d/rc.halt +++ b/src/rc.d/rc.halt @@ -15,48 +15,48 @@ progressbar() fi } # Set bootsplash -progressbar 9 +progressbar 0 if [ -e /proc/splash ]; then echo "silent" > /proc/splash fi echo "Stopping the RED interface..." -progressbar 8 +progressbar 1 /etc/rc.d/rc.red stop 2>/dev/null /etc/rc.d/rc.red clear 2>/dev/null echo "Shutting down..." -progressbar 7 +progressbar 2 sleep 3 echo "Saving the clock" -progressbar 6 +progressbar 3 /sbin/hwclock --systohc echo "Sending all processes the TERM signal..." -progressbar 5 +progressbar 4 /sbin/killall5 -15 sleep 3 echo "Sending all processes the KILL signal..." -progressbar 4 +progressbar 5 /sbin/killall5 -9 sleep 3 echo "Turning off swap" -progressbar 3 +progressbar 6 swapoff -a echo "Unmounting others" -progressbar 2 +progressbar 7 umount -n -a echo "Unmounting root" -progressbar 1 +progressbar 8 mount -n -o remount,ro / # Send nice shutdown beep now -progressbar 0 +progressbar 9 /usr/bin/beep -l 75 -f 3000 /usr/bin/beep -l 75 -f 2000 /usr/bin/beep -l 75 -f 1000