# Cross compile mtd-utils ###### tags: `blog` 因為工作的 kernel only 環境沒有用整合好的 build system,像是 yocto 之類的。想要使用 mtd-utils 這類 busybox 沒有提供的工具,就只能自己來 build 了。 ## Target board 環境 使用的 cross-compile toolchain 是 gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu。 target board 上跑的是 busybox。 ## References 1. https://wiki.beyondlogic.org/index.php/Cross_Compiling_MTD_Utils_for_ARM 2. https://elinux.org/CompilingMTDUtils e2fsprogs 3. https://www.cnblogs.com/schips/p/porting_e2fsprogs_on_arm_linux_with_usage.html 4. https://tldp.org/LDP/lfs/LFS-BOOK-6.1.1-HTML/chapter06/e2fsprogs.html exec mtd-utils fail 5. https://busybox.busybox.narkive.com/rSkeBEdC/how-to-execute-binary-other-than-busybox linker information 7. https://medium.com/fcamels-notes/linux-%E5%9F%B7%E8%A1%8C%E6%99%82%E5%B0%8B%E6%89%BE-symbol-%E7%9A%84%E6%B5%81%E7%A8%8B%E4%BB%A5%E5%8F%8A-shared-library-%E7%9B%B8%E9%97%9C%E7%9F%A5%E8%AD%98-b0cf1e19cbf3 8. https://stackoverflow.com/questions/11524820/what-is-the-difference-between-ldd-and-objdump find linked libraries 9. https://gist.github.com/jerome-pouiller/c403786c1394f53f44a3b61214489e6f ## Source Links zlib-1.2.11 http://www.zlib.net/zlib-1.2.11.tar.gz lzo-2.10 http://www.oberhumer.com/opensource/lzo/download/lzo-2.10.tar.gz e2fsprogs 1.45.6 https://kernel.googlesource.com/pub/scm/fs/ext2/e2fsprogs.git mtd-utils v2.1.2 https://github.com/sigma-star/mtd-utils ## Prepare working folder 準備給 `make install` 安裝的 folder (`MTD_OUTPUT_PATH`)。 ~~~ mkdir -p ~/mtd-build/install cd ~/mtd-build export MTD_SRC_PATH=$PWD export MTD_OUTPUT_PATH=$PWD/install echo $MTD_SRC_PATH; echo $MTD_OUTPUT_PATH ~~~ 另外也記得把 toolchain 加入到 PATH 裡。 ~~~ echo PATH=<path to toolchain>/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin:$PATH ~~~ ## Build zlib 參考 1. 裡面的步驟。 > Download, cross compile and install the zlib compression libraries. Configure doesn't accept the --host parameter (reports unknown option), so you need to hack the makefile. ~~~ wget http://www.zlib.net/zlib-1.2.11.tar.gz tar -xzf zlib-1.2.11.tar.gz cd zlib-1.2.11/ ./configure --prefix=$MTD_OUTPUT_PATH --host=aarch64-linux-gnu ~~~ > Edit the makefile and prefix the build tools with arm-none-linux-gnueabi-. 修改 Makefile,在底下這些參數前面加入 `aarch64-linux-gnu-`,下面是參數修改後的樣子。 ``` CC=aarch64-linux-gnu-gcc LDSHARED=arm-linux-gnueabi-gcc -shared -Wl,-soname,libz.so.1,--version-script,zlib.map CPP=aarch64-linux-gnu-gcc -E AR=aarch64-linux-gnu-ar RANLIB=aarch64-linux-gnu-ranlib ``` 改完 Makefile 後就可以 build 了。`make install` 如上面講的,會安裝到 `MTD_OUTPUT_PATH` 裡。 ``` make make install ``` ## Build LZO 同樣是參考 1. 裡面的步驟。 ``` cd $MTD_SRC_PATH wget http://www.oberhumer.com/opensource/lzo/download/lzo-2.10.tar.gz tar -xzf lzo-2.10.tar.gz cd lzo-2.10/ ./configure --host=aarch64-linux-gnu --prefix=$MTD_OUTPUT_PATH make make install ``` ## Build e2fsprogs 參考 1,2 裡面的步驟。這邊使用的是 clone git。 在做 configure 時,若只依照 1,2 的指令,在有鎖使用權限的 server 上 `make install` 會碰到如下的錯誤。 所以我需要也參考 3,4 去指定其他的安裝路徑。 ~~~ make[1]: Entering directory `<WORKING_PATH>/mtd-build/e2fsprogs/scrub' MKDIR_P /lib/udev/rules.d MKDIR_P /etc/cron.d MKDIR_P <WORKING_PATH>/mtd-build/install/lib/e2fsprogs MKDIR_P <WORKING_PATH>/mtd-build/install/sbin <WORKING_PATH>/mtd-build/install/share/man/man8 <WORKING_PATH>/mtd-build/install/etc INSTALL /lib/udev/rules.d/e2scrub.rules /usr/bin/install: cannot create regular file ‘/lib/udev/rules.d/96-e2scrub.rules’: Permission denied ~~~ 另外也有在 4 看到這個是必要的。 >--enable-elf-shlibs This creates the shared libraries which some programs in this package use. 如果有碰到這個 error 的話就先 `make clean` 後在試一次,可能是因為用別的 toolchain build 過。 ~~~ ../lib/libsupport.a: error adding symbols: File in wrong format collect2: error: ld returned 1 exit status make[2]: *** [e2fsck] Error 1 ~~~ 完整步驟如下。 :::warning 每次 configure 參數有改變時,先做 make clean 後在 make。 ::: ``` cd $MTD_SRC_PATH git clone https://kernel.googlesource.com/pub/scm/fs/ext2/e2fsprogs.git cd e2fsprogs git checkout v1.45.6 ./configure --host=aarch64-linux-gnu \ --prefix=$MTD_OUTPUT_PATH \ --with-udev-rules-dir=$MTD_OUTPUT_PATH \ --with-crond-dir=$MTD_OUTPUT_PATH \ --with-systemd-unit-dir=$MTD_OUTPUT_PATH \ --enable-elf-shlibs make make install cd lib/uuid/ make install ``` ## Build mtd-utils 在 v2.1.2 的 mtd-utils 有支援 configure 了。就不用像 1,2 的做法要去修改 Makefile。 build 的方式可以參考一下 make_a_relaease.sh 的作法。 `autogen.sh` 就直接 call 就可以了,沒有要傳參數。 因為需要用到上面 build 好的 library,所以需要在 configure 時把 MTD_OUTPUT_PATH 給傳進去。 `./configure --help` 可以看到我們有哪些參數可以用。 ``` cd $MTD_SRC_PATH git clone https://github.com/sigma-star/mtd-utils.git cd mtd-utils git checkout v2.1.2 export PREFIX=$MTD_OUTPUT_PATH export LDFLAGS=-L$PREFIX/lib export CPPFLAGS=-I$PREFIX/include ./autogen.sh ./configure --host=aarch64-linux-gnu \ --prefix=$MTD_OUTPUT_PATH \ --with-sysroot=$MTD_OUTPUT_PATH \ --without-xattr \ --without-zstd \ --without-crypto \ LDFLAGS=-L$MTD_OUTPUT_PATH/lib \ CPPFLAGS=-I$MTD_OUTPUT_PATH/include make make install ``` 這一步完 mtd-utils 就 build 成功了! 接下來就是要放到 target board 上面跑囉。 ## Copy mtd-utils to rootfs copy $MTD_OUTPUT_PATH/sbin 到 target board rootfs 的 /sbin。 $MTD_OUTPUT_PATH/lib 就 copy 到 /lib。 ## Copy necessary libraries 若跟我一樣 rootfs 是從零開始建,只有把 busybox 放進來的話,應該是甚麼 lib 都沒有的。 我推薦可以看一下 6,7 知道一下 link 相關的東西。 使用 8 的 script 來幫助我們檢查 cross-compile 出來的 binary 需要哪些 lib。 把 8 的 script 存成一個檔案後放到 toolchain 中的 bin,命名成 <toolchain>-ldd,來方便使用。 以我的環境來說,輸出如下。 ``` $ aarch64-linux-gnu-ldd sbin/flash_erase libc.so.6 => /lib/libc.so.6 (0xdeadbeef) ld-linux-aarch64.so.1 => /lib/ld-linux-aarch64.so.1 (0xdeadbeef) ```