* 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) {
* 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;
}
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;
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) {
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("Reading file %s from mmc partition %d\n", part,
+ partnum);
+ ret = fs_read(part, (ulong)addr, 0, len, &len_read);
+ if (ret < 0) {
+ printf("Failed to read %u byte from mmc partition %d\n",
+ len, partnum);
+ goto out;
+ }
+ if (len_read < len) {
+ printf("Read only %llu of %u bytes\n", (u64)len_read, len);
+ }
+ } 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;
}