]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - board/karo/common/mmc.c
fs/fs.c: correctly interpret the '(max)len' parameter to fs_read()
[karo-tx-uboot.git] / board / karo / common / mmc.c
index 635220e24bf733c9d8a06df47696376a6e3c311a..6143e1575649dac9f7af379a836ed0ea4c4340e8 100644 (file)
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
-*/
+ */
 
 #include <common.h>
 #include <errno.h>
 #include <libfdt.h>
 #include <fdt_support.h>
-//#include <nand.h>
 #include <mmc.h>
 #include <mxcfb.h>
+#include <fs.h>
+#include <fat.h>
+#include <malloc.h>
 #include <linux/list.h>
 #include <linux/fb.h>
 #include <jffs2/load_kernel.h>
-#include <malloc.h>
 
 #include "karo.h"
 
-#define CONFIG_MMC_BOOT_DEV 0
-
 DECLARE_GLOBAL_DATA_PTR;
 
-static void __maybe_unused memdmp(void *addr, size_t len)
-{
-       size_t i;
-
-       for (i = 0; i < len; i+= 16) {
-               size_t j;
-               u32 *wp = addr + i;
-
-               debug("%p: ", addr + i);
-               for (j = 0; j < 4; j++) {
-                       debug(" %08x", wp[j]);
-               }
-               debug("\n");
-       }
-}
-
 #define MAX_SEARCH_PARTITIONS 16
 
