Page MenuHomeFreeBSD

D8594.id24643.diff
No OneTemporary

D8594.id24643.diff

Index: sys/boot/common/disk.c
===================================================================
--- sys/boot/common/disk.c
+++ sys/boot/common/disk.c
@@ -46,6 +46,7 @@
struct open_disk {
struct ptable *table;
uint64_t mediasize;
+ uint64_t entrysize;
u_int sectorsize;
u_int flags;
int rcnt;
@@ -264,13 +265,28 @@
}
int
-disk_ioctl(struct disk_devdesc *dev, u_long cmd, void *buf)
+disk_ioctl(struct disk_devdesc *dev, u_long cmd, void *data)
{
+ struct open_disk *od = dev->d_opendata;
- if (dev->d_dev->dv_ioctl)
- return ((*dev->d_dev->dv_ioctl)(dev->d_opendata, cmd, buf));
+ if (od == NULL)
+ return (ENOTTY);
- return (ENXIO);
+ switch (cmd) {
+ case DIOCGSECTORSIZE:
+ *(u_int *)data = od->sectorsize;
+ break;
+ case DIOCGMEDIASIZE:
+ if (dev->d_offset == 0)
+ *(uint64_t *)data = od->mediasize;
+ else
+ *(uint64_t *)data = od->entrysize * od->sectorsize;
+ break;
+ default:
+ return (ENOTTY);
+ }
+
+ return (0);
}
int
@@ -315,6 +331,7 @@
}
dev->d_opendata = od;
od->rcnt = 0;
+ od->entrysize = 0;
}
od->mediasize = mediasize;
od->sectorsize = sectorsize;
@@ -330,14 +347,24 @@
rc = ENXIO;
goto out;
}
+
+ if (ptable_getsize(od->table, &mediasize) != 0) {
+ rc = ENXIO;
+ goto out;
+ }
+ if (mediasize > od->mediasize) {
+ od->mediasize = mediasize;
+ }
opened:
rc = 0;
if (ptable_gettype(od->table) == PTABLE_BSD &&
partition >= 0) {
/* It doesn't matter what value has d_slice */
rc = ptable_getpart(od->table, &part, partition);
- if (rc == 0)
+ if (rc == 0) {
dev->d_offset = part.start;
+ od->entrysize = part.end - part.start + 1;
+ }
} else if (slice >= 0) {
/* Try to get information about partition */
if (slice == 0)
@@ -347,6 +374,7 @@
if (rc != 0) /* Partition doesn't exist */
goto out;
dev->d_offset = part.start;
+ od->entrysize = part.end - part.start + 1;
slice = part.index;
if (ptable_gettype(od->table) == PTABLE_GPT) {
partition = 255;
@@ -389,6 +417,7 @@
if (rc != 0)
goto out;
dev->d_offset += part.start;
+ od->entrysize = part.end - part.start + 1;
}
out:
if (table != NULL)
Index: sys/boot/common/part.h
===================================================================
--- sys/boot/common/part.h
+++ sys/boot/common/part.h
@@ -70,6 +70,7 @@
diskread_t *dread);
void ptable_close(struct ptable *table);
enum ptable_type ptable_gettype(const struct ptable *table);
+int ptable_getsize(const struct ptable *table, uint64_t *sizep);
int ptable_getpart(const struct ptable *table, struct ptable_entry *part,
int index);
Index: sys/boot/common/part.c
===================================================================
--- sys/boot/common/part.c
+++ sys/boot/common/part.c
@@ -310,10 +310,30 @@
DEBUG("GPT detected");
size = MIN(hdr.hdr_entries * hdr.hdr_entsz,
MAXTBLSZ * table->sectorsize);
+
+ /*
+ * If the disk's sector count is smaller than the sector count recorded
+ * in the disk's GPT table header, set the table->sectors to the value
+ * recorded in GPT tables. This is done to work around buggy firmware
+ * that returns truncated disk sizes.
+ *
+ * Note, this is still not a foolproof way to get disk's size. For
+ * example, an image file can be truncated when copied to smaller media.
+ */
+ if (hdr.hdr_lba_alt + 1 > table->sectors)
+ table->sectors = hdr.hdr_lba_alt + 1;
+
for (i = 0; i < size / hdr.hdr_entsz; i++) {
ent = (struct gpt_ent *)(tbl + i * hdr.hdr_entsz);
if (uuid_equal(&ent->ent_type, &gpt_uuid_unused, NULL))
continue;
+
+ /* Simple sanity checks. */
+ if (ent->ent_lba_start < hdr.hdr_lba_start ||
+ ent->ent_lba_end > hdr.hdr_lba_end ||
+ ent->ent_lba_start > ent->ent_lba_end)
+ continue;
+
entry = malloc(sizeof(*entry));
if (entry == NULL)
break;
@@ -735,6 +755,19 @@
}
int
+ptable_getsize(const struct ptable *table, uint64_t *sizep)
+{
+ uint64_t tmp = table->sectors * table->sectorsize;
+
+ if (tmp < table->sectors)
+ return (EOVERFLOW);
+
+ if (sizep != NULL)
+ *sizep = tmp;
+ return (0);
+}
+
+int
ptable_getpart(const struct ptable *table, struct ptable_entry *part, int index)
{
struct pentry *entry;
Index: sys/boot/usb/storage/umass_loader.c
===================================================================
--- sys/boot/usb/storage/umass_loader.c
+++ sys/boot/usb/storage/umass_loader.c
@@ -137,10 +137,20 @@
}
static int
-umass_disk_ioctl(struct open_file *f __unused, u_long cmd, void *buf)
+umass_disk_ioctl(struct open_file *f, u_long cmd, void *buf)
{
+ struct disk_devdesc *dev;
uint32_t nblock;
uint32_t blocksize;
+ int rc;
+
+ dev = (struct disk_devdesc *)(f->f_devdata);
+ if (dev == NULL)
+ return (EINVAL);
+
+ rc = disk_ioctl(dev, cmd, buf);
+ if (rc != ENOTTY)
+ return (rc);
switch (cmd) {
case DIOCGSECTORSIZE:
Index: sys/boot/zfs/zfs.c
===================================================================
--- sys/boot/zfs/zfs.c
+++ sys/boot/zfs/zfs.c
@@ -483,7 +483,7 @@
{
struct ptable *table;
struct zfs_probe_args pa;
- off_t mediasz;
+ uint64_t mediasz;
int ret;
pa.fd = open(devname, O_RDONLY);

File Metadata

Mime Type
text/plain
Expires
Tue, Nov 11, 11:21 AM (3 h, 10 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
25157593
Default Alt Text
D8594.id24643.diff (5 KB)

Event Timeline