What changed, and why it matters
This commit is a large internal refactor of the Trezor firmware's third-party application loading system. It replaces the old ELF-based app loader with a new 'app_arena' subsystem that uses a custom binary format, Merkle-tree header verification, and ML-DSA-44 root-of-trust signatures. The change is explicitly marked as a feature ('feat(core): introduce app_arena') with '[no changelog]' and contains no vendor statement that it fixes a security bug. It appears to be a planned architectural redesign, not a security patch.
Treat this as a normal feature/refactor commit. No immediate security response is warranted. If reviewing for product security, focus on the new app_arena loader, root_packet signature verification, relocation bounds checks, and MPU switching logic in subsequent audits, because this is fresh attack surface for untrusted app execution.
Security signals we found
New security boundary code: custom app loader with MPU isolation, privilege rings, and signature verification
Adds ML-DSA-44 (mldsa44) root packet signature verification
Replaces ELF parsing with a custom, constrained binary format and relocation engine
Includes TODO comment about downgrade protection in app_root_update
No vendor disclosure of security relevance, CVE, or bug bounty attribution
Evidence from the diff
The commit removes the legacy app_loader module (app_arena.c/h, app_cache.c, app_task.c, elf.h, ELF loaders) and introduces a new app_arena module under core/embed/io/app_arena. New components include: app_arena.c (image lifecycle, chunking, MPU switching), app_header.c (header parsing and Merkle proof verification), app_root.c (root-of-trust storage), root_packet.c (signed root packet validation using sec/mldsa44), plus platform-specific app_loader.c files for stm32u5 and unix. The Cargo.toml change adds sec/mldsa44 to the app_loading feature. The code enforces header magic, ABI version, target architecture, bounds checks on offsets/sizes, and signature verification before any image is accepted. No vulnerability or security fix is mentioned in the commit metadata or diff comments.
Changed components
core/embed/io/app_arena/*core/embed/io/app_loader/* (removed)core/embed/io/Cargo.tomlcore/embed/sys/task/applet.ccore/embed/sys/syscall/*core/embed/upymod/modtrezorapp/*Inspect captured patch +3862 / −4820
### core/embed/io/Cargo.toml
@@ -41,7 +41,7 @@ secure_mode = ["sec/secure_mode"]
# Selectable components
# --------------------------------------------------------------------------
-app_loading = ["sys/app_loading"]
+app_loading = ["sys/app_loading", "sec/mldsa44"]
backlight = []
ble = ["nrf"]
button = []
### core/embed/io/app_arena/app_arena.c
@@ -0,0 +1,617 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef KERNEL_MODE
+
+#include <trezor_model.h>
+#include <trezor_rtl.h>
+
+#include <io/app_arena.h>
+#include <io/app_header.h>
+#include <io/app_root.h>
+#include <sys/applet.h>
+#include <sys/sysevent_source.h>
+
+#include <sha2.h>
+
+#ifdef USE_TRUSTZONE
+#include <sys/trustzone.h>
+#endif
+
+#include <stdlib.h>
+
+#include "app_loader.h"
+
+// Maximum number of application images that can be loaded in the arena
+// at the same time. If more images are needed, this can be increased
+// but the implementation of area memory management needs to be revisited.
+#define APP_ARENA_MAX_IMAGES 1
+
+// TLS for event handling
+typedef struct {
+ bool event_pending;
+} app_arena_tls_t;
+
+// Information about a loaded application image in the arena
+typedef struct {
+ // Handle of the loaded image
+ app_image_handle_t handle;
+
+ // Raw header data of the image (copied from the image file)
+ uint8_t header_raw[APP_HEADER_MAX_SIZE];
+ // Verified application header (points to the header_raw buffer)
+ const app_header_t* header;
+
+ // Set if image was fully loaded and verified
+ bool ready;
+ // Copy of the ready flag (FIH)
+ bool ready_fih;
+
+ // Set if image is currently running
+ bool running;
+
+ // Reserved memory for the application
+ void* mem_ptr;
+ // Reserved memory size
+ size_t mem_size;
+ // Number of bytes of the image loaded into the reserved memory
+ // (the rest of the reserved memory is used for rwdata)
+ size_t written_bytes;
+ // Hash of the next chunk
+ sha256_digest_t chunk_hash;
+ // Hash of the image header
+ sha256_digest_t header_hash;
+
+ // Applet associated with the application
+ applet_t applet;
+
+} app_arena_entry_t;
+
+typedef struct {
+ // Indicates whether the arena is initialized
+ bool initialized;
+
+ // Base pointer to the arena memory
+ uint8_t* mem_ptr;
+ // Total size of the arena memory
+ size_t mem_size;
+ // Amount of arena memory currently used by loaded images
+ size_t mem_used;
+
+ // TLS for event handling
+ app_arena_tls_t tls[SYSTASK_MAX_TASKS];
+ // Set if a systask associated with any loaded image has been killed
+ bool task_killed;
+
+ // Next handle value to assign for a new image.
+ // Handles are never reused, so this is just incremented for each new image.
+ app_image_handle_t next_handle;
+
+ // Slots for loaded images
+ app_arena_entry_t images[APP_ARENA_MAX_IMAGES];
+
+} app_arena_t;
+
+static app_arena_t g_app_arena = {
+ .initialized = false,
+};
+
+static const syshandle_vmt_t g_app_arena_handle_vmt;
+
+ts_t app_arena_init(void) {
+ app_arena_t* arena = &g_app_arena;
+ ts_t status;
+
+ if (arena->initialized) {
+ return TS_OK;
+ }
+
+ TSH_DECLARE;
+
+ memset(arena, 0, sizeof(app_arena_t));
+
+ arena->next_handle = APP_IMAGE_HANDLE_INVALID + 1;
+
+#ifdef TREZOR_EMULATOR
+ arena->mem_size = 64 * 1024 * 1024;
+ arena->mem_ptr = malloc(arena->mem_size);
+ TSH_CHECK(arena->mem_ptr != NULL, TS_ENOMEM);
+#else
+ arena->mem_size = APP_ARENA_RAM_SIZE;
+ arena->mem_ptr = (uint8_t*)APP_ARENA_RAM_START;
+ TSH_CHECK(arena->mem_ptr != NULL, TS_ENOMEM);
+
+#ifdef USE_TRUSTZONE
+ // Allow unprivileged access to app arena memory
+ tz_set_sram_unpriv(APP_ARENA_RAM_START, APP_ARENA_RAM_SIZE, true);
+#endif
+
+#endif
+
+ status = app_root_init();
+ TSH_CHECK_OK(status);
+
+ bool ok =
+ syshandle_register(SYSHANDLE_APP_ARENA, &g_app_arena_handle_vmt, arena);
+ TSH_CHECK(ok, TS_EINVAL);
+
+ arena->initialized = true;
+
+cleanup:
+ TSH_RETURN;
+}
+
+ts_t app_arena_get_info(app_arena_info_t* info) {
+ TSH_DECLARE;
+
+ app_arena_t* arena = &g_app_arena;
+
+ TSH_CHECK(arena->initialized, TS_ENOINIT);
+ TSH_CHECK_ARG(info != NULL);
+
+ memset(info, 0, sizeof(*info));
+
+ size_t image_count = 0;
+ for (size_t i = 0; i < ARRAY_LENGTH(arena->images); i++) {
+ if (arena->images[i].handle != APP_IMAGE_HANDLE_INVALID) {
+ image_count++;
+ }
+ }
+
+ info->total_size = arena->mem_size;
+ info->free_size = arena->mem_size - arena->mem_used;
+ info->image_count = image_count;
+
+cleanup:
+ TSH_RETURN;
+}
+
+ts_t app_arena_next_image(size_t* state, app_image_handle_t* handle) {
+ TSH_DECLARE;
+
+ app_arena_t* arena = &g_app_arena;
+
+ TSH_CHECK_ARG(state != NULL);
+ TSH_CHECK_ARG(handle != NULL);
+
+ *handle = APP_IMAGE_HANDLE_INVALID;
+
+ TSH_CHECK(arena->initialized, TS_ENOINIT);
+
+ size_t idx = *state;
+
+ // Find the next valid image
+ while (idx < ARRAY_LENGTH(arena->images)) {
+ app_arena_entry_t* entry = &arena->images[idx++];
+ if (entry->handle != APP_IMAGE_HANDLE_INVALID) {
+ *handle = entry->handle;
+ break;
+ }
+ }
+
+ *state = idx;
+
+cleanup:
+ TSH_RETURN;
+}
+
+ts_t app_arena_create_image(const void* header, size_t header_size,
+ const sha256_digest_t* proof, size_t proof_size,
+ app_image_handle_t* handle) {
+ TSH_DECLARE;
+ ts_t status;
+
+ app_arena_t* arena = &g_app_arena;
+
+ TSH_CHECK(arena->initialized, TS_ENOINIT);
+ TSH_CHECK_ARG(header != NULL);
+ TSH_CHECK_ARG(header_size <= APP_HEADER_MAX_SIZE);
+ TSH_CHECK_ARG(handle != NULL);
+ TSH_CHECK_ARG(proof != NULL || proof_size == 0);
+ TSH_CHECK_ARG(IS_ALIGNED(proof_size, sizeof(sha256_digest_t)));
+
+ *handle = APP_IMAGE_HANDLE_INVALID;
+
+ TSH_CHECK(arena->mem_used < arena->mem_size, TS_ENOMEM);
+
+ // Find an empty slot in the arena
+ for (size_t i = 0; i < ARRAY_LENGTH(arena->images); i++) {
+ app_arena_entry_t* entry = &arena->images[i];
+ if (entry->handle == APP_IMAGE_HANDLE_INVALID) {
+ memset(entry, 0, sizeof(*entry));
+
+ memcpy(entry->header_raw, header, header_size);
+ entry->header = app_header_verify(entry->header_raw, header_size);
+ TSH_CHECK(entry->header != NULL, TS_EBADMSG);
+ entry->chunk_hash = entry->header->chunk_hash;
+
+ // Calculate header hash
+ sha256_digest_t header_hash;
+ SHA256_CTX ctx;
+ sha256_Init(&ctx);
+ sha256_Update(&ctx, entry->header_raw, entry->header->header_size);
+ sha256_Final(&ctx, (uint8_t*)&header_hash);
+
+ entry->header_hash = header_hash;
+
+ // Verify the signature of the header
+ secbool signature_valid = secfalse;
+ status = app_header_verify_signature(entry->header, proof, proof_size,
+ &signature_valid);
+ TSH_CHECK_OK(status);
+ TSH_CHECK(signature_valid == sectrue, TS_EBADMSG);
+
+ secbool volatile signature_valid_fih = signature_valid; // FIH
+ TSH_CHECK(signature_valid_fih == sectrue, TS_EBADMSG); // FIH
+
+ // Allocate memory, for simplicity, we allow only using the whole arena.
+ entry->mem_ptr = arena->mem_ptr + arena->mem_used;
+ entry->mem_size = arena->mem_size - arena->mem_used;
+ arena->mem_used += entry->mem_size;
+ // Assign a new handle and mark the entry as loading
+ entry->handle = arena->next_handle++;
+ entry->ready = entry->ready_fih = false;
+ entry->running = false;
+
+ *handle = entry->handle;
+ break;
+ }
+ }
+
+ TSH_CHECK(*handle != APP_IMAGE_HANDLE_INVALID, TS_ENOMEM);
+
+cleanup:
+ TSH_RETURN;
+}
+
+static void app_arena_configure_mpu(const app_arena_entry_t* entry) {
+#ifndef TREZOR_EMULATOR
+ applet_layout_t layout = {
+ .data1 = {.start = (uintptr_t)entry->mem_ptr, .size = entry->mem_size},
+ };
+ mpu_set_active_applet(&layout);
+#endif
+}
+
+static void app_arena_restore_mpu(void) {
+#ifndef TREZOR_EMULATOR
+ systask_set_mpu(systask_active());
+#endif
+}
+
+static app_arena_entry_t* find_image_by_handle(app_image_handle_t handle) {
+ app_arena_t* arena = &g_app_arena;
+
+ if (!arena->initialized || handle == APP_IMAGE_HANDLE_INVALID) {
+ return NULL;
+ }
+
+ for (size_t i = 0; i < ARRAY_LENGTH(arena->images); i++) {
+ app_arena_entry_t* entry = &arena->images[i];
+ if (entry->handle == handle) {
+ return entry;
+ }
+ }
+
+ return NULL;
+}
+
+ts_t app_image_get_info(app_image_handle_t handle, app_image_info_t* info) {
+ TSH_DECLARE;
+
+ app_arena_t* arena = &g_app_arena;
+
+ TSH_CHECK(arena->initialized, TS_ENOINIT);
+ TSH_CHECK_ARG(info != NULL);
+
+ app_arena_entry_t* entry = find_image_by_handle(handle);
+ TSH_CHECK(entry != NULL, TS_ENOENT);
+
+ memset(info, 0, sizeof(*info));
+
+ info->ready = entry->ready;
+ info->running = entry->running;
+ info->code_size = entry->header->code_size;
+ info->data_size = entry->header->data_size;
+ info->chunk_size = entry->header->chunk_size;
+ info->version = entry->header->version;
+ info->header_hash = entry->header_hash;
+ info->ring = entry->header->app_ring;
+ memcpy(info->id, entry->header->id, sizeof(info->id));
+ memcpy(info->name, entry->header->app_name, sizeof(info->name));
+ memcpy(info->vendor, entry->header->vendor_name, sizeof(info->vendor));
+ memcpy(info->curves, entry->header->curves, sizeof(info->curves));
+ memcpy(info->paths, entry->header->paths, sizeof(info->paths));
+
+ if (entry->running) {
+ info->task_id = systask_id(&entry->applet.task);
+ }
+
+cleanup:
+ TSH_RETURN;
+}
+
+ts_t app_image_delete(app_image_handle_t handle) {
+ TSH_DECLARE;
+ ts_t status;
+
+ app_arena_t* arena = &g_app_arena;
+
+ TSH_CHECK(arena->initialized, TS_ENOINIT);
+
+ app_arena_entry_t* entry = find_image_by_handle(handle);
+ TSH_CHECK(entry != NULL, TS_ENOENT);
+
+ status = app_image_stop(handle);
+ TSH_CHECK_OK(status);
+
+ // Free the allocated memory
+ arena->mem_used -= entry->mem_size;
+
+ // Invalidate the entry
+ memset(entry, 0, sizeof(*entry));
+
+cleanup:
+ TSH_RETURN;
+}
+
+ts_t app_image_write_chunk(app_image_handle_t handle, const void* data,
+ size_t size, const sha256_digest_t* hash) {
+ TSH_DECLARE;
+ ts_t status;
+
+ app_arena_t* arena = &g_app_arena;
+
+ TSH_CHECK(arena->initialized, TS_ENOINIT);
+ TSH_CHECK_ARG(data != NULL);
+ TSH_CHECK_ARG(size > 0);
+ TSH_CHECK_ARG(hash != NULL);
+
+ app_arena_entry_t* entry = find_image_by_handle(handle);
+ TSH_CHECK(entry != NULL, TS_ENOENT);
+
+ // Do not allow writing to an image that is already marked as ready
+ TSH_CHECK(!entry->ready, TS_EINVAL);
+ TSH_CHECK(!entry->ready_fih, TS_EINVAL);
+
+ // Check that the new data fits in the reserved memory and does
+ // not exceed the code size specified in the header
+ TSH_CHECK(entry->written_bytes + size >= entry->written_bytes, TS_ENOMEM);
+ TSH_CHECK(entry->written_bytes + size <= entry->mem_size, TS_ENOMEM);
+ TSH_CHECK(entry->written_bytes + size <= entry->header->code_size,
+ TS_EBADMSG);
+
+ // Calculate chunk hash
+ sha256_digest_t digest;
+ SHA256_CTX ctx;
+ sha256_Init(&ctx);
+ sha256_Update(&ctx, (const uint8_t*)hash, sizeof(*hash));
+ sha256_Update(&ctx, data, size);
+ sha256_Final(&ctx, (uint8_t*)&digest);
+
+ // Compare the calculated hash with the expected one
+ volatile int cmp1 = memcmp(&digest, &entry->chunk_hash, sizeof(digest));
+ TSH_CHECK(cmp1 == 0, TS_EBADMSG);
+ // FIH
+ volatile int cmp2 =
+ memcmp(&entry->chunk_hash, &digest, sizeof(entry->chunk_hash));
+ TSH_CHECK(cmp2 == 0, TS_EBADMSG);
+
+ entry->chunk_hash = *hash;
+
+ const uint8_t* src = data;
+ const uint8_t* src_end = src + size;
+ uint8_t* dst = (uint8_t*)entry->mem_ptr + entry->written_bytes;
+
+ while (src < src_end) {
+ uint8_t temp[256];
+
+ size_t bytes_to_copy = MIN(src_end - src, sizeof(temp));
+
+ // We are copying data between two memory areas that are not
+ // accessible at the same time due to MPU restrictions.
+ memcpy(temp, src, bytes_to_copy);
+ app_arena_configure_mpu(entry);
+ memcpy(dst, temp, bytes_to_copy);
+ app_arena_restore_mpu();
+
+ src += bytes_to_copy;
+ dst += bytes_to_copy;
+ }
+
+ entry->written_bytes += size;
+
+ if (entry->written_bytes == entry->header->code_size) {
+ // All data has been written, verify the payload integrity
+ app_arena_configure_mpu(entry);
+ status = app_loader_verify_payload(entry->header, entry->mem_ptr,
+ entry->written_bytes);
+ app_arena_restore_mpu();
+ TSH_CHECK_OK(status);
+
+ entry->ready = entry->ready_fih = true;
+ }
+
+cleanup:
+ TSH_RETURN;
+}
+
+ts_t app_image_run(app_image_handle_t handle, systask_id_t* task_id) {
+ TSH_DECLARE;
+ ts_t status;
+
+ app_arena_t* arena = &g_app_arena;
+
+ TSH_CHECK(arena->initialized, TS_ENOINIT);
+ TSH_CHECK_ARG(task_id != NULL);
+ *task_id = 0;
+
+ app_arena_entry_t* entry = find_image_by_handle(handle);
+ TSH_CHECK(entry != NULL, TS_ENOENT);
+
+ // Check that the image is ready to be run
+ TSH_CHECK(entry->ready, TS_EINVAL);
+ TSH_CHECK(entry->ready_fih, TS_EINVAL);
+
+ if (entry->running) {
+ *task_id = entry->applet.task.id;
+ } else {
+ applet_unload(&entry->applet);
+
+ void* code = entry->mem_ptr;
+ void* data = (uint8_t*)entry->mem_ptr + entry->written_bytes;
+ size_t data_size = entry->mem_size - entry->written_bytes;
+
+ app_arena_configure_mpu(entry);
+
+ status = app_loader_prepare_applet(entry->header, code, data, data_size,
+ &entry->applet);
+ TSH_CHECK_OK(status);
+
+ entry->running = true;
+ applet_run(&entry->applet);
+
+ *task_id = entry->applet.task.id;
+ }
+
+cleanup:
+ app_arena_restore_mpu();
+ TSH_RETURN;
+}
+
+ts_t app_image_stop(app_image_handle_t handle) {
+ TSH_DECLARE;
+
+ app_arena_t* arena = &g_app_arena;
+
+ TSH_CHECK(arena->initialized, TS_ENOINIT);
+
+ app_arena_entry_t* entry = find_image_by_handle(handle);
+ TSH_CHECK(entry != NULL, TS_ENOENT);
+
+ applet_unload(&entry->applet);
+ memset(&entry->applet, 0, sizeof(entry->applet));
+ entry->running = false;
+
+cleanup:
+ TSH_RETURN;
+}
+
+ts_t app_image_get_pminfo(app_image_handle_t handle,
+ systask_postmortem_t* pminfo) {
+ TSH_DECLARE;
+
+ app_arena_t* arena = &g_app_arena;
+
+ TSH_CHECK(arena->initialized, TS_ENOINIT);
+ TSH_CHECK_ARG(pminfo != NULL);
+
+ app_arena_entry_t* entry = find_image_by_handle(handle);
+ TSH_CHECK(entry != NULL, TS_ENOENT);
+
+ *pminfo = entry->applet.task.pminfo;
+
+cleanup:
+ TSH_RETURN;
+}
+
+ts_t app_arena_clear_event(void) {
+ TSH_DECLARE;
+
+ app_arena_t* arena = &g_app_arena;
+
+ TSH_CHECK(arena->initialized, TS_ENOINIT);
+
+ systask_id_t task_id = systask_id(systask_active());
+ arena->tls[task_id].event_pending = false;
+
+cleanup:
+ TSH_RETURN;
+}
+
+#ifdef TREZOR_EMULATOR
+ts_t app_get_heap(void** heap_ptr, size_t* heap_size) {
+ applet_t* applet = applet_active();
+ return applet_get_heap(applet, heap_ptr, heap_size);
+}
+#endif
+
+// ---- app_arena event handling ----
+
+static void on_task_created(void* context, systask_id_t task_id) {
+ app_arena_t* arena = (app_arena_t*)context;
+
+ if (!arena->initialized) {
+ return;
+ }
+
+ // Just clear the TLS for the new task
+ memset(&arena->tls[task_id], 0, sizeof(arena->tls[task_id]));
+}
+
+static void on_task_killed(void* context, systask_id_t task_id) {
+ app_arena_t* arena = (app_arena_t*)context;
+
+ if (!arena->initialized) {
+ return;
+ }
+
+ for (size_t i = 0; i < ARRAY_LENGTH(arena->images); i++) {
+ app_arena_entry_t* entry = &arena->images[i];
+ if (entry->running && entry->applet.task.id == task_id) {
+ entry->running = false;
+ arena->task_killed = true;
+ break;
+ }
+ }
+}
+
+static void on_event_poll(void* context, bool read_awaited,
+ bool write_awaited) {
+ app_arena_t* arena = (app_arena_t*)context;
+
+ UNUSED(write_awaited);
+
+ if (read_awaited) {
+ syshandle_signal_read_ready(SYSHANDLE_APP_ARENA, &arena->task_killed);
+ arena->task_killed = false;
+ }
+}
+
+static bool on_check_read_ready(void* context, systask_id_t task_id,
+ void* param) {
+ app_arena_t* arena = (app_arena_t*)context;
+
+ bool task_killed = *(bool*)param;
+ if (task_killed) {
+ arena->tls[task_id].event_pending = true;
+ }
+
+ return arena->tls[task_id].event_pending;
+}
+
+static const syshandle_vmt_t g_app_arena_handle_vmt = {
+ .task_created = on_task_created,
+ .task_killed = on_task_killed,
+ .check_read_ready = on_check_read_ready,
+ .check_write_ready = NULL,
+ .poll = on_event_poll,
+};
+
+#endif // KERNEL_MODE
### core/embed/io/app_arena/app_header.c
@@ -0,0 +1,142 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <io/app_header.h>
+#include <io/app_root.h>
+
+#include <sha2.h>
+
+#include <sha2.h>
+
+const app_header_t* app_header_verify(const void* header_ptr,
+ size_t header_size) {
+ TSH_DECLARE;
+ const app_header_t* retval = NULL;
+
+ TSH_CHECK(header_ptr != NULL, TS_EINVAL);
+ TSH_CHECK(header_size >= sizeof(app_header_t), TS_EBADMSG);
+ TSH_CHECK(header_size <= APP_HEADER_MAX_SIZE, TS_EBADMSG);
+
+ const app_header_t* header = (const app_header_t*)header_ptr;
+
+ TSH_CHECK(header->magic == APP_HEADER_MAGIC, TS_EBADMSG);
+ TSH_CHECK(header->header_size == header_size, TS_EBADMSG);
+ TSH_CHECK(header->abi_version == 1, TS_EBADMSG);
+ TSH_CHECK(header->app_ring < APP_RING_COUNT, TS_EBADMSG);
+
+ retval = header;
+
+cleanup:
+ return retval;
+}
+
+ts_t app_header_calc_merkle_root(const app_header_t* header,
+ const sha256_digest_t* proof,
+ size_t proof_size, sha256_digest_t* root) {
+ TSH_DECLARE;
+
+ TSH_CHECK(root != NULL, TS_EINVAL);
+ memset(root, 0, sizeof(*root));
+
+ TSH_CHECK(header != NULL, TS_EINVAL);
+ TSH_CHECK(proof_size == 0 || proof != NULL, TS_EINVAL);
+ TSH_CHECK(proof_size % sizeof(sha256_digest_t) == 0, TS_EINVAL);
+
+ static const uint8_t prefix0[] = {0x00};
+ static const uint8_t prefix1[] = {0x01};
+
+ // Calculate header hash
+ SHA256_CTX ctx;
+ sha256_Init(&ctx);
+ sha256_Update(&ctx, (const uint8_t*)header, header->header_size);
+ sha256_Final(&ctx, root->bytes);
+
+ sha256_Init(&ctx);
+ sha256_Update(&ctx, prefix0, sizeof(prefix0));
+ sha256_Update(&ctx, root->bytes, sizeof(root->bytes));
+ sha256_Final(&ctx, root->bytes);
+
+ // Add the Merkle proof nodes to the hash
+ for (size_t i = 0; i < proof_size / sizeof(sha256_digest_t); i++) {
+ const sha256_digest_t* node = &proof[i];
+ sha256_Init(&ctx);
+ sha256_Update(&ctx, prefix1, sizeof(prefix1));
+ if (memcmp(node, root->bytes, sizeof(root->bytes)) < 0) {
+ sha256_Update(&ctx, node->bytes, sizeof(node->bytes));
+ sha256_Update(&ctx, root->bytes, sizeof(root->bytes));
+ } else {
+ sha256_Update(&ctx, root->bytes, sizeof(root->bytes));
+ sha256_Update(&ctx, node->bytes, sizeof(node->bytes));
+ }
+ sha256_Final(&ctx, root->bytes);
+ }
+
+cleanup:
+ TSH_RETURN;
+}
+
+ts_t app_header_verify_signature(const app_header_t* header,
+ const sha256_digest_t* proof,
+ size_t proof_size, secbool* valid) {
+ TSH_DECLARE;
+ ts_t status;
+
+ TSH_CHECK(header != NULL, TS_EINVAL);
+ TSH_CHECK(valid != NULL, TS_EINVAL);
+
+ *valid = secfalse;
+
+ sha256_digest_t calc_root = {.bytes = {0}};
+ status = app_header_calc_merkle_root(header, proof, proof_size, &calc_root);
+ TSH_CHECK_OK(status);
+
+ sha256_digest_t exp_root = {.bytes = {0}};
+ status = app_root_get_merkle_root(header->app_ring, &exp_root);
+ TSH_CHECK_OK(status);
+
+ volatile int cmp1 = memcmp(&calc_root, &exp_root, sizeof(calc_root));
+ if (cmp1 == 0) {
+ *valid = sectrue;
+ }
+
+ // FIH
+ volatile int cmp2 = memcmp(&exp_root, &calc_root, sizeof(calc_root));
+ if (cmp2 != 0) {
+ *valid = secfalse;
+ }
+
+cleanup:
+ TSH_RETURN;
+}
+
+ts_t app_header_get_app_ring(const void* header_ptr, size_t header_size,
+ uint8_t* app_ring) {
+ TSH_DECLARE;
+
+ TSH_CHECK_ARG(header_ptr != NULL);
+ TSH_CHECK_ARG(app_ring != NULL);
+
+ const app_header_t* header = app_header_verify(header_ptr, header_size);
+ TSH_CHECK(header != NULL, TS_EBADMSG);
+
+ *app_ring = header->app_ring;
+
+cleanup:
+ TSH_RETURN;
+}
### core/embed/io/app_arena/app_loader.h
@@ -0,0 +1,62 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <trezor_types.h>
+
+#include <io/app_header.h>
+#include <sys/applet.h>
+
+/**
+ * @brief Verifies the payload of an application image for integrity and
+ * correctness.
+ *
+ * Verifies the payload of the image if it is a valid application image (e.g.
+ * correct offsets, sizes, etc.)
+ *
+ * @param header Pointer to the header of the application image
+ * @param code Pointer to the payload of the application image
+ * @param code_size Size of the payload in bytes
+ *
+ * @return ts_t Status code indicating success or failure
+ * TS_EBADMSG - Invalid payload (e.g. incorrect sizes, offsets, etc.)
+ * TS_ENOMEM - Not enough memory to load the applet
+ */
+
+ts_t app_loader_verify_payload(const app_header_t* header, const void* code,
+ size_t code_size);
+
+/**
+ * @brief Initializes an applet structure for an application image
+ *
+ * Clears all applet rw memory and initializes .data section.
+ *
+ * @param header Pointer to the verified application header
+ * @param code Pointer to the payload of the application image
+ * @param data Pointer to the memory allocated for the applet's RW section
+ * @param data_size Size of the allocated RW memory
+ * @param applet Pointer to the applet structure to initialize
+ *
+ * @return ts_t Status code indicating success or failure
+ * TS_EBADMSG if the image payload is invalid
+ * TS_ENOMEM if there is not enough memory to initialize the applet
+ */
+ts_t app_loader_prepare_applet(const app_header_t* header, void* code,
+ void* data, size_t data_size, applet_t* applet);
### core/embed/io/app_arena/app_root.c
@@ -0,0 +1,164 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef KERNEL_MODE
+
+#include <trezor_rtl.h>
+
+#include <io/app_root.h>
+#include <sec/mldsa44.h>
+
+#include "root_packet.h"
+
+// Information held for each application ring, derived from the root packet
+typedef struct {
+ // Timestamp of the root packet the ring data was derived from
+ uint32_t timestamp;
+ // Merkle root for this ring
+ sha256_digest_t merkle_root;
+} app_ring_data_t;
+
+// Root-of-trust storage structure
+typedef struct {
+ // Set if the structure has been initialized
+ bool initialized;
+ // Merkle root for each ring, indexed by app_ring_t
+ app_ring_data_t ring[APP_RING_COUNT];
+} app_root_t;
+
+// App root-of-trust storage instance
+static app_root_t g_app_root = {
+ .initialized = false,
+};
+
+ts_t app_root_init(void) {
+ TSH_DECLARE;
+
+ app_root_t* root = &g_app_root;
+
+ if (root->initialized) {
+ TSH_RETURN;
+ }
+
+ memset(root, 0, sizeof(app_root_t));
+ root->initialized = true;
+
+ // cleanup:
+ TSH_RETURN;
+}
+
+ts_t app_root_update(const void* root_packet_data,
+ size_t root_packet_data_size) {
+ TSH_DECLARE;
+ ts_t status;
+
+ app_root_t* root = &g_app_root;
+ TSH_CHECK(root->initialized, TS_ENOINIT);
+
+ root_packet_auth_t* root_packet = NULL;
+ status =
+ root_packet_verify(root_packet_data, root_packet_data_size, &root_packet);
+ TSH_CHECK_OK(status);
+
+ TSH_CHECK(root_packet != NULL, TS_EBADMSG);
+
+ // !@# TODO: Consider downgrade protection
+
+ int slot = 0;
+ for (int id = 0; id < APP_RING_COUNT; id++) {
+ if (root_packet->ring_mask & (1 << id)) {
+ root->ring[id].timestamp = root_packet->timestamp;
+ root->ring[id].merkle_root = root_packet->merkle_root[slot];
+ ++slot;
+ }
+ }
+
+cleanup:
+ TSH_RETURN;
+}
+
+ts_t app_root_reset(void) {
+ TSH_DECLARE;
+
+ app_root_t* root = &g_app_root;
+ TSH_CHECK(root->initialized, TS_ENOINIT);
+
+ for (int i = 0; i < ARRAY_LENGTH(root->ring); i++) {
+ memset(&root->ring[i], 0, sizeof(app_ring_data_t));
+ }
+
+cleanup:
+ TSH_RETURN;
+}
+
+bool app_root_is_loaded(app_ring_t ring) {
+ app_root_t* root = &g_app_root;
+
+ if (!root->initialized) {
+ return false;
+ }
+
+ if (ring >= ARRAY_LENGTH(root->ring)) {
+ return false;
+ }
+
+ return root->ring[ring].timestamp != 0;
+}
+
+ts_t app_root_get_timestamp(app_ring_t ring, uint32_t* timestamp) {
+ TSH_DECLARE;
+
+ TSH_CHECK_ARG(timestamp != NULL);
+ *timestamp = 0;
+
+ app_root_t* root = &g_app_root;
+ TSH_CHECK(root->initialized, TS_ENOINIT);
+
+ TSH_CHECK_ARG(ring < ARRAY_LENGTH(root->ring));
+ app_ring_data_t* ring_data = &root->ring[ring];
+
+ TSH_CHECK(ring_data->timestamp != 0, TS_ENOENT);
+
+ *timestamp = ring_data->timestamp;
+
+cleanup:
+ TSH_RETURN;
+}
+
+ts_t app_root_get_merkle_root(app_ring_t ring, sha256_digest_t* merkle_root) {
+ TSH_DECLARE;
+
+ TSH_CHECK_ARG(merkle_root != NULL);
+ memset(merkle_root, 0, sizeof(sha256_digest_t));
+
+ app_root_t* root = &g_app_root;
+ TSH_CHECK(root->initialized, TS_ENOINIT);
+
+ TSH_CHECK_ARG(ring < ARRAY_LENGTH(root->ring));
+ app_ring_data_t* ring_data = &root->ring[ring];
+
+ TSH_CHECK(ring_data->timestamp != 0, TS_ENOENT);
+
+ *merkle_root = ring_data->merkle_root;
+
+cleanup:
+ TSH_RETURN;
+}
+
+#endif // KERNEL_MODE
### core/embed/io/app_arena/build.rs
@@ -0,0 +1,23 @@
+use xbuild::{CLibrary, Result, bail_unsupported};
+
+pub fn def_module(lib: &mut CLibrary) -> Result<()> {
+ lib.add_include("app_arena/inc");
+
+ // USE_APP_LOADING is defined in sys layer
+ lib.add_sources([
+ "app_arena/app_arena.c",
+ "app_arena/app_header.c",
+ "app_arena/app_root.c",
+ "app_arena/root_packet.c",
+ ]);
+
+ if cfg!(feature = "emulator") {
+ lib.add_source("app_arena/unix/app_loader.c");
+ } else if cfg!(feature = "mcu_stm32u5") {
+ lib.add_sources(["app_arena/stm32u5/app_loader.c"]);
+ } else {
+ bail_unsupported!();
+ }
+
+ Ok(())
+}
### core/embed/io/app_arena/inc/io/app_arena.h
@@ -0,0 +1,238 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <trezor_types.h>
+
+#include <io/app_header.h>
+#include <rtl/crypto_helpers.h>
+#include <sys/systask.h>
+
+#define APP_IMAGE_HANDLE_INVALID 0
+
+/** Handle for a loaded application image. */
+typedef uint32_t app_image_handle_t;
+
+/** Information about a loaded application image. */
+typedef struct {
+ /** Set if image was fully loaded and verified */
+ bool ready;
+ /** Set if image is currently running. */
+ bool running;
+ /** Unique identification of the application.
+ * UTF-8 encoded, zero-padded, but not necessarily null-terminated. */
+ char id[APP_HEADER_MAX_ID_LEN];
+ /** Name of the loaded application.
+ * UTF-8 encoded, zero-padded, but not necessarily null-terminated. */
+ char name[APP_HEADER_MAX_NAME_LEN];
+ /** Vendor of the loaded application.
+ * UTF-8 encoded, zero-padded, but not necessarily null-terminated. */
+ char vendor[APP_HEADER_MAX_VENDOR_LEN];
+ /** Version of the application. */
+ uint32_t version;
+ /** Privilege ring of the application. */
+ uint8_t ring;
+ /** ID of the running task (or 0 if not running). */
+ systask_id_t task_id;
+ /** Size of the image code in bytes. */
+ size_t code_size;
+ /** Size of the image data in bytes. */
+ size_t data_size;
+ /** Size of each chunk of the payload in bytes */
+ size_t chunk_size;
+ /** Calculated hash of the image header */
+ sha256_digest_t header_hash;
+ /** List of allowed curves (e.g., secp256k1, ed25519)
+ * Each entry is a null-terminated string, and the list
+ * is zero-padded to the maximum length */
+ char curves[APP_HEADER_CURVES_MAX_LEN];
+ /** List of allowed BIP32 path prefixes.
+ * Each entry is a null-terminated string, and the list
+ * is zero-padded to the maximum length */
+ char paths[APP_HEADER_PATHS_MAX_LEN];
+
+} app_image_info_t;
+
+/** Information about the application arena. */
+typedef struct {
+ /** Total size of the arena in bytes. */
+ size_t total_size;
+ /** Size of unused space in the arena in bytes. */
+ size_t free_size;
+ /** Number of images currently loaded in the arena. */
+ size_t image_count;
+} app_arena_info_t;
+
+/**
+ * @brief Initialize the application arena.
+ *
+ * This function must be called before any other functions in this module.
+ *
+ * @return TS_OK on success, or an error code on failure.
+ */
+ts_t app_arena_init(void);
+
+/**
+ * @brief Returns run-time information about the application arena.
+ *
+ * @param info Pointer to a structure to receive the arena info.
+ * @return TS_OK on success, or an error code on failure.
+ */
+ts_t app_arena_get_info(app_arena_info_t *info);
+
+/**
+ * @brief Clears the pending read event on SYSHANDLE_APP_ARENA, if any.
+ *
+ * app_arena signals stopped/killed task by signaling read readiness
+ * on SYSHANDLE_APP_ARENA. This event remains pending until the task
+ * that receives it calls this function.
+ *
+ * @return TS_OK on success, or an error code on failure.
+ */
+ts_t app_arena_clear_event(void);
+
+/**
+ * @brief Creates a new empty image in the application arena.
+ *
+ * @param header Pointer to the image header data.
+ * @param header_size Size of the image header data in bytes.
+ * @param proof Pointer to the Merkle proof data for signature
+ * verification.
+ * @param proof_size Size of the Merkle proof data in bytes.
+ * @param handle Pointer to store the handle of the newly allocated image.
+ *
+ * @return TS_OK on success, or an error code on failure.
+ * TS_EBADMSG if the header is invalid or verification failed.
+ * TS_ENOMEM if there is not enough memory to allocate a new image.
+ */
+ts_t app_arena_create_image(const void *header, size_t header_size,
+ const sha256_digest_t *proof, size_t proof_size,
+ app_image_handle_t *handle);
+
+/** Type for iterating over application images in the arena. */
+typedef size_t app_image_iter_t;
+
+/** Iterator initial value for app_image_iter_t. */
+#define APP_IMAGE_ITER_INIT ((app_image_iter_t)(0))
+
+/**
+ * @brief Retrieves the next loaded image handle.
+ *
+ * Set `state` to APP_IMAGE_ITER_INIT before the first call.
+ * Each call advances it to the next internal image slot.
+ * When no images remain, `handle` is set to APP_IMAGE_HANDLE_INVALID.
+ *
+ * @param state Iterator state. Opaque to the caller.
+ * @param handle Receives the next image handle.
+ * @return TS_OK on success, or an error code on failure.
+ */
+ts_t app_arena_next_image(app_image_iter_t *state, app_image_handle_t *handle);
+
+/**
+ * @brief Returns information about a loaded application image.
+ *
+ * @param handle Handle of the image to query.
+ * @param info Pointer to a structure to receive the image information.
+ * @return TS_OK on success, or an error code on failure.
+ * TS_ENOENT if the image handle is invalid.
+ */
+ts_t app_image_get_info(app_image_handle_t handle, app_image_info_t *info);
+
+/**
+ * @brief Writes image data to a loaded application image.
+ *
+ * This function can be used to load the application image data into the arena.
+ * The image must be in the loading state before calling this function.
+ *
+ * @param handle Handle of the image to write to.
+ * @param data Pointer to the data to write.
+ * @param size Size of the data in bytes.
+ * @param hash Pointer to the SHA-256 hash of the chunk chain
+ * @return TS_OK on success, or an error code on failure.
+ * TS_ENOENT if the image handle is invalid.
+ * TS_ENOMEM if there is not enough memory to write the data.
+ * TS_EBADMSG if the verification failed.
+ */
+ts_t app_image_write_chunk(app_image_handle_t handle, const void *data,
+ size_t size, const sha256_digest_t *hash);
+
+/**
+ * @brief Deletes a loaded application image.
+ *
+ * If the image is currently running, it will be stopped before being deleted.
+ *
+ * @param handle Handle of the image to delete.
+ * @return TS_OK on success, or an error code on failure.
+ * TS_ENOENT if the image handle is invalid.
+ */
+ts_t app_image_delete(app_image_handle_t handle);
+
+/**
+ * @brief Runs a loaded application image.
+ *
+ * If the image is fully loaded and verified, this function starts
+ * executing, otherwise it returns an error code.
+ * If the image is already running, it returns TS_OK without doing
+ * anything.
+ *
+ * @param handle Handle of the image to run.
+ * @param task_id Pointer to store the ID of the created task running the image.
+ * @return TS_OK on success, or an error code on failure.
+ * TS_ENOENT if the image handle is invalid.
+ * TS_EINVAL invalid argument or state (e.g. image is not ready to run).
+ * TS_EBADMSG if the image is invalid and can't be run.
+ */
+ts_t app_image_run(app_image_handle_t handle, systask_id_t *task_id);
+
+/**
+ * @brief Stops a running application image.
+ *
+ * If the image is currently running, this function stops its execution and
+ * transitions it back to the ready state. If the image is not running, it
+ * returns TS_OK without doing anything.
+ *
+ * @param handle Handle of the image to stop.
+ * @return TS_OK on success, or an error code on failure.
+ * TS_ENOENT if the image handle is invalid.
+ */
+ts_t app_image_stop(app_image_handle_t handle);
+
+/**
+ * @brief Gets postmortem information for a stopped application image.
+ *
+ * If the image is still running, the info structure will be invalid.
+ *
+ * @param handle Handle of the image to query.
+ * @param pminfo Pointer to a structure to receive postmortem information.
+ * @return TS_OK on success, or an error code on failure.
+ * TS_ENOENT if the image handle is invalid.
+ */
+ts_t app_image_get_pminfo(app_image_handle_t handle,
+ systask_postmortem_t *pminfo);
+
+/**
+ * @brief Gets the heap pointer and size for the currently active applet.
+ *
+ * @param heap_ptr Pointer to a variable to store the heap pointer.
+ * @param heap_size Pointer to a variable to store the heap size.
+ *
+ * @return TS_OK on success, or an error code on failure.
+ */
+ts_t app_get_heap(void **heap_ptr, size_t *heap_size);
### core/embed/io/app_arena/inc/io/app_header.h
@@ -0,0 +1,151 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <trezor_types.h>
+
+#include <rtl/crypto_helpers.h>
+
+#define APP_HEADER_MAGIC 0x415A5254 // "TRZA" in ASCII
+
+#define APP_TARGET_ARCH_ARMV8M 0
+#define APP_TARGET_ARCH_X86_64 1
+
+#define APP_HEADER_MAX_ID_LEN 32
+#define APP_HEADER_MAX_NAME_LEN 32
+#define APP_HEADER_MAX_VENDOR_LEN 32
+#define APP_HEADER_CURVES_MAX_LEN 64
+#define APP_HEADER_PATHS_MAX_LEN 256
+
+#define APP_HEADER_MAX_SIZE 512
+
+/** Header of an app file */
+typedef struct {
+ /** Magic number to identify the file format */
+ uint32_t magic;
+ /** Header size in bytes */
+ uint32_t header_size;
+ /** Unique identifier of the app (utf-8 encoded, zero-padded) */
+ char id[APP_HEADER_MAX_ID_LEN];
+ /** App name (utf-8 encoded, zero-padded) */
+ char app_name[APP_HEADER_MAX_NAME_LEN];
+ /** Vendor name (utf-8 encoded, zero-padded) */
+ char vendor_name[APP_HEADER_MAX_VENDOR_LEN];
+ /** Target model identifier (or zeros for universal apps) */
+ uint8_t model[4];
+ /** App version as major.minor.patch.build bytes */
+ uint32_t version;
+ /** SDK version used to build the app. */
+ uint32_t sdk_version;
+ /** ABI version used to build the app. */
+ uint8_t abi_version;
+ /** Target architecture of the binary payload (e.g., ARMV8M, X86_64) */
+ uint8_t target_arch;
+ /** Application privilege ring */
+ uint8_t app_ring;
+ /** Reserved for future use */
+ uint8_t reserved1;
+ /** Size of the binary payload in bytes. */
+ uint32_t code_size;
+ /** Size of RAM required by the app (includes stack, heap, and static data) */
+ uint32_t data_size;
+ /** Head hash of the application chunk chain */
+ sha256_digest_t chunk_hash;
+ /** Size of each chunk of the payload in bytes */
+ uint16_t chunk_size;
+ /** Reserved for future use */
+ uint16_t reserved2;
+ /** Allowed curves (e.g., secp256k1, ed25519)
+ * (array of null-terminated strings, zero-padded) */
+ char curves[APP_HEADER_CURVES_MAX_LEN];
+ /** Allowed BIP32 path prefixes
+ * (array of null-terminated strings, zero-padded) */
+ char paths[APP_HEADER_PATHS_MAX_LEN];
+
+} app_header_t;
+
+_Static_assert(
+ sizeof(app_header_t) == 484,
+ "app_header_t layout changed; the image format is not compatible");
+
+_Static_assert(sizeof(app_header_t) <= APP_HEADER_MAX_SIZE,
+ "app_header_t exceeds APP_HEADER_MAX_SIZE");
+
+/**
+ * @brief Verifies the header of an application image for integrity and
+ * correctness.
+ *
+ * Verifies the header of the image if it is a valid (e.g. correct
+ * magic, supported ABI version, etc.)
+ *
+ * @param header_ptr Pointer to the application header to verify
+ * @param header_size Size of the application header in bytes
+ *
+ * @return const app_header_t* Pointer to the verified header, or NULL if the
+ * header is invalid.
+ */
+const app_header_t* app_header_verify(const void* header_ptr,
+ size_t header_size);
+
+/**
+ * @brief Calculates the Merkle root of an application image header and its
+ * Merkle proof.
+ *
+ * @param header Pointer to the application header
+ * @param proof Pointer to the Merkle proof nodes (array of sha256_digest_t)
+ * @param proof_size Size of the Merkle proof in bytes (must be a multiple of
+ * sizeof(sha256_digest_t))
+ * @param root Pointer to the output buffer for the calculated Merkle root
+ * @return ts_t Status code indicating success or failure
+ */
+ts_t app_header_calc_merkle_root(const app_header_t* header,
+ const sha256_digest_t* proof,
+ size_t proof_size, sha256_digest_t* root);
+
+/**
+ * @brief Verifies the signature of an application image header.
+ *
+ * @param header Pointer to the application header
+ * @param proof Pointer to the Merkle proof nodes (array of sha256_digest_t)
+ * @param proof_size Size of the Merkle proof in bytes (must be a multiple of
+ * sizeof(sha256_digest_t))
+ * @param valid Pointer to a secbool variable that will be set to sectrue if the
+ * signature is valid, or secfalse otherwise.
+ *
+ * @return ts_t Status code indicating whether the signature verification
+ * completed or not (e.g., due to an error). The actual validity of the
+ * signature is indicated by the value of the `valid` parameter.
+ */
+ts_t app_header_verify_signature(const app_header_t* header,
+ const sha256_digest_t* proof,
+ size_t proof_size, secbool* valid);
+
+/**
+ * @brief Retrieves the application privilege ring from the app header.
+ *
+ * @param header_ptr Pointer to the application header.
+ * @param header_size Size of the application header in bytes.
+ * @param app_ring Pointer to the output variable for the application privilege
+ * ring.
+ *
+ * @return ts_t Status code indicating success or failure.
+ */
+ts_t app_header_get_app_ring(const void* header_ptr, size_t header_size,
+ uint8_t* app_ring);
### core/embed/io/app_arena/inc/io/app_root.h
@@ -0,0 +1,92 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <trezor_types.h>
+
+#include <rtl/crypto_helpers.h>
+
+/** Application ring identifiers */
+typedef enum {
+ APP_RING_0 = 0, // Most trusted ring
+ APP_RING_1 = 1,
+ APP_RING_2 = 2, // Least trusted ring
+ APP_RING_COUNT,
+} app_ring_t;
+
+/**
+ * @brief Initializes the root-of-trust storage.
+ *
+ * @return TS_OK on success, or an error code on failure.
+ */
+ts_t app_root_init(void);
+
+/**
+ * @brief Updates the root-of-trust storage with a new root packet.
+ *
+ * Before storing, the function checks the integrity and validity of the
+ * root packet, including its signature.
+ *
+ * @param root_packet Pointer to the root packet to store.
+ * @param root_packet_size Size of the root packet in bytes.
+ *
+ * @return TS_OK on success, or an error code on failure.
+ */
+ts_t app_root_update(const void* root_packet, size_t root_packet_size);
+
+/**
+ * @brief Deletes all stored root packets
+ *
+ * @return TS_OK on success, or an error code on failure.
+ */
+ts_t app_root_reset(void);
+
+/**
+ * @brief Checks if a root-of-trust is loaded for the given ring.
+ *
+ * @param ring The ring index to check for the presence of a root-of-trust.
+ *
+ * @return true if a root-of-trust is loaded for the given ring, false
+ * otherwise.
+ */
+bool app_root_is_loaded(app_ring_t ring);
+
+/**
+ * @brief Retrieves the timestamp from the root packet for the given ring.
+ *
+ * @param ring The ring index to retrieve the timestamp from.
+ * @param timestamp Pointer to a uint32_t variable to store the timestamp.
+ *
+ * @return TS_OK on success, or an error code on failure.
+ * TS_ENOENT if the root packet for the given ring does not exist.
+ */
+ts_t app_root_get_timestamp(app_ring_t ring, uint32_t* timestamp);
+
+/**
+ * @brief Retrieves the Merkle root from the root packet for the given ring.
+ *
+ * @param ring The ring index to retrieve the Merkle root from.
+ * @param merkle_root Pointer to a sha256_digest_t variable to store the Merkle
+ * root.
+ *
+ * @return TS_OK on success, or an error code on failure.
+ * TS_ENOENT if the root packet for the given ring does not exist.
+ */
+ts_t app_root_get_merkle_root(app_ring_t ring, sha256_digest_t* merkle_root);
### core/embed/io/app_arena/root_packet.c
@@ -0,0 +1,288 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef KERNEL_MODE
+
+#include <trezor_rtl.h>
+
+#include <io/app_root.h>
+#include <rtl/sizedefs.h>
+
+#include <sha2.h>
+
+#include "root_packet.h"
+
+static const mldsa44_public_key_t * const ROOT_PACKET_KEYS[] = {
+#if defined(BOOTLOADER_DEVEL) || defined(TREZOR_EMULATOR)
+ (const mldsa44_public_key_t*)
+ "\x9c\x2c\x88\x0b\xf1\xb7\x73\xc1\xfc\x7f\x68\xe8\x58\x89\x7e\x18"
+ "\x47\xd6\xbe\x83\xf0\x7f\xfc\xfa\xa1\x0e\xe3\x5e\x5b\x44\xff\x58"
+ "\xa4\x3b\x45\x95\x0b\x84\x1b\x91\xdc\x13\x3f\x96\xee\x14\x4e\x2c"
+ "\x9f\xb7\x75\x3a\x25\x07\x35\x30\x1a\x41\x41\xe5\xcb\xa8\xec\x2a"
+ "\x4b\x26\xf5\x42\xed\x53\x06\x01\x13\xc2\x1d\x6a\xdc\xda\x71\xaa"
+ "\xc5\x4c\xf8\x0d\x6d\xeb\xb1\xf5\x68\x4d\x5b\xd5\x59\x69\x4a\x1f"
+ "\x4c\x74\x69\x93\x42\xfb\x6a\x89\xf0\x17\x9f\xde\x32\x3d\x40\x98"
+ "\xb7\xfc\x7f\xd2\x58\x43\x6d\xae\x69\x9c\x90\x4d\x8c\xc7\xa8\xcb"
+ "\x55\x2a\xfe\xb9\x35\x33\x30\xc6\xec\xbe\x7f\x0d\xad\xff\xa9\xfa"
+ "\x0c\x74\xce\xef\xe1\xf9\x78\xd9\x41\x68\x72\x21\x17\x61\x99\x61"
+ "\x94\x5d\xf7\x6e\xba\xda\x2f\xff\xf4\x57\x32\xf0\x1d\x03\xa0\x40"
+ "\xf2\xc9\xa8\xab\x11\x29\x2e\x1b\x4b\x4c\x39\x37\x5c\x4f\xa9\x5d"
+ "\x1b\xcf\x53\x6d\x41\xc6\x63\xc2\xd0\xf5\x51\x22\x24\x62\x23\xbc"
+ "\xc1\x9c\xeb\xbb\xed\x76\xcb\xbe\x05\x26\xf3\x0b\xb3\x78\x5d\xc0"
+ "\x50\xdf\x59\xaf\x1a\xa8\x35\x80\x5a\x4e\x62\x20\x12\x83\x51\xc4"
+ "\x72\xa9\x9e\xf7\x90\x06\xd3\x3d\x5e\x19\x0b\xe8\x0b\x80\xbe\xed"
+ "\x3b\x0b\x53\xcb\xc6\xef\xc5\x2c\x8a\x7c\xa7\x2b\x69\x57\x99\xfc"
+ "\x63\x46\x7a\x88\xc2\xa1\xbf\x06\x6f\xbd\x0b\x4d\x61\x5b\xc2\x6a"
+ "\x2a\xd8\x98\x45\x2c\xe9\xd0\xc2\x08\x8c\x6e\xd9\xc3\x6d\x93\x04"
+ "\x6c\x50\x3e\x87\xb7\xdb\xdd\xcf\x25\x2e\x64\x3c\x9a\xa8\x84\xed"
+ "\xd9\x58\x10\xdf\x7e\x35\x15\xe9\x43\x00\x77\xc5\xd2\xb7\x9a\x79"
+ "\x41\x73\x34\x30\x90\x26\xfb\x71\x25\x13\xdc\xcf\xb0\xac\x00\x3a"
+ "\x06\x15\x69\x69\xb7\x6e\xf0\xd3\x03\xf0\xd2\x94\x4b\xc1\x44\x2f"
+ "\x64\x30\x15\xb5\xa4\xf5\x66\xda\x50\x20\x63\xc4\x07\x35\x47\x7e"
+ "\xbf\x9f\xd6\x60\xbb\xc3\x38\x22\x09\xbb\xfd\x70\x7a\xd7\x1d\x4b"
+ "\xdf\x31\xd1\xfb\x17\xd5\xfb\xa2\x56\xe5\xc2\xee\xf4\xf6\x73\x6d"
+ "\x49\xe4\x91\xb6\x7f\x46\x8a\xa1\x96\xa5\x3d\x3f\x8b\xe5\x8f\x6a"
+ "\x69\x5c\x10\x33\xa8\x8a\x2e\x5c\xea\xe7\x5b\x92\xa8\xf3\x13\x6e"
+ "\xbe\x8b\xfc\x25\xb1\xd7\xd1\x06\x73\x18\x90\xb1\x32\x7d\x0a\xaf"
+ "\x3f\xa8\x7f\x0b\xe4\x6d\x6d\x8c\x0e\x05\xc1\xa5\xce\x14\x61\x0e"
+ "\x5a\x40\xe1\x00\xf9\x6e\x21\x30\x8a\xb8\x97\x4c\x14\x4a\x2d\x86"
+ "\x84\x46\xd0\x31\x78\xcf\x1b\x5e\xb9\xad\xb0\x97\xeb\x9c\x78\x98"
+ "\xfa\x2d\x74\xcc\x06\xaf\xb7\x97\xbe\x8f\x79\x68\xf9\x45\x6d\x17"
+ "\x2e\x2e\x4d\x1c\x7d\x62\x4f\x8a\xd1\xea\xf5\x26\x56\x83\xfe\xe9"
+ "\xaa\x45\x8d\x9b\x67\x23\x7a\xb7\x40\xf7\xae\xc9\xbc\x1c\xea\xc3"
+ "\xde\xf1\xfc\x70\x95\x43\xd6\x83\x41\xa4\x5d\x8a\x18\x92\xbc\x7a"
+ "\x9b\x1d\xee\x38\x42\xcf\x32\x71\x00\xab\x17\xd6\x86\xc6\x7d\x11"
+ "\x7d\xcd\x3f\xbe\xe8\x5d\x6d\x3c\x4b\x71\x88\x11\xb1\x08\x13\x39"
+ "\x3a\x71\x54\x44\x51\x8c\xda\xa8\xf9\x91\xe6\x75\x9b\x25\x0e\xd0"
+ "\x5f\x09\x30\x1f\x9e\xbb\xdb\x1d\xe0\xa6\xf9\xb1\xb2\x63\x14\x36"
+ "\x05\x19\x9d\x07\x5a\x55\x90\x3d\x5b\x6b\xdd\xe1\xc4\xe2\x64\xe2"
+ "\x39\x7f\x14\x48\x8f\xdf\x49\x1f\x1d\xea\x22\x34\x87\x8d\x6e\x48"
+ "\x75\xc8\xe9\xce\xb3\xe7\x5c\xe4\x70\x0b\xa9\xee\x50\x59\xe9\x33"
+ "\x85\xf0\x3b\x76\xd2\xf5\x4c\x4a\x9c\xcb\xdf\x36\x38\x51\xb0\xbd"
+ "\x4a\x1a\xcb\xeb\x22\xe7\xf6\x2f\x5e\x94\xf9\x64\x6e\xd7\xcf\x91"
+ "\xf3\x85\xc4\x63\x09\xa3\x61\xd0\x2f\xcc\x1d\x28\xec\x2a\x6a\xfe"
+ "\x6c\xfa\x75\x2e\x81\x51\xb5\x43\xef\x31\x8b\x6d\xd3\x25\xe7\x1c"
+ "\xf7\xcb\x2c\x73\xb6\x4b\xa0\x9e\xb5\xff\xaa\xbd\xea\x54\x72\xa8"
+ "\x2f\x0f\xf2\xac\x34\xa5\xd8\xda\x82\x03\x77\x77\xd6\x1d\xf5\xf2"
+ "\x0e\xa2\x31\xae\xbb\xbf\xa6\xd5\x17\x2d\x2b\xcb\x41\x38\x61\xca"
+ "\x27\x66\x76\xb3\x62\xac\x7b\x22\x08\x50\x9b\xf1\xa8\xd6\x8e\xb6"
+ "\xad\x26\xc1\x47\xe4\xe6\x39\x5f\x7a\x9e\xcb\x7f\x6c\x2b\xf6\x43"
+ "\x13\x4f\xae\xcc\x7a\xa1\xcc\xcb\x74\xe1\xd5\xbd\x54\x1a\xed\x3a"
+ "\xa8\x4a\xa8\xc4\xa5\x3e\xef\x4d\x64\x04\xc0\x7a\xbf\x2e\xea\x99"
+ "\xfc\xa9\x13\x02\xa2\xbf\xac\x9c\x53\x8e\x16\x61\xb5\x89\x4f\x4c"
+ "\xbf\x51\xd1\x6d\x72\xdc\x72\x7b\x6d\x44\x45\xab\x0f\xfe\x32\x5d"
+ "\xbc\xd3\x31\xe6\xa9\x61\x9d\x5a\x7e\xcb\x83\x5e\xc0\xfa\xd5\x53"
+ "\x03\x00\x27\x0e\x4a\xff\x8a\x25\xed\xc1\x76\x37\xe0\x60\x8d\xe1"
+ "\x1a\x38\xf8\x35\x7f\xa8\x49\x6b\xa4\x8d\x7e\x2f\xce\xe7\x73\x56"
+ "\x02\x20\x54\x6f\x2f\x5a\x68\x50\x64\x9b\x8f\x46\x5d\xd7\xa6\xa4"
+ "\xb7\x5a\x00\xa4\x15\x23\x35\x04\x7d\x69\xa5\x5b\x23\x9a\x96\x2e"
+ "\x1c\x5e\x61\x54\x38\x85\xd6\x53\xd8\x6e\x9d\x83\xbb\xe0\xad\x86"
+ "\x60\xaf\x83\x9d\x53\xe0\x19\xf1\xc2\x50\x1f\xba\xee\x37\x2d\x11"
+ "\x72\x25\x09\xfe\xc2\x1b\x7d\x9f\x7a\x50\x80\x48\x45\x71\xf0\xd0"
+ "\x6e\xe5\xa9\x6d\x8b\x43\xb9\xd4\x3f\x87\x29\xc4\xdc\x39\xda\x36"
+ "\xf4\x18\x7c\xb4\x86\x6d\x55\xff\xe4\x67\xdc\xc2\x3a\x73\x89\x67"
+ "\xe3\x74\x86\xcc\x96\xeb\x85\x1d\x2d\x1e\x87\xab\xf6\x52\xc8\x22"
+ "\xe7\x4d\xa8\x21\x19\x47\x3b\x57\x54\xb2\x78\x96\x69\xd0\x8d\xe2"
+ "\x75\x35\xa1\x52\x18\x49\x62\x56\x77\xd2\xea\x68\x2a\x52\x33\x7e"
+ "\xb4\x0a\x2d\x4b\x92\xaf\x98\x29\x72\x51\x71\x74\x82\xf3\x51\xa9"
+ "\xac\x4d\x90\xe3\xcf\x34\x0b\xcb\x03\x2d\x92\xe6\x95\x9a\x6e\xae"
+ "\xd0\x2e\xc3\x6d\xd1\xda\x9d\x84\xc5\x17\xad\x2d\xa5\x50\x8e\x9d"
+ "\x6e\x05\xc8\x2f\xc0\xeb\x57\xcd\xa8\x3c\xfa\xd5\xb9\xf7\x42\x70"
+ "\xfa\x6a\xe0\x74\xe3\x52\xf4\x60\xa1\x35\xea\x31\x45\x9e\x54\xbd"
+ "\x33\xfc\x2e\x7e\x06\x37\xa4\x23\xb6\xdc\x62\xaf\xf3\x62\x60\x37"
+ "\x9f\x8f\x29\x2d\xc1\x99\x65\x8c\x9e\x28\x2b\xfe\xad\x1f\xc2\x67"
+ "\xb3\x71\x46\x00\x14\x21\xd0\xae\x99\x6e\xb7\x88\xbd\xfc\xc5\xd3"
+ "\x25\xc0\x49\x9e\x3b\x02\x96\xd4\x30\xd9\xd5\x48\xe4\x0f\xf0\x37"
+ "\x7d\xef\x89\x6d\xed\x18\x3a\x46\x20\x8c\xf5\x22\x47\x88\xf2\x61"
+ "\xd9\x6f\xa2\xff\x53\x92\x60\x27\x30\x81\x46\x8b\x13\xdc\xa6\x0a"
+ "\xc8\xcb\x12\x78\xbe\x17\xd5\x1c\x30\x6b\xfe\x33\x59\xab\xf8\x56"
+ "\x42\x4d\xcb\xa2\x0c\x52\x6f\x5c\x2e\x4c\x56\x38\x6b\x64\x17\xb1",
+ (const mldsa44_public_key_t*)
+ "\x60\xff\xdd\x95\xbc\xab\xf0\xae\x55\x3f\x20\x2d\xfb\xf4\x41\x5d"
+ "\x8e\x77\x00\xa8\x69\x99\x6f\x1b\x1c\x1b\xb4\x1f\x15\x98\x18\xf9"
+ "\xc0\xf5\x39\x99\x6c\x78\x1b\xb5\x86\xe0\x30\x60\xe2\xee\xae\x24"
+ "\xf2\xa7\x9a\x54\xf9\x04\x34\xe8\xfd\xf5\xb3\x3f\x51\xa1\x92\x75"
+ "\x01\x6f\xd7\x7d\x75\xcf\x62\x69\x12\x2e\xe9\x04\x86\xdd\x9f\xce"
+ "\xa0\x17\x67\x74\x8d\x15\x97\xef\x88\x21\x95\xca\xff\x6d\xc0\x39"
+ "\x22\x4e\xa9\xcc\xf7\xcd\xb3\x43\xe3\x14\xbf\xeb\xc2\x0f\xda\xeb"
+ "\x96\xb9\x90\xa6\xeb\x5d\x45\x0f\xae\x87\xfd\xd5\x2c\x0e\x0b\x9b"
+ "\x1d\x70\x15\x1f\xe3\x52\xa6\x82\x87\x7e\x83\xa3\xe3\x64\x5d\x43"
+ "\xad\xa6\xb4\x2e\x90\xc6\xf6\x64\x68\x51\xd7\xf7\xa0\x6e\xbf\xa0"
+ "\xa2\xe5\x51\x06\x5c\x9a\xaf\x1f\x81\xc4\x55\xd9\xb1\xf0\xda\xb7"
+ "\x4a\xae\x1a\xca\x09\xab\xe0\x06\x6a\x85\x48\xbe\xc2\xfa\x73\xa1"
+ "\x89\xe5\x82\xfc\xa5\xf4\x71\x05\x61\x38\xbc\xe1\xa6\x5f\xc0\x4b"
+ "\xb9\xfe\x4f\x76\xff\x7e\xc4\x9c\x78\xd1\x6b\xa8\xd2\xe5\x26\xf3"
+ "\xef\x54\x71\x6d\xde\xd4\x31\xf6\x9a\xf0\x44\x37\xd4\x19\xbd\x7b"
+ "\x2a\x45\x99\xe1\x26\x35\x31\x17\x62\x8e\x63\x90\xab\x6d\x3d\x22"
+ "\xd0\xe7\xf9\x2e\x8f\xb7\xc5\x01\xf7\x9b\x20\x17\xcc\x6a\xd5\x82"
+ "\xfc\xb2\x52\x10\x30\xaa\x7d\xd8\x70\x57\x1e\x64\xfa\x1c\xa7\x57"
+ "\x43\xd4\x00\xbc\xe2\x8c\xd2\x83\x4d\x90\xf7\x9c\x7d\xbe\x7a\x52"
+ "\x60\xbe\x72\xd8\x86\xf9\x79\xe9\x3c\x85\xf9\x9d\x9d\x12\xfb\x32"
+ "\xdf\xc5\x2a\x27\x57\xfb\xa0\xe8\x03\xf6\x56\xd9\x8c\xb5\x94\xea"
+ "\x2d\x59\x1b\xb7\xda\x55\xc5\x6e\x27\x10\x11\x58\xa5\x2b\x5d\x6a"
+ "\x80\x38\x9a\x3f\x48\xfe\xe7\x29\x21\x71\x2c\x96\x58\x4b\x63\xdb"
+ "\x2a\xed\x73\x79\xe8\x5c\xff\x3c\xb3\x63\xdb\x0e\x77\xd5\x3c\xcf"
+ "\xd8\xf2\x6a\xed\xaa\xc3\xe0\xa5\xdf\xae\x46\xba\x13\x0a\xe4\x7c"
+ "\xc6\xa1\x60\xce\x0a\x83\x0c\x33\x20\x23\x4f\xec\x17\x7f\xcd\xc0"
+ "\x56\xcb\x99\x29\x51\xea\x64\x78\x2d\x1e\x4d\xef\x95\x3a\x24\xe5"
+ "\x76\xd2\x98\x70\xee\x48\xd0\x50\x51\x89\x53\x67\x8d\x9e\x89\xf3"
+ "\x76\xa5\xf1\x0f\x58\x9f\x58\x2d\xf3\xb5\xd7\x83\xd7\xad\xcb\x90"
+ "\x06\x46\xae\xf5\xce\xbd\xa8\xe0\x8d\xe6\x09\xc6\xb8\x7b\x9e\xcd"
+ "\x08\x5a\x0d\x22\x73\x74\xe6\x44\x9a\x65\x17\x60\xb5\x0d\x80\x85"
+ "\xb2\x1e\x9d\xcb\xa6\x3b\xa0\xe7\xfc\x41\xf7\x6c\x1e\x89\x59\xbb"
+ "\xd6\x7a\x96\x37\x09\x82\x66\xe6\x5f\x0f\x82\x84\xba\x29\x34\x4b"
+ "\x19\x43\xae\x4e\xba\x12\xb4\xa1\xb4\x17\x85\x90\xe2\x95\x91\x43"
+ "\x44\x9c\xdd\x2d\x2d\x5b\x9a\x45\xda\x8f\x74\x69\x84\x4a\x23\x08"
+ "\x87\x0e\x6f\xe6\x97\xb9\x2b\x7d\x1d\x91\x0b\x7d\xd6\x03\x95\x3f"
+ "\x3d\x05\xc8\x6e\x8a\xab\x93\xf2\xf7\x72\xe1\xaf\x53\x82\x96\x29"
+ "\x6f\xa7\x35\x25\x26\xab\xea\xf3\xa2\x80\x50\xf0\x95\xe2\x66\x7c"
+ "\x94\x01\x3c\x9e\x13\x6c\xb4\x7b\x64\x04\x88\x91\xc7\x74\xc9\x64"
+ "\xcb\xc5\x12\xc8\xa3\x47\x13\x6f\x9e\x27\x12\xe5\x5d\xbe\xf2\xca"
+ "\xcd\xcf\xcf\x68\x71\x0e\x34\x76\x48\xf2\xea\xd2\x07\x90\x36\x10"
+ "\xd0\xba\x44\xf6\xa4\x27\x5b\x8e\x03\x74\xd2\x11\x84\xd1\x08\x5a"
+ "\xac\xdc\xef\x2e\x43\x79\x31\x46\x5b\x29\xe9\x81\xff\xbf\xec\x01"
+ "\xec\x12\xae\xf6\x26\x2d\x73\x85\xdf\x58\xa1\x6a\x8b\xa1\x25\xf5"
+ "\xd6\xab\xe1\xe2\x85\x66\xdb\xe2\xb3\xf4\x5d\x3f\x41\xa1\xa0\x69"
+ "\xc3\x4f\xcc\x6f\x3d\x19\x76\x23\xd6\x26\x61\x83\x03\xf9\xb0\xc5"
+ "\xe9\x3f\x5b\xb8\x6f\xbe\x1d\x92\xb4\x9f\x9c\xa7\x37\x49\x4a\xf7"
+ "\x71\xd2\x19\xc5\x35\xac\x78\x6a\xae\x9e\x02\xbe\x66\x7c\xd4\xb5"
+ "\x34\x71\xc4\x51\x4f\x43\x3f\xa9\xd6\xa4\x48\x88\xf3\x0b\x83\x19"
+ "\x25\xe5\xb4\x9c\x98\xd2\x98\x6c\x6f\xf5\x8e\x99\xf8\x04\x4c\x7e"
+ "\xd5\xa1\x20\xf2\xcd\xbc\x85\x57\x63\xf0\x5f\xa1\x0a\x26\x01\xe8"
+ "\x23\x20\x45\xff\x55\xe9\xc7\xc6\xbd\xf5\xe8\x84\x88\x84\x76\x00"
+ "\x11\x0a\x49\xbf\x0b\x17\x1e\x21\x61\x25\xa7\x62\x5b\xe6\x2c\xfd"
+ "\x6c\x9d\xbd\x3c\x55\xc5\x73\xf5\x90\x51\x49\x4a\x24\xe5\xa1\x2d"
+ "\xf3\x0d\xa4\x9d\x04\x6e\x68\xd4\x98\x2f\x14\x3a\xfb\x90\xfe\xe2"
+ "\x8c\x8a\xdd\x36\x5f\xad\x97\xb6\x3c\x43\xad\xee\x4e\xfc\xcc\x40"
+ "\x84\x4e\xe8\x14\x10\x2d\xd1\x2a\xba\x36\xd5\xcf\x75\xe4\x3a\xa4"
+ "\xd3\xa2\xec\x8a\x46\xac\x3b\x1e\x2a\x4e\xf3\xa3\xee\xe1\x87\x27"
+ "\x31\x13\xa5\x39\x24\x8b\xde\x99\x8a\x9a\x1e\x20\x79\x55\xa6\x53"
+ "\xe9\x74\xa5\x81\x14\xe2\xb4\x41\x85\x07\x5b\x20\x54\x1e\x6a\x60"
+ "\x7f\xa3\x4a\x56\xef\x7c\x08\xa7\x2c\xa7\x97\xae\x25\xac\x5b\xd6"
+ "\x72\xcb\xa7\xf6\x75\x11\xd4\x96\x3c\xc1\xa5\xbb\x01\x0b\x13\x40"
+ "\x15\xb8\x49\x7e\xb8\xb2\xc3\xfc\x69\x6b\x06\x2c\x7c\x6d\x20\x0f"
+ "\x4e\xdb\x47\xc7\xc5\xc1\xa3\x4c\x1f\x20\x92\x19\x27\x11\xe5\x46"
+ "\xc9\x05\x6b\xf3\xdf\x1e\x30\x88\xe5\x57\xad\x99\x51\x29\x8f\x44"
+ "\x7a\x75\xb8\x2b\xb8\x3e\x82\x19\x30\xfb\x22\x82\x24\xa2\x8a\x66"
+ "\x71\x49\xe0\x97\x9d\x89\x93\xd7\xb3\x25\x41\xc5\xc0\x5e\xf8\x11"
+ "\xc8\xa7\xfb\xaf\x62\x68\x09\xb7\x97\x02\x0e\x44\x3d\x74\xe4\xb6"
+ "\x0e\x7a\x1a\xcb\xd6\xa2\xb3\xbe\xf7\x07\xa4\xa1\x5b\xb2\x26\x74"
+ "\x39\xc3\x1d\x27\xa7\x4b\x1d\x9f\xd2\x02\xcb\x37\x0b\xae\x3c\x9f"
+ "\xca\xad\x33\x0d\xdb\xcc\x4b\x58\xd8\xec\x75\x5a\xe0\x3d\xca\xde"
+ "\x4c\x8c\xd1\xd6\x8a\xdc\xe2\x8f\x89\x02\x40\x37\x6d\x45\x22\x51"
+ "\xf6\x82\x96\xa6\xb5\xc6\x93\x50\xa8\x4e\xe6\xda\x35\xe5\xbd\x45"
+ "\xab\xe5\x94\xdc\xd1\xf2\x14\x22\x8a\x62\xb0\x33\x90\xcb\xe3\x74"
+ "\xdd\xf3\x7e\xf5\x30\x19\x70\x6f\x06\x4d\x37\x8e\x5a\x62\xc1\xeb"
+ "\xd1\xce\xff\x59\xfd\x6e\x81\x4a\xa6\x94\xaf\x70\x72\xf4\x4a\xdc"
+ "\xe6\x35\x24\x93\x29\x24\x27\x54\x4b\x85\xb0\x57\x35\x3e\x77\x60"
+ "\x72\xbf\x27\xd7\x02\x87\x0b\xcb\x2f\x5e\x2a\xb8\x16\xd5\xdb\xdf"
+ "\xc3\x6c\xf8\x59\xb5\x07\x4d\xc4\xd4\x23\x84\x91\x6b\x46\x00\xd8"
+ "\xfc\x1b\x4b\xe0\x26\xc1\x67\x6f\xea\x9c\xf5\x93\xe5\x29\xc8\x0b"
+ "\xfe\xdf\x83\x9e\x00\x14\x3c\x9c\x13\xa6\xfb\x16\x4c\xfd\x16\x0f"
+ "\x4b\x72\x91\xb2\x01\x0e\xba\xbd\xb4\xc6\x04\x7d\xb2\x94\x71\x96"
+#else
+ MODEL_ROOT_PACKET_KEYS
+#endif
+};
+
+static int popcount(uint8_t value) {
+ int count = 0;
+ while (value != 0) {
+ if ((value & 1) != 0) {
+ count++;
+ }
+ value >>= 1;
+ }
+ return count;
+}
+
+ts_t root_packet_verify(const void* data, size_t size,
+ root_packet_auth_t** out) {
+ TSH_DECLARE;
+ ts_t status;
+
+ TSH_CHECK_ARG(data != NULL);
+ TSH_CHECK_ARG(out != NULL);
+
+ *out = NULL;
+
+ TSH_CHECK(size >= sizeof(root_packet_auth_t), TS_EBADMSG);
+ TSH_CHECK(IS_ALIGNED((uintptr_t)data, _Alignof(root_packet_auth_t)),
+ TS_EBADMSG);
+
+ root_packet_auth_t* auth = (root_packet_auth_t*)data;
+
+ TSH_CHECK(auth->magic == ROOT_PACKET_MAGIC, TS_EBADMSG);
+ TSH_CHECK(auth->version == ROOT_PACKET_VERSION, TS_EBADMSG);
+ TSH_CHECK(auth->ring_mask != 0, TS_EBADMSG);
+ TSH_CHECK(auth->ring_mask <= (1 << APP_RING_COUNT) - 1, TS_EBADMSG);
+ TSH_CHECK(auth->timestamp != 0, TS_EBADMSG);
+
+ // Calculate the expected size of the authenticated part of the root packet
+ size_t auth_part_size = sizeof(root_packet_auth_t) +
+ sizeof(sha256_digest_t) * popcount(auth->ring_mask);
+
+ TSH_CHECK(size == auth_part_size + sizeof(root_packet_unauth_t), TS_EBADMSG);
+
+ // Calculate hash of authenticated part of the root packet
+ sha256_digest_t auth_hash;
+ SHA256_CTX ctx;
+ sha256_Init(&ctx);
+ sha256_Update(&ctx, (const uint8_t*)auth, auth_part_size);
+ sha256_Final(&ctx, auth_hash.bytes);
+
+ // Verify signatures
+ root_packet_unauth_t* unauth =
+ (root_packet_unauth_t*)((uint8_t*)auth + auth_part_size);
+ TSH_CHECK(IS_ALIGNED((uintptr_t)unauth, _Alignof(root_packet_unauth_t)),
+ TS_EBADMSG);
+
+ uint8_t sigmask = unauth->sigmask;
+ uint8_t sigmask_inv = 0; // FIH
+
+ TSH_CHECK(popcount(sigmask) == ARRAY_LENGTH(unauth->signature), TS_EBADMSG);
+
+ for (int sig_idx = 0; sig_idx < ARRAY_LENGTH(unauth->signature); sig_idx++) {
+ // Get the index of the public key in the signature mask
+ int key_idx = __builtin_ctz(sigmask);
+ TSH_CHECK(key_idx < ARRAY_LENGTH(ROOT_PACKET_KEYS), TS_EBADMSG);
+
+ secbool valid = secfalse;
+ status =
+ mldsa44_verify(&unauth->signature[sig_idx], &auth_hash,
+ sizeof(auth_hash), ROOT_PACKET_KEYS[key_idx], &valid);
+ TSH_CHECK_OK(status);
+ TSH_CHECK(valid == sectrue, TS_EBADMSG);
+
+ // Mark the key as used
+ sigmask &= ~(1 << key_idx);
+ sigmask_inv |= (1 << key_idx);
+ }
+
+ // Check that all signatures were verified
+ TSH_CHECK(sigmask == 0, TS_EBADMSG);
+ TSH_CHECK(sigmask_inv == unauth->sigmask, TS_EBADMSG); // FIH
+
+ *out = auth;
+
+cleanup:
+ TSH_RETURN;
+}
+
+#endif // KERNEL_MODE
### core/embed/io/app_arena/root_packet.h
@@ -0,0 +1,77 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <trezor_types.h>
+
+#include <rtl/crypto_helpers.h>
+#include <sec/mldsa44.h>
+
+/** Root packet magic number */
+#define ROOT_PACKET_MAGIC 0x50525254 // 'TRRP'
+
+/** Supported root packet version */
+#define ROOT_PACKET_VERSION 0x01
+
+/** Authenticated part of the root packet */
+typedef struct {
+ /** Magic constant 'TRRP' */
+ uint32_t magic;
+ /** Root packet format version */
+ uint8_t version;
+ /** Bitmask of included Merkle roots. Each bit maps to a ring in
+ * app_ring_t. Up to three bits may be set. */
+ uint8_t ring_mask;
+ /** Reserved for future use */
+ uint8_t reserved[2];
+ /** Root packet timestamp */
+ uint32_t timestamp;
+ /** Merkle roots for the rings in ring_mask. The roots are stored
+ * in the order of the bits in ring_mask, from least significant to
+ * most significant. */
+ sha256_digest_t merkle_root[];
+} root_packet_auth_t;
+
+/** Unauthenticated part of the root packet.
+ *
+ * This part is placed directly after the authenticated part
+ * in memory, and contains the signatures of the authenticated part hash.
+ */
+typedef struct {
+ /** Bitmask of signature verification keys. Each bit maps to a public key
+ * in ROOT_PACKET_KEYS. Exactly two bits must be set. */
+ uint8_t sigmask;
+ /** Reserved for future use */
+ uint8_t reserved[3];
+ /* Signatures of authenticated root packet part */
+ mldsa44_signature_t signature[2];
+} root_packet_unauth_t;
+
+/**
+ * @brief Verifies the integrity and validity of a root packet.
+ *
+ * @param data Pointer to the root packet data.
+ * @param size Size of the root packet data.
+ * @param out Pointer to the output authenticated root packet structure.
+ *
+ * @return TS_OK if the root packet is valid, otherwise an error code.
+ */
+ts_t root_packet_verify(const void* data, size_t size,
+ root_packet_auth_t** out);
### core/embed/io/app_arena/stm32u5/app_loader.c
@@ -0,0 +1,553 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef KERNEL_MODE
+
+#include <trezor_model.h>
+#include <trezor_rtl.h>
+
+#include <rtl/sizedefs.h>
+#include <sys/applet.h>
+#include <sys/coreapp.h>
+#include <sys/logging.h>
+#include <sys/mpu.h>
+
+#include "../app_loader.h"
+
+LOG_DECLARE(app_loader)
+
+#define MPU_ALIGNMENT 32 // Required alignment for MPU regions
+#define STACK_ALIGNMENT 8 // Required alignment for stack end
+
+// RO segment has been relocated to RW segment
+#define RUNTIME_FLAG_RO_SEGMENT_RELOCATED (1 << 0)
+
+typedef struct {
+ // Header version. Currently only 0 is supported
+ uint32_t version;
+ // Offset of the read-only segment from the end of the header
+ uint32_t ro_offset;
+ // Virtual address of the read-only segment
+ uint32_t ro_va;
+ // Size of the read-only segment
+ uint32_t ro_size;
+ // Offset of the relocation table
+ uint32_t ro_rel_offset;
+ // Size of the relocation table in bytes
+ uint32_t ro_rel_size;
+ // Virtual address of the read-write segment
+ uint32_t rw_va;
+ // Read-write segment size to reserve at load time
+ uint32_t rw_size;
+ // Offset of the relocation table for the RW segment
+ uint32_t rw_rel_offset;
+ // Size of the relocation table for the RW segment in bytes
+ uint32_t rw_rel_size;
+ // Offset of the RW init data
+ uint32_t rw_init_offset;
+ // Size of RW init data in bytes
+ uint32_t rw_init_size;
+ // Minimal stack size in bytes
+ uint32_t stack_size;
+ // Minimal heap size in bytes.
+ uint32_t heap_size;
+ // Virtual address of entry function (applet_main) in RO segment
+ uint32_t entry_va;
+ // Flags for future use
+ uint32_t runtime_flags;
+ // Reserved for future use
+ uint32_t reserved[16];
+} app_code_header_t;
+
+_Static_assert(sizeof(app_code_header_t) == 128,
+ "app_code_header_t must be 128 bytes");
+
+typedef struct {
+ // RO segment (from original elf)
+ uint32_t ro_v_addr;
+ uint32_t ro_p_addr;
+ uint32_t ro_size;
+ // RW segment (from original elf)
+ uint32_t rw_v_addr;
+ uint32_t rw_p_addr;
+ uint32_t rw_size;
+ // Stack address and size
+ uint32_t stack_p_addr;
+ uint32_t stack_size;
+ // Heap address and size
+ uint32_t heap_p_addr;
+ uint32_t heap_size;
+} va_map_t;
+
+static const uint8_t* offset_to_ptr(const app_code_header_t* chdr,
+ uint32_t offset) {
+ return (const uint8_t*)chdr + sizeof(app_code_header_t) + offset;
+}
+
+// Map virtual address to physical address using the provided mapping
+static uint8_t* map_va_size(const va_map_t* map, uint32_t va, size_t size) {
+ if (va + size < va) {
+ // Overflow
+ return NULL;
+ }
+
+ if (va >= map->rw_v_addr && va + size <= map->rw_v_addr + map->rw_size) {
+ // Address within RW segment
+ return (uint8_t*)map->rw_p_addr + (va - map->rw_v_addr);
+ }
+
+ if (va >= map->ro_v_addr && va + size <= map->ro_v_addr + map->ro_size) {
+ // Address within RO segment
+ return (uint8_t*)map->ro_p_addr + (va - map->ro_v_addr);
+ }
+
+ // Address not within any mapped segment
+ return NULL;
+}
+
+static uint8_t* map_va(const va_map_t* map, uint32_t va) {
+ return map_va_size(map, va, 0);
+}
+
+/*
+// Map physical address to virtual address using the provided mapping
+static uint8_t* map_pa_size(const va_map_t* map, uint32_t pa, size_t size) {
+ if (pa + size < pa) {
+ // Overflow
+ return NULL;
+ }
+
+ if (pa >= map->rw_p_addr && pa + size <= map->rw_p_addr + map->rw_size) {
+ // Address within RW segment
+ return (uint8_t*)map->rw_v_addr + (pa - map->rw_p_addr);
+ }
+
+ if (pa >= map->ro_p_addr && pa + size <= map->ro_p_addr + map->ro_size) {
+ // Address within RO segment
+ return (uint8_t*)map->ro_v_addr + (pa - map->ro_p_addr);
+ }
+
+ // Address not within any mapped segment
+ return NULL;
+}
+
+static uint8_t* map_pa(const va_map_t* map, uint32_t pa) {
+ return map_pa_size(map, pa, 0);
+}
+*/
+
+ts_t app_loader_verify_payload(const app_header_t* header, const void* code,
+ size_t code_size) {
+ TSH_DECLARE;
+
+ TSH_CHECK_ARG(header != NULL);
+ TSH_CHECK_ARG(code != NULL);
+ TSH_CHECK_ARG(code_size >= sizeof(app_code_header_t));
+
+ TSH_CHECK(code_size == header->code_size, TS_EBADMSG);
+
+ TSH_CHECK(header->target_arch == APP_TARGET_ARCH_ARMV8M, TS_EBADMSG);
+
+ const app_code_header_t* chdr = (const app_code_header_t*)code;
+
+ uint32_t raw_code_size = header->code_size - sizeof(app_code_header_t);
+
+ TSH_CHECK(chdr->version == 0, TS_EBADMSG);
+
+ // Check that ro segment size and relocations fit within the image
+ TSH_CHECK(chdr->ro_offset <= raw_code_size, TS_EBADMSG);
+ TSH_CHECK(chdr->ro_offset + chdr->ro_size >= chdr->ro_offset, TS_EBADMSG);
+ TSH_CHECK(chdr->ro_offset + chdr->ro_size <= raw_code_size, TS_EBADMSG);
+ TSH_CHECK(chdr->ro_va + chdr->ro_size >= chdr->ro_va, TS_EBADMSG);
+
+ // Check that relocation table fits within the image
+ TSH_CHECK(chdr->ro_rel_offset <= raw_code_size, TS_EBADMSG);
+ TSH_CHECK(chdr->ro_rel_offset + chdr->ro_rel_size >= chdr->ro_rel_offset,
+ TS_EBADMSG);
+ TSH_CHECK(chdr->ro_rel_offset + chdr->ro_rel_size <= raw_code_size,
+ TS_EBADMSG);
+
+ // Check that RW segment size and address are valid
+ TSH_CHECK(chdr->rw_va >= chdr->ro_va + chdr->ro_size, TS_EBADMSG);
+ TSH_CHECK(chdr->rw_va + chdr->rw_size >= chdr->rw_va, TS_EBADMSG);
+ TSH_CHECK(chdr->rw_size < APP_ARENA_RAM_SIZE, TS_ENOMEM);
+
+ /// Check that RW relocation table fits within the image
+ TSH_CHECK(chdr->rw_rel_offset <= raw_code_size, TS_EBADMSG);
+ TSH_CHECK(chdr->rw_rel_offset + chdr->rw_rel_size >= chdr->rw_rel_offset,
+ TS_EBADMSG);
+ TSH_CHECK(chdr->rw_rel_offset + chdr->rw_rel_size <= raw_code_size,
+ TS_EBADMSG);
+
+ // Check that the RW init data is within the image
+ TSH_CHECK(chdr->rw_init_offset <= raw_code_size, TS_EBADMSG);
+ TSH_CHECK(chdr->rw_init_offset + chdr->rw_init_size >= chdr->rw_init_offset,
+ TS_EBADMSG);
+ TSH_CHECK(chdr->rw_init_offset + chdr->rw_init_size <= raw_code_size,
+ TS_EBADMSG);
+
+ // Check that the stack size is reasonable
+ TSH_CHECK(chdr->stack_size < APP_ARENA_RAM_SIZE, TS_ENOMEM);
+
+ // Check that the heap size is reasonable
+ TSH_CHECK(chdr->heap_size < APP_ARENA_RAM_SIZE, TS_ENOMEM);
+
+ // Check that the entrypoint is within the RO segment
+ TSH_CHECK(chdr->entry_va >= chdr->ro_va, TS_EBADMSG);
+ TSH_CHECK(chdr->entry_va < chdr->ro_va + chdr->ro_size, TS_EBADMSG);
+
+ // Check that the runtime flags are zeroed
+ TSH_CHECK(chdr->runtime_flags == 0, TS_EBADMSG);
+
+cleanup:
+ TSH_RETURN;
+}
+
+// Takes an unused memory block in the app arena and trims it to the
+// largest MPU-aligned block fully contained within it. Any bytes removed
+// from the beginning or end are unused and contain no applet data.
+static ts_t align_data(void** data, size_t* data_size) {
+ TSH_DECLARE;
+
+ uintptr_t addr = (uintptr_t)(*data);
+ size_t size = *data_size;
+
+ uintptr_t aligned_addr = ALIGN_UP(addr, MPU_ALIGNMENT);
+ size_t offset = aligned_addr - addr;
+
+ TSH_CHECK(size >= offset, TS_ENOMEM);
+
+ *data = (void*)aligned_addr;
+ *data_size = ALIGN_DOWN(size - offset, MPU_ALIGNMENT);
+
+cleanup:
+ TSH_RETURN;
+}
+
+static ts_t fit_in_memory(const app_code_header_t* chdr, void* data,
+ size_t data_size, va_map_t* map) {
+ TSH_DECLARE;
+ ts_t status;
+
+ status = align_data(&data, &data_size);
+ TSH_CHECK_OK(status);
+
+ TSH_CHECK(data_size >= chdr->rw_size + chdr->stack_size + chdr->heap_size,
+ TS_ENOMEM);
+
+ map->ro_v_addr = chdr->ro_va;
+ map->ro_p_addr = (uint32_t)offset_to_ptr(chdr, chdr->ro_offset);
+ map->ro_size = chdr->ro_size;
+
+ TSH_CHECK(IS_ALIGNED(map->ro_p_addr, MPU_ALIGNMENT), TS_EBADMSG);
+ TSH_CHECK(IS_ALIGNED(map->ro_size, MPU_ALIGNMENT), TS_EBADMSG);
+
+ map->rw_v_addr = chdr->rw_va;
+ map->rw_p_addr = (uint32_t)data;
+ map->rw_size = ALIGN_UP(chdr->rw_size, STACK_ALIGNMENT);
+
+ // Place the stack after the RW segment
+ map->stack_p_addr = map->rw_p_addr + map->rw_size;
+ map->stack_size = ALIGN_UP(chdr->stack_size, STACK_ALIGNMENT);
+
+ // Place the heap after the stack
+ map->heap_p_addr = map->stack_p_addr + map->stack_size;
+ uint32_t heap_end =
+ ALIGN_UP(map->heap_p_addr + chdr->heap_size, MPU_ALIGNMENT);
+ map->heap_size = heap_end - map->heap_p_addr;
+
+ TSH_CHECK(heap_end <= (uint32_t)data + data_size, TS_ENOMEM);
+
+cleanup:
+ TSH_RETURN;
+}
+
+// Callback invoked when applet is unloaded
+static void unload_cb(applet_t* applet) {
+ mpu_set_active_applet(&applet->layout);
+
+ // Clear RW segment, stack and the heap to remove any sensitive information
+ // before freeing the memory
+
+ void* data = (void*)applet->layout.data1.start;
+ size_t data_size = applet->layout.data1.size;
+ memset(data, 0, data_size);
+
+ systask_set_mpu(systask_active());
+}
+
+// 16-bit Relocation format
+// -----------------------------------------------------------------------
+// | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+// | REL_TYPE_xxx | offset |
+// -----------------------------------------------------------------------
+
+// Relocation/Command types
+typedef enum {
+ REL_TYPE_RESET = 0, // Reset address to 0
+ REL_TYPE_SKIP = 1, // Skip up to 4095 bytes
+ REL_TYPE_SKIP_LONG = 2, // Skip up to 4095 * 65536 bytes
+ REL_TYPE_ABS32 = 3, // Absolute 32-bit address
+ REL_TYPE_MOVW_ABS = 4, // Absolute (low 16 bits)
+ REL_TYPE_MOVT_ABS = 5, // Absolute (high 16 bits)
+ REL_TYPE_MOVW_MOVT_ABS = 6, // Absolute movw/movt pair (full 32 bits)
+} reloc_type_t;
+
+// Extract the immediate value from a MOVT or MOVW instructions
+static uint16_t extract_movx_value(uint32_t instruction) {
+ uint16_t imm1 = (instruction >> 10) & 0x1;
+ uint16_t imm4 = (instruction >> 0) & 0xF;
+ uint16_t imm3 = (instruction >> 28) & 0x7;
+ uint16_t imm8 = (instruction >> 16) & 0xFF;
+ return (imm4 << 12) | (imm1 << 11) | (imm3 << 8) | imm8;
+}
+
+// Insert the immediate value into a MOVT or MOVW instruction
+static uint32_t insert_movx_value(uint32_t instruction, uint16_t value) {
+ uint16_t imm4 = (value >> 12) & 0xF;
+ uint16_t imm1 = (value >> 11) & 0x1;
+ uint16_t imm3 = (value >> 8) & 0x7;
+ uint16_t imm8 = value & 0xFF;
+ instruction = (instruction & ~0x000F) | (imm4 << 0);
+ instruction = (instruction & ~0x0400) | (imm1 << 10);
+ instruction = (instruction & ~0x70000000) | (imm3 << 28);
+ instruction = (instruction & ~0x00FF0000) | (imm8 << 16);
+ return instruction;
+}
+
+// Perform relocations normally
+#define RELOC_FLAG_NORMAL 0x00
+// Perform relocations without modifying the memory
+#define RELOC_FLAG_DRY_RUN 0x01
+// Enfornce relocations only in rw segment
+#define RELOC_FLAG_RW_SEGMENT 0x02
+// Enforce relocation only in ro segment
+#define RELOC_FLAG_RO_SEGMENT 0x04
+
+ts_t apply_relocations(const void* rel_table, size_t rel_size,
+ const va_map_t* map, uint32_t flags) {
+ TSH_DECLARE;
+
+ TSH_CHECK(rel_size % sizeof(uint16_t) == 0, TS_EBADMSG);
+
+ const uint16_t* rel_ptr = (uint16_t*)rel_table;
+ const uint16_t* rel_end = rel_ptr + (rel_size / sizeof(uint16_t));
+
+ uint32_t address = 0;
+
+ while (rel_ptr < rel_end) {
+ uint16_t entry = *rel_ptr++;
+
+ reloc_type_t type = (entry >> 12) & 0xF;
+ uint16_t offset = entry & ((1 << 12) - 1);
+
+ // Handle address adjustments commands
+ switch (type) {
+ case REL_TYPE_RESET:
+ address = 0;
+ continue;
+
+ case REL_TYPE_SKIP:
+ address += offset;
+ continue;
+
+ case REL_TYPE_SKIP_LONG:
+ TSH_CHECK(rel_ptr < rel_end, TS_EBADMSG);
+ uint16_t low = *rel_ptr++;
+ address += (offset << 16) + low;
+ continue;
+
+ default:
+ break;
+ }
+
+ // Handle relocation commands
+ address += offset;
+
+ if (flags & RELOC_FLAG_RW_SEGMENT) {
+ // Ensure the address falls within the rw segment.
+ TSH_CHECK(address >= map->rw_v_addr, TS_EBADMSG);
+ TSH_CHECK(address < map->rw_v_addr + map->rw_size, TS_EBADMSG);
+ }
+
+ if (flags & RELOC_FLAG_RO_SEGMENT) {
+ // Ensure the address falls within the ro segment.
+ TSH_CHECK(address >= map->ro_v_addr, TS_EBADMSG);
+ TSH_CHECK(address < map->ro_v_addr + map->ro_size, TS_EBADMSG);
+ }
+
+ uint32_t* ptr = (uint32_t*)map_va_size(map, address, sizeof(uint32_t));
+ TSH_CHECK(ptr != NULL, TS_EBADMSG);
+
+ switch (type) {
+ case REL_TYPE_ABS32: {
+ uint32_t pa = (uint32_t)map_va(map, *ptr);
+ LOG_DBG("0x%08lX: ABS32: 0x%08lX -> 0x%08lX", address, *ptr, pa);
+ TSH_CHECK(pa != 0, TS_EBADMSG);
+ if ((flags & RELOC_FLAG_DRY_RUN) == 0) {
+ *ptr = pa;
+ }
+ } break;
+
+ case REL_TYPE_MOVT_ABS: {
+ TSH_CHECK(rel_ptr < rel_end, TS_EBADMSG);
+ uint16_t low = *rel_ptr++;
+ uint32_t va = ((uint32_t)extract_movx_value(*ptr) << 16) | low;
+ uint32_t pa = (uint32_t)map_va(map, va);
+ LOG_DBG("0x%08lX: MOVT_ABS: 0x%08lX -> 0x%08lX", address, va, pa);
+ TSH_CHECK(pa != 0, TS_EBADMSG);
+ if ((flags & RELOC_FLAG_DRY_RUN) == 0) {
+ *ptr = insert_movx_value(*ptr, (uint16_t)(pa >> 16));
+ }
+ } break;
+
+ case REL_TYPE_MOVW_ABS: {
+ TSH_CHECK(rel_ptr < rel_end, TS_EBADMSG);
+ uint16_t high = *rel_ptr++;
+ uint32_t va = extract_movx_value(*ptr) | ((uint32_t)high << 16);
+ uint32_t pa = (uint32_t)map_va(map, va);
+ LOG_DBG("0x%08lX: MOVW_ABS: 0x%08lX -> 0x%08lX", address, va, pa);
+ TSH_CHECK(pa != 0, TS_EBADMSG);
+ if ((flags & RELOC_FLAG_DRY_RUN) == 0) {
+ *ptr = insert_movx_value(*ptr, (uint16_t)(pa & 0xFFFF));
+ }
+ } break;
+
+ case REL_TYPE_MOVW_MOVT_ABS: {
+ // `ptr` points at the movw instruction; the paired movt instruction is
+ // the next 32-bit instruction. The full target address is recovered
+ // from the low 16 bits held by movw and the high 16 bits held by movt.
+ uint32_t* movt = (uint32_t*)map_va_size(map, address + sizeof(uint32_t),
+ sizeof(uint32_t));
+ TSH_CHECK(movt != NULL, TS_EBADMSG);
+ uint32_t va = extract_movx_value(*ptr) |
+ ((uint32_t)extract_movx_value(*movt) << 16);
+ uint32_t pa = (uint32_t)map_va(map, va);
+ LOG_DBG("0x%08lX: MOVW_MOVT_ABS: 0x%08lX -> 0x%08lX", address, va, pa);
+ TSH_CHECK(pa != 0, TS_EBADMSG);
+ if ((flags & RELOC_FLAG_DRY_RUN) == 0) {
+ *ptr = insert_movx_value(*ptr, (uint16_t)(pa & 0xFFFF));
+ *movt = insert_movx_value(*movt, (uint16_t)(pa >> 16));
+ }
+ } break;
+
+ default:
+ TSH_CHECK(false, TS_EBADMSG);
+ }
+ }
+
+cleanup:
+ TSH_RETURN;
+}
+
+ts_t app_loader_prepare_applet(const app_header_t* header, void* code,
+ void* data, size_t data_size, applet_t* applet) {
+ TSH_DECLARE;
+ ts_t status;
+
+ memset(applet, 0, sizeof(applet_t));
+
+ va_map_t map = {0};
+
+ app_code_header_t* chdr = (app_code_header_t*)code;
+
+ memset(data, 0, data_size);
+
+ status = fit_in_memory(chdr, data, data_size, &map);
+ TSH_CHECK_OK(status);
+
+ // Apply relocations
+ if ((chdr->runtime_flags & RUNTIME_FLAG_RO_SEGMENT_RELOCATED) == 0) {
+ status = apply_relocations(offset_to_ptr(chdr, chdr->ro_rel_offset),
+ chdr->ro_rel_size, &map,
+ RELOC_FLAG_DRY_RUN | RELOC_FLAG_RO_SEGMENT);
+ TSH_CHECK_OK(status);
+
+ status = apply_relocations(offset_to_ptr(chdr, chdr->ro_rel_offset),
+ chdr->ro_rel_size, &map,
+ RELOC_FLAG_NORMAL | RELOC_FLAG_RO_SEGMENT);
+ TSH_CHECK_OK(status);
+
+ chdr->runtime_flags |= RUNTIME_FLAG_RO_SEGMENT_RELOCATED;
+ }
+
+ // Copy initialized data from RO to RW segment
+ if (chdr->rw_init_size > 0) {
+ const uint8_t* src = offset_to_ptr(chdr, chdr->rw_init_offset);
+ void* dst = map_va_size(&map, chdr->rw_va, chdr->rw_init_size);
+ TSH_CHECK(dst != NULL, TS_EBADMSG);
+ memcpy(dst, src, chdr->rw_init_size);
+ }
+
+ // Apply relocations for RW segment
+ status = apply_relocations(offset_to_ptr(chdr, chdr->rw_rel_offset),
+ chdr->rw_rel_size, &map,
+ RELOC_FLAG_NORMAL | RELOC_FLAG_RW_SEGMENT);
+ TSH_CHECK_OK(status);
+
+ // Get entrypoint address
+ void* entrypoint = map_va(&map, chdr->entry_va);
+ TSH_CHECK(entrypoint != NULL, TS_EBADMSG);
+
+ // Initialize applet privileges
+ applet_privileges_t privileges = {0};
+
+ applet_init(applet, &privileges, unload_cb);
+
+ applet_set_heap(applet, (void*)map.heap_p_addr, map.heap_size);
+
+ applet->layout = (applet_layout_t){
+ .code1.start = map.ro_p_addr,
+ .code1.size = map.ro_size,
+ .data1.start = map.rw_p_addr,
+ .data1.size = map.rw_size + map.stack_size + map.heap_size,
+ .code2 = coreapp_get_code_area(), // app needs access to coreapp code
+ .tls = coreapp_get_tls_area(), // app needs access to coreapp TLS
+ };
+
+ // Enable access to applet memory regions
+ mpu_set_active_applet(&applet->layout);
+
+ // Initialize the applet task
+ bool ok = systask_init(&applet->task, map.stack_p_addr, map.stack_size,
+ map.rw_p_addr, applet);
+ TSH_CHECK(ok, TS_ENOMEM);
+
+ // Enable coreapp TLS area swapping
+ systask_enable_tls(&applet->task, coreapp_get_tls_area());
+
+ uint32_t api_getter = (uint32_t)coreapp_get_api_getter();
+
+ // Prepare the applet to run - push exception frame on the stack
+ // with the entrypoint address
+ ok = systask_push_call(&applet->task, entrypoint, api_getter, 0, 0);
+ TSH_CHECK(ok, TS_ENOMEM);
+
+ systask_set_mpu(systask_active());
+ TSH_RETURN;
+
+cleanup:
+ applet_unload(applet);
+ memset(applet, 0, sizeof(*applet));
+
+ systask_set_mpu(systask_active());
+ TSH_RETURN;
+}
+
+#endif // KERNEL_MODE
### core/embed/io/app_arena/unix/app_loader.c
@@ -0,0 +1,138 @@
+/*
+ * This file is part of the Trezor project, https://trezor.io/
+ *
+ * Copyright (c) SatoshiLabs
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <trezor_rtl.h>
+
+#include <sys/applet.h>
+#include <sys/coreapp.h>
+#include <sys/logging.h>
+#include <sys/profile.h>
+#include <sys/systask.h>
+
+#include "../app_loader.h"
+
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+LOG_DECLARE(app_loader)
+
+ts_t app_loader_verify_payload(const app_header_t* header, const void* code,
+ size_t code_size) {
+ TSH_DECLARE;
+
+ TSH_CHECK_ARG(header != NULL);
+ TSH_CHECK_ARG(code != NULL);
+
+ TSH_CHECK(header->target_arch == APP_TARGET_ARCH_X86_64, TS_EBADMSG);
+ TSH_CHECK(code_size == header->code_size, TS_EBADMSG);
+
+cleanup:
+ TSH_RETURN;
+}
+
+static ts_t write_to_file(const char* filename, const void* elf_ptr,
+ size_t elf_size) {
+ TSH_DECLARE;
+
+ FILE* f = fopen(filename, "wb");
+ TSH_CHECK(f != NULL, TS_EIO);
+
+ size_t rc = fwrite(elf_ptr, 1, elf_size, f);
+ TSH_CHECK(rc == elf_size, TS_EIO);
+
+cleanup:
+ if (f != NULL) {
+ fclose(f);
+ }
+
+ TSH_RETURN;
+}
+
+static void app_loader_applet_unload(applet_t* applet) {
+ if (applet->handle != NULL) {
+ // Unload dynamic library
+ dlclose(applet->handle);
+ applet->handle = NULL;
+ }
+}
+
+ts_t app_loader_prepare_applet(const app_header_t* header, void* code,
+ void* data, size_t data_size, applet_t* applet) {
+ TSH_DECLARE;
+ ts_t status;
+ char* directory = NULL;
+ char* filename = NULL;
+ int rc;
+
+ applet_privileges_t privileges = {0};
+
+ applet_init(applet, &privileges, app_loader_applet_unload);
+
+ applet_set_heap(applet, data, data_size);
+
+ // Isolate the applet file from other users before loading it.
+ rc = asprintf(&directory, "%s/trezor_ext_app.XXXXXX", profile_dir());
+ TSH_CHECK(rc >= 0, TS_ENOMEM);
+ TSH_CHECK(mkdtemp(directory) != NULL, TS_EIO);
+
+ rc = asprintf(&filename, "%s/applet.so", directory);
+ TSH_CHECK(rc >= 0, TS_ENOMEM);
+
+ // Copy the embedded elf image to a file in a private temporary directory.
+ status = write_to_file(filename, code, header->code_size);
+ TSH_CHECK_OK(status);
+
+ // Load the dynamic library from the temporary file
+ applet->handle = dlopen(filename, RTLD_NOW);
+
+ if (applet->handle == NULL) {
+ LOG_ERR("dlopen failed: %s", dlerror());
+ }
+ TSH_CHECK(applet->handle != NULL, TS_EBADMSG);
+
+ // Get the entrypoint function from the dynamic library
+ void* entrypoint = dlsym(applet->handle, "applet_main");
+ TSH_CHECK(entrypoint != NULL, TS_EBADMSG);
+
+ bool ok = systask_init(&applet->task, 0, 0, 0, applet);
+ TSH_CHECK(ok, TS_ENOMEM);
+
+ uintptr_t api_getter = (uintptr_t)coreapp_get_api_getter();
+
+ ok = systask_push_call(&applet->task, entrypoint, api_getter, 0, 0);
+ TSH_CHECK(ok, TS_ENOMEM);
+
+cleanup:
+ if (ts_error(TSH_STATUS)) {
+ applet_unload(applet);
+ }
+
+ if (filename != NULL) {
+ unlink(filename);
+ free(filename);
+ }
+
+ if (directory != NULL) {
+ rmdir(directory);
+ free(directory);
+ }
+
+ TSH_RETURN;
+}
### core/embed/io/app_loader/app_arena.c
@@ -1,157 +0,0 @@
-/*
- * This file is part of the Trezor project, https://trezor.io/
- *
- * Copyright (c) SatoshiLabs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <trezor_model.h>
-#include <trezor_rtl.h>
-
-#include "app_arena.h"
-
-#include <stdlib.h>
-
-#ifdef USE_TRUSTZONE
-#include <sys/trustzone.h>
-#endif
-
-// Simple arena allocator that can allocate up to two blocks:
-// - one "image" block from the front of the arena
-// - one "data" block from the back of the arena
-//
-// The image block always starts at mem_ptr (offset 0).
-// The data block always grows from the end of the arena backwards.
-//
-// At most one image block and one data block can exist at the same time.
-// This allocator does NOT support general-purpose malloc/free patterns.
-//
-
-typedef struct {
- // Indicates whether the arena is initialized
- bool initialized;
-
- // Base pointer to the arena memoru
- uint8_t* mem_ptr;
- // Total size of the arena memory
- size_t mem_size;
-
- // Size of the image block at the fron (0 if none)
- size_t front_used;
- // Size of the data block at the back (0 if none)
- size_t back_used;
-
-} app_arena_t;
-
-// Global app arena instance
-static app_arena_t g_app_arena = {0};
-
-ts_t app_arena_init() {
- app_arena_t* arena = &g_app_arena;
-
- if (arena->initialized) {
- return TS_OK;
- }
-
- TSH_DECLARE;
-
- memset(arena, 0, sizeof(app_arena_t));
-
-#ifdef TREZOR_EMULATOR
- arena->mem_size = 64 * 1024 * 1024;
- arena->mem_ptr = malloc(arena->mem_size);
- TSH_CHECK(arena->mem_ptr != NULL, TS_ENOMEM);
-#else
- arena->mem_size = APPDATA_RAM_SIZE;
- arena->mem_ptr = (uint8_t*)APPDATA_RAM_START;
- TSH_CHECK(arena->mem_ptr != NULL, TS_ENOMEM);
-
-#ifdef USE_TRUSTZONE
- // Allow unprivileged access to app arena memory
- tz_set_sram_unpriv(APPDATA_RAM_START, APPDATA_RAM_SIZE, true);
- // Allow unprivileged access to app code area
- tz_set_flash_unpriv(APPCODE_START, APPCODE_MAXSIZE, true);
-#endif
-
-#endif
-
- arena->initialized = true;
-
-cleanup:
- TSH_RETURN;
-}
-
-void* app_arena_alloc(size_t block_size, app_alloc_type_t type) {
- app_arena_t* arena = &g_app_arena;
-
- if (!arena->initialized) {
- return NULL;
- }
-
- switch (type) {
- case APP_ALLOC_IMAGE:
- // Only one image block allowed
- if (arena->front_used > 0) {
- return NULL;
- }
-
- // Check for available space
- if (arena->back_used + block_size > arena->mem_size) {
- return NULL;
- }
-
- arena->front_used = block_size;
-
- // Image block always starts at the beginning of the arena
- return arena->mem_ptr;
-
- case APP_ALLOC_DATA:
- // Only one data block allowed
- if (arena->back_used > 0) {
- return NULL;
- }
-
- // Check for available space
- if (arena->front_used + block_size > arena->mem_size) {
- return NULL;
- }
-
- arena->back_used = block_size;
-
- // Data block grows from the end of the arena backwards
- return arena->mem_ptr + (arena->mem_size - arena->back_used);
- }
-
- return NULL;
-}
-
-void app_arena_free(void* ptr) {
- app_arena_t* arena = &g_app_arena;
-
- if (!arena->initialized) {
- return;
- }
-
- if (ptr == arena->mem_ptr && arena->front_used > 0) {
- arena->front_used = 0;
- return;
- }
-
- if (ptr == arena->mem_ptr + (arena->mem_size - arena->back_used) &&
- arena->back_used > 0) {
- arena->back_used = 0;
- return;
- }
-}
### core/embed/io/app_loader/app_arena.h
@@ -1,49 +0,0 @@
-/*
- * This file is part of the Trezor project, https://trezor.io/
- *
- * Copyright (c) SatoshiLabs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include <trezor_types.h>
-
-typedef enum {
- APP_ALLOC_IMAGE, /** Image memory allocation */
- APP_ALLOC_DATA, /** Data memory allocation */
-} app_alloc_type_t;
-
-/** Initializes the application arena.
- *
- * @return TS_OK on success, or an error code on failure.
- */
-ts_t __wur app_arena_init(void);
-
-/**
- * Allocates memory for an application.
- *
- * @param size The size of the memory to allocate in bytes.
- *
- * @return Pointer to the allocated memory, or NULL if allocation failed.
- */
-void* app_arena_alloc(size_t size, app_alloc_type_t type);
-
-/**
- * Frees memory previously allocated with app_arena_alloc().
- *
- * @param ptr Pointer to the memory to free. If NULL, no action is taken.
- */
-void app_arena_free(void* ptr);
### core/embed/io/app_loader/app_cache.c
@@ -1,327 +0,0 @@
-/*
- * This file is part of the Trezor project, https://trezor.io/
- *
- * Copyright (c) SatoshiLabs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef KERNEL_MODE
-
-#include <trezor_rtl.h>
-
-#include <io/app_cache.h>
-
-#include "app_arena.h"
-
-// Maximum number of tracked app cache entries
-#define MAX_APP_CACHE_ENTRIES 1
-
-typedef struct {
- // Application identifier (hash of the application image)
- app_hash_t hash;
- // Application is locked, preventing deletion
- bool locked;
- // Application image is being loaded
- bool loading;
- // Allocated space for the application image
- void* image_data;
- // Allocated size of the application image
- size_t image_size;
-} app_cache_image_t;
-
-typedef struct {
- // Indicates whether the app cache is initialized
- bool initialized;
- // Tracked app cache entries
- app_cache_image_t apps[MAX_APP_CACHE_ENTRIES];
-} app_cache_t;
-
-// Global app cache instance
-static app_cache_t g_app_cache;
-
-ts_t app_cache_init(void) {
- app_cache_t* cache = &g_app_cache;
-
- if (cache->initialized) {
- return TS_OK;
- }
-
- TSH_DECLARE;
- ts_t status;
-
- memset(cache, 0, sizeof(*cache));
-
- status = app_arena_init();
- TSH_CHECK_OK(status);
-
- cache->initialized = true;
-
-cleanup:
- TSH_RETURN;
-}
-
-static app_cache_image_t* find_entry_by_hash(const app_hash_t* hash) {
- app_cache_t* cache = &g_app_cache;
-
- for (size_t i = 0; i < MAX_APP_CACHE_ENTRIES; i++) {
- app_cache_image_t* image = &cache->apps[i];
- if (memcmp(&image->hash, hash, sizeof(app_hash_t)) == 0) {
- return image;
- }
- }
-
- return NULL;
-}
-
-static app_cache_image_t* validate_image_handle(app_cache_handle_t handle) {
- app_cache_t* cache = &g_app_cache;
-
- if (!cache->initialized) {
- return NULL;
- }
-
- for (size_t i = 0; i < MAX_APP_CACHE_ENTRIES; i++) {
- app_cache_image_t* image = &cache->apps[i];
- if (image == (app_cache_image_t*)handle) {
- return image;
- }
- }
-
- return NULL;
-}
-
-static inline app_cache_handle_t image_to_handle(app_cache_image_t* image) {
- return (app_cache_handle_t)image;
-}
-
-static app_cache_image_t* alloc_entry(const app_hash_t* hash) {
- app_cache_t* cache = &g_app_cache;
-
- app_hash_t zero_hash = {0};
-
- for (size_t i = 0; i < MAX_APP_CACHE_ENTRIES; i++) {
- app_cache_image_t* image = &cache->apps[i];
- if (memcmp(&image->hash, &zero_hash, sizeof(app_hash_t)) == 0) {
- memcpy(&image->hash, hash, sizeof(app_hash_t));
- return image;
- }
- }
-
- return NULL;
-}
-
-static void remove_entry(app_cache_image_t* image) {
- if (image->image_data != NULL) {
- app_arena_free(image->image_data);
- }
- memset(image, 0, sizeof(*image));
-}
-
-static void reclaim_free_space(size_t size) {
- app_cache_t* cache = &g_app_cache;
-
- // basic implementation: remove all non-locked entries
- for (size_t i = 0; i < MAX_APP_CACHE_ENTRIES; i++) {
- app_cache_image_t* image = &cache->apps[i];
- if (!image->locked) {
- remove_entry(image);
- }
- }
-}
-
-app_cache_handle_t app_cache_create_image(const app_hash_t* hash, size_t size) {
- app_cache_t* cache = &g_app_cache;
-
- if (!cache->initialized) {
- return APP_CACHE_INVALID_HANDLE;
- }
-
- app_cache_image_t* image = find_entry_by_hash(hash);
- if (image != NULL) {
- if (image->loading || image->locked) {
- // Image is already being used
- return APP_CACHE_INVALID_HANDLE;
- }
-
- // Remove existing image to create a new one
- remove_entry(image);
- }
-
- reclaim_free_space(size);
-
- image = alloc_entry(hash);
- if (image == NULL) {
- // No space for new app image
- return APP_CACHE_INVALID_HANDLE;
- }
-
- image->image_data = app_arena_alloc(size, APP_ALLOC_IMAGE);
- image->image_size = size;
- image->loading = true;
-
- if (image->image_data == NULL) {
- // Allocation failed, invalidate the image
- remove_entry(image);
- return APP_CACHE_INVALID_HANDLE;
- }
-
- return image_to_handle(image);
-}
-
-ts_t app_cache_write_image(app_cache_handle_t handle, uintptr_t offset,
- const void* data, size_t size) {
- app_cache_t* cache = &g_app_cache;
-
- TSH_DECLARE;
-
- TSH_CHECK(cache->initialized, TS_ENOINIT);
-
- app_cache_image_t* image = validate_image_handle(handle);
-
- // Check whether the image exists and can be written to
- TSH_CHECK(image != NULL, TS_ENOENT);
- TSH_CHECK(image->loading, TS_EBUSY);
-
- // Check whether the image data is allocated
- TSH_CHECK(image->image_data != NULL, TS_EINVAL);
-
- // Check whether the offset and size are within bounds
- TSH_CHECK(offset < image->image_size, TS_EINVAL);
- TSH_CHECK(size <= image->image_size - offset, TS_EINVAL);
-
- // TODO: Consider a special new mpu mode or reusing MPU_MODE_APP here
- mpu_mode_t mpu_mode = mpu_reconfig(MPU_MODE_DISABLED);
- memcpy((uint8_t*)image->image_data + offset, data, size);
- mpu_restore(mpu_mode);
-
-cleanup:
- TSH_RETURN;
-}
-
-ts_t app_cache_finalize_image(app_cache_handle_t handle, bool accept) {
- app_cache_t* cache = &g_app_cache;
-
- TSH_DECLARE;
-
- TSH_CHECK(cache->initialized, TS_ENOINIT);
-
- app_cache_image_t* image = validate_image_handle(handle);
- TSH_CHECK(image != NULL, TS_ENOENT);
- TSH_CHECK(image->loading, TS_EINVAL);
-
- if (accept) {
- image->loading = false;
- } else {
- remove_entry(image);
- }
-
-cleanup:
- TSH_RETURN;
-}
-
-app_cache_handle_t app_cache_lock_image(const app_hash_t* hash, void** ptr,
- size_t* size) {
- app_cache_t* cache = &g_app_cache;
-
- *ptr = NULL;
- *size = 0;
-
- if (!cache->initialized) {
- return APP_CACHE_INVALID_HANDLE;
- }
-
- app_cache_image_t* image = find_entry_by_hash(hash);
- if (image == NULL || image->locked || image->loading) {
- return APP_CACHE_INVALID_HANDLE;
- }
-
- image->locked = true;
-
- *ptr = image->image_data;
- *size = image->image_size;
- return image_to_handle(image);
-}
-
-void app_cache_unlock_image(app_cache_handle_t handle) {
- app_cache_t* cache = &g_app_cache;
-
- if (!cache->initialized) {
- return;
- }
-
- app_cache_image_t* image = validate_image_handle(handle);
-
- if (image != NULL) {
- image->locked = false;
- }
-}
-
-#ifdef TREZOR_EMULATOR
-ts_t app_cache_load_file(const app_hash_t* hash, const char* filename) {
- TSH_DECLARE;
- ts_t status;
-
- app_cache_handle_t image = APP_CACHE_INVALID_HANDLE;
-
- FILE* f = fopen(filename, "rb");
- TSH_CHECK(f != NULL, TS_EIO);
-
- fseek(f, 0, SEEK_END);
- size_t size = ftell(f);
- fseek(f, 0, SEEK_SET);
-
- image = app_cache_create_image(hash, size);
- TSH_CHECK(image != APP_CACHE_INVALID_HANDLE, TS_ENOMEM);
-
- uintptr_t offset = 0;
-
- while (size > 0) {
- uint8_t buffer[1024];
- size_t to_read = size < sizeof(buffer) ? size : sizeof(buffer);
-
- size_t read = fread(buffer, 1, to_read, f);
- TSH_CHECK(read == to_read, TS_EIO);
-
- status = app_cache_write_image(image, offset, buffer, read);
- TSH_CHECK_OK(status);
-
- offset += read;
- size -= read;
- }
-
- fclose(f);
- f = NULL;
-
- status = app_cache_finalize_image(image, true);
- TSH_CHECK_OK(status);
-
- image = APP_CACHE_INVALID_HANDLE;
-
-cleanup:
- if (f != NULL) {
- fclose(f);
- }
-
- if (image != APP_CACHE_INVALID_HANDLE) {
- status = app_cache_finalize_image(image, false);
- UNUSED(status);
- }
-
- TSH_RETURN;
-}
-
-#endif
-
-#endif // KERNEL_MODE
### core/embed/io/app_loader/app_task.c
@@ -1,221 +0,0 @@
-/*
- * This file is part of the Trezor project, https://trezor.io/
- *
- * Copyright (c) SatoshiLabs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifdef KERNEL_MODE
-
-#include <trezor_model.h>
-#include <trezor_rtl.h>
-
-#include <sys/applet.h>
-
-#include <io/app_cache.h>
-#include <io/app_loader.h>
-#include <io/elf_loader.h>
-
-#include "app_arena.h"
-
-// Maximum number of tracked app loader entries
-#define MAX_APP_LOADER_ENTRIES 1
-
-typedef struct {
- // Application identifier (hash of the application image)
- app_hash_t hash;
- // Locked application image in the cache (or 0 if not used)
- app_cache_handle_t locked_image;
- // Applet associated with the application
- applet_t applet;
-} app_entry_t;
-
-typedef struct {
- // Indicates whether the app loader is initialized
- bool initialized;
- // Tracked app loader entries
- app_entry_t apps[MAX_APP_LOADER_ENTRIES];
-} app_loader_t;
-
-// Global app loader instance
-static app_loader_t g_app_loader;
-
-ts_t app_loader_init(void) {
- app_loader_t* loader = &g_app_loader;
-
- if (loader->initialized) {
- return TS_OK;
- }
-
- TSH_DECLARE;
- ts_t status;
-
- memset(loader, 0, sizeof(*loader));
-
- status = app_arena_init();
- TSH_CHECK_OK(status);
-
- loader->initialized = true;
-
-cleanup:
- TSH_RETURN;
-}
-
-static app_entry_t* find_app_by_task(systask_id_t task_id) {
- app_loader_t* loader = &g_app_loader;
-
- for (size_t i = 0; i < MAX_APP_LOADER_ENTRIES; i++) {
- app_entry_t* entry = &loader->apps[i];
- if (entry->applet.task.id == task_id) {
- return entry;
- }
- }
-
- return NULL;
-}
-
-static app_entry_t* find_app_by_hash(const app_hash_t* hash) {
- app_loader_t* loader = &g_app_loader;
-
- for (size_t i = 0; i < MAX_APP_LOADER_ENTRIES; i++) {
- app_entry_t* entry = &loader->apps[i];
- if (memcmp(&entry->hash, hash, sizeof(app_hash_t)) == 0) {
- return entry;
- }
- }
-
- return NULL;
-}
-
-static app_entry_t* alloc_entry(const app_hash_t* hash) {
- app_loader_t* loader = &g_app_loader;
-
- app_hash_t zero_hash = {0};
-
- for (size_t i = 0; i < MAX_APP_LOADER_ENTRIES; i++) {
- app_entry_t* entry = &loader->apps[i];
- if (memcmp(&entry->hash, &zero_hash, sizeof(app_hash_t)) == 0) {
- memset(entry, 0, sizeof(app_entry_t));
- memcpy(&entry->hash, hash, sizeof(app_hash_t));
- return entry;
- }
- }
-
- return NULL;
-}
-
-static void remove_entry(app_entry_t* entry) {
- if (entry->locked_image != APP_CACHE_INVALID_HANDLE) {
- app_cache_unlock_image(entry->locked_image);
- entry->locked_image = APP_CACHE_INVALID_HANDLE;
- }
-
- memset(entry, 0, sizeof(*entry));
-}
-
-ts_t app_task_spawn(const app_hash_t* hash, systask_id_t* task_id) {
- app_loader_t* loader = &g_app_loader;
-
- TSH_DECLARE;
- ts_t status;
-
- app_entry_t* entry = NULL;
-
- TSH_CHECK(loader->initialized, TS_ENOINIT);
-
- // Check if the application is already spawned
- TSH_CHECK(find_app_by_hash(hash) == NULL, TS_EBUSY);
-
- entry = alloc_entry(hash);
- TSH_CHECK(entry != NULL, TS_ENOMEM); // No space for new app entry
-
- void* image_ptr = NULL;
- size_t image_size = 0;
-
- entry->locked_image = app_cache_lock_image(hash, &image_ptr, &image_size);
- TSH_CHECK(entry->locked_image != APP_CACHE_INVALID_HANDLE, TS_ENOENT);
-
- status = elf_load(&entry->applet, image_ptr, image_size);
-
- if (ts_error(status)) {
- if (!ts_eq(status, TS_ENOMEM)) {
- // Remap to generic error
- status = TS_EINVAL;
- }
- }
- TSH_CHECK_OK(status);
-
- applet_run(&entry->applet);
-
- *task_id = entry->applet.task.id;
-
- TSH_RETURN;
-
-cleanup:
- if (entry != NULL) {
- remove_entry(entry);
- }
-
- TSH_RETURN;
-}
-
-bool app_task_is_running(systask_id_t task_id) {
- app_loader_t* loader = &g_app_loader;
-
- if (!loader->initialized) {
- return false;
- }
-
- app_entry_t* entry = find_app_by_task(task_id);
- if (entry == NULL) {
- return false;
- }
-
- return systask_is_alive(&entry->applet.task);
-}
-
-ts_t app_task_get_pminfo(systask_id_t task_id, systask_postmortem_t* pminfo) {
- app_loader_t* loader = &g_app_loader;
-
- TSH_DECLARE;
-
- memset(pminfo, 0, sizeof(*pminfo));
-
- TSH_CHECK(loader->initialized, TS_ENOINIT);
-
- app_entry_t* entry = find_app_by_task(task_id);
- TSH_CHECK(entry != NULL, TS_ENOENT);
-
- *pminfo = entry->applet.task.pminfo;
-
-cleanup:
- TSH_RETURN;
-}
-
-void app_task_unload(systask_id_t task_id) {
- app_loader_t* loader = &g_app_loader;
-
- if (!loader->initialized) {
- return;
- }
-
- app_entry_t* entry = find_app_by_task(task_id);
- if (entry != NULL) {
- applet_unload(&entry->applet);
- remove_entry(entry);
- }
-}
-
-#endif // KERNEL_MODE
### core/embed/io/app_loader/build.rs
@@ -1,27 +0,0 @@
-use xbuild::{CLibrary, Result, bail_unsupported};
-
-pub fn def_module(lib: &mut CLibrary) -> Result<()> {
- lib.add_include("app_loader/inc");
-
- // USE_APP_LOADING is defined in sys layer
-
- if cfg!(not(feature = "emulator")) {
- lib.add_define("THREAD_LOCAL", Some("__attribute__((section(\".tls\")))"));
- }
-
- lib.add_sources([
- "app_loader/app_arena.c",
- "app_loader/app_task.c",
- "app_loader/app_cache.c",
- ]);
-
- if cfg!(feature = "emulator") {
- lib.add_source("app_loader/unix/elf_loader.c");
- } else if cfg!(feature = "mcu_stm32") {
- lib.add_source("app_loader/stm32/elf_loader.c");
- } else {
- bail_unsupported!();
- }
-
- Ok(())
-}
### core/embed/io/app_loader/elf.h
@@ -1,2913 +0,0 @@
-/*
-From musl include/elf.h
-
-Copyright © 2005-2014 Rich Felker, et al.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-*/
-
-#ifndef _ELF_H
-#define _ELF_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stdint.h>
-
-typedef uint16_t Elf32_Half;
-typedef uint16_t Elf64_Half;
-
-typedef uint32_t Elf32_Word;
-typedef int32_t Elf32_Sword;
-typedef uint32_t Elf64_Word;
-typedef int32_t Elf64_Sword;
-
-typedef uint64_t Elf32_Xword;
-typedef int64_t Elf32_Sxword;
-typedef uint64_t Elf64_Xword;
-typedef int64_t Elf64_Sxword;
-
-typedef uint32_t Elf32_Addr;
-typedef uint64_t Elf64_Addr;
-
-typedef uint32_t Elf32_Off;
-typedef uint64_t Elf64_Off;
-
-typedef uint16_t Elf32_Section;
-typedef uint16_t Elf64_Section;
-
-typedef Elf32_Half Elf32_Versym;
-typedef Elf64_Half Elf64_Versym;
-
-#define EI_NIDENT (16)
-
-typedef struct {
- unsigned char e_ident[EI_NIDENT];
- Elf32_Half e_type;
- Elf32_Half e_machine;
- Elf32_Word e_version;
- Elf32_Addr e_entry;
- Elf32_Off e_phoff;
- Elf32_Off e_shoff;
- Elf32_Word e_flags;
- Elf32_Half e_ehsize;
- Elf32_Half e_phentsize;
- Elf32_Half e_phnum;
- Elf32_Half e_shentsize;
- Elf32_Half e_shnum;
- Elf32_Half e_shstrndx;
-} Elf32_Ehdr;
-
-typedef struct {
- unsigned char e_ident[EI_NIDENT];
- Elf64_Half e_type;
- Elf64_Half e_machine;
- Elf64_Word e_version;
- Elf64_Addr e_entry;
- Elf64_Off e_phoff;
- Elf64_Off e_shoff;
- Elf64_Word e_flags;
- Elf64_Half e_ehsize;
- Elf64_Half e_phentsize;
- Elf64_Half e_phnum;
- Elf64_Half e_shentsize;
- Elf64_Half e_shnum;
- Elf64_Half e_shstrndx;
-} Elf64_Ehdr;
-
-#define EI_MAG0 0
-#define ELFMAG0 0x7f
-
-#define EI_MAG1 1
-#define ELFMAG1 'E'
-
-#define EI_MAG2 2
-#define ELFMAG2 'L'
-
-#define EI_MAG3 3
-#define ELFMAG3 'F'
-
-#define ELFMAG "\177ELF"
-#define SELFMAG 4
-
-#define EI_CLASS 4
-#define ELFCLASSNONE 0
-#define ELFCLASS32 1
-#define ELFCLASS64 2
-#define ELFCLASSNUM 3
-
-#define EI_DATA 5
-#define ELFDATANONE 0
-#define ELFDATA2LSB 1
-#define ELFDATA2MSB 2
-#define ELFDATANUM 3
-
-#define EI_VERSION 6
-
-#define EI_OSABI 7
-#define ELFOSABI_NONE 0
-#define ELFOSABI_SYSV 0
-#define ELFOSABI_HPUX 1
-#define ELFOSABI_NETBSD 2
-#define ELFOSABI_LINUX 3
-#define ELFOSABI_GNU 3
-#define ELFOSABI_SOLARIS 6
-#define ELFOSABI_AIX 7
-#define ELFOSABI_IRIX 8
-#define ELFOSABI_FREEBSD 9
-#define ELFOSABI_TRU64 10
-#define ELFOSABI_MODESTO 11
-#define ELFOSABI_OPENBSD 12
-#define ELFOSABI_ARM 97
-#define ELFOSABI_STANDALONE 255
-
-#define EI_ABIVERSION 8
-
-#define EI_PAD 9
-
-#define ET_NONE 0
-#define ET_REL 1
-#define ET_EXEC 2
-#define ET_DYN 3
-#define ET_CORE 4
-#define ET_NUM 5
-#define ET_LOOS 0xfe00
-#define ET_HIOS 0xfeff
-#define ET_LOPROC 0xff00
-#define ET_HIPROC 0xffff
-
-#define EM_NONE 0
-#define EM_M32 1
-#define EM_SPARC 2
-#define EM_386 3
-#define EM_68K 4
-#define EM_88K 5
-#define EM_860 7
-#define EM_MIPS 8
-#define EM_S370 9
-#define EM_MIPS_RS3_LE 10
-
-#define EM_PARISC 15
-#define EM_VPP500 17
-#define EM_SPARC32PLUS 18
-#define EM_960 19
-#define EM_PPC 20
-#define EM_PPC64 21
-#define EM_S390 22
-
-#define EM_V800 36
-#define EM_FR20 37
-#define EM_RH32 38
-#define EM_RCE 39
-#define EM_ARM 40
-#define EM_FAKE_ALPHA 41
-#define EM_SH 42
-#define EM_SPARCV9 43
-#define EM_TRICORE 44
-#define EM_ARC 45
-#define EM_H8_300 46
-#define EM_H8_300H 47
-#define EM_H8S 48
-#define EM_H8_500 49
-#define EM_IA_64 50
-#define EM_MIPS_X 51
-#define EM_COLDFIRE 52
-#define EM_68HC12 53
-#define EM_MMA 54
-#define EM_PCP 55
-#define EM_NCPU 56
-#define EM_NDR1 57
-#define EM_STARCORE 58
-#define EM_ME16 59
-#define EM_ST100 60
-#define EM_TINYJ 61
-#define EM_X86_64 62
-#define EM_PDSP 63
-
-#define EM_FX66 66
-#define EM_ST9PLUS 67
-#define EM_ST7 68
-#define EM_68HC16 69
-#define EM_68HC11 70
-#define EM_68HC08 71
-#define EM_68HC05 72
-#define EM_SVX 73
-#define EM_ST19 74
-#define EM_VAX 75
-#define EM_CRIS 76
-#define EM_JAVELIN 77
-#define EM_FIREPATH 78
-#define EM_ZSP 79
-#define EM_MMIX 80
-#define EM_HUANY 81
-#define EM_PRISM 82
-#define EM_AVR 83
-#define EM_FR30 84
-#define EM_D10V 85
-#define EM_D30V 86
-#define EM_V850 87
-#define EM_M32R 88
-#define EM_MN10300 89
-#define EM_MN10200 90
-#define EM_PJ 91
-#define EM_OR1K 92
-#define EM_OPENRISC 92
-#define EM_ARC_A5 93
-#define EM_ARC_COMPACT 93
-#define EM_XTENSA 94
-#define EM_VIDEOCORE 95
-#define EM_TMM_GPP 96
-#define EM_NS32K 97
-#define EM_TPC 98
-#define EM_SNP1K 99
-#define EM_ST200 100
-#define EM_IP2K 101
-#define EM_MAX 102
-#define EM_CR 103
-#define EM_F2MC16 104
-#define EM_MSP430 105
-#define EM_BLACKFIN 106
-#define EM_SE_C33 107
-#define EM_SEP 108
-#define EM_ARCA 109
-#define EM_UNICORE 110
-#define EM_EXCESS 111
-#define EM_DXP 112
-#define EM_ALTERA_NIOS2 113
-#define EM_CRX 114
-#define EM_XGATE 115
-#define EM_C166 116
-#define EM_M16C 117
-#define EM_DSPIC30F 118
-#define EM_CE 119
-#define EM_M32C 120
-#define EM_TSK3000 131
-#define EM_RS08 132
-#define EM_SHARC 133
-#define EM_ECOG2 134
-#define EM_SCORE7 135
-#define EM_DSP24 136
-#define EM_VIDEOCORE3 137
-#define EM_LATTICEMICO32 138
-#define EM_SE_C17 139
-#define EM_TI_C6000 140
-#define EM_TI_C2000 141
-#define EM_TI_C5500 142
-#define EM_TI_ARP32 143
-#define EM_TI_PRU 144
-#define EM_MMDSP_PLUS 160
-#define EM_CYPRESS_M8C 161
-#define EM_R32C 162
-#define EM_TRIMEDIA 163
-#define EM_QDSP6 164
-#define EM_8051 165
-#define EM_STXP7X 166
-#define EM_NDS32 167
-#define EM_ECOG1X 168
-#define EM_MAXQ30 169
-#define EM_XIMO16 170
-#define EM_MANIK 171
-#define EM_CRAYNV2 172
-#define EM_RX 173
-#define EM_METAG 174
-#define EM_MCST_ELBRUS 175
-#define EM_ECOG16 176
-#define EM_CR16 177
-#define EM_ETPU 178
-#define EM_SLE9X 179
-#define EM_L10M 180
-#define EM_K10M 181
-#define EM_AARCH64 183
-#define EM_AVR32 185
-#define EM_STM8 186
-#define EM_TILE64 187
-#define EM_TILEPRO 188
-#define EM_MICROBLAZE 189
-#define EM_CUDA 190
-#define EM_TILEGX 191
-#define EM_CLOUDSHIELD 192
-#define EM_COREA_1ST 193
-#define EM_COREA_2ND 194
-#define EM_ARC_COMPACT2 195
-#define EM_OPEN8 196
-#define EM_RL78 197
-#define EM_VIDEOCORE5 198
-#define EM_78KOR 199
-#define EM_56800EX 200
-#define EM_BA1 201
-#define EM_BA2 202
-#define EM_XCORE 203
-#define EM_MCHP_PIC 204
-#define EM_KM32 210
-#define EM_KMX32 211
-#define EM_EMX16 212
-#define EM_EMX8 213
-#define EM_KVARC 214
-#define EM_CDP 215
-#define EM_COGE 216
-#define EM_COOL 217
-#define EM_NORC 218
-#define EM_CSR_KALIMBA 219
-#define EM_Z80 220
-#define EM_VISIUM 221
-#define EM_FT32 222
-#define EM_MOXIE 223
-#define EM_AMDGPU 224
-#define EM_RISCV 243
-#define EM_BPF 247
-#define EM_NUM 248
-
-#define EM_ALPHA 0x9026
-
-#define EV_NONE 0
-#define EV_CURRENT 1
-#define EV_NUM 2
-
-typedef struct {
- Elf32_Word sh_name;
- Elf32_Word sh_type;
- Elf32_Word sh_flags;
- Elf32_Addr sh_addr;
- Elf32_Off sh_offset;
- Elf32_Word sh_size;
- Elf32_Word sh_link;
- Elf32_Word sh_info;
- Elf32_Word sh_addralign;
- Elf32_Word sh_entsize;
-} Elf32_Shdr;
-
-typedef struct {
- Elf64_Word sh_name;
- Elf64_Word sh_type;
- Elf64_Xword sh_flags;
- Elf64_Addr sh_addr;
- Elf64_Off sh_offset;
- Elf64_Xword sh_size;
- Elf64_Word sh_link;
- Elf64_Word sh_info;
- Elf64_Xword sh_addralign;
- Elf64_Xword sh_entsize;
-} Elf64_Shdr;
-
-#define SHN_UNDEF 0
-#define SHN_LORESERVE 0xff00
-#define SHN_LOPROC 0xff00
-#define SHN_BEFORE 0xff00
-
-#define SHN_AFTER 0xff01
-
-#define SHN_HIPROC 0xff1f
-#define SHN_LOOS 0xff20
-#define SHN_HIOS 0xff3f
-#define SHN_ABS 0xfff1
-#define SHN_COMMON 0xfff2
-#define SHN_XINDEX 0xffff
-#define SHN_HIRESERVE 0xffff
-
-#define SHT_NULL 0
-#define SHT_PROGBITS 1
-#define SHT_SYMTAB 2
-#define SHT_STRTAB 3
-#define SHT_RELA 4
-#define SHT_HASH 5
-#define SHT_DYNAMIC 6
-#define SHT_NOTE 7
-#define SHT_NOBITS 8
-#define SHT_REL 9
-#define SHT_SHLIB 10
-#define SHT_DYNSYM 11
-#define SHT_INIT_ARRAY 14
-#define SHT_FINI_ARRAY 15
-#define SHT_PREINIT_ARRAY 16
-#define SHT_GROUP 17
-#define SHT_SYMTAB_SHNDX 18
-#define SHT_NUM 19
-#define SHT_LOOS 0x60000000
-#define SHT_GNU_ATTRIBUTES 0x6ffffff5
-#define SHT_GNU_HASH 0x6ffffff6
-#define SHT_GNU_LIBLIST 0x6ffffff7
-#define SHT_CHECKSUM 0x6ffffff8
-#define SHT_LOSUNW 0x6ffffffa
-#define SHT_SUNW_move 0x6ffffffa
-#define SHT_SUNW_COMDAT 0x6ffffffb
-#define SHT_SUNW_syminfo 0x6ffffffc
-#define SHT_GNU_verdef 0x6ffffffd
-#define SHT_GNU_verneed 0x6ffffffe
-#define SHT_GNU_versym 0x6fffffff
-#define SHT_HISUNW 0x6fffffff
-#define SHT_HIOS 0x6fffffff
-#define SHT_LOPROC 0x70000000
-#define SHT_HIPROC 0x7fffffff
-#define SHT_LOUSER 0x80000000
-#define SHT_HIUSER 0x8fffffff
-
-#define SHF_WRITE (1 << 0)
-#define SHF_ALLOC (1 << 1)
-#define SHF_EXECINSTR (1 << 2)
-#define SHF_MERGE (1 << 4)
-#define SHF_STRINGS (1 << 5)
-#define SHF_INFO_LINK (1 << 6)
-#define SHF_LINK_ORDER (1 << 7)
-#define SHF_OS_NONCONFORMING (1 << 8)
-
-#define SHF_GROUP (1 << 9)
-#define SHF_TLS (1 << 10)
-#define SHF_COMPRESSED (1 << 11)
-#define SHF_MASKOS 0x0ff00000
-#define SHF_MASKPROC 0xf0000000
-#define SHF_ORDERED (1 << 30)
-#define SHF_EXCLUDE (1U << 31)
-
-typedef struct {
- Elf32_Word ch_type;
- Elf32_Word ch_size;
- Elf32_Word ch_addralign;
-} Elf32_Chdr;
-
-typedef struct {
- Elf64_Word ch_type;
- Elf64_Word ch_reserved;
- Elf64_Xword ch_size;
- Elf64_Xword ch_addralign;
-} Elf64_Chdr;
-
-#define ELFCOMPRESS_ZLIB 1
-#define ELFCOMPRESS_LOOS 0x60000000
-#define ELFCOMPRESS_HIOS 0x6fffffff
-#define ELFCOMPRESS_LOPROC 0x70000000
-#define ELFCOMPRESS_HIPROC 0x7fffffff
-
-#define GRP_COMDAT 0x1
-
-typedef struct {
- Elf32_Word st_name;
- Elf32_Addr st_value;
- Elf32_Word st_size;
- unsigned char st_info;
- unsigned char st_other;
- Elf32_Section st_shndx;
-} Elf32_Sym;
-
-typedef struct {
- Elf64_Word st_name;
- unsigned char st_info;
- unsigned char st_other;
- Elf64_Section st_shndx;
- Elf64_Addr st_value;
- Elf64_Xword st_size;
-} Elf64_Sym;
-
-typedef struct {
- Elf32_Half si_boundto;
- Elf32_Half si_flags;
-} Elf32_Syminfo;
-
-typedef struct {
- Elf64_Half si_boundto;
- Elf64_Half si_flags;
-} Elf64_Syminfo;
-
-#define SYMINFO_BT_SELF 0xffff
-#define SYMINFO_BT_PARENT 0xfffe
-#define SYMINFO_BT_LOWRESERVE 0xff00
-
-#define SYMINFO_FLG_DIRECT 0x0001
-#define SYMINFO_FLG_PASSTHRU 0x0002
-#define SYMINFO_FLG_COPY 0x0004
-#define SYMINFO_FLG_LAZYLOAD 0x0008
-
-#define SYMINFO_NONE 0
-#define SYMINFO_CURRENT 1
-#define SYMINFO_NUM 2
-
-#define ELF32_ST_BIND(val) (((unsigned char)(val)) >> 4)
-#define ELF32_ST_TYPE(val) ((val) & 0xf)
-#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
-
-#define ELF64_ST_BIND(val) ELF32_ST_BIND(val)
-#define ELF64_ST_TYPE(val) ELF32_ST_TYPE(val)
-#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO((bind), (type))
-
-#define STB_LOCAL 0
-#define STB_GLOBAL 1
-#define STB_WEAK 2
-#define STB_NUM 3
-#define STB_LOOS 10
-#define STB_GNU_UNIQUE 10
-#define STB_HIOS 12
-#define STB_LOPROC 13
-#define STB_HIPROC 15
-
-#define STT_NOTYPE 0
-#define STT_OBJECT 1
-#define STT_FUNC 2
-#define STT_SECTION 3
-#define STT_FILE 4
-#define STT_COMMON 5
-#define STT_TLS 6
-#define STT_NUM 7
-#define STT_LOOS 10
-#define STT_GNU_IFUNC 10
-#define STT_HIOS 12
-#define STT_LOPROC 13
-#define STT_HIPROC 15
-
-#define STN_UNDEF 0
-
-#define ELF32_ST_VISIBILITY(o) ((o) & 0x03)
-#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY(o)
-
-#define STV_DEFAULT 0
-#define STV_INTERNAL 1
-#define STV_HIDDEN 2
-#define STV_PROTECTED 3
-
-typedef struct {
- Elf32_Addr r_offset;
- Elf32_Word r_info;
-} Elf32_Rel;
-
-typedef struct {
- Elf64_Addr r_offset;
- Elf64_Xword r_info;
-} Elf64_Rel;
-
-typedef struct {
- Elf32_Addr r_offset;
- Elf32_Word r_info;
- Elf32_Sword r_addend;
-} Elf32_Rela;
-
-typedef struct {
- Elf64_Addr r_offset;
- Elf64_Xword r_info;
- Elf64_Sxword r_addend;
-} Elf64_Rela;
-
-#define ELF32_R_SYM(val) ((val) >> 8)
-#define ELF32_R_TYPE(val) ((val) & 0xff)
-#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff))
-
-#define ELF64_R_SYM(i) ((i) >> 32)
-#define ELF64_R_TYPE(i) ((i) & 0xffffffff)
-#define ELF64_R_INFO(sym, type) ((((Elf64_Xword)(sym)) << 32) + (type))
-
-typedef struct {
- Elf32_Word p_type;
- Elf32_Off p_offset;
- Elf32_Addr p_vaddr;
- Elf32_Addr p_paddr;
- Elf32_Word p_filesz;
- Elf32_Word p_memsz;
- Elf32_Word p_flags;
- Elf32_Word p_align;
-} Elf32_Phdr;
-
-typedef struct {
- Elf64_Word p_type;
- Elf64_Word p_flags;
- Elf64_Off p_offset;
- Elf64_Addr p_vaddr;
- Elf64_Addr p_paddr;
- Elf64_Xword p_filesz;
- Elf64_Xword p_memsz;
- Elf64_Xword p_align;
-} Elf64_Phdr;
-
-#define PT_NULL 0
-#define PT_LOAD 1
-#define PT_DYNAMIC 2
-#define PT_INTERP 3
-#define PT_NOTE 4
-#define PT_SHLIB 5
-#define PT_PHDR 6
-#define PT_TLS 7
-#define PT_NUM 8
-#define PT_LOOS 0x60000000
-#define PT_GNU_EH_FRAME 0x6474e550
-#define PT_GNU_STACK 0x6474e551
-#define PT_GNU_RELRO 0x6474e552
-#define PT_LOSUNW 0x6ffffffa
-#define PT_SUNWBSS 0x6ffffffa
-#define PT_SUNWSTACK 0x6ffffffb
-#define PT_HISUNW 0x6fffffff
-#define PT_HIOS 0x6fffffff
-#define PT_LOPROC 0x70000000
-#define PT_HIPROC 0x7fffffff
-
-#define PN_XNUM 0xffff
-
-#define PF_X (1 << 0)
-#define PF_W (1 << 1)
-#define PF_R (1 << 2)
-#define PF_MASKOS 0x0ff00000
-#define PF_MASKPROC 0xf0000000
-
-#define NT_PRSTATUS 1
-#define NT_FPREGSET 2
-#define NT_PRPSINFO 3
-#define NT_PRXREG 4
-#define NT_TASKSTRUCT 4
-#define NT_PLATFORM 5
-#define NT_AUXV 6
-#define NT_GWINDOWS 7
-#define NT_ASRS 8
-#define NT_PSTATUS 10
-#define NT_PSINFO 13
-#define NT_PRCRED 14
-#define NT_UTSNAME 15
-#define NT_LWPSTATUS 16
-#define NT_LWPSINFO 17
-#define NT_PRFPXREG 20
-#define NT_SIGINFO 0x53494749
-#define NT_FILE 0x46494c45
-#define NT_PRXFPREG 0x46e62b7f
-#define NT_PPC_VMX 0x100
-#define NT_PPC_SPE 0x101
-#define NT_PPC_VSX 0x102
-#define NT_386_TLS 0x200
-#define NT_386_IOPERM 0x201
-#define NT_X86_XSTATE 0x202
-#define NT_S390_HIGH_GPRS 0x300
-#define NT_S390_TIMER 0x301
-#define NT_S390_TODCMP 0x302
-#define NT_S390_TODPREG 0x303
-#define NT_S390_CTRS 0x304
-#define NT_S390_PREFIX 0x305
-#define NT_S390_LAST_BREAK 0x306
-#define NT_S390_SYSTEM_CALL 0x307
-#define NT_S390_TDB 0x308
-#define NT_ARM_VFP 0x400
-#define NT_ARM_TLS 0x401
-#define NT_ARM_HW_BREAK 0x402
-#define NT_ARM_HW_WATCH 0x403
-#define NT_ARM_SYSTEM_CALL 0x404
-#define NT_ARM_SVE 0x405
-#define NT_METAG_CBUF 0x500
-#define NT_METAG_RPIPE 0x501
-#define NT_METAG_TLS 0x502
-#define NT_VERSION 1
-
-typedef struct {
- Elf32_Sword d_tag;
- union {
- Elf32_Word d_val;
- Elf32_Addr d_ptr;
- } d_un;
-} Elf32_Dyn;
-
-typedef struct {
- Elf64_Sxword d_tag;
- union {
- Elf64_Xword d_val;
- Elf64_Addr d_ptr;
- } d_un;
-} Elf64_Dyn;
-
-#define DT_NULL 0
-#define DT_NEEDED 1
-#define DT_PLTRELSZ 2
-#define DT_PLTGOT 3
-#define DT_HASH 4
-#define DT_STRTAB 5
-#define DT_SYMTAB 6
-#define DT_RELA 7
-#define DT_RELASZ 8
-#define DT_RELAENT 9
-#define DT_STRSZ 10
-#define DT_SYMENT 11
-#define DT_INIT 12
-#define DT_FINI 13
-#define DT_SONAME 14
-#define DT_RPATH 15
-#define DT_SYMBOLIC 16
-#define DT_REL 17
-#define DT_RELSZ 18
-#define DT_RELENT 19
-#define DT_PLTREL 20
-#define DT_DEBUG 21
-#define DT_TEXTREL 22
-#define DT_JMPREL 23
-#define DT_BIND_NOW 24
-#define DT_INIT_ARRAY 25
-#define DT_FINI_ARRAY 26
-#define DT_INIT_ARRAYSZ 27
-#define DT_FINI_ARRAYSZ 28
-#define DT_RUNPATH 29
-#define DT_FLAGS 30
-#define DT_ENCODING 32
-#define DT_PREINIT_ARRAY 32
-#define DT_PREINIT_ARRAYSZ 33
-#define DT_NUM 34
-#define DT_LOOS 0x6000000d
-#define DT_HIOS 0x6ffff000
-#define DT_LOPROC 0x70000000
-#define DT_HIPROC 0x7fffffff
-#define DT_PROCNUM DT_MIPS_NUM
-
-#define DT_VALRNGLO 0x6ffffd00
-#define DT_GNU_PRELINKED 0x6ffffdf5
-#define DT_GNU_CONFLICTSZ 0x6ffffdf6
-#define DT_GNU_LIBLISTSZ 0x6ffffdf7
-#define DT_CHECKSUM 0x6ffffdf8
-#define DT_PLTPADSZ 0x6ffffdf9
-#define DT_MOVEENT 0x6ffffdfa
-#define DT_MOVESZ 0x6ffffdfb
-#define DT_FEATURE_1 0x6ffffdfc
-#define DT_POSFLAG_1 0x6ffffdfd
-
-#define DT_SYMINSZ 0x6ffffdfe
-#define DT_SYMINENT 0x6ffffdff
-#define DT_VALRNGHI 0x6ffffdff
-#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag))
-#define DT_VALNUM 12
-
-#define DT_ADDRRNGLO 0x6ffffe00
-#define DT_GNU_HASH 0x6ffffef5
-#define DT_TLSDESC_PLT 0x6ffffef6
-#define DT_TLSDESC_GOT 0x6ffffef7
-#define DT_GNU_CONFLICT 0x6ffffef8
-#define DT_GNU_LIBLIST 0x6ffffef9
-#define DT_CONFIG 0x6ffffefa
-#define DT_DEPAUDIT 0x6ffffefb
-#define DT_AUDIT 0x6ffffefc
-#define DT_PLTPAD 0x6ffffefd
-#define DT_MOVETAB 0x6ffffefe
-#define DT_SYMINFO 0x6ffffeff
-#define DT_ADDRRNGHI 0x6ffffeff
-#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag))
-#define DT_ADDRNUM 11
-
-#define DT_VERSYM 0x6ffffff0
-
-#define DT_RELACOUNT 0x6ffffff9
-#define DT_RELCOUNT 0x6ffffffa
-
-#define DT_FLAGS_1 0x6ffffffb
-#define DT_VERDEF 0x6ffffffc
-
-#define DT_VERDEFNUM 0x6ffffffd
-#define DT_VERNEED 0x6ffffffe
-
-#define DT_VERNEEDNUM 0x6fffffff
-#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag))
-#define DT_VERSIONTAGNUM 16
-
-#define DT_AUXILIARY 0x7ffffffd
-#define DT_FILTER 0x7fffffff
-#define DT_EXTRATAGIDX(tag) ((Elf32_Word) - ((Elf32_Sword)(tag) << 1 >> 1) - 1)
-#define DT_EXTRANUM 3
-
-#define DF_ORIGIN 0x00000001
-#define DF_SYMBOLIC 0x00000002
-#define DF_TEXTREL 0x00000004
-#define DF_BIND_NOW 0x00000008
-#define DF_STATIC_TLS 0x00000010
-
-#define DF_1_NOW 0x00000001
-#define DF_1_GLOBAL 0x00000002
-#define DF_1_GROUP 0x00000004
-#define DF_1_NODELETE 0x00000008
-#define DF_1_LOADFLTR 0x00000010
-#define DF_1_INITFIRST 0x00000020
-#define DF_1_NOOPEN 0x00000040
-#define DF_1_ORIGIN 0x00000080
-#define DF_1_DIRECT 0x00000100
-#define DF_1_TRANS 0x00000200
-#define DF_1_INTERPOSE 0x00000400
-#define DF_1_NODEFLIB 0x00000800
-#define DF_1_NODUMP 0x00001000
-#define DF_1_CONFALT 0x00002000
-#define DF_1_ENDFILTEE 0x00004000
-#define DF_1_DISPRELDNE 0x00008000
-#define DF_1_DISPRELPND 0x00010000
-#define DF_1_NODIRECT 0x00020000
-#define DF_1_IGNMULDEF 0x00040000
-#define DF_1_NOKSYMS 0x00080000
-#define DF_1_NOHDR 0x00100000
-#define DF_1_EDITED 0x00200000
-#define DF_1_NORELOC 0x00400000
-#define DF_1_SYMINTPOSE 0x00800000
-#define DF_1_GLOBAUDIT 0x01000000
-#define DF_1_SINGLETON 0x02000000
-
-#define DTF_1_PARINIT 0x00000001
-#define DTF_1_CONFEXP 0x00000002
-
-#define DF_P1_LAZYLOAD 0x00000001
-#define DF_P1_GROUPPERM 0x00000002
-
-typedef struct {
- Elf32_Half vd_version;
- Elf32_Half vd_flags;
- Elf32_Half vd_ndx;
- Elf32_Half vd_cnt;
- Elf32_Word vd_hash;
- Elf32_Word vd_aux;
- Elf32_Word vd_next;
-} Elf32_Verdef;
-
-typedef struct {
- Elf64_Half vd_version;
- Elf64_Half vd_flags;
- Elf64_Half vd_ndx;
- Elf64_Half vd_cnt;
- Elf64_Word vd_hash;
- Elf64_Word vd_aux;
- Elf64_Word vd_next;
-} Elf64_Verdef;
-
-#define VER_DEF_NONE 0
-#define VER_DEF_CURRENT 1
-#define VER_DEF_NUM 2
-
-#define VER_FLG_BASE 0x1
-#define VER_FLG_WEAK 0x2
-
-#define VER_NDX_LOCAL 0
-#define VER_NDX_GLOBAL 1
-#define VER_NDX_LORESERVE 0xff00
-#define VER_NDX_ELIMINATE 0xff01
-
-typedef struct {
- Elf32_Word vda_name;
- Elf32_Word vda_next;
-} Elf32_Verdaux;
-
-typedef struct {
- Elf64_Word vda_name;
- Elf64_Word vda_next;
-} Elf64_Verdaux;
-
-typedef struct {
- Elf32_Half vn_version;
- Elf32_Half vn_cnt;
- Elf32_Word vn_file;
- Elf32_Word vn_aux;
- Elf32_Word vn_next;
-} Elf32_Verneed;
-
-typedef struct {
- Elf64_Half vn_version;
- Elf64_Half vn_cnt;
- Elf64_Word vn_file;
- Elf64_Word vn_aux;
- Elf64_Word vn_next;
-} Elf64_Verneed;
-
-#define VER_NEED_NONE 0
-#define VER_NEED_CURRENT 1
-#define VER_NEED_NUM 2
-
-typedef struct {
- Elf32_Word vna_hash;
- Elf32_Half vna_flags;
- Elf32_Half vna_other;
- Elf32_Word vna_name;
- Elf32_Word vna_next;
-} Elf32_Vernaux;
-
-typedef struct {
- Elf64_Word vna_hash;
- Elf64_Half vna_flags;
- Elf64_Half vna_other;
- Elf64_Word vna_name;
- Elf64_Word vna_next;
-} Elf64_Vernaux;
-
-#define VER_FLG_WEAK 0x2
-
-typedef struct {
- uint32_t a_type;
- union {
- uint32_t a_val;
- } a_un;
-} Elf32_auxv_t;
-
-typedef struct {
- uint64_t a_type;
- union {
- uint64_t a_val;
- } a_un;
-} Elf64_auxv_t;
-
-#define AT_NULL 0
-#define AT_IGNORE 1
-#define AT_EXECFD 2
-#define AT_PHDR 3
-#define AT_PHENT 4
-#define AT_PHNUM 5
-#define AT_PAGESZ 6
-#define AT_BASE 7
-#define AT_FLAGS 8
-#define AT_ENTRY 9
-#define AT_NOTELF 10
-#define AT_UID 11
-#define AT_EUID 12
-#define AT_GID 13
-#define AT_EGID 14
-#define AT_CLKTCK 17
-
-#define AT_PLATFORM 15
-#define AT_HWCAP 16
-
-#define AT_FPUCW 18
-
-#define AT_DCACHEBSIZE 19
-#define AT_ICACHEBSIZE 20
-#define AT_UCACHEBSIZE 21
-
-#define AT_IGNOREPPC 22
-
-#define AT_SECURE 23
-
-#define AT_BASE_PLATFORM 24
-
-#define AT_RANDOM 25
-
-#define AT_HWCAP2 26
-
-#define AT_EXECFN 31
-
-#define AT_SYSINFO 32
-#define AT_SYSINFO_EHDR 33
-
-#define AT_L1I_CACHESHAPE 34
-#define AT_L1D_CACHESHAPE 35
-#define AT_L2_CACHESHAPE 36
-#define AT_L3_CACHESHAPE 37
-
-typedef struct {
- Elf32_Word n_namesz;
- Elf32_Word n_descsz;
- Elf32_Word n_type;
-} Elf32_Nhdr;
-
-typedef struct {
- Elf64_Word n_namesz;
- Elf64_Word n_descsz;
- Elf64_Word n_type;
-} Elf64_Nhdr;
-
-#define ELF_NOTE_SOLARIS "SUNW Solaris"
-
-#define ELF_NOTE_GNU "GNU"
-
-#define ELF_NOTE_PAGESIZE_HINT 1
-
-#define NT_GNU_ABI_TAG 1
-#define ELF_NOTE_ABI NT_GNU_ABI_TAG
-
-#define ELF_NOTE_OS_LINUX 0
-#define ELF_NOTE_OS_GNU 1
-#define ELF_NOTE_OS_SOLARIS2 2
-#define ELF_NOTE_OS_FREEBSD 3
-
-#define NT_GNU_BUILD_ID 3
-#define NT_GNU_GOLD_VERSION 4
-
-typedef struct {
- Elf32_Xword m_value;
- Elf32_Word m_info;
- Elf32_Word m_poffset;
- Elf32_Half m_repeat;
- Elf32_Half m_stride;
-} Elf32_Move;
-
-typedef struct {
- Elf64_Xword m_value;
- Elf64_Xword m_info;
- Elf64_Xword m_poffset;
- Elf64_Half m_repeat;
- Elf64_Half m_stride;
-} Elf64_Move;
-
-#define ELF32_M_SYM(info) ((info) >> 8)
-#define ELF32_M_SIZE(info) ((unsigned char)(info))
-#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char)(size))
-
-#define ELF64_M_SYM(info) ELF32_M_SYM(info)
-#define ELF64_M_SIZE(info) ELF32_M_SIZE(info)
-#define ELF64_M_INFO(sym, size) ELF32_M_INFO(sym, size)
-
-#define EF_CPU32 0x00810000
-
-#define R_68K_NONE 0
-#define R_68K_32 1
-#define R_68K_16 2
-#define R_68K_8 3
-#define R_68K_PC32 4
-#define R_68K_PC16 5
-#define R_68K_PC8 6
-#define R_68K_GOT32 7
-#define R_68K_GOT16 8
-#define R_68K_GOT8 9
-#define R_68K_GOT32O 10
-#define R_68K_GOT16O 11
-#define R_68K_GOT8O 12
-#define R_68K_PLT32 13
-#define R_68K_PLT16 14
-#define R_68K_PLT8 15
-#define R_68K_PLT32O 16
-#define R_68K_PLT16O 17
-#define R_68K_PLT8O 18
-#define R_68K_COPY 19
-#define R_68K_GLOB_DAT 20
-#define R_68K_JMP_SLOT 21
-#define R_68K_RELATIVE 22
-#define R_68K_NUM 23
-
-#define R_386_NONE 0
-#define R_386_32 1
-#define R_386_PC32 2
-#define R_386_GOT32 3
-#define R_386_PLT32 4
-#define R_386_COPY 5
-#define R_386_GLOB_DAT 6
-#define R_386_JMP_SLOT 7
-#define R_386_RELATIVE 8
-#define R_386_GOTOFF 9
-#define R_386_GOTPC 10
-#define R_386_32PLT 11
-#define R_386_TLS_TPOFF 14
-#define R_386_TLS_IE 15
-#define R_386_TLS_GOTIE 16
-#define R_386_TLS_LE 17
-#define R_386_TLS_GD 18
-#define R_386_TLS_LDM 19
-#define R_386_16 20
-#define R_386_PC16 21
-#define R_386_8 22
-#define R_386_PC8 23
-#define R_386_TLS_GD_32 24
-#define R_386_TLS_GD_PUSH 25
-#define R_386_TLS_GD_CALL 26
-#define R_386_TLS_GD_POP 27
-#define R_386_TLS_LDM_32 28
-#define R_386_TLS_LDM_PUSH 29
-#define R_386_TLS_LDM_CALL 30
-#define R_386_TLS_LDM_POP 31
-#define R_386_TLS_LDO_32 32
-#define R_386_TLS_IE_32 33
-#define R_386_TLS_LE_32 34
-#define R_386_TLS_DTPMOD32 35
-#define R_386_TLS_DTPOFF32 36
-#define R_386_TLS_TPOFF32 37
-#define R_386_SIZE32 38
-#define R_386_TLS_GOTDESC 39
-#define R_386_TLS_DESC_CALL 40
-#define R_386_TLS_DESC 41
-#define R_386_IRELATIVE 42
-#define R_386_GOT32X 43
-#define R_386_NUM 44
-
-#define STT_SPARC_REGISTER 13
-
-#define EF_SPARCV9_MM 3
-#define EF_SPARCV9_TSO 0
-#define EF_SPARCV9_PSO 1
-#define EF_SPARCV9_RMO 2
-#define EF_SPARC_LEDATA 0x800000
-#define EF_SPARC_EXT_MASK 0xFFFF00
-#define EF_SPARC_32PLUS 0x000100
-#define EF_SPARC_SUN_US1 0x000200
-#define EF_SPARC_HAL_R1 0x000400
-#define EF_SPARC_SUN_US3 0x000800
-
-#define R_SPARC_NONE 0
-#define R_SPARC_8 1
-#define R_SPARC_16 2
-#define R_SPARC_32 3
-#define R_SPARC_DISP8 4
-#define R_SPARC_DISP16 5
-#define R_SPARC_DISP32 6
-#define R_SPARC_WDISP30 7
-#define R_SPARC_WDISP22 8
-#define R_SPARC_HI22 9
-#define R_SPARC_22 10
-#define R_SPARC_13 11
-#define R_SPARC_LO10 12
-#define R_SPARC_GOT10 13
-#define R_SPARC_GOT13 14
-#define R_SPARC_GOT22 15
-#define R_SPARC_PC10 16
-#define R_SPARC_PC22 17
-#define R_SPARC_WPLT30 18
-#define R_SPARC_COPY 19
-#define R_SPARC_GLOB_DAT 20
-#define R_SPARC_JMP_SLOT 21
-#define R_SPARC_RELATIVE 22
-#define R_SPARC_UA32 23
-
-#define R_SPARC_PLT32 24
-#define R_SPARC_HIPLT22 25
-#define R_SPARC_LOPLT10 26
-#define R_SPARC_PCPLT32 27
-#define R_SPARC_PCPLT22 28
-#define R_SPARC_PCPLT10 29
-#define R_SPARC_10 30
-#define R_SPARC_11 31
-#define R_SPARC_64 32
-#define R_SPARC_OLO10 33
-#define R_SPARC_HH22 34
-#define R_SPARC_HM10 35
-#define R_SPARC_LM22 36
-#define R_SPARC_PC_HH22 37
-#define R_SPARC_PC_HM10 38
-#define R_SPARC_PC_LM22 39
-#define R_SPARC_WDISP16 40
-#define R_SPARC_WDISP19 41
-#define R_SPARC_GLOB_JMP 42
-#define R_SPARC_7 43
-#define R_SPARC_5 44
-#define R_SPARC_6 45
-#define R_SPARC_DISP64 46
-#define R_SPARC_PLT64 47
-#define R_SPARC_HIX22 48
-#define R_SPARC_LOX10 49
-#define R_SPARC_H44 50
-#define R_SPARC_M44 51
-#define R_SPARC_L44 52
-#define R_SPARC_REGISTER 53
-#define R_SPARC_UA64 54
-#define R_SPARC_UA16 55
-#define R_SPARC_TLS_GD_HI22 56
-#define R_SPARC_TLS_GD_LO10 57
-#define R_SPARC_TLS_GD_ADD 58
-#define R_SPARC_TLS_GD_CALL 59
-#define R_SPARC_TLS_LDM_HI22 60
-#define R_SPARC_TLS_LDM_LO10 61
-#define R_SPARC_TLS_LDM_ADD 62
-#define R_SPARC_TLS_LDM_CALL 63
-#define R_SPARC_TLS_LDO_HIX22 64
-#define R_SPARC_TLS_LDO_LOX10 65
-#define R_SPARC_TLS_LDO_ADD 66
-#define R_SPARC_TLS_IE_HI22 67
-#define R_SPARC_TLS_IE_LO10 68
-#define R_SPARC_TLS_IE_LD 69
-#define R_SPARC_TLS_IE_LDX 70
-#define R_SPARC_TLS_IE_ADD 71
-#define R_SPARC_TLS_LE_HIX22 72
-#define R_SPARC_TLS_LE_LOX10 73
-#define R_SPARC_TLS_DTPMOD32 74
-#define R_SPARC_TLS_DTPMOD64 75
-#define R_SPARC_TLS_DTPOFF32 76
-#define R_SPARC_TLS_DTPOFF64 77
-#define R_SPARC_TLS_TPOFF32 78
-#define R_SPARC_TLS_TPOFF64 79
-#define R_SPARC_GOTDATA_HIX22 80
-#define R_SPARC_GOTDATA_LOX10 81
-#define R_SPARC_GOTDATA_OP_HIX22 82
-#define R_SPARC_GOTDATA_OP_LOX10 83
-#define R_SPARC_GOTDATA_OP 84
-#define R_SPARC_H34 85
-#define R_SPARC_SIZE32 86
-#define R_SPARC_SIZE64 87
-#define R_SPARC_GNU_VTINHERIT 250
-#define R_SPARC_GNU_VTENTRY 251
-#define R_SPARC_REV32 252
-
-#define R_SPARC_NUM 253
-
-#define DT_SPARC_REGISTER 0x70000001
-#define DT_SPARC_NUM 2
-
-#define EF_MIPS_NOREORDER 1
-#define EF_MIPS_PIC 2
-#define EF_MIPS_CPIC 4
-#define EF_MIPS_XGOT 8
-#define EF_MIPS_64BIT_WHIRL 16
-#define EF_MIPS_ABI2 32
-#define EF_MIPS_ABI_ON32 64
-#define EF_MIPS_FP64 512
-#define EF_MIPS_NAN2008 1024
-#define EF_MIPS_ARCH 0xf0000000
-
-#define EF_MIPS_ARCH_1 0x00000000
-#define EF_MIPS_ARCH_2 0x10000000
-#define EF_MIPS_ARCH_3 0x20000000
-#define EF_MIPS_ARCH_4 0x30000000
-#define EF_MIPS_ARCH_5 0x40000000
-#define EF_MIPS_ARCH_32 0x50000000
-#define EF_MIPS_ARCH_64 0x60000000
-#define EF_MIPS_ARCH_32R2 0x70000000
-#define EF_MIPS_ARCH_64R2 0x80000000
-
-#define E_MIPS_ARCH_1 0x00000000
-#define E_MIPS_ARCH_2 0x10000000
-#define E_MIPS_ARCH_3 0x20000000
-#define E_MIPS_ARCH_4 0x30000000
-#define E_MIPS_ARCH_5 0x40000000
-#define E_MIPS_ARCH_32 0x50000000
-#define E_MIPS_ARCH_64 0x60000000
-
-#define SHN_MIPS_ACOMMON 0xff00
-#define SHN_MIPS_TEXT 0xff01
-#define SHN_MIPS_DATA 0xff02
-#define SHN_MIPS_SCOMMON 0xff03
-#define SHN_MIPS_SUNDEFINED 0xff04
-
-#define SHT_MIPS_LIBLIST 0x70000000
-#define SHT_MIPS_MSYM 0x70000001
-#define SHT_MIPS_CONFLICT 0x70000002
-#define SHT_MIPS_GPTAB 0x70000003
-#define SHT_MIPS_UCODE 0x70000004
-#define SHT_MIPS_DEBUG 0x70000005
-#define SHT_MIPS_REGINFO 0x70000006
-#define SHT_MIPS_PACKAGE 0x70000007
-#define SHT_MIPS_PACKSYM 0x70000008
-#define SHT_MIPS_RELD 0x70000009
-#define SHT_MIPS_IFACE 0x7000000b
-#define SHT_MIPS_CONTENT 0x7000000c
-#define SHT_MIPS_OPTIONS 0x7000000d
-#define SHT_MIPS_SHDR 0x70000010
-#define SHT_MIPS_FDESC 0x70000011
-#define SHT_MIPS_EXTSYM 0x70000012
-#define SHT_MIPS_DENSE 0x70000013
-#define SHT_MIPS_PDESC 0x70000014
-#define SHT_MIPS_LOCSYM 0x70000015
-#define SHT_MIPS_AUXSYM 0x70000016
-#define SHT_MIPS_OPTSYM 0x70000017
-#define SHT_MIPS_LOCSTR 0x70000018
-#define SHT_MIPS_LINE 0x70000019
-#define SHT_MIPS_RFDESC 0x7000001a
-#define SHT_MIPS_DELTASYM 0x7000001b
-#define SHT_MIPS_DELTAINST 0x7000001c
-#define SHT_MIPS_DELTACLASS 0x7000001d
-#define SHT_MIPS_DWARF 0x7000001e
-#define SHT_MIPS_DELTADECL 0x7000001f
-#define SHT_MIPS_SYMBOL_LIB 0x70000020
-#define SHT_MIPS_EVENTS 0x70000021
-#define SHT_MIPS_TRANSLATE 0x70000022
-#define SHT_MIPS_PIXIE 0x70000023
-#define SHT_MIPS_XLATE 0x70000024
-#define SHT_MIPS_XLATE_DEBUG 0x70000025
-#define SHT_MIPS_WHIRL 0x70000026
-#define SHT_MIPS_EH_REGION 0x70000027
-#define SHT_MIPS_XLATE_OLD 0x70000028
-#define SHT_MIPS_PDR_EXCEPTION 0x70000029
-
-#define SHF_MIPS_GPREL 0x10000000
-#define SHF_MIPS_MERGE 0x20000000
-#define SHF_MIPS_ADDR 0x40000000
-#define SHF_MIPS_STRINGS 0x80000000
-#define SHF_MIPS_NOSTRIP 0x08000000
-#define SHF_MIPS_LOCAL 0x04000000
-#define SHF_MIPS_NAMES 0x02000000
-#define SHF_MIPS_NODUPE 0x01000000
-
-#define STO_MIPS_DEFAULT 0x0
-#define STO_MIPS_INTERNAL 0x1
-#define STO_MIPS_HIDDEN 0x2
-#define STO_MIPS_PROTECTED 0x3
-#define STO_MIPS_PLT 0x8
-#define STO_MIPS_SC_ALIGN_UNUSED 0xff
-
-#define STB_MIPS_SPLIT_COMMON 13
-
-typedef union {
- struct {
- Elf32_Word gt_current_g_value;
- Elf32_Word gt_unused;
- } gt_header;
- struct {
- Elf32_Word gt_g_value;
- Elf32_Word gt_bytes;
- } gt_entry;
-} Elf32_gptab;
-
-typedef struct {
- Elf32_Word ri_gprmask;
- Elf32_Word ri_cprmask[4];
- Elf32_Sword ri_gp_value;
-} Elf32_RegInfo;
-
-typedef struct {
- unsigned char kind;
-
- unsigned char size;
- Elf32_Section section;
-
- Elf32_Word info;
-} Elf_Options;
-
-#define ODK_NULL 0
-#define ODK_REGINFO 1
-#define ODK_EXCEPTIONS 2
-#define ODK_PAD 3
-#define ODK_HWPATCH 4
-#define ODK_FILL 5
-#define ODK_TAGS 6
-#define ODK_HWAND 7
-#define ODK_HWOR 8
-
-#define OEX_FPU_MIN 0x1f
-#define OEX_FPU_MAX 0x1f00
-#define OEX_PAGE0 0x10000
-#define OEX_SMM 0x20000
-#define OEX_FPDBUG 0x40000
-#define OEX_PRECISEFP OEX_FPDBUG
-#define OEX_DISMISS 0x80000
-
-#define OEX_FPU_INVAL 0x10
-#define OEX_FPU_DIV0 0x08
-#define OEX_FPU_OFLO 0x04
-#define OEX_FPU_UFLO 0x02
-#define OEX_FPU_INEX 0x01
-
-#define OHW_R4KEOP 0x1
-#define OHW_R8KPFETCH 0x2
-#define OHW_R5KEOP 0x4
-#define OHW_R5KCVTL 0x8
-
-#define OPAD_PREFIX 0x1
-#define OPAD_POSTFIX 0x2
-#define OPAD_SYMBOL 0x4
-
-typedef struct {
- Elf32_Word hwp_flags1;
- Elf32_Word hwp_flags2;
-} Elf_Options_Hw;
-
-#define OHWA0_R4KEOP_CHECKED 0x00000001
-#define OHWA1_R4KEOP_CLEAN 0x00000002
-
-#define R_MIPS_NONE 0
-#define R_MIPS_16 1
-#define R_MIPS_32 2
-#define R_MIPS_REL32 3
-#define R_MIPS_26 4
-#define R_MIPS_HI16 5
-#define R_MIPS_LO16 6
-#define R_MIPS_GPREL16 7
-#define R_MIPS_LITERAL 8
-#define R_MIPS_GOT16 9
-#define R_MIPS_PC16 10
-#define R_MIPS_CALL16 11
-#define R_MIPS_GPREL32 12
-
-#define R_MIPS_SHIFT5 16
-#define R_MIPS_SHIFT6 17
-#define R_MIPS_64 18
-#define R_MIPS_GOT_DISP 19
-#define R_MIPS_GOT_PAGE 20
-#define R_MIPS_GOT_OFST 21
-#define R_MIPS_GOT_HI16 22
-#define R_MIPS_GOT_LO16 23
-#define R_MIPS_SUB 24
-#define R_MIPS_INSERT_A 25
-#define R_MIPS_INSERT_B 26
-#define R_MIPS_DELETE 27
-#define R_MIPS_HIGHER 28
-#define R_MIPS_HIGHEST 29
-#define R_MIPS_CALL_HI16 30
-#define R_MIPS_CALL_LO16 31
-#define R_MIPS_SCN_DISP 32
-#define R_MIPS_REL16 33
-#define R_MIPS_ADD_IMMEDIATE 34
-#define R_MIPS_PJUMP 35
-#define R_MIPS_RELGOT 36
-#define R_MIPS_JALR 37
-#define R_MIPS_TLS_DTPMOD32 38
-#define R_MIPS_TLS_DTPREL32 39
-#define R_MIPS_TLS_DTPMOD64 40
-#define R_MIPS_TLS_DTPREL64 41
-#define R_MIPS_TLS_GD 42
-#define R_MIPS_TLS_LDM 43
-#define R_MIPS_TLS_DTPREL_HI16 44
-#define R_MIPS_TLS_DTPREL_LO16 45
-#define R_MIPS_TLS_GOTTPREL 46
-#define R_MIPS_TLS_TPREL32 47
-#define R_MIPS_TLS_TPREL64 48
-#define R_MIPS_TLS_TPREL_HI16 49
-#define R_MIPS_TLS_TPREL_LO16 50
-#define R_MIPS_GLOB_DAT 51
-#define R_MIPS_COPY 126
-#define R_MIPS_JUMP_SLOT 127
-
-#define R_MIPS_NUM 128
-
-#define PT_MIPS_REGINFO 0x70000000
-#define PT_MIPS_RTPROC 0x70000001
-#define PT_MIPS_OPTIONS 0x70000002
-#define PT_MIPS_ABIFLAGS 0x70000003
-
-#define PF_MIPS_LOCAL 0x10000000
-
-#define DT_MIPS_RLD_VERSION 0x70000001
-#define DT_MIPS_TIME_STAMP 0x70000002
-#define DT_MIPS_ICHECKSUM 0x70000003
-#define DT_MIPS_IVERSION 0x70000004
-#define DT_MIPS_FLAGS 0x70000005
-#define DT_MIPS_BASE_ADDRESS 0x70000006
-#define DT_MIPS_MSYM 0x70000007
-#define DT_MIPS_CONFLICT 0x70000008
-#define DT_MIPS_LIBLIST 0x70000009
-#define DT_MIPS_LOCAL_GOTNO 0x7000000a
-#define DT_MIPS_CONFLICTNO 0x7000000b
-#define DT_MIPS_LIBLISTNO 0x70000010
-#define DT_MIPS_SYMTABNO 0x70000011
-#define DT_MIPS_UNREFEXTNO 0x70000012
-#define DT_MIPS_GOTSYM 0x70000013
-#define DT_MIPS_HIPAGENO 0x70000014
-#define DT_MIPS_RLD_MAP 0x70000016
-#define DT_MIPS_DELTA_CLASS 0x70000017
-#define DT_MIPS_DELTA_CLASS_NO 0x70000018
-
-#define DT_MIPS_DELTA_INSTANCE 0x70000019
-#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a
-
-#define DT_MIPS_DELTA_RELOC 0x7000001b
-#define DT_MIPS_DELTA_RELOC_NO 0x7000001c
-
-#define DT_MIPS_DELTA_SYM 0x7000001d
-
-#define DT_MIPS_DELTA_SYM_NO 0x7000001e
-
-#define DT_MIPS_DELTA_CLASSSYM 0x70000020
-
-#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021
-
-#define DT_MIPS_CXX_FLAGS 0x70000022
-#define DT_MIPS_PIXIE_INIT 0x70000023
-#define DT_MIPS_SYMBOL_LIB 0x70000024
-#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025
-#define DT_MIPS_LOCAL_GOTIDX 0x70000026
-#define DT_MIPS_HIDDEN_GOTIDX 0x70000027
-#define DT_MIPS_PROTECTED_GOTIDX 0x70000028
-#define DT_MIPS_OPTIONS 0x70000029
-#define DT_MIPS_INTERFACE 0x7000002a
-#define DT_MIPS_DYNSTR_ALIGN 0x7000002b
-#define DT_MIPS_INTERFACE_SIZE 0x7000002c
-#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d
-
-#define DT_MIPS_PERF_SUFFIX 0x7000002e
-
-#define DT_MIPS_COMPACT_SIZE 0x7000002f
-#define DT_MIPS_GP_VALUE 0x70000030
-#define DT_MIPS_AUX_DYNAMIC 0x70000031
-
-#define DT_MIPS_PLTGOT 0x70000032
-
-#define DT_MIPS_RWPLT 0x70000034
-#define DT_MIPS_RLD_MAP_REL 0x70000035
-#define DT_MIPS_NUM 0x36
-
-#define RHF_NONE 0
-#define RHF_QUICKSTART (1 << 0)
-#define RHF_NOTPOT (1 << 1)
-#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2)
-#define RHF_NO_MOVE (1 << 3)
-#define RHF_SGI_ONLY (1 << 4)
-#define RHF_GUARANTEE_INIT (1 << 5)
-#define RHF_DELTA_C_PLUS_PLUS (1 << 6)
-#define RHF_GUARANTEE_START_INIT (1 << 7)
-#define RHF_PIXIE (1 << 8)
-#define RHF_DEFAULT_DELAY_LOAD (1 << 9)
-#define RHF_REQUICKSTART (1 << 10)
-#define RHF_REQUICKSTARTED (1 << 11)
-#define RHF_CORD (1 << 12)
-#define RHF_NO_UNRES_UNDEF (1 << 13)
-#define RHF_RLD_ORDER_SAFE (1 << 14)
-
-typedef struct {
- Elf32_Word l_name;
- Elf32_Word l_time_stamp;
- Elf32_Word l_checksum;
- Elf32_Word l_version;
- Elf32_Word l_flags;
-} Elf32_Lib;
-
-typedef struct {
- Elf64_Word l_name;
- Elf64_Word l_time_stamp;
- Elf64_Word l_checksum;
- Elf64_Word l_version;
- Elf64_Word l_flags;
-} Elf64_Lib;
-
-#define LL_NONE 0
-#define LL_EXACT_MATCH (1 << 0)
-#define LL_IGNORE_INT_VER (1 << 1)
-#define LL_REQUIRE_MINOR (1 << 2)
-#define LL_EXPORTS (1 << 3)
-#define LL_DELAY_LOAD (1 << 4)
-#define LL_DELTA (1 << 5)
-
-typedef Elf32_Addr Elf32_Conflict;
-
-typedef struct {
- Elf32_Half version;
- unsigned char isa_level;
- unsigned char isa_rev;
- unsigned char gpr_size;
- unsigned char cpr1_size;
- unsigned char cpr2_size;
- unsigned char fp_abi;
- Elf32_Word isa_ext;
- Elf32_Word ases;
- Elf32_Word flags1;
- Elf32_Word flags2;
-} Elf_MIPS_ABIFlags_v0;
-
-#define MIPS_AFL_REG_NONE 0x00
-#define MIPS_AFL_REG_32 0x01
-#define MIPS_AFL_REG_64 0x02
-#define MIPS_AFL_REG_128 0x03
-
-#define MIPS_AFL_ASE_DSP 0x00000001
-#define MIPS_AFL_ASE_DSPR2 0x00000002
-#define MIPS_AFL_ASE_EVA 0x00000004
-#define MIPS_AFL_ASE_MCU 0x00000008
-#define MIPS_AFL_ASE_MDMX 0x00000010
-#define MIPS_AFL_ASE_MIPS3D 0x00000020
-#define MIPS_AFL_ASE_MT 0x00000040
-#define MIPS_AFL_ASE_SMARTMIPS 0x00000080
-#define MIPS_AFL_ASE_VIRT 0x00000100
-#define MIPS_AFL_ASE_MSA 0x00000200
-#define MIPS_AFL_ASE_MIPS16 0x00000400
-#define MIPS_AFL_ASE_MICROMIPS 0x00000800
-#define MIPS_AFL_ASE_XPA 0x00001000
-#define MIPS_AFL_ASE_MASK 0x00001fff
-
-#define MIPS_AFL_EXT_XLR 1
-#define MIPS_AFL_EXT_OCTEON2 2
-#define MIPS_AFL_EXT_OCTEONP 3
-#define MIPS_AFL_EXT_LOONGSON_3A 4
-#define MIPS_AFL_EXT_OCTEON 5
-#define MIPS_AFL_EXT_5900 6
-#define MIPS_AFL_EXT_4650 7
-#define MIPS_AFL_EXT_4010 8
-#define MIPS_AFL_EXT_4100 9
-#define MIPS_AFL_EXT_3900 10
-#define MIPS_AFL_EXT_10000 11
-#define MIPS_AFL_EXT_SB1 12
-#define MIPS_AFL_EXT_4111 13
-#define MIPS_AFL_EXT_4120 14
-#define MIPS_AFL_EXT_5400 15
-#define MIPS_AFL_EXT_5500 16
-#define MIPS_AFL_EXT_LOONGSON_2E 17
-#define MIPS_AFL_EXT_LOONGSON_2F 18
-
-#define MIPS_AFL_FLAGS1_ODDSPREG 1
-
-enum {
- Val_GNU_MIPS_ABI_FP_ANY = 0,
- Val_GNU_MIPS_ABI_FP_DOUBLE = 1,
- Val_GNU_MIPS_ABI_FP_SINGLE = 2,
- Val_GNU_MIPS_ABI_FP_SOFT = 3,
- Val_GNU_MIPS_ABI_FP_OLD_64 = 4,
- Val_GNU_MIPS_ABI_FP_XX = 5,
- Val_GNU_MIPS_ABI_FP_64 = 6,
- Val_GNU_MIPS_ABI_FP_64A = 7,
- Val_GNU_MIPS_ABI_FP_MAX = 7
-};
-
-#define EF_PARISC_TRAPNIL 0x00010000
-#define EF_PARISC_EXT 0x00020000
-#define EF_PARISC_LSB 0x00040000
-#define EF_PARISC_WIDE 0x00080000
-#define EF_PARISC_NO_KABP 0x00100000
-
-#define EF_PARISC_LAZYSWAP 0x00400000
-#define EF_PARISC_ARCH 0x0000ffff
-
-#define EFA_PARISC_1_0 0x020b
-#define EFA_PARISC_1_1 0x0210
-#define EFA_PARISC_2_0 0x0214
-
-#define SHN_PARISC_ANSI_COMMON 0xff00
-
-#define SHN_PARISC_HUGE_COMMON 0xff01
-
-#define SHT_PARISC_EXT 0x70000000
-#define SHT_PARISC_UNWIND 0x70000001
-#define SHT_PARISC_DOC 0x70000002
-
-#define SHF_PARISC_SHORT 0x20000000
-#define SHF_PARISC_HUGE 0x40000000
-#define SHF_PARISC_SBP 0x80000000
-
-#define STT_PARISC_MILLICODE 13
-
-#define STT_HP_OPAQUE (STT_LOOS + 0x1)
-#define STT_HP_STUB (STT_LOOS + 0x2)
-
-#define R_PARISC_NONE 0
-#define R_PARISC_DIR32 1
-#define R_PARISC_DIR21L 2
-#define R_PARISC_DIR17R 3
-#define R_PARISC_DIR17F 4
-#define R_PARISC_DIR14R 6
-#define R_PARISC_PCREL32 9
-#define R_PARISC_PCREL21L 10
-#define R_PARISC_PCREL17R 11
-#define R_PARISC_PCREL17F 12
-#define R_PARISC_PCREL14R 14
-#define R_PARISC_DPREL21L 18
-#define R_PARISC_DPREL14R 22
-#define R_PARISC_GPREL21L 26
-#define R_PARISC_GPREL14R 30
-#define R_PARISC_LTOFF21L 34
-#define R_PARISC_LTOFF14R 38
-#define R_PARISC_SECREL32 41
-#define R_PARISC_SEGBASE 48
-#define R_PARISC_SEGREL32 49
-#define R_PARISC_PLTOFF21L 50
-#define R_PARISC_PLTOFF14R 54
-#define R_PARISC_LTOFF_FPTR32 57
-#define R_PARISC_LTOFF_FPTR21L 58
-#define R_PARISC_LTOFF_FPTR14R 62
-#define R_PARISC_FPTR64 64
-#define R_PARISC_PLABEL32 65
-#define R_PARISC_PLABEL21L 66
-#define R_PARISC_PLABEL14R 70
-#define R_PARISC_PCREL64 72
-#define R_PARISC_PCREL22F 74
-#define R_PARISC_PCREL14WR 75
-#define R_PARISC_PCREL14DR 76
-#define R_PARISC_PCREL16F 77
-#define R_PARISC_PCREL16WF 78
-#define R_PARISC_PCREL16DF 79
-#define R_PARISC_DIR64 80
-#define R_PARISC_DIR14WR 83
-#define R_PARISC_DIR14DR 84
-#define R_PARISC_DIR16F 85
-#define R_PARISC_DIR16WF 86
-#define R_PARISC_DIR16DF 87
-#define R_PARISC_GPREL64 88
-#define R_PARISC_GPREL14WR 91
-#define R_PARISC_GPREL14DR 92
-#define R_PARISC_GPREL16F 93
-#define R_PARISC_GPREL16WF 94
-#define R_PARISC_GPREL16DF 95
-#define R_PARISC_LTOFF64 96
-#define R_PARISC_LTOFF14WR 99
-#define R_PARISC_LTOFF14DR 100
-#define R_PARISC_LTOFF16F 101
-#define R_PARISC_LTOFF16WF 102
-#define R_PARISC_LTOFF16DF 103
-#define R_PARISC_SECREL64 104
-#define R_PARISC_SEGREL64 112
-#define R_PARISC_PLTOFF14WR 115
-#define R_PARISC_PLTOFF14DR 116
-#define R_PARISC_PLTOFF16F 117
-#define R_PARISC_PLTOFF16WF 118
-#define R_PARISC_PLTOFF16DF 119
-#define R_PARISC_LTOFF_FPTR64 120
-#define R_PARISC_LTOFF_FPTR14WR 123
-#define R_PARISC_LTOFF_FPTR14DR 124
-#define R_PARISC_LTOFF_FPTR16F 125
-#define R_PARISC_LTOFF_FPTR16WF 126
-#define R_PARISC_LTOFF_FPTR16DF 127
-#define R_PARISC_LORESERVE 128
-#define R_PARISC_COPY 128
-#define R_PARISC_IPLT 129
-#define R_PARISC_EPLT 130
-#define R_PARISC_TPREL32 153
-#define R_PARISC_TPREL21L 154
-#define R_PARISC_TPREL14R 158
-#define R_PARISC_LTOFF_TP21L 162
-#define R_PARISC_LTOFF_TP14R 166
-#define R_PARISC_LTOFF_TP14F 167
-#define R_PARISC_TPREL64 216
-#define R_PARISC_TPREL14WR 219
-#define R_PARISC_TPREL14DR 220
-#define R_PARISC_TPREL16F 221
-#define R_PARISC_TPREL16WF 222
-#define R_PARISC_TPREL16DF 223
-#define R_PARISC_LTOFF_TP64 224
-#define R_PARISC_LTOFF_TP14WR 227
-#define R_PARISC_LTOFF_TP14DR 228
-#define R_PARISC_LTOFF_TP16F 229
-#define R_PARISC_LTOFF_TP16WF 230
-#define R_PARISC_LTOFF_TP16DF 231
-#define R_PARISC_GNU_VTENTRY 232
-#define R_PARISC_GNU_VTINHERIT 233
-#define R_PARISC_TLS_GD21L 234
-#define R_PARISC_TLS_GD14R 235
-#define R_PARISC_TLS_GDCALL 236
-#define R_PARISC_TLS_LDM21L 237
-#define R_PARISC_TLS_LDM14R 238
-#define R_PARISC_TLS_LDMCALL 239
-#define R_PARISC_TLS_LDO21L 240
-#define R_PARISC_TLS_LDO14R 241
-#define R_PARISC_TLS_DTPMOD32 242
-#define R_PARISC_TLS_DTPMOD64 243
-#define R_PARISC_TLS_DTPOFF32 244
-#define R_PARISC_TLS_DTPOFF64 245
-#define R_PARISC_TLS_LE21L R_PARISC_TPREL21L
-#define R_PARISC_TLS_LE14R R_PARISC_TPREL14R
-#define R_PARISC_TLS_IE21L R_PARISC_LTOFF_TP21L
-#define R_PARISC_TLS_IE14R R_PARISC_LTOFF_TP14R
-#define R_PARISC_TLS_TPREL32 R_PARISC_TPREL32
-#define R_PARISC_TLS_TPREL64 R_PARISC_TPREL64
-#define R_PARISC_HIRESERVE 255
-
-#define PT_HP_TLS (PT_LOOS + 0x0)
-#define PT_HP_CORE_NONE (PT_LOOS + 0x1)
-#define PT_HP_CORE_VERSION (PT_LOOS + 0x2)
-#define PT_HP_CORE_KERNEL (PT_LOOS + 0x3)
-#define PT_HP_CORE_COMM (PT_LOOS + 0x4)
-#define PT_HP_CORE_PROC (PT_LOOS + 0x5)
-#define PT_HP_CORE_LOADABLE (PT_LOOS + 0x6)
-#define PT_HP_CORE_STACK (PT_LOOS + 0x7)
-#define PT_HP_CORE_SHM (PT_LOOS + 0x8)
-#define PT_HP_CORE_MMF (PT_LOOS + 0x9)
-#define PT_HP_PARALLEL (PT_LOOS + 0x10)
-#define PT_HP_FASTBIND (PT_LOOS + 0x11)
-#define PT_HP_OPT_ANNOT (PT_LOOS + 0x12)
-#define PT_HP_HSL_ANNOT (PT_LOOS + 0x13)
-#define PT_HP_STACK (PT_LOOS + 0x14)
-
-#define PT_PARISC_ARCHEXT 0x70000000
-#define PT_PARISC_UNWIND 0x70000001
-
-#define PF_PARISC_SBP 0x08000000
-
-#define PF_HP_PAGE_SIZE 0x00100000
-#define PF_HP_FAR_SHARED 0x00200000
-#define PF_HP_NEAR_SHARED 0x00400000
-#define PF_HP_CODE 0x01000000
-#define PF_HP_MODIFY 0x02000000
-#define PF_HP_LAZYSWAP 0x04000000
-#define PF_HP_SBP 0x08000000
-
-#define EF_ALPHA_32BIT 1
-#define EF_ALPHA_CANRELAX 2
-
-#define SHT_ALPHA_DEBUG 0x70000001
-#define SHT_ALPHA_REGINFO 0x70000002
-
-#define SHF_ALPHA_GPREL 0x10000000
-
-#define STO_ALPHA_NOPV 0x80
-#define STO_ALPHA_STD_GPLOAD 0x88
-
-#define R_ALPHA_NONE 0
-#define R_ALPHA_REFLONG 1
-#define R_ALPHA_REFQUAD 2
-#define R_ALPHA_GPREL32 3
-#define R_ALPHA_LITERAL 4
-#define R_ALPHA_LITUSE 5
-#define R_ALPHA_GPDISP 6
-#define R_ALPHA_BRADDR 7
-#define R_ALPHA_HINT 8
-#define R_ALPHA_SREL16 9
-#define R_ALPHA_SREL32 10
-#define R_ALPHA_SREL64 11
-#define R_ALPHA_GPRELHIGH 17
-#define R_ALPHA_GPRELLOW 18
-#define R_ALPHA_GPREL16 19
-#define R_ALPHA_COPY 24
-#define R_ALPHA_GLOB_DAT 25
-#define R_ALPHA_JMP_SLOT 26
-#define R_ALPHA_RELATIVE 27
-#define R_ALPHA_TLS_GD_HI 28
-#define R_ALPHA_TLSGD 29
-#define R_ALPHA_TLS_LDM 30
-#define R_ALPHA_DTPMOD64 31
-#define R_ALPHA_GOTDTPREL 32
-#define R_ALPHA_DTPREL64 33
-#define R_ALPHA_DTPRELHI 34
-#define R_ALPHA_DTPRELLO 35
-#define R_ALPHA_DTPREL16 36
-#define R_ALPHA_GOTTPREL 37
-#define R_ALPHA_TPREL64 38
-#define R_ALPHA_TPRELHI 39
-#define R_ALPHA_TPRELLO 40
-#define R_ALPHA_TPREL16 41
-
-#define R_ALPHA_NUM 46
-
-#define LITUSE_ALPHA_ADDR 0
-#define LITUSE_ALPHA_BASE 1
-#define LITUSE_ALPHA_BYTOFF 2
-#define LITUSE_ALPHA_JSR 3
-#define LITUSE_ALPHA_TLS_GD 4
-#define LITUSE_ALPHA_TLS_LDM 5
-
-#define DT_ALPHA_PLTRO (DT_LOPROC + 0)
-#define DT_ALPHA_NUM 1
-
-#define EF_PPC_EMB 0x80000000
-
-#define EF_PPC_RELOCATABLE 0x00010000
-#define EF_PPC_RELOCATABLE_LIB 0x00008000
-
-#define R_PPC_NONE 0
-#define R_PPC_ADDR32 1
-#define R_PPC_ADDR24 2
-#define R_PPC_ADDR16 3
-#define R_PPC_ADDR16_LO 4
-#define R_PPC_ADDR16_HI 5
-#define R_PPC_ADDR16_HA 6
-#define R_PPC_ADDR14 7
-#define R_PPC_ADDR14_BRTAKEN 8
-#define R_PPC_ADDR14_BRNTAKEN 9
-#define R_PPC_REL24 10
-#define R_PPC_REL14 11
-#define R_PPC_REL14_BRTAKEN 12
-#define R_PPC_REL14_BRNTAKEN 13
-#define R_PPC_GOT16 14
-#define R_PPC_GOT16_LO 15
-#define R_PPC_GOT16_HI 16
-#define R_PPC_GOT16_HA 17
-#define R_PPC_PLTREL24 18
-#define R_PPC_COPY 19
-#define R_PPC_GLOB_DAT 20
-#define R_PPC_JMP_SLOT 21
-#define R_PPC_RELATIVE 22
-#define R_PPC_LOCAL24PC 23
-#define R_PPC_UADDR32 24
-#define R_PPC_UADDR16 25
-#define R_PPC_REL32 26
-#define R_PPC_PLT32 27
-#define R_PPC_PLTREL32 28
-#define R_PPC_PLT16_LO 29
-#define R_PPC_PLT16_HI 30
-#define R_PPC_PLT16_HA 31
-#define R_PPC_SDAREL16 32
-#define R_PPC_SECTOFF 33
-#define R_PPC_SECTOFF_LO 34
-#define R_PPC_SECTOFF_HI 35
-#define R_PPC_SECTOFF_HA 36
-
-#define R_PPC_TLS 67
-#define R_PPC_DTPMOD32 68
-#define R_PPC_TPREL16 69
-#define R_PPC_TPREL16_LO 70
-#define R_PPC_TPREL16_HI 71
-#define R_PPC_TPREL16_HA 72
-#define R_PPC_TPREL32 73
-#define R_PPC_DTPREL16 74
-#define R_PPC_DTPREL16_LO 75
-#define R_PPC_DTPREL16_HI 76
-#define R_PPC_DTPREL16_HA 77
-#define R_PPC_DTPREL32 78
-#define R_PPC_GOT_TLSGD16 79
-#define R_PPC_GOT_TLSGD16_LO 80
-#define R_PPC_GOT_TLSGD16_HI 81
-#define R_PPC_GOT_TLSGD16_HA 82
-#define R_PPC_GOT_TLSLD16 83
-#define R_PPC_GOT_TLSLD16_LO 84
-#define R_PPC_GOT_TLSLD16_HI 85
-#define R_PPC_GOT_TLSLD16_HA 86
-#define R_PPC_GOT_TPREL16 87
-#define R_PPC_GOT_TPREL16_LO 88
-#define R_PPC_GOT_TPREL16_HI 89
-#define R_PPC_GOT_TPREL16_HA 90
-#define R_PPC_GOT_DTPREL16 91
-#define R_PPC_GOT_DTPREL16_LO 92
-#define R_PPC_GOT_DTPREL16_HI 93
-#define R_PPC_GOT_DTPREL16_HA 94
-#define R_PPC_TLSGD 95
-#define R_PPC_TLSLD 96
-
-#define R_PPC_EMB_NADDR32 101
-#define R_PPC_EMB_NADDR16 102
-#define R_PPC_EMB_NADDR16_LO 103
-#define R_PPC_EMB_NADDR16_HI 104
-#define R_PPC_EMB_NADDR16_HA 105
-#define R_PPC_EMB_SDAI16 106
-#define R_PPC_EMB_SDA2I16 107
-#define R_PPC_EMB_SDA2REL 108
-#define R_PPC_EMB_SDA21 109
-#define R_PPC_EMB_MRKREF 110
-#define R_PPC_EMB_RELSEC16 111
-#define R_PPC_EMB_RELST_LO 112
-#define R_PPC_EMB_RELST_HI 113
-#define R_PPC_EMB_RELST_HA 114
-#define R_PPC_EMB_BIT_FLD 115
-#define R_PPC_EMB_RELSDA 116
-
-#define R_PPC_DIAB_SDA21_LO 180
-#define R_PPC_DIAB_SDA21_HI 181
-#define R_PPC_DIAB_SDA21_HA 182
-#define R_PPC_DIAB_RELSDA_LO 183
-#define R_PPC_DIAB_RELSDA_HI 184
-#define R_PPC_DIAB_RELSDA_HA 185
-
-#define R_PPC_IRELATIVE 248
-
-#define R_PPC_REL16 249
-#define R_PPC_REL16_LO 250
-#define R_PPC_REL16_HI 251
-#define R_PPC_REL16_HA 252
-
-#define R_PPC_TOC16 255
-
-#define DT_PPC_GOT (DT_LOPROC + 0)
-#define DT_PPC_OPT (DT_LOPROC + 1)
-#define DT_PPC_NUM 2
-
-#define PPC_OPT_TLS 1
-
-#define R_PPC64_NONE R_PPC_NONE
-#define R_PPC64_ADDR32 R_PPC_ADDR32
-#define R_PPC64_ADDR24 R_PPC_ADDR24
-#define R_PPC64_ADDR16 R_PPC_ADDR16
-#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO
-#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI
-#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA
-#define R_PPC64_ADDR14 R_PPC_ADDR14
-#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN
-#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN
-#define R_PPC64_REL24 R_PPC_REL24
-#define R_PPC64_REL14 R_PPC_REL14
-#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN
-#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN
-#define R_PPC64_GOT16 R_PPC_GOT16
-#define R_PPC64_GOT16_LO R_PPC_GOT16_LO
-#define R_PPC64_GOT16_HI R_PPC_GOT16_HI
-#define R_PPC64_GOT16_HA R_PPC_GOT16_HA
-
-#define R_PPC64_COPY R_PPC_COPY
-#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT
-#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT
-#define R_PPC64_RELATIVE R_PPC_RELATIVE
-
-#define R_PPC64_UADDR32 R_PPC_UADDR32
-#define R_PPC64_UADDR16 R_PPC_UADDR16
-#define R_PPC64_REL32 R_PPC_REL32
-#define R_PPC64_PLT32 R_PPC_PLT32
-#define R_PPC64_PLTREL32 R_PPC_PLTREL32
-#define R_PPC64_PLT16_LO R_PPC_PLT16_LO
-#define R_PPC64_PLT16_HI R_PPC_PLT16_HI
-#define R_PPC64_PLT16_HA R_PPC_PLT16_HA
-
-#define R_PPC64_SECTOFF R_PPC_SECTOFF
-#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO
-#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI
-#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA
-#define R_PPC64_ADDR30 37
-#define R_PPC64_ADDR64 38
-#define R_PPC64_ADDR16_HIGHER 39
-#define R_PPC64_ADDR16_HIGHERA 40
-#define R_PPC64_ADDR16_HIGHEST 41
-#define R_PPC64_ADDR16_HIGHESTA 42
-#define R_PPC64_UADDR64 43
-#define R_PPC64_REL64 44
-#define R_PPC64_PLT64 45
-#define R_PPC64_PLTREL64 46
-#define R_PPC64_TOC16 47
-#define R_PPC64_TOC16_LO 48
-#define R_PPC64_TOC16_HI 49
-#define R_PPC64_TOC16_HA 50
-#define R_PPC64_TOC 51
-#define R_PPC64_PLTGOT16 52
-#define R_PPC64_PLTGOT16_LO 53
-#define R_PPC64_PLTGOT16_HI 54
-#define R_PPC64_PLTGOT16_HA 55
-
-#define R_PPC64_ADDR16_DS 56
-#define R_PPC64_ADDR16_LO_DS 57
-#define R_PPC64_GOT16_DS 58
-#define R_PPC64_GOT16_LO_DS 59
-#define R_PPC64_PLT16_LO_DS 60
-#define R_PPC64_SECTOFF_DS 61
-#define R_PPC64_SECTOFF_LO_DS 62
-#define R_PPC64_TOC16_DS 63
-#define R_PPC64_TOC16_LO_DS 64
-#define R_PPC64_PLTGOT16_DS 65
-#define R_PPC64_PLTGOT16_LO_DS 66
-
-#define R_PPC64_TLS 67
-#define R_PPC64_DTPMOD64 68
-#define R_PPC64_TPREL16 69
-#define R_PPC64_TPREL16_LO 70
-#define R_PPC64_TPREL16_HI 71
-#define R_PPC64_TPREL16_HA 72
-#define R_PPC64_TPREL64 73
-#define R_PPC64_DTPREL16 74
-#define R_PPC64_DTPREL16_LO 75
-#define R_PPC64_DTPREL16_HI 76
-#define R_PPC64_DTPREL16_HA 77
-#define R_PPC64_DTPREL64 78
-#define R_PPC64_GOT_TLSGD16 79
-#define R_PPC64_GOT_TLSGD16_LO 80
-#define R_PPC64_GOT_TLSGD16_HI 81
-#define R_PPC64_GOT_TLSGD16_HA 82
-#define R_PPC64_GOT_TLSLD16 83
-#define R_PPC64_GOT_TLSLD16_LO 84
-#define R_PPC64_GOT_TLSLD16_HI 85
-#define R_PPC64_GOT_TLSLD16_HA 86
-#define R_PPC64_GOT_TPREL16_DS 87
-#define R_PPC64_GOT_TPREL16_LO_DS 88
-#define R_PPC64_GOT_TPREL16_HI 89
-#define R_PPC64_GOT_TPREL16_HA 90
-#define R_PPC64_GOT_DTPREL16_DS 91
-#define R_PPC64_GOT_DTPREL16_LO_DS 92
-#define R_PPC64_GOT_DTPREL16_HI 93
-#define R_PPC64_GOT_DTPREL16_HA 94
-#define R_PPC64_TPREL16_DS 95
-#define R_PPC64_TPREL16_LO_DS 96
-#define R_PPC64_TPREL16_HIGHER 97
-#define R_PPC64_TPREL16_HIGHERA 98
-#define R_PPC64_TPREL16_HIGHEST 99
-#define R_PPC64_TPREL16_HIGHESTA 100
-#define R_PPC64_DTPREL16_DS 101
-#define R_PPC64_DTPREL16_LO_DS 102
-#define R_PPC64_DTPREL16_HIGHER 103
-#define R_PPC64_DTPREL16_HIGHERA 104
-#define R_PPC64_DTPREL16_HIGHEST 105
-#define R_PPC64_DTPREL16_HIGHESTA 106
-#define R_PPC64_TLSGD 107
-#define R_PPC64_TLSLD 108
-#define R_PPC64_TOCSAVE 109
-#define R_PPC64_ADDR16_HIGH 110
-#define R_PPC64_ADDR16_HIGHA 111
-#define R_PPC64_TPREL16_HIGH 112
-#define R_PPC64_TPREL16_HIGHA 113
-#define R_PPC64_DTPREL16_HIGH 114
-#define R_PPC64_DTPREL16_HIGHA 115
-
-#define R_PPC64_JMP_IREL 247
-#define R_PPC64_IRELATIVE 248
-#define R_PPC64_REL16 249
-#define R_PPC64_REL16_LO 250
-#define R_PPC64_REL16_HI 251
-#define R_PPC64_REL16_HA 252
-
-#define EF_PPC64_ABI 3
-
-#define DT_PPC64_GLINK (DT_LOPROC + 0)
-#define DT_PPC64_OPD (DT_LOPROC + 1)
-#define DT_PPC64_OPDSZ (DT_LOPROC + 2)
-#define DT_PPC64_OPT (DT_LOPROC + 3)
-#define DT_PPC64_NUM 4
-
-#define PPC64_OPT_TLS 1
-#define PPC64_OPT_MULTI_TOC 2
-
-#define STO_PPC64_LOCAL_BIT 5
-#define STO_PPC64_LOCAL_MASK 0xe0
-#define PPC64_LOCAL_ENTRY_OFFSET(x) (1 << (((x) & 0xe0) >> 5) & 0xfc)
-
-#define EF_ARM_RELEXEC 0x01
-#define EF_ARM_HASENTRY 0x02
-#define EF_ARM_INTERWORK 0x04
-#define EF_ARM_APCS_26 0x08
-#define EF_ARM_APCS_FLOAT 0x10
-#define EF_ARM_PIC 0x20
-#define EF_ARM_ALIGN8 0x40
-#define EF_ARM_NEW_ABI 0x80
-#define EF_ARM_OLD_ABI 0x100
-#define EF_ARM_SOFT_FLOAT 0x200
-#define EF_ARM_VFP_FLOAT 0x400
-#define EF_ARM_MAVERICK_FLOAT 0x800
-
-#define EF_ARM_ABI_FLOAT_SOFT 0x200
-#define EF_ARM_ABI_FLOAT_HARD 0x400
-
-#define EF_ARM_SYMSARESORTED 0x04
-#define EF_ARM_DYNSYMSUSESEGIDX 0x08
-#define EF_ARM_MAPSYMSFIRST 0x10
-#define EF_ARM_EABIMASK 0XFF000000
-
-#define EF_ARM_BE8 0x00800000
-#define EF_ARM_LE8 0x00400000
-
-#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK)
-#define EF_ARM_EABI_UNKNOWN 0x00000000
-#define EF_ARM_EABI_VER1 0x01000000
-#define EF_ARM_EABI_VER2 0x02000000
-#define EF_ARM_EABI_VER3 0x03000000
-#define EF_ARM_EABI_VER4 0x04000000
-#define EF_ARM_EABI_VER5 0x05000000
-
-#define STT_ARM_TFUNC STT_LOPROC
-#define STT_ARM_16BIT STT_HIPROC
-
-#define SHF_ARM_ENTRYSECT 0x10000000
-#define SHF_ARM_COMDEF 0x80000000
-
-#define PF_ARM_SB 0x10000000
-
-#define PF_ARM_PI 0x20000000
-#define PF_ARM_ABS 0x40000000
-
-#define PT_ARM_EXIDX (PT_LOPROC + 1)
-
-#define SHT_ARM_EXIDX (SHT_LOPROC + 1)
-#define SHT_ARM_PREEMPTMAP (SHT_LOPROC + 2)
-#define SHT_ARM_ATTRIBUTES (SHT_LOPROC + 3)
-
-#define R_AARCH64_NONE 0
-#define R_AARCH64_P32_ABS32 1
-#define R_AARCH64_P32_COPY 180
-#define R_AARCH64_P32_GLOB_DAT 181
-#define R_AARCH64_P32_JUMP_SLOT 182
-#define R_AARCH64_P32_RELATIVE 183
-#define R_AARCH64_P32_TLS_DTPMOD 184
-#define R_AARCH64_P32_TLS_DTPREL 185
-#define R_AARCH64_P32_TLS_TPREL 186
-#define R_AARCH64_P32_TLSDESC 187
-#define R_AARCH64_P32_IRELATIVE 188
-#define R_AARCH64_ABS64 257
-#define R_AARCH64_ABS32 258
-#define R_AARCH64_ABS16 259
-#define R_AARCH64_PREL64 260
-#define R_AARCH64_PREL32 261
-#define R_AARCH64_PREL16 262
-#define R_AARCH64_MOVW_UABS_G0 263
-#define R_AARCH64_MOVW_UABS_G0_NC 264
-#define R_AARCH64_MOVW_UABS_G1 265
-#define R_AARCH64_MOVW_UABS_G1_NC 266
-#define R_AARCH64_MOVW_UABS_G2 267
-#define R_AARCH64_MOVW_UABS_G2_NC 268
-#define R_AARCH64_MOVW_UABS_G3 269
-#define R_AARCH64_MOVW_SABS_G0 270
-#define R_AARCH64_MOVW_SABS_G1 271
-#define R_AARCH64_MOVW_SABS_G2 272
-#define R_AARCH64_LD_PREL_LO19 273
-#define R_AARCH64_ADR_PREL_LO21 274
-#define R_AARCH64_ADR_PREL_PG_HI21 275
-#define R_AARCH64_ADR_PREL_PG_HI21_NC 276
-#define R_AARCH64_ADD_ABS_LO12_NC 277
-#define R_AARCH64_LDST8_ABS_LO12_NC 278
-#define R_AARCH64_TSTBR14 279
-#define R_AARCH64_CONDBR19 280
-#define R_AARCH64_JUMP26 282
-#define R_AARCH64_CALL26 283
-#define R_AARCH64_LDST16_ABS_LO12_NC 284
-#define R_AARCH64_LDST32_ABS_LO12_NC 285
-#define R_AARCH64_LDST64_ABS_LO12_NC 286
-#define R_AARCH64_MOVW_PREL_G0 287
-#define R_AARCH64_MOVW_PREL_G0_NC 288
-#define R_AARCH64_MOVW_PREL_G1 289
-#define R_AARCH64_MOVW_PREL_G1_NC 290
-#define R_AARCH64_MOVW_PREL_G2 291
-#define R_AARCH64_MOVW_PREL_G2_NC 292
-#define R_AARCH64_MOVW_PREL_G3 293
-#define R_AARCH64_LDST128_ABS_LO12_NC 299
-#define R_AARCH64_MOVW_GOTOFF_G0 300
-#define R_AARCH64_MOVW_GOTOFF_G0_NC 301
-#define R_AARCH64_MOVW_GOTOFF_G1 302
-#define R_AARCH64_MOVW_GOTOFF_G1_NC 303
-#define R_AARCH64_MOVW_GOTOFF_G2 304
-#define R_AARCH64_MOVW_GOTOFF_G2_NC 305
-#define R_AARCH64_MOVW_GOTOFF_G3 306
-#define R_AARCH64_GOTREL64 307
-#define R_AARCH64_GOTREL32 308
-#define R_AARCH64_GOT_LD_PREL19 309
-#define R_AARCH64_LD64_GOTOFF_LO15 310
-#define R_AARCH64_ADR_GOT_PAGE 311
-#define R_AARCH64_LD64_GOT_LO12_NC 312
-#define R_AARCH64_LD64_GOTPAGE_LO15 313
-#define R_AARCH64_TLSGD_ADR_PREL21 512
-#define R_AARCH64_TLSGD_ADR_PAGE21 513
-#define R_AARCH64_TLSGD_ADD_LO12_NC 514
-#define R_AARCH64_TLSGD_MOVW_G1 515
-#define R_AARCH64_TLSGD_MOVW_G0_NC 516
-#define R_AARCH64_TLSLD_ADR_PREL21 517
-#define R_AARCH64_TLSLD_ADR_PAGE21 518
-#define R_AARCH64_TLSLD_ADD_LO12_NC 519
-#define R_AARCH64_TLSLD_MOVW_G1 520
-#define R_AARCH64_TLSLD_MOVW_G0_NC 521
-#define R_AARCH64_TLSLD_LD_PREL19 522
-#define R_AARCH64_TLSLD_MOVW_DTPREL_G2 523
-#define R_AARCH64_TLSLD_MOVW_DTPREL_G1 524
-#define R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC 525
-#define R_AARCH64_TLSLD_MOVW_DTPREL_G0 526
-#define R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC 527
-#define R_AARCH64_TLSLD_ADD_DTPREL_HI12 528
-#define R_AARCH64_TLSLD_ADD_DTPREL_LO12 529
-#define R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC 530
-#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12 531
-#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC 532
-#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12 533
-#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC 534
-#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12 535
-#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC 536
-#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12 537
-#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC 538
-#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 539
-#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC 540
-#define R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 541
-#define R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC 542
-#define R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 543
-#define R_AARCH64_TLSLE_MOVW_TPREL_G2 544
-#define R_AARCH64_TLSLE_MOVW_TPREL_G1 545
-#define R_AARCH64_TLSLE_MOVW_TPREL_G1_NC 546
-#define R_AARCH64_TLSLE_MOVW_TPREL_G0 547
-#define R_AARCH64_TLSLE_MOVW_TPREL_G0_NC 548
-#define R_AARCH64_TLSLE_ADD_TPREL_HI12 549
-#define R_AARCH64_TLSLE_ADD_TPREL_LO12 550
-#define R_AARCH64_TLSLE_ADD_TPREL_LO12_NC 551
-#define R_AARCH64_TLSLE_LDST8_TPREL_LO12 552
-#define R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC 553
-#define R_AARCH64_TLSLE_LDST16_TPREL_LO12 554
-#define R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC 555
-#define R_AARCH64_TLSLE_LDST32_TPREL_LO12 556
-#define R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC 557
-#define R_AARCH64_TLSLE_LDST64_TPREL_LO12 558
-#define R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC 559
-#define R_AARCH64_TLSDESC_LD_PREL19 560
-#define R_AARCH64_TLSDESC_ADR_PREL21 561
-#define R_AARCH64_TLSDESC_ADR_PAGE21 562
-#define R_AARCH64_TLSDESC_LD64_LO12 563
-#define R_AARCH64_TLSDESC_ADD_LO12 564
-#define R_AARCH64_TLSDESC_OFF_G1 565
-#define R_AARCH64_TLSDESC_OFF_G0_NC 566
-#define R_AARCH64_TLSDESC_LDR 567
-#define R_AARCH64_TLSDESC_ADD 568
-#define R_AARCH64_TLSDESC_CALL 569
-#define R_AARCH64_TLSLE_LDST128_TPREL_LO12 570
-#define R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC 571
-#define R_AARCH64_TLSLD_LDST128_DTPREL_LO12 572
-#define R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC 573
-#define R_AARCH64_COPY 1024
-#define R_AARCH64_GLOB_DAT 1025
-#define R_AARCH64_JUMP_SLOT 1026
-#define R_AARCH64_RELATIVE 1027
-#define R_AARCH64_TLS_DTPMOD 1028
-#define R_AARCH64_TLS_DTPMOD64 1028
-#define R_AARCH64_TLS_DTPREL 1029
-#define R_AARCH64_TLS_DTPREL64 1029
-#define R_AARCH64_TLS_TPREL 1030
-#define R_AARCH64_TLS_TPREL64 1030
-#define R_AARCH64_TLSDESC 1031
-
-#define R_ARM_NONE 0
-#define R_ARM_PC24 1
-#define R_ARM_ABS32 2
-#define R_ARM_REL32 3
-#define R_ARM_PC13 4
-#define R_ARM_ABS16 5
-#define R_ARM_ABS12 6
-#define R_ARM_THM_ABS5 7
-#define R_ARM_ABS8 8
-#define R_ARM_SBREL32 9
-#define R_ARM_THM_PC22 10
-#define R_ARM_THM_PC8 11
-#define R_ARM_AMP_VCALL9 12
-#define R_ARM_TLS_DESC 13
-#define R_ARM_THM_SWI8 14
-#define R_ARM_XPC25 15
-#define R_ARM_THM_XPC22 16
-#define R_ARM_TLS_DTPMOD32 17
-#define R_ARM_TLS_DTPOFF32 18
-#define R_ARM_TLS_TPOFF32 19
-#define R_ARM_COPY 20
-#define R_ARM_GLOB_DAT 21
-#define R_ARM_JUMP_SLOT 22
-#define R_ARM_RELATIVE 23
-#define R_ARM_GOTOFF 24
-#define R_ARM_GOTPC 25
-#define R_ARM_GOT32 26
-#define R_ARM_PLT32 27
-#define R_ARM_CALL 28
-#define R_ARM_JUMP24 29
-#define R_ARM_THM_JUMP24 30
-#define R_ARM_BASE_ABS 31
-#define R_ARM_ALU_PCREL_7_0 32
-#define R_ARM_ALU_PCREL_15_8 33
-#define R_ARM_ALU_PCREL_23_15 34
-#define R_ARM_LDR_SBREL_11_0 35
-#define R_ARM_ALU_SBREL_19_12 36
-#define R_ARM_ALU_SBREL_27_20 37
-#define R_ARM_TARGET1 38
-#define R_ARM_SBREL31 39
-#define R_ARM_V4BX 40
-#define R_ARM_TARGET2 41
-#define R_ARM_PREL31 42
-#define R_ARM_MOVW_ABS_NC 43
-#define R_ARM_MOVT_ABS 44
-#define R_ARM_MOVW_PREL_NC 45
-#define R_ARM_MOVT_PREL 46
-#define R_ARM_THM_MOVW_ABS_NC 47
-#define R_ARM_THM_MOVT_ABS 48
-#define R_ARM_THM_MOVW_PREL_NC 49
-#define R_ARM_THM_MOVT_PREL 50
-#define R_ARM_THM_JUMP19 51
-#define R_ARM_THM_JUMP6 52
-#define R_ARM_THM_ALU_PREL_11_0 53
-#define R_ARM_THM_PC12 54
-#define R_ARM_ABS32_NOI 55
-#define R_ARM_REL32_NOI 56
-#define R_ARM_ALU_PC_G0_NC 57
-#define R_ARM_ALU_PC_G0 58
-#define R_ARM_ALU_PC_G1_NC 59
-#define R_ARM_ALU_PC_G1 60
-#define R_ARM_ALU_PC_G2 61
-#define R_ARM_LDR_PC_G1 62
-#define R_ARM_LDR_PC_G2 63
-#define R_ARM_LDRS_PC_G0 64
-#define R_ARM_LDRS_PC_G1 65
-#define R_ARM_LDRS_PC_G2 66
-#define R_ARM_LDC_PC_G0 67
-#define R_ARM_LDC_PC_G1 68
-#define R_ARM_LDC_PC_G2 69
-#define R_ARM_ALU_SB_G0_NC 70
-#define R_ARM_ALU_SB_G0 71
-#define R_ARM_ALU_SB_G1_NC 72
-#define R_ARM_ALU_SB_G1 73
-#define R_ARM_ALU_SB_G2 74
-#define R_ARM_LDR_SB_G0 75
-#define R_ARM_LDR_SB_G1 76
-#define R_ARM_LDR_SB_G2 77
-#define R_ARM_LDRS_SB_G0 78
-#define R_ARM_LDRS_SB_G1 79
-#define R_ARM_LDRS_SB_G2 80
-#define R_ARM_LDC_SB_G0 81
-#define R_ARM_LDC_SB_G1 82
-#define R_ARM_LDC_SB_G2 83
-#define R_ARM_MOVW_BREL_NC 84
-#define R_ARM_MOVT_BREL 85
-#define R_ARM_MOVW_BREL 86
-#define R_ARM_THM_MOVW_BREL_NC 87
-#define R_ARM_THM_MOVT_BREL 88
-#define R_ARM_THM_MOVW_BREL 89
-#define R_ARM_TLS_GOTDESC 90
-#define R_ARM_TLS_CALL 91
-#define R_ARM_TLS_DESCSEQ 92
-#define R_ARM_THM_TLS_CALL 93
-#define R_ARM_PLT32_ABS 94
-#define R_ARM_GOT_ABS 95
-#define R_ARM_GOT_PREL 96
-#define R_ARM_GOT_BREL12 97
-#define R_ARM_GOTOFF12 98
-#define R_ARM_GOTRELAX 99
-#define R_ARM_GNU_VTENTRY 100
-#define R_ARM_GNU_VTINHERIT 101
-#define R_ARM_THM_PC11 102
-#define R_ARM_THM_PC9 103
-#define R_ARM_TLS_GD32 104
-
-#define R_ARM_TLS_LDM32 105
-
-#define R_ARM_TLS_LDO32 106
-
-#define R_ARM_TLS_IE32 107
-
-#define R_ARM_TLS_LE32 108
-#define R_ARM_TLS_LDO12 109
-#define R_ARM_TLS_LE12 110
-#define R_ARM_TLS_IE12GP 111
-#define R_ARM_ME_TOO 128
-#define R_ARM_THM_TLS_DESCSEQ 129
-#define R_ARM_THM_TLS_DESCSEQ16 129
-#define R_ARM_THM_TLS_DESCSEQ32 130
-#define R_ARM_THM_GOT_BREL12 131
-#define R_ARM_IRELATIVE 160
-#define R_ARM_RXPC25 249
-#define R_ARM_RSBREL32 250
-#define R_ARM_THM_RPC22 251
-#define R_ARM_RREL32 252
-#define R_ARM_RABS22 253
-#define R_ARM_RPC24 254
-#define R_ARM_RBASE 255
-
-#define R_ARM_NUM 256
-
-#define EF_IA_64_MASKOS 0x0000000f
-#define EF_IA_64_ABI64 0x00000010
-#define EF_IA_64_ARCH 0xff000000
-
-#define PT_IA_64_ARCHEXT (PT_LOPROC + 0)
-#define PT_IA_64_UNWIND (PT_LOPROC + 1)
-#define PT_IA_64_HP_OPT_ANOT (PT_LOOS + 0x12)
-#define PT_IA_64_HP_HSL_ANOT (PT_LOOS + 0x13)
-#define PT_IA_64_HP_STACK (PT_LOOS + 0x14)
-
-#define PF_IA_64_NORECOV 0x80000000
-
-#define SHT_IA_64_EXT (SHT_LOPROC + 0)
-#define SHT_IA_64_UNWIND (SHT_LOPROC + 1)
-
-#define SHF_IA_64_SHORT 0x10000000
-#define SHF_IA_64_NORECOV 0x20000000
-
-#define DT_IA_64_PLT_RESERVE (DT_LOPROC + 0)
-#define DT_IA_64_NUM 1
-
-#define R_IA64_NONE 0x00
-#define R_IA64_IMM14 0x21
-#define R_IA64_IMM22 0x22
-#define R_IA64_IMM64 0x23
-#define R_IA64_DIR32MSB 0x24
-#define R_IA64_DIR32LSB 0x25
-#define R_IA64_DIR64MSB 0x26
-#define R_IA64_DIR64LSB 0x27
-#define R_IA64_GPREL22 0x2a
-#define R_IA64_GPREL64I 0x2b
-#define R_IA64_GPREL32MSB 0x2c
-#define R_IA64_GPREL32LSB 0x2d
-#define R_IA64_GPREL64MSB 0x2e
-#define R_IA64_GPREL64LSB 0x2f
-#define R_IA64_LTOFF22 0x32
-#define R_IA64_LTOFF64I 0x33
-#define R_IA64_PLTOFF22 0x3a
-#define R_IA64_PLTOFF64I 0x3b
-#define R_IA64_PLTOFF64MSB 0x3e
-#define R_IA64_PLTOFF64LSB 0x3f
-#define R_IA64_FPTR64I 0x43
-#define R_IA64_FPTR32MSB 0x44
-#define R_IA64_FPTR32LSB 0x45
-#define R_IA64_FPTR64MSB 0x46
-#define R_IA64_FPTR64LSB 0x47
-#define R_IA64_PCREL60B 0x48
-#define R_IA64_PCREL21B 0x49
-#define R_IA64_PCREL21M 0x4a
-#define R_IA64_PCREL21F 0x4b
-#define R_IA64_PCREL32MSB 0x4c
-#define R_IA64_PCREL32LSB 0x4d
-#define R_IA64_PCREL64MSB 0x4e
-#define R_IA64_PCREL64LSB 0x4f
-#define R_IA64_LTOFF_FPTR22 0x52
-#define R_IA64_LTOFF_FPTR64I 0x53
-#define R_IA64_LTOFF_FPTR32MSB 0x54
-#define R_IA64_LTOFF_FPTR32LSB 0x55
-#define R_IA64_LTOFF_FPTR64MSB 0x56
-#define R_IA64_LTOFF_FPTR64LSB 0x57
-#define R_IA64_SEGREL32MSB 0x5c
-#define R_IA64_SEGREL32LSB 0x5d
-#define R_IA64_SEGREL64MSB 0x5e
-#define R_IA64_SEGREL64LSB 0x5f
-#define R_IA64_SECREL32MSB 0x64
-#define R_IA64_SECREL32LSB 0x65
-#define R_IA64_SECREL64MSB 0x66
-#define R_IA64_SECREL64LSB 0x67
-#define R_IA64_REL32MSB 0x6c
-#define R_IA64_REL32LSB 0x6d
-#define R_IA64_REL64MSB 0x6e
-#define R_IA64_REL64LSB 0x6f
-#define R_IA64_LTV32MSB 0x74
-#define R_IA64_LTV32LSB 0x75
-#define R_IA64_LTV64MSB 0x76
-#define R_IA64_LTV64LSB 0x77
-#define R_IA64_PCREL21BI 0x79
-#define R_IA64_PCREL22 0x7a
-#define R_IA64_PCREL64I 0x7b
-#define R_IA64_IPLTMSB 0x80
-#define R_IA64_IPLTLSB 0x81
-#define R_IA64_COPY 0x84
-#define R_IA64_SUB 0x85
-#define R_IA64_LTOFF22X 0x86
-#define R_IA64_LDXMOV 0x87
-#define R_IA64_TPREL14 0x91
-#define R_IA64_TPREL22 0x92
-#define R_IA64_TPREL64I 0x93
-#define R_IA64_TPREL64MSB 0x96
-#define R_IA64_TPREL64LSB 0x97
-#define R_IA64_LTOFF_TPREL22 0x9a
-#define R_IA64_DTPMOD64MSB 0xa6
-#define R_IA64_DTPMOD64LSB 0xa7
-#define R_IA64_LTOFF_DTPMOD22 0xaa
-#define R_IA64_DTPREL14 0xb1
-#define R_IA64_DTPREL22 0xb2
-#define R_IA64_DTPREL64I 0xb3
-#define R_IA64_DTPREL32MSB 0xb4
-#define R_IA64_DTPREL32LSB 0xb5
-#define R_IA64_DTPREL64MSB 0xb6
-#define R_IA64_DTPREL64LSB 0xb7
-#define R_IA64_LTOFF_DTPREL22 0xba
-
-#define EF_SH_MACH_MASK 0x1f
-#define EF_SH_UNKNOWN 0x0
-#define EF_SH1 0x1
-#define EF_SH2 0x2
-#define EF_SH3 0x3
-#define EF_SH_DSP 0x4
-#define EF_SH3_DSP 0x5
-#define EF_SH4AL_DSP 0x6
-#define EF_SH3E 0x8
-#define EF_SH4 0x9
-#define EF_SH2E 0xb
-#define EF_SH4A 0xc
-#define EF_SH2A 0xd
-#define EF_SH4_NOFPU 0x10
-#define EF_SH4A_NOFPU 0x11
-#define EF_SH4_NOMMU_NOFPU 0x12
-#define EF_SH2A_NOFPU 0x13
-#define EF_SH3_NOMMU 0x14
-#define EF_SH2A_SH4_NOFPU 0x15
-#define EF_SH2A_SH3_NOFPU 0x16
-#define EF_SH2A_SH4 0x17
-#define EF_SH2A_SH3E 0x18
-
-#define R_SH_NONE 0
-#define R_SH_DIR32 1
-#define R_SH_REL32 2
-#define R_SH_DIR8WPN 3
-#define R_SH_IND12W 4
-#define R_SH_DIR8WPL 5
-#define R_SH_DIR8WPZ 6
-#define R_SH_DIR8BP 7
-#define R_SH_DIR8W 8
-#define R_SH_DIR8L 9
-#define R_SH_SWITCH16 25
-#define R_SH_SWITCH32 26
-#define R_SH_USES 27
-#define R_SH_COUNT 28
-#define R_SH_ALIGN 29
-#define R_SH_CODE 30
-#define R_SH_DATA 31
-#define R_SH_LABEL 32
-#define R_SH_SWITCH8 33
-#define R_SH_GNU_VTINHERIT 34
-#define R_SH_GNU_VTENTRY 35
-#define R_SH_TLS_GD_32 144
-#define R_SH_TLS_LD_32 145
-#define R_SH_TLS_LDO_32 146
-#define R_SH_TLS_IE_32 147
-#define R_SH_TLS_LE_32 148
-#define R_SH_TLS_DTPMOD32 149
-#define R_SH_TLS_DTPOFF32 150
-#define R_SH_TLS_TPOFF32 151
-#define R_SH_GOT32 160
-#define R_SH_PLT32 161
-#define R_SH_COPY 162
-#define R_SH_GLOB_DAT 163
-#define R_SH_JMP_SLOT 164
-#define R_SH_RELATIVE 165
-#define R_SH_GOTOFF 166
-#define R_SH_GOTPC 167
-#define R_SH_GOT20 201
-#define R_SH_GOTOFF20 202
-#define R_SH_GOTFUNCDESC 203
-#define R_SH_GOTFUNCDEST20 204
-#define R_SH_GOTOFFFUNCDESC 205
-#define R_SH_GOTOFFFUNCDEST20 206
-#define R_SH_FUNCDESC 207
-#define R_SH_FUNCDESC_VALUE 208
-
-#define R_SH_NUM 256
-
-#define R_390_NONE 0
-#define R_390_8 1
-#define R_390_12 2
-#define R_390_16 3
-#define R_390_32 4
-#define R_390_PC32 5
-#define R_390_GOT12 6
-#define R_390_GOT32 7
-#define R_390_PLT32 8
-#define R_390_COPY 9
-#define R_390_GLOB_DAT 10
-#define R_390_JMP_SLOT 11
-#define R_390_RELATIVE 12
-#define R_390_GOTOFF32 13
-#define R_390_GOTPC 14
-#define R_390_GOT16 15
-#define R_390_PC16 16
-#define R_390_PC16DBL 17
-#define R_390_PLT16DBL 18
-#define R_390_PC32DBL 19
-#define R_390_PLT32DBL 20
-#define R_390_GOTPCDBL 21
-#define R_390_64 22
-#define R_390_PC64 23
-#define R_390_GOT64 24
-#define R_390_PLT64 25
-#define R_390_GOTENT 26
-#define R_390_GOTOFF16 27
-#define R_390_GOTOFF64 28
-#define R_390_GOTPLT12 29
-#define R_390_GOTPLT16 30
-#define R_390_GOTPLT32 31
-#define R_390_GOTPLT64 32
-#define R_390_GOTPLTENT 33
-#define R_390_PLTOFF16 34
-#define R_390_PLTOFF32 35
-#define R_390_PLTOFF64 36
-#define R_390_TLS_LOAD 37
-#define R_390_TLS_GDCALL 38
-
-#define R_390_TLS_LDCALL 39
-
-#define R_390_TLS_GD32 40
-
-#define R_390_TLS_GD64 41
-
-#define R_390_TLS_GOTIE12 42
-
-#define R_390_TLS_GOTIE32 43
-
-#define R_390_TLS_GOTIE64 44
-
-#define R_390_TLS_LDM32 45
-
-#define R_390_TLS_LDM64 46
-
-#define R_390_TLS_IE32 47
-
-#define R_390_TLS_IE64 48
-
-#define R_390_TLS_IEENT 49
-
-#define R_390_TLS_LE32 50
-
-#define R_390_TLS_LE64 51
-
-#define R_390_TLS_LDO32 52
-
-#define R_390_TLS_LDO64 53
-
-#define R_390_TLS_DTPMOD 54
-#define R_390_TLS_DTPOFF 55
-#define R_390_TLS_TPOFF 56
-
-#define R_390_20 57
-#define R_390_GOT20 58
-#define R_390_GOTPLT20 59
-#define R_390_TLS_GOTIE20 60
-
-#define R_390_NUM 61
-
-#define R_CRIS_NONE 0
-#define R_CRIS_8 1
-#define R_CRIS_16 2
-#define R_CRIS_32 3
-#define R_CRIS_8_PCREL 4
-#define R_CRIS_16_PCREL 5
-#define R_CRIS_32_PCREL 6
-#define R_CRIS_GNU_VTINHERIT 7
-#define R_CRIS_GNU_VTENTRY 8
-#define R_CRIS_COPY 9
-#define R_CRIS_GLOB_DAT 10
-#define R_CRIS_JUMP_SLOT 11
-#define R_CRIS_RELATIVE 12
-#define R_CRIS_16_GOT 13
-#define R_CRIS_32_GOT 14
-#define R_CRIS_16_GOTPLT 15
-#define R_CRIS_32_GOTPLT 16
-#define R_CRIS_32_GOTREL 17
-#define R_CRIS_32_PLT_GOTREL 18
-#define R_CRIS_32_PLT_PCREL 19
-
-#define R_CRIS_NUM 20
-
-#define R_X86_64_NONE 0
-#define R_X86_64_64 1
-#define R_X86_64_PC32 2
-#define R_X86_64_GOT32 3
-#define R_X86_64_PLT32 4
-#define R_X86_64_COPY 5
-#define R_X86_64_GLOB_DAT 6
-#define R_X86_64_JUMP_SLOT 7
-#define R_X86_64_RELATIVE 8
-#define R_X86_64_GOTPCREL 9
-
-#define R_X86_64_32 10
-#define R_X86_64_32S 11
-#define R_X86_64_16 12
-#define R_X86_64_PC16 13
-#define R_X86_64_8 14
-#define R_X86_64_PC8 15
-#define R_X86_64_DTPMOD64 16
-#define R_X86_64_DTPOFF64 17
-#define R_X86_64_TPOFF64 18
-#define R_X86_64_TLSGD 19
-
-#define R_X86_64_TLSLD 20
-
-#define R_X86_64_DTPOFF32 21
-#define R_X86_64_GOTTPOFF 22
-
-#define R_X86_64_TPOFF32 23
-#define R_X86_64_PC64 24
-#define R_X86_64_GOTOFF64 25
-#define R_X86_64_GOTPC32 26
-#define R_X86_64_GOT64 27
-#define R_X86_64_GOTPCREL64 28
-#define R_X86_64_GOTPC64 29
-#define R_X86_64_GOTPLT64 30
-#define R_X86_64_PLTOFF64 31
-#define R_X86_64_SIZE32 32
-#define R_X86_64_SIZE64 33
-
-#define R_X86_64_GOTPC32_TLSDESC 34
-#define R_X86_64_TLSDESC_CALL 35
-
-#define R_X86_64_TLSDESC 36
-#define R_X86_64_IRELATIVE 37
-#define R_X86_64_RELATIVE64 38
-#define R_X86_64_GOTPCRELX 41
-#define R_X86_64_REX_GOTPCRELX 42
-#define R_X86_64_NUM 43
-
-#define R_MN10300_NONE 0
-#define R_MN10300_32 1
-#define R_MN10300_16 2
-#define R_MN10300_8 3
-#define R_MN10300_PCREL32 4
-#define R_MN10300_PCREL16 5
-#define R_MN10300_PCREL8 6
-#define R_MN10300_GNU_VTINHERIT 7
-#define R_MN10300_GNU_VTENTRY 8
-#define R_MN10300_24 9
-#define R_MN10300_GOTPC32 10
-#define R_MN10300_GOTPC16 11
-#define R_MN10300_GOTOFF32 12
-#define R_MN10300_GOTOFF24 13
-#define R_MN10300_GOTOFF16 14
-#define R_MN10300_PLT32 15
-#define R_MN10300_PLT16 16
-#define R_MN10300_GOT32 17
-#define R_MN10300_GOT24 18
-#define R_MN10300_GOT16 19
-#define R_MN10300_COPY 20
-#define R_MN10300_GLOB_DAT 21
-#define R_MN10300_JMP_SLOT 22
-#define R_MN10300_RELATIVE 23
-
-#define R_MN10300_NUM 24
-
-#define R_M32R_NONE 0
-#define R_M32R_16 1
-#define R_M32R_32 2
-#define R_M32R_24 3
-#define R_M32R_10_PCREL 4
-#define R_M32R_18_PCREL 5
-#define R_M32R_26_PCREL 6
-#define R_M32R_HI16_ULO 7
-#define R_M32R_HI16_SLO 8
-#define R_M32R_LO16 9
-#define R_M32R_SDA16 10
-#define R_M32R_GNU_VTINHERIT 11
-#define R_M32R_GNU_VTENTRY 12
-
-#define R_M32R_16_RELA 33
-#define R_M32R_32_RELA 34
-#define R_M32R_24_RELA 35
-#define R_M32R_10_PCREL_RELA 36
-#define R_M32R_18_PCREL_RELA 37
-#define R_M32R_26_PCREL_RELA 38
-#define R_M32R_HI16_ULO_RELA 39
-#define R_M32R_HI16_SLO_RELA 40
-#define R_M32R_LO16_RELA 41
-#define R_M32R_SDA16_RELA 42
-#define R_M32R_RELA_GNU_VTINHERIT 43
-#define R_M32R_RELA_GNU_VTENTRY 44
-#define R_M32R_REL32 45
-
-#define R_M32R_GOT24 48
-#define R_M32R_26_PLTREL 49
-#define R_M32R_COPY 50
-#define R_M32R_GLOB_DAT 51
-#define R_M32R_JMP_SLOT 52
-#define R_M32R_RELATIVE 53
-#define R_M32R_GOTOFF 54
-#define R_M32R_GOTPC24 55
-#define R_M32R_GOT16_HI_ULO 56
-
-#define R_M32R_GOT16_HI_SLO 57
-
-#define R_M32R_GOT16_LO 58
-#define R_M32R_GOTPC_HI_ULO 59
-
-#define R_M32R_GOTPC_HI_SLO 60
-
-#define R_M32R_GOTPC_LO 61
-
-#define R_M32R_GOTOFF_HI_ULO 62
-
-#define R_M32R_GOTOFF_HI_SLO 63
-
-#define R_M32R_GOTOFF_LO 64
-#define R_M32R_NUM 256
-
-#define R_MICROBLAZE_NONE 0
-#define R_MICROBLAZE_32 1
-#define R_MICROBLAZE_32_PCREL 2
-#define R_MICROBLAZE_64_PCREL 3
-#define R_MICROBLAZE_32_PCREL_LO 4
-#define R_MICROBLAZE_64 5
-#define R_MICROBLAZE_32_LO 6
-#define R_MICROBLAZE_SRO32 7
-#define R_MICROBLAZE_SRW32 8
-#define R_MICROBLAZE_64_NONE 9
-#define R_MICROBLAZE_32_SYM_OP_SYM 10
-#define R_MICROBLAZE_GNU_VTINHERIT 11
-#define R_MICROBLAZE_GNU_VTENTRY 12
-#define R_MICROBLAZE_GOTPC_64 13
-#define R_MICROBLAZE_GOT_64 14
-#define R_MICROBLAZE_PLT_64 15
-#define R_MICROBLAZE_REL 16
-#define R_MICROBLAZE_JUMP_SLOT 17
-#define R_MICROBLAZE_GLOB_DAT 18
-#define R_MICROBLAZE_GOTOFF_64 19
-#define R_MICROBLAZE_GOTOFF_32 20
-#define R_MICROBLAZE_COPY 21
-#define R_MICROBLAZE_TLS 22
-#define R_MICROBLAZE_TLSGD 23
-#define R_MICROBLAZE_TLSLD 24
-#define R_MICROBLAZE_TLSDTPMOD32 25
-#define R_MICROBLAZE_TLSDTPREL32 26
-#define R_MICROBLAZE_TLSDTPREL64 27
-#define R_MICROBLAZE_TLSGOTTPREL32 28
-#define R_MICROBLAZE_TLSTPREL32 29
-
-#define DT_NIOS2_GP 0x70000002
-
-#define R_NIOS2_NONE 0
-#define R_NIOS2_S16 1
-#define R_NIOS2_U16 2
-#define R_NIOS2_PCREL16 3
-#define R_NIOS2_CALL26 4
-#define R_NIOS2_IMM5 5
-#define R_NIOS2_CACHE_OPX 6
-#define R_NIOS2_IMM6 7
-#define R_NIOS2_IMM8 8
-#define R_NIOS2_HI16 9
-#define R_NIOS2_LO16 10
-#define R_NIOS2_HIADJ16 11
-#define R_NIOS2_BFD_RELOC_32 12
-#define R_NIOS2_BFD_RELOC_16 13
-#define R_NIOS2_BFD_RELOC_8 14
-#define R_NIOS2_GPREL 15
-#define R_NIOS2_GNU_VTINHERIT 16
-#define R_NIOS2_GNU_VTENTRY 17
-#define R_NIOS2_UJMP 18
-#define R_NIOS2_CJMP 19
-#define R_NIOS2_CALLR 20
-#define R_NIOS2_ALIGN 21
-#define R_NIOS2_GOT16 22
-#define R_NIOS2_CALL16 23
-#define R_NIOS2_GOTOFF_LO 24
-#define R_NIOS2_GOTOFF_HA 25
-#define R_NIOS2_PCREL_LO 26
-#define R_NIOS2_PCREL_HA 27
-#define R_NIOS2_TLS_GD16 28
-#define R_NIOS2_TLS_LDM16 29
-#define R_NIOS2_TLS_LDO16 30
-#define R_NIOS2_TLS_IE16 31
-#define R_NIOS2_TLS_LE16 32
-#define R_NIOS2_TLS_DTPMOD 33
-#define R_NIOS2_TLS_DTPREL 34
-#define R_NIOS2_TLS_TPREL 35
-#define R_NIOS2_COPY 36
-#define R_NIOS2_GLOB_DAT 37
-#define R_NIOS2_JUMP_SLOT 38
-#define R_NIOS2_RELATIVE 39
-#define R_NIOS2_GOTOFF 40
-#define R_NIOS2_CALL26_NOAT 41
-#define R_NIOS2_GOT_LO 42
-#define R_NIOS2_GOT_HA 43
-#define R_NIOS2_CALL_LO 44
-#define R_NIOS2_CALL_HA 45
-
-#define R_OR1K_NONE 0
-#define R_OR1K_32 1
-#define R_OR1K_16 2
-#define R_OR1K_8 3
-#define R_OR1K_LO_16_IN_INSN 4
-#define R_OR1K_HI_16_IN_INSN 5
-#define R_OR1K_INSN_REL_26 6
-#define R_OR1K_GNU_VTENTRY 7
-#define R_OR1K_GNU_VTINHERIT 8
-#define R_OR1K_32_PCREL 9
-#define R_OR1K_16_PCREL 10
-#define R_OR1K_8_PCREL 11
-#define R_OR1K_GOTPC_HI16 12
-#define R_OR1K_GOTPC_LO16 13
-#define R_OR1K_GOT16 14
-#define R_OR1K_PLT26 15
-#define R_OR1K_GOTOFF_HI16 16
-#define R_OR1K_GOTOFF_LO16 17
-#define R_OR1K_COPY 18
-#define R_OR1K_GLOB_DAT 19
-#define R_OR1K_JMP_SLOT 20
-#define R_OR1K_RELATIVE 21
-#define R_OR1K_TLS_GD_HI16 22
-#define R_OR1K_TLS_GD_LO16 23
-#define R_OR1K_TLS_LDM_HI16 24
-#define R_OR1K_TLS_LDM_LO16 25
-#define R_OR1K_TLS_LDO_HI16 26
-#define R_OR1K_TLS_LDO_LO16 27
-#define R_OR1K_TLS_IE_HI16 28
-#define R_OR1K_TLS_IE_LO16 29
-#define R_OR1K_TLS_LE_HI16 30
-#define R_OR1K_TLS_LE_LO16 31
-#define R_OR1K_TLS_TPOFF 32
-#define R_OR1K_TLS_DTPOFF 33
-#define R_OR1K_TLS_DTPMOD 34
-
-#define R_BPF_NONE 0
-#define R_BPF_MAP_FD 1
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
### core/embed/io/app_loader/inc/io/app_cache.h
@@ -1,128 +0,0 @@
-/*
- * This file is part of the Trezor project, https://trezor.io/
- *
- * Copyright (c) SatoshiLabs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include <trezor_types.h>
-
-#include <sys/systask.h>
-
-// 32-byte application hash serving as application identifier
-typedef struct {
- uint8_t bytes[32];
-} app_hash_t;
-
-/** Handle to an application image in the cache */
-typedef uintptr_t app_cache_handle_t;
-
-/** Invalid handle value indicating failure or uninitialized state */
-#define APP_CACHE_INVALID_HANDLE ((app_cache_handle_t)0)
-
-#ifdef KERNEL_MODE
-
-/**
- * Initializes the app cache subsystem.
- *
- * @return TS_OK on success, error code on failure.
- */
-ts_t __wur app_cache_init(void);
-
-#endif
-
-/**
- * Allocates a space for an application image and returns a handle to it.
- *
- * Caller is responsible for writing the application image data
- * using `app_cache_write_image()` and unlocking the image when done using
- * `app_cache_unlock_image()`.
- *
- * @param hash The application image hash.
- * @param size The size of the application image to create.
- *
- * @return A handle to the allocated application image, or
- * APP_CACHE_INVALID_HANDLE on failure.
- */
-app_cache_handle_t app_cache_create_image(const app_hash_t* hash, size_t size);
-
-/**
- * Writes application image data to the allocated space.
- *
- * app_image_write() fails if the app image was verified and is now read-only.
- *
- * @param handle The application image handle.
- * @param offset The offset within the application image to write to.
- * @param data Pointer to the data to write.
- * @param size The size of the data to write.
- *
- * @return TS_OK on success, error code on failure.
- */
-ts_t __wur app_cache_write_image(app_cache_handle_t handle, uintptr_t offset,
- const void* data, size_t size);
-
-/**
- * Finalizes loading of the application image. If `accept` is true,
- * the image is marked as loaded and will be available for execution.
- * If `accept` is false, the image is discarded.
- *
- * @param handle The application image handle.
- * @param accept If true, the image is marked as loaded; if false,
- * the image is discarded.
- * @return TS_OK on success, error code on failure.
- */
-ts_t __wur app_cache_finalize_image(app_cache_handle_t handle, bool accept);
-
-#ifdef KERNEL_MODE
-
-/**
- * Locks the application image in memory for access.
- *
- * @param hash The application image hash.
- * @param ptr Pointer to store the address of the application image.
- * @param size Pointer to store the size of the application image.
- *
- * @return A handle to the locked application image.
- */
-
-app_cache_handle_t app_cache_lock_image(const app_hash_t* hash, void** ptr,
- size_t* size);
-
-/**
- * Unlocks the application image previously locked with `app_cache_lock()`.
- *
- * @param handle The application image handle.
- */
-void app_cache_unlock_image(app_cache_handle_t handle);
-
-#endif // KERNEL_MODE
-
-#ifdef TREZOR_EMULATOR
-
-/**
- * Loads an application image from a file into the app cache.
- *
- * This function is only available in the emulator build.
- *
- * @param hash The application hash.
- * @param filename The path to the file containing the application image.
- *
- * @return TS_OK on success, error code on failure.
- */
-ts_t __wur app_cache_load_file(const app_hash_t* hash, const char* filename);
-
-#endif // TREZOR_EMULATOR
### core/embed/io/app_loader/inc/io/app_loader.h
@@ -1,78 +0,0 @@
-/*
- * This file is part of the Trezor project, https://trezor.io/
- *
- * Copyright (c) SatoshiLabs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#pragma once
-
-#include <trezor_types.h>
-
-#include <sys/systask.h>
-
-#include <io/app_cache.h>
-
-#ifdef KERNEL_MODE
-
-/**
- * Initializes the app loader module.
- *
- * @return TS_OK on success, or an error code on failure.
- */
-ts_t __wur app_loader_init(void);
-
-#endif
-
-/**
- * Spawns an external application with the given application ID.
- *
- * @param hash Pointer to the application hash.
- * @param task_id Pointer to store the spawned application's task ID.
- *
- * @return TS_OK on success, or an error code on failure:
- * TS_ENOENT if image not found, or an pother error
- * TS_ENOMEM if there is not enough memory
- * TS_EINVAL if the application image is invalid
- */
-ts_t __wur app_task_spawn(const app_hash_t* hash, systask_id_t* task_id);
-
-/**
- * Checks if an application is currently running.
- */
-bool app_task_is_running(systask_id_t task_id);
-
-/**
- * Retrieves postmortem information for a terminated application.
- *
- * If the application is still running, the info structure will be invalid.
- *
- * @param task_id The system task identifier of the application.
- * @param info Pointer to a structure to receive postmortem information.
- * @return TS_OK on success, or an error code on failure.
- */
-ts_t __wur app_task_get_pminfo(systask_id_t task_id,
- systask_postmortem_t* pminfo);
-
-/**
- * Unloads an application and frees all associated resources.
- *
- * When an application is unloaded the task_id becomes invalid and
- * cannot be used in subsequent calls to app_task_is_running() or other
- * functions.
- *
- * @param task_id The system task identifier of the application to unload.
- */
-void app_task_unload(systask_id_t task_id);
### core/embed/io/app_loader/stm32/elf_loader.c
@@ -1,442 +0,0 @@
-/*
- * This file is part of the Trezor project, https://trezor.io/
- *
- * Copyright (c) SatoshiLabs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#if PRODUCTION
-// We should rather replace this implementation with a Rust one in production
-#error DO NOT SHIP THIS FILE
-#endif
-
-#ifdef KERNEL_MODE
-
-#include <trezor_model.h>
-#include <trezor_rtl.h>
-
-#include <io/elf_loader.h>
-#include <sec/image.h>
-#include <sys/applet.h>
-#include <sys/coreapp.h>
-#include <sys/logging.h>
-#include <sys/mpu.h>
-
-#include "../app_arena.h"
-#include "elf.h"
-
-LOG_DECLARE(elf_loader)
-
-// Alignment required for MPU regions
-#define MPU_ALIGNMENT 32
-
-static const Elf32_Phdr* elf_get_phdr(const Elf32_Ehdr* ehdr, uint32_t index) {
- if (index >= ehdr->e_phnum) {
- return NULL;
- }
- return (Elf32_Phdr*)((uintptr_t)ehdr + ehdr->e_phoff +
- index * ehdr->e_phentsize);
-}
-
-static const Elf32_Shdr* elf_get_shdr(const Elf32_Ehdr* ehdr, uint32_t index) {
- if (index >= ehdr->e_shnum) {
- return NULL;
- }
- return (Elf32_Shdr*)((uintptr_t)ehdr + ehdr->e_shoff +
- index * ehdr->e_shentsize);
-}
-
-static const Elf32_Ehdr* elf_read_header(const void* elf, size_t elf_size) {
- if (elf_size < sizeof(Elf32_Ehdr)) {
- return NULL;
- }
-
- const Elf32_Ehdr* ehdr = (const Elf32_Ehdr*)elf;
-
- if (ehdr->e_ident[EI_MAG0] != ELFMAG0 || ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
- ehdr->e_ident[EI_MAG2] != ELFMAG2 || ehdr->e_ident[EI_MAG3] != ELFMAG3) {
- return NULL;
- }
-
- if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) {
- return NULL;
- }
-
- if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB) {
- return NULL;
- }
-
- if (ehdr->e_ident[EI_VERSION] != EV_CURRENT) {
- return NULL;
- }
-
- if (ehdr->e_type != ET_EXEC) {
- return NULL;
- }
-
- if (ehdr->e_machine != EM_ARM) {
- return NULL;
- }
-
- if (ehdr->e_version != EV_CURRENT) {
- return NULL;
- }
-
- if (ehdr->e_phoff >= elf_size || ehdr->e_phentsize != sizeof(Elf32_Phdr) ||
- ehdr->e_phnum > 32 ||
- ehdr->e_phoff + ehdr->e_phentsize * ehdr->e_phnum > elf_size) {
- return NULL;
- }
-
- if (ehdr->e_shoff >= elf_size || ehdr->e_shentsize != sizeof(Elf32_Shdr) ||
- ehdr->e_shnum > 32 ||
- ehdr->e_shoff + ehdr->e_shentsize * ehdr->e_shnum > elf_size) {
- return NULL;
- }
-
- if (ehdr->e_shstrndx >= ehdr->e_shnum) {
- return NULL;
- }
-
- if ((ehdr->e_flags & EF_ARM_ABI_FLOAT_HARD) == 0) {
- return NULL;
- }
-
- // Check all section references part of elf file
- for (int i = 0; i < ehdr->e_shnum; ++i) {
- const Elf32_Shdr* shdr = elf_get_shdr(ehdr, i);
- if (shdr->sh_type != SHT_NOBITS &&
- (shdr->sh_offset >= elf_size ||
- shdr->sh_size > elf_size - shdr->sh_offset)) {
- return NULL;
- }
- }
-
- return ehdr;
-}
-
-#define IS_RW_SEGMENT(phdr) \
- ((phdr)->p_type == PT_LOAD && \
- ((phdr)->p_flags & (PF_R | PF_W)) == (PF_R | PF_W))
-
-#define IS_RO_SEGMENT(phdr) \
- ((phdr)->p_type == PT_LOAD && \
- ((phdr)->p_flags & (PF_R | PF_X)) == (PF_R | PF_X))
-
-#define IS_IN_FILE_LIMIT(phdr, elf_size) \
- ((phdr)->p_offset < elf_size && \
- (phdr)->p_offset + (phdr)->p_filesz <= elf_size && \
- (phdr)->p_filesz <= (phdr)->p_memsz)
-
-static const char* elf_get_shdr_name(const Elf32_Ehdr* ehdr,
- const Elf32_Shdr* shdr) {
- const Elf32_Shdr* shstrtab = elf_get_shdr(ehdr, ehdr->e_shstrndx);
-
- const char* strings = (const char*)ehdr + shstrtab->sh_offset;
- // Ensure the name offset is within bounds
- if (shdr->sh_name >= shstrtab->sh_size) {
- return NULL;
- }
-
- const char* name = strings + shdr->sh_name;
-
- // Ensure the name is null-terminated and within bounds
- size_t remaining_bytes = (strings + shstrtab->sh_size) - name;
- if (strnlen(name, remaining_bytes) >= remaining_bytes) {
- return NULL;
- }
-
- return name;
-}
-
-static const Elf32_Phdr* elf_read_rw_phdr(const Elf32_Ehdr* ehdr,
- size_t elf_size) {
- const Elf32_Phdr* rw_phdr = NULL;
-
- // Parse program headers, find RO, RW segments
- for (int i = 0; i < ehdr->e_phnum; i++) {
- const Elf32_Phdr* phdr = elf_get_phdr(ehdr, i);
- if (IS_RW_SEGMENT(phdr)) {
- if (rw_phdr != NULL || !IS_IN_FILE_LIMIT(phdr, elf_size)) {
- // Multiple RW segments or invalid segment
- return NULL;
- }
- rw_phdr = phdr;
- }
- }
-
- // Check if the RW segment is present
- if (rw_phdr == NULL) {
- return NULL;
- }
-
- // Check if RO segment size is within elf file
- if (rw_phdr->p_memsz < rw_phdr->p_filesz) {
- return NULL;
- }
-
- return rw_phdr;
-}
-
-static const Elf32_Phdr* elf_read_ro_phdr(const Elf32_Ehdr* ehdr,
- size_t elf_size) {
- const Elf32_Phdr* ro_phdr = NULL;
-
- // Parse program headers, search for RO segment
- for (int i = 0; i < ehdr->e_phnum; i++) {
- const Elf32_Phdr* phdr = elf_get_phdr(ehdr, i);
- if (IS_RO_SEGMENT(phdr)) {
- if (ro_phdr != NULL || !IS_IN_FILE_LIMIT(phdr, elf_size)) {
- // Multiple RO segments or invalid segment
- return NULL;
- }
- ro_phdr = phdr;
- }
- }
-
- // Check if the RO segment is present
- if (ro_phdr == NULL) {
- return NULL;
- }
-
- // Check if RO segment size is within elf file
- if (ro_phdr->p_memsz < ro_phdr->p_filesz) {
- return NULL;
- }
-
- // Check if RO segment is aligned properly
- if (!IS_ALIGNED((uint32_t)ehdr + ro_phdr->p_offset, MPU_ALIGNMENT)) {
- return NULL;
- }
-
- return ro_phdr;
-}
-
-typedef struct {
- uint32_t ro_size;
- uint32_t ro_v_addr;
- uint32_t ro_p_addr;
-
- uint32_t rw_size;
- uint32_t rw_v_addr;
- uint32_t rw_p_addr;
-} va_mapping_t;
-
-static Elf32_Addr map_va(va_mapping_t* map, Elf32_Addr va) {
- if (va >= map->ro_v_addr && va <= map->ro_v_addr + map->ro_size) {
- return map->ro_p_addr + (va - map->ro_v_addr);
- } else if (va >= map->rw_v_addr && va <= map->rw_v_addr + map->rw_size) {
- return map->rw_p_addr + (va - map->rw_v_addr);
- }
- return 0;
-}
-
-static ts_t relocate_section(const Elf32_Ehdr* ehdr, const Elf32_Shdr* shdr,
- va_mapping_t* map) {
- TSH_DECLARE;
-
- const Elf32_Rel* rel = (Elf32_Rel*)((uint32_t)ehdr + shdr->sh_offset);
- const Elf32_Rel* rel_end = (Elf32_Rel*)((uint32_t)rel + shdr->sh_size);
-
- // Get section we are relocating
- const Elf32_Shdr* target_shdr = elf_get_shdr(ehdr, shdr->sh_info);
-
- TSH_CHECK(target_shdr != NULL, TS_EINVAL);
-
- // Get target section boundaries
- uint32_t target_start = map_va(map, target_shdr->sh_addr);
- uint32_t target_end = target_start + target_shdr->sh_size;
-
- while (rel < rel_end) {
- // Is relocation type supported?
- TSH_CHECK(ELF32_R_TYPE(rel->r_info) == R_ARM_ABS32, TS_EINVAL);
-
- // Get pointer to the relocated 32-bit word
- uint32_t* mem_ptr = (uint32_t*)map_va(map, rel->r_offset);
- TSH_CHECK(mem_ptr != NULL, TS_EINVAL);
-
- // Ensure the pointer is within the target section
- TSH_CHECK((uint32_t)mem_ptr >= target_start, TS_EINVAL);
- TSH_CHECK((uint32_t)mem_ptr + 4 <= target_end, TS_EINVAL);
-
- // Relocate the 32-bit word
- *mem_ptr = map_va(map, *mem_ptr);
-
- ++rel;
- }
-
-cleanup:
- TSH_RETURN;
-}
-
-static void get_stack_info(const Elf32_Ehdr* ehdr, uint32_t* stack_base,
- uint32_t* stack_size) {
- for (int i = 0; i < ehdr->e_shnum; i++) {
- const Elf32_Shdr* shdr = elf_get_shdr(ehdr, i);
- const char* section_name = elf_get_shdr_name(ehdr, shdr);
- if (section_name != NULL && strcmp(section_name, ".stack") == 0) {
- *stack_base = shdr->sh_addr;
- *stack_size = shdr->sh_size;
- break;
- }
- }
-}
-
-static void elf_unload_cb(applet_t* applet) {
- void* ram_start = (void*)applet->layout.data1.start;
- size_t ram_size = applet->layout.data1.size;
-
- if (ram_start != NULL && ram_size > 0) {
- // Clear applet data segment
- mpu_set_active_applet(&applet->layout);
- memset(ram_start, 0, ram_size);
- // Recover MPU state for the active task
- systask_set_mpu(systask_active());
-
- // Free applet RAM
- app_arena_free(ram_start);
- }
-}
-
-ts_t elf_load(applet_t* applet, const void* elf_ptr, size_t elf_size) {
- TSH_DECLARE;
- ts_t status;
-
- void* ram_ptr = NULL;
- size_t ram_size = 0;
-
- applet_init(applet, NULL, NULL);
-
- // Make sure the entire ELF file is accessible
- // (temporarily map it as data)
- const applet_layout_t temp_layout_1 = {
- .data1 = {.start = (uintptr_t)elf_ptr, .size = elf_size},
- };
- mpu_set_active_applet(&temp_layout_1);
-
- // Read and validate ELF header
- const Elf32_Ehdr* ehdr = elf_read_header(elf_ptr, elf_size);
- TSH_CHECK(ehdr != NULL, TS_EINVAL);
-
- // Read and validate RO segment
- const Elf32_Phdr* ro_phdr = elf_read_ro_phdr(ehdr, elf_size);
- TSH_CHECK(ro_phdr != NULL, TS_EINVAL);
-
- // Read and validate RW segment
- const Elf32_Phdr* rw_phdr = elf_read_rw_phdr(ehdr, elf_size);
- TSH_CHECK(rw_phdr != NULL, TS_EINVAL);
-
- // Allocate RAM for RW segment
- ram_size = ALIGN_UP(rw_phdr->p_memsz, MPU_ALIGNMENT);
- ram_ptr = app_arena_alloc(ram_size, APP_ALLOC_DATA);
- TSH_CHECK(ram_ptr != NULL, TS_ENOMEM);
-
- // Make sure ELF and allocated RAM are accessible
- // (temporarily map it as data => we can apply relocation fixups)
- const applet_layout_t temp_layout_2 = {
- .data1 = {.start = (uintptr_t)elf_ptr, .size = elf_size},
- .data2 = {.start = (uintptr_t)ram_ptr, .size = ram_size},
- };
- mpu_set_active_applet(&temp_layout_2);
-
- // Clear the allocated RAM
- memset(ram_ptr, 0, ram_size);
-
- // Copy initialized data
- memcpy(ram_ptr, (uint8_t*)elf_ptr + rw_phdr->p_offset, rw_phdr->p_filesz);
-
- // Prepare VA -> PA mapping
- va_mapping_t map = {
- .ro_size = ro_phdr->p_memsz,
- .ro_v_addr = ro_phdr->p_vaddr,
- .ro_p_addr = (uintptr_t)elf_ptr + ro_phdr->p_offset,
- .rw_size = rw_phdr->p_memsz,
- .rw_v_addr = rw_phdr->p_vaddr,
- .rw_p_addr = (uintptr_t)ram_ptr,
- };
-
- // Apply relocation fixups
- for (int i = 0; i < ehdr->e_shnum; i++) {
- const Elf32_Shdr* shdr = elf_get_shdr(ehdr, i);
- if (shdr->sh_type == SHT_REL) {
- status = relocate_section(ehdr, shdr, &map);
- TSH_CHECK_OK(status);
- }
- }
-
- // Get stack address and size
- uint32_t stack_base = 0;
- uint32_t stack_size = 0;
- get_stack_info(ehdr, &stack_base, &stack_size);
- stack_base = map_va(&map, stack_base);
- TSH_CHECK(stack_base != 0 && stack_size > 0, TS_EINVAL);
-
- // Get static base address
- uint32_t sb_addr = (uintptr_t)ram_ptr;
-
- // Get entrypoint address
- uint32_t entrypoint = map_va(&map, ehdr->e_entry);
-
- // Initialize applet privileges
- applet_privileges_t app_privileges = {0};
-
- applet_init(applet, &app_privileges, elf_unload_cb);
-
- applet->layout = (applet_layout_t){
- .code1.start = (uintptr_t)ehdr + ro_phdr->p_offset,
- .code1.size = ro_phdr->p_memsz,
- .data1.start = (uintptr_t)ram_ptr,
- .data1.size = ram_size,
- .code2 = coreapp_get_code_area(), // app needs access to coreapp code
- .tls = coreapp_get_tls_area(), // app needs access to coreapp TLS
- };
-
- ram_ptr = NULL; // ownership transferred to applet
-
- // Enable access to applet memory regions
- mpu_set_active_applet(&applet->layout);
-
- // Initialize the applet task
- bool ok =
- systask_init(&applet->task, stack_base, stack_size, sb_addr, applet);
- TSH_CHECK(ok, TS_ENOMEM);
-
- // Enable coreapp TLS area swapping
- systask_enable_tls(&applet->task, coreapp_get_tls_area());
-
- uint32_t api_getter = (uint32_t)coreapp_get_api_getter();
-
- // Prepare the applet to run - push exception frame on the stack
- // with the entrypoint address
- ok = systask_push_call(&applet->task, (void*)entrypoint, api_getter, 0, 0);
- TSH_CHECK(ok, TS_ENOMEM);
-
- // Recover MPU state for the active task
- systask_set_mpu(systask_active());
-
- TSH_RETURN;
-
-cleanup:
-
- app_arena_free(ram_ptr);
- applet_unload(applet);
-
- // Recover MPU state for the active task
- systask_set_mpu(systask_active());
-
- TSH_RETURN;
-}
-
-#endif // KERNEL_MODE
### core/embed/io/app_loader/unix/elf_loader.c
@@ -1,94 +0,0 @@
-/*
- * This file is part of the Trezor project, https://trezor.io/
- *
- * Copyright (c) SatoshiLabs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <trezor_rtl.h>
-
-#include <io/elf_loader.h>
-#include <sys/coreapp.h>
-#include <sys/logging.h>
-
-#include <dlfcn.h>
-#include <unistd.h>
-
-LOG_DECLARE(elf_loader)
-
-static void elf_applet_unload(applet_t* applet) {
- if (applet->handle != NULL) {
- // Unload dynamic library
- dlclose(applet->handle);
- }
-}
-
-ts_t write_to_file(const char* filename, const void* elf_ptr, size_t elf_size) {
- TSH_DECLARE;
-
- FILE* f = fopen(filename, "wb");
- TSH_CHECK(f != NULL, TS_EIO);
-
- size_t rc = fwrite(elf_ptr, 1, elf_size, f);
- TSH_CHECK(rc == elf_size, TS_EIO);
-
-cleanup:
- if (f != NULL) {
- fclose(f);
- }
-
- TSH_RETURN;
-}
-
-ts_t elf_load(applet_t* applet, const void* elf_ptr, size_t elf_size) {
- TSH_DECLARE;
- ts_t status;
-
- applet_privileges_t privileges = {0};
-
- applet_init(applet, &privileges, elf_applet_unload);
-
- const char* filename = "/tmp/trezor_ext_app.so";
-
- // Copy the image to the temporary file that will be
- // unlinked just after it's loaded
- status = write_to_file(filename, elf_ptr, elf_size);
- TSH_CHECK_OK(status);
-
- applet->handle = dlopen(filename, RTLD_NOW);
- unlink(filename);
- if (applet->handle == NULL) {
- LOG_ERR("dlopen failed: %s", dlerror());
- }
- TSH_CHECK(applet->handle != NULL, TS_EINVAL);
-
- void* entrypoint = dlsym(applet->handle, "applet_main");
- TSH_CHECK(entrypoint != NULL, TS_EINVAL);
-
- bool ok = systask_init(&applet->task, 0, 0, 0, applet);
- TSH_CHECK(ok, TS_ENOMEM);
-
- uintptr_t api_getter = (uintptr_t)coreapp_get_api_getter();
-
- ok = systask_push_call(&applet->task, entrypoint, api_getter, 0, 0);
- TSH_CHECK(ok, TS_ENOMEM);
-
- TSH_RETURN;
-
-cleanup:
- applet_unload(applet);
-
- TSH_RETURN;
-}
### core/embed/io/build.rs
@@ -1,7 +1,7 @@
use xbuild::{Result, build_mods};
-#[path = "app_loader/build.rs"]
-mod app_loader;
+#[path = "app_arena/build.rs"]
+mod app_arena;
#[path = "backlight/build.rs"]
mod backlight;
#[path = "ble/build.rs"]
@@ -46,7 +46,7 @@ fn main() -> Result<()> {
build_mods!(
lib,
[
- app_loader if cfg!(feature = "app_loading"),
+ app_arena if cfg!(feature = "app_loading"),
backlight if cfg!(feature = "backlight"),
ble if cfg!(feature = "ble"),
button if cfg!(feature = "button"),
### core/embed/models/build.rs
@@ -163,6 +163,11 @@ fn main() -> Result<()> {
lib.add_define("TREZOR_EMULATOR", None);
}
+ if cfg!(not(any(feature = "kernel_mode", feature = "emulator"))) {
+ // Support for multiple unprivileged tasks
+ lib.add_define("THREAD_LOCAL", Some("__attribute__((section(\".tls\")))"));
+ }
+
if cfg!(feature = "model_t2t1") {
define_model_t2t1(lib, &board_header)?;
} else if cfg!(feature = "model_t2b1") {
### core/embed/projects/kernel/main.c
@@ -38,8 +38,7 @@
#include <sys/systick.h>
#ifdef USE_APP_LOADING
-#include <io/app_cache.h>
-#include <io/app_loader.h>
+#include <io/app_arena.h>
#endif
#ifdef USE_BUTTON
@@ -228,11 +227,8 @@ void drivers_init() {
#endif
#ifdef USE_APP_LOADING
- status = app_cache_init();
- ensure_ok(status, "app_cache_init failed");
-
- status = app_loader_init();
- ensure_ok(status, "app_loader_init failed");
+ status = app_arena_init();
+ ensure_ok(status, "app_arena_init failed");
#endif
}
### core/embed/projects/secmon/project.toml
@@ -24,6 +24,7 @@ elf_sections = [".secmon_header", ".flash", ".data", ".gnu.sgstubs"]
# xtask build options mapped to the cargo features
[build-options]
+apps = { true = ["app_loading"] }
asan = { true = ["asan"] }
bootloader-devel = { true = ["bootloader_devel"] }
btc-only = { false = ["universal_fw"] }
### core/embed/projects/unix/main_main.c
@@ -39,8 +39,7 @@
#include <sys/systimer.h>
#ifdef USE_APP_LOADING
-#include <io/app_cache.h>
-#include <io/app_loader.h>
+#include <io/app_arena.h>
#endif
#ifdef USE_BUTTON
@@ -126,8 +125,7 @@ static void drivers_init(void) {
#endif
#ifdef USE_APP_LOADING
- app_cache_init();
- app_loader_init();
+ app_arena_init();
#endif
}
### core/embed/rtl/inc/rtl/crypto_helpers.h
@@ -21,20 +21,6 @@
#include <trezor_types.h>
-#include <sys/applet.h>
-
-/**
- * Loads an ELF image using the system dynamic loader.
- *
- * ELF file is expected to be loaded in SRAM in the block allocated
- * in app_arena memory (SRAM).
- *
- * @param applet Pointer to the applet_t structure to be initialized
- * @param elf_ptr Pointer to the pointer to the ELF image loaded in memory
- * @param elf_size Size of the ELF image in memory
- *
- * @return TS_OK on success, or an error code on failure:
- * TS_ENOMEM if there is not enough memory
- * TS_EINVAL if the ELF image is invalid
- */
-ts_t __wur elf_load(applet_t* applet, const void* elf_ptr, size_t elf_size);
+typedef struct {
+ uint8_t bytes[32];
+} sha256_digest_t;
### core/embed/rtl/inc/rtl/error_handling.h
@@ -234,6 +234,12 @@ void __attribute__((noreturn)) __fatal_error(const char *msg, const char *file,
return __status; \
} while (0)
+/**
+ * Retrieves the current status value that would return
+ * if `TSH_RETURN` is called.
+ */
+#define TSH_STATUS (__status)
+
/**
* Checks the status, if it indicates an error, set
* status variable and jumps to `cleanup` label.
### core/embed/sys/dbg/inc/sys/syslog_config.h
@@ -68,8 +68,8 @@
#define SYSLOG_ble_driver_MAX_LOG_LEVEL SYSLOG_DEFAULT_LOG_LEVEL
#endif
-#ifndef SYSLOG_elf_loader_MAX_LOG_LEVEL
-#define SYSLOG_elf_loader_MAX_LOG_LEVEL SYSLOG_DEFAULT_LOG_LEVEL
+#ifndef SYSLOG_app_loader_MAX_LOG_LEVEL
+#define SYSLOG_app_loader_MAX_LOG_LEVEL SYSLOG_DEFAULT_LOG_LEVEL
#endif
// Optiga command log is relatively quiet
### core/embed/sys/syscall/inc/sys/syscall_numbers.h
@@ -195,14 +195,23 @@ typedef enum {
SYSCALL_TROPIC_ECC_SIGN,
SYSCALL_TROPIC_DATA_READ,
- SYSCALL_APP_TASK_SPAWN,
- SYSCALL_APP_TASK_IS_RUNNING,
- SYSCALL_APP_TASK_GET_PMINFO,
- SYSCALL_APP_TASK_UNLOAD,
-
- SYSCALL_APP_CACHE_CREATE_IMAGE,
- SYSCALL_APP_CACHE_WRITE_IMAGE,
- SYSCALL_APP_CACHE_FINALIZE_IMAGE,
+ SYSCALL_APP_ROOT_UPDATE,
+ SYSCALL_APP_ROOT_IS_LOADED,
+ SYSCALL_APP_ROOT_GET_TIMESTAMP,
+
+ SYSCALL_APP_ARENA_CREATE_IMAGE,
+ SYSCALL_APP_ARENA_GET_INFO,
+ SYSCALL_APP_ARENA_NEXT_IMAGE,
+ SYSCALL_APP_ARENA_CLEAR_EVENT,
+
+ SYSCALL_APP_IMAGE_DELETE,
+ SYSCALL_APP_IMAGE_WRITE_CHUNK,
+ SYSCALL_APP_IMAGE_RUN,
+ SYSCALL_APP_IMAGE_STOP,
+ SYSCALL_APP_IMAGE_GET_INFO,
+ SYSCALL_APP_IMAGE_GET_PMINFO,
+
+ SYSCALL_APP_GET_HEAP,
SYSCALL_STORAGE_GET,
### core/embed/sys/syscall/stm32/syscall_dispatch.c
@@ -38,6 +38,10 @@
#include <sys/system.h>
#include <sys/systick.h>
+#ifdef USE_APP_LOADING
+#include <io/app_arena.h>
+#endif
+
#ifdef USE_SECRET
#include <sec/secret.h>
#endif
@@ -208,7 +212,6 @@ __attribute((no_stack_protector)) void syscall_handler(uint32_t *args,
size_t filter_len = (size_t)args[1];
args[0] = syslog_set_filter__verified(filter, filter_len);
} break;
-
#endif
#ifdef USE_IPC
@@ -1001,52 +1004,102 @@ __attribute((no_stack_protector)) void syscall_handler(uint32_t *args,
#endif
#ifdef USE_APP_LOADING
- case SYSCALL_APP_TASK_SPAWN: {
- const app_hash_t *hash = (const app_hash_t *)args[0];
- systask_id_t *task_id = (systask_id_t *)args[1];
- ts_t status = app_task_spawn__verified(hash, task_id);
+ case SYSCALL_APP_ROOT_UPDATE: {
+ const void *root_packet = (const void *)args[0];
+ size_t root_packet_size = (size_t)args[1];
+ ts_t status = app_root_update__verified(root_packet, root_packet_size);
args[0] = ts_code(status);
} break;
- case SYSCALL_APP_TASK_IS_RUNNING: {
- systask_id_t task_id = (systask_id_t)args[0];
- args[0] = app_task_is_running(task_id);
+ case SYSCALL_APP_ROOT_IS_LOADED: {
+ app_ring_t ring = (app_ring_t)args[0];
+ args[0] = (uint32_t)app_root_is_loaded(ring);
} break;
- case SYSCALL_APP_TASK_GET_PMINFO: {
- systask_id_t task_id = (systask_id_t)args[0];
- systask_postmortem_t *pminfo = (systask_postmortem_t *)args[1];
- ts_t status = app_task_get_pminfo__verified(task_id, pminfo);
+ case SYSCALL_APP_ROOT_GET_TIMESTAMP: {
+ app_ring_t ring = (app_ring_t)args[0];
+ uint32_t *timestamp = (uint32_t *)args[1];
+ ts_t status = app_root_get_timestamp__verified(ring, timestamp);
args[0] = ts_code(status);
} break;
- case SYSCALL_APP_TASK_UNLOAD: {
- systask_id_t task_id = (systask_id_t)args[0];
- app_task_unload(task_id);
+ case SYSCALL_APP_ARENA_GET_INFO: {
+ app_arena_info_t *info = (app_arena_info_t *)args[0];
+ ts_t status = app_arena_get_info__verified(info);
+ args[0] = ts_code(status);
} break;
- case SYSCALL_APP_CACHE_CREATE_IMAGE: {
- const app_hash_t *hash = (const app_hash_t *)args[0];
- size_t image_size = (size_t)args[1];
- args[0] = (uintptr_t)app_cache_create_image__verified(hash, image_size);
+ case SYSCALL_APP_ARENA_CLEAR_EVENT: {
+ ts_t status = app_arena_clear_event();
+ args[0] = ts_code(status);
} break;
- case SYSCALL_APP_CACHE_WRITE_IMAGE: {
- app_cache_handle_t handle = (app_cache_handle_t)args[0];
- uintptr_t offset = (uintptr_t)args[1];
- const void *data = (const void *)args[2];
- size_t size = (size_t)args[3];
- ts_t status = app_cache_write_image__verified(handle, offset, data, size);
+ case SYSCALL_APP_ARENA_CREATE_IMAGE: {
+ const void *header = (const void *)args[0];
+ size_t header_size = (size_t)args[1];
+ const sha256_digest_t *proof = (const sha256_digest_t *)args[2];
+ size_t proof_size = (size_t)args[3];
+ app_image_handle_t *handle = (app_image_handle_t *)args[4];
+ ts_t status = app_arena_create_image__verified(header, header_size, proof,
+ proof_size, handle);
args[0] = ts_code(status);
} break;
- case SYSCALL_APP_CACHE_FINALIZE_IMAGE: {
- app_cache_handle_t handle = (app_cache_handle_t)args[0];
- bool accept = (bool)args[1];
- ts_t status = app_cache_finalize_image(handle, accept);
+ case SYSCALL_APP_ARENA_NEXT_IMAGE: {
+ app_image_iter_t *state = (app_image_iter_t *)args[0];
+ app_image_handle_t *handle = (app_image_handle_t *)args[1];
+ ts_t status = app_arena_next_image__verified(state, handle);
+ args[0] = ts_code(status);
+ } break;
+
+ case SYSCALL_APP_IMAGE_GET_INFO: {
+ app_image_handle_t handle = (app_image_handle_t)args[0];
+ app_image_info_t *info = (app_image_info_t *)args[1];
+ ts_t status = app_image_get_info__verified(handle, info);
+ args[0] = ts_code(status);
+ } break;
+
+ case SYSCALL_APP_IMAGE_WRITE_CHUNK: {
+ app_image_handle_t handle = (app_image_handle_t)args[0];
+ const void *data = (const void *)args[1];
+ size_t size = (size_t)args[2];
+ sha256_digest_t *hash = (sha256_digest_t *)args[3];
+ ts_t status = app_image_write_chunk__verified(handle, data, size, hash);
args[0] = ts_code(status);
} break;
+ case SYSCALL_APP_IMAGE_DELETE: {
+ app_image_handle_t handle = (app_image_handle_t)args[0];
+ ts_t status = app_image_delete(handle);
+ args[0] = ts_code(status);
+ } break;
+
+ case SYSCALL_APP_IMAGE_RUN: {
+ app_image_handle_t handle = (app_image_handle_t)args[0];
+ systask_id_t *task_id = (systask_id_t *)args[1];
+ ts_t status = app_image_run__verified(handle, task_id);
+ args[0] = ts_code(status);
+ } break;
+
+ case SYSCALL_APP_IMAGE_STOP: {
+ app_image_handle_t handle = (app_image_handle_t)args[0];
+ ts_t status = app_image_stop(handle);
+ args[0] = ts_code(status);
+ } break;
+
+ case SYSCALL_APP_IMAGE_GET_PMINFO: {
+ app_image_handle_t handle = (app_image_handle_t)args[0];
+ systask_postmortem_t *pminfo = (systask_postmortem_t *)args[1];
+ ts_t status = app_image_get_pminfo__verified(handle, pminfo);
+ args[0] = ts_code(status);
+ } break;
+
+ case SYSCALL_APP_GET_HEAP: {
+ void **heap_ptr = (void **)args[0];
+ size_t *heap_size = (size_t *)args[1];
+ ts_t status = app_get_heap__verified(heap_ptr, heap_size);
+ args[0] = ts_code(status);
+ } break;
#endif
default:
### core/embed/sys/syscall/stm32/syscall_stubs.c
@@ -998,41 +998,79 @@ bool tropic_data_read(uint16_t udata_slot, uint8_t *data, uint16_t *size) {
#ifdef USE_APP_LOADING
-#include <io/app_loader.h>
+#include <io/app_root.h>
-ts_t app_task_spawn(const app_hash_t *hash, systask_id_t *task_id) {
- return ts_make(syscall_invoke2((uint32_t)hash, (uint32_t)task_id,
- SYSCALL_APP_TASK_SPAWN));
+ts_t app_root_update(const void *root_packet, size_t root_packet_size) {
+ return ts_make(syscall_invoke2((uint32_t)root_packet, root_packet_size,
+ SYSCALL_APP_ROOT_UPDATE));
}
-bool app_task_is_running(systask_id_t task_id) {
- return (bool)syscall_invoke1((uint32_t)task_id, SYSCALL_APP_TASK_IS_RUNNING);
+bool app_root_is_loaded(app_ring_t ring) {
+ return (bool)syscall_invoke1(ring, SYSCALL_APP_ROOT_IS_LOADED);
}
-ts_t app_task_get_pminfo(systask_id_t task_id, systask_postmortem_t *pminfo) {
- return ts_make(syscall_invoke2((uint32_t)task_id, (uint32_t)pminfo,
- SYSCALL_APP_TASK_GET_PMINFO));
+ts_t app_root_get_timestamp(app_ring_t ring, uint32_t *timestamp) {
+ return ts_make(syscall_invoke2(ring, (uint32_t)timestamp,
+ SYSCALL_APP_ROOT_GET_TIMESTAMP));
}
-void app_task_unload(systask_id_t task_id) {
- syscall_invoke1((uint32_t)task_id, SYSCALL_APP_TASK_UNLOAD);
+#include <io/app_arena.h>
+
+ts_t app_arena_get_info(app_arena_info_t *info) {
+ return ts_make(syscall_invoke1((uint32_t)info, SYSCALL_APP_ARENA_GET_INFO));
+}
+
+ts_t app_arena_clear_event(void) {
+ return ts_make(syscall_invoke0(SYSCALL_APP_ARENA_CLEAR_EVENT));
+}
+
+ts_t app_arena_create_image(const void *header, size_t header_size,
+ const sha256_digest_t *proof, size_t proof_size,
+ app_image_handle_t *handle) {
+ return ts_make(syscall_invoke5(
+ (uint32_t)header, (uint32_t)header_size, (uint32_t)proof,
+ (uint32_t)proof_size, (uint32_t)handle, SYSCALL_APP_ARENA_CREATE_IMAGE));
+}
+
+ts_t app_arena_next_image(app_image_iter_t *state, app_image_handle_t *handle) {
+ return ts_make(syscall_invoke2((uint32_t)state, (uint32_t)handle,
+ SYSCALL_APP_ARENA_NEXT_IMAGE));
+}
+
+ts_t app_image_get_info(app_image_handle_t handle, app_image_info_t *info) {
+ return ts_make(syscall_invoke2((uint32_t)handle, (uint32_t)info,
+ SYSCALL_APP_IMAGE_GET_INFO));
+}
+
+ts_t app_image_write_chunk(app_image_handle_t handle, const void *data,
+ size_t size, const sha256_digest_t *hash) {
+ return ts_make(syscall_invoke4((uint32_t)handle, (uint32_t)data, size,
+ (uint32_t)hash,
+ SYSCALL_APP_IMAGE_WRITE_CHUNK));
+}
+
+ts_t app_image_delete(app_image_handle_t handle) {
+ return ts_make(syscall_invoke1((uint32_t)handle, SYSCALL_APP_IMAGE_DELETE));
+}
+
+ts_t app_image_run(app_image_handle_t handle, systask_id_t *task_id) {
+ return ts_make(syscall_invoke2((uint32_t)handle, (uint32_t)task_id,
+ SYSCALL_APP_IMAGE_RUN));
}
-app_cache_handle_t app_cache_create_image(const app_hash_t *hash, size_t size) {
- return (app_cache_handle_t)syscall_invoke2((uint32_t)hash, (uint32_t)size,
- SYSCALL_APP_CACHE_CREATE_IMAGE);
+ts_t app_image_stop(app_image_handle_t handle) {
+ return ts_make(syscall_invoke1((uint32_t)handle, SYSCALL_APP_IMAGE_STOP));
}
-ts_t app_cache_write_image(app_cache_handle_t handle, uintptr_t offset,
- const void *data, size_t data_size) {
- return ts_make(syscall_invoke4((uint32_t)handle, (uint32_t)offset,
- (uint32_t)data, data_size,
- SYSCALL_APP_CACHE_WRITE_IMAGE));
+ts_t app_image_get_pminfo(app_image_handle_t handle,
+ systask_postmortem_t *pminfo) {
+ return ts_make(syscall_invoke2((uint32_t)handle, (uint32_t)pminfo,
+ SYSCALL_APP_IMAGE_GET_PMINFO));
}
-ts_t app_cache_finalize_image(app_cache_handle_t handle, bool accept) {
- return ts_make(syscall_invoke2((uint32_t)handle, (uint32_t)accept,
- SYSCALL_APP_CACHE_FINALIZE_IMAGE));
+ts_t app_get_heap(void **heap_ptr, size_t *heap_size) {
+ return ts_make(syscall_invoke2((uint32_t)heap_ptr, (uint32_t)heap_size,
+ SYSCALL_APP_GET_HEAP));
}
#endif
### core/embed/sys/syscall/stm32/syscall_verifiers.c
@@ -23,6 +23,7 @@
#include <trezor_rtl.h>
+#include <sys/applet.h>
#include <sys/systask.h>
#include "syscall_probe.h"
@@ -1547,53 +1548,152 @@ bool tropic_data_read__verified(uint16_t udata_slot, uint8_t *data,
#ifdef USE_APP_LOADING
-ts_t app_task_spawn__verified(const app_hash_t *hash, systask_id_t *task_id) {
- if (!probe_read_access(hash, sizeof(*hash))) {
+ts_t app_root_update__verified(const void *root_packet,
+ size_t root_packet_size) {
+ if (!probe_read_access(root_packet, root_packet_size)) {
goto access_violation;
}
- if (!probe_write_access(task_id, sizeof(*task_id))) {
+ return app_root_update(root_packet, root_packet_size);
+
+access_violation:
+ apptask_access_violation();
+ return TS_EACCES;
+}
+
+ts_t app_root_get_timestamp__verified(app_ring_t ring, uint32_t *timestamp) {
+ if (!probe_write_access(timestamp, sizeof(*timestamp))) {
goto access_violation;
}
- return app_task_spawn(hash, task_id);
+ return app_root_get_timestamp(ring, timestamp);
+
access_violation:
apptask_access_violation();
return TS_EACCES;
}
-ts_t app_task_get_pminfo__verified(systask_id_t task_id,
- systask_postmortem_t *pminfo) {
- if (!probe_write_access(pminfo, sizeof(*pminfo))) {
+ts_t app_arena_get_info__verified(app_arena_info_t *info) {
+ if (!probe_write_access(info, sizeof(*info))) {
+ goto access_violation;
+ }
+
+ return app_arena_get_info(info);
+
+access_violation:
+ apptask_access_violation();
+ return TS_EACCES;
+}
+
+ts_t app_arena_create_image__verified(const void *header, size_t header_size,
+ const sha256_digest_t *proof,
+ size_t proof_size,
+ app_image_handle_t *handle) {
+ if (!probe_read_access(header, header_size)) {
+ goto access_violation;
+ }
+
+ if (!probe_read_access(proof, proof_size)) {
+ goto access_violation;
+ }
+
+ if (!probe_write_access(handle, sizeof(*handle))) {
+ goto access_violation;
+ }
+
+ return app_arena_create_image(header, header_size, proof, proof_size, handle);
+
+access_violation:
+ apptask_access_violation();
+ return TS_EACCES;
+}
+
+ts_t app_arena_next_image__verified(app_image_iter_t *state,
+ app_image_handle_t *handle) {
+ if (!probe_write_access(state, sizeof(*state))) {
+ goto access_violation;
+ }
+
+ if (!probe_write_access(handle, sizeof(*handle))) {
+ goto access_violation;
+ }
+
+ return app_arena_next_image(state, handle);
+
+access_violation:
+ apptask_access_violation();
+ return TS_EACCES;
+}
+
+ts_t app_image_get_info__verified(app_image_handle_t handle,
+ app_image_info_t *info) {
+ if (!probe_write_access(info, sizeof(*info))) {
goto access_violation;
}
- return app_task_get_pminfo(task_id, pminfo);
+ return app_image_get_info(handle, info);
+
access_violation:
apptask_access_violation();
return TS_EACCES;
}
-app_cache_handle_t app_cache_create_image__verified(const app_hash_t *hash,
- size_t image_size) {
+ts_t app_image_write_chunk__verified(app_image_handle_t handle,
+ const void *data, size_t size,
+ const sha256_digest_t *hash) {
+ if (!probe_read_access(data, size)) {
+ goto access_violation;
+ }
+
if (!probe_read_access(hash, sizeof(*hash))) {
goto access_violation;
}
- return app_cache_create_image(hash, image_size);
+ return app_image_write_chunk(handle, data, size, hash);
access_violation:
apptask_access_violation();
- return APP_CACHE_INVALID_HANDLE;
+ return TS_EACCES;
}
-ts_t app_cache_write_image__verified(app_cache_handle_t handle,
- uintptr_t offset, const void *data,
- size_t data_size) {
- if (!probe_read_access(data, data_size)) {
+ts_t app_image_run__verified(app_image_handle_t handle, systask_id_t *task_id) {
+ if (!probe_write_access(task_id, sizeof(*task_id))) {
+ goto access_violation;
+ }
+
+ return app_image_run(handle, task_id);
+
+access_violation:
+
+ apptask_access_violation();
+ return TS_EACCES;
+}
+
+ts_t app_image_get_pminfo__verified(app_image_handle_t handle,
+ systask_postmortem_t *pminfo) {
+ if (!probe_write_access(pminfo, sizeof(*pminfo))) {
+ goto access_violation;
+ }
+
+ return app_image_get_pminfo(handle, pminfo);
+
+access_violation:
+ apptask_access_violation();
+ return TS_EACCES;
+}
+
+// ---------------------------------------------------------------------
+
+ts_t app_get_heap__verified(void **heap_ptr, size_t *heap_size) {
+ if (!probe_write_access(heap_ptr, sizeof(*heap_ptr))) {
goto access_violation;
}
- return app_cache_write_image(handle, offset, data, data_size);
+
+ if (!probe_write_access(heap_size, sizeof(*heap_size))) {
+ goto access_violation;
+ }
+
+ return applet_get_heap(syscall_get_context(), heap_ptr, heap_size);
access_violation:
apptask_access_violation();
### core/embed/sys/syscall/stm32/syscall_verifiers.h
@@ -376,19 +376,38 @@ bool tropic_data_read__verified(uint16_t udata_slot, uint8_t *data,
#ifdef USE_APP_LOADING
-#include <io/app_loader.h>
+#include <io/app_root.h>
-ts_t app_task_spawn__verified(const app_hash_t *hash, systask_id_t *task_id);
+ts_t app_root_update__verified(const void *root_packet,
+ size_t root_packet_size);
-ts_t app_task_get_pminfo__verified(systask_id_t task_id,
- systask_postmortem_t *pminfo);
+ts_t app_root_get_timestamp__verified(app_ring_t ring, uint32_t *timestamp);
-app_cache_handle_t app_cache_create_image__verified(const app_hash_t *hash,
- size_t image_size);
+#include <io/app_arena.h>
-ts_t app_cache_write_image__verified(app_cache_handle_t handle,
- uintptr_t offset, const void *data,
- size_t data_size);
+ts_t app_arena_get_info__verified(app_arena_info_t *info);
+
+ts_t app_arena_create_image__verified(const void *header, size_t header_size,
+ const sha256_digest_t *proof,
+ size_t proof_size,
+ app_image_handle_t *handle);
+
+ts_t app_arena_next_image__verified(app_image_iter_t *state,
+ app_image_handle_t *handle);
+
+ts_t app_image_get_info__verified(app_image_handle_t handle,
+ app_image_info_t *info);
+
+ts_t app_image_write_chunk__verified(app_image_handle_t handle,
+ const void *data, size_t size,
+ const sha256_digest_t *hash);
+
+ts_t app_image_run__verified(app_image_handle_t handle, systask_id_t *task_id);
+
+ts_t app_image_get_pminfo__verified(app_image_handle_t handle,
+ systask_postmortem_t *pminfo);
+
+ts_t app_get_heap__verified(void **heap_ptr, size_t *heap_size);
#endif
### core/embed/sys/task/applet.c
@@ -65,4 +65,23 @@ applet_t* applet_active(void) {
return (applet_t*)task->applet;
}
+void applet_set_heap(applet_t* applet, void* heap_ptr, size_t heap_size) {
+ applet->heap_ptr = heap_ptr;
+ applet->heap_size = heap_size;
+}
+
+ts_t applet_get_heap(applet_t* applet, void** heap_ptr, size_t* heap_size) {
+ TSH_DECLARE;
+
+ TSH_CHECK_ARG(applet != NULL);
+ TSH_CHECK_ARG(heap_ptr != NULL);
+ TSH_CHECK_ARG(heap_size != NULL);
+
+ *heap_ptr = applet->heap_ptr;
+ *heap_size = applet->heap_size;
+
+cleanup:
+ TSH_RETURN;
+}
+
#endif // USE_APPLETS && KERNEL_MODE
### core/embed/sys/task/inc/sys/applet.h
@@ -45,6 +45,11 @@ struct applet {
/** Callback called when the applet is unloaded */
applet_unload_cb_t unload_cb;
+ /** Pointer to the applet's heap */
+ void* heap_ptr;
+ /** Size of the applet's heap */
+ size_t heap_size;
+
#ifdef TREZOR_EMULATOR
/** Handle returned by `dlopen()` */
void* handle;
@@ -99,4 +104,21 @@ bool applet_is_alive(applet_t* applet);
*/
applet_t* applet_active(void);
+/**
+ * @brief Sets the heap pointer and size for the applet.
+ * @param applet Pointer to the applet to set the heap for.
+ * @param heap_ptr Pointer to the start of the heap.
+ * @param heap_size Size of the heap in bytes.
+ */
+void applet_set_heap(applet_t* applet, void* heap_ptr, size_t heap_size);
+
+/**
+ * @brief Gets the heap pointer and size for the applet.
+ * @param applet Pointer to the applet to get the heap for.
+ * @param heap_ptr Pointer to a variable to store the heap pointer.
+ * @param heap_size Pointer to a variable to store the heap size.
+ * @return TS_OK on success, or an error code on failure.
+ */
+ts_t applet_get_heap(applet_t* applet, void** heap_ptr, size_t* heap_size);
+
#endif // USE_APPLETS
### core/embed/sys/task/inc/sys/sysevent.h
@@ -36,6 +36,7 @@ typedef enum {
SYSHANDLE_BLE,
SYSHANDLE_SYSCALL,
SYSHANDLE_NFC,
+ SYSHANDLE_APP_ARENA,
#ifdef USE_IPC
SYSHANDLE_IPC0,
SYSHANDLE_IPC1,
### core/embed/upymod/build.rs
@@ -109,7 +109,6 @@ fn main() -> Result<()> {
"modutime.c",
"rustmods.c",
"trezorobj.c",
- "modtrezorapp/modtrezorapp.c",
"modtrezorconfig/modtrezorconfig.c",
"modtrezorcrypto/modtrezorcrypto.c",
"modtrezorcrypto/crc.c",
@@ -118,6 +117,10 @@ fn main() -> Result<()> {
"modtrezorutils/modtrezorutils.c",
]);
+ if cfg!(feature = "app_loading") {
+ lib.add_sources(["modtrezorapp/modtrezorapp.c"]);
+ }
+
if cfg!(feature = "sd_card") {
lib.add_sources(["modtrezorio/ff.c", "modtrezorio/ffunicode.c"]);
}
@@ -1198,6 +1201,10 @@ impl<'a> MpyBuilder<'a> {
files.add(src, "apps/thp/*.py")?;
}
+ if cfg!(feature = "app_loading") {
+ files.add(src, "apps/trezorapp/*.py")?;
+ }
+
if cfg!(feature = "universal_fw") {
files.add(src, "apps/common/definitions.py")?;
files.add(src, "trezor/enums/DefinitionType.py")?;
### core/embed/upymod/modtrezorapp/modtrezorapp-image.h
@@ -17,78 +17,492 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <py/obj.h>
+#include <py/runtime.h>
+
#include <trezor_rtl.h>
-#include <io/app_loader.h>
+#include <io/app_arena.h>
+
+/// package: trezorapp
+
+/// class AppError(Exception):
+/// """
+/// Base exception for all trezorapp errors.
+/// """
+MP_DEFINE_EXCEPTION(AppError, Exception)
+
+/// class AppImageError(AppError):
+/// """
+/// Base exception for app image errors.
+/// """
+MP_DEFINE_EXCEPTION(AppImageError, AppError)
+
+/// class AppImageNotFoundError(AppImageError):
+/// """
+/// Raised when the AppImage handle is invalid or the image no longer
+/// exists.
+/// """
+MP_DEFINE_EXCEPTION(AppImageNotFoundError, AppImageError)
+
+/// class AppImageMemoryError(AppImageError):
+/// """
+/// Raised when there is not enough memory in the app arena.
+/// """
+MP_DEFINE_EXCEPTION(AppImageMemoryError, AppImageError)
+
+/// class AppImageVerificationError(AppImageError):
+/// """
+/// Raised when the app image data fails verification.
+/// """
+MP_DEFINE_EXCEPTION(AppImageVerificationError, AppImageError)
-/// package: trezorapp.__init__
+/// class AppArenaError(AppError):
+/// """
+/// Raised when an app arena operation fails.
+/// """
+MP_DEFINE_EXCEPTION(AppArenaError, AppError)
/// class AppImage:
/// """
-/// Application image image.
+/// External application loaded in the app arena
/// """
typedef struct _mp_obj_AppImage_t {
mp_obj_base_t base;
- app_cache_handle_t image;
+ app_image_handle_t handle;
} mp_obj_AppImage_t;
-/// def write(self, offset: int, data: AnyBytes) -> None
+static void app_image_get_info_or_raise(app_image_handle_t handle,
+ app_image_info_t *info) {
+ ts_t status = app_image_get_info(handle, info);
+ if (ts_eq(status, TS_ENOENT)) {
+ mp_raise_type(&mp_type_AppImageNotFoundError);
+ } else if (ts_error(status)) {
+ mp_raise_type(&mp_type_AppImageError);
+ }
+}
+
+/// def handle(self) -> int:
/// """
-/// Writes data to the application image at the specified offset.
+/// Return the image internal unique handle.
/// """
-static mp_obj_t mod_trezorapp_AppImage_write(mp_obj_t self, mp_obj_t offset_obj,
- mp_obj_t data_obj) {
+static mp_obj_t mod_trezorapp_AppImage_handle(mp_obj_t self) {
mp_obj_AppImage_t *o = MP_OBJ_TO_PTR(self);
- app_cache_handle_t image = o->image;
+ return mp_obj_new_int(o->handle);
+}
+static MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorapp_AppImage_handle_obj,
+ mod_trezorapp_AppImage_handle);
- mp_buffer_info_t bufinfo = {0};
- mp_get_buffer_raise(data_obj, &bufinfo, MP_BUFFER_READ);
+/// def task_id(self) -> int:
+/// """
+/// Return the task ID associated with the application image.
+/// """
+static mp_obj_t mod_trezorapp_AppImage_task_id(mp_obj_t self) {
+ mp_obj_AppImage_t *o = MP_OBJ_TO_PTR(self);
- uintptr_t offset = mp_obj_get_int(offset_obj);
+ app_image_info_t info;
+ app_image_get_info_or_raise(o->handle, &info);
- ts_t status = app_cache_write_image(image, offset, bufinfo.buf, bufinfo.len);
- if (ts_error(status)) {
- mp_raise_msg(&mp_type_RuntimeError,
- MP_ERROR_TEXT("Failed to write to app image."));
+ if (!info.running) {
+ mp_raise_type(&mp_type_AppImageError);
+ }
+
+ return mp_obj_new_int(info.task_id);
+}
+static MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorapp_AppImage_task_id_obj,
+ mod_trezorapp_AppImage_task_id);
+
+/// def is_running(self) -> bool:
+/// """
+/// Check if the application image is currently running.
+/// """
+static mp_obj_t mod_trezorapp_AppImage_is_running(mp_obj_t self) {
+ mp_obj_AppImage_t *o = MP_OBJ_TO_PTR(self);
+
+ app_image_info_t info;
+ app_image_get_info_or_raise(o->handle, &info);
+
+ return mp_obj_new_bool(info.running);
+}
+static MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorapp_AppImage_is_running_obj,
+ mod_trezorapp_AppImage_is_running);
+
+/// def is_ready(self) -> bool:
+/// """
+/// Check if the application image has been fully loaded and verified.
+/// """
+static mp_obj_t mod_trezorapp_AppImage_is_ready(mp_obj_t self) {
+ mp_obj_AppImage_t *o = MP_OBJ_TO_PTR(self);
+
+ app_image_info_t info;
+ app_image_get_info_or_raise(o->handle, &info);
+
+ return mp_obj_new_bool(info.ready);
+}
+static MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorapp_AppImage_is_ready_obj,
+ mod_trezorapp_AppImage_is_ready);
+
+/// def id(self) -> str:
+/// """
+/// Return the ID of the application image.
+/// """
+static mp_obj_t mod_trezorapp_AppImage_id(mp_obj_t self) {
+ mp_obj_AppImage_t *o = MP_OBJ_TO_PTR(self);
+
+ app_image_info_t info;
+ app_image_get_info_or_raise(o->handle, &info);
+
+ return mp_obj_new_str(info.id, strnlen(info.id, sizeof(info.id)));
+}
+static MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorapp_AppImage_id_obj,
+ mod_trezorapp_AppImage_id);
+
+/// def size(self) -> int:
+/// """
+/// Return the size of the application image in bytes.
+/// """
+static mp_obj_t mod_trezorapp_AppImage_size(mp_obj_t self) {
+ mp_obj_AppImage_t *o = MP_OBJ_TO_PTR(self);
+
+ app_image_info_t info;
+ app_image_get_info_or_raise(o->handle, &info);
+
+ return mp_obj_new_int(info.code_size);
+}
+static MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorapp_AppImage_size_obj,
+ mod_trezorapp_AppImage_size);
+
+/// def chunk_size(self) -> int:
+/// """
+/// Return the expected size of each payload chunk in bytes.
+/// """
+static mp_obj_t mod_trezorapp_AppImage_chunk_size(mp_obj_t self) {
+ mp_obj_AppImage_t *o = MP_OBJ_TO_PTR(self);
+
+ app_image_info_t info;
+ app_image_get_info_or_raise(o->handle, &info);
+
+ return mp_obj_new_int(info.chunk_size);
+}
+static MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorapp_AppImage_chunk_size_obj,
+ mod_trezorapp_AppImage_chunk_size);
+
+/// def version(self) -> tuple[int, int, int, int]:
+/// """
+/// Return the version of the application image as a tuple (major, minor,
+/// patch, build).
+/// """
+static mp_obj_t mod_trezorapp_AppImage_version(mp_obj_t self) {
+ mp_obj_AppImage_t *o = MP_OBJ_TO_PTR(self);
+
+ app_image_info_t info;
+ app_image_get_info_or_raise(o->handle, &info);
+
+ mp_obj_t version_tuple[4];
+ version_tuple[0] = mp_obj_new_int((info.version >> 0) & 0xFF); // major
+ version_tuple[1] = mp_obj_new_int((info.version >> 8) & 0xFF); // minor
+ version_tuple[2] = mp_obj_new_int((info.version >> 16) & 0xFF); // patch
+ version_tuple[3] = mp_obj_new_int((info.version >> 24) & 0xFF); // build
+
+ return mp_obj_new_tuple(4, version_tuple);
+}
+static MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorapp_AppImage_version_obj,
+ mod_trezorapp_AppImage_version);
+
+/// def name(self) -> str:
+/// """
+/// Return the name of the application.
+/// """
+static mp_obj_t mod_trezorapp_AppImage_name(mp_obj_t self) {
+ mp_obj_AppImage_t *o = MP_OBJ_TO_PTR(self);
+
+ app_image_info_t info;
+ app_image_get_info_or_raise(o->handle, &info);
+
+ return mp_obj_new_str(info.name, strnlen(info.name, sizeof(info.name)));
+}
+static MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorapp_AppImage_name_obj,
+ mod_trezorapp_AppImage_name);
+
+/// def vendor(self) -> str:
+/// """
+/// Return the vendor of the application.
+/// """
+static mp_obj_t mod_trezorapp_AppImage_vendor(mp_obj_t self) {
+ mp_obj_AppImage_t *o = MP_OBJ_TO_PTR(self);
+
+ app_image_info_t info;
+ app_image_get_info_or_raise(o->handle, &info);
+
+ return mp_obj_new_str(info.vendor, strnlen(info.vendor, sizeof(info.vendor)));
+}
+static MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorapp_AppImage_vendor_obj,
+ mod_trezorapp_AppImage_vendor);
+
+/// def ring(self) -> int:
+/// """
+/// Return the privilege ring of the application.
+/// """
+static mp_obj_t mod_trezorapp_AppImage_ring(mp_obj_t self) {
+ mp_obj_AppImage_t *o = MP_OBJ_TO_PTR(self);
+
+ app_image_info_t info;
+ app_image_get_info_or_raise(o->handle, &info);
+
+ return mp_obj_new_int(info.ring);
+}
+static MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorapp_AppImage_ring_obj,
+ mod_trezorapp_AppImage_ring);
+
+/// def header_hash(self) -> bytes:
+/// """
+/// Return the hash of the application image header.
+/// """
+static mp_obj_t mod_trezorapp_AppImage_header_hash(mp_obj_t self) {
+ mp_obj_AppImage_t *o = MP_OBJ_TO_PTR(self);
+
+ app_image_info_t info;
+ app_image_get_info_or_raise(o->handle, &info);
+
+ return mp_obj_new_bytes((const byte *)&info.header_hash,
+ sizeof(info.header_hash));
+}
+static MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorapp_AppImage_header_hash_obj,
+ mod_trezorapp_AppImage_header_hash);
+
+/// def write_chunk(self, data: AnyBytes, hash: AnyBytes) -> None:
+/// """
+/// Write a chunk of image data into app-arena memory.
+/// Allowed only while the image is in the loading state.
+/// """
+static mp_obj_t mod_trezorapp_AppImage_write_chunk(mp_obj_t self,
+ mp_obj_t data_obj,
+ mp_obj_t hash_obj) {
+ mp_obj_AppImage_t *o = MP_OBJ_TO_PTR(self);
+
+ mp_buffer_info_t data = {0};
+ mp_get_buffer_raise(data_obj, &data, MP_BUFFER_READ);
+
+ mp_buffer_info_t hash = {0};
+ mp_get_buffer_raise(hash_obj, &hash, MP_BUFFER_READ);
+ if (hash.len != sizeof(sha256_digest_t)) {
+ mp_raise_ValueError(MP_ERROR_TEXT("Hash must be 32 bytes"));
+ }
+
+ ts_t status = app_image_write_chunk(o->handle, data.buf, data.len,
+ (const sha256_digest_t *)hash.buf);
+
+ if (ts_eq(status, TS_ENOENT)) {
+ mp_raise_type(&mp_type_AppImageNotFoundError);
+ } else if (ts_eq(status, TS_ENOMEM)) {
+ mp_raise_type(&mp_type_AppImageMemoryError);
+ } else if (ts_eq(status, TS_EBADMSG)) {
+ mp_raise_type(&mp_type_AppImageVerificationError);
+ } else if (ts_error(status)) {
+ mp_raise_type(&mp_type_AppImageError);
}
return mp_const_none;
}
-static MP_DEFINE_CONST_FUN_OBJ_3(mod_trezorapp_AppImage_write_obj,
- mod_trezorapp_AppImage_write);
+static MP_DEFINE_CONST_FUN_OBJ_3(mod_trezorapp_AppImage_write_chunk_obj,
+ mod_trezorapp_AppImage_write_chunk);
-/// def finalize(self, bool accept) -> None:
+/// def delete(self) -> None:
/// """
-/// Finalizes loading of the application image. If `accept` is true,
-/// the image is marked as loaded and will be available for execution.
-/// If `accept` is false, the image is discarded.
+/// Delete the application and release its resources.
+/// If the image is currently running, it is stopped before
+/// deletion. After deletion, the AppImage object is invalid
+/// and must not be used.
/// """
-static mp_obj_t mod_trezorapp_AppImage_finalize(mp_obj_t self,
- mp_obj_t accept_obj) {
+static mp_obj_t mod_trezorapp_AppImage_delete(mp_obj_t self) {
mp_obj_AppImage_t *o = MP_OBJ_TO_PTR(self);
- bool accept = mp_obj_is_true(accept_obj);
+ ts_t status = app_image_delete(o->handle);
+ if (ts_eq(status, TS_ENOENT)) {
+ mp_raise_type(&mp_type_AppImageNotFoundError);
+ } else if (ts_error(status)) {
+ mp_raise_type(&mp_type_AppImageError);
+ }
+
+ return mp_const_none;
+}
+static MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorapp_AppImage_delete_obj,
+ mod_trezorapp_AppImage_delete);
- ts_t status = app_cache_finalize_image(o->image, accept);
+/// def run(self) -> int:
+/// """
+/// Run the loaded application image and return its task ID.
+/// If the image is already running, the function returns its task ID.
+/// Only ready images are runnable.
+/// """
+static mp_obj_t mod_trezorapp_AppImage_run(mp_obj_t self) {
+ mp_obj_AppImage_t *o = MP_OBJ_TO_PTR(self);
- if (accept && ts_error(status)) {
- mp_raise_msg(&mp_type_RuntimeError,
- MP_ERROR_TEXT("Failed to finalize app image."));
+ systask_id_t task_id = 0;
+ ts_t status = app_image_run(o->handle, &task_id);
+ if (ts_eq(status, TS_ENOENT)) {
+ mp_raise_type(&mp_type_AppImageNotFoundError);
+ } else if (ts_error(status)) {
+ mp_raise_type(&mp_type_AppImageError);
}
- UNUSED(status);
+ return mp_obj_new_int(task_id);
+}
+static MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorapp_AppImage_run_obj,
+ mod_trezorapp_AppImage_run);
- o->image = APP_CACHE_INVALID_HANDLE;
+/// def stop(self) -> None:
+/// """
+/// Stop the running application image. If the image is not running,
+/// this operation has no effect.
+/// """
+static mp_obj_t mod_trezorapp_AppImage_stop(mp_obj_t self) {
+ mp_obj_AppImage_t *o = MP_OBJ_TO_PTR(self);
+ ts_t status = app_image_stop(o->handle);
+ if (ts_eq(status, TS_ENOENT)) {
+ mp_raise_type(&mp_type_AppImageNotFoundError);
+ } else if (ts_error(status)) {
+ mp_raise_type(&mp_type_AppImageError);
+ }
return mp_const_none;
}
-static MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorapp_AppImage_finalize_obj,
- mod_trezorapp_AppImage_finalize);
+static MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorapp_AppImage_stop_obj,
+ mod_trezorapp_AppImage_stop);
+
+typedef struct {
+ mp_obj_base_t base;
+ // Handle of the AppImage being iterated over
+ app_image_handle_t handle;
+ // Offset in the curves array of the next curve to return
+ size_t offset;
+} mp_obj_AppCurveIter_t;
+
+static mp_obj_t mod_trezorapp_AppCurveIter_iternext(mp_obj_t self_in) {
+ mp_obj_AppCurveIter_t *self = MP_OBJ_TO_PTR(self_in);
+
+ app_image_info_t info;
+ app_image_get_info_or_raise(self->handle, &info);
+
+ size_t offset = self->offset;
+ if (offset >= APP_HEADER_CURVES_MAX_LEN) {
+ return MP_OBJ_STOP_ITERATION;
+ }
+
+ size_t len = strnlen(info.curves + offset, sizeof(info.curves) - offset);
+ if (len == 0) {
+ return MP_OBJ_STOP_ITERATION;
+ }
+
+ self->offset = MIN(offset + len + 1, APP_HEADER_CURVES_MAX_LEN);
+
+ return mp_obj_new_str(info.curves + offset, len);
+}
+
+// clang-format off
+static MP_DEFINE_CONST_OBJ_TYPE(mod_trezorapp_AppCurveIter_type,
+ MP_QSTR_AppCurveIter, MP_TYPE_FLAG_ITER_IS_ITERNEXT,
+ iter, mod_trezorapp_AppCurveIter_iternext);
+// clang-format on
+
+/// def allowed_curves(self) -> Iterator[str]:
+/// """
+/// Return an iterator over the allowed curves
+/// """
+static mp_obj_t mod_trezorapp_allowed_curves(mp_obj_t self) {
+ mp_obj_AppImage_t *image = MP_OBJ_TO_PTR(self);
+
+ mp_obj_AppCurveIter_t *o =
+ mp_obj_malloc(mp_obj_AppCurveIter_t, &mod_trezorapp_AppCurveIter_type);
+ o->handle = image->handle;
+ o->offset = 0;
+ return MP_OBJ_FROM_PTR(o);
+}
+static MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorapp_allowed_curves_obj,
+ mod_trezorapp_allowed_curves);
+
+typedef struct {
+ mp_obj_base_t base;
+ // Handle of the AppImage being iterated over
+ app_image_handle_t handle;
+ // Offset in the paths array of the next path to return
+ size_t offset;
+} mp_obj_AppPathIter_t;
+
+static mp_obj_t mod_trezorapp_AppPathIter_iternext(mp_obj_t self_in) {
+ mp_obj_AppPathIter_t *self = MP_OBJ_TO_PTR(self_in);
+
+ app_image_info_t info;
+ app_image_get_info_or_raise(self->handle, &info);
+
+ size_t offset = self->offset;
+ if (offset >= APP_HEADER_PATHS_MAX_LEN) {
+ return MP_OBJ_STOP_ITERATION;
+ }
+
+ size_t len = strnlen(info.paths + offset, sizeof(info.paths) - offset);
+ if (len == 0) {
+ return MP_OBJ_STOP_ITERATION;
+ }
+
+ self->offset = MIN(offset + len + 1, APP_HEADER_PATHS_MAX_LEN);
+
+ return mp_obj_new_str(info.paths + offset, len);
+}
+
+// clang-format off
+static MP_DEFINE_CONST_OBJ_TYPE(mod_trezorapp_AppPathIter_type,
+ MP_QSTR_AppPathIter, MP_TYPE_FLAG_ITER_IS_ITERNEXT,
+ iter, mod_trezorapp_AppPathIter_iternext);
+// clang-format on
+
+/// def allowed_paths(self) -> Iterator[str]:
+/// """
+/// Return an iterator over the allowed BIP32 path prefixes.
+/// """
+static mp_obj_t mod_trezorapp_allowed_paths(mp_obj_t self) {
+ mp_obj_AppImage_t *image = MP_OBJ_TO_PTR(self);
+
+ mp_obj_AppPathIter_t *o =
+ mp_obj_malloc(mp_obj_AppPathIter_t, &mod_trezorapp_AppPathIter_type);
+ o->handle = image->handle;
+ o->offset = 0;
+ return MP_OBJ_FROM_PTR(o);
+}
+static MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorapp_allowed_paths_obj,
+ mod_trezorapp_allowed_paths);
static const mp_rom_map_elem_t mod_trezorapp_AppImage_locals_dict_table[] = {
- {MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mod_trezorapp_AppImage_write_obj)},
- {MP_ROM_QSTR(MP_QSTR_finalize),
- MP_ROM_PTR(&mod_trezorapp_AppImage_finalize_obj)},
+ {MP_ROM_QSTR(MP_QSTR_handle),
+ MP_ROM_PTR(&mod_trezorapp_AppImage_handle_obj)},
+ {MP_ROM_QSTR(MP_QSTR_task_id),
+ MP_ROM_PTR(&mod_trezorapp_AppImage_task_id_obj)},
+ {MP_ROM_QSTR(MP_QSTR_is_running),
+ MP_ROM_PTR(&mod_trezorapp_AppImage_is_running_obj)},
+ {MP_ROM_QSTR(MP_QSTR_is_ready),
+ MP_ROM_PTR(&mod_trezorapp_AppImage_is_ready_obj)},
+ {MP_ROM_QSTR(MP_QSTR_id), MP_ROM_PTR(&mod_trezorapp_AppImage_id_obj)},
+ {MP_ROM_QSTR(MP_QSTR_size), MP_ROM_PTR(&mod_trezorapp_AppImage_size_obj)},
+ {MP_ROM_QSTR(MP_QSTR_chunk_size),
+ MP_ROM_PTR(&mod_trezorapp_AppImage_chunk_size_obj)},
+ {MP_ROM_QSTR(MP_QSTR_version),
+ MP_ROM_PTR(&mod_trezorapp_AppImage_version_obj)},
+ {MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&mod_trezorapp_AppImage_name_obj)},
+ {MP_ROM_QSTR(MP_QSTR_vendor),
+ MP_ROM_PTR(&mod_trezorapp_AppImage_vendor_obj)},
+ {MP_ROM_QSTR(MP_QSTR_ring), MP_ROM_PTR(&mod_trezorapp_AppImage_ring_obj)},
+ {MP_ROM_QSTR(MP_QSTR_header_hash),
+ MP_ROM_PTR(&mod_trezorapp_AppImage_header_hash_obj)},
+ {MP_ROM_QSTR(MP_QSTR_write_chunk),
+ MP_ROM_PTR(&mod_trezorapp_AppImage_write_chunk_obj)},
+ {MP_ROM_QSTR(MP_QSTR_delete),
+ MP_ROM_PTR(&mod_trezorapp_AppImage_delete_obj)},
+ {MP_ROM_QSTR(MP_QSTR_run), MP_ROM_PTR(&mod_trezorapp_AppImage_run_obj)},
+ {MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&mod_trezorapp_AppImage_stop_obj)},
+ {MP_ROM_QSTR(MP_QSTR_allowed_curves),
+ MP_ROM_PTR(&mod_trezorapp_allowed_curves_obj)},
+ {MP_ROM_QSTR(MP_QSTR_allowed_paths),
+ MP_ROM_PTR(&mod_trezorapp_allowed_paths_obj)},
};
static MP_DEFINE_CONST_DICT(mod_trezorapp_AppImage_locals_dict,
mod_trezorapp_AppImage_locals_dict_table);
### core/embed/upymod/modtrezorapp/modtrezorapp-task.h
@@ -1,91 +0,0 @@
-/*
- * This file is part of the Trezor project, https://trezor.io/
- *
- * Copyright (c) SatoshiLabs
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <trezor_rtl.h>
-
-#include <io/app_loader.h>
-
-/// package: trezorapp.__init__
-
-/// class AppTask:
-/// """
-/// App task structure.
-/// """
-typedef struct _mp_obj_AppTask_t {
- mp_obj_base_t base;
- systask_id_t task_id;
-} mp_obj_AppTask_t;
-
-/// def id(self) -> int:
-/// """
-/// Returns the task id.
-/// """
-static mp_obj_t mod_trezorapp_AppTask_id(mp_obj_t self) {
- mp_obj_AppTask_t *o = MP_OBJ_TO_PTR(self);
- return MP_OBJ_NEW_SMALL_INT(o->task_id);
-}
-static MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorapp_AppTask_id_obj,
- mod_trezorapp_AppTask_id);
-
-/// def is_running(self) -> bool:
-/// """
-/// Returns whether the application is still running.
-/// """
-static mp_obj_t mod_trezorapp_AppTask_is_running(mp_obj_t self) {
- mp_obj_AppTask_t *o = MP_OBJ_TO_PTR(self);
-
- if (app_task_is_running(o->task_id)) {
- return mp_const_true;
- } else {
- return mp_const_false;
- }
-}
-static MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorapp_AppTask_is_running_obj,
- mod_trezorapp_AppTask_is_running);
-
-/// def unload(self) -> None:
-/// """
-/// Unloads the application associated with this task.
-/// """
-static mp_obj_t mod_trezorapp_AppTask_unload(mp_obj_t self) {
- mp_obj_AppTask_t *o = MP_OBJ_TO_PTR(self);
-
- app_task_unload(o->task_id);
- o->task_id = 0;
-
- return mp_const_none;
-}
-static MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorapp_AppTask_unload_obj,
- mod_trezorapp_AppTask_unload);
-
-static const mp_rom_map_elem_t mod_trezorapp_AppTask_locals_dict_table[] = {
- {MP_ROM_QSTR(MP_QSTR_id), MP_ROM_PTR(&mod_trezorapp_AppTask_id_obj)},
- {MP_ROM_QSTR(MP_QSTR_is_running),
- MP_ROM_PTR(&mod_trezorapp_AppTask_is_running_obj)},
- {MP_ROM_QSTR(MP_QSTR_unload),
- MP_ROM_PTR(&mod_trezorapp_AppTask_unload_obj)},
-};
-static MP_DEFINE_CONST_DICT(mod_trezorapp_AppTask_locals_dict,
- mod_trezorapp_AppTask_locals_dict_table);
-
-// clang-format off
-static MP_DEFINE_CONST_OBJ_TYPE(mod_trezorapp_AppTask_type,
- MP_QSTR_AppTask, MP_TYPE_FLAG_NONE,
- locals_dict, &mod_trezorapp_AppTask_locals_dict);
-// clang-format on
### core/embed/upymod/modtrezorapp/modtrezorapp.c
@@ -17,130 +17,295 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#ifdef USE_APP_LOADING
+
#include <trezor_rtl.h>
-#include <unistd.h>
+#include <io/app_arena.h>
+#include <io/app_header.h>
+#include <io/app_root.h>
#include "py/mphal.h"
#include "py/objstr.h"
#include "py/runtime.h"
-#if MICROPY_PY_TREZORAPP
-
-#include <io/app_cache.h>
-#include <io/app_loader.h>
-
#include "../trezorobj.h"
#include "modtrezorapp-image.h"
-#include "modtrezorapp-task.h"
-/// package: trezorapp.__init__
+/// package: trezorapp
-/// def spawn_task(app_hash: bytes) -> AppTask:
+/// def create_image(header: AnyBytes, proof: AnyBytes) -> AppImage:
/// """
-/// Spawns an application task from the app cache.
+/// Create a new application image from header and proof.
+/// The returned handle can be used to load the rest of the
+/// image content and run it.
/// """
-static mp_obj_t mod_trezorapp_spawn_task(mp_obj_t app_hash_obj) {
- mp_buffer_info_t hash = {0};
- mp_get_buffer_raise(app_hash_obj, &hash, MP_BUFFER_READ);
+static mp_obj_t mod_trezorapp_create_image(mp_obj_t header_obj,
+ mp_obj_t proof_obj) {
+ mp_buffer_info_t header_buf;
+ mp_get_buffer_raise(header_obj, &header_buf, MP_BUFFER_READ);
- if (hash.len != sizeof(app_hash_t)) {
- mp_raise_ValueError(MP_ERROR_TEXT("Invalid app hash size"));
- }
+ mp_buffer_info_t proof_buf;
+ mp_get_buffer_raise(proof_obj, &proof_buf, MP_BUFFER_READ);
+
+ mp_obj_AppImage_t *o =
+ mp_obj_malloc(mp_obj_AppImage_t, &mod_trezorapp_AppImage_type);
- const app_hash_t *hash_ptr = (const app_hash_t *)hash.buf;
+ ts_t status = app_arena_create_image(
+ header_buf.buf, header_buf.len, proof_buf.buf, proof_buf.len, &o->handle);
- systask_id_t task_id;
- ts_t status = app_task_spawn(hash_ptr, &task_id);
- if (ts_error(status)) {
- mp_raise_msg(&mp_type_RuntimeError,
- MP_ERROR_TEXT("Failed to spawn app from app cache"));
+ if (ts_eq(status, TS_ENOMEM)) {
+ mp_raise_type(&mp_type_AppImageMemoryError);
+ } else if (ts_eq(status, TS_EBADMSG)) {
+ mp_raise_type(&mp_type_AppImageVerificationError);
+ } else if (ts_error(status)) {
+ mp_raise_type(&mp_type_AppImageError);
}
- mp_obj_AppTask_t *o =
- mp_obj_malloc(mp_obj_AppTask_t, &mod_trezorapp_AppTask_type);
- o->task_id = task_id;
return MP_OBJ_FROM_PTR(o);
}
-static MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorapp_spawn_task_obj,
- mod_trezorapp_spawn_task);
+static MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorapp_create_image_obj,
+ mod_trezorapp_create_image);
-/// def create_image(app_hash: bytes, size: int) -> AppImage:
-/// """
-/// Creates a new application image in the app cache.
-/// """
-static mp_obj_t mod_trezorapp_create_image(mp_obj_t app_hash_obj,
- mp_obj_t size_obj) {
- mp_buffer_info_t hash = {0};
- mp_get_buffer_raise(app_hash_obj, &hash, MP_BUFFER_READ);
+typedef struct {
+ mp_obj_base_t base;
+ app_image_iter_t state;
+} mp_obj_AppImageIter_t;
+
+static mp_obj_t mod_trezorapp_images_iternext(mp_obj_t self_in) {
+ mp_obj_AppImageIter_t *self = MP_OBJ_TO_PTR(self_in);
+
+ app_image_handle_t handle = APP_IMAGE_HANDLE_INVALID;
+ ts_t status = app_arena_next_image(&self->state, &handle);
+ if (ts_error(status)) {
+ mp_raise_type(&mp_type_AppArenaError);
+ }
- if (hash.len != sizeof(app_hash_t)) {
- mp_raise_ValueError(MP_ERROR_TEXT("Invalid app hash size"));
+ if (handle == APP_IMAGE_HANDLE_INVALID) {
+ return MP_OBJ_STOP_ITERATION;
}
- const app_hash_t *hash_ptr = (const app_hash_t *)hash.buf;
+ mp_obj_AppImage_t *o =
+ mp_obj_malloc(mp_obj_AppImage_t, &mod_trezorapp_AppImage_type);
+ o->handle = handle;
+ return MP_OBJ_FROM_PTR(o);
+}
+
+// clang-format off
+static MP_DEFINE_CONST_OBJ_TYPE(mod_trezorapp_AppImageIter_type,
+ MP_QSTR_AppImageIter, MP_TYPE_FLAG_ITER_IS_ITERNEXT,
+ iter, mod_trezorapp_images_iternext);
+// clang-format on
- size_t size = mp_obj_get_int(size_obj);
+/// def images() -> Iterator[AppImage]:
+/// """
+/// Return an iterator over all app images in the app arena.
+/// """
+static mp_obj_t mod_trezorapp_images(void) {
+ mp_obj_AppImageIter_t *o =
+ mp_obj_malloc(mp_obj_AppImageIter_t, &mod_trezorapp_AppImageIter_type);
+ o->state = APP_IMAGE_ITER_INIT;
+ return MP_OBJ_FROM_PTR(o);
+}
+static MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorapp_images_obj,
+ mod_trezorapp_images);
- app_cache_handle_t image = app_cache_create_image(hash_ptr, size);
+/// def image_by_handle(handle: int) -> AppImage:
+/// """
+/// Return the application image with the specified handle.
+/// """
+static mp_obj_t mod_trezorapp_arena_image_by_handle(mp_obj_t handle_obj) {
+ app_image_handle_t handle = mp_obj_get_int(handle_obj);
- if (image == APP_CACHE_INVALID_HANDLE) {
- mp_raise_msg(&mp_type_RuntimeError,
- MP_ERROR_TEXT("Failed to create app image in app cache"));
+ app_image_info_t info;
+ ts_t status = app_image_get_info(handle, &info);
+ if (ts_eq(status, TS_ENOENT)) {
+ mp_raise_type(&mp_type_AppImageNotFoundError);
+ } else if (ts_error(status)) {
+ mp_raise_type(&mp_type_AppImageError);
}
+
mp_obj_AppImage_t *o =
mp_obj_malloc(mp_obj_AppImage_t, &mod_trezorapp_AppImage_type);
- o->image = image;
+ o->handle = handle;
return MP_OBJ_FROM_PTR(o);
}
-static MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorapp_create_image_obj,
- mod_trezorapp_create_image);
+static MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorapp_arena_image_by_handle_obj,
+ mod_trezorapp_arena_image_by_handle);
-#ifdef TREZOR_EMULATOR
-/// def load_file(app_hash: bytes, filename: Str) -> None:
+/// def clear_event() -> None:
/// """
-/// Loads an application image from a file into the app cache.
+/// Clear the pending event on the app arena, if any.
/// """
-static mp_obj_t mod_trezorapp_load_file(mp_obj_t app_hash_obj,
- mp_obj_t filename_obj) {
- mp_buffer_info_t hash = {0};
- mp_get_buffer_raise(app_hash_obj, &hash, MP_BUFFER_READ);
+static mp_obj_t mod_trezorapp_arena_clear_event(void) {
+ ts_t status = app_arena_clear_event();
+ if (ts_error(status)) {
+ mp_raise_type(&mp_type_AppArenaError);
+ }
+ return mp_const_none;
+}
+static MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorapp_arena_clear_event_obj,
+ mod_trezorapp_arena_clear_event);
- if (hash.len != sizeof(app_hash_t)) {
- mp_raise_ValueError(MP_ERROR_TEXT("Invalid app hash size"));
+/// def image_count() -> int:
+/// """
+/// Return the number of application images currently
+/// loaded in the app arena.
+/// """
+static mp_obj_t mod_trezorapp_arena_image_count(void) {
+ app_arena_info_t info;
+ ts_t status = app_arena_get_info(&info);
+ if (ts_error(status)) {
+ mp_raise_type(&mp_type_AppArenaError);
}
- const app_hash_t *hash_ptr = (const app_hash_t *)hash.buf;
+ return mp_obj_new_int(info.image_count);
+}
+static MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorapp_arena_image_count_obj,
+ mod_trezorapp_arena_image_count);
- const char *filename = mp_obj_str_get_str(filename_obj);
+/// def mem_total() -> int:
+/// """
+/// Return the total memory available in the app arena.
+/// """
+static mp_obj_t mod_trezorapp_arena_mem_total(void) {
+ app_arena_info_t info;
+ ts_t status = app_arena_get_info(&info);
+ if (ts_error(status)) {
+ mp_raise_type(&mp_type_AppArenaError);
+ }
+
+ return mp_obj_new_int(info.total_size);
+}
+static MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorapp_arena_mem_total_obj,
+ mod_trezorapp_arena_mem_total);
+
+/// def mem_free() -> int:
+/// """
+/// Return the free memory available in the app arena.
+/// """
+static mp_obj_t mod_trezorapp_arena_mem_free(void) {
+ app_arena_info_t info;
+ ts_t status = app_arena_get_info(&info);
+ if (ts_error(status)) {
+ mp_raise_type(&mp_type_AppArenaError);
+ }
+
+ return mp_obj_new_int(info.free_size);
+}
+static MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorapp_arena_mem_free_obj,
+ mod_trezorapp_arena_mem_free);
- ts_t status = app_cache_load_file(hash_ptr, filename);
+/// def root_update(root_packet: AnyBytes) -> None:
+/// """
+/// Update the root-of-trust storage with the provided root packet.
+/// The root packet is verified for integrity and validity before being
+/// stored. If the verification fails, an AppArenaError is raised.
+/// """
+static mp_obj_t mod_trezorapp_root_update(mp_obj_t root_packet_obj) {
+ mp_buffer_info_t root_packet_buf;
+ mp_get_buffer_raise(root_packet_obj, &root_packet_buf, MP_BUFFER_READ);
+
+ ts_t status = app_root_update(root_packet_buf.buf, root_packet_buf.len);
if (ts_error(status)) {
- mp_raise_msg(&mp_type_RuntimeError,
- MP_ERROR_TEXT("Failed to load app image from file"));
+ mp_raise_type(&mp_type_AppArenaError);
}
return mp_const_none;
}
-static MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorapp_load_file_obj,
- mod_trezorapp_load_file);
-#endif // TREZOR_EMULATOR
+static MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorapp_root_update_obj,
+ mod_trezorapp_root_update);
-static const mp_rom_map_elem_t mp_module_trezorapp_globals_table[] = {
- {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_trezorapp)},
+/// def root_is_loaded(ring: uint) -> bool:
+/// """
+/// Return True if a root-of-trust is present for the specified ring,
+/// otherwise return False.
+/// """
+static mp_obj_t mod_trezorapp_root_is_loaded(mp_obj_t ring_obj) {
+ mp_uint_t ring = mp_obj_get_uint(ring_obj);
+ return mp_obj_new_bool(app_root_is_loaded(ring));
+}
+static MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorapp_root_is_loaded_obj,
+ mod_trezorapp_root_is_loaded);
- {MP_ROM_QSTR(MP_QSTR_spawn_task),
- MP_ROM_PTR(&mod_trezorapp_spawn_task_obj)},
+/// def root_timestamp(ring: uint) -> int:
+/// """
+/// Return the timestamp of the root-of-trust for the specified ring.
+/// """
+static mp_obj_t mod_trezorapp_root_timestamp(mp_obj_t ring_obj) {
+ mp_uint_t ring = mp_obj_get_uint(ring_obj);
+
+ uint32_t timestamp = 0;
+
+ ts_t status = app_root_get_timestamp(ring, ×tamp);
+ if (ts_error(status)) {
+ mp_raise_type(&mp_type_AppArenaError);
+ }
+
+ return mp_obj_new_int(timestamp);
+}
+static MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorapp_root_timestamp_obj,
+ mod_trezorapp_root_timestamp);
+
+/// def app_ring_from_header(header: AnyBytes) -> uint:
+/// """
+/// Return the application privilege ring from the provided header.
+/// """
+static mp_obj_t mod_trezorapp_app_ring_from_header(mp_obj_t header_obj) {
+ mp_buffer_info_t header_buf;
+ mp_get_buffer_raise(header_obj, &header_buf, MP_BUFFER_READ);
+
+ uint8_t app_ring = 0;
+
+ ts_t status =
+ app_header_get_app_ring(header_buf.buf, header_buf.len, &app_ring);
+
+ if (ts_error(status)) {
+ mp_raise_type(&mp_type_AppArenaError);
+ }
+
+ return mp_obj_new_int(app_ring);
+}
+static MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorapp_app_ring_from_header_obj,
+ mod_trezorapp_app_ring_from_header);
+
+static const mp_rom_map_elem_t mod_module_trezorapp_globals_table[] = {
+ {MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_trezorapp)},
+ {MP_ROM_QSTR(MP_QSTR_AppImage), MP_ROM_PTR(&mod_trezorapp_AppImage_type)},
+ {MP_ROM_QSTR(MP_QSTR_AppError), MP_ROM_PTR(&mp_type_AppError)},
+ {MP_ROM_QSTR(MP_QSTR_AppImageError), MP_ROM_PTR(&mp_type_AppImageError)},
+ {MP_ROM_QSTR(MP_QSTR_AppImageNotFoundError),
+ MP_ROM_PTR(&mp_type_AppImageNotFoundError)},
+ {MP_ROM_QSTR(MP_QSTR_AppImageMemoryError),
+ MP_ROM_PTR(&mp_type_AppImageMemoryError)},
+ {MP_ROM_QSTR(MP_QSTR_AppImageVerificationError),
+ MP_ROM_PTR(&mp_type_AppImageVerificationError)},
+ {MP_ROM_QSTR(MP_QSTR_AppArenaError), MP_ROM_PTR(&mp_type_AppArenaError)},
{MP_ROM_QSTR(MP_QSTR_create_image),
MP_ROM_PTR(&mod_trezorapp_create_image_obj)},
-#ifdef TREZOR_EMULATOR
- {MP_ROM_QSTR(MP_QSTR_load_file), MP_ROM_PTR(&mod_trezorapp_load_file_obj)},
-#endif
+ {MP_ROM_QSTR(MP_QSTR_images), MP_ROM_PTR(&mod_trezorapp_images_obj)},
+ {MP_ROM_QSTR(MP_QSTR_image_count),
+ MP_ROM_PTR(&mod_trezorapp_arena_image_count_obj)},
+ {MP_ROM_QSTR(MP_QSTR_image_by_handle),
+ MP_ROM_PTR(&mod_trezorapp_arena_image_by_handle_obj)},
+ {MP_ROM_QSTR(MP_QSTR_clear_event),
+ MP_ROM_PTR(&mod_trezorapp_arena_clear_event_obj)},
+ {MP_ROM_QSTR(MP_QSTR_mem_total),
+ MP_ROM_PTR(&mod_trezorapp_arena_mem_total_obj)},
+ {MP_ROM_QSTR(MP_QSTR_mem_free),
+ MP_ROM_PTR(&mod_trezorapp_arena_mem_free_obj)},
+ {MP_ROM_QSTR(MP_QSTR_root_update),
+ MP_ROM_PTR(&mod_trezorapp_root_update_obj)},
+ {MP_ROM_QSTR(MP_QSTR_root_is_loaded),
+ MP_ROM_PTR(&mod_trezorapp_root_is_loaded_obj)},
+ {MP_ROM_QSTR(MP_QSTR_root_timestamp),
+ MP_ROM_PTR(&mod_trezorapp_root_timestamp_obj)},
+ {MP_ROM_QSTR(MP_QSTR_app_ring_from_header),
+ MP_ROM_PTR(&mod_trezorapp_app_ring_from_header_obj)},
};
-
static MP_DEFINE_CONST_DICT(mp_module_trezorapp_globals,
- mp_module_trezorapp_globals_table);
+ mod_module_trezorapp_globals_table);
const mp_obj_module_t mp_module_trezorapp = {
.base = {&mp_type_module},
@@ -149,4 +314,4 @@ const mp_obj_module_t mp_module_trezorapp = {
MP_REGISTER_MODULE(MP_QSTR_trezorapp, mp_module_trezorapp);
-#endif // MICROPY_PY_TREZORAPP
+#endif // USE_APP_LOADING
### core/embed/upymod/modtrezorio/modtrezorio-poll.h
@@ -24,6 +24,10 @@
#include <sys/sysevent.h>
#include <sys/systick.h>
+#ifdef USE_APP_LOADING
+#include <io/app_arena.h>
+#endif
+
#ifdef USE_BLE
#include <io/ble.h>
#endif
@@ -262,6 +266,15 @@ static mp_obj_t mod_trezorio_poll(mp_obj_t ifaces, mp_obj_t list_ref,
}
#endif
+#ifdef USE_APP_LOADING
+ if (signalled.read_ready & (1 << SYSHANDLE_APP_ARENA)) {
+ app_arena_clear_event();
+ ret->items[0] = MP_OBJ_NEW_SMALL_INT(SYSHANDLE_APP_ARENA);
+ ret->items[1] = mp_const_none;
+ return mp_const_true;
+ }
+#endif
+
if (signalled.read_ready & (1 << SYSHANDLE_USB)) {
usb_event_t event = usb_get_event();
ret->items[0] = MP_OBJ_NEW_SMALL_INT(SYSHANDLE_USB);
### core/embed/upymod/modtrezorio/modtrezorio.c
@@ -161,6 +161,9 @@ static const mp_rom_map_elem_t mp_module_trezorio_globals_table[] = {
#ifdef USE_IPC
{MP_ROM_QSTR(MP_QSTR_IPC2_EVENT), MP_ROM_INT(SYSHANDLE_IPC2)},
{MP_ROM_QSTR(MP_QSTR_ipc_send), MP_ROM_PTR(&mod_trezorio_ipc_send_obj)},
+#endif
+#ifdef USE_APP_LOADING
+ {MP_ROM_QSTR(MP_QSTR_APP_ARENA_EVENT), MP_ROM_INT(SYSHANDLE_APP_ARENA)},
#endif
{MP_ROM_QSTR(MP_QSTR_USB), MP_ROM_PTR(&mod_trezorio_USB_type)},
{MP_ROM_QSTR(MP_QSTR_USBIF), MP_ROM_PTR(&mod_trezorio_USBIF_type)},
### core/mocks/generated/trezorapp.pyi
@@ -0,0 +1,233 @@
+from typing import *
+from buffer_types import *
+
+
+# upymod/modtrezorapp/modtrezorapp-image.h
+class AppError(Exception):
+ """
+ Base exception for all trezorapp errors.
+ """
+
+
+# upymod/modtrezorapp/modtrezorapp-image.h
+class AppImageError(AppError):
+ """
+ Base exception for app image errors.
+ """
+
+
+# upymod/modtrezorapp/modtrezorapp-image.h
+class AppImageNotFoundError(AppImageError):
+ """
+ Raised when the AppImage handle is invalid or the image no longer
+ exists.
+ """
+
+
+# upymod/modtrezorapp/modtrezorapp-image.h
+class AppImageMemoryError(AppImageError):
+ """
+ Raised when there is not enough memory in the app arena.
+ """
+
+
+# upymod/modtrezorapp/modtrezorapp-image.h
+class AppImageVerificationError(AppImageError):
+ """
+ Raised when the app image data fails verification.
+ """
+
+
+# upymod/modtrezorapp/modtrezorapp-image.h
+class AppArenaError(AppError):
+ """
+ Raised when an app arena operation fails.
+ """
+
+
+# upymod/modtrezorapp/modtrezorapp-image.h
+class AppImage:
+ """
+ External application loaded in the app arena
+ """
+
+ def handle(self) -> int:
+ """
+ Return the image internal unique handle.
+ """
+
+ def task_id(self) -> int:
+ """
+ Return the task ID associated with the application image.
+ """
+
+ def is_running(self) -> bool:
+ """
+ Check if the application image is currently running.
+ """
+
+ def is_ready(self) -> bool:
+ """
+ Check if the application image has been fully loaded and verified.
+ """
+
+ def id(self) -> str:
+ """
+ Return the ID of the application image.
+ """
+
+ def size(self) -> int:
+ """
+ Return the size of the application image in bytes.
+ """
+
+ def chunk_size(self) -> int:
+ """
+ Return the expected size of each payload chunk in bytes.
+ """
+
+ def version(self) -> tuple[int, int, int, int]:
+ """
+ Return the version of the application image as a tuple (major, minor,
+ patch, build).
+ """
+
+ def name(self) -> str:
+ """
+ Return the name of the application.
+ """
+
+ def vendor(self) -> str:
+ """
+ Return the vendor of the application.
+ """
+
+ def ring(self) -> int:
+ """
+ Return the privilege ring of the application.
+ """
+
+ def header_hash(self) -> bytes:
+ """
+ Return the hash of the application image header.
+ """
+
+ def write_chunk(self, data: AnyBytes, hash: AnyBytes) -> None:
+ """
+ Write a chunk of image data into app-arena memory.
+ Allowed only while the image is in the loading state.
+ """
+
+ def delete(self) -> None:
+ """
+ Delete the application and release its resources.
+ If the image is currently running, it is stopped before
+ deletion. After deletion, the AppImage object is invalid
+ and must not be used.
+ """
+
+ def run(self) -> int:
+ """
+ Run the loaded application image and return its task ID.
+ If the image is already running, the function returns its task ID.
+ Only ready images are runnable.
+ """
+
+ def stop(self) -> None:
+ """
+ Stop the running application image. If the image is not running,
+ this operation has no effect.
+ """
+
+ def allowed_curves(self) -> Iterator[str]:
+ """
+ Return an iterator over the allowed curves
+ """
+
+ def allowed_paths(self) -> Iterator[str]:
+ """
+ Return an iterator over the allowed BIP32 path prefixes.
+ """
+
+
+# upymod/modtrezorapp/modtrezorapp.c
+def create_image(header: AnyBytes, proof: AnyBytes) -> AppImage:
+ """
+ Create a new application image from header and proof.
+ The returned handle can be used to load the rest of the
+ image content and run it.
+ """
+
+
+# upymod/modtrezorapp/modtrezorapp.c
+def images() -> Iterator[AppImage]:
+ """
+ Return an iterator over all app images in the app arena.
+ """
+
+
+# upymod/modtrezorapp/modtrezorapp.c
+def image_by_handle(handle: int) -> AppImage:
+ """
+ Return the application image with the specified handle.
+ """
+
+
+# upymod/modtrezorapp/modtrezorapp.c
+def clear_event() -> None:
+ """
+ Clear the pending event on the app arena, if any.
+ """
+
+
+# upymod/modtrezorapp/modtrezorapp.c
+def image_count() -> int:
+ """
+ Return the number of application images currently
+ loaded in the app arena.
+ """
+
+
+# upymod/modtrezorapp/modtrezorapp.c
+def mem_total() -> int:
+ """
+ Return the total memory available in the app arena.
+ """
+
+
+# upymod/modtrezorapp/modtrezorapp.c
+def mem_free() -> int:
+ """
+ Return the free memory available in the app arena.
+ """
+
+
+# upymod/modtrezorapp/modtrezorapp.c
+def root_update(root_packet: AnyBytes) -> None:
+ """
+ Update the root-of-trust storage with the provided root packet.
+ The root packet is verified for integrity and validity before being
+ stored. If the verification fails, an AppArenaError is raised.
+ """
+
+
+# upymod/modtrezorapp/modtrezorapp.c
+def root_is_loaded(ring: uint) -> bool:
+ """
+ Return True if a root-of-trust is present for the specified ring,
+ otherwise return False.
+ """
+
+
+# upymod/modtrezorapp/modtrezorapp.c
+def root_timestamp(ring: uint) -> int:
+ """
+ Return the timestamp of the root-of-trust for the specified ring.
+ """
+
+
+# upymod/modtrezorapp/modtrezorapp.c
+def app_ring_from_header(header: AnyBytes) -> uint:
+ """
+ Return the application privilege ring from the provided header.
+ """
### core/mocks/generated/trezorapp/__init__.pyi
@@ -1,64 +0,0 @@
-from typing import *
-from buffer_types import *
-
-
-# upymod/modtrezorapp/modtrezorapp-image.h
-class AppImage:
- """
- Application image image.
- """
-
- def write(self, offset: int, data: AnyBytes) -> None
- """
- Writes data to the application image at the specified offset.
- """
-
- def finalize(self, bool accept) -> None:
- """
- Finalizes loading of the application image. If `accept` is true,
- the image is marked as loaded and will be available for execution.
- If `accept` is false, the image is discarded.
- """
-
-
-# upymod/modtrezorapp/modtrezorapp-task.h
-class AppTask:
- """
- App task structure.
- """
-
- def id(self) -> int:
- """
- Returns the task id.
- """
-
- def is_running(self) -> bool:
- """
- Returns whether the application is still running.
- """
-
- def unload(self) -> None:
- """
- Unloads the application associated with this task.
- """
-
-
-# upymod/modtrezorapp/modtrezorapp.c
-def spawn_task(app_hash: bytes) -> AppTask:
- """
- Spawns an application task from the app cache.
- """
-
-
-# upymod/modtrezorapp/modtrezorapp.c
-def create_image(app_hash: bytes, size: int) -> AppImage:
- """
- Creates a new application image in the app cache.
- """
-
-
-# upymod/modtrezorapp/modtrezorapp.c
-def load_file(app_hash: bytes, filename: Str) -> None:
- """
- Loads an application image from a file into the app cache.
- """Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.