---
tags: linux2019
---
riscv 作業紀錄
===
作業要求
---
* 回答上述「自我檢查清單」的所有問題,需要附上對應的參考資料和必要的程式碼,以第一手材料 (包含自己設計的實驗) 為佳
* 調整 buildroot 設定,讓原本輸出的 ext2 image 佔用約 14 MB 空間,變得更精簡
* 移除套件,但確保仍可開機並提供必要的服務及工具
* Busybox 裡頭的 vi 也不需要存在,改用 kilo
* 編譯 [kilo](https://github.com/sysprog21/kilo) 編輯器,允許在 RISC-V/Linux 模擬環境中運作
* 客製化 buildroot,將 [kilo](https://github.com/sysprog21/kilo) 編輯器加入到 build image,建立 Git repository 來追蹤你對 buildroot 做的變更,並依據 [Buildroot Manual](https://buildroot.org/downloads/manual/manual.html) 更新套件描述和建構方式
* 重新編譯 Linux 核心,確保能在 [riscv-emu](https://github.com/sysprog21/riscv-emu) 運作,並思考縮減 image size 的方法
* 先從 `$ make menuconfig` 調整核心選項開始,當然要能開機才有效益
* 參照 [Linux Kernel Tinification](https://tiny.wiki.kernel.org)
What is virtio
---
引用 [Virtio: An I/O virtualization framework for Linux](https://developer.ibm.com/articles/l-virtio/) 中的圖片,virtio 是作為在半虛擬化中,hypervisor 與 guest OS 溝通的通用 interface,也就是無論是哪個 hypervisor,只要他遵守 virtio 的規範實作 backend driver 便可以運作,通常會是以一個 kernel module 或是 driver 的形式存在

Buildroot
---
在配置實驗環境過程中有使用到 Buildroot 這個工具,那究竟甚麼是 Buildroot? 他在安裝過程中的角色又是甚麼呢? 先翻翻維基百科:
> Buildroot is a set of Makefiles and patches that simplifies and **automates the process of building a complete and bootable Linux environment** for an embedded system, while using cross-compilation to allow building for multiple target platforms on a single Linux-based development system.
整理一下,Buildroot 可以做到以下幾件事情:
- build cross-compilation toolchain
- create root file system <--- 注意,這是我們正要做的事
- compile linux kernel image
- generate bootloader
利用 `make menuconfig` 指令調整 .config 文件中的內容,可以看到有不少選項可以做調整,而這些選項的設定則是在 `package/` 資料夾以及各子資料夾中的 `Config.in` 來做調整

make
---
首先解決 dependency
```
apt install libncurses5-dev kernel-package fakeroot dpkg-dev build-essential libc6-dev libssl-dev libelf-dev bison flex
```
在我的環境下編譯會發生奇怪的錯誤
```
echo timestamp > s-fixinc_list
/usr/bin/g++ -no-pie -O2 -I/home/hexrabbit/riscv-emu/buildroot/buildroot-riscv-2018-10-20/output/host/usr/include -DIN_GCC -DCROSS_DIRECTORY_STRUCTURE -fno-exceptions -fno-rtti -fasynchronous-unwind-tables -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual -Wmissing-format-attribute -Woverloaded-virtual -pedantic -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -DHAVE_CONFIG_H -static-libstdc++ -static-libgcc -L/home/hexrabbit/riscv-emu/buildroot/buildroot-riscv-2018-10-20/output/host/lib -L/home/hexrabbit/riscv-emu/buildroot/buildroot-riscv-2018-10-20/output/host/usr/lib -Wl,-rpath,/home/hexrabbit/riscv-emu/buildroot/buildroot-riscv-2018-10-20/output/host/usr/lib -o cc1 c/c-lang.o c-family/stub-objc.o attribs.o c/c-errors.o c/c-decl.o c/c-typeck.o c/c-convert.o c/c-aux-info.o c/c-objc-common.o c/c-parser.o c/c-array-notation.o c/c-fold.o c/gimple-parser.o c-family/c-common.o c-family/c-cppbuiltin.o c-family/c-dump.o c-family/c-format.o c-family/c-gimplify.o c-family/c-indentation.o c-family/c-lex.o c-family/c-omp.o c-family/c-opts.o c-family/c-pch.o c-family/c-ppoutput.o c-family/c-pragma.o c-family/c-pretty-print.o c-family/c-semantics.o c-family/c-ada-spec.o c-family/c-cilkplus.o c-family/array-notation-common.o c-family/cilk.o c-family/c-ubsan.o c-family/c-attribs.o c-family/c-warn.o glibc-c.o \
cc1-checksum.o libbackend.a main.o libcommon-target.a libcommon.a ../libcpp/libcpp.a ../libdecnumber/libdecnumber.a libcommon.a ../libcpp/libcpp.a ../libbacktrace/.libs/libbacktrace.a ../libiberty/libiberty.a ../libdecnumber/libdecnumber.a -L/home/hexrabbit/riscv-emu/buildroot/buildroot-riscv-2018-10-20/output/host/usr/lib -L/home/hexrabbit/riscv-emu/buildroot/buildroot-riscv-2018-10-20/output/host/usr/lib -L/home/hexrabbit/riscv-emu/buildroot/buildroot-riscv-2018-10-20/output/host/usr/lib -lmpc -lmpfr -lgmp -rdynamic -ldl -L./../zlib -lz
collect2: error: ld returned 1 exit status
../../gcc/c/Make-lang.in:85: recipe for target 'cc1' failed
make[3]: *** [cc1] Error 1
make[3]: *** Waiting for unfinished jobs....
rm gcc.pod
Makefile:4208: recipe for target 'all-gcc' failed
```
浪費接近一個小時後發現是我 server 上的 lvm 設定太小,空間不足造成的...
接著又出現新的問題
```
configure: error:
*** These critical programs are missing or too old: bison
*** Check the INSTALL file for required versions.
```
不過這次簡單多了,一句 `apt install bison` 就可以解決
Remove vi
---
可以利用
```
make busybox-menuconfig
```
來設定 busybox 中要編入的 binary,將 `vi` 那欄取消勾選即可
Customize buildroot
---
有關如何新增 package 到 buildroot 裡的方法可以在 manual 的 [Adding packages](https://buildroot.org/downloads/manual/manual.html#adding-packages) 條目找到,不過在這之前可以先閱讀 [How buildroot works](https://buildroot.org/downloads/manual/manual.html#_how_buildroot_works)
:::info
The `package/` directory contains the Makefiles and associated files for all user-space tools and libraries that Buildroot can compile and add to the target root filesystem. There is one sub-directory per package.
:::
可以得知 userspace tools 會被放在 `package/` 裡,並且每個工具皆會被放在獨立的資料夾中,資料夾中的檔案至少會有以下兩個:
- **`something.mk`**: the Makefile that downloads, configures, compiles and installs the package something.
- **`Config.in`**: a part of the configuration tool description file. It describes the options related to the package.
對 kilo 這個小程式來說,也只需要用到這兩個檔案便可以完成設定,將 Github 作為 source 的方式可以參考 [How to add a package from Github](https://buildroot.org/downloads/manual/manual.html#github-download-url)
**kilo.mk**
```
################################################################################
#
## kilo
#
#################################################################################
KILO_VERSION = "af3919d68cb2e70a3d9a2309596cf290cf6bc1ac"
KILO_SITE = $(call github,sysprog21,kilo,$(FOO_VERSION))
define KILO_BUILD_CMDS
$(MAKE) CC="$(TARGET_CC)" LD="$(TARGET_LD)" -C $(@D)
endef
define KILO_INSTALL_TARGET_CMDS
$(INSTALL) -D -m 0755 $(@D)/kilo $(TARGET_DIR)/usr/bin
endef
$(eval $(generic-package))
```
**Config.in**
```
config BR2_PACKAGE_KILO
bool "kilo"
help
Kilo is a small text editor in less than 1K lines of code (counted with cloc).
https://github.com/sysprog21/kilo
```
ERROR!
---
原以為這樣就設定好了,結果 make 的時候依然報錯,似乎是 KILO_SITE 的設定出了點問題,但是 `$(call github,sysprog21,kilo,$(FOO_VERSION))` 確實和官方提供的腳本一致阿?
```shell
package/kilo/kilo.mk:18: *** KILO_SITE (https://github.com/sysprog21/kilo/archive/) cannot have a trailing slash. Stop.
Makefile:36: recipe for target '_all' failed
make: *** [_all] Error 2
```
嘗試將 KILO_SITE 手動改成 `https://github.com/sysprog21/kilo/archive` 結果變成另一個錯誤
```
>>> kilo af3919d68cb2e70a3d9a2309596cf290cf6bc1ac Downloading
--2019-05-05 08:16:05-- https://github.com/sysprog21/kilo/archive/kilo-af3919d68cb2e70a3d9a2309596cf290cf6bc1ac.tar.gz
Resolving github.com (github.com)... 192.30.253.113
Connecting to github.com (github.com)|192.30.253.113|:443... connected.
HTTP request sent, awaiting response... 302 Found
Location: https://codeload.github.com/sysprog21/kilo/tar.gz/kilo-af3919d68cb2e70a3d9a2309596cf290cf6bc1ac [following]
--2019-05-05 08:16:06-- https://codeload.github.com/sysprog21/kilo/tar.gz/kilo-af3919d68cb2e70a3d9a2309596cf290cf6bc1ac
Resolving codeload.github.com (codeload.github.com)... 192.30.253.121
Connecting to codeload.github.com (codeload.github.com)|192.30.253.121|:443... connected.
HTTP request sent, awaiting response... 404 Not Found
2019-05-05 08:16:07 ERROR 404: Not Found.
```
這真的是太迷了,自己手動 request 上面的網址後也發現沒辦法下載,但將 `kilo-` prefix 去掉後就可以了,初步判斷可能是 github 更新了下載 archive 的方式,
接著嘗試設定
```
KILO_SITE = git://github.com/sysprog21/kilo
KILO_SITE_METHOD = git
```
之後重新 make 便可以正常運作了,編譯好的 rootfs 會被放在 output/images 之下
編譯結束後開啟 temu 便可以發現 build 好的 kilo 在系統中了

Network setting
---
根據 temu 的 [readme.txt](https://bellard.org/tinyemu/readme.txt) 我們可以透過 tap/tun 建立的虛擬網路環境來讓 guest 能夠連接上網路,以下是 temu 提供的預設 script `netinit.sh`:
```shell
internet_ifname="eno1" # Change it to your network interface
# setup bridge interface
ip link add br0 type bridge
# create and add tap0 interface to bridge
ip tuntap add dev tap0 mode tap user $USER
ip link set tap0 master br0
ip link set dev br0 up
ip link set dev tap0 up
ifconfig br0 192.168.3.1
# setup NAT to access to Internet
echo 1 > /proc/sys/net/ipv4/ip_forward
# delete forwarding reject rule if present
iptables -D FORWARD 1
iptables -t nat -A POSTROUTING -o $internet_ifname -j MASQUERADE
```
照著設定結果 guest 那邊沒辦法連上網路,
弄了 4 個小時依然不行,先不往下繼續做