From 0697f206dfbbb5821fbf03283dce0b96515167cf Mon Sep 17 00:00:00 2001
From: Przemyslaw Marczak
Date: Wed, 23 Oct 2013 14:30:44 +0200
Subject: usb: ums: fix disk capacity miscalculation and code cleanup
This patch prevents:
- ums disk capacity miscalculation because of integer overflow
Changes v2:
- Prevents passing zero size disk capacity to ums gadget driver
- Change function ums_get_capacity() to ums_disk_init() and do ums disk
initialization before gadget init
- Remove unnecessary code from mass storage driver
Signed-off-by: Przemyslaw Marczak
Cc: Marek Vasut
---
board/samsung/trats/trats.c | 49 ++++++++++++++++++++++++-------------
drivers/usb/gadget/storage_common.c | 26 +++-----------------
include/usb_mass_storage.h | 6 ++---
3 files changed, 37 insertions(+), 44 deletions(-)
diff --git a/board/samsung/trats/trats.c b/board/samsung/trats/trats.c
index 7d91d88..dab790f 100644
--- a/board/samsung/trats/trats.c
+++ b/board/samsung/trats/trats.c
@@ -778,7 +778,7 @@ static int ums_read_sector(struct ums *ums_dev,
ulong start, lbaint_t blkcnt, void *buf)
{
block_dev_desc_t *block_dev = &ums_dev->mmc->block_dev;
- lbaint_t blkstart = start + ums_dev->offset;
+ lbaint_t blkstart = start + ums_dev->start_sector;
int dev_num = block_dev->dev;
return block_dev->block_read(dev_num, blkstart, blkcnt, buf);
@@ -788,30 +788,47 @@ static int ums_write_sector(struct ums *ums_dev,
ulong start, lbaint_t blkcnt, const void *buf)
{
block_dev_desc_t *block_dev = &ums_dev->mmc->block_dev;
- lbaint_t blkstart = start + ums_dev->offset;
+ lbaint_t blkstart = start + ums_dev->start_sector;
int dev_num = block_dev->dev;
return block_dev->block_write(dev_num, blkstart, blkcnt, buf);
}
-static void ums_get_capacity(struct ums *ums_dev, long long int *capacity)
-{
- long long int tmp_capacity;
-
- tmp_capacity = (long long int)((ums_dev->offset + ums_dev->part_size)
- * SECTOR_SIZE);
- *capacity = ums_dev->mmc->capacity - tmp_capacity;
-}
-
static struct ums ums_dev = {
.read_sector = ums_read_sector,
.write_sector = ums_write_sector,
- .get_capacity = ums_get_capacity,
.name = "UMS disk",
- .offset = UMS_START_SECTOR,
- .part_size = UMS_NUM_SECTORS,
};
+static struct ums *ums_disk_init(struct mmc *mmc)
+{
+ uint64_t mmc_end_sector = mmc->capacity / SECTOR_SIZE;
+ uint64_t ums_end_sector = UMS_NUM_SECTORS + UMS_START_SECTOR;
+
+ if (!mmc_end_sector) {
+ error("MMC capacity is not valid");
+ return NULL;
+ }
+
+ ums_dev.mmc = mmc;
+
+ if (ums_end_sector <= mmc_end_sector) {
+ ums_dev.start_sector = UMS_START_SECTOR;
+ if (UMS_NUM_SECTORS)
+ ums_dev.num_sectors = UMS_NUM_SECTORS;
+ else
+ ums_dev.num_sectors = mmc_end_sector - UMS_START_SECTOR;
+ } else {
+ ums_dev.num_sectors = mmc_end_sector;
+ puts("UMS: defined bad disk parameters. Using default.\n");
+ }
+
+ printf("UMS: disk start sector: %#x, count: %#x\n",
+ ums_dev.start_sector, ums_dev.num_sectors);
+
+ return &ums_dev;
+}
+
struct ums *ums_init(unsigned int dev_num)
{
struct mmc *mmc = NULL;
@@ -820,8 +837,6 @@ struct ums *ums_init(unsigned int dev_num)
if (!mmc)
return NULL;
- ums_dev.mmc = mmc;
-
- return &ums_dev;
+ return ums_disk_init(mmc);
}
#endif
diff --git a/drivers/usb/gadget/storage_common.c b/drivers/usb/gadget/storage_common.c
index c2c5424..02803df 100644
--- a/drivers/usb/gadget/storage_common.c
+++ b/drivers/usb/gadget/storage_common.c
@@ -572,36 +572,16 @@ static struct usb_gadget_strings fsg_stringtab = {
static int fsg_lun_open(struct fsg_lun *curlun, const char *filename)
{
int ro;
- int rc = -EINVAL;
- loff_t size;
- loff_t num_sectors;
- loff_t min_sectors;
/* R/W if we can, R/O if we must */
ro = curlun->initially_ro;
- ums->get_capacity(ums, &size);
- if (size < 0) {
- printf("unable to find file size: %s\n", filename);
- rc = (int) size;
- goto out;
- }
- num_sectors = size >> 9; /* File size in 512-byte blocks */
- min_sectors = 1;
- if (num_sectors < min_sectors) {
- printf("file too small: %s\n", filename);
- rc = -ETOOSMALL;
- goto out;
- }
-
curlun->ro = ro;
- curlun->file_length = size;
- curlun->num_sectors = num_sectors;
+ curlun->file_length = ums->num_sectors << 9;
+ curlun->num_sectors = ums->num_sectors;
debug("open backing file: %s\n", filename);
- rc = 0;
-out:
- return rc;
+ return 0;
}
static void fsg_lun_close(struct fsg_lun *curlun)
diff --git a/include/usb_mass_storage.h b/include/usb_mass_storage.h
index 674ca70..9df3adc 100644
--- a/include/usb_mass_storage.h
+++ b/include/usb_mass_storage.h
@@ -25,12 +25,10 @@ struct ums {
ulong start, lbaint_t blkcnt, void *buf);
int (*write_sector)(struct ums *ums_dev,
ulong start, lbaint_t blkcnt, const void *buf);
- void (*get_capacity)(struct ums *ums_dev,
- long long int *capacity);
+ unsigned int start_sector;
+ unsigned int num_sectors;
const char *name;
struct mmc *mmc;
- int offset;
- int part_size;
};
extern struct ums *ums;
--
cgit v1.1