Bug#254798: Grub patches from Red Hat

Joshua Kwan joshk@triplehelix.org (Joshua Kwan), 254798@bugs.debian.org
Wed, 16 Jun 2004 16:08:46 -0700


--+PbGPm1eXpwOoWkI
Content-Type: multipart/mixed; boundary="0XhtP95kHFp3KGBe"
Content-Disposition: inline


--0XhtP95kHFp3KGBe
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

Package: grub
Tags: patch
Severity: normal

Hi Jason, Grub-Devel,

Attached are some patches from Fedora/RH's grub packages which I think are
really beneficial. Let me describe each one:

[01-0.94-addsyncs.patch]

This adds 'sync' to a bunch of places in grub-install where it's
crucial. We've tried to do something like this in debian-installer
because we found that grub-install was hanging, most often on XFS
root/boot, adding 'sync; sync; sync' before the grub-install call. This
is obviously more fine grained. And it can't hurt, IMO.

[01-0.94-geometry-26kernel.patch, 01-0.94-initrdmax.patch]

Read the comments in the geometry patch for details of what they are.
_One_ or both of these patches allowed me to boot my AMD64 machine with
grub, not sure which yet (I don't have time at work to mess with it too
much, but I will certainly check sometime.) Without the patches, grub
would complain that "Selected item cannot fit into memory." I am told
this has to do with the amount of memory in my machine (~4GB.)

Of course the problem was moot when I used a non-initrd kernel, so I
suspect it's the last patch that does the trick. It seems kind of
hackish though, but if you believe it can't hurt please add it.

Thanks for hearing me out. I hope we can get a good usable Grub for
beefy AMD64 machines like the ones I have at work :)

For license purposes, each of these patches were extracted from SRPMS
available at

http://mirror.linux.duke.edu/pub/fedora/linux/core/test/1.92/SRPMS/grub-0.9=
4-4.src.rpm

Regards

--=20
Joshua Kwan

--0XhtP95kHFp3KGBe
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="01-0.94-addsyncs.patch"
Content-Transfer-Encoding: quoted-printable

I just found another semi-critical bug, whose fix should really get
into 0.91.

It turns out that "grub-install" doesn't have any "sync" calls to make
sure any filesystem caches are coherent with the raw devices they are
on top of...  so if your filesystem waits to write out any data from the
copy command in the script to put the "stage1" and "stage2" in their
final location, you're hosed.

I found this because it just bit me on one of my systems running stock
RedHat 7.2 with a large "stage2".

The only script that is patched here is "grub-install".  The others
don't appear to need it as they either unmount things first or don't
refer to devices.

Hmm.  Maybe the right fix is to make the "sync" system call when
starting the GRUB shell with a device map that refers to any real disks
or something like that.

    Erich Stefan Boleyn     <erich@uruk.org>     http://www.uruk.org/
"Reality is truly stranger than fiction; Probably why fiction is so popular"

--- grub-0.94/util/grub-install.in.addsync	2004-02-02 17:22:26.672520324 -0=
500
+++ grub-0.94/util/grub-install.in	2004-02-02 17:23:16.147712327 -0500
@@ -351,6 +351,10 @@
     # Create a safe temporary file.
     test -n "$mklog" && log_file=3D`$mklog`
=20
+    # Before all invocations of the grub shell, call sync to make sure
+    # the raw device is in sync with any bufferring in filesystems.
+    sync
+=20
     $grub_shell --batch $no_floppy --device-map=3D$device_map <<EOF >$log_=
file
 quit
 EOF
@@ -457,6 +461,10 @@
 # Create a safe temporary file.
 test -n "$mklog" && log_file=3D`$mklog`
=20
+# Before all invocations of the grub shell, call sync to make sure
+# the raw device is in sync with any bufferring in filesystems.
+sync
+
 # Now perform the installation.
 $grub_shell --batch $no_floppy --device-map=3D$device_map <<EOF >$log_file
 root $root_drive

--0XhtP95kHFp3KGBe
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="01-0.94-geometry-26kernel.patch"
Content-Transfer-Encoding: quoted-printable

--- grub-0.94/lib/device.c.26geom	2004-04-14 14:05:24.786938853 -0400
+++ grub-0.94/lib/device.c	2004-04-14 14:32:50.768600176 -0400
@@ -88,6 +88,122 @@
 #include <shared.h>
 #include <device.h>
