#!/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)