解析移植uboot2017到nuc970的第16天

顺着昨天的整理下

struct spl_image_info {
	const char *name;
	u8 os;
	ulong load_addr;
	ulong entry_point;
	u32 size;
	u32 flags;
};

void board_init_r(gd_t *dummy1, ulong dummy2)
{
	u32 spl_boot_list[] = {
		BOOT_DEVICE_NONE,
		BOOT_DEVICE_NONE,
		BOOT_DEVICE_NONE,
		BOOT_DEVICE_NONE,
		BOOT_DEVICE_NONE,
	};
	struct spl_image_info spl_image;
	if (!(gd->flags & GD_FLG_SPL_INIT)) {
		if (spl_init())
			hang();
	}
	memset(&spl_image, '', sizeof(spl_image));
	board_boot_order(spl_boot_list);
	if (boot_from_devices(&spl_image, spl_boot_list,
			      ARRAY_SIZE(spl_boot_list))) {
		puts("SPL: failed to boot from all boot devicesn");
		hang();
	}
	jump_to_image_no_args(&spl_image);
    
}
上述代码删减了不会编译的部分,和debug部分,及空函数部分

之前分析,最为重要的就是在boot_from_devices实现

static int boot_from_devices(struct spl_image_info *spl_image,
			     u32 spl_boot_list[], int count)
{
	int i;

	for (i = 0; i < count && spl_boot_list[i] != BOOT_DEVICE_NONE; i++) {
		struct spl_image_loader *loader;

		loader = spl_ll_find_loader(spl_boot_list[i]);
#if defined(CONFIG_SPL_SERIAL_SUPPORT) && defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
		if (loader)
			printf("Trying to boot from %sn", loader->name);
		else
			puts("SPL: Unsupported Boot Device!n");
#endif
		if (loader && !spl_load_image(spl_image, loader))
			return 0;
	}

	return -ENODEV;
}
上次的分析已经指明了spl_load_image位于spl_nand.c中的

static int spl_nand_load_image(struct spl_image_info *spl_image,
			 ? ? ? struct spl_boot_device *bootdev)
{
	int err;
	struct image_header *header;
	int *src __attribute__((unused));
	int *dst __attribute__((unused));
	nand_init();
	/*use CONFIG_SYS_TEXT_BASE as temporary storage area */
	header = (struct image_header *)(CONFIG_SYS_TEXT_BASE);
#ifdef CONFIG_NAND_ENV_DST
	spl_nand_load_element(spl_image, CONFIG_ENV_OFFSET, header);
#ifdef CONFIG_ENV_OFFSET_REDUND
	spl_nand_load_element(spl_image, CONFIG_ENV_OFFSET_REDUND, header);
#endif
#endif
	/* Load u-boot */
	err = spl_nand_load_element(spl_image, CONFIG_SYS_NAND_U_BOOT_OFFS,
				 ? ?header);
	nand_deselect();
	return err;
}
#endif
以上代码删去不会编译的,空代码,及debug

在分析这个函数之前先看

typedef struct image_header {
	__be32		ih_magic;	/* Image Header Magic Number	*/
	__be32		ih_hcrc;	/* Image Header CRC Checksum	*/
	__be32		ih_time;	/* Image Creation Timestamp	*/
	__be32		ih_size;	/* Image Data Size		*/
	__be32		ih_load;	/* Data	 Load  Address		*/
	__be32		ih_ep;		/* Entry Point Address		*/
	__be32		ih_dcrc;	/* Image Data CRC Checksum	*/
	uint8_t		ih_os;		/* Operating System		*/
	uint8_t		ih_arch;	/* CPU architecture		*/
	uint8_t		ih_type;	/* Image Type			*/
	uint8_t		ih_comp;	/* Compression Type		*/
	uint8_t		ih_name[IH_NMLEN];	/* Image Name		*/
} image_header_t;
之后到了nand_init()

void nand_init(void)
{
#ifdef CONFIG_SYS_NAND_SELF_INIT
	board_nand_init();
#else
	int i;

	for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)
		nand_init_chip(i);
#endif

	printf("%lu MiBn", total_nand_size / 1024);

#ifdef CONFIG_SYS_NAND_SELECT_DEVICE
	/*
	 * Select the chip in the board/cpu specific driver
	 */
	board_nand_select_device(mtd_to_nand(nand_info[nand_curr_device]),
				 nand_curr_device);
