2 Commits

Author SHA1 Message Date
Christoph Baumann
f07eb50e68 support for sd redirection, changed config 2025-02-20 17:13:52 +01:00
Christoph Baumann
ed17414b50 initial support for emummc on emmc 2025-02-19 14:44:19 +01:00
8 changed files with 214 additions and 176 deletions

View File

@@ -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<const SecureMonitorStorageConfiguration>(); 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;

View File

@@ -279,32 +279,17 @@ namespace ams::secmon::smc {
break;
case ConfigItem::ExosphereAllowCalWrites:
/* Get whether this unit should allow writing to the calibration partition. */
args.r[1] = (GetEmummcEmmcConfiguration().IsActive() || GetSecmonConfiguration().AllowWritingToCalibrationBinarySysmmc());
args.r[1] = (GetEmummcConfiguration().IsEmummcActive() || GetSecmonConfiguration().AllowWritingToCalibrationBinarySysmmc());
break;
case ConfigItem::ExosphereEmummcEmmcType:
/* Get what kind of eMMC redirection this unit has active. */
/* NOTE: Even when returning 0, the emummc driver may be used if SD is redirected */
{
auto &cfg = GetEmummcEmmcConfiguration();
if(cfg.IsActive()) {
args.r[1] = cfg.base_cfg.type;
}else{
args.r[1] = 0;
}
}
break;
case ConfigItem::ExosphereEmummcSdType:
/* Get what kind of SD redirection this unit has active. */
/* NOTE: Even when returning 0, the emummc driver may be used if eMMC is redirected */
{
auto &cfg = GetEmummcSdConfiguration();
if(cfg.IsActive()) {
args.r[1] = cfg.base_cfg.type;
}else{
args.r[1] = 0;
}
}
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) {
@@ -440,65 +425,48 @@ namespace ams::secmon::smc {
const uintptr_t user_offset = user_address % 4_KB;
/* Validate arguments. */
/* NOTE: Only eMMC and SD redirection supported. GC redirection may be supported in the future */
SMC_R_UNLESS(mmc == EmummcMmc_Nand || mmc == EmummcMmc_Sd, NotSupported);
SMC_R_UNLESS(mmc != EmummcMmc_Nand || user_offset + 2 * sizeof(EmummcFilePath) <= 4_KB, InvalidArgument);
/* 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 = mmc == EmummcMmc_Nand ? GetEmummcConfiguration() : GetEmummcSdConfiguration();
/* Clear the output. */
constexpr size_t InlineOutputSize = sizeof(args) - sizeof(args.r[0]);
u8 * const inline_output = static_cast<u8 *>(static_cast<void *>(std::addressof(args.r[1])));
std::memset(inline_output, 0, InlineOutputSize);
if(mmc == EmummcMmc_Nand){
/* Copy emummc config for eMMC redirection */
/* Get emummc config for eMMC redirection */
const auto &cfg = GetEmummcEmmcConfiguration();
static_assert(sizeof(cfg.base_cfg) <= InlineOutputSize);
std::memcpy(inline_output, std::addressof(cfg.base_cfg), sizeof(cfg.base_cfg));
/* Copy out the configuration. */
{
/* Map the user output page. */
AtmosphereUserPageMapper mapper(user_address);
SMC_R_UNLESS(mapper.Map(), InvalidArgument);
switch(cfg.base_cfg.type){
case EmummcEmmcType_None:
/* Nothing to copy if disabled */
/* Copy the base configuration. */
static_assert(sizeof(cfg.base_cfg) <= InlineOutputSize);
std::memcpy(inline_output, std::addressof(cfg.base_cfg), sizeof(cfg.base_cfg));
/* Copy out type-specific data. */
switch (cfg.base_cfg.type) {
case EmummcType_Raw_Emmc:
/* No additional configuration needs to be copied. */
break;
case EmummcEmmcType_Partition_Emmc:
case EmummcEmmcType_Partition_Sd:
/* Copy file config, if file based */
case EmummcType_Partition_Sd:
case EmummcType_Partition_Emmc:
/* Copy the partition config. */
static_assert(sizeof(cfg.base_cfg) + sizeof(cfg.partition_cfg) <= InlineOutputSize);
std::memcpy(inline_output + sizeof(cfg.base_cfg), std::addressof(cfg.partition_cfg), sizeof(cfg.partition_cfg));
break;
case EmummcEmmcType_File_Emmc:
case EmummcEmmcType_File_Sd:
/* Copy partition config, if partition based */
case EmummcType_File:
/* Copy the file config. */
SMC_R_UNLESS(mapper.CopyToUser(user_address, std::addressof(cfg.file_cfg), sizeof(cfg.file_cfg)), InvalidArgument);
break;
AMS_UNREACHABLE_DEFAULT_CASE();
}
/* Copy the redirection directory path to the user page */
SMC_R_UNLESS(mapper.CopyToUser(user_address + sizeof(cfg.file_cfg), std::addressof(cfg.emu_dir_path), sizeof(cfg.emu_dir_path)), InvalidArgument);
}else if(mmc == EmummcMmc_Sd){
/* Copy emummc config for SD redirection */
/* Get emummc config for SD redirection */
const auto &cfg = GetEmummcSdConfiguration();
static_assert(sizeof(cfg.base_cfg) <= InlineOutputSize);
std::memcpy(inline_output, std::addressof(cfg.base_cfg), sizeof(cfg.base_cfg));
switch(cfg.base_cfg.type) {
case EmummcSdType_None:
break;
case EmummcSdType_Partition_Emmc:
static_assert(sizeof(cfg.base_cfg) + sizeof(cfg.partition_cfg) <= InlineOutputSize);
std::memcpy(inline_output + sizeof(cfg.base_cfg), std::addressof(cfg.partition_cfg), sizeof(cfg.partition_cfg));
break;
/* File based and SD partition based (currently) not supported for SD redirection */
AMS_UNREACHABLE_DEFAULT_CASE();
}
/* Copy the redirection directory path to the user page. */
SMC_R_UNLESS(mapper.CopyToUser(user_address + sizeof(EmummcFilePath), std::addressof(cfg.emu_dir_path), sizeof(cfg.emu_dir_path)), InvalidArgument);
}
return SmcResult::Success;

View File

@@ -47,13 +47,12 @@ namespace ams::secmon::smc {
ExosphereHasRcmBugPatch = 65004,
ExosphereBlankProdInfo = 65005,
ExosphereAllowCalWrites = 65006,
ExosphereEmummcEmmcType = 65007,
ExosphereEmummcType = 65007,
ExospherePayloadAddress = 65008,
ExosphereLogConfiguration = 65009,
ExosphereForceEnableUsb30 = 65010,
ExosphereSupportedHosVersion = 65011,
ExosphereApproximateApiVersion = 65012,
ExosphereEmummcSdType = 65013,
};
SmcResult SmcGetConfigUser(SmcArguments &args);

View File

@@ -236,16 +236,34 @@ namespace ams::nxboot {
void InitializeEmummc(bool emummc_enabled, const secmon::EmummcConfiguration &emummc_cfg) {
Result result;
if (emummc_enabled) {
/* Get sd card size. */
s64 sd_card_size;
if (R_FAILED((result = g_sd_card_storage.GetSize(std::addressof(sd_card_size))))) {
ShowFatalError("Failed to get sd card size: 0x%08" PRIx32 "!\n", result.GetValue());
}
if (emummc_cfg.base_cfg.type == secmon::EmummcType_Partition) {
if (emummc_cfg.base_cfg.type == secmon::EmummcType_Partition_Sd) {
/* Get sd card size. */
s64 sd_card_size;
if (R_FAILED((result = g_sd_card_storage.GetSize(std::addressof(sd_card_size))))) {
ShowFatalError("Failed to get sd card size: 0x%08" PRIx32 "!\n", result.GetValue());
}
const s64 partition_start = emummc_cfg.partition_cfg.start_sector * sdmmc::SectorSize;
g_boot0_storage = AllocateObject<fs::SubStorage>(g_sd_card_storage, partition_start, 4_MB);
g_user_storage = AllocateObject<fs::SubStorage>(g_sd_card_storage, partition_start + 8_MB, sd_card_size - (partition_start + 8_MB));
} else if (emummc_cfg.base_cfg.type == secmon::EmummcType_Partition_Emmc) {
{
const Result result = InitializeMmc();
if (R_FAILED(result)) {
ShowFatalError("Failed to initialize mmc: 0x%08" PRIx32 "\n", result.GetValue());
}
}
/* Get emmc size. */
s64 emmc_size;
if (R_FAILED((result = g_mmc_user_storage.GetSize(std::addressof(emmc_size))))) {
ShowFatalError("Failed to get emmc size: 0x%08" PRIx32 "!\n", result.GetValue());
}
const s64 partition_start = emummc_cfg.partition_cfg.start_sector * sdmmc::SectorSize;
g_boot0_storage = AllocateObject<fs::SubStorage>(g_mmc_user_storage, partition_start, 4_MB);
g_user_storage = AllocateObject<fs::SubStorage>(g_mmc_user_storage, partition_start + 8_MB, emmc_size - (partition_start + 8_MB));
} else if (emummc_cfg.base_cfg.type == secmon::EmummcType_File) {
/* Get the base emummc path. */
std::memcpy(g_emummc_path, emummc_cfg.file_cfg.path.str, sizeof(emummc_cfg.file_cfg.path.str));
@@ -288,6 +306,16 @@ namespace ams::nxboot {
/* Create partitions. */
g_boot0_storage = AllocateObject<fs::FileHandleStorage>(boot0_file);
g_user_storage = AllocateObject<EmummcFileStorage>(user00_file, len + 1);
} else if (emummc_cfg.base_cfg.type == secmon::EmummcType_Raw_Emmc) {
{
const Result result = InitializeMmc();
if(R_FAILED(result)) {
ShowFatalError("Failed to initialize mmc: 0x%08" PRIx32 "\n", result.GetValue());
}
}
g_boot0_storage = std::addressof(g_mmc_boot0_storage);
g_user_storage = std::addressof(g_mmc_user_storage);
} else {
ShowFatalError("Unknown emummc type %d\n", static_cast<int>(emummc_cfg.base_cfg.type));
}

View File

@@ -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,14 +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 = "";
secmon::EmummcType type = secmon::EmummcType_Max;
secmon::EmummcType type_sd = secmon::EmummcType_Max;
{
IniSectionList sections;
if (ParseIniSafe(sections, "sdmc:/emummc/emummc.ini")) {
@@ -150,11 +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, "type") == 0) {
type = static_cast<secmon::EmummcType>(ParseHexInteger(entry.value));
} else if (std::strcmp(entry.key, "type_sd") == 0) {
type_sd = static_cast<secmon::EmummcType>(ParseHexInteger(entry.value));
}
}
}
@@ -162,21 +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) {
if (sector > 0) {
g_emummc_cfg.base_cfg.type = secmon::EmummcType_Partition;
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 (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!");
}
}
@@ -494,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 */
{

View File

@@ -28,14 +28,18 @@ namespace ams::secmon {
};
union {
EmummcConfiguration emummc_cfg;
u8 _raw_emummc_config[0x128];
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]; */
};
@@ -88,12 +92,12 @@ namespace ams::secmon {
return GetConfigurationContext().secmon_cfg;
}
ALWAYS_INLINE const EmummcEmmcConfiguration &GetEmummcEmmcConfiguration() {
return GetConfigurationContext().emummc_cfg.emmc_cfg;
ALWAYS_INLINE const EmummcConfiguration &GetEmummcConfiguration() {
return GetConfigurationContext().emummc_cfg;
}
ALWAYS_INLINE const EmummcSdConfiguration &GetEmummcSdConfiguration() {
return GetConfigurationContext().emummc_cfg.sd_cfg;
return GetConfigurationContext().emummc_sd_cfg;
}
ALWAYS_INLINE const pkg1::BootConfig &GetBootConfig() {

View File

@@ -18,21 +18,13 @@
namespace ams::secmon {
enum EmummcEmmcType : u32 {
EmummcEmmcType_None = 0,
EmummcEmmcType_Partition_Sd = 1,
EmummcEmmcType_File_Sd = 2,
EmummcEmmcType_Partition_Emmc = 3,
EmummcEmmcType_File_Emmc = 4,
};
enum EmummcSdType : u32 {
EmummcSdType_None = 0,
EmummcSdType_Partition_Emmc = 3,
// Not (currently) supported
// EmummcSdType_Partition_Sd = 1,
// EmummcSdType_File_Sd = 2,
// EmummcSdType_File_Emmc = 4,
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 {
@@ -49,6 +41,24 @@ namespace ams::secmon {
static_assert(util::is_pod<EmummcFilePath>::value);
static_assert(sizeof(EmummcFilePath) == EmummcFilePathLengthMax);
struct EmummcBaseConfiguration {
static constexpr u32 Magic = util::FourCC<'E','F','S','0'>::Code;
u32 magic;
EmummcType type;
u32 id;
u32 fs_version;
constexpr bool IsValid() const {
return this->magic == Magic;
}
constexpr bool IsEmummcActive() const {
return this->IsValid() && this->type != EmummcType_Raw_Emmc;
}
};
static_assert(util::is_pod<EmummcBaseConfiguration>::value);
static_assert(sizeof(EmummcBaseConfiguration) == 0x10);
struct EmummcPartitionConfiguration {
u64 start_sector;
@@ -60,27 +70,8 @@ namespace ams::secmon {
};
static_assert(util::is_pod<EmummcFileConfiguration>::value);
struct EmummcEmmcBaseConfiguration {
static constexpr u32 Magic = util::FourCC<'E','F','S','0'>::Code;
u32 magic;
EmummcEmmcType type;
u32 id;
u32 fs_version;
constexpr bool IsValid() const {
return this->magic == Magic;
}
constexpr bool IsActive() const {
return this->IsValid() && this->type != EmummcEmmcType::EmummcType_None;
}
};
static_assert(util::is_pod<EmummcEmmcBaseConfiguration>::value);
static_assert(sizeof(EmummcEmmcBaseConfiguration) == 0x10);
struct EmummcEmmcConfiguration {
EmummcEmmcBaseConfiguration base_cfg;
struct EmummcConfiguration {
EmummcBaseConfiguration base_cfg;
union {
EmummcPartitionConfiguration partition_cfg;
EmummcFileConfiguration file_cfg;
@@ -91,54 +82,21 @@ namespace ams::secmon {
return this->base_cfg.IsValid();
}
constexpr bool IsActive() const {
return this->base_cfg.IsActive();
constexpr bool IsEmummcActive() const {
return this->base_cfg.IsEmummcActive();
}
};
static_assert(util::is_pod<EmummcEmmcConfiguration>::value);
static_assert(sizeof(EmummcEmmcConfiguration) == 0x110);
struct EmummcSdBaseConfiguration {
static constexpr u32 Magic = util::FourCC<'E','F','S','0'>::Code;
u32 magic;
EmummcSdType type;
u32 fs_version;
constexpr bool IsValid() const {
return this->magic == Magic;
}
constexpr bool IsActive() const {
return this->IsValid() && this->type != EmummcSdType::EmummcSdType_None;
}
};
static_assert(util::is_pod<EmummcSdBaseConfiguration>::value);
static_assert(sizeof(EmummcSdBaseConfiguration) == 0x0C);
struct EmummcSdConfiguration {
EmummcSdBaseConfiguration base_cfg;
union {
EmummcPartitionConfiguration partition_cfg;
// File based (currently) not supported
// EmummcFileConfiguration file_cfg
};
constexpr bool IsValid() const {
return this->base_cfg.IsValid();
}
constexpr bool IsActive() const {
return this->base_cfg.IsActive();
}
};
static_assert(util::is_pod<EmummcSdConfiguration>::value);
static_assert(sizeof(EmummcSdConfiguration) == 0x18);
struct EmummcConfiguration {
EmummcEmmcConfiguration emmc_cfg;
EmummcSdConfiguration sd_cfg;
};
static_assert(util::is_pod<EmummcConfiguration>::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;
}
};
}

View File

@@ -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<SecureMonitorStorageConfiguration>::value);
static_assert(sizeof(SecureMonitorStorageConfiguration) == 0x148);
static_assert(sizeof(SecureMonitorStorageConfiguration) == 0x240);
struct SecureMonitorConfiguration {
ams::TargetFirmware target_firmware;