2008-05-30 Robert Millan <rmh@aybabtu.com>
* util/biosdisk.c (map): Redefine structure to hold information about GRUB drive name. (get_drive): Reimplement without assuming (and verifiing) BIOS-like drive names. (call_hook): Remove. (grub_util_biosdisk_iterate): Access drive names via `.drive' struct member. Assume drive has partitions. (grub_util_biosdisk_open): Access device names via `.device' struct member. (open_device): Likewise. (find_drive): Likewise. (read_device_map): Adjust map[] usage to match the new struct definition. Don't check for duplicates (still possible, but not cheap anymore). (grub_util_biosdisk_fini): Free malloced buffers referenced by map[]. (make_device_name): Remove assumption of BIOS-like drive names.
This commit is contained in:
parent
bbb64db0d3
commit
01b73ec8eb
2 changed files with 73 additions and 59 deletions
19
ChangeLog
19
ChangeLog
|
@ -1,3 +1,22 @@
|
||||||
|
2008-05-30 Robert Millan <rmh@aybabtu.com>
|
||||||
|
|
||||||
|
* util/biosdisk.c (map): Redefine structure to hold information
|
||||||
|
about GRUB drive name.
|
||||||
|
(get_drive): Reimplement without assuming (and verifiing) BIOS-like
|
||||||
|
drive names.
|
||||||
|
(call_hook): Remove.
|
||||||
|
(grub_util_biosdisk_iterate): Access drive names via `.drive' struct
|
||||||
|
member. Assume drive has partitions.
|
||||||
|
(grub_util_biosdisk_open): Access device names via `.device' struct
|
||||||
|
member.
|
||||||
|
(open_device): Likewise.
|
||||||
|
(find_drive): Likewise.
|
||||||
|
(read_device_map): Adjust map[] usage to match the new struct
|
||||||
|
definition. Don't check for duplicates (still possible, but not cheap
|
||||||
|
anymore).
|
||||||
|
(grub_util_biosdisk_fini): Free malloced buffers referenced by map[].
|
||||||
|
(make_device_name): Remove assumption of BIOS-like drive names.
|
||||||
|
|
||||||
2008-05-30 Pavel Roskin <proski@gnu.org>
|
2008-05-30 Pavel Roskin <proski@gnu.org>
|
||||||
|
|
||||||
* conf/i386-efi.rmk (normal/execute.c_DEPENDENCIES): Remove, as
|
* conf/i386-efi.rmk (normal/execute.c_DEPENDENCIES): Remove, as
|
||||||
|
|
113
util/biosdisk.c
113
util/biosdisk.c
|
@ -85,7 +85,11 @@ struct hd_geometry
|
||||||
# define FLOPPY_MAJOR 2
|
# define FLOPPY_MAJOR 2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static char *map[256];
|
struct
|
||||||
|
{
|
||||||
|
char *drive;
|
||||||
|
char *device;
|
||||||
|
} map[256];
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
/* Check if we have devfs support. */
|
/* Check if we have devfs support. */
|
||||||
|
@ -108,45 +112,31 @@ have_devfs (void)
|
||||||
static int
|
static int
|
||||||
get_drive (const char *name)
|
get_drive (const char *name)
|
||||||
{
|
{
|
||||||
unsigned long drive;
|
unsigned int i;
|
||||||
char *p;
|
|
||||||
|
|
||||||
if ((name[0] != 'f' && name[0] != 'h') || name[1] != 'd')
|
if (name)
|
||||||
goto fail;
|
{
|
||||||
|
for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
|
||||||
|
if (! strcmp (map[i].drive, name))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
|
||||||
|
if (! map[i].drive)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
drive = strtoul (name + 2, &p, 10);
|
|
||||||
if (p == name + 2)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
if (name[0] == 'h')
|
|
||||||
drive += 0x80;
|
|
||||||
|
|
||||||
if (drive > sizeof (map) / sizeof (map[0]))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
return (int) drive;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
grub_error (GRUB_ERR_UNKNOWN_DEVICE, "not a biosdisk");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
call_hook (int (*hook) (const char *name), int drive)
|
|
||||||
{
|
|
||||||
char name[10];
|
|
||||||
|
|
||||||
sprintf (name, (drive & 0x80) ? "hd%d" : "fd%d", drive & (~0x80));
|
|
||||||
return hook (name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
grub_util_biosdisk_iterate (int (*hook) (const char *name))
|
grub_util_biosdisk_iterate (int (*hook) (const char *name))
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
|
for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
|
||||||
if (map[i] && call_hook (hook, i))
|
if (map[i].drive && hook (map[i].drive))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -160,13 +150,10 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
|
||||||
|
|
||||||
drive = get_drive (name);
|
drive = get_drive (name);
|
||||||
if (drive < 0)
|
if (drive < 0)
|
||||||
return grub_errno;
|
|
||||||
|
|
||||||
if (! map[drive])
|
|
||||||
return grub_error (GRUB_ERR_BAD_DEVICE,
|
return grub_error (GRUB_ERR_BAD_DEVICE,
|
||||||
"no mapping exists for `%s'", name);
|
"no mapping exists for `%s'", name);
|
||||||
|
|
||||||
disk->has_partitions = (drive & 0x80);
|
disk->has_partitions = 1;
|
||||||
disk->id = drive;
|
disk->id = drive;
|
||||||
|
|
||||||
/* Get the size. */
|
/* Get the size. */
|
||||||
|
@ -175,9 +162,9 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
|
||||||
unsigned long long nr;
|
unsigned long long nr;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
fd = open (map[drive], O_RDONLY);
|
fd = open (map[drive].device, O_RDONLY);
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
return grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s'", map[drive]);
|
return grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s'", map[drive].device);
|
||||||
|
|
||||||
if (fstat (fd, &st) < 0 || ! S_ISBLK (st.st_mode))
|
if (fstat (fd, &st) < 0 || ! S_ISBLK (st.st_mode))
|
||||||
{
|
{
|
||||||
|
@ -207,8 +194,8 @@ grub_util_biosdisk_open (const char *name, grub_disk_t disk)
|
||||||
#elif !defined (__GNU__)
|
#elif !defined (__GNU__)
|
||||||
# warning "No special routine to get the size of a block device is implemented for your OS. This is not possibly fatal."
|
# warning "No special routine to get the size of a block device is implemented for your OS. This is not possibly fatal."
|
||||||
#endif
|
#endif
|
||||||
if (stat (map[drive], &st) < 0)
|
if (stat (map[drive].device, &st) < 0)
|
||||||
return grub_error (GRUB_ERR_BAD_DEVICE, "cannot stat `%s'", map[drive]);
|
return grub_error (GRUB_ERR_BAD_DEVICE, "cannot stat `%s'", map[drive].device);
|
||||||
|
|
||||||
disk->total_sectors = st.st_size >> GRUB_DISK_SECTOR_BITS;
|
disk->total_sectors = st.st_size >> GRUB_DISK_SECTOR_BITS;
|
||||||
|
|
||||||
|
@ -325,8 +312,8 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
|
||||||
int is_partition = 0;
|
int is_partition = 0;
|
||||||
char dev[PATH_MAX];
|
char dev[PATH_MAX];
|
||||||
|
|
||||||
strcpy (dev, map[disk->id]);
|
strcpy (dev, map[disk->id].device);
|
||||||
if (disk->partition && strncmp (map[disk->id], "/dev/", 5) == 0)
|
if (disk->partition && strncmp (map[disk->id].device, "/dev/", 5) == 0)
|
||||||
is_partition = linux_find_partition (dev, disk->partition->start);
|
is_partition = linux_find_partition (dev, disk->partition->start);
|
||||||
|
|
||||||
/* Open the partition. */
|
/* Open the partition. */
|
||||||
|
@ -345,10 +332,10 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
|
||||||
sector -= disk->partition->start;
|
sector -= disk->partition->start;
|
||||||
}
|
}
|
||||||
#else /* ! __linux__ */
|
#else /* ! __linux__ */
|
||||||
fd = open (map[disk->id], flags);
|
fd = open (map[disk->id].device, flags);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s'", map[disk->id]);
|
grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s'", map[disk->id].device);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif /* ! __linux__ */
|
#endif /* ! __linux__ */
|
||||||
|
@ -366,7 +353,7 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
|
||||||
offset = (loff_t) sector << GRUB_DISK_SECTOR_BITS;
|
offset = (loff_t) sector << GRUB_DISK_SECTOR_BITS;
|
||||||
if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
|
if (_llseek (fd, offset >> 32, offset & 0xffffffff, &result, SEEK_SET))
|
||||||
{
|
{
|
||||||
grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id]);
|
grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id].device);
|
||||||
close (fd);
|
close (fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -377,7 +364,7 @@ open_device (const grub_disk_t disk, grub_disk_addr_t sector, int flags)
|
||||||
|
|
||||||
if (lseek (fd, offset, SEEK_SET) != offset)
|
if (lseek (fd, offset, SEEK_SET) != offset)
|
||||||
{
|
{
|
||||||
grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id]);
|
grub_error (GRUB_ERR_BAD_DEVICE, "cannot seek `%s'", map[disk->id].device);
|
||||||
close (fd);
|
close (fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -458,7 +445,7 @@ grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
parts. -jochen */
|
parts. -jochen */
|
||||||
if (nread (fd, buf, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE)
|
if (nread (fd, buf, GRUB_DISK_SECTOR_SIZE) != GRUB_DISK_SECTOR_SIZE)
|
||||||
{
|
{
|
||||||
grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id]);
|
grub_error (GRUB_ERR_READ_ERROR, "cannot read `%s'", map[disk->id].device);
|
||||||
close (fd);
|
close (fd);
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
}
|
}
|
||||||
|
@ -470,7 +457,7 @@ grub_util_biosdisk_read (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
|
|
||||||
if (nread (fd, buf, size << GRUB_DISK_SECTOR_BITS)
|
if (nread (fd, buf, size << GRUB_DISK_SECTOR_BITS)
|
||||||
!= (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
|
!= (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
|
||||||
grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id]);
|
grub_error (GRUB_ERR_READ_ERROR, "cannot read from `%s'", map[disk->id].device);
|
||||||
|
|
||||||
close (fd);
|
close (fd);
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
@ -488,7 +475,7 @@ grub_util_biosdisk_write (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
|
|
||||||
if (nwrite (fd, buf, size << GRUB_DISK_SECTOR_BITS)
|
if (nwrite (fd, buf, size << GRUB_DISK_SECTOR_BITS)
|
||||||
!= (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
|
!= (ssize_t) (size << GRUB_DISK_SECTOR_BITS))
|
||||||
grub_error (GRUB_ERR_WRITE_ERROR, "cannot write to `%s'", map[disk->id]);
|
grub_error (GRUB_ERR_WRITE_ERROR, "cannot write to `%s'", map[disk->id].device);
|
||||||
|
|
||||||
close (fd);
|
close (fd);
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
@ -544,14 +531,20 @@ read_device_map (const char *dev_map)
|
||||||
show_error ("No open parenthesis found");
|
show_error ("No open parenthesis found");
|
||||||
|
|
||||||
p++;
|
p++;
|
||||||
drive = get_drive (p);
|
/* Find a free slot. */
|
||||||
if (drive < 0 || drive >= (int) (sizeof (map) / sizeof (map[0])))
|
drive = get_drive (NULL);
|
||||||
show_error ("Bad device name");
|
if (drive < 0)
|
||||||
|
show_error ("Map table size exceeded");
|
||||||
|
|
||||||
|
e = p;
|
||||||
p = strchr (p, ')');
|
p = strchr (p, ')');
|
||||||
if (! p)
|
if (! p)
|
||||||
show_error ("No close parenthesis found");
|
show_error ("No close parenthesis found");
|
||||||
|
|
||||||
|
map[drive].drive = xmalloc (p - e + sizeof ('\0'));
|
||||||
|
strncpy (map[drive].drive, e, p - e + sizeof ('\0'));
|
||||||
|
map[drive].drive[p - e] = '\0';
|
||||||
|
|
||||||
p++;
|
p++;
|
||||||
/* Skip leading spaces. */
|
/* Skip leading spaces. */
|
||||||
while (*p && isspace (*p))
|
while (*p && isspace (*p))
|
||||||
|
@ -566,10 +559,6 @@ read_device_map (const char *dev_map)
|
||||||
e++;
|
e++;
|
||||||
*e = '\0';
|
*e = '\0';
|
||||||
|
|
||||||
/* Multiple entries for a given drive is not allowed. */
|
|
||||||
if (map[drive])
|
|
||||||
show_error ("Duplicated entry found");
|
|
||||||
|
|
||||||
if (stat (p, &st) == -1)
|
if (stat (p, &st) == -1)
|
||||||
{
|
{
|
||||||
grub_util_info ("Cannot stat `%s', skipping", p);
|
grub_util_info ("Cannot stat `%s', skipping", p);
|
||||||
|
@ -580,11 +569,11 @@ read_device_map (const char *dev_map)
|
||||||
/* On Linux, the devfs uses symbolic links horribly, and that
|
/* On Linux, the devfs uses symbolic links horribly, and that
|
||||||
confuses the interface very much, so use realpath to expand
|
confuses the interface very much, so use realpath to expand
|
||||||
symbolic links. */
|
symbolic links. */
|
||||||
map[drive] = xmalloc (PATH_MAX);
|
map[drive].device = xmalloc (PATH_MAX);
|
||||||
if (! realpath (p, map[drive]))
|
if (! realpath (p, map[drive].device))
|
||||||
grub_util_error ("Cannot get the real path of `%s'", p);
|
grub_util_error ("Cannot get the real path of `%s'", p);
|
||||||
#else
|
#else
|
||||||
map[drive] = xstrdup (p);
|
map[drive].device = xstrdup (p);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -604,7 +593,13 @@ grub_util_biosdisk_fini (void)
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
|
for (i = 0; i < sizeof (map) / sizeof (map[0]); i++)
|
||||||
free (map[i]);
|
{
|
||||||
|
if (map[i].drive)
|
||||||
|
free (map[i].drive);
|
||||||
|
if (map[i].device)
|
||||||
|
free (map[i].device);
|
||||||
|
map[i].drive = map[i].device = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
grub_disk_dev_unregister (&grub_util_biosdisk_dev);
|
grub_disk_dev_unregister (&grub_util_biosdisk_dev);
|
||||||
}
|
}
|
||||||
|
@ -615,7 +610,7 @@ make_device_name (int drive, int dos_part, int bsd_part)
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
p = xmalloc (30);
|
p = xmalloc (30);
|
||||||
sprintf (p, (drive & 0x80) ? "hd%d" : "fd%d", drive & ~0x80);
|
sprintf (p, "%s", map[drive].drive);
|
||||||
|
|
||||||
if (dos_part >= 0)
|
if (dos_part >= 0)
|
||||||
sprintf (p + strlen (p), ",%d", dos_part + 1);
|
sprintf (p + strlen (p), ",%d", dos_part + 1);
|
||||||
|
@ -746,7 +741,7 @@ find_drive (const char *os_dev)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
for (i = 0; i < (int) (sizeof (map) / sizeof (map[0])); i++)
|
for (i = 0; i < (int) (sizeof (map) / sizeof (map[0])); i++)
|
||||||
if (map[i] && strcmp (map[i], os_disk) == 0)
|
if (map[i].device && strcmp (map[i].device, os_disk) == 0)
|
||||||
{
|
{
|
||||||
free (os_disk);
|
free (os_disk);
|
||||||
return i;
|
return i;
|
||||||
|
|
Loading…
Reference in a new issue