Barebox支持MCI接口即SD卡设备,但是并没有移植fat文件系统,因此SD卡中的内容无法识别。由于bootloader阶段对SD卡的需求基本上也就在更新loader,kernel或者rootfs上,因此这次的目标只是增加一个sdupd命令+3个Option(loader,kernel,rootfs),能够自动读取SD卡根目录下的文件到对应地址。
首先分析下barebox的MCI接口,通过imx.c->mci-core.c->disk_driver.c,分别对应创建了imx-mmc0设备到mci0设备到disk0设备,最终在disk0上创建了一个命名为disk0.0的分区,disk0.0就是一个标准的FAT系统。
读取disk0.0的头512个字节进行分析:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
2
3 0 3 :跳转指令,对应NTFS为EB 52 90 ,对应FAT32为EB 58 90 ,对应FAT16为EB 3C 90
4
5 3 8 :OEM名称,常见有 " MSDOS5.0 " , " IBM 3.3 " , " MSWIN4.1 "
6
7 B 2 :每扇区字节数,允许值为512, 1024 , 2048 , 4096 ,不过基本上都为512
8
9 D 1 :每簇扇区数,允许值为1, 2 , 4 , 8 , 16 , 32 , 64 , 128 ,通常一簇为8个扇区
10
11 E 2 :保留扇区数,FAT之前扇区数,包含DBR即现在所分析的512字节。
12
13 10 1 :FAT数,为2
14
15 11 2 :最大根目录数,对于FAT12和16来说,通常为512,对于FAT32设为0
16
17 13 2 :总扇区数,如果该值为0,那么在offset 0x20处设置
18
19 15 1 :介质描述符,如硬盘是0xF8,软盘是0xF0
20
21 16 2 :每FAT扇区数,FAT32的设置见offset 0x24 ,此处为0
22
23 18 2 :每磁道扇区数
24
25 1A 2 :磁头数
26
27 1C 4 :隐藏扇区数
28
29 20 4 :总扇区数(注意offset 0x13 ),另总扇区数 / 每簇扇区数 = 总簇数必须为2的次方
30
31 以下FAT32专有:
32
33 24 4 :每个FAT扇区数
34
35 28 2 :扩展标记
36
37 2A 2 :文件系统版本
38
39 2C 4 :根目录簇号,通常为2
40
41 30 2 :文件系统信息扇区号
42
43 34 2 :备份引导扇区号
44
45 36 12 :保留为0
46
47 40 1 :物理驱动器号
48
49 41 1 :保留为0
50
51 42 1 :扩展引导标签
52
53 43 4 :分区序号
54
55 47 11 :卷标
56
57 52 8 :系统ID,为 " FAT32 "
58
59 5A 420 :操作系统代码
60
61 以下为FAT12 / 16专有:
62
63 24 1 :物理驱动器号
64
65 25 1 :保留
66
67 26 1 :扩展引导标签
68
69 27 4 :分区序号
70
71 2B 11 :卷标
72
73 36 8 : " FAT16 " 或 " FAT12 "
74
75 3E 448 : 操作系统代码
76
77 以下共有:
78
79 1FE 2 :扇区结束标示 0x55 0xAA ( 0xAA55 )
80
81
鉴于长文件名用到Unicode,暂时不做考虑,但对于SD card类型做到尽量多支持,如FAT12/FAT16/FAT32。(FAT12的卡在16MB或以下,比较少见,却是最麻烦的...)
具体思路是鉴于文件的读写是单线程,所以对FAT entry做cache,即每次以当前簇号在FAT中位置为起始地址读取一个扇区512字节,如果当前簇号指向的下一个簇号的位置也在这个区域,那么读出来放到cache,以此类推。
文件以扇区为单位进行读,以2KB为单位进行写NAND。最终实现FAT12/16/32下的SD卡更新:
sdupd loader 目标对应/dev/nand0.barebox.bb
sdupd kernel 目标对应/dev/nand0.kernel.bb
sdupd rootfs 目标对应/dev/ubi0.root
以上对应目标必须存在且已经先通过erase擦掉
需要注意的是对于ushort data=*(ushort *) &buf[i] 仅当i为偶数的时候可以用,不然会导致异常命令中断。