From c9f158361cba8218a45fdc0ccb9a14ba05ddac3a Mon Sep 17 00:00:00 2001 From: Richard Qin Date: Wed, 13 May 2026 15:54:04 +0800 Subject: feat: add KASLR configuration options and implement LZ4 compression in pack_image script --- na/scripts/pack_image.py | 227 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 na/scripts/pack_image.py (limited to 'na/scripts/pack_image.py') diff --git a/na/scripts/pack_image.py b/na/scripts/pack_image.py new file mode 100644 index 0000000..dc5c6db --- /dev/null +++ b/na/scripts/pack_image.py @@ -0,0 +1,227 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2026 Richard Qin + +import argparse +import struct +import sys + +MAGIC = 0x4C554D45434F4D50 # "LUMECOMP" +COMP_NONE = 0 +COMP_LZ4 = 1 + +HDR_FMT = " int: + for b in data: + crc ^= b + for _ in range(8): + mask = -(crc & 1) & 0xFFFFFFFF + crc = ((crc >> 1) ^ (0xEDB88320 & mask)) & 0xFFFFFFFF + return crc + + +def crc32_ieee(data: bytes) -> int: + crc = 0xFFFFFFFF + crc = crc32_update(crc, data) + return (crc ^ 0xFFFFFFFF) & 0xFFFFFFFF + + +def lz4_compress(data: bytes) -> bytes: + n = len(data) + if n == 0: + return b"" + + min_match = 4 + hash_log = 16 + hash_size = 1 << hash_log + max_offset = 65535 + + def hash4(b0, b1, b2, b3): + v = b0 | (b1 << 8) | (b2 << 16) | (b3 << 24) + return (v * 2654435761) & (hash_size - 1) + + htab = [-1] * hash_size + out = bytearray() + anchor = 0 + i = 0 + + while i + min_match <= n: + h = hash4(data[i], data[i + 1], data[i + 2], data[i + 3]) + ref = htab[h] + htab[h] = i + + if ref >= 0 and i - ref <= max_offset and data[ref:ref + min_match] == data[i:i + min_match]: + match_len = min_match + while i + match_len < n and data[ref + match_len] == data[i + match_len]: + match_len += 1 + + lit_len = i - anchor + token = (15 if lit_len >= 15 else lit_len) << 4 + match_field = match_len - min_match + token |= 15 if match_field >= 15 else match_field + out.append(token) + + if lit_len >= 15: + l = lit_len - 15 + while l >= 255: + out.append(255) + l -= 255 + out.append(l) + + out.extend(data[anchor:i]) + + offset = i - ref + out.append(offset & 0xFF) + out.append((offset >> 8) & 0xFF) + + if match_field >= 15: + l = match_field - 15 + while l >= 255: + out.append(255) + l -= 255 + out.append(l) + + i += match_len + anchor = i + continue + + i += 1 + + lit_len = n - anchor + token = (15 if lit_len >= 15 else lit_len) << 4 + out.append(token) + if lit_len >= 15: + l = lit_len - 15 + while l >= 255: + out.append(255) + l -= 255 + out.append(l) + out.extend(data[anchor:]) + return bytes(out) + + +def get_header_offset(data: bytes) -> int: + if len(data) < HDR_OFFSET + HDR_SIZE: + return -1 + if data[HDR_OFFSET:HDR_OFFSET + 8] != struct.pack("= e_shnum: + continue + str_off = e_shoff + sh_link * e_shentsize + (sname, stype, sflags, saddr, soff, ssize, slink, sinfo, + salign, sentsz), _ = read_struct("= link_base: + payload_offset = (bss_end - link_base + 7) & ~7 + + header[4] = comp + header[6] = uncompressed_size + header[7] = compressed_size + header[8] = 0 # load_phys_base auto + header[11] = payload_offset + header[12] = 0 + header[13] = crc32_ieee(payload) if payload else 0 + + header_bytes = struct.pack(HDR_FMT, *header) + header[12] = crc32_ieee(header_bytes) + + out = bytearray(raw) + struct.pack_into(HDR_FMT, out, hdr_off, *header) + if payload: + if payload_offset > len(out): + out.extend(b"\x00" * (payload_offset - len(out))) + out.extend(payload) + + with open(args.output, "wb") as f: + f.write(out) + + return 0 + + +if __name__ == "__main__": + try: + sys.exit(main()) + except Exception as e: + print("pack_image: " + str(e), file=sys.stderr) + sys.exit(1) -- cgit v1.2.3