Fix emummc nintendo dir redirection

This commit is contained in:
Michael Scire 2019-06-14 21:20:53 -07:00
parent c8f2d17d02
commit 0dcb496522
8 changed files with 66 additions and 26 deletions

View file

@ -59,9 +59,9 @@ typedef struct {
emummc_partition_config_t partition_cfg;
emummc_file_config_t file_cfg;
};
//char emu_dir_path[EMUMMC_FILE_PATH_MAX];
char emu_dir_path[EMUMMC_FILE_PATH_MAX];
} exo_emummc_config_t;
_Static_assert(sizeof(exo_emummc_config_t) == 0x90, "exo_emummc_config_t definition!");
_Static_assert(sizeof(exo_emummc_config_t) == 0x110, "exo_emummc_config_t definition!");
#endif

View file

@ -228,10 +228,10 @@ uint32_t ams_write_address(smc_args_t *args) {
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;
/* args->X[2] = Pointer to output (for paths for filebased + nintendo dir), must be at least 0x100 bytes. */
const uint32_t mmc_id = (uint32_t)args->X[1];
void *user_address = (void *)args->X[2];
const uintptr_t dram_address = args->X[2];
const uintptr_t dram_page_offset = (dram_address & 0xFFFULL);
const exo_emummc_config_t *emummc_cfg = exosphere_get_emummc_config();
if (mmc_id != EMUMMC_MMC_NAND) {
@ -239,35 +239,52 @@ uint32_t ams_get_emummc_config(smc_args_t *args) {
return 1;
}
/* Require page alignment for input address. */
if (!ams_is_user_addr_valid(dram_address) || dram_page_offset > 0x1000 - 0x100) {
return 2;
}
/* Map pages. */
ams_map_userpage(dram_address);
void *user_address = (void *)(AMS_USER_PAGE_SECURE_MONITOR_ADDR + dram_page_offset);
/* Copy redirection dir out to user. */
memcpy((void *)((uintptr_t)user_address + sizeof(emummc_cfg->file_cfg)), emummc_cfg->emu_dir_path, sizeof(emummc_cfg->emu_dir_path));
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!");
/* Unmap pages. */
ams_unmap_userpage();
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!");
/* Unmap pages. */
ams_unmap_userpage();
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 file dir path output to user. */
memcpy(user_address, &emummc_cfg->file_cfg, sizeof(emummc_cfg->file_cfg));
/* 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!");
/* Unmap pages. */
ams_unmap_userpage();
return 0;
} else {
/* Unmap pages. */
ams_unmap_userpage();
return 2;
}
}

View file

@ -98,9 +98,9 @@ typedef struct {
emummc_partition_config_t partition_cfg;
emummc_file_config_t file_cfg;
};
//char emu_dir_path[EMUMMC_FILE_PATH_MAX];
char emu_dir_path[EMUMMC_FILE_PATH_MAX];
} exo_emummc_config_t;
_Static_assert(sizeof(exo_emummc_config_t) == 0x90, "exo_emummc_config_t definition!");
_Static_assert(sizeof(exo_emummc_config_t) == 0x110, "exo_emummc_config_t definition!");
#endif

View file

