Hello!

The last changes in GRUB make it possible to install it on floppy
images. It is even possible to debug GRUB without access rights to
the floppy disk!

As usually, the current code needs some fixes.

ChangeLog for the attached patch:

        * grub/asmstub.c (grub_stage2): Disable hard disk probing
        for systems other than Linux and Hurd. Checking SCSI disks
        (check_device): new function, check if the device is readable
        stage2/shared.h [GRUB_UTIL]: declare check_device()
        * stage2/builtins.c (device_func): Check the device before
        assigning
        (geometry_func) [GRUB_UTIL]: print the resulting geometry, not
        the old one, but leave get_diskinfo() before setting new values
        to make sure that the disk has been probed. Reload buf_geom if
        needed.
        * stage2/fsys_ext2fs.c (ext2_rdfsb): buffer should be (char *),
        not int. Remove/simplify related casts
        * stage2/fsys_minix.c (minix_rdfsb): Likewise

Known problems:

"device" reports "File not found" even for other errors (EISDIR, EPERM
etc). Maybe I should use strerror(errno) ?

Drive numbers should always be within 0x00-0x07 or 0x80-0x87
set_device should check what safe_parse_maxint returns.

Pavel Roskin
Index: grub/asmstub.c
===================================================================
RCS file: /var/cvs/grub/grub/asmstub.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- grub/asmstub.c      1999/09/10 19:46:09     1.1.1.1
+++ grub/asmstub.c      1999/09/10 19:48:05     1.2
@@ -149,56 +149,23 @@
   assign_device_name (1, "/dev/fd1");
 #endif
 
+#if defined(__linux__) || defined(__GNU__)
   /* IDE disks.  */
   for (i = 0; i < 4; i++)
     {
       char name[10];
-      FILE *fp;
-      char buf[512];
 #ifdef __linux__
       char unit = 'a' + i;
 #elif defined(__GNU__)
       char unit = '0' + i;
-#else
-#warning "BIOS drives cannot be guessed in your operating system."
 #endif
 
       sprintf (name, "/dev/hd%c", unit);
-      fp = fopen (name, "r");
-      if (! fp)
-       {
-         switch (errno)
-           {
-#ifdef ENOMEDIUM
-           case ENOMEDIUM:
-#if 0
-             /* At the moment, this finds only CDROMs, which can't be
-                read anyway, so leave it out. Code should be
-                reactivated if `removable disks' and CDROMs are
-                supported.  */
-             /* register it, it may be inserted.  */
-             assign_device_name (num_hd++ + 0x80, name);
-#endif
-             break;
-#endif /* ENOMEDIUM */
-           default:
-             /* break case and leave */
-             break;
-           }
-         /* continue: there may be more disks sitting sparse on the
-            controllers */
-         continue;
-       }
-
-      /* Attempt to read the first sector.  */
-      if (fread (buf, 1, 512, fp) != 512)
+      if (!check_device (name))
        {
-         fclose (fp);
-         break;
+         assign_device_name (num_hd + 0x80, name);
+         num_hd++;
        }
-
-      fclose (fp);
-      assign_device_name (num_hd++ + 0x80, name);
     }
 
   /* The rest is SCSI disks.  */
@@ -211,8 +178,15 @@
 #elif defined(__GNU__)
       sprintf (name, "/dev/sd%d", i);
 #endif
-      assign_device_name (num_hd++ + 0x80, name);
+      if (!check_device (name))
+       {
+         assign_device_name (num_hd + 0x80, name);
+         num_hd++;
+       }
     }
+#else /* Neither Linux nor Hurd */
+#warning "BIOS drives cannot be guessed in your operating system."
+#endif
 
   /* Check some invariants. */
   assert ((SCRATCHSEG << 4) == SCRATCHADDR);
@@ -274,6 +248,48 @@
 
   /* Ahh... at last we're ready to return to caller. */
   return status;