#endif

	create_mtd_concat();
}


这里选择默认的初始化即

nand_init_chip

static void nand_init_chip(int i)
{
	struct nand_chip *nand = &nand_chip[i];
	struct mtd_info *mtd = nand_to_mtd(nand);
	ulong base_addr = base_address[i];
	int maxchips = CONFIG_SYS_NAND_MAX_CHIPS;

	if (maxchips < 1)
		maxchips = 1;

	nand->IO_ADDR_R = nand->IO_ADDR_W = (void  __iomem *)base_addr;

	if (board_nand_init(nand))
		return;

	if (nand_scan(mtd, maxchips))
		return;

	nand_register(i, mtd);
}
这里,从头分析首先看 nand_chip和mtd_info,非常多,这里用到哪里摘出来哪里

struct nand_chip {
	struct mtd_info mtd;


解释了前两句的关系,nand指向nand_chip[0],mtd指向nand->mtd,其中nand_to_mtd为内联函数

其中

tatic ulong base_address[CONFIG_SYS_MAX_NAND_DEVICE] = CONFIG_SYS_NAND_BASE_LIST

而后面的config_sys_nand_base_list由自定义的头文件定义。由注释看见

 * @IO_ADDR_R:		[BOARDSPECIFIC] address to read the 8 I/O lines of the
 *			flash device
 * @IO_ADDR_W:		[BOARDSPECIFIC] address to write the 8 I/O lines of the
 *			flash device.
其为板级指定的nand_flash_base_address

接着

board_nand_init

为板级制定,追踪已有的s3c2410,是17.3rc uboot自带的,我的板级为nuvton

int board_nand_init(struct nand_chip *nand)
{
	u_int32_t cfg;
	u_int8_t tacls, twrph0, twrph1;
	struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();
	struct s3c24x0_nand *nand_reg = s3c24x0_get_base_nand();

	debug("board_nand_init()n");

	writel(readl(&clk_power->clkcon) | (1 << 4), &clk_power->clkcon);

	/* initialize hardware */
#if defined(CONFIG_S3C24XX_CUSTOM_NAND_TIMING)
	tacls  = CONFIG_S3C24XX_TACLS;
	twrph0 = CONFIG_S3C24XX_TWRPH0;
	twrph1 =  CONFIG_S3C24XX_TWRPH1;
#else
	tacls = 4;
	twrph0 = 8;
	twrph1 = 8;
#endif

	cfg = S3C2410_NFCONF_EN;
	cfg |= S3C2410_NFCONF_TACLS(tacls - 1);
	cfg |= S3C2410_NFCONF_TWRPH0(twrph0 - 1);
	cfg |= S3C2410_NFCONF_TWRPH1(twrph1 - 1);
	writel(cfg, &nand_reg->nfconf);

	/* initialize nand_chip data structure */
	nand->IO_ADDR_R = (void *)&nand_reg->nfdata;
	nand->IO_ADDR_W = (void *)&nand_reg->nfdata;

	nand->select_chip = NULL;

	/* read_buf and write_buf are default */
	/* read_byte and write_byte are default */
#ifdef CONFIG_NAND_SPL
	nand->read_buf = nand_read_buf;
#endif

	/* hwcontrol always must be implemented */
	nand->cmd_ctrl = s3c24x0_hwcontrol;

	nand->dev_ready = s3c24x0_dev_ready;

#ifdef CONFIG_S3C2410_NAND_HWECC
	nand->ecc.hwctl = s3c24x0_nand_enable_hwecc;
	nand->ecc.calculate = s3c24x0_nand_calculate_ecc;
	nand->ecc.correct = s3c24x0_nand_correct_data;
	nand->ecc.mode = NAND_ECC_HW;
	nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
	nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
	nand->ecc.strength = 1;
#else
	nand->ecc.mode = NAND_ECC_SOFT;
#endif

#ifdef CONFIG_S3C2410_NAND_BBT
	nand->bbt_options |= NAND_BBT_USE_FLASH;
#endif

	debug("end of nand_initn");

	return 0;
}
nand_scan
int nand_scan(struct mtd_info *mtd, int maxchips)
{
	int ret;

	ret = nand_scan_ident(mtd, maxchips, NULL);
	if (!ret)
		ret = nand_scan_tail(mtd);
	return ret;
}
/**
 * nand_scan_ident - [NAND Interface] Scan for the NAND device
 * @mtd: MTD device structure
 * @maxchips: number of chips to scan for
 * @table: alternative NAND ID table
 *
 * This is the first phase of the normal nand_scan() function. It reads the
 * flash ID and sets up MTD fields accordingly.
 *
 */
int nand_scan_ident(struct mtd_info *mtd, int maxchips,
		    struct nand_flash_dev *table)
{
	int i, nand_maf_id, nand_dev_id;
	struct nand_chip *chip = mtd_to_nand(mtd);
	struct nand_flash_dev *type;
	int ret;

