summaryrefslogtreecommitdiff
path: root/na/scripts/gen_reloc.py
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-07-10 11:24:56 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-07-10 11:24:56 +0800
commit1767d390fbf3d0c65389de46caf0b6d43ef3b6ad (patch)
tree0f5e01cd7c7a05abb6b1c7472d7f00f49caf02cc /na/scripts/gen_reloc.py
parent63dc025705f6533b91fb1a7d26e6ed864efd9900 (diff)
downloadlume-1767d390fbf3d0c65389de46caf0b6d43ef3b6ad.tar.gz
lume-1767d390fbf3d0c65389de46caf0b6d43ef3b6ad.tar.xz
feat: establish bootable new architecture checkpoint
Replace the compressed boot path with a relocatable higher-half RISC-V entry, expand memory and SMP support, and add the driver, TTY, VFS, exec, signal, syscall, initramfs, and self-test infrastructure needed for a bootable kernel checkpoint.
Diffstat (limited to 'na/scripts/gen_reloc.py')
-rw-r--r--na/scripts/gen_reloc.py224
1 files changed, 0 insertions, 224 deletions
diff --git a/na/scripts/gen_reloc.py b/na/scripts/gen_reloc.py
deleted file mode 100644
index 6709e17..0000000
--- a/na/scripts/gen_reloc.py
+++ /dev/null
@@ -1,224 +0,0 @@
-#!/usr/bin/env python3
-# SPDX-License-Identifier: GPL-2.0-or-later
-# Copyright (C) 2026 Richard Qin
-
-import argparse
-import struct
-import sys
-
-ELF_MAGIC = b"\x7fELF"
-ELFCLASS64 = 2
-ELFDATA2LSB = 1
-EM_RISCV = 243
-SHT_SYMTAB = 2
-SHT_RELA = 4
-PT_LOAD = 1
-
-R_RISCV_64 = 2
-R_RISCV_RELATIVE = 3
-
-RELOC_MAGIC = 0x4C554D45524C4F43 # "LUMERLOC"
-RELOC_VERSION = 1
-RELOC_ARCH_RISCV = 1
-
-
-def read_struct(fmt, data, offset):
- size = struct.calcsize(fmt)
- return struct.unpack_from(fmt, data, offset), size
-
-
-def parse_elf_header(data):
- if data[:4] != ELF_MAGIC:
- raise ValueError("not an ELF file")
- ei_class = data[4]
- ei_data = data[5]
- if ei_class != ELFCLASS64 or ei_data != ELFDATA2LSB:
- raise ValueError("unsupported ELF class/data")
- fmt = "<16sHHIQQQIHHHHHH"
- (e_ident, e_type, e_machine, e_version, e_entry, e_phoff, e_shoff,
- e_flags, e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum,
- e_shstrndx), _ = read_struct(fmt, data, 0)
- return {
- "e_machine": e_machine,
- "e_phoff": e_phoff,
- "e_phentsize": e_phentsize,
- "e_phnum": e_phnum,
- "e_shoff": e_shoff,
- "e_shentsize": e_shentsize,
- "e_shnum": e_shnum,
- "e_shstrndx": e_shstrndx,
- }
-
-
-def parse_program_headers(data, ehdr):
- phdrs = []
- fmt = "<IIQQQQQQ"
- for i in range(ehdr["e_phnum"]):
- off = ehdr["e_phoff"] + i * ehdr["e_phentsize"]
- (p_type, p_flags, p_offset, p_vaddr, p_paddr, p_filesz, p_memsz,
- p_align), _ = read_struct(fmt, data, off)
- phdrs.append({
- "p_type": p_type,
- "p_offset": p_offset,
- "p_vaddr": p_vaddr,
- "p_filesz": p_filesz,
- "p_memsz": p_memsz,
- })
- return phdrs
-
-
-def parse_section_headers(data, ehdr):
- shdrs = []
- fmt = "<IIQQQQIIQQ"
- for i in range(ehdr["e_shnum"]):
- off = ehdr["e_shoff"] + i * ehdr["e_shentsize"]
- (sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size,
- sh_link, sh_info, sh_addralign, sh_entsize), _ = read_struct(fmt, data, off)
- shdrs.append({
- "sh_name": sh_name,
- "sh_type": sh_type,
- "sh_addr": sh_addr,
- "sh_offset": sh_offset,
- "sh_size": sh_size,
- "sh_link": sh_link,
- "sh_entsize": sh_entsize,
- })
- return shdrs
-
-
-def get_strtab(data, shdrs, idx):
- sh = shdrs[idx]
- return data[sh["sh_offset"]:sh["sh_offset"] + sh["sh_size"]]
-
-
-def get_section_name(strtab, sh_name):
- end = strtab.find(b"\x00", sh_name)
- if end < 0:
- return ""
- return strtab[sh_name:end].decode("ascii", errors="ignore")
-
-
-def find_symbol(data, shdrs, name):
- for i, sh in enumerate(shdrs):
- if sh["sh_type"] != SHT_SYMTAB:
- continue
- strtab = get_strtab(data, shdrs, sh["sh_link"])
- entsize = sh["sh_entsize"] or 24
- count = sh["sh_size"] // entsize
- for j in range(count):
- off = sh["sh_offset"] + j * entsize
- (st_name, st_info, st_other, st_shndx, st_value, st_size), _ = read_struct(
- "<IBBHQQ", data, off
- )
- sym_name = get_section_name(strtab, st_name)
- if sym_name == name:
- return st_value
- return None
-
-
-def read_symtab(data, shdrs, idx):
- sh = shdrs[idx]
- entsize = sh["sh_entsize"] or 24
- count = sh["sh_size"] // entsize
- syms = []
- for j in range(count):
- off = sh["sh_offset"] + j * entsize
- (st_name, st_info, st_other, st_shndx, st_value, st_size), _ = read_struct(
- "<IBBHQQ", data, off
- )
- syms.append((st_value, st_size, st_info, st_shndx))
- return syms
-
-
-def vaddr_in_load(vaddr, phdrs, size):
- for ph in phdrs:
- if ph["p_type"] != PT_LOAD:
- continue
- start = ph["p_vaddr"]
- end = ph["p_vaddr"] + ph["p_memsz"]
- if vaddr >= start and vaddr + size <= end:
- return True
- return False
-
-
-def main():
- ap = argparse.ArgumentParser()
- ap.add_argument("--elf", required=True)
- ap.add_argument("--out", required=True)
- args = ap.parse_args()
-
- data = open(args.elf, "rb").read()
- ehdr = parse_elf_header(data)
- if ehdr["e_machine"] != EM_RISCV:
- raise ValueError("only EM_RISCV supported")
-
- phdrs = parse_program_headers(data, ehdr)
- shdrs = parse_section_headers(data, ehdr)
-
- link_base = find_symbol(data, shdrs, "_start")
- if link_base is None:
- raise ValueError("_start symbol not found")
-
- image_end = find_symbol(data, shdrs, "__lume_image_end")
- if image_end is None:
- raise ValueError("__lume_image_end symbol not found")
- image_size = image_end - link_base
-
- entries = []
- for sh in shdrs:
- if sh["sh_type"] != SHT_RELA:
- continue
- if sh["sh_link"] >= len(shdrs):
- continue
- symtab = read_symtab(data, shdrs, sh["sh_link"])
- entsize = sh["sh_entsize"] or 24
- count = sh["sh_size"] // entsize
- for i in range(count):
- off = sh["sh_offset"] + i * entsize
- (r_offset, r_info, r_addend), _ = read_struct("<QQq", data, off)
- r_type = r_info & 0xFFFFFFFF
- r_sym = r_info >> 32
- if r_type not in (R_RISCV_RELATIVE, R_RISCV_64):
- continue
- if r_offset < link_base or r_offset >= link_base + image_size:
- continue
- if not vaddr_in_load(r_offset, phdrs, 8):
- continue
- ent_offset = r_offset - link_base
- if r_type == R_RISCV_RELATIVE:
- ent_addend = r_addend
- ent_type = 1
- else:
- sym_val = 0
- if r_sym < len(symtab):
- sym_val = symtab[r_sym][0]
- ent_addend = sym_val + r_addend
- if ent_addend < link_base or ent_addend >= link_base + image_size:
- continue
- ent_type = 2
- entries.append((ent_offset, ent_addend, ent_type))
-
- header = struct.pack(
- "<QHHIII",
- RELOC_MAGIC,
- RELOC_VERSION,
- RELOC_ARCH_RISCV,
- 24,
- len(entries),
- 0,
- )
-
- with open(args.out, "wb") as f:
- f.write(header)
- for off, add, typ in entries:
- f.write(struct.pack("<QQII", off, add, typ, 0))
-
- return 0
-
-
-if __name__ == "__main__":
- try:
- sys.exit(main())
- except Exception as e:
- print("gen_reloc: " + str(e), file=sys.stderr)
- sys.exit(1)