# 建立 Debian root file system :::danger TODO: 列出完整步驟和描述實驗平台 ::: ## 建立 rootfs.img 實驗環境組態: Ubuntu 24.04 ### 1. 配置基本服務 #### 安裝所需要的套件: ```shell $ sudo apt install \ debootstrap \ qemu qemu-user-static qemu-system qemu-utils qemu-system-misc \ binfmt-support \ dpkg-cross debian-ports-archive-keyring --no-install-recommends ``` 升級到 Ubuntu 24.04 之後的版本會遇到: ```shell E: Package 'qemu' has no installation candidate ``` 因為直接把整個 meta-packages下載下來已經過時了,根據[官網](https://www.qemu.org/download/#linux:~:text=pacman%20%2DS%20qemu-,Debian/Ubuntu%3A,-For%20full%20system)所揭露的資訊,使用 `apt-get install qemu-system` 與 ` apt-get install qemu-user-static` 即可。 #### 創建、格式化並掛載一個新的檔案系統映像: ```shell $ dd if=/dev/zero of=rootfs.img bs=1M count=4096 $ mkdir rootfs $ mkfs.ext4 rootfs.img $ sudo mount rootfs.img rootfs ``` #### 執行 `debootstrap`: 此處要修改 debian 鏡像的來源,將`http://deb.debian.org/debian-ports` 改為 `http://httpredir.debian.org/debian` ,由於前者已失效,若未改正則會得到錯誤訊息 `E: Invalid Release file, no entry for main/binary-riscv64/Packages ` 更正後如下: ```shell $ sudo debootstrap --arch=riscv64 --foreign --keyring /usr/share/keyrings/debian-archive-keyring.gpg --include=debian-archive-keyring sid ./temp-rootfs http://deb.debian.org/debian ``` 注意在此命令中使用了 `--foreign` ,此選項可以使 `debootstrap` 僅執行安裝過程的第一階段: 下載所需的 package,但不進行解壓縮或配置,此舉可以在一個不同架構的環境下(x86)下載和準備所有必要的文件,然後在目標架構的環境下(riscv64)完成安裝。 若遇到 `E: Release signed by unknown key (key id 6ED0E7B82643E131)` 則需要要手動下載並導入鑰匙,由於錯誤訊息中指出具體的鑰匙 ID(6ED0E7B82643E131),我們可以直接從 Debian 的加密金鑰伺服器下載並手動導入這個鑰匙: ```shell gpg --keyserver keyserver.ubuntu.com --recv-keys 6ED0E7B82643E131 gpg --export 6ED0E7B82643E131 | sudo gpg --no-default-keyring --keyring /usr/share/keyrings/debian-ports-archive-keyring.gpg --import ``` 為何需要「鑰匙」呢?這牽扯到[RSA加密演算法](https://en.wikipedia.org/wiki/RSA_(cryptosystem)),為了..(待補充) 命令執行完後可以進入 `rootfs` 內檢查是否有配置成功,若缺乏 ### 3. 配置 binfmt: binfmt_misc 是一個用於告知 Linux 如何處理不同執行檔格式的核心模組,註冊後便可以夠識別並運行 `riscv64` 架構的執行檔。 此外,為了確保在使用 chroot 更改根目錄後,依然能在新的根目錄中執行 `/usr/bin/qemu-riscv64-static`,須先將 `qemu-riscv64-static ` 複製至 rootfs 的 `/usr/bin/` 在開始複製前可以用`qemu-riscv64-static --version`檢查 `qemu-riscv64-static` 的版本: ```shell qemu-riscv64 version 9.0.2 (v9.0.2) Copyright (c) 2003-2024 Fabrice Bellard and the QEMU Project developers ``` 確認是最新的後便可以複製到 `rootfs` 中 ```shell $ sudo cp -rf /usr/bin/qemu-riscv64-static rootfs/usr/bin/ ``` #### 註冊: ```shell $ cat > /tmp/riscv64 <<- EOF package qemu-user-static type magic offset 0 magic \x7f\x45\x4c\x46\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xf3\x00 mask \xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff interpreter /usr/bin/qemu-riscv64-static EOF ``` 接著導入 `binfmt` ```shell $ sudo update-binfmts --import /tmp/riscv64 ``` 最後檢查是否註冊成功: ```shell $ ls /proc/sys/fs/binfmt_misc/riscv64 ``` 若未輸出:`/proc/sys/fs/binfmt_misc/riscv64` 則可以嘗試重啟 binfmt_misc ```shell $ sudo systemctl restart binfmt-support ``` 如果沒有這步驟的話 host 端(x86_64)會認不得 rootfs/bin/bash (riscv64),也就無法進入 chroot. 然而這個錯誤在更新 ubuntu 之後便消失了,原因待查明。 ### 4. 完成第二階段 `debootstrap` 第二階段的 `debootstrap` 會在由 qemu 模擬的 riscv64 的環境下進行,如此一來便可以避免因 host 與 target 端不相容而產生錯誤。 進入 `chroot` 環境 : ```shell sudo chroot rootfs/ ``` 執行 `debootstrap` 命令的 `--second-stage` ```shell $ /debootstrap/debootstrap --second-stage ``` #### 配置 `rootfs` 配置 source.list 並將 source 改為 `http://ftp.debian.org/debian`: ```shell $ cat >/etc/apt/sources.list <<EOF deb http://ftp.debian.org/debian sid main deb http://ftp.debian.org/debian unstable main deb http://ftp.debian.org/debian experimental main EOF ``` 若未對其修正會遇到以下錯誤: ``` shell N: Skipping acquire of configured file 'main/binary-riscv64/Packages' as repository 'http://ftp.ports.debian.org/debian-ports experimental InRelease' doesn't support architecture 'riscv64' E: The repository 'http://ftp.debian.org/debian unreleased Release' does not have a Release file. ``` 安裝套件包: ```shell $ apt-get update $ apt-get install -y util-linux haveged openssh-server systemd kmod initramfs-tools conntrack ebtables ethtool iproute2 iptables mount socat ifupdown iputils-ping vim neofetch sudo chrony pciutils ``` 配置網路: ```shell $ mkdir -p /etc/network $ cat >/etc/network/interfaces <<EOF auto lo iface lo inet loopback auto eth0 iface eth0 inet dhcp EOF $ cat >/etc/resolv.conf <<EOF nameserver 1.1.1.1 nameserver 8.8.8.8 EOF ``` 配置分區: ```shell $ cat >/etc/fstab <<EOF LABEL=rootfs / ext4 user_xattr,errors=remount-ro 0 1 EOF ``` 清理暫存: ```shell $ apt-get clean $ rm -rf /var/cache/apt/ ``` 退出 `chroot` 並解除 `mount` : ```shell $ exit $ sudo umount rootfs ``` 輸出得到的 `rootfs.img` ## 利用 [qemu-system-riscv64](https://github.com/oscomp/riscv-linux-rootfs) 運作 Debian GNU/Linux - virtio-net - virtio-block - dropbear ssh server 照著 README 的教學執行 make 時會遇到錯誤: ```shell ../sysoptions.h:258:10: error: #error "DROPBEAR_SVR_PASSWORD_AUTH requires `crypt()'." 258 | #error "DROPBEAR_SVR_PASSWORD_AUTH requires `crypt()'." | ^~~~~ ``` 顯示 DROPBEAR_SVR_PASSWORD_AUTH 需要 crypt(),查閱 [manpage](https://man7.org/linux/man-pages/man3/crypt.3.html) 可以得到: >crypt() is the password hashing function. It is based on the Data Encryption Standard algorithm with variations intended (among other things) to discourage use of hardware implementations of a key search. ## 建立測試環境 1. 備份鏡像檔: 利用 Win32 Disk Imager 備份目前使用的 SD card 內容,將其備份為 [backup.img](https://drive.google.com/file/d/1yPnVa5qMaCEQ_XvOX_64E2x7Sg9pMyzw/view?usp=sharing) 後再用 Win32 Disk Imager 燒錄至其他 SD card ,以便在其他 Tinker V 上運行。 3. 同時連接多台 Tinker V : 為了要同時連接多台 Tinker V ,需要設定 wifi 路由器,使得每台 Tinker V 能被分配到固定的 ip 地址: ![image](https://hackmd.io/_uploads/BJpSxBZ-ye.png) 設定完 ip 地址後便可以不用 UART ,之後要使用時可以直接使用 ssh 連線來連接板子(當然,要接上電源與網路線) 為了避免搞混,我將板子的 hostname 改為其 ip 地址。 此外可以在板子 108 上用 ssh 連線到板子 105 上: ```shell root@192-168-0-108:~# ssh root@192.168.0.105 Last login: Thu Oct 31 17:44:22 2024 from 192.168.0.106 root@192-168-0-105:~# ``` 蠻酷的,之後如果要在板子之間傳遞資訊便可以不需要依賴 PC 端,但缺點是 wifi 路由器會很燙,建議買好一點的。 3. USB 連線: 先在 pc 端下載 Android Debug Bridge (adb) 可以在 pc 端用 `adb devices -l` 命令來檢查已連線至哪些 `adb` 伺服器。 有時會遇到未列出已連接的裝置,此時可以注意電腦與開發板是否過熱 ## 參考資訊 * [从零开始构建 RISC-V 架构下的 Debian 根文件镜像](https://www.gloomyghost.com/live/20220503.aspx) * [Debian-Rootfs-Guide](https://github.com/carlosedp/riscv-bringup/blob/master/Debian-Rootfs-Guide.md) * [binfmt_misc]() * [Debootstrap](https://linux.die.net/man/8/debootstrap) * [RISC-V System emulator](https://www.qemu.org/docs/master/system/target-riscv.html) * [virt Generic Virtual Platform ](https://www.qemu.org/docs/master/system/riscv/virt.html) * [RISC-V Debian Rootfs from scratch](https://github.com/carlosedp/riscv-bringup/blob/master/Debian-Rootfs-Guide.md)