美文网首页
无法挂载根目录排查

无法挂载根目录排查

作者: 叶迎宪 | 来源:发表于2023-02-05 21:07 被阅读0次

    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

    相关文章

      网友评论

          本文标题:无法挂载根目录排查

          本文链接:https://www.haomeiwen.com/subject/zpkzhdtx.html