merge mainline into ahci

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-05-16 17:17:04 +02:00
commit 0670a9751b
385 changed files with 14296 additions and 2152 deletions

View file

@ -127,11 +127,13 @@ struct grub_ahci_device
struct grub_pci_dma_chunk *command_table_chunk;
volatile struct grub_ahci_cmd_table *command_table;
struct grub_pci_dma_chunk *rfis;
int present;
};
static grub_err_t
grub_ahci_readwrite_real (struct grub_ahci_device *dev,
struct grub_disk_ata_pass_through_parms *parms);
struct grub_disk_ata_pass_through_parms *parms,
int spinup);
enum
@ -370,6 +372,7 @@ grub_ahci_pciinit (grub_pci_device_t dev,
adev->hba = hba;
adev->port = i;
adev->present = 1;
adev->num = numdevs++;
if (init_port (adev))
@ -495,7 +498,8 @@ static const int register_map[11] = { 3 /* Features */,
static grub_err_t
grub_ahci_readwrite_real (struct grub_ahci_device *dev,
struct grub_disk_ata_pass_through_parms *parms)
struct grub_disk_ata_pass_through_parms *parms,
int spinup)
{
struct grub_pci_dma_chunk *bufc;
grub_uint64_t endtime;
@ -516,7 +520,7 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev,
break;
}
dev->hba->ports[dev->port].command |= GRUB_AHCI_HBA_PORT_CMD_ST;
endtime = grub_get_time_ms () + 1000;
endtime = grub_get_time_ms () + (spinup ? 10000 : 1000);
while (!(dev->hba->ports[dev->port].command & GRUB_AHCI_HBA_PORT_CMD_CR))
if (grub_get_time_ms () > endtime)
{
@ -606,7 +610,7 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev,
grub_dprintf ("ahci", "AHCI tfd = %x\n",
dev->hba->ports[dev->port].task_file_data);
endtime = grub_get_time_ms () + 1000;
endtime = grub_get_time_ms () + (spinup ? 10000 : 1000);
while ((dev->hba->ports[dev->port].command_issue & 1))
if (grub_get_time_ms () > endtime)
{
@ -656,9 +660,10 @@ grub_ahci_readwrite_real (struct grub_ahci_device *dev,
static grub_err_t
grub_ahci_readwrite (grub_ata_t disk,
struct grub_disk_ata_pass_through_parms *parms)
struct grub_disk_ata_pass_through_parms *parms,
int spinup)
{
return grub_ahci_readwrite_real (disk->data, parms);
return grub_ahci_readwrite_real (disk->data, parms, spinup);
}
static grub_err_t
@ -680,6 +685,7 @@ grub_ahci_open (int id, int devnum, struct grub_ata *ata)
ata->data = dev;
ata->dma = 1;
ata->present = &dev->present;
return GRUB_ERR_NONE;
}

View file

@ -23,6 +23,8 @@
#include <grub/mm.h>
#include <grub/scsi.h>
GRUB_MOD_LICENSE ("GPLv3+");
static grub_ata_dev_t grub_ata_dev_list;
/* Byteorder has to be changed before strings can be read. */
@ -75,13 +77,19 @@ grub_atapi_identify (struct grub_ata *dev)
parms.size = GRUB_DISK_SECTOR_SIZE;
parms.buffer = info;
err = dev->dev->readwrite (dev, &parms);
err = dev->dev->readwrite (dev, &parms, *dev->present);
if (err)
return err;
{
*dev->present = 0;
return err;
}
if (parms.size != GRUB_DISK_SECTOR_SIZE)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"device cannot be identified");
{
*dev->present = 0;
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"device cannot be identified");
}
dev->atapi = 1;
@ -112,7 +120,7 @@ grub_ata_identify (struct grub_ata *dev)
parms.taskfile.cmd = GRUB_ATA_CMD_IDENTIFY_DEVICE;
err = dev->dev->readwrite (dev, &parms);
err = dev->dev->readwrite (dev, &parms, *dev->present);
if (err || parms.size != GRUB_DISK_SECTOR_SIZE)
{
@ -126,13 +134,18 @@ grub_ata_identify (struct grub_ata *dev)
return grub_atapi_identify (dev);
else if (sts == 0x00)
/* No device, return error but don't print message. */
return GRUB_ERR_UNKNOWN_DEVICE;
{
*dev->present = 0;
/* No device, return error but don't print message. */
return GRUB_ERR_UNKNOWN_DEVICE;
}
else
/* Other Error. */
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"device cannot be identified");
{
*dev->present = 0;
/* Other Error. */
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"device cannot be identified");
}
}
/* Now it is certain that this is not an ATAPI device. */
@ -306,7 +319,7 @@ grub_ata_readwrite (grub_disk_t disk, grub_disk_addr_t sector,
if (ata->dma)
parms.dma = 1;
err = ata->dev->readwrite (ata, &parms);
err = ata->dev->readwrite (ata, &parms, 0);
if (err)
return err;
if (parms.size != batch * GRUB_DISK_SECTOR_SIZE)
@ -489,7 +502,7 @@ grub_atapi_read (struct grub_scsi *scsi, grub_size_t cmdsize, char *cmd,
parms.size = size;
parms.buffer = buf;
err = dev->dev->readwrite (dev, &parms);
err = dev->dev->readwrite (dev, &parms, 0);
if (err)
return err;

View file

@ -24,6 +24,8 @@
#include <grub/misc.h>
#include <grub/raid.h>
GRUB_MOD_LICENSE ("GPLv3+");
#define NV_SIGNATURES 4
#define NV_IDLE 0

View file

@ -28,6 +28,8 @@
#include <grub/err.h>
#include <grub/term.h>
GRUB_MOD_LICENSE ("GPLv3+");
static int cd_drive = 0;
static int grub_biosdisk_rw_int13_extensions (int ah, int drive, void *dap);
@ -624,6 +626,11 @@ GRUB_MOD_INIT(biosdisk)
((cdrp->media_type & GRUB_BIOSDISK_CDTYPE_MASK)
== GRUB_BIOSDISK_CDTYPE_NO_EMUL))
cd_drive = cdrp->drive_no;
/* Since diskboot.S rejects devices over 0x90 it must be a CD booted with
cdboot.S
*/
if (grub_boot_drive >= 0x90)
cd_drive = grub_boot_drive;
grub_disk_dev_register (&grub_biosdisk_dev);
}

