142 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			142 lines
		
	
	
		
			4.1 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
Lightweight UBI and UBI fastmap support
 | 
						|
 | 
						|
# Copyright (C) Thomas Gleixner <tglx@linutronix.de>
 | 
						|
#
 | 
						|
# SPDX-License-Identifier: GPL 2.0+ BSD-3-Clause
 | 
						|
 | 
						|
Scans the UBI information and loads the requested static volumes into
 | 
						|
memory.
 | 
						|
 | 
						|
Configuration Options:
 | 
						|
 | 
						|
   CONFIG_SPL_UBI
 | 
						|
     Enables the SPL UBI support
 | 
						|
 | 
						|
   CONFIG_SPL_UBI_MAX_VOL_LEBS
 | 
						|
     The maximum number of logical eraseblocks which a static volume
 | 
						|
     to load can contain. Used for sizing the scan data structure
 | 
						|
 | 
						|
   CONFIG_SPL_UBI_MAX_PEB_SIZE
 | 
						|
     The maximum physical erase block size. Either a compile time
 | 
						|
     constant or runtime detection. Used for sizing the scan data
 | 
						|
     structure
 | 
						|
 | 
						|
   CONFIG_SPL_UBI_MAX_PEBS
 | 
						|
     The maximum physical erase block count. Either a compile time
 | 
						|
     constant or runtime detection. Used for sizing the scan data
 | 
						|
     structure
 | 
						|
 | 
						|
   CONFIG_SPL_UBI_VOL_IDS
 | 
						|
     The maximum volume ids which can be loaded. Used for sizing the
 | 
						|
     scan data structure.
 | 
						|
 | 
						|
Usage notes:
 | 
						|
 | 
						|
In the board config file define for example:
 | 
						|
 | 
						|
#define CONFIG_SPL_UBI
 | 
						|
#define CONFIG_SPL_UBI_MAX_VOL_LEBS	256
 | 
						|
#define CONFIG_SPL_UBI_MAX_PEB_SIZE	(256*1024)
 | 
						|
#define CONFIG_SPL_UBI_MAX_PEBS		4096
 | 
						|
#define CONFIG_SPL_UBI_VOL_IDS		8
 | 
						|
 | 
						|
The size requirement is roughly as follows:
 | 
						|
 | 
						|
    2k for the basic data structure
 | 
						|
  + CONFIG_SPL_UBI_VOL_IDS * CONFIG_SPL_UBI_MAX_VOL_LEBS * 8
 | 
						|
  + CONFIG_SPL_UBI_MAX_PEBS * 64
 | 
						|
  + CONFIG_SPL_UBI_MAX_PEB_SIZE * UBI_FM_MAX_BLOCKS
 | 
						|
 | 
						|
The last one is big, but I really don't care in that stage. Real world
 | 
						|
implementations only use the first couple of blocks, but the code
 | 
						|
handles up to UBI_FM_MAX_BLOCKS.
 | 
						|
 | 
						|
Given the above configuration example the requirement is about 5M
 | 
						|
which is usually not a problem to reserve in the RAM along with the
 | 
						|
other areas like the kernel/dts load address.
 | 
						|
 | 
						|
So something like this will do the trick:
 | 
						|
 | 
						|
#define SPL_FINFO_ADDR			0x80800000
 | 
						|
#define SPL_DTB_LOAD_ADDR		0x81800000
 | 
						|
#define SPL_KERNEL_LOAD_ADDR		0x82000000
 | 
						|
 | 
						|
In the board file, implement the following:
 | 
						|
 | 
						|
static struct ubispl_load myvolumes[] = {
 | 
						|
	{
 | 
						|
		.vol_id		= 0,	/* kernel volume */
 | 
						|
		.load_addr	= (void *)SPL_KERNEL_LOAD_ADDR,
 | 
						|
	},
 | 
						|
	{
 | 
						|
		.vol_id		= 1,	/* DT blob */
 | 
						|
		.load_addr	= (void *)SPL_DTB_LOAD_ADDR,
 | 
						|
	}
 | 
						|
};
 | 
						|
 | 
						|
