From: Colin Watson Date: Tue, 18 May 2010 10:14:13 +0000 (+0100) Subject: merge from trunk X-Git-Tag: 1.99~897^2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e6127bed2587f94edd9501438acb19f23a9ce507;p=thirdparty%2Fgrub.git merge from trunk --- e6127bed2587f94edd9501438acb19f23a9ce507 diff --cc conf/common.rmk index 94a96a313,56e4ca631..19082f90e --- a/conf/common.rmk +++ b/conf/common.rmk @@@ -3,8 -6,7 +6,8 @@@ script/lexer.c_DEPENDENCIES = grub_scri sbin_UTILITIES += grub-mkdevicemap grub_mkdevicemap_SOURCES = gnulib/progname.c util/grub-mkdevicemap.c \ util/deviceiter.c \ - util/misc.c \ - kern/env.c kern/err.c kern/list.c kern/misc.c - util/misc.c kern/emu/misc.c ++ util/misc.c kern/emu/misc.c \ ++ kern/env.c kern/err.c kern/list.c kern/misc.c kern/emu/mm.c ifeq ($(target_cpu)-$(platform), sparc64-ieee1275) grub_mkdevicemap_SOURCES += util/ieee1275/ofpath.c util/ieee1275/devicemap.c diff --cc kern/emu/hostdisk.c index 464977978,983f101ae..0ab25ec7d --- a/kern/emu/hostdisk.c +++ b/kern/emu/hostdisk.c @@@ -97,10 -98,18 +98,22 @@@ struct hd_geometr # include #endif +#ifdef HAVE_DEVICE_MAPPER +# include +#endif + + #if defined(__NetBSD__) + # include + # include /* struct disklabel */ + # ifdef HAVE_GETRAWPARTITION + # include /* getrawpartition */ + # endif /* HAVE_GETRAWPARTITION */ + # include + # ifndef RAW_FLOPPY_MAJOR + # define RAW_FLOPPY_MAJOR 9 + # endif /* ! RAW_FLOPPY_MAJOR */ + #endif /* defined(__NetBSD__) */ + struct { char *drive; @@@ -257,116 -312,18 +316,152 @@@ grub_util_biosdisk_open (const char *na return GRUB_ERR_NONE; } +#ifdef HAVE_DEVICE_MAPPER +static int +device_is_mapped (const char *dev) +{ + struct stat st; + + if (stat (dev, &st) < 0) + return 0; + + return dm_is_dm_major (major (st.st_rdev)); +} +#endif /* HAVE_DEVICE_MAPPER */ + - #if defined(__linux__) || defined(__CYGWIN__) ++#if defined(__linux__) || defined(__CYGWIN__) || defined(__NetBSD__) +static grub_disk_addr_t +find_partition_start (const char *dev) +{ + int fd; ++# if !defined(__NetBSD__) + struct hd_geometry hdg; ++# else /* defined(__NetBSD__) */ ++ struct disklabel label; ++ int index; ++# endif /* !defined(__NetBSD__) */ + - #ifdef HAVE_DEVICE_MAPPER ++# ifdef HAVE_DEVICE_MAPPER + if (device_is_mapped (dev)) { + struct dm_task *task = NULL; + grub_uint64_t start, length; + char *target_type, *params, *space; + grub_disk_addr_t partition_start; + + /* If any device-mapper operation fails, we fall back silently to + HDIO_GETGEO. */ + task = dm_task_create (DM_DEVICE_TABLE); + if (! task) + { + grub_dprintf ("hostdisk", "dm_task_create failed\n"); + goto devmapper_fail; + } + + if (! dm_task_set_name (task, dev)) + { + grub_dprintf ("hostdisk", "dm_task_set_name failed\n"); + goto devmapper_fail; + } + + if (! dm_task_run (task)) + { + grub_dprintf ("hostdisk", "dm_task_run failed\n"); + goto devmapper_fail; + } + + dm_get_next_target (task, NULL, &start, &length, &target_type, ¶ms); + if (! target_type) + { + grub_dprintf ("hostdisk", "no dm target\n"); + goto devmapper_fail; + } + if (strcmp (target_type, "linear") != 0) + { + grub_dprintf ("hostdisk", "ignoring dm target %s (not linear)\n", + target_type); + goto devmapper_fail; + } + if (! params) + { + grub_dprintf ("hostdisk", "no dm params\n"); + goto devmapper_fail; + } + + /* The params string for a linear target looks like this: + DEVICE-NAME START-SECTOR + Parse this out. */ + space = strchr (params, ' '); + if (! space) + goto devmapper_fail; + errno = 0; + partition_start = strtoull (space + 1, NULL, 10); + if (errno == 0) + { + grub_dprintf ("hostdisk", "dm %s starts at %llu\n", - dev, partition_start); ++ dev, (unsigned long long) partition_start); + dm_task_destroy (task); + return partition_start; + } + +devmapper_fail: + if (task) + dm_task_destroy (task); + } - #endif /* HAVE_DEVICE_MAPPER */ ++# endif /* HAVE_DEVICE_MAPPER */ + + fd = open (dev, O_RDONLY); + if (fd == -1) + { + grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s' while attempting to get disk geometry", dev); + return 0; + } + ++# if !defined(__NetBSD__) + if (ioctl (fd, HDIO_GETGEO, &hdg)) ++# else /* defined(__NetBSD__) */ ++ configure_device_driver (fd); ++ if (ioctl (fd, DIOCGDINFO, &label) == -1) ++# endif /* !defined(__NetBSD__) */ + { + grub_error (GRUB_ERR_BAD_DEVICE, - "cannot get geometry of `%s'", dev); ++ "cannot get disk geometry of `%s'", dev); + close (fd); + return 0; + } + + close (fd); + ++# if !defined(__NetBSD__) + return hdg.start; ++# else /* defined(__NetBSD__) */ ++ /* Since dev and convert_system_partition_to_system_disk (dev) are ++ * different, we know that dev is of the form /dev/r[wsc]d[0-9]+[a-z] ++ * and in particular it cannot be a floppy device. */ ++ index = dev[strlen(dev) - 1] - 'a'; ++ ++ if (index >= label.d_npartitions) ++ { ++ grub_error (GRUB_ERR_BAD_DEVICE, ++ "no disk label entry for `%s'", dev); ++ return 0; ++ } ++ return (grub_disk_addr_t) label.d_partitions[index].p_offset; ++# endif /* !defined(__NetBSD__) */ +} +#endif /* __linux__ || __CYGWIN__ */ + #ifdef __linux__ + /* Cache of partition start sectors for each disk. */ + struct linux_partition_cache + { + struct linux_partition_cache *next; + char *dev; + unsigned long start; + int partno; + }; + + struct linux_partition_cache *linux_partition_cache_list; + static int linux_find_partition (char *dev, unsigned long sector) { @@@ -404,14 -371,26 +510,23 @@@ fd = open (real_dev, O_RDONLY); if (fd == -1) return 0; - - if (ioctl (fd, HDIO_GETGEO, &hdg)) - { - close (fd); - return 0; - } - close (fd); - if (hdg.start == sector) + start = find_partition_start (real_dev); + /* We don't care about errors here. */ + grub_errno = GRUB_ERR_NONE; + + if (start == sector) { + struct linux_partition_cache *new_cache_item; + + new_cache_item = xmalloc (sizeof *new_cache_item); + new_cache_item->dev = xstrdup (dev); - new_cache_item->start = hdg.start; ++ new_cache_item->start = start; + new_cache_item->partno = i; + grub_list_push (GRUB_AS_LIST_P (&linux_partition_cache_list), + GRUB_AS_LIST (new_cache_item)); + strcpy (dev, real_dev); return 1; } @@@ -1072,8 -1070,28 +1296,28 @@@ device_is_wholedisk (const char *os_dev } #endif + #if defined(__NetBSD__) + /* Try to determine whether a given device name corresponds to a whole disk. + This function should give in most cases a definite answer, but it may + actually give an approximate one in the following sense: if the return + value is 0 then the device name does not correspond to a whole disk. */ + static int + device_is_wholedisk (const char *os_dev) + { + int len = strlen (os_dev); + int rawpart = -1; + + # ifdef HAVE_GETRAWPARTITION + rawpart = getrawpartition(); + # endif /* HAVE_GETRAWPARTITION */ + if (rawpart < 0) + return 1; + return (os_dev[len - 1] == ('a' + rawpart)); + } + #endif /* defined(__NetBSD__) */ + static int -find_system_device (const char *os_dev) +find_system_device (const char *os_dev, struct stat *st) { unsigned int i; char *os_disk; @@@ -1112,19 -1130,19 +1356,19 @@@ grub_util_biosdisk_get_grub_dev (const return 0; } - drive = find_system_device (os_dev); + drive = find_system_device (os_dev, &st); if (drive < 0) { - grub_error (GRUB_ERR_BAD_DEVICE, + grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no mapping exists for `%s'", os_dev); return 0; } - if (grub_strcmp (os_dev, convert_system_partition_to_system_disk (os_dev)) - == 0) + if (grub_strcmp (os_dev, + convert_system_partition_to_system_disk (os_dev, &st)) == 0) return make_device_name (drive, -1, -1); - #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) + #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) if (! S_ISCHR (st.st_mode)) #else if (! S_ISBLK (st.st_mode)) @@@ -1143,42 -1164,35 +1390,27 @@@ { char *name; grub_disk_t disk; - int fd; -# if !defined(__NetBSD__) - struct hd_geometry hdg; - typeof (hdg.start) p_offset; -# else /* defined(__NetBSD__) */ - struct disklabel label; - int index; - u_int32_t p_offset; -# endif /* !defined(__NetBSD__) */ + grub_disk_addr_t start; int dos_part = -1; int bsd_part = -1; - auto int find_partition (grub_disk_t disk, + auto int find_partition (grub_disk_t dsk, const grub_partition_t partition); - int find_partition (grub_disk_t disk __attribute__ ((unused)), + int find_partition (grub_disk_t dsk __attribute__ ((unused)), const grub_partition_t partition) { - struct grub_msdos_partition *pcdata = NULL; - - if (strcmp (partition->partmap->name, "part_msdos") == 0) - pcdata = partition->data; + grub_disk_addr_t part_start = 0; + grub_util_info ("Partition %d starts from %lu", + partition->number, partition->start); - if (pcdata) - { - if (pcdata->bsd_part < 0) - grub_util_info ("DOS partition %d starts from %lu", - pcdata->dos_part, partition->start); - else - grub_util_info ("BSD partition %d,%c starts from %lu", - pcdata->dos_part, pcdata->bsd_part + 'a', - partition->start); - } - else - { - grub_util_info ("Partition %d starts from %lu", - partition->index, partition->start); - } + part_start = grub_partition_get_start (partition); - if (start == partition->start) - if (p_offset == part_start) ++ if (start == part_start) { - if (pcdata) + if (partition->parent) { - dos_part = pcdata->dos_part; - bsd_part = pcdata->bsd_part; + dos_part = partition->parent->number; + bsd_part = partition->number; } else { @@@ -1193,12 -1208,47 +1426,19 @@@ name = make_device_name (drive, -1, -1); + # if !defined(__NetBSD__) if (MAJOR (st.st_rdev) == FLOPPY_MAJOR) return name; + # else /* defined(__NetBSD__) */ + /* Since os_dev and convert_system_partition_to_system_disk (os_dev) are + * different, we know that os_dev is of the form /dev/r[wsc]d[0-9]+[a-z] + * and in particular it cannot be a floppy device. */ + index = os_dev[strlen(os_dev) - 1] - 'a'; + # endif /* !defined(__NetBSD__) */ - fd = open (os_dev, O_RDONLY); - if (fd == -1) - { - grub_error (GRUB_ERR_BAD_DEVICE, "cannot open `%s' while attempting to get disk geometry", os_dev); - free (name); - return 0; - } - -# if !defined(__NetBSD__) - if (ioctl (fd, HDIO_GETGEO, &hdg)) -# else /* defined(__NetBSD__) */ - configure_device_driver (fd); - if (ioctl (fd, DIOCGDINFO, &label) == -1) -# endif /* !defined(__NetBSD__) */ - { - grub_error (GRUB_ERR_BAD_DEVICE, - "cannot get disk geometry of `%s'", os_dev); - close (fd); - free (name); - return 0; - } - - close (fd); - -# if !defined(__NetBSD__) - p_offset = hdg.start; -# else /* defined(__NetBSD__) */ - if (index >= label.d_npartitions) + start = find_partition_start (os_dev); + if (grub_errno != GRUB_ERR_NONE) { - grub_error (GRUB_ERR_BAD_DEVICE, - "no disk label entry for `%s'", os_dev); free (name); return 0; }