+}
+
+/* Check if the device can be read. Return 0 on success, -1 on error */
+int
+check_device (const char *device)
+{
+  char buf[512];
+  FILE *fp;
+  fp = fopen (device, "r");
+  if (!fp)
+    {
+      switch (errno)
+       {
+#ifdef ENOMEDIUM
+       case ENOMEDIUM:
+#if 0
+         /* At the moment, this finds only CDROMs, which can't be
+            read anyway, so leave it out. Code should be
+            reactivated if `removable disks' and CDROMs are
+            supported.  */
+         /* accept it, it may be inserted.  */
+         return 0;
+#endif
+         break;
+#endif /* ENOMEDIUM */
+       default:
+         /* break case and leave */
+         break;
+       }
+      /* error opening the device */
+      return -1;
+    }
+
+  /* Attempt to read the first sector.  */
+  if (fread (buf, 1, 512, fp) != 512)
+    {
+      fclose (fp);
+      return -1;
+    }
+
+  fclose (fp);
+  return 0;
 }
 
 /* Assign DRIVE to a device name DEVICE.  */
Index: stage2/builtins.c
===================================================================
RCS file: /var/cvs/grub/stage2/builtins.c,v
retrieving revision 1.1.1.1
retrieving revision 1.4
diff -u -r1.1.1.1 -r1.4
--- stage2/builtins.c   1999/09/10 19:46:10     1.1.1.1
+++ stage2/builtins.c   1999/09/10 22:47:03     1.4
@@ -300,7 +300,7 @@
 
   /* Get the device argument.  */
   device = skip_to (0, drive);
-  if (! *device)
+  if (! *device || check_device (device))
     {
       errnum = ERR_FILE_NOT_FOUND;
       return 1;
@@ -450,12 +450,6 @@
   if (errnum)
     return 1;
 
-  if (get_diskinfo (current_drive, &geom))
-    {
-      errnum = ERR_NO_DISK;
-      return 1;
-    }
-
 #ifdef GRUB_UTIL
   ptr = skip_to (0, device);
   if (*ptr)
@@ -472,6 +466,9 @@
          || ! safe_parse_maxint (&sector, &num_sector))
        return 1;
 
+      /* Make sure that the disk has been probed */
+      get_diskinfo (current_drive, &geom);
+
       disks[current_drive].cylinders = num_cylinder;
       disks[current_drive].heads = num_head;
       disks[current_drive].sectors = num_sector;
@@ -481,10 +478,21 @@
       else
        disks[current_drive].total_sectors
          = num_cylinder * num_head * num_sector;
+
+      /* Reload buf_geom if we are working with buf_drive */
+      if (buf_drive == current_drive)
+       get_diskinfo (current_drive, &buf_geom);
+
       errnum = 0;
     }
 #endif /* GRUB_UTIL */
   
+  if (get_diskinfo (current_drive, &geom))
+    {
+      errnum = ERR_NO_DISK;
+      return 1;
+    }
+
 #ifdef GRUB_UTIL
   msg = device_map[current_drive];
 #else
Index: stage2/fsys_ext2fs.c
===================================================================
RCS file: /var/cvs/grub/stage2/fsys_ext2fs.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- stage2/fsys_ext2fs.c        1999/09/10 19:46:10     1.1.1.1
+++ stage2/fsys_ext2fs.c        1999/09/10 21:41:45     1.2
@@ -210,9 +210,9 @@
 #define INODE \
     ((struct ext2_inode *)((int)GROUP_DESC + EXT2_BLOCK_SIZE(SUPERBLOCK)))
 #define DATABLOCK1 \
-    ((int)((int)INODE + sizeof(struct ext2_inode)))
+    ((char *)INODE + sizeof(struct ext2_inode))
 #define DATABLOCK2 \
-    ((int)((int)DATABLOCK1 + EXT2_BLOCK_SIZE(SUPERBLOCK)))
+    ((char *)DATABLOCK1 + EXT2_BLOCK_SIZE(SUPERBLOCK))
 
 /* linux/ext2_fs.h */
 #define EXT2_ADDR_PER_BLOCK(s)          (EXT2_BLOCK_SIZE(s) / sizeof (__u32))
