Deploy script - set correct hashes with esptool

This commit is contained in:
Martin Bauer 2021-07-26 19:20:16 +02:00
parent 89bc990bec
commit 654ff2e7c3
1 changed files with 34 additions and 38 deletions

View File

@ -1,19 +1,14 @@
import struct import struct
import locale
from collections import namedtuple from collections import namedtuple
from datetime import datetime from datetime import datetime
import subprocess import subprocess
from distutils.version import StrictVersion from distutils.version import StrictVersion
import subprocess from esptool import LoadFirmwareImage # required to get hash and checksum right
import os import os
#locale.setlocale(locale.LC_ALL, 'en_US') # locale.setlocale(locale.LC_ALL, 'en_US')
# sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) APP_DESC_SIZE = 256 # sizeof(esp_app_desc_t)
APP_DESC_OFFSET = 32
# sizeof(esp_app_desc_t)
APP_DESC_SIZE = 256
APP_DESC_STRUCT = "<II2I32s32s16s16s32s32B20I" APP_DESC_STRUCT = "<II2I32s32s16s16s32s32B20I"
AppDesc = namedtuple('AppDesc', AppDesc = namedtuple('AppDesc',
@ -28,6 +23,7 @@ AppDesc = namedtuple('AppDesc',
] ]
) )
def version_number_from_git(tag_prefix='release/', sha_length=10, version_format="{version}.dev{commits}+{sha}"): def version_number_from_git(tag_prefix='release/', sha_length=10, version_format="{version}.dev{commits}+{sha}"):
def get_released_versions(): def get_released_versions():
tags = sorted(subprocess.getoutput('git tag').split('\n')) tags = sorted(subprocess.getoutput('git tag').split('\n'))
@ -64,24 +60,22 @@ def version_number_from_git(tag_prefix='release/', sha_length=10, version_format
return version_string return version_string
def read_app_description(file_name): def read_app_description_from_segment(segment):
def process_bytes(b): def process_bytes(b):
if not isinstance(b, bytes): if not isinstance(b, bytes):
return b return b
s = b.decode() s = b.decode()
return s[:s.find("\x00")] return s[:s.find("\x00")]
with open(file_name, 'rb') as f: unpacked = struct.unpack(APP_DESC_STRUCT, segment.data[:APP_DESC_SIZE])
f.seek(APP_DESC_OFFSET, 0) unpacked = tuple(process_bytes(e) for e in unpacked)
raw_app_desc = f.read(APP_DESC_SIZE) magic_word, secure_version, _, _, version, project_name, time, date, idf_ver, app_elf_sha256, *_ = unpacked
unpacked = struct.unpack(APP_DESC_STRUCT, raw_app_desc) assert magic_word == 0xABCD5432
unpacked = tuple(process_bytes(e) for e in unpacked) return AppDesc(secure_version, version, project_name, time, date, idf_ver, app_elf_sha256)
magic_word, secure_version, _, _, version, project_name, time, date, idf_ver, app_elf_sha256, *_ = unpacked
assert magic_word == 0xABCD5432
return AppDesc(secure_version, version, project_name, time, date, idf_ver, app_elf_sha256)
def patch_app_description(file_name, version, project_name, time, date):
def patch_app_description_in_segment(segment, version, project_name, time, date):
assert len(version) < 32 assert len(version) < 32
assert len(project_name) < 32 assert len(project_name) < 32
assert len(time) < 16 assert len(time) < 16
@ -93,39 +87,41 @@ def patch_app_description(file_name, version, project_name, time, date):
assert len(s) == total_length assert len(s) == total_length
return s return s
with open(file_name, 'r+b') as f: raw_app_desc = segment.data[:APP_DESC_SIZE]
f.seek(APP_DESC_OFFSET, 0) unpacked = list(struct.unpack(APP_DESC_STRUCT, raw_app_desc))
raw_app_desc = f.read(APP_DESC_SIZE) unpacked[4] = fill_zeros(version, 32)
unpacked = list(struct.unpack(APP_DESC_STRUCT, raw_app_desc)) unpacked[5] = fill_zeros(project_name, 32)
unpacked[4] = fill_zeros(version, 32) unpacked[6] = fill_zeros(time, 16)
unpacked[5] = fill_zeros(project_name, 32) unpacked[7] = fill_zeros(date, 16)
unpacked[6] = fill_zeros(time, 16) packed = struct.pack(APP_DESC_STRUCT, *unpacked)
unpacked[7] = fill_zeros(date, 16)
packed = struct.pack(APP_DESC_STRUCT, *unpacked) original_data = segment.data
f.seek(APP_DESC_OFFSET, 0) segment.data = packed + original_data[APP_DESC_SIZE:]
f.write(packed)
def add_info_to_firmware(firmware_file, version): def patch_firmware(input_file, output_file):
img = LoadFirmwareImage("esp32", input_file)
version = version_number_from_git()
now = datetime.now() now = datetime.now()
date = now.strftime("%b %d %Y")
time = now.strftime("%H:%M:%S") time = now.strftime("%H:%M:%S")
patch_app_description(firmware_file, version=version, date = now.strftime("%b %d %Y")
project_name="swimtracker.bauer.tech", time=time, date=date) patch_app_description_in_segment(img.segments[0], version, "swimtracker.bauer.tech", time, date)
img.save(output_file)
if __name__ == "__main__": if __name__ == "__main__":
firmware_file = ".pio/build/esp32/firmware.bin" firmware_file = ".pio/build/esp32/firmware.bin"
version_file_name = "VERSION" version_file_name = "VERSION"
version = version_number_from_git() patch_firmware(firmware_file, firmware_file) # patch inplace
add_info_to_firmware(firmware_file, version)
print(read_app_description(firmware_file))
with open(version_file_name, "w") as version_file: with open(version_file_name, "w") as version_file:
print(version, file=version_file) print(version_number_from_git(), file=version_file)
subprocess.run(["scp", firmware_file, "root@server:/volumes/swimtracker-update"]) subprocess.run(["scp", firmware_file, "root@server:/volumes/swimtracker-update"])
subprocess.run(["scp", version_file_name, "root@server:/volumes/swimtracker-update"]) subprocess.run(["scp", version_file_name, "root@server:/volumes/swimtracker-update"])
os.unlink(firmware_file) os.unlink(firmware_file)
os.unlink(version_file_name) os.unlink(version_file_name)