[beken-72xx] Generate UF2 firmware images

This commit is contained in:
Kuba Szczodrzyński
2022-06-23 13:32:31 +02:00
parent 94e8b9f87e
commit 236e9ccda6
5 changed files with 108 additions and 17 deletions

View File

@@ -552,6 +552,12 @@ env.Replace(
SIZEPRINTCMD="$SIZETOOL -B -d $SOURCES",
)
# Calculate RBL header offset
app_offs = int(env["FLASH_APP_OFFSET"], 16)
app_size = int(board.get("build.bkrbl_size_app"), 16)
rbl_offs = int(app_size // 32 * 34) - 102
env.Replace(FLASH_RBL_OFFSET=f"0x{app_offs + rbl_offs:06X}")
# Build all libraries
env.BuildLibraries()
@@ -559,4 +565,21 @@ env.BuildLibraries()
env.Replace(
# linker command (encryption + packaging)
LINK="${LINK2BIN} ${VARIANT} '' ''",
# UF2OTA input list
UF2OTA=[
# app binary image (enc+crc), OTA1 (uploader) only
(
"app",
"${BUILD_DIR}/${MCULC}_app_${FLASH_APP_OFFSET}.crc",
"",
"",
),
# app RBL header (crc), OTA1 (uploader) only
(
f"app+{rbl_offs}",
"${BUILD_DIR}/${MCULC}_app_${FLASH_RBL_OFFSET}.rblh",
"", # not used for OTA2
"",
),
],
)

View File

@@ -32,6 +32,7 @@ def env_add_defaults(env, platform, board):
LDSCRIPT_PATH=["${LDSCRIPT_SDK}"],
# Board config variables
MCU=board.get("build.mcu").upper(),
MCULC=board.get("build.mcu"),
VARIANT=board.get("build.variant"),
LDSCRIPT_SDK=board.get("build.ldscript_sdk"),
LDSCRIPT_ARDUINO=board.get("build.ldscript_arduino"),

View File

@@ -5,7 +5,7 @@ from os import stat
from os.path import basename
from typing import Tuple
from tools.util.bkutil import RBL, BekenBinary
from tools.util.bkutil import RBL, BekenBinary, DataType
from tools.util.fileio import chext, chname, isnewer, writebin, writejson
from tools.util.models import Family
from tools.util.obj import get
@@ -31,9 +31,10 @@ def elf2bin_bk72xx(
app_addr = nmap["_vector_start"]
app_offs = calc_offset(app_addr)
app_size = int(rbl_size, 16)
rbl_offs = app_offs
# build output name
output = chname(input, f"{mcu}_app_0x{app_offs:06X}.bin")
output = chname(input, f"{mcu}_app_0x{app_offs:06X}.rbl")
fw_bin = chext(input, "bin")
# print graph element
print(f"| |-- {basename(output)}")
@@ -53,5 +54,42 @@ def elf2bin_bk72xx(
fw_size = stat(fw_bin).st_size
raw = open(fw_bin, "rb")
out = open(output, "wb")
for data in bk.package(raw, app_addr, fw_size, rbl):
# open encrypted+CRC binary output
out_crc = chname(input, f"{mcu}_app_0x{app_offs:06X}.crc")
print(f"| |-- {basename(out_crc)}")
crc = open(out_crc, "wb")
# get partial (type, bytes) data generator
package_gen = bk.package(raw, app_addr, fw_size, rbl, partial=True)
# write all BINARY blocks
for data_type, data in package_gen:
if data_type != DataType.BINARY:
break
out.write(data)
crc.write(data)
rbl_offs += len(data)
# skip PADDING_SIZE bytes for RBL header, write it to main output
if data_type == DataType.PADDING_SIZE:
out.write(b"\xff" * data)
rbl_offs += data
# open RBL header output
out_rblh = chname(input, f"{mcu}_app_0x{rbl_offs:06X}.rblh")
print(f"| |-- {basename(out_rblh)}")
rblh = open(out_rblh, "wb")
# write all RBL blocks
for data_type, data in package_gen:
if data_type != DataType.RBL:
break
out.write(data)
rblh.write(data)
# close all files
raw.close()
out.close()
crc.close()
rblh.close()

View File

@@ -91,19 +91,19 @@ class Input:
if input[0] and input[1]:
if "+" in input[0]:
(self.ota1_part, self.ota1_offs) = input[0].split("+")
self.ota1_offs = int(self.ota1_offs, 16)
self.ota1_offs = int(self.ota1_offs, 0)
else:
self.ota1_part = input[0]
self.ota1_file = input[1]
if input[2] and input[3]:
if "+" in input[2]:
(self.ota2_part, self.ota2_offs) = input[2].split("+")
self.ota2_offs = int(self.ota2_offs, 16)
self.ota2_offs = int(self.ota2_offs, 0)
else:
self.ota2_part = input[2]
self.ota2_file = input[3]
if self.ota1_offs != self.ota2_offs:
if self.ota1_file and self.ota2_file and self.ota1_offs != self.ota2_offs:
# currently, offsets cannot differ when storing images
# (this would require to actually store it twice)
raise ValueError(f"Offsets cannot differ ({self.ota1_file})")

View File

@@ -8,12 +8,12 @@ sys.path.append(join(dirname(__file__), "..", ".."))
from argparse import ArgumentParser, FileType
from binascii import crc32
from dataclasses import dataclass, field
from enum import IntFlag
from enum import Enum, IntFlag
from io import SEEK_SET, FileIO
from os import stat
from struct import Struct
from time import time
from typing import Union
from typing import Generator, Tuple, Union
from tools.util.bitint import BitInt
from tools.util.bkcrypto import BekenCrypto
@@ -34,6 +34,17 @@ from tools.util.intbin import (
)
class DataType(Enum):
BINARY = "BINARY"
PADDING_SIZE = "PADDING_SIZE"
RBL = "RBL"
DataTuple = Tuple[DataType, Union[bytes, int]]
DataUnion = Union[bytes, DataTuple]
DataGenerator = Generator[DataUnion, None, None]
class OTAAlgorithm(IntFlag):
NONE = 0
CRYPT_XOR = 1
@@ -125,11 +136,14 @@ class BekenBinary:
coeffs = list(map(BitInt, map(betoint, biniter(coeffs, 4))))
self.crypto = BekenCrypto(coeffs)
def crc(self, data: ByteGenerator) -> ByteGenerator:
def crc(self, data: ByteGenerator, type: DataType = None) -> DataGenerator:
for block in geniter(data, 32):
crc = CRC16.CMS.calc(block)
yield block
yield inttobe16(crc)
block += inttobe16(crc)
if type:
yield (type, block)
else:
yield block
def uncrc(self, data: ByteGenerator, check: bool = True) -> ByteGenerator:
for block in geniter(data, 34):
@@ -149,11 +163,23 @@ class BekenBinary:
yield word
addr += 4
def package(self, f: FileIO, addr: int, size: int, rbl: RBL) -> ByteGenerator:
def package(
self,
f: FileIO,
addr: int,
size: int,
rbl: RBL,
partial: bool = False,
) -> DataGenerator:
if not rbl.container_size:
raise ValueError("RBL must have a total size when packaging")
crc_total = 0
# yield all data as (type, bytes) tuples, if partial mode enabled
type_binary = DataType.BINARY if partial else None
type_padding = DataType.PADDING_SIZE if partial else None
type_rbl = DataType.RBL if partial else None
# when to stop reading input data
data_end = size
if rbl.has_part_table:
@@ -169,7 +195,7 @@ class BekenBinary:
# iterate over encrypted 32-byte blocks
for block in geniter(data_crypt_gen, 32):
# add CRC16 and yield
yield from self.crc(block)
yield from self.crc(block, type_binary)
crc_total += 2
rbl.update(block)
@@ -188,16 +214,19 @@ class BekenBinary:
# add last padding with normal values
buf += b"\xff" * 16
# yield the temporary buffer
yield from self.crc(buf)
yield from self.crc(buf, type_binary)
crc_total += 2 * (len(buf) // 32)
# pad the entire container with 0xFF, excluding RBL and its CRC16
pad_size = pad_up(rbl.data_size + crc_total, rbl.container_size_crc) - 102
for _ in range(pad_size):
yield b"\xff"
if type_padding:
yield (type_padding, pad_size)
else:
for _ in range(pad_size):
yield b"\xff"
# yield RBL with CRC16
yield from self.crc(rbl.serialize())
yield from self.crc(rbl.serialize(), type_rbl)
def auto_int(x):