	if (chip->flash_node) {
		ret = nand_dt_init(mtd, chip, chip->flash_node);
		if (ret)
			return ret;
	}

	/* Set the default functions */
	nand_set_defaults(chip, chip->options & NAND_BUSWIDTH_16);

	/* Read the flash type */
	type = nand_get_flash_type(mtd, chip, &nand_maf_id,
				   &nand_dev_id, table);

	if (IS_ERR(type)) {
		if (!(chip->options & NAND_SCAN_SILENT_NODEV))
			pr_warn("No NAND device foundn");
		chip->select_chip(mtd, -1);
		return PTR_ERR(type);
	}

	chip->select_chip(mtd, -1);

	/* Check for a chip array */
	for (i = 1; i < maxchips; i++) {
		chip->select_chip(mtd, i);
		/* See comment in nand_get_flash_type for reset */
		chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
		/* Send the command for reading device ID */
		chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
		/* Read manufacturer and device IDs */
		if (nand_maf_id != chip->read_byte(mtd) ||
		    nand_dev_id != chip->read_byte(mtd)) {
			chip->select_chip(mtd, -1);
			break;
		}
		chip->select_chip(mtd, -1);
	}

#ifdef DEBUG
	if (i > 1)
		pr_info("%d chips detectedn", i);
#endif

	/* Store the number of chips and calc total size for mtd */
	chip->numchips = i;
	mtd->size = i * chip->chipsize;

