ldr: address review commentary.

This commit is contained in:
Michael Scire 2019-06-27 17:37:33 -07:00
parent 61fcf5e0f4
commit 6ba2090c01
8 changed files with 129 additions and 156 deletions

View file

@ -28,7 +28,7 @@ namespace sts::ldr::args {
ArgumentInfo g_argument_infos[MaxArgumentInfos];
/* Helpers. */
ArgumentInfo *GetArgumentInfo(ncm::TitleId title_id) {
ArgumentInfo *FindArgumentInfo(ncm::TitleId title_id) {
for (size_t i = 0; i < MaxArgumentInfos; i++) {
if (g_argument_infos[i].title_id == title_id) {
return &g_argument_infos[i];
@ -37,15 +37,15 @@ namespace sts::ldr::args {
return nullptr;
}
ArgumentInfo *GetFreeArgumentInfo() {
return GetArgumentInfo(FreeTitleId);
ArgumentInfo *FindFreeArgumentInfo() {
return FindArgumentInfo(FreeTitleId);
}
}
/* API. */
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) {
@ -53,9 +53,9 @@ namespace sts::ldr::args {
return ResultLoaderTooLongArgument;
}
ArgumentInfo *arg_info = GetArgumentInfo(title_id);
ArgumentInfo *arg_info = FindArgumentInfo(title_id);
if (arg_info == nullptr) {
arg_info = GetFreeArgumentInfo();
arg_info = FindFreeArgumentInfo();
}
if (arg_info == nullptr) {
return ResultLoaderTooManyArguments;

View file

@ -16,7 +16,7 @@
#include "ldr_capabilities.hpp"
namespace sts::ldr {
namespace sts::ldr::caps {
namespace {
@ -39,10 +39,10 @@ namespace sts::ldr {
return static_cast<CapabilityId>(__builtin_ctz(~cap));
}
template<CapabilityId id>
template<CapabilityId Id>
class Capability {
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;
private:
u32 value;
@ -50,7 +50,7 @@ namespace sts::ldr {
Capability(u32 v) : value(v) { /* ... */ }
CapabilityId GetId() const {
return id;
return Id;
}
u32 GetValue() const {
@ -92,16 +92,16 @@ namespace sts::ldr {
bool IsValid(const u32 *kac, size_t kac_count) const {
for (size_t i = 0; i < kac_count; i++) {
if (GetCapabilityId(kac[i]) == this->GetId()) {
const auto restrict = Decode(kac[i]);
const auto restriction = Decode(kac[i]);
if (this->GetMinimumThreadPriority() < restrict.GetMinimumThreadPriority() ||
this->GetMaximumThreadPriority() > restrict.GetMaximumThreadPriority() ||
if (this->GetMinimumThreadPriority() < restriction.GetMinimumThreadPriority() ||
this->GetMaximumThreadPriority() > restriction.GetMaximumThreadPriority() ||
this->GetMinimumThreadPriority() > this->GetMaximumThreadPriority()) {
return false;
}
if (this->GetMinimumCoreId() < restrict.GetMinimumCoreId() ||
this->GetMaximumCoreId() > restrict.GetMaximumCoreId() ||
if (this->GetMinimumCoreId() < restriction.GetMinimumCoreId() ||
this->GetMaximumCoreId() > restriction.GetMaximumCoreId() ||
this->GetMinimumCoreId() > this->GetMaximumCoreId()) {
return false;
}
@ -125,9 +125,9 @@ namespace sts::ldr {
bool IsValid(const u32 *kac, size_t kac_count) const {
for (size_t i = 0; i < kac_count; i++) {
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;
}
}
@ -162,22 +162,21 @@ namespace sts::ldr {
for (size_t i = 0; i < kac_count; i++) {
if (GetCapabilityId(kac[i]) == this->GetId()) {
const auto restrict = Decode(kac[i]);
i++;
const auto restriction = Decode(kac[i++]);
if (i >= kac_count || GetCapabilityId(kac[i]) != this->GetId()) {
return false;
}
const auto restrict_next = Decode(kac[i]);
const u32 restrict_start = restrict.GetAddressSize();
const u32 restrict_size = restrict_next.GetAddressSize();
const u32 restrict_end = restrict_start + restrict_size;
const auto restriction_next = Decode(kac[i]);
const u32 restriction_start = restriction.GetAddressSize();
const u32 restriction_size = restriction_next.GetAddressSize();
const u32 restriction_end = restriction_start + restriction_size;
if (restrict_size >= SizeMax) {
if (restriction_size >= SizeMax) {
continue;
}
if (this->GetFlag() == restrict.GetFlag() && next.GetFlag() == restrict_next.GetFlag()) {
if (restrict_start <= start && start <= restrict_end && end <= restrict_end) {
if (this->GetFlag() == restriction.GetFlag() && next.GetFlag() == restriction_next.GetFlag()) {
if (restriction_start <= start && start <= restriction_end && end <= restriction_end) {
return true;
}
}
@ -195,9 +194,9 @@ namespace sts::ldr {
bool IsValid(const u32 *kac, size_t kac_count) const {
for (size_t i = 0; i < kac_count; i++) {
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;
}
}
@ -207,8 +206,6 @@ namespace sts::ldr {
);
DEFINE_CAPABILITY_CLASS(InterruptPair,
Result Validate(const u32 *kac, size_t kac_count) const;
static constexpr u32 EmptyInterruptId = 0x3FF;
u32 GetInterruptId0() const {
@ -222,13 +219,13 @@ namespace sts::ldr {
bool IsSingleIdValid(const u32 id, const u32 *kac, size_t kac_count) const {
for (size_t i = 0; i < kac_count; i++) {
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;
}
if (restrict.GetInterruptId0() == id || restrict.GetInterruptId1() == id) {
if (restriction.GetInterruptId0() == id || restriction.GetInterruptId1() == id) {
return true;
}
}
@ -249,9 +246,9 @@ namespace sts::ldr {
bool IsValid(const u32 *kac, size_t kac_count) const {
for (size_t i = 0; i < kac_count; i++) {
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;
@ -275,9 +272,9 @@ namespace sts::ldr {
bool IsValid(const u32 *kac, size_t kac_count) const {
for (size_t i = 0; i < kac_count; i++) {
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;
@ -292,9 +289,9 @@ namespace sts::ldr {
bool IsValid(const u32 *kac, size_t kac_count) const {
for (size_t i = 0; i < kac_count; i++) {
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;
@ -303,19 +300,19 @@ namespace sts::ldr {
DEFINE_CAPABILITY_CLASS(DebugFlags,
bool GetAllowDebug() const {
return ((this->GetValue() >> 0) & 1) != 0;
return (this->GetValue() >> 0) & 1;
}
bool GetForceDebug() const {
return ((this->GetValue() >> 1) & 1) != 0;
return (this->GetValue() >> 1) & 1;
}
bool IsValid(const u32 *kac, size_t kac_count) const {
for (size_t i = 0; i < kac_count; i++) {
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;

View file

@ -19,7 +19,7 @@
#include <stratosphere.hpp>
#include <stratosphere/ldr.hpp>
namespace sts::ldr {
namespace sts::ldr::caps {
/* Capabilities API. */
Result ValidateCapabilities(const void *acid_kac, size_t acid_kac_size, const void *aci_kac, size_t aci_kac_size);

View file

@ -14,7 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <dirent.h>
#include <stratosphere/cfg.hpp>
#include <stratosphere/cfg.hpp>
#include "ldr_content_management.hpp"
#include "ldr_ecs.hpp"
@ -39,6 +39,7 @@ namespace sts::ldr {
/* Helpers. */
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++) {
if (path[i] == '\\') {
path[i] = '/';
@ -47,6 +48,7 @@ namespace sts::ldr {
}
inline const char *GetRelativePathStart(const char *relative_path) {
/* We assume filenames don't start with slashes when formatting. */
while (*relative_path == '/' || *relative_path == '\\') {
relative_path++;
}
@ -81,40 +83,7 @@ namespace sts::ldr {
Result MountNspFileSystem(const char *device_name, const char *path) {
FsFileSystem fs;
R_TRY(fsOpenFileSystemWithId(&fs, 0, FsFileSystemType_ApplicationPackage, path));
if(fsdevMountDevice(device_name, fs) == -1) {
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) {
if(fsdevMountDevice(device_name, fs) < 0) {
std::abort();
}
return ResultSuccess;
@ -166,17 +135,6 @@ namespace sts::ldr {
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) {
/* Allow nullptr relative path -- those are simply not openable. */
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() {
/* Unmount devices. */
if (this->is_code_mounted) {
@ -206,9 +169,52 @@ namespace sts::ldr {
InvalidateShouldOverrideCache();
}
Result MountCode(ScopedCodeMount &out, const ncm::TitleLocation &loc) {
ScopedCodeMount mount;
Result ScopedCodeMount::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();
}
/* 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();
/* Check if we're ready to mount the SD card. */
@ -222,25 +228,18 @@ namespace sts::ldr {
/* Check if we should override contents. */
if (ShouldOverrideWithHbl(loc.title_id)) {
/* Try to mount HBL. */
if (R_SUCCEEDED(MountHblFileSystem())) {
mount.SetHblMounted();
}
this->MountHblFileSystem();
}
if (ShouldOverrideWithSd(loc.title_id)) {
/* Try to mount Code NSP on SD. */
if (R_SUCCEEDED(MountSdCardCodeFileSystem(loc.title_id))) {
mount.SetCodeMounted();
}
this->MountSdCardCodeFileSystem(loc);
}
/* If we haven't already mounted code, mount it. */
if (!mount.IsCodeMounted()) {
R_TRY(MountCodeFileSystem(loc));
mount.SetCodeMounted();
if (!this->IsCodeMounted()) {
R_TRY(this->MountCodeFileSystem(loc));
}
/* Set out to scoped holder. */
out = std::move(mount);
return ResultSuccess;
}
@ -248,11 +247,11 @@ namespace sts::ldr {
FILE *f = nullptr;
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. */
f = OpenFile(ecs_device_name, relative_path);
} else if (ShouldOverrideWithHbl(title_id)) {
/* Next, try to mount from HBL. */
/* Next, try to open from HBL. */
f = OpenFile(HblFileSystemDeviceName, relative_path);
} else {
/* 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) {
char path[FS_MAX_PATH];
/* Open a locaiton resolver. */
/* Open a location resolver. */
LrLocationResolver lr;
R_TRY(lrOpenLocationResolver(static_cast<FsStorageId>(loc.storage_id), &lr));
ON_SCOPE_EXIT { serviceClose(&lr.s); };

View file

@ -25,36 +25,15 @@ namespace sts::ldr {
class ScopedCodeMount {
NON_COPYABLE(ScopedCodeMount);
private:
Result result;
bool is_code_mounted;
bool is_hbl_mounted;
public:
ScopedCodeMount() : is_code_mounted(false), is_hbl_mounted(false) { /* ... */ }
ScopedCodeMount(bool c, bool h) : is_code_mounted(c), is_hbl_mounted(h) { /* ... */ }
ScopedCodeMount(const ncm::TitleLocation &loc);
~ScopedCodeMount();
ScopedCodeMount(ScopedCodeMount&& rhs) {
this->is_code_mounted = rhs.is_code_mounted;
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;
Result GetResult() const {
return this->result;
}
bool IsCodeMounted() const {
@ -62,12 +41,18 @@ namespace sts::ldr {
}
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. */
Result MountCode(ScopedCodeMount &out, const ncm::TitleLocation &loc);
Result OpenCodeFile(FILE *&out, ncm::TitleId title_id, const char *relative_path);
Result OpenCodeFileFromBaseExefs(FILE *&out, ncm::TitleId title_id, const char *relative_path);

View file

@ -74,12 +74,7 @@ namespace sts::ldr::ecs {
/* Create session. */
AutoHandle server, client;
{
Handle s_h, c_h;
R_TRY(svcCreateSession(&s_h, &c_h, 0, 0));
server.Reset(s_h);
client.Reset(c_h);
}
R_TRY(svcCreateSession(server.GetPointer(), client.GetPointer(), 0, 0));
/* Create service. */
Service srv;
@ -100,10 +95,7 @@ namespace sts::ldr::ecs {
Result Clear(ncm::TitleId title_id) {
/* Delete if present. */
auto it = g_map.find(static_cast<u64>(title_id));
if (it != g_map.end()) {
g_map.erase(it);
}
g_map.erase(static_cast<u64>(title_id));
return ResultSuccess;
}

View file

@ -187,9 +187,9 @@ namespace sts::ldr {
}
/* Fix flags. */
const u16 program_info_flags = GetProgramInfoFlags(o_meta->aci_kac, o_meta->aci->kac_size);
SetProgramInfoFlags(program_info_flags, meta->acid_kac, meta->acid->kac_size);
SetProgramInfoFlags(program_info_flags, meta->aci_kac, meta->aci->kac_size);
const u16 program_info_flags = caps::GetProgramInfoFlags(o_meta->aci_kac, o_meta->aci->kac_size);
caps::SetProgramInfoFlags(program_info_flags, meta->acid_kac, meta->acid->kac_size);
caps::SetProgramInfoFlags(program_info_flags, meta->aci_kac, meta->aci->kac_size);
}
}
}

View file

@ -175,16 +175,16 @@ namespace sts::ldr {
#undef COPY_ACCESS_CONTROL
/* 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;
}
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) {
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) {
@ -278,8 +278,8 @@ namespace sts::ldr {
return ResultLoaderInvalidProgramId;
}
/* Validate the kernel capacilities. */
R_TRY(ValidateCapabilities(meta->acid_kac, meta->acid->kac_size, meta->aci_kac, meta->aci->kac_size));
/* Validate the kernel capabilities. */
R_TRY(caps::ValidateCapabilities(meta->acid_kac, meta->acid->kac_size, meta->aci_kac, meta->aci->kac_size));
/* All good. */
return ResultSuccess;
@ -510,7 +510,7 @@ namespace sts::ldr {
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*. */
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) {
@ -647,8 +647,8 @@ namespace sts::ldr {
{
/* Mount code. */
ScopedCodeMount mount;
R_TRY(MountCode(mount, loc));
ScopedCodeMount mount(loc);
R_TRY(mount.GetResult());
/* Load meta, possibly from cache. */
Meta meta;
@ -700,8 +700,8 @@ namespace sts::ldr {
/* Load Meta. */
{
ScopedCodeMount mount;
R_TRY(MountCode(mount, loc));
ScopedCodeMount mount(loc);
R_TRY(mount.GetResult());
R_TRY(LoadMeta(&meta, loc.title_id));
}