--- 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 的形式存在 ![](https://i.imgur.com/CSqXql8.png) 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` 來做調整 ![](https://i.imgur.com/OwK34K0.png) 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 在系統中了 ![](https://i.imgur.com/PZkA4b9.png) 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 個小時依然不行,先不往下繼續做