	return 0;
}
/* Register an initialized NAND mtd device with the U-Boot NAND command. */
int nand_register(int devnum, struct mtd_info *mtd)
{
	if (devnum >= CONFIG_SYS_MAX_NAND_DEVICE)
		return -EINVAL;

	nand_info[devnum] = mtd;

	sprintf(dev_name[devnum], "nand%d", devnum);
	mtd->name = dev_name[devnum];

#ifdef CONFIG_MTD_DEVICE
	/*
	 * Add MTD device so that we can reference it later
	 * via the mtdcore infrastructure (e.g. ubi).
	 */
	add_mtd_device(mtd);
#endif

	total_nand_size += mtd->size / 1024;

	if (nand_curr_device == -1)
		nand_curr_device = devnum;

	return 0;
}


?

思考,如果正确返回nand结构体的值,也意味着正确返回了mtd,之后的函数采用Uboot原版的方式

所以主要重点在于

board_nand_init

*************************************************************************************************************************************

修改,复制13板的文件到自己的板级目录,着重看这个文件

int board_nand_init(struct nand_chip *nand)
{
    struct mtd_info *mtd;
    nuc970_nand = &g_nuc970_nand; //struct nuc970_nand_info g_nuc970_nand;
                     // struct nuc970_nand_info *nuc970_nand;最前面的定义,
    memset((void*)nuc970_nand,0,sizeof(struct nuc970_nand_info)); //CWWeng
	
    if (!nuc970_nand)
        return -1;

    mtd=&nuc970_nand->mtd;
    nuc970_nand->chip.controller = &nuc970_nand->controller;

    /* initialize nand_chip data structure */
    nand->IO_ADDR_R = (void *)REG_SMDATA;
    nand->IO_ADDR_W = (void *)REG_SMDATA;

    /* read_buf and write_buf are default */
    /* read_byte and write_byte are default */
    nand->read_buf = nand_read_buf;

    /* hwcontrol always must be implemented */
    nand->cmd_ctrl = nuc970_hwcontrol;
    nand->cmdfunc = nuc970_nand_command_lp;
    nand->dev_ready = nuc970_dev_ready;
    nand->select_chip = nuc970_nand_select_chip;

    nand->read_byte = nuc970_nand_read_byte;
    nand->write_buf = nuc970_nand_write_buf;
    nand->read_buf = nuc970_nand_read_buf;
    //nand->verify_buf = nuc970_verify_buf;
    nand->chip_delay = 50;

    nand->controller = &nuc970_nand->controller;
    nand->ecc.mode      = NAND_ECC_HW_OOB_FIRST;
    nand->ecc.hwctl     = nuc970_nand_enable_hwecc;
    nand->ecc.calculate = nuc970_nand_calculate_ecc;
    nand->ecc.correct   = nuc970_nand_correct_data;
    nand->ecc.write_page= nuc970_nand_write_page_hwecc;
    nand->ecc.read_page = nuc970_nand_read_page_hwecc_oob_first;
    nand->ecc.read_oob  = nuc970_nand_read_oob_hwecc;
    nand->ecc.layout    = &nuc970_nand_oob;

    mtd->priv = nand;

    /* initial NAND controller */
    writel( (readl(REG_HCLKEN)|(0x300000)), REG_HCLKEN);

    if (readl(REG_PWRON) & 0x08000000)
    {
        writel( 0x55555550, REG_MFP_GPI_L);
        writel( 0x55555555, REG_MFP_GPI_H);
    }
    else
    {
        writel( 0x55555555, REG_MFP_GPC_L);
        writel( 0x05555555, REG_MFP_GPC_H);
    }

    // Enable SM_EN
    writel(NAND_EN, REG_FMICSR);
    writel(0x20305, REG_SMTCR);

    // Enable SM_CS0
    writel((readl(REG_SMCSR)&(~0x06000000))|0x04000000, REG_SMCSR);
    writel(0x1, REG_NFECR); /* un-lock write protect */

    // NAND Reset
    writel(readl(REG_SMCSR) | 0x1, REG_SMCSR);    // software reset
    while (readl(REG_SMCSR) & 0x1);

    /* Detect NAND chips */
    /* first scan to find the device and get the page size */
    if (nand_scan_ident(&(nuc970_nand->mtd), 1, NULL)) {
        printf("NAND Flash not found !n");
        return -1;
    }

这里需要修改,与外面的nand_scan_ident一样,我们只要给正确的mtd指针就行

&(nuc970_nand->mtd),所以这里删掉前面的定义,这里采用外面的结构

删除

 /* Detect NAND chips */
    /* first scan to find the device and get the page size */
    if (nand_scan_ident(&(nuc970_nand->mtd), 1, NULL)) {
        printf("NAND Flash not found !n");
        return -1;
    }

之后都不要变动,makefile,添加编译新的文件,且注意与原来的nand_base间的关系,

obj-y += nuc970_nand.o


检查CONFIG_SPL_NAND_BASE是否定义

将原厂的nand文件放置drivers/mtd/nand/里面注意添加makefile,并注意有没有kconfig的修改

之后看看

/*use CONFIG_SYS_TEXT_BASE as temporary storage area */	header = (struct image_header *)(CONFIG_SYS_TEXT_BASE);
#ifdef CONFIG_NAND_ENV_DST	spl_nand_load_element(spl_image, CONFIG_ENV_OFFSET, header);
#endif	/* Load u-boot */	err = spl_nand_load_element(spl_image, CONFIG_SYS_NAND_U_BOOT_OFFS,				 ? ?header);	nand_deselect();	return err;
}
//这个函数很关键
static int spl_nand_load_element(struct spl_image_info *spl_image,
				 int offset, struct image_header *header)
{
	int err;

	err = nand_spl_load_image(offset, sizeof(*header), (void *)header);
	if (err)
		return err;

	if (IS_ENABLED(CONFIG_SPL_LOAD_FIT) &&
	    image_get_magic(header) == FDT_MAGIC) {
		struct spl_load_info load;

		debug("Found FITn");
		load.dev = NULL;
		load.priv = NULL;
		load.filename = NULL;
		load.bl_len = 1;
		load.read = spl_nand_fit_read;
		return spl_load_simple_fit(spl_image, &load, offset, header);
	} else {
		err = spl_parse_image_header(spl_image, header);
		if (err)
			return err;
		return nand_spl_load_image(offset, spl_image->size,
					   (void *)(ulong)spl_image->load_addr);
	}
}



其中,采用默认的nand_spl_simple.c中,但是不能编译其,需要在另外的位置添加这个函数,换句话说,只是利用了这个文件里面的函数

int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst)
{                       //CONFIG_ENV_OFFSET  sizeof(*header)  (void *)header
  

	unsigned int block, lastblock;
	unsigned int page;

	/*
	 * offs has to be aligned to a page address!
	 */
	block = offs / CONFIG_SYS_NAND_BLOCK_SIZE;
	lastblock = (offs + size - 1) / CONFIG_SYS_NAND_BLOCK_SIZE;
	page = (offs % CONFIG_SYS_NAND_BLOCK_SIZE) / CONFIG_SYS_NAND_PAGE_SIZE;

	while (block <= lastblock) {
		if (!nand_is_bad_block(block)) {
			/*
			 * Skip bad blocks
			 */
			while (page < CONFIG_SYS_NAND_PAGE_COUNT) {
				nand_read_page(block, page, dst);
				dst += CONFIG_SYS_NAND_PAGE_SIZE;
				page++;
			}

			page = 0;
		} else {
			lastblock++;
		}

		block++;
	}

	return 0;
}
nand_read_page
static int nand_read_page(int block, int page, void *dst)
{
	struct nand_chip *this = mtd_to_nand(mtd);
	u_char ecc_calc[ECCTOTAL];
	u_char ecc_code[ECCTOTAL];
	u_char oob_data[CONFIG_SYS_NAND_OOBSIZE];
	int i;
	int eccsize = CONFIG_SYS_NAND_ECCSIZE;
	int eccbytes = CONFIG_SYS_NAND_ECCBYTES;
	int eccsteps = ECCSTEPS;
	uint8_t *p = dst;

	nand_command(block, page, 0, NAND_CMD_READ0);

	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
		if (this->ecc.mode != NAND_ECC_SOFT)
			this->ecc.hwctl(mtd, NAND_ECC_READ);
		this->read_buf(mtd, p, eccsize);
		this->ecc.calculate(mtd, p, &ecc_calc[i]);
	}
	this->read_buf(mtd, oob_data, CONFIG_SYS_NAND_OOBSIZE);

	/* Pick the ECC bytes out of the oob data */
	for (i = 0; i < ECCTOTAL; i++)
		ecc_code[i] = oob_data[nand_ecc_pos[i]];

	eccsteps = ECCSTEPS;
	p = dst;

	for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
		/* No chance to do something with the possible error message
		 * from correct_data(). We just hope that all possible errors
		 * are corrected by this routine.
		 */
		this->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
	}

	return 0;
}
static int nand_command(int block, int page, uint32_t offs,
	u8 cmd)
{
	struct nand_chip *this = mtd_to_nand(mtd);
	int page_addr = page + block * CONFIG_SYS_NAND_PAGE_COUNT;

	while (!this->dev_ready(mtd))
		;

	/* Begin command latch cycle */
	this->cmd_ctrl(mtd, cmd, NAND_CTRL_CLE | NAND_CTRL_CHANGE);
	/* Set ALE and clear CLE to start address cycle */
	/* Column address */
	this->cmd_ctrl(mtd, offs, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
	this->cmd_ctrl(mtd, page_addr & 0xff, NAND_CTRL_ALE); /* A[16:9] */
	this->cmd_ctrl(mtd, (page_addr >> 8) & 0xff,
		       NAND_CTRL_ALE); /* A[24:17] */
#ifdef CONFIG_SYS_NAND_4_ADDR_CYCLE
	/* One more address cycle for devices > 32MiB */
	this->cmd_ctrl(mtd, (page_addr >> 16) & 0x0f,
		       NAND_CTRL_ALE); /* A[28:25] */
#endif
	/* Latch in address */
	this->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);

	/*
	 * Wait a while for the data to be ready
	 */
	while (!this->dev_ready(mtd))
		;

	return 0;
}
//对比13版的,发现简化了不少
static int nand_read_page(struct mtd_info *mtd, int block, int page, uchar *dst)
{
	struct nand_chip *this = mtd->priv;
	int real_page;

	real_page = block * (CONFIG_SYS_NAND_BLOCK_SIZE / CONFIG_SYS_NAND_PAGE_SIZE) + page;

	if (this->ecc.read_page)
		this->ecc.read_page(mtd, this, dst, real_page); //CWWeng : it calls nuc970_nand_read_page_hwecc_oob_first

	return 0;
}
//修改得到我自己的
static int nand_read_page(int block, int page, void *dst)
{
	struct nand_chip *this = mtd_to_nand(mtd);
        int real_page;
        real_page = block * (CONFIG_SYS_NAND_BLOCK_SIZE / CONFIG_SYS_NAND_PAGE_SIZE) + page;

	if (this->ecc.read_page)
		this->ecc.read_page(mtd, this, dst, real_page); //CWWeng : it calls nuc970_nand_read_page_hwecc_oob_first

	return 0;
}
//回过头来最后看
err = spl_parse_image_header(spl_image, header);
if (err)
	return err;
