Загрузка данных
#!/usr/bin/env python3
import sys
import subprocess
import os
import struct
def patch_boot_data_length(bin_path, final_length):
if not os.path.exists(bin_path):
return
try:
with open(bin_path, "r+b") as f:
f.seek(0x24) # Смещение поля Boot Data Length в архитектуре NXP
f.write(struct.pack("<I", final_length))
print(f"[LMA Filter] BootROM Patch: Fixed Boot Data Length to {final_length} bytes")
except Exception as e:
print(f"[LMA Filter] BootROM Patch Error: {e}")
def generate_native_hex_0x60000000(bin_path, hex_path):
""" Генератор Intel HEX файла на чистом Python со сдвигом LMA в 0x60000000 """
try:
with open(bin_path, "rb") as f:
data = f.read()
hex_lines = []
# Запись Extended Linear Address (базовый адрес 0x60000000)
hex_lines.append(":0200000460009A")
address = 0
for i in range(0, len(data), 16):
chunk = data[i:i+16]
length = len(chunk)
# Контроль перехода 64-килобайтных страниц во флеш-памяти
if address > 0 and (address % 0x10000 == 0):
upper_hex = 0x6000 + ((address >> 16) & 0xFFFF)
payload = struct.pack(">H", upper_hex)
checksum = (0x02 + 0x04 + sum(payload)) & 0xFF
checksum = (-checksum) & 0xFF
hex_lines.append(f":02000004{upper_hex:04X}{checksum:02X}")
offset = address & 0xFFFF
record_type = 0x00 # Данные
# Расчет контрольной суммы строки Intel HEX
checksum = length + (offset >> 8) + (offset & 0xFF) + record_type + sum(chunk)
checksum = (-checksum) & 0xFF
hex_data = "".join(f"{b:02X}" for b in chunk)
hex_lines.append(f":{length:02X}{offset:04X}{record_type:02X}{hex_data}{checksum:02X}")
address += length
hex_lines.append(":00000001FF") # Конец файла
with open(hex_path, "w") as f:
f.write("\n".join(hex_lines) + "\n")
print("[LMA Filter] Success: Shifted 0x60000000 LMA zephyr.hex generated via pure Python")
except Exception as e:
print(f"[LMA Filter] HEX Generator Error: {e}")
def main():
if len(sys.argv) < 2:
sys.exit(1)
real_objcopy = sys.argv[1]
args = sys.argv[2:]
elf_path = "zephyr.elf"
for arg in args:
if arg.endswith("zephyr.elf"):
elf_path = arg
break
# 1. Даем стандартной утилите выполнить свою команду, но перехватываем падение
final_cmd = [real_objcopy] + args
try:
subprocess.run(final_cmd, check=True)
except subprocess.CalledProcessError:
pass # Игнорируем ошибку private headers, мы скорректируем файлы ниже
# 2. Активируем фильтр на этапе генерации финальных файлов прошивки
if "--output-target=ihex" in " ".join(args):
build_dir = os.path.dirname(elf_path)
bin_path = os.path.join(build_dir, "zephyr.bin")
hex_path = os.path.join(build_dir, "zephyr.hex")
# Если objcopy упал до того, как успел создать bin, создаем его принудительно.
# Извлечение чистого бинарника из ELF обычно не вызывает сбоев из-за TLS-заголовков.
if not os.path.exists(bin_path):
gen_bin_cmd = [real_objcopy, "-O", "binary", elf_path, bin_path]
subprocess.run(gen_bin_cmd, check=True)
if os.path.exists(bin_path):
image_size = os.path.getsize(bin_path)
# Патчим Boot Data Length
patch_boot_data_length(bin_path, image_size)
# Генерируем правильный HEX-файл
generate_native_hex_0x60000000(bin_path, hex_path)
if __name__ == "__main__":
main()