ramdisk 模式下启动报错问题分析报告
1 关键字 ramdisk; fstab.required; kernel崩溃 2 问题描述 2.1 运行环境 软件环境: OH版本:3.1release kernel版本:firefly-4.19 硬件环境: firefly 3568-pc 2.2 问题现象: 在OpenHarmony 3.1-Release当中,默认使用了ramdisk启动引导,但使用第三方内核+OH应用启动时,会出现内核崩
1 关键字
ramdisk; fstab.required; kernel崩溃
2 问题描述
2.1 运行环境
-
软件环境:
-
OH版本:3.1release
-
kernel版本:firefly-4.19
-
-
硬件环境:
-
firefly 3568-pc
-
2.2 问题现象:
在OpenHarmony 3.1-Release当中,默认使用了ramdisk启动引导,但使用第三方内核+OH应用启动时,会出现内核崩溃的问题,崩溃日志日志如下:
……
run-init: /etc/init: Permission denied
[ 4.389343] [pid=1][INIT][INFO] [init.c:225)] DISABLE_INIT_TWO_STAGES not defined
[ 4.389498] [pid=1][INIT][ERROR] [init.c:175)] Failed get fstab.required
[ 4.389569] Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000004
[ 4.389569]
[ 4.391468] CPU: 3 PID: 1 Comm: init Not tainted 4.19.219 #5
[ 4.391965] Hardware name: Firefly RK3568-ROC-PC HDMI (Linux) (DT)
[ 4.392508] Call trace:
[ 4.392739] dump_backtrace+0x0/0x188
[ 4.393067] show_stack+0x24/0x30
[ 4.393373] dump_stack+0x8c/0xb4
[ 4.393677] panic+0x138/0x2b0
[ 4.393958] do_exit+0x1a4/0x868
[ 4.394250] __arm64_sys_exit_group+0x0/0x24
[ 4.394634] get_signal+0x694/0x698
[ 4.394949] do_signal+0x9c/0x238
[ 4.395252] do_notify_resume+0xc8/0x110
[ 4.395601] work_pending+0x8/0x10
[ 4.395907] SMP: stopping secondary CPUs
[ 4.396304] PMU CRU:
……
2.3 测试步骤
-
1、生成firefly 4.19 未修改过的源码内核文件。boot.img,MiniLoaderAll.bin,misc.img,parameter.txt,recovery.img,uboot.img
-
2、生成OpenHarmony 3.1-Release 编译后提供的system.img,userdata.img,vector.img
-
3、使用1提供的分区表文件parameter.txt,把img下载到硬件。
-
4、启动后直接发现内核崩溃.
3 问题原因
3.1 正常机制
-
在正常情况下,uboot->kernel->initrd(设置root=/dev/ram0)->init->mount file system->init->启动OpenHarmony
3.2 异常机制
-
kernel执行init过程中,找不到fstab.required文件,导致kernel直接崩溃。
4 解决方案
fstab.required 文件只存在于OpenHarmony生成的ramdisk.img中,解决方案分两种情况:
1、kernel不支持ramdisk方式。
在OpenHarmony中关闭ramdisk(rk3568 修改路径:productdefine\common\device\rk3568.json)。 相应配置修改成:"enable_ramdisk": false。
2、kernel支持ramdisk方式。以firefly rk3568为例:
把OpenHarmony生成的ramdisk.img覆盖firefly kernel使用的ramdisk.img。重新编译,下载。这样就可以找到fstab.required。并挂载文件系统,启动OpenHarmony相关服务。这种方法要确保OpenHarmony与Kernel的编译工具链的一致性。
5 定位过程
1、从崩溃日志可以看到如下打印:
[ 2.168829] Run /init as init process ………… [ 4.552748] fusb302 0-0022: PD disabled [ 4.603896] [pid=1][INIT][INFO] [init.c:225)] DISABLE_INIT_TWO_STAGES not defined [ 4.604088] [pid=1][INIT][ERROR] [init.c:175)] Failed get fstab.required [ 4.604173] Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000004 [ 4.604173] [ 4.606027] CPU: 1 PID: 1 Comm: init Not tainted 4.19.219 #5 [ 4.606527] Hardware name: Firefly RK3568-ROC-PC HDMI (Linux) (DT) [ 4.607073] Call trace: ……………
在启动init时,有两个关键的打印:
-
DISABLE_INIT_TWO_STAGES not defined
-
Failed get fstab.required
从DISABLE_INIT_TWO_STAGES 打印可以看出,与ramdisk有关
if (!enable_ramdisk) { defines += [ "DISABLE_INIT_TWO_STAGES" ] }
enable_ramdisk 在以下路径中有定义:productdefine\common\device\rk3568.json
"enable_ramdisk": true,
Failed get fstab.required 打印源码如下:
static void StartInitSecondStage(void) { const char *fstabFile = "/etc/fstab.required"; Fstab *fstab = NULL; if (access(fstabFile, F_OK) != 0) { fstabFile = "/system/etc/fstab.required"; } INIT_ERROR_CHECK(access(fstabFile, F_OK) == 0, abort(), "Failed get fstab.required"); fstab = ReadFstabFromFile(fstabFile, false); INIT_ERROR_CHECK(fstab != NULL, abort(), "Read fstab file \" %s \" failed\n", fstabFile);
找不到fstab.required。
搜索out目录:fstab.required存在于./rk3568/packages/phone/ramdisk/etc/fstab.required中。
由此可以看出,找不到fstab.required。是因为ramdisk.img没有加载成功。
我们发现,在打开了ramdisk后,ramdisk.img是打包在了boot_linux.img中的。如下:
root@wuhphis03349:~/ohos/openHarmony/3.1-release/out/rk3568/packages/phone/images/temp# ls
extlinux logo.bmp logo_kernel.bmp lost+found
t@wuhphis03349:~/ohos/openHarmony/3.1-release/out/rk3568/packages/phone/images/temp/extlinux# ls
extlinux.conf Image ramdisk.img toybrick.dtb
root@wuhphis03349:~/ohos/openHarmony/3.1-release/out/rk3568/packages/phone/images/temp/extlinux# cat extlinux.conf
label rockchip-kernel-5.10
kernel /extlinux/Image
fdt /extlinux/toybrick.dtb
initrd /extlinux/ramdisk.img
append earlycon=uart8250,mmio32,0xfe660000 root=PARTUUID=614e0000-0000-4b53-8000-1d28000054a9 rw rootwait rootfstype=ext4
initrd 使用的就是ramdisk.img
那boot_linux.img我们并没有用到,boot使用的是firefly编译出的kernel。
我们的解决办法就是要把ramdisk.img移植到firefly的boot.img中。
ramdisk.img在kernel里面是存在的,直接替换就可以。
然后编译、下载。发现不再崩溃,启动日志如下:
………… [ 1.872984] Run /init as init process [ 1.878187] [pid=1][INIT][INFO] [init.c:225)] DISABLE_INIT_TWO_STAGES not defined ………… [ 2.525787] BEGET[pid=1][INIT][INFO] [fstab_mount.c:331)] Mount /dev/block/platform/fe310000.sdhci/by-name/rootfs to /usr successful [ 2.525821] BEGET[pid=1][INIT][ERROR] [fstab_mount.c:299)] Unsupported file system " none " [ 2.653223] phy phy-fe8a0000.usb2-phy.8: charger = USB_CDP_CHARGER [ 3.033396] EXT4-fs (mmcblk0p6): mounted filesystem without journal. Opts: barrier=1 [ 3.033517] BEGET[pid=1][INIT][INFO] [fstab_mount.c:331)] Mount /dev/block/platform/fe310000.sdhci/by-name/oem to /vendor successful …………
6 知识分享
OpenHarmony ramdisk 简要介绍:
ramdisk是在正式文件系统挂载之前,为OS提供一些基础能力。通过设置root=/dev/ram0,把ramdisk挂载成一个根文件系统,在ramdisk里面,可以做一些前期准备工作。在OpenHarmony当中,打开ramdisk后,init会执行二次启动。第一次启动ramdisk中的init,并通过执行/etc/fstab.required,完成对system、vendor、userdata等挂载,然后切换根文件系统,再次执行init,完成OpenHarmony相关服务的启动。目前ramdisk功能有限,后期会不断优化,提升系统的启动效率。
更多推荐
所有评论(0)