Raspberry PI NFS rootfs 和 Remote linux kernel === 本篇主要透過TFTP和NFS功能,實作遠端系統開機(就是Rootfs和Linux kernel在遠端主機上)。 之前看到了一些介紹NFS rootfs的文章,感到有興趣,於是打算來實作看看。由於是第一次嘗試,所以遇到了一些問題。感謝各位社群網友的幫忙,才讓我成功完成。 --- ### 環境: Linux Kernel: https://github.com/raspberrypi/linux U-Boot: https://github.com/u-boot/u-boot Raspberry pi 4b+ Debian rootfs: https://rcn-ee.com/rootfs/eewiki/minfs/debian-11-minimal-arm64-2021-08-17.tar.xz Raspberry pi Firmware: https://github.com/raspberrypi/firmware Raspberry pi官方建置Linux Kernel文件: https://www.raspberrypi.org/documentation/computers/linux_kernel.html Ubuntu Host USB Ethernet Card Raspberry pi PXE參考資料: https://linuxhit.com/raspberry-pi-pxe-boot-netbooting-a-pi-4-without-an-sd-card/ --- ### Linux Kernel,Uboot編譯過程,Raspberry pi Firmware安裝請參考: [Raspberry pi Build System (64bits)](https://hackmd.io/p_eQ-5QdRE-NpweHBE4_Eg?view) 請事先編譯好Linux Kernel, Uboot,分割好SDCARD, 並將Raspberry pi Firmware, config.txt安裝在SDCARD第一分區(FAT32開機磁區)。 :::info * 由於Raspberry pi 預設的Linux Kernel設定檔案(bcm2711_defconfig)並沒有啟用Network NFS Rootfs,要在設定檔中補上設定。 * 需要補上設定的檔案為(Linux Kernel資料夾裡): arch/arm64/configs/bcm2711_defconfig * 確認圖中的設定,都有在檔案裡: ![](https://i.imgur.com/H1zuIZv.png) ::: 本次實作僅保留第一分區的檔案(Raspberry pi Firmware, FDT, config.txt),並且砍掉Image(Linux Kernel)。 * Image(Linux Kernel)會由tftp load進來。 * Rootfs(第二分區)會由NFS load進來。 本次實作開機過程: Mount the FAT32 boot partition => bootcode.bin => GPU firmware => UBoot (u-boot.bin) => Linux Kernel(tftp load) => Rootfs(Linux kernel load over NFS) --- ### TFTP架設: * 透過xinetd將TFTP-server放置至背景執行。 [參考](https://yulun.me/2016/setup-tftp-server-on-ubuntu/) 1. 安裝套件 ```bash= sudo apt-get install xinetd tftpd tftp ``` 2. 新增設定檔,/etc/xinetd.d/tftp ```text= service tftp { protocol = udp port = 69 socket_type = dgram wait = yes user = nobody server = /usr/sbin/in.tftpd server_args = -s /tftpboot flags = IPv4 disable = no } ``` :::info * server_args: TFTP資料夾位置,這裡我直接指定Kernel編譯完成後,Image產生的資料夾 * user: nobody [參考](https://zh.wikipedia.org/wiki/Nobody_(%E7%94%A8%E6%88%B7%E5%90%8D)) * nobody是一個沒有任何權限的用戶。該用戶不擁有任何文件,也沒有任何特殊權限。只能訪問所有帳戶都能訪問的目錄或檔案。 ::: 3. 建立目錄: ```bash= sudo mkdir /tftpboot sudo chmod -R 777 /tftpboot ``` 4. 重新啟動xinetd: ```bash= sudo service xinetd restart ``` 5. 搬移編譯好的Linux Kernel到指定目錄: ```bash= sudo cp arch/arm64/boot/Image /tftpboot ``` --- ### NFS Server架設: 1. 安裝nfs-server ```bash= sudo apt-get install nfs-kernel-server ``` 2. 指定NFS server版本到V3,編輯/etc/default/nfs-kernel-server ```bash= #RPCNFSDCOUNT=8 RPCNFSDCOUNT="--no-nfs-version 4" ``` 3. 指定NFS分享目錄,編輯cat /etc/exports ```bash= /export/user/fs *(rw,nohide,insecure,no_subtree_check,sync,no_root_squash) ``` :::info /export/user/fs 為放置Rootfs的目錄 ::: :::info no_root_squash: 用戶端使用 NFS 檔案系統的帳號若為 root 時,系統不會壓縮成nobody使用者,直接給予用戶端root權限 ::: 4. 輸出設定內容並重新啟動nfs server完成設定 ```bash= sudo exportfs -ra sudo systemctl restart nfs-kernel-server ``` --- ### 安裝rootf到指定目錄: 請參考[完整範例](https://hackmd.io/p_eQ-5QdRE-NpweHBE4_Eg) 1. 從官方git將rootfs下載下來: ```bash= wget https://rcn-ee.com/rootfs/eewiki/minfs/debian-11-minimal-arm64-2021-08-17.tar.xz ``` 2. 解壓縮後,檔案如下: ```bash= user@user-machine:~/test$ tar Jxvf debian-11-minimal-arm64-2021-08-17.tar.xz ./debian-11-minimal-arm64-2021-08-17/ ./debian-11-minimal-arm64-2021-08-17/image-builder.project ./debian-11-minimal-arm64-2021-08-17/arm64-rootfs-debian-bullseye.tar ./debian-11-minimal-arm64-2021-08-17/user_password.list ``` 3. 將Rootfs放置到目標目錄(/export/user/fs): ```bash= sudo tar xvf debian-11-minimal-arm64-2021-08-17/arm64-rootfs-debian-bullseye.tar -C /export/user/fs ``` --- ### 安裝Kernel到指定目錄: Kernel編譯請參考[連結](https://hackmd.io/p_eQ-5QdRE-NpweHBE4_Eg) * 安裝Linux module ```bash= sudo make -j6 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- INSTALL_MOD_PATH=/export/user/fs modules_install ``` --- ### 設定Uboot開機參數: Uboot編譯請參考[連結](https://hackmd.io/p_eQ-5QdRE-NpweHBE4_Eg?view) 1. 新增u-boot script檔案。 ```bash= touch boot.cmd ``` 內容如下: ```bash= setenv ipaddr 192.168.1.10 setenv serverip 192.168.1.8 setenv bootargs 8250.nr_uarts=1 console=ttyS0,115200 root=/dev/nfs nfsroot=192.168.1.8:/export/user/fs,proto=tcp,nfsvers=3 rw ip=192.168.1.10 rootfstype=nfs elevator=deadline rootwait tftp ${kernel_addr_r} Image booti ${kernel_addr_r} - ${fdt_addr} ``` :::info 如果是非靜態IP,"setenv ipaddr 192.168.1.10" 請改成 "dhcp" 192.168.1.8: 請填入自己遠端Server IP 192.168.1.10: 請填入自己Raspberry pi端IP(靜態IP請自己設定,但要與Server IP在同一個網域底下。如果是DHCP就請填上dhcp就可以了) ::: 2. 編譯(將boot.cmd編譯成boot.scr) ```bash= mkimage -C none -A arm64 -T script -d boot.cmd boot.scr ``` 3. 複製u-boot映像檔到SDCard第一分區(FAT32) ```bash= sudo cp -v boot.scr ${SDCard第一分區} ``` --- 最後 插上Raspberry pi開機,即可在console操作Raspberry pi 這裡透過screen操作console sudo screen /dev/ttyUSB0 115200 * TFTP載入Linux Kernel: ![](https://i.imgur.com/9pL9F7q.png) * Linux Kernel 載入 Rootfs: ![](https://i.imgur.com/PQY3gvI.png)