diff --git a/exosphere/program/source/secmon_setup.cpp b/exosphere/program/source/secmon_setup.cpp index 6479fa43b..ab8ac87b1 100644 --- a/exosphere/program/source/secmon_setup.cpp +++ b/exosphere/program/source/secmon_setup.cpp @@ -91,7 +91,8 @@ namespace ams::secmon { /* If the storage context is valid, we want to copy it to the global context. */ if (const auto &storage_ctx = *MemoryRegionPhysicalDramMonitorConfiguration.GetPointer(); storage_ctx.IsValid()) { ctx.secmon_cfg.CopyFrom(storage_ctx); - ctx.emummc_cfg = storage_ctx.emummc_cfg; + ctx.emummc_cfg = storage_ctx.emummc_cfg; + ctx.emummc_sd_cfg = storage_ctx.emummc_sd_cfg; } else { /* If we don't have a valid storage context, we can just use the default one. */ ctx.secmon_cfg = DefaultSecureMonitorConfiguration; diff --git a/exosphere/program/source/smc/secmon_smc_info.cpp b/exosphere/program/source/smc/secmon_smc_info.cpp index 01cc412d6..a84fe8dda 100644 --- a/exosphere/program/source/smc/secmon_smc_info.cpp +++ b/exosphere/program/source/smc/secmon_smc_info.cpp @@ -284,8 +284,12 @@ namespace ams::secmon::smc { case ConfigItem::ExosphereEmummcType: /* Get what kind of emummc this unit has active. */ /* NOTE: This may return values other than 1 in the future. */ + // TODO: Return redirection type instead args.r[1] = (GetEmummcConfiguration().IsEmummcActive() ? 1 : 0); break; + // TODO: GetConfig to get sd redirection type? + // For sd redirection type 0 (EmummcType_Emmc_Raw) doesn't indicate disabled, + // Add EmummcType_Disabled to explicitly indicate no redirection? case ConfigItem::ExospherePayloadAddress: /* Gets the physical address of the reboot payload buffer, if one exists. */ if (g_payload_address != 0) { @@ -421,14 +425,12 @@ namespace ams::secmon::smc { const uintptr_t user_offset = user_address % 4_KB; /* Validate arguments. */ - /* NOTE: In the future, configuration for non-NAND storage may be implemented. */ - SMC_R_UNLESS(mmc == EmummcMmc_Nand, NotSupported); + /* NOTE: In the future, configuration for non-NAND/non-SD storage may be implemented. */ + SMC_R_UNLESS(mmc == EmummcMmc_Nand || mmc == EmummcMmc_Sd, NotSupported); SMC_R_UNLESS(user_offset + 2 * sizeof(EmummcFilePath) <= 4_KB, InvalidArgument); /* Get the emummc config. */ - const auto &cfg = GetEmummcConfiguration(); - static_assert(sizeof(cfg.file_cfg) == sizeof(EmummcFilePath)); - static_assert(sizeof(cfg.emu_dir_path) == sizeof(EmummcFilePath)); + const auto &cfg = mmc == EmummcMmc_Nand ? GetEmummcConfiguration() : GetEmummcSdConfiguration(); /* Clear the output. */ constexpr size_t InlineOutputSize = sizeof(args) - sizeof(args.r[0]); diff --git a/fusee/program/source/fusee_setup_horizon.cpp b/fusee/program/source/fusee_setup_horizon.cpp index 52cad9d3f..ffe76cbfe 100644 --- a/fusee/program/source/fusee_setup_horizon.cpp +++ b/fusee/program/source/fusee_setup_horizon.cpp @@ -37,7 +37,8 @@ namespace ams::nxboot { constexpr inline const uintptr_t PMC = secmon::MemoryRegionPhysicalDevicePmc.GetAddress(); constexpr inline const uintptr_t MC = secmon::MemoryRegionPhysicalDeviceMemoryController.GetAddress(); - constinit secmon::EmummcConfiguration g_emummc_cfg = {}; + constinit secmon::EmummcConfiguration g_emummc_cfg = {}; + constinit secmon::EmummcSdConfiguration g_emummc_sd_cfg = {}; void DeriveAllKeys(const fuse::SocType soc_type) { /* If on erista, run the TSEC keygen firmware. */ @@ -126,15 +127,24 @@ namespace ams::nxboot { bool ConfigureEmummc() { /* Set magic. */ - g_emummc_cfg.base_cfg.magic = secmon::EmummcBaseConfiguration::Magic; + g_emummc_cfg.base_cfg.magic = secmon::EmummcBaseConfiguration::Magic; + + g_emummc_sd_cfg.base_cfg.magic = secmon::EmummcBaseConfiguration::Magic; + // Add EmummcType_Disabled to explicitly indicate no redirection (vs. offset 0 + Partition_Sd / Emummc_Raw) + g_emummc_sd_cfg.base_cfg.type = secmon::EmummcType_Partition_Sd; /* Parse ini. */ - bool enabled = false; - u32 id = 0; - u32 sector = 0; - const char *path = ""; + bool enabled = false; + u32 id = 0; + u32 sector = 0; + bool has_sector = false; + u32 sector_sd = 0; + bool has_sector_sd = false; + const char *path = ""; const char *n_path = ""; - const char *device = ""; + secmon::EmummcType type = secmon::EmummcType_Max; + secmon::EmummcType type_sd = secmon::EmummcType_Max; + { IniSectionList sections; if (ParseIniSafe(sections, "sdmc:/emummc/emummc.ini")) { @@ -151,13 +161,19 @@ namespace ams::nxboot { } else if (std::strcmp(entry.key, "id") == 0) { id = ParseHexInteger(entry.value); } else if (std::strcmp(entry.key, "sector") == 0) { + has_sector = true; sector = ParseHexInteger(entry.value); + } else if (std::strcmp(entry.key, "sector_sd") == 0) { + has_sector_sd = true; + sector_sd = ParseHexInteger(entry.value); } else if (std::strcmp(entry.key, "path") == 0) { path = entry.value; } else if (std::strcmp(entry.key, "nintendo_path") == 0) { n_path = entry.value; - } else if (std::strcmp(entry.key, "device") == 0) { - device = entry.value; + } else if (std::strcmp(entry.key, "type") == 0) { + type = static_cast(ParseHexInteger(entry.value)); + } else if (std::strcmp(entry.key, "type_sd") == 0) { + type_sd = static_cast(ParseHexInteger(entry.value)); } } } @@ -165,31 +181,76 @@ namespace ams::nxboot { } /* Set values parsed from config. */ - g_emummc_cfg.base_cfg.id = id; + g_emummc_cfg.base_cfg.id = id; + g_emummc_sd_cfg.base_cfg.id = id; std::strncpy(g_emummc_cfg.emu_dir_path.str, n_path, sizeof(g_emummc_cfg.emu_dir_path.str)); g_emummc_cfg.emu_dir_path.str[sizeof(g_emummc_cfg.emu_dir_path.str) - 1] = '\x00'; + std::strncpy(g_emummc_sd_cfg.emu_dir_path.str, n_path, sizeof(g_emummc_sd_cfg.emu_dir_path.str)); + g_emummc_sd_cfg.emu_dir_path.str[sizeof(g_emummc_sd_cfg.emu_dir_path.str) - 1] = '\x00'; if (enabled) { - // TODO: proper ini config - if (std::strcmp(device, "no_redirect") == 0 ) { - g_emummc_cfg.base_cfg.type = secmon::EmummcType_Raw_Emmc; - } else if (sector > 0) { - if (std::strcmp(device, "sd") == 0 || device[0] == '\x00' ) { + bool has_valid_config = false; + if (has_sector) { + // Might want to redirect to sector 0 on sd/emmc gpp -> dont check if sector > 0 + if (type == secmon::EmummcType_Max) { + // When sector given, and type not explicitly set, assume raw sd g_emummc_cfg.base_cfg.type = secmon::EmummcType_Partition_Sd; - } else if (std::strcmp(device, "internal") == 0) { - g_emummc_cfg.base_cfg.type = secmon::EmummcType_Partition_Emmc; + } else if (type == secmon::EmummcType_Partition_Emmc || type == secmon::EmummcType_Partition_Emmc) { + g_emummc_cfg.base_cfg.type = type; } else { ShowFatalError("Invalid emummc setting!"); } g_emummc_cfg.partition_cfg.start_sector = sector; - } else if (path[0] != '\x00' && IsDirectoryExist(path)) { - g_emummc_cfg.base_cfg.type = secmon::EmummcType_File; + + has_valid_config = true; + } else if (path[0] != '\x00') { + if(!IsDirectoryExist(path)){ + ShowFatalError("Invalid emummc setting!"); + } + + if(type == secmon::EmummcType_File || type == secmon::EmummcType_Max){ + g_emummc_cfg.base_cfg.type = secmon::EmummcType_File; + } else { + ShowFatalError("Invalid emummc setting!"); + } std::strncpy(g_emummc_cfg.file_cfg.path.str, path, sizeof(g_emummc_cfg.file_cfg.path.str)); g_emummc_cfg.file_cfg.path.str[sizeof(g_emummc_cfg.file_cfg.path.str) - 1] = '\x00'; + + has_valid_config = true; } else { - ShowFatalError("Invalid emummc setting!\n"); + g_emummc_cfg.base_cfg.type = secmon::EmummcType_Raw_Emmc; + g_emummc_cfg.partition_cfg.start_sector = 0; + } + + if (has_sector_sd) { + if (type_sd == secmon::EmummcType_Partition_Sd || type_sd == secmon::EmummcType_Partition_Emmc) { + // must explicitly set sd type + g_emummc_sd_cfg.base_cfg.type = type_sd; + + has_valid_config = true; + } else { + ShowFatalError("Invalid emummc setting!"); + } + + g_emummc_sd_cfg.partition_cfg.start_sector = sector_sd; + + has_valid_config = true; + } else { + g_emummc_sd_cfg.base_cfg.type = secmon::EmummcType_Partition_Sd; + g_emummc_sd_cfg.partition_cfg.start_sector = 0; + } + + if(n_path[0] != '\0') { + // no redirection, but we have custom Nintendo path + // ...whyever one might use that + has_valid_config = true; + } + + if(!has_valid_config) { + // emummc enabled, but neither sd nor emmc redirected + ShowFatalError("Invalid emummc setting!"); } } @@ -507,13 +568,15 @@ namespace ams::nxboot { storage_ctx.target_firmware = target_firmware; storage_ctx.lcd_vendor = GetDisplayLcdVendor(); storage_ctx.emummc_cfg = g_emummc_cfg; + storage_ctx.emummc_sd_cfg = g_emummc_sd_cfg; storage_ctx.flags[0] = secmon::SecureMonitorConfigurationFlag_Default; storage_ctx.flags[1] = secmon::SecureMonitorConfigurationFlag_None; storage_ctx.log_port = uart::Port_ReservedDebug; storage_ctx.log_baud_rate = 115200; /* Set the fs version. */ - storage_ctx.emummc_cfg.base_cfg.fs_version = fs_version; + storage_ctx.emummc_cfg.base_cfg.fs_version = fs_version; + storage_ctx.emummc_sd_cfg.base_cfg.fs_version = fs_version; /* Parse fields from exosphere.ini */ { diff --git a/libraries/libexosphere/include/exosphere/secmon/secmon_configuration_context.arch.arm64.hpp b/libraries/libexosphere/include/exosphere/secmon/secmon_configuration_context.arch.arm64.hpp index 9eacd856f..19e3eca7f 100644 --- a/libraries/libexosphere/include/exosphere/secmon/secmon_configuration_context.arch.arm64.hpp +++ b/libraries/libexosphere/include/exosphere/secmon/secmon_configuration_context.arch.arm64.hpp @@ -30,12 +30,16 @@ namespace ams::secmon { EmummcConfiguration emummc_cfg; u8 _raw_emummc_config[0x120]; }; + union { + EmummcSdConfiguration emummc_sd_cfg; + u8 _raw_emummc_sd_config[0x120]; + }; u8 sealed_device_keys[pkg1::KeyGeneration_Max][se::AesBlockSize]; u8 sealed_master_keys[pkg1::KeyGeneration_Max][se::AesBlockSize]; pkg1::BootConfig boot_config; u8 rsa_private_exponents[4][se::RsaSize]; union { - u8 _misc_data[0xFC0 - sizeof(_raw_exosphere_config) - sizeof(_raw_emummc_config) - sizeof(sealed_device_keys) - sizeof(sealed_master_keys) - sizeof(boot_config) - sizeof(rsa_private_exponents)]; + u8 _misc_data[0xFC0 - sizeof(_raw_exosphere_config) - sizeof(_raw_emummc_sd_config) - sizeof(_raw_emummc_config) - sizeof(sealed_device_keys) - sizeof(sealed_master_keys) - sizeof(boot_config) - sizeof(rsa_private_exponents)]; }; /* u8 l1_page_table[0x40]; */ }; @@ -92,6 +96,10 @@ namespace ams::secmon { return GetConfigurationContext().emummc_cfg; } + ALWAYS_INLINE const EmummcSdConfiguration &GetEmummcSdConfiguration() { + return GetConfigurationContext().emummc_sd_cfg; + } + ALWAYS_INLINE const pkg1::BootConfig &GetBootConfig() { return GetConfigurationContext().boot_config; } diff --git a/libraries/libexosphere/include/exosphere/secmon/secmon_emummc_context.hpp b/libraries/libexosphere/include/exosphere/secmon/secmon_emummc_context.hpp index 1a54179dc..94d38c74a 100644 --- a/libraries/libexosphere/include/exosphere/secmon/secmon_emummc_context.hpp +++ b/libraries/libexosphere/include/exosphere/secmon/secmon_emummc_context.hpp @@ -19,10 +19,12 @@ namespace ams::secmon { enum EmummcType : u32 { + EmummcType_Min = 0, EmummcType_Raw_Emmc = 0, EmummcType_Partition_Sd = 1, EmummcType_Partition_Emmc = 2, EmummcType_File = 3, + EmummcType_Max = 4, }; enum EmummcMmc { @@ -87,4 +89,14 @@ namespace ams::secmon { static_assert(util::is_pod::value); static_assert(sizeof(EmummcConfiguration) <= 0x200); + struct EmummcSdConfiguration : public EmummcConfiguration { + constexpr bool IsEmummcActive() const { + if(IsValid()){ + if(this->base_cfg.type == EmummcType_Partition_Emmc || this->partition_cfg.start_sector != 0){ + return true; + } + } + return false; + } + }; } \ No newline at end of file diff --git a/libraries/libexosphere/include/exosphere/secmon/secmon_monitor_context.hpp b/libraries/libexosphere/include/exosphere/secmon/secmon_monitor_context.hpp index c37b76c82..7d886a525 100644 --- a/libraries/libexosphere/include/exosphere/secmon/secmon_monitor_context.hpp +++ b/libraries/libexosphere/include/exosphere/secmon/secmon_monitor_context.hpp @@ -45,12 +45,16 @@ namespace ams::secmon { u8 log_flags; u32 log_baud_rate; u32 reserved1[2]; - EmummcConfiguration emummc_cfg; + EmummcConfiguration emummc_cfg; + // TODO: most of emummc_sd_cfg is a duplicate of emummc_cfg + // (fs_version, id, n_path...), emu path never used since + // file based not supported for sd redirection. + EmummcSdConfiguration emummc_sd_cfg; constexpr bool IsValid() const { return this->magic == Magic; } }; static_assert(util::is_pod::value); - static_assert(sizeof(SecureMonitorStorageConfiguration) == 0x130); + static_assert(sizeof(SecureMonitorStorageConfiguration) == 0x240); struct SecureMonitorConfiguration { ams::TargetFirmware target_firmware;