Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F135514477
D8594.id24643.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D8594.id24643.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D8594: Implement disk_ioctl() to support DIOCGSECTORSIZE and DIOCGMEDIASIZE.
Attached
Detach File
Event Timeline
Log In to Comment