|
| 1 | +# Nuke built-in rules and variables. |
| 2 | +MAKEFLAGS += -rR |
| 3 | +.SUFFIXES: |
| 4 | + |
| 5 | +# This is the name that our final executable will have. |
| 6 | +# Change as needed. |
| 7 | +override OUTPUT := csmwrap |
| 8 | + |
| 9 | +# Target architecture to build for. Default to x86_64. |
| 10 | +ARCH := x86_64 |
| 11 | + |
| 12 | +# Check if the architecture is supported. |
| 13 | +ifeq ($(filter $(ARCH),aarch64 loongarch64 riscv64 x86_64),) |
| 14 | + $(error Architecture $(ARCH) not supported) |
| 15 | +endif |
| 16 | + |
| 17 | +# Default user QEMU flags. These are appended to the QEMU command calls. |
| 18 | +QEMUFLAGS := -m 2G |
| 19 | + |
| 20 | +# User controllable C compiler command. |
| 21 | +CC := cc |
| 22 | + |
| 23 | +# User controllable objcopy command. |
| 24 | +OBJCOPY := objcopy |
| 25 | + |
| 26 | +# User controllable C flags. |
| 27 | +CFLAGS := -g -O2 -pipe |
| 28 | + |
| 29 | +# User controllable C preprocessor flags. We set none by default. |
| 30 | +CPPFLAGS := |
| 31 | + |
| 32 | +ifeq ($(ARCH),x86_64) |
| 33 | + # User controllable nasm flags. |
| 34 | + NASMFLAGS := -F dwarf -g |
| 35 | +endif |
| 36 | + |
| 37 | +# User controllable linker flags. We set none by default. |
| 38 | +LDFLAGS := |
| 39 | + |
| 40 | +# Ensure the dependencies have been obtained. |
| 41 | +ifeq ($(shell ( ! test -d freestnd-c-hdrs || ! test -d src/cc-runtime || ! test -d nyu-efi ); echo $$?),0) |
| 42 | + $(error Please run the ./get-deps script first) |
| 43 | +endif |
| 44 | + |
| 45 | +# Check if CC is Clang. |
| 46 | +override CC_IS_CLANG := $(shell ! $(CC) --version 2>/dev/null | grep 'clang' >/dev/null 2>&1; echo $$?) |
| 47 | + |
| 48 | +# Save user CFLAGS and CPPFLAGS before we append internal flags. |
| 49 | +override USER_CFLAGS := $(CFLAGS) |
| 50 | +override USER_CPPFLAGS := $(CPPFLAGS) |
| 51 | + |
| 52 | +# Internal C flags that should not be changed by the user. |
| 53 | +override CFLAGS += \ |
| 54 | + -Wall \ |
| 55 | + -Wextra \ |
| 56 | + -std=gnu11 \ |
| 57 | + -nostdinc \ |
| 58 | + -ffreestanding \ |
| 59 | + -fno-stack-protector \ |
| 60 | + -fno-stack-check \ |
| 61 | + -fshort-wchar \ |
| 62 | + -fPIE \ |
| 63 | + -ffunction-sections \ |
| 64 | + -fdata-sections |
| 65 | + |
| 66 | +# Internal C preprocessor flags that should not be changed by the user. |
| 67 | +override CPPFLAGS := \ |
| 68 | + -I src \ |
| 69 | + -I nyu-efi/inc \ |
| 70 | + -isystem freestnd-c-hdrs \ |
| 71 | + $(CPPFLAGS) \ |
| 72 | + -MMD \ |
| 73 | + -MP |
| 74 | + |
| 75 | +ifeq ($(ARCH),x86_64) |
| 76 | + # Internal nasm flags that should not be changed by the user. |
| 77 | + override NASMFLAGS += \ |
| 78 | + -Wall |
| 79 | +endif |
| 80 | + |
| 81 | +# Architecture specific internal flags. |
| 82 | +ifeq ($(ARCH),x86_64) |
| 83 | + ifeq ($(CC_IS_CLANG),1) |
| 84 | + override CC += \ |
| 85 | + -target x86_64-unknown-none |
| 86 | + endif |
| 87 | + override CFLAGS += \ |
| 88 | + -m64 \ |
| 89 | + -march=x86-64 \ |
| 90 | + -mno-80387 \ |
| 91 | + -mno-mmx \ |
| 92 | + -mno-sse \ |
| 93 | + -mno-sse2 \ |
| 94 | + -mno-red-zone |
| 95 | + override LDFLAGS += \ |
| 96 | + -Wl,-m,elf_x86_64 |
| 97 | + override NASMFLAGS += \ |
| 98 | + -f elf64 |
| 99 | +endif |
| 100 | +ifeq ($(ARCH),aarch64) |
| 101 | + ifeq ($(CC_IS_CLANG),1) |
| 102 | + override CC += \ |
| 103 | + -target aarch64-unknown-none |
| 104 | + endif |
| 105 | + override CFLAGS += \ |
| 106 | + -mgeneral-regs-only |
| 107 | + override LDFLAGS += \ |
| 108 | + -Wl,-m,aarch64elf |
| 109 | +endif |
| 110 | +ifeq ($(ARCH),riscv64) |
| 111 | + ifeq ($(CC_IS_CLANG),1) |
| 112 | + override CC += \ |
| 113 | + -target riscv64-unknown-none |
| 114 | + override CFLAGS += \ |
| 115 | + -march=rv64imac |
| 116 | + else |
| 117 | + override CFLAGS += \ |
| 118 | + -march=rv64imac_zicsr_zifencei |
| 119 | + endif |
| 120 | + override CFLAGS += \ |
| 121 | + -mabi=lp64 \ |
| 122 | + -mno-relax |
| 123 | + override LDFLAGS += \ |
| 124 | + -Wl,-m,elf64lriscv \ |
| 125 | + -Wl,--no-relax |
| 126 | +endif |
| 127 | +ifeq ($(ARCH),loongarch64) |
| 128 | + ifeq ($(CC_IS_CLANG),1) |
| 129 | + override CC += \ |
| 130 | + -target loongarch64-unknown-none |
| 131 | + endif |
| 132 | + override CFLAGS += \ |
| 133 | + -march=loongarch64 \ |
| 134 | + -mabi=lp64s |
| 135 | + override LDFLAGS += \ |
| 136 | + -Wl,-m,elf64loongarch \ |
| 137 | + -Wl,--no-relax |
| 138 | +endif |
| 139 | + |
| 140 | +# Internal linker flags that should not be changed by the user. |
| 141 | +override LDFLAGS += \ |
| 142 | + -Wl,--build-id=none \ |
| 143 | + -nostdlib \ |
| 144 | + -pie \ |
| 145 | + -z text \ |
| 146 | + -z max-page-size=0x1000 \ |
| 147 | + -Wl,--gc-sections \ |
| 148 | + -T nyu-efi/src/elf_$(ARCH)_efi.lds |
| 149 | + |
| 150 | +# Use "find" to glob all *.c, *.S, and *.asm files in the tree and obtain the |
| 151 | +# object and header dependency file names. |
| 152 | +override SRCFILES := $(shell cd src && find -L * -type f | LC_ALL=C sort) |
| 153 | +override CFILES := $(filter %.c,$(SRCFILES)) |
| 154 | +override ASFILES := $(filter %.S,$(SRCFILES)) |
| 155 | +ifeq ($(ARCH),x86_64) |
| 156 | +override NASMFILES := $(filter %.asm,$(SRCFILES)) |
| 157 | +endif |
| 158 | +override OBJ := $(addprefix obj-$(ARCH)/,$(CFILES:.c=.c.o) $(ASFILES:.S=.S.o)) |
| 159 | +ifeq ($(ARCH),x86_64) |
| 160 | +override OBJ += $(addprefix obj-$(ARCH)/,$(NASMFILES:.asm=.asm.o)) |
| 161 | +endif |
| 162 | +override HEADER_DEPS := $(addprefix obj-$(ARCH)/,$(CFILES:.c=.c.d) $(ASFILES:.S=.S.d)) |
| 163 | + |
| 164 | +# Default target. This must come first, before header dependencies. |
| 165 | +.PHONY: all |
| 166 | +all: bin-$(ARCH)/$(OUTPUT).efi |
| 167 | + |
| 168 | +# Include header dependencies. |
| 169 | +-include $(HEADER_DEPS) |
| 170 | + |
| 171 | +# Rules to build the nyu-efi objects we need. |
| 172 | +nyu-efi/src/crt0-efi-$(ARCH).S.o: nyu-efi |
| 173 | + |
| 174 | +nyu-efi/src/reloc_$(ARCH).c.o: nyu-efi |
| 175 | + |
| 176 | +.PHONY: nyu-efi |
| 177 | +nyu-efi: |
| 178 | + $(MAKE) -C nyu-efi/src -f nyu-efi.mk \ |
| 179 | + ARCH="$(ARCH)" \ |
| 180 | + CC="$(CC)" \ |
| 181 | + CFLAGS="$(USER_CFLAGS) -nostdinc" \ |
| 182 | + CPPFLAGS="$(USER_CPPFLAGS) -isystem ../../freestnd-c-hdrs" |
| 183 | + |
| 184 | +# Rule to convert the final ELF executable to a .EFI PE executable. |
| 185 | +bin-$(ARCH)/$(OUTPUT).efi: bin-$(ARCH)/$(OUTPUT) GNUmakefile |
| 186 | + mkdir -p "$$(dirname $@)" |
| 187 | + $(OBJCOPY) -O binary $< $@ |
| 188 | + dd if=/dev/zero of=$@ bs=4096 count=0 seek=$$(( ($$(wc -c < $@) + 4095) / 4096 )) 2>/dev/null |
| 189 | + |
| 190 | +# Link rules for the final executable. |
| 191 | +bin-$(ARCH)/$(OUTPUT): GNUmakefile nyu-efi/src/elf_$(ARCH)_efi.lds nyu-efi/src/crt0-efi-$(ARCH).S.o nyu-efi/src/reloc_$(ARCH).c.o $(OBJ) |
| 192 | + mkdir -p "$$(dirname $@)" |
| 193 | + $(CC) $(CFLAGS) $(LDFLAGS) nyu-efi/src/crt0-efi-$(ARCH).S.o nyu-efi/src/reloc_$(ARCH).c.o $(OBJ) -o $@ |
| 194 | + |
| 195 | +# Compilation rules for *.c files. |
| 196 | +obj-$(ARCH)/%.c.o: src/%.c GNUmakefile |
| 197 | + mkdir -p "$$(dirname $@)" |
| 198 | + $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ |
| 199 | + |
| 200 | +# Compilation rules for *.S files. |
| 201 | +obj-$(ARCH)/%.S.o: src/%.S GNUmakefile |
| 202 | + mkdir -p "$$(dirname $@)" |
| 203 | + $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ |
| 204 | + |
| 205 | +ifeq ($(ARCH),x86_64) |
| 206 | +# Compilation rules for *.asm (nasm) files. |
| 207 | +obj-$(ARCH)/%.asm.o: src/%.asm GNUmakefile |
| 208 | + mkdir -p "$$(dirname $@)" |
| 209 | + nasm $(NASMFLAGS) $< -o $@ |
| 210 | +endif |
| 211 | + |
| 212 | +# Rules to download the UEFI firmware per architecture for testing. |
| 213 | +ovmf/ovmf-code-$(ARCH).fd: |
| 214 | + mkdir -p ovmf |
| 215 | + curl -Lo $@ https://github.com/osdev0/edk2-ovmf-nightly/releases/latest/download/ovmf-code-$(ARCH).fd |
| 216 | + case "$(ARCH)" in \ |
| 217 | + aarch64) dd if=/dev/zero of=$@ bs=1 count=0 seek=67108864 2>/dev/null;; \ |
| 218 | + riscv64) dd if=/dev/zero of=$@ bs=1 count=0 seek=33554432 2>/dev/null;; \ |
| 219 | + esac |
| 220 | + |
| 221 | +ovmf/ovmf-vars-$(ARCH).fd: |
| 222 | + mkdir -p ovmf |
| 223 | + curl -Lo $@ https://github.com/osdev0/edk2-ovmf-nightly/releases/latest/download/ovmf-vars-$(ARCH).fd |
| 224 | + case "$(ARCH)" in \ |
| 225 | + aarch64) dd if=/dev/zero of=$@ bs=1 count=0 seek=67108864 2>/dev/null;; \ |
| 226 | + riscv64) dd if=/dev/zero of=$@ bs=1 count=0 seek=33554432 2>/dev/null;; \ |
| 227 | + esac |
| 228 | + |
| 229 | +# Rules for running our executable in QEMU. |
| 230 | +.PHONY: run |
| 231 | +run: all ovmf/ovmf-code-$(ARCH).fd ovmf/ovmf-vars-$(ARCH).fd |
| 232 | + mkdir -p boot/EFI/BOOT |
| 233 | +ifeq ($(ARCH),x86_64) |
| 234 | + cp bin-$(ARCH)/$(OUTPUT).efi boot/EFI/BOOT/BOOTX64.EFI |
| 235 | + qemu-system-$(ARCH) \ |
| 236 | + -M q35 \ |
| 237 | + -drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-$(ARCH).fd,readonly=on \ |
| 238 | + -drive if=pflash,unit=1,format=raw,file=ovmf/ovmf-vars-$(ARCH).fd \ |
| 239 | + -drive file=fat:rw:boot \ |
| 240 | + $(QEMUFLAGS) |
| 241 | +endif |
| 242 | +ifeq ($(ARCH),aarch64) |
| 243 | + cp bin-$(ARCH)/$(OUTPUT).efi boot/EFI/BOOT/BOOTAA64.EFI |
| 244 | + qemu-system-$(ARCH) \ |
| 245 | + -M virt \ |
| 246 | + -cpu cortex-a72 \ |
| 247 | + -device ramfb \ |
| 248 | + -device qemu-xhci \ |
| 249 | + -device usb-kbd \ |
| 250 | + -device usb-mouse \ |
| 251 | + -drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-$(ARCH).fd,readonly=on \ |
| 252 | + -drive if=pflash,unit=1,format=raw,file=ovmf/ovmf-vars-$(ARCH).fd \ |
| 253 | + -drive file=fat:rw:boot \ |
| 254 | + $(QEMUFLAGS) |
| 255 | +endif |
| 256 | +ifeq ($(ARCH),riscv64) |
| 257 | + cp bin-$(ARCH)/$(OUTPUT).efi boot/EFI/BOOT/BOOTRISCV64.EFI |
| 258 | + qemu-system-$(ARCH) \ |
| 259 | + -M virt \ |
| 260 | + -cpu rv64 \ |
| 261 | + -device ramfb \ |
| 262 | + -device qemu-xhci \ |
| 263 | + -device usb-kbd \ |
| 264 | + -device usb-mouse \ |
| 265 | + -drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-$(ARCH).fd,readonly=on \ |
| 266 | + -drive if=pflash,unit=1,format=raw,file=ovmf/ovmf-vars-$(ARCH).fd \ |
| 267 | + -drive file=fat:rw:boot \ |
| 268 | + $(QEMUFLAGS) |
| 269 | +endif |
| 270 | +ifeq ($(ARCH),loongarch64) |
| 271 | + cp bin-$(ARCH)/$(OUTPUT).efi boot/EFI/BOOT/BOOTLOONGARCH64.EFI |
| 272 | + qemu-system-$(ARCH) \ |
| 273 | + -M virt \ |
| 274 | + -cpu la464 \ |
| 275 | + -device ramfb \ |
| 276 | + -device qemu-xhci \ |
| 277 | + -device usb-kbd \ |
| 278 | + -device usb-mouse \ |
| 279 | + -drive if=pflash,unit=0,format=raw,file=ovmf/ovmf-code-$(ARCH).fd,readonly=on \ |
| 280 | + -drive if=pflash,unit=1,format=raw,file=ovmf/ovmf-vars-$(ARCH).fd \ |
| 281 | + -drive file=fat:rw:boot \ |
| 282 | + $(QEMUFLAGS) |
| 283 | +endif |
| 284 | + rm -rf boot |
| 285 | + |
| 286 | +# Remove object files and the final executable. |
| 287 | +.PHONY: clean |
| 288 | +clean: |
| 289 | + $(MAKE) -C nyu-efi/src -f nyu-efi.mk ARCH="$(ARCH)" clean |
| 290 | + rm -rf bin-$(ARCH) obj-$(ARCH) |
| 291 | + |
| 292 | +# Remove everything built and generated including downloaded dependencies. |
| 293 | +.PHONY: distclean |
| 294 | +distclean: |
| 295 | + rm -rf bin-* obj-* freestnd-c-hdrs src/cc-runtime nyu-efi ovmf |
0 commit comments