Fix block device accesses beyond 2TiB
authorSascha Silbe <t-uboot@infra-silbe.de>
Fri, 14 Jun 2013 11:07:25 +0000 (13:07 +0200)
committerTom Rini <trini@ti.com>
Wed, 26 Jun 2013 14:26:06 +0000 (10:26 -0400)
With CONFIG_SYS_64BIT_LBA, lbaint_t gets defined as a 64-bit type,
which is required to represent block numbers for storage devices that
exceed 2TiB (the block size usually is 512B), e.g. recent hard drives.

For some obscure reason, the current U-Boot code uses lbaint_t for the
number of blocks to read (a rather optimistic estimation of how RAM
sizes will evolve), but not for the starting address. Trying to access
blocks beyond the 2TiB boundary will simply wrap around and read a
block within the 0..2TiB range.

We now use lbaint_t for block start addresses, too. This required
changes to all block drivers as the signature of block_read(),
block_write() and block_erase() in block_dev_desc_t changed.

Signed-off-by: Sascha Silbe <t-uboot@infra-silbe.de>
common/cmd_ide.c
common/usb_storage.c
drivers/mmc/mmc.c
include/ide.h
include/part.h

index 78b4aa70ba7d05da59b0b1f14381a3102d6f4cf1..59e95dfa12ef0623cd20e4bb2ac8a8e3828eecde 100644 (file)
@@ -830,7 +830,7 @@ static void ide_ident(block_dev_desc_t *dev_desc)
 
 /* ------------------------------------------------------------------------- */
 
-ulong ide_read(int device, ulong blknr, lbaint_t blkcnt, void *buffer)
+ulong ide_read(int device, lbaint_t blknr, lbaint_t blkcnt, void *buffer)
 {
        ulong n = 0;
        unsigned char c;
@@ -844,7 +844,7 @@ ulong ide_read(int device, ulong blknr, lbaint_t blkcnt, void *buffer)
                lba48 = 1;
        }
 #endif
-       debug("ide_read dev %d start %lX, blocks " LBAF " buffer at %lX\n",
+       debug("ide_read dev %d start " LBAF ", blocks " LBAF " buffer at %lX\n",
              device, blknr, blkcnt, (ulong) buffer);
 
        ide_led(DEVICE_LED(device), 1); /* LED on       */
@@ -934,8 +934,8 @@ ulong ide_read(int device, ulong blknr, lbaint_t blkcnt, void *buffer)
 
                if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) !=
                    ATA_STAT_DRQ) {
-                       printf("Error (no IRQ) dev %d blk %ld: status %#02x\n",
-                               device, blknr, c);
+                       printf("Error (no IRQ) dev %d blk " LBAF ": status "
+                              "%#02x\n", device, blknr, c);
                        break;
                }
 
@@ -954,7 +954,7 @@ IDE_READ_E:
 /* ------------------------------------------------------------------------- */
 
 
-ulong ide_write(int device, ulong blknr, lbaint_t blkcnt, const void *buffer)
+ulong ide_write(int device, lbaint_t blknr, lbaint_t blkcnt, const void *buffer)
 {
        ulong n = 0;
        unsigned char c;
@@ -1022,8 +1022,8 @@ ulong ide_write(int device, ulong blknr, lbaint_t blkcnt, const void *buffer)
 
                if ((c & (ATA_STAT_DRQ | ATA_STAT_BUSY | ATA_STAT_ERR)) !=
                    ATA_STAT_DRQ) {
-                       printf("Error (no IRQ) dev %d blk %ld: status %#02x\n",
-                               device, blknr, c);
+                       printf("Error (no IRQ) dev %d blk " LBAF ": status "
+                               "%#02x\n", device, blknr, c);
                        goto WR_OUT;
                }
 
index 457970f770ce774b6c3e5f461f3216b411258951..4599d03c3ad6a3d6e6b36d25d14e6d2efce71c42 100644 (file)
@@ -170,9 +170,9 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *us,
                      block_dev_desc_t *dev_desc);
 int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
                      struct us_data *ss);
