Skip to content

Commit d011ad1

Browse files
committed
RKUSBMaskromDriver: add support for using vendor loader images
Add support for using vendor loader image files, typically created using the vendor boot_merger tool in the rkbin repo. Signed-off-by: Jonas Karlman <[email protected]>
1 parent 13af276 commit d011ad1

File tree

3 files changed

+113
-15
lines changed

3 files changed

+113
-15
lines changed

doc/configuration.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2670,7 +2670,8 @@ Arguments:
26702670
- initial (str): optional, key in :ref:`images <labgrid-device-config-images>` containing the path
26712671
of an image that typically initializes DRAM of the target
26722672
- image (str): optional, key in :ref:`images <labgrid-device-config-images>` containing the path
2673-
of a bootloader image to load to start of DRAM, or to SRAM when an initial image is unused
2673+
of a bootloader image to load to start of DRAM, or to SRAM when an initial image is unused, or
2674+
the path to a vendor loader image typically created using the vendor boot_merger tool
26742675

26752676
UUUDriver
26762677
~~~~~~~~~

labgrid/util/agents/rkusbmaskrom.py

Lines changed: 104 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
that typically initializes DRAM, followed by optionally loading a secondary
44
image to start of DRAM, when a Rockchip device is in MASKROM mode.
55
"""
6+
from collections import namedtuple
7+
from struct import unpack
68
from time import sleep
79

810
import usb.core
@@ -52,12 +54,55 @@
5254
]
5355

5456

57+
# polynomial: 0x04c10db7
58+
CRC32_TABLE = [
59+
0x00000000, 0x04c10db7, 0x09821b6e, 0x0d4316d9, 0x130436dc, 0x17c53b6b, 0x1a862db2, 0x1e472005,
60+
0x26086db8, 0x22c9600f, 0x2f8a76d6, 0x2b4b7b61, 0x350c5b64, 0x31cd56d3, 0x3c8e400a, 0x384f4dbd,
61+
0x4c10db70, 0x48d1d6c7, 0x4592c01e, 0x4153cda9, 0x5f14edac, 0x5bd5e01b, 0x5696f6c2, 0x5257fb75,
62+
0x6a18b6c8, 0x6ed9bb7f, 0x639aada6, 0x675ba011, 0x791c8014, 0x7ddd8da3, 0x709e9b7a, 0x745f96cd,
63+
0x9821b6e0, 0x9ce0bb57, 0x91a3ad8e, 0x9562a039, 0x8b25803c, 0x8fe48d8b, 0x82a79b52, 0x866696e5,
64+
0xbe29db58, 0xbae8d6ef, 0xb7abc036, 0xb36acd81, 0xad2ded84, 0xa9ece033, 0xa4aff6ea, 0xa06efb5d,
65+
0xd4316d90, 0xd0f06027, 0xddb376fe, 0xd9727b49, 0xc7355b4c, 0xc3f456fb, 0xceb74022, 0xca764d95,
66+
0xf2390028, 0xf6f80d9f, 0xfbbb1b46, 0xff7a16f1, 0xe13d36f4, 0xe5fc3b43, 0xe8bf2d9a, 0xec7e202d,
67+
0x34826077, 0x30436dc0, 0x3d007b19, 0x39c176ae, 0x278656ab, 0x23475b1c, 0x2e044dc5, 0x2ac54072,
68+
0x128a0dcf, 0x164b0078, 0x1b0816a1, 0x1fc91b16, 0x018e3b13, 0x054f36a4, 0x080c207d, 0x0ccd2dca,
69+
0x7892bb07, 0x7c53b6b0, 0x7110a069, 0x75d1adde, 0x6b968ddb, 0x6f57806c, 0x621496b5, 0x66d59b02,
70+
0x5e9ad6bf, 0x5a5bdb08, 0x5718cdd1, 0x53d9c066, 0x4d9ee063, 0x495fedd4, 0x441cfb0d, 0x40ddf6ba,
71+
0xaca3d697, 0xa862db20, 0xa521cdf9, 0xa1e0c04e, 0xbfa7e04b, 0xbb66edfc, 0xb625fb25, 0xb2e4f692,
72+
0x8aabbb2f, 0x8e6ab698, 0x8329a041, 0x87e8adf6, 0x99af8df3, 0x9d6e8044, 0x902d969d, 0x94ec9b2a,
73+
0xe0b30de7, 0xe4720050, 0xe9311689, 0xedf01b3e, 0xf3b73b3b, 0xf776368c, 0xfa352055, 0xfef42de2,
74+
0xc6bb605f, 0xc27a6de8, 0xcf397b31, 0xcbf87686, 0xd5bf5683, 0xd17e5b34, 0xdc3d4ded, 0xd8fc405a,
75+
0x6904c0ee, 0x6dc5cd59, 0x6086db80, 0x6447d637, 0x7a00f632, 0x7ec1fb85, 0x7382ed5c, 0x7743e0eb,
76+
0x4f0cad56, 0x4bcda0e1, 0x468eb638, 0x424fbb8f, 0x5c089b8a, 0x58c9963d, 0x558a80e4, 0x514b8d53,
77+
0x25141b9e, 0x21d51629, 0x2c9600f0, 0x28570d47, 0x36102d42, 0x32d120f5, 0x3f92362c, 0x3b533b9b,
78+
0x031c7626, 0x07dd7b91, 0x0a9e6d48, 0x0e5f60ff, 0x101840fa, 0x14d94d4d, 0x199a5b94, 0x1d5b5623,
79+
0xf125760e, 0xf5e47bb9, 0xf8a76d60, 0xfc6660d7, 0xe22140d2, 0xe6e04d65, 0xeba35bbc, 0xef62560b,
80+
0xd72d1bb6, 0xd3ec1601, 0xdeaf00d8, 0xda6e0d6f, 0xc4292d6a, 0xc0e820dd, 0xcdab3604, 0xc96a3bb3,
81+
0xbd35ad7e, 0xb9f4a0c9, 0xb4b7b610, 0xb076bba7, 0xae319ba2, 0xaaf09615, 0xa7b380cc, 0xa3728d7b,
82+
0x9b3dc0c6, 0x9ffccd71, 0x92bfdba8, 0x967ed61f, 0x8839f61a, 0x8cf8fbad, 0x81bbed74, 0x857ae0c3,
83+
0x5d86a099, 0x5947ad2e, 0x5404bbf7, 0x50c5b640, 0x4e829645, 0x4a439bf2, 0x47008d2b, 0x43c1809c,
84+
0x7b8ecd21, 0x7f4fc096, 0x720cd64f, 0x76cddbf8, 0x688afbfd, 0x6c4bf64a, 0x6108e093, 0x65c9ed24,
85+
0x11967be9, 0x1557765e, 0x18146087, 0x1cd56d30, 0x02924d35, 0x06534082, 0x0b10565b, 0x0fd15bec,
86+
0x379e1651, 0x335f1be6, 0x3e1c0d3f, 0x3add0088, 0x249a208d, 0x205b2d3a, 0x2d183be3, 0x29d93654,
87+
0xc5a71679, 0xc1661bce, 0xcc250d17, 0xc8e400a0, 0xd6a320a5, 0xd2622d12, 0xdf213bcb, 0xdbe0367c,
88+
0xe3af7bc1, 0xe76e7676, 0xea2d60af, 0xeeec6d18, 0xf0ab4d1d, 0xf46a40aa, 0xf9295673, 0xfde85bc4,
89+
0x89b7cd09, 0x8d76c0be, 0x8035d667, 0x84f4dbd0, 0x9ab3fbd5, 0x9e72f662, 0x9331e0bb, 0x97f0ed0c,
90+
0xafbfa0b1, 0xab7ead06, 0xa63dbbdf, 0xa2fcb668, 0xbcbb966d, 0xb87a9bda, 0xb5398d03, 0xb1f880b4,
91+
]
92+
93+
5594
def crc16_ccitt_false(data, crc=0xffff):
5695
for byte in data:
5796
crc = ((crc << 8) & 0xff00) ^ CRC16_TABLE[((crc >> 8) & 0xff) ^ byte]
5897
return crc & 0xffff
5998

6099

100+
def crc32_rkboot(data, crc=0x0):
101+
for byte in data:
102+
crc = ((crc << 8) & 0xffffff00) ^ CRC32_TABLE[((crc >> 24) & 0xff) ^ byte]
103+
return crc & 0xffffffff
104+
105+
61106
def rc4_ksa(key):
62107
keylength = len(key)
63108
S = list(range(256))
@@ -79,6 +124,37 @@ def rc4_prga(S):
79124
yield K
80125

81126

127+
def prase_rkboot_header(data):
128+
RKBootHeader = namedtuple('RKBootHeader', [
129+
'tag', 'size', 'version', 'mergerVersion',
130+
'code471Num', 'code471Offset', 'code471Size',
131+
'code472Num', 'code472Offset', 'code472Size',
132+
])
133+
tag = int.from_bytes(data[0:4], 'little')
134+
if tag in (0x544f4f42, 0x2052444c) and \
135+
crc32_rkboot(data[0:-4]) == int.from_bytes(data[-4:], 'little'):
136+
header = RKBootHeader._make(unpack('<LHLL11xBLBBLB65x', data[0:102]))
137+
if header.code471Num + header.code472Num > 0:
138+
return header
139+
return None
140+
141+
142+
def get_rkboot_entries(data, header):
143+
RKBootEntry = namedtuple('RKBootEntry', [
144+
'size', 'type', 'dataOffset', 'dataSize', 'dataDelay',
145+
])
146+
for code in (0x471, 0x472):
147+
entries = getattr(header, f'code{code:x}Num')
148+
offset = getattr(header, f'code{code:x}Offset')
149+
size = getattr(header, f'code{code:x}Size')
150+
for _ in range(entries):
151+
header_data = data[offset:offset + size]
152+
entry = RKBootEntry._make(unpack('<BL40xLLL', header_data))
153+
entry_data = data[entry.dataOffset:entry.dataOffset + entry.dataSize]
154+
yield code, entry_data, entry.dataDelay / 1000
155+
offset += size
156+
157+
82158
class RKUSBMaskrom:
83159
def __init__(self, **args):
84160
self._dev = usb.core.find(**args)
@@ -99,14 +175,17 @@ def __exit__(self, exc_type, exc_value, traceback):
99175
usb.util.release_interface(self._dev, 0)
100176
usb.util.dispose_resources(self._dev)
101177

102-
def load(self, code, path):
103-
with open(path, 'rb') as fh:
104-
data = bytearray(fh.read())
178+
def load(self, code, bytesOrPath):
179+
if isinstance(bytesOrPath, bytes):
180+
data = bytearray(bytesOrPath)
181+
else:
182+
with open(bytesOrPath, 'rb') as fh:
183+
data = bytearray(fh.read())
105184

106-
# encrypt data using the known rockchip key for older devices
107-
if self._dev.idProduct < 0x3500:
108-
keystream = rc4_prga(rc4_ksa(RK_RC4_KEY))
109-
data = bytearray([byte ^ next(keystream) for byte in data])
185+
# encrypt data using the known rockchip key for older devices
186+
if self._dev.idProduct < 0x3500:
187+
keystream = rc4_prga(rc4_ksa(RK_RC4_KEY))
188+
data = bytearray([byte ^ next(keystream) for byte in data])
110189

111190
# ensure crc16 fit in the last chunk
112191
if len(data) % 4096 == 4095:
@@ -128,12 +207,25 @@ def load(self, code, path):
128207

129208

130209
def handle_load(busnum, devnum, initial, secondary=None, delay=None):
210+
with open(initial, 'rb') as fh:
211+
data = fh.read()
212+
header = prase_rkboot_header(data)
213+
if header is None and secondary is not None:
214+
with open(secondary, 'rb') as fh:
215+
data = fh.read()
216+
header = prase_rkboot_header(data)
131217
with RKUSBMaskrom(bus=busnum, address=devnum) as maskrom:
132-
maskrom.load(0x471, initial)
133-
if secondary is not None:
134-
if delay:
135-
sleep(delay)
136-
maskrom.load(0x472, secondary)
218+
if header is not None:
219+
for code, entry_data, entry_delay in get_rkboot_entries(data, header):
220+
maskrom.load(code, entry_data)
221+
if entry_delay:
222+
sleep(entry_delay)
223+
else:
224+
maskrom.load(0x471, initial)
225+
if secondary is not None:
226+
if delay:
227+
sleep(delay)
228+
maskrom.load(0x472, secondary)
137229

138230

139231
methods = {

tests/test_rkusbmaskromagent.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1-
from labgrid.util.agents.rkusbmaskrom import (crc16_ccitt_false, rc4_ksa,
2-
rc4_prga)
1+
from labgrid.util.agents.rkusbmaskrom import (crc16_ccitt_false, crc32_rkboot,
2+
rc4_ksa, rc4_prga)
33

44

55
def test_crc16_ccitt_false():
66
crc = crc16_ccitt_false("123456789".encode())
77
assert crc == 0x29b1
88

99

10+
def test_crc32_rkboot():
11+
crc = crc32_rkboot("123456789".encode())
12+
assert crc == 0x889a9615
13+
14+
1015
def test_rc4_keystream():
1116
# from RFC 6229: Test Vectors for the Stream Cipher RC4
1217
key = list(bytes.fromhex("1ada31d5cf688221c109163908ebe51debb46227c6cc8b37641910833222772a"))

0 commit comments

Comments
 (0)