Linux 内核移植要让内核正确识别并使用目标硬件。完整系统适配还包括 Bootloader、根文件系统和应用;它们与内核相互依赖,但不是同一项工作。本文保留 LicheePi Nano / F1C100S 一类旧实验的结构,同时把板卡专用配置与通用构建步骤分开说明。
先找到启动链中的问题位置
跳转到“先找到启动链中的问题位置”
通常先执行芯片内置的 Boot ROM,再进入 SPL 或其他早期固件、U-Boot 和内核,最后启动用户空间。具体阶段依 SoC 和 BSP 而定,图中的组件关系不能直接当作所有存储介质的分区布局。
ROM 可能提供 USB 下载模式,但它不一定独立完成所有 Flash 擦写;主机工具也可能先下载一个 RAM 中运行的加载器,再由加载器驱动存储设备。调试时应分别确认串口最早输出、DRAM 初始化、内核加载与入口、设备树、根分区挂载和 PID 1 启动。
设备、驱动和源码目录
跳转到“设备、驱动和源码目录”
字符设备常通过设备节点提供文件操作,块设备通过块层支持存储访问,网络设备主要经网络栈和 socket 使用。图是入门分类,不表示所有硬件访问都走同一条路径,也不表示所有文件系统都必须建立在磁盘上,例如 procfs 和 sysfs 就不需要磁盘分区。

对这张历史目录图,需按以下含义阅读:
| 目录 | 主要内容 |
|---|---|
arch/ | 架构相关实现、板级配置与设备树等 |
drivers/ | 设备驱动及相关子系统 |
block/ | 通用块层,不是所有块设备驱动的集中目录 |
fs/ | VFS 与具体文件系统 |
kernel/、mm/ | 调度等核心机制与内存管理 |
net/ | 网络协议栈和网络子系统 |
ipc/ | System V IPC 等进程间通信实现,匿名管道等不都在这里 |
lib/ | 内核使用的通用辅助代码,不是用户空间标准 C 库 |
include/ | 内核头文件及对外接口定义 |
init/ | 内核初始化 |
usr/ | initramfs 构建相关内容 |
scripts/、tools/、Documentation/ | 构建辅助、工具和文档 |
原图中的 firmware/ 等目录随内核版本变化。查阅源码时应先确认当前提交,不能用一张旧目录图推断所有版本的布局。
文件权限与 rootfs 部署
跳转到“文件权限与 rootfs 部署”
ls -l 输出中,第一个字符表示类型,如 d 是目录、- 是普通文件、l 是符号链接。其后的三组三位依次对应文件属主、属组、其他用户:
- 属主是文件记录的所有者,不固定等于 root。
- 属组权限适用于符合该组身份条件的进程,不等于系统中所有其他用户。
- 其他用户权限是未按属主或属组匹配时的权限类别;ACL、能力与安全策略等还可能影响实际访问。
rwxr-xr-x 对应普通权限 755;前面的类型字符不是这个八进制数的一部分。目录上的 x 表示搜索/穿越权限,与普通文件的执行权限含义不同。部署 rootfs 时,复制内容还必须保留所有者、权限、符号链接和必要的设备节点。
配置和构建内核
跳转到“配置和构建内核”原实验链接到 Planck-Pi Kernel 的 4.15 分支,并记录过 linux-licheepi_nano_defconfig。该名称属于当时源码树的约定;本次没有取得该分支下对应配置文件,不能把它当作主线通用目标。先检查所用 BSP 的 README 与 arch/arm/configs/ 中实际存在的配置,再选择目标。设备树节点的入门材料仍可参考原记录的 Sipeed Nano 文档。
原记录还保存了 Planck-Pi 开启 Gadget RNDIS 教程,可作为查找当时 USB 网络配置的历史线索;本次未复现该教程。原实验的设备树产物名为 suniv-f1c100s-licheepi-nano.dtb,放在 arch/arm/boot/dts/ 下;应以自己所用源码版本、板卡和输出目录中的实际产物为准。
不必为切换工具链去修改顶层 Makefile 的某个固定行号。下面是 32 位 ARM BSP 的命令模板;linux-src、工具链前缀和 BOARD_DEFCONFIG 需要替换为已验证的实际值:
set -esrc="$PWD/linux-src"out="$PWD/out-nano-kernel"cross=arm-linux-gnueabi-: "${BOARD_DEFCONFIG:?Set the defconfig name from this BSP}"
test -f "$src/arch/arm/configs/$BOARD_DEFCONFIG"command -v "${cross}gcc"make -C "$src" O="$out" ARCH=arm CROSS_COMPILE="$cross" "$BOARD_DEFCONFIG"make -C "$src" O="$out" ARCH=arm CROSS_COMPILE="$cross" menuconfigmake -C "$src" O="$out" ARCH=arm CROSS_COMPILE="$cross" \ -j"$(nproc)" zImage dtbs modulesO= 将配置和构建产物放入单独输出目录,同一轮构建的每次调用都要一致使用它。menuconfig 中可按 / 搜索配置;保存后的 .config 在输出目录。modules 只会为配置为模块的功能生成相应产物。以上模板未进行整套板级内核编译。Linux 构建说明 介绍了输出目录与配置步骤。
对于这些 32 位 ARM 构建,zImage 通常在输出目录的 arch/arm/boot/。设备树产物应在该版本的 arch/arm/boot/dts/ 及其子目录查找;较新的源码会按厂商分子目录,不能固定假设 DTB 永远位于同一层。i.MX8MP 的 AArch64 内核通常使用 ARCH=arm64 与 Image,不能照搬本例。
把内核接入可启动系统
跳转到“把内核接入可启动系统”将新内核和匹配的 DTB 放入启动方案指定位置,同时把相同内核版本的模块安装进待打包 rootfs。检查 bootcmd/启动脚本中加载的文件名、地址和 bootargs,确认存储控制器、根文件系统驱动及其依赖可以在挂载根分区前使用;它们若只存在于尚未挂载的根分区模块目录中,就不能完成这一步。
旧实验使用过以下布局,它只是一组历史参数:
| 分区 | 原记录容量 | 文件系统 | 用途 |
|---|---|---|---|
| boot | 10 MB | FAT16 | 内核和 DTB |
| rootfs | 余下空间 | ext4 | 根文件系统 |
今天复现时须根据实际产物大小、ROM 保留区域、启动程序支持与更新空间重新计算,不能保证 10 MB 足够。内核、设备树、rootfs 与模块应作为匹配的一组验证,并通过串口日志确认真实启动结果。
原记录另引用了一张
无标题-1713119368920-1.png,但资料中没有该图片文件。这里保留缺失说明,不据此重建或推断图中内容。