Skip to content

Commit 221e186

Browse files
committed
src/snagrecover/protocols/rockchip.py: Add rockchip maskrom support
Add support for uploading blods to the maskrom memory using Rockchip maskrom protocol. Signed-off-by: Arnaud Patard <[email protected]>
1 parent 7853615 commit 221e186

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# Copyright 2025 Collabora Ltd.
2+
#
3+
# SPDX-License-Identifier: GPL-2.0+
4+
#
5+
# Author: Arnaud Patard <[email protected]>
6+
7+
8+
from crccheck.crc import Crc16Ibm3740
9+
import logging
10+
import usb
11+
12+
from snagrecover import utils
13+
14+
logger = logging.getLogger("snagrecover")
15+
16+
17+
class RochipBootRomError(Exception):
18+
pass
19+
20+
class RochipBootRom():
21+
def __init__(self, dev: usb.core.Device):
22+
self.dev = dev
23+
cfg = dev.get_active_configuration()
24+
25+
eps_found = False
26+
for intf in cfg.interfaces():
27+
ep_in, ep_out = None, None
28+
for ep in intf.endpoints():
29+
is_bulk = (ep.bmAttributes & usb.ENDPOINT_TYPE_MASK) == usb.ENDPOINT_TYPE_BULK
30+
is_in = (ep.bmAttributes & usb.ENDPOINT_TYPE_MASK) == usb.ENDPOINT_TYPE_BULK
31+
if not is_bulk:
32+
continue
33+
is_in = (ep.bEndpointAddress & usb.ENDPOINT_DIR_MASK) == usb.ENDPOINT_IN
34+
if is_in:
35+
ep_in = ep.bEndpointAddress
36+
else:
37+
ep_out = ep.bEndpointAddress
38+
if not ((ep_in is None) or (ep_out is None)):
39+
eps_found = True
40+
break
41+
if not eps_found:
42+
raise RochipBootRomError("No BULK IN/OUT endpoint pair found in device")
43+
self.ep_in = ep_in
44+
self.ep_out = ep_out
45+
46+
def __write_chunk(self, addr: int, chunk: bytes) -> bool:
47+
logger.debug(f"Sending {len(chunk)} bytes")
48+
return self.dev.ctrl_transfer(0x40, 0x0c, 0, addr, chunk)
49+
50+
def write_blob(self, blob: bytes, addr: int) -> bool:
51+
if addr != 0x471 and addr != 0x472:
52+
raise RochipBootRomError("Invalid address. Can only be 471 or 472")
53+
crc = Crc16Ibm3740()
54+
total_written = 0
55+
crc_sent = False
56+
for chunk in utils.dnload_iter(blob, 4096):
57+
chunk_len = len(chunk)
58+
if chunk_len == 4096:
59+
crc.process(chunk)
60+
elif chunk_len == 4095:
61+
chunk.append(0x00)
62+
crc.process(chunk)
63+
else:
64+
crc.process(chunk)
65+
crcbytes = crc.final()
66+
chunk = bytearray(chunk)
67+
chunk.append(crcbytes >> 8)
68+
chunk.append(crcbytes & 0xff)
69+
crc_sent = True
70+
written = self.__write_chunk(addr, chunk)
71+
ret = written == len(chunk)
72+
if ret is False:
73+
return ret
74+
total_written += written
75+
if chunk_len+2 == 4096:
76+
chunk = [0x00]
77+
written = self.__write_chunk(addr, chunk)
78+
ret = written == len(chunk)
79+
if ret is False:
80+
return ret
81+
if crc_sent is False:
82+
chunk = bytearray()
83+
crcbytes = crc.final()
84+
chunk.append(crcbytes >> 8)
85+
chunk.append(crcbytes & 0xff)
86+
written = self.__write_chunk(addr, chunk)
87+
ret = written == len(chunk)
88+
if ret is False:
89+
return ret
90+
91+
return True

0 commit comments

Comments
 (0)