diff --git a/common/common_module.h b/common/common_module.h
new file mode 100644
index 0000000..1d3fb89
--- /dev/null
+++ b/common/common_module.h
@@ -0,0 +1,39 @@
+/*
+ * Common Module Header
+ * Copyright (C) 2018 M4xw
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 .
+*/
+
+#pragma once
+#include
+//TODO: Move it to BDK
+#include "common_gfx.h"
+#include "common_heap.h"
+
+// Module Callback
+typedef void (*cbMainModule_t)(const char *s);
+typedef void (*memcpy_t)(void *, void *, size_t);
+typedef void (*memset_t)(void *, int, size_t);
+
+typedef struct _bdkParams_t
+{
+ gfx_con_t *gfxCon;
+ gfx_ctxt_t *gfxCtx;
+ heap_t *sharedHeap;
+ memcpy_t memcpy;
+ memset_t memset;
+} *bdkParams_t;
+
+// Module Entrypoint
+typedef void (*moduleEntrypoint_t)(void *, bdkParams_t);
diff --git a/source/gfx/tui.c b/source/gfx/tui.c
index ed2357a..cd3cea6 100644
--- a/source/gfx/tui.c
+++ b/source/gfx/tui.c
@@ -147,13 +147,11 @@ void *tui_do_menu(menu_t *menu)
gfx_con_setcol(0xFF1B1B1B, 1, 0xFFCCCCCC);
else
gfx_con_setcol(0xFFCCCCCC, 1, 0xFF1B1B1B);
- // if (menu->ents[cnt].type == MENT_CAPTION)
- // gfx_printf("%k %s", menu->ents[cnt].color, menu->ents[cnt].caption);
- if (menu->ents[cnt].type != MENT_CHGLINE) {
+ if (menu->ents[cnt].type != MENT_CHGLINE && menu->ents[cnt].type != MENT_MENU) {
if (cnt == idx)
gfx_printf(" %s", menu->ents[cnt].caption);
else
- gfx_printf("%k %s", menu->ents[cnt].color, menu->ents[cnt].caption);//gfx_printf(" %s", menu->ents[cnt].caption);
+ gfx_printf("%k %s", menu->ents[cnt].color, menu->ents[cnt].caption);
}
if(menu->ents[cnt].type == MENT_MENU)
gfx_printf("%k...", 0xFF0099EE);
diff --git a/source/hos/sept.c b/source/hos/sept.c
index 3ec628e..f991cf9 100644
--- a/source/hos/sept.c
+++ b/source/hos/sept.c
@@ -56,6 +56,7 @@ u8 warmboot_reboot[] = {
#define SEPT_STG2_ADDR (SEPT_PK1T_ADDR + 0x60E0)
#define SEPT_PKG_SZ (0x2F100 + WB_RST_SIZE)
+extern u32 color_idx;
extern boot_cfg_t b_cfg;
extern void sd_unmount();
extern void reloc_patcher(u32 payload_dst, u32 payload_src, u32 payload_size);
@@ -115,7 +116,7 @@ int reboot_to_sept(const u8 *tsec_fw, const u32 tsec_size, const u32 kb)
f_close(&fp);
sd_unmount();
- gfx_printf("\n%kPress Power or Vol +/-\n%k to Reboot to Sept...", COLOR_BLUE, COLOR_VIOLET);
+ gfx_printf("\n%kPress Power or Vol +/-\n to Reboot to Sept...", colors[(color_idx++) % 6]);
btn_wait();
u32 pk1t_sept = SEPT_PK1T_ADDR - (ALIGN(PATCHED_RELOC_SZ, 0x10) + WB_RST_SIZE);
diff --git a/source/ianos/ianos.c b/source/ianos/ianos.c
new file mode 100644
index 0000000..18d4165
--- /dev/null
+++ b/source/ianos/ianos.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2018 M4xw
+ * Copyright (c) 2018-2019 CTCaer
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 .
+ */
+
+#include
+
+#include "ianos.h"
+#include "../utils/types.h"
+#include "../libs/elfload/elfload.h"
+#include "../../common/common_module.h"
+#include "../mem/heap.h"
+#include "../gfx/gfx.h"
+
+#define IRAM_LIB_ADDR 0x4002B000
+#define DRAM_LIB_ADDR 0xE0000000
+
+extern heap_t _heap;
+
+extern void *sd_file_read(const char *path, u32 *fsize);
+extern bool sd_mount();
+extern void sd_unmount();
+
+void *elfBuf = NULL;
+void *fileBuf = NULL;
+
+static void _ianos_call_ep(moduleEntrypoint_t entrypoint, void *moduleConfig)
+{
+ bdkParams_t bdkParameters = (bdkParams_t)malloc(sizeof(struct _bdkParams_t));
+ bdkParameters->gfxCon = &gfx_con;
+ bdkParameters->gfxCtx = &gfx_ctxt;
+ bdkParameters->memcpy = (memcpy_t)&memcpy;
+ bdkParameters->memset = (memset_t)&memset;
+ bdkParameters->sharedHeap = &_heap;
+
+ entrypoint(moduleConfig, bdkParameters);
+}
+
+static void *_ianos_alloc_cb(el_ctx *ctx, Elf_Addr phys, Elf_Addr virt, Elf_Addr size)
+{
+ (void)ctx;
+ (void)phys;
+ (void)size;
+ return (void *)virt;
+}
+
+static bool _ianos_read_cb(el_ctx *ctx, void *dest, size_t numberBytes, size_t offset)
+{
+ (void)ctx;
+
+ memcpy(dest, fileBuf + offset, numberBytes);
+
+ return true;
+}
+
+//TODO: Support shared libraries.
+uintptr_t ianos_loader(bool sdmount, char *path, elfType_t type, void *moduleConfig)
+{
+ uintptr_t epaddr = 0;
+
+ if (sdmount)
+ {
+ if (!sd_mount())
+ goto elfLoadFinalOut;
+ }
+
+ fileBuf = sd_file_read(path, NULL);
+
+ if (sdmount)
+ sd_unmount();
+
+ if (!fileBuf)
+ goto elfLoadFinalOut;
+
+
+ el_ctx ctx;
+ ctx.pread = _ianos_read_cb;
+
+ if (el_init(&ctx))
+ goto elfLoadFinalOut;
+
+ // Set our relocated library's buffer.
+ switch (type & 0xFFFF)
+ {
+ case EXEC_ELF:
+ case AR64_ELF:
+ elfBuf = (void *)DRAM_LIB_ADDR;
+ sd_unmount();
+ break;
+ default:
+ elfBuf = malloc(ctx.memsz); // Aligned to 0x10 by default.
+ }
+
+ if (!elfBuf)
+ goto elfLoadFinalOut;
+
+ // Load and relocate library.
+ ctx.base_load_vaddr = ctx.base_load_paddr = (uintptr_t)elfBuf;
+ if (el_load(&ctx, _ianos_alloc_cb))
+ goto elfFreeOut;
+
+ if (el_relocate(&ctx))
+ goto elfFreeOut;
+
+ // Launch.
+ epaddr = ctx.ehdr.e_entry + (uintptr_t)elfBuf;
+ moduleEntrypoint_t ep = (moduleEntrypoint_t)epaddr;
+
+ _ianos_call_ep(ep, moduleConfig);
+
+elfFreeOut:
+ free(fileBuf);
+ elfBuf = NULL;
+ fileBuf = NULL;
+
+elfLoadFinalOut:
+
+ return epaddr;
+}
\ No newline at end of file
diff --git a/source/ianos/ianos.h b/source/ianos/ianos.h
new file mode 100644
index 0000000..74d02c1
--- /dev/null
+++ b/source/ianos/ianos.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018 M4xw
+ * Copyright (c) 2018 CTCaer
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 .
+ */
+
+#ifndef IANOS_H
+#define IANOS_H
+
+#include "../utils/types.h"
+
+typedef enum
+{
+ DRAM_LIB = 0, // DRAM library.
+ EXEC_ELF = 1, // Executable elf that does not return.
+ DR64_LIB = 2, // AARCH64 DRAM library.
+ AR64_ELF = 3, // Executable elf that does not return.
+ KEEP_IN_RAM = (1 << 31) // Shared library mask.
+} elfType_t;
+
+uintptr_t ianos_loader(bool sdmount, char *path, elfType_t type, void* config);
+
+#endif
\ No newline at end of file
diff --git a/source/keys/keys.c b/source/keys/keys.c
index ca4b9f9..2af24cd 100644
--- a/source/keys/keys.c
+++ b/source/keys/keys.c
@@ -26,6 +26,7 @@
#include "../libs/fatfs/ff.h"
#include "../mem/heap.h"
#include "../mem/mc.h"
+#include "../mem/minerva.h"
#include "../mem/sdram.h"
#include "../sec/se.h"
#include "../sec/se_t210.h"
@@ -51,7 +52,8 @@ extern int sd_save_to_file(void *buf, u32 size, const char *filename);
extern hekate_config h_cfg;
-u32 _key_count = 0;
+u32 _key_count = 0, _titlekey_count = 0;
+u32 color_idx = 0;
sdmmc_storage_t storage;
emmc_part_t *system_part;
u32 start_time, end_time;
@@ -59,13 +61,17 @@ u32 start_time, end_time;
#define TPRINTF(text) \
end_time = get_tmr_us(); \
gfx_printf(text" done in %d us\n", end_time - start_time); \
- start_time = get_tmr_us()
+ start_time = get_tmr_us(); \
+ minerva_periodic_training()
+
#define TPRINTFARGS(text, args...) \
end_time = get_tmr_us(); \
gfx_printf(text" done in %d us\n", args, end_time - start_time); \
- start_time = get_tmr_us()
+ start_time = get_tmr_us(); \
+ minerva_periodic_training()
+
#define SAVE_KEY(name, src, len) _save_key(name, src, len, text_buffer)
-#define SAVE_KEY_FAMILY(name, src, count, len) _save_key_family(name, src, count, len, text_buffer)
+#define SAVE_KEY_FAMILY(name, src, start, count, len) _save_key_family(name, src, start, count, len, text_buffer)
static u8 temp_key[0x10],
bis_key[4][0x20] = {0},
@@ -94,27 +100,31 @@ static u8 temp_key[0x10],
titlekek[KB_FIRMWARE_VERSION_MAX+1][0x10] = {0};
// key functions
-static bool _key_exists(const void *data) { return memcmp(data, zeros, 0x10); };
-static void _save_key(const char *name, const void *data, const u32 len, char *outbuf);
-static void _save_key_family(const char *name, const void *data, const u32 num_keys, const u32 len, char *outbuf);
-static void _generate_kek(u32 ks, const void *key_source, void *master_key, const void *kek_seed, const void *key_seed);
+static bool _key_exists(const void *data) { return memcmp(data, zeros, 0x10); };
+static void _save_key(const char *name, const void *data, u32 len, char *outbuf);
+static void _save_key_family(const char *name, const void *data, u32 start_key, u32 num_keys, u32 len, char *outbuf);
+static void _generate_kek(u32 ks, const void *key_source, void *master_key, const void *kek_seed, const void *key_seed);
// nca functions
-static void *_nca_process(u32 hk_ks1, u32 hk_ks2, FIL *fp, u32 key_offset, u32 len);
-static u32 _nca_fread_ctr(u32 ks, FIL *fp, void *buffer, u32 offset, u32 len, u8 *ctr);
-static void _update_ctr(u8 *ctr, u32 ofs);
+static void *_nca_process(u32 hk_ks1, u32 hk_ks2, FIL *fp, u32 key_offset, u32 len);
+static u32 _nca_fread_ctr(u32 ks, FIL *fp, void *buffer, u32 offset, u32 len, u8 *ctr);
+static void _update_ctr(u8 *ctr, u32 ofs);
+// titlekey functions
+static bool _test_key_pair(const void *E, const void *D, const void *N);
+static void _mgf1_xor(void *masked, u32 masked_size, const void *seed, u32 seed_size);
void dump_keys() {
- display_backlight_brightness(100, 1000);
+ display_backlight_brightness(h_cfg.backlight, 1000);
gfx_clear_partial_grey(0x1B, 0, 1256);
gfx_con_setpos(0, 0);
gfx_printf("[%kLo%kck%kpi%kck%k_R%kCM%k v%d.%d.%d%k]\n\n",
colors[0], colors[1], colors[2], colors[3], colors[4], colors[5], 0xFFFF00FF, LP_VER_MJ, LP_VER_MN, LP_VER_BF, 0xFFCCCCCC);
+ tui_sbar(true);
+
start_time = get_tmr_us();
u32 begin_time = get_tmr_us();
u32 retries = 0;
- u32 color_idx = 0;
tsec_ctxt_t tsec_ctxt;
sdmmc_t sdmmc;
@@ -141,10 +151,12 @@ void dump_keys() {
}
}
if (!found_tsec_fw) {
- EPRINTF("Failed to locate TSEC firmware.");
+ EPRINTF("Unable to locate TSEC firmware.");
goto out_wait;
}
+ minerva_periodic_training();
+
tsec_key_data_t *key_data = (tsec_key_data_t *)(tsec_ctxt.fw + TSEC_KEY_DATA_ADDR);
tsec_ctxt.pkg1 = pkg1;
tsec_ctxt.size = 0x100 + key_data->blob0_size + key_data->blob1_size + key_data->blob2_size + key_data->blob3_size + key_data->blob4_size;
@@ -177,10 +189,10 @@ void dump_keys() {
u32 payload_size = *(u32 *)(IPL_LOAD_ADDR + 0x84) - IPL_LOAD_ADDR;
f_write(&fp, (u8 *)IPL_LOAD_ADDR, payload_size, NULL);
f_close(&fp);
- gfx_printf("%k\nFirmware 7.x or higher detected.\n%kRenamed /sept/payload.bin", colors[(color_idx) % 6], colors[(color_idx + 1) % 6]);
- color_idx += 2;
- gfx_printf("\n%k to /sept/payload.bak\n%kCopied self to /sept/payload.bin", colors[(color_idx) % 6], colors[(color_idx + 1) % 6]);
- color_idx += 2;
+ gfx_printf("%k\nFirmware 7.x or higher detected.\n\n", colors[(color_idx++) % 6]);
+ gfx_printf("%kRenamed /sept/payload.bin", colors[(color_idx++) % 6]);
+ gfx_printf("\n to /sept/payload.bak\n\n", colors[(color_idx++) % 6]);
+ gfx_printf("%kCopied self to /sept/payload.bin\n", colors[(color_idx++) % 6]);
sdmmc_storage_end(&storage);
if (!reboot_to_sept((u8 *)tsec_ctxt.fw, tsec_ctxt.size, pkg1_id->kb))
goto out_wait;
@@ -239,7 +251,8 @@ get_tsec: ;
se_aes_key_set(8, master_key[0], 0x10);
se_aes_crypt_block_ecb(8, 0, temp_key, mkey_vectors[0]);
if (_key_exists(temp_key)) {
- EPRINTFARGS("Failed to derive master key. kb = %d", pkg1_id->kb);
+ EPRINTFARGS("Unable to derive master key. kb = %d.\n Put current sept files on SD and retry.", pkg1_id->kb);
+ memset(master_key, 0, sizeof(master_key));
}
} else if (_key_exists(master_key[KB_FIRMWARE_VERSION_MAX])) {
// handle sept version differences
@@ -257,7 +270,8 @@ get_tsec: ;
memcpy(master_key[kb], zeros, 0x10);
}
if (_key_exists(temp_key)) {
- EPRINTF("Failed to derive master key.");
+ EPRINTF("Unable to derive master key.");
+ memset(master_key, 0, sizeof(master_key));
}
}
}
@@ -269,6 +283,7 @@ get_tsec: ;
se_aes_key_set(8, tsec_keys, 0x10);
se_aes_key_set(9, sbk, 0x10);
for (u32 i = 0; i <= KB_FIRMWARE_VERSION_600; i++) {
+ minerva_periodic_training();
se_aes_crypt_block_ecb(8, 0, keyblob_key[i], keyblob_key_source[i]); // temp = unwrap(kbks, tsec)
se_aes_crypt_block_ecb(9, 0, keyblob_key[i], keyblob_key[i]); // kbk = unwrap(temp, sbk)
se_aes_key_set(7, keyblob_key[i], 0x10);
@@ -305,7 +320,7 @@ get_tsec: ;
/* key = unwrap(source, wrapped_key):
key_set(ks, wrapped_key), block_ecb(ks, 0, key, source) -> final key in key
*/
-
+ minerva_periodic_training();
u32 key_generation = 0;
if (pkg1_id->kb >= KB_FIRMWARE_VERSION_500) {
if ((fuse_read_odm(4) & 0x800) && fuse_read_odm(0) == 0x8E61ECAE && fuse_read_odm(1) == 0xF2BA3BB2) {
@@ -346,7 +361,7 @@ get_tsec: ;
// Find package2 partition.
emmc_part_t *pkg2_part = nx_emmc_part_find(&gpt, "BCPKG2-1-Normal-Main");
if (!pkg2_part) {
- EPRINTF("Failed to locate Package2.");
+ EPRINTF("Unable to locate Package2.");
goto pkg2_done;
}
@@ -367,6 +382,7 @@ get_tsec: ;
nx_emmc_part_read(&storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE, pkg2_size_aligned / NX_EMMC_BLOCKSIZE, pkg2);
// Decrypt package2 and parse KIP1 blobs in INI1 section. Try all available key generations in case of pkg1/pkg2 mismatch.
+ minerva_periodic_training();
pkg2_hdr_t *pkg2_hdr;
pkg2_hdr_t hdr;
u32 pkg2_kb;
@@ -379,14 +395,14 @@ get_tsec: ;
break;
}
if (pkg2_kb == MAX_KEY) {
- EPRINTF("Failed to derive Package2 key.");
+ EPRINTF("Unable to derive Package2 key.");
goto pkg2_done;
} else if (pkg2_kb != pkg1_id->kb)
EPRINTFARGS("Warning! Package1-Package2 mismatch: %d, %d", pkg1_id->kb, pkg2_kb);
pkg2_hdr = pkg2_decrypt(pkg2);
if (!pkg2_hdr) {
- EPRINTF("Failed to decrypt Package2.");
+ EPRINTF("Unable to decrypt Package2.");
goto pkg2_done;
}
@@ -406,7 +422,7 @@ get_tsec: ;
free(CONTAINER_OF(iter, pkg2_kip1_info_t, link));
if (!ki) {
- EPRINTF("Failed to parse INI1.");
+ EPRINTF("Unable to parse INI1.");
goto pkg2_done;
}
@@ -485,6 +501,7 @@ get_tsec: ;
u8 temp_hash[0x20];
for (u32 i = ki->kip1->sections[0].size_comp + start_offset; i < ki->size - 0x20; ) {
+ minerva_periodic_training();
se_calc_sha256(temp_hash, ki->kip1->data + i, key_lengths[hash_order[hash_index]]);
if (!memcmp(temp_hash, fs_hashes_sha256[hash_order[hash_index]], 0x20)) {
memcpy(fs_keys[hash_order[hash_index]], ki->kip1->data + i, key_lengths[hash_order[hash_index]]);
@@ -504,11 +521,12 @@ get_tsec: ;
i += alignment;
}
}
-
pkg2_done:
free(pkg2);
free(ki);
+ u8 *rights_ids = NULL, *titlekeys = NULL;
+
TPRINTFARGS("%kFS keys... ", colors[(color_idx++) % 6]);
if (_key_exists(fs_keys[0]) && _key_exists(fs_keys[1]) && _key_exists(master_key[0])) {
@@ -539,7 +557,6 @@ pkg2_done:
se_aes_crypt_block_ecb(8, 0, titlekek[i], titlekek_source);
}
-
if (!_key_exists(header_key) || !_key_exists(bis_key[2]))
{
EPRINTF("Missing FS keys. Skipping ES/SSL keys.");
@@ -553,12 +570,12 @@ pkg2_done:
system_part = nx_emmc_part_find(&gpt, "SYSTEM");
if (!system_part) {
- EPRINTF("Failed to locate System partition.");
+ EPRINTF("Unable to locate System partition.");
goto key_output;
}
__attribute__ ((aligned (16))) FATFS emmc_fs;
if (f_mount(&emmc_fs, "emmc:", 1)) {
- EPRINTF("Mount failed.");
+ EPRINTF("Mount Unable.");
goto key_output;
}
@@ -574,7 +591,7 @@ pkg2_done:
u8 *temp_file = NULL;
if (f_opendir(&dir, path)) {
- EPRINTF("Failed to open System:/Contents/registered.");
+ EPRINTF("Unable to open System:/Contents/registered.");
goto dismount;
}
@@ -583,14 +600,14 @@ pkg2_done:
f_closedir(&dir);
if (f_opendir(&dir, path)) {
- EPRINTF("Failed to open System:/Contents/registered.");
+ EPRINTF("Unable to open System:/Contents/registered.");
goto dismount;
}
path[25] = '/';
start_offset = 0;
-
while (!f_readdir(&dir, &fno) && fno.fname[0] && titles_found < title_limit) {
+ minerva_periodic_training();
memcpy(path + 26, fno.fname, 36);
path[62] = 0;
if (fno.fattrib & AM_DIR)
@@ -711,6 +728,20 @@ pkg2_done:
f_closedir(&dir);
free(dec_header);
+ // derive eticket_rsa_kek and ssl_rsa_kek
+ if (_key_exists(es_keys[0]) && _key_exists(es_keys[1]) && _key_exists(master_key[0])) {
+ for (u32 i = 0; i < 0x10; i++)
+ temp_key[i] = aes_kek_generation_source[i] ^ aes_kek_seed_03[i];
+ _generate_kek(7, es_keys[1], master_key[0], temp_key, NULL);
+ se_aes_crypt_block_ecb(7, 0, eticket_rsa_kek, es_keys[0]);
+ }
+ if (_key_exists(ssl_keys[1]) && _key_exists(es_keys[2]) && _key_exists(master_key[0])) {
+ for (u32 i = 0; i < 0x10; i++)
+ temp_key[i] = aes_kek_generation_source[i] ^ aes_kek_seed_01[i];
+ _generate_kek(7, es_keys[2], master_key[0], temp_key, NULL);
+ se_aes_crypt_block_ecb(7, 0, ssl_rsa_kek, ssl_keys[1]);
+ }
+
if (memcmp(pkg1_id->id, "2016", 4)) {
TPRINTFARGS("%kES & SSL keys...", colors[(color_idx++) % 6]);
} else {
@@ -718,23 +749,22 @@ pkg2_done:
}
if (f_open(&fp, "sd:/Nintendo/Contents/private", FA_READ | FA_OPEN_EXISTING)) {
- EPRINTF("Unable to locate SD seed. Skipping.");
- goto dismount;
+ EPRINTF("Unable to open SD seed vector. Skipping.");
+ goto get_titlekeys;
}
// get sd seed verification vector
if (f_read(&fp, temp_key, 0x10, &read_bytes) || read_bytes != 0x10) {
- EPRINTF("Unable to locate SD seed. Skipping.");
+ EPRINTF("Unable to read SD seed vector. Skipping.");
f_close(&fp);
- goto dismount;
+ goto get_titlekeys;
}
f_close(&fp);
if (f_open(&fp, "emmc:/save/8000000000000043", FA_READ | FA_OPEN_EXISTING)) {
- EPRINTF("Failed to open ns_appman save.\nSkipping SD seed.");
- goto dismount;
+ EPRINTF("Unable to open ns_appman save.\nSkipping SD seed.");
+ goto get_titlekeys;
}
- // locate sd seed
u8 read_buf[0x20] = {0};
for (u32 i = 0x8000; i < f_size(&fp); i += 0x4000) {
if (f_lseek(&fp, i) || f_read(&fp, read_buf, 0x20, &read_bytes) || read_bytes != 0x20)
@@ -748,33 +778,188 @@ pkg2_done:
TPRINTFARGS("%kSD Seed... ", colors[(color_idx++) % 6]);
+get_titlekeys:
+ if (!_key_exists(eticket_rsa_kek))
+ goto dismount;
+
+ if (!minerva_cfg) {
+ gfx_printf("%k Minerva not found!\n This may take up to a minute...\n", colors[(color_idx++) % 6]);
+ gfx_printf(" For better performance, download Hekate\n and put bootloader/sys/libsys_minerva.bso\n on SD.\n");
+ }
+ gfx_printf("%kTitlekeys... ", colors[(color_idx++) % 6]);
+ u32 save_x = gfx_con.x, save_y = gfx_con.y;
+ gfx_printf("\n");
+
+ u8 null_hash[0x20] = {
+ 0xE3, 0xB0, 0xC4, 0x42, 0x98, 0xFC, 0x1C, 0x14, 0x9A, 0xFB, 0xF4, 0xC8, 0x99, 0x6F, 0xB9, 0x24,
+ 0x27, 0xAE, 0x41, 0xE4, 0x64, 0x9B, 0x93, 0x4C, 0xA4, 0x95, 0x99, 0x1B, 0x78, 0x52, 0xB8, 0x55};
+
+ se_aes_key_set(8, bis_key[0] + 0x00, 0x10);
+ se_aes_key_set(9, bis_key[0] + 0x10, 0x10);
+
+ u32 buf_size = 0x80000;
+ u8 *buffer = (u8 *)malloc(buf_size);
+
+ u8 keypair[0x230] = {0};
+
+ emummc_storage_read(&storage, 0x4400 / NX_EMMC_BLOCKSIZE, 0x4000 / NX_EMMC_BLOCKSIZE, buffer);
+
+ se_aes_xts_crypt(9, 8, 0, 0, buffer, buffer, 0x4000, 1);
+
+ se_aes_key_set(8, bis_key[2] + 0x00, 0x10);
+ se_aes_key_set(9, bis_key[2] + 0x10, 0x10);
+
+ if (*(u32 *)buffer != 0x304C4143) {
+ EPRINTF("CAL0 magic not found. Check BIS key 0.");
+ free(buffer);
+ goto dismount;
+ }
+
+ se_aes_key_set(2, eticket_rsa_kek, 0x10);
+ se_aes_crypt_ctr(2, keypair, 0x230, buffer + 0x38a0, 0x230, buffer + 0x3890);
+
+ u8 *D = keypair, *N = keypair + 0x100, *E = keypair + 0x200;
+
+ // Check public exponent is 0x10001 big endian
+ if (E[0] != 0 || E[1] != 1 || E[2] != 0 || E[3] != 1) {
+ EPRINTF("Invalid public exponent.");
+ free(buffer);
+ goto dismount;
+ }
+
+ if (!_test_key_pair(E, D, N)) {
+ EPRINTF("Invalid keypair. Check eticket_rsa_kek.");
+ free(buffer);
+ goto dismount;
+ }
+
+ se_rsa_key_set(0, N, 0x100, D, 0x100);
+
+ if (f_stat("emmc:/save/80000000000000E1", &fno)) {
+ EPRINTF("Unable to stat ES save 1. Skipping.");
+ free(buffer);
+ goto dismount;
+ }
+ u64 total_size = fno.fsize;
+ if (f_stat("emmc:/save/80000000000000E2", &fno)) {
+ EPRINTF("Unable to stat ES save 2. Skipping.");
+ free(buffer);
+ goto dismount;
+ }
+ total_size += fno.fsize;
+ u32 br;
+ u64 total_br = 0;
+ rights_ids = (u8 *)malloc(0x400000);
+ titlekeys = (u8 *)malloc(0x400000);
+ u8 M[0x100];
+ if (f_open(&fp, "emmc:/save/80000000000000E1", FA_READ | FA_OPEN_EXISTING)) {
+ EPRINTF("Unable to open ES save 1. Skipping.");
+ free(buffer);
+ goto dismount;
+ }
+ f_lseek(&fp, 0x8000);
+ u32 pct = 0, last_pct = 0;
+ tui_pbar(save_x, save_y, pct, COLOR_GREEN, 0xFF155500);
+
+ while (!f_read(&fp, buffer, buf_size, &br)) {
+ total_br += br;
+ for (u32 i = 0; i < br; i += 0x4000) {
+ pct = (u32)((total_br + i) * 100 / total_size);
+ if (pct > last_pct && pct <= 100) {
+ last_pct = pct;
+ tui_pbar(save_x, save_y, pct, COLOR_GREEN, 0xFF155500);
+ }
+ for (u32 j = i; j < i + 0x4000; j += 0x400) {
+ minerva_periodic_training();
+ if (buffer[j] == 4 && buffer[j+1] == 0 && buffer[j+2] == 1 && buffer[j+3] == 0) {
+ u32 k = 0;
+ bool titlekey_found = false;
+ for (; k < _titlekey_count; k++) {
+ if (!memcmp(rights_ids + 0x10 * k, buffer + j + 0x2a0, 0x10)) {
+ titlekey_found = true;
+ break;
+ }
+ }
+ if (titlekey_found)
+ continue;
+ memcpy(rights_ids + 0x10 * _titlekey_count, buffer + j + 0x2a0, 0x10);
+ memcpy(titlekeys + 0x10 * _titlekey_count, buffer + j + 0x180, 0x10);
+ _titlekey_count++;
+ } else {
+ break;
+ }
+ }
+ }
+ if (br < buf_size) break;
+ }
+
+ u32 common_titlekey_count = _titlekey_count;
+ if (f_open(&fp, "emmc:/save/80000000000000E2", FA_READ | FA_OPEN_EXISTING)) {
+ EPRINTF("Unable to open ES save 2. Skipping.");
+ free(buffer);
+ goto dismount;
+ }
+ f_lseek(&fp, 0x8000);
+ while (!f_read(&fp, buffer, buf_size, &br)) {
+ total_br += br;
+ for (u32 i = 0; i < br; i += 0x4000) {
+ pct = (u32)((total_br + i) * 100 / total_size);
+ if (pct > last_pct && pct <= 100) {
+ last_pct = pct;
+ tui_pbar(save_x, save_y, pct, COLOR_GREEN, 0xFF155500);
+ }
+ for (u32 j = i; j < i + 0x4000; j += 0x400) {
+ minerva_periodic_training();
+ if (buffer[j] == 4 && buffer[j+1] == 0 && buffer[j+2] == 1 && buffer[j+3] == 0) {
+ u32 k = common_titlekey_count;
+ bool titlekey_found = false;
+ for (; k < _titlekey_count; k++) {
+ if (!memcmp(rights_ids + 0x10 * k, buffer + j + 0x2a0, 0x10)) {
+ titlekey_found = true;
+ break;
+ }
+ }
+ if (titlekey_found)
+ continue;
+ memcpy(rights_ids + 0x10 * _titlekey_count, buffer + j + 0x2a0, 0x10);
+
+ u8 *titlekey_block = buffer + j + 0x180;
+ se_rsa_exp_mod(0, M, 0x100, titlekey_block, 0x100);
+ u8 *salt = M + 1;
+ u8 *db = M + 0x21;
+ _mgf1_xor(salt, 0x20, db, 0xdf);
+ _mgf1_xor(db, 0xdf, salt, 0x20);
+ if (memcmp(db, null_hash, 0x20))
+ continue;
+ memcpy(titlekeys + 0x10 * _titlekey_count, db + 0xcf, 0x10);
+ _titlekey_count++;
+ } else {
+ break;
+ }
+ }
+ }
+ if (br < buf_size) break;
+ }
+ free(buffer);
+ f_close(&fp);
+
+ gfx_con_setpos(0, save_y);
+ TPRINTFARGS("\n%k ", colors[(color_idx++) % 6]);
+ gfx_printf("\n%k Found %d titlekeys.\n", colors[(color_idx++) % 6], _titlekey_count);
+
dismount:
f_mount(NULL, "emmc:", 1);
nx_emmc_gpt_free(&gpt);
emummc_storage_end(&storage);
- // derive eticket_rsa_kek and ssl_rsa_kek
- if (_key_exists(es_keys[0]) && _key_exists(es_keys[1]) && _key_exists(master_key[0])) {
- for (u32 i = 0; i < 0x10; i++)
- temp_key[i] = aes_kek_generation_source[i] ^ aes_kek_seed_03[i];
- _generate_kek(8, es_keys[1], master_key[0], temp_key, NULL);
- se_aes_crypt_block_ecb(8, 0, eticket_rsa_kek, es_keys[0]);
- }
- if (_key_exists(ssl_keys[1]) && _key_exists(es_keys[2]) && _key_exists(master_key[0])) {
- for (u32 i = 0; i < 0x10; i++)
- temp_key[i] = aes_kek_generation_source[i] ^ aes_kek_seed_01[i];
- _generate_kek(8, es_keys[2], master_key[0], temp_key, NULL);
- se_aes_crypt_block_ecb(8, 0, ssl_rsa_kek, ssl_keys[1]);
- }
-
key_output: ;
- __attribute__ ((aligned (16))) char text_buffer[0x3000] = {0};
+ char *text_buffer = (char *)malloc(_titlekey_count * 68 < 0x3000 ? 0x3000 : _titlekey_count * 68 + 1);
SAVE_KEY("aes_kek_generation_source", aes_kek_generation_source, 0x10);
SAVE_KEY("aes_key_generation_source", aes_key_generation_source, 0x10);
SAVE_KEY("bis_kek_source", bis_kek_source, 0x10);
- SAVE_KEY_FAMILY("bis_key", bis_key, 4, 0x20);
- SAVE_KEY_FAMILY("bis_key_source", bis_key_source, 3, 0x20);
+ SAVE_KEY_FAMILY("bis_key", bis_key, 0, 4, 0x20);
+ SAVE_KEY_FAMILY("bis_key_source", bis_key_source, 0, 3, 0x20);
SAVE_KEY("device_key", device_key, 0x10);
SAVE_KEY("eticket_rsa_kek", eticket_rsa_kek, 0x10);
SAVE_KEY("eticket_rsa_kek_source", es_keys[0], 0x10);
@@ -782,26 +967,23 @@ key_output: ;
SAVE_KEY("header_kek_source", fs_keys[0], 0x10);
SAVE_KEY("header_key", header_key, 0x20);
SAVE_KEY("header_key_source", fs_keys[1], 0x20);
- SAVE_KEY_FAMILY("key_area_key_application", key_area_key[0], MAX_KEY, 0x10);
+ SAVE_KEY_FAMILY("key_area_key_application", key_area_key[0], 0, MAX_KEY, 0x10);
SAVE_KEY("key_area_key_application_source", fs_keys[2], 0x10);
- SAVE_KEY_FAMILY("key_area_key_ocean", key_area_key[1], MAX_KEY, 0x10);
+ SAVE_KEY_FAMILY("key_area_key_ocean", key_area_key[1], 0, MAX_KEY, 0x10);
SAVE_KEY("key_area_key_ocean_source", fs_keys[3], 0x10);
- SAVE_KEY_FAMILY("key_area_key_system", key_area_key[2], MAX_KEY, 0x10);
+ SAVE_KEY_FAMILY("key_area_key_system", key_area_key[2], 0, MAX_KEY, 0x10);
SAVE_KEY("key_area_key_system_source", fs_keys[4], 0x10);
- SAVE_KEY_FAMILY("keyblob", keyblob, 6, 0x90);
- SAVE_KEY_FAMILY("keyblob_key", keyblob_key, 6, 0x10);
- SAVE_KEY_FAMILY("keyblob_key_source", keyblob_key_source, 6, 0x10);
- SAVE_KEY_FAMILY("keyblob_mac_key", keyblob_mac_key, 6, 0x10);
+ SAVE_KEY_FAMILY("keyblob", keyblob, 0, 6, 0x90);
+ SAVE_KEY_FAMILY("keyblob_key", keyblob_key, 0, 6, 0x10);
+ SAVE_KEY_FAMILY("keyblob_key_source", keyblob_key_source, 0, 6, 0x10);
+ SAVE_KEY_FAMILY("keyblob_mac_key", keyblob_mac_key, 0, 6, 0x10);
SAVE_KEY("keyblob_mac_key_source", keyblob_mac_key_source, 0x10);
- SAVE_KEY_FAMILY("master_kek", master_kek, MAX_KEY, 0x10);
- SAVE_KEY("master_kek_source_06", master_kek_sources[0], 0x10);
- SAVE_KEY("master_kek_source_07", master_kek_sources[1], 0x10);
- SAVE_KEY("master_kek_source_08", master_kek_sources[2], 0x10);
- SAVE_KEY("master_kek_source_09", master_kek_sources[3], 0x10);
- SAVE_KEY_FAMILY("master_key", master_key, MAX_KEY, 0x10);
+ SAVE_KEY_FAMILY("master_kek", master_kek, 0, MAX_KEY, 0x10);
+ SAVE_KEY_FAMILY("master_kek_source", master_kek_sources, KB_FIRMWARE_VERSION_620, sizeof(master_kek_sources) / 0x10, 0x10);
+ SAVE_KEY_FAMILY("master_key", master_key, 0, MAX_KEY, 0x10);
SAVE_KEY("master_key_source", master_key_source, 0x10);
- SAVE_KEY_FAMILY("package1_key", package1_key, 6, 0x10);
- SAVE_KEY_FAMILY("package2_key", package2_key, MAX_KEY, 0x10);
+ SAVE_KEY_FAMILY("package1_key", package1_key, 0, 6, 0x10);
+ SAVE_KEY_FAMILY("package2_key", package2_key, 0, MAX_KEY, 0x10);
SAVE_KEY("package2_key_source", package2_key_source, 0x10);
SAVE_KEY("per_console_key_source", per_console_key_source, 0x10);
SAVE_KEY("retail_specific_aes_key_source", retail_specific_aes_key_source, 0x10);
@@ -822,7 +1004,7 @@ key_output: ;
SAVE_KEY("ssl_rsa_kek", ssl_rsa_kek, 0x10);
SAVE_KEY("ssl_rsa_kek_source_x", es_keys[2], 0x10);
SAVE_KEY("ssl_rsa_kek_source_y", ssl_keys[1], 0x10);
- SAVE_KEY_FAMILY("titlekek", titlekek, MAX_KEY, 0x10);
+ SAVE_KEY_FAMILY("titlekek", titlekek, 0, MAX_KEY, 0x10);
SAVE_KEY("titlekek_source", titlekek_source, 0x10);
SAVE_KEY("tsec_key", tsec_keys, 0x10);
if (pkg1_id->kb == KB_FIRMWARE_VERSION_620)
@@ -831,10 +1013,10 @@ key_output: ;
//gfx_con.fntsz = 8; gfx_puts(text_buffer); gfx_con.fntsz = 16;
end_time = get_tmr_us();
- gfx_printf("\n%kFound %d keys.", colors[(color_idx++) % 6], _key_count);
+ gfx_printf("\n%k Found %d keys.\n\n", colors[(color_idx++) % 6], _key_count);
_key_count = 0;
- gfx_printf("\n%kLockpick totally done in %d us", colors[(color_idx++) % 6], end_time - begin_time);
- gfx_printf("\n%kFound through master_key_%02x\n", colors[(color_idx++) % 6], MAX_KEY - 1);
+ gfx_printf("%kLockpick totally done in %d us\n\n", colors[(color_idx++) % 6], end_time - begin_time);
+ gfx_printf("%kFound through master_key_%02x.\n\n", colors[(color_idx++) % 6], MAX_KEY - 1);
f_mkdir("sd:/switch");
char keyfile_path[30] = "sd:/switch/";
@@ -845,17 +1027,36 @@ key_output: ;
if (sd_mount() && !sd_save_to_file(text_buffer, strlen(text_buffer), keyfile_path) && !f_stat(keyfile_path, &fno)) {
gfx_printf("%kWrote %d bytes to %s\n", colors[(color_idx++) % 6], (u32)fno.fsize, keyfile_path);
} else
- EPRINTF("Failed to save keys to SD.");
- h_cfg.emummc_force_disable = emummc_load_cfg();
+ EPRINTF("Unable to save keys to SD.");
+
+ if (_titlekey_count == 0)
+ goto out_wait;
+ memset(text_buffer, 0, _titlekey_count * 68 + 1);
+ for (u32 i = 0; i < _titlekey_count; i++) {
+ for (u32 j = 0; j < 0x10; j++)
+ sprintf(&text_buffer[i * 68 + j * 2], "%02x", rights_ids[i * 0x10 + j]);
+ sprintf(&text_buffer[i * 68 + 0x20], " = ");
+ for (u32 j = 0; j < 0x10; j++)
+ sprintf(&text_buffer[i * 68 + 0x23 + j * 2], "%02x", titlekeys[i * 0x10 + j]);
+ sprintf(&text_buffer[i * 68 + 0x43], "\n");
+ }
+ sprintf(&keyfile_path[11], "title.keys");
+ if (sd_mount() && !sd_save_to_file(text_buffer, strlen(text_buffer), keyfile_path) && !f_stat(keyfile_path, &fno)) {
+ gfx_printf("%kWrote %d bytes to %s\n", colors[(color_idx++) % 6], (u32)fno.fsize, keyfile_path);
+ } else
+ EPRINTF("Unable to save titlekeys to SD.");
+ free(rights_ids);
+ free(titlekeys);
+ free(text_buffer);
out_wait:
+ h_cfg.emummc_force_disable = emummc_load_cfg();
sd_unmount();
gfx_printf("\n%kPress any key to return to the main menu.", colors[(color_idx) % 6], colors[(color_idx + 1) % 6], colors[(color_idx + 2) % 6]);
-
btn_wait();
}
-static void _save_key(const char *name, const void *data, const u32 len, char *outbuf) {
+static void _save_key(const char *name, const void *data, u32 len, char *outbuf) {
if (!_key_exists(data))
return;
u32 pos = strlen(outbuf);
@@ -866,9 +1067,9 @@ static void _save_key(const char *name, const void *data, const u32 len, char *o
_key_count++;
}
-static void _save_key_family(const char *name, const void *data, const u32 num_keys, const u32 len, char *outbuf) {
+static void _save_key_family(const char *name, const void *data, u32 start_key, u32 num_keys, u32 len, char *outbuf) {
char temp_name[0x40] = {0};
- for (u32 i = 0; i < num_keys; i++) {
+ for (u32 i = start_key; i < num_keys + start_key; i++) {
sprintf(temp_name, "%s_%02x", name, i);
_save_key(temp_name, data + i * len, len, outbuf);
}
@@ -950,3 +1151,45 @@ static void _update_ctr(u8 *ctr, u32 ofs) {
for (u32 i = 0; i < 4; i++, ofs >>= 8)
ctr[0x10-i-1] = (u8)(ofs & 0xff);
}
+
+static bool _test_key_pair(const void *E, const void *D, const void *N) {
+ u8 X[0x100] = {0}, Y[0x100] = {0}, Z[0x100] = {0};
+
+ // 0xCAFEBABE
+ X[0xfc] = 0xca; X[0xfd] = 0xfe; X[0xfe] = 0xba; X[0xff] = 0xbe;
+ se_rsa_key_set(0, N, 0x100, D, 0x100);
+ se_rsa_exp_mod(0, Y, 0x100, X, 0x100);
+ se_rsa_key_set(0, N, 0x100, E, 4);
+ se_rsa_exp_mod(0, Z, 0x100, Y, 0x100);
+
+ return !memcmp(X, Z, 0x100);
+}
+
+// _mgf1_xor() was derived from Atmosphère's calculate_mgf1_and_xor
+static void _mgf1_xor(void *masked, u32 masked_size, const void *seed, u32 seed_size) {
+ u8 cur_hash[0x20];
+ u8 hash_buf[0xe4];
+
+ u32 hash_buf_size = seed_size + 4;
+ memcpy(hash_buf, seed, seed_size);
+ u32 round_num = 0;
+
+ u8 *p_out = (u8 *)masked;
+
+ while (masked_size) {
+ u32 cur_size = masked_size > 0x20 ? 0x20 : masked_size;
+
+ for (u32 i = 0; i < 4; i++)
+ hash_buf[seed_size + 3 - i] = (round_num >> (8 * i)) & 0xff;
+ round_num++;
+
+ se_calc_sha256(cur_hash, hash_buf, hash_buf_size);
+
+ for (unsigned int i = 0; i < cur_size; i++) {
+ *p_out ^= cur_hash[i];
+ p_out++;
+ }
+
+ masked_size -= cur_size;
+ }
+}
diff --git a/source/libs/elfload/elf.h b/source/libs/elfload/elf.h
new file mode 100644
index 0000000..196cf87
--- /dev/null
+++ b/source/libs/elfload/elf.h
@@ -0,0 +1,589 @@
+/* $OpenBSD: exec_elf.h,v 1.53 2014/01/03 03:00:39 guenther Exp $ */
+/*
+ * Copyright (c) 1995, 1996 Erik Theisen. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* imported sys/exec_elf.h from OpenBSD */
+
+#ifndef ELF_H
+#define ELF_H
+#include
+
+typedef uint8_t Elf_Byte;
+
+typedef uint32_t Elf32_Addr; /* Unsigned program address */
+typedef uint32_t Elf32_Off; /* Unsigned file offset */
+typedef int32_t Elf32_Sword; /* Signed large integer */
+typedef uint32_t Elf32_Word; /* Unsigned large integer */
+typedef uint16_t Elf32_Half; /* Unsigned medium integer */
+
+typedef uint64_t Elf64_Addr;
+typedef uint64_t Elf64_Off;
+typedef int32_t Elf64_Shalf;
+
+#ifdef __alpha__
+typedef int64_t Elf64_Sword;
+typedef uint64_t Elf64_Word;
+#else
+typedef int32_t Elf64_Sword;
+typedef uint32_t Elf64_Word;
+#endif
+
+typedef int64_t Elf64_Sxword;
+typedef uint64_t Elf64_Xword;
+
+typedef uint32_t Elf64_Half;
+typedef uint16_t Elf64_Quarter;
+
+/*
+ * e_ident[] identification indexes
+ * See http://www.sco.com/developers/gabi/latest/ch4.eheader.html
+ */
+#define EI_MAG0 0 /* file ID */
+#define EI_MAG1 1 /* file ID */
+#define EI_MAG2 2 /* file ID */
+#define EI_MAG3 3 /* file ID */
+#define EI_CLASS 4 /* file class */
+#define EI_DATA 5 /* data encoding */
+#define EI_VERSION 6 /* ELF header version */
+#define EI_OSABI 7 /* OS/ABI ID */
+#define EI_ABIVERSION 8 /* ABI version */
+#define EI_PAD 9 /* start of pad bytes */
+#define EI_NIDENT 16 /* Size of e_ident[] */
+
+/* e_ident[] magic number */
+#define ELFMAG0 0x7f /* e_ident[EI_MAG0] */
+#define ELFMAG1 'E' /* e_ident[EI_MAG1] */
+#define ELFMAG2 'L' /* e_ident[EI_MAG2] */
+#define ELFMAG3 'F' /* e_ident[EI_MAG3] */
+#define ELFMAG "\177ELF" /* magic */
+#define SELFMAG 4 /* size of magic */
+
+/* e_ident[] file class */
+#define ELFCLASSNONE 0 /* invalid */
+#define ELFCLASS32 1 /* 32-bit objs */
+#define ELFCLASS64 2 /* 64-bit objs */
+#define ELFCLASSNUM 3 /* number of classes */
+
+/* e_ident[] data encoding */
+#define ELFDATANONE 0 /* invalid */
+#define ELFDATA2LSB 1 /* Little-Endian */
+#define ELFDATA2MSB 2 /* Big-Endian */
+#define ELFDATANUM 3 /* number of data encode defines */
+
+/* e_ident[] Operating System/ABI */
+#define ELFOSABI_SYSV 0 /* UNIX System V ABI */
+#define ELFOSABI_HPUX 1 /* HP-UX operating system */
+#define ELFOSABI_NETBSD 2 /* NetBSD */
+#define ELFOSABI_LINUX 3 /* GNU/Linux */
+#define ELFOSABI_HURD 4 /* GNU/Hurd */
+#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */
+#define ELFOSABI_SOLARIS 6 /* Solaris */
+#define ELFOSABI_MONTEREY 7 /* Monterey */
+#define ELFOSABI_IRIX 8 /* IRIX */
+#define ELFOSABI_FREEBSD 9 /* FreeBSD */
+#define ELFOSABI_TRU64 10 /* TRU64 UNIX */
+#define ELFOSABI_MODESTO 11 /* Novell Modesto */
+#define ELFOSABI_OPENBSD 12 /* OpenBSD */
+#define ELFOSABI_ARM 97 /* ARM */
+#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
+
+/* e_ident */
+#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \
+ (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \
+ (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \
+ (ehdr).e_ident[EI_MAG3] == ELFMAG3)
+
+/* ELF Header */
+typedef struct
+{
+ unsigned char e_ident[EI_NIDENT]; /* ELF Identification */
+ Elf32_Half e_type; /* object file type */
+ Elf32_Half e_machine; /* machine */
+ Elf32_Word e_version; /* object file version */
+ Elf32_Addr e_entry; /* virtual entry point */
+ Elf32_Off e_phoff; /* program header table offset */
+ Elf32_Off e_shoff; /* section header table offset */
+ Elf32_Word e_flags; /* processor-specific flags */
+ Elf32_Half e_ehsize; /* ELF header size */
+ Elf32_Half e_phentsize; /* program header entry size */
+ Elf32_Half e_phnum; /* number of program header entries */
+ Elf32_Half e_shentsize; /* section header entry size */
+ Elf32_Half e_shnum; /* number of section header entries */
+ Elf32_Half e_shstrndx; /* section header table's "section
+ header string table" entry offset */
+} Elf32_Ehdr;
+
+typedef struct
+{
+ unsigned char e_ident[EI_NIDENT]; /* Id bytes */
+ Elf64_Quarter e_type; /* file type */
+ Elf64_Quarter e_machine; /* machine type */
+ Elf64_Half e_version; /* version number */
+ Elf64_Addr e_entry; /* entry point */
+ Elf64_Off e_phoff; /* Program hdr offset */
+ Elf64_Off e_shoff; /* Section hdr offset */
+ Elf64_Half e_flags; /* Processor flags */
+ Elf64_Quarter e_ehsize; /* sizeof ehdr */
+ Elf64_Quarter e_phentsize; /* Program header entry size */
+ Elf64_Quarter e_phnum; /* Number of program headers */
+ Elf64_Quarter e_shentsize; /* Section header entry size */
+ Elf64_Quarter e_shnum; /* Number of section headers */
+ Elf64_Quarter e_shstrndx; /* String table index */
+} Elf64_Ehdr;
+
+/* e_type */
+#define ET_NONE 0 /* No file type */
+#define ET_REL 1 /* relocatable file */
+#define ET_EXEC 2 /* executable file */
+#define ET_DYN 3 /* shared object file */
+#define ET_CORE 4 /* core file */
+#define ET_NUM 5 /* number of types */
+#define ET_LOPROC 0xff00 /* reserved range for processor */
+#define ET_HIPROC 0xffff /* specific e_type */
+
+/* e_machine */
+#define EM_NONE 0 /* No Machine */
+#define EM_M32 1 /* AT&T WE 32100 */
+#define EM_SPARC 2 /* SPARC */
+#define EM_386 3 /* Intel 80386 */
+#define EM_68K 4 /* Motorola 68000 */
+#define EM_88K 5 /* Motorola 88000 */
+#define EM_486 6 /* Intel 80486 - unused? */
+#define EM_860 7 /* Intel 80860 */
+#define EM_MIPS 8 /* MIPS R3000 Big-Endian only */
+/*
+ * Don't know if EM_MIPS_RS4_BE,
+ * EM_SPARC64, EM_PARISC,
+ * or EM_PPC are ABI compliant
+ */
+#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */
+#define EM_SPARC64 11 /* SPARC v9 64-bit unofficial */
+#define EM_PARISC 15 /* HPPA */
+#define EM_SPARC32PLUS 18 /* Enhanced instruction set SPARC */
+#define EM_PPC 20 /* PowerPC */
+#define EM_ARM 40 /* ARM AArch32 */
+#define EM_ALPHA 41 /* DEC ALPHA */
+#define EM_SH 42 /* Hitachi/Renesas Super-H */
+#define EM_SPARCV9 43 /* SPARC version 9 */
+#define EM_IA_64 50 /* Intel IA-64 Processor */
+#define EM_AMD64 62 /* AMD64 architecture */
+#define EM_VAX 75 /* DEC VAX */
+#define EM_AARCH64 183 /* ARM AArch64 */
+
+/* Non-standard */
+#define EM_ALPHA_EXP 0x9026 /* DEC ALPHA */
+
+/* Version */
+#define EV_NONE 0 /* Invalid */
+#define EV_CURRENT 1 /* Current */
+#define EV_NUM 2 /* number of versions */
+
+/* Section Header */
+typedef struct
+{
+ Elf32_Word sh_name; /* name - index into section header
+ * string table section */
+ Elf32_Word sh_type; /* type */
+ Elf32_Word sh_flags; /* flags */
+ Elf32_Addr sh_addr; /* address */
+ Elf32_Off sh_offset; /* file offset */
+ Elf32_Word sh_size; /* section size */
+ Elf32_Word sh_link; /* section header table index link */
+ Elf32_Word sh_info; /* extra information */
+ Elf32_Word sh_addralign; /* address alignment */
+ Elf32_Word sh_entsize; /* section entry size */
+} Elf32_Shdr;
+
+typedef struct
+{
+ Elf64_Half sh_name; /* section name */
+ Elf64_Half sh_type; /* section type */
+ Elf64_Xword sh_flags; /* section flags */
+ Elf64_Addr sh_addr; /* virtual address */
+ Elf64_Off sh_offset; /* file offset */
+ Elf64_Xword sh_size; /* section size */
+ Elf64_Half sh_link; /* link to another */
+ Elf64_Half sh_info; /* misc info */
+ Elf64_Xword sh_addralign; /* memory alignment */
+ Elf64_Xword sh_entsize; /* table entry size */
+} Elf64_Shdr;
+
+/* Special Section Indexes */
+#define SHN_UNDEF 0 /* undefined */
+#define SHN_LORESERVE 0xff00 /* lower bounds of reserved indexes */
+#define SHN_LOPROC 0xff00 /* reserved range for processor */
+#define SHN_HIPROC 0xff1f /* specific section indexes */
+#define SHN_ABS 0xfff1 /* absolute value */
+#define SHN_COMMON 0xfff2 /* common symbol */
+#define SHN_HIRESERVE 0xffff /* upper bounds of reserved indexes */
+
+/* sh_type */
+#define SHT_NULL 0 /* inactive */
+#define SHT_PROGBITS 1 /* program defined information */
+#define SHT_SYMTAB 2 /* symbol table section */
+#define SHT_STRTAB 3 /* string table section */
+#define SHT_RELA 4 /* relocation section with addends*/
+#define SHT_HASH 5 /* symbol hash table section */
+#define SHT_DYNAMIC 6 /* dynamic section */
+#define SHT_NOTE 7 /* note section */
+#define SHT_NOBITS 8 /* no space section */
+#define SHT_REL 9 /* relation section without addends */
+#define SHT_SHLIB 10 /* reserved - purpose unknown */
+#define SHT_DYNSYM 11 /* dynamic symbol table section */
+#define SHT_NUM 12 /* number of section types */
+#define SHT_LOPROC 0x70000000 /* reserved range for processor */
+#define SHT_HIPROC 0x7fffffff /* specific section header types */
+#define SHT_LOUSER 0x80000000 /* reserved range for application */
+#define SHT_HIUSER 0xffffffff /* specific indexes */
+
+/* Section names */
+#define ELF_BSS ".bss" /* uninitialized data */
+#define ELF_DATA ".data" /* initialized data */
+#define ELF_DEBUG ".debug" /* debug */
+#define ELF_DYNAMIC ".dynamic" /* dynamic linking information */
+#define ELF_DYNSTR ".dynstr" /* dynamic string table */
+#define ELF_DYNSYM ".dynsym" /* dynamic symbol table */
+#define ELF_FINI ".fini" /* termination code */
+#define ELF_GOT ".got" /* global offset table */
+#define ELF_HASH ".hash" /* symbol hash table */
+#define ELF_INIT ".init" /* initialization code */
+#define ELF_REL_DATA ".rel.data" /* relocation data */
+#define ELF_REL_FINI ".rel.fini" /* relocation termination code */
+#define ELF_REL_INIT ".rel.init" /* relocation initialization code */
+#define ELF_REL_DYN ".rel.dyn" /* relocation dynamic link info */
+#define ELF_REL_RODATA ".rel.rodata" /* relocation read-only data */
+#define ELF_REL_TEXT ".rel.text" /* relocation code */
+#define ELF_RODATA ".rodata" /* read-only data */
+#define ELF_SHSTRTAB ".shstrtab" /* section header string table */
+#define ELF_STRTAB ".strtab" /* string table */
+#define ELF_SYMTAB ".symtab" /* symbol table */
+#define ELF_TEXT ".text" /* code */
+
+/* Section Attribute Flags - sh_flags */
+#define SHF_WRITE 0x1 /* Writable */
+#define SHF_ALLOC 0x2 /* occupies memory */
+#define SHF_EXECINSTR 0x4 /* executable */
+#define SHF_TLS 0x400 /* thread local storage */
+#define SHF_MASKPROC 0xf0000000 /* reserved bits for processor \
+ * specific section attributes */
+
+/* Symbol Table Entry */
+typedef struct elf32_sym
+{
+ Elf32_Word st_name; /* name - index into string table */
+ Elf32_Addr st_value; /* symbol value */
+ Elf32_Word st_size; /* symbol size */
+ unsigned char st_info; /* type and binding */
+ unsigned char st_other; /* 0 - no defined meaning */
+ Elf32_Half st_shndx; /* section header index */
+} Elf32_Sym;
+
+typedef struct
+{
+ Elf64_Half st_name; /* Symbol name index in str table */
+ Elf_Byte st_info; /* type / binding attrs */
+ Elf_Byte st_other; /* unused */
+ Elf64_Quarter st_shndx; /* section index of symbol */
+ Elf64_Xword st_value; /* value of symbol */
+ Elf64_Xword st_size; /* size of symbol */
+} Elf64_Sym;
+
+/* Symbol table index */
+#define STN_UNDEF 0 /* undefined */
+
+/* Extract symbol info - st_info */
+#define ELF32_ST_BIND(x) ((x) >> 4)
+#define ELF32_ST_TYPE(x) (((unsigned int)x) & 0xf)
+#define ELF32_ST_INFO(b, t) (((b) << 4) + ((t)&0xf))
+
+#define ELF64_ST_BIND(x) ((x) >> 4)
+#define ELF64_ST_TYPE(x) (((unsigned int)x) & 0xf)
+#define ELF64_ST_INFO(b, t) (((b) << 4) + ((t)&0xf))
+
+/* Symbol Binding - ELF32_ST_BIND - st_info */
+#define STB_LOCAL 0 /* Local symbol */
+#define STB_GLOBAL 1 /* Global symbol */
+#define STB_WEAK 2 /* like global - lower precedence */
+#define STB_NUM 3 /* number of symbol bindings */
+#define STB_LOPROC 13 /* reserved range for processor */
+#define STB_HIPROC 15 /* specific symbol bindings */
+
+/* Symbol type - ELF32_ST_TYPE - st_info */
+#define STT_NOTYPE 0 /* not specified */
+#define STT_OBJECT 1 /* data object */
+#define STT_FUNC 2 /* function */
+#define STT_SECTION 3 /* section */
+#define STT_FILE 4 /* file */
+#define STT_TLS 6 /* thread local storage */
+#define STT_LOPROC 13 /* reserved range for processor */
+#define STT_HIPROC 15 /* specific symbol types */
+
+/* Relocation entry with implicit addend */
+typedef struct
+{
+ Elf32_Addr r_offset; /* offset of relocation */
+ Elf32_Word r_info; /* symbol table index and type */
+} Elf32_Rel;
+
+/* Relocation entry with explicit addend */
+typedef struct
+{
+ Elf32_Addr r_offset; /* offset of relocation */
+ Elf32_Word r_info; /* symbol table index and type */
+ Elf32_Sword r_addend;
+} Elf32_Rela;
+
+/* Extract relocation info - r_info */
+#define ELF32_R_SYM(i) ((i) >> 8)
+#define ELF32_R_TYPE(i) ((unsigned char)(i))
+#define ELF32_R_INFO(s, t) (((s) << 8) + (unsigned char)(t))
+
+typedef struct
+{
+ Elf64_Xword r_offset; /* where to do it */
+ Elf64_Xword r_info; /* index & type of relocation */
+} Elf64_Rel;
+
+typedef struct
+{
+ Elf64_Xword r_offset; /* where to do it */
+ Elf64_Xword r_info; /* index & type of relocation */
+ Elf64_Sxword r_addend; /* adjustment value */
+} Elf64_Rela;
+
+#define ELF64_R_SYM(info) ((info) >> 32)
+#define ELF64_R_TYPE(info) ((info)&0xFFFFFFFF)
+#define ELF64_R_INFO(s, t) (((s) << 32) + (__uint32_t)(t))
+
+#if defined(__mips64__) && defined(__MIPSEL__)
+/*
+ * The 64-bit MIPS ELF ABI uses a slightly different relocation format
+ * than the regular ELF ABI: the r_info field is split into several
+ * pieces (see gnu/usr.bin/binutils/include/elf/mips.h for details).
+ */
+#undef ELF64_R_SYM
+#undef ELF64_R_TYPE
+#undef ELF64_R_INFO
+#define ELF64_R_TYPE(info) (swap32((info) >> 32))
+#define ELF64_R_SYM(info) ((info)&0xFFFFFFFF)
+#define ELF64_R_INFO(s, t) (((__uint64_t)swap32(t) << 32) + (__uint32_t)(s))
+#endif /* __mips64__ && __MIPSEL__ */
+
+/* Program Header */
+typedef struct
+{
+ Elf32_Word p_type; /* segment type */
+ Elf32_Off p_offset; /* segment offset */
+ Elf32_Addr p_vaddr; /* virtual address of segment */
+ Elf32_Addr p_paddr; /* physical address - ignored? */
+ Elf32_Word p_filesz; /* number of bytes in file for seg. */
+ Elf32_Word p_memsz; /* number of bytes in mem. for seg. */
+ Elf32_Word p_flags; /* flags */
+ Elf32_Word p_align; /* memory alignment */
+} Elf32_Phdr;
+
+typedef struct
+{
+ Elf64_Half p_type; /* entry type */
+ Elf64_Half p_flags; /* flags */
+ Elf64_Off p_offset; /* offset */
+ Elf64_Addr p_vaddr; /* virtual address */
+ Elf64_Addr p_paddr; /* physical address */
+ Elf64_Xword p_filesz; /* file size */
+ Elf64_Xword p_memsz; /* memory size */
+ Elf64_Xword p_align; /* memory & file alignment */
+} Elf64_Phdr;
+
+/* Segment types - p_type */
+#define PT_NULL 0 /* unused */
+#define PT_LOAD 1 /* loadable segment */
+#define PT_DYNAMIC 2 /* dynamic linking section */
+#define PT_INTERP 3 /* the RTLD */
+#define PT_NOTE 4 /* auxiliary information */
+#define PT_SHLIB 5 /* reserved - purpose undefined */
+#define PT_PHDR 6 /* program header */
+#define PT_TLS 7 /* thread local storage */
+#define PT_LOOS 0x60000000 /* reserved range for OS */
+#define PT_HIOS 0x6fffffff /* specific segment types */
+#define PT_LOPROC 0x70000000 /* reserved range for processor */
+#define PT_HIPROC 0x7fffffff /* specific segment types */
+
+#define PT_OPENBSD_RANDOMIZE 0x65a3dbe6 /* fill with random data */
+#define PT_GANDR_KERNEL 0x67646b6c /* gdkl */
+
+/* Segment flags - p_flags */
+#define PF_X 0x1 /* Executable */
+#define PF_W 0x2 /* Writable */
+#define PF_R 0x4 /* Readable */
+#define PF_MASKPROC 0xf0000000 /* reserved bits for processor */
+ /* specific segment flags */
+
+/* Dynamic structure */
+typedef struct
+{
+ Elf32_Sword d_tag; /* controls meaning of d_val */
+ union {
+ Elf32_Word d_val; /* Multiple meanings - see d_tag */
+ Elf32_Addr d_ptr; /* program virtual address */
+ } d_un;
+} Elf32_Dyn;
+
+typedef struct
+{
+ Elf64_Xword d_tag; /* controls meaning of d_val */
+ union {
+ Elf64_Addr d_ptr;
+ Elf64_Xword d_val;
+ } d_un;
+} Elf64_Dyn;
+
+/* Dynamic Array Tags - d_tag */
+#define DT_NULL 0 /* marks end of _DYNAMIC array */
+#define DT_NEEDED 1 /* string table offset of needed lib */
+#define DT_PLTRELSZ 2 /* size of relocation entries in PLT */
+#define DT_PLTGOT 3 /* address PLT/GOT */
+#define DT_HASH 4 /* address of symbol hash table */
+#define DT_STRTAB 5 /* address of string table */
+#define DT_SYMTAB 6 /* address of symbol table */
+#define DT_RELA 7 /* address of relocation table */
+#define DT_RELASZ 8 /* size of relocation table */
+#define DT_RELAENT 9 /* size of relocation entry */
+#define DT_STRSZ 10 /* size of string table */
+#define DT_SYMENT 11 /* size of symbol table entry */
+#define DT_INIT 12 /* address of initialization func. */
+#define DT_FINI 13 /* address of termination function */
+#define DT_SONAME 14 /* string table offset of shared obj */
+#define DT_RPATH 15 /* string table offset of library \
+ * search path */
+#define DT_SYMBOLIC 16 /* start sym search in shared obj. */
+#define DT_REL 17 /* address of rel. tbl. w addends */
+#define DT_RELSZ 18 /* size of DT_REL relocation table */
+#define DT_RELENT 19 /* size of DT_REL relocation entry */
+#define DT_PLTREL 20 /* PLT referenced relocation entry */
+#define DT_DEBUG 21 /* bugger */
+#define DT_TEXTREL 22 /* Allow rel. mod. to unwritable seg */
+#define DT_JMPREL 23 /* add. of PLT's relocation entries */
+#define DT_BIND_NOW 24 /* Bind now regardless of env setting */
+#define DT_LOOS 0x6000000d /* reserved range for OS */
+#define DT_HIOS 0x6ffff000 /* specific dynamic array tags */
+#define DT_LOPROC 0x70000000 /* reserved range for processor */
+#define DT_HIPROC 0x7fffffff /* specific dynamic array tags */
+
+/* some other useful tags */
+#define DT_RELACOUNT 0x6ffffff9 /* if present, number of RELATIVE */
+#define DT_RELCOUNT 0x6ffffffa /* relocs, which must come first */
+#define DT_FLAGS_1 0x6ffffffb
+
+/* Dynamic Flags - DT_FLAGS_1 .dynamic entry */
+#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_CONLFAT 0x00002000
+
+/* ld.so: number of low tags that are used saved internally (0 .. DT_NUM-1) */
+#define DT_NUM (DT_JMPREL + 1)
+
+/*
+ * Note Definitions
+ */
+typedef struct
+{
+ Elf32_Word namesz;
+ Elf32_Word descsz;
+ Elf32_Word type;
+} Elf32_Note;
+
+typedef struct
+{
+ Elf64_Half namesz;
+ Elf64_Half descsz;
+ Elf64_Half type;
+} Elf64_Note;
+
+#if defined(ELFSIZE) && (ELFSIZE == 32)
+#define Elf_Ehdr Elf32_Ehdr
+#define Elf_Phdr Elf32_Phdr
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define Elf_Rel Elf32_Rel
+#define Elf_RelA Elf32_Rela
+#define Elf_Dyn Elf32_Dyn
+#define Elf_Half Elf32_Half
+#define Elf_Word Elf32_Word
+#define Elf_Sword Elf32_Sword
+#define Elf_Addr Elf32_Addr
+#define Elf_Off Elf32_Off
+#define Elf_Nhdr Elf32_Nhdr
+#define Elf_Note Elf32_Note
+
+#define ELF_R_SYM ELF32_R_SYM
+#define ELF_R_TYPE ELF32_R_TYPE
+#define ELF_R_INFO ELF32_R_INFO
+#define ELFCLASS ELFCLASS32
+
+#define ELF_ST_BIND ELF32_ST_BIND
+#define ELF_ST_TYPE ELF32_ST_TYPE
+#define ELF_ST_INFO ELF32_ST_INFO
+
+#elif defined(ELFSIZE) && (ELFSIZE == 64)
+
+#define Elf_Ehdr Elf64_Ehdr
+#define Elf_Phdr Elf64_Phdr
+#define Elf_Shdr Elf64_Shdr
+#define Elf_Sym Elf64_Sym
+#define Elf_Rel Elf64_Rel
+#define Elf_RelA Elf64_Rela
+#define Elf_Dyn Elf64_Dyn
+#define Elf_Half Elf64_Half
+#define Elf_Word Elf64_Word
+#define Elf_Sword Elf64_Sword
+#define Elf_Addr Elf64_Addr
+#define Elf_Off Elf64_Off
+#define Elf_Nhdr Elf64_Nhdr
+#define Elf_Note Elf64_Note
+
+#define ELF_R_SYM ELF64_R_SYM
+#define ELF_R_TYPE ELF64_R_TYPE
+#define ELF_R_INFO ELF64_R_INFO
+#define ELFCLASS ELFCLASS64
+
+#define ELF_ST_BIND ELF64_ST_BIND
+#define ELF_ST_TYPE ELF64_ST_TYPE
+#define ELF_ST_INFO ELF64_ST_INFO
+
+#endif
+
+#endif
diff --git a/source/libs/elfload/elfarch.h b/source/libs/elfload/elfarch.h
new file mode 100644
index 0000000..f1cc388
--- /dev/null
+++ b/source/libs/elfload/elfarch.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright © 2014, Owen Shepherd
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ELFARCH_H
+#define ELFARCH_H
+
+#if defined(__i386__)
+#define EM_THIS EM_386
+#define EL_ARCH_USES_REL
+#elif defined(__amd64__)
+#define EM_THIS EM_AMD64
+#define EL_ARCH_USES_RELA
+#elif defined(__arm__)
+#define EM_THIS EM_ARM
+#define EL_ARCH_USES_REL
+#elif defined(__aarch64__)
+#define EM_THIS EM_AARCH64
+#define EL_ARCH_USES_RELA
+#define EL_ARCH_USES_REL
+#else
+#error specify your ELF architecture
+#endif
+
+#if defined(__LP64__) || defined(__LLP64__)
+#define ELFSIZE 64
+#else
+#define ELFSIZE 32
+#endif
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#define ELFDATATHIS ELFDATA2LSB
+#else
+#define ELFDATATHIS ELFDATA2MSB
+#endif
+
+#endif
diff --git a/source/libs/elfload/elfload.c b/source/libs/elfload/elfload.c
new file mode 100644
index 0000000..16f8200
--- /dev/null
+++ b/source/libs/elfload/elfload.c
@@ -0,0 +1,324 @@
+/*
+ * Copyright © 2018, M4xw
+ * Copyright © 2014, Owen Shepherd
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include
+
+#include "elfload.h"
+
+el_status el_pread(el_ctx *ctx, void *def, size_t nb, size_t offset)
+{
+ return ctx->pread(ctx, def, nb, offset) ? EL_OK : EL_EIO;
+}
+
+#define EL_PHOFF(ctx, num) (((ctx)->ehdr.e_phoff + (num) *(ctx)->ehdr.e_phentsize))
+el_status el_findphdr(el_ctx *ctx, Elf_Phdr *phdr, uint32_t type, unsigned *i)
+{
+ el_status rv = EL_OK;
+ for (; *i < ctx->ehdr.e_phnum; (*i)++)
+ {
+ if ((rv = el_pread(ctx, phdr, sizeof *phdr, EL_PHOFF(ctx, *i))))
+ return rv;
+
+ if (phdr->p_type == type)
+ {
+ return rv;
+ }
+ }
+
+ *i = -1;
+ return rv;
+}
+
+#define EL_SHOFF(ctx, num) (((ctx)->ehdr.e_shoff + (num) *(ctx)->ehdr.e_shentsize))
+el_status el_findshdr(el_ctx *ctx, Elf_Shdr *shdr, uint32_t type, unsigned *i)
+{
+ el_status rv = EL_OK;
+
+ for (; *i < ctx->ehdr.e_shnum; (*i)++)
+ {
+ if ((rv = el_pread(ctx, shdr, sizeof *shdr, EL_SHOFF(ctx, *i))))
+
+ return rv;
+
+ if (shdr->sh_type == type)
+ {
+ return rv;
+ }
+ }
+
+ *i = -1;
+
+ return rv;
+}
+
+el_status el_init(el_ctx *ctx)
+{
+ el_status rv = EL_OK;
+ if ((rv = el_pread(ctx, &ctx->ehdr, sizeof ctx->ehdr, 0)))
+ return rv;
+
+ /* validate header */
+
+ if (!IS_ELF(ctx->ehdr))
+ return EL_NOTELF;
+
+ if (ctx->ehdr.e_ident[EI_CLASS] != ELFCLASS)
+ return EL_WRONGBITS;
+
+ if (ctx->ehdr.e_ident[EI_DATA] != ELFDATATHIS)
+ return EL_WRONGENDIAN;
+
+ if (ctx->ehdr.e_ident[EI_VERSION] != EV_CURRENT)
+ return EL_NOTELF;
+
+ if (ctx->ehdr.e_type != ET_EXEC && ctx->ehdr.e_type != ET_DYN)
+ return EL_NOTEXEC;
+
+ if (ctx->ehdr.e_machine != EM_THIS)
+ return EL_WRONGARCH;
+
+ if (ctx->ehdr.e_version != EV_CURRENT)
+ return EL_NOTELF;
+
+ /* load phdrs */
+ Elf_Phdr ph;
+
+ /* iterate through, calculate extents */
+ ctx->base_load_paddr = ctx->base_load_vaddr = 0;
+ ctx->align = 1;
+ ctx->memsz = 0;
+
+ unsigned i = 0;
+ for (;;)
+ {
+ if ((rv = el_findphdr(ctx, &ph, PT_LOAD, &i)))
+ return rv;
+
+ if (i == (unsigned)-1)
+ break;
+
+ Elf_Addr phend = ph.p_vaddr + ph.p_memsz;
+ if (phend > ctx->memsz)
+ ctx->memsz = phend;
+
+ if (ph.p_align > ctx->align)
+ ctx->align = ph.p_align;
+
+ i++;
+ }
+
+ // Program Header
+ if (ctx->ehdr.e_type == ET_DYN)
+ {
+ i = 0;
+
+ if ((rv = el_findphdr(ctx, &ph, PT_DYNAMIC, &i)))
+ return rv;
+
+ if (i == (unsigned)-1)
+ return EL_NODYN;
+
+ ctx->dynoff = ph.p_offset;
+ ctx->dynsize = ph.p_filesz;
+ }
+ else
+ {
+ ctx->dynoff = 0;
+ ctx->dynsize = 0;
+ }
+
+ // Section String Table
+ if (ctx->ehdr.e_type == ET_DYN)
+ {
+ i = ctx->ehdr.e_shstrndx - 1;
+
+ if ((rv = el_findshdr(ctx, &ctx->shstr, SHT_STRTAB, &i)))
+ return rv;
+
+ // Reset
+ i = 0;
+
+ if ((rv = el_findshdr(ctx, &ctx->symtab, SHT_SYMTAB, &i)))
+ return rv;
+
+ if (i == (unsigned)-1)
+ return EL_NODYN;
+ }
+
+ return rv;
+}
+
+/*
+typedef void* (*el_alloc_cb)(
+ el_ctx *ctx,
+ Elf_Addr phys,
+ Elf_Addr virt,
+ Elf_Addr size);
+*/
+
+el_status el_load(el_ctx *ctx, el_alloc_cb alloc)
+{
+ el_status rv = EL_OK;
+
+ /* address deltas */
+ Elf_Addr pdelta = ctx->base_load_paddr;
+ Elf_Addr vdelta = ctx->base_load_vaddr;
+
+ /* iterate paddrs */
+ Elf_Phdr ph;
+ unsigned i = 0;
+ for (;;)
+ {
+ if ((rv = el_findphdr(ctx, &ph, PT_LOAD, &i)))
+ return rv;
+
+ if (i == (unsigned)-1)
+ break;
+
+ Elf_Addr pload = ph.p_paddr + pdelta;
+ Elf_Addr vload = ph.p_vaddr + vdelta;
+
+ /* allocate mem */
+ char *dest = alloc(ctx, pload, vload, ph.p_memsz);
+ if (!dest)
+ return EL_ENOMEM;
+
+ EL_DEBUG("Loading seg fileoff %x, vaddr %x to %p\n",
+ ph.p_offset, ph.p_vaddr, dest);
+
+ /* read loaded portion */
+ if ((rv = el_pread(ctx, dest, ph.p_filesz, ph.p_offset)))
+ return rv;
+
+ /* zero mem-only portion */
+ memset(dest + ph.p_filesz, 0, ph.p_memsz - ph.p_filesz);
+
+ i++;
+ }
+
+ return rv;
+}
+
+el_status el_finddyn(el_ctx *ctx, Elf_Dyn *dyn, uint32_t tag)
+{
+ el_status rv = EL_OK;
+ size_t ndyn = ctx->dynsize / sizeof(Elf_Dyn);
+
+ for (unsigned i = 0; i < ndyn; i++)
+ {
+ if ((rv = el_pread(ctx, dyn, sizeof *dyn, ctx->dynoff + i * sizeof *dyn)))
+ return rv;
+
+ if (dyn->d_tag == tag)
+ return EL_OK;
+ }
+
+ dyn->d_tag = DT_NULL;
+ return EL_OK;
+}
+
+el_status el_findrelocs(el_ctx *ctx, el_relocinfo *ri, uint32_t type)
+{
+ el_status rv = EL_OK;
+
+ Elf_Dyn rel, relsz, relent;
+
+ if ((rv = el_finddyn(ctx, &rel, type)))
+ return rv;
+
+ if ((rv = el_finddyn(ctx, &relsz, type + 1)))
+ return rv;
+
+ if ((rv = el_finddyn(ctx, &relent, type + 2)))
+ return rv;
+
+ if (rel.d_tag == DT_NULL || relsz.d_tag == DT_NULL || relent.d_tag == DT_NULL)
+ {
+ ri->entrysize = 0;
+ ri->tablesize = 0;
+ ri->tableoff = 0;
+ }
+ else
+ {
+ ri->tableoff = rel.d_un.d_ptr;
+ ri->tablesize = relsz.d_un.d_val;
+ ri->entrysize = relent.d_un.d_val;
+ }
+
+ return rv;
+}
+
+extern el_status el_applyrel(el_ctx *ctx, Elf_Rel *rel);
+extern el_status el_applyrela(el_ctx *ctx, Elf_RelA *rela);
+
+el_status el_relocate(el_ctx *ctx)
+{
+ el_status rv = EL_OK;
+
+ // not dynamic
+ if (ctx->ehdr.e_type != ET_DYN)
+ return EL_OK;
+
+ char *base = (char *)ctx->base_load_paddr;
+
+ el_relocinfo ri;
+#ifdef EL_ARCH_USES_REL
+ if ((rv = el_findrelocs(ctx, &ri, DT_REL)))
+ return rv;
+
+ if (ri.entrysize != sizeof(Elf_Rel) && ri.tablesize)
+ {
+ EL_DEBUG("Relocation size %u doesn't match expected %u\n",
+ ri.entrysize, sizeof(Elf_Rel));
+ return EL_BADREL;
+ }
+
+ size_t relcnt = ri.tablesize / sizeof(Elf_Rel);
+ Elf_Rel *reltab = (Elf_Rel *)(base + ri.tableoff);
+ for (size_t i = 0; i < relcnt; i++)
+ {
+ if ((rv = el_applyrel(ctx, &reltab[i])))
+ return rv;
+ }
+#endif
+
+#ifdef EL_ARCH_USES_RELA
+ if ((rv = el_findrelocs(ctx, &ri, DT_RELA)))
+ return rv;
+
+ if (ri.entrysize != sizeof(Elf_RelA) && ri.tablesize)
+ {
+ EL_DEBUG("Relocation size %u doesn't match expected %u\n",
+ ri.entrysize, sizeof(Elf_RelA));
+ return EL_BADREL;
+ }
+
+ size_t relacnt = ri.tablesize / sizeof(Elf_RelA);
+ Elf_RelA *relatab = (Elf_RelA *)(base + ri.tableoff);
+ for (size_t i = 0; i < relacnt; i++)
+ {
+ if ((rv = el_applyrela(ctx, &relatab[i])))
+ return rv;
+ }
+#endif
+
+#if !defined(EL_ARCH_USES_REL) && !defined(EL_ARCH_USES_RELA)
+#error No relocation type defined!
+#endif
+
+ return rv;
+}
diff --git a/source/libs/elfload/elfload.h b/source/libs/elfload/elfload.h
new file mode 100644
index 0000000..3a15dc2
--- /dev/null
+++ b/source/libs/elfload/elfload.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright © 2018, M4xw
+ * Copyright © 2014, Owen Shepherd
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef ELFLOAD_H
+#define ELFLOAD_H
+#include
+
+#include "elfarch.h"
+#include "elf.h"
+
+#include "../../utils/types.h"
+
+#ifdef DEBUG
+#include "../../gfx/gfx.h"
+#define EL_DEBUG(format, ...) \
+ gfx_printf(format __VA_OPT__(, ) __VA_ARGS__)
+#else
+#define EL_DEBUG(...) \
+ do \
+ { \
+ } while (0)
+#endif
+
+typedef enum
+{
+ EL_OK = 0,
+
+ EL_EIO,
+ EL_ENOMEM,
+
+ EL_NOTELF,
+ EL_WRONGBITS,
+ EL_WRONGENDIAN,
+ EL_WRONGARCH,
+ EL_WRONGOS,
+ EL_NOTEXEC,
+ EL_NODYN,
+ EL_BADREL,
+
+} el_status;
+
+typedef struct el_ctx
+{
+ bool (*pread)(struct el_ctx *ctx, void *dest, size_t nb, size_t offset);
+
+ /* base_load_* -> address we are actually going to load at
+ */
+ Elf_Addr
+ base_load_paddr,
+ base_load_vaddr;
+
+ /* size in memory of binary */
+ Elf_Addr memsz;
+
+ /* required alignment */
+ Elf_Addr align;
+
+ /* ELF header */
+ Elf_Ehdr ehdr;
+
+ // Section Header Str Table
+ Elf_Shdr shstr;
+ Elf_Shdr symtab;
+
+ /* Offset of dynamic table (0 if not ET_DYN) */
+ Elf_Off dynoff;
+ /* Size of dynamic table (0 if not ET_DYN) */
+ Elf_Addr dynsize;
+} el_ctx;
+
+el_status el_pread(el_ctx *ctx, void *def, size_t nb, size_t offset);
+
+el_status el_init(el_ctx *ctx);
+typedef void *(*el_alloc_cb)(
+ el_ctx *ctx,
+ Elf_Addr phys,
+ Elf_Addr virt,
+ Elf_Addr size);
+
+el_status el_load(el_ctx *ctx, el_alloc_cb alloccb);
+
+/* find the next phdr of type \p type, starting at \p *i.
+ * On success, returns EL_OK with *i set to the phdr number, and the phdr loaded
+ * in *phdr.
+ *
+ * If the end of the phdrs table was reached, *i is set to -1 and the contents
+ * of *phdr are undefined
+ */
+el_status el_findphdr(el_ctx *ctx, Elf_Phdr *phdr, uint32_t type, unsigned *i);
+
+/* Relocate the loaded executable */
+el_status el_relocate(el_ctx *ctx);
+
+/* find a dynamic table entry
+ * returns the entry on success, dyn->d_tag = DT_NULL on failure
+ */
+el_status el_finddyn(el_ctx *ctx, Elf_Dyn *dyn, uint32_t type);
+
+typedef struct
+{
+ Elf_Off tableoff;
+ Elf_Addr tablesize;
+ Elf_Addr entrysize;
+} el_relocinfo;
+
+/* find all information regarding relocations of a specific type.
+ *
+ * pass DT_REL or DT_RELA for type
+ * sets ri->entrysize = 0 if not found
+ */
+el_status el_findrelocs(el_ctx *ctx, el_relocinfo *ri, uint32_t type);
+
+#endif
diff --git a/source/libs/elfload/elfreloc_aarch64.c b/source/libs/elfload/elfreloc_aarch64.c
new file mode 100644
index 0000000..bbb0ce4
--- /dev/null
+++ b/source/libs/elfload/elfreloc_aarch64.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright © 2014, Owen Shepherd
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "elfload.h"
+
+#if defined(__aarch64__)
+
+#define R_AARCH64_NONE 0
+#define R_AARCH64_RELATIVE 1027
+
+el_status el_applyrela(el_ctx *ctx, Elf_RelA *rel)
+{
+ uintptr_t *p = (uintptr_t *)(rel->r_offset + ctx->base_load_paddr);
+ uint32_t type = ELF_R_TYPE(rel->r_info);
+ uint32_t sym = ELF_R_SYM(rel->r_info);
+
+ switch (type)
+ {
+ case R_AARCH64_NONE:
+ EL_DEBUG("R_AARCH64_NONE\n");
+ break;
+ case R_AARCH64_RELATIVE:
+ if (sym)
+ {
+ EL_DEBUG("R_AARCH64_RELATIVE with symbol ref!\n");
+ return EL_BADREL;
+ }
+
+ EL_DEBUG("Applying R_AARCH64_RELATIVE reloc @%p\n", p);
+ *p = rel->r_addend + ctx->base_load_vaddr;
+ break;
+
+ default:
+ EL_DEBUG("Bad relocation %u\n", type);
+ return EL_BADREL;
+ }
+
+ return EL_OK;
+}
+
+el_status el_applyrel(el_ctx *ctx, Elf_Rel *rel)
+{
+ uintptr_t *p = (uintptr_t *)(rel->r_offset + ctx->base_load_paddr);
+ uint32_t type = ELF_R_TYPE(rel->r_info);
+ uint32_t sym = ELF_R_SYM(rel->r_info);
+
+ switch (type)
+ {
+ case R_AARCH64_NONE:
+ EL_DEBUG("R_AARCH64_NONE\n");
+ break;
+ case R_AARCH64_RELATIVE:
+ if (sym)
+ {
+ EL_DEBUG("R_AARCH64_RELATIVE with symbol ref!\n");
+ return EL_BADREL;
+ }
+
+ EL_DEBUG("Applying R_AARCH64_RELATIVE reloc @%p\n", p);
+ *p += ctx->base_load_vaddr;
+ break;
+
+ default:
+ EL_DEBUG("Bad relocation %u\n", type);
+ return EL_BADREL;
+ }
+
+ return EL_OK;
+}
+
+#endif
diff --git a/source/libs/elfload/elfreloc_arm.c b/source/libs/elfload/elfreloc_arm.c
new file mode 100644
index 0000000..8b905cb
--- /dev/null
+++ b/source/libs/elfload/elfreloc_arm.c
@@ -0,0 +1,66 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * wrote this file. As long as you retain this notice you can do
+ * whatever you want with this stuff. If we meet some day, and you think this
+ * stuff is worth it, you can buy me a beer in return. M4xw
+ * ----------------------------------------------------------------------------
+ */
+
+#include "elfload.h"
+
+#if defined(__arm__)
+
+// Taken from http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044f/IHI0044F_aaelf.pdf
+#define R_ARM_NONE 0
+#define R_ARM_ABS32 2
+#define R_ARM_JUMP_SLOT 22
+#define R_ARM_GLOB_DAT 21
+#define R_ARM_RELATIVE 23
+
+el_status el_applyrel(el_ctx *ctx, Elf_Rel *rel)
+{
+ uint32_t sym = ELF_R_SYM(rel->r_info); // Symbol offset
+ uint32_t type = ELF_R_TYPE(rel->r_info); // Relocation Type
+ uintptr_t *p = (uintptr_t *)(rel->r_offset + ctx->base_load_paddr); // Target Addr
+
+#if 0 // For later symbol usage
+ Elf32_Sym *elfSym;
+ const char *symbolName;
+
+ // We resolve relocs from the originating elf-image
+ elfSym = (Elf32_Sym *)(ctx->symtab.sh_offset + (char *)buffteg) + sym;
+ int strtab_offset = ctx->shstr.sh_offset;
+ char *strtab = (char *)buffteg + strtab_offset;
+ symbolName = strtab + elfSym->st_name;
+ //EL_DEBUG("Str: %s sz: %x val: %x\n", symbolName, elfSym->st_size, elfSym->st_value);
+#endif
+
+ switch (type)
+ {
+ case R_ARM_NONE:
+ EL_DEBUG("R_ARM_NONE\n");
+ break;
+ case R_ARM_JUMP_SLOT:
+ case R_ARM_ABS32:
+ case R_ARM_GLOB_DAT:
+ // Stubbed for later purpose
+ //*p += elfSym->st_value; // + vaddr from sec
+ //*p |= 0; // 1 if Thumb && STT_FUNC, ignored for now
+ break;
+ case R_ARM_RELATIVE: // Needed for PIE
+ if (sym)
+ {
+ return EL_BADREL;
+ }
+ *p += ctx->base_load_vaddr;
+ break;
+
+ default:
+ return EL_BADREL;
+ }
+
+ return EL_OK;
+}
+
+#endif
diff --git a/source/libs/fatfs/diskio.c b/source/libs/fatfs/diskio.c
index 97f8336..5f48faa 100644
--- a/source/libs/fatfs/diskio.c
+++ b/source/libs/fatfs/diskio.c
@@ -46,7 +46,7 @@ typedef struct {
} sector_cache_t;
#define MAX_SEC_CACHE_ENTRIES 64
-static sector_cache_t *sector_cache = (sector_cache_t*)0x40022000;
+static sector_cache_t *sector_cache;
static u32 secindex = 0;
DSTATUS disk_status (
@@ -135,7 +135,15 @@ DRESULT disk_read (
switch (pdrv)
{
case 0:
- return sdmmc_storage_read(&sd_storage, sector, count, buff) ? RES_OK : RES_ERROR;
+ if (((u32)buff >= DRAM_START) && !((u32)buff % 8))
+ return sdmmc_storage_read(&sd_storage, sector, count, buff) ? RES_OK : RES_ERROR;
+ u8 *buf = (u8 *)SDMMC_UPPER_BUFFER;
+ if (sdmmc_storage_read(&sd_storage, sector, count, buf))
+ {
+ memcpy(buff, buf, 512 * count);
+ return RES_OK;
+ }
+ return RES_ERROR;
case 1:;
__attribute__ ((aligned (16))) static u8 tweak[0x10];
@@ -144,6 +152,10 @@ DRESULT disk_read (
u32 tweak_exp = 0;
bool regen_tweak = true, cache_sector = false;
+ if (secindex == 0) {
+ sector_cache = (sector_cache_t *)malloc(sizeof(sector_cache_t) * MAX_SEC_CACHE_ENTRIES);
+ }
+
u32 s = 0;
if (count == 1) {
for ( ; s < secindex; s++) {
@@ -199,7 +211,14 @@ DRESULT disk_write (
{
if (pdrv == 1)
return RES_WRPRT;
- return sdmmc_storage_write(&sd_storage, sector, count, (void *)buff) ? RES_OK : RES_ERROR;
+
+ if (((u32)buff >= DRAM_START) && !((u32)buff % 8))
+ return sdmmc_storage_write(&sd_storage, sector, count, (void *)buff) ? RES_OK : RES_ERROR;
+ u8 *buf = (u8 *)SDMMC_UPPER_BUFFER; //TODO: define this somewhere.
+ memcpy(buf, buff, 512 * count);
+ if (sdmmc_storage_write(&sd_storage, sector, count, buf))
+ return RES_OK;
+ return RES_ERROR;
}
DRESULT disk_ioctl (
diff --git a/source/main.c b/source/main.c
index 3fcdef5..26a84a4 100644
--- a/source/main.c
+++ b/source/main.c
@@ -24,6 +24,7 @@
#include "gfx/tui.h"
#include "libs/fatfs/ff.h"
#include "mem/heap.h"
+#include "mem/minerva.h"
#include "power/max77620.h"
#include "rtc/max77620-rtc.h"
#include "soc/bpmp.h"
@@ -165,18 +166,18 @@ void dump_emunand()
}
ment_t ment_top[] = {
- MDEF_HANDLER("Dump keys from SysNAND", dump_sysnand, COLOR_RED),
+ MDEF_HANDLER("Dump keys from SysNAND", dump_sysnand, COLOR_RED),
MDEF_HANDLER("Dump keys from emuMMC", dump_emunand, COLOR_ORANGE),
- MDEF_CAPTION("---------------", COLOR_YELLOW),
- MDEF_HANDLER("Reboot (Normal)", reboot_normal, COLOR_GREEN),
- MDEF_HANDLER("Reboot (RCM)", reboot_rcm, COLOR_BLUE),
- MDEF_HANDLER("Power off", power_off, COLOR_VIOLET),
- MDEF_END()
+ MDEF_CAPTION("---------------", COLOR_YELLOW),
+ MDEF_HANDLER("Reboot (Normal)", reboot_normal, COLOR_GREEN),
+ MDEF_HANDLER("Reboot (RCM)", reboot_rcm, COLOR_BLUE),
+ MDEF_HANDLER("Power off", power_off, COLOR_VIOLET),
+ MDEF_END()
};
menu_t menu_top = { ment_top, NULL, 0, 0 };
-#define IPL_STACK_TOP 0x4003F000
+#define IPL_STACK_TOP 0x90010000//0x4003F000
#define IPL_HEAP_START 0x90020000
extern void pivot_stack(u32 stack_top);
@@ -189,6 +190,10 @@ void ipl_main()
set_default_configuration();
+ sd_mount();
+ minerva_init();
+ minerva_change_freq(FREQ_1600);
+
display_init();
u32 *fb = display_init_framebuffer();
gfx_init_ctxt(fb, 720, 1280, 720);
diff --git a/source/mem/minerva.c b/source/mem/minerva.c
new file mode 100644
index 0000000..2ac8516
--- /dev/null
+++ b/source/mem/minerva.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2019 CTCaer
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 .
+ */
+
+#include
+#include
+
+#include "minerva.h"
+#include "../soc/fuse.h"
+#include "../utils/util.h"
+
+#include "../soc/clock.h"
+#include "../ianos/ianos.h"
+#include "../soc/fuse.h"
+#include "../soc/t210.h"
+
+volatile nyx_storage_t *nyx_str = (nyx_storage_t *)0xED000000;
+
+void minerva_init()
+{
+ u32 curr_ram_idx = 0;
+
+ mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
+
+ // Set table to ram.
+ mtc_cfg->mtc_table = NULL;
+ mtc_cfg->sdram_id = (fuse_read_odm(4) >> 3) & 0x1F;
+ u32 ep_addr = ianos_loader(false, "bootloader/sys/libsys_minerva.bso", DRAM_LIB, (void *)mtc_cfg);
+ minerva_cfg = (void *)ep_addr;
+
+ if (!minerva_cfg)
+ return;
+
+ // Get current frequency
+ for (curr_ram_idx = 0; curr_ram_idx < 10; curr_ram_idx++)
+ {
+ if (CLOCK(CLK_RST_CONTROLLER_CLK_SOURCE_EMC) == mtc_cfg->mtc_table[curr_ram_idx].clk_src_emc)
+ break;
+ }
+
+ mtc_cfg->rate_from = mtc_cfg->mtc_table[curr_ram_idx].rate_khz;
+ mtc_cfg->rate_to = 204000;
+ mtc_cfg->train_mode = OP_TRAIN;
+ minerva_cfg(mtc_cfg, NULL);
+ mtc_cfg->rate_to = 800000;
+ minerva_cfg(mtc_cfg, NULL);
+ mtc_cfg->rate_to = 1600000;
+ minerva_cfg(mtc_cfg, NULL);
+}
+
+void minerva_change_freq(minerva_freq_t freq)
+{
+ if (!minerva_cfg)
+ return;
+
+ mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
+ if (minerva_cfg && (mtc_cfg->rate_from != freq))
+ {
+ mtc_cfg->rate_to = freq;
+ mtc_cfg->train_mode = OP_SWITCH;
+ minerva_cfg(mtc_cfg, NULL);
+ }
+}
+
+void minerva_periodic_training()
+{
+ if (!minerva_cfg)
+ return;
+
+ mtc_config_t *mtc_cfg = (mtc_config_t *)&nyx_str->mtc_cfg;
+ if (minerva_cfg && mtc_cfg->rate_from == FREQ_1600)
+ {
+ mtc_cfg->train_mode = OP_PERIODIC_TRAIN;
+ minerva_cfg(mtc_cfg, NULL);
+ }
+}
\ No newline at end of file
diff --git a/source/mem/minerva.h b/source/mem/minerva.h
new file mode 100644
index 0000000..dd71658
--- /dev/null
+++ b/source/mem/minerva.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2019 CTCaer
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 .
+ */
+
+#ifndef _FE_MINERVA_H_
+#define _FE_MINERVA_H_
+
+#include "mtc_table.h"
+#include "../utils/types.h"
+
+#define EMC_PERIODIC_TRAIN_MS 100
+
+typedef struct
+{
+ s32 rate_to;
+ s32 rate_from;
+ emc_table_t *mtc_table;
+ u32 table_entries;
+ emc_table_t *current_emc_table;
+ u32 train_mode;
+ u32 sdram_id;
+ u32 prev_temp;
+ bool emc_2X_clk_src_is_pllmb;
+ bool fsp_for_src_freq;
+ bool train_ram_patterns;
+} mtc_config_t;
+
+enum train_mode_t
+{
+ OP_SWITCH = 0,
+ OP_TRAIN = 1,
+ OP_TRAIN_SWITCH = 2,
+ OP_PERIODIC_TRAIN = 3,
+ OP_TEMP_COMP = 4
+};
+
+typedef enum
+{
+ FREQ_204 = 204000,
+ FREQ_800 = 800000,
+ FREQ_1600 = 1600000
+} minerva_freq_t;
+
+void (*minerva_cfg)(mtc_config_t *mtc_cfg, void *);
+void minerva_init();
+void minerva_change_freq(minerva_freq_t freq);
+void minerva_periodic_training();
+
+#endif
diff --git a/source/mem/mtc_table.h b/source/mem/mtc_table.h
new file mode 100644
index 0000000..38a3e2f
--- /dev/null
+++ b/source/mem/mtc_table.h
@@ -0,0 +1,560 @@
+/*
+ * Minerva Training Cell
+ * DRAM Training for Tegra X1 SoC. Supports DDR2/3 and LPDDR3/4.
+ *
+ * Copyright (c) 2018 CTCaer
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 .
+ */
+
+#ifndef _MTC_TABLE_H_
+#define _MTC_TABLE_H_
+
+#include "../utils/types.h"
+
+typedef struct
+{
+ s32 pll_osc_in;
+ s32 pll_out;
+ u32 pll_feedback_div;
+ u32 pll_input_div;
+ u32 pll_post_div;
+} pllm_clk_config_t;
+
+typedef struct
+{
+ u32 emc_rc_idx;
+ u32 emc_rfc_idx;
+ u32 emc_rfcpb_idx;
+ u32 emc_refctrl2_idx;
+ u32 emc_rfc_slr_idx;
+ u32 emc_ras_idx;
+ u32 emc_rp_idx;
+ u32 emc_r2w_idx;
+ u32 emc_w2r_idx;
+ u32 emc_r2p_idx;
+ u32 emc_w2p_idx;
+ u32 emc_r2r_idx;
+ u32 emc_tppd_idx;
+ u32 emc_ccdmw_idx;
+ u32 emc_rd_rcd_idx;
+ u32 emc_wr_rcd_idx;
+ u32 emc_rrd_idx;
+ u32 emc_rext_idx;
+ u32 emc_wext_idx;
+ u32 emc_wdv_chk_idx;
+ u32 emc_wdv_idx;
+ u32 emc_wsv_idx;
+ u32 emc_wev_idx;
+ u32 emc_wdv_mask_idx;
+ u32 emc_ws_duration_idx;
+ u32 emc_we_duration_idx;
+ u32 emc_quse_idx;
+ u32 emc_quse_width_idx;
+ u32 emc_ibdly_idx;
+ u32 emc_obdly_idx;
+ u32 emc_einput_idx;
+ u32 emc_mrw6_idx;
+ u32 emc_einput_duration_idx;
+ u32 emc_puterm_extra_idx;
+ u32 emc_puterm_width_idx;
+ u32 emc_qrst_idx;
+ u32 emc_qsafe_idx;
+ u32 emc_rdv_idx;
+ u32 emc_rdv_mask_idx;
+ u32 emc_rdv_early_idx;
+ u32 emc_rdv_early_mask_idx;
+ u32 emc_refresh_idx;
+ u32 emc_burst_refresh_num_idx;
+ u32 emc_pre_refresh_req_cnt_idx;
+ u32 emc_pdex2wr_idx;
+ u32 emc_pdex2rd_idx;
+ u32 emc_pchg2pden_idx;
+ u32 emc_act2pden_idx;
+ u32 emc_ar2pden_idx;
+ u32 emc_rw2pden_idx;
+ u32 emc_cke2pden_idx;
+ u32 emc_pdex2cke_idx;
+ u32 emc_pdex2mrr_idx;
+ u32 emc_txsr_idx;
+ u32 emc_txsrdll_idx;
+ u32 emc_tcke_idx;
+ u32 emc_tckesr_idx;
+ u32 emc_tpd_idx;
+ u32 emc_tfaw_idx;
+ u32 emc_trpab_idx;
+ u32 emc_tclkstable_idx;
+ u32 emc_tclkstop_idx;
+ u32 emc_mrw7_idx;
+ u32 emc_trefbw_idx;
+ u32 emc_odt_write_idx;
+ u32 emc_fbio_cfg5_idx;
+ u32 emc_fbio_cfg7_idx;
+ u32 emc_cfg_dig_dll_idx;
+ u32 emc_cfg_dig_dll_period_idx;
+ u32 emc_pmacro_ib_rxrt_idx;
+ u32 emc_cfg_pipe_1_idx;
+ u32 emc_cfg_pipe_2_idx;
+ u32 emc_pmacro_quse_ddll_rank0_4_idx;
+ u32 emc_pmacro_quse_ddll_rank0_5_idx;
+ u32 emc_pmacro_quse_ddll_rank1_4_idx;
+ u32 emc_pmacro_quse_ddll_rank1_5_idx;
+ u32 emc_mrw8_idx;
+ u32 emc_pmacro_ob_ddll_long_dq_rank1_4_idx;
+ u32 emc_pmacro_ob_ddll_long_dq_rank1_5_idx;
+ u32 emc_pmacro_ob_ddll_long_dqs_rank0_0_idx;
+ u32 emc_pmacro_ob_ddll_long_dqs_rank0_1_idx;
+ u32 emc_pmacro_ob_ddll_long_dqs_rank0_2_idx;
+ u32 emc_pmacro_ob_ddll_long_dqs_rank0_3_idx;
+ u32 emc_pmacro_ob_ddll_long_dqs_rank0_4_idx;
+ u32 emc_pmacro_ob_ddll_long_dqs_rank0_5_idx;
+ u32 emc_pmacro_ob_ddll_long_dqs_rank1_0_idx;
+ u32 emc_pmacro_ob_ddll_long_dqs_rank1_1_idx;
+ u32 emc_pmacro_ob_ddll_long_dqs_rank1_2_idx;
+ u32 emc_pmacro_ob_ddll_long_dqs_rank1_3_idx;
+ u32 emc_pmacro_ob_ddll_long_dqs_rank1_4_idx;
+ u32 emc_pmacro_ob_ddll_long_dqs_rank1_5_idx;
+ u32 emc_pmacro_ddll_long_cmd_0_idx;
+ u32 emc_pmacro_ddll_long_cmd_1_idx;
+ u32 emc_pmacro_ddll_long_cmd_2_idx;
+ u32 emc_pmacro_ddll_long_cmd_3_idx;
+ u32 emc_pmacro_ddll_long_cmd_4_idx;
+ u32 emc_pmacro_ddll_short_cmd_0_idx;
+ u32 emc_pmacro_ddll_short_cmd_1_idx;
+ u32 emc_pmacro_ddll_short_cmd_2_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte0_3_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte1_3_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte2_3_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte3_3_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte4_3_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte5_3_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte6_3_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte7_3_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd0_3_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd1_3_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd2_3_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd3_3_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte0_3_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte1_3_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte2_3_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte3_3_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte4_3_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte5_3_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte6_3_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte7_3_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd0_0_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd0_1_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd0_2_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd0_3_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd1_0_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd1_1_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd1_2_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd1_3_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd2_0_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd2_1_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd2_2_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd2_3_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd3_0_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd3_1_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd3_2_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_cmd3_3_idx;
+ u32 emc_txdsrvttgen_idx;
+ u32 emc_fdpd_ctrl_dq_idx;
+ u32 emc_fdpd_ctrl_cmd_idx;
+ u32 emc_fbio_spare_idx;
+ u32 emc_zcal_interval_idx;
+ u32 emc_zcal_wait_cnt_idx;
+ u32 emc_mrs_wait_cnt_idx;
+ u32 emc_mrs_wait_cnt2_idx;
+ u32 emc_auto_cal_channel_idx;
+ u32 emc_dll_cfg_0_idx;
+ u32 emc_dll_cfg_1_idx;
+ u32 emc_pmacro_autocal_cfg_common_idx;
+ u32 emc_pmacro_zctrl_idx;
+ u32 emc_cfg_idx;
+ u32 emc_cfg_pipe_idx;
+ u32 emc_dyn_self_ref_control_idx;
+ u32 emc_qpop_idx;
+ u32 emc_dqs_brlshft_0_idx;
+ u32 emc_dqs_brlshft_1_idx;
+ u32 emc_cmd_brlshft_2_idx;
+ u32 emc_cmd_brlshft_3_idx;
+ u32 emc_pmacro_pad_cfg_ctrl_idx;
+ u32 emc_pmacro_data_pad_rx_ctrl_idx;
+ u32 emc_pmacro_cmd_pad_rx_ctrl_idx;
+ u32 emc_pmacro_data_rx_term_mode_idx;
+ u32 emc_pmacro_cmd_rx_term_mode_idx;
+ u32 emc_pmacro_cmd_pad_tx_ctrl_idx;
+ u32 emc_pmacro_data_pad_tx_ctrl_idx;
+ u32 emc_pmacro_common_pad_tx_ctrl_idx;
+ u32 emc_pmacro_vttgen_ctrl_0_idx;
+ u32 emc_pmacro_vttgen_ctrl_1_idx;
+ u32 emc_pmacro_vttgen_ctrl_2_idx;
+ u32 emc_pmacro_brick_ctrl_rfu1_idx;
+ u32 emc_pmacro_cmd_brick_ctrl_fdpd_idx;
+ u32 emc_pmacro_brick_ctrl_rfu2_idx;
+ u32 emc_pmacro_data_brick_ctrl_fdpd_idx;
+ u32 emc_pmacro_bg_bias_ctrl_0_idx;
+ u32 emc_cfg_3_idx;
+ u32 emc_pmacro_tx_pwrd_0_idx;
+ u32 emc_pmacro_tx_pwrd_1_idx;
+ u32 emc_pmacro_tx_pwrd_2_idx;
+ u32 emc_pmacro_tx_pwrd_3_idx;
+ u32 emc_pmacro_tx_pwrd_4_idx;
+ u32 emc_pmacro_tx_pwrd_5_idx;
+ u32 emc_config_sample_delay_idx;
+ u32 emc_pmacro_tx_sel_clk_src_0_idx;
+ u32 emc_pmacro_tx_sel_clk_src_1_idx;
+ u32 emc_pmacro_tx_sel_clk_src_2_idx;
+ u32 emc_pmacro_tx_sel_clk_src_3_idx;
+ u32 emc_pmacro_tx_sel_clk_src_4_idx;
+ u32 emc_pmacro_tx_sel_clk_src_5_idx;
+ u32 emc_pmacro_ddll_bypass_idx;
+ u32 emc_pmacro_ddll_pwrd_0_idx;
+ u32 emc_pmacro_ddll_pwrd_1_idx;
+ u32 emc_pmacro_ddll_pwrd_2_idx;
+ u32 emc_pmacro_cmd_ctrl_0_idx;
+ u32 emc_pmacro_cmd_ctrl_1_idx;
+ u32 emc_pmacro_cmd_ctrl_2_idx;
+ u32 emc_tr_timing_0_idx;
+ u32 emc_tr_dvfs_idx;
+ u32 emc_tr_ctrl_1_idx;
+ u32 emc_tr_rdv_idx;
+ u32 emc_tr_qpop_idx;
+ u32 emc_tr_rdv_mask_idx;
+ u32 emc_mrw14_idx;
+ u32 emc_tr_qsafe_idx;
+ u32 emc_tr_qrst_idx;
+ u32 emc_training_ctrl_idx;
+ u32 emc_training_settle_idx;
+ u32 emc_training_vref_settle_idx;
+ u32 emc_training_ca_fine_ctrl_idx;
+ u32 emc_training_ca_ctrl_misc_idx;
+ u32 emc_training_ca_ctrl_misc1_idx;
+ u32 emc_training_ca_vref_ctrl_idx;
+ u32 emc_training_quse_cors_ctrl_idx;
+ u32 emc_training_quse_fine_ctrl_idx;
+ u32 emc_training_quse_ctrl_misc_idx;
+ u32 emc_training_quse_vref_ctrl_idx;
+ u32 emc_training_read_fine_ctrl_idx;
+ u32 emc_training_read_ctrl_misc_idx;
+ u32 emc_training_read_vref_ctrl_idx;
+ u32 emc_training_write_fine_ctrl_idx;
+ u32 emc_training_write_ctrl_misc_idx;
+ u32 emc_training_write_vref_ctrl_idx;
+ u32 emc_training_mpc_idx;
+ u32 emc_mrw15_idx;
+} burst_regs_t;
+
+
+typedef struct
+{
+ u32 burst_regs[221];
+ u32 burst_reg_per_ch[8];
+ u32 shadow_regs_ca_train[221];
+ u32 shadow_regs_quse_train[221];
+ u32 shadow_regs_rdwr_train[221];
+} burst_regs_table_t;
+
+typedef struct
+{
+ u32 ptfv_dqsosc_movavg_c0d0u0_idx;
+ u32 ptfv_dqsosc_movavg_c0d0u1_idx;
+ u32 ptfv_dqsosc_movavg_c0d1u0_idx;
+ u32 ptfv_dqsosc_movavg_c0d1u1_idx;
+ u32 ptfv_dqsosc_movavg_c1d0u0_idx;
+ u32 ptfv_dqsosc_movavg_c1d0u1_idx;
+ u32 ptfv_dqsosc_movavg_c1d1u0_idx;
+ u32 ptfv_dqsosc_movavg_c1d1u1_idx;
+ u32 ptfv_write_samples_idx;
+ u32 ptfv_dvfs_samples_idx;
+ u32 ptfv_movavg_weight_idx;
+ u32 ptfv_config_ctrl_idx;
+} ptfv_list_table_t;
+
+typedef struct
+{
+ u32 emc0_mrw10_idx;
+ u32 emc1_mrw10_idx;
+ u32 emc0_mrw11_idx;
+ u32 emc1_mrw11_idx;
+ u32 emc0_mrw12_idx;
+ u32 emc1_mrw12_idx;
+ u32 emc0_mrw13_idx;
+ u32 emc1_mrw13_idx;
+} burst_reg_per_ch_t;
+
+typedef struct
+{
+ u32 emc_pmacro_ib_ddll_long_dqs_rank0_0_idx;
+ u32 emc_pmacro_ib_ddll_long_dqs_rank0_1_idx;
+ u32 emc_pmacro_ib_ddll_long_dqs_rank0_2_idx;
+ u32 emc_pmacro_ib_ddll_long_dqs_rank0_3_idx;
+ u32 emc_pmacro_ib_ddll_long_dqs_rank1_0_idx;
+ u32 emc_pmacro_ib_ddll_long_dqs_rank1_1_idx;
+ u32 emc_pmacro_ib_ddll_long_dqs_rank1_2_idx;
+ u32 emc_pmacro_ib_ddll_long_dqs_rank1_3_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank0_byte0_0_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank0_byte0_1_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank0_byte0_2_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank0_byte1_0_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank0_byte1_1_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank0_byte1_2_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank0_byte2_0_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank0_byte2_1_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank0_byte2_2_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank0_byte3_0_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank0_byte3_1_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank0_byte3_2_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank0_byte4_0_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank0_byte4_1_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank0_byte4_2_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank0_byte5_0_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank0_byte5_1_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank0_byte5_2_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank0_byte6_0_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank0_byte6_1_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank0_byte6_2_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank0_byte7_0_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank0_byte7_1_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank0_byte7_2_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank1_byte0_0_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank1_byte0_1_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank1_byte0_2_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank1_byte1_0_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank1_byte1_1_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank1_byte1_2_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank1_byte2_0_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank1_byte2_1_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank1_byte2_2_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank1_byte3_0_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank1_byte3_1_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank1_byte3_2_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank1_byte4_0_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank1_byte4_1_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank1_byte4_2_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank1_byte5_0_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank1_byte5_1_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank1_byte5_2_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank1_byte6_0_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank1_byte6_1_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank1_byte6_2_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank1_byte7_0_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank1_byte7_1_idx;
+ u32 emc_pmacro_ib_ddll_short_dq_rank1_byte7_2_idx;
+ u32 emc_pmacro_ib_vref_dqs_0_idx;
+ u32 emc_pmacro_ib_vref_dqs_1_idx;
+ u32 emc_pmacro_ib_vref_dq_0_idx;
+ u32 emc_pmacro_ib_vref_dq_1_idx;
+ u32 emc_pmacro_ob_ddll_long_dq_rank0_0_idx;
+ u32 emc_pmacro_ob_ddll_long_dq_rank0_1_idx;
+ u32 emc_pmacro_ob_ddll_long_dq_rank0_2_idx;
+ u32 emc_pmacro_ob_ddll_long_dq_rank0_3_idx;
+ u32 emc_pmacro_ob_ddll_long_dq_rank0_4_idx;
+ u32 emc_pmacro_ob_ddll_long_dq_rank0_5_idx;
+ u32 emc_pmacro_ob_ddll_long_dq_rank1_0_idx;
+ u32 emc_pmacro_ob_ddll_long_dq_rank1_1_idx;
+ u32 emc_pmacro_ob_ddll_long_dq_rank1_2_idx;
+ u32 emc_pmacro_ob_ddll_long_dq_rank1_3_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte0_0_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte0_1_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte0_2_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte1_0_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte1_1_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte1_2_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte2_0_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte2_1_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte2_2_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte3_0_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte3_1_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte3_2_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte4_0_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte4_1_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte4_2_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte5_0_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte5_1_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte5_2_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte6_0_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte6_1_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte6_2_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte7_0_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte7_1_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_byte7_2_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd0_0_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd0_1_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd0_2_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd1_0_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd1_1_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd1_2_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd2_0_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd2_1_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd2_2_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd3_0_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd3_1_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank0_cmd3_2_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte0_0_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte0_1_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte0_2_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte1_0_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte1_1_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte1_2_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte2_0_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte2_1_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte2_2_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte3_0_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte3_1_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte3_2_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte4_0_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte4_1_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte4_2_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte5_0_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte5_1_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte5_2_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte6_0_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte6_1_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte6_2_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte7_0_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte7_1_idx;
+ u32 emc_pmacro_ob_ddll_short_dq_rank1_byte7_2_idx;
+ u32 emc_pmacro_quse_ddll_rank0_0_idx;
+ u32 emc_pmacro_quse_ddll_rank0_1_idx;
+ u32 emc_pmacro_quse_ddll_rank0_2_idx;
+ u32 emc_pmacro_quse_ddll_rank0_3_idx;
+ u32 emc_pmacro_quse_ddll_rank1_0_idx;
+ u32 emc_pmacro_quse_ddll_rank1_1_idx;
+ u32 emc_pmacro_quse_ddll_rank1_2_idx;
+ u32 emc_pmacro_quse_ddll_rank1_3_idx;
+} trim_regs_t;
+
+typedef struct
+{
+ u32 emc_cmd_brlshft_0_idx;
+ u32 emc_cmd_brlshft_1_idx;
+ u32 emc0_data_brlshft_0_idx;
+ u32 emc1_data_brlshft_0_idx;
+ u32 emc0_data_brlshft_1_idx;
+ u32 emc1_data_brlshft_1_idx;
+ u32 emc_quse_brlshft_0_idx;
+ u32 emc_quse_brlshft_1_idx;
+ u32 emc_quse_brlshft_2_idx;
+ u32 emc_quse_brlshft_3_idx;
+} trim_perch_regs_t;
+
+typedef struct
+{
+ u32 t_rp;
+ u32 t_fc_lpddr4;
+ u32 t_rfc;
+ u32 t_pdex;
+ u32 rl;
+} dram_timings_t;
+
+typedef struct
+{
+ u32 emc0_training_opt_dqs_ib_vref_rank0_idx;
+ u32 emc1_training_opt_dqs_ib_vref_rank0_idx;
+ u32 emc0_training_opt_dqs_ib_vref_rank1_idx;
+ u32 emc1_training_opt_dqs_ib_vref_rank1_idx;
+} vref_perch_regs_t;
+
+typedef struct
+{
+ u32 trim_regs[138];
+ u32 trim_perch_regs[10];
+ u32 vref_perch_regs[4];
+} trim_regs_table_t;
+
+typedef struct
+{
+ u32 rev;
+ char dvfs_ver[60];
+ u32 rate_khz;
+ u32 min_volt;
+ u32 gpu_min_volt;
+ char clock_src[32];
+ u32 clk_src_emc;
+ u32 needs_training;
+ u32 training_pattern;
+ u32 trained;
+ u32 periodic_training;
+ u32 trained_dram_clktree_c0d0u0;
+ u32 trained_dram_clktree_c0d0u1;
+ u32 trained_dram_clktree_c0d1u0;
+ u32 trained_dram_clktree_c0d1u1;
+ u32 trained_dram_clktree_c1d0u0;
+ u32 trained_dram_clktree_c1d0u1;
+ u32 trained_dram_clktree_c1d1u0;
+ u32 trained_dram_clktree_c1d1u1;
+ u32 current_dram_clktree_c0d0u0;
+ u32 current_dram_clktree_c0d0u1;
+ u32 current_dram_clktree_c0d1u0;
+ u32 current_dram_clktree_c0d1u1;
+ u32 current_dram_clktree_c1d0u0;
+ u32 current_dram_clktree_c1d0u1;
+ u32 current_dram_clktree_c1d1u0;
+ u32 current_dram_clktree_c1d1u1;
+ u32 run_clocks;
+ u32 tree_margin;
+ u32 num_burst;
+ u32 num_burst_per_ch;
+ u32 num_trim;
+ u32 num_trim_per_ch;
+ u32 num_mc_regs;
+ u32 num_up_down;
+ u32 vref_num;
+ u32 training_mod_num;
+ u32 dram_timing_num;
+
+ ptfv_list_table_t ptfv_list;
+
+ burst_regs_t burst_regs;
+ burst_reg_per_ch_t burst_reg_per_ch;
+ burst_regs_t shadow_regs_ca_train;
+ burst_regs_t shadow_regs_quse_train;
+ burst_regs_t shadow_regs_rdwr_train;
+ trim_regs_t trim_regs;
+ trim_perch_regs_t trim_perch_regs;
+ vref_perch_regs_t vref_perch_regs;
+ dram_timings_t dram_timings;
+
+ u32 training_mod_regs[20];
+ u32 save_restore_mod_regs[12];
+ u32 burst_mc_regs[33];
+ u32 la_scale_regs[24];
+
+ u32 min_mrs_wait;
+ u32 emc_mrw;
+ u32 emc_mrw2;
+ u32 emc_mrw3;
+ u32 emc_mrw4;
+ u32 emc_mrw9;
+ u32 emc_mrs;
+ u32 emc_emrs;
+ u32 emc_emrs2;
+ u32 emc_auto_cal_config;
+ u32 emc_auto_cal_config2;
+ u32 emc_auto_cal_config3;
+ u32 emc_auto_cal_config4;
+ u32 emc_auto_cal_config5;
+ u32 emc_auto_cal_config6;
+ u32 emc_auto_cal_config7;
+ u32 emc_auto_cal_config8;
+ u32 emc_cfg_2;
+ u32 emc_sel_dpd_ctrl;
+ u32 emc_fdpd_ctrl_cmd_no_ramp;
+ u32 dll_clk_src;
+ u32 clk_out_enb_x_0_clk_enb_emc_dll;
+ u32 latency;
+} emc_table_t;
+
+#endif
\ No newline at end of file
diff --git a/source/sec/se.c b/source/sec/se.c
index 6070400..fbd0d4c 100644
--- a/source/sec/se.c
+++ b/source/sec/se.c
@@ -33,6 +33,9 @@ typedef struct _se_ll_t
vu32 size;
} se_ll_t;
+static u32 _se_rsa_mod_sizes[TEGRA_SE_RSA_KEYSLOT_COUNT];
+static u32 _se_rsa_exp_sizes[TEGRA_SE_RSA_KEYSLOT_COUNT];
+
static void _gf256_mul_x(void *block)
{
u8 *pdata = (u8 *)block;
@@ -158,6 +161,66 @@ void se_rsa_acc_ctrl(u32 rs, u32 flags)
SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) &= ~(1 << rs);
}
+// se_rsa_key_set() was derived from Atmosphère's set_rsa_keyslot
+void se_rsa_key_set(u32 ks, const void *mod, u32 mod_size, const void *exp, u32 exp_size)
+{
+ u32 *data = (u32 *)mod;
+ for (u32 i = 0; i < mod_size / 4; i++)
+ {
+ SE(SE_RSA_KEYTABLE_ADDR) = RSA_KEY_NUM(ks) | RSA_KEY_TYPE(RSA_KEY_TYPE_MOD) | i;
+ SE(SE_RSA_KEYTABLE_DATA) = byte_swap_32(data[mod_size / 4 - i - 1]);
+ }
+
+ data = (u32 *)exp;
+ for (u32 i = 0; i < exp_size / 4; i++)
+ {
+ SE(SE_RSA_KEYTABLE_ADDR) = RSA_KEY_NUM(ks) | RSA_KEY_TYPE(RSA_KEY_TYPE_EXP) | i;
+ SE(SE_RSA_KEYTABLE_DATA) = byte_swap_32(data[exp_size / 4 - i - 1]);
+ }
+
+ _se_rsa_mod_sizes[ks] = mod_size;
+ _se_rsa_exp_sizes[ks] = exp_size;
+}
+
+// se_rsa_key_clear() was derived from Atmosphère's clear_rsa_keyslot
+void se_rsa_key_clear(u32 ks)
+{
+ for (u32 i = 0; i < TEGRA_SE_RSA2048_DIGEST_SIZE / 4; i++)
+ {
+ SE(SE_RSA_KEYTABLE_ADDR) = RSA_KEY_NUM(ks) | RSA_KEY_TYPE(RSA_KEY_TYPE_MOD) | i;
+ SE(SE_RSA_KEYTABLE_DATA) = 0;
+ }
+ for (u32 i = 0; i < TEGRA_SE_RSA2048_DIGEST_SIZE / 4; i++)
+ {
+ SE(SE_RSA_KEYTABLE_ADDR) = RSA_KEY_NUM(ks) | RSA_KEY_TYPE(RSA_KEY_TYPE_EXP) | i;
+ SE(SE_RSA_KEYTABLE_DATA) = 0;
+ }
+}
+
+// se_rsa_exp_mod() was derived from Atmosphère's se_synchronous_exp_mod and se_get_exp_mod_output
+int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size)
+{
+ int res;
+ u8 stack_buf[TEGRA_SE_RSA2048_DIGEST_SIZE];
+
+ for (u32 i = 0; i < src_size; i++)
+ stack_buf[i] = *((u8 *)src + src_size - i - 1);
+
+ SE(SE_CONFIG_REG_OFFSET) = SE_CONFIG_ENC_ALG(ALG_RSA) | SE_CONFIG_DST(DST_RSAREG);
+ SE(SE_RSA_CONFIG) = RSA_KEY_SLOT(ks);
+ SE(SE_RSA_KEY_SIZE_REG_OFFSET) = (_se_rsa_mod_sizes[ks] >> 6) - 1;
+ SE(SE_RSA_EXP_SIZE_REG_OFFSET) = _se_rsa_exp_sizes[ks] >> 2;
+
+ res = _se_execute(OP_START, NULL, 0, stack_buf, src_size);
+
+ // Copy output hash.
+ u32 *dst32 = (u32 *)dst;
+ for (u32 i = 0; i < dst_size / 4; i++)
+ dst32[dst_size / 4 - i - 1] = byte_swap_32(SE(SE_RSA_OUTPUT + (i << 2)));
+
+ return res;
+}
+
void se_key_acc_ctrl(u32 ks, u32 flags)
{
if (flags & 0x7F)
diff --git a/source/sec/se.h b/source/sec/se.h
index 263fe02..434a97a 100644
--- a/source/sec/se.h
+++ b/source/sec/se.h
@@ -20,6 +20,9 @@
#include "../utils/types.h"
void se_rsa_acc_ctrl(u32 rs, u32 flags);
+void se_rsa_key_set(u32 ks, const void *mod, u32 mod_size, const void *exp, u32 exp_size);
+void se_rsa_key_clear(u32 ks);
+int se_rsa_exp_mod(u32 ks, void *dst, u32 dst_size, const void *src, u32 src_size);
void se_key_acc_ctrl(u32 ks, u32 flags);
void se_aes_key_set(u32 ks, const void *key, u32 size);
void se_aes_key_read(u32 ks, void *key, u32 size);
diff --git a/source/soc/hw_init.c b/source/soc/hw_init.c
index 7cdea95..e343fd0 100644
--- a/source/soc/hw_init.c
+++ b/source/soc/hw_init.c
@@ -28,6 +28,7 @@
#include "t210.h"
#include "../gfx/di.h"
#include "../mem/mc.h"
+#include "../mem/minerva.h"
#include "../mem/sdram.h"
#include "../power/max77620.h"
#include "../power/max7762x.h"
@@ -309,6 +310,7 @@ void reconfig_hw_workaround(bool extra_reconfig, u32 magic)
// Flush and disable MMU.
bpmp_mmu_disable();
bpmp_clk_rate_set(BPMP_CLK_NORMAL);
+ minerva_change_freq(FREQ_204);
// Re-enable clocks to Audio Processing Engine as a workaround to hanging.
CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= (1 << 10); // Enable AHUB clock.
diff --git a/source/storage/sdmmc_driver.c b/source/storage/sdmmc_driver.c
index 9330eac..96910c8 100644
--- a/source/storage/sdmmc_driver.c
+++ b/source/storage/sdmmc_driver.c
@@ -32,6 +32,10 @@
//#define DPRINTF(...) gfx_printf(__VA_ARGS__)
#define DPRINTF(...)
+#pragma GCC push_options
+#pragma GCC target ("thumb")
+#pragma GCC optimize ("Os")
+
/*! SCMMC controller base addresses. */
static const u32 _sdmmc_bases[4] = {
0x700B0000,
@@ -1146,3 +1150,5 @@ int sdmmc_enable_low_voltage(sdmmc_t *sdmmc)
return 0;
}
+
+#pragma GCC pop_options
diff --git a/source/utils/util.h b/source/utils/util.h
index 7186263..2eb0899 100644
--- a/source/utils/util.h
+++ b/source/utils/util.h
@@ -19,6 +19,7 @@
#define _UTIL_H_
#include "types.h"
+#include "../mem/minerva.h"
#define byte_swap_32(num) (((num >> 24) & 0xff) | ((num << 8) & 0xff0000) | \
((num >> 8 )& 0xff00) | ((num << 24) & 0xff000000))
@@ -29,6 +30,17 @@ typedef struct _cfg_op_t
u32 val;
} cfg_op_t;
+typedef struct _nyx_storage_t
+{
+ u32 version;
+ u32 cfg;
+ u8 irama[0x8000];
+ u8 hekate[0x30000];
+ u8 rsvd[0x800000];
+ mtc_config_t mtc_cfg;
+ emc_table_t mtc_table;
+} nyx_storage_t;
+
u32 get_tmr_us();
u32 get_tmr_ms();
u32 get_tmr_s();