移植u-boot-2016.11到JZ2440(七:修改源码之烧写JFFS2、烧写YAFFS与制作补丁)

目录

7. 修改源码之烧写JFFS2、烧写YAFFS与制作补丁
    7.1 烧写JFFS2
    7.2 烧写YAFFS
        7.2.1 分析nand write.yaffs
        7.2.2 修改代码
            7.2.2.1 添加nand操作帮助信息
            7.2.2.2 添加支持nand write.yaffs操作代码
            7.2.2.3 修改nand_write_skip_bad()函数
            7.2.2.4 添加宏
        7.2.3 测试
    7.3 制作补丁


7. 修改源码之烧写JFFS2、烧写YAFFS与制作补丁

7.1 烧写JFFS2

    该uboot已经支持JFFS2文件格式的烧写,启动进入命令行,准备好匹配的uImage内核与fs_mini.jffs2文件系统文件,使用如下命令:
      tftp 30000000 fs_mini.jffs2    (下载fs_mini.jffs2文件系统到30000000地址)
      nand erase.part rootfs    (擦除rootfs分区)
      nand write.jffs2 30000000 rootfs $filesize    (使用nand write.jffs2将30000000地址的大小为filesize的文件写到rootfs分区)
      set bootargs console=ttySAC0 root=/dev/mtdblock3 rootfstype= jffs2     (设置启动参数)
      save   
     如果NAND Flash里没有内核再使用移植u-boot-2016.11到JZ2440(六:修改源码之环境变量、裁剪uboot与设置分区)的6.2.2 使用分区名烧写文件方式烧写uImage。重启uboot或者执行bootm 30000000命令就能启动内核运行fs_mini.jffs2文件系统了。

7.2 烧写YAFFS

7.2.1 分析nand write.yaffs

    当前uboot不支持烧写YAFFS文件系统,在uboot下执行nand write.yaffs 30000000 rootfs $(filesize)有如下错误:

NAND write: device 0 offset 0x260000, size 0x59ad78
Unknown nand command suffix '.yaffs'.
JZ2440 #

在源码查找“Unknown nand command suffix”定位到cmd/nand.c文件的do_nand()函数,部分代码如下:

static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
        ... ...
        if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
            ... ...

		if (!s || !strcmp(s, ".jffs2") ||
		    !strcmp(s, ".e") || !strcmp(s, ".i")) {
			if (read)
				ret = nand_read_skip_bad(mtd, off, &rwsize,
							 NULL, maxsize,
							 (u_char *)addr);
			else
				ret = nand_write_skip_bad(mtd, off, &rwsize,
							  NULL, maxsize,
							  (u_char *)addr,
							  WITH_WR_VERIFY);
#ifdef CONFIG_CMD_NAND_TRIMFFS
		} else if (!strcmp(s, ".trimffs")) {
			if (read) {
				printf("Unknown nand command suffix '%s'\n", s);
				return 1;
			}
			ret = nand_write_skip_bad(mtd, off, &rwsize, NULL,
						maxsize, (u_char *)addr,
						WITH_DROP_FFS | WITH_WR_VERIFY);
#endif
		} else if (!strcmp(s, ".oob")) {
			/* out-of-band data */
			mtd_oob_ops_t ops = {
				.oobbuf = (u8 *)addr,
				.ooblen = rwsize,
				.mode = MTD_OPS_RAW
			};

			if (read)
				ret = mtd_read_oob(mtd, off, &ops);
			else
				ret = mtd_write_oob(mtd, off, &ops);
		} else if (raw) {
			ret = raw_access(mtd, addr, off, pagecount, read,
					 no_verify);
		} else {
			printf("Unknown nand command suffix '%s'.\n", s);
			return 1;
		}

		printf(" %zu bytes %s: %s\n", rwsize,
		       read ? "read" : "written", ret ? "ERROR" : "OK");

		return ret == 0 ? 0 : 1;
	}
        ... ...
}

    对比u-boot-2012.04.01发现u-boot-2016.11已经剔除了yaffs的代码,我们仿造移植u-boot-2012.04.01到JZ2440(七:修改源码之烧写JFFS2、烧写YAFFS与制作补丁)的7.2.1 分析nand write.yaffs小结来添加支持烧写yaffs的代码。