View file

@ -23,6 +23,8 @@
#include <grub/dl.h>
#include <grub/ieee1275/ieee1275.h>
GRUB_MOD_LICENSE ("GPLv3+");
struct grub_nand_data
{
grub_ieee1275_ihandle_t handle;

View file

@ -62,11 +62,10 @@ ofdisk_hash_find (const char *devpath)
}
static struct ofdisk_hash_ent *
ofdisk_hash_add (char *devpath)
ofdisk_hash_add_real (char *devpath)
{
struct ofdisk_hash_ent *p;
struct ofdisk_hash_ent **head = &ofdisk_hash[ofdisk_hash_fn(devpath)];
struct ofdisk_hash_ent *p, *pcan;
char *curcan;
p = grub_malloc(sizeof (*p));
if (!p)
@ -76,17 +75,27 @@ ofdisk_hash_add (char *devpath)
p->next = *head;
p->shortest = 0;
*head = p;
return p;
}
static struct ofdisk_hash_ent *
ofdisk_hash_add (char *devpath, char *curcan)
{
struct ofdisk_hash_ent *p, *pcan;
p = ofdisk_hash_add_real (devpath);
grub_dprintf ("disk", "devpath = %s, canonical = %s\n", devpath, curcan);
curcan = grub_ieee1275_canonicalise_devname (devpath);
if (!curcan)
{
grub_errno = GRUB_ERR_NONE;
p->shortest = devpath;
return p;
}
pcan = ofdisk_hash_find (curcan);
if (!pcan)
pcan = ofdisk_hash_add (curcan);
pcan = ofdisk_hash_add_real (curcan);
else
grub_free (curcan);
@ -118,17 +127,22 @@ scan (void)
return 0;
grub_dprintf ("disk", "disk name = %s\n", alias->name);
grub_dprintf ("disk", "disk name = %s, path = %s\n", alias->name,
alias->path);
op = ofdisk_hash_find (alias->path);
op = ofdisk_hash_find (alias->name);
if (!op)
{
char *name = grub_strdup (alias->name);
if (!name)
char *can = grub_strdup (alias->path);
if (!name || !can)
{
grub_errno = GRUB_ERR_NONE;
grub_free (name);
grub_free (can);
return 0;
}
op = ofdisk_hash_add (name);
op = ofdisk_hash_add (name, can);
}
return 0;
}
@ -247,7 +261,7 @@ grub_ofdisk_open (const char *name, grub_disk_t disk)
struct ofdisk_hash_ent *op;
op = ofdisk_hash_find (devpath);
if (!op)
op = ofdisk_hash_add (devpath);
op = ofdisk_hash_add (devpath, NULL);
else
grub_free (devpath);
if (!op)

View file

