十、移植u-boot-2016.03到Jz2440之修改源码烧写JFFS2、烧写YAFFS与制作补丁

10. u-boot-2016.03移植之修改源码烧写JFFS2、烧写YAFFS与制作补丁

    前面我们通过修改uboot的代码让它支持串口、nand flash,nor flash,网络下载文件等功能,现在我们来实现最后一个功能,实现Uboot烧写YAFFS文件系统,同时制作uboot补丁方便以后的移植,避免重复造轮子。

10.1 烧写JFFS2文件系统

该uboot已经支持JFFS2文件系统的烧写了,我们先来烧写JFFS2文件系统,命令如下:

nfs 30000000 192.168.0.103:/home/book/works/first_fs/fs_mini_mdev.jffs2  //使用nfs下载fs_mini.jffs2文件系统到30000000地址
nand erase.part rootfs    //擦除rootfs分区
nand write.jffs2 30000000 rootfs $filesize  //使用nand write.jffs2将30000000地址的大小为filesize的文件写到rootfs分区

烧写完后,需要先设置文件系统的类型,在uboot中输入命令:

setenv bootargs console=ttySAC0 root=/dev/mtdblock3 rootfstype=jffs2

然后下载uImage:

nfs 32000000 192.168.0.103:/home/book/works/first_fs/uImage_4.3   //该uImage_4.3是Jz2440开发板资料提供的映像文件

然后输入以下命令,启动linux内核:

bootm 32000000

从下图的打印信息可知,linux成功挂载了JFFS2文件系统,启动成功。
在这里插入图片描述

10.2 修改代码支持YAFFS文件系统烧写

当前uboot不支持烧写YAFFS文件系统,可以验证一下,在uboot下执行以下命令:

nfs 30000000 192.168.0.102:/home/book/works/first_fs/fs_mini_mdev.yaffs2
nand erase.part rootfs
nand write.yaffs 30000000 rootfs $filesize 

打印信息如下:
在这里插入图片描述
上图显示:Unknown nand command suffix '.yaffs'.,说明此时的uboot还没有支持yaffs文件系统是烧写。
在uboot源码目录中搜索:Unknown nand command suffix,定位到cmd/nand.c 的do_nand函数,发现在do_nand函数里,有nand read或write的代码,而其中有对jffs2的支持,却并没有对yaffs2的支持。我们可以参考老版本的uboot(例如u-boot-2012.04.01的),在do_nand函数里的nand write/read部分加上一段代码,如下:

#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(nand, off, &rwsize, NULL,
                        maxsize, (u_char *)addr,
                        WITH_DROP_FFS | WITH_WR_VERIFY);
