disk/part.c: 'usb storage' avoiding overflow when output capacity
authorSergei Trofimovich <slyfox@gentoo.org>
Sun, 8 Aug 2010 12:05:39 +0000 (15:05 +0300)
committerWolfgang Denk <wd@denx.de>
Tue, 10 Aug 2010 21:08:55 +0000 (23:08 +0200)
Before:
    Marvell>> usb storage
      Device 0: Vendor: StoreJet Rev:  Prod:  Transcend
                Type: Hard Disk
                Capacity: 28759.9 MB = 28.0 GB (488397168 x 512)
After:
    Marvell>> usb storage
      Device 0: Vendor: StoreJet Rev:  Prod:  Transcend
                Type: Hard Disk
                Capacity: 238475.1 MB = 232.8 GB (488397168 x 512)

Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
disk/part.c

index b6bae1794085db7d66fd4181c1dda2aec89f5e84..3ba88c7e817b5dc8b146545ed46586c70e5ce85c 100644 (file)
@@ -109,14 +109,31 @@ block_dev_desc_t *get_dev(char* ifname, int dev)
 /*
  * reports device info to the user
  */
-void dev_print (block_dev_desc_t *dev_desc)
-{
+
 #ifdef CONFIG_LBA48
-       uint64_t lba512; /* number of blocks if 512bytes block size */
+typedef uint64_t lba512_t;
 #else
-       lbaint_t lba512;
+typedef lbaint_t lba512_t;
 #endif
 
+/*
+ * Overflowless variant of (block_count * mul_by / div_by)
+ * when div_by > mul_by
+ */
+static lba512_t lba512_muldiv (lba512_t block_count, lba512_t mul_by, lba512_t div_by)
+{
+       lba512_t bc_quot, bc_rem;
+
+       /* x * m / d == x / d * m + (x % d) * m / d */
+       bc_quot = block_count / div_by;
+       bc_rem  = block_count - div_by * bc_quot;
+       return bc_quot * mul_by + (bc_rem * mul_by) / div_by;
+}
+
+void dev_print (block_dev_desc_t *dev_desc)
+{
+       lba512_t lba512; /* number of blocks if 512bytes block size */
+
        if (dev_desc->type == DEV_TYPE_UNKNOWN) {
                puts ("not available\n");
                return;
@@ -184,8 +201,9 @@ void dev_print (block_dev_desc_t *dev_desc)
                lba = dev_desc->lba;
 
                lba512 = (lba * (dev_desc->blksz/512));
-               mb = (10 * lba512) / 2048;      /* 2048 = (1024 * 1024) / 512 MB */
                /* round to 1 digit */
+               mb = lba512_muldiv(lba512, 10, 2048);   /* 2048 = (1024 * 1024) / 512 MB */
+
                mb_quot = mb / 10;
                mb_rem  = mb - (10 * mb_quot);