@ -25,6 +25,8 @@
#include <grub/extcmd.h>
#include <grub/i18n.h>
GRUB_MOD_LICENSE ("GPLv3+");
struct grub_loopback
{
char *devname;
@ -97,10 +99,6 @@ grub_cmd_loopback (grub_extcmd_context_t ctxt, int argc, char **args)
if (newdev)
{
char *newname = grub_strdup (args[1]);
if (! newname)
goto fail;
grub_file_close (newdev->file);
newdev->file = file;
@ -166,7 +164,7 @@ grub_loopback_open (const char *name, grub_disk_t disk)
disk->total_sectors = GRUB_DISK_SIZE_UNKNOWN;
disk->id = (unsigned long) dev;
disk->data = dev->file;
disk->data = dev;
return 0;
}
@ -175,7 +173,7 @@ static grub_err_t
grub_loopback_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf)
{
grub_file_t file = (grub_file_t) disk->data;
grub_file_t file = ((struct grub_loopback *) disk->data)->file;
grub_off_t pos;
grub_file_seek (file, sector << GRUB_DISK_SECTOR_BITS);
@ -222,7 +220,7 @@ static grub_extcmd_t cmd;
GRUB_MOD_INIT(loopback)
{
cmd = grub_register_extcmd ("loopback", grub_cmd_loopback, 0,
N_("[-d|-p] DEVICENAME FILE."),
N_("[-d] DEVICENAME FILE."),
N_("Make a device of a file."), options);
grub_disk_dev_register (&grub_loopback_dev);
}

View file

@ -28,6 +28,8 @@
#include <grub/emu/misc.h>
#endif
GRUB_MOD_LICENSE ("GPLv3+");
static struct grub_lvm_vg *vg_list;
static int lv_count;
@ -45,6 +47,7 @@ grub_lvm_getvalue (char **p, char *str)
return grub_strtoul (*p, NULL, 10);
}
#if 0
static int
grub_lvm_checkvalue (char **p, char *str, char *tmpl)
{
@ -57,6 +60,7 @@ grub_lvm_checkvalue (char **p, char *str, char *tmpl)
return 0;
return (grub_memcmp (*p + 1, tmpl, tmpllen) == 0 && (*p)[tmpllen + 1] == '"');
}
#endif
static int
grub_lvm_check_flag (char *p, char *str, char *flag)
@ -100,7 +104,7 @@ grub_lvm_iterate (int (*hook) (const char *name))
struct grub_lvm_lv *lv;
if (vg->lvs)
for (lv = vg->lvs; lv; lv = lv->next)
if (hook (lv->name))
if (lv->visible && hook (lv->name))
return 1;
}
@ -164,18 +168,45 @@ grub_lvm_close (grub_disk_t disk __attribute ((unused)))
}
static grub_err_t
grub_lvm_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf)
read_lv (struct grub_lvm_lv *lv, grub_disk_addr_t sector,
grub_size_t size, char *buf);
static grub_err_t
read_node (const struct grub_lvm_node *node, grub_disk_addr_t sector,
grub_size_t size, char *buf)
{
/* Check whether we actually know the physical volume we want to
read from. */
if (node->pv)
{
if (node->pv->disk)
return grub_disk_read (node->pv->disk, sector + node->pv->start, 0,
size << GRUB_DISK_SECTOR_BITS, buf);
else
return grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"physical volume %s not found", node->pv->name);
}
if (node->lv)
return read_lv (node->lv, sector, size, buf);
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown node '%s'", node->name);
}
static grub_err_t
read_lv (struct grub_lvm_lv *lv, grub_disk_addr_t sector,
grub_size_t size, char *buf)
{
grub_err_t err = 0;
struct grub_lvm_lv *lv = disk->data;
struct grub_lvm_vg *vg = lv->vg;
struct grub_lvm_segment *seg = lv->segments;
struct grub_lvm_pv *pv;
struct grub_lvm_node *node;
grub_uint64_t offset;
grub_uint64_t extent;
unsigned int i;
if (!lv)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown volume");
extent = grub_divmod64 (sector, vg->extent_size, NULL);
/* Find the right segment. */
@ -190,59 +221,75 @@ grub_lvm_read (grub_disk_t disk, grub_disk_addr_t sector,
seg++;
}
if (seg->stripe_count == 1)
if (i == lv->segment_count)
return grub_error (GRUB_ERR_READ_ERROR, "incorrect segment");
switch (seg->type)
{
/* This segment is linear, so that's easy. We just need to find
out the offset in the physical volume and read SIZE bytes
from that. */
struct grub_lvm_stripe *stripe = seg->stripes;
grub_uint64_t seg_offset; /* Offset of the segment in PV device. */
case GRUB_LVM_STRIPED:
if (seg->node_count == 1)
{
/* This segment is linear, so that's easy. We just need to find
out the offset in the physical volume and read SIZE bytes
from that. */
struct grub_lvm_node *stripe = seg->nodes;
grub_uint64_t seg_offset; /* Offset of the segment in PV device. */
pv = stripe->pv;
seg_offset = ((grub_uint64_t) stripe->start
* (grub_uint64_t) vg->extent_size) + pv->start;
node = stripe;
seg_offset = ((grub_uint64_t) stripe->start
* (grub_uint64_t) vg->extent_size);
offset = sector - ((grub_uint64_t) seg->start_extent
* (grub_uint64_t) vg->extent_size) + seg_offset;
offset = sector - ((grub_uint64_t) seg->start_extent
* (grub_uint64_t) vg->extent_size) + seg_offset;
}
else
{
/* This is a striped segment. We have to find the right PV
similar to RAID0. */
struct grub_lvm_node *stripe = seg->nodes;
grub_uint32_t a, b;
grub_uint64_t seg_offset; /* Offset of the segment in PV device. */
unsigned int stripenr;
offset = sector - ((grub_uint64_t) seg->start_extent
* (grub_uint64_t) vg->extent_size);
a = grub_divmod64 (offset, seg->stripe_size, NULL);
grub_divmod64 (a, seg->node_count, &stripenr);
a = grub_divmod64 (offset, seg->stripe_size * seg->node_count, NULL);
grub_divmod64 (offset, seg->stripe_size, &b);
offset = a * seg->stripe_size + b;
stripe += stripenr;
node = stripe;
seg_offset = ((grub_uint64_t) stripe->start
* (grub_uint64_t) vg->extent_size);
offset += seg_offset;
}
return read_node (node, offset, size, buf);
case GRUB_LVM_MIRROR:
i = 0;
while (1)
{
err = read_node (&seg->nodes[i], sector, size, buf);
if (!err)
return err;
if (++i >= seg->node_count)
return err;
grub_errno = GRUB_ERR_NONE;
}
}
else
{
/* This is a striped segment. We have to find the right PV
similar to RAID0. */
struct grub_lvm_stripe *stripe = seg->stripes;
grub_uint32_t a, b;
grub_uint64_t seg_offset; /* Offset of the segment in PV device. */
unsigned int stripenr;
return grub_error (GRUB_ERR_IO, "unknown LVM segment");
}
offset = sector - ((grub_uint64_t) seg->start_extent
* (grub_uint64_t) vg->extent_size);
a = grub_divmod64 (offset, seg->stripe_size, NULL);
grub_divmod64 (a, seg->stripe_count, &stripenr);
a = grub_divmod64 (offset, seg->stripe_size * seg->stripe_count, NULL);
grub_divmod64 (offset, seg->stripe_size, &b);
offset = a * seg->stripe_size + b;
stripe += stripenr;
pv = stripe->pv;
seg_offset = ((grub_uint64_t) stripe->start
* (grub_uint64_t) vg->extent_size) + pv->start;
offset += seg_offset;
}
/* Check whether we actually know the physical volume we want to
read from. */
if (pv->disk)
err = grub_disk_read (pv->disk, offset, 0,
size << GRUB_DISK_SECTOR_BITS, buf);
else
err = grub_error (GRUB_ERR_UNKNOWN_DEVICE,
"physical volume %s not found", pv->name);
return err;
static grub_err_t
grub_lvm_read (grub_disk_t disk, grub_disk_addr_t sector,
grub_size_t size, char *buf)
{
return read_lv (disk->data, sector, size, buf);
}
static grub_err_t
@ -303,7 +350,7 @@ grub_lvm_scan_device (const char *name)
if (i == GRUB_LVM_LABEL_SCAN_SECTORS)
{
#ifdef GRUB_UTIL
grub_util_info ("no LVM signature found\n");
grub_util_info ("no LVM signature found");
#endif
goto fail;
}
@ -511,6 +558,7 @@ grub_lvm_scan_device (const char *name)
int skip_lv = 0;
struct grub_lvm_lv *lv;
struct grub_lvm_segment *seg;
int is_pvmove;
while (grub_isspace (*p))
p++;
@ -533,11 +581,8 @@ grub_lvm_scan_device (const char *name)
lv->size = 0;
if (!grub_lvm_check_flag (p, "status", "VISIBLE"))
{
skip_lv = 1;
goto lv_parsed;
}
lv->visible = grub_lvm_check_flag (p, "status", "VISIBLE");
is_pvmove = grub_lvm_check_flag (p, "status", "PVMOVE");
lv->segment_count = grub_lvm_getvalue (&p, "segment_count = ");
if (p == NULL)
@ -552,7 +597,6 @@ grub_lvm_scan_device (const char *name)
for (i = 0; i < lv->segment_count; i++)
{
struct grub_lvm_stripe *stripe;
p = grub_strstr (p, "segment");
if (p == NULL)
@ -580,90 +624,147 @@ grub_lvm_scan_device (const char *name)
goto lvs_segment_fail;
}
if (grub_lvm_checkvalue (&p, "type = ", "snapshot"))
{
/* Found a snapshot, give up and move on. */
skip_lv = 1;
break;
}
seg->stripe_count = grub_lvm_getvalue (&p, "stripe_count = ");
p = grub_strstr (p, "type = \"");
if (p == NULL)
{
#ifdef GRUB_UTIL
grub_util_info ("unknown stripe_count\n");
#endif
goto lvs_segment_fail;
}
goto lvs_segment_fail;
p += sizeof("type = \"") - 1;
lv->size += seg->extent_count * vg->extent_size;
if (seg->stripe_count != 1)
seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = ");
if (grub_memcmp (p, "striped\"",
sizeof ("striped\"") - 1) == 0)
{
struct grub_lvm_node *stripe;
seg->stripes = grub_malloc (sizeof (*stripe)
* seg->stripe_count);
stripe = seg->stripes;
seg->type = GRUB_LVM_STRIPED;
seg->node_count = grub_lvm_getvalue (&p, "stripe_count = ");
if (p == NULL)
{
#ifdef GRUB_UTIL
grub_util_info ("unknown stripe_count\n");
#endif
goto lvs_segment_fail;
}
p = grub_strstr (p, "stripes = [");
if (p == NULL)
if (seg->node_count != 1)
seg->stripe_size = grub_lvm_getvalue (&p, "stripe_size = ");
seg->nodes = grub_zalloc (sizeof (*stripe)
* seg->node_count);
stripe = seg->nodes;
p = grub_strstr (p, "stripes = [");
if (p == NULL)
{
#ifdef GRUB_UTIL
grub_util_info ("unknown stripes\n");
#endif
goto lvs_segment_fail2;
}
p += sizeof("stripes = [") - 1;
for (j = 0; j < seg->node_count; j++)
{
p = grub_strchr (p, '"');
if (p == NULL)
continue;
q = ++p;
while (*q != '"')
q++;
s = q - p;
stripe->name = grub_malloc (s + 1);
if (stripe->name == NULL)
goto lvs_segment_fail2;
grub_memcpy (stripe->name, p, s);
stripe->name[s] = '\0';
stripe->start = grub_lvm_getvalue (&p, ",");
if (p == NULL)
continue;
stripe++;
}
}
else if (grub_memcmp (p, "mirror\"", sizeof ("mirror\"") - 1)
== 0)
{
seg->type = GRUB_LVM_MIRROR;
seg->node_count = grub_lvm_getvalue (&p, "mirror_count = ");
if (p == NULL)
{
#ifdef GRUB_UTIL
grub_util_info ("unknown mirror_count\n");
#endif
goto lvs_segment_fail;
}
seg->nodes = grub_zalloc (sizeof (seg->nodes[0])
* seg->node_count);
p = grub_strstr (p, "mirrors = [");
if (p == NULL)
{
#ifdef GRUB_UTIL
grub_util_info ("unknown mirrors\n");
#endif
goto lvs_segment_fail2;
}
p += sizeof("mirrors = [") - 1;
for (j = 0; j < seg->node_count; j++)
{
char *lvname;
p = grub_strchr (p, '"');
if (p == NULL)
continue;
q = ++p;
while (*q != '"')
q++;
s = q - p;
lvname = grub_malloc (s + 1);
if (lvname == NULL)
goto lvs_segment_fail2;
grub_memcpy (lvname, p, s);
lvname[s] = '\0';
seg->nodes[j].name = lvname;
p = q + 1;
}
/* Only first (original) is ok with in progress pvmove. */
if (is_pvmove)
seg->node_count = 1;
}
else
{
#ifdef GRUB_UTIL
grub_util_info ("unknown stripes\n");
char *p2;
p2 = grub_strchr (p, '"');
if (p2)
*p2 = 0;
grub_util_info ("unknown LVM type %s\n", p);
if (p2)
*p2 ='"';
#endif
goto lvs_segment_fail2;
}
p += sizeof("stripes = [") - 1;
for (j = 0; j < seg->stripe_count; j++)
{
char *pvname;
p = grub_strchr (p, '"');
if (p == NULL)
continue;
q = ++p;
while (*q != '"')
q++;
s = q - p;
pvname = grub_malloc (s + 1);
if (pvname == NULL)
goto lvs_segment_fail2;
grub_memcpy (pvname, p, s);
pvname[s] = '\0';
if (vg->pvs)
for (pv = vg->pvs; pv; pv = pv->next)
{
if (! grub_strcmp (pvname, pv->name))
{
stripe->pv = pv;
break;
}
}
grub_free(pvname);
stripe->start = grub_lvm_getvalue (&p, ",");
if (p == NULL)
continue;
stripe++;
/* Found a non-supported type, give up and move on. */
skip_lv = 1;
break;
}
seg++;
continue;
lvs_segment_fail2:
grub_free (seg->stripes);
grub_free (seg->nodes);
lvs_segment_fail:
goto fail4;
}
lv_parsed:
if (p != NULL)
p = grub_strchr (p, '}');
if (p == NULL)
@ -690,6 +791,33 @@ grub_lvm_scan_device (const char *name)
}
}
/* Match lvs. */
{
struct grub_lvm_lv *lv1;
struct grub_lvm_lv *lv2;
for (lv1 = vg->lvs; lv1; lv1 = lv1->next)
for (i = 0; i < lv1->segment_count; i++)
for (j = 0; j < lv1->segments[i].node_count; j++)
{
if (vg->pvs)
for (pv = vg->pvs; pv; pv = pv->next)
{
if (! grub_strcmp (pv->name,
lv1->segments[i].nodes[j].name))
{
lv1->segments[i].nodes[j].pv = pv;
break;
}
}
if (lv1->segments[i].nodes[j].pv == NULL)
for (lv2 = vg->lvs; lv2; lv2 = lv2->next)
if (grub_strcmp (lv2->name + grub_strlen (vg->name) + 1,
lv1->segments[i].nodes[j].name) == 0)
lv1->segments[i].nodes[j].lv = lv2;
}
}
vg->next = vg_list;
vg_list = vg;
}
@ -728,6 +856,7 @@ grub_lvm_scan_device (const char *name)
grub_disk_close (disk);
if (grub_errno == GRUB_ERR_OUT_OF_RANGE)
grub_errno = GRUB_ERR_NONE;
grub_print_error ();
return 0;
}

