Загрузка данных


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