@ -112,9 +112,14 @@ static int emummc_ini_handler(void *user, const char *section, const char *name,
uintptr_t sector = 0;
sscanf(value, "%x", &sector);
emummc_cfg->sector = sector;
} else if (strcmp(name, EMUMMC_ID_KEY) == 0) {
sscanf(value, "%lx", &emummc_cfg->id);
} else if (strcmp(name, EMUMMC_PATH_KEY) == 0) {
strncpy(emummc_cfg->path, value, sizeof(emummc_cfg->path) - 1);
emummc_cfg->path[sizeof(emummc_cfg->path) - 1] = '\0';
} else if (strcmp(name, EMUMMC_NINTENDO_PATH_KEY) == 0) {
strncpy(emummc_cfg->nintendo_path, value, sizeof(emummc_cfg->nintendo_path) - 1);
emummc_cfg->nintendo_path[sizeof(emummc_cfg->nintendo_path) - 1] = '\0';
} else {
return 0;
}
@ -209,7 +214,7 @@ static uint32_t nxboot_get_target_firmware(const void *package1loader) {
}
static bool nxboot_configure_emummc(exo_emummc_config_t *exo_emummc_config) {
emummc_config_t emummc_cfg = {.enabled = false, .sector = -1, .path = ""};
emummc_config_t emummc_cfg = {.enabled = false, .id = 0, .sector = -1, .path = "", .nintendo_path = ""};
/* Load emummc settings from BCT.ini file. */
if (ini_parse_string(get_loader_ctx()->bct0, emummc_ini_handler, &emummc_cfg) < 0) {
@ -219,8 +224,10 @@ static bool nxboot_configure_emummc(exo_emummc_config_t *exo_emummc_config) {
memset(exo_emummc_config, 0, sizeof(*exo_emummc_config));
exo_emummc_config->base_cfg.magic = MAGIC_EMUMMC_CONFIG;
exo_emummc_config->base_cfg.type = EMUMMC_TYPE_NONE;
exo_emummc_config->base_cfg.id = 0; /* TODO: Multiple ID support. */
exo_emummc_config->base_cfg.id = emummc_cfg.id;
exo_emummc_config->base_cfg.fs_version = FS_VER_1_0_0; /* Will be filled out later. */
strncpy(exo_emummc_config->emu_dir_path, emummc_cfg.nintendo_path, sizeof(exo_emummc_config->emu_dir_path));
exo_emummc_config->emu_dir_path[sizeof(exo_emummc_config->emu_dir_path) - 1] = '\0';
if (emummc_cfg.enabled) {
if (emummc_cfg.sector >= 0) {
@ -233,7 +240,8 @@ static bool nxboot_configure_emummc(exo_emummc_config_t *exo_emummc_config) {
}
} else if (is_valid_folder(emummc_cfg.path)) {
exo_emummc_config->base_cfg.type = EMUMMC_TYPE_FILES;
strncpy(exo_emummc_config->file_cfg.path, emummc_cfg.path, sizeof(exo_emummc_config->file_cfg.path) - 1);
strncpy(exo_emummc_config->file_cfg.path, emummc_cfg.path, sizeof(exo_emummc_config->file_cfg.path));
exo_emummc_config->file_cfg.path[sizeof(exo_emummc_config->file_cfg.path) - 1] = '\0';
int num_parts = 0;
uint64_t part_limit = 0;

View file

@ -22,11 +22,15 @@
#define EMUMMC_ENABLED_KEY "emummc_enabled"
#define EMUMMC_SECTOR_KEY "emummc_sector"
#define EMUMMC_PATH_KEY "emummc_path"
#define EMUMMC_NINTENDO_PATH_KEY "emummc_nintendo_path"
#define EMUMMC_ID_KEY "emummc_id"
typedef struct {
bool enabled;
uint32_t id;
uint64_t sector;
char path[0x100];
char path[0x80];
char nintendo_path[0x80];
} emummc_config_t;
#define MAILBOX_NX_BOOTLOADER_BASE_100_620 0x40002E00

View file

@ -163,11 +163,11 @@ Result FsMitmService::OpenFileSystemWithId(Out<std::shared_ptr<IFileSystemInterf
}
Result FsMitmService::OpenSdCardFileSystem(Out<std::shared_ptr<IFileSystemInterface>> out_fs) {
/* We only care about redirecting this for NS/Emunand. */
if (!IsEmunand()) {
/* We only care about redirecting this for NS/Emummc. */
if (this->title_id != TitleId_Ns) {
return ResultAtmosphereMitmShouldForwardToSession;
}
if (this->title_id != TitleId_Ns) {
if (!IsEmummc()) {
return ResultAtmosphereMitmShouldForwardToSession;
}
@ -190,7 +190,7 @@ Result FsMitmService::OpenSdCardFileSystem(Out<std::shared_ptr<IFileSystemInterf
return rc;
}
std::shared_ptr<IFileSystem> redir_fs = std::make_shared<DirectoryRedirectionFileSystem>(new ProxyFileSystem(sd_fs), "/Nintendo", "/Emu/0000" /* TODO: Real Path */);
std::shared_ptr<IFileSystem> redir_fs = std::make_shared<DirectoryRedirectionFileSystem>(new ProxyFileSystem(sd_fs), "/Nintendo", GetEmummcNintendoDirPath());
fs = std::make_shared<IFileSystemInterface>(redir_fs);
if (out_fs.IsDomain()) {
out_domain_id = sd_fs.s.object_id;

View file

@ -65,6 +65,9 @@ static FsFile g_cal0_file = {0};
static u8 g_cal0_storage_backup[ProdinfoSize];
static u8 g_cal0_backup[ProdinfoSize];
/* Emummc-related file. */
static FsFile g_emummc_file = {0};
static bool IsHexadecimal(const char *str) {
while (*str) {
if (isxdigit(*str)) {
@ -197,6 +200,14 @@ void Utils::InitializeThreadFunc(void *args) {
Utils::RefreshConfiguration();
/* If we're emummc, persist a write handle to prevent other processes from touching the image. */
if (IsEmummc()) {
const char *emummc_file_path = GetEmummcFilePath();
if (emummc_file_path != nullptr) {
fsFsOpenFile(&g_sd_filesystem, emummc_file_path, FS_OPEN_READ | FS_OPEN_WRITE, &g_emummc_file);
}
}
/* Initialize set:sys. */
DoWithSmSession([&]() {
if (R_FAILED(setsysInitialize())) {

@ -1 +1 @@
Subproject commit 05c58ef00263552d4925ed29ac0828cacdfc2ed1
Subproject commit afcd075354dec43fae882c3ad4d5220336231d04