View file

@ -24,6 +24,8 @@
#include <grub/misc.h>
#include <grub/raid.h>
GRUB_MOD_LICENSE ("GPLv3+");
/* Linux RAID on disk structures and constants,
copied from include/linux/raid/md_p.h. */
@ -110,7 +112,6 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
struct grub_raid_super_1x sb;
grub_uint8_t minor_version;
/* The sector where the mdraid 0.90 superblock is stored, if available. */
size = grub_disk_get_size (disk);
/* Check for an 1.x superblock.
@ -143,24 +144,28 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
&sb))
return grub_errno;
if (sb.magic != SB_MAGIC)
if (grub_le_to_cpu32 (sb.magic) != SB_MAGIC
|| grub_le_to_cpu64 (sb.super_offset) != sector)
continue;
{
grub_uint64_t sb_size;
struct grub_raid_super_1x *real_sb;
grub_uint32_t level;
if (sb.major_version != 1)
if (grub_le_to_cpu32 (sb.major_version) != 1)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"Unsupported RAID version: %d",
sb.major_version);
grub_le_to_cpu32 (sb.major_version));
level = grub_le_to_cpu32 (sb.level);
/* Multipath. */
if ((int) sb.level == -4)
sb.level = 1;
if ((int) level == -4)
level = 1;
if (sb.level != 0 && sb.level != 1 && sb.level != 4 &&
sb.level != 5 && sb.level != 6 && sb.level != 10)
if (level != 0 && level != 1 && level != 4 &&
level != 5 && level != 6 && level != 10)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"Unsupported RAID level: %d", sb.level);
@ -189,16 +194,22 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
array->level = grub_le_to_cpu32 (real_sb->level);
array->layout = grub_le_to_cpu32 (real_sb->layout);
array->total_devs = grub_le_to_cpu32 (real_sb->raid_disks);
array->disk_size = grub_le_to_cpu64 (real_sb->size);
if (real_sb->size)
array->disk_size = grub_le_to_cpu64 (real_sb->size);
else
array->disk_size = grub_le_to_cpu64 (real_sb->data_size);
array->chunk_size = grub_le_to_cpu32 (real_sb->chunksize);
if (grub_le_to_cpu32 (real_sb->dev_number) >=
grub_le_to_cpu32 (real_sb->max_dev))
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
return grub_error (GRUB_ERR_OUT_OF_RANGE,
"spares aren't implemented");
array->index = grub_le_to_cpu16
(real_sb->dev_roles[grub_le_to_cpu32 (real_sb->dev_number)]);
if (array->index >= array->total_devs)
return grub_error (GRUB_ERR_OUT_OF_RANGE,
"spares aren't implemented");
array->uuid_len = 16;
array->uuid = grub_malloc (16);
if (!array->uuid)
@ -209,7 +220,7 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
grub_memcpy (array->uuid, real_sb->set_uuid, 16);
*start_sector = real_sb->data_offset;
*start_sector = grub_le_to_cpu64 (real_sb->data_offset);
grub_free (real_sb);
return 0;

