97 lines
3.1 KiB
Python
97 lines
3.1 KiB
Python
#!/usr/bin/env python
|
|
|
|
import json
|
|
import sys
|
|
import argparse
|
|
import os
|
|
|
|
def extract_firmware_version():
|
|
with open('main/CommandHandler.cpp', 'r') as file:
|
|
for line in file:
|
|
if 'const char FIRMWARE_VERSION[] = ' in line:
|
|
# The line format is `const char FIRMWARE_VERSION[] = "2.0.0-adafruit";`
|
|
# Split by double quote and get the second element
|
|
version = line.split('"')[1]
|
|
return version
|
|
raise RuntimeError("FIRMWARE_VERSION not found in CommandHandler.cpp")
|
|
|
|
def get_idf_target(build_dir):
|
|
with open(f"{build_dir}/config.env") as file:
|
|
config = json.load(file)
|
|
return config["IDF_TARGET"]
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('outfile', help='output file')
|
|
parser.add_argument('-b', '--build_dir', default='build', help='build directory')
|
|
|
|
args = parser.parse_args()
|
|
outfile = args.outfile
|
|
build_dir = os.path.normpath(args.build_dir)
|
|
|
|
bootloaderData = open(f"{build_dir}/bootloader/bootloader.bin", "rb").read()
|
|
partitionData = open(f"{build_dir}/partition_table/partition-table.bin", "rb").read()
|
|
#phyData = open("data/phy.bin", "rb").read()
|
|
appData = open(f"{build_dir}/nina-fw.bin", "rb").read()
|
|
|
|
# remove everything between certificate markers to save space. There might be comments and other information.
|
|
certsData = b""
|
|
with open("certificates/data/roots.pem", "rb") as certs_file:
|
|
in_cert = False
|
|
for line in certs_file:
|
|
if line.startswith(b"-----BEGIN CERTIFICATE-----"):
|
|
in_cert = True
|
|
if in_cert:
|
|
certsData += line
|
|
if line.startswith(b"-----END CERTIFICATE-----"):
|
|
in_cert = False
|
|
|
|
# calculate the output binary size, app offset
|
|
outputSize = 0x30000 + len(appData)
|
|
if outputSize % 1024:
|
|
outputSize += 1024 - (outputSize % 1024)
|
|
|
|
# allocate and init to 0xff
|
|
outputData = bytearray(b"\xff") * outputSize
|
|
|
|
# copy data: bootloader, partitions, app
|
|
BOOTLOADER_OFFSET = {
|
|
"esp32" : 0x1000,
|
|
"esp32c6" : 0x0000,
|
|
}
|
|
|
|
try:
|
|
idf_target = get_idf_target(build_dir)
|
|
bootloader_offset = BOOTLOADER_OFFSET[idf_target]
|
|
except KeyError:
|
|
raise RuntimeError(f"unsupported IDF_TARGET: {idf_target}")
|
|
|
|
for i in range(0, len(bootloaderData)):
|
|
outputData[bootloader_offset + i] = bootloaderData[i]
|
|
|
|
for i in range(0, len(partitionData)):
|
|
outputData[0x8000 + i] = partitionData[i]
|
|
|
|
#for i in range(0, len(phyData)):
|
|
# outputData[0xf000 + i] = phyData[i]
|
|
|
|
for i in range(0, len(certsData)):
|
|
outputData[0x10000 + i] = certsData[i]
|
|
|
|
# zero terminate the pem file
|
|
outputData[0x10000 + len(certsData)] = 0
|
|
|
|
for i in range(0, len(appData)):
|
|
outputData[0x30000 + i] = appData[i]
|
|
|
|
version = extract_firmware_version()
|
|
outputFilename = f"{outfile}-{version}.bin"
|
|
|
|
# write out
|
|
with open(outputFilename, "w+b") as f:
|
|
f.seek(0)
|
|
f.write(outputData)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|