FreeBSD Kernel-编译环境搭建

yyi
yyi
2023-08-30 / 0 评论 / 304 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2023年09月07日,已超过315天没有更新,若内容或图片失效,请留言反馈。

FreeBSD Kernel-编译环境搭建

0 概述

本文章介绍一个搭建基于Qemu的FreeBSD虚拟机、在Linux下交叉编译FreeBSD内核并替换FreeBSD内核的开发环境。

1 文件准备

我把以下的步骤都打包为一个docker image:yirannn/modular-os-env,如果你使用该镜像,可以略过文件准备部分

1.1 FreeBSD SRC

你可以在官方网站或者科大镜像下载你需要的文件,其中src.txz为FreeBSD的源码

1.2 FreeBSD QCOW2

你可以在官方网站或者科大镜像下载qemu可用的qcow2文件,用于作为替换内核的基础镜像

1.3 编译软件包

下载好文件后,你可以选择参照我的镜像Dockerfile来安装软件包。

apt-get install qemu-system wget bmake gcc g++ clang-14 lld-14 libarchive-dev

1.4 启动Docker

docker run -it --name modular-os-zswap --privileged=true yirannn/modular-os-env bash
如果出现 mount无权限、qemu无kvm,首先怀疑是不是privileged没打开

2 编译

2.1 编译命令的来源

FreeBSD的源码并未直接准备好在Linux下编译,但是在FreeBSD 13之后,官方开始在macOS、Linux下进行交叉编译,并提供了Github CI进行验证。我在Action中翻到了相关的编译命令,仿照相关命令进行编译。这意味着我其实并不知道每一步具体都干了什么,如果你对此有疑问,建议可以自行查阅FreeBSD的Github Action

name: Cross-build Kernel

on:
  push:
    branches: [ main, 'stable/13' ]
  pull_request:
    branches: [ main ]

permissions:
  contents: read

jobs:
  build:
    name: ${{ matrix.target_arch }} ${{ matrix.os }} (${{ matrix.compiler }})
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        target_arch: [ amd64, aarch64 ]
        os: [ ubuntu-20.04, ubuntu-22.04, macos-latest ]
        include:
          # TODO: both Ubuntu and macOS have bmake packages, we should try them instead of bootstrapping our own copy.
          - os: ubuntu-20.04
            compiler: clang-12
            cross-bindir: /usr/lib/llvm-12/bin
            pkgs: bmake libarchive-dev clang-12 lld-12
          - os: ubuntu-22.04
            compiler: clang-14
            cross-bindir: /usr/lib/llvm-14/bin
            pkgs: bmake libarchive-dev clang-14 lld-14
          - os: macos-latest
            compiler: clang-13
            cross-bindir: /usr/local/opt/llvm@13/bin
            pkgs: bmake libarchive llvm@13
          - target_arch: amd64
            target: amd64
          - target_arch: aarch64
            target: arm64
    steps:
      - uses: actions/checkout@v3
      - name: install packages (Ubuntu)
        if: runner.os == 'Linux'
        run: |
          sudo apt-get update --quiet || true
          sudo apt-get -yq --no-install-suggests --no-install-recommends install ${{ matrix.pkgs }}
      - name: install packages (macOS)
        if: runner.os == 'macOS'
        run: |
          brew update --quiet || true
          brew install ${{ matrix.pkgs }} || true
      - name: create environment
        run: |
          echo "GITHUB_WORKSPACE = $GITHUB_WORKSPACE"
          if [ -n "${{ matrix.cross-bindir }}" ]; then
            echo "EXTRA_BUILD_ARGS=--cross-bindir=${{ matrix.cross-bindir }}" >> $GITHUB_ENV
          fi
          mkdir -p ../build
          echo "MAKEOBJDIRPREFIX=${PWD%/*}/build" >> $GITHUB_ENV
          # heh, works on Linux/BSD/macOS ...
          echo "NPROC=`getconf _NPROCESSORS_ONLN 2>/dev/null || getconf NPROCESSORS_ONLN 2>/dev/null || echo 1`" >> $GITHUB_ENV
      - name: bootstrap bmake
        run: ./tools/build/make.py --debug $EXTRA_BUILD_ARGS TARGET=${{ matrix.target }} TARGET_ARCH=${{ matrix.target_arch }} -n
      - name: make kernel-toolchain
        run: ./tools/build/make.py --debug $EXTRA_BUILD_ARGS TARGET=${{ matrix.target }} TARGET_ARCH=${{ matrix.target_arch }} kernel-toolchain -s -j$NPROC -DWITH_DISK_IMAGE_TOOLS_BOOTSTRAP
      - name: make buildkernel
        run: ./tools/build/make.py --debug $EXTRA_BUILD_ARGS TARGET=${{ matrix.target }} TARGET_ARCH=${{ matrix.target_arch }} KERNCONF=GENERIC NO_MODULES=yes buildkernel -s -j$NPROC $EXTRA_MAKE_ARGS