View file

@ -27,6 +27,8 @@
/* Linux RAID on disk structures and constants,
copied from include/linux/raid/md_p.h. */
GRUB_MOD_LICENSE ("GPLv3+");
#define RESERVED_BYTES (64 * 1024)
#define RESERVED_SECTORS (RESERVED_BYTES / 512)
@ -167,6 +169,7 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
grub_uint64_t size;
struct grub_raid_super_09 sb;
grub_uint32_t *uuid;
grub_uint32_t level;
/* The sector where the mdraid 0.90 superblock is stored, if available. */
size = grub_disk_get_size (disk);
@ -178,46 +181,50 @@ grub_mdraid_detect (grub_disk_t disk, struct grub_raid_array *array,
return grub_errno;
/* Look whether there is a mdraid 0.90 superblock. */
if (sb.md_magic != SB_MAGIC)
if (grub_le_to_cpu32 (sb.md_magic) != SB_MAGIC)
return grub_error (GRUB_ERR_OUT_OF_RANGE, "not 0.9x raid");
if (sb.major_version != 0 || sb.minor_version != 90)
if (grub_le_to_cpu32 (sb.major_version) != 0
|| grub_le_to_cpu32 (sb.minor_version) != 90)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unsupported RAID version: %d.%d",
sb.major_version, sb.minor_version);
grub_le_to_cpu32 (sb.major_version),
grub_le_to_cpu32 (sb.minor_version));
/* FIXME: Check the checksum. */
level = grub_le_to_cpu32 (sb.level);
/* Multipath. */
if ((int) sb.level == -4)
sb.level = 1;
if ((int) level == -4)
level = 1;
if (sb.level != 0 && sb.level != 1 && sb.level != 4 &&
sb.level != 5 && sb.level != 6 && sb.level != 10)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unsupported RAID level: %d", sb.level);
if (sb.this_disk.number == 0xffff || sb.this_disk.number == 0xfffe)
if (level != 0 && level != 1 && level != 4 &&
level != 5 && level != 6 && level != 10)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unsupported RAID level: %d", level);
if (grub_le_to_cpu32 (sb.this_disk.number) == 0xffff
|| grub_le_to_cpu32 (sb.this_disk.number) == 0xfffe)
return grub_error (GRUB_ERR_OUT_OF_RANGE,
"spares aren't implemented");
array->name = NULL;
array->number = sb.md_minor;
array->level = sb.level;
array->layout = sb.layout;
array->total_devs = sb.raid_disks;
array->disk_size = (sb.size) ? sb.size * 2 : sector;
array->chunk_size = sb.chunk_size >> 9;
array->index = sb.this_disk.number;
array->number = grub_le_to_cpu32 (sb.md_minor);
array->level = level;
array->layout = grub_le_to_cpu32 (sb.layout);
array->total_devs = grub_le_to_cpu32 (sb.raid_disks);
array->disk_size = (sb.size) ? grub_le_to_cpu32 (sb.size) * 2 : sector;
array->chunk_size = grub_le_to_cpu32 (sb.chunk_size) >> 9;
array->index = grub_le_to_cpu32 (sb.this_disk.number);
array->uuid_len = 16;
array->uuid = grub_malloc (16);
if (!array->uuid)
return grub_errno;
uuid = (grub_uint32_t *) array->uuid;
uuid[0] = sb.set_uuid0;
uuid[1] = sb.set_uuid1;
uuid[2] = sb.set_uuid2;
uuid[3] = sb.set_uuid3;
uuid[0] = grub_swap_bytes32 (sb.set_uuid0);
uuid[1] = grub_swap_bytes32 (sb.set_uuid1);
uuid[2] = grub_swap_bytes32 (sb.set_uuid2);
uuid[3] = grub_swap_bytes32 (sb.set_uuid3);
*start_sector = 0;