=20
+#if defined(__linux__)
+/* The 2.6 kernel has removed all of the geometry handling for IDE drives
+ * that did fixups for LBA, etc.  This means that the geometry we get
+ * with the ioctl has a good chance of being wrong.  So, we get to=20
+ * also know about partition tables and try to read what the geometry
+ * is there. *grumble*   Very closely based on code from cfdisk
+ */
+static void get_kernel_geometry(int fd, int *cyl, int *heads, int *sectors=
) {
+    struct hd_geometry hdg;
+   =20
+    if (ioctl (fd, HDIO_GETGEO, &hdg))
+        return;
+
+    *cyl =3D hdg.cylinders;
+    *heads =3D hdg.heads;
+    *sectors =3D hdg.sectors;
+}
+
+struct partition {
+        unsigned char boot_ind;         /* 0x80 - active */
+        unsigned char head;             /* starting head */
+        unsigned char sector;           /* starting sector */
+        unsigned char cyl;              /* starting cylinder */
+        unsigned char sys_ind;          /* What partition type */
+        unsigned char end_head;         /* end head */
+        unsigned char end_sector;       /* end sector */
+        unsigned char end_cyl;          /* end cylinder */
+        unsigned char start4[4];        /* starting sector counting from 0=
 */
+        unsigned char size4[4];         /* nr of sectors in partition */
+};
+
+#define ALIGNMENT 2
+typedef union {
+    struct {
+	unsigned char align[ALIGNMENT];
+	unsigned char b[SECTOR_SIZE];
+    } c;
+    struct {
+	unsigned char align[ALIGNMENT];
+	unsigned char buffer[0x1BE];
+	struct partition part[4];
+	unsigned char magicflag[2];
+    } p;
+} partition_table;
+
+#define PART_TABLE_FLAG0 0x55
+#define PART_TABLE_FLAG1 0xAA
+
+static void
+get_partition_table_geometry(partition_table *bufp, int *cyl, int *heads,=
=20
+                             int *sectors) {
+    struct partition *p;
+    int i,h,s,hh,ss;
+    int first =3D 1;
+    int bad =3D 0;
+
+    if (bufp->p.magicflag[0] !=3D PART_TABLE_FLAG0 ||
+	bufp->p.magicflag[1] !=3D PART_TABLE_FLAG1) {
+	    /* Matthew Wilcox: slightly friendlier version of
+	       fatal(_("Bad signature on partition table"), 3);
+	    */
+            fprintf(stderr, "Unknown partition table signature\n");
+	    return;
+    }
+
+    hh =3D ss =3D 0;
+    for (i=3D0; i<4; i++) {
+	p =3D &(bufp->p.part[i]);
+	if (p->sys_ind !=3D 0) {
+	    h =3D p->end_head + 1;
+	    s =3D (p->end_sector & 077);
+	    if (first) {
+		hh =3D h;
+		ss =3D s;
+		first =3D 0;
+	    } else if (hh !=3D h || ss !=3D s)
+		bad =3D 1;
+	}
+    }
+
+    if (!first && !bad) {
+	*heads =3D hh;
+	*sectors =3D ss;
+    }
+}
+
+static void get_linux_geometry (int fd, struct geometry *geom) {
+    int kern_cyl =3D 0, kern_head =3D 0, kern_sectors =3D 0;
+    int pt_cyl =3D 0, pt_head =3D 0, pt_sectors =3D 0;
+    partition_table bufp;
+
+    get_kernel_geometry(fd, &kern_cyl, &kern_head, &kern_sectors);
+
+    if (read(fd, bufp.c.b, SECTOR_SIZE) =3D=3D SECTOR_SIZE) {
+        get_partition_table_geometry(&bufp, &pt_cyl, &pt_head, &pt_sectors=
);
+    } else {
+        fprintf(stderr, "Unable to read partition table: %s\n", strerror(e=
rrno));
+    }
+
+    if (pt_head && pt_sectors) {
+        int cyl_size;
+
+        geom->heads =3D pt_head;
+        geom->sectors =3D pt_sectors;
+        cyl_size =3D pt_head * pt_sectors;
+        geom->cylinders =3D geom->total_sectors/cyl_size;
+    } else {
+        geom->heads =3D kern_head;
+        geom->sectors =3D kern_sectors;
+        geom->cylinders =3D kern_cyl;
+    }
+
+    return;
+}
+#endif
+
 /* Get the geometry of a drive DRIVE.  */
 void
 get_drive_geometry (struct geometry *geom, char **map, int drive)