int spl_start_uboot(void)
 | 
						|
{
 | 
						|
	struct ubispl_info info;
 | 
						|
 | 
						|
	info.ubi = (struct ubi_scan_info *) SPL_FINFO_ADDR;
 | 
						|
	info.fastmap = 1;
 | 
						|
	info.read = nand_spl_read_flash;
 | 
						|
 | 
						|
#if COMPILE_TIME_DEFINED
 | 
						|
	/*
 | 
						|
	 * MY_NAND_NR_SPL_PEBS is the number of physical erase blocks
 | 
						|
	 * in the FLASH which are reserved for the SPL. Think about
 | 
						|
	 * mtd partitions:
 | 
						|
	 *
 | 
						|
	 * part_spl { .start = 0, .end = 4 }
 | 
						|
	 * part_ubi { .start = 4, .end = NR_PEBS }
 | 
						|
	 */
 | 
						|
	info.peb_offset = MY_NAND_NR_SPL_PEBS;
 | 
						|
	info.peb_size = CONFIG_SYS_NAND_BLOCK_SIZE;
 | 
						|
	info.vid_offset = MY_NAND_UBI_VID_OFFS;
 | 
						|
	info.leb_start = MY_NAND_UBI_DATA_OFFS;
 | 
						|
	info.peb_count = MY_NAND_UBI_NUM_PEBS;
 | 
						|
#else
 | 
						|
	get_flash_info(&flash_info);
 | 
						|
	info.peb_offset = MY_NAND_NR_SPL_PEBS;
 | 
						|
	info.peb_size = flash_info.peb_size;
 | 
						|
 | 
						|
	/*
 | 
						|
	 * The VID and Data offset depend on the capability of the
 | 
						|
	 * FLASH chip to do subpage writes.
 | 
						|
	 *
 | 
						|
	 * If the flash chip supports subpage writes, then the VID
 | 
						|
	 * header starts at the second subpage. So for 2k pages size
 | 
						|
	 * with 4 subpages the VID offset is 512. The DATA offset is 2k.
 | 
						|
	 *
 | 
						|
	 * If the flash chip does not support subpage writes then the
 | 
						|
	 * VID offset is FLASH_PAGE_SIZE and the DATA offset
 | 
						|
	 * 2 * FLASH_PAGE_SIZE
 | 
						|
	 */
 | 
						|
	info.vid_offset = flash_info.vid_offset;
 | 
						|
	info.leb_start = flash_info.data_offset;
 | 
						|
 | 
						|
	/*
 | 
						|
	 * The flash reports the total number of erase blocks, so
 | 
						|
	 * we need to subtract the number of blocks which are reserved
 | 
						|
	 * for the SPL itself and not managed by UBI.
 | 
						|
	 */
 | 
						|
	info.peb_count = flash_info.peb_count - MY_NAND_NR_SPL_PEBS;
 | 
						|
#endif
 | 
						|
 | 
						|
	ret = ubispl_load_volumes(&info, myvolumes, ARRAY_SIZE(myvolumes);
 | 
						|
 | 
						|
	....
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
Note: you can load any payload that way. You can even load u-boot from
 | 
						|
UBI, so the only non UBI managed FLASH area is the one which is
 | 
						|
reserved for the SPL itself and read from the SoC ROM.
 | 
						|
 | 
						|
And you can do fallback scenarios:
 | 
						|
 | 
						|
    if (ubispl_load_volumes(&info, volumes0, ARRAY_SIZE(volumes0)))
 | 
						|
        if (ubispl_load_volumes(&info, volumes1, ARRAY_SIZE(volumes1)))
 | 
						|
	    ubispl_load_volumes(&info, vol_uboot, ARRAY_SIZE(vol_uboot));
 |