Репозиторий Sisyphus
Последнее обновление: 1 октября 2023 | Пакетов: 18631 | Посещений: 37409989
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.95-geometry-26kernel.patch
Скачать


--- grub-0.95/lib/device.c.26geom	2004-11-30 16:33:00.186025728 -0500
+++ grub-0.95/lib/device.c	2004-11-30 16:45:09.073218032 -0500
@@ -131,6 +131,152 @@
 #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, long long *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, long long *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 long long my_lseek (unsigned int fd, long long offset, 
+                           unsigned int origin)
+{
+#if defined(__linux__) && (!defined(__GLIBC__) || \
+        ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))))
+  /* Maybe libc doesn't have large file support.  */
+  loff_t offset, result;
+  static int _llseek (uint filedes, ulong hi, ulong lo,
+                      loff_t *res, uint wh);
+  _syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo,
+             loff_t *, res, uint, wh);
+  
+  if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET) < 0)
+    return (long long) -1;
+  return result;
+#else
+  return lseek(fd, offset, SEEK_SET);
+#endif
+}
+
+static void get_linux_geometry (int fd, struct geometry *geom) {
+    long long kern_cyl = 0; int kern_head = 0, kern_sectors = 0;
+    long long pt_cyl = 0; int pt_head = 0, pt_sectors = 0;
+    partition_table bufp;
+    char *buff, *buf_unaligned;
+
+    buf_unaligned = malloc(sizeof(partition_table) + 4095);
+    buff = (char *) (((unsigned long)buf_unaligned + 4096 - 1) &
+                     (~(4096-1)));
+
+    get_kernel_geometry(fd, &kern_cyl, &kern_head, &kern_sectors);
+
+    if (my_lseek (fd, 0*SECTOR_SIZE, SEEK_SET) < 0) {
+        fprintf(stderr, "Unable to seek");
+    }
+
+    if (read(fd, buff, SECTOR_SIZE) == SECTOR_SIZE) {
+        memcpy(bufp.c.b, buff, 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)
@@ -151,21 +297,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;
     goto success;
   }
 
@@ -841,6 +982,7 @@
 {
   char dev[PATH_MAX];	/* XXX */
   int fd;
+  off_t offset = (off_t) sector * (off_t) SECTOR_SIZE;
   
   if ((partition & 0x00FF00) != 0x00FF00)
     {
@@ -874,35 +1016,13 @@
       errnum = ERR_NO_PART;
       return 0;
     }
-  
-#if defined(__linux__) && (!defined(__GLIBC__) || \
-        ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1))))
-  /* Maybe libc doesn't have large file support.  */
-  {
-    loff_t offset, result;
-    static int _llseek (uint filedes, ulong hi, ulong lo,
-                        loff_t *res, uint wh);
-    _syscall5 (int, _llseek, uint, filedes, ulong, hi, ulong, lo,
-               loff_t *, res, uint, wh);
 
-    offset = (loff_t) sector * (loff_t) SECTOR_SIZE;
-    if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
-      {
-	errnum = ERR_DEV_VALUES;
-	return 0;
-      }
-  }
-#else
-  {
-    off_t offset = (off_t) sector * (off_t) SECTOR_SIZE;
 
-    if (lseek (fd, offset, SEEK_SET) != offset)
-      {
-	errnum = ERR_DEV_VALUES;
-	return 0;
-      }
-  }
-#endif
+  if (my_lseek(fd, offset, SEEK_SET) != offset)
+    {
+      errnum = ERR_DEV_VALUES;
+      return 0;
+    }
   
   if (write (fd, buf, size * SECTOR_SIZE) != (size * SECTOR_SIZE))
     {
 
дизайн и разработка: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
текущий майнтейнер: Michael Shigorin