170 lines
4.4 KiB
Python
170 lines
4.4 KiB
Python
# (c) Copyright 2018 by Coinkite Inc. This file is covered by license found in COPYING-CC.
|
|
#
|
|
# main.py
|
|
#
|
|
# - importing this file starts the system, see "go()"
|
|
# - NO: main.loop is imported and "run forever" by boot.py, forced into place by COLDCARD/initfs code
|
|
# - cannot be changed by /flash/lib overrides, because already imported before that.
|
|
#
|
|
|
|
# see RAM_HEADER_BASE, and coldcardFirmwareHeader_t in sigheader.h
|
|
import pyb, sys, gc, glob
|
|
from imptask import IMPT, die_with_debug
|
|
|
|
assert not glob.dis, "main reimport"
|
|
|
|
# this makes the GC run when larger objects are free in an attempt to reduce fragmentation.
|
|
gc.threshold(4096)
|
|
|
|
# useful for debug: start serial port early, when possible
|
|
try:
|
|
from h import *
|
|
import ckcc
|
|
ckcc.vcp_enabled(True)
|
|
except:
|
|
# above will fail on release build, because:
|
|
# - 'h.py' not included
|
|
# - excludes serial port code access completely (see vcp_lockdown.c)
|
|
pass
|
|
|
|
# Sometimes useful: die early for debug
|
|
#raise SystemExit
|
|
|
|
print("---\nColdcard Wallet from Coinkite Inc. (c) 2018-2024.")
|
|
|
|
import version
|
|
datestamp,vers,_ = version.get_mpy_version()
|
|
print("Version: %s / %s\n" % (vers, datestamp))
|
|
|
|
# Setup display and get something onto it.
|
|
if version.has_qwerty:
|
|
from lcd_display import Display
|
|
else:
|
|
from display import Display
|
|
|
|
dis = Display()
|
|
dis.splash()
|
|
glob.dis = dis
|
|
|
|
# Slowish imports, some with side-effects
|
|
import ckcc, uasyncio
|
|
|
|
# Early setup code
|
|
try:
|
|
if version.has_qwerty:
|
|
import q1
|
|
q1.init0()
|
|
else:
|
|
import mk4
|
|
mk4.init0()
|
|
|
|
from psram import PSRAMWrapper
|
|
glob.PSRAM = PSRAMWrapper()
|
|
|
|
except: pass # continue tho
|
|
|
|
# Setup keypad/keyboard
|
|
if version.has_qwerty:
|
|
from keyboard import FullKeyboard
|
|
numpad = FullKeyboard()
|
|
glob.numpad = numpad
|
|
else:
|
|
from mempad import MembraneNumpad
|
|
numpad = MembraneNumpad()
|
|
glob.numpad = numpad
|
|
|
|
# NV settings
|
|
from nvstore import SettingsObject
|
|
settings = SettingsObject()
|
|
settings.load(glob.dis)
|
|
glob.settings = settings
|
|
|
|
async def more_setup():
|
|
# Boot up code; splash screen is being shown
|
|
|
|
try:
|
|
from files import CardSlot
|
|
CardSlot.setup()
|
|
|
|
# This "pa" object holds some state shared w/ bootloader about the PIN
|
|
try:
|
|
from pincodes import pa
|
|
pa.setup(b'') # just to see where we stand.
|
|
is_blank = pa.is_blank()
|
|
except RuntimeError as e:
|
|
is_blank = True
|
|
print("Problem: %r" % e)
|
|
|
|
if version.is_factory_mode:
|
|
print("factory mode")
|
|
# in factory mode, turn on USB early to allow debug/setup
|
|
from usb import enable_usb
|
|
enable_usb()
|
|
|
|
# always start the self test.
|
|
if not settings.get('tested', False):
|
|
from actions import start_selftest
|
|
await start_selftest()
|
|
|
|
elif is_blank:
|
|
# force them to accept terms (unless marked as already done in settings)
|
|
# only if no main PIN chosen
|
|
from actions import accept_terms
|
|
await accept_terms()
|
|
|
|
# Prompt for PIN and then pick appropriate top-level menu,
|
|
# based on contents of secure chip (ie. is there a wallet defined)
|
|
from actions import start_login_sequence
|
|
await start_login_sequence()
|
|
except BaseException as exc:
|
|
die_with_debug(exc)
|
|
|
|
# define contents of main menu
|
|
from actions import goto_top_menu
|
|
goto_top_menu()
|
|
|
|
# fetch this function for mainline to use
|
|
from ux import the_ux
|
|
doit = the_ux.interact
|
|
|
|
IMPT.start_task('mainline', mainline(doit))
|
|
|
|
async def mainline(doit):
|
|
# Mainline of program, after startup. Never stops.
|
|
#
|
|
# - Do not add to this function, its vars are
|
|
# in memory forever; instead, extend more_setup() above.
|
|
|
|
gc.collect()
|
|
#print("Free mem: %d" % gc.mem_free()) # 515536 on mk4!
|
|
|
|
while 1:
|
|
await doit()
|
|
|
|
|
|
def go():
|
|
# Wrapper for better error handling/recovery at top level.
|
|
#
|
|
try:
|
|
uasyncio.get_event_loop().run_forever()
|
|
raise RuntimeError('main.stop') # not expected
|
|
except BaseException as exc:
|
|
die_with_debug(exc)
|
|
|
|
if version.is_devmode:
|
|
# Start some debug-only code.
|
|
try:
|
|
import dev_helper
|
|
dev_helper.setup()
|
|
except: pass
|
|
|
|
# Simulator code
|
|
try:
|
|
import sim_quickstart
|
|
except: pass
|
|
|
|
uasyncio.create_task(more_setup())
|
|
go()
|
|
|
|
# EOF
|