#endif
/*上面是原代码,在这里添加如下代码*/
#ifdef CONFIG_CMD_NAND_YAFFS
         } else if (!strcmp(s, ".yaffs")) {
    
    
            if (read) {
    
    
                printf("Unknown nand command suffix ‘%s‘.\n", s);
                 return 1;
            }
            ret = nand_write_skip_bad(nand, off, &rwsize,NULL,//这里参数和老版比要修改下
                        maxsize,(u_char *)addr,
                         WITH_YAFFS_OOB);
#endif

nand_help_text[]里添加nand write.yaffs的帮助信息:(在cmd/nand.c)

#ifdef CONFIG_CMD_NAND_YAFFS
    "nand write.yaffs - addr off|partition size\n"
    "    write ‘size‘ bytes starting at offset ‘off‘ with yaffs format\n"
    "    from memory address ‘addr‘, skipping bad blocks.\n"
#endif  

修改nand_write_skip_bad函数,该函数代码如下:(该函数在drivers/mtd/nand/nand_util.c)

int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
		size_t *actual, loff_t lim, u_char *buffer, int flags)
{
    
    
	int rval = 0, blocksize;
	size_t left_to_write = *length;
	size_t used_for_write = 0;
	u_char *p_buffer = buffer;
	int need_skip;

	if (actual)
		*actual = 0;
/*以下是添加*/
#ifdef CONFIG_CMD_NAND_YAFFS                                                       
     if (flags & WITH_YAFFS_OOB) {
    
                                                      
        if (flags & ~WITH_YAFFS_OOB)                                               
            return -EINVAL;                                                        
                                                                                   
        int pages;                                                                 
        pages = nand->erasesize / nand->writesize;                                 
        blocksize = (pages * nand->oobsize) + nand->erasesize;                     
        if (*length % (nand->writesize + nand->oobsize)) {
    
                             
            printf ("Attempt to write incomplete page"                             
                " in yaffs mode\n");                                               
            return -EINVAL;                                                        
        }                                                                          
    } else                                                                         
#endif /*以上是添加*/ 
	{
    
    
		blocksize = nand->erasesize;
	}
	/*
	 * nand_write() handles unaligned, partial page writes.
	 *
	 * We allow length to be unaligned, for convenience in
	 * using the $filesize variable.
	 *
	 * However, starting at an unaligned offset makes the
	 * semantics of bad block skipping ambiguous (really,
	 * you should only start a block skipping access at a
	 * partition boundary).  So don't try to handle that.
	 */
	if ((offset & (nand->writesize - 1)) != 0) {
    
    
		printf("Attempt to write non page-aligned data\n");
		*length = 0;
		return -EINVAL;
	}

	need_skip = check_skip_len(nand, offset, *length, &used_for_write);

	if (actual)
		*actual = used_for_write;

	if (need_skip < 0) {
    
    
		printf("Attempt to write outside the flash area\n");
		*length = 0;
		return -EINVAL;
	}

	if (used_for_write > lim) {
    
    
		puts("Size of write exceeds partition or device limit\n");
		*length = 0;
		return -EFBIG;
	}

	if (!need_skip && !(flags & WITH_DROP_FFS)) {
    
    
		rval = nand_write(nand, offset, length, buffer);

		if ((flags & WITH_WR_VERIFY) && !rval)
			rval = nand_verify(nand, offset, *length, buffer);

		if (rval == 0)
			return 0;

		*length = 0;
		printf("NAND write to offset %llx failed %d\n",
			offset, rval);
		return rval;
	}

	while (left_to_write > 0) {
    
    
		size_t block_offset = offset & (nand->erasesize - 1);
		size_t write_size, truncated_write_size;

		WATCHDOG_RESET();

		if (nand_block_isbad(nand, offset & ~(nand->erasesize - 1))) {
    
    
			printf("Skip bad block 0x%08llx\n",
				offset & ~(nand->erasesize - 1));
			offset += nand->erasesize - block_offset;
			continue;
		}

		if (left_to_write < (blocksize - block_offset))
			write_size = left_to_write;
		else
			write_size = blocksize - block_offset;
#ifdef CONFIG_CMD_NAND_YAFFS     /*以下是添加*/                                                  
		if (flags & WITH_YAFFS_OOB) {
    
                                                  
			int page, pages;                                                       
            size_t pagesize = nand->writesize;                                     
			size_t pagesize_oob = pagesize + nand->oobsize;                        
			struct mtd_oob_ops ops;                                                
                                                                               
			ops.len = pagesize;                                                    
			ops.ooblen = nand->oobsize;                                            
			ops.mode = MTD_OPS_RAW;       //这里要改为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 = nand->_write_oob(nand, offset, &ops);                        
				if (rval != 0) 
					 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(nand, p_buffer,
					&write_size);
#endif

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

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

		offset += write_size;
		p_buffer += write_size;
	  } /*这里要添加右大括号*/
		if (rval != 0) {
    
    
			printf("NAND write to offset %llx failed %d\n",
				offset, rval);
			*length -= left_to_write;
			return rval;
		}

		left_to_write -= write_size;
	}

	return 0;
}

10.3 测试

修改好代码后,重新编译uboot,烧写到开发板NOR Flash,重新启动输入以下命令:

nfs 30000000 192.168.0.102:/home/book/works/first_fs/fs_mini_mdev.yaffs2
nand erase.part rootfs
nand write.yaffs 30000000 rootfs $filesize  //烧写文件系统
setenv bootargs console=ttySAC0 root=/dev/mtdblock3 rootfstype=yaffs
nfs 32000000 192.168.0.102:/home/book/works/first_fs/uImage_4.3   //该uImage_4.3是Jz2440开发板资料提供的映像文件
bootm 32000000

打印信息如下:
在这里插入图片描述
从下图的打印信息可知,linux成功挂载了YAFFS2文件系统,启动成功。
在这里插入图片描述

10.4 制作补丁

在uboot根目录执行如下命令:

make distclean    (清除之前编译生成的所有文件)
rm u-boot.dis
cd ..
mv u-boot-2016.03 u-boot-2016.03_jz2440    (重命名)
tar xjf u-boot-2016.03.tar.bz2    (解压得到源码)
diff -urN u-boot-2016.03 u-boot-2016.03_jz2440 > u-boot-2016.03_jz2440.patch    (这就是补丁文件名)

打补丁命令:

cd u-boot-2016.03
patch -p1 < ../u-boot-2016.03_jz2440.patch

u-boot-2016.03_jz2440.patch补丁文件的下载地址:https://download.csdn.net/download/qq_35031421/12232755

猜你喜欢

转载自blog.csdn.net/qq_35031421/article/details/104528381