To start with a clean slate, erased the entire 16MB SPI-Flash so that all bytes are 0xff.
python3 ./firmware/Kboot/build/ktool.py -B goE -b 1500000 -E
...
[INFO] Erasing the whole SPI Flash.
[INFO] SPI Flash erased.
Downloaded krux-v22.08.2.zip
from https://github.com/selfcustody/krux/releases/tag/v22.08.2
unzip -l ~/Downloads/krux-v22.08.2.zip
...
Archive: ~/Downloads/krux-v22.08.2.zip
Length Date Time Name
--------- ---------- ----- ----
0 2022-09-13 05:14 krux-v22.08.2/
0 2022-09-13 05:34 krux-v22.08.2/maixpy_bit/
70 1980-01-01 00:00 krux-v22.08.2/maixpy_bit/firmware.bin.sig
1705088 2022-09-13 05:03 krux-v22.08.2/maixpy_bit/firmware.bin
894855 2022-09-13 05:03 krux-v22.08.2/maixpy_bit/kboot.kfpkg
7806062 2022-09-13 04:22 krux-v22.08.2/ktool-win.exe
6313696 2022-09-13 04:22 krux-v22.08.2/ktool-mac-10
7222448 2022-09-13 04:22 krux-v22.08.2/ktool-mac
0 2022-09-13 05:34 krux-v22.08.2/maixpy_amigo_tft/
70 1980-01-01 00:00 krux-v22.08.2/maixpy_amigo_tft/firmware.bin.sig
1716288 2022-09-13 04:52 krux-v22.08.2/maixpy_amigo_tft/firmware.bin
897074 2022-09-13 04:52 krux-v22.08.2/maixpy_amigo_tft/kboot.kfpkg
0 2022-09-13 05:33 krux-v22.08.2/maixpy_m5stickv/
70 1980-01-01 00:00 krux-v22.08.2/maixpy_m5stickv/firmware.bin.sig
1712000 2022-09-13 04:31 krux-v22.08.2/maixpy_m5stickv/firmware.bin
896570 2022-09-13 04:31 krux-v22.08.2/maixpy_m5stickv/kboot.kfpkg
16478872 2022-09-13 04:22 krux-v22.08.2/ktool-linux
0 2022-09-13 05:34 krux-v22.08.2/maixpy_amigo_ips/
70 1980-01-01 00:00 krux-v22.08.2/maixpy_amigo_ips/firmware.bin.sig
1716288 2022-09-13 04:41 krux-v22.08.2/maixpy_amigo_ips/firmware.bin
897059 2022-09-13 04:41 krux-v22.08.2/maixpy_amigo_ips/kboot.kfpkg
0 2022-09-13 05:34 krux-v22.08.2/maixpy_dock/
70 1980-01-01 00:00 krux-v22.08.2/maixpy_dock/firmware.bin.sig
1705088 2022-09-13 05:14 krux-v22.08.2/maixpy_dock/firmware.bin
894856 2022-09-13 05:14 krux-v22.08.2/maixpy_dock/kboot.kfpkg
--------- -------
50856594 25 files
Inflated kboot.kfpkg
and got sha256 hashes of binaries contained within.
unzip -e ~/Downloads/krux-v22.08.2.zip krux-v22.08.2/maixpy_amigo_tft/kboot.kfpkg
...
inflating: krux-v22.08.2/maixpy_amigo_tft/kboot.kfpkg
sha256sum krux-v22.08.2/maixpy_amigo_tft/kboot.kfpkg
...
11669c3addf05af3dc102d22c942b80483fa839a7cfb07ad9cfe60ade5067cfd krux-v22.08.2/maixpy_amigo_tft/kboot.kfpkg
unzip -l krux-v22.08.2/maixpy_amigo_tft/kboot.kfpkg
...
Archive: krux-v22.08.2/maixpy_amigo_tft/kboot.kfpkg
Length Date Time Name
--------- ---------- ----- ----
647 2022-09-13 04:52 flash-list.json
608 2022-09-13 04:52 bootloader_lo.bin
8112 2022-09-13 04:52 bootloader_hi.bin
4096 2022-03-30 15:38 config.bin
1716288 2022-09-13 04:52 firmware.bin
--------- -------
1729751 5 files
unzip -p krux-v22.08.2/maixpy_amigo_tft/kboot.kfpkg bootloader_lo.bin | sha256sum
...
2e050a92efdcb172cb5c6f7cb0b669ba654d2d20219f810fd9fc543f7ef05c3e -
unzip -p krux-v22.08.2/maixpy_amigo_tft/kboot.kfpkg bootloader_hi.bin | sha256sum
...
f005f7c8b13aa2719cad58492a8432f14b68b2f845b58e5b5e81ed6309be6172 -
unzip -p krux-v22.08.2/maixpy_amigo_tft/kboot.kfpkg config.bin | sha256sum
c9b9c4adcabe9c353a907f44c101c3b29756b30762e4b282d87d2a92400e2198 -
unzip -p krux-v22.08.2/maixpy_amigo_tft/kboot.kfpkg firmware.bin | sha256sum
5067429beb16bd0eac55401ea673f55f9cc97585b1a0607d64f8e5f486d4988b -
Using usb, flashed the device with v22.08.2 kboot.kfpkg
python3 ./firmware/Kboot/build/ktool.py -B goE -b 1500000 krux-v22.08.2/maixpy_amigo_tft/kboot.kfpkg
...
[INFO] Flashed 1716325 B [27 chunks of 65536B] (00080000~0022FFFF) in 22.967s
[INFO] Rebooting...
Connecting to the amigo via usb console and interrupting krux, stopping WDT, to work in python REPL.
screen /dev/ttyUSB1 115200
...
<ctrl>-C
...
KeyboardInterrupt:
MicroPython v1.11 on 2022-09-13; Sipeed_M1 with kendryte-k210
Type "help()" for more information.
>>>
>>> from machine import WDT;WDT().stop()
>>>
Cutting and pasting scripts for analyzing SPI-Flash.
Btw, it's <ctrl>-E
to enter cut/paste mode, <ctrl>-D
when done.
I do it in small chunks to avoid un-explained syntax errors with large cut/pastes.
TODO: publish scripts when they're mature enough for others to use.
Click to see hacky/prototype code.
class MockedMaixUtils:
def flash_read(self, address, length):
with open('/tmp/k210.flash_dump', 'rb') as f:
f.seek(address)
return f.read(length)
try: from Maix import utils
except: utils = MockedMaixUtils()
def decremented_bool(value):
'''returns value as a bool or an int > 0'''
if type(value) == int:
if value > 0:
return value - 1
elif value == 0:
return False
else:
raise TypeError('if value is <int>, must be >= 0: found %d' % value)
elif type(value) == bool:
return value
else:
raise TypeError('value must be <int> >= 0 or <bool> found %s' % value)
def hash_flash(begin=0x00, length=2**24, block_size=2**12, verbose=False):
'''
hash the entirety of flash memory
assumes that utils.flash_read() behaves as if imported from Maix
'''
from math import ceil
from hashlib import sha256
from binascii import hexlify
assert block_size % block_size == 0, 'block_size must be divisible by 4096'
_hash = sha256()
if verbose:
print('Hashing %s bytes of flash at %s...' % (length, hex(begin)), end='')
bytes_read = 0
while bytes_read < length:
if bytes_read + block_size < length:
_hash.update(utils.flash_read(begin+bytes_read, block_size))
bytes_read += block_size
else:
_hash.update(utils.flash_read(begin+bytes_read, length-bytes_read))
bytes_read += length - bytes_read
if verbose:
print('.', end='')
answer = _hash.digest()
if verbose:
print('\nsha256 of %s bytes at %s:\n%s' % (bytes_read, hex(begin), hexlify(answer).decode()
))
return answer
def all_bytes_are(byte, begin, length, block_size=2**12, verbose=False):
'''
returns True if all bytes in flash are the same as byte, otherwise False
assumes that utils.flash_read() behaves as if imported from Maix
'''
from binascii import hexlify
answer = True
if verbose:
print("Checking if %s bytes of flash at %s are all 0x%s..." % (
length, hex(begin), hexlify(byte).decode()), end='')
bytes_read = 0
while bytes_read < length:
if bytes_read + block_size < length:
if utils.flash_read(begin+bytes_read, block_size) != byte * block_size:
answer = False
break
bytes_read += block_size
else:
if utils.flash_read(begin+bytes_read, length-bytes_read) != byte * (length - bytes_read):
answer = False
break
bytes_read += length - bytes_read
if verbose:
print('.', end='')
if verbose:
print("\nthe %s bytes at %s are %s 0x%s." % (
length, hex(begin), 'ALL' if answer else 'NOT all', hexlify(byte).decode()))
return answer
def validate_aes_size_app_sha(begin, verbose=False):
'''
verify a ktool sector as (0x0 aes byte + 4B-lil-size + appdata + shasuffix) for standard sectors
assumes that utils.flash_read() behaves as if imported from Maix
'''
from binascii import hexlify
sectors = {
# address, block_size, sector_name
0x0: (0x1000, 'Kboot stage-0'),
0x1000: (0x1000, 'Kboot stage-1'),
0x80000: (0x10000, 'firmware slot1'),
0x280000: (0x10000, 'firmware slot2'),
}
bytes_read = 0
if verbose:
print('Validating sector format (aes+size+app+sha) at %s...' % hex(begin))
if begin not in sectors:
if verbose:
print('%s not in %s.' % (begin, sectors))
return None, bytes_read
block_size, sector_name = sectors[begin]
if verbose:
print('sector known as "%s", will use blocks_size %s,' % (sector_name, block_size))
header = utils.flash_read(begin, 5)
bytes_read += 5
if not header[0] == 0x00:
if verbose:
print('first (aes) byte of header 0x%s is not 0x00.' % (hexlify(header).decode()))
return None, bytes_read
length = int.from_bytes(header[1:5], 'little')
bytes_read += length
if verbose:
print('header indicates %s bytes of data,' % length)
hash_suffix = utils.flash_read(begin+5+length, 32)
bytes_read += 32
_hash = hash_flash(begin, length=5+length, block_size=block_size, verbose=decremented_bool(verbose))
if _hash != hash_suffix:
if verbose:
print('hash of %s bytes of header+data does not match suffix:\n suffix: %s\n found: %s' % (
5+length, hexlify(hash_suffix).decode(), hexlify(_hash).decode()))
hash_flash(begin + 5, length, block_size=block_size, verbose=1)
return None, bytes_read
if verbose:
print('sha256(header + data) == suffix, is expected format for this sector,')
partial = (5 + length + 32) % block_size
if partial:
padding = block_size - partial
if not all_bytes_are(b'\x00', begin+5+length+32, block_size-partial, verbose=decremented_bool(verbose)):
if verbose:
print('%s bytes to pad rest of sector are not all 0x00 bytes.' % padding)
return None, bytes_read
bytes_read += padding
if verbose:
print('%s bytes to pad rest of sector are ALL 0x00 bytes.' % padding)
return True, bytes_read
def analyze_spi_flash(verbose=False):
'''
Analyze the entirety of SPI flash
assumes that utils.flash_read() behaves as if imported from Maix
'''
from binascii import hexlify
def ktool_app_size(address):
size = int.from_bytes(utils.flash_read(address+1, 4), 'little')
if size > 2**24 - address: return 0
else: return size
def be_verbose(msg='', *args):
messages = {
'ktool_sector': '\nChecking "%s" from %s to %s-1', # 3 args: name, start, end+1
'validated': 'SPI flash from %s to %s-1 is %s.', # 3 args: start, end+1, 'valid'|'invalid'
'hashed': 'sha256 hash of SPI flash from %s to %s-1 is:\n%s', # 3 args: start, end+1, hash
'filesizehash': 'sha256 hash of "%s" having %s bytes is:\n%s', # 3 args: name, size, hash
}
if msg in messages and len(args):
print(messages[msg] % args)
else:
print(msg)
spi_flash_size = 2**24
cursor = 0x0
# 4096 bytes at 0x0 are of aes_size_app_sha format
be_verbose('ktool_sector', 'Kboot stage-0', hex(cursor), hex(cursor+4096))
valid, bytes_read = validate_aes_size_app_sha(cursor, verbose=decremented_bool(verbose))
be_verbose('validated', hex(cursor), hex(cursor+bytes_read), 'valid' if valid else 'INVALID')
assert valid and bytes_read, 'checking "Kboot stage-0"'
_size = ktool_app_size(cursor)
_hash = hash_flash(cursor+5, _size, verbose=decremented_bool(verbose))
be_verbose('filesizehash', 'bootloader_lo.bin', _size, hexlify(_hash).decode())
cursor += bytes_read
# 8192 bytes at 0x1000 are of aes_size_app_sha format and the next 4096 are 0xff
be_verbose('ktool_sector', 'Kboot stage-1', hex(cursor), hex(cursor+12288))
valid, bytes_read = validate_aes_size_app_sha(cursor, verbose=decremented_bool(verbose))
be_verbose('validated', hex(cursor), hex(cursor+bytes_read), 'valid' if valid else 'INVALID')
assert valid and bytes_read, 'checking "Kboot stage-1"'
_size = ktool_app_size(cursor)
_hash = hash_flash(cursor+5, _size, verbose=decremented_bool(verbose))
be_verbose('filesizehash', 'bootloader_hi.bin', _size, hexlify(_hash).decode())
cursor += bytes_read
valid = all_bytes_are(b'\xff', cursor, 4096, verbose=decremented_bool(verbose))
if type(valid) == bool:
bytes_read = 4096
be_verbose('validated', hex(cursor), hex(cursor+bytes_read), 'all 0xff' if valid else 'NOT all 0xff!')
assert valid and bytes_read, 'checking last third of "Kboot stage-1"'
cursor += bytes_read
# 4096 bytes at 0x4000 are main config
be_verbose('ktool_sector', 'main config', hex(cursor), hex(cursor+4096))
_hash = hash_flash(cursor, 4096, verbose=decremented_bool(verbose))
if len(_hash) == 32:
valid, bytes_read = True, 4096
be_verbose('filesizehash', 'config.bin', 4096, hexlify(_hash).decode())
assert valid and bytes_read, 'hashing "main config"'
cursor += bytes_read
# 4096 bytes at 0x5000 are config backup
be_verbose('ktool_sector', 'backup config', hex(cursor), hex(cursor+4096))
_other_hash = hash_flash(cursor, 4096, verbose=decremented_bool(verbose))
if len(_hash) == 32:
valid, bytes_read = True, 4096
be_verbose('hashed', hex(cursor), hex(cursor+bytes_read), hexlify(_other_hash).decode())
assert valid and bytes_read, 'hashing "backup config"'
cursor += bytes_read
# 40960 bytes at 0x6000 are reserved
be_verbose('ktool_sector', 'reserved', hex(cursor), hex(cursor+40960))
valid = all_bytes_are(b'\xff', cursor, 40960, verbose=decremented_bool(verbose))
if type(valid) == bool:
bytes_read = 40960
be_verbose('validated', hex(cursor), hex(cursor+bytes_read), 'all 0xff' if valid else 'NOT all 0xff!')
assert valid and bytes_read, 'checking that "reserved" is unused'
cursor += bytes_read
# the first 0x70000 bytes are unused
be_verbose('ktool_sector', 'unused app/user', hex(cursor), hex(cursor+0x70000))
valid = all_bytes_are(b'\xff', cursor, 0x70000, verbose=decremented_bool(verbose))
if type(valid) == bool:
bytes_read = 0x70000
be_verbose('validated', hex(cursor), hex(cursor+bytes_read), 'all 0xff' if valid else 'NOT all 0xff!')
assert valid and bytes_read, 'checking that "app/user" is unused'
cursor += bytes_read
# variable bytes at firmware slot1 0x80000 are firmware
valid, bytes_read = validate_aes_size_app_sha(cursor, verbose=decremented_bool(verbose))
be_verbose('ktool_sector', 'firmware_slot1', hex(cursor), hex(cursor+bytes_read))
be_verbose('validated', hex(cursor), hex(cursor+bytes_read), 'valid' if valid else 'INVALID')
_size = ktool_app_size(cursor)
_hash = hash_flash(cursor+5, _size, verbose=decremented_bool(verbose))
be_verbose('filesizehash', 'firmware.bin', _size, hexlify(_hash).decode())
assert valid and bytes_read, 'checking firmware slot1'
cursor += bytes_read
# variable bytes up to firmware slot2 are unused
_size = 0x280000 - cursor
be_verbose('ktool_sector', 'unused app/user', hex(cursor), hex(cursor+_size))
valid = all_bytes_are(b'\xff', cursor, _size, verbose=decremented_bool(verbose))
if type(valid) == bool:
bytes_read = _size
be_verbose('validated', hex(cursor), hex(cursor+_size), 'all 0xff' if valid else 'NOT all 0xff!')
assert valid and bytes_read, 'checking that "app/user" is unused'
cursor += bytes_read
# variable bytes at firmware slot2 0x280000 are firmware
valid, bytes_read = validate_aes_size_app_sha(cursor, verbose=decremented_bool(verbose))
be_verbose('ktool_sector', 'firmware_slot2', hex(cursor), hex(cursor+bytes_read))
be_verbose('validated', hex(cursor), hex(cursor+bytes_read), 'valid' if valid else 'INVALID')
if valid:
_size = ktool_app_size(cursor)
_hash = hash_flash(cursor+5, _size, verbose=decremented_bool(verbose))
be_verbose('filesizehash', 'firmware.bin', _size, hexlify(_hash).decode())
cursor += bytes_read
# bytes between firmware and spiffs are unused
_size = 0xd00000 - cursor
be_verbose('ktool_sector', 'unused app/user', hex(cursor), hex(cursor+_size))
valid = all_bytes_are(b'\xff', cursor, _size, verbose=decremented_bool(verbose))
if type(valid) == bool:
bytes_read = _size
be_verbose('validated', hex(cursor), hex(cursor+_size), 'all 0xff' if valid else 'NOT all 0xff!')
assert valid and bytes_read, 'checking that "app/user" is unused'
cursor += bytes_read
# 0x300000 spiffs bytes at 0xD00000
_size = 0x300000
be_verbose('ktool_sector', 'SPI Flash Filing System', hex(cursor), hex(cursor+_size))
_hash = hash_flash(cursor, _size, verbose=decremented_bool(verbose))
if len(_hash) == 32:
valid, bytes_read = True, _size
be_verbose('filesizehash', 'SPI Flash Filing System', _size, hexlify(_hash).decode())
assert valid and bytes_read, 'hashing SPIFFS'
cursor += bytes_read
# hash entirety of SPI flash
be_verbose('ktool_sector', 'SPI flash', hex(0x0), hex(spi_flash_size))
_hash = hash_flash(0x0, spi_flash_size, verbose=decremented_bool(verbose))
be_verbose('filesizehash', '16MB SPI flash', spi_flash_size, hexlify(_hash).decode())
class HexDumpSPIFlash:
'''
hex dump for maixpy 16MB SPI Flash
assumes that utils.flash_read() behaves as if imported from Maix
'''
size = 2**24
def __init__(self, begin=0x0, width=16, lines=16, squeeze=True):
self.cursor = begin
self.configure(width=width, lines=lines, squeeze=squeeze)
def next(self):
pass
def prev(self):
page_size = self.width * self.lines
self.cursor = (self.size + self.cursor - (page_size * 2)) % self.size
def seek(self, address):
self.cursor = address % self.size
def configure(self, width=None, lines=None, squeeze=True):
if type(width) == int and width > 0:
self.width = width
if type(lines) == int and lines > 0:
self.lines = lines
if type(squeeze) == bool:
self.squeeze = squeeze
byte_format = ' '.join([' '.join(['{:02x}']*4)]*(self.width//4))
if self.width % 4:
byte_format = ' '.join([byte_format, ' '.join(['{:02x}']*(self.width%4))])
self.fmt = '{} {} |{}|'.format('{:06x}', byte_format, '{:.1s}'*self.width)
def read(self, update_cursor=False):
def format_record(address, record):
if len(record) == self.width:
return self.fmt.format(
*[address]
+[x for x in record]
+[len(repr(str(chr(x))))==3 and str(chr(x)) or '.' for x in record]
)
else:
return '{:06x} {} [EOR]'.format(
address,
' '.join(['{:02x}'.format(x) for x in record])
)
first = self.cursor
answer, buf, i_buf, line_no, repeats, last_record = [], (None, b''), 0, 0, 0, (None, b'')
while line_no < self.lines:
if i_buf + 1 >= len(buf[1]):
buf = (first, utils.flash_read(first, self.width*self.lines))
i_buf = 0
record = (first, buf[1][i_buf:i_buf+self.width])
if repeats:
if record[1] != last_record[1]:
answer.extend([
'... {:d} squeezed'.format(repeats-1) if repeats>1 else '',
format_record(*last_record),
format_record(*record)
])
repeats = 0
line_no += 3
else:
repeats += 1
else:
if self.squeeze and record[1] == last_record[1]:
repeats += 1
else:
answer.append(format_record(*record))
line_no += 1
i_buf += len(record[1])
first = (first + len(record[1])) % self.size
last_record = record
if repeats:
answer.extend([
'... {:d} squeezed'.format(repeats-1) if repeats>1 else '',
format_record(*record)
])
if update_cursor:
self.cursor = first
return '\n'.join(answer)
def run(self):
def set_lines():
self.configure(lines=int(input('Enter number of lines: ')))
def set_width():
self.configure(width=int(input('Enter number of bytes per line: ')))
def toggle_squeeze():
self.configure(squeeze=not self.squeeze)
def seek():
address = input('Enter an address: ')
if address[:2] == '0b':
address = int(address[2:], 2)
elif address[:2] == '0x':
address = int(address[2:], 16)
else:
address = int(address)
self.seek(address)
repl = {
'j': self.next,
'k': self.prev,
'l': set_lines,
'w': set_width,
's': toggle_squeeze,
'/': seek,
}
print(self.read(update_cursor=True))
while True:
_in = input('\b')
if _in and _in[0] in repl:
repl[_in]()
print(self.read(update_cursor=True))
elif _in == 'q':
return
else: print('Try one of %s or "q" to quit.' % [x for x in repl.keys()])
Running the analyze_spi_flash function:
>>> analyze_spi_flash()
Checking "Kboot stage-0" from 0x0 to 0x1000-1
SPI flash from 0x0 to 0x1000-1 is valid.
sha256 hash of "bootloader_lo.bin" having 608 bytes is:
2e050a92efdcb172cb5c6f7cb0b669ba654d2d20219f810fd9fc543f7ef05c3e
Checking "Kboot stage-1" from 0x1000 to 0x4000-1
SPI flash from 0x1000 to 0x3000-1 is valid.
sha256 hash of "bootloader_hi.bin" having 8112 bytes is:
f005f7c8b13aa2719cad58492a8432f14b68b2f845b58e5b5e81ed6309be6172
SPI flash from 0x3000 to 0x4000-1 is all 0xff.
Checking "main config" from 0x4000 to 0x5000-1
sha256 hash of "config.bin" having 4096 bytes is:
c9b9c4adcabe9c353a907f44c101c3b29756b30762e4b282d87d2a92400e2198
Checking "backup config" from 0x5000 to 0x6000-1
sha256 hash of SPI flash from 0x5000 to 0x6000-1 is:
c9b9c4adcabe9c353a907f44c101c3b29756b30762e4b282d87d2a92400e2198
Checking "reserved" from 0x6000 to 0x10000-1
SPI flash from 0x6000 to 0x10000-1 is all 0xff.
Checking "unused app/user" from 0x10000 to 0x80000-1
SPI flash from 0x10000 to 0x80000-1 is all 0xff.
Checking "firmware_slot1" from 0x80000 to 0x230000-1
SPI flash from 0x80000 to 0x230000-1 is valid.
sha256 hash of "firmware.bin" having 1716288 bytes is:
5067429beb16bd0eac55401ea673f55f9cc97585b1a0607d64f8e5f486d4988b
Checking "unused app/user" from 0x230000 to 0x280000-1
SPI flash from 0x230000 to 0x280000-1 is all 0xff.
Checking "firmware_slot2" from 0x280000 to 0x280005-1
SPI flash from 0x280000 to 0x280005-1 is INVALID.
Checking "unused app/user" from 0x280000 to 0xd00000-1
SPI flash from 0x280000 to 0xd00000-1 is all 0xff.
Checking "SPI Flash Filing System" from 0xd00000 to 0x1000000-1
sha256 hash of "SPI Flash Filing System" having 3145728 bytes is:
e945c6bf2b3bdcf927b19a24e911f0cac73fb39a95a606cb6c043e335433b118
Checking "SPI flash" from 0x0 to 0x1000000-1
sha256 hash of "16MB SPI flash" having 16777216 bytes is:
ee874f63fbeab613db997a60408c332848f619c833e27ef1778e85f2fd23c6fb
Downloaded krux-v23.09.0.zip
from https://github.com/selfcustody/krux/releases/tag/v23.09.0
unzip -l ~/Downloads/krux-v23.09.0.zip
...
Length Date Time Name
--------- ---------- ----- ----
0 2023-09-12 22:17 krux-v23.09.0/
14691000 2023-09-12 22:14 krux-v23.09.0/ktool-linux
6314320 2023-09-12 22:14 krux-v23.09.0/ktool-mac
6313696 2023-09-12 22:14 krux-v23.09.0/ktool-mac-10
6843031 2023-09-12 22:14 krux-v23.09.0/ktool-win.exe
0 2023-09-12 22:21 krux-v23.09.0/maixpy_m5stickv/
1897920 2023-09-12 22:14 krux-v23.09.0/maixpy_m5stickv/firmware.bin
935564 2023-09-12 22:14 krux-v23.09.0/maixpy_m5stickv/kboot.kfpkg
70 2023-09-12 22:23 krux-v23.09.0/maixpy_m5stickv/firmware.bin.sig
0 2023-09-12 22:23 krux-v23.09.0/maixpy_amigo_ips/
1902592 2023-09-12 22:15 krux-v23.09.0/maixpy_amigo_ips/firmware.bin
935735 2023-09-12 22:15 krux-v23.09.0/maixpy_amigo_ips/kboot.kfpkg
70 2023-09-12 22:23 krux-v23.09.0/maixpy_amigo_ips/firmware.bin.sig
0 2023-09-12 22:24 krux-v23.09.0/maixpy_amigo_tft/
1902592 2023-09-12 22:16 krux-v23.09.0/maixpy_amigo_tft/firmware.bin
935729 2023-09-12 22:16 krux-v23.09.0/maixpy_amigo_tft/kboot.kfpkg
70 2023-09-12 22:24 krux-v23.09.0/maixpy_amigo_tft/firmware.bin.sig
0 2023-09-12 22:24 krux-v23.09.0/maixpy_bit/
1890816 2023-09-12 22:17 krux-v23.09.0/maixpy_bit/firmware.bin
933632 2023-09-12 22:17 krux-v23.09.0/maixpy_bit/kboot.kfpkg
70 2023-09-12 22:24 krux-v23.09.0/maixpy_bit/firmware.bin.sig
0 2023-09-12 22:24 krux-v23.09.0/maixpy_dock/
1890816 2023-09-12 22:17 krux-v23.09.0/maixpy_dock/firmware.bin
933619 2023-09-12 22:17 krux-v23.09.0/maixpy_dock/kboot.kfpkg
70 2023-09-12 22:24 krux-v23.09.0/maixpy_dock/firmware.bin.sig
--------- -------
48321412 25 files
Inflated firmware.bin
and firmware.bin.sig
, and got sha256 hashes for those binaries.
unzip -e ~/Downloads/krux-v23.09.0.zip krux-v23.09.0/maixpy_amigo_tft/firmware.bin
unzip -e ~/Downloads/krux-v23.09.0.zip krux-v23.09.0/maixpy_amigo_tft/firmware.bin.sig
sha256sum krux-v23.09.0/maixpy_amigo_tft/*
2da65b95435eff19a10fb0d88479bd7a7a86134577a972ab9012790dcac7e3c9 krux-v23.09.0/maixpy_amigo_tft/firmware.bin
4c51d4cc2facffb2e59db08266396095a30cd66108262b723ac1ba13759928cf krux-v23.09.0/maixpy_amigo_tft/firmware.bin.sig
and put both files in root directory of a vfat microsd card.
Booting amigo with microsd card, confirmed new firmware w/ correct hash.
upgrading firmware
backing up bootloader
updating bootloader
shutting down.
Removed sdcard, held power for 6 seconds, powered back on, now krux shows version 23.09.0.
Back in the usb console to analyze_spi_flash after upgrading from v22.08.2 to v23.9.0
>>> analyze_spi_flash()
Checking "Kboot stage-0" from 0x0 to 0x1000-1
SPI flash from 0x0 to 0x1000-1 is valid.
sha256 hash of "bootloader_lo.bin" having 608 bytes is:
2e050a92efdcb172cb5c6f7cb0b669ba654d2d20219f810fd9fc543f7ef05c3e
Checking "Kboot stage-1" from 0x1000 to 0x4000-1
SPI flash from 0x1000 to 0x3000-1 is valid.
sha256 hash of "bootloader_hi.bin" having 8112 bytes is:
f005f7c8b13aa2719cad58492a8432f14b68b2f845b58e5b5e81ed6309be6172
SPI flash from 0x3000 to 0x4000-1 is all 0xff.
Checking "main config" from 0x4000 to 0x5000-1
sha256 hash of "config.bin" having 4096 bytes is:
7d454bbe28244529f4bca414883a208b60f860b00cdaf8ab50bc4fafa038819c
Checking "backup config" from 0x5000 to 0x6000-1
sha256 hash of SPI flash from 0x5000 to 0x6000-1 is:
c9b9c4adcabe9c353a907f44c101c3b29756b30762e4b282d87d2a92400e2198
Checking "reserved" from 0x6000 to 0x10000-1
SPI flash from 0x6000 to 0x10000-1 is all 0xff.
Checking "unused app/user" from 0x10000 to 0x80000-1
SPI flash from 0x10000 to 0x80000-1 is all 0xff.
Checking "firmware_slot1" from 0x80000 to 0x230000-1
SPI flash from 0x80000 to 0x230000-1 is valid.
sha256 hash of "firmware.bin" having 1716288 bytes is:
5067429beb16bd0eac55401ea673f55f9cc97585b1a0607d64f8e5f486d4988b
Checking "unused app/user" from 0x230000 to 0x280000-1
SPI flash from 0x230000 to 0x280000-1 is all 0xff.
Checking "firmware_slot2" from 0x280000 to 0x460000-1
SPI flash from 0x280000 to 0x460000-1 is valid.
sha256 hash of "firmware.bin" having 1902592 bytes is:
2da65b95435eff19a10fb0d88479bd7a7a86134577a972ab9012790dcac7e3c9
Checking "unused app/user" from 0x460000 to 0xd00000-1
SPI flash from 0x460000 to 0xd00000-1 is all 0xff.
Checking "SPI Flash Filing System" from 0xd00000 to 0x1000000-1
sha256 hash of "SPI Flash Filing System" having 3145728 bytes is:
eb438b1b25cdc59e90c28072c88910e913fc4b36abf165025055f0202d6fed55
Checking "SPI flash" from 0x0 to 0x1000000-1
sha256 hash of "16MB SPI flash" having 16777216 bytes is:
73283f944f73b980120e3684daa756f73dc94696bff24c71c18bb6ac3a846fb5
Summary of what changed:
- kboot stage0 is unchanged
- kboot stage1 is unchanged
- main config has changed
- backup config is unchanged, but only because it got backed-up from main config during the upgrade.
- v22.08.2 firmware is still in slot1
- v23.09.0 firmware is now in slot2
- SPIFFS has changed but I never took a look originally. It's expected with any new settings.
Hex dumping the main config which changed, and the backup config which has the original.
>>> hd = HexDumpSPIFlash(0x4000, lines=45, width=32)
>>> hd.run()
004000 5a a5 d0 cd 00 28 00 00 00 1d 08 00 24 c6 ab aa 66 69 72 6d 77 61 72 65 00 00 00 00 00 00 00 00 |Z....(......$...firmware........|
004020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................................|
... 6 squeezed
004100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................................|
004120 5a a5 d0 cf 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |Z...............................|
004140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................................|
... 116 squeezed
004fe0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................................|
005000 5a a5 d0 c5 00 08 00 00 00 1a a0 00 24 c6 ab aa 66 69 72 6d 77 61 72 65 00 00 00 00 00 00 00 00 |Z...........$...firmware........|
005020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................................|
... 6 squeezed
005100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................................|
005120 5a a5 d0 cf 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |Z...............................|
005140 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................................|
... 116 squeezed
005fe0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................................|
Main config starts at 0x4000. Backup config starts at 0x5000
Docs are https://github.com/loboris/Kboot/blob/master/Kboot.md
Each config entry is 32 bytes, an entire line above, and kboot supports 8 entries.
The first 4 bytes always start like "0x5aa5d0c*" and the last nible is a 4 bit mask called "Entry flags", they are
- 0001 = This is the ACTIVE flag, if set, this is the active configuration to use.
- 0010 = this is the CRC32 flag, if set, the app's calculated CRC32 value must match the configuration's CRC32 value.
- 0100 = This is the AES256 flag, if set, the app's calculated AES256 value must match after the application sha256 hash.
- 1000 = this is the SIZE flag, if set, the app's size must match the configuration's size value.
We can see that main configuration has Entry flags of "D"=1101 (Check SIZE, Check AES256, Ignore CRC32, Is ACTIVE) We can see its backup configuration had Entry flags of "5"=0101 (Ignore SIZE, Check AES256, Ignore CRC32, Is ACTIVE)
The next 4 bytes, as a big-endian int, are the location of the application in SPI Flash. We can see that it was at 0x80000 in the backup config and that it is now at 0x280000 in main config.
The next 4 bytes, as a big-endian int, are the application size. We can see that the backup config indicates the application size was 1744896 when up above we see that it was really 1716288, but because the configuration entry flag was "5"=0101, the highest SIZE flag was not set and there were no problems. In the new configuration which uses "D"=1101, the highest SIZE flag is set and we have a matching size in configuration of 1902592 in slot 2.
The next 4 bytes are the application's CRC32 value, in both cases above they are 0x24 0xc6 0xab 0xaa bytes, but according to the configuration, they're not used and I don't know what they mean, just that they came from config.bin
within the kboot.kfpkg
archive.
The next 16 bytes are the application name or description, in our case, it's "firmware" follwed by 8 null bytes.
Hex dumping the SPI Flash File System
>>> hd = HexDumpSPIFlash(0xd00000, lines=45, width=32)
>>> hd.run()
d00000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 80 01 00 ff ff ff ff ff ff ff ff |................................|
d00020 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 124 squeezed
d00fc0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
d00fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 31 15 00 00 |............................1...|
d01000 01 80 00 00 7e 00 00 00 2f 00 00 00 01 2f 73 65 74 74 69 6e 67 73 2e 6a 73 6f 6e 00 00 00 00 00 |....~.../..../settings.json.....|
d01020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................................|
... 1 squeezed
d01060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................................|
d01080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
d010a0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 121 squeezed
d01fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
d02000 01 00 00 00 7e 7b 22 73 65 74 74 69 6e 67 73 22 3a 20 7b 22 61 70 70 65 61 72 61 6e 63 65 22 3a |....~{"settings": {"appearance":|
d02020 20 7b 22 74 68 65 6d 65 22 3a 20 22 44 61 72 6b 22 7d 7d 7d ff ff ff ff ff ff ff ff ff ff ff ff | {"theme": "Dark"}}}............|
d02040 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 124 squeezed
d02fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
d03000 01 80 00 00 7e 00 00 00 51 00 00 00 01 2f 73 65 74 74 69 6e 67 73 2e 6a 73 6f 6e 00 00 00 00 00 |....~...Q..../settings.json.....|
d03020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................................|
... 1 squeezed
d03060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................................|
d03080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
d030a0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 121 squeezed
d03fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
d04000 01 00 00 00 7e 7b 22 73 65 74 74 69 6e 67 73 22 3a 20 7b 22 74 6f 75 63 68 73 63 72 65 65 6e 22 |....~{"settings": {"touchscreen"|
d04020 3a 20 7b 22 74 68 72 65 73 68 6f 6c 64 22 3a 20 32 32 7d 2c 20 22 61 70 70 65 61 72 61 6e 63 65 |: {"threshold": 22}, "appearance|
d04040 22 3a 20 7b 22 74 68 65 6d 65 22 3a 20 22 44 61 72 6b 22 7d 7d 7d ff ff ff ff ff ff ff ff ff ff |": {"theme": "Dark"}}}..........|
d04060 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 123 squeezed
d04fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
d05000 01 80 00 00 7e 00 00 00 7b 00 00 00 01 2f 73 65 74 74 69 6e 67 73 2e 6a 73 6f 6e 00 00 00 00 00 |....~...{..../settings.json.....|
d05020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................................|
... 1 squeezed
d05060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................................|
d05080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 06 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
d050a0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 121 squeezed
d05fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
d06000 01 00 00 00 7e 7b 22 73 65 74 74 69 6e 67 73 22 3a 20 7b 22 61 70 70 65 61 72 61 6e 63 65 22 3a |....~{"settings": {"appearance":|
d06020 20 7b 22 74 68 65 6d 65 22 3a 20 22 44 61 72 6b 22 7d 2c 20 22 6c 6f 67 22 3a 20 7b 22 70 61 74 | {"theme": "Dark"}, "log": {"pat|
d06040 68 22 3a 20 22 2f 73 64 2f 2e 6b 72 75 78 2e 6c 6f 67 22 2c 20 22 6c 65 76 65 6c 22 3a 20 39 39 |h": "/sd/.krux.log", "level": 99|
d06060 7d 2c 20 22 69 31 38 6e 22 3a 20 7b 22 6c 6f 63 61 6c 65 22 3a 20 22 65 6e 2d 55 53 22 7d 7d 7d |}, "i18n": {"locale": "en-US"}}}|
d06080 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
d060a0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 121 squeezed
d06fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
d07000 01 80 00 00 7e 00 00 00 9d 00 00 00 01 2f 73 65 74 74 69 6e 67 73 2e 6a 73 6f 6e 00 00 00 00 00 |....~......../settings.json.....|
d07020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................................|
... 1 squeezed
d07060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................................|
d07080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 08 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
d070a0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 121 squeezed
d07fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
d08000 01 00 00 00 7e 7b 22 73 65 74 74 69 6e 67 73 22 3a 20 7b 22 61 70 70 65 61 72 61 6e 63 65 22 3a |....~{"settings": {"appearance":|
d08020 20 7b 22 74 68 65 6d 65 22 3a 20 22 44 61 72 6b 22 7d 2c 20 22 6c 6f 67 22 3a 20 7b 22 70 61 74 | {"theme": "Dark"}, "log": {"pat|
d08040 68 22 3a 20 22 2f 73 64 2f 2e 6b 72 75 78 2e 6c 6f 67 22 2c 20 22 6c 65 76 65 6c 22 3a 20 39 39 |h": "/sd/.krux.log", "level": 99|
d08060 7d 2c 20 22 74 6f 75 63 68 73 63 72 65 65 6e 22 3a 20 7b 22 74 68 72 65 73 68 6f 6c 64 22 3a 20 |}, "touchscreen": {"threshold": |
d08080 32 32 7d 2c 20 22 69 31 38 6e 22 3a 20 7b 22 6c 6f 63 61 6c 65 22 3a 20 22 65 6e 2d 55 53 22 7d |22}, "i18n": {"locale": "en-US"}|
d080a0 7d 7d ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |}}..............................|
d080c0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 120 squeezed
d08fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
d09000 01 80 00 00 7e 00 00 00 bb 00 00 00 01 2f 73 65 74 74 69 6e 67 73 2e 6a 73 6f 6e 00 00 00 00 00 |....~......../settings.json.....|
d09020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................................|
... 1 squeezed
d09060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................................|
d09080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0a 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
d090a0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 121 squeezed
d09fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
d0a000 01 00 00 00 7e 7b 22 73 65 74 74 69 6e 67 73 22 3a 20 7b 22 6c 6f 67 67 69 6e 67 22 3a 20 7b 22 |....~{"settings": {"logging": {"|
d0a020 6c 65 76 65 6c 22 3a 20 22 4e 4f 4e 45 22 7d 2c 20 22 74 6f 75 63 68 73 63 72 65 65 6e 22 3a 20 |level": "NONE"}, "touchscreen": |
d0a040 7b 22 74 68 72 65 73 68 6f 6c 64 22 3a 20 32 32 7d 2c 20 22 61 70 70 65 61 72 61 6e 63 65 22 3a |{"threshold": 22}, "appearance":|
d0a060 20 7b 22 74 68 65 6d 65 22 3a 20 22 44 61 72 6b 22 7d 2c 20 22 6c 6f 67 22 3a 20 7b 22 70 61 74 | {"theme": "Dark"}, "log": {"pat|
d0a080 68 22 3a 20 22 2f 73 64 2f 2e 6b 72 75 78 2e 6c 6f 67 22 2c 20 22 6c 65 76 65 6c 22 3a 20 39 39 |h": "/sd/.krux.log", "level": 99|
d0a0a0 7d 2c 20 22 69 31 38 6e 22 3a 20 7b 22 6c 6f 63 61 6c 65 22 3a 20 22 65 6e 2d 55 53 22 7d 7d 7d |}, "i18n": {"locale": "en-US"}}}|
d0a0c0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 120 squeezed
d0afe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
d0b000 01 80 00 00 f8 00 00 00 db 00 00 00 01 2f 73 65 74 74 69 6e 67 73 2e 6a 73 6f 6e 00 00 00 00 00 |............./settings.json.....|
d0b020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................................|
... 1 squeezed
d0b060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................................|
d0b080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0c 00 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
d0b0a0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 121 squeezed
d0bfe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
d0c000 01 00 00 00 fc 7b 22 73 65 74 74 69 6e 67 73 22 3a 20 7b 22 6c 6f 67 67 69 6e 67 22 3a 20 7b 22 |.....{"settings": {"logging": {"|
d0c020 6c 65 76 65 6c 22 3a 20 22 4e 4f 4e 45 22 7d 2c 20 22 62 69 74 63 6f 69 6e 22 3a 20 7b 22 6e 65 |level": "NONE"}, "bitcoin": {"ne|
d0c040 74 77 6f 72 6b 22 3a 20 22 6d 61 69 6e 22 7d 2c 20 22 74 6f 75 63 68 73 63 72 65 65 6e 22 3a 20 |twork": "main"}, "touchscreen": |
d0c060 7b 22 74 68 72 65 73 68 6f 6c 64 22 3a 20 32 32 7d 2c 20 22 61 70 70 65 61 72 61 6e 63 65 22 3a |{"threshold": 22}, "appearance":|
d0c080 20 7b 22 74 68 65 6d 65 22 3a 20 22 44 61 72 6b 22 7d 2c 20 22 6c 6f 67 22 3a 20 7b 22 70 61 74 | {"theme": "Dark"}, "log": {"pat|
d0c0a0 68 22 3a 20 22 2f 73 64 2f 2e 6b 72 75 78 2e 6c 6f 67 22 2c 20 22 6c 65 76 65 6c 22 3a 20 39 39 |h": "/sd/.krux.log", "level": 99|
d0c0c0 7d 2c 20 22 69 31 38 6e 22 3a 20 7b 22 6c 6f 63 61 6c 65 22 3a 20 22 65 6e 2d 55 53 22 7d 7d 7d |}, "i18n": {"locale": "en-US"}}}|
d0c0e0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 2678 squeezed
d20fc0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
d20fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 3e 15 00 00 |............................>...|
d21000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 4093 squeezed
d40fc0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
d40fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 3f 15 00 00 |............................?...|
d41000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 4093 squeezed
d60fc0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
d60fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 3c 15 00 00 |............................<...|
d61000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 4093 squeezed
d80fc0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
d80fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 3d 15 00 00 |............................=...|
d81000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 4093 squeezed
da0fc0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
da0fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 3a 15 00 00 |............................:...|
da1000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 4093 squeezed
dc0fc0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
dc0fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 3b 15 00 00 |............................;...|
dc1000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 4093 squeezed
de0fc0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
de0fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 38 15 00 00 |............................8...|
de1000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 4093 squeezed
e00fc0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
e00fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 39 15 00 00 |............................9...|
e01000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 4093 squeezed
e20fc0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
e20fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 26 15 00 00 |............................&...|
e21000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 4093 squeezed
e40fc0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
e40fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 27 15 00 00 |............................'...|
e41000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 4093 squeezed
e60fc0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
e60fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 24 15 00 00 |............................$...|
e61000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 4093 squeezed
e80fc0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
e80fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 25 15 00 00 |............................%...|
e81000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 4093 squeezed
ea0fc0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
ea0fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 22 15 00 00 |............................"...|
ea1000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 4093 squeezed
ec0fc0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
ec0fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 23 15 00 00 |............................#...|
ec1000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 4093 squeezed
ee0fc0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
ee0fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 20 15 00 00 |............................ ...|
ee1000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 4093 squeezed
f00fc0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
f00fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 21 15 00 00 |............................!...|
f01000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 4093 squeezed
f20fc0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
f20fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 2e 15 00 00 |................................|
f21000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 4093 squeezed
f40fc0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
f40fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 2f 15 00 00 |............................/...|
f41000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 4093 squeezed
f60fc0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
f60fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 2c 15 00 00 |............................,...|
f61000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 4093 squeezed
f80fc0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
f80fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 2d 15 00 00 |............................-...|
f81000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 4093 squeezed
fa0fc0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
fa0fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 2a 15 00 00 |............................*...|
fa1000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
fa1020 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 4092 squeezed
fc0fc0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
fc0fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 2b 15 00 00 |............................+...|
fc1000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 4093 squeezed
fe0fc0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
fe0fe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff 28 15 00 00 |............................(...|
fe1000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|
... 3966 squeezed
ffffe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................................|