@@ -268,13 +268,13 @@
 
 /* Takes a file system block number and reads it into BUFFER. */
 static int
-ext2_rdfsb (int fsblock, int buffer)
+ext2_rdfsb (int fsblock, char *buffer)
 {
 #ifdef E2DEBUG
   printf ("fsblock %d buffer %d\n", fsblock, buffer);
 #endif /* E2DEBUG */
   return devread (fsblock * (EXT2_BLOCK_SIZE (SUPERBLOCK) / DEV_BSIZE), 0,
-                 EXT2_BLOCK_SIZE (SUPERBLOCK), (char *) buffer);
+                 EXT2_BLOCK_SIZE (SUPERBLOCK), buffer);
 }
 
 /* from
@@ -536,7 +536,7 @@
 #endif /* E2DEBUG */
       if (!ext2_rdfsb (
                        (WHICH_SUPER + group_desc + SUPERBLOCK->s_first_data_block),
-                       (int) GROUP_DESC))
+                       (char *) GROUP_DESC))
        {
          return 0;
        }
@@ -547,7 +547,7 @@
 #ifdef E2DEBUG
       printf ("inode table fsblock=%d\n", ino_blk);
 #endif /* E2DEBUG */
-      if (!ext2_rdfsb (ino_blk, (int) INODE))
+      if (!ext2_rdfsb (ino_blk, (char *) INODE))
        {
          return 0;
        }
Index: stage2/fsys_minix.c
===================================================================
RCS file: /var/cvs/grub/stage2/fsys_minix.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- stage2/fsys_minix.c 1999/09/10 19:46:10     1.1.1.1
+++ stage2/fsys_minix.c 1999/09/10 21:41:45     1.2
@@ -140,9 +140,9 @@
 #define INODE \
     ((struct minix_inode *)((int) SUPERBLOCK + BLOCK_SIZE))
 #define DATABLOCK1 \
-    ((int)((int)INODE + sizeof(struct minix_inode)))
+    ((char *)INODE + sizeof(struct minix_inode))
 #define DATABLOCK2 \
-    ((int)((int)DATABLOCK1 + BLOCK_SIZE))
+    ((char *)DATABLOCK1 + BLOCK_SIZE)
 
 /* linux/stat.h */
 #define S_IFMT  00170000
@@ -190,10 +190,10 @@
 
 /* Takes a file system block number and reads it into BUFFER. */
 static int
-minix_rdfsb (int fsblock, int buffer)
+minix_rdfsb (int fsblock, char *buffer)
 {
   return devread (fsblock * (BLOCK_SIZE / DEV_BSIZE), 0,
-                 BLOCK_SIZE, (char *) buffer);
+                 BLOCK_SIZE, buffer);
 }
 
 /* Maps LOGICAL_BLOCK (the file offset divided by the blocksize) into
@@ -340,7 +340,7 @@
 
       ino_blk = (2 + SUPERBLOCK->s_imap_blocks + SUPERBLOCK->s_zmap_blocks
                 + (current_ino - 1) / MINIX_INODES_PER_BLOCK);
-      if (! minix_rdfsb (ino_blk, (int) INODE))
+      if (! minix_rdfsb (ino_blk, (char *) INODE))
        return 0;
 
       /* reset indirect blocks! */
Index: stage2/shared.h
===================================================================
RCS file: /var/cvs/grub/stage2/shared.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- stage2/shared.h     1999/09/10 19:46:10     1.1.1.1
+++ stage2/shared.h     1999/09/10 19:48:05     1.2
@@ -338,6 +338,8 @@
 extern char **device_map;
 /* The array of geometries.  */
 extern struct geometry *disks;
+/* Check if the device can be read. Return 0 on success, -1 on error */
+extern int check_device (const char *device);
 /* Assign DRIVE to a device name DEVICE.  */
 extern void assign_device_name (int drive, const char *device);
 #endif

Reply via email to