XiaomiRouter自学之路(14-Openwrt文件系统读取失败问题解决)

题图:gratisography

11-Openwrt配置编译烧录中,我们将编译好的openwrt-ramips-mt7620-xiaomi-miwifi-mini-squashfs-sysupgrade.bin烧录进去后,发现系统可以正常启动,但是出现了Kernel panic,Unable to mount root fs on unknown-block(0,0),貌似文件系统出现了问题。

查看openwrt的启动信息,找到MTD分区信息的位置,如下:

[    0.710000] 7 ofpart partitions found on MTD device spi32766.0
[    0.710000] Creating 7 MTD partitions on "spi32766.0":
[    0.720000] 0x000000000000-0x000000030000 : "u-boot"
[    0.730000] 0x000000030000-0x000000040000 : "u-boot-env"
[    0.730000] 0x000000040000-0x000000050000 : "factory"
[    0.740000] 0x000000050000-0x000000fd0000 : "firmware"
[    0.920000] 0x000000fd0000-0x000000fe0000 : "crash"
[    0.930000] 0x000000fe0000-0x000000ff0000 : "reserved"
[    0.930000] 0x000000ff0000-0x000001000000 : "Bdata"
[    0.940000] gsw: setting port4 to ephy mode
[    0.950000] ralink_soc_eth 10100000.ethernet eth0 (uninitialized): port 1 link up (10Mbps/Half duplex)
[    0.960000] ralink_soc_eth 10100000.ethernet: loaded mt7620 driver
[    0.960000] ralink_soc_eth 10100000.ethernet eth0: ralink at 0xb0100000, irq 5
[    0.970000] rt2880_wdt 10000120.watchdog: Initialized
[    0.980000] TCP: cubic registered
[    0.980000] NET: Registered protocol family 17
[    0.990000] bridge: automatic filtering via arp/ip/ip6tables has been deprecated. Update your scripts to load br_netfilter if you need this.
[    1.000000] 8021q: 802.1Q VLAN Support v1.8
[    1.010000] VFS: Cannot open root device "(null)" or unknown-block(0,0): error -6
[    1.020000] Please append a correct "root=" boot option; here are the available partitions:
[    1.020000] 1f00             192 mtdblock0  (driver?)
[    1.030000] 1f01              64 mtdblock1  (driver?)
[    1.030000] 1f02              64 mtdblock2  (driver?)
[    1.040000] 1f03           15872 mtdblock3  (driver?)
[    1.040000] 1f04              64 mtdblock4  (driver?)
[    1.050000] 1f05              64 mtdblock5  (driver?)
[    1.060000] 1f06              64 mtdblock6  (driver?)
[    1.060000] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
[    1.060000] ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)

可以看到分成7个partition,对于partition的添加我在Linux mtd system里面已经有说了三种方式,这边使用的是dts添加的方式,该dts文件为target/linux/ramips/dts/XIAOMI-MIWIFI-MINI.dts,打开dts可以看到有如下内容:

m25p80@0 {
        #address-cells = <1>;
        #size-cells = <1>;
        compatible = "w25q128";
        reg = <0 0>;
        linux,modalias = "m25p80", "w25q128";
        spi-max-frequency = <10000000>;

        partition@0 {
            label = "u-boot";
            reg = <0x0 0x30000>;
        };

        partition@30000 {
            label = "u-boot-env";
            reg = <0x30000 0x10000>;
            read-only;
        };

        factory: partition@40000 {
            label = "factory";
            reg = <0x40000 0x10000>;
            read-only;
        };

        partition@50000 {
            label = "firmware";
            reg = <0x50000 0xf80000>;
        };

        partition@fd0000 {
            label = "crash";
            reg = <0xfd0000 0x10000>;
        };

        partition@fe0000 {
            label = "reserved";
            reg = <0xfe0000 0x10000>;
            read-only;
        };

        partition@ff0000 {
            label = "Bdata";
            reg = <0xff0000 0x10000>;
        };
    };

