From: Ladislav Michl Date: Tue, 12 Jul 2016 18:28:13 +0000 (+0200) Subject: spl: support loading from UBI volumes X-Git-Tag: KARO-TXSD-2017-03-15~538 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=bf55cd4f3e3bc0ebf92c81bde1921f983e999451;p=karo-tx-uboot.git spl: support loading from UBI volumes Add support for loading from UBI volumes on the top of NAND and OneNAND. Signed-off-by: Ladislav Michl Reviewed-by: Heiko Schocher --- diff --git a/common/spl/Makefile b/common/spl/Makefile index 2e0f695e46..b15f0f6dcd 100644 --- a/common/spl/Makefile +++ b/common/spl/Makefile @@ -13,8 +13,11 @@ obj-$(CONFIG_SPL_FRAMEWORK) += spl.o obj-$(CONFIG_SPL_LOAD_FIT) += spl_fit.o obj-$(CONFIG_SPL_NOR_SUPPORT) += spl_nor.o obj-$(CONFIG_SPL_YMODEM_SUPPORT) += spl_ymodem.o +ifndef CONFIG_SPL_UBI obj-$(CONFIG_SPL_NAND_SUPPORT) += spl_nand.o obj-$(CONFIG_SPL_ONENAND_SUPPORT) += spl_onenand.o +endif +obj-$(CONFIG_SPL_UBI) += spl_ubi.o obj-$(CONFIG_SPL_NET_SUPPORT) += spl_net.o obj-$(CONFIG_SPL_MMC_SUPPORT) += spl_mmc.o obj-$(CONFIG_SPL_USB_SUPPORT) += spl_usb.o diff --git a/common/spl/spl.c b/common/spl/spl.c index 14320fe75c..e6a1d79425 100644 --- a/common/spl/spl.c +++ b/common/spl/spl.c @@ -330,6 +330,11 @@ static int spl_load_image(u32 boot_device) case BOOT_DEVICE_MMC2_2: return spl_mmc_load_image(boot_device); #endif +#ifdef CONFIG_SPL_UBI + case BOOT_DEVICE_NAND: + case BOOT_DEVICE_ONENAND: + return spl_ubi_load_image(boot_device); +#else #ifdef CONFIG_SPL_NAND_SUPPORT case BOOT_DEVICE_NAND: return spl_nand_load_image(); @@ -338,6 +343,7 @@ static int spl_load_image(u32 boot_device) case BOOT_DEVICE_ONENAND: return spl_onenand_load_image(); #endif +#endif #ifdef CONFIG_SPL_NOR_SUPPORT case BOOT_DEVICE_NOR: return spl_nor_load_image(); diff --git a/common/spl/spl_ubi.c b/common/spl/spl_ubi.c new file mode 100644 index 0000000000..f97e1ef680 --- /dev/null +++ b/common/spl/spl_ubi.c @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2016 + * Ladislav Michl + * + * SPDX-License-Identifier: GPL 2.0+ BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +int spl_ubi_load_image(u32 boot_device) +{ + struct image_header *header; + struct ubispl_info info; + struct ubispl_load volumes[2]; + int ret = 1; + + switch (boot_device) { +#ifdef CONFIG_SPL_NAND_SUPPORT + case BOOT_DEVICE_NAND: + nand_init(); + info.read = nand_spl_read_block; + info.peb_size = CONFIG_SYS_NAND_BLOCK_SIZE; + break; +#endif +#ifdef CONFIG_SPL_ONENAND_SUPPORT + case BOOT_DEVICE_ONENAND: + info.read = onenand_spl_read_block; + info.peb_size = CONFIG_SYS_ONENAND_BLOCK_SIZE; + break; +#endif + default: + goto out; + } + info.ubi = (struct ubi_scan_info *)CONFIG_SPL_UBI_INFO_ADDR; + info.fastmap = 1; + + info.peb_offset = CONFIG_SPL_UBI_PEB_OFFSET; + info.vid_offset = CONFIG_SPL_UBI_VID_OFFSET; + info.leb_start = CONFIG_SPL_UBI_LEB_START; + info.peb_count = CONFIG_SPL_UBI_MAX_PEBS - info.peb_offset; + +#ifdef CONFIG_SPL_OS_BOOT + if (!spl_start_uboot()) { + volumes[0].vol_id = CONFIG_SPL_UBI_LOAD_KERNEL_ID; + volumes[0].load_addr = (void *)CONFIG_SYS_LOAD_ADDR; + volumes[1].vol_id = CONFIG_SPL_UBI_LOAD_ARGS_ID; + volumes[1].load_addr = (void *)CONFIG_SYS_SPL_ARGS_ADDR; + + ret = ubispl_load_volumes(&info, volumes, 2); + if (!ret) { + header = (struct image_header *)volumes[0].load_addr; + spl_parse_image_header(header); + puts("Linux loaded.\n"); + goto out; + } + puts("Loading Linux failed, falling back to U-Boot.\n"); + } +#endif + header = (struct image_header *) + (CONFIG_SYS_TEXT_BASE - sizeof(struct image_header)); + volumes[0].vol_id = CONFIG_SPL_UBI_LOAD_MONITOR_ID; + volumes[0].load_addr = (void *)header; + + ret = ubispl_load_volumes(&info, volumes, 1); + if (!ret) + spl_parse_image_header(header); +out: +#ifdef CONFIG_SPL_NAND_SUPPORT + if (boot_device == BOOT_DEVICE_NAND) + nand_deselect(); +#endif + return ret; +} diff --git a/include/spl.h b/include/spl.h index 23604667fa..8afa0856c5 100644 --- a/include/spl.h +++ b/include/spl.h @@ -71,6 +71,7 @@ void spl_set_header_raw_uboot(void); int spl_parse_image_header(const struct image_header *header); void spl_board_prepare_for_linux(void); void spl_board_prepare_for_boot(void); +int spl_board_ubi_load_image(u32 boot_device); void __noreturn jump_to_image_linux(void *arg); int spl_start_uboot(void); void spl_display_print(void); @@ -84,6 +85,9 @@ int spl_onenand_load_image(void); /* NOR SPL functions */ int spl_nor_load_image(void); +/* UBI SPL functions */ +int spl_ubi_load_image(u32 boot_device); + /* MMC SPL functions */ int spl_mmc_load_image(u32 boot_device);