mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2025-01-03 11:11:14 +00:00
exo: add smcAmsGetEmummcConfig
This commit is contained in:
parent
1021b4a455
commit
4f8ab5c599
15 changed files with 156 additions and 39 deletions
|
@ -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)"
|
DEFINES := -D__CCPLEX__ -DATMOSPHERE_GIT_BRANCH=\"$(AMSBRANCH)\" -DATMOSPHERE_GIT_REV=\"$(AMSREV)\" -DATMOSPHERE_RELEASE_VERSION_HASH="0x$(AMSHASH)"
|
||||||
CFLAGS := \
|
CFLAGS := \
|
||||||
-g \
|
-g \
|
||||||
-O2 \
|
-Os \
|
||||||
-ffunction-sections \
|
-ffunction-sections \
|
||||||
-fdata-sections \
|
-fdata-sections \
|
||||||
-fomit-frame-pointer \
|
-fomit-frame-pointer \
|
||||||
|
|
|
@ -29,7 +29,7 @@ ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
|
||||||
|
|
||||||
CFLAGS := \
|
CFLAGS := \
|
||||||
-g \
|
-g \
|
||||||
-O2 \
|
-Os \
|
||||||
-ffunction-sections \
|
-ffunction-sections \
|
||||||
-fdata-sections \
|
-fdata-sections \
|
||||||
-fomit-frame-pointer \
|
-fomit-frame-pointer \
|
||||||
|
|
|
@ -29,7 +29,7 @@ ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
|
||||||
|
|
||||||
CFLAGS := \
|
CFLAGS := \
|
||||||
-g \
|
-g \
|
||||||
-O2 \
|
-Os \
|
||||||
-ffunction-sections \
|
-ffunction-sections \
|
||||||
-fdata-sections \
|
-fdata-sections \
|
||||||
-fomit-frame-pointer \
|
-fomit-frame-pointer \
|
||||||
|
|
|
@ -29,7 +29,7 @@ ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork
|
||||||
|
|
||||||
CFLAGS := \
|
CFLAGS := \
|
||||||
-g \
|
-g \
|
||||||
-O2 \
|
-Os \
|
||||||
-ffunction-sections \
|
-ffunction-sections \
|
||||||
-fdata-sections \
|
-fdata-sections \
|
||||||
-fomit-frame-pointer \
|
-fomit-frame-pointer \
|
||||||
|
|
|
@ -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. */
|
/* UNOFFICIAL: Gets whether this unit has the RCM bug patched. */
|
||||||
*p_outvalue = (int)(fuse_has_rcm_bug_patch());;
|
*p_outvalue = (int)(fuse_has_rcm_bug_patch());;
|
||||||
break;
|
break;
|
||||||
case CONFIGITEM_EMUNAND_CONFIG:
|
|
||||||
/* UNOFFICIAL: Gets configuration meta for emunand. */
|
|
||||||
*p_outvalue = 1; //exosphere_get_emunand_config();
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
result = 2;
|
result = 2;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -45,9 +45,6 @@ typedef enum {
|
||||||
CONFIGITEM_NEEDS_SHUTDOWN = 65002,
|
CONFIGITEM_NEEDS_SHUTDOWN = 65002,
|
||||||
CONFIGITEM_EXOSPHERE_VERHASH = 65003,
|
CONFIGITEM_EXOSPHERE_VERHASH = 65003,
|
||||||
CONFIGITEM_HAS_RCM_BUG_PATCH = 65004,
|
CONFIGITEM_HAS_RCM_BUG_PATCH = 65004,
|
||||||
|
|
||||||
/* These are unofficial, emunand-related. */
|
|
||||||
CONFIGITEM_EMUNAND_CONFIG = 65100,
|
|
||||||
} ConfigItem;
|
} ConfigItem;
|
||||||
|
|
||||||
#define REBOOT_KIND_NO_REBOOT 0
|
#define REBOOT_KIND_NO_REBOOT 0
|
||||||
|
|
66
exosphere/src/emummc_cfg.h
Normal file
66
exosphere/src/emummc_cfg.h
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EXOSPHERE_EMUMMC_CONFIG_H
|
||||||
|
#define EXOSPHERE_EMUMMC_CONFIG_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <atmosphere.h>
|
||||||
|
#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
|
|
@ -84,10 +84,10 @@ unsigned int exosphere_should_disable_usermode_exception_handlers(void) {
|
||||||
return EXOSPHERE_CHECK_FLAG(EXOSPHERE_FLAG_DISABLE_USERMODE_EXCEPTION_HANDLERS);
|
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) {
|
if (!g_has_loaded_config) {
|
||||||
generic_panic();
|
generic_panic();
|
||||||
}
|
}
|
||||||
|
|
||||||
return g_exosphere_cfg.emunand_config;
|
return &g_exosphere_cfg.emummc_cfg;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
#include "memory_map.h"
|
#include "memory_map.h"
|
||||||
|
#include "emummc_cfg.h"
|
||||||
|
|
||||||
/* This serves to set configuration for *exosphere itself*, separate from the SecMon Exosphere mimics. */
|
/* 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 magic;
|
||||||
uint32_t target_firmware;
|
uint32_t target_firmware;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
uint32_t reserved;
|
uint32_t reserved[5];
|
||||||
uint64_t emunand_config;
|
exo_emummc_config_t emummc_cfg;
|
||||||
} exosphere_config_t;
|
} 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_load_config(void);
|
||||||
unsigned int exosphere_get_target_firmware(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_override_debugmode_user(void);
|
||||||
unsigned int exosphere_should_disable_usermode_exception_handlers(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) {
|
static inline unsigned int exosphere_get_target_firmware_for_init(void) {
|
||||||
const unsigned int magic = MAILBOX_EXOSPHERE_CONFIG_PHYS.magic;
|
const unsigned int magic = MAILBOX_EXOSPHERE_CONFIG_PHYS.magic;
|
||||||
|
|
|
@ -819,7 +819,7 @@ strcpy (char *dst0,
|
||||||
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
|
#if defined(PREFER_SIZE_OVER_SPEED) || defined(__OPTIMIZE_SIZE__)
|
||||||
char *s = dst0;
|
char *s = dst0;
|
||||||
|
|
||||||
while (*dst0++ = *src0++)
|
while ((*dst0++ = *src0++))
|
||||||
;
|
;
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
#include "synchronization.h"
|
#include "synchronization.h"
|
||||||
#include "memory_map.h"
|
#include "memory_map.h"
|
||||||
#include "mmu.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_userpage_mapped = ATOMIC_FLAG_INIT;
|
||||||
static atomic_flag g_ams_iram_page_mapped = ATOMIC_FLAG_INIT;
|
static atomic_flag g_ams_iram_page_mapped = ATOMIC_FLAG_INIT;
|
||||||
|
@ -222,3 +224,50 @@ uint32_t ams_write_address(smc_args_t *args) {
|
||||||
|
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,6 +22,8 @@
|
||||||
uint32_t ams_iram_copy(smc_args_t *args);
|
uint32_t ams_iram_copy(smc_args_t *args);
|
||||||
uint32_t ams_write_address(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_map_irampage(uintptr_t iram_address);
|
||||||
void ams_unmap_irampage(void);
|
void ams_unmap_irampage(void);
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,7 @@ uint32_t smc_read_write_register(smc_args_t *args);
|
||||||
/* Atmosphere SMC prototypes */
|
/* Atmosphere SMC prototypes */
|
||||||
uint32_t smc_ams_iram_copy(smc_args_t *args);
|
uint32_t smc_ams_iram_copy(smc_args_t *args);
|
||||||
uint32_t smc_ams_write_address(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... */
|
/* TODO: Provide a way to set this. It's 0 on non-recovery boot anyway... */
|
||||||
static uint32_t g_smc_blacklist_mask = 0;
|
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},
|
{0xF0000201, 0, smc_ams_iram_copy},
|
||||||
{0xF0000002, 0, smc_read_write_register},
|
{0xF0000002, 0, smc_read_write_register},
|
||||||
{0xF0000003, 0, smc_ams_write_address},
|
{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]))
|
#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) {
|
uint32_t smc_ams_write_address(smc_args_t *args) {
|
||||||
return smc_wrapper_sync(args, ams_write_address);
|
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);
|
||||||
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
static uintptr_t g_user_page_user_address = 0ull;
|
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;
|
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;
|
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. */
|
/* Fail if the page doesn't match. */
|
||||||
if (get_page_for_address(user_src) != upage->user_address) {
|
if (get_page_for_address(user_src) != upage->user_address) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -67,14 +67,14 @@ bool user_copy_to_secure(upage_ref_t *upage, void *secure_dst, void *user_src, s
|
||||||
return false;
|
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) {
|
if (size != 0) {
|
||||||
memcpy(secure_dst, secure_src, size);
|
memcpy(secure_dst, secure_src, size);
|
||||||
}
|
}
|
||||||
return true;
|
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. */
|
/* Fail if the page doesn't match. */
|
||||||
if (get_page_for_address(user_dst) != upage->user_address) {
|
if (get_page_for_address(user_dst) != upage->user_address) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -33,7 +33,7 @@ typedef struct {
|
||||||
|
|
||||||
bool upage_init(upage_ref_t *user_page, void *user_address);
|
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 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, void *secure_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
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue