diff --git a/exosphere/Makefile b/exosphere/Makefile
index 7c638dfab..3b9792116 100644
--- a/exosphere/Makefile
+++ b/exosphere/Makefile
@@ -37,7 +37,7 @@ ARCH := -march=armv8-a -mtune=cortex-a57 -mgeneral-regs-only #<- important
DEFINES := -D__CCPLEX__ -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\" -DATMOSPHERE_RELEASE_VERSION_HASH="0x$(AMSHASH)"
CFLAGS := \
-g \
- -O2 \
+ -Os \
-ffunction-sections \
-fdata-sections \
-fomit-frame-pointer \
diff --git a/exosphere/lp0fw/Makefile b/exosphere/lp0fw/Makefile
index e8afccfd1..b3b032b84 100644
--- a/exosphere/lp0fw/Makefile
+++ b/exosphere/lp0fw/Makefile
@@ -29,7 +29,7 @@ ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
CFLAGS := \
-g \
- -O2 \
+ -Os \
-ffunction-sections \
-fdata-sections \
-fomit-frame-pointer \
diff --git a/exosphere/rebootstub/Makefile b/exosphere/rebootstub/Makefile
index 0eadd1314..ff265beef 100644
--- a/exosphere/rebootstub/Makefile
+++ b/exosphere/rebootstub/Makefile
@@ -29,7 +29,7 @@ ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
CFLAGS := \
-g \
- -O2 \
+ -Os \
-ffunction-sections \
-fdata-sections \
-fomit-frame-pointer \
diff --git a/exosphere/sc7fw/Makefile b/exosphere/sc7fw/Makefile
index 0eadd1314..ff265beef 100644
--- a/exosphere/sc7fw/Makefile
+++ b/exosphere/sc7fw/Makefile
@@ -29,7 +29,7 @@ ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
CFLAGS := \
-g \
- -O2 \
+ -Os \
-ffunction-sections \
-fdata-sections \
-fomit-frame-pointer \
diff --git a/exosphere/src/configitem.c b/exosphere/src/configitem.c
index 4adb878b3..b53421d6f 100644
--- a/exosphere/src/configitem.c
+++ b/exosphere/src/configitem.c
@@ -284,10 +284,6 @@ uint32_t configitem_get(bool privileged, ConfigItem item, uint64_t *p_outvalue)
/* UNOFFICIAL: Gets whether this unit has the RCM bug patched. */
*p_outvalue = (int)(fuse_has_rcm_bug_patch());;
break;
- case CONFIGITEM_EMUNAND_CONFIG:
- /* UNOFFICIAL: Gets configuration meta for emunand. */
- *p_outvalue = 1; //exosphere_get_emunand_config();
- break;
default:
result = 2;
break;
diff --git a/exosphere/src/configitem.h b/exosphere/src/configitem.h
index f727e87f0..b9600c833 100644
--- a/exosphere/src/configitem.h
+++ b/exosphere/src/configitem.h
@@ -45,9 +45,6 @@ typedef enum {
CONFIGITEM_NEEDS_SHUTDOWN = 65002,
CONFIGITEM_EXOSPHERE_VERHASH = 65003,
CONFIGITEM_HAS_RCM_BUG_PATCH = 65004,
-
- /* These are unofficial, emunand-related. */
- CONFIGITEM_EMUNAND_CONFIG = 65100,
} ConfigItem;
#define REBOOT_KIND_NO_REBOOT 0
diff --git a/exosphere/src/emummc_cfg.h b/exosphere/src/emummc_cfg.h
new file mode 100644
index 000000000..3a7f01f5b
--- /dev/null
+++ b/exosphere/src/emummc_cfg.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018-2019 Atmosphère-NX
+ *
+ * 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 EXOSPHERE_EMUMMC_CONFIG_H
+#define EXOSPHERE_EMUMMC_CONFIG_H
+
+#include
+#include
+#include "utils.h"
+
+/* "EFS0" */
+#define MAGIC_EMUMMC_CONFIG (0x30534645)
+
+#define EMUMMC_FILE_PATH_MAX (0x80)
+
+typedef enum {
+ EMUMMC_TYPE_NONE = 0,
+ EMUMMC_TYPE_PARTITION = 1,
+ EMUMMC_TYPE_FILES = 2,
+} emummc_type_t;
+
+typedef enum {
+ EMUMMC_MMC_NAND = 0,
+ EMUMMC_MMC_SD = 1,
+ EMUMMC_MMC_GC = 2,
+} emummc_mmc_t;
+
+typedef struct {
+ uint32_t magic;
+ uint32_t type;
+ uint32_t id;
+ uint32_t fs_version;
+} emummc_base_config_t;
+
+typedef struct {
+ uint64_t start_sector;
+} emummc_partition_config_t;
+
+typedef struct {
+ char path[EMUMMC_FILE_PATH_MAX];
+} emummc_file_config_t;
+
+typedef struct {
+ emummc_base_config_t base_cfg;
+ union {
+ emummc_partition_config_t partition_cfg;
+ emummc_file_config_t file_cfg;
+ };
+} exo_emummc_config_t;
+
+_Static_assert(sizeof(exo_emummc_config_t) == 0x90, "exo_emummc_config_t definition!");
+
+#endif
diff --git a/exosphere/src/exocfg.c b/exosphere/src/exocfg.c
index ad782b33d..7cf9488bd 100644
--- a/exosphere/src/exocfg.c
+++ b/exosphere/src/exocfg.c
@@ -84,10 +84,10 @@ unsigned int exosphere_should_disable_usermode_exception_handlers(void) {
return EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_DISABLE_USERMODE_EXCEPTION_HANDLERS);
}
-uint64_t exosphere_get_emunand_config(void) {
+const exo_emummc_config_t *exosphere_get_emummc_config(void) {
if (!g_has_loaded_config) {
generic_panic();
}
- return g_exosphere_cfg.emunand_config;
+ return &g_exosphere_cfg.emummc_cfg;
}
diff --git a/exosphere/src/exocfg.h b/exosphere/src/exocfg.h
index d6a12eb22..316aa5646 100644
--- a/exosphere/src/exocfg.h
+++ b/exosphere/src/exocfg.h
@@ -22,6 +22,7 @@
#include "utils.h"
#include "memory_map.h"
+#include "emummc_cfg.h"
/* This serves to set configuration for *exosphere itself*, separate from the SecMon Exosphere mimics. */
@@ -45,11 +46,11 @@ typedef struct {
uint32_t magic;
uint32_t target_firmware;
uint32_t flags;
- uint32_t reserved;
- uint64_t emunand_config;
+ uint32_t reserved[5];
+ exo_emummc_config_t emummc_cfg;
} exosphere_config_t;
-_Static_assert(sizeof(exosphere_config_t) == 0x18, "exosphere config definition");
+_Static_assert(sizeof(exosphere_config_t) == 0x20 + sizeof(exo_emummc_config_t), "exosphere config definition");
unsigned int exosphere_load_config(void);
unsigned int exosphere_get_target_firmware(void);
@@ -58,7 +59,7 @@ unsigned int exosphere_should_override_debugmode_priv(void);
unsigned int exosphere_should_override_debugmode_user(void);
unsigned int exosphere_should_disable_usermode_exception_handlers(void);
-uint64_t exosphere_get_emunand_config(void);
+const exo_emummc_config_t *exosphere_get_emummc_config(void);
static inline unsigned int exosphere_get_target_firmware_for_init(void) {
const unsigned int magic = MAILBOX_EXOSPHERE_CONFIG_PHYS.magic;
diff --git a/exosphere/src/my_libc.c b/exosphere/src/my_libc.c
index 35bd35bbb..2117f2483 100644
--- a/exosphere/src/my_libc.c
+++ b/exosphere/src/my_libc.c
@@ -819,7 +819,7 @@ strcpy (char *dst0,
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
char *s = dst0;
- while (*dst0++ = *src0++)
+ while ((*dst0++ = *src0++))
;
return s;
diff --git a/exosphere/src/smc_ams.c b/exosphere/src/smc_ams.c
index f71d947a6..3fc1769ee 100644
--- a/exosphere/src/smc_ams.c
+++ b/exosphere/src/smc_ams.c
@@ -13,8 +13,8 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-
-
+
+
#include
#include
#include
@@ -26,6 +26,8 @@
#include "synchronization.h"
#include "memory_map.h"
#include "mmu.h"
+#include "userpage.h"
+#include "exocfg.h"
static atomic_flag g_ams_userpage_mapped = ATOMIC_FLAG_INIT;
static atomic_flag g_ams_iram_page_mapped = ATOMIC_FLAG_INIT;
@@ -94,42 +96,42 @@ uint32_t ams_iram_copy(smc_args_t *args) {
/* args->X[2] = IRAM address, must be 4-byte aligned. */
/* args->X[3] = size (must be <= 0x1000 and 4-byte aligned). */
/* args->X[4] = 0 for read, 1 for write. */
-
+
const uintptr_t dram_address = (uintptr_t)args->X[1];
const uintptr_t iram_address = (uintptr_t)args->X[2];
const uintptr_t dram_page_offset = (dram_address & 0xFFFULL);
const uintptr_t iram_page_offset = (iram_address & 0xFFFULL);
const size_t size = args->X[3];
const uint32_t option = (uint32_t)args->X[4];
-
+
/* Validate addresses. */
if (!ams_is_user_addr_valid(dram_address) || !ams_is_iram_addr_valid(iram_address)) {
return 2;
}
-
+
/* Validate size. */
if (size > 0x1000 || (size + dram_page_offset) > 0x1000 || (size + iram_page_offset) > 0x1000) {
return 2;
}
-
+
/* Validate alignment. */
if (size % sizeof(uint32_t) || dram_page_offset % sizeof(uint32_t) || iram_page_offset % sizeof(uint32_t)) {
return 2;
}
-
+
/* Validate argument. */
if (option != 0 && option != 1) {
return 2;
}
-
+
/* Map pages. */
ams_map_userpage(dram_address);
ams_map_irampage(iram_address);
-
+
/* Set source/destination for copy. */
volatile uint32_t *dram_ptr = (volatile uint32_t *)(AMS_USER_PAGE_SECURE_MONITOR_ADDR + dram_page_offset);
volatile uint32_t *iram_ptr = (volatile uint32_t *)(AMS_IRAM_PAGE_SECURE_MONITOR_ADDR + iram_page_offset);
-
+
volatile uint32_t *dst;
volatile uint32_t *src;
const size_t num_dwords = size / sizeof(uint32_t);
@@ -140,19 +142,19 @@ uint32_t ams_iram_copy(smc_args_t *args) {
dst = iram_ptr;
src = dram_ptr;
}
-
+
/* Actually copy data. */
for (size_t i = 0; i < num_dwords; i++) {
dst[i] = src[i];
}
-
+
/* Flush! */
- flush_dcache_range((void *)dst, (void *)(dst + num_dwords));
-
+ flush_dcache_range((void *)dst, (void *)(dst + num_dwords));
+
/* Unmap pages. */
ams_unmap_irampage();
ams_unmap_userpage();
-
+
return 0;
}
@@ -222,3 +224,50 @@ uint32_t ams_write_address(smc_args_t *args) {
return 0;
}
+
+uint32_t ams_get_emummc_config(smc_args_t *args) {
+ /* This retrieves configuration for the current emummc context. */
+ /* args->X[1] = MMC id, must be size-bytes aligned and readable by EL0. */
+ /* args->X[2] = Pointer to output (for path for filebased), must be at least 0x80 bytes. */
+ upage_ref_t page_ref;
+ const uint32_t mmc_id = (uint32_t)args->X[1];
+ void *user_address = (void *)args->X[2];
+ const exo_emummc_config_t *emummc_cfg = exosphere_get_emummc_config();
+
+ if (mmc_id != EMUMMC_MMC_NAND) {
+ /* Emummc config for non-NAND storage is not yet implemented. */
+ return 1;
+ }
+
+ if (emummc_cfg->base_cfg.type == EMUMMC_TYPE_NONE) {
+ /* Just copy base config. */
+ memset(args, 0, sizeof(*args));
+ memcpy(&args->X[1], emummc_cfg, sizeof(emummc_cfg->base_cfg));
+ _Static_assert(sizeof(emummc_cfg->base_cfg) <= sizeof(*args) - sizeof(args->X[0]), "Emunand base config too big!");
+ return 0;
+ } else if (emummc_cfg->base_cfg.type == EMUMMC_TYPE_PARTITION) {
+ /* Copy base config and partition config. */
+ memset(args, 0, sizeof(*args));
+ memcpy(&args->X[1], emummc_cfg, sizeof(emummc_cfg->base_cfg) + sizeof(emummc_cfg->partition_cfg));
+ _Static_assert(sizeof(emummc_cfg->base_cfg) + sizeof(emummc_cfg->partition_cfg) <= sizeof(*args) - sizeof(args->X[0]), "Emunand partition config too big!");
+ return 0;
+ } else if (emummc_cfg->base_cfg.type == EMUMMC_TYPE_FILES) {
+ /* Copy path to userpage. */
+ /* Initialize page reference. */
+ if (upage_init(&page_ref, user_address) == 0) {
+ return 2;
+ }
+ /* Copy result output back to user. */
+ if (secure_copy_to_user(&page_ref, user_address, &emummc_cfg->file_cfg, sizeof(emummc_cfg->file_cfg)) == 0) {
+ return 2;
+ }
+
+ /* Copy base config afterwards, since this can't fail. */
+ memset(args, 0, sizeof(*args));
+ memcpy(&args->X[1], emummc_cfg, sizeof(emummc_cfg->base_cfg));
+ _Static_assert(sizeof(emummc_cfg->base_cfg) <= sizeof(*args) - sizeof(args->X[0]), "Emunand base config too big!");
+ return 0;
+ } else {
+ return 2;
+ }
+}
\ No newline at end of file
diff --git a/exosphere/src/smc_ams.h b/exosphere/src/smc_ams.h
index cbae64d63..4061dd454 100644
--- a/exosphere/src/smc_ams.h
+++ b/exosphere/src/smc_ams.h
@@ -22,6 +22,8 @@
uint32_t ams_iram_copy(smc_args_t *args);
uint32_t ams_write_address(smc_args_t *args);
+uint32_t ams_get_emummc_config(smc_args_t *args);
+
void ams_map_irampage(uintptr_t iram_address);
void ams_unmap_irampage(void);
diff --git a/exosphere/src/smc_api.c b/exosphere/src/smc_api.c
index 65762233e..5a5d6cadc 100644
--- a/exosphere/src/smc_api.c
+++ b/exosphere/src/smc_api.c
@@ -78,6 +78,7 @@ uint32_t smc_read_write_register(smc_args_t *args);
/* Atmosphere SMC prototypes */
uint32_t smc_ams_iram_copy(smc_args_t *args);
uint32_t smc_ams_write_address(smc_args_t *args);
+uint32_t smc_ams_get_emummc_config(smc_args_t *args);
/* TODO: Provide a way to set this. It's 0 on non-recovery boot anyway... */
static uint32_t g_smc_blacklist_mask = 0;
@@ -135,6 +136,7 @@ static smc_table_entry_t g_smc_ams_table[] = {
{0xF0000201, 0, smc_ams_iram_copy},
{0xF0000002, 0, smc_read_write_register},
{0xF0000003, 0, smc_ams_write_address},
+ {0xF0000404, 0, smc_ams_get_emummc_config},
};
#define SMC_AMS_HANDLERS (sizeof(g_smc_ams_table) / sizeof(g_smc_ams_table[0]))
@@ -724,3 +726,7 @@ uint32_t smc_ams_iram_copy(smc_args_t *args) {
uint32_t smc_ams_write_address(smc_args_t *args) {
return smc_wrapper_sync(args, ams_write_address);
}
+
+uint32_t smc_ams_get_emummc_config(smc_args_t *args) {
+ return smc_wrapper_sync(args, ams_get_emummc_config);
+}
diff --git a/exosphere/src/userpage.c b/exosphere/src/userpage.c
index 3be1d5335..51cdf48b0 100644
--- a/exosphere/src/userpage.c
+++ b/exosphere/src/userpage.c
@@ -23,7 +23,7 @@
static uintptr_t g_user_page_user_address = 0ull;
-static inline uintptr_t get_page_for_address(void *address) {
+static inline uintptr_t get_page_for_address(const void *address) {
return ((uintptr_t)(address)) & ~0xFFFULL;
}
@@ -56,7 +56,7 @@ bool upage_init(upage_ref_t *upage, void *user_address) {
return upage->secure_monitor_address != 0ull;
}
-bool user_copy_to_secure(upage_ref_t *upage, void *secure_dst, void *user_src, size_t size) {
+bool user_copy_to_secure(upage_ref_t *upage, void *secure_dst, const void *user_src, size_t size) {
/* Fail if the page doesn't match. */
if (get_page_for_address(user_src) != upage->user_address) {
return false;
@@ -67,14 +67,14 @@ bool user_copy_to_secure(upage_ref_t *upage, void *secure_dst, void *user_src, s
return false;
}
- void *secure_src = (void *)(upage->secure_monitor_address + ((uintptr_t)user_src - upage->user_address));
+ const void *secure_src = (const void *)(upage->secure_monitor_address + ((uintptr_t)user_src - upage->user_address));
if (size != 0) {
memcpy(secure_dst, secure_src, size);
}
return true;
}
-bool secure_copy_to_user(upage_ref_t *upage, void *user_dst, void *secure_src, size_t size) {
+bool secure_copy_to_user(upage_ref_t *upage, void *user_dst, const void *secure_src, size_t size) {
/* Fail if the page doesn't match. */
if (get_page_for_address(user_dst) != upage->user_address) {
return false;
diff --git a/exosphere/src/userpage.h b/exosphere/src/userpage.h
index 19c140b20..23742db1c 100644
--- a/exosphere/src/userpage.h
+++ b/exosphere/src/userpage.h
@@ -33,7 +33,7 @@ typedef struct {
bool upage_init(upage_ref_t *user_page, void *user_address);
-bool user_copy_to_secure(upage_ref_t *user_page, void *secure_dst, void *user_src, size_t size);
-bool secure_copy_to_user(upage_ref_t *user_page, void *user_dst, void *secure_src, size_t size);
+bool user_copy_to_secure(upage_ref_t *user_page, void *secure_dst, const void *user_src, size_t size);
+bool secure_copy_to_user(upage_ref_t *user_page, void *user_dst, const void *secure_src, size_t size);
#endif