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