系统启动后更新u-boot.bin zImage rootf.img
避免掉电时的风险
分区情况
256M分为7个区
u-boot params logo kernel yaffs_1 yaffs_2 config
size 1M 1M 4M 10M 100M 100M 40
58648656
SMDK # mtdparts default
SMDK # mtd
device nand0 <nandflash0>, # parts = 7
#: name size offset mask_flags
0: u-boot 0x00100000 0x00000000 0
1: params 0x00100000 0x00100000 0
2: logo 0x00400000 0x00200000 0
3: kernel 0x00a00000 0x00600000 0
4: yaffs_1 0x06400000 0x01000000 0
5: yaffs_2 0x06400000 0x07400000 0
6: config 0x02800000 0x0d800000 0
active partition: nand0,0 - (u-boot) 0x00100000 @ 0x00000000
defaults:
mtdids : nand0=nandflash0
mtdparts: mtdparts=nandflash0:1m@0(u-boot),1m(params),4m(logo),10m(kernel),100m(yaffs_1),100m(yaffs_2),-(config)
前提:
设置bootargs的u-boot.bin,zImage,rootfs.img的更新标志,不清除标志,系统启动后用dd命令(dd if=/dev/mtd1 of=/uboot_para)备份为uboot_para
(oob和write_page为编写的更新分区的应用程序和页对齐的应用程序,见最下面的代码区)
1.如需要更新zImage时,将编译好的zImage用软件write_page写为页对齐的zImage.bin(/write_page /zImage /zImage.bin),再用软件(/oob /zImage.bin /dev/mtd5)写到mtd5区,(/oob /uboot_para /dev/mtd1)写到params区,重启
2.
u-boot启动时读取params的参数,当有更新u-boot.bin或zImage或rootfs.img的标志时,从对应的config或者yaffs_2读到内存中,然后更新到u-boot.bin zImage yaffs_1对应的区,除了u-boot.bin有掉电写入风险外,zImage和yaffs写入都没有风险.
3.更新完成后将对应的标志清零,保存到env区,然后启动系统即完成了zImage的更新
当运行中掉电时,不影响更新,会再次执行
内存64m,设置读取10m的rootfs
//nfs挂载方式测试
set bootargs console=ttySAC0 root=/dev/nfs nfsroot=192.168.1.117:/opt/rootfs,tcp ip=192.168.1.50:192.168.1.117:192.168.1.1:255.255.255.0:haozi:eth0:off
//实际使用
set bootargs console=ttySAC0,115200 root=/dev/mtdblock4 init=/linuxrc
比用软件直接更新内核区要安全,避免掉电发生时,无法启动系统(除uboot外)
提前设置环境变量
set bootargs console=ttySAC0,115200 root=/dev/mtdblock4 init=/linuxrc
set act_update_uboot nand read 30000000 7400000 100000\;nand erase 0 100000\;nand write 30000000 0 100000\;run act_save_uflag
set act_save_uflag set update_uboot_flag 0\;save\;run bootcmd
set act_update_zImage nand read 30000000 7400000 a00000\;nand erase 600000 a00000\;nand write 30000000 600000 a00000\;run act_save_zflag
set act_save_zflag set update_zImage_flag 0\;save\;run bootcmd
set act_update_rootfs nand read 30000000 7400000 a00000\;nand erase 1000000 a00000\;nand write 30000000 1000000 a00000\;run act_save_rflag
set act_save_rflag set update_rootfs_flag 0\;save\;run bootcmd
set update_zImage_flag 1
set update_rootfs_flag 1
set update_uboot_flag 1
set bootcmd nand read 30008000 600000 a00000\;go 30008000
更新zImage和rootfs.img
uboot所需逻辑
1.判断
update_zImage_flag=1
2.为0时执行run bootcmd
为1时执行run act_update_zImage
main.c中的main_loop中添加my_fun()
void my_fun(void) {
char *s;
int i;
char buf[10] = {0};
s = getenv("update_zImage_flag");
strcpy(buf, s);
i = simple_strtoul(buf, NULL, 10);
printf("i is %d\n", i);
if (i == 1) {
s = getenv ("act_update_zImage");
} else {
s = getenv ("bootcmd");
}
run_command (s, 0);
}
以上仅做了zImage在nfs的测试,其他类似
oob中添加了写入oob的信息,否则uboot无法读取(mtd-util和dd命令没有此功能不能用)
未做处理的部分
1.uboot写时遇到坏块的处理
读时遇到坏块的处理
2.应用程序更新时写到mtd时遇到坏块的处理,ecc处理,越过坏块的处理
write_page.c
#include <stdio.h>
#define CONTROL_SIZE (2048)
int main(int argc, char **argv) {
FILE *fp1, *fp2;
int size;
char buf[CONTROL_SIZE];
int yu;
int i;
char extra[CONTROL_SIZE];
if (argc != 3) {
printf("usage:write_page [source] [target]\n");
return 0;
}
fp1 = fopen(argv[1], "rb");
if (fp1 == NULL) {
fprintf(stderr, "open fail %s\n", argv[1]);
return 0;
}
fp2 = fopen(argv[2], "wb+");
if (fp2 == NULL) {
fprintf(stderr, "open fail %s\n", argv[2]);
return 0;
}
do {
size = fread(buf, 1, CONTROL_SIZE, fp1);
if (size > 0) {
yu = fwrite(buf, 1, size, fp2);
} else {
printf("write over here\n");
break;
}
if (size != CONTROL_SIZE) {
printf("over here\n");
break;
}
} while (1);
if (size != 0) {
size = CONTROL_SIZE - size;
for (i = 0; i < size; i++) {
extra[i] = 0xff;
}
yu = fwrite(extra, 1, size, fp2);
}
fclose(fp1);
fclose(fp2);
return 0;
}
oob.c如下