|
| 1 | +# Sources |
| 2 | +MUSL_SOURCE := git://git.musl-libc.org/musl |
| 3 | +BUSYBOX_SOURCE := git://busybox.net/busybox.git |
| 4 | +LINUX_SOURCE := git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git |
| 5 | + |
| 6 | +# Configuration |
| 7 | +BUSYBOX_CONFIG := busybox.config |
| 8 | +ROOTFS_OVERLAYDIR := rootfs-overlay |
| 9 | +LINUX_CONFIG := linux.config |
| 10 | +BOOTFS_LABEL := BOOT |
| 11 | +BOOTFS_SIZE := 1440 |
| 12 | +BOOTFS_CREATE_GPT := 0 |
| 13 | +QEMU_CMD := qemu-system-x86_64 -bios /usr/share/ovmf/x64/OVMF.fd -smp 2 |
| 14 | + |
| 15 | +# Temporary directories |
| 16 | +ROOTFS_DIR := rootfs |
| 17 | +BOOTFS_MOUNTDIR := floppy |
| 18 | + |
| 19 | +# Recipe targets |
| 20 | +MUSL_DIR := musl |
| 21 | +MUSL_BUILD_DIR := musl-build |
| 22 | +MUSL_GCC := $(MUSL_BUILD_DIR)/bin/musl-gcc |
| 23 | +BUSYBOX_DIR := busybox |
| 24 | +BUSYBOX := $(BUSYBOX_DIR)/busybox |
| 25 | +ROOTFS_CPIO := rootfs.cpio |
| 26 | +LINUX_DIR := linux |
| 27 | +LINUX_HEADERS_DIR := linux-headers |
| 28 | +LINUX_BZIMAGE := $(LINUX_DIR)/arch/x86/boot/bzImage |
| 29 | +BOOTFS_IMAGE := floppy.img |
| 30 | + |
| 31 | +.PHONY: all source update configure build clean reset |
| 32 | +all: configure $(BOOTFS_IMAGE) |
| 33 | +source: $(MUSL_DIR) $(BUSYBOX_DIR) $(LINUX_DIR) |
| 34 | +update: musl-update busybox-update linux-update |
| 35 | +configure: musl-configure busybox-configure linux-configure |
| 36 | +clean: musl-clean busybox-clean rootfs-clean linux-clean |
| 37 | +reset: |
| 38 | + rm -rf "$(MUSL_DIR)" "$(MUSL_BUILD_DIR)" "$(BUSYBOX_DIR)" "$(LINUX_DIR)" \ |
| 39 | + "$(LINUX_HEADERS_DIR)" "$(ROOTFS_DIR)" "$(ROOTFS_CPIO)" \ |
| 40 | + "$(BOOTFS_MOUNTDIR)" "$(BOOTFS_IMAGE)" |
| 41 | + |
| 42 | +$(MUSL_DIR): |
| 43 | + git clone --depth=1 "$(MUSL_SOURCE)" "$(MUSL_DIR)" |
| 44 | + |
| 45 | +$(MUSL_BUILD_DIR): |
| 46 | + mkdir -p "$(MUSL_BUILD_DIR)"/{bin,include,lib} |
| 47 | + |
| 48 | +# These symlinks ensure that programs and headers required for building BusyBox |
| 49 | +# under musl are present (besides musl-gcc). |
| 50 | +# Refer: https://www.openwall.com/lists/musl/2014/08/08/13 |
| 51 | + ln -s "$$(which as)" "$(MUSL_BUILD_DIR)"/bin/musl-as |
| 52 | + ln -s "$$(which ar)" "$(MUSL_BUILD_DIR)"/bin/musl-ar |
| 53 | + ln -s "$$(which nm)" "$(MUSL_BUILD_DIR)"/bin/musl-nm |
| 54 | + ln -s "$$(which strip)" "$(MUSL_BUILD_DIR)"/bin/musl-strip |
| 55 | + ln -s "$$(which objcopy)" "$(MUSL_BUILD_DIR)"/bin/musl-objcopy |
| 56 | + ln -s "$$(which objdump)" "$(MUSL_BUILD_DIR)"/bin/musl-objdum |
| 57 | + ln -s "$$(which pkg-config)" "$(MUSL_BUILD_DIR)"/bin/musl-pkg-config |
| 58 | + ln -s ../../linux-headers/include/linux "$(MUSL_BUILD_DIR)"/include/linux |
| 59 | + ln -s ../../linux-headers/include/mtd "$(MUSL_BUILD_DIR)"/include/mtd |
| 60 | + ln -s ../../linux-headers/include/asm "$(MUSL_BUILD_DIR)"/include/asm |
| 61 | + ln -s ../../linux-headers/include/asm-generic "$(MUSL_BUILD_DIR)"/include/asm-generic |
| 62 | + |
| 63 | +$(MUSL_GCC): $(MUSL_DIR) $(MUSL_BUILD_DIR) $(LINUX_HEADERS_DIR) | musl-configure |
| 64 | + $(MAKE) -C "$(MUSL_DIR)" -j "$$(nproc)" all |
| 65 | + $(MAKE) -C "$(MUSL_DIR)" install |
| 66 | + |
| 67 | +.PHONY: musl-update musl-configure musl-clean |
| 68 | + |
| 69 | +musl-update: $(MUSL_DIR) |
| 70 | + git -C "$(MUSL_DIR)" pull |
| 71 | + |
| 72 | +musl-configure: $(MUSL_DIR) |
| 73 | + cd "$(MUSL_DIR)" && ./configure --prefix=../"$(MUSL_BUILD_DIR)" |
| 74 | + |
| 75 | +musl-clean: |
| 76 | + [ -d "$(MUSL_DIR)" ] && $(MAKE) -C "$(MUSL_DIR)" distclean |
| 77 | + rm -rf "$(MUSL_BUILD_DIR)" |
| 78 | + |
| 79 | +$(BUSYBOX_DIR): |
| 80 | + git clone --depth=1 "$(BUSYBOX_SOURCE)" "$(BUSYBOX_DIR)" |
| 81 | + |
| 82 | +$(BUSYBOX): $(BUSYBOX_DIR) $(MUSL_BUILD_DIR) | busybox-configure |
| 83 | + $(MAKE) -C "$(BUSYBOX_DIR)" -j "$$(nproc)" CC=../$(MUSL_GCC) all |
| 84 | + |
| 85 | +.PHONY: busybox-update busybox-configure busybox-clean |
| 86 | + |
| 87 | +busybox-update: $(BUSYBOX_DIR) |
| 88 | + git -C "$(BUSYBOX_DIR)" pull |
| 89 | + |
| 90 | +busybox-configure: $(BUSYBOX_DIR) $(MUSL_GCC) |
| 91 | + cp "$(BUSYBOX_CONFIG)" "$(BUSYBOX_DIR)"/.config |
| 92 | + $(MAKE) -C "$(BUSYBOX_DIR)" CC=../$(MUSL_GCC) oldconfig |
| 93 | + |
| 94 | +busybox-clean: |
| 95 | + [ -d "$(BUSYBOX_DIR)" ] && $(MAKE) -C "$(BUSYBOX_DIR)" distclean |
| 96 | + |
| 97 | +# https://www.kernel.org/doc/Documentation/admin-guide/devices.txt |
| 98 | +define _ROOTFS_BUILD_CMDS := |
| 99 | +set -e |
| 100 | +mkdir -p "$(ROOTFS_DIR)"/{root,bin,sbin,dev,proc,etc,sys,tmp} |
| 101 | +$(MAKE) -C "$(BUSYBOX_DIR)" CC=../$(MUSL_GCC) CONFIG_PREFIX=../"$(ROOTFS_DIR)" install |
| 102 | +mknod "$(ROOTFS_DIR)"/dev/null c 1 3 |
| 103 | +mknod "$(ROOTFS_DIR)"/dev/zero c 1 5 |
| 104 | +mknod "$(ROOTFS_DIR)"/dev/random c 1 8 |
| 105 | +mknod "$(ROOTFS_DIR)"/dev/urandom c 1 9 |
| 106 | +mknod "$(ROOTFS_DIR)"/dev/tty0 c 4 0 |
| 107 | +mknod "$(ROOTFS_DIR)"/dev/tty1 c 4 1 |
| 108 | +mknod "$(ROOTFS_DIR)"/dev/tty2 c 4 2 |
| 109 | +mknod "$(ROOTFS_DIR)"/dev/tty3 c 4 3 |
| 110 | +mknod "$(ROOTFS_DIR)"/dev/tty c 5 0 |
| 111 | +ln -s /proc/self/fd/0 "$(ROOTFS_DIR)"/dev/stdin |
| 112 | +ln -s /proc/self/fd/1 "$(ROOTFS_DIR)"/dev/stdout |
| 113 | +ln -s /proc/self/fd/2 "$(ROOTFS_DIR)"/dev/stderr |
| 114 | +cp -rfv "$(ROOTFS_OVERLAYDIR)"/* "$(ROOTFS_DIR)" |
| 115 | +cd "$(ROOTFS_DIR)" && find . | cpio -H newc -o > ../"$(ROOTFS_CPIO)" |
| 116 | +rm -rf "$(ROOTFS_DIR)" |
| 117 | +endef |
| 118 | +export ROOTFS_BUILD_CMDS := $(value _ROOTFS_BUILD_CMDS) |
| 119 | +$(ROOTFS_CPIO): $(BUSYBOX) |
| 120 | +# We don't need actual root privileges for this operation. |
| 121 | + echo "$${ROOTFS_BUILD_CMDS}" | fakeroot |
| 122 | + |
| 123 | +.PHONY: rootfs-clean |
| 124 | +rootfs-clean: |
| 125 | + rm -rf "$(ROOTFS_DIR)" "$(ROOTFS_CPIO)" |
| 126 | + |
| 127 | +$(LINUX_DIR): |
| 128 | + git clone --depth=1 "$(LINUX_SOURCE)" "$(LINUX_DIR)" |
| 129 | + |
| 130 | +$(LINUX_HEADERS_DIR): $(LINUX_DIR) |
| 131 | + $(MAKE) -C "$(LINUX_DIR)" \ |
| 132 | + headers_install INSTALL_HDR_PATH=../"$(LINUX_HEADERS_DIR)" |
| 133 | + |
| 134 | +$(LINUX_BZIMAGE): $(LINUX_DIR) $(ROOTFS_CPIO) | linux-configure |
| 135 | + $(MAKE) -C "$(LINUX_DIR)" -j "$$(nproc)" bzImage |
| 136 | + |
| 137 | +.PHONY: linux-update linux-configure linux-clean |
| 138 | + |
| 139 | +linux-update: $(LINUX_DIR) |
| 140 | + git -C "$(LINUX_DIR)" pull |
| 141 | + |
| 142 | +linux-configure: $(LINUX_DIR) |
| 143 | + cp "$(LINUX_CONFIG)" "$(LINUX_DIR)"/.config |
| 144 | + $(MAKE) -C "$(LINUX_DIR)" oldconfig |
| 145 | + |
| 146 | +linux-clean: |
| 147 | + [ -d "$(LINUX_DIR)" ] && $(MAKE) -C "$(LINUX_DIR)" distclean |
| 148 | + rm -rf "$(LINUX_HEADERS_DIR)" |
| 149 | + |
| 150 | +define _BOOTFS_BUILD_CMDS := |
| 151 | +set -e |
| 152 | +losetup -j "$(BOOTFS_IMAGE)" | cut -d ':' -f 1 | xargs -r losetup -d |
| 153 | +if [ "$(BOOTFS_CREATE_GPT)" = 1 ]; then |
| 154 | + sgdisk -a 2 -N -t 1:EF00 |
| 155 | + loopdev="$$(losetup -P -f "$(BOOTFS_IMAGE)" --show)"p1 |
| 156 | +else |
| 157 | + loopdev="$$(losetup -f "$(BOOTFS_IMAGE)" --show)" |
| 158 | +fi |
| 159 | +mkfs.fat -F 12 -n "$(BOOTFS_LABEL)" "$${loopdev}" |
| 160 | +mountpoint -q "$(BOOTFS_MOUNTDIR)" && umount "$(BOOTFS_MOUNTDIR)" |
| 161 | +mount -m "$${loopdev}" "$(BOOTFS_MOUNTDIR)" |
| 162 | +mkdir -p "$(BOOTFS_MOUNTDIR)"/EFI/BOOT |
| 163 | +cp "$(LINUX_BZIMAGE)" "$(BOOTFS_MOUNTDIR)"/EFI/BOOT/BOOTX64.EFI |
| 164 | +umount "$(BOOTFS_MOUNTDIR)" |
| 165 | +rmdir "$(BOOTFS_MOUNTDIR)" |
| 166 | +losetup -d "$${loopdev%p1}" |
| 167 | +endef |
| 168 | +export BOOTFS_BUILD_CMDS := $(value _BOOTFS_BUILD_CMDS) |
| 169 | +$(BOOTFS_IMAGE): $(LINUX_BZIMAGE) |
| 170 | + dd if=/dev/zero of="$(BOOTFS_IMAGE)" \ |
| 171 | + bs=1024 count="$(BOOTFS_SIZE)" conv=fsync |
| 172 | + |
| 173 | +# losetup, mount and mkfs.fat likely require actual root privileges. |
| 174 | + echo "$${BOOTFS_BUILD_CMDS}" | sudo -s |
| 175 | + |
| 176 | +.PHONY: runqemu-bzImage runqemu-floppy.img |
| 177 | + |
| 178 | +runqemu-bzImage: |
| 179 | + $(QEMU_CMD) -kernel "$(LINUX_BZIMAGE)" |
| 180 | + |
| 181 | +runqemu-$(BOOTFS_IMAGE): |
| 182 | +# QEMU's UEFI implementation doesn't seem to support booting from an internal |
| 183 | +# FDD, so we simulate an external USB-connected drive instead. |
| 184 | + $(QEMU_CMD) \ |
| 185 | + -drive id=usbstick,if=none,file="$(BOOTFS_IMAGE)",format=raw \ |
| 186 | + -usb \ |
| 187 | + -device usb-ehci,id=ehci \ |
| 188 | + -device usb-storage,bus=ehci.0,drive=usbstick,bootindex=1 |
0 commit comments