# 建立 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 地址:

設定完 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)