/* hostdisk.c - emulate biosdisk */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 1999,2000,2001,2002,2003,2004,2006,2007,2008,2009,2010 Free Software Foundation, Inc.
*
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#define FORCE_INCLUDE_CONFIG_UTIL_H
#include <config.h>
#include <grub/partition.h>
#include <grub/msdos_partition.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <limits.h>
#ifdef __linux__
# if !defined(__GLIBC__) || \
/* Maybe libc doesn't have large file support. */
# endif /* (GLIBC < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR < 1)) */
# ifndef BLKFLSBUF
# endif /* ! BLKFLSBUF */
# ifndef HDIO_GETGEO
/* If HDIO_GETGEO is not defined, it is unlikely that hd_geometry is
defined. */
struct hd_geometry
{
unsigned char heads;
unsigned char sectors;
unsigned short cylinders;
unsigned long start;
};
# endif /* ! HDIO_GETGEO */
# ifndef BLKGETSIZE64
# endif /* ! BLKGETSIZE64 */
# ifndef MAJOR
# ifndef MINORBITS
# endif /* ! MINORBITS */
# endif /* ! MAJOR */
# ifndef FLOPPY_MAJOR
# endif /* ! FLOPPY_MAJOR */
# ifndef LOOP_MAJOR
# endif /* ! LOOP_MAJOR */
#endif /* __linux__ */
#ifdef __CYGWIN__
#endif
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
#include <libgeom.h>
#endif
#if defined (__sun__)
#endif
#if defined(__APPLE__)
#endif
#ifdef HAVE_DEVICE_MAPPER
# include <libdevmapper.h>
#endif
#if defined(__NetBSD__)
# define HAVE_DIOCGDINFO
#else /* !defined(__NetBSD__) && !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) */
#endif /* defined(__NetBSD__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) */
#if defined(__NetBSD__)
# ifdef HAVE_GETRAWPARTITION
# include <util.h> /* getrawpartition */
# endif /* HAVE_GETRAWPARTITION */
# ifndef FLOPPY_MAJOR
# endif /* ! FLOPPY_MAJOR */
# ifndef RAW_FLOPPY_MAJOR
# endif /* ! RAW_FLOPPY_MAJOR */
#endif /* defined(__NetBSD__) */
#if defined(__sun__)
#endif
struct
{
char *drive;
char *device;
int device_map;
struct grub_util_biosdisk_data
{
char *dev;
int access_mode;
int fd;
int is_disk;
int device_map;
};
#ifdef __linux__
/* Check if we have devfs support. */
static int
have_devfs (void)
{
if (dev_devfsd_exists < 0)
{
}
return dev_devfsd_exists;
}
#endif /* __linux__ */
#if defined(__NetBSD__)
/* Adjust device driver parameters. This function should be called just
after successfully opening the device. For now, it simply prevents the
floppy driver from retrying operations on failure, as otherwise the
driver takes a while to abort when there is no floppy in the drive. */
static void
{
return;
{
int floppy_opts;
return;
return;
}
}
#endif /* defined(__NetBSD__) */
static int
{
while (*a || *b_escaped)
{
b_escaped++;
if (*a < *b_escaped)
return -1;
if (*a > *b_escaped)
return +1;
a++;
b_escaped++;
}
if (*a)
return +1;
if (*b_escaped)
return -1;
return 0;
}
static int
{
unsigned int i;
if (name)
{
for (i = 0; i < ARRAY_SIZE (map); i++)
return i;
}
return -1;
}
static int
find_free_slot (void)
{
unsigned int i;
return i;
return -1;
}
static int
{
unsigned i;
if (pull != GRUB_DISK_PULL_NONE)
return 0;
return 1;
return 0;
}
#if !defined(__MINGW32__)
{
# if defined(__NetBSD__)
unsigned long long nr;
#else
unsigned long long nr;
# endif
grub_util_error (_("fstat failed"));
|| defined (__sun__)
# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) || defined (__sun__)
# else
# endif
goto fail;
# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
# elif defined(__NetBSD__)
# else
# endif
goto fail;
# if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
goto fail;
# elif defined(__NetBSD__)
# else
goto fail;
# endif
goto fail;
for (log_sector_size = 0;
log_sector_size++);
if (log_secsize)
# if defined (__APPLE__)
return nr;
# elif defined(__NetBSD__)
return label.d_secperunit;
# else
grub_util_error ("unaligned device size (nr = 0x%llx, log_sector_size = 0x%x)", nr, log_sector_size);
return (nr >> log_sector_size);
# endif
fail:
# warning "No special routine to get the size of a block device is implemented for your OS. This is not possibly fatal."
#endif
sector_size = 512;
log_sector_size = 9;
if (log_secsize)
*log_secsize = 9;
}
#endif
static grub_err_t
{
int drive;
if (drive < 0)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"no mapping exists for `%s'", name);
data->access_mode = 0;
/* Get the size. */
#if defined(__MINGW32__)
{
if (size % 512)
grub_util_error (_("unaligned device size"));
return GRUB_ERR_NONE;
}
#else
{
int fd;
if (fd == -1)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "cannot open `%s' while attempting to get disk size", map[drive].device);
defined(__NetBSD__) || defined(__sun__)
# else
# endif
return GRUB_ERR_NONE;
}
#endif
}
int
{
#ifdef HAVE_DEVICE_MAPPER
if (!grub_device_mapper_supported ())
return 0;
return 0;
#else
return 0;
#endif /* HAVE_DEVICE_MAPPER */
}
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
/* FIXME: geom actually gives us the whole container hierarchy.
It can be used more efficiently than this. */
void
{
int error;
if (error != 0)
grub_util_error (_("couldn't open geom"));
break;
if (!class)
grub_util_error (_("couldn't open geom part"));
{
{
if (off_out)
return;
}
}
if (name_out)
if (off_out)
*off_out = 0;
}
static grub_disk_addr_t
{
return 0;
return out;
}
static grub_disk_addr_t
{
int fd;
#ifdef __sun__
# elif !defined(HAVE_DIOCGDINFO)
# else /* defined(HAVE_DIOCGDINFO) */
int p_index;
# endif /* !defined(HAVE_DIOCGDINFO) */
# ifdef HAVE_DEVICE_MAPPER
if (grub_util_device_is_mapped (dev)) {
/* If any device-mapper operation fails, we fall back silently to
HDIO_GETGEO. */
if (! task)
{
goto devmapper_fail;
}
{
goto devmapper_fail;
}
if (! dm_task_run (task))
{
goto devmapper_fail;
}
if (! target_type)
{
goto devmapper_fail;
}
{
goto devmapper_fail;
}
if (! params)
{
goto devmapper_fail;
}
/* The params string for a linear target looks like this:
DEVICE-NAME START-SECTOR
Parse this out. */
if (! space)
goto devmapper_fail;
errno = 0;
if (errno == 0)
{
dev, (unsigned long long) partition_start);
return partition_start;
}
if (task)
}
# endif /* HAVE_DEVICE_MAPPER */
if (fd == -1)
{
# if !defined(HAVE_DIOCGDINFO)
"cannot open `%s' while attempting to get disk geometry", dev);
# else /* defined(HAVE_DIOCGDINFO) */
"cannot open `%s' while attempting to get disk label", dev);
# endif /* !defined(HAVE_DIOCGDINFO) */
return 0;
}
#if defined(__sun__)
# elif !defined(HAVE_DIOCGDINFO)
# else /* defined(HAVE_DIOCGDINFO) */
# if defined(__NetBSD__)
# endif /* defined(__NetBSD__) */
# endif /* !defined(HAVE_DIOCGDINFO) */
{
# if !defined(HAVE_DIOCGDINFO)
"cannot get disk geometry of `%s'", dev);
# else /* defined(HAVE_DIOCGDINFO) */
"cannot get disk label of `%s'", dev);
# endif /* !defined(HAVE_DIOCGDINFO) */
return 0;
}
#ifdef __sun__
# elif !defined(HAVE_DIOCGDINFO)
# else /* defined(HAVE_DIOCGDINFO) */
if (dev[0])
else
p_index = -1;
{
"no disk label entry for `%s'", dev);
return 0;
}
# endif /* !defined(HAVE_DIOCGDINFO) */
}
#endif /* __linux__ || __CYGWIN__ || HAVE_DIOCGDINFO */
#ifdef __linux__
/* Cache of partition start sectors for each disk. */
struct linux_partition_cache
{
char *dev;
unsigned long start;
int partno;
};
static int
{
const char *format;
char *p;
int i;
int missing = 0;
{
format = "part%d";
}
{
format = "-part%d";
}
{
format = "p%d";
}
else
{
format = "%d";
}
{
{
return 1;
}
}
for (i = 1; i < 10000; i++)
{
int fd;
if (fd == -1)
{
if (missing++ < 10)
continue;
else
return 0;
}
missing = 0;
/* We don't care about errors here. */
{
new_cache_item->partno = i;
return 1;
}
}
return 0;
}
#endif /* __linux__ */
/* Maybe libc doesn't have large file support. */
{
{
}
return GRUB_ERR_NONE;
}
#else
{
return 0;
}
#endif
static int
{
int fd;
#ifdef O_LARGEFILE
flags |= O_LARGEFILE;
#endif
#ifdef O_SYNC
#endif
#ifdef O_FSYNC
#endif
#ifdef O_BINARY
#endif
#ifdef __linux__
/* Linux has a bug that the disk cache for a whole disk is not consistent
with the one for a partition of the disk. */
{
int is_partition = 0;
{
}
else
{
{
{
#ifdef __linux__
#endif
}
}
/* Open the partition. */
if (fd < 0)
{
return -1;
}
}
if (is_partition)
sector -= part_start;
}
#else /* ! __linux__ */
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
{
return -1;
}
if (! (sysctl_oldflags & 0x10)
{
return -1;
}
#endif
{
}
else
{
{
{
#ifdef __linux__
#endif
}
}
if (fd >= 0)
{
}
}
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
if (! (sysctl_oldflags & 0x10)
{
grub_error (GRUB_ERR_BAD_DEVICE, "cannot set flags back to the old value for sysctl kern.geom.debugflags");
return -1;
}
#endif
#if defined(__APPLE__)
/* If we can't have exclusive access, try shared access */
if (fd < 0)
#endif
if (fd < 0)
{
return -1;
}
#endif /* ! __linux__ */
#if defined(__NetBSD__)
#endif /* defined(__NetBSD__) */
{
return -1;
}
return fd;
}
/* Read LEN bytes from FD in BUF. Return less than or equal to zero if an
error occurs, otherwise return LEN. */
{
while (len)
{
if (ret <= 0)
{
continue;
else
return ret;
}
}
return size;
}
/* Write LEN bytes from BUF to FD. Return less than or equal to zero if an
error occurs, otherwise return LEN. */
static ssize_t
{
while (len)
{
if (ret <= 0)
{
continue;
else
return ret;
}
}
return size;
}
static grub_err_t
{
int fd;
/* Split pre-partition and partition reads. */
{
buf);
if (err)
return err;
<< GRUB_DISK_SECTOR_BITS));
}
if (fd < 0)
return grub_errno;
#ifdef __linux__
{
/* Work around a bug in Linux ez remapping. Linux remaps all
sectors that are read together with the MBR in one read. It
should only remap the MBR, so we split the read in two
parts. -jochen */
{
return grub_errno;
}
size--;
}
#endif /* __linux__ */
return grub_errno;
}
static grub_err_t
{
int fd;
/* Split pre-partition and partition writes. */
{
buf);
if (err)
return err;
<< GRUB_DISK_SECTOR_BITS));
}
if (fd < 0)
return grub_errno;
return grub_errno;
}
{
return GRUB_ERR_NONE;
{
return grub_errno;
}
#ifdef __linux__
#endif
return GRUB_ERR_NONE;
}
static void
{
{
}
}
{
.name = "biosdisk",
.next = 0
};
static void
{
int lineno = 0;
auto void show_error (const char *msg);
{
}
if (dev_map[0] == '\0')
{
grub_util_info (_("no device.map"));
return;
}
if (! fp)
{
return;
}
{
char *p = buf;
char *e;
int drive;
lineno++;
/* Skip leading spaces. */
while (*p && isspace (*p))
p++;
/* If the first character is `#' or NUL, skip this line. */
if (*p == '\0' || *p == '#')
continue;
if (*p != '(')
show_error (_("No open parenthesis found"));
p++;
/* Find a free slot. */
drive = find_free_slot ();
if (drive < 0)
show_error (_("Map table size exceeded"));
e = p;
p = strchr (p, ')');
if (! p)
show_error (_("No close parenthesis found"));
p++;
/* Skip leading spaces. */
while (*p && isspace (*p))
p++;
if (*p == '\0')
show_error (_("No filename found"));
/* NUL-terminate the filename. */
e = p;
while (*e && ! isspace (*e))
e++;
*e = '\0';
#ifdef __MINGW32__
(void) st;
if (grub_util_get_disk_size (p) == -1LL)
#else
#endif
{
grub_util_info ("Cannot stat `%s', skipping", p);
continue;
}
#ifdef __linux__
/* On Linux, the devfs uses symbolic links horribly, and that
confuses the interface very much, so use realpath to expand
{
grub_util_error (_("cannot get the real path of `%s'"), p);
}
else
#endif
}
}
void
{
}
void
grub_util_biosdisk_fini (void)
{
unsigned i;
{
}
}
/*
* Note: we do not use the new partition naming scheme as dos_part does not
* necessarily correspond to an msdos partition.
*/
static char *
{
const char *iptr;
+ sizeof (",XXXXXXXXXXXXXXXXXXXXXXXXXX"
",XXXXXXXXXXXXXXXXXXXXXXXXXX"));
+ sizeof (",XXXXXXXXXXXXXXXXXXXXXXXXXX"
",XXXXXXXXXXXXXXXXXXXXXXXXXX"));
{
if (*iptr == ',')
*ptr++ = '\\';
}
*ptr = 0;
if (dos_part >= 0)
if (bsd_part >= 0)
return ret;
}
#ifdef HAVE_DEVICE_MAPPER
static int
{
char *ptr;
if (!dmt)
return 0;
return 0;
if (!dm_task_run(dmt))
return 0;
return 0;
if (grub_errno)
{
return 0;
}
if (*ptr != ':')
return 0;
ptr++;
if (grub_errno)
{
return 0;
}
if (maj)
if (min)
return 1;
}
#endif
static char *
#if defined(__sun__)
convert_system_partition_to_system_disk (const char *os_dev, struct stat *st __attribute__((unused)))
#else
#endif
{
#if defined(__linux__)
return NULL;
{
char *p = path + 5;
/* If this is an IDE disk. */
{
p = strstr (p, "part");
if (p)
strcpy (p, "disc");
return path;
}
/* If this is a SCSI disk. */
{
p = strstr (p, "part");
if (p)
strcpy (p, "disc");
return path;
}
/* If this is a DAC960 disk. */
{
p = strchr (p, 'p');
if (p)
*p = '\0';
return path;
}
/* If this is a Mylex AcceleRAID Array. */
{
p = strchr (p, 'p');
if (p)
*p = '\0';
return path;
}
/* If this is a CCISS disk. */
{
p = strchr (p, 'p');
if (p)
*p = '\0';
return path;
}
/* If this is a Compaq Intelligent Drive Array. */
{
p = strchr (p, 'p');
if (p)
*p = '\0';
return path;
}
/* If this is an I2O disk. */
{
return path;
}
/* If this is a MultiMediaCard (MMC). */
{
p = strchr (p, 'p');
if (p)
*p = '\0';
return path;
}
&& p[2] >= '0' && p[2] <= '9')
{
ptr++;
*ptr = 0;
return path;
}
/* If this is an IDE, SCSI or Virtio disk. */
&& p[5] >= 'a' && p[5] <= 'z')
{
p[6] = '\0';
return path;
}
&& p[2] >= 'a' && p[2] <= 'z')
{
pp++;
/* /dev/[hsv]d[a-z]+[0-9]* */
*pp = '\0';
return path;
}
/* If this is a Xen virtual block device. */
{
pp++;
*pp = '\0';
return path;
}
#ifdef HAVE_DEVICE_MAPPER
/* If this is a DM-RAID device.
Compare os_dev rather than path here, since nodes under
{
void *handle;
tree = dm_tree_create ();
if (! tree)
{
goto devmapper_out;
}
{
goto devmapper_out;
}
if (! node)
{
goto devmapper_out;
}
if (! node_uuid)
{
goto devmapper_out;
}
{
goto devmapper_out;
}
{
/* Multipath partitions have partN-mpath-* UUIDs, and are
linear mappings so are handled by
grub_util_get_dm_node_linear_info. Multipath disks are not
linear mappings and must be handled specially. */
goto devmapper_out;
}
{
const char *node_name;
{
if (tree)
dm_tree_free (tree);
return ret;
}
goto devmapper_out;
}
/* Counter-intuitively, device-mapper refers to the disk-like
device containing a DM-RAID partition device as a "child" of
the partition device. */
if (! child)
{
goto devmapper_out;
}
if (! child_uuid)
{
goto devmapper_out;
}
{
goto devmapper_out;
}
if (! child_name)
{
goto devmapper_out;
}
if (! mapper_name && node)
{
/* This is a DM-RAID disk, not a partition. */
if (! mapper_name)
}
if (tree)
dm_tree_free (tree);
if (mapper_name)
else
return NULL;
}
#endif /* HAVE_DEVICE_MAPPER */
}
return path;
{
if (p)
*p = '\0';
}
return path;
#elif defined(__CYGWIN__)
path[8] = 0;
return path;
return out2;
{
char *p;
for (p = path + 5; *p; ++p)
if (grub_isdigit(*p))
{
p = strpbrk (p, "sp");
if (p)
*p = '\0';
break;
}
}
return path;
#elif defined(__NetBSD__)
/* NetBSD uses "/dev/r[a-z]+[0-9][a-z]". */
{
char *p;
if (grub_isdigit(*p))
{
p++;
if ((*p >= 'a' && *p <= 'z') && (*(p+1) == '\0'))
{
/* path matches the required regular expression and
p points to its last character. */
int rawpart = -1;
# ifdef HAVE_GETRAWPARTITION
rawpart = getrawpartition();
# endif /* HAVE_GETRAWPARTITION */
if (rawpart >= 0)
*p = 'a' + rawpart;
}
}
}
return path;
/* To get the whole disk device from a slice, change the s<N>[<N>] to p0 */
/* For lofi devices, there is no "whole disk" -- it is what it is */
return path;
/* For ramdisk devices, there is no "whole disk" -- it is what it is */
return path;
/* XXX handle floppy, gpt-labeled disks */
{
return (path);
}
{
return (path);
}
{
return (path);
}
else if (len > 3 && grub_isdigit(path[len - 1]) && grub_isdigit(path[len - 2]) && path[len - 3] == 'p')
{
return (path);
}
return (path);
else
{
return (0);
}
#else
# warning "The function `convert_system_partition_to_system_disk' might not work on your OS correctly."
#endif
}
#if defined(__sun__)
static int
{
return 1;
":q,raw", (sizeof (":q,raw") - 1)) == 0)
return 1;
return 0;
}
#endif
#if defined(__linux__) || defined(__CYGWIN__)
static int
{
return 1;
return 0;
}
#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
{
# ifdef HAVE_GETRAWPARTITION
rawpart = getrawpartition();
# endif /* HAVE_GETRAWPARTITION */
if (rawpart < 0)
return 1;
}
#endif /* defined(__NetBSD__) */
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
static int
{
const char *p;
return 0;
if (grub_isdigit (*p))
{
if (strchr (p, 's'))
return 0;
break;
}
return 1;
}
#endif /* defined(__FreeBSD__) || defined(__FreeBSD_kernel__) */
static int
{
unsigned int i;
char *os_disk;
if (convert)
else
if (! os_disk)
return -1;
for (i = 0; i < ARRAY_SIZE (map); i++)
break;
{
return i;
}
if (!add)
{
return -1;
}
if (i == ARRAY_SIZE (map))
grub_util_error (_("device count exceeds limit"));
map[i].device_map = 0;
return i;
}
int
{
return 0;
}
char *
{
int drive;
char *sys_disk;
{
return 0;
}
if (drive < 0)
{
"no mapping exists for `%s'", os_dev);
return 0;
}
sys_disk);
{
}
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__NetBSD__) || defined (__sun__)
#else
#endif
#if defined(__linux__) || defined(__CYGWIN__) || defined(HAVE_DIOCGDINFO) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined (__sun__)
/* Linux counts partitions uniformly, whether a BSD partition or a DOS
partition, so mapping them to GRUB devices is not trivial.
Here, get the start sector of a partition by HDIO_GETGEO, and
compare it with each partition GRUB recognizes.
does not count the extended partition and missing primary
partitions. Use same method as on Linux here.
For NetBSD and FreeBSD, proceed as for Linux, except that the start
sector is obtained from the disk label. */
{
const grub_partition_t partition);
const grub_partition_t partition)
{
grub_util_info ("%s: Partition %d starts from %lu",
if (start == part_start)
{
return 1;
}
return 0;
}
# if !defined(HAVE_DIOCGDINFO) && !defined(__sun__)
return name;
# else /* defined(HAVE_DIOCGDINFO) */
/* Since os_dev and convert_system_partition_to_system_disk (os_dev) are
* different, we know that os_dev cannot be a floppy device. */
# endif /* !defined(HAVE_DIOCGDINFO) */
if (grub_errno != GRUB_ERR_NONE)
{
return 0;
}
return name;
if (! disk)
{
/* We already know that the partition exists. Given that we already
checked the device map above, we can only get
GRUB_ERR_UNKNOWN_DEVICE at this point if the disk does not exist.
This can happen on Xen, where disk images in the host can be
assigned to devices that have partition-like names in the guest
but are really more like disks. */
if (grub_errno == GRUB_ERR_UNKNOWN_DEVICE)
{
("disk does not exist, so falling back to partition device %s",
os_dev);
if (drive < 0)
{
"no mapping exists for `%s'", os_dev);
return 0;
}
}
else
return 0;
}
if (grub_errno != GRUB_ERR_NONE)
{
return 0;
}
{
"cannot find the partition of `%s'", os_dev);
return 0;
}
return name;
}
/* GNU uses "/dev/[hs]d[0-9]+(s[0-9]+[a-z]?)?". */
{
char *p;
int dos_part = -1;
int bsd_part = -1;
if (p)
{
long int n;
char *q;
p++;
n = strtol (p, &q, 10);
if (p != q && n != GRUB_LONG_MIN && n != GRUB_LONG_MAX)
{
dos_part = (int) n - 1;
if (*q >= 'a' && *q <= 'g')
bsd_part = *q - 'a';
}
}
}
{
/* XXX handle floppy, gpt-labeled disks */
{
int fd;
int dos_part = -1;
int slice = -1;
struct extpart_info epartinfo;
const grub_partition_t partition);
const grub_partition_t partition)
{
grub_util_info ("Partition %d starts from %llu%s and is %llu sectors in length",
if (solaris_part_start == part_start &&
{
{
}
else
{
slice = -1;
}
return 1;
}
return 0;
}
return name;
if (fd == -1)
{
return 0;
}
/* Figure out where the slice starts */
{
{
"cannot get slice information for `%s'", os_dev);
return 0;
}
}
else
{
}
grub_util_info("Solaris partition start %llu size %llu",
(unsigned long long)solaris_part_start,
(unsigned long long)solaris_part_len);
/* XXX do we really need solaris_part_start == 0 ? */
return name;
if (! disk) {
return 0;
}
if (grub_errno != GRUB_ERR_NONE)
{
return 0;
}
if (dos_part < 0)
{
"cannot find the partition of `%s'", os_dev);
return 0;
}
if (partition_part)
{
return outbuf;
}
else
{
grub_util_info("Making device name: drive=%d, dos_part=%d, slice=%d",
}
}
else
{
"Cannot handle device `%s'", os_dev);
return 0;
}
}
#else
# warning "The function `grub_util_biosdisk_get_grub_dev' might not work on your OS correctly."
#endif
}
const char *
{
return 0;
}
const char *
{
}
int
{
int fd;
return 0;
/* Shouldn't happen. */
if (fd == -1)
return 0;
/* Shouldn't happen either. */
{
return 0;
}
#if defined(__NetBSD__)
return 1;
#endif
#if defined(FLOPPY_MAJOR)
#else
/* Some kernels (e.g. kFreeBSD) don't have a static major number
for floppies, but they still use a "fd[0-9]" pathname. */
#endif
return 1;
return 0;
}