mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-14 00:56:35 +00:00
ldr: address review commentary.
This commit is contained in:
parent
61fcf5e0f4
commit
6ba2090c01
8 changed files with 129 additions and 156 deletions
|
@ -28,7 +28,7 @@ namespace sts::ldr::args {
|
||||||
ArgumentInfo g_argument_infos[MaxArgumentInfos];
|
ArgumentInfo g_argument_infos[MaxArgumentInfos];
|
||||||
|
|
||||||
/* Helpers. */
|
/* Helpers. */
|
||||||
ArgumentInfo *GetArgumentInfo(ncm::TitleId title_id) {
|
ArgumentInfo *FindArgumentInfo(ncm::TitleId title_id) {
|
||||||
for (size_t i = 0; i < MaxArgumentInfos; i++) {
|
for (size_t i = 0; i < MaxArgumentInfos; i++) {
|
||||||
if (g_argument_infos[i].title_id == title_id) {
|
if (g_argument_infos[i].title_id == title_id) {
|
||||||
return &g_argument_infos[i];
|
return &g_argument_infos[i];
|
||||||
|
@ -37,15 +37,15 @@ namespace sts::ldr::args {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArgumentInfo *GetFreeArgumentInfo() {
|
ArgumentInfo *FindFreeArgumentInfo() {
|
||||||
return GetArgumentInfo(FreeTitleId);
|
return FindArgumentInfo(FreeTitleId);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* API. */
|
/* API. */
|
||||||
const ArgumentInfo *Get(ncm::TitleId title_id) {
|
const ArgumentInfo *Get(ncm::TitleId title_id) {
|
||||||
return GetArgumentInfo(title_id);
|
return FindArgumentInfo(title_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Set(ncm::TitleId title_id, const void *args, size_t args_size) {
|
Result Set(ncm::TitleId title_id, const void *args, size_t args_size) {
|
||||||
|
@ -53,9 +53,9 @@ namespace sts::ldr::args {
|
||||||
return ResultLoaderTooLongArgument;
|
return ResultLoaderTooLongArgument;
|
||||||
}
|
}
|
||||||
|
|
||||||
ArgumentInfo *arg_info = GetArgumentInfo(title_id);
|
ArgumentInfo *arg_info = FindArgumentInfo(title_id);
|
||||||
if (arg_info == nullptr) {
|
if (arg_info == nullptr) {
|
||||||
arg_info = GetFreeArgumentInfo();
|
arg_info = FindFreeArgumentInfo();
|
||||||
}
|
}
|
||||||
if (arg_info == nullptr) {
|
if (arg_info == nullptr) {
|
||||||
return ResultLoaderTooManyArguments;
|
return ResultLoaderTooManyArguments;
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
#include "ldr_capabilities.hpp"
|
#include "ldr_capabilities.hpp"
|
||||||
|
|
||||||
namespace sts::ldr {
|
namespace sts::ldr::caps {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -39,10 +39,10 @@ namespace sts::ldr {
|
||||||
return static_cast<CapabilityId>(__builtin_ctz(~cap));
|
return static_cast<CapabilityId>(__builtin_ctz(~cap));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<CapabilityId id>
|
template<CapabilityId Id>
|
||||||
class Capability {
|
class Capability {
|
||||||
public:
|
public:
|
||||||
static constexpr u32 ValueShift = static_cast<u32>(id) + 1;
|
static constexpr u32 ValueShift = static_cast<u32>(Id) + 1;
|
||||||
static constexpr u32 IdMask = (1u << (ValueShift - 1)) - 1;
|
static constexpr u32 IdMask = (1u << (ValueShift - 1)) - 1;
|
||||||
private:
|
private:
|
||||||
u32 value;
|
u32 value;
|
||||||
|
@ -50,7 +50,7 @@ namespace sts::ldr {
|
||||||
Capability(u32 v) : value(v) { /* ... */ }
|
Capability(u32 v) : value(v) { /* ... */ }
|
||||||
|
|
||||||
CapabilityId GetId() const {
|
CapabilityId GetId() const {
|
||||||
return id;
|
return Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 GetValue() const {
|
u32 GetValue() const {
|
||||||
|
@ -92,16 +92,16 @@ namespace sts::ldr {
|
||||||
bool IsValid(const u32 *kac, size_t kac_count) const {
|
bool IsValid(const u32 *kac, size_t kac_count) const {
|
||||||
for (size_t i = 0; i < kac_count; i++) {
|
for (size_t i = 0; i < kac_count; i++) {
|
||||||
if (GetCapabilityId(kac[i]) == this->GetId()) {
|
if (GetCapabilityId(kac[i]) == this->GetId()) {
|
||||||
const auto restrict = Decode(kac[i]);
|
const auto restriction = Decode(kac[i]);
|
||||||
|
|
||||||
if (this->GetMinimumThreadPriority() < restrict.GetMinimumThreadPriority() ||
|
if (this->GetMinimumThreadPriority() < restriction.GetMinimumThreadPriority() ||
|
||||||
this->GetMaximumThreadPriority() > restrict.GetMaximumThreadPriority() ||
|
this->GetMaximumThreadPriority() > restriction.GetMaximumThreadPriority() ||
|
||||||
this->GetMinimumThreadPriority() > this->GetMaximumThreadPriority()) {
|
this->GetMinimumThreadPriority() > this->GetMaximumThreadPriority()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->GetMinimumCoreId() < restrict.GetMinimumCoreId() ||
|
if (this->GetMinimumCoreId() < restriction.GetMinimumCoreId() ||
|
||||||
this->GetMaximumCoreId() > restrict.GetMaximumCoreId() ||
|
this->GetMaximumCoreId() > restriction.GetMaximumCoreId() ||
|
||||||
this->GetMinimumCoreId() > this->GetMaximumCoreId()) {
|
this->GetMinimumCoreId() > this->GetMaximumCoreId()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -125,9 +125,9 @@ namespace sts::ldr {
|
||||||
bool IsValid(const u32 *kac, size_t kac_count) const {
|
bool IsValid(const u32 *kac, size_t kac_count) const {
|
||||||
for (size_t i = 0; i < kac_count; i++) {
|
for (size_t i = 0; i < kac_count; i++) {
|
||||||
if (GetCapabilityId(kac[i]) == this->GetId()) {
|
if (GetCapabilityId(kac[i]) == this->GetId()) {
|
||||||
const auto restrict = Decode(kac[i]);
|
const auto restriction = Decode(kac[i]);
|
||||||
|
|
||||||
if (this->GetIndex() == restrict.GetIndex() && this->GetMask() == restrict.GetMask()) {
|
if (this->GetIndex() == restriction.GetIndex() && this->GetMask() == restriction.GetMask()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -162,22 +162,21 @@ namespace sts::ldr {
|
||||||
|
|
||||||
for (size_t i = 0; i < kac_count; i++) {
|
for (size_t i = 0; i < kac_count; i++) {
|
||||||
if (GetCapabilityId(kac[i]) == this->GetId()) {
|
if (GetCapabilityId(kac[i]) == this->GetId()) {
|
||||||
const auto restrict = Decode(kac[i]);
|
const auto restriction = Decode(kac[i++]);
|
||||||
i++;
|
|
||||||
if (i >= kac_count || GetCapabilityId(kac[i]) != this->GetId()) {
|
if (i >= kac_count || GetCapabilityId(kac[i]) != this->GetId()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto restrict_next = Decode(kac[i]);
|
const auto restriction_next = Decode(kac[i]);
|
||||||
const u32 restrict_start = restrict.GetAddressSize();
|
const u32 restriction_start = restriction.GetAddressSize();
|
||||||
const u32 restrict_size = restrict_next.GetAddressSize();
|
const u32 restriction_size = restriction_next.GetAddressSize();
|
||||||
const u32 restrict_end = restrict_start + restrict_size;
|
const u32 restriction_end = restriction_start + restriction_size;
|
||||||
|
|
||||||
if (restrict_size >= SizeMax) {
|
if (restriction_size >= SizeMax) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->GetFlag() == restrict.GetFlag() && next.GetFlag() == restrict_next.GetFlag()) {
|
if (this->GetFlag() == restriction.GetFlag() && next.GetFlag() == restriction_next.GetFlag()) {
|
||||||
if (restrict_start <= start && start <= restrict_end && end <= restrict_end) {
|
if (restriction_start <= start && start <= restriction_end && end <= restriction_end) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -195,9 +194,9 @@ namespace sts::ldr {
|
||||||
bool IsValid(const u32 *kac, size_t kac_count) const {
|
bool IsValid(const u32 *kac, size_t kac_count) const {
|
||||||
for (size_t i = 0; i < kac_count; i++) {
|
for (size_t i = 0; i < kac_count; i++) {
|
||||||
if (GetCapabilityId(kac[i]) == this->GetId()) {
|
if (GetCapabilityId(kac[i]) == this->GetId()) {
|
||||||
const auto restrict = Decode(kac[i]);
|
const auto restriction = Decode(kac[i]);
|
||||||
|
|
||||||
if (this->GetValue() == restrict.GetValue()) {
|
if (this->GetValue() == restriction.GetValue()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,8 +206,6 @@ namespace sts::ldr {
|
||||||
);
|
);
|
||||||
|
|
||||||
DEFINE_CAPABILITY_CLASS(InterruptPair,
|
DEFINE_CAPABILITY_CLASS(InterruptPair,
|
||||||
Result Validate(const u32 *kac, size_t kac_count) const;
|
|
||||||
|
|
||||||
static constexpr u32 EmptyInterruptId = 0x3FF;
|
static constexpr u32 EmptyInterruptId = 0x3FF;
|
||||||
|
|
||||||
u32 GetInterruptId0() const {
|
u32 GetInterruptId0() const {
|
||||||
|
@ -222,13 +219,13 @@ namespace sts::ldr {
|
||||||
bool IsSingleIdValid(const u32 id, const u32 *kac, size_t kac_count) const {
|
bool IsSingleIdValid(const u32 id, const u32 *kac, size_t kac_count) const {
|
||||||
for (size_t i = 0; i < kac_count; i++) {
|
for (size_t i = 0; i < kac_count; i++) {
|
||||||
if (GetCapabilityId(kac[i]) == this->GetId()) {
|
if (GetCapabilityId(kac[i]) == this->GetId()) {
|
||||||
const auto restrict = Decode(kac[i]);
|
const auto restriction = Decode(kac[i]);
|
||||||
|
|
||||||
if (restrict.GetInterruptId0() == EmptyInterruptId && restrict.GetInterruptId1() == EmptyInterruptId) {
|
if (restriction.GetInterruptId0() == EmptyInterruptId && restriction.GetInterruptId1() == EmptyInterruptId) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (restrict.GetInterruptId0() == id || restrict.GetInterruptId1() == id) {
|
if (restriction.GetInterruptId0() == id || restriction.GetInterruptId1() == id) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -249,9 +246,9 @@ namespace sts::ldr {
|
||||||
bool IsValid(const u32 *kac, size_t kac_count) const {
|
bool IsValid(const u32 *kac, size_t kac_count) const {
|
||||||
for (size_t i = 0; i < kac_count; i++) {
|
for (size_t i = 0; i < kac_count; i++) {
|
||||||
if (GetCapabilityId(kac[i]) == this->GetId()) {
|
if (GetCapabilityId(kac[i]) == this->GetId()) {
|
||||||
const auto restrict = Decode(kac[i]);
|
const auto restriction = Decode(kac[i]);
|
||||||
|
|
||||||
return restrict.GetValue() == this->GetValue();
|
return restriction.GetValue() == this->GetValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -275,9 +272,9 @@ namespace sts::ldr {
|
||||||
bool IsValid(const u32 *kac, size_t kac_count) const {
|
bool IsValid(const u32 *kac, size_t kac_count) const {
|
||||||
for (size_t i = 0; i < kac_count; i++) {
|
for (size_t i = 0; i < kac_count; i++) {
|
||||||
if (GetCapabilityId(kac[i]) == this->GetId()) {
|
if (GetCapabilityId(kac[i]) == this->GetId()) {
|
||||||
const auto restrict = Decode(kac[i]);
|
const auto restriction = Decode(kac[i]);
|
||||||
|
|
||||||
return restrict.GetValue() == this->GetValue();
|
return restriction.GetValue() == this->GetValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -292,9 +289,9 @@ namespace sts::ldr {
|
||||||
bool IsValid(const u32 *kac, size_t kac_count) const {
|
bool IsValid(const u32 *kac, size_t kac_count) const {
|
||||||
for (size_t i = 0; i < kac_count; i++) {
|
for (size_t i = 0; i < kac_count; i++) {
|
||||||
if (GetCapabilityId(kac[i]) == this->GetId()) {
|
if (GetCapabilityId(kac[i]) == this->GetId()) {
|
||||||
const auto restrict = Decode(kac[i]);
|
const auto restriction = Decode(kac[i]);
|
||||||
|
|
||||||
return this->GetSize() <= restrict.GetSize();
|
return this->GetSize() <= restriction.GetSize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -303,19 +300,19 @@ namespace sts::ldr {
|
||||||
|
|
||||||
DEFINE_CAPABILITY_CLASS(DebugFlags,
|
DEFINE_CAPABILITY_CLASS(DebugFlags,
|
||||||
bool GetAllowDebug() const {
|
bool GetAllowDebug() const {
|
||||||
return ((this->GetValue() >> 0) & 1) != 0;
|
return (this->GetValue() >> 0) & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetForceDebug() const {
|
bool GetForceDebug() const {
|
||||||
return ((this->GetValue() >> 1) & 1) != 0;
|
return (this->GetValue() >> 1) & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsValid(const u32 *kac, size_t kac_count) const {
|
bool IsValid(const u32 *kac, size_t kac_count) const {
|
||||||
for (size_t i = 0; i < kac_count; i++) {
|
for (size_t i = 0; i < kac_count; i++) {
|
||||||
if (GetCapabilityId(kac[i]) == this->GetId()) {
|
if (GetCapabilityId(kac[i]) == this->GetId()) {
|
||||||
const auto restrict = Decode(kac[i]);
|
const auto restriction = Decode(kac[i]);
|
||||||
|
|
||||||
return (restrict.GetValue() & this->GetValue()) == this->GetValue();
|
return (restriction.GetValue() & this->GetValue()) == this->GetValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
#include <stratosphere.hpp>
|
#include <stratosphere.hpp>
|
||||||
#include <stratosphere/ldr.hpp>
|
#include <stratosphere/ldr.hpp>
|
||||||
|
|
||||||
namespace sts::ldr {
|
namespace sts::ldr::caps {
|
||||||
|
|
||||||
/* Capabilities API. */
|
/* Capabilities API. */
|
||||||
Result ValidateCapabilities(const void *acid_kac, size_t acid_kac_size, const void *aci_kac, size_t aci_kac_size);
|
Result ValidateCapabilities(const void *acid_kac, size_t acid_kac_size, const void *aci_kac, size_t aci_kac_size);
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <stratosphere/cfg.hpp>
|
#include <stratosphere/cfg.hpp>
|
||||||
|
|
||||||
#include "ldr_content_management.hpp"
|
#include "ldr_content_management.hpp"
|
||||||
#include "ldr_ecs.hpp"
|
#include "ldr_ecs.hpp"
|
||||||
|
@ -39,6 +39,7 @@ namespace sts::ldr {
|
||||||
|
|
||||||
/* Helpers. */
|
/* Helpers. */
|
||||||
inline void FixFileSystemPath(char *path) {
|
inline void FixFileSystemPath(char *path) {
|
||||||
|
/* Paths will fail when passed to FS if they use the wrong kinds of slashes. */
|
||||||
for (size_t i = 0; i < FS_MAX_PATH && path[i]; i++) {
|
for (size_t i = 0; i < FS_MAX_PATH && path[i]; i++) {
|
||||||
if (path[i] == '\\') {
|
if (path[i] == '\\') {
|
||||||
path[i] = '/';
|
path[i] = '/';
|
||||||
|
@ -47,6 +48,7 @@ namespace sts::ldr {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const char *GetRelativePathStart(const char *relative_path) {
|
inline const char *GetRelativePathStart(const char *relative_path) {
|
||||||
|
/* We assume filenames don't start with slashes when formatting. */
|
||||||
while (*relative_path == '/' || *relative_path == '\\') {
|
while (*relative_path == '/' || *relative_path == '\\') {
|
||||||
relative_path++;
|
relative_path++;
|
||||||
}
|
}
|
||||||
|
@ -81,40 +83,7 @@ namespace sts::ldr {
|
||||||
Result MountNspFileSystem(const char *device_name, const char *path) {
|
Result MountNspFileSystem(const char *device_name, const char *path) {
|
||||||
FsFileSystem fs;
|
FsFileSystem fs;
|
||||||
R_TRY(fsOpenFileSystemWithId(&fs, 0, FsFileSystemType_ApplicationPackage, path));
|
R_TRY(fsOpenFileSystemWithId(&fs, 0, FsFileSystemType_ApplicationPackage, path));
|
||||||
if(fsdevMountDevice(device_name, fs) == -1) {
|
if(fsdevMountDevice(device_name, fs) < 0) {
|
||||||
std::abort();
|
|
||||||
}
|
|
||||||
return ResultSuccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result MountHblFileSystem() {
|
|
||||||
char path[FS_MAX_PATH];
|
|
||||||
|
|
||||||
/* Print and fix path. */
|
|
||||||
std::snprintf(path, FS_MAX_PATH, "%s:/%s", SdCardStorageMountPoint, GetRelativePathStart(cfg::GetHblPath()));
|
|
||||||
FixFileSystemPath(path);
|
|
||||||
return MountNspFileSystem(HblFileSystemDeviceName, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result MountSdCardCodeFileSystem(ncm::TitleId title_id) {
|
|
||||||
char path[FS_MAX_PATH];
|
|
||||||
|
|
||||||
/* Print and fix path. */
|
|
||||||
std::snprintf(path, FS_MAX_PATH, "%s:/atmosphere/titles/%016lx/exefs.nsp", SdCardStorageMountPoint, static_cast<u64>(title_id));
|
|
||||||
FixFileSystemPath(path);
|
|
||||||
return MountNspFileSystem(CodeFileSystemDeviceName, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result MountCodeFileSystem(const ncm::TitleLocation &loc) {
|
|
||||||
char path[FS_MAX_PATH];
|
|
||||||
|
|
||||||
/* Try to get the content path. */
|
|
||||||
R_TRY(ResolveContentPath(path, loc));
|
|
||||||
|
|
||||||
/* Try to mount the content path. */
|
|
||||||
FsFileSystem fs;
|
|
||||||
R_TRY(fsldrOpenCodeFileSystem(static_cast<u64>(loc.title_id), path, &fs));
|
|
||||||
if(fsdevMountDevice(CodeFileSystemDeviceName, fs) == -1) {
|
|
||||||
std::abort();
|
std::abort();
|
||||||
}
|
}
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
|
@ -166,17 +135,6 @@ namespace sts::ldr {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsMounted(const char *device_name) {
|
|
||||||
/* Allow nullptr device_name -- those are simply not openable. */
|
|
||||||
if (device_name == nullptr) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
char path[FS_MAX_PATH];
|
|
||||||
std::snprintf(path, FS_MAX_PATH, "%s:", device_name);
|
|
||||||
return FindDevice(device_name) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
FILE *OpenBaseExefsFile(ncm::TitleId title_id, const char *relative_path) {
|
FILE *OpenBaseExefsFile(ncm::TitleId title_id, const char *relative_path) {
|
||||||
/* Allow nullptr relative path -- those are simply not openable. */
|
/* Allow nullptr relative path -- those are simply not openable. */
|
||||||
if (relative_path == nullptr) {
|
if (relative_path == nullptr) {
|
||||||
|
@ -193,6 +151,11 @@ namespace sts::ldr {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ScopedCodeMount functionality. */
|
||||||
|
ScopedCodeMount::ScopedCodeMount(const ncm::TitleLocation &loc) : is_code_mounted(false), is_hbl_mounted(false) {
|
||||||
|
this->result = this->Initialize(loc);
|
||||||
|
}
|
||||||
|
|
||||||
ScopedCodeMount::~ScopedCodeMount() {
|
ScopedCodeMount::~ScopedCodeMount() {
|
||||||
/* Unmount devices. */
|
/* Unmount devices. */
|
||||||
if (this->is_code_mounted) {
|
if (this->is_code_mounted) {
|
||||||
|
@ -206,9 +169,52 @@ namespace sts::ldr {
|
||||||
InvalidateShouldOverrideCache();
|
InvalidateShouldOverrideCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result MountCode(ScopedCodeMount &out, const ncm::TitleLocation &loc) {
|
Result ScopedCodeMount::MountCodeFileSystem(const ncm::TitleLocation &loc) {
|
||||||
ScopedCodeMount mount;
|
char path[FS_MAX_PATH];
|
||||||
|
|
||||||
|
/* Try to get the content path. */
|
||||||
|
R_TRY(ResolveContentPath(path, loc));
|
||||||
|
|
||||||
|
/* Try to mount the content path. */
|
||||||
|
FsFileSystem fs;
|
||||||
|
R_TRY(fsldrOpenCodeFileSystem(static_cast<u64>(loc.title_id), path, &fs));
|
||||||
|
if(fsdevMountDevice(CodeFileSystemDeviceName, fs) == -1) {
|
||||||
|
std::abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note that we mounted code. */
|
||||||
|
this->is_code_mounted = true;
|
||||||
|
return ResultSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ScopedCodeMount::MountSdCardCodeFileSystem(const ncm::TitleLocation &loc) {
|
||||||
|
char path[FS_MAX_PATH];
|
||||||
|
|
||||||
|
/* Print and fix path. */
|
||||||
|
std::snprintf(path, FS_MAX_PATH, "%s:/atmosphere/titles/%016lx/exefs.nsp", SdCardStorageMountPoint, static_cast<u64>(loc.title_id));
|
||||||
|
FixFileSystemPath(path);
|
||||||
|
R_TRY(MountNspFileSystem(CodeFileSystemDeviceName, path));
|
||||||
|
|
||||||
|
/* Note that we mounted code. */
|
||||||
|
this->is_code_mounted = true;
|
||||||
|
return ResultSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ScopedCodeMount::MountHblFileSystem() {
|
||||||
|
char path[FS_MAX_PATH];
|
||||||
|
|
||||||
|
/* Print and fix path. */
|
||||||
|
std::snprintf(path, FS_MAX_PATH, "%s:/%s", SdCardStorageMountPoint, GetRelativePathStart(cfg::GetHblPath()));
|
||||||
|
FixFileSystemPath(path);
|
||||||
|
R_TRY(MountNspFileSystem(HblFileSystemDeviceName, path));
|
||||||
|
|
||||||
|
/* Note that we mounted HBL. */
|
||||||
|
this->is_hbl_mounted = true;
|
||||||
|
return ResultSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Result ScopedCodeMount::Initialize(const ncm::TitleLocation &loc) {
|
||||||
bool is_sd_initialized = cfg::IsSdCardInitialized();
|
bool is_sd_initialized = cfg::IsSdCardInitialized();
|
||||||
|
|
||||||
/* Check if we're ready to mount the SD card. */
|
/* Check if we're ready to mount the SD card. */
|
||||||
|
@ -222,25 +228,18 @@ namespace sts::ldr {
|
||||||
/* Check if we should override contents. */
|
/* Check if we should override contents. */
|
||||||
if (ShouldOverrideWithHbl(loc.title_id)) {
|
if (ShouldOverrideWithHbl(loc.title_id)) {
|
||||||
/* Try to mount HBL. */
|
/* Try to mount HBL. */
|
||||||
if (R_SUCCEEDED(MountHblFileSystem())) {
|
this->MountHblFileSystem();
|
||||||
mount.SetHblMounted();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (ShouldOverrideWithSd(loc.title_id)) {
|
if (ShouldOverrideWithSd(loc.title_id)) {
|
||||||
/* Try to mount Code NSP on SD. */
|
/* Try to mount Code NSP on SD. */
|
||||||
if (R_SUCCEEDED(MountSdCardCodeFileSystem(loc.title_id))) {
|
this->MountSdCardCodeFileSystem(loc);
|
||||||
mount.SetCodeMounted();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we haven't already mounted code, mount it. */
|
/* If we haven't already mounted code, mount it. */
|
||||||
if (!mount.IsCodeMounted()) {
|
if (!this->IsCodeMounted()) {
|
||||||
R_TRY(MountCodeFileSystem(loc));
|
R_TRY(this->MountCodeFileSystem(loc));
|
||||||
mount.SetCodeMounted();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set out to scoped holder. */
|
|
||||||
out = std::move(mount);
|
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,11 +247,11 @@ namespace sts::ldr {
|
||||||
FILE *f = nullptr;
|
FILE *f = nullptr;
|
||||||
const char *ecs_device_name = ecs::Get(title_id);
|
const char *ecs_device_name = ecs::Get(title_id);
|
||||||
|
|
||||||
if (IsMounted(ecs_device_name)) {
|
if (ecs_device_name != nullptr) {
|
||||||
/* First priority: Open from external content. */
|
/* First priority: Open from external content. */
|
||||||
f = OpenFile(ecs_device_name, relative_path);
|
f = OpenFile(ecs_device_name, relative_path);
|
||||||
} else if (ShouldOverrideWithHbl(title_id)) {
|
} else if (ShouldOverrideWithHbl(title_id)) {
|
||||||
/* Next, try to mount from HBL. */
|
/* Next, try to open from HBL. */
|
||||||
f = OpenFile(HblFileSystemDeviceName, relative_path);
|
f = OpenFile(HblFileSystemDeviceName, relative_path);
|
||||||
} else {
|
} else {
|
||||||
/* If not ECS or HBL, try a loose file on the SD. */
|
/* If not ECS or HBL, try a loose file on the SD. */
|
||||||
|
@ -323,7 +322,7 @@ namespace sts::ldr {
|
||||||
Result RedirectHtmlDocumentPathForHbl(const ncm::TitleLocation &loc) {
|
Result RedirectHtmlDocumentPathForHbl(const ncm::TitleLocation &loc) {
|
||||||
char path[FS_MAX_PATH];
|
char path[FS_MAX_PATH];
|
||||||
|
|
||||||
/* Open a locaiton resolver. */
|
/* Open a location resolver. */
|
||||||
LrLocationResolver lr;
|
LrLocationResolver lr;
|
||||||
R_TRY(lrOpenLocationResolver(static_cast<FsStorageId>(loc.storage_id), &lr));
|
R_TRY(lrOpenLocationResolver(static_cast<FsStorageId>(loc.storage_id), &lr));
|
||||||
ON_SCOPE_EXIT { serviceClose(&lr.s); };
|
ON_SCOPE_EXIT { serviceClose(&lr.s); };
|
||||||
|
|
|
@ -25,36 +25,15 @@ namespace sts::ldr {
|
||||||
class ScopedCodeMount {
|
class ScopedCodeMount {
|
||||||
NON_COPYABLE(ScopedCodeMount);
|
NON_COPYABLE(ScopedCodeMount);
|
||||||
private:
|
private:
|
||||||
|
Result result;
|
||||||
bool is_code_mounted;
|
bool is_code_mounted;
|
||||||
bool is_hbl_mounted;
|
bool is_hbl_mounted;
|
||||||
public:
|
public:
|
||||||
ScopedCodeMount() : is_code_mounted(false), is_hbl_mounted(false) { /* ... */ }
|
ScopedCodeMount(const ncm::TitleLocation &loc);
|
||||||
ScopedCodeMount(bool c, bool h) : is_code_mounted(c), is_hbl_mounted(h) { /* ... */ }
|
|
||||||
~ScopedCodeMount();
|
~ScopedCodeMount();
|
||||||
|
|
||||||
ScopedCodeMount(ScopedCodeMount&& rhs) {
|
Result GetResult() const {
|
||||||
this->is_code_mounted = rhs.is_code_mounted;
|
return this->result;
|
||||||
this->is_hbl_mounted = rhs.is_hbl_mounted;
|
|
||||||
rhs.is_code_mounted = false;
|
|
||||||
rhs.is_hbl_mounted = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ScopedCodeMount& operator=(ScopedCodeMount&& rhs) {
|
|
||||||
rhs.Swap(*this);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Swap(ScopedCodeMount& rhs) {
|
|
||||||
std::swap(this->is_code_mounted, rhs.is_code_mounted);
|
|
||||||
std::swap(this->is_hbl_mounted, rhs.is_hbl_mounted);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetCodeMounted() {
|
|
||||||
this->is_code_mounted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetHblMounted() {
|
|
||||||
this->is_hbl_mounted = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsCodeMounted() const {
|
bool IsCodeMounted() const {
|
||||||
|
@ -62,12 +41,18 @@ namespace sts::ldr {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsHblMounted() const {
|
bool IsHblMounted() const {
|
||||||
return this->is_hbl_mounted;
|
return this->is_code_mounted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Result Initialize(const ncm::TitleLocation &loc);
|
||||||
|
|
||||||
|
Result MountCodeFileSystem(const ncm::TitleLocation &loc);
|
||||||
|
Result MountSdCardCodeFileSystem(const ncm::TitleLocation &loc);
|
||||||
|
Result MountHblFileSystem();
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Content Management API. */
|
/* Content Management API. */
|
||||||
Result MountCode(ScopedCodeMount &out, const ncm::TitleLocation &loc);
|
|
||||||
Result OpenCodeFile(FILE *&out, ncm::TitleId title_id, const char *relative_path);
|
Result OpenCodeFile(FILE *&out, ncm::TitleId title_id, const char *relative_path);
|
||||||
Result OpenCodeFileFromBaseExefs(FILE *&out, ncm::TitleId title_id, const char *relative_path);
|
Result OpenCodeFileFromBaseExefs(FILE *&out, ncm::TitleId title_id, const char *relative_path);
|
||||||
|
|
||||||
|
|
|
@ -74,12 +74,7 @@ namespace sts::ldr::ecs {
|
||||||
|
|
||||||
/* Create session. */
|
/* Create session. */
|
||||||
AutoHandle server, client;
|
AutoHandle server, client;
|
||||||
{
|
R_TRY(svcCreateSession(server.GetPointer(), client.GetPointer(), 0, 0));
|
||||||
Handle s_h, c_h;
|
|
||||||
R_TRY(svcCreateSession(&s_h, &c_h, 0, 0));
|
|
||||||
server.Reset(s_h);
|
|
||||||
client.Reset(c_h);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create service. */
|
/* Create service. */
|
||||||
Service srv;
|
Service srv;
|
||||||
|
@ -100,10 +95,7 @@ namespace sts::ldr::ecs {
|
||||||
|
|
||||||
Result Clear(ncm::TitleId title_id) {
|
Result Clear(ncm::TitleId title_id) {
|
||||||
/* Delete if present. */
|
/* Delete if present. */
|
||||||
auto it = g_map.find(static_cast<u64>(title_id));
|
g_map.erase(static_cast<u64>(title_id));
|
||||||
if (it != g_map.end()) {
|
|
||||||
g_map.erase(it);
|
|
||||||
}
|
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -187,9 +187,9 @@ namespace sts::ldr {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fix flags. */
|
/* Fix flags. */
|
||||||
const u16 program_info_flags = GetProgramInfoFlags(o_meta->aci_kac, o_meta->aci->kac_size);
|
const u16 program_info_flags = caps::GetProgramInfoFlags(o_meta->aci_kac, o_meta->aci->kac_size);
|
||||||
SetProgramInfoFlags(program_info_flags, meta->acid_kac, meta->acid->kac_size);
|
caps::SetProgramInfoFlags(program_info_flags, meta->acid_kac, meta->acid->kac_size);
|
||||||
SetProgramInfoFlags(program_info_flags, meta->aci_kac, meta->aci->kac_size);
|
caps::SetProgramInfoFlags(program_info_flags, meta->aci_kac, meta->aci->kac_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -175,16 +175,16 @@ namespace sts::ldr {
|
||||||
#undef COPY_ACCESS_CONTROL
|
#undef COPY_ACCESS_CONTROL
|
||||||
|
|
||||||
/* Copy flags. */
|
/* Copy flags. */
|
||||||
out->flags = GetProgramInfoFlags(meta->acid_kac, meta->acid->kac_size);
|
out->flags = caps::GetProgramInfoFlags(meta->acid_kac, meta->acid->kac_size);
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsApplet(const Meta *meta) {
|
bool IsApplet(const Meta *meta) {
|
||||||
return (GetProgramInfoFlags(meta->aci_kac, meta->aci->kac_size) & ProgramInfoFlag_ApplicationTypeMask) == ProgramInfoFlag_Applet;
|
return (caps::GetProgramInfoFlags(meta->aci_kac, meta->aci->kac_size) & ProgramInfoFlag_ApplicationTypeMask) == ProgramInfoFlag_Applet;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsApplication(const Meta *meta) {
|
bool IsApplication(const Meta *meta) {
|
||||||
return (GetProgramInfoFlags(meta->aci_kac, meta->aci->kac_size) & ProgramInfoFlag_ApplicationTypeMask) == ProgramInfoFlag_Application;
|
return (caps::GetProgramInfoFlags(meta->aci_kac, meta->aci->kac_size) & ProgramInfoFlag_ApplicationTypeMask) == ProgramInfoFlag_Application;
|
||||||
}
|
}
|
||||||
|
|
||||||
Npdm::AddressSpaceType GetAddressSpaceType(const Meta *meta) {
|
Npdm::AddressSpaceType GetAddressSpaceType(const Meta *meta) {
|
||||||
|
@ -278,8 +278,8 @@ namespace sts::ldr {
|
||||||
return ResultLoaderInvalidProgramId;
|
return ResultLoaderInvalidProgramId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Validate the kernel capacilities. */
|
/* Validate the kernel capabilities. */
|
||||||
R_TRY(ValidateCapabilities(meta->acid_kac, meta->acid->kac_size, meta->aci_kac, meta->aci->kac_size));
|
R_TRY(caps::ValidateCapabilities(meta->acid_kac, meta->acid->kac_size, meta->aci_kac, meta->aci->kac_size));
|
||||||
|
|
||||||
/* All good. */
|
/* All good. */
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
|
@ -510,7 +510,7 @@ namespace sts::ldr {
|
||||||
R_TRY(DecideAddressSpaceLayout(out, &cpi, nso_headers, has_nso, arg_info));
|
R_TRY(DecideAddressSpaceLayout(out, &cpi, nso_headers, has_nso, arg_info));
|
||||||
|
|
||||||
/* Actually create process. const_cast necessary because libnx doesn't declare svcCreateProcess with const u32*. */
|
/* Actually create process. const_cast necessary because libnx doesn't declare svcCreateProcess with const u32*. */
|
||||||
return svcCreateProcess(out->process_handle.GetPointer(), &cpi, const_cast<u32 *>(reinterpret_cast<const u32 *>(meta->aci_kac)), meta->aci->kac_size / sizeof(u32));
|
return svcCreateProcess(out->process_handle.GetPointer(), &cpi, reinterpret_cast<const u32 *>(meta->aci_kac), meta->aci->kac_size / sizeof(u32));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result LoadNsoSegment(FILE *f, const NsoHeader::SegmentInfo *segment, size_t file_size, const u8 *file_hash, bool is_compressed, bool check_hash, uintptr_t map_base, uintptr_t map_end) {
|
Result LoadNsoSegment(FILE *f, const NsoHeader::SegmentInfo *segment, size_t file_size, const u8 *file_hash, bool is_compressed, bool check_hash, uintptr_t map_base, uintptr_t map_end) {
|
||||||
|
@ -647,8 +647,8 @@ namespace sts::ldr {
|
||||||
|
|
||||||
{
|
{
|
||||||
/* Mount code. */
|
/* Mount code. */
|
||||||
ScopedCodeMount mount;
|
ScopedCodeMount mount(loc);
|
||||||
R_TRY(MountCode(mount, loc));
|
R_TRY(mount.GetResult());
|
||||||
|
|
||||||
/* Load meta, possibly from cache. */
|
/* Load meta, possibly from cache. */
|
||||||
Meta meta;
|
Meta meta;
|
||||||
|
@ -700,8 +700,8 @@ namespace sts::ldr {
|
||||||
|
|
||||||
/* Load Meta. */
|
/* Load Meta. */
|
||||||
{
|
{
|
||||||
ScopedCodeMount mount;
|
ScopedCodeMount mount(loc);
|
||||||
R_TRY(MountCode(mount, loc));
|
R_TRY(mount.GetResult());
|
||||||
R_TRY(LoadMeta(&meta, loc.title_id));
|
R_TRY(LoadMeta(&meta, loc.title_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue