[tools] uf2ota: fix for Python 3.7, fix Windows path compatibility

This commit is contained in:
Kuba Szczodrzyński
2022-06-02 14:09:16 +02:00
parent 81897e634c
commit 79a701a4d4
6 changed files with 26 additions and 23 deletions

View File

@@ -12,12 +12,12 @@ Some CPUs support dual-OTA schemes: firmware runs from one image, while the othe
Each firmware image may be either applicable:
1. only when flashing OTA1 (`part:file::`)
2. only when flashing OTA2 (`::part:file`)
3. for both schemes to a single partition (`part:file`)
4. for both schemes but different partitions (`part1:file:part2:file`)
5. for both schemes but with a different binary (`part:file1:part:file2`)
6. for both schemes, with different binaries and target partitions (`part1:file1:part2:file2`)
1. only when flashing OTA1 (`part;file;;`)
2. only when flashing OTA2 (`;;part;file`)
3. for both schemes to a single partition (`part;file`)
4. for both schemes but different partitions (`part1;file;part2;file`)
5. for both schemes but with a different binary (`part;file1;part;file2`)
6. for both schemes, with different binaries and target partitions (`part1;file1;part2;file2`)
\* *`part` means partition here*

View File

@@ -13,7 +13,7 @@ uf2ota: error: the following arguments are required: action, inputs
Generate a UF2 file from a firmware image or several images.
```bash
$ python uf2ota.py write --family RTL8710B --board wr3 --version 0.4.0 --fw esphome:2022.6.0-dev ota1:xip1.bin:ota2:xip2.bin
$ python uf2ota.py write --family RTL8710B --board wr3 --version 0.4.0 --fw esphome:2022.6.0-dev "ota1;xip1.bin;ota2;xip2.bin"
$ ls -l out.uf2
-rw-r--r-- 1 Kuba None 605696 May 28 14:35 out.uf2
@@ -21,15 +21,15 @@ $ ls -l out.uf2
## inputs format
Format for `inputs` parameter is `part:file[:part:file]` (square brackets mean optional). First two (colon separated) values correspond to flashing OTA1 region, second two to OTA2.
Format for `inputs` parameter is `part;file[;part;file]` (square brackets mean optional). First two (colon separated) values correspond to flashing OTA1 region, second two to OTA2.
Partition name can be suffixed by `+offset`, which causes writing the image file to the partition after some byte offset. Both files and/or partition names can be equal. Values can be empty (like `part:file::` or `::part:file`) if OTA1/2 images are not present in this file.
Partition name can be suffixed by `+offset`, which causes writing the image file to the partition after some byte offset. Both files and/or partition names can be equal. Values can be empty (like `part;file;;` or `;;part;file`) if OTA1/2 images are not present in this file.
When using two different firmware binaries, they need to have the same `offset` and be of the same size.
`inputs` parameter can be repeated in order to embed multiple files in the UF2. For example:
```
bootloader:boot.bin ota1:xip1.bin:ota2:xip2.bin config:config1.bin:config:config2.bin
```bash
"bootloader;boot.bin" "ota1;xip1.bin;ota2;xip2.bin" "config;config1.bin;config;config2.bin"
```
will:
- flash the bootloader in both OTA schemes

View File

@@ -129,11 +129,11 @@ class Input:
ota2_file: str = None
def __init__(self, input: str) -> None:
input = input.split(":")
input = input.split(";")
n = len(input)
if n not in [2, 4]:
raise ValueError(
"Incorrect input format - should be part+offs:file[:part+offs:file]"
"Incorrect input format - should be part+offs;file[;part+offs;file]"
)
# just spread the same image twice for single-OTA scheme
if n == 2:

View File

@@ -60,7 +60,7 @@ class UF2:
while True:
data = self.f.read(512)
if len(data) not in [0, 512]:
print(f"Block size invalid ({len(data)=})")
print(f"Block size invalid ({len(data)})")
return False
if not len(data):
break
@@ -69,7 +69,7 @@ class UF2:
return False
if self.family != Family.INVALID and self.family != block.family:
print(f"Mismatched family ({self.family=} != {block.family=})")
print(f"Mismatched family ({self.family} != {block.family})")
return False
self.family = block.family

View File

@@ -68,19 +68,19 @@ class Block:
def decode(self, data: bytes) -> bool:
# check block size
if len(data) != 512:
print(f"Invalid block size ({len(data)=})")
print(f"Invalid block size ({len(data)})")
return False
# check Magic 1
if letoint(data[0:4]) != 0x0A324655:
print(f"Invalid Magic 1 ({data[0:4]=})")
print(f"Invalid Magic 1 ({data[0:4]})")
return False
# check Magic 2
if letoint(data[4:8]) != 0x9E5D5157:
print(f"Invalid Magic 2 ({data[4:8]=})")
print(f"Invalid Magic 2 ({data[4:8]})")
return False
# check Magic 3
if letoint(data[508:512]) != 0x0AB16F30:
print(f"Invalid Magic 13({data[508:512]=})")
print(f"Invalid Magic 13({data[508:512]})")
return False
self.flags.decode(letoint(data[8:12]))
@@ -134,4 +134,4 @@ class Block:
file_size = self.file_size
family = self.family.name
tags = [(k.name, v) for k, v in self.tags.items()]
return f"Block[{block_seq}/{block_count}]({flags=}, {address=}, {length=}, {file_size=}, {family=}, {tags=})"
return f"Block[{block_seq}/{block_count}](flags={flags}, address={address}, length={length}, file_size={file_size}, family={family}, tags={tags})"

View File

@@ -61,9 +61,12 @@ def cli():
uf2.put_str(Tag.LT_VERSION, args.version)
if args.fw:
(fw_name, fw_ver) = args.fw.split(":")
uf2.put_str(Tag.FIRMWARE, fw_name)
uf2.put_str(Tag.VERSION, fw_ver)
if ":" in args.fw:
(fw_name, fw_ver) = args.fw.split(":")
uf2.put_str(Tag.FIRMWARE, fw_name)
uf2.put_str(Tag.VERSION, fw_ver)
else:
uf2.put_str(Tag.FIRMWARE, args.fw)
uf2.put_int8(Tag.OTA_VERSION, 1)
uf2.put_str(Tag.DEVICE, "LibreTuya")