-static int find_efi_partition(const char *ifname, int devno, const char *part_str,
-                            block_dev_desc_t **dev_desc,
-                            disk_partition_t *info)
+static int find_partitions(const char *ifname, int devno, int fstype,
+                       block_dev_desc_t **dev_desc, disk_partition_t *info)
 {
        int ret = -1;
        char *dup_str = NULL;
        int p;
        int part;
        block_dev_desc_t *dd;
-
-printf("Searching for partition '%s'\n", part_str);
+       char dev_part_str[16];
 
        dd = get_dev(ifname, devno);
        if (!dd || dd->type == DEV_TYPE_UNKNOWN) {
@@ -75,8 +56,8 @@ printf("Searching for partition '%s'\n", part_str);
         * or user requested partition 0 (entire device).
         */
        if (dd->part_type == PART_TYPE_UNKNOWN) {
-               printf("** No partition table - %s %d **\n", ifname,
-                       devno);
+               printf("** No partition table on device %s %d **\n",
+                       ifname, devno);
                goto cleanup;
        }
 
@@ -86,18 +67,20 @@ printf("Searching for partition '%s'\n", part_str);
                if (ret)
                        continue;
 
-               if (strcmp((char *)info->name, part_str) == 0) {
+               if (fat_register_device(dd, p) == 0) {
                        part = p;
                        dd->log2blksz = LOG2(dd->blksz);
                        break;
                }
        }
        if (!part) {
-               printf("** No valid partitions found **\n");
+               printf("** No valid partition on device %s %d **\n",
+                       ifname, devno);
                ret = -1;
                goto cleanup;
        }
-
+       snprintf(dev_part_str, sizeof(dev_part_str), "%d:%d", devno, part);
+       fs_set_blk_dev(ifname, dev_part_str, fstype);
        ret = part;
        *dev_desc = dd;
 
@@ -106,13 +89,41 @@ cleanup:
        return ret;
 }
 
+static int karo_mmc_find_part(struct mmc *mmc, const char *part, int devno,
+                       disk_partition_t *part_info)
+{
+       int ret;
+       block_dev_desc_t *mmc_dev;
+
+#if defined(CONFIG_SYS_DTB_OFFSET) && defined(CONFIG_SYS_MMC_ENV_PART)
+       if (strcmp(part, "dtb") == 0) {
+               const int partnum = CONFIG_SYS_MMC_ENV_PART;
+
+               part_info->blksz = mmc->read_bl_len;
+               part_info->start = CONFIG_SYS_DTB_OFFSET / part_info->blksz;
+               part_info->size = CONFIG_SYS_DTB_PART_SIZE / part_info->blksz;
+               printf("Using virtual partition %s(%d) ["LBAF".."LBAF"]\n",
+                       part, partnum, part_info->start,
+                       part_info->start + part_info->size - 1);
+               return partnum;
+       }
+#endif
+       ret = find_partitions("mmc", devno, FS_TYPE_FAT, &mmc_dev, part_info);
+       if (ret < 0) {
+               printf("No (e)MMC partition found: %d\n", ret);
+               return ret;
+       }
+       return 0;
+}
+
 int karo_load_mmc_part(const char *part, void *addr, size_t len)
 {
        int ret;
        struct mmc *mmc;
        disk_partition_t part_info;
-       int devno = CONFIG_MMC_BOOT_DEV;
-       uint blk_start, blk_cnt;
+       int devno = CONFIG_SYS_MMC_ENV_DEV;
+       lbaint_t blk_cnt;
+       int partnum;
 
        mmc = find_mmc_device(devno);
        if (!mmc) {
@@ -120,46 +131,56 @@ int karo_load_mmc_part(const char *part, void *addr, size_t len)
                return -ENODEV;
        }
 
-       mmc_init(mmc);
+       if (mmc_init(mmc)) {
+               printf("Failed to init MMC device %d\n", devno);
+               return -EIO;
+       }
 
-//     mmc_boot_part_access(mmc, 1, part_num, part_num);
-#if 1
-       block_dev_desc_t *mmc_dev;
+       blk_cnt = DIV_ROUND_UP(len, mmc->read_bl_len);
 
-       ret = find_efi_partition("mmc", devno, part, &mmc_dev, &part_info);
-       if (ret < 0) {
-               printf("eMMC partition '%s' not found: %d\n", part, ret);
-               goto out;
-       }
-       mmc_switch_part(devno, ret);
+       partnum = karo_mmc_find_part(mmc, part, devno, &part_info);
+       if (partnum > 0) {
+               if (part_info.start + blk_cnt < part_info.start) {
+                       printf("%s: given length 0x%08x exceeds size of partition\n",
+                               __func__, len);
+                       return -EINVAL;
+               }
+               if (part_info.start + blk_cnt > mmc->block_dev.lba)
+                       blk_cnt = mmc->block_dev.lba - part_info.start;
 
-       blk_start = 0;
-       blk_cnt = DIV_ROUND_UP(len, part_info.blksz);
+               mmc_switch_part(devno, partnum);
 
-       printf("Using mmc%d blksz %lu blks %lu\n", devno,
-               mmc_dev->blksz, mmc_dev->lba);
-#endif
-       debug("Found partition '%s': offset=%08x size=%08lx\n",
-               part, blk_start, part_info.size);
-       if (part_info.size < blk_cnt) {
-               printf("Warning: partition '%s' smaller than requested size: %u; truncating data to %lu blocks\n",
-                       part, len, part_info.size * mmc->read_bl_len);
-               blk_cnt = part_info.size;
-       }
+               memset(addr, 0xee, len);
 
-       debug("Reading %u blks from MMC partition '%s' offset %u to %p\n",
-               blk_cnt, part, blk_start, addr);
-       ret = mmc->block_dev.block_read(devno, blk_start, blk_cnt, addr);
-       if (ret == 0) {
-               printf("Failed to read MMC partition %s\n", part);
+               debug("Reading 0x"LBAF" blks from MMC partition %d offset 0x"LBAF" to %p\n",
+                       blk_cnt, partnum, part_info.start, addr);
+               ret = mmc->block_dev.block_read(devno, part_info.start, blk_cnt, addr);
+               if (ret == 0) {
+                       printf("Failed to read MMC partition %s\n", part);
+                       ret = -EIO;
+                       goto out;
+               }
+               debug("Read %u (%u) byte from partition '%s' @ offset 0x"LBAF"\n",
+                       ret * mmc->read_bl_len, len, part, part_info.start);
+       } else if (partnum == 0) {
+               loff_t len_read;
+
+               debug("Trying to read (%u) byte from file '%s' in mmc partition %d\n",
+                       len, part, partnum);
+               ret = fs_read(part, (ulong)addr, 0, len, &len_read);
+               if (ret < 0) {
+                       printf("Failed to read %u byte from %s in mmc partition %d; err: %d\n",
+                               len, part, partnum, ret);
+                       goto out;
+               }
+               debug("Read %llu bytes from %s\n", len_read, part);
+       } else {
+               ret = partnum;
                goto out;
        }
-       debug("Read %u byte from partition '%s' @ offset %08x\n",
-               ret * mmc->read_bl_len, part, blk_start);
-       memdmp(addr, 512);
        ret = 0;
 out:
-//     mmc_boot_part_access(mmc, 1, part_num, 0);
-       mmc_switch_part(devno, 0);
-       return ret;
+       if (partnum > 0)
+               mmc_switch_part(devno, 0);
+       return ret < 0 ? ret : 0;
 }