View file

@ -24,6 +24,8 @@
#include <grub/mm.h>
#include <grub/types.h>
GRUB_MOD_LICENSE ("GPLv3+");
static char *memdisk_addr;
static grub_off_t memdisk_size = 0;

View file

@ -26,6 +26,8 @@
#include <grub/cs5536.h>
#include <grub/time.h>
GRUB_MOD_LICENSE ("GPLv3+");
/* At the moment, only two IDE ports are supported. */
static const grub_port_t grub_pata_ioaddress[] = { GRUB_ATA_CH0_PORT1,
GRUB_ATA_CH1_PORT1 };
@ -44,6 +46,8 @@ struct grub_pata_device
(commonly known as "slave"). */
int device;
int present;
struct grub_pata_device *next;
};
@ -90,10 +94,11 @@ grub_pata_wait_not_busy (struct grub_pata_device *dev, int milliseconds)
}
static inline grub_err_t
grub_pata_check_ready (struct grub_pata_device *dev)
grub_pata_check_ready (struct grub_pata_device *dev, int spinup)
{
if (grub_pata_regget (dev, GRUB_ATA_REG_STATUS) & GRUB_ATA_STATUS_BUSY)
return grub_pata_wait_not_busy (dev, GRUB_ATA_TOUT_STD);
return grub_pata_wait_not_busy (dev, spinup ? GRUB_ATA_TOUT_SPINUP
: GRUB_ATA_TOUT_STD);
return GRUB_ERR_NONE;
}
@ -132,10 +137,12 @@ grub_pata_pio_write (struct grub_pata_device *dev, char *buf, grub_size_t size)
/* ATA pass through support, used by hdparm.mod. */
static grub_err_t
grub_pata_readwrite (struct grub_ata *disk,
struct grub_disk_ata_pass_through_parms *parms)
struct grub_disk_ata_pass_through_parms *parms,
int spinup)
{
struct grub_pata_device *dev = (struct grub_pata_device *) disk->data;
grub_size_t nread = 0;
int i;
if (! (parms->cmdsize == 0 || parms->cmdsize == 12))
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
@ -153,10 +160,9 @@ grub_pata_readwrite (struct grub_ata *disk,
/* Set registers. */
grub_pata_regset (dev, GRUB_ATA_REG_DISK, (dev->device << 4)
| (parms->taskfile.disk & 0xef));
if (grub_pata_check_ready (dev))
if (grub_pata_check_ready (dev, spinup))
return grub_errno;
int i;
for (i = GRUB_ATA_REG_SECTORS; i <= GRUB_ATA_REG_LBAHIGH; i++)
grub_pata_regset (dev, i,
parms->taskfile.raw[7 + (i - GRUB_ATA_REG_SECTORS)]);
@ -299,6 +305,7 @@ grub_pata_device_initialize (int port, int device, int addr)
dev->port = port;
dev->device = device;
dev->ioaddress = addr + GRUB_MACHINE_PCI_IO_BASE;
dev->present = 1;
dev->next = NULL;
/* Register the device. */
@ -454,6 +461,7 @@ grub_pata_open (int id, int devnum, struct grub_ata *ata)
ata->data = devfnd;
ata->dma = 0;
ata->present = &devfnd->present;
return GRUB_ERR_NONE;
}

View file

@ -23,6 +23,11 @@
#include <grub/err.h>
#include <grub/misc.h>
#include <grub/raid.h>
#ifdef GRUB_UTIL
#include <grub/util/misc.h>
#endif
GRUB_MOD_LICENSE ("GPLv3+");
/* Linked list of RAID arrays. */
static struct grub_raid_array *array_list;
@ -117,18 +122,49 @@ grub_raid_getname (struct grub_disk *disk)
}
#endif
static inline int
ascii2hex (char c)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
return 0;
}
static grub_err_t
grub_raid_open (const char *name, grub_disk_t disk)
{
struct grub_raid_array *array;
unsigned n;
for (array = array_list; array != NULL; array = array->next)
if (grub_memcmp (name, "mduuid/", sizeof ("mduuid/") - 1) == 0)
{
if (!grub_strcmp (array->name, name))
if (grub_is_array_readable (array))
break;
const char *uuidstr = name + sizeof ("mduuid/") - 1;
grub_size_t uuid_len = grub_strlen (uuidstr) / 2;
grub_uint8_t uuidbin[uuid_len];
unsigned i;
for (i = 0; i < uuid_len; i++)
uuidbin[i] = ascii2hex (uuidstr[2 * i + 1])
| (ascii2hex (uuidstr[2 * i]) << 4);
for (array = array_list; array != NULL; array = array->next)
{
if (uuid_len == (unsigned) array->uuid_len
&& grub_memcmp (uuidbin, array->uuid, uuid_len) == 0)
if (grub_is_array_readable (array))
break;
}
}
else
for (array = array_list; array != NULL; array = array->next)
{
if (!grub_strcmp (array->name, name))
if (grub_is_array_readable (array))
break;
}
if (!array)
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "unknown RAID device %s",
@ -530,8 +566,8 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
/* We found multiple devices with the same number. Again,
this shouldn't happen. */
return grub_error (GRUB_ERR_BAD_DEVICE,
"found two disks with the number %d",
new_array->number);
"found two disks with the index %d for RAID %s",
new_array->index, array->name);
if (new_array->disk_size < array->disk_size)
array->disk_size = new_array->disk_size;
@ -570,7 +606,7 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
{
for (p = array_list; p != NULL; p = p->next)
{
if (! p->name && p->number == array->number)
if (p->number == array->number)
break;
}
}
@ -638,6 +674,10 @@ insert_array (grub_disk_t disk, struct grub_raid_array *new_array,
grub_dprintf ("raid", "Found array %s (%s)\n", array->name,
scanner_name);
#ifdef GRUB_UTIL
grub_util_info ("Found array %s (%s)", array->name,
scanner_name);
#endif
/* Add our new array to the list. */
array->next = array_list;
@ -696,7 +736,12 @@ grub_raid_register (grub_raid_t raid)
struct grub_raid_array array;
grub_disk_addr_t start_sector;
grub_dprintf ("raid", "Scanning for RAID devices on disk %s\n", name);
grub_dprintf ("raid", "Scanning for %s RAID devices on disk %s\n",
grub_raid_list->name, name);
#ifdef GRUB_UTIL
grub_util_info ("Scanning for %s RAID devices on disk %s",
grub_raid_list->name, name);
#endif
disk = grub_disk_open (name);
if (!disk)

View file

@ -24,6 +24,8 @@
#include <grub/misc.h>
#include <grub/raid.h>
GRUB_MOD_LICENSE ("GPLv3+");
static grub_err_t
grub_raid5_recover (struct grub_raid_array *array, int disknr,
char *buf, grub_disk_addr_t sector, int size)
@ -45,7 +47,9 @@ grub_raid5_recover (struct grub_raid_array *array, int disknr,
if (i == disknr)
continue;
err = grub_disk_read (array->members[i].device, sector, 0, size, buf2);
err = grub_disk_read (array->members[i].device,
array->members[i].start_sector + sector,
0, size, buf2);
if (err)
{

View file

@ -24,6 +24,8 @@
#include <grub/misc.h>
#include <grub/raid.h>
GRUB_MOD_LICENSE ("GPLv3+");
static grub_uint8_t raid6_table1[256][256];
static grub_uint8_t raid6_table2[256][256];
@ -119,7 +121,8 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
else
{
if ((array->members[pos].device) &&
(! grub_disk_read (array->members[pos].device, sector,
(! grub_disk_read (array->members[pos].device,
array->members[i].start_sector + sector,
0, size, buf)))
{
grub_raid_block_xor (pbuf, buf, size);
@ -150,7 +153,9 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
{
/* One bad device */
if ((array->members[p].device) &&
(! grub_disk_read (array->members[p].device, sector, 0, size, buf)))
(! grub_disk_read (array->members[p].device,
array->members[i].start_sector + sector,
0, size, buf)))
{
grub_raid_block_xor (buf, pbuf, size);
goto quit;
@ -163,7 +168,8 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
}
grub_errno = GRUB_ERR_NONE;
if (grub_disk_read (array->members[q].device, sector, 0, size, buf))
if (grub_disk_read (array->members[q].device,
array->members[i].start_sector + sector, 0, size, buf))
goto quit;
grub_raid_block_xor (buf, qbuf, size);
@ -181,12 +187,16 @@ grub_raid6_recover (struct grub_raid_array *array, int disknr, int p,
goto quit;
}
if (grub_disk_read (array->members[p].device, sector, 0, size, buf))
if (grub_disk_read (array->members[p].device,
array->members[i].start_sector + sector,
0, size, buf))
goto quit;
grub_raid_block_xor (pbuf, buf, size);
if (grub_disk_read (array->members[q].device, sector, 0, size, buf))
if (grub_disk_read (array->members[q].device,
array->members[i].start_sector + sector,
0, size, buf))
goto quit;
grub_raid_block_xor (qbuf, buf, size);

View file

@ -27,6 +27,8 @@
#include <grub/scsicmd.h>
#include <grub/time.h>
GRUB_MOD_LICENSE ("GPLv3+");
static grub_scsi_dev_t grub_scsi_dev_list;
@ -522,7 +524,7 @@ grub_scsi_read (grub_disk_t disk, grub_disk_addr_t sector,
if (scsi->blocksize != GRUB_DISK_SECTOR_SIZE)
{
unsigned spb = scsi->blocksize >> GRUB_DISK_SECTOR_BITS;
if (! (spb != 0 && (scsi->blocksize & GRUB_DISK_SECTOR_SIZE) == 0))
if (spb == 0 || (scsi->blocksize & (GRUB_DISK_SECTOR_SIZE - 1)) != 0)
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"unsupported SCSI block size");

View file

@ -24,6 +24,8 @@
#include <grub/scsicmd.h>
#include <grub/misc.h>
GRUB_MOD_LICENSE ("GPLv3+");
#define GRUB_USBMS_DIRECTION_BIT 7
/* The USB Mass Storage Command Block Wrapper. */
@ -70,7 +72,11 @@ static int first_available_slot = 0;
static grub_err_t
grub_usbms_reset (grub_usb_device_t dev, int interface)
{
return grub_usb_control_msg (dev, 0x21, 255, 0, interface, 0, 0);
grub_usb_err_t u;
u = grub_usb_control_msg (dev, 0x21, 255, 0, interface, 0, 0);
if (u)
return grub_error (GRUB_ERR_IO, "USB error %d", u);
return GRUB_ERR_NONE;
}
static void
@ -410,7 +416,7 @@ static struct grub_scsi_dev grub_usbms_dev =
.write = grub_usbms_write
};
struct grub_usb_attach_desc attach_hook =
static struct grub_usb_attach_desc attach_hook =
{
.class = GRUB_USB_CLASS_MASS_STORAGE,
.hook = grub_usbms_attach