2 * (C) Copyright 2014 Lothar Waßmann <LW@KARO-electronics.de>
4 * See file CREDITS for list of people who contributed to this
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2 as published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
21 #include <fdt_support.h>
27 #include <linux/list.h>
29 #include <jffs2/load_kernel.h>
33 DECLARE_GLOBAL_DATA_PTR;
35 #define MAX_SEARCH_PARTITIONS 16
37 static int find_partitions(const char *ifname, int devno, int fstype,
38 block_dev_desc_t **dev_desc, disk_partition_t *info)
45 char dev_part_str[16];
47 dd = get_dev(ifname, devno);
48 if (!dd || dd->type == DEV_TYPE_UNKNOWN) {
49 printf("** Bad device %s %d **\n", ifname, devno);
55 * No partition table on device,
56 * or user requested partition 0 (entire device).
58 if (dd->part_type == PART_TYPE_UNKNOWN) {
59 printf("** No partition table on device %s %d **\n",
65 for (p = 1; p <= MAX_SEARCH_PARTITIONS; p++) {
66 ret = get_partition_info(dd, p, info);
70 if (fat_register_device(dd, p) == 0) {
72 dd->log2blksz = LOG2(dd->blksz);
77 printf("** No valid partition on device %s %d **\n",
82 snprintf(dev_part_str, sizeof(dev_part_str), "%d:%d", devno, part);
83 fs_set_blk_dev(ifname, dev_part_str, fstype);
92 static int karo_mmc_find_part(struct mmc *mmc, const char *part, int devno,
93 disk_partition_t *part_info)
96 block_dev_desc_t *mmc_dev;
98 #if defined(CONFIG_SYS_DTB_OFFSET) && defined(CONFIG_SYS_MMC_ENV_PART)
99 if (strcmp(part, "dtb") == 0) {
100 const int partnum = CONFIG_SYS_MMC_ENV_PART;
102 part_info->blksz = mmc->read_bl_len;
103 part_info->start = CONFIG_SYS_DTB_OFFSET / part_info->blksz;
104 part_info->size = CONFIG_SYS_DTB_PART_SIZE / part_info->blksz;
105 printf("Using virtual partition %s(%d) ["LBAF".."LBAF"]\n",
106 part, partnum, part_info->start,
107 part_info->start + part_info->size - 1);
111 ret = find_partitions("mmc", devno, FS_TYPE_FAT, &mmc_dev, part_info);
113 printf("No (e)MMC partition found: %d\n", ret);
119 int karo_load_mmc_part(const char *part, void *addr, size_t len)
123 disk_partition_t part_info;
124 int devno = CONFIG_SYS_MMC_ENV_DEV;
128 mmc = find_mmc_device(devno);
130 printf("Failed to find mmc%u\n", devno);
135 printf("Failed to init MMC device %d\n", devno);
139 blk_cnt = DIV_ROUND_UP(len, mmc->read_bl_len);
141 partnum = karo_mmc_find_part(mmc, part, devno, &part_info);
143 if (part_info.start + blk_cnt < part_info.start) {
144 printf("%s: given length 0x%08x exceeds size of partition\n",
148 if (part_info.start + blk_cnt > mmc->block_dev.lba)
149 blk_cnt = mmc->block_dev.lba - part_info.start;
151 mmc_switch_part(devno, partnum);
153 memset(addr, 0xee, len);
155 debug("Reading 0x"LBAF" blks from MMC partition %d offset 0x"LBAF" to %p\n",
156 blk_cnt, partnum, part_info.start, addr);
157 ret = mmc->block_dev.block_read(devno, part_info.start, blk_cnt, addr);
159 printf("Failed to read MMC partition %s\n", part);
163 debug("Read %u (%u) byte from partition '%s' @ offset 0x"LBAF"\n",
164 ret * mmc->read_bl_len, len, part, part_info.start);
165 } else if (partnum == 0) {
168 debug("Reading file %s from mmc partition %d\n", part,
170 ret = fs_read(part, (ulong)addr, 0, len, &len_read);
172 printf("Failed to read %u byte from mmc partition %d\n",
176 if (len_read < len) {
177 printf("Read only %llu of %u bytes\n", (u64)len_read, len);
186 mmc_switch_part(devno, 0);
187 return ret < 0 ? ret : 0;