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 (§or, &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