linux启动后,发现无法自动挂载 /dev/system 下的根目录。于是开始研究
一、根目录在哪个设备上,是由uboot传递过来的内核参数决定的。通过内核启动日志,或者 /proc/cmdline 可以看到 root=/dev/system rootfstype=ext4 init=/sbin/init,说明uboot传递过来的参数没有问题
二、启动过程中有一个报错 Failed to switch root, dropping to a shell
通过搜索,发现包含此字符串的地方位于
output/sm1_ac200_a6432_release/build/buildroot-fs/cpio/target_recovery/init 和
output/sm1_ac200_a6432_release/build//buildroot-fs/cpio/target_ota/init
在切换根目录失败的板子上,看到init内容为
#!/bin/sh
#Mount things needed by this script
/bin/mount -t sysfs sysfs /sys
/bin/mount -t devtmpfs devtmpfs /dev
/bin/mount -t proc proc /proc
#Create device nodes
mdev -s
#This will only be run if the exec above failed
echo "Failed to switch root, dropping to a shell"
exec /sbin/init
内容很简短,正是 target_recovery/init 的内容。由于脚本之中压根就没有读取内核参数root的路径,也没有挂载,因此必然走到 "Failed to switch root"。说明系统是进入recovery了,而不是正常的启动。正常启动时 target_ota/init 的内容节选
#Process command line options
for i in $(cat /proc/cmdline); do
case $i in
root\=*)
root=$(get_opt $i)
;;
firmware\=*)
firmware=$(get_opt $i)
;;
rootfstype\=*)
rootfstype=$(get_opt $i)
;;
init\=*)
init=$(get_opt $i)
;;
slot_suffix\=*)
slot_suffix=$(get_opt $i)
;;
system_partition_name\=*)
system_partition_name=$(get_opt $i)
;;
kernel_version\=*)
kernel_version=$(get_opt $i)
;;
esac
done
if [ "${rootfstype}" = "ubifs" ]; then
echo "#[ubiattach /dev/ubi_ctrl -m ${system_mtd_number}]"
ubiattach /dev/ubi_ctrl -m ${system_mtd_number}
echo "#[ mount -t ubifs /dev/ubi0_0 /mnt ]"
mount -t ${rootfstype} /dev/ubi0_0 /mnt
elif [ "${rootfstype}" != "" ]; then
mount -t ${rootfstype} "${root}" /mnt
else
mount "${root}" /mnt
fi
#Check if $init exists and is executable
if [[ -x "/mnt/${init}" ]] ; then
#Unmount all other mounts so that the ram used by
#the initramfs can be cleared after switch_root
umount /sys /proc /dev
#Switch to the new root and execute init
/bin/mount -t devtmpfs devtmpfs /mnt/dev
exec 0</mnt/dev/console
exec 1>/mnt/dev/console
exec 2>/mnt/dev/console
exec switch_root -c /dev/console /mnt "${init}"
fi
#This will only be run if the exec above failed
echo "Failed to switch root, dropping to a shell"
在正常启动时,init会解析内核参数,找到root挂载路径,然后挂载到 /mnt 下。最后通过 exec switch_root 切换到新根目录下
三、分析为何会进recovery
查看uboot的日志,发现有以下一行
gpio: pin GPIOAO_3 (gpio 3) value is 0
detect upgrade key
通过搜索代码,发现detect upgrade key是uboot中打印的 uboot-next-2015-dev/bl33/v2015/board/amlogic/configs/g12a_u200_v1.h
#define CONFIG_PREBOOT \
"run bcb_cmd; "\
"run factory_reset_poweroff_protect;"\
"run upgrade_check;"\
"run init_display;"\
"run storeargs;"\
"run upgrade_key;" \
"forceupdate;" \
"bcb uboot-command;"\
"run switch_bootmode;"
"upgrade_key="\
"if gpio input GPIOAO_3; then "\
"echo detect upgrade key; run update;"\
"fi;"\
"\0"\
"update="\
/*first usb burning, second sdc_burn, third ext-sd autoscr/recovery, last udisk autoscr/recovery*/\
"run usb_burning; "\
"run sdc_burning; "\
"if mmcinfo; then "\
"run recovery_from_sdcard;"\
"fi;"\
"if usb start 0; then "\
"run recovery_from_udisk;"\
"fi;"\
"run recovery_from_flash;"\
"\0"\
因为检测到GPIOAO_3有输入,因此执行了update,最后执行了recovery_from_flash
网友评论