# # Kurzanleitung # ============= # # +++ General Targets +++ # # make -- siehe -> make all # # make all -- Baut kernel.elf und generiert einen dump # # make install -- Baut kernel.img und transferiert ihn auf den Server. # Das Board holt sich diesen Kernel beim nächsten Reset. # # make qemu -- Baut den Kernel und führt ihn unter QEMU aus # # make qemu_debug -- Baut den Kernel und führt ihn unter QEMU mit debug # Optionen aus. Zum debuggen in einem zweiten Terminal # folgendes ausführen: # $ arm-none-eabi-gdb build/kernel.elf # $ target remote localhost:1234 # make qemu_trace -- Wie qemu, gibt aber zusätzlich bei bestimmten MMIO-Zugriffen # Meldungen aus # make qemu_trace_mmu -- Wie qemu_trace, gibt aber nur Meldungen zur MMU aus # # make gdb -- Startet gdb und verbindet sich mit qemu # # make gdb_window -- Führt `make gdb` in einem neuen terminal aus # # make debug -- Führt qemu_debug gdb_window aus # # make clean -- Löscht alle erzeugten Dateien. # # make format -- Formatiert alle .c und .h Dateien im Stil von kernel.org # # make submission -- Verpackt alle Dateien die von git getrackt sind # Hierbei wird immer der Branch genutzt, der unter # SUBMISSION_BRANCH eingetragen ist. # # make home -- kopiert das fertige image nach $TFTP_PATH, für die # Arbeit zuhause einfach den Pfad eintragen # # +++ Single File Targets +++ # # make kernel -- Baut kernel.elf im build Ordner # # make kernel.bin -- Baut kernel.bin im build Ordner # # make kernel.img -- Baut kernel.img im build Ordner # # make kernel_only -- Baut den kernel aber nur mit den Dateien aus SRC # Zum testen, ob der Kernel unabhängig kompiliert # # make user_only -- Baut nur die User Dateien aus USRC # Zum testen, ob Userland unabhängig kompiliert # # +++ Sonstiges +++ # # MODE=strict make TARGET -- Baut TARGET mit allen Warnings, die GCC # -- unterstütz, sowie undefined behaviour sanitzers. # -- Baut nicht alles neu, d.h. im Zweifel zuerst # -- make clean ausführen. # # make qemu_record -- Erstellt eine "Aufnahme" einer Ausführung des OS. # Diese kann mit qemu_replay, qemu_debug_replay, # und debug_replay zum debugging abgespielt werden. # Dabei ist es dann in GDB möglich mit reverse-stepi # und reverse-continue "rückwärts" zu debuggen. # Binäre Lsg (falls verwendet, ansonsten leer lassen) BIN_LSG = # Hier eure source files hinzufügen SRC = arch/cpu/entry.S kernel/start.c arch/bsp/yellow_led.c lib/ubsan.c lib/mem.c # Hier separate user source files hinzufügen USRC = user/main.c # Hier können eigene GCC flags mit angegeben werden. # Die vorgegebenen Flags können weiter unten gefunden werden unter # CFLAGS_ALL und dürfen nicht verändert werden # Bsp: CFLAGS = -Wpedantic -Werror -O2 CFLAGS = -std=gnu23 # 'strict' Modus ifeq ($(MODE), strict) CFLAGS_AVAIL = $(shell $(CC) -Q --help=warning | sed -e 's/^\s*\(\-\S*\)\s*\[\w*\]/\1 /gp;d' | tr -d '\n') $(CFLAGS_LAX) IGNORED_CFLAGS = -Wabi -Wc90-c99-compat -Wc99-c11-compat -Wc++-compat -Wtraditional \ -Wtraditional-conversion -Wold-style-declaration -Wold-style-definition \ -Wlong-long -Wdeclaration-after-statement -Wmain -Wswitch-default -Wstrict-flex-arrays \ -Wsystem-headers CFLAGS_STRICT = $(filter-out $(IGNORED_CFLAGS), $(CFLAGS_AVAIL)) CFLAGS += $(CFLAGS_STRICT) -Werror CFLAGS += -fsanitize=undefined endif # Gleiches gilt für Linkerflags, solltet ihr bspw. die libgcc mitlinken müssen LDFLAGS = # Hier den git branch angeben, der für die Abgabe benutzt werden soll SUBMISSION_BRANCH = main # Wenn ihr zuhause auf der Hardware arbeitet, hier das TFTP-Verzeichnis eintragen TFTP_PATH = /srv/tftp # Standardinstallationspunkt der Toolchain -include config.mk # Default if not defined in config.mk PREFIX ?= $(HOME)/Nextcloud/UNI/25-26_TI/BSP/arm all: echo $(PREFIX) # +-----------------------------------------------------+ # | | # | Ab hier nichts mehr anpassen! Änderungen unter- | # | halb dieses Banners führen zu Punktabzug! | # | | # +-----------------------------------------------------+ # Source files, die fürs Testen einkompiliert werden. TSRC = SRC += $(TSRC) # build directory BUILD_DIR = build # separate kernel files and add build prefix KSRC_C = $(filter %.c, $(SRC)) KSRC_S = $(filter %.S, $(SRC)) KOBJ_C = $(addprefix $(BUILD_DIR)/,$(KSRC_C:%.c=%.o)) KOBJ_S = $(addprefix $(BUILD_DIR)/,$(KSRC_S:%.S=%.o)) KOBJ = $(KOBJ_C) $(KOBJ_S) # separate user files and add build prefix USRC_C = $(filter %.c, $(USRC)) USRC_S = $(filter %.S, $(USRC)) UOBJ_C = $(addprefix $(BUILD_DIR)/,$(USRC_C:%.c=%.o)) UOBJ_S = $(addprefix $(BUILD_DIR)/,$(USRC_S:%.S=%.o)) UOBJ = $(UOBJ_C) $(UOBJ_S) # accumulate OBJ_C = $(KOBJ_C) $(UOBJ_C) OBJ_S = $(KOBJ_S) $(UOBJ_S) OBJ = $(KOBJ) $(UOBJ) # all header files HEADER_FILES = $$(find . -name '*.h') # auto generated dep files DEP = $(OBJ:.o=.d) # linker script LSCRIPT = kernel.lds # static lib location for binary solution BIN_LSG_DIR = ./ # toolchain CC = $(PREFIX)/bin/arm-none-eabi-gcc LD = $(PREFIX)/bin/arm-none-eabi-ld OBJCOPY = $(PREFIX)/bin/arm-none-eabi-objcopy OBJDUMP = $(PREFIX)/bin/arm-none-eabi-objdump IMG = $(PREFIX)/bin/mkimage QEMU = $(PREFIX)/bin/qemu-system-arm QEMU_IMG = $(PREFIX)/bin/qemu-img GDB = $(PREFIX)/bin/arm-none-eabi-gdb FORMAT = $(PREFIX)/bin/clang-format # configuration CFLAGS_ALL = -Wall -Wextra -ggdb -ffreestanding -mcpu=cortex-a7 -mfloat-abi=soft -mno-unaligned-access $(CFLAGS) CPPFLAGS = -Iinclude LDFLAGS += -T$(LSCRIPT) -nostdlib --fatal-warnings ifneq ($(BIN_LSG), ) LDFLAGS += -L$(BIN_LSG_DIR) $(addprefix -l,$(BIN_LSG)) endif OBJCOPYFLAGS = -Obinary -S --set-section-flags .bss=contents,alloc,load,data OBJDUMPFLAGS = -dfzh IMGFLAGS = -A arm -T standalone -C none -a 0x8000 QEMUFLAGS = -M raspi2b -nographic -icount shift=9 QEMU_REPLAY_FLAGS = -icount rrfile=$(BUILD_DIR)/replay.bin FORMATFLAGS = --style="file:.clang-format" -i # Regeln .PHONY: all # default target all: kernel dump # include auto generated targets -include $(DEP) # single file targets $(OBJ_S):$(BUILD_DIR)/%.o: %.S @mkdir -p $(dir $@) $(CC) $(CPPFLAGS) $(CFLAGS_ALL) -MMD -MP -o $@ -c $< $(OBJ_C):$(BUILD_DIR)/%.o: %.c @mkdir -p $(dir $@) $(CC) $(CPPFLAGS) $(CFLAGS_ALL) -MMD -MP -o $@ -c $< $(BUILD_DIR)/kernel.elf: $(OBJ) $(LSCRIPT) ifneq ($(words $(OBJ)), $(words $(SRC) $(USRC))) @echo The number of objects files given to the linker does not match the\ number of kernel and user files specified. Check your file extensions.; exit 1 else $(LD) -o $@ $(wordlist 2,$(words $^),x $^) $(LDFLAGS) endif $(BUILD_DIR)/kernel.bin: $(BUILD_DIR)/kernel.elf $(OBJCOPY) $(OBJCOPYFLAGS) $< $@ $(BUILD_DIR)/kernel.img: $(BUILD_DIR)/kernel.bin $(IMG) $(IMGFLAGS) -d $< $@ $(BUILD_DIR)/kernel_only.elf: $(KOBJ) $(LSCRIPT) $(LD) -o $@ $(wordlist 2,$(words $^),x $^) $(LDFLAGS) $(BUILD_DIR)/user_only.elf: $(UOBJ) $(LSCRIPT) $(LD) -o $@ $(wordlist 2,$(words $^),x $^) $(LDFLAGS) --entry=0 $(BUILD_DIR)/kernel_dump.s: $(BUILD_DIR)/kernel.elf $(OBJDUMP) $(OBJDUMPFLAGS) $< > $@ # aliases .PHONY: dump kernel kernel.bin kernel.img kernel_only user_only dump: $(BUILD_DIR)/kernel_dump.s kernel: $(BUILD_DIR)/kernel.elf kernel.bin: $(BUILD_DIR)/kernel.bin kernel.img: $(BUILD_DIR)/kernel.img kernel_only: $(BUILD_DIR)/kernel_only.elf user_only: $(BUILD_DIR)/user_only.elf # general targets .PHONY: install home qemu qemu_debug clean submission install: $(BUILD_DIR)/kernel.img arm-install-image $(BUILD_DIR)/kernel.img home: $(BUILD_DIR)/kernel.img cp -v $(BUILD_DIR)/kernel.img $(TFTP_PATH) $(BUILD_DIR)/vmstate.qcow2: $(BUILD_DIR)/kernel.elf mkdir -p $(BUILD_DIR) $(QEMU_IMG) create -f qcow2 $@ 32M qemu: $(BUILD_DIR)/kernel.elf $(QEMU) $(QEMUFLAGS) -kernel $(BUILD_DIR)/kernel.elf qemu_record: $(BUILD_DIR)/kernel.elf $(QEMU) $(QEMUFLAGS) $(QEMU_REPLAY_FLAGS) -icount rr=record -kernel $(BUILD_DIR)/kernel.elf qemu_replay: $(BUILD_DIR)/kernel.elf $(BUILD_DIR)/replay.bin $(QEMU) $(QEMUFLAGS) $(QEMU_REPLAY_FLAGS) -icount rr=replay -kernel $(BUILD_DIR)/kernel.elf qemu_debug: $(BUILD_DIR)/kernel.elf $(QEMU) $(QEMUFLAGS) -s -S -kernel $(BUILD_DIR)/kernel.elf qemu_debug_replay: $(BUILD_DIR)/kernel.elf $(BUILD_DIR)/vmstate.qcow2 $(BUILD_DIR)/replay.bin $(QEMU) $(QEMUFLAGS) $(QEMU_REPLAY_FLAGS) -drive file=$(BUILD_DIR)/vmstate.qcow2,if=none,snapshot=on,id=img-direct -icount rr=replay -s -S -kernel $(BUILD_DIR)/kernel.elf qemu_trace: $(BUILD_DIR)/kernel.elf $(QEMU) $(QEMUFLAGS) -d "trace:bcm283*,trace:pl011*" -kernel $< qemu_trace_mmu: $(BUILD_DIR)/kernel.elf $(QEMU) $(QEMUFLAGS) -d "mmu" -kernel $< gdb: $(BUILD_DIR)/kernel.elf $(GDB) --ex="target remote localhost:1234" --ex "set scheduler-locking on" $< gdb_window: $(BUILD_DIR)/kernel.elf ifeq (, $(shell which x-terminal-emulator 2>/dev/null)) @which $(TERM) || { echo "TERM not set properly, please do so, e.g. with 'export TERM=xterm'"; exit 1; } $(TERM) -e "bash -c 'make gdb; killall $(QEMU)'" & else x-terminal-emulator -e "make gdb; killall $(QEMU)" & endif debug: gdb_window qemu_debug debug_replay: gdb_window qemu_debug_replay format: @$(FORMAT) $(FORMATFLAGS) $$(find . -name '*.c' -o -name '*.h') @echo "Finished reformatting code." clean: rm -rf $(BUILD_DIR) CURR_BRANCH = $(shell git branch --show-current 2> /dev/null) STATUS_BRANCH = "$(shell git status --porcelain 2> /dev/null)" submission: ifneq ($(CURR_BRANCH), $(SUBMISSION_BRANCH)) @echo "Refusing to create submission!" @echo "Current branch does not match submission branch." @echo " > Currently on branch: '$(CURR_BRANCH)'" @echo " > But registered submission branch is: '$(SUBMISSION_BRANCH)'" @echo "Please change branch or fix submission branch." @exit 1 endif ifneq ($(STATUS_BRANCH), "") @echo "Refusing to create submission!" @echo "Submission branch is dirty or contains untracked files." @echo "" @echo "Please commit changes and add non essential files to '.gitignore'." @echo "Use 'git status' for a detailed list." @echo "" @exit 1 endif git archive --format=tar.gz -o submission.tar.gz $(SUBMISSION_BRANCH) @echo Successfully created submission.tar.gz @echo We recommend testing archive before submitting it.