标签:kernel arr vol 分区 echo 主备 ubi rootfs
ubi 分区
这边只记录实战,其他博客上写的很常见的内容就不介绍啦。
通常介绍的ubi使用都是例如左图中的方法,也就是flash设备,并不是所有的空间都被格式化为ubi的分区。仍有其他文件系统直接在mtd分区之上。而右图中,所有的flash都被格式化为ubi分区。而在ubi之上,会有多个卷,这才是呈现给用户的分区。但是实际上只有一个mtd。也就是说用户看到的分区,不直接是mtd的分区。这样的好处是:
- UBI 系统提供了基于大的MTD 分区的坏块管理和擦写均衡
- 基于 UBI Volume 的升级接口,由 UBI 系统管理坏块,实现容易
- UBI Volume 的大小可以动态调整,分区调整的更加容易
uboot环境变量设置
#define CONFIG_BOOTARGS "console=ttyAMA0,115200n8 ubi.mtd=1 ubi.mtd=2 rootfstype=ubifs"
#define CONFIG_BOOTCOMMAND "bootm 0x82000000"
#define CONFIG_MEM_LINUXOS_SIZE "128M"
#define CONFIG_MTDPART "hinand:2M(boot),75M(main),75M(backup),100M(data)"
以上是非常关键的信息,解释如下:
- ubi.mtd=1 ubi.mtd=2,这里之所以有mtd1,2是根据ubi的规则,kernel将会将这两个ubi区域,进行挂载。
- bootm 0x82000000,这里并没有看到将kernel进行拷贝的命令,后面会解释,这里不需要拷贝。因为已经提前通过uboot的ubi的接口加载到了内存当中。
- CONFIG_MTDPART ,这个是真正的mtd的分区,但不是用户看到的分区,因为会在大的mtd的分区之上建立卷。
用户镜像制作
run "${MKUBIFS} -F -d ${rootfs_dir} -m ${pagesize} -o ${rootfs_img} -e ${LEB} -c ${MAX_LEB_CNT_ROOTFS}"
run "${MKUBIFS} -F -d ${userdata_dir} -m ${pagesize} -o ${userdata_img} -e ${LEB} -c ${MAX_LEB_CNT_USERDATA}"
run "${MKUBIFS} -F -d ${configb_dir} -m ${pagesize} -o ${configb_img} -e ${LEB} -c ${MAX_LEB_CNT_CONFIGB}"
{
echo "[kernel]"
echo "mode=ubi"
echo "image=${rootdir}/image/ubifs/kernel.images"
echo "vol_id=0"
echo "vol_size=4092KiB"
echo "vol_type=static"
echo "vol_alignment=1"
echo "vol_name=kernel"
echo ""
echo "[rootfs]"
echo "mode=ubi"
echo "image=${rootdir}/image/ubifs/rootfs_128k.ubiimg"
echo "vol_id=1"
echo "vol_size=68200KiB"
echo "vol_type=dynamic"
echo "vol_alignment=1"
echo "vol_name=rootfs"
echo ""
echo "[flaga]"
echo "mode=ubi"
echo "image=${rootdir}/image/ubifs/flagdata.bin"
echo "vol_id=2"
echo "vol_size=124KiB"
echo "vol_type=dynamic"
echo "vol_alignment=1"
echo "vol_name=flaga"
echo ""
echo "[flagb]"
echo "mode=ubi"
echo "image=${rootdir}/image/ubifs/flagdata.bin"
echo "vol_id=3"
echo "vol_size=124KiB"
echo "vol_type=dynamic"
echo "vol_alignment=1"
echo "vol_name=flagb"
echo ""
} > ${ubicfg}
run "${MKUBI} -o ${ubifsimg} -m ${pagesize} -p ${blocksize} ${ubicfg}"
这里介绍了在一个大的ubi分区上如何建立卷。实现多个文件系统。
uboot实现kernel双备份
//一个ubi分区中,卷的描述信息,根据这个可以扫描到对应的卷
static vol_scan_rec_t st_scan_rec_arr[UBI_MAX_SCAN_VOL] = {
[0] = {
.vol_id = KERNEL_VOL_ID,
.max_lebs = KERNEL_MAX_LEBS,
.map_arr = map_arr_rec_0,
.sqnum_arr = sqnum_arr_rec_0,
.leb_cnt = 0
},
[1] = {
.vol_id = LAYOUT_VOL_ID,
.max_lebs = LAYOUT_MAX_LEBS,
.map_arr = map_arr_rec_1,
.sqnum_arr = sqnum_arr_rec_1,
.leb_cnt = 0
},
[2] = {
.vol_id = FLAGA_VOL_ID,
.max_lebs = FLAGA_MAX_LEBS,
.map_arr = map_arr_rec_2,
.sqnum_arr = sqnum_arr_rec_2,
.leb_cnt = 0
},
[3] = {
.vol_id = FLAGB_VOL_ID,
.max_lebs = FLAGB_MAX_LEBS,
.map_arr = map_arr_rec_3,
.sqnum_arr = sqnum_arr_rec_3,
.leb_cnt = 0
},
[4] = {
.vol_id = KERNEL_VOL_ID,
.max_lebs = KERNEL_MAX_LEBS,
.map_arr = map_arr_rec_4,
.sqnum_arr = sqnum_arr_rec_4,
.leb_cnt = 0
},
}
//拷贝kernel到内存中地址
#define HI_CFG_MEM_RESV_HIGH 0x82000000
int fh_read_kernel(unsigned int flag)
{
if (0 == is_main_scanned)
{
if (0 != fh_boot_ubi_scan(0))
return HI_RET_FAIL;
}
if (0 == flag)
{
if (0 != main_upd_marker_arr[KERNEL_VOL_ID])
return HI_RET_FAIL;
if (0 != ubi_read_kernel(&st_scan_rec_arr[0], (char *)HI_CFG_MEM_RESV_HIGH))
return HI_RET_FAIL;
}
else
{
if (0 == is_bkup_scanned)
{
if (0 != fh_boot_ubi_scan(1))
return HI_RET_FAIL;
}
if (0 != bkup_upd_marker_arr[KERNEL_VOL_ID])
return HI_RET_FAIL;
if (0 != ubi_read_kernel(&st_scan_rec_arr[4], (char *)HI_CFG_MEM_RESV_HIGH))
return HI_RET_FAIL;
}
}
void autoboot_command(const char *s)
{
char *pc_buf = NULL;
unsigned int ui_flag = 0;
unsigned int ui_cnt = 0;
char c_hint[64];
debug("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");
for ( ui_cnt = 0; ui_cnt < 2; ui_cnt++ )
{
if( 1 == ui_cnt)
fh_set_bootstate( FH_KERNEL_FLAG, (ui_flag ? FH_SET_FLAGB : FH_SET_FLAGA) );
if ( 0 == ui_flag )
sprintf( c_hint, "\nBoot from %s...","kernelA" );
else
sprintf( c_hint, "\nBoot from %s...","kernelB" );
// 这里已经将kernel,读取到内存中去了,所以bootm哪里没有读取命令
if (0 != fh_read_kernel(ui_flag ? 1 : 0))
{
ui_flag = !ui_flag;
continue;
}
debug("\n %s\n",c_hint);
run_command_list(s, -1, 0);
}
}
kernel实现rootfs双备份
这里和镜像制作中的内容是一一对应的。kernel挂载ubi0和ubi1中的rootfs。
static int fhdrv_kdrv_rootfs_roll_back(unsigned char rfs_st, char *fs, int flags, void *data)
{
int err = 0;
printk(KERN_INFO "rootfs_roll_back parm: rfs_st=%c.\n", rfs_st);
if (0 == strcmp(fs, "ubifs"))
{
if('0' == rfs_st)
{
printk(KERN_INFO "rootfs trying roll back ubi1:rootfs.\n");
err = sys_mount("ubi1:rootfs", "/root", fs, flags, data);
}
else
{
printk(KERN_INFO "rootfs trying roll back ubi0:rootfs.\n");
err = sys_mount("ubi0:rootfs", "/root", fs, flags, data);
}
}
if(err)
return err;
printk(KERN_INFO "rootfs mount roll back %c.\n", (rfs_st == '1' ? '0' : '1'));
fhdrv_kdrv_set_rootfs_bootstate(rfs_st);
return 0;
}
实际使用的分区
uboot中升级
使用flash命令操作,会破坏卷。因为单个分区进行升级,需要使用ubi的命令。使用烧片镜像就可以使用flash操作命令进行升级。
kernel中升级
标签:kernel,arr,vol,分区,echo,主备,ubi,rootfs 来源: https://blog.csdn.net/qq_27087571/article/details/119007369
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。