mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-11-18 01:51:28 +01:00
loader: update for 20.0.0/21.0.0
This commit is contained in:
parent
4b32a2b964
commit
db71eefd9f
@ -100,6 +100,7 @@ namespace ams::ldr {
|
|||||||
Flag_CheckHashText = (1 << 3),
|
Flag_CheckHashText = (1 << 3),
|
||||||
Flag_CheckHashRo = (1 << 4),
|
Flag_CheckHashRo = (1 << 4),
|
||||||
Flag_CheckHashRw = (1 << 5),
|
Flag_CheckHashRw = (1 << 5),
|
||||||
|
Flag_PreventCodeReads = (1 << 6),
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SegmentInfo {
|
struct SegmentInfo {
|
||||||
@ -180,6 +181,8 @@ namespace ams::ldr {
|
|||||||
|
|
||||||
AcidFlag_PoolPartitionShift = 2,
|
AcidFlag_PoolPartitionShift = 2,
|
||||||
AcidFlag_PoolPartitionMask = (0xF << AcidFlag_PoolPartitionShift),
|
AcidFlag_PoolPartitionMask = (0xF << AcidFlag_PoolPartitionShift),
|
||||||
|
|
||||||
|
AcidFlag_LoadBrowserCoreDll = (1 << 7),
|
||||||
};
|
};
|
||||||
|
|
||||||
enum PoolPartition {
|
enum PoolPartition {
|
||||||
|
|||||||
@ -102,6 +102,8 @@ namespace ams::ncm {
|
|||||||
|
|
||||||
static const SystemProgramId End;
|
static const SystemProgramId End;
|
||||||
|
|
||||||
|
static const SystemProgramId BrowserCoreDll;
|
||||||
|
|
||||||
static const SystemProgramId Manu;
|
static const SystemProgramId Manu;
|
||||||
static const SystemProgramId Htc;
|
static const SystemProgramId Htc;
|
||||||
static const SystemProgramId DmntGen2;
|
static const SystemProgramId DmntGen2;
|
||||||
@ -212,6 +214,8 @@ namespace ams::ncm {
|
|||||||
|
|
||||||
inline constexpr const SystemProgramId SystemProgramId::End = { 0x01000000000007FFul };
|
inline constexpr const SystemProgramId SystemProgramId::End = { 0x01000000000007FFul };
|
||||||
|
|
||||||
|
inline constexpr const SystemProgramId SystemProgramId::BrowserCoreDll = { 0x010000000000085Dul };
|
||||||
|
|
||||||
inline constexpr const SystemProgramId SystemProgramId::Manu = { 0x010000000000B14Aul };
|
inline constexpr const SystemProgramId SystemProgramId::Manu = { 0x010000000000B14Aul };
|
||||||
inline constexpr const SystemProgramId SystemProgramId::Htc = { 0x010000000000B240ul };
|
inline constexpr const SystemProgramId SystemProgramId::Htc = { 0x010000000000B240ul };
|
||||||
inline constexpr const SystemProgramId SystemProgramId::DmntGen2 = { 0x010000000000D609ul };
|
inline constexpr const SystemProgramId SystemProgramId::DmntGen2 = { 0x010000000000D609ul };
|
||||||
|
|||||||
@ -18,31 +18,25 @@
|
|||||||
|
|
||||||
namespace ams::ldr {
|
namespace ams::ldr {
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
constinit os::SdkMutex g_scoped_code_mount_lock;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ScopedCodeMount functionality. */
|
/* ScopedCodeMount functionality. */
|
||||||
ScopedCodeMount::ScopedCodeMount(const ncm::ProgramLocation &loc, const ldr::ProgramAttributes &attrs) : m_lk(g_scoped_code_mount_lock), m_has_status(false), m_mounted_ams(false), m_mounted_sd_or_code(false), m_mounted_code(false) {
|
ScopedCodeMount::ScopedCodeMount(const ncm::ProgramLocation &loc, const ldr::ProgramAttributes &attrs, os::SdkMutex &mutex, const char *ams, const char *sd_b, const char *b) : m_lk(mutex), m_ams_path(ams), m_sd_or_base_path(sd_b), m_base_path(b), m_has_status(false), m_mounted_ams(false), m_mounted_sd_or_code(false), m_mounted_code(false) {
|
||||||
m_result = this->Initialize(loc, attrs);
|
m_result = this->Initialize(loc, attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScopedCodeMount::ScopedCodeMount(const ncm::ProgramLocation &loc, const cfg::OverrideStatus &o, const ldr::ProgramAttributes &attrs) : m_lk(g_scoped_code_mount_lock), m_override_status(o), m_has_status(true), m_mounted_ams(false), m_mounted_sd_or_code(false), m_mounted_code(false) {
|
ScopedCodeMount::ScopedCodeMount(const ncm::ProgramLocation &loc, const cfg::OverrideStatus &o, const ldr::ProgramAttributes &attrs, os::SdkMutex &mutex, const char *ams, const char *sd_b, const char *b) : m_lk(mutex), m_ams_path(ams), m_sd_or_base_path(sd_b), m_base_path(b), m_override_status(o), m_has_status(true), m_mounted_ams(false), m_mounted_sd_or_code(false), m_mounted_code(false) {
|
||||||
m_result = this->Initialize(loc, attrs);
|
m_result = this->Initialize(loc, attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
ScopedCodeMount::~ScopedCodeMount() {
|
ScopedCodeMount::~ScopedCodeMount() {
|
||||||
/* Unmount filesystems. */
|
/* Unmount filesystems. */
|
||||||
if (m_mounted_ams) {
|
if (m_mounted_ams) {
|
||||||
fs::Unmount(AtmosphereCodeMountName);
|
fs::Unmount(m_ams_path);
|
||||||
}
|
}
|
||||||
if (m_mounted_sd_or_code) {
|
if (m_mounted_sd_or_code) {
|
||||||
fs::Unmount(SdOrCodeMountName);
|
fs::Unmount(m_sd_or_base_path);
|
||||||
}
|
}
|
||||||
if (m_mounted_code) {
|
if (m_mounted_code) {
|
||||||
fs::Unmount(CodeMountName);
|
fs::Unmount(m_base_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,15 +53,15 @@ namespace ams::ldr {
|
|||||||
const auto content_attributes = attrs.content_attributes;
|
const auto content_attributes = attrs.content_attributes;
|
||||||
|
|
||||||
/* Mount the atmosphere code file system. */
|
/* Mount the atmosphere code file system. */
|
||||||
R_TRY(fs::MountCodeForAtmosphereWithRedirection(std::addressof(m_ams_code_verification_data), AtmosphereCodeMountName, content_path, content_attributes, loc.program_id, static_cast<ncm::StorageId>(loc.storage_id), m_override_status.IsHbl(), m_override_status.IsProgramSpecific()));
|
R_TRY(fs::MountCodeForAtmosphereWithRedirection(std::addressof(m_ams_code_verification_data), m_ams_path, content_path, content_attributes, loc.program_id, static_cast<ncm::StorageId>(loc.storage_id), m_override_status.IsHbl(), m_override_status.IsProgramSpecific()));
|
||||||
m_mounted_ams = true;
|
m_mounted_ams = true;
|
||||||
|
|
||||||
/* Mount the sd or base code file system. */
|
/* Mount the sd or base code file system. */
|
||||||
R_TRY(fs::MountCodeForAtmosphere(std::addressof(m_sd_or_base_code_verification_data), SdOrCodeMountName, content_path, content_attributes, loc.program_id, static_cast<ncm::StorageId>(loc.storage_id)));
|
R_TRY(fs::MountCodeForAtmosphere(std::addressof(m_sd_or_base_code_verification_data), m_sd_or_base_path, content_path, content_attributes, loc.program_id, static_cast<ncm::StorageId>(loc.storage_id)));
|
||||||
m_mounted_sd_or_code = true;
|
m_mounted_sd_or_code = true;
|
||||||
|
|
||||||
/* Mount the base code file system. */
|
/* Mount the base code file system. */
|
||||||
if (R_SUCCEEDED(fs::MountCode(std::addressof(m_base_code_verification_data), CodeMountName, content_path, content_attributes, loc.program_id, static_cast<ncm::StorageId>(loc.storage_id)))) {
|
if (R_SUCCEEDED(fs::MountCode(std::addressof(m_base_code_verification_data), m_base_path, content_path, content_attributes, loc.program_id, static_cast<ncm::StorageId>(loc.storage_id)))) {
|
||||||
m_mounted_code = true;
|
m_mounted_code = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,9 @@ namespace ams::ldr {
|
|||||||
NON_MOVEABLE(ScopedCodeMount);
|
NON_MOVEABLE(ScopedCodeMount);
|
||||||
private:
|
private:
|
||||||
std::scoped_lock<os::SdkMutex> m_lk;
|
std::scoped_lock<os::SdkMutex> m_lk;
|
||||||
|
const char *m_ams_path;
|
||||||
|
const char *m_sd_or_base_path;
|
||||||
|
const char *m_base_path;
|
||||||
cfg::OverrideStatus m_override_status;
|
cfg::OverrideStatus m_override_status;
|
||||||
fs::CodeVerificationData m_ams_code_verification_data;
|
fs::CodeVerificationData m_ams_code_verification_data;
|
||||||
fs::CodeVerificationData m_sd_or_base_code_verification_data;
|
fs::CodeVerificationData m_sd_or_base_code_verification_data;
|
||||||
@ -34,8 +37,8 @@ namespace ams::ldr {
|
|||||||
bool m_mounted_sd_or_code;
|
bool m_mounted_sd_or_code;
|
||||||
bool m_mounted_code;
|
bool m_mounted_code;
|
||||||
public:
|
public:
|
||||||
ScopedCodeMount(const ncm::ProgramLocation &loc, const ldr::ProgramAttributes &attrs);
|
ScopedCodeMount(const ncm::ProgramLocation &loc, const ldr::ProgramAttributes &attrs, os::SdkMutex &mutex, const char *ams, const char *sd_b, const char *b);
|
||||||
ScopedCodeMount(const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, const ldr::ProgramAttributes &attrs);
|
ScopedCodeMount(const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, const ldr::ProgramAttributes &attrs, os::SdkMutex &mutex, const char *ams, const char *sd_b, const char *b);
|
||||||
~ScopedCodeMount();
|
~ScopedCodeMount();
|
||||||
|
|
||||||
Result GetResult() const {
|
Result GetResult() const {
|
||||||
@ -65,15 +68,62 @@ namespace ams::ldr {
|
|||||||
|
|
||||||
constexpr inline const char * const AtmosphereCodeMountName = "ams-code";
|
constexpr inline const char * const AtmosphereCodeMountName = "ams-code";
|
||||||
constexpr inline const char * const AtmosphereCompatMountName = "ams-cmpt";
|
constexpr inline const char * const AtmosphereCompatMountName = "ams-cmpt";
|
||||||
|
constexpr inline const char * const AtmosphereBrowserCoreDllMountName = "ams-bdll";
|
||||||
constexpr inline const char * const SdOrCodeMountName = "sd-code";
|
constexpr inline const char * const SdOrCodeMountName = "sd-code";
|
||||||
|
constexpr inline const char * const SdOrCompatMountName = "sd-code";
|
||||||
|
constexpr inline const char * const SdOrBrowserCoreDllMountName = "sd-bdll";
|
||||||
constexpr inline const char * const CodeMountName = "code";
|
constexpr inline const char * const CodeMountName = "code";
|
||||||
constexpr inline const char * const CompatMountName = "cmpt";
|
constexpr inline const char * const CompatMountName = "cmpt";
|
||||||
|
constexpr inline const char * const BrowserCoreDllMountName = "bdll";
|
||||||
|
|
||||||
#define ENCODE_ATMOSPHERE_CODE_PATH(relative) "ams-code:" relative
|
#define ENCODE_ATMOSPHERE_CODE_PATH(relative) "ams-code:" relative
|
||||||
#define ENCODE_ATMOSPHERE_CMPT_PATH(relative) "ams-cmpt:" relative
|
#define ENCODE_ATMOSPHERE_CMPT_PATH(relative) "ams-cmpt:" relative
|
||||||
|
#define ENCODE_ATMOSPHERE_BDLL_PATH(relative) "ams-bdll:" relative
|
||||||
#define ENCODE_SD_OR_CODE_PATH(relative) "sd-code:" relative
|
#define ENCODE_SD_OR_CODE_PATH(relative) "sd-code:" relative
|
||||||
|
#define ENCODE_SD_OR_CMPT_PATH(relative) "sd-cmpt:" relative
|
||||||
|
#define ENCODE_SD_OR_BDLL_PATH(relative) "sd-bdll:" relative
|
||||||
#define ENCODE_CODE_PATH(relative) "code:" relative
|
#define ENCODE_CODE_PATH(relative) "code:" relative
|
||||||
#define ENCODE_CMPT_PATH(relative) "cmpt:" relative
|
#define ENCODE_CMPT_PATH(relative) "cmpt:" relative
|
||||||
|
#define ENCODE_BDLL_PATH(relative) "bdll:" relative
|
||||||
|
|
||||||
|
class ScopedCodeMountForCode : public ScopedCodeMount {
|
||||||
|
private:
|
||||||
|
static constinit inline os::SdkMutex s_mutex;
|
||||||
|
public:
|
||||||
|
ScopedCodeMountForCode(const ncm::ProgramLocation &loc, const ldr::ProgramAttributes &attrs) : ScopedCodeMount(loc, attrs, s_mutex, AtmosphereCodeMountName, SdOrCodeMountName, CodeMountName) {
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopedCodeMountForCode(const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, const ldr::ProgramAttributes &attrs) : ScopedCodeMount(loc, override_status, attrs, s_mutex, AtmosphereCodeMountName, SdOrCodeMountName, CodeMountName) {
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ScopedCodeMountForCompat : public ScopedCodeMount {
|
||||||
|
private:
|
||||||
|
static constinit inline os::SdkMutex s_mutex;
|
||||||
|
public:
|
||||||
|
ScopedCodeMountForCompat(const ncm::ProgramLocation &loc, const ldr::ProgramAttributes &attrs) : ScopedCodeMount(loc, attrs, s_mutex, AtmosphereCompatMountName, SdOrCompatMountName, CompatMountName) {
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopedCodeMountForCompat(const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, const ldr::ProgramAttributes &attrs) : ScopedCodeMount(loc, override_status, attrs, s_mutex, AtmosphereCompatMountName, SdOrCompatMountName, CompatMountName) {
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ScopedCodeMountForBrowserCoreDll : public ScopedCodeMount {
|
||||||
|
private:
|
||||||
|
static constinit inline os::SdkMutex s_mutex;
|
||||||
|
public:
|
||||||
|
ScopedCodeMountForBrowserCoreDll(const ncm::ProgramLocation &loc, const ldr::ProgramAttributes &attrs) : ScopedCodeMount(loc, attrs, s_mutex, AtmosphereBrowserCoreDllMountName, SdOrBrowserCoreDllMountName, BrowserCoreDllMountName) {
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopedCodeMountForBrowserCoreDll(const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, const ldr::ProgramAttributes &attrs) : ScopedCodeMount(loc, override_status, attrs, s_mutex, AtmosphereBrowserCoreDllMountName, SdOrBrowserCoreDllMountName, BrowserCoreDllMountName) {
|
||||||
|
/* ... */
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/* Redirection API. */
|
/* Redirection API. */
|
||||||
Result GetProgramPath(char *out_path, size_t out_size, const ncm::ProgramLocation &loc, const ldr::ProgramAttributes &attrs);
|
Result GetProgramPath(char *out_path, size_t out_size, const ncm::ProgramLocation &loc, const ldr::ProgramAttributes &attrs);
|
||||||
|
|||||||
@ -25,9 +25,13 @@ namespace ams::ldr {
|
|||||||
|
|
||||||
/* Convenience definitions. */
|
/* Convenience definitions. */
|
||||||
constexpr size_t MetaCacheBufferSize = 0x8000;
|
constexpr size_t MetaCacheBufferSize = 0x8000;
|
||||||
constexpr inline const char AtmosphereMetaPath[] = ENCODE_ATMOSPHERE_CODE_PATH("/main.npdm");
|
constexpr inline const char AtmosphereCodeMetaPath[] = ENCODE_ATMOSPHERE_CODE_PATH("/main.npdm");
|
||||||
constexpr inline const char SdOrBaseMetaPath[] = ENCODE_SD_OR_CODE_PATH("/main.npdm");
|
constexpr inline const char SdOrBaseCodeMetaPath[] = ENCODE_SD_OR_CODE_PATH("/main.npdm");
|
||||||
constexpr inline const char BaseMetaPath[] = ENCODE_CODE_PATH("/main.npdm");
|
constexpr inline const char BaseCodeMetaPath[] = ENCODE_CODE_PATH("/main.npdm");
|
||||||
|
|
||||||
|
constexpr inline const char AtmosphereBrowserCoreDllMetaPath[] = ENCODE_ATMOSPHERE_BDLL_PATH("/main.npdm");
|
||||||
|
constexpr inline const char SdOrBaseBrowserCoreDllMetaPath[] = ENCODE_SD_OR_BDLL_PATH("/main.npdm");
|
||||||
|
constexpr inline const char BaseBrowserCoreDllMetaPath[] = ENCODE_BDLL_PATH("/main.npdm");
|
||||||
|
|
||||||
/* Types. */
|
/* Types. */
|
||||||
struct MetaCache {
|
struct MetaCache {
|
||||||
@ -35,11 +39,40 @@ namespace ams::ldr {
|
|||||||
u8 buffer[MetaCacheBufferSize];
|
u8 buffer[MetaCacheBufferSize];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MetaLoader {
|
||||||
|
ncm::ProgramId m_cached_program_id;
|
||||||
|
cfg::OverrideStatus m_cached_override_status;
|
||||||
|
MetaCache m_meta_cache;
|
||||||
|
MetaCache m_original_meta_cache;
|
||||||
|
|
||||||
|
Result LoadMeta(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, ncm::ContentMetaPlatform platform, bool unk_unused, const char *ams_path, const char *sd_or_base_path, const char *base_path);
|
||||||
|
Result LoadMetaFromCache(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, ncm::ContentMetaPlatform platform, const char *ams_path, const char *sd_or_base_path, const char *base_path);
|
||||||
|
void InvalidateMetaCache();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MetaLoaderForCode : public MetaLoader {
|
||||||
|
Result LoadMeta(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, ncm::ContentMetaPlatform platform, bool unk_unused) {
|
||||||
|
R_RETURN(MetaLoader::LoadMeta(out_meta, loc, status, platform, unk_unused, AtmosphereCodeMetaPath, SdOrBaseCodeMetaPath, BaseCodeMetaPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result LoadMetaFromCache(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, ncm::ContentMetaPlatform platform) {
|
||||||
|
R_RETURN(MetaLoader::LoadMetaFromCache(out_meta, loc, status, platform, AtmosphereCodeMetaPath, SdOrBaseCodeMetaPath, BaseCodeMetaPath));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MetaLoaderForBdll : public MetaLoader {
|
||||||
|
Result LoadMeta(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, ncm::ContentMetaPlatform platform, bool unk_unused) {
|
||||||
|
R_RETURN(MetaLoader::LoadMeta(out_meta, loc, status, platform, unk_unused, AtmosphereBrowserCoreDllMetaPath, SdOrBaseBrowserCoreDllMetaPath, BaseBrowserCoreDllMetaPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result LoadMetaFromCache(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, ncm::ContentMetaPlatform platform) {
|
||||||
|
R_RETURN(MetaLoader::LoadMetaFromCache(out_meta, loc, status, platform, AtmosphereBrowserCoreDllMetaPath, SdOrBaseBrowserCoreDllMetaPath, BaseBrowserCoreDllMetaPath));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/* Global storage. */
|
/* Global storage. */
|
||||||
ncm::ProgramId g_cached_program_id;
|
MetaLoaderForCode g_meta_loader_for_code;
|
||||||
cfg::OverrideStatus g_cached_override_status;
|
MetaLoaderForBdll g_meta_loader_for_bdll;
|
||||||
MetaCache g_meta_cache;
|
|
||||||
MetaCache g_original_meta_cache;
|
|
||||||
|
|
||||||
/* Helpers. */
|
/* Helpers. */
|
||||||
Result ValidateSubregion(size_t allowed_start, size_t allowed_end, size_t start, size_t size, size_t min_size = 0) {
|
Result ValidateSubregion(size_t allowed_start, size_t allowed_end, size_t start, size_t size, size_t min_size = 0) {
|
||||||
@ -187,35 +220,32 @@ namespace ams::ldr {
|
|||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
Result MetaLoader::LoadMeta(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, ncm::ContentMetaPlatform platform, bool unk_unused, const char *ams_path, const char *sd_or_base_path, const char *base_path) {
|
||||||
|
|
||||||
/* API. */
|
|
||||||
Result LoadMeta(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, ncm::ContentMetaPlatform platform, bool unk_unused) {
|
|
||||||
/* Set the cached program id back to zero. */
|
/* Set the cached program id back to zero. */
|
||||||
g_cached_program_id = {};
|
m_cached_program_id = {};
|
||||||
|
|
||||||
/* Try to load meta from file. */
|
/* Try to load meta from file. */
|
||||||
fs::FileHandle file;
|
fs::FileHandle file;
|
||||||
R_TRY(fs::OpenFile(std::addressof(file), AtmosphereMetaPath, fs::OpenMode_Read));
|
R_TRY(fs::OpenFile(std::addressof(file), ams_path, fs::OpenMode_Read));
|
||||||
{
|
{
|
||||||
ON_SCOPE_EXIT { fs::CloseFile(file); };
|
ON_SCOPE_EXIT { fs::CloseFile(file); };
|
||||||
R_TRY(LoadMetaFromFile(file, std::addressof(g_meta_cache)));
|
R_TRY(LoadMetaFromFile(file, std::addressof(m_meta_cache)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Patch meta. Start by setting all program ids to the current program id. */
|
/* Patch meta. Start by setting all program ids to the current program id. */
|
||||||
Meta *meta = std::addressof(g_meta_cache.meta);
|
Meta *meta = std::addressof(m_meta_cache.meta);
|
||||||
meta->acid->program_id_min = loc.program_id;
|
meta->acid->program_id_min = loc.program_id;
|
||||||
meta->acid->program_id_max = loc.program_id;
|
meta->acid->program_id_max = loc.program_id;
|
||||||
meta->aci->program_id = loc.program_id;
|
meta->aci->program_id = loc.program_id;
|
||||||
|
|
||||||
/* For HBL, we need to copy some information from the base meta. */
|
/* For HBL, we need to copy some information from the base meta. */
|
||||||
if (status.IsHbl()) {
|
if (status.IsHbl()) {
|
||||||
if (R_SUCCEEDED(fs::OpenFile(std::addressof(file), SdOrBaseMetaPath, fs::OpenMode_Read))) {
|
if (R_SUCCEEDED(fs::OpenFile(std::addressof(file), sd_or_base_path, fs::OpenMode_Read))) {
|
||||||
ON_SCOPE_EXIT { fs::CloseFile(file); };
|
ON_SCOPE_EXIT { fs::CloseFile(file); };
|
||||||
|
|
||||||
|
|
||||||
if (R_SUCCEEDED(LoadMetaFromFile(file, std::addressof(g_original_meta_cache)))) {
|
if (R_SUCCEEDED(LoadMetaFromFile(file, std::addressof(m_original_meta_cache)))) {
|
||||||
Meta *o_meta = std::addressof(g_original_meta_cache.meta);
|
Meta *o_meta = std::addressof(m_original_meta_cache.meta);
|
||||||
|
|
||||||
/* Fix pool partition. */
|
/* Fix pool partition. */
|
||||||
if (hos::GetVersion() >= hos::Version_5_0_0) {
|
if (hos::GetVersion() >= hos::Version_5_0_0) {
|
||||||
@ -260,12 +290,12 @@ namespace ams::ldr {
|
|||||||
/* If storage id is none, there is no base code filesystem, and thus it is impossible for us to validate. */
|
/* If storage id is none, there is no base code filesystem, and thus it is impossible for us to validate. */
|
||||||
/* However, if we're an application, we are guaranteed a base code filesystem. */
|
/* However, if we're an application, we are guaranteed a base code filesystem. */
|
||||||
if (static_cast<ncm::StorageId>(loc.storage_id) != ncm::StorageId::None || ncm::IsApplicationId(loc.program_id)) {
|
if (static_cast<ncm::StorageId>(loc.storage_id) != ncm::StorageId::None || ncm::IsApplicationId(loc.program_id)) {
|
||||||
R_TRY(fs::OpenFile(std::addressof(file), BaseMetaPath, fs::OpenMode_Read));
|
R_TRY(fs::OpenFile(std::addressof(file), base_path, fs::OpenMode_Read));
|
||||||
ON_SCOPE_EXIT { fs::CloseFile(file); };
|
ON_SCOPE_EXIT { fs::CloseFile(file); };
|
||||||
R_TRY(LoadMetaFromFile(file, std::addressof(g_original_meta_cache)));
|
R_TRY(LoadMetaFromFile(file, std::addressof(m_original_meta_cache)));
|
||||||
R_TRY(ValidateAcidSignature(std::addressof(g_original_meta_cache.meta), platform, unk_unused));
|
R_TRY(ValidateAcidSignature(std::addressof(m_original_meta_cache.meta), platform, unk_unused));
|
||||||
meta->modulus = g_original_meta_cache.meta.modulus;
|
meta->modulus = m_original_meta_cache.meta.modulus;
|
||||||
meta->check_verification_data = g_original_meta_cache.meta.check_verification_data;
|
meta->check_verification_data = m_original_meta_cache.meta.check_verification_data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,24 +305,51 @@ namespace ams::ldr {
|
|||||||
PreProcessCapability(static_cast<util::BitPack32 *>(meta->aci_kac), meta->aci->kac_size / sizeof(util::BitPack32));
|
PreProcessCapability(static_cast<util::BitPack32 *>(meta->aci_kac), meta->aci->kac_size / sizeof(util::BitPack32));
|
||||||
|
|
||||||
/* Set output. */
|
/* Set output. */
|
||||||
g_cached_program_id = loc.program_id;
|
m_cached_program_id = loc.program_id;
|
||||||
g_cached_override_status = status;
|
m_cached_override_status = status;
|
||||||
*out_meta = *meta;
|
*out_meta = *meta;
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result LoadMetaFromCache(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, ncm::ContentMetaPlatform platform) {
|
Result MetaLoader::LoadMetaFromCache(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, ncm::ContentMetaPlatform platform, const char *ams_path, const char *sd_or_base_path, const char *base_path) {
|
||||||
if (g_cached_program_id != loc.program_id || g_cached_override_status != status) {
|
if (m_cached_program_id != loc.program_id || m_cached_override_status != status) {
|
||||||
R_RETURN(LoadMeta(out_meta, loc, status, platform, false));
|
R_RETURN(this->LoadMeta(out_meta, loc, status, platform, false, ams_path, sd_or_base_path, base_path));
|
||||||
}
|
}
|
||||||
*out_meta = g_meta_cache.meta;
|
*out_meta = m_meta_cache.meta;
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InvalidateMetaCache() {
|
void MetaLoader::InvalidateMetaCache() {
|
||||||
/* Set the cached program id back to zero. */
|
/* Set the cached program id back to zero. */
|
||||||
g_cached_program_id = {};
|
m_cached_program_id = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* API. */
|
||||||
|
Result LoadMeta(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, ncm::ContentMetaPlatform platform, bool unk_unused) {
|
||||||
|
R_RETURN(g_meta_loader_for_code.LoadMeta(out_meta, loc, status, platform, unk_unused));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result LoadMetaFromCache(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, ncm::ContentMetaPlatform platform) {
|
||||||
|
R_RETURN(g_meta_loader_for_code.LoadMetaFromCache(out_meta, loc, status, platform));
|
||||||
|
}
|
||||||
|
|
||||||
|
void InvalidateMetaCache() {
|
||||||
|
g_meta_loader_for_code.InvalidateMetaCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result LoadMetaForBrowserCoreDll(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, ncm::ContentMetaPlatform platform, bool unk_unused) {
|
||||||
|
R_RETURN(g_meta_loader_for_bdll.LoadMeta(out_meta, loc, status, platform, unk_unused));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result LoadMetaFromCacheForBrowserCoreDll(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, ncm::ContentMetaPlatform platform) {
|
||||||
|
R_RETURN(g_meta_loader_for_bdll.LoadMetaFromCache(out_meta, loc, status, platform));
|
||||||
|
}
|
||||||
|
|
||||||
|
void InvalidateMetaCacheForBrowserCoreDll() {
|
||||||
|
g_meta_loader_for_bdll.InvalidateMetaCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,4 +40,8 @@ namespace ams::ldr {
|
|||||||
Result LoadMetaFromCache(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, ncm::ContentMetaPlatform platform);
|
Result LoadMetaFromCache(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, ncm::ContentMetaPlatform platform);
|
||||||
void InvalidateMetaCache();
|
void InvalidateMetaCache();
|
||||||
|
|
||||||
|
Result LoadMetaForBrowserCoreDll(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, ncm::ContentMetaPlatform platform, bool unk_unused);
|
||||||
|
Result LoadMetaFromCacheForBrowserCoreDll(Meta *out_meta, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &status, ncm::ContentMetaPlatform platform);
|
||||||
|
void InvalidateMetaCacheForBrowserCoreDll();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,21 +29,22 @@ namespace ams::ldr {
|
|||||||
|
|
||||||
/* Convenience defines. */
|
/* Convenience defines. */
|
||||||
constexpr size_t SystemResourceSizeMax = 0x1FE00000;
|
constexpr size_t SystemResourceSizeMax = 0x1FE00000;
|
||||||
|
constexpr size_t AutoLoadModuleSizeMax = 0x800000000;
|
||||||
|
|
||||||
/* Types. */
|
/* Types. */
|
||||||
enum NsoIndex {
|
enum NsoIndex {
|
||||||
Nso_Rtld = 0,
|
Nso_Rtld = 0,
|
||||||
Nso_Main = 1,
|
Nso_Main = 1,
|
||||||
Nso_Compat0 = 2,
|
Nso_Wkc0 = 2,
|
||||||
Nso_Compat1 = 3,
|
Nso_Wkc1 = 3,
|
||||||
Nso_Compat2 = 4,
|
Nso_Wkc2 = 4,
|
||||||
Nso_Compat3 = 5,
|
Nso_Wkc3 = 5,
|
||||||
Nso_Compat4 = 6,
|
Nso_Wkc4 = 6,
|
||||||
Nso_Compat5 = 7,
|
Nso_Wkc5 = 7,
|
||||||
Nso_Compat6 = 8,
|
Nso_Wkc6 = 8,
|
||||||
Nso_Compat7 = 9,
|
Nso_Wkc7 = 9,
|
||||||
Nso_Compat8 = 10,
|
Nso_Wkc8 = 10,
|
||||||
Nso_Compat9 = 11,
|
Nso_Wkc9 = 11,
|
||||||
Nso_SubSdk0 = 12,
|
Nso_SubSdk0 = 12,
|
||||||
Nso_SubSdk1 = 13,
|
Nso_SubSdk1 = 13,
|
||||||
Nso_SubSdk2 = 14,
|
Nso_SubSdk2 = 14,
|
||||||
@ -61,16 +62,16 @@ namespace ams::ldr {
|
|||||||
constexpr inline const char *NsoPaths[Nso_Count] = {
|
constexpr inline const char *NsoPaths[Nso_Count] = {
|
||||||
ENCODE_ATMOSPHERE_CODE_PATH("/rtld"),
|
ENCODE_ATMOSPHERE_CODE_PATH("/rtld"),
|
||||||
ENCODE_ATMOSPHERE_CODE_PATH("/main"),
|
ENCODE_ATMOSPHERE_CODE_PATH("/main"),
|
||||||
ENCODE_ATMOSPHERE_CMPT_PATH("/compat0"),
|
ENCODE_ATMOSPHERE_BDLL_PATH("/wkc0"),
|
||||||
ENCODE_ATMOSPHERE_CMPT_PATH("/compat1"),
|
ENCODE_ATMOSPHERE_BDLL_PATH("/wkc1"),
|
||||||
ENCODE_ATMOSPHERE_CMPT_PATH("/compat2"),
|
ENCODE_ATMOSPHERE_BDLL_PATH("/wkc2"),
|
||||||
ENCODE_ATMOSPHERE_CMPT_PATH("/compat3"),
|
ENCODE_ATMOSPHERE_BDLL_PATH("/wkc3"),
|
||||||
ENCODE_ATMOSPHERE_CMPT_PATH("/compat4"),
|
ENCODE_ATMOSPHERE_BDLL_PATH("/wkc4"),
|
||||||
ENCODE_ATMOSPHERE_CMPT_PATH("/compat5"),
|
ENCODE_ATMOSPHERE_BDLL_PATH("/wkc5"),
|
||||||
ENCODE_ATMOSPHERE_CMPT_PATH("/compat6"),
|
ENCODE_ATMOSPHERE_BDLL_PATH("/wkc6"),
|
||||||
ENCODE_ATMOSPHERE_CMPT_PATH("/compat7"),
|
ENCODE_ATMOSPHERE_BDLL_PATH("/wkc7"),
|
||||||
ENCODE_ATMOSPHERE_CMPT_PATH("/compat8"),
|
ENCODE_ATMOSPHERE_BDLL_PATH("/wkc8"),
|
||||||
ENCODE_ATMOSPHERE_CMPT_PATH("/compat9"),
|
ENCODE_ATMOSPHERE_BDLL_PATH("/wkc9"),
|
||||||
ENCODE_ATMOSPHERE_CODE_PATH("/subsdk0"),
|
ENCODE_ATMOSPHERE_CODE_PATH("/subsdk0"),
|
||||||
ENCODE_ATMOSPHERE_CODE_PATH("/subsdk1"),
|
ENCODE_ATMOSPHERE_CODE_PATH("/subsdk1"),
|
||||||
ENCODE_ATMOSPHERE_CODE_PATH("/subsdk2"),
|
ENCODE_ATMOSPHERE_CODE_PATH("/subsdk2"),
|
||||||
@ -97,8 +98,15 @@ namespace ams::ldr {
|
|||||||
size_t nso_size[Nso_Count];
|
size_t nso_size[Nso_Count];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AutoLoadModuleInfo {
|
||||||
|
bool has_rtld;
|
||||||
|
bool has_main;
|
||||||
|
bool has_sdk;
|
||||||
|
bool has_subsdk;
|
||||||
|
bool has_nso[Nso_Count];
|
||||||
|
};
|
||||||
|
|
||||||
/* Global NSO header cache. */
|
/* Global NSO header cache. */
|
||||||
bool g_has_nso[Nso_Count];
|
|
||||||
NsoHeader g_nso_headers[Nso_Count];
|
NsoHeader g_nso_headers[Nso_Count];
|
||||||
|
|
||||||
Result ValidateProgramVersion(ncm::ProgramId program_id, u32 version) {
|
Result ValidateProgramVersion(ncm::ProgramId program_id, u32 version) {
|
||||||
@ -161,12 +169,30 @@ namespace ams::ldr {
|
|||||||
return static_cast<Acid::PoolPartition>((meta->acid->flags & Acid::AcidFlag_PoolPartitionMask) >> Acid::AcidFlag_PoolPartitionShift);
|
return static_cast<Acid::PoolPartition>((meta->acid->flags & Acid::AcidFlag_PoolPartitionMask) >> Acid::AcidFlag_PoolPartitionShift);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result LoadAutoLoadHeaders(NsoHeader *nso_headers, bool *has_nso) {
|
Result LoadAutoLoadHeaders(NsoHeader *nso_headers, AutoLoadModuleInfo *ali, u32 acid_flags) {
|
||||||
/* Clear NSOs. */
|
/* Clear NSOs. */
|
||||||
std::memset(nso_headers, 0, sizeof(*nso_headers) * Nso_Count);
|
std::memset(nso_headers, 0, sizeof(*nso_headers) * Nso_Count);
|
||||||
std::memset(has_nso, 0, sizeof(*has_nso) * Nso_Count);
|
*ali = {};
|
||||||
|
|
||||||
for (size_t i = 0; i < Nso_Count; i++) {
|
for (size_t i = 0; i < Nso_Count; i++) {
|
||||||
|
/* Only load browser DLLs if acid flags say to do so. */
|
||||||
|
switch (i) {
|
||||||
|
case Nso_Wkc0:
|
||||||
|
case Nso_Wkc1:
|
||||||
|
case Nso_Wkc2:
|
||||||
|
case Nso_Wkc3:
|
||||||
|
case Nso_Wkc4:
|
||||||
|
case Nso_Wkc5:
|
||||||
|
case Nso_Wkc6:
|
||||||
|
case Nso_Wkc7:
|
||||||
|
case Nso_Wkc8:
|
||||||
|
case Nso_Wkc9:
|
||||||
|
if ((acid_flags & Acid::AcidFlag_LoadBrowserCoreDll) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
fs::FileHandle file;
|
fs::FileHandle file;
|
||||||
if (R_SUCCEEDED(fs::OpenFile(std::addressof(file), GetNsoPath(i), fs::OpenMode_Read))) {
|
if (R_SUCCEEDED(fs::OpenFile(std::addressof(file), GetNsoPath(i), fs::OpenMode_Read))) {
|
||||||
ON_SCOPE_EXIT { fs::CloseFile(file); };
|
ON_SCOPE_EXIT { fs::CloseFile(file); };
|
||||||
@ -176,27 +202,82 @@ namespace ams::ldr {
|
|||||||
R_TRY(fs::ReadFile(std::addressof(read_size), file, 0, nso_headers + i, sizeof(*nso_headers)));
|
R_TRY(fs::ReadFile(std::addressof(read_size), file, 0, nso_headers + i, sizeof(*nso_headers)));
|
||||||
R_UNLESS(read_size == sizeof(*nso_headers), ldr::ResultInvalidNso());
|
R_UNLESS(read_size == sizeof(*nso_headers), ldr::ResultInvalidNso());
|
||||||
|
|
||||||
has_nso[i] = true;
|
/* Note nso is present. */
|
||||||
|
switch (i) {
|
||||||
|
case Nso_Rtld:
|
||||||
|
ali->has_rtld = true;
|
||||||
|
break;
|
||||||
|
case Nso_Main:
|
||||||
|
ali->has_main = true;
|
||||||
|
break;
|
||||||
|
case Nso_SubSdk0:
|
||||||
|
case Nso_SubSdk1:
|
||||||
|
case Nso_SubSdk2:
|
||||||
|
case Nso_SubSdk3:
|
||||||
|
case Nso_SubSdk4:
|
||||||
|
case Nso_SubSdk5:
|
||||||
|
case Nso_SubSdk6:
|
||||||
|
case Nso_SubSdk7:
|
||||||
|
case Nso_SubSdk8:
|
||||||
|
case Nso_SubSdk9:
|
||||||
|
ali->has_subsdk = true;
|
||||||
|
break;
|
||||||
|
case Nso_Sdk:
|
||||||
|
ali->has_sdk = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ali->has_nso[i] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result CheckAutoLoad(const NsoHeader *nso_headers, const bool *has_nso) {
|
Result CheckAutoLoad(const NsoHeader *nso_headers, const AutoLoadModuleInfo *ali, u32 acid_flags) {
|
||||||
/* We must always have a main. */
|
/* We must always have a main. */
|
||||||
R_UNLESS(has_nso[Nso_Main], ldr::ResultInvalidNso());
|
R_UNLESS(ali->has_main, ldr::ResultInvalidNso());
|
||||||
|
|
||||||
|
/* All NSOs must not be --X. */
|
||||||
|
/* This is "probably" not checked on Ounce? */
|
||||||
|
for (size_t i = 0; i < Nso_Count; ++i) {
|
||||||
|
R_UNLESS((nso_headers[i].flags & NsoHeader::Flag_PreventCodeReads) == 0, ldr::ResultInvalidNso());
|
||||||
|
}
|
||||||
|
|
||||||
/* If we don't have an RTLD, we must only have a main. */
|
/* If we don't have an RTLD, we must only have a main. */
|
||||||
if (!has_nso[Nso_Rtld]) {
|
const bool has_browser_dll = (acid_flags & Acid::AcidFlag_LoadBrowserCoreDll) != 0;
|
||||||
for (size_t i = Nso_Main + 1; i < Nso_Count; i++) {
|
if (ali->has_rtld) {
|
||||||
R_UNLESS(!has_nso[i], ldr::ResultInvalidNso());
|
/* If we have rtld, we must also have sdk. */
|
||||||
}
|
R_UNLESS(ali->has_sdk, ldr::ResultInvalidNso());
|
||||||
|
|
||||||
|
/* We must also only have one of [subsdk, browser dll]. */
|
||||||
|
R_UNLESS(!(ali->has_subsdk && has_browser_dll), ldr::ResultInvalidNso());
|
||||||
|
} else {
|
||||||
|
/* If we don't have rtld, we are not browser, and must not have browser core dll. */
|
||||||
|
R_UNLESS(!has_browser_dll, ldr::ResultInvalidNso());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* All NSOs must have zero text offset. */
|
/* Check NSO extents. */
|
||||||
for (size_t i = 0; i < Nso_Count; i++) {
|
for (size_t i = 0; i < Nso_Count; i++) {
|
||||||
|
/* Only validate the nsos we have. */
|
||||||
|
if (!ali->has_nso[i]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NSOs must have page-aligned segments. */
|
||||||
|
R_UNLESS(util::IsAligned(nso_headers[i].text_dst_offset, os::MemoryPageSize), ldr::ResultInvalidNso());
|
||||||
|
R_UNLESS(util::IsAligned(nso_headers[i].ro_dst_offset, os::MemoryPageSize), ldr::ResultInvalidNso());
|
||||||
|
R_UNLESS(util::IsAligned(nso_headers[i].rw_dst_offset, os::MemoryPageSize), ldr::ResultInvalidNso());
|
||||||
|
|
||||||
|
/* NSOs must have zero text offset. */
|
||||||
R_UNLESS(nso_headers[i].text_dst_offset == 0, ldr::ResultInvalidNso());
|
R_UNLESS(nso_headers[i].text_dst_offset == 0, ldr::ResultInvalidNso());
|
||||||
|
|
||||||
|
/* NSO .text must precede .rodata. */
|
||||||
|
const size_t text_end = static_cast<size_t>(nso_headers[i].text_dst_offset) + static_cast<size_t>(nso_headers[i].text_size);
|
||||||
|
R_UNLESS(text_end <= static_cast<size_t>(nso_headers[i].ro_dst_offset), ldr::ResultInvalidNso());
|
||||||
|
|
||||||
|
/* NSO .rodata must precede .rwdata. */
|
||||||
|
const size_t ro_end = static_cast<size_t>(nso_headers[i].ro_dst_offset) + static_cast<size_t>(nso_headers[i].ro_size);
|
||||||
|
R_UNLESS(ro_end <= static_cast<size_t>(nso_headers[i].rw_dst_offset), ldr::ResultInvalidNso());
|
||||||
}
|
}
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
@ -433,7 +514,7 @@ namespace ams::ldr {
|
|||||||
return rand % (max + 1);
|
return rand % (max + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result DecideAddressSpaceLayout(ProcessInfo *out, svc::CreateProcessParameter *out_param, const NsoHeader *nso_headers, const bool *has_nso, const ArgumentStore::Entry *argument) {
|
Result DecideAddressSpaceLayout(ProcessInfo *out, svc::CreateProcessParameter *out_param, const NsoHeader *nso_headers, const AutoLoadModuleInfo *ali, const ArgumentStore::Entry *argument) {
|
||||||
/* Clear output. */
|
/* Clear output. */
|
||||||
out->args_address = 0;
|
out->args_address = 0;
|
||||||
out->args_size = 0;
|
out->args_size = 0;
|
||||||
@ -445,22 +526,32 @@ namespace ams::ldr {
|
|||||||
|
|
||||||
/* Calculate base offsets. */
|
/* Calculate base offsets. */
|
||||||
for (size_t i = 0; i < Nso_Count; i++) {
|
for (size_t i = 0; i < Nso_Count; i++) {
|
||||||
if (has_nso[i]) {
|
if (ali->has_nso[i]) {
|
||||||
out->nso_address[i] = total_size;
|
out->nso_address[i] = total_size;
|
||||||
const size_t text_end = nso_headers[i].text_dst_offset + nso_headers[i].text_size;
|
const size_t text_end = static_cast<size_t>(nso_headers[i].text_dst_offset) + static_cast<size_t>(nso_headers[i].text_size);
|
||||||
const size_t ro_end = nso_headers[i].ro_dst_offset + nso_headers[i].ro_size;
|
const size_t ro_end = static_cast<size_t>(nso_headers[i].ro_dst_offset) + static_cast<size_t>(nso_headers[i].ro_size);
|
||||||
const size_t rw_end = nso_headers[i].rw_dst_offset + nso_headers[i].rw_size + nso_headers[i].bss_size;
|
const size_t rw_end = static_cast<size_t>(nso_headers[i].rw_dst_offset) + static_cast<size_t>(nso_headers[i].rw_size);
|
||||||
out->nso_size[i] = text_end;
|
out->nso_size[i] = text_end;
|
||||||
out->nso_size[i] = std::max(out->nso_size[i], ro_end);
|
out->nso_size[i] = std::max(out->nso_size[i], ro_end);
|
||||||
out->nso_size[i] = std::max(out->nso_size[i], rw_end);
|
out->nso_size[i] = std::max(out->nso_size[i], rw_end);
|
||||||
out->nso_size[i] = util::AlignUp(out->nso_size[i], os::MemoryPageSize);
|
out->nso_size[i] += static_cast<size_t>(nso_headers[i].bss_size);
|
||||||
|
|
||||||
|
const size_t aligned_up_size = util::AlignUp(out->nso_size[i], os::MemoryPageSize) & (AutoLoadModuleSizeMax - 1);
|
||||||
|
R_UNLESS(out->nso_size[i] <= aligned_up_size, ldr::ResultInvalidNso());
|
||||||
|
R_UNLESS(aligned_up_size > 0, ldr::ResultInvalidNso());
|
||||||
|
|
||||||
|
out->nso_size[i] = aligned_up_size;
|
||||||
|
|
||||||
|
R_UNLESS(util::CanAddWithoutOverflow(total_size, out->nso_size[i]), ldr::ResultInvalidNso());
|
||||||
total_size += out->nso_size[i];
|
total_size += out->nso_size[i];
|
||||||
|
|
||||||
if (!argument_allocated && argument != nullptr) {
|
if (!argument_allocated && argument != nullptr) {
|
||||||
out->args_address = total_size;
|
out->args_address = total_size;
|
||||||
out->args_size = util::AlignUp(2 * sizeof(u32) + argument->argument_size * 2 + ArgumentStore::ArgumentBufferSize, os::MemoryPageSize);
|
out->args_size = util::AlignUp(2 * sizeof(u32) + argument->argument_size * 2 + ArgumentStore::ArgumentBufferSize, os::MemoryPageSize);
|
||||||
|
|
||||||
|
R_UNLESS(util::CanAddWithoutOverflow(total_size, out->args_size), ldr::ResultInvalidNso());
|
||||||
total_size += out->args_size;
|
total_size += out->args_size;
|
||||||
|
|
||||||
argument_allocated = true;
|
argument_allocated = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -508,11 +599,13 @@ namespace ams::ldr {
|
|||||||
/* Set out. */
|
/* Set out. */
|
||||||
aslr_start += aslr_slide;
|
aslr_start += aslr_slide;
|
||||||
for (size_t i = 0; i < Nso_Count; i++) {
|
for (size_t i = 0; i < Nso_Count; i++) {
|
||||||
if (has_nso[i]) {
|
if (ali->has_nso[i]) {
|
||||||
|
R_UNLESS(util::CanAddWithoutOverflow(out->nso_address[i], aslr_start), ldr::ResultInvalidNso());
|
||||||
out->nso_address[i] += aslr_start;
|
out->nso_address[i] += aslr_start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (out->args_address) {
|
if (out->args_address) {
|
||||||
|
R_UNLESS(util::CanAddWithoutOverflow(out->args_address, aslr_start), ldr::ResultInvalidNso());
|
||||||
out->args_address += aslr_start;
|
out->args_address += aslr_start;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -555,7 +648,7 @@ namespace ams::ldr {
|
|||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result LoadAutoLoadModule(os::NativeHandle process_handle, fs::FileHandle file, const NsoHeader *nso_header, uintptr_t nso_address, size_t nso_size, bool prevent_code_reads) {
|
Result LoadAutoLoadModule(os::NativeHandle process_handle, fs::FileHandle file, const NsoHeader *nso_header, uintptr_t nso_address, size_t nso_size) {
|
||||||
/* Map and read data from file. */
|
/* Map and read data from file. */
|
||||||
{
|
{
|
||||||
/* Map the process memory. */
|
/* Map the process memory. */
|
||||||
@ -574,9 +667,9 @@ namespace ams::ldr {
|
|||||||
(nso_header->flags & NsoHeader::Flag_CheckHashRw) != 0, map_address + nso_header->rw_dst_offset, map_address + nso_size));
|
(nso_header->flags & NsoHeader::Flag_CheckHashRw) != 0, map_address + nso_header->rw_dst_offset, map_address + nso_size));
|
||||||
|
|
||||||
/* Clear unused space to zero. */
|
/* Clear unused space to zero. */
|
||||||
const size_t text_end = nso_header->text_dst_offset + nso_header->text_size;
|
const size_t text_end = static_cast<size_t>(nso_header->text_dst_offset) + static_cast<size_t>(nso_header->text_size);
|
||||||
const size_t ro_end = nso_header->ro_dst_offset + nso_header->ro_size;
|
const size_t ro_end = static_cast<size_t>(nso_header->ro_dst_offset) + static_cast<size_t>(nso_header->ro_size);
|
||||||
const size_t rw_end = nso_header->rw_dst_offset + nso_header->rw_size;
|
const size_t rw_end = static_cast<size_t>(nso_header->rw_dst_offset) + static_cast<size_t>(nso_header->rw_size);
|
||||||
std::memset(reinterpret_cast<void *>(map_address + 0), 0, nso_header->text_dst_offset);
|
std::memset(reinterpret_cast<void *>(map_address + 0), 0, nso_header->text_dst_offset);
|
||||||
std::memset(reinterpret_cast<void *>(map_address + text_end), 0, nso_header->ro_dst_offset - text_end);
|
std::memset(reinterpret_cast<void *>(map_address + text_end), 0, nso_header->ro_dst_offset - text_end);
|
||||||
std::memset(reinterpret_cast<void *>(map_address + ro_end), 0, nso_header->rw_dst_offset - ro_end);
|
std::memset(reinterpret_cast<void *>(map_address + ro_end), 0, nso_header->rw_dst_offset - ro_end);
|
||||||
@ -594,6 +687,7 @@ namespace ams::ldr {
|
|||||||
const size_t ro_size = util::AlignUp(nso_header->ro_size, os::MemoryPageSize);
|
const size_t ro_size = util::AlignUp(nso_header->ro_size, os::MemoryPageSize);
|
||||||
const size_t rw_size = util::AlignUp(nso_header->rw_size + nso_header->bss_size, os::MemoryPageSize);
|
const size_t rw_size = util::AlignUp(nso_header->rw_size + nso_header->bss_size, os::MemoryPageSize);
|
||||||
if (text_size) {
|
if (text_size) {
|
||||||
|
const bool prevent_code_reads = (nso_header->flags & NsoHeader::Flag_PreventCodeReads);
|
||||||
R_TRY(os::SetProcessMemoryPermission(process_handle, nso_address + nso_header->text_dst_offset, text_size, prevent_code_reads ? os::MemoryPermission_ExecuteOnly : os::MemoryPermission_ReadExecute));
|
R_TRY(os::SetProcessMemoryPermission(process_handle, nso_address + nso_header->text_dst_offset, text_size, prevent_code_reads ? os::MemoryPermission_ExecuteOnly : os::MemoryPermission_ReadExecute));
|
||||||
}
|
}
|
||||||
if (ro_size) {
|
if (ro_size) {
|
||||||
@ -606,15 +700,15 @@ namespace ams::ldr {
|
|||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result LoadAutoLoadModules(const ProcessInfo *process_info, const NsoHeader *nso_headers, const bool *has_nso, const ArgumentStore::Entry *argument, bool prevent_code_reads) {
|
Result LoadAutoLoadModules(const ProcessInfo *process_info, const NsoHeader *nso_headers, const AutoLoadModuleInfo *ali, const ArgumentStore::Entry *argument) {
|
||||||
/* Load each NSO. */
|
/* Load each NSO. */
|
||||||
for (size_t i = 0; i < Nso_Count; i++) {
|
for (size_t i = 0; i < Nso_Count; i++) {
|
||||||
if (has_nso[i]) {
|
if (ali->has_nso[i]) {
|
||||||
fs::FileHandle file;
|
fs::FileHandle file;
|
||||||
R_TRY(fs::OpenFile(std::addressof(file), GetNsoPath(i), fs::OpenMode_Read));
|
R_TRY(fs::OpenFile(std::addressof(file), GetNsoPath(i), fs::OpenMode_Read));
|
||||||
ON_SCOPE_EXIT { fs::CloseFile(file); };
|
ON_SCOPE_EXIT { fs::CloseFile(file); };
|
||||||
|
|
||||||
R_TRY(LoadAutoLoadModule(process_info->process_handle, file, nso_headers + i, process_info->nso_address[i], process_info->nso_size[i], prevent_code_reads));
|
R_TRY(LoadAutoLoadModule(process_info->process_handle, file, nso_headers + i, process_info->nso_address[i], process_info->nso_size[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -641,13 +735,13 @@ namespace ams::ldr {
|
|||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result CreateProcessAndLoadAutoLoadModules(ProcessInfo *out, const Meta *meta, const NsoHeader *nso_headers, const bool *has_nso, const ArgumentStore::Entry *argument, u32 flags, os::NativeHandle resource_limit) {
|
Result CreateProcessAndLoadAutoLoadModules(ProcessInfo *out, const Meta *meta, const NsoHeader *nso_headers, const AutoLoadModuleInfo *ali, const ArgumentStore::Entry *argument, u32 flags, os::NativeHandle resource_limit) {
|
||||||
/* Get CreateProcessParameter. */
|
/* Get CreateProcessParameter. */
|
||||||
svc::CreateProcessParameter param;
|
svc::CreateProcessParameter param;
|
||||||
R_TRY(GetCreateProcessParameter(std::addressof(param), meta, flags, resource_limit));
|
R_TRY(GetCreateProcessParameter(std::addressof(param), meta, flags, resource_limit));
|
||||||
|
|
||||||
/* Decide on an NSO layout. */
|
/* Decide on an NSO layout. */
|
||||||
R_TRY(DecideAddressSpaceLayout(out, std::addressof(param), nso_headers, has_nso, argument));
|
R_TRY(DecideAddressSpaceLayout(out, std::addressof(param), nso_headers, ali, argument));
|
||||||
|
|
||||||
/* Actually create process. */
|
/* Actually create process. */
|
||||||
svc::Handle process_handle;
|
svc::Handle process_handle;
|
||||||
@ -658,7 +752,7 @@ namespace ams::ldr {
|
|||||||
ON_RESULT_FAILURE { svc::CloseHandle(process_handle); };
|
ON_RESULT_FAILURE { svc::CloseHandle(process_handle); };
|
||||||
|
|
||||||
/* Load all auto load modules. */
|
/* Load all auto load modules. */
|
||||||
R_RETURN(LoadAutoLoadModules(out, nso_headers, has_nso, argument, (meta->npdm->flags & ldr::Npdm::MetaFlag_PreventCodeReads) != 0));
|
R_RETURN(LoadAutoLoadModules(out, nso_headers, ali, argument));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -667,7 +761,7 @@ namespace ams::ldr {
|
|||||||
Result CreateProcess(os::NativeHandle *out, PinId pin_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, const char *path, const ArgumentStore::Entry *argument, u32 flags, os::NativeHandle resource_limit, const ldr::ProgramAttributes &attrs) {
|
Result CreateProcess(os::NativeHandle *out, PinId pin_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, const char *path, const ArgumentStore::Entry *argument, u32 flags, os::NativeHandle resource_limit, const ldr::ProgramAttributes &attrs) {
|
||||||
/* Mount code. */
|
/* Mount code. */
|
||||||
AMS_UNUSED(path);
|
AMS_UNUSED(path);
|
||||||
ScopedCodeMount mount(loc, override_status, attrs);
|
ScopedCodeMountForCode mount(loc, override_status, attrs);
|
||||||
R_TRY(mount.GetResult());
|
R_TRY(mount.GetResult());
|
||||||
|
|
||||||
/* Load meta, possibly from cache. */
|
/* Load meta, possibly from cache. */
|
||||||
@ -677,13 +771,35 @@ namespace ams::ldr {
|
|||||||
/* Validate meta. */
|
/* Validate meta. */
|
||||||
R_TRY(ValidateMeta(std::addressof(meta), loc, mount.GetCodeVerificationData()));
|
R_TRY(ValidateMeta(std::addressof(meta), loc, mount.GetCodeVerificationData()));
|
||||||
|
|
||||||
|
/* If we should, load/validate the browser core dll. */
|
||||||
|
util::optional<ScopedCodeMountForBrowserCoreDll> bdll_mount;
|
||||||
|
if ((meta.acid->flags & Acid::AcidFlag_LoadBrowserCoreDll)) {
|
||||||
|
/* NOTE: I'm unsure whether we should be getting a fresh override status (allowing for different override between main and bdll?) */
|
||||||
|
/* or whether we should be using the main override status. Going to go with main, for sanity's sake. */
|
||||||
|
/* Also noting that Nintendo always passes ProgramAttributes=0 here, but this "should" be different on Ounce? */
|
||||||
|
/* Kind of unclear how to handle this without knowing what exactly is being ifdef'd. */
|
||||||
|
const ncm::ProgramLocation bdll_loc = ncm::ProgramLocation::Make(ncm::SystemProgramId::BrowserCoreDll, ncm::StorageId::BuiltInSystem);
|
||||||
|
const cfg::OverrideStatus bdll_override_status = override_status;
|
||||||
|
const ldr::ProgramAttributes bdll_attrs = attrs;
|
||||||
|
bdll_mount.emplace(bdll_loc, bdll_override_status, bdll_attrs);
|
||||||
|
R_TRY(bdll_mount->GetResult());
|
||||||
|
|
||||||
|
/* Load browser dll meta, possibly from cache. */
|
||||||
|
Meta bdll_meta;
|
||||||
|
R_TRY(LoadMetaFromCacheForBrowserCoreDll(std::addressof(bdll_meta), bdll_loc, bdll_override_status, bdll_attrs.platform));
|
||||||
|
|
||||||
|
/* Validate browser dll meta. */
|
||||||
|
R_TRY(ValidateMeta(std::addressof(bdll_meta), loc, mount.GetCodeVerificationData()));
|
||||||
|
}
|
||||||
|
|
||||||
/* Load, validate NSO headers. */
|
/* Load, validate NSO headers. */
|
||||||
R_TRY(LoadAutoLoadHeaders(g_nso_headers, g_has_nso));
|
AutoLoadModuleInfo auto_load_info = {};
|
||||||
R_TRY(CheckAutoLoad(g_nso_headers, g_has_nso));
|
R_TRY(LoadAutoLoadHeaders(g_nso_headers, std::addressof(auto_load_info), meta.acid->flags));
|
||||||
|
R_TRY(CheckAutoLoad(g_nso_headers, std::addressof(auto_load_info), meta.acid->flags));
|
||||||
|
|
||||||
/* Actually create the process and load NSOs into process memory. */
|
/* Actually create the process and load NSOs into process memory. */
|
||||||
ProcessInfo info;
|
ProcessInfo info;
|
||||||
R_TRY(CreateProcessAndLoadAutoLoadModules(std::addressof(info), std::addressof(meta), g_nso_headers, g_has_nso, argument, flags, resource_limit));
|
R_TRY(CreateProcessAndLoadAutoLoadModules(std::addressof(info), std::addressof(meta), g_nso_headers, std::addressof(auto_load_info), argument, flags, resource_limit));
|
||||||
|
|
||||||
/* Register NSOs with the RoManager. */
|
/* Register NSOs with the RoManager. */
|
||||||
{
|
{
|
||||||
@ -696,7 +812,7 @@ namespace ams::ldr {
|
|||||||
|
|
||||||
/* Register all NSOs. */
|
/* Register all NSOs. */
|
||||||
for (size_t i = 0; i < Nso_Count; i++) {
|
for (size_t i = 0; i < Nso_Count; i++) {
|
||||||
if (g_has_nso[i]) {
|
if (auto_load_info.has_nso[i]) {
|
||||||
RoManager::GetInstance().AddNso(pin_id, g_nso_headers[i].module_id, info.nso_address[i], info.nso_size[i]);
|
RoManager::GetInstance().AddNso(pin_id, g_nso_headers[i].module_id, info.nso_address[i], info.nso_size[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -727,7 +843,7 @@ namespace ams::ldr {
|
|||||||
{
|
{
|
||||||
AMS_UNUSED(path);
|
AMS_UNUSED(path);
|
||||||
|
|
||||||
ScopedCodeMount mount(loc, attrs);
|
ScopedCodeMountForCode mount(loc, attrs);
|
||||||
R_TRY(mount.GetResult());
|
R_TRY(mount.GetResult());
|
||||||
R_TRY(LoadMeta(std::addressof(meta), loc, mount.GetOverrideStatus(), attrs.platform, false));
|
R_TRY(LoadMeta(std::addressof(meta), loc, mount.GetOverrideStatus(), attrs.platform, false));
|
||||||
if (out_status != nullptr) {
|
if (out_status != nullptr) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user