感谢分享, 有空我也照着你的步奏一步一步跑起来。
好的,大佬。
我想知道为什么你有那么多的时间,为什么俺觉得老是没时间用
6. 网络挂载根文件系统 NFS
a. NFS 服务端配置
i. 服务端ip地址是 192.168.1.76
ii. 安装软件
sudo apt-get install nfs-kernel-server
iii. 配置目录: 配置要服务的目录
sudo vi /etc/exports
/nfs/rootfs *(rw,sync,no_root_squash,no_subtree_check)
iv. 启动服务
sudo service nfs-kernel-server restart
v. 检测是否 exported
sudo showmount -e
以上,把 /nfs/rootfs 作为 nfs 目录共享到网络上
vi. 解压根文件系统镜像 到 /nfs/rootfs
1) 上面一节我们得到了 rootfs.tar
2) 创建目录 sudo mkdir /nfs/rootfs
3) 解压 rootfs.tar 到 nfs/rootfs 目录
sudo tar xvf rootfs.tar -C /nfs/rootfs
4) 注意要 sudo,因为根文件系统里用户是 root
vii. 至此,我们准备好了 NFS 服务端
b. u-boot NFS 测试
在 u-boot 命令行
=> nfs 0x41000000 192.168.1.76:/helloworld.out
若 nfs 服务通畅,日志会显示下载成功
c. 挂载根文件系统到 NFS
要让内核启动后把 NFS 作为 根文件系统挂载,需要在 bootargs 指定正确的参数
setenv bootargs noinitrd console=ttyS0,115200 panic=5 rootwait ip=192.168.1.172:192.168.1.76:192.168.1.1:255.255.255.0:opz:::192.168.1.1
nfsroot=192.168.1.76:/nfs/rootfs,nfsvers=3,tcp
root=/dev/nfs rw loglevel=7 earlyprintk init=/sbin/init
以上,bootargs 指定了 根文件系统是 nfs 类型, nfsroot 设置了 服务器的地址,nfsvers 指定协议版本
版本非常重要,大部分教程都没有说版本,但是在我的环境里没有指定 nfsvers 确实是挂载不上去的。
详细说明参考:nfs 启动的说明: https://www.kernel.org/doc/Documentation/filesystems/nfs/nfsroot.txt
d. 挂载成功,系统启动
e. 以上,通过tftp和nfs网络手段,验证了 u-boot,内核, 根文件系统可以正常工作,就可以烧写到 sd 卡。
NFS 可以减少我们频繁插拔操作sd卡的次数,提供 根文件系统构建过程的调试效率
tftp 可以提高内核替换验证速度
7. 烧写 sd 卡
a. u-boot 烧写
i. 把 sd 读卡器接入 vmware 虚拟机
ii. 烧写u-boot 镜像
ls /dev/sd* 查看sd卡的磁盘标号 一般是 sdb,sdb1,sdb2
dd if=u-boot-sunxi-with-spl.bin of=/dev/sdb bs=1024 seek=8
sync && eject /dev/sdb
b. 分区
i. sd 分区格式化的说明文档: https://linux-sunxi.org/Bootable_SD_card
1) 为全志芯片定制的 u-boot,对 mmc 有如下要求:
2) 8KB 偏移处,存储 u-boot-spl
3) 大部分分区工具从 1MB 开始第一个分区,u-boot 可以使用 前1MB 的空间。
8KB 偏移是全志 SOC BROM 检测的,它会检查 8KB 偏移处是否有 eGON/TOC0 头部签名
40KB 偏移是 U-Boot proper 默认定义的位置,可以通过修改 CONFIS_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 配置
新的全志SOC 如 H2+, 如果检测不到 8KB 偏移的签名,就会从 128KB 加载 SPL,响应的 U-Boot proper 偏移需要修改。
u-boot 被分为两部分:SPL 和 U-Boot proper,我们编译得到的 u-boot-sunxi-with-spl.bin 已经打包了这两部分。烧写进 8KB 偏移时,两部分都烧写了。
ii. sd 卡通过读卡器接入 ubuntu 系统
1) 查看sd卡设备号 blkid
2) 定义shell 变量
export card=/dev/sdb
export p=""
iii. 烧写 u-boot
1) 清空前1MB,为u-boot 烧写做准备
dd if=/dev/zero of=${card} bs=1M count=1
2) 烧写 u-boot
dd if=u-boot-sunxi-with-spl.bin of=${card} bs=1024 seek=8
iv. 创建分区
1) 如果分区被挂载中,需要 umount
sudo umount /media/panic/linux/
2) fdisk /dev/sdb
n: 新建
p 主分区
交互式创建分区
分区代号表:
v. 调整分区格式
sudo mkfs.vfat /dev/sdb1
sudo mkfs.ext4 /dev/sdb2
遇到一个问题,格式化之后,fdisk 里,l 命令查看分区表,发现 第一个分区也是 linux,不知是否格式化失败
$ sudo mkfs.vfat /dev/sdb1
mkfs.fat 3.0.26 (2014-03-07)
$ sudo fdisk -l /dev/sdb
Disk /dev/sdb: 3904 MB, 3904897024 bytes
121 heads, 62 sectors/track, 1016 cylinders, total 7626752 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0xed2d5f33
Device Boot Start End Blocks Id System
/dev/sdb1 4096 69631 32768 83 Linux
/dev/sdb2 69632 7626751 3778560 83 Linux
mkfs.msdos, mkfs.ntfs 都是显示 一样的结果
但是从上图可以看出,实际文件格式是 fat,因为用 fat 命令可以读取到文件
vi. 查看分区列表
c. 挂载 sd 分区
d. 内核 zImage, dtb, boot.scr 拷贝
i. boot.cmd
setenv bootargs console=ttyS0,115200 panic=5 rootwait root=/dev/mmcblk0p2 earlyprintk rw
load mmc 0:1 0x41000000 zImage
load mmc 0:1 0x41800000 opz.dtb
bootz 0x41000000 - 0x41800000
由于粗心,bootargs 里多写了 一个 console=tty0 导致内核启动之后,日志打印不出来以为没启动,怀疑式根文件系统的问题,
因为 nfs 挂载可以成功,恰恰式因为 nfs 的 bootargs 没多写 console
ii. boot.scr
mkimage -C none -A arm -T script -d boot.cmd boot.scr
iii. zImage , dtb 拷贝到 sd 卡 boot 分区
iv. bootcmd 环境变量
v. tftp 0x43100000 boot-mmc.scr; source 0x43100000
e. 根文件系统拷贝
i. 把sd卡第二分区挂载到 pc上
sudo mount /dev/sdb2 /mnt
(ubuntu 桌面系统会自动挂载到 /media/panic/XXX )
ii. 解压跟文件系统
sudo tar xvf rootfs.tar -C /nfs/rootfs
iii. 遇到的问题
1) boot 分区 fat 格式有问题,
1) ubuntu fdisk -l 显示boot分区为 linux 格式,而 gparted 显示 fat16
2) 从 boot 分区加载 zImage , 运行不起来,同一个 zImage 放在网络或者 linux 分区加载,都可以成功
3) 讲boot 分区格式化为 ext4, 可以正常加载linux
mkfs.vfat /dev/sdb1 之后,fdisk -l 查看到的 分区,仍然识别为 linux,但 gparted 却可以是被为 fat16, windows 也可以识别。
but 在 u-boot 里,虽然加载到 zImage ,但是启动不起来 到 starting kernel 就停了。于是我把boot分区格式化为 ext4, 内核起得来了
2) 根文件系统,nfs 可以正常,但是放在 sd 卡上就不正常了
[ 2.352629] mmc3: new high speed SDIO card at address 0001
[ 2.359692] random: fast init done
[ 2.365871] EXT4-fs (mmcblk2p2): mounted filesystem with ordered data mode. Opts: (null)
[ 2.374086] VFS: Mounted root (ext4 filesystem) on device 179:2.
[ 2.381915] devtmpfs: mounted
[ 2.387054] Freeing unused kernel memory: 2048K
[ 2.495571] EXT4-fs (mmcblk2p2): re-mounted. Opts: data=ordered
[ 2.676719] random: dd: uninitialized urandom read (512 bytes read)
[ 2.834544] Generic PHY stmmac-0:01: attached PHY driver [Generic PHY] (mii_bus:phy_addr=stmmac-0:01, irq=POLL)
[ 2.846970] dwmac-sun8i 1c30000.ethernet eth0: No MAC Management Counters available
[ 2.854702] dwmac-sun8i 1c30000.ethernet eth0: PTP not supported by HW
[ 2.861597] IPv6: ADDRCONF(NETDEV_UP): eth0: link is not ready
[ 5.978730] dwmac-sun8i 1c30000.ethernet eth0: Link is Up - 100Mbps/Full - flow control rx/tx
[ 5.987345] IPv6: ADDRCONF(NETDEV_CHANGE): eth0: link becomes ready
改了 bootargs,去掉多余的 console 字段之后,终于正常。
3) mount /dev/mmcblk2p1 /mnt 挂载问题
# mount /dev/mmcblk2p1 /mnt
[ 167.579602] FAT-fs (mmcblk2p1): IO charset ascii not found
[ 167.591458] FAT-fs (mmcblk2p1): Volume was not properly unmounted. Some data may be corrupt. Please run fsck
虽然有警告,但是可以挂载
要内核配置为支持 fat 文件系统 File systems-> ms dos blablabla -> *
iv. 恢复 u-boot bootcmd 默认引导
setenv bootcmd "load mmc 0:1 ${scriptaddr} boot.scr; source ${scriptaddr}"
fatload 改为 load , load 支持其他格式文件系统
v. 调试技巧
1) 从 tftp 加载 boot.scr,并启动
setenv bootcmd "tftp ${scriptaddr} boot.scr; source ${scriptaddr}"
saveenv
boot
2) 从 tftp 更新 zImage
setenv bootcmd "tftp ${scriptaddr} boot.scr; source ${scriptaddr}"
setenv serverip 192.168.1.76
setenv ipaddr 192.168.1.172
tftp 命令需要先设置好ip
3) 在linux系统里从 tftp 下载文件
tftp -g -r boot-mmc.scr 192.168.1.76
8. 内核模块拷贝进入根文件系统
a. 内核编译生成目录
i. 编译模块
make ARCH=arm modules
ii. 安装模块 INSTALL_MOD_PATH 指定安装的目录,我们安装到源码目录下
make INSTALL_MOD_PATH=out modules_install
iii. 得到 out/lib/modules/4.14.111-g08b7e83/
b. 拷贝
一般编译的是时候,文件系统没有挂载到主机上,所以需要多一步
把 p2 挂载到 /mnt,再把上一步生成的目录拷贝到目标根文件系统上。
sudo mkdir -p /mnt/lib/modules/$VERSION/ &&\
sudo cp modules/* /mnt/lib/modules/$VERSION -r &&\
$VERSION 是目标内核的版本号 通过 uname -r 查看
c. 疑问
i. 文件夹的名字需要改么,生成的 modules 带后缀
https://unix.stackexchange.com/questions/231500/difference-between-lib-module-uname-r-and-sys-module
-需要相同
ii. 内核模块安装错误
appledisplay: version magic '4.14.111-g08b7e83 SMP mod_unload ARMv7 p2v8 ' should be '4.14.111-g25f7b00-dirty SMP mod_unload ARMv7 p2v8 '
编译版本和运行版本不是一样的
http://billauer.co.il/blog/2013/10/version-magic-insmod-modprobe-force/
1) include/generated/utsrelease.h 里记录了自动生成的版本号
2) include/linux/vermagic.h 决定了随机的版本号
3) 编译菜单 General setup -> Automatically append version information to version string 去勾选,会去掉 版本后面的随机串,但是最后有个加号
4) 加号来源是版本控制系统,当前版本处于改动中就会自动附上+ http://smilejay.com/2012/07/kernel-version-plus-sign/
iii. 内核如何决定是否使用 这些模块,开机使用还是需要手动
应该是在内核使用到相应的功能时,会自动去查找安装