1// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause 2/* 3 * Copyright (C) 2016 4 * Ladislav Michl <ladis@linux-mips.org> 5 */ 6 7#include <common.h> 8#include <config.h> 9#include <image.h> 10#include <nand.h> 11#include <onenand_uboot.h> 12#include <ubispl.h> 13#include <spl.h> 14 15int spl_ubi_load_image(struct spl_image_info *spl_image, 16 struct spl_boot_device *bootdev) 17{ 18 struct legacy_img_hdr *header; 19 struct ubispl_info info; 20 struct ubispl_load volumes[2]; 21 int ret = 1; 22 23 switch (bootdev->boot_device) { 24#ifdef CONFIG_SPL_NAND_SUPPORT 25 case BOOT_DEVICE_NAND: 26 nand_init(); 27 info.read = nand_spl_read_block; 28 info.peb_size = CONFIG_SYS_NAND_BLOCK_SIZE; 29 break; 30#endif 31#ifdef CONFIG_SPL_ONENAND_SUPPORT 32 case BOOT_DEVICE_ONENAND: 33 info.read = onenand_spl_read_block; 34 info.peb_size = CFG_SYS_ONENAND_BLOCK_SIZE; 35 break; 36#endif 37 default: 38 goto out; 39 } 40 info.ubi = (struct ubi_scan_info *)CONFIG_SPL_UBI_INFO_ADDR; 41 info.fastmap = IS_ENABLED(CONFIG_MTD_UBI_FASTMAP); 42 43 info.peb_offset = CONFIG_SPL_UBI_PEB_OFFSET; 44 info.vid_offset = CONFIG_SPL_UBI_VID_OFFSET; 45 info.leb_start = CONFIG_SPL_UBI_LEB_START; 46 info.peb_count = CONFIG_SPL_UBI_MAX_PEBS - info.peb_offset; 47 48#if CONFIG_IS_ENABLED(OS_BOOT) 49 if (!spl_start_uboot()) { 50 volumes[0].vol_id = CONFIG_SPL_UBI_LOAD_KERNEL_ID; 51 volumes[0].load_addr = (void *)CONFIG_SYS_LOAD_ADDR; 52 volumes[1].vol_id = CONFIG_SPL_UBI_LOAD_ARGS_ID; 53 volumes[1].load_addr = (void *)CONFIG_SPL_PAYLOAD_ARGS_ADDR; 54 55 ret = ubispl_load_volumes(&info, volumes, 2); 56 if (!ret) { 57 header = (struct legacy_img_hdr *)volumes[0].load_addr; 58 spl_parse_image_header(spl_image, bootdev, header); 59 puts("Linux loaded.\n"); 60 goto out; 61 } 62 puts("Loading Linux failed, falling back to U-Boot.\n"); 63 } 64#endif 65 header = spl_get_load_buffer(-sizeof(*header), sizeof(header)); 66#ifdef CONFIG_SPL_UBI_LOAD_BY_VOLNAME 67 volumes[0].vol_id = -1; 68 strncpy(volumes[0].name, 69 CONFIG_SPL_UBI_LOAD_MONITOR_VOLNAME, 70 UBI_VOL_NAME_MAX + 1); 71#else 72 volumes[0].vol_id = CONFIG_SPL_UBI_LOAD_MONITOR_ID; 73#endif 74 volumes[0].load_addr = (void *)header; 75 76 ret = ubispl_load_volumes(&info, volumes, 1); 77 if (!ret) 78 spl_parse_image_header(spl_image, bootdev, header); 79out: 80#ifdef CONFIG_SPL_NAND_SUPPORT 81 if (bootdev->boot_device == BOOT_DEVICE_NAND) 82 nand_deselect(); 83#endif 84 return ret; 85} 86/* Use priorty 0 so that Ubi will override NAND and ONENAND methods */ 87SPL_LOAD_IMAGE_METHOD("NAND", 0, BOOT_DEVICE_NAND, spl_ubi_load_image); 88SPL_LOAD_IMAGE_METHOD("OneNAND", 0, BOOT_DEVICE_ONENAND, spl_ubi_load_image); 89