Репозиторий Sisyphus
Последнее обновление: 1 октября 2023 | Пакетов: 18631 | Посещений: 37544599
en ru br
Репозитории ALT
S:2.06-alt16
D:0.97-alt2
5.1: 0.97-alt5
4.1: 0.97-alt4.M41.1
3.0: 0.95-alt1
www.altlinux.org/Changes

Группа :: Система/Ядро и оборудование
Пакет: grub

 Главная   Изменения   Спек   Патчи   Sources   Загрузить   Gear   Bugs and FR  Repocop 

Патч: grub-0.94-rh-geometry-26kernel.patch
Скачать


--- 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>
 
+#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 
+ * 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;
+    
+    if (ioctl (fd, HDIO_GETGEO, &hdg))
+        return;
+
+    *cyl = hdg.cylinders;
+    *heads = hdg.heads;
+    *sectors = 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, 
+                             int *sectors) {
+    struct partition *p;
+    int i,h,s,hh,ss;
+    int first = 1;
+    int bad = 0;
+
+    if (bufp->p.magicflag[0] != PART_TABLE_FLAG0 ||
+	bufp->p.magicflag[1] != 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 = ss = 0;
+    for (i=0; i<4; i++) {
+	p = &(bufp->p.part[i]);
+	if (p->sys_ind != 0) {
+	    h = p->end_head + 1;
+	    s = (p->end_sector & 077);
+	    if (first) {
+		hh = h;
+		ss = s;
+		first = 0;
+	    } else if (hh != h || ss != s)
+		bad = 1;
+	}
+    }
+
+    if (!first && !bad) {
+	*heads = hh;
+	*sectors = ss;
+    }
+}
+
+static void get_linux_geometry (int fd, struct geometry *geom) {
+    int kern_cyl = 0, kern_head = 0, kern_sectors = 0;
+    int pt_cyl = 0, pt_head = 0, pt_sectors = 0;
+    partition_table bufp;
+
+    get_kernel_geometry(fd, &kern_cyl, &kern_head, &kern_sectors);
+
+    if (read(fd, bufp.c.b, SECTOR_SIZE) == SECTOR_SIZE) {
+        get_partition_table_geometry(&bufp, &pt_cyl, &pt_head, &pt_sectors);
+    } else {
+        fprintf(stderr, "Unable to read partition table: %s\n", strerror(errno));
+    }
+
+    if (pt_head && pt_sectors) {
+        int cyl_size;
+
+        geom->heads = pt_head;
+        geom->sectors = pt_sectors;
+        cyl_size = pt_head * pt_sectors;
+        geom->cylinders = geom->total_sectors/cyl_size;
+    } else {
+        geom->heads = kern_head;
+        geom->sectors = kern_sectors;
+        geom->cylinders = 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;
     
-    if (ioctl (fd, HDIO_GETGEO, &hdg))
-      goto fail;
-
     if (ioctl (fd, BLKGETSIZE, &nr))
       goto fail;
-    
-    /* Got the geometry, so save it. */
-    geom->cylinders = hdg.cylinders;
-    geom->heads = hdg.heads;
-    geom->sectors = hdg.sectors;
+
     geom->total_sectors = nr;
+    get_linux_geometry(fd, geom);
+
+    if (!geom->heads && !geom->cylinders && !geom->sectors)
+        goto fail;
     
     close (fd);
     return;
 
дизайн и разработка: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
текущий майнтейнер: Michael Shigorin