On Mon, Jan 04, 2016 at 10:30:03AM +0100, Heiko Schocher wrote: > Am 30.12.2015 um 03:12 schrieb Ladislav Michl: > >From: Thomas Gleixner <t...@linutronix.de> > > > >This is an update of Thomas's patch: > >https://patchwork.ozlabs.org/patch/367306/ > >patch still depends on spl_nand_simple implementation: > >https://patchwork.ozlabs.org/patch/367305/ > > Huh, in patchwork, this patch is in "deferred" state ... > Tom? > > Maybe you should add it to your patch and make a patchseries.
Will post entire serie. > >Changes from original version: > >- fixes ubi_calc_fm_size to include also sizeof(struct ubi_fm_sb) > >- dropped private copy of ubi-media.h > >- accomodate for actual Makefile > > > >As original patch is more that a year old, should we update to current > >linux fastmap code? > > Yes, please! I did for U-Boot an UBI/UBIFS update to linux 4.2, as > Richard Weinberger stated, that the old fastmap implementation is > buggy! I just checked that, there are two functions involved: ubi_scan_fastmap and ubi_attach_fastmap where the newer version of the latter is quite bloated for spl (uses lists), so I'll left it for later. Note that ubi_calc_fm_size bug is already fixed. [...] > No real showstoppers, besides that the patch doubles a lot of > defines, which are already defined in ubi headers. You should > try (if it is possible, I didn;t looked deeper into it), if you > could prevent this. Removing ubi-wrapper.h and using defines from ubi.h and ubi-user.h makes things even worse as ubispl.c uses lighter struct ubi_scan_info instead of struct ubi_device as function parameter. However I synced defines used where appropriate. > [...] > >diff --git a/drivers/Makefile b/drivers/Makefile > >index c9031f2..e0bcb52 100644 > >--- a/drivers/Makefile > >+++ b/drivers/Makefile > >@@ -22,10 +22,11 @@ obj-$(CONFIG_SPL_SPI_FLASH_SUPPORT) += mtd/spi/ > > obj-$(CONFIG_SPL_SPI_SUPPORT) += spi/ > > obj-$(CONFIG_SPL_POWER_SUPPORT) += power/ power/pmic/ > > obj-$(CONFIG_SPL_POWER_SUPPORT) += power/regulator/ > >+obj-$(CONFIG_SPL_DRIVERS_MISC_SUPPORT) += misc/ > > obj-$(CONFIG_SPL_MTD_SUPPORT) += mtd/ > > obj-$(CONFIG_SPL_NAND_SUPPORT) += mtd/nand/ > >-obj-$(CONFIG_SPL_DRIVERS_MISC_SUPPORT) += misc/ > > Is this an ubi related change? And please sort alphabetical. No, it is a result of alphabetical sorting :) What about something like this applied first? -- >8 -- Subject: mtd: Sort subsystem directories aplhabeticaly in Makefile Signed-off-by: Ladislav Michl <la...@linux-mips.org> diff --git a/drivers/Makefile b/drivers/Makefile index c9031f2..9c5c6c0 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -18,14 +18,14 @@ obj-$(CONFIG_SYS_MVEBU_DDR_A38X) += ddr/marvell/a38x/ obj-$(CONFIG_SYS_MVEBU_DDR_AXP) += ddr/marvell/axp/ obj-$(CONFIG_ALTERA_SDRAM) += ddr/altera/ obj-$(CONFIG_SPL_SERIAL_SUPPORT) += serial/ -obj-$(CONFIG_SPL_SPI_FLASH_SUPPORT) += mtd/spi/ obj-$(CONFIG_SPL_SPI_SUPPORT) += spi/ obj-$(CONFIG_SPL_POWER_SUPPORT) += power/ power/pmic/ obj-$(CONFIG_SPL_POWER_SUPPORT) += power/regulator/ +obj-$(CONFIG_SPL_DRIVERS_MISC_SUPPORT) += misc/ obj-$(CONFIG_SPL_MTD_SUPPORT) += mtd/ obj-$(CONFIG_SPL_NAND_SUPPORT) += mtd/nand/ -obj-$(CONFIG_SPL_DRIVERS_MISC_SUPPORT) += misc/ obj-$(CONFIG_SPL_ONENAND_SUPPORT) += mtd/onenand/ +obj-$(CONFIG_SPL_SPI_FLASH_SUPPORT) += mtd/spi/ obj-$(CONFIG_SPL_DMA_SUPPORT) += dma/ obj-$(CONFIG_SPL_ETH_SUPPORT) += net/ obj-$(CONFIG_SPL_ETH_SUPPORT) += net/phy/ > > obj-$(CONFIG_SPL_ONENAND_SUPPORT) += mtd/onenand/ > >+obj-$(CONFIG_SPL_UBI) += mtd/ubispl/ > > obj-$(CONFIG_SPL_DMA_SUPPORT) += dma/ > > obj-$(CONFIG_SPL_ETH_SUPPORT) += net/ > > obj-$(CONFIG_SPL_ETH_SUPPORT) += net/phy/ > >diff --git a/drivers/mtd/ubispl/Makefile b/drivers/mtd/ubispl/Makefile > >new file mode 100644 > >index 0000000..740dbed > >--- /dev/null > >+++ b/drivers/mtd/ubispl/Makefile > >@@ -0,0 +1 @@ > >+obj-y += ubispl.o ../ubi/crc32.o > >diff --git a/drivers/mtd/ubispl/ubi-wrapper.h > >b/drivers/mtd/ubispl/ubi-wrapper.h > >new file mode 100644 > >index 0000000..dd76e6b > >--- /dev/null > >+++ b/drivers/mtd/ubispl/ubi-wrapper.h > >@@ -0,0 +1,104 @@ > >+/* > >+ * The parts taken from the kernel implementation are: > >+ * > >+ * Copyright (c) International Business Machines Corp., 2006 > >+ * > >+ * UBISPL specific wrappers and defines: > >+ * > >+ * Copyright (c) Thomas Gleixner <t...@linutronix.de> > >+ * > >+ * SPDX-License-Identifier: GPL-2.0+ > >+ */ > >+ > >+/* > >+ * Contains various defines, wrappers to make the upstream fastboot > >+ * code happy. > >+ */ > >+#ifndef __UBOOT_UBI_WRAPPER_H > >+#define __UBOOT_UBI_WRAPPER_H > >+ > >+/* > >+ * Error codes returned by the I/O sub-system. > >+ * > >+ * UBI_IO_FF: the read region of flash contains only 0xFFs > >+ * UBI_IO_FF_BITFLIPS: the same as %UBI_IO_FF, but also also there was a > >data > >+ * integrity error reported by the MTD driver > >+ * (uncorrectable ECC error in case of NAND) > >+ * UBI_IO_BAD_HDR: the EC or VID header is corrupted (bad magic or CRC) > >+ * UBI_IO_BAD_HDR_EBADMSG: the same as %UBI_IO_BAD_HDR, but also there was a > >+ * data integrity error reported by the MTD driver > >+ * (uncorrectable ECC error in case of NAND) > >+ * UBI_IO_BITFLIPS: bit-flips were detected and corrected > >+ * > >+ * UBI_FASTMAP_ANCHOR: u-boot SPL add on to tell the caller that the > >fastmap > >+ * anchor block has been found > >+ * > >+ * Note, it is probably better to have bit-flip and ebadmsg as flags which > >can > >+ * be or'ed with other error code. But this is a big change because there > >are > >+ * may callers, so it does not worth the risk of introducing a bug > >+ */ > >+enum { > >+ UBI_IO_FF = 1, > >+ UBI_IO_FF_BITFLIPS, > >+ UBI_IO_BAD_HDR, > >+ UBI_IO_BAD_HDR_EBADMSG, > >+ UBI_IO_BITFLIPS, > >+ UBI_FASTMAP_ANCHOR, > >+}; > > Couldn;t you use the definition from ./drivers/mtd/ubi/ubi.h ? > > >+/* > >+ * UBI volume type constants. > >+ * > >+ * @UBI_DYNAMIC_VOLUME: dynamic volume > >+ * @UBI_STATIC_VOLUME: static volume > >+ */ > >+enum { > >+ UBI_DYNAMIC_VOLUME = 3, > >+ UBI_STATIC_VOLUME = 4, > >+}; > > Same here, this is already defined here: > ./include/mtd/ubi-user.h Those definitions could be used for a price of some ifdefs in common code. I consider duplication a better option. > >+#define UBI_BAD_FASTMAP (-1) > > ./drivers/mtd/ubi/ubi.h: > > /* > * Return codes of the fastmap sub-system > * > * UBI_NO_FASTMAP: No fastmap super block was found > * UBI_BAD_FASTMAP: A fastmap was found but it's unusable > */ > enum { > UBI_NO_FASTMAP = 1, > UBI_BAD_FASTMAP, > }; > > differ to existing definition... maybe a bad idea? fixed in next version. > >+ > >+/* > >+ * Stub structure so the fastmap code is happy. > >+ */ > >+struct ubi_attach_info { > >+ int i; > >+}; > >+ > >+/** > >+ * struct ubi_fastmap_layout - in-memory fastmap data structure. > >+ * @e: PEBs used by the current fastmap > >+ * @to_be_tortured: if non-zero tortured this PEB > >+ * @used_blocks: number of used PEBs > >+ * @max_pool_size: maximal size of the user pool > >+ * @max_wl_pool_size: maximal size of the pool used by the WL sub-system > >+ */ > >+struct ubi_fastmap_layout { > >+ struct ubi_wl_entry *e[UBI_FM_MAX_BLOCKS]; > >+ int to_be_tortured[UBI_FM_MAX_BLOCKS]; > >+ int used_blocks; > >+ int max_pool_size; > >+ int max_wl_pool_size; > >+}; > >+ > >+/** > >+ * struct ubi_fm_pool - in-memory fastmap pool > >+ * @pebs: PEBs in this pool > >+ * @used: number of used PEBs > >+ * @size: total number of PEBs in this pool > >+ * @max_size: maximal size of the pool > >+ * > >+ * A pool gets filled with up to max_size. > >+ * If all PEBs within the pool are used a new fastmap will be written > >+ * to the flash and the pool gets refilled with empty PEBs. > >+ * > >+ */ > >+struct ubi_fm_pool { > >+ int pebs[UBI_FM_MAX_POOL_SIZE]; > >+ int used; > >+ int size; > >+ int max_size; > >+}; > >+ > >+#endif > > Do we really need this wrapper file ... At last we need some comments > in the not spl ubi code, that we double the defines ... It makes things actually simpler. File modified to contain only copy and paste defines except UBI_FASTMAP_ANCHOR. > Do you have some numbers how many bytes the current ubispl implementation > needs? text data bss dec hex filename 46989 1368 201084 249441 3ce61 spl 53041 1368 203132 257541 3ee05 spl.ubi (compared to SPL which is loading kernel from fixed NAND offset) > >diff --git a/drivers/mtd/ubispl/ubispl.c b/drivers/mtd/ubispl/ubispl.c > >new file mode 100644 > >index 0000000..9b11bd4 > >--- /dev/null > >+++ b/drivers/mtd/ubispl/ubispl.c > >@@ -0,0 +1,921 @@ > >+/* > >+ * Copyright (c) Thomas Gleixner <t...@linutronix.de> > >+ * > >+ * The parts taken from the kernel implementation are: > >+ * > >+ * Copyright (c) International Business Machines Corp., 2006 > >+ > >+ * SPDX-License-Identifier: GPL-2.0+ > >+ */ > >+ > >+#include <common.h> > >+#include <ubispl.h> > >+ > >+#include <linux/crc32.h> > >+ > >+#include "ubispl.h" > >+ > >+/** > >+ * ubi_calc_fm_size - calculates the fastmap size in bytes for an UBI > >device. > >+ * @ubi: UBI device description object > >+ */ > >+static size_t ubi_calc_fm_size(struct ubi_scan_info *ubi) > >+{ > >+ size_t size; > >+ > >+ size = sizeof(struct ubi_fm_sb) + > >+ sizeof(struct ubi_fm_hdr) + > >+ sizeof(struct ubi_fm_scan_pool) + > >+ sizeof(struct ubi_fm_scan_pool) + > >+ (ubi->peb_count * sizeof(struct ubi_fm_ec)) + > >+ (sizeof(struct ubi_fm_eba) + > >+ (ubi->peb_count * sizeof(__be32))) + > >+ sizeof(struct ubi_fm_volhdr) * UBI_MAX_VOLUMES; > >+ return roundup(size, ubi->leb_size); > >+} > >+ > >+static int ubi_io_read(struct ubi_scan_info *ubi, void *buf, int pnum, > >+ unsigned long from, unsigned long len) > >+{ > >+ return ubi->read(pnum + ubi->peb_offset, from, len, buf); > >+} > >+ > >+static int ubi_io_is_bad(struct ubi_scan_info *ubi, int peb) > >+{ > >+ return peb >= ubi->peb_count || peb < 0; > >+} > >+ > >+static int ubi_io_read_vid_hdr(struct ubi_scan_info *ubi, int pnum, > >+ struct ubi_vid_hdr *vh, int unused) > >+{ > >+ u32 magic; > >+ int res; > >+ > >+ /* No point in rescanning a corrupt block */ > >+ if (test_bit(pnum, ubi->corrupt)) > >+ return -1; > > Please use defines from errno.h (fix this globally). fixed. > >+ /* > >+ * If the block has been scanned already, no need to rescan > >+ */ > >+ if (test_and_set_bit(pnum, ubi->scanned)) > >+ return 0; > >+ > >+ res = ubi_io_read(ubi, vh, pnum, ubi->vid_offset, sizeof(*vh)); > >+ > >+ /* > >+ * Bad block, unrecoverable ECC error, skip the block > >+ */ > >+ if (res) { > >+ ubi_dbg("Skipping bad or unreadable block %d", pnum); > >+ vh->magic = 0; > >+ generic_set_bit(pnum, ubi->corrupt); > >+ return res; > >+ } > >+ > >+ /* Magic number available ? */ > >+ magic = be32_to_cpu(vh->magic); > >+ if ((magic != UBI_VID_HDR_MAGIC)) { > >+ generic_set_bit(pnum, ubi->corrupt); > >+ if (magic == 0xffffffff) > >+ return UBI_IO_FF; > >+ ubi_msg("Bad magic in block 0%d %08x", pnum, magic); > >+ return UBI_IO_BAD_HDR; > >+ } > >+ > >+ /* Header CRC correct ? */ > >+ if (crc32(UBI_CRC32_INIT, vh, UBI_VID_HDR_SIZE_CRC) != > >+ be32_to_cpu(vh->hdr_crc)) { > >+ ubi_msg("Bad CRC in block 0%d", pnum); > >+ generic_set_bit(pnum, ubi->corrupt); > >+ return UBI_IO_BAD_HDR; > >+ } > >+ > >+ ubi_dbg("RV: pnum: %i sqnum %llu", pnum, be64_to_cpu(vh->sqnum)); > >+ > >+ return 0; > >+} > >+ > >+static int ubi_rescan_fm_vid_hdr(struct ubi_scan_info *ubi, > >+ struct ubi_vid_hdr *vh, > >+ u32 fm_pnum, u32 fm_vol_id, u32 fm_lnum) > >+{ > >+ int res; > >+ > >+ if (ubi_io_is_bad(ubi, fm_pnum)) > >+ return -1; > >+ > >+ res = ubi_io_read_vid_hdr(ubi, fm_pnum, vh, 0); > >+ if (!res) { > >+ /* Check volume id, volume type and lnum */ > >+ if (be32_to_cpu(vh->vol_id) == fm_vol_id && > >+ vh->vol_type == UBI_VID_STATIC && > >+ be32_to_cpu(vh->lnum) == fm_lnum) > >+ return 0; > >+ ubi_dbg("RS: PEB %u vol: %u : %u typ %u lnum %u %u", > >+ fm_pnum, fm_vol_id, vh->vol_type, > >+ be32_to_cpu(vh->vol_id), > >+ fm_lnum, be32_to_cpu(vh->lnum)); > >+ } > >+ return -1; > >+} > >+ > >+/* Insert the logic block into the volume info */ > >+static int ubi_add_peb_to_vol(struct ubi_scan_info *ubi, > >+ struct ubi_vid_hdr *vh, u32 vol_id, > >+ u32 vol_type, u32 pnum, u32 lnum) > >+{ > >+ struct ubi_vol_info *vi = ubi->volinfo + vol_id; > >+ u32 *ltp; > >+ > >+ /* > >+ * We only care about static volumes with an id < > >+ * UBI_SPL_VOL_IDS. > >+ */ > >+ if (vol_id >= UBI_SPL_VOL_IDS || vol_type != UBI_VID_STATIC) > >+ return 0; > >+ > >+ /* > >+ * If the volume is larger than expected, yell and give up :( > >+ */ > >+ if (lnum >= UBI_MAX_VOL_LEBS) { > >+ ubi_warn("Vol: %u LEB %d > %d", vol_id, lnum, UBI_MAX_VOL_LEBS); > >+ return -1; > >+ } > >+ > >+ ubi_dbg("SC: Add PEB %u to Vol %u as LEB %u fnd %d sc %d", > >+ pnum, vol_id, lnum, !!test_bit(lnum, vi->found), > >+ !!test_bit(pnum, ubi->scanned)); > >+ > >+ /* Points to the translation entry */ > >+ ltp = vi->lebs_to_pebs + lnum; > >+ > >+ /* If the block is already assigned, check sqnum */ > >+ if (__test_and_set_bit(lnum, vi->found)) { > >+ u32 cur_pnum = *ltp; > >+ struct ubi_vid_hdr *cur = ubi->blockinfo + cur_pnum; > >+ > >+ /* > >+ * If the current block hase not yet been scanned, we > >+ * need to do that. The other block might be stale or > >+ * the current block corrupted and the FM not yet > >+ * updated. > >+ */ > >+ if (!test_bit(cur_pnum, ubi->scanned)) { > >+ /* > >+ * If the scan fails, we use the valid block > >+ */ > >+ if (ubi_rescan_fm_vid_hdr(ubi, cur, cur_pnum, vol_id, > >+ lnum)) { > >+ *ltp = pnum; > >+ return 0; > >+ } > >+ } > >+ > >+ /* > >+ * Should not happen .... > >+ */ > >+ if (test_bit(cur_pnum, ubi->corrupt)) { > >+ *ltp = pnum; > >+ return 0; > >+ } > >+ > >+ ubi_dbg("Vol %u LEB %u PEB %u->sqnum %llu NPEB %u->sqnum %llu", > >+ vol_id, lnum, cur_pnum, be64_to_cpu(cur->sqnum), pnum, > >+ be64_to_cpu(vh->sqnum)); > >+ > >+ /* > >+ * Compare sqnum and take the newer one > >+ */ > >+ if (be64_to_cpu(cur->sqnum) < be64_to_cpu(vh->sqnum)) > >+ *ltp = pnum; > >+ } else { > >+ *ltp = pnum; > >+ if (lnum > vi->last_block) > >+ vi->last_block = lnum; > >+ } > >+ > >+ return 0; > >+} > >+ > >+static int ubi_scan_vid_hdr(struct ubi_scan_info *ubi, struct ubi_vid_hdr > >*vh, > >+ u32 pnum) > >+{ > >+ u32 vol_id, lnum; > >+ int res; > >+ > >+ if (ubi_io_is_bad(ubi, pnum)) > >+ return -1; > >+ > >+ res = ubi_io_read_vid_hdr(ubi, pnum, vh, 0); > >+ if (res) > >+ return res; > >+ > >+ /* Get volume id */ > >+ vol_id = be32_to_cpu(vh->vol_id); > >+ > >+ /* If this is the fastmap anchor, return right away */ > >+ if (vol_id == UBI_FM_SB_VOLUME_ID) > >+ return ubi->fm_enabled ? UBI_FASTMAP_ANCHOR : 0; > >+ > >+ /* We are only interested in the volumes to load */ > >+ if (!test_bit(vol_id, ubi->toload)) > >+ return 0; > >+ > >+ lnum = be32_to_cpu(vh->lnum); > >+ > >+ return ubi_add_peb_to_vol(ubi, vh, vol_id, vh->vol_type, pnum, lnum); > >+} > >+ > >+static int assign_aeb_to_av(struct ubi_scan_info *ubi, u32 pnum, u32 lnum, > >+ u32 vol_id, u32 vol_type, u32 used) > >+{ > >+ struct ubi_vid_hdr *vh; > >+ > >+ if (ubi_io_is_bad(ubi, pnum)) > >+ return -1; > >+ > >+ ubi->fastmap_pebs++; > >+ > >+ if (vol_id >= UBI_SPL_VOL_IDS || vol_type != UBI_STATIC_VOLUME) > >+ return 0; > >+ > >+ /* We are only interested in the volumes to load */ > >+ if (!test_bit(vol_id, ubi->toload)) > >+ return 0; > >+ > >+ vh = ubi->blockinfo + pnum; > >+ > >+ return ubi_scan_vid_hdr(ubi, vh, pnum); > >+} > >+ > >+static int scan_pool(struct ubi_scan_info *ubi, __be32 *pebs, int pool_size) > >+{ > >+ struct ubi_vid_hdr *vh; > >+ u32 pnum; > >+ int i; > >+ > >+ ubi_dbg("Scanning pool size: %d", pool_size); > >+ > >+ for (i = 0; i < pool_size; i++) { > >+ pnum = be32_to_cpu(pebs[i]); > >+ > >+ if (ubi_io_is_bad(ubi, pnum)) { > >+ ubi_err("FM: Bad PEB in fastmap pool! %u", pnum); > >+ return UBI_BAD_FASTMAP; > >+ } > >+ > >+ vh = ubi->blockinfo + pnum; > >+ /* > >+ * We allow the scan to fail here. The loader will notice > >+ * and look for a replacement. > >+ */ > >+ ubi_scan_vid_hdr(ubi, vh, pnum); > >+ } > >+ return 0; > >+} > >+ > >+static int ubi_attach_fastmap(struct ubi_scan_info *ubi, > >+ struct ubi_attach_info *ai, > >+ struct ubi_fastmap_layout *fm) > >+{ > >+ struct ubi_fm_hdr *fmhdr; > >+ struct ubi_fm_scan_pool *fmpl1, *fmpl2; > >+ struct ubi_fm_ec *fmec; > >+ struct ubi_fm_volhdr *fmvhdr; > >+ struct ubi_fm_eba *fm_eba; > >+ int ret, i, j, pool_size, wl_pool_size; > >+ size_t fm_pos = 0, fm_size = ubi->fm_size; > >+ void *fm_raw = ubi->fm_buf; > >+ > >+ memset(ubi->fm_used, 0, sizeof(ubi->fm_used)); > >+ > >+ fm_pos += sizeof(struct ubi_fm_sb); > >+ if (fm_pos >= fm_size) > >+ goto fail_bad; > >+ > >+ fmhdr = (struct ubi_fm_hdr *)(fm_raw + fm_pos); > >+ fm_pos += sizeof(*fmhdr); > >+ if (fm_pos >= fm_size) > >+ goto fail_bad; > >+ > >+ if (be32_to_cpu(fmhdr->magic) != UBI_FM_HDR_MAGIC) { > >+ ubi_err("bad fastmap header magic: 0x%x, expected: 0x%x", > >+ be32_to_cpu(fmhdr->magic), UBI_FM_HDR_MAGIC); > >+ goto fail_bad; > >+ } > >+ > >+ fmpl1 = (struct ubi_fm_scan_pool *)(fm_raw + fm_pos); > >+ fm_pos += sizeof(*fmpl1); > >+ if (fm_pos >= fm_size) > >+ goto fail_bad; > >+ if (be32_to_cpu(fmpl1->magic) != UBI_FM_POOL_MAGIC) { > >+ ubi_err("bad fastmap pool magic: 0x%x, expected: 0x%x", > >+ be32_to_cpu(fmpl1->magic), UBI_FM_POOL_MAGIC); > >+ goto fail_bad; > >+ } > >+ > >+ fmpl2 = (struct ubi_fm_scan_pool *)(fm_raw + fm_pos); > >+ fm_pos += sizeof(*fmpl2); > >+ if (fm_pos >= fm_size) > >+ goto fail_bad; > >+ if (be32_to_cpu(fmpl2->magic) != UBI_FM_POOL_MAGIC) { > >+ ubi_err("bad fastmap pool magic: 0x%x, expected: 0x%x", > >+ be32_to_cpu(fmpl2->magic), UBI_FM_POOL_MAGIC); > >+ goto fail_bad; > >+ } > >+ > >+ pool_size = be16_to_cpu(fmpl1->size); > >+ wl_pool_size = be16_to_cpu(fmpl2->size); > >+ fm->max_pool_size = be16_to_cpu(fmpl1->max_size); > >+ fm->max_wl_pool_size = be16_to_cpu(fmpl2->max_size); > >+ > >+ if (pool_size > UBI_FM_MAX_POOL_SIZE || pool_size < 0) { > >+ ubi_err("bad pool size: %i", pool_size); > >+ goto fail_bad; > >+ } > >+ > >+ if (wl_pool_size > UBI_FM_MAX_POOL_SIZE || wl_pool_size < 0) { > >+ ubi_err("bad WL pool size: %i", wl_pool_size); > >+ goto fail_bad; > >+ } > >+ > >+ if (fm->max_pool_size > UBI_FM_MAX_POOL_SIZE || > >+ fm->max_pool_size < 0) { > >+ ubi_err("bad maximal pool size: %i", fm->max_pool_size); > >+ goto fail_bad; > >+ } > >+ > >+ if (fm->max_wl_pool_size > UBI_FM_MAX_POOL_SIZE || > >+ fm->max_wl_pool_size < 0) { > >+ ubi_err("bad maximal WL pool size: %i", fm->max_wl_pool_size); > >+ goto fail_bad; > >+ } > >+ > >+ /* read EC values from free list */ > >+ for (i = 0; i < be32_to_cpu(fmhdr->free_peb_count); i++) { > >+ fmec = (struct ubi_fm_ec *)(fm_raw + fm_pos); > >+ fm_pos += sizeof(*fmec); > >+ if (fm_pos >= fm_size) > >+ goto fail_bad; > >+ } > >+ > >+ /* read EC values from used list */ > >+ for (i = 0; i < be32_to_cpu(fmhdr->used_peb_count); i++) { > >+ fmec = (struct ubi_fm_ec *)(fm_raw + fm_pos); > >+ fm_pos += sizeof(*fmec); > >+ if (fm_pos >= fm_size) > >+ goto fail_bad; > >+ > >+ generic_set_bit(be32_to_cpu(fmec->pnum), ubi->fm_used); > >+ } > >+ > >+ /* read EC values from scrub list */ > >+ for (i = 0; i < be32_to_cpu(fmhdr->scrub_peb_count); i++) { > >+ fmec = (struct ubi_fm_ec *)(fm_raw + fm_pos); > >+ fm_pos += sizeof(*fmec); > >+ if (fm_pos >= fm_size) > >+ goto fail_bad; > >+ } > >+ > >+ /* read EC values from erase list */ > >+ for (i = 0; i < be32_to_cpu(fmhdr->erase_peb_count); i++) { > >+ fmec = (struct ubi_fm_ec *)(fm_raw + fm_pos); > >+ fm_pos += sizeof(*fmec); > >+ if (fm_pos >= fm_size) > >+ goto fail_bad; > >+ } > >+ > >+ /* Iterate over all volumes and read their EBA table */ > >+ for (i = 0; i < be32_to_cpu(fmhdr->vol_count); i++) { > >+ u32 vol_id, vol_type, used, reserved; > >+ > >+ fmvhdr = (struct ubi_fm_volhdr *)(fm_raw + fm_pos); > >+ fm_pos += sizeof(*fmvhdr); > >+ if (fm_pos >= fm_size) > >+ goto fail_bad; > >+ > >+ if (be32_to_cpu(fmvhdr->magic) != UBI_FM_VHDR_MAGIC) { > >+ ubi_err("bad fastmap vol header magic: 0x%x, " \ > >+ "expected: 0x%x", > >+ be32_to_cpu(fmvhdr->magic), UBI_FM_VHDR_MAGIC); > >+ goto fail_bad; > >+ } > >+ > >+ vol_id = be32_to_cpu(fmvhdr->vol_id); > >+ vol_type = fmvhdr->vol_type; > >+ used = be32_to_cpu(fmvhdr->used_ebs); > >+ > >+ fm_eba = (struct ubi_fm_eba *)(fm_raw + fm_pos); > >+ fm_pos += sizeof(*fm_eba); > >+ fm_pos += (sizeof(__be32) * be32_to_cpu(fm_eba->reserved_pebs)); > >+ if (fm_pos >= fm_size) > >+ goto fail_bad; > >+ > >+ if (be32_to_cpu(fm_eba->magic) != UBI_FM_EBA_MAGIC) { > >+ ubi_err("bad fastmap EBA header magic: 0x%x, " \ > >+ "expected: 0x%x", > >+ be32_to_cpu(fm_eba->magic), UBI_FM_EBA_MAGIC); > >+ goto fail_bad; > >+ } > >+ > >+ reserved = be32_to_cpu(fm_eba->reserved_pebs); > >+ ubi_dbg("FA: vol %u used %u res: %u", vol_id, used, reserved); > >+ for (j = 0; j < reserved; j++) { > >+ int pnum = be32_to_cpu(fm_eba->pnum[j]); > >+ > >+ if ((int)be32_to_cpu(fm_eba->pnum[j]) < 0) > >+ continue; > >+ > >+ if (!__test_and_clear_bit(pnum, ubi->fm_used)) > >+ continue; > >+ > >+ /* > >+ * We only handle static volumes so used_ebs > >+ * needs to be handed in. And we do not assign > >+ * the reserved blocks > >+ */ > >+ if (j >= used) > >+ continue; > >+ > >+ ret = assign_aeb_to_av(ubi, pnum, j, vol_id, > >+ vol_type, used); > >+ if (!ret) > >+ continue; > >+ > >+ /* > >+ * Nasty: The fastmap claims that the volume > >+ * has one block more than it, but that block > >+ * is always empty and the other blocks have > >+ * the correct number of total LEBs in the > >+ * headers. Deal with it. > >+ */ > >+ if (ret != UBI_IO_FF && j != used - 1) > >+ goto fail_bad; > >+ ubi_dbg("FA: Vol: %u Ignoring empty LEB %d of %d", > >+ vol_id, j, used); > >+ } > >+ } > >+ > >+ ret = scan_pool(ubi, fmpl1->pebs, pool_size); > >+ if (ret) > >+ goto fail; > >+ > >+ ret = scan_pool(ubi, fmpl2->pebs, wl_pool_size); > >+ if (ret) > >+ goto fail; > >+ > >+#ifdef CHECKME > > ? > > >+ /* > >+ * If fastmap is leaking PEBs (must not happen), raise a > >+ * fat warning and fall back to scanning mode. > >+ * We do this here because in ubi_wl_init() it's too late > >+ * and we cannot fall back to scanning. > >+ */ > >+ if (WARN_ON(count_fastmap_pebs(ai) != ubi->peb_count - > >+ ai->bad_peb_count - fm->used_blocks)) > >+ goto fail_bad; > >+#endif > >+ > >+ return 0; > >+ > >+fail_bad: > >+ ret = UBI_BAD_FASTMAP; > >+fail: > >+ return ret; > >+} > >+ > >+static int ubi_scan_fastmap(struct ubi_scan_info *ubi, struct > >ubi_attach_info *ai, > >+ int fm_anchor) > >+{ > >+ struct ubi_fm_sb *fmsb, *fmsb2; > >+ struct ubi_vid_hdr *vh; > >+ struct ubi_fastmap_layout *fm; > >+ int i, used_blocks, pnum, ret = 0; > >+ unsigned int fsize, nblocks; > >+ size_t fm_size; > >+ __be32 crc, tmp_crc; > >+ unsigned long long sqnum = 0; > >+ > >+ fmsb = &ubi->fm_sb; > >+ fm = &ubi->fm_layout; > >+ > >+ ret = ubi_io_read(ubi, fmsb, fm_anchor, ubi->leb_start, sizeof(*fmsb)); > >+ if (ret && ret != UBI_IO_BITFLIPS) > >+ goto free_fm_sb; > >+ else if (ret == UBI_IO_BITFLIPS) > >+ fm->to_be_tortured[0] = 1; > >+ > >+ if (be32_to_cpu(fmsb->magic) != UBI_FM_SB_MAGIC) { > >+ ubi_err("bad super block magic: 0x%x, expected: 0x%x", > >+ be32_to_cpu(fmsb->magic), UBI_FM_SB_MAGIC); > >+ ret = UBI_BAD_FASTMAP; > >+ goto free_fm_sb; > >+ } > >+ > >+ if (fmsb->version != UBI_FM_FMT_VERSION) { > >+ ubi_err("bad fastmap version: %i, expected: %i", > >+ fmsb->version, UBI_FM_FMT_VERSION); > >+ ret = UBI_BAD_FASTMAP; > >+ goto free_fm_sb; > >+ } > >+ > >+ used_blocks = be32_to_cpu(fmsb->used_blocks); > >+ if (used_blocks > UBI_FM_MAX_BLOCKS || used_blocks < 1) { > >+ ubi_err("number of fastmap blocks is invalid: %i", used_blocks); > >+ ret = UBI_BAD_FASTMAP; > >+ goto free_fm_sb; > >+ } > >+ > >+ fm_size = ubi->leb_size * used_blocks; > >+ if (fm_size != ubi->fm_size) { > >+ ubi_err("bad fastmap size: %zi, expected: %zi", fm_size, > >+ ubi->fm_size); > >+ ret = UBI_BAD_FASTMAP; > >+ goto free_fm_sb; > >+ } > >+ > >+ vh = &ubi->fm_vh; > >+ > >+ for (i = 0; i < used_blocks; i++) { > >+ > >+ pnum = be32_to_cpu(fmsb->block_loc[i]); > >+ > >+ if (ubi_io_is_bad(ubi, pnum)) { > >+ ret = UBI_BAD_FASTMAP; > >+ goto free_hdr; > >+ } > >+ > >+#ifdef LATER > > What means this? I do not know. Thomas probably decided not to handle UBI volumes created by ancient UBI implementations. > >+ int image_seq; > >+ ret = ubi_io_read_ec_hdr(ubi, pnum, ech, 0); > >+ if (ret && ret != UBI_IO_BITFLIPS) { > >+ ubi_err("unable to read fastmap block# %i EC (PEB: %i)", > >+ i, pnum); > >+ if (ret > 0) > >+ ret = UBI_BAD_FASTMAP; > >+ goto free_hdr; > >+ } else if (ret == UBI_IO_BITFLIPS) > >+ fm->to_be_tortured[i] = 1; > >+ > >+ image_seq = be32_to_cpu(ech->image_seq); > >+ if (!ubi->image_seq) > >+ ubi->image_seq = image_seq; > >+ /* > >+ * Older UBI implementations have image_seq set to zero, so > >+ * we shouldn't fail if image_seq == 0. > >+ */ > >+ if (image_seq && (image_seq != ubi->image_seq)) { > >+ ubi_err("wrong image seq:%d instead of %d", > >+ be32_to_cpu(ech->image_seq), ubi->image_seq); > >+ ret = UBI_BAD_FASTMAP; > >+ goto free_hdr; > >+ } > >+#endif > >+ ret = ubi_io_read_vid_hdr(ubi, pnum, vh, 0); > >+ if (ret && ret != UBI_IO_BITFLIPS) { > >+ ubi_err("unable to read fastmap block# %i (PEB: %i)", > >+ i, pnum); > >+ goto free_hdr; > >+ } > >+ > >+ /* > >+ * Mainline code rescans the anchor header. We've done > >+ * that already so we merily copy it over. > >+ */ > >+ if (pnum == fm_anchor) > >+ memcpy(vh, ubi->blockinfo + pnum, sizeof(*fm)); > >+ > >+ if (i == 0) { > >+ if (be32_to_cpu(vh->vol_id) != UBI_FM_SB_VOLUME_ID) { > >+ ubi_err("bad fastmap anchor vol_id: 0x%x," \ > >+ " expected: 0x%x", > >+ be32_to_cpu(vh->vol_id), > >+ UBI_FM_SB_VOLUME_ID); > >+ ret = UBI_BAD_FASTMAP; > >+ goto free_hdr; > >+ } > >+ } else { > >+ if (be32_to_cpu(vh->vol_id) != UBI_FM_DATA_VOLUME_ID) { > >+ ubi_err("bad fastmap data vol_id: 0x%x," \ > >+ " expected: 0x%x", > >+ be32_to_cpu(vh->vol_id), > >+ UBI_FM_DATA_VOLUME_ID); > >+ ret = UBI_BAD_FASTMAP; > >+ goto free_hdr; > >+ } > >+ } > >+ > >+ if (sqnum < be64_to_cpu(vh->sqnum)) > >+ sqnum = be64_to_cpu(vh->sqnum); > >+ > >+ ret = ubi_io_read(ubi, ubi->fm_buf + (ubi->leb_size * i), pnum, > >+ ubi->leb_start, ubi->leb_size); > >+ if (ret && ret != UBI_IO_BITFLIPS) { > >+ ubi_err("unable to read fastmap block# %i (PEB: %i, " \ > >+ "err: %i)", i, pnum, ret); > >+ goto free_hdr; > >+ } > >+ } > >+ > >+ fmsb2 = (struct ubi_fm_sb *)(ubi->fm_buf); > >+ tmp_crc = be32_to_cpu(fmsb2->data_crc); > >+ fmsb2->data_crc = 0; > >+ crc = crc32(UBI_CRC32_INIT, ubi->fm_buf, fm_size); > >+ if (crc != tmp_crc) { > >+ ubi_err("fastmap data CRC is invalid"); > >+ ubi_err("CRC should be: 0x%x, calc: 0x%x", tmp_crc, crc); > >+ ret = UBI_BAD_FASTMAP; > >+ goto free_hdr; > >+ } > >+ > >+ fmsb2->sqnum = sqnum; > >+ > >+ fm->used_blocks = used_blocks; > >+ > >+ ret = ubi_attach_fastmap(ubi, ai, fm); > >+ if (ret) { > >+ if (ret > 0) > >+ ret = UBI_BAD_FASTMAP; > >+ goto free_hdr; > >+ } > >+ > >+ ubi->fm = fm; > >+ ubi->fm_pool.max_size = ubi->fm->max_pool_size; > >+ ubi->fm_wl_pool.max_size = ubi->fm->max_wl_pool_size; > >+ nblocks = ubi->peb_count; > >+ fsize = ubi->fsize_mb; > >+ ubi_msg("attached by fastmap %uMB %u blocks", fsize, nblocks); > >+ ubi_dbg("fastmap pool size: %d", ubi->fm_pool.max_size); > >+ ubi_dbg("fastmap WL pool size: %d", ubi->fm_wl_pool.max_size); > >+ > >+out: > >+ if (ret) > >+ ubi_err("Attach by fastmap failed, doing a full scan!"); > >+ return ret; > >+ > >+free_hdr: > >+free_fm_sb: > >+ goto out; > >+} > >+ > >+/* > >+ * Scan the flash and attempt to attach via fastmap > >+ */ > >+static void ipl_scan(struct ubi_scan_info *ubi) > >+{ > >+ unsigned int pnum; > >+ int res; > >+ > >+ /* > >+ * Scan first for the fastmap super block > >+ */ > >+ for (pnum = 0; pnum < UBI_FM_MAX_START; pnum++) { > >+ res = ubi_scan_vid_hdr(ubi, ubi->blockinfo + pnum, pnum); > >+ /* > >+ * We ignore errors here as we are meriliy scanning > >+ * the headers. > >+ */ > >+ if (res != UBI_FASTMAP_ANCHOR) > >+ continue; > >+ > >+ /* > >+ * If fastmap is disabled, continue scanning. This > >+ * might happen because the previous attempt failed or > >+ * the caller disabled it right away. > >+ */ > >+ if (!ubi->fm_enabled) > >+ continue; > >+ > >+ /* > >+ * Try to attach the fastmap, if that fails continue > >+ * scanning. > >+ */ > >+ if (!ubi_scan_fastmap(ubi, NULL, pnum)) > >+ return; > >+ /* > >+ * Fastmap failed. Clear everything we have and start > >+ * over. We are paranoid and do not trust anything. > >+ */ > >+ memset(ubi->volinfo, 0, sizeof(ubi->volinfo)); > >+ pnum = 0; > >+ break; > >+ } > >+ > >+ /* > >+ * Continue scanning, ignore errors, we might find what we are > >+ * looking for, > >+ */ > >+ for (; pnum < ubi->peb_count; pnum++) > >+ ubi_scan_vid_hdr(ubi, ubi->blockinfo + pnum, pnum); > >+} > >+ > >+/* > >+ * Load a logical block of a volume into memory > >+ */ > >+static int ubi_load_block(struct ubi_scan_info *ubi, uint8_t *laddr, > >+ struct ubi_vol_info *vi, u32 vol_id, u32 lnum, > >+ u32 last) > >+{ > >+ struct ubi_vid_hdr *vh, *vrepl; > >+ u32 pnum, crc, dlen; > >+ > >+retry: > >+ /* > >+ * If this is a fastmap run, we try to rescan full, otherwise > >+ * we simply give up. > >+ */ > >+ if (!test_bit(lnum, vi->found)) { > >+ ubi_warn("LEB %d of %d is missing", lnum, last); > >+ return -1; > >+ } > >+ > >+ pnum = vi->lebs_to_pebs[lnum]; > >+ > >+ ubi_dbg("Load vol %u LEB %u PEB %u", vol_id, lnum, pnum); > >+ > >+ if (ubi_io_is_bad(ubi, pnum)) { > >+ ubi_warn("Corrupted mapping block %d PB %d\n", lnum, pnum); > >+ return -1; > >+ } > >+ > >+ if (test_bit(pnum, ubi->corrupt)) > >+ goto find_other; > >+ > >+ /* > >+ * Lets try to read that block > >+ */ > >+ vh = ubi->blockinfo + pnum; > >+ > >+ if (!test_bit(pnum, ubi->scanned)) { > >+ ubi_warn("Vol: %u LEB %u PEB %u not yet scanned", vol_id, > >+ lnum, pnum); > >+ if (ubi_rescan_fm_vid_hdr(ubi, vh, pnum, vol_id, lnum)) > >+ goto find_other; > >+ } > >+ > >+ /* > >+ * Check, if the total number of blocks is correct > >+ */ > >+ if (be32_to_cpu(vh->used_ebs) != last) { > >+ ubi_dbg("Block count missmatch."); > >+ ubi_dbg("vh->used_ebs: %d nrblocks: %d", > >+ be32_to_cpu(vh->used_ebs), last); > >+ generic_set_bit(pnum, ubi->corrupt); > >+ goto find_other; > >+ } > >+ > >+ /* > >+ * Get the data length of this block. > >+ */ > >+ dlen = be32_to_cpu(vh->data_size); > >+ > >+ /* > >+ * Read the data into RAM. We ignore the return value > >+ * here as the only thing which might go wrong are > >+ * bitflips. Try nevertheless. > >+ */ > >+ ubi_io_read(ubi, laddr, pnum, ubi->leb_start, dlen); > >+ > >+ /* Calculate CRC over the data */ > >+ crc = crc32(UBI_CRC32_INIT, laddr, dlen); > >+ > >+ if (crc != be32_to_cpu(vh->data_crc)) { > >+ ubi_warn("Vol: %u LEB %u PEB %u data CRC failure", vol_id, > >+ lnum, pnum); > >+ generic_set_bit(pnum, ubi->corrupt); > >+ goto find_other; > >+ } > >+ > >+ /* We are good. Return the data length we read */ > >+ return dlen; > >+ > >+find_other: > >+ ubi_dbg("Find replacement for LEB %u PEB %u", lnum, pnum); > >+ generic_clear_bit(lnum, vi->found); > >+ vrepl = NULL; > >+ > >+ for (pnum = 0; pnum < ubi->peb_count; pnum++) { > >+ struct ubi_vid_hdr *tmp = ubi->blockinfo + pnum; > >+ u32 t_vol_id = be32_to_cpu(tmp->vol_id); > >+ u32 t_lnum = be32_to_cpu(tmp->lnum); > >+ > >+ if (test_bit(pnum, ubi->corrupt)) > >+ continue; > >+ > >+ if (t_vol_id != vol_id || t_lnum != lnum) > >+ continue; > >+ > >+ if (!test_bit(pnum, ubi->scanned)) { > >+ ubi_warn("Vol: %u LEB %u PEB %u not yet scanned", > >vol_id, > >+ lnum, pnum); > >+ if (ubi_rescan_fm_vid_hdr(ubi, tmp, pnum, vol_id, lnum)) > >+ continue; > >+ } > >+ > >+ /* > >+ * We found one. If its the first, assign it otherwise > >+ * compare the sqnum > >+ */ > >+ generic_set_bit(lnum, vi->found); > >+ > >+ if (!vrepl) { > >+ vrepl = tmp; > >+ continue; > >+ } > >+ > >+ if (be64_to_cpu(vrepl->sqnum) < be64_to_cpu(tmp->sqnum)) > >+ vrepl = tmp; > >+ } > >+ > >+ if (vrepl) { > >+ /* Update the vi table */ > >+ pnum = vrepl - ubi->blockinfo; > >+ vi->lebs_to_pebs[lnum] = pnum; > >+ ubi_dbg("Trying PEB %u for LEB %u", pnum, lnum); > >+ vh = vrepl; > >+ } > >+ goto retry; > >+} > >+ > >+/* > >+ * Load a volume into RAM > >+ */ > >+static int ipl_load(struct ubi_scan_info *ubi, const u32 vol_id, uint8_t > >*laddr) > >+{ > >+ struct ubi_vol_info *vi; > >+ u32 lnum, last; > >+ > >+ if (vol_id >= UBI_SPL_VOL_IDS) > >+ return -1; > >+ > >+ vi = ubi->volinfo + vol_id; > >+ last = vi->last_block + 1; > >+ > >+ /* Read the blocks to RAM, check CRC */ > >+ for (lnum = 0 ; lnum < last; lnum++) { > >+ int res = ubi_load_block(ubi, laddr, vi, vol_id, lnum, last); > >+ > >+ if (res < 0) { > >+ ubi_warn("Failed to load volume %u", vol_id); > >+ return res; > >+ } > >+ /* res is the data length of the read block */ > >+ laddr += res; > >+ } > >+ return 0; > >+} > >+ > >+int ubispl_load_volumes(struct ubispl_info *info, struct ubispl_load *lvols, > >+ int nrvols) > >+{ > >+ struct ubi_scan_info *ubi = info->ubi; > >+ int res, i, fastmap = info->fastmap; > >+ u32 fsize; > >+ > >+retry: > >+ /* > >+ * We do a partial initializiation of @ubi. Cleaning fm_buf is > >+ * not necessary. > >+ */ > >+ memset(ubi, 0, offsetof(struct ubi_scan_info, fm_buf)); > >+ > >+ ubi->read = info->read; > >+ > >+ /* Precalculate the offsets */ > >+ ubi->vid_offset = info->vid_offset; > >+ ubi->leb_start = info->leb_start; > >+ ubi->leb_size = info->peb_size - ubi->leb_start; > >+ ubi->peb_count = info->peb_count; > >+ ubi->peb_offset = info->peb_offset; > >+ > >+ fsize = info->peb_size * info->peb_count; > >+ ubi->fsize_mb = fsize >> 20; > >+ > >+ /* Fastmap init */ > >+ ubi->fm_size = ubi_calc_fm_size(ubi); > >+ ubi->fm_enabled = fastmap; > >+ > >+ for (i = 0; i < nrvols; i++) { > >+ struct ubispl_load *lv = lvols + i; > >+ > >+ generic_set_bit(lv->vol_id, ubi->toload); > >+ } > >+ > >+ ipl_scan(ubi); > >+ > >+ for (i = 0; i < nrvols; i++) { > >+ struct ubispl_load *lv = lvols + i; > >+ > >+ ubi_msg("Load %s (#%d)", lv->name, lv->vol_id); > >+ res = ipl_load(ubi, lv->vol_id, lv->load_addr); > >+ if (res) { > >+ if (fastmap) { > >+ fastmap = 0; > >+ goto retry; > >+ } > >+ ubi_warn("Failed \n"); > >+ return res; > >+ } > >+ } > >+ return 0; > >+} > >diff --git a/drivers/mtd/ubispl/ubispl.h b/drivers/mtd/ubispl/ubispl.h > >new file mode 100644 > >index 0000000..a64a394 > >--- /dev/null > >+++ b/drivers/mtd/ubispl/ubispl.h > >@@ -0,0 +1,136 @@ > >+/* > >+ * Copyright (c) Thomas Gleixner <t...@linutronix.de> > >+ * > >+ * SPDX-License-Identifier: GPL-2.0+ > >+ */ > >+ > >+#ifndef _UBOOT_MTD_UBISPL_H > >+#define _UBOOT_MTD_UBISPL_H > >+ > >+#include "../ubi/ubi-media.h" > >+#include "ubi-wrapper.h" > >+ > >+/* > >+ * The maximum number of volume ids we scan. So you can load volume id > >+ * 0 to (CONFIG_SPL_UBI_VOL_ID_MAX - 1) > >+ */ > >+#define UBI_SPL_VOL_IDS CONFIG_SPL_UBI_VOL_IDS > >+/* > >+ * The size of the read buffer for the fastmap blocks. In theory up to > >+ * UBI_FM_MAX_BLOCKS * CONFIG_SPL_MAX_PEB_SIZE. In practice today > >+ * one or two blocks. > >+ */ > >+#define UBI_FM_BUF_SIZE (UBI_FM_MAX_BLOCKS * > >CONFIG_SPL_UBI_MAX_PEB_SIZE) > >+/* > >+ * The size of the bitmaps for the attach/ scan > >+ */ > >+#define UBI_FM_BM_SIZE ((CONFIG_SPL_UBI_MAX_PEBS / > >BITS_PER_LONG) + 1) > >+/* > >+ * The maximum number of logical erase blocks per loadable volume > >+ */ > >+#define UBI_MAX_VOL_LEBS CONFIG_SPL_UBI_MAX_VOL_LEBS > >+/* > >+ * The bitmap size for the above to denote the found blocks inside the > >volume > >+ */ > >+#define UBI_VOL_BM_SIZE ((UBI_MAX_VOL_LEBS / BITS_PER_LONG) + 1) > >+ > >+/** > >+ * struct ubi_vol_info - UBISPL internal volume represenation > >+ * @last_block: The last block (highest LEB) found for this > >volume > >+ * @found: Bitmap to mark found LEBS > >+ * @lebs_to_pebs: LEB to PEB translation table > >+ */ > >+struct ubi_vol_info { > >+ u32 last_block; > >+ unsigned long found[UBI_VOL_BM_SIZE]; > >+ u32 lebs_to_pebs[UBI_MAX_VOL_LEBS]; > >+}; > >+ > >+/** > >+ * struct ubi_scan_info - UBISPL internal data for FM attach and full scan > >+ * > >+ * @read: Read function to access the flash provided by the caller > >+ * @peb_count: Number of physical erase blocks in the UBI > >FLASH area > >+ * aka MTD partition. > >+ * @peb_offset: Offset of PEB0 in the UBI FLASH area (aka MTD > >partition) > >+ * to the real start of the FLASH in erase blocks. > >+ * @fsize_mb: Size of the scanned FLASH area in MB (stats > >only) > >+ * @vid_offset: Offset from the start of a PEB to the VID header > >+ * @leb_start: Offset from the start of a PEB to the data area > >+ * @leb_size: Size of the data area > >+ * > >+ * @fastmap_pebs: Counter of PEBs "attached" by fastmap > >+ * @fastmap_anchor: The anchor PEB of the fastmap > >+ * @fm_sb: The fastmap super block data > >+ * @fm_vh: The fastmap VID header > >+ * @fm: Pointer to the fastmap layout > >+ * @fm_layout: The fastmap layout itself > >+ * @fm_pool: The pool of PEBs to scan at fastmap attach time > >+ * @fm_wl_pool: The pool of PEBs scheduled for wearleveling > >+ * > >+ * @fm_enabled: Indicator whether fastmap attachment is enabled. > >+ * @fm_used: Bitmap to indicate the PEBS covered by fastmap > >+ * @scanned: Bitmap to indicate the PEBS of which the VID > >header > >+ * hase been physically scanned. > >+ * @corrupt: Bitmap to indicate corrupt blocks > >+ * @toload: Bitmap to indicate the volumes which should be loaded > >+ * > >+ * @blockinfo: The vid headers of the scanned blocks > >+ * @volinfo: The volume information of the interesting > >(toload) > >+ * volumes > >+ * > >+ * @fm_buf: The large fastmap attach buffer > >+ */ > >+struct ubi_scan_info { > >+ int (*read)(u32 pnum, u32 offset, u32 len, > >void *dest); > >+ unsigned int fsize_mb; > >+ unsigned int peb_count; > >+ unsigned int peb_offset; > >+ > >+ unsigned long vid_offset; > >+ unsigned long leb_start; > >+ unsigned long leb_size; > >+ > >+ /* Fastmap: The upstream required fields */ > >+ int fastmap_pebs; > >+ int fastmap_anchor; > >+ size_t fm_size; > >+ struct ubi_fm_sb fm_sb; > >+ struct ubi_vid_hdr fm_vh; > >+ struct ubi_fastmap_layout *fm; > >+ struct ubi_fastmap_layout fm_layout; > >+ struct ubi_fm_pool fm_pool; > >+ struct ubi_fm_pool fm_wl_pool; > >+ > >+ /* Fastmap: UBISPL specific data */ > >+ int fm_enabled; > >+ unsigned long fm_used[UBI_FM_BM_SIZE]; > >+ unsigned long scanned[UBI_FM_BM_SIZE]; > >+ unsigned long corrupt[UBI_FM_BM_SIZE]; > >+ unsigned long toload[UBI_FM_BM_SIZE]; > >+ > >+ /* Data for storing the VID and volume information */ > >+ struct ubi_vol_info volinfo[UBI_SPL_VOL_IDS]; > >+ struct ubi_vid_hdr blockinfo[CONFIG_SPL_UBI_MAX_PEBS]; > >+ > >+ /* The large buffer for the fastmap */ > >+ uint8_t fm_buf[UBI_FM_BUF_SIZE]; > >+}; > >+ > >+#ifdef CFG_DEBUG > >+#define ubi_dbg(fmt, ...) printf("UBI: debug:" fmt "\n", ##__VA_ARGS__) > >+#else > >+#define ubi_dbg(fmt, ...) > >+#endif > >+ > >+#ifdef CONFIG_UBI_SILENCE_MSG > >+#define ubi_msg(fmt, ...) > >+#else > >+#define ubi_msg(fmt, ...) printf("UBI: " fmt "\n", ##__VA_ARGS__) > >+#endif > >+/* UBI warning messages */ > >+#define ubi_warn(fmt, ...) printf("UBI warning: " fmt "\n", ##__VA_ARGS__) > >+/* UBI error messages */ > >+#define ubi_err(fmt, ...) printf("UBI error: " fmt "\n", ##__VA_ARGS__) > >+ > >+#endif > > Isn;t it possible to avoid this duplications ? See above. [...] Best regards, ladis _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot