summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Lee <me@nwlee.tech>2026-09-13 17:46:26 -0500
committerNathan Lee <me@nwlee.tech>2026-09-13 17:46:26 -0500
commit09be8ace254a7f8bb69542d09a6b2013636123a2 (patch)
tree928011aa958624369cefeb46f9e206093a55e0a2
parent11501f6f0c82712ea5f172f9177f2375c87d06e9 (diff)
EFI boot header support
-rw-r--r--Makefile24
-rw-r--r--kernel/riscv/header.S23
-rw-r--r--kernel/riscv/linker.ld13
-rw-r--r--misc/kassemble.c47
4 files changed, 103 insertions, 4 deletions
diff --git a/Makefile b/Makefile
index 8ea760b..ad38c9a 100644
--- a/Makefile
+++ b/Makefile
@@ -2,6 +2,7 @@ VERSION = 0.1.0-alpha
CC = clang
LD = ld.lld
+NM = llvm-nm
OBJCOPY = llvm-objcopy
COMPILER = $(shell $(CC) --version | head -n 1)
@@ -99,20 +100,27 @@ KERNEL_OBJS = $(KERNEL_SRCS:.c=.o)
KERNEL_OBJS := $(KERNEL_OBJS:.S=.o)
KERNEL_BIN := $(KERNEL_TARGET)/kernel.bin
KERNEL_ELF := $(KERNEL_TARGET)/kernel.elf
+KERNEL_IMAGE := $(KERNEL_TARGET)/Image
+
+KASSEMBLE_BIN := misc/kassemble
+KASSEMBLE_SRC := misc/kassemble.c
GENERATED = \
$(KERNEL_OBJS) \
$(KERNEL_ELF) \
$(KERNEL_BIN) \
+ $(KERNEL_IMAGE) \
$(foreach m,$(MODULES),$(m)/$(m).elf) \
$(foreach m,$(MODULES),$(m)/$(m).ko) \
- $(foreach m,$(MODULES),$($(m)_OBJS))
+ $(foreach m,$(MODULES),$($(m)_OBJS)) \
+ $(KASSEMBLE_BIN)
-.PHONY: all kernel clean modules $(MODULES)
+.PHONY: all kernel kassemble clean modules $(MODULES)
$(V).SILENT:
-all: kernel modules
-kernel: $(KERNEL_BIN)
+all: kassemble kernel modules
+kernel: $(KERNEL_IMAGE)
modules: $(MODULES)
+kassemble: $(KASSEMBLE_BIN)
$(MODULES): $(MODULE_OBJECTS)
%.o: %.c
@@ -122,6 +130,10 @@ $(MODULES): $(MODULE_OBJECTS)
@echo " AS $<"
$(CC) $(KERNEL_CFLAGS) -c $< -o $@
+$(KASSEMBLE_BIN): $(KASSEMBLE_SRC)
+ @echo " HOSTCC $<"
+ $(CC) -O2 $< -o $@
+
$(KERNEL_ELF): $(KERNEL_OBJS) $(KERNEL_LD) | $(KERNEL_OUTDIR)/
@echo " LD $@"
$(LD) $(KERNEL_LD_FLAG) $(KERNEL_OBJS) -o $@
@@ -130,6 +142,10 @@ $(KERNEL_BIN): $(KERNEL_ELF) | $(KERNEL_OUTDIR)/
@echo " OBJCOPY $@"
$(OBJCOPY) $(KERNEL_OBJCOPY_FLAG) $(KERNEL_ELF) $(KERNEL_BIN)
+$(KERNEL_IMAGE): $(KERNEL_BIN) | $(KERNEL_OUTDIR)/
+ @echo " KASSEMBLE $@"
+ $(KASSEMBLE_BIN) $< $@ $$($(NM) $(KERNEL_ELF) | awk '/__image_size/{print $$1}')
+
clean:
@echo " CLEAN $(GENERATED)"
$(RM) $(GENERATED)
diff --git a/kernel/riscv/header.S b/kernel/riscv/header.S
new file mode 100644
index 0000000..cca2594
--- /dev/null
+++ b/kernel/riscv/header.S
@@ -0,0 +1,23 @@
+.section .header, "a", @progbits
+.extern _start
+#define CODE0 0x4d, 0x5a, 0, 0
+#define FLAGS 0
+#define TEXT_OFFSET 0
+#define HEADER_VERSION 0x00000002
+#define RES1 0
+#define RES2 0
+#define RES3 0
+#define MAGIC 0x5643534952
+#define MAGIC2 0x05435352
+header:
+ .byte CODE0
+ j _start
+ .quad TEXT_OFFSET
+ .quad 0 # image_size
+ .quad FLAGS
+ .int HEADER_VERSION
+ .int RES1
+ .quad RES2
+ .quad MAGIC
+ .int MAGIC2
+ .int RES3
diff --git a/kernel/riscv/linker.ld b/kernel/riscv/linker.ld
index ec51176..6689dce 100644
--- a/kernel/riscv/linker.ld
+++ b/kernel/riscv/linker.ld
@@ -10,6 +10,11 @@ MEMORY
SECTIONS
{
+ .header : {
+ KEEP(*(.header))
+ *(.header)
+ } > ROM
+
.text : {
KEEP(*(.text._start))
KEEP(*(.text.start))
@@ -60,6 +65,11 @@ SECTIONS
__ringbuf_end = .;
} > LOGRAM
+ .image_end (NOLOAD) : {
+ . = ALIGN(4);
+ __image_end = .;
+ } > ROM
+
/DISCARD/ : {
*(.eh_frame)
*(.eh_frame.*)
@@ -71,4 +81,7 @@ SECTIONS
*(.llvm_*)
*(.rela.*)
}
+
+ __image_start = ORIGIN(ROM);
+ __image_size = __image_end - __image_start;
}
diff --git a/misc/kassemble.c b/misc/kassemble.c
new file mode 100644
index 0000000..a818cc5
--- /dev/null
+++ b/misc/kassemble.c
@@ -0,0 +1,47 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <errno.h>
+
+int main(int argc, char **argv) {
+ if (argc != 4) {
+ fprintf(stderr, "usage: %s <in> <out> <image_size>\n", argv[0]);
+ return 1;
+ }
+
+ const char *in_path = argv[1];
+ const char *out_path = argv[2];
+ char *end;
+ errno = 0;
+ unsigned long long size = strtoull(argv[3], &end, 16);
+ if (errno || *end != '\0') {
+ fprintf(stderr, "bad size: %s, invalid chars: %s\n", argv[3], end);
+ return 1;
+ }
+
+ FILE *in = fopen(in_path, "rb");
+ if (!in) { perror("fopen in"); return 1; }
+
+ FILE *out = fopen(out_path, "wb");
+ if (!out) { perror("fopen out"); fclose(in); return 1; }
+
+ /* Copy in -> out */
+ unsigned char buf[65536];
+ size_t n;
+ while ((n = fread(buf, 1, sizeof buf, in)) > 0) {
+ if (fwrite(buf, 1, n, out) != n) { perror("fwrite"); return 1; }
+ }
+ if (ferror(in)) { perror("fread"); return 1; }
+
+ /* Write size as u64 little-endian at offset 16 */
+ unsigned char le[8];
+ for (int i = 0; i < 8; i++)
+ le[i] = (unsigned char)(size >> (8 * i));
+
+ if (fseek(out, 16, SEEK_SET) != 0) { perror("fseek"); return 1; }
+ if (fwrite(le, 1, 8, out) != 8) { perror("fwrite size"); return 1; }
+
+ fclose(in);
+ if (fclose(out) != 0) { perror("fclose out"); return 1; }
+ return 0;
+}