直接观察这7个分区,好像没看到linux和rootfs,其实这两部分被cat连接成一个.img文件,存放在firmware分区里面,对于openwrt的firmware生成过程后期会专门写一篇文章介绍。

既然分区文件系统什么都有了为什么rootfs没有引导成功呢?再查看下u-boot下个文件所存到的地址是否与kernel下的地址一致呢?

08-U-boot启动数值具体说明里面有提到U-boot下文件的存储位置,在include/configs/rt2880.h中有如下定义:

#define CFG_BOOTLOADER_SIZE 0x20000
#define CFG_CONFIG_SIZE     0x10000
#define CFG_FACTORY_SIZE    0x10000

#define CFG_ENV_ADDR        (CFG_FLASH_BASE + CFG_BOOTLOADER_SIZE)
#define CFG_FACTORY_ADDR    (CFG_FLASH_BASE + CFG_BOOTLOADER_SIZE + CFG_CONFIG_SIZE)
#define CFG_KERN_ADDR       (CFG_FLASH_BASE + (CFG_BOOTLOADER_SIZE + CFG_CONFIG_SIZE + CFG_FACTORY_SIZE))
#ifdef DUAL_IMAGE_SUPPORT
#define CFG_KERN2_ADDR      (CFG_FLASH2_BASE + (CFG_BOOTLOADER_SIZE + CFG_CONFIG_SIZE + CFG_FACTORY_SIZE))

发现u-boot阶段对u-boot的大小定义为0x20000,而kernel那边对u-boot的大小定义却为0x30000,地址已经错位了,我们将u-boot下的CFG_BOOTLOADER_SIZE改成0x30000后,对u-boot、openwrt进行重新烧录测试。

重新烧录后,可以观察到一切都正常,可以引导文件系统了,启动完按下Enter键进入命令行模式,如下:

BusyBox v1.23.2 (2017-02-21 05:58:37 PST) built-in shell (ash)

  _______                     ________        __
 |       |.-----.-----.-----.|  |  |  |.----.|  |_
 |   -   ||  _  |  -__|     ||  |  |  ||   _||   _|
 |_______||   __|_____|__|__||________||__|  |____|
          |__| W I R E L E S S   F R E E D O M
 -----------------------------------------------------
 CHAOS CALMER (Chaos Calmer, r49389)
 -----------------------------------------------------
  * 1 1/2 oz Gin            Shake with a glassful
  * 1/4 oz Triple Sec       of broken ice and pour
  * 3/4 oz Lime Juice       unstrained into a goblet.
  * 1 1/2 oz Orange Juice
  * 1 tsp. Grenadine Syrup
 -----------------------------------------------------
root@OpenWrt:/# 
root@OpenWrt:/# ls
bin      etc      mnt      proc     root     sys      usr      www
dev      lib      overlay  rom      sbin     tmp      var

现在已经可以正常引导了,试着去分析下是为什么会出现内核正常启动,可是文件系统引导不成功呢?

看下新的启动信息中MTD的分区信息有了一些信息,如下:

[    0.700000] m25p80 spi32766.0: w25q128 (16384 Kbytes)
[    0.710000] 7 ofpart partitions found on MTD device spi32766.0
[    0.710000] Creating 7 MTD partitions on "spi32766.0":
[    0.720000] 0x000000000000-0x000000030000 : "u-boot"
[    0.730000] 0x000000030000-0x000000040000 : "u-boot-env"
[    0.730000] 0x000000040000-0x000000050000 : "factory"
[    0.740000] 0x000000050000-0x000000fd0000 : "firmware"
[    0.860000] 2 uimage-fw partitions found on MTD device firmware
[    0.870000] 0x000000050000-0x0000001668b5 : "kernel"
[    0.870000] 0x0000001668b5-0x000000fd0000 : "rootfs"
[    0.880000] mtd: device 5 (rootfs) set to be root filesystem
[    0.890000] 1 squashfs-split partitions found on MTD device rootfs
[    0.890000] 0x000000360000-0x000000fd0000 : "rootfs_data"
[    0.900000] 0x000000fd0000-0x000000fe0000 : "crash"
[    0.910000] 0x000000fe0000-0x000000ff0000 : "reserved"
[    0.910000] 0x000000ff0000-0x000001000000 : "Bdata"
[    0.920000] gsw: setting port4 to ephy mode