-unsigned long usb_stor_read(int device, unsigned long blknr,
+unsigned long usb_stor_read(int device, lbaint_t blknr,
                            lbaint_t blkcnt, void *buffer);
-unsigned long usb_stor_write(int device, unsigned long blknr,
+unsigned long usb_stor_write(int device, lbaint_t blknr,
                             lbaint_t blkcnt, const void *buffer);
 struct usb_device * usb_get_dev_index(int index);
 void uhci_show_temp_int_td(void);
@@ -1054,7 +1054,7 @@ static void usb_bin_fixup(struct usb_device_descriptor descriptor,
 }
 #endif /* CONFIG_USB_BIN_FIXUP */
 
-unsigned long usb_stor_read(int device, unsigned long blknr,
+unsigned long usb_stor_read(int device, lbaint_t blknr,
                            lbaint_t blkcnt, void *buffer)
 {
        lbaint_t start, blks;
@@ -1127,7 +1127,7 @@ retry_it:
        return blkcnt;
 }
 
-unsigned long usb_stor_write(int device, unsigned long blknr,
+unsigned long usb_stor_write(int device, lbaint_t blknr,
                                lbaint_t blkcnt, const void *buffer)
 {
        lbaint_t start, blks;
index 83d2df7744465678d6f161b26d4d976251b77252..73f71957926b8c73adcd3a37ccd2917ddbbc53e1 100644 (file)
@@ -254,7 +254,7 @@ err_out:
 }
 
 static unsigned long
-mmc_berase(int dev_num, unsigned long start, lbaint_t blkcnt)
+mmc_berase(int dev_num, lbaint_t start, lbaint_t blkcnt)
 {
        int err = 0;
        struct mmc *mmc = find_mmc_device(dev_num);
@@ -266,7 +266,8 @@ mmc_berase(int dev_num, unsigned long start, lbaint_t blkcnt)
 
        if ((start % mmc->erase_grp_size) || (blkcnt % mmc->erase_grp_size))
                printf("\n\nCaution! Your devices Erase group is 0x%x\n"
-                       "The erase range would be change to 0x%lx~0x%lx\n\n",
+                      "The erase range would be change to "
+                      "0x" LBAF "~0x" LBAF "\n\n",
                       mmc->erase_grp_size, start & ~(mmc->erase_grp_size - 1),
                       ((start + blkcnt + mmc->erase_grp_size)
                       & ~(mmc->erase_grp_size - 1)) - 1);
@@ -289,14 +290,14 @@ mmc_berase(int dev_num, unsigned long start, lbaint_t blkcnt)
 }
 
 static ulong
-mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)
+mmc_write_blocks(struct mmc *mmc, lbaint_t start, lbaint_t blkcnt, const void*src)
 {
        struct mmc_cmd cmd;
        struct mmc_data data;
        int timeout = 1000;
 
        if ((start + blkcnt) > mmc->block_dev.lba) {
-               printf("MMC: block number 0x%lx exceeds max(0x%lx)\n",
+               printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
                        start + blkcnt, mmc->block_dev.lba);
                return 0;
        }
@@ -346,7 +347,7 @@ mmc_write_blocks(struct mmc *mmc, ulong start, lbaint_t blkcnt, const void*src)
 }
 
 static ulong
-mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void*src)
+mmc_bwrite(int dev_num, lbaint_t start, lbaint_t blkcnt, const void*src)
 {
        lbaint_t cur, blocks_todo = blkcnt;
 
@@ -369,7 +370,7 @@ mmc_bwrite(int dev_num, ulong start, lbaint_t blkcnt, const void*src)
        return blkcnt;
 }
 
-static int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start,
+static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
                           lbaint_t blkcnt)
 {
        struct mmc_cmd cmd;
@@ -408,7 +409,7 @@ static int mmc_read_blocks(struct mmc *mmc, void *dst, ulong start,
        return blkcnt;
 }
 
-static ulong mmc_bread(int dev_num, ulong start, lbaint_t blkcnt, void *dst)
+static ulong mmc_bread(int dev_num, lbaint_t start, lbaint_t blkcnt, void *dst)
 {
        lbaint_t cur, blocks_todo = blkcnt;
 
@@ -420,7 +421,7 @@ static ulong mmc_bread(int dev_num, ulong start, lbaint_t blkcnt, void *dst)
                return 0;
 
        if ((start + blkcnt) > mmc->block_dev.lba) {
-               printf("MMC: block number 0x%lx exceeds max(0x%lx)\n",
+               printf("MMC: block number 0x" LBAF " exceeds max(0x" LBAF ")\n",
                        start + blkcnt, mmc->block_dev.lba);
                return 0;
        }
index afea85cdc2cb3b5739e390d3bd02001f782fe9d3..f691a74ab46a9dc177379eb52077efdc67e81d15 100644 (file)
@@ -54,8 +54,9 @@ typedef ulong lbaint_t;
  */
 
 void ide_init(void);
-ulong ide_read(int device, ulong blknr, lbaint_t blkcnt, void *buffer);
-ulong ide_write(int device, ulong blknr, lbaint_t blkcnt, const void *buffer);
+ulong ide_read(int device, lbaint_t blknr, lbaint_t blkcnt, void *buffer);
+ulong ide_write(int device, lbaint_t blknr, lbaint_t blkcnt,
+               const void *buffer);
 
 #ifdef CONFIG_IDE_PREINIT
 int ide_preinit(void);
index f7c7cc59fca2dccb41635e1f28666aed60234449..35c1c5b5f58bf54f573ac696c550ccad385731ea 100644 (file)
@@ -43,15 +43,15 @@ typedef struct block_dev_desc {
        char            product[20+1];  /* IDE Serial no, SCSI product */
        char            revision[8+1];  /* firmware revision */
        unsigned long   (*block_read)(int dev,
-                                     unsigned long start,
+                                     lbaint_t start,
                                      lbaint_t blkcnt,
                                      void *buffer);
        unsigned long   (*block_write)(int dev,
-                                      unsigned long start,
+                                      lbaint_t start,
                                       lbaint_t blkcnt,
                                       const void *buffer);
        unsigned long   (*block_erase)(int dev,
-                                      unsigned long start,
+                                      lbaint_t start,
                                       lbaint_t blkcnt);
        void            *priv;          /* driver private struct pointer */
 }block_dev_desc_t;