From 2616b1c667de91b049d1cf03807dede8ca4e8cc2 Mon Sep 17 00:00:00 2001
From: Jordan Carlin <jordanmcarlin@gmail.com>
Date: Tue, 21 Jan 2025 20:14:01 -0800
Subject: [PATCH] Overhaul linux makefile

---
 linux/Makefile                                | 127 +++++++++---------
 linux/README.MD                               |   2 +-
 .../board/wally/post_image.sh                 |   5 +
 .../br2-external-tree/configs/wally_defconfig |   1 +
 4 files changed, 70 insertions(+), 65 deletions(-)
 create mode 100644 linux/br2-external-tree/board/wally/post_image.sh

diff --git a/linux/Makefile b/linux/Makefile
index 8852c02ad..3c0c996d3 100644
--- a/linux/Makefile
+++ b/linux/Makefile
@@ -1,27 +1,32 @@
-# .SECONDEXPANSION:
-
-BUILDROOT := buildroot
-IMAGES := ${BUILDROOT}/output/images
-WALLYLINUX := $(WALLY)/linux
-DIS := ${IMAGES}/disassembly
+BUILDROOT         := buildroot
+IMAGE_DIR         := ${BUILDROOT}/output/images
+DISASSEMBLY_DIR   := ${IMAGE_DIR}/disassembly
+WALLYLINUX        := $(WALLY)/linux
 BR2_EXTERNAL_TREE := $(WALLYLINUX)/br2-external-tree
-LINUX_TEST_VECTORS := $(RISCV)/linux-testvectors
+LINUX_TESTVECTORS := $(RISCV)/linux-testvectors
 
