# eel **Repository Path**: kingdix10/eel ## Basic Information - **Project Name**: eel - **Description**: Easing Embedded System Learning - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 1 - **Created**: 2022-12-03 - **Last Updated**: 2025-05-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README --- # type: docs title: eel articleID: 021367259375810 date: 2021-11-21 lastmod: 2024-12-04 23:34:34 description: introDescription: abstract: summary: draft: true featured: false hidden: false toc: true keywords: tags: categories: series: - 未分类 math: # pinned: # pinnedWeight: images: shareImage: codeMaxLines: codeLineNumbers: comments: true showDate: true showShare: showReadTime: true sidebar: true singleColumn: showRelatedInArticle: license: --- # 1. eel简介 ## 1.1. 特性 - 支持多个源码版本 - 支持一键下载、编译、运行 - 支持一键qemu运行u-boot、kernel,支持使用busybox、buildroot、debian根文件系统 - 支持qemu + gdb调试 - 支持arm/arm64/riscv32/riscv64 * arm支持:atf、optee_os、optee_client、optee_examples * riscv支持:opensbi - 支持多种自定义配置 - 尽可能遵循官方说明的编译方法,编译过程和命令对用户可见 ## 1.2. 测试环境 Debian 12 Docker。理论上Debian的物理机、虚拟机也可。Ubuntu系统未测试。 ## 1.3. 测试版本 | 模块 | version | | :------------------- | :---------------------- | | ARM trusted firmware | 2.7.0/2.8.0/2.10.0 | | optee | 3.18.0/4.1.0 | | u-boot | 2022.10/2024.01 | | linux | 5.10/5.15/6.0/6.1/6.6 | | busybox | 1.35.0/1.36.0 | | buildroot | 2023.02/2024.02/2024.11 | ## 1.4. 其他说明 1. optee-3.19.0及之后版本增加了libacl,需要`-lbuuid`选项,依赖buildroot使能`BR2_PACKAGE_UTIL_LINUX_UUIDD`,如果使用buildroot编译,buildroot会自动处理依赖。这里手动编译时,临时使用宿主机的库。 2. linux-4.x版本编译时依赖compile-gcc\$version.h,\$version为gcc版本,源码中默认没有高版本的头文件,可以复制其他文件作为compile-gcc$version.h # 2. 仓库说明 eel仓库下的几个仓库本身属于eel的子模块,但是 `git submodule`命令相对小众,使用起来也没有明显的优势,这几个仓库还是作为独立的仓库处理。 - 环境搭建脚本仓库:[https://gitee.com/kingdix10/envsetup](https://gitee.com/kingdix10/envsetup) - eel主仓库:[https://gitee.com/kingdix10/eel](https://gitee.com/kingdix10/eel) - eel改动仓库:[https://gitee.com/kingdix10/eel-changes](https://gitee.com/kingdix10/eel-changes) - 驱动示例仓库:[https://gitee.com/kingdix10/eel-kmodules](https://gitee.com/kingdix10/eel-kmodules) - 辅助工具仓库:[https://gitee.com/kingdix10/eel-ctools](https://gitee.com/kingdix10/eel-ctools) 源码下载可以参考《快速上手》部分。 ## 2.1. 主目录结构 ```shell $(EELDIR) ├── Makefile # 主Makefile ├── README.md # 说明文档 ├── arch/ # 体系架构配置文件 ├── changes/ # 与源码目录对应的修改,来自eel-changes仓库 ├── configs/ # 通用配置文件目录 ├── ctools/ # 辅助工具及脚本目录 ├── democodes/ # 示例代码,包含驱动、用户程序、脚本等 ├── docs/ # 文档目录 ├── download/ # 下载目录 │ └── buildroot-dl/ # buildroot下载目录 ├── dumpdt/ # 存放qemu用到的dtb反汇编的源码 ├── function.include # 自定义函数库 ├── os/ # 与操作系统相关的配置文件 ├── output/ # 编译生成物,按系统架构划分二级目录 ├── presets/ # 预定义的配置文件目录 ├── select # 用于选择预定义的配置文件,选择后使用.tmp.config.mk链接实际的文件 ├── share/ # QEMU虚拟机共享目录 ├── source/ # 源码目录 ├── submake/ # 子模块编译规则目录 └── toolchain/ # 交叉编译工具 ``` 根文件系统中,会自动挂载主机与虚拟机共享目录到 `/mnt/`和 `/mnt/arch/`,分别是公共共享目录和体系结构相关目录,对应主机目录分别为 `$(EELDIR)/share/`和 `$(OUTDIR)/$(ARCH)/rootfs/share/`。 默认虚拟机启动时会自动执行`share/init.sh`,挂载共享目录到虚拟机。 ## 2.2. source目录 ```shell $(EELDIR) └── source ├── kernel │ ├── linux-6.1 # linux-6.1源码解压,使用git管理,方便代码阅读 │ └── linux-repo # 官方git仓库 ├── democodes # 例程 │ └── kmodules # 内核模块例程,按内核般般划分 │ └── linux-6.6 # linux-6.6内核模块例程 ├── optee │ ├── optee_client-repo │ ├── optee_examples-repo │ └── optee_os-repo ├── rootfs │ ├── buildroot-repo │ └── busybox-repo ├── trusted-firmware │ └── trusted-firmware-a-repo └── u-boot ├── u-boot-2022.10 # u-boot-2022.10源码解压,使用git管理,方便代码阅读 └── u-boot-repo # 官方git仓库 ``` ## 2.3. changes目录 ```shell $(EELDIR) └── changes ├── kernel │ ├── linux-5.10 │ ├── linux-5.15 │ └── linux-6.1 # 针对linux-6.1的修改,包含deconfig等 ├── rootfs │ ├── bb-etc # busybox根文件系统/etc目录示例 │ ├── br-rfs-overlay # 用于新增/覆盖buildroot根文件系统部分文件 │ ├── buildroot-2022.11 # 针对buildroot-2022.11的修改,包含deconfig等 │ └── busybox-1.35.0 # 针对busybox-1.35.0的修改,包含deconfig等 └── u-boot └── u-boot-2022.10 ``` # 3. 快速上手 ## 3.1. 准备工作 做完开发环境搭建或安装 `git`、`make`等工具后,可以使用如下命令下载。 eel下的几个子仓库地址在 `configs/repo.mk`中定义,默认使用的是https协议,如果已经把ssh公钥添加到gitee,可以改成ssh协议。 开源代码默认使用gitee镜像,可能比官方仓库更新慢。 ```shell git clone https://gitee.com/kingdix10/eel.git # 或者git clone git@gitee.com:kingdix10/eel.git cd eel # 根据需要修改configs/repo.mk make ARCH=arm64 changes-gitclone ctools-gitclone democodes-gitclone ``` ## 3.2. 获取帮助 为了统一代码规则,规定必须指定ARCH才可以执行make。如果没有执行过select,可以随意指定一个,比如 `arm`: ```shell make ARCH=arm help make ARCH=arm help-uboot ``` 注意:同名的编译目标在不同的ARCH下可能是不一样的,help信息也是如此。比如riscv不会有atf和optee相关的帮助信息。 ## 3.3. 下载源码 默认情况下,编译时会自动检查依赖,如果源码不存在,会自动通过clone源码。当然也可以手动clone。 这里同样需要指定ARCH,比如optee只能在ARCH为arm或者arm64时下载。如果提前使用select选择了预定义的配置,可以省略ARCH。 官方仓库会包含各个版本的tag。在编译时,会自动checkout到指定的tag。 但是需要注意,重新编译时,在仓库里的修改会被覆盖掉。 ```shell # 下载configs/kernel.mk指定的内核版本,并解压 make ARCH=arm64 kernel-gitclone ``` 如果要分析、修改特定版本的代码,建议下载源码的压缩包,并创建本地git仓库 ```shell # 下载configs/kernel.mk指定的内核版本,并解压 make ARCH=arm64 kernel-dec # 下载、解压自己指定的内核版本,并创建本地git仓库 make ARCH=arm64 UB_VERSION=2022.10 uboot-gitlocl ``` ## 3.4. 变量配置 配置文件后缀为`.mk`,默认的配置文件在`arch`和`configs`目录下,`presets`下也预定义了一些配置。默认配置的形式为`VAR ?= xxx`。 如果需要自己添加配置,只需要在presets创建后缀为`.mk`的文件即可。 presets下预定义的配置可以使用select来进行选择: ```shell $ ./select select from: 1. arm.config.mk 2. arm.tee.config.mk 3. arm64.config.mk 4. arm64.tee.config.mk Please input index: 2 ``` 也可以采用`select + 文件名`的方式: ```shell ./select arm64.config.mk ./select mks/arm64.config.mk ``` 另外select是按字母顺序排列的,也可以直接使用如下命令 ```shell # 通过数字选择 ./select arm64.config.mk ./select 1 ``` select之后,可以直接执行make相关命令,如`make qemu-kernel`。 **注意**: 1. `ARCH`变量必须被指定。 2. 变量优先级:`命令行参数 > export环境变量 > .tmp.config.mk(CONF=) > arch/$(ARCH)/*.mk > configs/*.mk` 3. 部分命令需要 `root`权限,需要提前修改 `SUDO`配置项,防止在执行过程中频繁提示输入密码,如 `SUDO = echo xxxx | sudo`,也可以 `echo "$username ALL=NOPASSWD: ALL" > /etc/sudoers.d/$user`后重新登录来关掉密码。 ## 3.5. 一键运行 如下命令会自动完成代码下载、编译,并使用QEMU模拟启动,命令含义可以参考命令说明部分。 - `make ARCH=arm64 qemu-uboot` - `make ARCH=arm64 qemu-kernel` - `make ARCH=arm64 qemu` ## 3.6. 查看详细过程 可以使用`make V=n`来控制编译时的日志详细程度,n取值为0~5,默认为1,数字越大,详细程度越高。详见`configs/q.mk`。 # 4. 命令说明 ## 4.1. 下载命令 以U-Boot为例, ```shell uboot-gitclone # 下载官方仓库源码 # uboot-gitlocal依赖uboot-dec,uboot-dec依赖uboot-download # 每个命令可单独使用,Makefile中自动处理依赖 uboot-download # 下载特定版本源码压缩包 uboot-dec # 解压下载的源码压缩包 uboot-gitlocal # 在解压后的的目录建立本地git仓库 uboot-gitgc # 清理git仓库中无用的数据,压缩仓库大小 ``` ## 4.2. 编译命令 默认编译命令与模块名相同 ```shell ub-% # 对原u-boot命令的封装,如make ub-help,相对于make -C $uboot_dir help ARCH=... uboot # 编译生成u-boot.bin,会自动同步changes下的修改,并执行uboot-defconfig uboot-defconfig # 使用UB_CONFIG指定的config文件生成.config uboot-menuconfig # 手动修改.config,注意此时执行make uboot会导致修改失效 # 如果只是编译查看效果,可以执行make uboot-all # 如果需要执行make uboot,需要先执行make uboot-savedefconfig uboot-savedefconfig # 保持配置文件changes目录下UB_SAVECONF指定的文件,UB_SAVECONF默认与UB_CONFIG相同 uboot-dis # 反汇编elf文件 ``` ## 4.3. qemu命令 ```shell qemu-dumpdt # 反汇编dtb文件 ``` ## 4.4. arm ```shell qemu # 启动u-boot,u-boot使用qfw加载kernel和rootfs后启动内核 qemu-uboot # 启动u-boot qemu-kernel # 直接启动kernel ``` ## 4.5. arm tee模式 需要将`ARM_TEE`配置为1。注意此时qemu命令与非安全模式不同,使用的defconfig也可能不同。 ```shell qemu # 使用atf启动optee_os和u-boot,u-boot使用qfw加载kernel和rootfs后启动内核 qemu-uboot # 使用atf启动optee_os和u-boot ``` 在tee模式下,qemu会有两个串口,如果不指定,命令行中使用的是normal world的串口。 如果需要指定串口,可以使用QE_SERIAL指定。 | QE_SERIAL | command | 优势 | 缺点 | | :-------- | :----------------------- | :--------------------- | ------------------------------------------------------------------------------------- | | none | 无 | 可直接操作 | 仅支持normal world交互 | | file | 无 | 可保存完整启动日志 | 不可交互 | | udp | nc -u -l -p $port | 可查看启动日志,可交互 | 交互时使用Ctrl + C会使nc退出,重启QEMU需重新连接 | | tcp | nc -l -p $port | 可查看启动日志,可交互 | 需先启动nc监听tcp所有端口再启动QEMU,交互时使用Ctrl + C会使nc退出,重启QEMU需重新连接 | | pty | minicom -D /dev/pty/$NUM | 可交互、可自动重连 | NUM每次运行可能会变,如果不使用-S冻结cpu,会丢失部分启动日志 | QE_SERIAL主要用在 `make qemu-tee`或 `make qemu-ub-tee`时,file/pty/udp/tcp都设置了两个串口,分别用于REE和TEE。 - file:日志分别记录到serial0.log(non-secure)和serial1.log(secure) - udp:port值为55550(non-secure)和55551(secure) - tcp:port值为55500(non-secure)和55501(secure) - pty:可查看QEMU启动最后的日志来得到NUM的值,serial0为non-secure,serial1为secure `make qemu QE_SERIAL=pyt QEO_EXTRA=-S`后,使用minicom连接pty。再到qemu命令行输入c解冻cpu后可以看到输出。 ## 4.6. riscv ```shell qemu # 使用opensbi启动kernel qemu-uboot # 启动u-boot qemu-kernel # 同qemu ``` # 5. gdb 当前仅支持arm非安全模式,使用如下命令,可在qemu启动时冻结cpu。 ```shell make qemu-uboot-gdb make qemu-kernel-gdb ``` 之后,在另一终端执行如下命令可以启动gdb命令 ```shell make gdb-uboot make gdb-kernel ``` # 6. 根文件系统 `RFS_MODE`选择使用`busybox(bb)/buildroot(br)/debootstrap(bs)`,括号内是`RFS_MODE`的取值,默认为`br`。 `RFS_TYPE`选择根文件系统类型,默认为`ext4`。 注意在`ARM_TEE`为1的情况,busybox和buildroot会编译optee_client和optee_examples。 ## 6.1. busybox ## 6.2. buildroot 为保证buildroot使用的busybox与bb模式版本一致,使用外部busybox仓库。 ## 6.3. bootstrap 构建需要sudo权限。构建出的根文件系统默认用户为root,密码123。 # 7. 其他操作 ## 7.1. 新建defconfig 以U-Boot为例 方式一: 1. 基于现有的 `xxx_defconfig`进行 `make uboot-defconfig`,如 `make ARCH=arm64 uboot-defconfig UB_CONFIG=mine_arm64_defconfig`。 2. 执行 `make ARCH=arm64 ub-menuconfig`,并根据需要进行修改并保存。 3. 执行 `make ARCH=arm64 uboot-savedefconfig UB_SAVECONF=mine_arm64_defconfig`。 方式二: 1. 基于现有的 `xxx_defconfig`复制生成新的config,如 `cp u-boot/configs/qemu_arm64_defconfig u-boot/configs/mine_arm64_defconfig`。 2. 执行 `make ARCH=arm64 ub-menuconfig`,并根据需要进行修改并保存。 3. 执行 `make ARCH=arm64 uboot-savedefconfig`,这一步会生成 `defcong`并,将 `defconfig`保存到 `u-boot/configs/mine_arm64_defconfig` 之后就可以通过修改 `config.mk`或使用 `make ARCH=arm64 uboot UB_CONFIG=mine_arm64_defconfig`进行编译。 # 8. 已知问题 1. debootstrap只能构建与所属根文件系统相同的根文件系统,如Debian系统或docker不能构建Ubuntu rootfs 2. Ubuntu dbootstrap只支持amd64和i386,不支持ARM 3. Debian debootstrap构建riscv根文件系统要求目标为Debian 13