return nand_spl_load_image(offset, spl_image->size,(void *)(ulong)spl_image->load_addr);

spl_parse_image_header
int spl_parse_image_header(struct spl_image_info *spl_image,
			   const struct image_header *header)
{
	u32 header_size = sizeof(struct image_header);

	if (image_get_magic(header) == IH_MAGIC) {
		if (spl_image->flags & SPL_COPY_PAYLOAD_ONLY) {
			/*
			 * On some system (e.g. powerpc), the load-address and
			 * entry-point is located at address 0. We can't load
			 * to 0-0x40. So skip header in this case.
			 */
			spl_image->load_addr = image_get_load(header);
			spl_image->entry_point = image_get_ep(header);
			spl_image->size = image_get_data_size(header);
		} else {
			spl_image->entry_point = image_get_load(header);
			/* Load including the header */
			spl_image->load_addr = spl_image->entry_point -
				header_size;
			spl_image->size = image_get_data_size(header) +
				header_size;
		}
		spl_image->os = image_get_os(header);
		spl_image->name = image_get_name(header);
		debug("spl: payload image: %.*s load addr: 0x%lx size: %dn",
			(int)sizeof(spl_image->name), spl_image->name,
			spl_image->load_addr, spl_image->size);
	} else {
#ifdef CONFIG_SPL_PANIC_ON_RAW_IMAGE
		/*
		 * CONFIG_SPL_PANIC_ON_RAW_IMAGE is defined when the
		 * code which loads images in SPL cannot guarantee that
		 * absolutely all read errors will be reported.
		 * An example is the LPC32XX MLC NAND driver, which
		 * will consider that a completely unreadable NAND block
		 * is bad, and thus should be skipped silently.
		 */
		panic("** no mkimage signature but raw image not supported");
#endif

#ifdef CONFIG_SPL_OS_BOOT
		ulong start, end;

		if (!bootz_setup((ulong)header, &start, &end)) {
			spl_image->name = "Linux";
			spl_image->os = IH_OS_LINUX;
			spl_image->load_addr = CONFIG_SYS_LOAD_ADDR;
			spl_image->entry_point = CONFIG_SYS_LOAD_ADDR;
			spl_image->size = end - start;
			debug("spl: payload zImage, load addr: 0x%lx size: %dn",
			      spl_image->load_addr, spl_image->size);
			return 0;
		}
#endif

#ifdef CONFIG_SPL_ABORT_ON_RAW_IMAGE
		/* Signature not found, proceed to other boot methods. */
		return -EINVAL;
#else
		/* Signature not found - assume u-boot.bin */
		debug("mkimage signature not found - ih_magic = %xn",
			header->ih_magic);
		spl_set_header_raw_uboot(spl_image);
#endif
	}
	return 0;
}

这里面体现了13版和17版的差别,17解析了镜像头部,填充了image的信息,从而做出选择流

return nand_spl_load_image(offset, spl_image->size,(void *)(ulong)spl_image->load_addr);

这里才是真正去加载ubootram

因为手头没有工具,也没有电脑,具体明天开始移植修改?
这里要真的明白一些问题,需要理解env_data,还有uboot,还有header,还有header里面的信息。

当然还有

CONFIG_SYS_TEXT_BASE

这个比较重要的地方
第一遍的认识为,首先进行缓冲存储,此时镜像存储在buffer,最后return真正加载。具体明天细究

几个问题:

1. env_data的组织结构,与uboot的组织结构

2.理解加载地址,运行地址的区别

3.指出来uboot,env_dataload_addr在哪里被指定。

4.nand储存芯片一些必备的常识

相关内容推荐