-# set sudo if needed depending on $RISCV
-SUDO := $(shell mkdir -p $(RISCV)/.test > /dev/null 2>&1 || echo sudo)
+BUILDROOT_OUTPUTS := Image fw_jump.bin fw_jump.elf rootfs.cpio vmlinux busybox
 
 # Device tree files
 DTS ?= $(wildcard devicetree/*.dts)
-DTB := $(foreach name, $(DTS:%.dts=%.dtb), $(IMAGES)/$(notdir $(name)))
+DTB := $(foreach name, $(DTS:%.dts=%.dtb), $(IMAGE_DIR)/$(notdir $(name)))
 
-# Disassembly stuff
+# Disassembly files
 BINARIES := fw_jump.elf vmlinux busybox
-OBJDUMPS := $(foreach name, $(basename $(BINARIES) .elf), $(DIS)/$(name).objdump)
+OBJDUMPS := $(foreach name, $(basename $(BINARIES) .elf), $(DISASSEMBLY_DIR)/$(name).objdump)
 
-.PHONY: all check_environment check_write_permissions config Image disassemble generate install dumptvs clean cleanDTB
+# Testvector files
+RAW_RAM_FILE     := ${LINUX_TESTVECTORS}/ramGDB.bin
+RAM_FILE         := ${LINUX_TESTVECTORS}/ram.bin
+RAW_BOOTMEM_FILE := ${LINUX_TESTVECTORS}/bootmemGDB.bin
+BOOTMEM_FILE     := ${LINUX_TESTVECTORS}/bootmem.bin
 
-all: check_write_permissions clean config Image disassemble install dumptvs
+.PHONY: all check_environment check_write_permissions config build disassemble devicetrees install dumptvs clean cleanDTB
 
+# Default target
+all: check_write_permissions clean config build disassemble install dumptvs
+
+# Check if the environment variables are set correctly
 check_environment: $(RISCV)
 ifeq ($(findstring :$(RISCV)/lib:,:$(LD_LIBRARY_PATH):),)
 	@(echo "ERROR: Your environment variables are not set correctly." >&2 \
@@ -29,6 +34,8 @@ ifeq ($(findstring :$(RISCV)/lib:,:$(LD_LIBRARY_PATH):),)
 	&& exit 1)
 endif
 
+# Check if the user has write permissions to the RISCV directory, potentially using sudo
+SUDO := $(shell mkdir -p $(RISCV)/.test > /dev/null 2>&1 || echo sudo)
 check_write_permissions: check_environment
 ifeq ($(SUDO), sudo)
 	@echo "Cannot write to '$(RISCV)'." \
@@ -39,31 +46,30 @@ endif
 		&& exit 1)
 	@$(SUDO) rm -r $(RISCV)/.test
 
-Image: check_environment $(BUILDROOT)
-	bash -c "unset LD_LIBRARY_PATH; $(MAKE) -C $(BUILDROOT)"
-# $(MAKE) generate
-	@echo "Buildroot Image successfully generated."
+# Build buildroot and device tree binaries
+build: $(BUILDROOT_OUTPUTS) devicetrees
 
+# Build buildroot itself
+# LD_LIBRARY_PATH must be unset to avoid conflicts between the host and cross compiler
+$(BUILDROOT_OUTPUTS): check_environment $(BUILDROOT)
+	bash -c "unset LD_LIBRARY_PATH; $(MAKE) -C $(BUILDROOT)"
+
+# Install buildroot to $RISCV
 install: check_write_permissions
 	$(SUDO) rm -rf $(RISCV)/$(BUILDROOT)
 	$(SUDO) mv $(BUILDROOT) $(RISCV)/$(BUILDROOT)
-	@echo "Buildroot successfully installed."
 
-TCP_PORT=1235
-RAW_RAM_FILE=${LINUX_TEST_VECTORS}/ramGDB.bin
-RAM_FILE=${LINUX_TEST_VECTORS}/ram.bin
-RAW_BOOTMEM_FILE=${LINUX_TEST_VECTORS}/bootmemGDB.bin
-BOOTMEM_FILE=${LINUX_TEST_VECTORS}/bootmem.bin
+# Generate linux boot testvectors
+dumptvs: ${RAM_FILE} ${BOOTMEM_FILE}
 
-MEM_FILES=${RAM_FILE} ${BOOTMEM_FILE}
-
-dumptvs: check_write_permissions ${MEM_FILES}
-
-${LINUX_TEST_VECTORS}/%.bin: ${LINUX_TEST_VECTORS}/%GDB.bin
+# Format QEMU memory dumps for use as testvectors
+${LINUX_TESTVECTORS}/%.bin: ${LINUX_TESTVECTORS}/%GDB.bin
 	truncate -s %8 $^ # Extend file to 8 byte multiple
 	objcopy --reverse-bytes=8 -F binary $^ $@ # Reverse bytes
 
-${LINUX_TEST_VECTORS}/%GDB.bin: | $(LINUX_TEST_VECTORS)
+# Generate memory dumps from QEMU buildroot boot
+TCP_PORT := 1235
+${LINUX_TESTVECTORS}/%GDB.bin: | $(LINUX_TESTVECTORS)
 	${WALLYLINUX}/qemuBoot.sh --gdb ${TCP_PORT} &
 	riscv64-unknown-elf-gdb -batch \
 		-ex "target remote :${TCP_PORT}" \
@@ -72,60 +78,53 @@ ${LINUX_TEST_VECTORS}/%GDB.bin: | $(LINUX_TEST_VECTORS)
 		-ex "dump binary memory ${RAW_BOOTMEM_FILE} 0x1000 0x1fff" \
 		-ex "printf \"Creating ${RAW_RAM_FILE}\n\"" \
 		-ex "dump binary memory ${RAW_RAM_FILE} 0x80000000 0x8fffffff" \
-		-ex "kill" \
+		-ex "kill"
 
-generate: $(DTB) $(IMAGES)
-
-$(IMAGES)/%.dtb: ${WALLYLINUX}/devicetree/%.dts
+# Generate device tree binaries
+devicetrees: $(DTB)
+$(IMAGE_DIR)/%.dtb: ${WALLYLINUX}/devicetree/%.dts
 	dtc -I dts -O dtb $< > $@
 
-$(IMAGES):
-	@ echo "No output/images directory in buildroot."
-	@ echo "Run make --jobs in buildroot directory before generating device tree binaries."; exit 1
+# Create disassembly files
+disassemble: check_environment $(OBJDUMPS) $(DISASSEMBLY_DIR)/rootfs
 
-$(RISCV):
-	@ echo "ERROR: No $(RISCV) directory. Make sure you have installed the Wally Toolchain."
-	@ echo "and sourced setup.sh"
-
-# Disassembly rules ---------------------------------------------------
-disassemble: check_environment
-	cp $(BUILDROOT)/output/build/linux-*/vmlinux $(IMAGES)
-	$(MAKE) $(OBJDUMPS) $(DIS)/rootfs
-
-$(DIS)/rootfs: $(IMAGES)/rootfs.cpio
+# Extract rootfs
+$(DISASSEMBLY_DIR)/rootfs: $(IMAGE_DIR)/rootfs.cpio
 	@echo "Ignore error about dev/console when extracting rootfs from rootfs.cpio"
-	mkdir -p $(DIS)/rootfs
-	-cpio -i -D $(DIS)/rootfs < $(IMAGES)rootfs.cpio
+	mkdir -p $(DISASSEMBLY_DIR)/rootfs
+	-cpio -i -D $(DISASSEMBLY_DIR)/rootfs -F $(IMAGE_DIR)rootfs.cpio
 
-$(DIS)/%.objdump: $(IMAGES)/%.elf | $(DIS)
-	riscv64-unknown-elf-objdump -DS $< >> $@
+# Disassemble binaries
+objdump_flags = $(if $(findstring .elf,$<),-SD,-S) # Add -D flag for .elf files
+$(DISASSEMBLY_DIR)/%.objdump: $(IMAGE_DIR)/% | $(DISASSEMBLY_DIR)
+	riscv64-unknown-elf-objdump $(objdump_flags) $< >> $@
 	$(WALLY)/bin/extractFunctionRadix.sh $@
 
-$(DIS)/%.objdump: $(IMAGES)/% | $(DIS)
-	riscv64-unknown-elf-objdump -S $< >> $@
-	$(WALLY)/bin/extractFunctionRadix.sh $@
-
-$(IMAGES)/vmlinux:
-	cp $(BUILDROOT)/output/build/linux-*/vmlinux $@
-
-$(IMAGES)/busybox:
-	cp $(BUILDROOT)/output/build/busybox-*/busybox $@
-
+# Load wally buildroot configuration
 config: $(BUILDROOT) $(BR2_EXTERNAL_TREE)/configs/wally_defconfig
 	$(MAKE) -C $(BUILDROOT) wally_defconfig BR2_EXTERNAL=$(BR2_EXTERNAL_TREE)
 
+# Clone buildroot and checkout the correct version
 $(BUILDROOT):
 	git clone https://github.com/buildroot/buildroot.git $@
 	cd $@; git checkout 2024.11.x
 
-$(LINUX_TEST_VECTORS):
+# Create directories
+$(LINUX_TESTVECTORS): check_write_permissions
 	$(SUDO) mkdir -p $@
 
-$(DIS):
+$(DISASSEMBLY_DIR):
 	mkdir -p $@
 
+# Remove device tree binaries
 cleanDTB:
-	rm -f $(IMAGES)/*.dtb
+	rm -f $(IMAGE_DIR)/*.dtb
 
+# Remove buildroot directory
 clean:
 	rm -rf $(BUILDROOT)
+
+# Check if the RISCV environment variable is set
+$(RISCV):
+	@ echo "ERROR: No $(RISCV) directory. Make sure you have installed the Wally Toolchain."
+	@ echo "and sourced setup.sh"
diff --git a/linux/README.MD b/linux/README.MD
index b7a031ce6..2e8405f70 100644
--- a/linux/README.MD
+++ b/linux/README.MD
@@ -35,7 +35,7 @@ The device tree files for the various FPGAs Wally supports, as well as QEMU's de
 They are built automatically using the main `make` command. To build the device tree binaries (.dtb) from the device tree sources (.dts) separately, we can build all of them at once using:
 
 ```bash
-$ make generate # optionally override BUILDROOT
+$ make devicetrees # optionally override BUILDROOT
 ```
 
 The .dts files will end up in the `<BUILDROOT>/output/images` folder of your chosen buildroot directory.
diff --git a/linux/br2-external-tree/board/wally/post_image.sh b/linux/br2-external-tree/board/wally/post_image.sh
new file mode 100644
index 000000000..53544d8b3
--- /dev/null
+++ b/linux/br2-external-tree/board/wally/post_image.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+# Copy linux and busybox binaries (with symbol info) to images directory
+cp "$BUILD_DIR"/linux-*/vmlinux "$BINARIES_DIR"/vmlinux
+cp "$BUILD_DIR"busybox-*/busybox "$BINARIES_DIR"/busybox
diff --git a/linux/br2-external-tree/configs/wally_defconfig b/linux/br2-external-tree/configs/wally_defconfig
index 24d82e9d0..8759588a7 100644
--- a/linux/br2-external-tree/configs/wally_defconfig
+++ b/linux/br2-external-tree/configs/wally_defconfig
@@ -19,6 +19,7 @@ BR2_TARGET_GENERIC_ISSUE="Greetings! This RISC-V Linux image was built for Wally
 BR2_ROOTFS_DEVICE_TABLE_SUPPORTS_EXTENDED_ATTRIBUTES=y
 BR2_SYSTEM_DHCP="eth0"
 BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_WALLY_PATH)/board/wally/rootfs_overlay"
+BR2_ROOTFS_POST_IMAGE_SCRIPT="$(BR2_EXTERNAL_WALLY_PATH)/board/wally/post_image.sh"
 BR2_LINUX_KERNEL=y
 BR2_LINUX_KERNEL_CUSTOM_VERSION=y
 BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.8"