@@ -100,20 +216,16 @@
 #if defined(__linux__)
   /* Linux */
   {
-    struct hd_geometry hdg;
     unsigned long nr;
    =20
-    if (ioctl (fd, HDIO_GETGEO, &hdg))
-      goto fail;
-
     if (ioctl (fd, BLKGETSIZE, &nr))
       goto fail;
-   =20
-    /* Got the geometry, so save it. */
-    geom->cylinders =3D hdg.cylinders;
-    geom->heads =3D hdg.heads;
-    geom->sectors =3D hdg.sectors;
+
     geom->total_sectors =3D nr;
+    get_linux_geometry(fd, geom);
+
+    if (!geom->heads && !geom->cylinders && !geom->sectors)
+        goto fail;
    =20
     close (fd);
     return;

--0XhtP95kHFp3KGBe
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="01-0.94-initrdmax.patch"
Content-Transfer-Encoding: quoted-printable

--- grub-0.94/stage2/boot.c.initrdmax	2004-02-25 13:49:00.801945416 -0500
+++ grub-0.94/stage2/boot.c	2004-02-25 13:49:25.267226128 -0500
@@ -810,8 +810,12 @@
     moveto =3D (mbi.mem_upper + 0x400) << 10;
  =20
   moveto =3D (moveto - len) & 0xfffff000;
+#if 0
   max_addr =3D (lh->header =3D=3D LINUX_MAGIC_SIGNATURE && lh->version >=
=3D 0x0203
 	      ? lh->initrd_addr_max : LINUX_INITRD_MAX_ADDRESS);
+#else
+  max_addr =3D LINUX_INITRD_MAX_ADDRESS;
+#endif
   if (moveto + len >=3D max_addr)
     moveto =3D (max_addr - len) & 0xfffff000;
  =20

--0XhtP95kHFp3KGBe--

--+PbGPm1eXpwOoWkI
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: Digital signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (GNU/Linux)
Comment: http://triplehelix.org/~joshk/pubkey_gpg.asc

iQIVAwUBQNDS/KOILr94RG8mAQI+gQ/9EM93BpfXfJkh1uaQ7t3DQCP1fWMH/ivZ
ZKvis4leW7UcC2liKrGpV1QB3wLcguzJu283r62HymsYHl43i7Phc2QCfTuFLCBk
PvUIXKcBAU++VkvJSUFxnlauvsuh8p7P+nVpMDfLrNjYRRf781JbcLG0MqqPrGd2
21dCRZyqtvoOMpLjzEn1RBegYoU1watipbI3+UXmcv/LptM8ZVqgE0VvcouVffVQ
OVVUonXMVXeH/3uZhQjkA5bKaO/PIw3cyHLdIBNK7DvgJCcoJaPZAWzhJAZc9sf2
ZNn6Zu/aNzaPIRmnKUrmpwmPrwypRcGjp+heywA21McC1kILMUW8BReDCbK4gIax
lVPqn2q68Mls6Ewri4w49+oJXhl/GSQn8ufsa5KAYuRemWS3VH68QKLrFPsKdNjp
UWWOP2RK+PsPHgMjfscFwNih6pQbrzVno2r2MaaLXoLdBwy4k2/E5B3faRp43Vpw
IcyLbFSD5iF6i8daNjzV8nA1ZM0NFgf7wWKzCXRm2RpimZmGY/I+ILAzAb/vRC5n
LvOARDLL2/CSqVmE37U/KamMUubjlxctEg25h20c2RD4kOQOVcWOoq/gQQqhzuTf
1S257Vj3bRK5+PgpOzUx5VO2gw/Qhhhq5vr0+F9qC4Tur8IGyrmV6zgVDG/xd3U4
yhlAUEiprGk=
=FVhy
-----END PGP SIGNATURE-----

--+PbGPm1eXpwOoWkI--