Build a Linux kernel from scratch and create a bootable USB with EFI.
This is a simple script to build a Linux kernel from scratch and create a bootable USB with EFI.
Most of things are followed by the Monkey See, Monkey Do LINUX series and msmd-linux. I have just modified all the parts in the tutorials that were directly downloaded from its own GitHub repository without mentioning how to create them.
The platform to build the Linux kernel is 64-bit Ubuntu 22.04. All necessary tools are supposed to be included in. No extra installation is required.
By default, the script build.sh works fine. Some customized configurations should be made if necessary.
Some global variables controlled the version are defined in the top of the build.sh:
KERNEL_FILENAME="linux-6.12.9.tar.xz"
GLIBC_FILENAME="glibc-2.40.tar.xz"
BUSYBOX_FILENAME="busybox-1.37.0.tar.bz2"One may want to change the version to fit his/her needs.
By default, the source code are downloaded from the official websites. One may want to change it to a mirror for faster download.
# Build and install glibc
build_glibc() {
rm -rf "$GLIBC_DIR"
mkdir "$GLIBC_DIR"
cd "$GLIBC_DIR"
# wget "https://ftp.gnu.org/gnu/glibc/$GLIBC_FILENAME"
wget "https://mirror.ossplanet.net/gnu/glibc/$GLIBC_FILENAME" # mirror is used
#...
}For example, the default url for glibc is https://ftp.gnu.org/gnu/glibc. It is changed to the mirror https://mirror.ossplanet.net/gnu/glibc.
By default, the target platform is 64-bit. Because almost all the things are compiled and built from scratch, the target platform is also needed to be specified. If one wants to build for 32-bit machine, the Linux kernel, glibc, and busybox should all be compiled and built for 32-bit.
Note:
/includeand/libin sysroot are directly synced from/usr/includeand/usr/lib. If one wants to compile and build 32-bit busybox with sysroot, one should check the/usr/includeand/usr/libare 32-bit or 64-bit.- There is a symbol link
/lib64to/libwhen creating the rootfs. It is also needed to be changed to/lib32. - Also, when installing GRUB to the USB, the target platform should be specified to 32-bit.
In utils/create_bootable_usb.sh, the device to create the bootable USB is specified by the variable DEVICE. By default, it is /dev/sdb. One may want to change it to another device.
Note that INSTALL_DEVICE in build.sh should be the same as DEVICE in utils/create_bootable_usb.sh. They both means the device path on the host, while DEVICE in build.sh means the device path on the target machine(not the host).
To trigger the hardware devices on the target machine, some necessary modules are needed when compiling the Linux kernel. Remember to update the config/module_list for the target machine. If one doesn't know which modules are needed, one can use make allmodconfig or make allyesconfig to enable almost all available modules but the Linux kernel will be very large and the build process will take a long time. Instead, one can use make localmodconfig or make localyesconfig to enable only the loaded modules(lsmod) on the host.
If someone connect the target machine via the terminal emulator(e.g. Minicom, Tera Term, or Putty), the output console should be specified with the corresponding serial port and the baud rate to display the messages correctly.
menuentry "kylinux" --class os {
insmod gzio
insmod part_msdos
linux /boot/bzImage console=ttyS1,115200n8
initrd /boot/rootfs.cpio.gz
}
The iso file is also created and tested with QEMU. The QEMU should be modified to 32-bit if 32-bit version is used.
After watching the series of the tutorials Monkey See, Monkey Do LINUX and successfully running the build.sh script to create your own bootable USB, there are still some additional things that can be added to the script to become more familiar with the process:
- Install static vim binary file
- Install Python3 binary file(Note build Python statically is difficult...)
- install the wifi firmware for the target machine and test whether it is working