可以看到中间多了一些信息,上面有说过firmware里面其实包含了kernel和rootfs两个部分,所以其实是有两个partition在里面,内核在调用add_mtd_partitions()函数里面会调用mtd分离函数mtd_partition_split(),看下函数的原型:

static void mtd_partition_split(struct mtd_info *master, struct mtd_part *part)
{
    static int rootfs_found = 0;

    if (rootfs_found)
        return;

    if (!strcmp(part->mtd.name, "rootfs")) {
        int num = run_parsers_by_type(part, MTD_PARSER_TYPE_ROOTFS);

        if (num <= 0 && config_enabled(CONFIG_MTD_ROOTFS_SPLIT))
            split_rootfs_data(master, part);

        rootfs_found = 1;
    }

    if (!strcmp(part->mtd.name, SPLIT_FIRMWARE_NAME) &&
        config_enabled(CONFIG_MTD_SPLIT_FIRMWARE))
        split_firmware(master, part);

    arch_split_mtd_part(master, part->mtd.name, part->offset,
                part->mtd.size);
}

该函数会先判断有没有rootfs该partition,如果有直接对该partition进行解析,如果没有那就说明在firmware里面,所以会先调用split_firmware()函数,简单说明该函数就是将firmware里面的kernel和rootfs分离出来,再对rootfs的partition进行解析。

该函数具体做了以下几件事:

  • 找type为MTD_PARSER_TYPE_FIRMWARE的分区解析器来分析。
  • "uimage-fw" 解析器读出 firmware 分区的头部,成功找到一个 uImage。
  • 跃过uImage,紧接着成功找到 squashfs 的头信息,于是找到了格式为 squashfs 的 rootfs。
  • 解析器在找到一个分区后,会调用 __mtd_add_partition() 将此分区添加到系统中。
  • __mtd_add_partition() 最后又调用 mtd_partition_split(),因为此时 rootfs已经找到,所以会调用 split_rootfs_data() 找 rootfs_data 分区。
  • rootfs 为 squashfs 分区,该格式的文件系统只读,且头信息里有标记分区大小。所以很容易就可以找到 rootfs_data 的起始位置。

通过上面这么一分析其实我们就大概知道没有引导文件系统的原因了:

1.kernel能够启动那是因为kernel的启动与mtd分区是没有关系的,只跟u-boot的引导地址有关,又因为在u-boot阶段,kernel所存储的位于与启动的引导地址肯定是一致的,所以kernel正常启动。

2.rootfs的启动与mtd分区是有关的,因为后面是通过读取分区块的内容来载入数据的,所以当所存放的地址和所要取的地址错误时,调用split_firmware()函数没能找出rootfs所处的位置,没能为rootfs建立分区块,所以会提示Unable to mount root fs on unknown-block(0,0)无法挂载rootfs文件系统。

Openwrt文件系统读取失败问题解决的分析就到这边,有感悟时会持续会更新。

注:以上内容都是本人在学习过程积累的一些心得,难免会有参考到其他文章的一些知识,如有侵权,请及时通知我,我将及时删除或标注内容出处,如有错误之处也请指出,进行探讨学习。文章只是起一个引导作用,详细的数据解析内容还请查看XiaomiRouter相关教程,感谢您的查阅。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,064评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,606评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,011评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,550评论 1 269
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,465评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,919评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,428评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,075评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,208评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,185评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,191评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,914评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,482评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,585评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,825评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,194评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,703评论 2 339

推荐阅读更多精彩内容