137 lines
4.2 KiB
Python
137 lines
4.2 KiB
Python
# (c) Copyright 2018 by Coinkite Inc. This file is covered by license found in COPYING-CC.
|
|
#
|
|
# version.py - Get lots of different version numbers from stuff.
|
|
#
|
|
# REMINDER: update simulator version of this file if API changes are made.
|
|
#
|
|
from public_constants import MAX_TXN_LEN_MK4 as MAX_TXN_LEN
|
|
from public_constants import MAX_UPLOAD_LEN_MK4 as MAX_UPLOAD_LEN
|
|
|
|
def decode_firmware_header(hdr):
|
|
from sigheader import FWH_PY_FORMAT
|
|
import ustruct
|
|
|
|
magic_value, timestamp, version_string = ustruct.unpack_from(FWH_PY_FORMAT, hdr)[0:3]
|
|
|
|
parts = ['%02x'%i for i in timestamp]
|
|
date = '20' + '-'.join(parts[0:3])
|
|
|
|
vers = bytes(version_string).rstrip(b'\0').decode()
|
|
|
|
return date, vers, ''.join(parts[:-2])
|
|
|
|
def get_fw_header():
|
|
# located in our own flash
|
|
from sigheader import FLASH_HEADER_BASE_MK4, FW_HEADER_SIZE
|
|
import uctypes
|
|
|
|
global mk_num
|
|
|
|
return uctypes.bytes_at(FLASH_HEADER_BASE_MK4,
|
|
FW_HEADER_SIZE)
|
|
|
|
def get_mpy_version():
|
|
# read my own file header
|
|
# see stm32/bootloader/sigheader.h
|
|
|
|
try:
|
|
hdr = get_fw_header()
|
|
return decode_firmware_header(hdr)
|
|
except:
|
|
# this is early in boot process, so don't fail!
|
|
return '20YY-MM-DD', '?.??', '180731121314'
|
|
|
|
def get_header_value(fld_name):
|
|
# get a single value, raw, from header; based on field name
|
|
from sigheader import FWH_PY_FORMAT, FWH_PY_VALUES
|
|
import ustruct
|
|
|
|
idx = FWH_PY_VALUES.split().index(fld_name)
|
|
hdr = get_fw_header()
|
|
|
|
return ustruct.unpack_from(FWH_PY_FORMAT, hdr)[idx]
|
|
|
|
def nfc_presence_check():
|
|
# Does NFC hardware exist on this board?
|
|
# SDA/SCL will be tied low
|
|
from machine import Pin
|
|
return Pin('NFC_SDA', mode=Pin.IN).value() or Pin('NFC_SCL', mode=Pin.IN).value()
|
|
|
|
def get_is_devmode():
|
|
# what firmware signing key did we boot with? are we in dev mode?
|
|
import ckcc
|
|
return ckcc.is_debug_build()
|
|
|
|
|
|
def serial_number():
|
|
# Our USB serial number, both in DFU mode (system boot ROM), and later thanks to code in
|
|
# USBD_StrDescriptor()
|
|
#
|
|
# - this is **probably** public info, since shared freely over USB during enumeration
|
|
#
|
|
import machine
|
|
i = machine.unique_id()
|
|
return "%02X%02X%02X%02X%02X%02X" % (i[11], i[10] + i[2], i[9], i[8] + i[0], i[7], i[6])
|
|
|
|
def probe_system():
|
|
# run-once code to determine what hardware we are running on
|
|
global hw_label, has_608, is_factory_mode, is_devmode, has_psram, is_edge
|
|
global has_se2, mk_num, has_nfc, has_qr, num_sd_slots, has_qwerty, has_battery, supports_hsm
|
|
|
|
from sigheader import RAM_BOOT_FLAGS, RBF_FACTORY_MODE
|
|
import ckcc, callgate, machine
|
|
from machine import Pin
|
|
|
|
hw_label = 'mk4'
|
|
has_608 = True
|
|
has_qr = False # QR scanner
|
|
num_sd_slots = 1 # might have dual slots on Q1
|
|
mk_num = 4
|
|
has_battery = False
|
|
has_qwerty = False
|
|
is_edge = False
|
|
supports_hsm = True
|
|
has_nfc = nfc_presence_check() # hardware present; they might not use it.
|
|
|
|
cpuid = ckcc.get_cpu_id()
|
|
assert cpuid == 0x470 # STM32L4S5VI
|
|
|
|
# detect Q1 based on pins.csv
|
|
try:
|
|
Pin('LCD_TEAR') # only defined on Q1 build, will error otherwise
|
|
has_qr = True
|
|
num_sd_slots = 2
|
|
hw_label = 'q1'
|
|
has_battery = True
|
|
has_qwerty = True
|
|
supports_hsm = False
|
|
# but, still mk_num = 4
|
|
except ValueError:
|
|
pass
|
|
|
|
try:
|
|
# only defined on Mk4/5 build, will error otherwise; was open on Mk1-4, low on Mk5
|
|
s0 = Pin('STRAP_MK5', mode=Pin.IN, pull=Pin.PULL_UP)
|
|
if s0() == 0:
|
|
hw_label = 'mk5'
|
|
mk_num = 5
|
|
except ValueError:
|
|
pass
|
|
|
|
# Boot loader needs to tell us stuff about how we were booted, sometimes:
|
|
# - did we just install a new version, for example (obsolete in mk4)
|
|
# - are we running in "factory mode" with flash un-secured?
|
|
is_factory_mode = callgate.get_factory_mode()
|
|
|
|
bn = callgate.get_bag_number()
|
|
if bn:
|
|
# this path supports testing/dev with RDP!=2, which normal production bootroms enforce
|
|
is_factory_mode = False
|
|
|
|
# what firmware signing key did we boot with? are we in dev mode?
|
|
is_devmode = get_is_devmode()
|
|
|
|
probe_system()
|
|
|
|
# EOF
|