diff --git a/core/embed/extmod/modtrezorui/display-unix.h b/core/embed/extmod/modtrezorui/display-unix.h index bb261b990..9a472c065 100644 --- a/core/embed/extmod/modtrezorui/display-unix.h +++ b/core/embed/extmod/modtrezorui/display-unix.h @@ -19,7 +19,9 @@ #include #include +#include #include +#include "profile.h" #define EMULATOR_BORDER 16 @@ -96,8 +98,14 @@ void display_init(void) { ensure(secfalse, "SDL_Init error"); } atexit(SDL_Quit); + + char *window_title; + if (!asprintf(&window_title, "TREZOR^emu: %s", profile_name())) { + window_title = "TREZOR^emu"; + } + SDL_Window *win = - SDL_CreateWindow("TREZOR Emulator", SDL_WINDOWPOS_UNDEFINED, + SDL_CreateWindow(window_title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WINDOW_WIDTH, WINDOW_HEIGHT, #ifdef TREZOR_EMULATOR_RASPI SDL_WINDOW_SHOWN | SDL_WINDOW_FULLSCREEN diff --git a/core/embed/extmod/modtrezorui/display.c b/core/embed/extmod/modtrezorui/display.c index fedda40ab..056cf166b 100644 --- a/core/embed/extmod/modtrezorui/display.c +++ b/core/embed/extmod/modtrezorui/display.c @@ -17,6 +17,8 @@ * along with this program. If not, see . */ +#define _GNU_SOURCE + #include "font_bitmap.h" #include "inflate.h" #ifdef TREZOR_FONT_NORMAL_ENABLE diff --git a/core/embed/unix/common.c b/core/embed/unix/common.c index 00767b1b6..a5898175d 100644 --- a/core/embed/unix/common.c +++ b/core/embed/unix/common.c @@ -25,9 +25,11 @@ #include "display.h" #include "memzero.h" +extern void main_clean_exit(); + void __shutdown(void) { printf("SHUTDOWN\n"); - exit(3); + main_clean_exit(); } #define COLOR_FATAL_ERROR RGB16(0x7F, 0x00, 0x00) diff --git a/core/embed/unix/main.c b/core/embed/unix/main.c index c31c260ab..0d24c668e 100644 --- a/core/embed/unix/main.c +++ b/core/embed/unix/main.c @@ -40,7 +40,6 @@ #include "extmod/misc.h" #include "genhdr/mpversion.h" #include "input.h" -#include "profile.h" #include "py/builtin.h" #include "py/compile.h" #include "py/gc.h" @@ -406,6 +405,18 @@ STATIC void set_sys_argv(char *argv[], int argc, int start_arg) { } } +void main_clean_exit() { + fflush(stdout); + fflush(stderr); + mp_obj_t sys_exit = + mp_obj_dict_get(mp_module_sys.globals, MP_ROM_QSTR(MP_QSTR_exit)); + if (mp_obj_is_callable(sys_exit)) { + mp_call_function_1(MP_OBJ_TO_PTR(sys_exit), MP_OBJ_NEW_SMALL_INT(3)); + } + // sys.exit shouldn't return so force exit in case it does. + exit(3); +} + #ifdef _WIN32 #define PATHLIST_SEP_CHAR ';' #else @@ -415,9 +426,6 @@ STATIC void set_sys_argv(char *argv[], int argc, int start_arg) { MP_NOINLINE int main_(int argc, char **argv); int main(int argc, char **argv) { - // Through TREZOR_PROFILE you can set the directory for trezor.flash file. - profile_init(); - collect_hw_entropy(); #if MICROPY_PY_THREAD diff --git a/core/embed/unix/profile.c b/core/embed/unix/profile.c index 443deae35..78a7403ef 100644 --- a/core/embed/unix/profile.c +++ b/core/embed/unix/profile.c @@ -18,112 +18,51 @@ */ #define _GNU_SOURCE -#include #include #include -#include -#include -#include -#include -#include "common.h" #include "profile.h" -static int mkpath(const char *path, mode_t mode) { - if (!path) { - errno = EINVAL; - return 1; +#define SVAR(varname) \ + static char *varname; \ + if (varname) { \ + return varname; \ } - struct stat sb; - if (!stat(strdup(path), &sb)) { - return 0; +#define GETENV(varname, envname, fallback) \ + varname = getenv(envname); \ + if (!varname) { \ + varname = fallback; \ } - // dirname has multiple incompatible implementations. - // Some modify input argument some share output buffer. - char *pathdup = strdup(path); - char *subpath = strdup(dirname(pathdup)); - mkpath(subpath, mode); - free(pathdup); - free(subpath); - return mkdir(path, mode); -} - -void profile_init(void) { - const char *dir = profile_dir(); - if (mkpath(dir, 0755)) { - perror(dir); - printf("!!! Unable to initialize profile directory `%s`. Quitting\n", dir); - exit(1); +#define FILE_PATH(varname, filename) \ + if (asprintf(&varname, "%s/" filename, profile_dir()) < 0) { \ + varname = NULL; \ + } \ + if (!varname) { \ + varname = PROFILE_DIR_DEFAULT filename; \ } - printf("Profile directory: %s\n", dir); + +const char *profile_name(void) { + SVAR(_profile_name); + GETENV(_profile_name, "TREZOR_PROFILE_NAME", PROFILE_NAME_DEFAULT); + return _profile_name; } const char *profile_dir(void) { - static const char *_profile_dir; - - if (_profile_dir) { - return _profile_dir; - } - - char *trezor_profile = getenv("TREZOR_PROFILE"); - if (!trezor_profile || strlen(trezor_profile) < 1) { - trezor_profile = PROFILE_DEFAULT; - } - - char *path; - if (trezor_profile[0] == '/') { - // TREZOR_PROFILE is a full path to profile directory - path = strdup(trezor_profile); - } else { - // TREZOR_PROFILE is just a profile name and will be put in ~/.trezoremu/ - int print_length = asprintf(&path, "%s/" PROFILE_HOMEDOT "/%s", - getenv("HOME"), trezor_profile); - if (print_length == -1) { - path = NULL; - } - } - - if (!path) { // last resort fallback - path = PROFILE_DEFAULT; - } - - _profile_dir = path; - + SVAR(_profile_dir); + GETENV(_profile_dir, "TREZOR_PROFILE_DIR", PROFILE_DIR_DEFAULT); return _profile_dir; } const char *profile_flash_path(void) { - static char *_flash_path; - if (_flash_path) { - return _flash_path; - } - - if (asprintf(&_flash_path, "%s/trezor.flash", profile_dir()) < 0) { - _flash_path = NULL; - } - - if (!_flash_path) { // last resort fallback - _flash_path = PROFILE_DEFAULT "/trezor.flash"; - } - + SVAR(_flash_path); + FILE_PATH(_flash_path, "/trezor.flash"); return _flash_path; } const char *profile_sdcard_path(void) { - static char *_sdcard_path; - if (_sdcard_path) { - return _sdcard_path; - } - - if (asprintf(&_sdcard_path, "%s/trezor.sdcard", profile_dir()) < 0) { - _sdcard_path = NULL; - } - - if (!_sdcard_path) { // last resort fallback - _sdcard_path = PROFILE_DEFAULT "/trezor.sdcard"; - } - + SVAR(_sdcard_path); + FILE_PATH(_sdcard_path, "/trezor.sdcard"); return _sdcard_path; } diff --git a/core/embed/unix/profile.h b/core/embed/unix/profile.h index 0a15c4023..6fa657f25 100644 --- a/core/embed/unix/profile.h +++ b/core/embed/unix/profile.h @@ -20,20 +20,16 @@ #ifndef __TREZOR_PROFILE_H__ #define __TREZOR_PROFILE_H__ -// TREZOR_PROFILE environment variable can be a full path -// or just a name that will result in the path: -// ~/${PROFILE_HOMEDOT}/${TREZOR_PROFILE} -// If the variable is not set the default is ${PROFILE_DEFAULT} +// Environment variables meaning: +// TREZOR_PROFILE_NAME sets the title of the emulator window. +// TREZOR_PROFILE_DIR contains flash files. +// +// If those are not set int the environment these default values are used. -#ifndef PROFILE_DEFAULT -#define PROFILE_DEFAULT "/var/tmp" -#endif +#define PROFILE_DIR_DEFAULT "/var/tmp" +#define PROFILE_NAME_DEFAULT "/var/tmp" -#ifndef PROFILE_HOMEDOT -#define PROFILE_HOMEDOT ".trezoremu" -#endif - -void profile_init(void); +const char *profile_name(void); const char *profile_dir(void); const char *profile_flash_path(void); const char *profile_sdcard_path(void); diff --git a/core/emu.sh b/core/emu.sh index 86282e50d..816b23561 100755 --- a/core/emu.sh +++ b/core/emu.sh @@ -1,32 +1,27 @@ -#!/bin/sh +#!/bin/bash -if [ -f emu.config ]; then - . emu.config -fi +MICROPYTHON="${MICROPYTHON:-${PWD}/build/unix/micropython}" +TREZOR_SRC=$(cd "${PWD}/src/"; pwd) +BROWSER="${BROWSER:-chromium}" -EXE=build/unix/micropython -PYOPT="${PYOPT:-1}" -MAIN="${MAIN:-src/main.py}" -HEAPSIZE="${HEAPSIZE:-50M}" +source ./trezor_cmd.sh -ARGS="-O${PYOPT} -X heapsize=${HEAPSIZE}" - -cd `dirname $0` +cd "${TREZOR_SRC}" case "$1" in "-d") shift OPERATING_SYSTEM=$(uname) if [ "$OPERATING_SYSTEM" = "Darwin" ]; then - PATH=/usr/bin /usr/bin/lldb -f $EXE -- $ARGS $* $MAIN + PATH=/usr/bin /usr/bin/lldb -f $MICROPYTHON -- $ARGS $* $MAIN else - gdb --args $EXE $ARGS $* $MAIN + gdb --args $MICROPYTHON $ARGS $* $MAIN fi ;; "-r") shift while true; do - $EXE $ARGS $* $MAIN & + $MICROPYTHON $ARGS $* $MAIN & UPY_PID=$! find -name '*.py' | inotifywait -q -e close_write --fromfile - echo Restarting ... @@ -34,5 +29,7 @@ case "$1" in done ;; *) - $EXE $ARGS $* $MAIN + echo "Starting emulator: $MICROPYTHON $ARGS $* $MAIN" + $MICROPYTHON $ARGS $* $MAIN 2>&1 | tee "${TREZOR_LOGFILE}" + exit ${PIPESTATUS[0]} esac diff --git a/core/trezor_cmd.sh b/core/trezor_cmd.sh new file mode 100644 index 000000000..74c4d123a --- /dev/null +++ b/core/trezor_cmd.sh @@ -0,0 +1,78 @@ +#!/bin/bash + +# expected inputs: +# TREZOR_SRC -- directory containing python code for uMP + +if [[ ! "${TREZOR_SRC}" ]]; then echo "expecting TREZOR_SRC"; exit 0; fi + +# optional inputs: +# TREZOR_PROFILE -- profile name (directory) in ~/.trezoremu or full path +# PROFILING -- wrap the uMP/python in the profiler script + +# outputs: +## uMP +# PYOPT +# HEAPSIZE +# ARGS -- uMP arguments +# MAIN -- uMP file to execute +## TREZOR core +# TREZOR_PROFILE_DIR +# TREZOR_PROFILE_NAME +# TREZOR_UDP_PORT +## this script +# TREZOR_SRC +# TREZOR_LOGFILE +## python-trezor +# TREZOR_PATH -- connect string + + +# defaults +PYOPT="${PYOPT:-1}" +HEAPSIZE="${HEAPSIZE:-20M}" + +TREZOR_PROFILE="${TREZOR_PROFILE:-/var/tmp}" +TREZOR_PROFILE_DIR="${TREZOR_PROFILE}" +TREZOR_PROFILE_NAME="${TREZOR_PROFILE}" + +# for profile names create profile directory if not existent +if ! [[ "$TREZOR_PROFILE" == "/"* ]]; then + TREZOR_PROFILE_DIR="${HOME}/.trezoremu/${TREZOR_PROFILE}" + if ! [[ -d "${TREZOR_PROFILE_DIR}" ]]; then + mkdir -p "${TREZOR_PROFILE_DIR}" + PORT=$(( ( RANDOM % 1000 ) + 1 + 21324 )) + echo "# autogenerated config" > "${TREZOR_PROFILE_DIR}/emu.config" + echo "TREZOR_UDP_PORT=\"\${TREZOR_UDP_PORT:-${PORT}}\"" >> "${TREZOR_PROFILE_DIR}/emu.config" + fi +fi + +# load profile config +if [[ -f "${TREZOR_PROFILE_DIR}/emu.config" ]]; then + source "${TREZOR_PROFILE_DIR}/emu.config" +fi + +# for profiling wrap +if [[ "$PROFILING" -gt 0 ]]; then + MAIN="${TREZOR_SRC}/../prof/prof.py" +else + MAIN="${TREZOR_SRC}/main.py" +fi + +TREZOR_LOGFILE="${TREZOR_PROFILE_DIR}/trezor.log" +TREZOR_UDP_PORT="${TREZOR_UDP_PORT:-21324}" +TREZOR_PATH="${TREZOR_PATH:-udp:127.0.0.1:${TREZOR_UDP_PORT}}" + +echo "TREZOR^emu profile name: ${TREZOR_PROFILE_NAME}" +echo "TREZOR^emu profile directory: ${TREZOR_PROFILE_DIR}" +echo "TREZOR^emu log file: ${TREZOR_LOGFILE}" +echo "TREZOR^emu UDP port: ${TREZOR_UDP_PORT}" +echo "TREZOR^emu path: ${TREZOR_PATH}" +echo "TREZOR^emu src: ${TREZOR_SRC}" + +export TREZOR_PROFILE_NAME="${TREZOR_PROFILE_NAME}" +export TREZOR_PROFILE_DIR="${TREZOR_PROFILE_DIR}" +export TREZOR_LOGFILE="${TREZOR_LOGFILE}" +export TREZOR_UDP_PORT="${TREZOR_UDP_PORT}" +export TREZOR_PATH="${TREZOR_PATH}" +export TREZOR_SRC="${TREZOR_SRC}" + +ARGS="-O${PYOPT} -X heapsize=${HEAPSIZE}"