mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-26 13:52:21 +00:00
emunand: Move all emulation code to fusee-secondary and simplify logic
This commit is contained in:
parent
9eb0b84ed1
commit
92816be055
8 changed files with 315 additions and 193 deletions
|
@ -35,14 +35,7 @@ extern void (*__program_exit_callback)(int rc);
|
||||||
static void *g_framebuffer;
|
static void *g_framebuffer;
|
||||||
static char g_bct0_buffer[BCTO_MAX_SIZE];
|
static char g_bct0_buffer[BCTO_MAX_SIZE];
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
bool enabled;
|
|
||||||
char path[0x100];
|
|
||||||
} emunand_config_t;
|
|
||||||
|
|
||||||
#define CONFIG_LOG_LEVEL_KEY "log_level"
|
#define CONFIG_LOG_LEVEL_KEY "log_level"
|
||||||
#define EMUNAND_ENABLED_KEY "emunand_enabled"
|
|
||||||
#define EMUNAND_PATH_KEY "emunand_path"
|
|
||||||
|
|
||||||
#define DEFAULT_BCT0_FOR_DEBUG \
|
#define DEFAULT_BCT0_FOR_DEBUG \
|
||||||
"BCT0\n"\
|
"BCT0\n"\
|
||||||
|
@ -91,26 +84,6 @@ static int config_ini_handler(void *user, const char *section, const char *name,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int emunand_ini_handler(void *user, const char *section, const char *name, const char *value) {
|
|
||||||
emunand_config_t *emunand_cfg = (emunand_config_t *)user;
|
|
||||||
if (strcmp(section, "emunand") == 0) {
|
|
||||||
if (strcmp(name, EMUNAND_ENABLED_KEY) == 0) {
|
|
||||||
int tmp = 0;
|
|
||||||
sscanf(value, "%d", &tmp);
|
|
||||||
emunand_cfg->enabled = (tmp != 0);
|
|
||||||
}
|
|
||||||
if (strcmp(name, EMUNAND_PATH_KEY) == 0) {
|
|
||||||
strncpy(emunand_cfg->path, value, sizeof(emunand_cfg->path) - 1);
|
|
||||||
emunand_cfg->path[sizeof(emunand_cfg->path) - 1] = '\0';
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setup_env(void) {
|
static void setup_env(void) {
|
||||||
g_framebuffer = (void *)0xC0000000;
|
g_framebuffer = (void *)0xC0000000;
|
||||||
|
|
||||||
|
@ -159,7 +132,6 @@ int main(void) {
|
||||||
stage2_args_t *stage2_args;
|
stage2_args_t *stage2_args;
|
||||||
uint32_t stage2_version = 0;
|
uint32_t stage2_version = 0;
|
||||||
ScreenLogLevel log_level = SCREEN_LOG_LEVEL_MANDATORY;
|
ScreenLogLevel log_level = SCREEN_LOG_LEVEL_MANDATORY;
|
||||||
emunand_config_t emunand_cfg = {.enabled = false, .path = ""};
|
|
||||||
|
|
||||||
/* Override the global logging level. */
|
/* Override the global logging level. */
|
||||||
log_set_log_level(log_level);
|
log_set_log_level(log_level);
|
||||||
|
@ -170,9 +142,8 @@ int main(void) {
|
||||||
/* Load the BCT0 configuration ini off of the SD. */
|
/* Load the BCT0 configuration ini off of the SD. */
|
||||||
bct0 = load_config();
|
bct0 = load_config();
|
||||||
|
|
||||||
/* Extract the logging level and emunand settings from the BCT.ini file. */
|
/* Extract the logging level from the BCT.ini file. */
|
||||||
if ((ini_parse_string(bct0, config_ini_handler, &log_level) < 0) ||
|
if (ini_parse_string(bct0, config_ini_handler, &log_level) < 0) {
|
||||||
(ini_parse_string(bct0, emunand_ini_handler, &emunand_cfg) < 0)) {
|
|
||||||
fatal_error("Failed to parse BCT.ini!\n");
|
fatal_error("Failed to parse BCT.ini!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,9 +161,6 @@ int main(void) {
|
||||||
memcpy(&stage2_args->version, &stage2_version, 4);
|
memcpy(&stage2_args->version, &stage2_version, 4);
|
||||||
memcpy(&stage2_args->log_level, &log_level, sizeof(log_level));
|
memcpy(&stage2_args->log_level, &log_level, sizeof(log_level));
|
||||||
stage2_args->display_initialized = false;
|
stage2_args->display_initialized = false;
|
||||||
stage2_args->emunand_enabled = emunand_cfg.enabled;
|
|
||||||
strncpy(stage2_args->emunand_path, emunand_cfg.path, sizeof(stage2_args->emunand_path) - 1);
|
|
||||||
stage2_args->emunand_path[sizeof(stage2_args->emunand_path) - 1] = '\0';
|
|
||||||
strcpy(stage2_args->bct0, bct0);
|
strcpy(stage2_args->bct0, bct0);
|
||||||
g_chainloader_argc = 2;
|
g_chainloader_argc = 2;
|
||||||
|
|
||||||
|
@ -205,4 +173,4 @@ int main(void) {
|
||||||
/* Finally, after the cleanup routines (__libc_fini_array, etc.) are called, jump to Stage2. */
|
/* Finally, after the cleanup routines (__libc_fini_array, etc.) are called, jump to Stage2. */
|
||||||
__program_exit_callback = exit_callback;
|
__program_exit_callback = exit_callback;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
|
@ -46,12 +46,10 @@ typedef struct {
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
ScreenLogLevel log_level;
|
ScreenLogLevel log_level;
|
||||||
bool display_initialized;
|
bool display_initialized;
|
||||||
bool emunand_enabled;
|
|
||||||
char emunand_path[0x100];
|
|
||||||
char bct0[BCTO_MAX_SIZE];
|
char bct0[BCTO_MAX_SIZE];
|
||||||
} stage2_args_t;
|
} stage2_args_t;
|
||||||
|
|
||||||
const char *stage2_get_program_path(void);
|
const char *stage2_get_program_path(void);
|
||||||
void load_stage2(const char *bct0);
|
void load_stage2(const char *bct0);
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -51,8 +51,9 @@ static void setup_env(void) {
|
||||||
/* Set up exception handlers. */
|
/* Set up exception handlers. */
|
||||||
setup_exception_handlers();
|
setup_exception_handlers();
|
||||||
|
|
||||||
if (nxfs_mount_all(g_stage2_args->emunand_enabled, g_stage2_args->emunand_path) < 0) {
|
/* Initialize the file system by mounting the SD card. */
|
||||||
fatal_error("Failed to mount at least one partition: %s\n", strerror(errno));
|
if (nxfs_init() < 0) {
|
||||||
|
fatal_error("Failed to initialize the file system: %s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Train DRAM. */
|
/* Train DRAM. */
|
||||||
|
@ -61,7 +62,7 @@ static void setup_env(void) {
|
||||||
|
|
||||||
static void cleanup_env(void) {
|
static void cleanup_env(void) {
|
||||||
/* Unmount everything (this causes all open files to be flushed and closed) */
|
/* Unmount everything (this causes all open files to be flushed and closed) */
|
||||||
nxfs_unmount_all();
|
nxfs_end();
|
||||||
//console_end();
|
//console_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,6 +100,26 @@ static const uint8_t dev_pkc_modulus[0x100] = {
|
||||||
0xD5, 0x52, 0xDA, 0xEC, 0x41, 0xA4, 0xAD, 0x7B, 0x36, 0x86, 0x18, 0xB4, 0x5B, 0xD1, 0x30, 0xBB
|
0xD5, 0x52, 0xDA, 0xEC, 0x41, 0xA4, 0xAD, 0x7B, 0x36, 0x86, 0x18, 0xB4, 0x5B, 0xD1, 0x30, 0xBB
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int emunand_ini_handler(void *user, const char *section, const char *name, const char *value) {
|
||||||
|
emunand_config_t *emunand_cfg = (emunand_config_t *)user;
|
||||||
|
if (strcmp(section, "emunand") == 0) {
|
||||||
|
if (strcmp(name, EMUNAND_ENABLED_KEY) == 0) {
|
||||||
|
int tmp = 0;
|
||||||
|
sscanf(value, "%d", &tmp);
|
||||||
|
emunand_cfg->enabled = (tmp != 0);
|
||||||
|
}
|
||||||
|
if (strcmp(name, EMUNAND_PATH_KEY) == 0) {
|
||||||
|
strncpy(emunand_cfg->path, value, sizeof(emunand_cfg->path) - 1);
|
||||||
|
emunand_cfg->path[sizeof(emunand_cfg->path) - 1] = '\0';
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static int exosphere_ini_handler(void *user, const char *section, const char *name, const char *value) {
|
static int exosphere_ini_handler(void *user, const char *section, const char *name, const char *value) {
|
||||||
exosphere_config_t *exo_cfg = (exosphere_config_t *)user;
|
exosphere_config_t *exo_cfg = (exosphere_config_t *)user;
|
||||||
int tmp = 0;
|
int tmp = 0;
|
||||||
|
@ -177,6 +197,44 @@ static uint32_t nxboot_get_target_firmware(const void *package1loader) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool nxboot_configure_emunand() {
|
||||||
|
emunand_config_t emunand_cfg = {.enabled = false, .path = ""};
|
||||||
|
|
||||||
|
/* Load emunand settings from BCT.ini file. */
|
||||||
|
if (ini_parse_string(get_loader_ctx()->bct0, emunand_ini_handler, &emunand_cfg) < 0) {
|
||||||
|
fatal_error("[NXBOOT]: Failed to parse BCT.ini!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (emunand_cfg.enabled) {
|
||||||
|
bool do_nand_backup = false;
|
||||||
|
|
||||||
|
/* TODO: Check if the supplied path is valid. */
|
||||||
|
|
||||||
|
/* TODO: Check if all emunand image files are present. */
|
||||||
|
|
||||||
|
if (do_nand_backup) {
|
||||||
|
/* Mount real NAND. */
|
||||||
|
if (nxfs_mount_emmc() < 0) {
|
||||||
|
fatal_error("[NXBOOT]: Failed to mount eMMC!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: Read real NAND and create a backup image. */
|
||||||
|
|
||||||
|
/* Unmount real NAND. */
|
||||||
|
if (nxfs_unmount_emmc() < 0) {
|
||||||
|
fatal_error("[NXBOOT]: Failed to unmount eMMC!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mount emulated NAND. */
|
||||||
|
if (nxfs_mount_emu_emmc(emunand_cfg.path) < 0) {
|
||||||
|
fatal_error("[NXBOOT]: Failed to mount emulated eMMC!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return emunand_cfg.enabled;
|
||||||
|
}
|
||||||
|
|
||||||
static void nxboot_configure_exosphere(uint32_t target_firmware, unsigned int keygen_type) {
|
static void nxboot_configure_exosphere(uint32_t target_firmware, unsigned int keygen_type) {
|
||||||
exosphere_config_t exo_cfg = {0};
|
exosphere_config_t exo_cfg = {0};
|
||||||
|
|
||||||
|
@ -334,6 +392,13 @@ uint32_t nxboot_main(void) {
|
||||||
uint32_t available_revision;
|
uint32_t available_revision;
|
||||||
FILE *boot0, *pk2file;
|
FILE *boot0, *pk2file;
|
||||||
void *exosphere_memaddr;
|
void *exosphere_memaddr;
|
||||||
|
|
||||||
|
/* Configure emunand or mount the real NAND. */
|
||||||
|
if (!nxboot_configure_emunand()) {
|
||||||
|
if (nxfs_mount_emmc() < 0) {
|
||||||
|
fatal_error("[NXBOOT]: Failed to mount eMMC!\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Allocate memory for reading Package2. */
|
/* Allocate memory for reading Package2. */
|
||||||
package2 = memalign(0x1000, PACKAGE2_SIZE_MAX);
|
package2 = memalign(0x1000, PACKAGE2_SIZE_MAX);
|
||||||
|
@ -601,7 +666,7 @@ uint32_t nxboot_main(void) {
|
||||||
print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Powering on the CCPLEX...\n");
|
print(SCREEN_LOG_LEVEL_INFO, "[NXBOOT]: Powering on the CCPLEX...\n");
|
||||||
|
|
||||||
/* Unmount everything. */
|
/* Unmount everything. */
|
||||||
nxfs_unmount_all();
|
nxfs_end();
|
||||||
|
|
||||||
/* Return the memory address for booting CPU0. */
|
/* Return the memory address for booting CPU0. */
|
||||||
return (uint32_t)exosphere_memaddr;
|
return (uint32_t)exosphere_memaddr;
|
||||||
|
|
|
@ -19,6 +19,14 @@
|
||||||
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
#define EMUNAND_ENABLED_KEY "emunand_enabled"
|
||||||
|
#define EMUNAND_PATH_KEY "emunand_path"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool enabled;
|
||||||
|
char path[0x100];
|
||||||
|
} emunand_config_t;
|
||||||
|
|
||||||
#define MAILBOX_NX_BOOTLOADER_BASE_100_620 0x40002E00
|
#define MAILBOX_NX_BOOTLOADER_BASE_100_620 0x40002E00
|
||||||
#define MAILBOX_NX_BOOTLOADER_BASE_700 0x40000000
|
#define MAILBOX_NX_BOOTLOADER_BASE_700 0x40000000
|
||||||
#define MAILBOX_NX_BOOTLOADER_BASE(targetfw) ((targetfw >= ATMOSPHERE_TARGET_FIRMWARE_700) ? (MAILBOX_NX_BOOTLOADER_BASE_700) : (MAILBOX_NX_BOOTLOADER_BASE_100_620))
|
#define MAILBOX_NX_BOOTLOADER_BASE(targetfw) ((targetfw >= ATMOSPHERE_TARGET_FIRMWARE_700) ? (MAILBOX_NX_BOOTLOADER_BASE_700) : (MAILBOX_NX_BOOTLOADER_BASE_100_620))
|
||||||
|
|
|
@ -30,6 +30,10 @@ static bool g_ahb_redirect_enabled = false;
|
||||||
static bool g_sd_device_initialized = false;
|
static bool g_sd_device_initialized = false;
|
||||||
static bool g_emmc_device_initialized = false;
|
static bool g_emmc_device_initialized = false;
|
||||||
|
|
||||||
|
static bool g_fsdev_ready = false;
|
||||||
|
static bool g_rawdev_ready = false;
|
||||||
|
static bool g_emudev_ready = false;
|
||||||
|
|
||||||
static sdmmc_t g_sd_sdmmc = {0};
|
static sdmmc_t g_sd_sdmmc = {0};
|
||||||
static sdmmc_t g_emmc_sdmmc = {0};
|
static sdmmc_t g_emmc_sdmmc = {0};
|
||||||
|
|
||||||
|
@ -264,10 +268,9 @@ static int nxfs_mount_partition_gpt_callback(const efi_entry_t *entry, void *par
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nxfs_mount_all(bool emunand_enabled, const char *emunand_path) {
|
int nxfs_mount_sd() {
|
||||||
device_partition_t model;
|
device_partition_t model;
|
||||||
int rc;
|
int rc;
|
||||||
FILE *rawnand;
|
|
||||||
|
|
||||||
/* Setup a template for the SD card. */
|
/* Setup a template for the SD card. */
|
||||||
model = g_mmc_devpart_template;
|
model = g_mmc_devpart_template;
|
||||||
|
@ -288,152 +291,226 @@ int nxfs_mount_all(bool emunand_enabled, const char *emunand_path) {
|
||||||
if (rc == -1) {
|
if (rc == -1) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (emunand_enabled) {
|
|
||||||
/* Setup emunand paths. */
|
|
||||||
char emu_boot0_path[0x100];
|
|
||||||
char emu_boot1_path[0x100];
|
|
||||||
char emu_rawnand_path[0x100];
|
|
||||||
memset(emu_boot0_path, 0, sizeof(emu_boot0_path));
|
|
||||||
memset(emu_boot1_path, 0, sizeof(emu_boot1_path));
|
|
||||||
memset(emu_rawnand_path, 0, sizeof(emu_rawnand_path));
|
|
||||||
snprintf(emu_boot0_path, sizeof(emu_boot0_path), "sdmc:/%s/%s", emunand_path, "boot0");
|
|
||||||
snprintf(emu_boot1_path, sizeof(emu_boot1_path), "sdmc:/%s/%s", emunand_path, "boot1");
|
|
||||||
snprintf(emu_rawnand_path, sizeof(emu_rawnand_path), "sdmc:/%s/%s", emunand_path, "rawnand");
|
|
||||||
|
|
||||||
/* Setup an emulation template for boot0. */
|
/* All fs devices are ready. */
|
||||||
model = g_emummc_devpart_template;
|
if (rc == 0) {
|
||||||
model.start_sector = 0;
|
g_fsdev_ready = true;
|
||||||
model.num_sectors = 0x184000 / model.sector_size;
|
}
|
||||||
|
|
||||||
/* Mount emulated boot0 device. */
|
return rc;
|
||||||
rc = emudev_mount_device("boot0", emu_boot0_path, &model);
|
}
|
||||||
|
|
||||||
if (rc == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Register emulated boot0 device. */
|
|
||||||
rc = emudev_register_device("boot0");
|
|
||||||
|
|
||||||
if (rc == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Setup an emulation template for boot1. */
|
|
||||||
model = g_emummc_devpart_template;
|
|
||||||
model.start_sector = 0;
|
|
||||||
model.num_sectors = 0x80000 / model.sector_size;
|
|
||||||
|
|
||||||
/* Mount emulated boot1 device. */
|
|
||||||
rc = emudev_mount_device("boot1", emu_boot1_path, &model);
|
|
||||||
|
|
||||||
if (rc == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Don't register emulated boot1 for now. */
|
int nxfs_mount_emmc() {
|
||||||
|
device_partition_t model;
|
||||||
/* Setup a template for raw NAND. */
|
int rc;
|
||||||
model = g_emummc_devpart_template;
|
FILE *rawnand;
|
||||||
model.start_sector = 0;
|
|
||||||
model.num_sectors = (256ull << 30) / model.sector_size;
|
/* Setup a template for boot0. */
|
||||||
|
model = g_mmc_devpart_template;
|
||||||
/* Mount emulated raw NAND device. */
|
model.device_struct = &g_emmc_boot0_mmcpart;
|
||||||
rc = emudev_mount_device("rawnand", emu_rawnand_path, &model);
|
model.start_sector = 0;
|
||||||
|
model.num_sectors = 0x184000 / model.sector_size;
|
||||||
if (rc == -1) {
|
|
||||||
return -1;
|
/* Mount boot0 device. */
|
||||||
}
|
rc = rawdev_mount_device("boot0", &model, true);
|
||||||
|
|
||||||
/* Register emulated raw NAND device. */
|
if (rc == -1) {
|
||||||
rc = emudev_register_device("rawnand");
|
return -1;
|
||||||
if (rc == -1) {
|
}
|
||||||
return -1;
|
|
||||||
}
|
/* Register boot0 device. */
|
||||||
|
rc = rawdev_register_device("boot0");
|
||||||
/* Open emulated raw NAND device. */
|
|
||||||
rawnand = fopen("rawnand:/", "rb");
|
if (rc == -1) {
|
||||||
|
return -1;
|
||||||
if (rawnand == NULL) {
|
}
|
||||||
return -1;
|
|
||||||
}
|
/* Setup a template for boot1. */
|
||||||
|
model = g_mmc_devpart_template;
|
||||||
/* Iterate the GPT and mount each emulated raw NAND partition. */
|
model.device_struct = &g_emmc_boot1_mmcpart;
|
||||||
rc = gpt_iterate_through_entries(rawnand, model.sector_size, nxfs_mount_partition_gpt_callback, &model);
|
model.start_sector = 0;
|
||||||
|
model.num_sectors = 0x80000 / model.sector_size;
|
||||||
/* Close emulated raw NAND device. */
|
|
||||||
fclose(rawnand);
|
/* Mount boot1 device. */
|
||||||
} else {
|
rc = rawdev_mount_device("boot1", &model, false);
|
||||||
/* Setup a template for boot0. */
|
|
||||||
model = g_mmc_devpart_template;
|
if (rc == -1) {
|
||||||
model.device_struct = &g_emmc_boot0_mmcpart;
|
return -1;
|
||||||
model.start_sector = 0;
|
|
||||||
model.num_sectors = 0x184000 / model.sector_size;
|
|
||||||
|
|
||||||
/* Mount boot0 device. */
|
|
||||||
rc = rawdev_mount_device("boot0", &model, true);
|
|
||||||
|
|
||||||
if (rc == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Register boot0 device. */
|
|
||||||
rc = rawdev_register_device("boot0");
|
|
||||||
|
|
||||||
if (rc == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Setup a template for boot1. */
|
|
||||||
model = g_mmc_devpart_template;
|
|
||||||
model.device_struct = &g_emmc_boot1_mmcpart;
|
|
||||||
model.start_sector = 0;
|
|
||||||
model.num_sectors = 0x80000 / model.sector_size;
|
|
||||||
|
|
||||||
/* Mount boot1 device. */
|
|
||||||
rc = rawdev_mount_device("boot1", &model, false);
|
|
||||||
|
|
||||||
if (rc == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Don't register boot1 for now. */
|
|
||||||
|
|
||||||
/* Setup a template for raw NAND. */
|
|
||||||
model = g_mmc_devpart_template;
|
|
||||||
model.device_struct = &g_emmc_user_mmcpart;
|
|
||||||
model.start_sector = 0;
|
|
||||||
model.num_sectors = (256ull << 30) / model.sector_size;
|
|
||||||
|
|
||||||
/* Mount raw NAND device. */
|
|
||||||
rc = rawdev_mount_device("rawnand", &model, false);
|
|
||||||
|
|
||||||
if (rc == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Register raw NAND device. */
|
|
||||||
rc = rawdev_register_device("rawnand");
|
|
||||||
if (rc == -1) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Open raw NAND device. */
|
|
||||||
rawnand = fopen("rawnand:/", "rb");
|
|
||||||
|
|
||||||
if (rawnand == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Iterate the GPT and mount each raw NAND partition. */
|
|
||||||
rc = gpt_iterate_through_entries(rawnand, model.sector_size, nxfs_mount_partition_gpt_callback, &model);
|
|
||||||
|
|
||||||
/* Close raw NAND device. */
|
|
||||||
fclose(rawnand);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the default file system device. */
|
/* Don't register boot1 for now. */
|
||||||
|
|
||||||
|
/* Setup a template for raw NAND. */
|
||||||
|
model = g_mmc_devpart_template;
|
||||||
|
model.device_struct = &g_emmc_user_mmcpart;
|
||||||
|
model.start_sector = 0;
|
||||||
|
model.num_sectors = (256ull << 30) / model.sector_size;
|
||||||
|
|
||||||
|
/* Mount raw NAND device. */
|
||||||
|
rc = rawdev_mount_device("rawnand", &model, false);
|
||||||
|
|
||||||
|
if (rc == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Register raw NAND device. */
|
||||||
|
rc = rawdev_register_device("rawnand");
|
||||||
|
if (rc == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open raw NAND device. */
|
||||||
|
rawnand = fopen("rawnand:/", "rb");
|
||||||
|
|
||||||
|
if (rawnand == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Iterate the GPT and mount each raw NAND partition. */
|
||||||
|
rc = gpt_iterate_through_entries(rawnand, model.sector_size, nxfs_mount_partition_gpt_callback, &model);
|
||||||
|
|
||||||
|
/* Close raw NAND device. */
|
||||||
|
fclose(rawnand);
|
||||||
|
|
||||||
|
/* All raw devices are ready. */
|
||||||
|
if (rc == 0) {
|
||||||
|
g_rawdev_ready = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nxfs_mount_emu_emmc(const char *emunand_path) {
|
||||||
|
device_partition_t model;
|
||||||
|
int rc;
|
||||||
|
FILE *rawnand;
|
||||||
|
|
||||||
|
/* Setup emunand paths. */
|
||||||
|
char emu_boot0_path[0x100];
|
||||||
|
char emu_boot1_path[0x100];
|
||||||
|
char emu_rawnand_path[0x100];
|
||||||
|
memset(emu_boot0_path, 0, sizeof(emu_boot0_path));
|
||||||
|
memset(emu_boot1_path, 0, sizeof(emu_boot1_path));
|
||||||
|
memset(emu_rawnand_path, 0, sizeof(emu_rawnand_path));
|
||||||
|
snprintf(emu_boot0_path, sizeof(emu_boot0_path), "sdmc:/%s/%s", emunand_path, "boot0");
|
||||||
|
snprintf(emu_boot1_path, sizeof(emu_boot1_path), "sdmc:/%s/%s", emunand_path, "boot1");
|
||||||
|
snprintf(emu_rawnand_path, sizeof(emu_rawnand_path), "sdmc:/%s/%s", emunand_path, "rawnand");
|
||||||
|
|
||||||
|
/* Setup an emulation template for boot0. */
|
||||||
|
model = g_emummc_devpart_template;
|
||||||
|
model.start_sector = 0;
|
||||||
|
model.num_sectors = 0x184000 / model.sector_size;
|
||||||
|
|
||||||
|
/* Mount emulated boot0 device. */
|
||||||
|
rc = emudev_mount_device("boot0", emu_boot0_path, &model);
|
||||||
|
|
||||||
|
if (rc == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Register emulated boot0 device. */
|
||||||
|
rc = emudev_register_device("boot0");
|
||||||
|
|
||||||
|
if (rc == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup an emulation template for boot1. */
|
||||||
|
model = g_emummc_devpart_template;
|
||||||
|
model.start_sector = 0;
|
||||||
|
model.num_sectors = 0x80000 / model.sector_size;
|
||||||
|
|
||||||
|
/* Mount emulated boot1 device. */
|
||||||
|
rc = emudev_mount_device("boot1", emu_boot1_path, &model);
|
||||||
|
|
||||||
|
if (rc == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Don't register emulated boot1 for now. */
|
||||||
|
|
||||||
|
/* Setup a template for raw NAND. */
|
||||||
|
model = g_emummc_devpart_template;
|
||||||
|
model.start_sector = 0;
|
||||||
|
model.num_sectors = (256ull << 30) / model.sector_size;
|
||||||
|
|
||||||
|
/* Mount emulated raw NAND device. */
|
||||||
|
rc = emudev_mount_device("rawnand", emu_rawnand_path, &model);
|
||||||
|
|
||||||
|
if (rc == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Register emulated raw NAND device. */
|
||||||
|
rc = emudev_register_device("rawnand");
|
||||||
|
if (rc == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open emulated raw NAND device. */
|
||||||
|
rawnand = fopen("rawnand:/", "rb");
|
||||||
|
|
||||||
|
if (rawnand == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Iterate the GPT and mount each emulated raw NAND partition. */
|
||||||
|
rc = gpt_iterate_through_entries(rawnand, model.sector_size, nxfs_mount_partition_gpt_callback, &model);
|
||||||
|
|
||||||
|
/* Close emulated raw NAND device. */
|
||||||
|
fclose(rawnand);
|
||||||
|
|
||||||
|
/* All emulated devices are ready. */
|
||||||
|
if (rc == 0) {
|
||||||
|
g_emudev_ready = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nxfs_unmount_sd() {
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
/* Unmount all fs devices. */
|
||||||
|
if (g_fsdev_ready) {
|
||||||
|
rc = fsdev_unmount_all();
|
||||||
|
g_fsdev_ready = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nxfs_unmount_emmc() {
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
/* Unmount all raw devices. */
|
||||||
|
if (g_rawdev_ready) {
|
||||||
|
rc = rawdev_unmount_all();
|
||||||
|
g_rawdev_ready = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nxfs_unmount_emu_emmc() {
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
/* Unmount all emulated devices. */
|
||||||
|
if (g_emudev_ready) {
|
||||||
|
rc = emudev_unmount_all();
|
||||||
|
g_emudev_ready = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nxfs_init() {
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/* Mount and register the SD card. */
|
||||||
|
rc = nxfs_mount_sd();
|
||||||
|
|
||||||
|
/* Set the SD card as the default file system device. */
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
rc = fsdev_set_default_device("sdmc");
|
rc = fsdev_set_default_device("sdmc");
|
||||||
}
|
}
|
||||||
|
@ -441,6 +518,6 @@ int nxfs_mount_all(bool emunand_enabled, const char *emunand_path) {
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int nxfs_unmount_all() {
|
int nxfs_end() {
|
||||||
return ((fsdev_unmount_all() || rawdev_unmount_all() || emudev_unmount_all()) ? -1 : 0);
|
return ((nxfs_unmount_sd() || nxfs_unmount_emmc() || nxfs_unmount_emu_emmc()) ? -1 : 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,14 @@
|
||||||
#include "raw_dev.h"
|
#include "raw_dev.h"
|
||||||
#include "emu_dev.h"
|
#include "emu_dev.h"
|
||||||
|
|
||||||
int nxfs_mount_all(bool emunand_enabled, const char *emunand_path);
|
int nxfs_init();
|
||||||
int nxfs_unmount_all();
|
int nxfs_end();
|
||||||
|
|
||||||
|
int nxfs_mount_sd();
|
||||||
|
int nxfs_mount_emmc();
|
||||||
|
int nxfs_mount_emu_emmc(const char *emunand_path);
|
||||||
|
int nxfs_unmount_sd();
|
||||||
|
int nxfs_unmount_emmc();
|
||||||
|
int nxfs_unmount_emu_emmc();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -32,9 +32,7 @@ typedef struct {
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
ScreenLogLevel log_level;
|
ScreenLogLevel log_level;
|
||||||
bool display_initialized;
|
bool display_initialized;
|
||||||
bool emunand_enabled;
|
|
||||||
char emunand_path[0x100];
|
|
||||||
char bct0[BCTO_MAX_SIZE];
|
char bct0[BCTO_MAX_SIZE];
|
||||||
} stage2_args_t;
|
} stage2_args_t;
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
Reference in a new issue