mirror of
https://github.com/saymrwulf/xous-core.git
synced 2026-11-04 04:27:34 +00:00
make usb_update.py appear only once in the tree
This commit is contained in:
parent
47ce1e3149
commit
796256cfb0
1 changed files with 1 additions and 739 deletions
|
|
@ -1,739 +0,0 @@
|
|||
#! /usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
|
||||
import usb.core
|
||||
import usb.util
|
||||
import array
|
||||
import sys
|
||||
import hashlib
|
||||
import csv
|
||||
import urllib.request
|
||||
|
||||
from progressbar.bar import ProgressBar
|
||||
|
||||
class PrecursorUsb:
|
||||
def __init__(self, dev):
|
||||
self.dev = dev
|
||||
self.RDSR = 0x05
|
||||
self.RDSCUR = 0x2B
|
||||
self.RDID = 0x9F
|
||||
self.WREN = 0x06
|
||||
self.WRDI = 0x04
|
||||
self.SE4B = 0x21
|
||||
self.BE4B = 0xDC
|
||||
self.PP4B = 0x12
|
||||
self.registers = {}
|
||||
self.regions = {}
|
||||
self.gitrev = ''
|
||||
|
||||
def register(self, name):
|
||||
return int(self.registers[name], 0)
|
||||
|
||||
def peek(self, addr, display=False):
|
||||
_dummy_s = '\x00'.encode('utf-8')
|
||||
data = array.array('B', _dummy_s * 4)
|
||||
|
||||
numread = self.dev.ctrl_transfer(bmRequestType=(0x80 | 0x43), bRequest=0,
|
||||
wValue=(addr & 0xffff), wIndex=((addr >> 16) & 0xffff),
|
||||
data_or_wLength=data, timeout=500)
|
||||
|
||||
read_data = int.from_bytes(data.tobytes(), byteorder='little', signed=False)
|
||||
if display == True:
|
||||
print("0x{:08x}".format(read_data))
|
||||
return read_data
|
||||
|
||||
def poke(self, addr, wdata, check=False, display=False):
|
||||
if check == True:
|
||||
_dummy_s = '\x00'.encode('utf-8')
|
||||
data = array.array('B', _dummy_s * 4)
|
||||
|
||||
numread = self.dev.ctrl_transfer(bmRequestType=(0x80 | 0x43), bRequest=0,
|
||||
wValue=(addr & 0xffff), wIndex=((addr >> 16) & 0xffff),
|
||||
data_or_wLength=data, timeout=500)
|
||||
|
||||
read_data = int.from_bytes(data.tobytes(), byteorder='little', signed=False)
|
||||
print("before poke: 0x{:08x}".format(read_data))
|
||||
|
||||
data = array.array('B', wdata.to_bytes(4, 'little'))
|
||||
numwritten = self.dev.ctrl_transfer(bmRequestType=(0x00 | 0x43), bRequest=0,
|
||||
wValue=(addr & 0xffff), wIndex=((addr >> 16) & 0xffff),
|
||||
data_or_wLength=data, timeout=500)
|
||||
|
||||
if check == True:
|
||||
_dummy_s = '\x00'.encode('utf-8')
|
||||
data = array.array('B', _dummy_s * 4)
|
||||
|
||||
numread = self.dev.ctrl_transfer(bmRequestType=(0x80 | 0x43), bRequest=0,
|
||||
wValue=(addr & 0xffff), wIndex=((addr >> 16) & 0xffff),
|
||||
data_or_wLength=data, timeout=500)
|
||||
|
||||
read_data = int.from_bytes(data.tobytes(), byteorder='little', signed=False)
|
||||
print("after poke: 0x{:08x}".format(read_data))
|
||||
if display == True:
|
||||
print("wrote 0x{:08x} to 0x{:08x}".format(wdata, addr))
|
||||
|
||||
def burst_read(self, addr, len):
|
||||
_dummy_s = '\x00'.encode('utf-8')
|
||||
maxlen = 4096
|
||||
|
||||
ret = bytearray()
|
||||
packet_count = len // maxlen
|
||||
if (len % maxlen) != 0:
|
||||
packet_count += 1
|
||||
|
||||
for pkt_num in range(packet_count):
|
||||
cur_addr = addr + pkt_num * maxlen
|
||||
if pkt_num == packet_count - 1:
|
||||
if len % maxlen != 0:
|
||||
bufsize = len % maxlen
|
||||
else:
|
||||
bufsize = maxlen
|
||||
else:
|
||||
bufsize = maxlen
|
||||
|
||||
data = array.array('B', _dummy_s * bufsize)
|
||||
numread = self.dev.ctrl_transfer(bmRequestType=(0x80 | 0x43), bRequest=0,
|
||||
wValue=(cur_addr & 0xffff), wIndex=((cur_addr >> 16) & 0xffff),
|
||||
data_or_wLength=data, timeout=500)
|
||||
|
||||
if numread != bufsize:
|
||||
print("Burst read error: {} bytes requested, {} bytes read at 0x{:08x}".format(bufsize, numread, cur_addr))
|
||||
exit(1)
|
||||
|
||||
ret = ret + data
|
||||
|
||||
return ret
|
||||
|
||||
def burst_write(self, addr, data):
|
||||
if len(data) == 0:
|
||||
return
|
||||
|
||||
# the actual "addr" doesn't matter for a burst_write, because it's specified
|
||||
# as an argument to the flash_pp4b command. We lock out access to the base of
|
||||
# SPINOR because it's part of the gateware, so, we pick a "safe" address to
|
||||
# write to instead. The page write responder will aggregate any write data
|
||||
# to anywhere in the SPINOR address range.
|
||||
writebuf_addr = 0x2098_0000 # the current start address of the kernel, for example
|
||||
|
||||
maxlen = 4096
|
||||
packet_count = len(data) // maxlen
|
||||
if (len(data) % maxlen) != 0:
|
||||
packet_count += 1
|
||||
|
||||
for pkt_num in range(packet_count):
|
||||
cur_addr = addr + pkt_num * maxlen
|
||||
if pkt_num == packet_count - 1:
|
||||
if len(data) % maxlen != 0:
|
||||
bufsize = len(data) % maxlen
|
||||
else:
|
||||
bufsize = maxlen
|
||||
else:
|
||||
bufsize = maxlen
|
||||
|
||||
wdata = array.array('B', data[(pkt_num * maxlen):(pkt_num * maxlen) + bufsize])
|
||||
numwritten = self.dev.ctrl_transfer(bmRequestType=(0x00 | 0x43), bRequest=0,
|
||||
# note use of writebuf_addr instead of cur_addr -> see comment above about the quirk of write addressing
|
||||
wValue=(writebuf_addr & 0xffff), wIndex=((writebuf_addr >> 16) & 0xffff),
|
||||
data_or_wLength=wdata, timeout=500)
|
||||
|
||||
if numwritten != bufsize:
|
||||
print("Burst write error: {} bytes requested, {} bytes written at 0x{:08x}".format(bufsize, numwritten, cur_addr))
|
||||
exit(1)
|
||||
|
||||
def ping_wdt(self):
|
||||
self.poke(self.register('wdt_watchdog'), 1, display=False)
|
||||
self.poke(self.register('wdt_watchdog'), 1, display=False)
|
||||
|
||||
def spinor_command_value(self, exec=0, lock_reads=0, cmd_code=0, dummy_cycles=0, data_words=0, has_arg=0):
|
||||
return ((exec & 1) << 1 |
|
||||
(lock_reads & 1) << 24 |
|
||||
(cmd_code & 0xff) << 2 |
|
||||
(dummy_cycles & 0x1f) << 11 |
|
||||
(data_words & 0xff) << 16 |
|
||||
(has_arg & 1) << 10
|
||||
)
|
||||
|
||||
def flash_rdsr(self, lock_reads):
|
||||
self.poke(self.register('spinor_cmd_arg'), 0)
|
||||
self.poke(self.register('spinor_command'),
|
||||
self.spinor_command_value(exec=1, lock_reads=lock_reads, cmd_code=self.RDSR, dummy_cycles=4, data_words=1, has_arg=1)
|
||||
)
|
||||
return self.peek(self.register('spinor_cmd_rbk_data'), display=False)
|
||||
|
||||
def flash_rdscur(self):
|
||||
self.poke(self.register('spinor_cmd_arg'), 0)
|
||||
self.poke(self.register('spinor_command'),
|
||||
self.spinor_command_value(exec=1, lock_reads=1, cmd_code=self.RDSCUR, dummy_cycles=4, data_words=1, has_arg=1)
|
||||
)
|
||||
return self.peek(self.register('spinor_cmd_rbk_data'), display=False)
|
||||
|
||||
def flash_rdid(self, offset):
|
||||
self.poke(self.register('spinor_cmd_arg'), 0)
|
||||
self.poke(self.register('spinor_command'),
|
||||
self.spinor_command_value(exec=1, cmd_code=self.RDID, dummy_cycles=4, data_words=offset, has_arg=1)
|
||||
)
|
||||
return self.peek(self.register('spinor_cmd_rbk_data'), display=False)
|
||||
|
||||
def flash_wren(self):
|
||||
self.poke(self.register('spinor_cmd_arg'), 0)
|
||||
self.poke(self.register('spinor_command'),
|
||||
self.spinor_command_value(exec=1, lock_reads=1, cmd_code=self.WREN)
|
||||
)
|
||||
|
||||
def flash_wrdi(self):
|
||||
self.poke(self.register('spinor_cmd_arg'), 0)
|
||||
self.poke(self.register('spinor_command'),
|
||||
self.spinor_command_value(exec=1, lock_reads=1, cmd_code=self.WRDI)
|
||||
)
|
||||
|
||||
def flash_se4b(self, sector_address):
|
||||
self.poke(self.register('spinor_cmd_arg'), sector_address)
|
||||
self.poke(self.register('spinor_command'),
|
||||
self.spinor_command_value(exec=1, lock_reads=1, cmd_code=self.SE4B, has_arg=1)
|
||||
)
|
||||
|
||||
def flash_be4b(self, block_address):
|
||||
self.poke(self.register('spinor_cmd_arg'), block_address)
|
||||
self.poke(self.register('spinor_command'),
|
||||
self.spinor_command_value(exec=1, lock_reads=1, cmd_code=self.BE4B, has_arg=1)
|
||||
)
|
||||
|
||||
def flash_pp4b(self, address, data_bytes):
|
||||
self.poke(self.register('spinor_cmd_arg'), address)
|
||||
self.poke(self.register('spinor_command'),
|
||||
self.spinor_command_value(exec=1, lock_reads=1, cmd_code=self.PP4B, has_arg=1, data_words=(data_bytes//2))
|
||||
)
|
||||
|
||||
def load_csrs(self, fname=None):
|
||||
LOC_CSRCSV = 0x20277000 # this address shouldn't change because it's how we figure out our version number
|
||||
# CSR extraction:
|
||||
# dd if=soc_csr.bin of=csr_data_0.9.6.bin skip=2524 count=32 bs=1024
|
||||
if fname == None:
|
||||
csr_data = self.burst_read(LOC_CSRCSV, 0x8000)
|
||||
else:
|
||||
with open(fname, "rb") as f:
|
||||
csr_data = f.read(0x8000)
|
||||
|
||||
hasher = hashlib.sha512()
|
||||
hasher.update(csr_data[:0x7FC0])
|
||||
digest = hasher.digest()
|
||||
if digest != csr_data[0x7fc0:]:
|
||||
print("Could not find a valid csr.csv descriptor on the device, aborting!")
|
||||
exit(1)
|
||||
|
||||
csr_len = int.from_bytes(csr_data[:4], 'little')
|
||||
csr_extracted = csr_data[4:4+csr_len]
|
||||
decoded = csr_extracted.decode('utf-8')
|
||||
# strip comments
|
||||
stripped = []
|
||||
for line in decoded.split('\n'):
|
||||
if line.startswith('#') == False:
|
||||
stripped.append(line)
|
||||
# create database
|
||||
csr_db = csv.reader(stripped)
|
||||
for row in csr_db:
|
||||
if len(row) > 1:
|
||||
if 'csr_register' in row[0]:
|
||||
self.registers[row[1]] = row[2]
|
||||
if 'memory_region' in row[0]:
|
||||
self.regions[row[1]] = [row[2], row[3]]
|
||||
if 'git_rev' in row[0]:
|
||||
self.gitrev = row[1]
|
||||
print("Using SoC {} registers".format(self.gitrev))
|
||||
|
||||
def erase_region(self, addr, length):
|
||||
# ID code check
|
||||
code = self.flash_rdid(1)
|
||||
print("ID code bytes 1-2: 0x{:08x}".format(code))
|
||||
if code != 0x8080c2c2:
|
||||
print("ID code mismatch")
|
||||
exit(1)
|
||||
code = self.flash_rdid(2)
|
||||
print("ID code bytes 2-3: 0x{:08x}".format(code))
|
||||
if code != 0x3b3b8080:
|
||||
print("ID code mismatch")
|
||||
exit(1)
|
||||
|
||||
# block erase
|
||||
progress = ProgressBar(min_value=0, max_value=length, prefix='Erasing ').start()
|
||||
erased = 0
|
||||
while erased < length:
|
||||
self.ping_wdt()
|
||||
if (length - erased >= 65536) and ((addr & 0xFFFF) == 0):
|
||||
blocksize = 65536
|
||||
else:
|
||||
blocksize = 4096
|
||||
|
||||
while True:
|
||||
self.flash_wren()
|
||||
status = self.flash_rdsr(1)
|
||||
if status & 0x02 != 0:
|
||||
break
|
||||
|
||||
if blocksize == 4096:
|
||||
self.flash_se4b(addr + erased)
|
||||
else:
|
||||
self.flash_be4b(addr + erased)
|
||||
erased += blocksize
|
||||
|
||||
while (self.flash_rdsr(1) & 0x01) != 0:
|
||||
pass
|
||||
|
||||
result = self.flash_rdscur()
|
||||
if result & 0x60 != 0:
|
||||
print("E_FAIL/P_FAIL set on erase, programming may fail, but trying anyways...")
|
||||
|
||||
if self.flash_rdsr(1) & 0x02 != 0:
|
||||
self.flash_wrdi()
|
||||
while (self.flash_rdsr(1) & 0x02) != 0:
|
||||
pass
|
||||
if erased < length:
|
||||
progress.update(erased)
|
||||
progress.finish()
|
||||
print("Erase finished")
|
||||
|
||||
# addr is relative to the base of FLASH (not absolute)
|
||||
def flash_program(self, addr, data, verify=True):
|
||||
flash_region = int(self.regions['spiflash'][0], 0)
|
||||
flash_len = int(self.regions['spiflash'][1], 0)
|
||||
|
||||
if (addr + len(data) > flash_len):
|
||||
print("Write data out of bounds! Aborting.")
|
||||
exit(1)
|
||||
|
||||
# ID code check
|
||||
code = self.flash_rdid(1)
|
||||
print("ID code bytes 1-2: 0x{:08x}".format(code))
|
||||
if code != 0x8080c2c2:
|
||||
print("ID code mismatch")
|
||||
exit(1)
|
||||
code = self.flash_rdid(2)
|
||||
print("ID code bytes 2-3: 0x{:08x}".format(code))
|
||||
if code != 0x3b3b8080:
|
||||
print("ID code mismatch")
|
||||
exit(1)
|
||||
|
||||
# block erase
|
||||
progress = ProgressBar(min_value=0, max_value=len(data), prefix='Erasing ').start()
|
||||
erased = 0
|
||||
while erased < len(data):
|
||||
self.ping_wdt()
|
||||
if (len(data) - erased >= 65536) and ((addr & 0xFFFF) == 0):
|
||||
blocksize = 65536
|
||||
else:
|
||||
blocksize = 4096
|
||||
|
||||
while True:
|
||||
self.flash_wren()
|
||||
status = self.flash_rdsr(1)
|
||||
if status & 0x02 != 0:
|
||||
break
|
||||
|
||||
if blocksize == 4096:
|
||||
self.flash_se4b(addr + erased)
|
||||
else:
|
||||
self.flash_be4b(addr + erased)
|
||||
erased += blocksize
|
||||
|
||||
while (self.flash_rdsr(1) & 0x01) != 0:
|
||||
pass
|
||||
|
||||
result = self.flash_rdscur()
|
||||
if result & 0x60 != 0:
|
||||
print("E_FAIL/P_FAIL set on erase, programming may fail, but trying anyways...")
|
||||
|
||||
if self.flash_rdsr(1) & 0x02 != 0:
|
||||
self.flash_wrdi()
|
||||
while (self.flash_rdsr(1) & 0x02) != 0:
|
||||
pass
|
||||
if erased < len(data):
|
||||
progress.update(erased)
|
||||
progress.finish()
|
||||
print("Erase finished")
|
||||
|
||||
# program
|
||||
# pad out to the nearest word length
|
||||
if len(data) % 4 != 0:
|
||||
data += bytearray([0xff] * (4 - (len(data) % 4)))
|
||||
written = 0
|
||||
progress = ProgressBar(min_value=0, max_value=len(data), prefix='Writing ').start()
|
||||
while written < len(data):
|
||||
self.ping_wdt()
|
||||
if len(data) - written > 256:
|
||||
chunklen = 256
|
||||
else:
|
||||
chunklen = len(data) - written
|
||||
|
||||
while True:
|
||||
self.flash_wren()
|
||||
status = self.flash_rdsr(1)
|
||||
if status & 0x02 != 0:
|
||||
break
|
||||
|
||||
self.burst_write(self.register('spinor_wdata'), data[written:(written+chunklen)])
|
||||
self.flash_pp4b(addr + written, chunklen)
|
||||
|
||||
written += chunklen
|
||||
if written < len(data):
|
||||
progress.update(written)
|
||||
progress.finish()
|
||||
print("Write finished")
|
||||
|
||||
if self.flash_rdsr(1) & 0x02 != 0:
|
||||
self.flash_wrdi()
|
||||
while (self.flash_rdsr(1) & 0x02) != 0:
|
||||
pass
|
||||
|
||||
# dummy reads to clear the "read lock" bit
|
||||
self.flash_rdsr(0)
|
||||
|
||||
# verify
|
||||
self.ping_wdt()
|
||||
if verify:
|
||||
print("Performing readback for verification...")
|
||||
self.ping_wdt()
|
||||
rbk_data = self.burst_read(addr + flash_region, len(data))
|
||||
if rbk_data != data:
|
||||
errs = 0
|
||||
err_thresh = 64
|
||||
for i in range(0, len(rbk_data)):
|
||||
if rbk_data[i] != data[i]:
|
||||
if errs < err_thresh:
|
||||
print("Error at 0x{:x}: {:x}->{:x}".format(i, data[i], rbk_data[i]))
|
||||
errs += 1
|
||||
if errs == err_thresh:
|
||||
print("Too many errors, stopping print...")
|
||||
print("Errors were found in verification, programming failed")
|
||||
print("Total byte errors: {}".format(errs))
|
||||
exit(1)
|
||||
else:
|
||||
print("Verification passed.")
|
||||
else:
|
||||
print("Skipped verification at user request")
|
||||
|
||||
self.ping_wdt()
|
||||
|
||||
def auto_int(x):
|
||||
return int(x, 0)
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Update/upload to a Precursor device running Xous 0.8/0.9")
|
||||
parser.add_argument(
|
||||
"--soc", required=False, help="'Factory Reset' the SoC gateware. Note: this will overwrite any secret keys stored in your device!", type=str, nargs='?', metavar=('SoC gateware file'), const='../precursors/soc_csr.bin'
|
||||
)
|
||||
parser.add_argument(
|
||||
"-s", "--staging", required=False, help="Stage an update to apply", type=str, nargs='?', metavar=('SoC gateware file'), const='../precursors/soc_csr.bin'
|
||||
)
|
||||
parser.add_argument(
|
||||
"-l", "--loader", required=False, help="Loader", type=str, nargs='?', metavar=('loader file'), const='../target/riscv32imac-unknown-xous-elf/release/loader.bin'
|
||||
)
|
||||
parser.add_argument(
|
||||
"--disable-boot", required=False, action='store_true', help="Disable system boot (for use in multi-stage updates)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--enable-boot-wipe", required=False, action='store_true', help="Re-enable system boot for factory reset. Requires both a loader (-l) and a soc (--soc) spec. Overwrites root keys."
|
||||
)
|
||||
parser.add_argument(
|
||||
"--enable-boot-update", required=False, action='store_true', help="Re-enable system boot for updates. Requires both a loader (-l) and a staging (-s) spec. Stages SOC without overwriting root keys."
|
||||
)
|
||||
parser.add_argument(
|
||||
"-k", "--kernel", required=False, help="Kernel", type=str, nargs='?', metavar=('kernel file'), const='../target/riscv32imac-unknown-xous-elf/release/xous.img'
|
||||
)
|
||||
parser.add_argument(
|
||||
"-e", "--ec", required=False, help="EC gateware", type=str, nargs='?', metavar=('EC gateware package'), const='ec_fw.bin'
|
||||
)
|
||||
parser.add_argument(
|
||||
"-w", "--wf200", required=False, help="WF200 firmware", type=str, nargs='?', metavar=('WF200 firmware package'), const='wf200_fw.bin'
|
||||
)
|
||||
parser.add_argument(
|
||||
"--erase-pddb", help="Erase the PDDB area", action="store_true"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--audiotest", required=False, help="Test audio clip (must be 8kHz WAV)", type=str, nargs='?', metavar=('Test audio clip'), const="testaudio.wav"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--peek", required=False, help="Inspect an address", type=auto_int, metavar=('ADDR')
|
||||
)
|
||||
parser.add_argument(
|
||||
"--poke", required=False, help="Write to an address", type=auto_int, nargs=2, metavar=('ADDR', 'DATA')
|
||||
)
|
||||
parser.add_argument(
|
||||
"--check-poke", required=False, action='store_true', help="Read data before and after the poke"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--config", required=False, help="Print the descriptor", action='store_true'
|
||||
)
|
||||
parser.add_argument(
|
||||
"-i", "--image", required=False, help="Manually specify an image and address. Offset is relative to bottom of flash.", type=str, nargs=2, metavar=('IMAGEFILE', 'ADDR')
|
||||
)
|
||||
parser.add_argument(
|
||||
"--verify", help="Readback verification. May fail for large files due to WDT timeout.", default=False, action='store_true'
|
||||
)
|
||||
parser.add_argument(
|
||||
"--force", help="Ignore gitrev version on SoC and try to burn an image anyways", action="store_true"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--bounce", help="cycle the device through a reset", action="store_true"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--factory-new", help="reset the entire image to mimic exactly what comes out of the factory, including temp files for testing. Warning: this will take a long time.", action="store_true"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--override-csr", required=False, help="CSR file to use instead of CSR values stored with the image. Used to recover in case of partial update of soc_csr.bin", type=str,
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
if not len(sys.argv) > 1:
|
||||
print("No arguments specified, doing nothing. Use --help for more information.")
|
||||
exit(1)
|
||||
|
||||
dev = usb.core.find(idProduct=0x5bf0, idVendor=0x1209)
|
||||
|
||||
if dev is None:
|
||||
raise ValueError('Precursor device not found')
|
||||
|
||||
dev.set_configuration()
|
||||
if args.config:
|
||||
cfg = dev.get_active_configuration()
|
||||
print(cfg)
|
||||
|
||||
pc_usb = PrecursorUsb(dev)
|
||||
|
||||
if args.verify:
|
||||
verify = True
|
||||
else:
|
||||
verify = False
|
||||
|
||||
if args.peek:
|
||||
pc_usb.peek(args.peek, display=True)
|
||||
# print(burst_read(dev, args.peek, 256).hex())
|
||||
exit(0)
|
||||
|
||||
if args.poke:
|
||||
addr, data = args.poke
|
||||
pc_usb.poke(addr, data, check=args.check_poke, display=True)
|
||||
# import os
|
||||
# d = bytearray(os.urandom(8000))
|
||||
# burst_write(dev, addr, d)
|
||||
# r = burst_read(dev, addr, 8000)
|
||||
# print(r.hex())
|
||||
# if d != r:
|
||||
# print("mismatch")
|
||||
# else:
|
||||
# print("match")
|
||||
exit(0)
|
||||
|
||||
pc_usb.load_csrs(args.override_csr) # prime the CSR values
|
||||
if "v0.8" in pc_usb.gitrev:
|
||||
locs = {
|
||||
"LOC_SOC" : [0x0000_0000, "soc_csr.bin"],
|
||||
"LOC_STAGING": [0x0028_0000, "pass"],
|
||||
"LOC_LOADER" : [0x0050_0000, "loader.bin"],
|
||||
"LOC_KERNEL" : [0x0098_0000, "xous.img"],
|
||||
"LOC_WF200" : [0x07F8_0000, "pass"],
|
||||
"LOC_EC" : [0x07FC_E000, "pass"],
|
||||
"LOC_AUDIO" : [0x0634_0000, "short_8khz.wav"],
|
||||
"LEN_AUDIO" : [0x01C4_0000, "pass"],
|
||||
"LOC_PDDB" : [0x0100_0000, "pass"],
|
||||
}
|
||||
elif "v0.9" in pc_usb.gitrev:
|
||||
locs = {
|
||||
"LOC_SOC" : [0x0000_0000, "soc_csr.bin"],
|
||||
"LOC_STAGING": [0x0028_0000, "pass"],
|
||||
"LOC_LOADER" : [0x0050_0000, "loader.bin"],
|
||||
"LOC_KERNEL" : [0x0098_0000, "xous.img"],
|
||||
"LOC_WF200" : [0x07F8_0000, "pass"],
|
||||
"LOC_EC" : [0x07FC_E000, "pass"],
|
||||
"LOC_AUDIO" : [0x0634_0000, "short_8khz.wav"],
|
||||
"LEN_AUDIO" : [0x01C4_0000, "pass"],
|
||||
"LOC_PDDB" : [0x01D8_0000, "pass"],
|
||||
}
|
||||
elif args.force == True:
|
||||
# try the v0.9 offsets
|
||||
locs = {
|
||||
"LOC_SOC" : [0x00000000, "soc_csr.bin"],
|
||||
"LOC_STAGING": [0x00280000, "pass"],
|
||||
"LOC_LOADER" : [0x00500000, "loader.bin"],
|
||||
"LOC_KERNEL" : [0x00980000, "xous.img"],
|
||||
"LOC_WF200" : [0x07F80000, "pass"],
|
||||
"LOC_EC" : [0x07FCE000, "pass"],
|
||||
"LOC_AUDIO" : [0x06340000, "short_8khz.wav"],
|
||||
"LEN_AUDIO" : [0x01C40000, "pass"],
|
||||
"LOC_PDDB" : [0x01D80000, "pass"],
|
||||
}
|
||||
else:
|
||||
print("SoC is from an unknow rev '{}', use --force to continue anyways with v0.9 firmware offsets".format(pc_usb.load_csrs()))
|
||||
exit(1)
|
||||
|
||||
vexdbg_addr = int(pc_usb.regions['vexriscv_debug'][0], 0)
|
||||
pc_usb.ping_wdt()
|
||||
print("Halting CPU.")
|
||||
pc_usb.poke(vexdbg_addr, 0x00020000)
|
||||
|
||||
if args.erase_pddb:
|
||||
print("Erasing PDDB region")
|
||||
pc_usb.erase_region(locs['LOC_PDDB'][0], locs['LOC_EC'][0] - locs['LOC_PDDB'][0])
|
||||
|
||||
if args.disable_boot:
|
||||
print("Disabling boot")
|
||||
pc_usb.erase_region(locs['LOC_LOADER'][0], 1024 * 256)
|
||||
|
||||
if args.enable_boot_wipe:
|
||||
if args.loader == None:
|
||||
print("Must provide both a loader and soc image")
|
||||
if args.soc == None:
|
||||
print("Must provide both a soc and loader image")
|
||||
print("Enabling boot with {} and {}".format(args.loader, args.soc))
|
||||
print("Programming loader image {}".format(args.loader))
|
||||
with open(args.loader, "rb") as f:
|
||||
image = f.read()
|
||||
pc_usb.flash_program(locs['LOC_LOADER'][0], image, verify=verify)
|
||||
print("Programming SoC gateware".format(args.soc))
|
||||
with open(args.soc, "rb") as f:
|
||||
image = f.read()
|
||||
if verify == True:
|
||||
print("Note: SoC verification is not possible as readback is locked for security purposes")
|
||||
pc_usb.flash_program(locs['LOC_SOC'][0], image, verify=False)
|
||||
|
||||
print("Erasing PDDB root structures")
|
||||
pc_usb.erase_region(locs['LOC_PDDB'][0], 1024 * 1024)
|
||||
|
||||
print("Resuming CPU.")
|
||||
pc_usb.poke(vexdbg_addr, 0x02000000)
|
||||
|
||||
print("Resetting SOC...")
|
||||
try:
|
||||
pc_usb.poke(pc_usb.register('reboot_soc_reset'), 0xac, display=False)
|
||||
except usb.core.USBError:
|
||||
pass # we expect an error because we reset the SOC and that includes the USB core
|
||||
exit(0)
|
||||
|
||||
if args.enable_boot_update:
|
||||
if args.loader == None:
|
||||
print("Must provide both a loader and soc image")
|
||||
if args.staging == None:
|
||||
print("Must provide both a soc and loader image")
|
||||
print("Enabling boot with {} and {}".format(args.loader, args.staging))
|
||||
print("Programming loader image {}".format(args.loader))
|
||||
with open(args.loader, "rb") as f:
|
||||
image = f.read()
|
||||
pc_usb.flash_program(locs['LOC_LOADER'][0], image, verify=verify)
|
||||
print("Staging SoC gateware".format(args.staging))
|
||||
with open(args.staging, "rb") as f:
|
||||
image = f.read()
|
||||
if verify == True:
|
||||
print("Note: staging area verification is not possible as readback is locked for security purposes")
|
||||
pc_usb.flash_program(locs['LOC_STAGING'][0], image, verify=verify)
|
||||
|
||||
print("Resuming CPU.")
|
||||
pc_usb.poke(vexdbg_addr, 0x02000000)
|
||||
|
||||
print("Resetting SOC...")
|
||||
try:
|
||||
pc_usb.poke(pc_usb.register('reboot_soc_reset'), 0xac, display=False)
|
||||
except usb.core.USBError:
|
||||
pass # we expect an error because we reset the SOC and that includes the USB core
|
||||
exit(0)
|
||||
|
||||
if args.image:
|
||||
image_file, addr_str = args.image
|
||||
addr = int(addr_str, 0)
|
||||
print("Burning manually specified image '{}' to address 0x{:08x} relative to bottom of FLASH".format(image_file, addr))
|
||||
with open(image_file, "rb") as f:
|
||||
image_data = f.read()
|
||||
pc_usb.flash_program(addr, image_data, verify=verify)
|
||||
|
||||
if args.ec != None:
|
||||
print("Staging EC firmware package '{}' in SOC memory space...".format(args.ec))
|
||||
with open(args.ec, "rb") as f:
|
||||
image = f.read()
|
||||
pc_usb.flash_program(locs['LOC_EC'][0], image, verify=verify)
|
||||
|
||||
if args.wf200 != None:
|
||||
print("Staging WF200 firmware package '{}' in SOC memory space...".format(args.wf200))
|
||||
with open(args.wf200, "rb") as f:
|
||||
image = f.read()
|
||||
pc_usb.flash_program(locs['LOC_WF200'][0], image, verify=verify)
|
||||
|
||||
if args.staging != None:
|
||||
print("Staging SoC gateware {}".format(args.soc))
|
||||
with open(args.staging, "rb") as f:
|
||||
image = f.read()
|
||||
if verify == True:
|
||||
print("Note: staging area verification is not possible as readback is locked for security purposes")
|
||||
pc_usb.flash_program(locs['LOC_STAGING'][0], image, verify=verify)
|
||||
|
||||
if args.kernel != None:
|
||||
print("Programming kernel image {}".format(args.kernel))
|
||||
with open(args.kernel, "rb") as f:
|
||||
image = f.read()
|
||||
pc_usb.flash_program(locs['LOC_KERNEL'][0], image, verify=verify)
|
||||
|
||||
if args.loader != None:
|
||||
print("Programming loader image {}".format(args.loader))
|
||||
with open(args.loader, "rb") as f:
|
||||
image = f.read()
|
||||
pc_usb.flash_program(locs['LOC_LOADER'][0], image, verify=verify)
|
||||
|
||||
if args.soc != None:
|
||||
if args.force == True:
|
||||
print("Programming SoC gateware {}".format(args.soc))
|
||||
with open(args.soc, "rb") as f:
|
||||
image = f.read()
|
||||
if verify == True:
|
||||
print("Note: SoC verification is not possible as readback is locked for security purposes")
|
||||
pc_usb.flash_program(locs['LOC_SOC'][0], image, verify=False)
|
||||
print("Erasing PDDB root structures")
|
||||
pc_usb.erase_region(locs['LOC_PDDB'][0], 1024 * 1024)
|
||||
else:
|
||||
print("This will overwrite any secret keys in your device and erase PDDB keys. Continue? (y/n)")
|
||||
confirm = input()
|
||||
if len(confirm) > 0 and confirm.lower()[:1] == 'y':
|
||||
print("Programming SoC gateware {}".format(args.soc))
|
||||
with open(args.soc, "rb") as f:
|
||||
image = f.read()
|
||||
if verify == True:
|
||||
print("Note: SoC verification is not possible as readback is locked for security purposes")
|
||||
pc_usb.flash_program(locs['LOC_SOC'][0], image, verify=False)
|
||||
print("Erasing PDDB root structures")
|
||||
pc_usb.erase_region(locs['LOC_PDDB'][0], 1024 * 1024)
|
||||
|
||||
|
||||
if args.audiotest != None:
|
||||
print("Loading audio test clip {}".format(args.audiotest))
|
||||
with open(args.audiotest, "rb") as f:
|
||||
image = f.read()
|
||||
if len(image) >= locs['LEN_AUDIO'][0]:
|
||||
print("audio file is too long, aborting audio burn!")
|
||||
else:
|
||||
pc_usb.flash_program(locs['LOC_AUDIO'][0], image, verify=verify)
|
||||
|
||||
if args.factory_new:
|
||||
base_url = "https://ci.betrusted.io/releases/v0.9.5/"
|
||||
# erase the entire flash
|
||||
pc_usb.erase_region(0, 0x800_0000)
|
||||
# burn the gateware
|
||||
for sections in locs.values():
|
||||
if sections[1] != 'pass':
|
||||
print('retrieving {}'.format(base_url + sections[1]))
|
||||
with urllib.request.urlopen(base_url + sections[1]) as f:
|
||||
print('burning at {:x}'.format(sections[0]))
|
||||
image = f.read()
|
||||
pc_usb.flash_program(sections[0], image, verify=False)
|
||||
|
||||
|
||||
print("Resuming CPU.")
|
||||
pc_usb.poke(vexdbg_addr, 0x02000000)
|
||||
|
||||
print("Resetting SOC...")
|
||||
try:
|
||||
pc_usb.poke(pc_usb.register('reboot_soc_reset'), 0xac, display=False)
|
||||
except usb.core.USBError:
|
||||
pass # we expect an error because we reset the SOC and that includes the USB core
|
||||
|
||||
# print("If you need to run more commands, please unplug and re-plug your device in, as the Precursor USB core was just reset")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
exit(0)
|
||||
1
tools/legacy/usb_update.py
Symbolic link
1
tools/legacy/usb_update.py
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
../usb_update.py
|
||||
Loading…
Reference in a new issue