--- grub-0.97/stage2/boot.c 2007-03-14 11:19:00.000000000 -0400 +++ grub-0.97/stage2/boot.c 2007-03-14 11:20:07.000000000 -0400 @@ -798,8 +798,8 @@ int load_initrd (char *initrd) { - int len; - unsigned long moveto; + int len, num_bytes = 0, total = 0; + unsigned long moveto, rdimg; unsigned long max_addr; struct linux_kernel_header *lh = (struct linux_kernel_header *) (cur_addr - LINUX_SETUP_MOVE_SIZE); @@ -814,8 +814,8 @@ if (! grub_open (initrd)) goto fail; - len = grub_read ((char *) cur_addr, -1); - if (! len) + len = grub_filelen (); + if(!len) { grub_close (); goto fail; @@ -834,12 +834,29 @@ XXX: Linux 2.2.xx has a bug in the memory range check, which is worse than that of Linux 2.3.xx, so avoid the last 64kb. *sigh* */ moveto -= 0x10000; - memmove ((void *) RAW_ADDR (moveto), (void *) cur_addr, len); printf (" [Linux-initrd @ 0x%x, 0x%x bytes]\n", moveto, len); + rdimg = moveto; + + while (total < len) + { + num_bytes = grub_read ((char *) cur_addr, 0x100000); + if (num_bytes == 0) + break; + memmove ((void *) RAW_ADDR (moveto), (void *) cur_addr, num_bytes); + moveto += num_bytes; + total += num_bytes; + } + + if (total < len) + { + grub_close (); + goto fail; + } + /* FIXME: Should check if the kernel supports INITRD. */ - lh->ramdisk_image = RAW_ADDR (moveto); + lh->ramdisk_image = RAW_ADDR (rdimg); lh->ramdisk_size = len; grub_close (); --- grub-0.97/stage2/disk_io.c 2007-03-14 11:19:00.000000000 -0400 +++ grub-0.97/stage2/disk_io.c 2007-03-14 11:20:10.000000000 -0400 @@ -1751,6 +1751,12 @@ return offset; } + int +grub_filelen (void) +{ + return filemax; +} + int dir (char *dirname) { --- grub-0.97/stage2/shared.h 2007-03-14 11:19:00.000000000 -0400 +++ grub-0.97/stage2/shared.h 2007-03-14 11:20:13.000000000 -0400 @@ -953,6 +953,9 @@ /* Reposition a file offset. */ int grub_seek (int offset); +/* Get the length of a file opened with grub_open. */ +int grub_filelen (void); + /* Close a file. */ void grub_close (void);