7.2.2 修改代码

7.2.2.1 添加nand操作帮助信息

    uboot命令行输入nand有如下输出:
    移植u-boot-2016.11到JZ2440(七:修改源码之烧写JFFS2、烧写YAFFS与制作补丁)_第1张图片
    打印的就是nand_help_text数组里的字符串,如下:
    移植u-boot-2016.11到JZ2440(七:修改源码之烧写JFFS2、烧写YAFFS与制作补丁)_第2张图片
    我们也添加yaffs2相关的帮助信息。在#endif后面添加如下代码cmd/nand.c文件中

#ifdef CONFIG_CMD_NAND_YAFFS
	"nand write.yaffs2 - addr off|partition size\n"
	"    write 'size' bytes starting at offset 'off' from memory address\n"
	"    'addr', skipping bad blocks and dropping any pages at the end\n"
	"    of eraseblocks that contain only 0xFF\n"
#endif

7.2.2.2 添加支持nand write.yaffs操作代码

    仿造u-boot-2012.04.01的源码在do_nand()函数中添加如下代码cmd/nand.c文件中

#ifdef CONFIG_CMD_NAND_YAFFS
		} else if (!strcmp(s, ".yaffs2")) {
			if (read) {
				printf("Unknown nand command suffix '%s'\n", s);
				return 1;
			}
			ret = nand_write_skip_bad(mtd, off, &rwsize, NULL,
						maxsize, (u_char *)addr,
						WITH_YAFFS_OOB);
#endif

    也就是添加到do_nand()函数的下图位置cmd/nand.c文件中
    移植u-boot-2016.11到JZ2440(七:修改源码之烧写JFFS2、烧写YAFFS与制作补丁)_第3张图片

    其中调用的nand_write_skip_bad()函数与u-boot.2012.04.01版本参数不一样了,仿造CONFIG_CMD_NAND_TRIMFFS宏内的代码编写参数。

7.2.2.3 修改nand_write_skip_bad()函数

    同样在nand_write_skip_bad()函数中仿造u-boot-2012.04.01版本添加支持yaffs2操作代码,将源码nand_write_skip_bad()函数如下内容(drivers/mtd/nand/nand_util.c文件中)
    移植u-boot-2016.11到JZ2440(七:修改源码之烧写JFFS2、烧写YAFFS与制作补丁)_第4张图片

    红框部分内容修改成如下代码:

#ifdef CONFIG_CMD_NAND_YAFFS
	if (flags & WITH_YAFFS_OOB) {
		if (flags & ~WITH_YAFFS_OOB)
			return -EINVAL;

		int pages;
		pages = mtd->erasesize / mtd->writesize;
		blocksize = (pages * mtd->oobsize) + mtd->erasesize;
		if (*length % (mtd->writesize + mtd->oobsize)) {
			printf ("Attempt to write incomplete page"
				" in yaffs2 mode\n");
			return -EINVAL;
		}
	} else
#endif
	{
		blocksize = mtd->erasesize;
	}

    再将如下内容:
    移植u-boot-2016.11到JZ2440(七:修改源码之烧写JFFS2、烧写YAFFS与制作补丁)_第5张图片
   红框部分内容修改成如下代码:

#ifdef CONFIG_CMD_NAND_YAFFS
		if (flags & WITH_YAFFS_OOB) {
			int page, pages;
			size_t pagesize = mtd->writesize;
			size_t pagesize_oob = pagesize + mtd->oobsize;
			struct mtd_oob_ops ops;

			ops.len = pagesize;
			ops.ooblen = mtd->oobsize;
			ops.mode = MTD_OPS_RAW;
			ops.ooboffs = 0;

			pages = write_size / pagesize_oob;
			for (page = 0; page < pages; page++) {
				WATCHDOG_RESET();

				ops.datbuf = p_buffer;
				ops.oobbuf = ops.datbuf + pagesize;

				rval = mtd->_write_oob(mtd, offset, &ops);
				if (rval)
					break;

				offset += pagesize;
				p_buffer += pagesize_oob;
			}
		}
		else
#endif
		{
			truncated_write_size = write_size;
#ifdef CONFIG_CMD_NAND_TRIMFFS
		if (flags & WITH_DROP_FFS)
			truncated_write_size = drop_ffs(mtd, p_buffer,
					&write_size);
#endif

		rval = nand_write(mtd, offset, &truncated_write_size,
				p_buffer);

		if ((flags & WITH_WR_VERIFY) && !rval)
			rval = nand_verify(mtd, offset,
				truncated_write_size, p_buffer);

		offset += write_size;
		p_buffer += write_size;
		}

7.2.2.4 添加宏

    再添加上面使用的相应宏。在单板头文件include/configs/jz2440.h中添加如下定义:

#define CONFIG_CMD_NAND_YAFFS

    同样还需将该宏添加到scripts/config_whitelist.txt文件:
   
    在include/nand.h文件中添加#define WITH_YAFFS_OOB  (1 << 0)如下:
   

7.2.3 测试

    重新编译烧写uboot,启动进入命令行,输入nand命令如下:
    移植u-boot-2016.11到JZ2440(七:修改源码之烧写JFFS2、烧写YAFFS与制作补丁)_第6张图片
    帮助信息已经正确添加了,再测试烧写yaffs2文件,准备好匹配的uImage内核与fs_mini.yffs2文件系统文件,执行命令如下:
      tftp 30000000 fs_mini.yaffs2    (下载fs_mini.yffs2文件系统到30000000地址)
      nand erase.part rootfs    (擦除rootfs分区)
      nand write.yaffs2 30000000 rootfs $(filesize)    (使用nand write.yffs2将30000000地址的大小为filesize的文件写到rootfs分区)
      set bootargs console=ttySAC0 root=/dev/mtdblock3 rootfstype=yaffs    (设置启动参数)
      save
   
移植u-boot-2016.11到JZ2440(七:修改源码之烧写JFFS2、烧写YAFFS与制作补丁)_第7张图片
    再输入nand dump 260000命令,如下:
    移植u-boot-2016.11到JZ2440(七:修改源码之烧写JFFS2、烧写YAFFS与制作补丁)_第8张图片
    fs_mini.yaffs2文件部分内容如下:
    移植u-boot-2016.11到JZ2440(七:修改源码之烧写JFFS2、烧写YAFFS与制作补丁)_第9张图片

    可以看到fs_mini.yaffs2文件里的OOB数据正确写入NAND FlashOOB区域了。

对于64ByteOOB而言,数据定义如下所示:
    Byte0表示该块的数据是否为坏,若为0xFF表示好的,0x00则是坏的;
    Byte1暂时没用到;
    Byte2~39表示用来存放oob数据,若是yaffs文件,则会存放yaffs参数;
    Byte40~63存放ecc校验值,该页的每256字节,就会生成3字节数据存放到ecc里。

    如果NAND Flash里没有内核再使用移植u-boot-2016.11到JZ2440(六:修改源码之环境变量、裁剪uboot与设置分区)的6.2.2 使用分区名烧写文件方式烧写uImage。重启uboot或者执行bootm 30000000命令就能启动内核运行fs_mini.yffs2文件系统了。

7.3 制作补丁

    uboot根目录执行如下命令:
      make distclean    (清除之前编译生成的所有文件)
      make clean
      rm u-boot.dis
      cd ..
      mv u-boot-2016.11 u-boot-2016.11_jz2440   
(重命名)
      tar xjf u-boot-2016.11.tar.bz2    (解压得到源码)
      diff -urN u-boot-2016.11 u-boot-2016.11_jz2440 > u-boot-2016.11_jz2440.patch    (这就是补丁文件名)
    使用补丁只需输入如下命令:   
      tar xjf u-boot-2016.11.tar.bz2
      cd u-boot-2016.11
      patch -p1 <   ../u-boot-2016.11_jz2440.patch
      make jz2440_defconfig
      make

你可能感兴趣的:(uboot移植)