2.2 编译

FreeBSD的编译需要几个环境变量,我们构建如下的目录结构

parent --|-- src
           |    |--- tools --- build
           |
           |-- obj

并在parent目录下声明如下变量

export BASEDIR=$(pwd)
export MAKEOBJDIRPREFIX=$BASEDIR/obj

这之后,进入src目录,开始编译

cd $BASEDIR/src
# 进入src目录
./tools/build/make.py --debug --cross-bindir=/usr/lib/llvm-14/bin/ TARGET=amd64 TARGET_ARCH=amd64 -n
# Bootstrap
./tools/build/make.py --debug --cross-bindir=/usr/lib/llvm-14/bin/ TARGET=amd64 TARGET_ARCH=amd64 kernel-toolchain -s -j32 -DWITH_DISK_IMAGE_TOOLS_BOOTSTRAP
# Toolchain
./tools/build/make.py --debug --cross-bindir=/usr/lib/llvm-14/bin/ TARGET=amd64 TARGET_ARCH=amd64 KERNCONF=GENERIC NO_MODULES=yes buildkernel -s -j32
# Kernel

其中 cross-bindir 指示了用于交叉编译的编译器二进制文件存放目录,TARGET和TARGET_ARCH指示了交叉编译的目标系统架构,编译好的内核在 obj/root/source/freebsd/src/amd64.amd64/sys/GENERIC/kernel.full

3 内核替换

3.1 准备共享区

共享区是为了把宿主机编译好的 kernel.full 传递给 qemu 启动的虚拟机

首先创建一块4M*1K的虚拟磁盘,用ext4格式化

dd if=/dev/zero of=/opt/share.img bs=4M count=1k
mkfs.ext4 /opt/share.img

创建一个目录,把该虚拟磁盘文件挂到该目录,并把编译好的内核放在该目录中

如果 mount 无权限,但已经在超级用户权限下了,考虑是否容器启动没有priviledged

mkdir /tmp/share
mount -o loop /opt/share.img /tmp/share
cp $BASEDIR/obj/root/source/freebsd/src/amd64.amd64/sys/GENERIC/kernel.full /tmp/share

3.2 准备虚拟机

3.2.1 启动虚拟机

在第一步骤中已经下载好了qcow2在本步骤中我们进行一个使用

unxz FreeBSD-12.4-RELEASE-amd64.qcow2.xz
qemu-img resize FreeBSD-12.4-RELEASE-amd64.qcow2 +1G
# 调整镜像大小,如果不调整,后续无法安装软件包

这之后,使用qemu启动FreeBSD

qemu-system-x86_64 -drive file=FreeBSD-12.4-RELEASE-amd64.qcow2,format=qcow2 -enable-kvm -hdb /opt/share.img
目前qemu启动FreeBSD还必须用一个图形界面,如果使用-nographic 选项,会导致FreeBSD无法正常Boot

image-20230830143855231

这之后,使用root用户登录,没有密码

输入uname -a 查看内核版本,可以看到我们加载的是 FreeBSD 12.4

image-20230830203237380

接下来挂载我们刚刚准备好的共享区

pkg install sysutils/fusefs-ext2

这一步需要按两次y,并有可能出现磁盘空间不足的问题。这可能是由于前步未执行扩展qcow2指令导致的

3.2.2 如果空间不足怎么办

关闭虚拟机,回到宿主机,尝试扩展qcow2文件

qemu-img resize FreeBSD-12.4-RELEASE-amd64.qcow2 +1G

重新用刚刚的命令启动qemu,在FreeBSD中

gpart show

image-20230830203714880

可以看到freebsd-ufs的空间情况和分区号

使用gpart扩展ufs分区

gpart resize -i 4 -a 4k -s 5G ada0
growfs /dev/gpt/rootfs

重新安装fusefs-ext2模块

3.2.3 挂载

使用camcontrol命令查看当前系统的硬件设备

image-20230830203949697

第一块盘ada0是启动的系统盘,第二块是我们在qemu中用hdb参数挂上去的共享盘

用fuse-ext2对这个盘进行映射

kldload fuse.ko # 如果不注册,每次用都得加载一下
mkdir /share
fuse-ext2 /dev/ada1 /share
ls /share

image-20230830205845006

把kernel替换掉

cd /boot/kernel
mv kernel kernel.old
cp /share/kernel.full ./kernel
reboot

等待系统重启,重新uname -a

image-20230830210308124

此时可以看到内核已经更新到我们编译的13.2

0

评论 (0)

取消