41 lines
1.9 KiB
Python
41 lines
1.9 KiB
Python
"""Portable, read-only TMS firmware verification against an immutable BIN."""
|
|
from protocan.tms2812 import build_upload_request, decode_upload_reply
|
|
from .bin_compare import compare_sha256
|
|
|
|
|
|
class TmsFirmwareCheck:
|
|
def __init__(self, controller, word_address, image, block_size=256):
|
|
self.image = bytes(image)
|
|
if not 1 <= controller <= 255:
|
|
raise ValueError("Для проверки нужен адрес контроллера 1..255")
|
|
if not self.image or len(self.image) > 4 * 1024 * 1024:
|
|
raise ValueError("Размер BIN должен быть 1..4194304 байт")
|
|
if not 0 <= word_address <= 0xFFFFFFFF or word_address + (len(self.image) + 1) // 2 > 0x100000000:
|
|
raise ValueError("Диапазон памяти вне 32-битного адресного пространства")
|
|
if not 2 <= block_size <= 65534 or block_size % 2:
|
|
raise ValueError("Размер блока должен быть чётным: 2..65534 байт")
|
|
self.controller, self.word_address = controller, word_address
|
|
self.block_size = block_size
|
|
self.readback = bytearray()
|
|
|
|
@property
|
|
def done(self):
|
|
return len(self.readback) == len(self.image)
|
|
|
|
@property
|
|
def count(self):
|
|
return min(self.block_size, len(self.image) - len(self.readback))
|
|
|
|
def request(self):
|
|
if self.done:
|
|
raise ValueError("Проверка уже завершена")
|
|
return build_upload_request(self.controller, self.word_address + len(self.readback) // 2, self.count)
|
|
|
|
def accept(self, reply):
|
|
if self.done:
|
|
raise ValueError("Проверка уже завершена")
|
|
self.readback.extend(decode_upload_reply(reply, self.controller, self.count))
|
|
|
|
def result(self):
|
|
return compare_sha256(self.image, bytes(self.readback))
|