Results: Implement namespaced, type-safe results.

Because I was working on multiple things at once, this commit also:
- Adds wrappers for/linker flags to wrap CXX exceptions to make them
  abort. This saves ~0x8000 of memory in every system module.
- Broadly replaces lines of the pattern if (cond) { return ResultX; }
  with R_UNLESS(!cond, ResultX());.
- Reworks the R_TRY_CATCH macros (and the result macros in general).
This commit is contained in:
Michael Scire
2019-10-24 01:40:44 -07:00
committed by SciresM
parent 15773e4755
commit 4059dc6187
169 changed files with 2172 additions and 1868 deletions

View File

@@ -125,7 +125,7 @@ namespace sts::ams {
::sts::ams::ExceptionHandler(&ams_ctx);
}
inline __attribute((noreturn)) void AbortImpl() {
inline NORETURN void AbortImpl() {
/* Just perform a data abort. */
register u64 addr __asm__("x27") = FatalErrorContext::StdAbortMagicAddress;
register u64 val __asm__("x28") = FatalErrorContext::StdAbortMagicValue;
@@ -145,9 +145,24 @@ extern "C" {
/* Redefine abort to trigger these handlers. */
void abort();
/* Redefine C++ exception handlers. Requires wrap linker flag. */
void __wrap___cxa_pure_virtual(void) { abort(); }
void __wrap___cxa_throw(void) { abort(); }
void __wrap___cxa_rethrow(void) { abort(); }
void __wrap___cxa_allocate_exception(void) { abort(); }
void __wrap___cxa_begin_catch(void) { abort(); }
void __wrap___cxa_end_catch(void) { abort(); }
void __wrap___cxa_call_unexpected(void) { abort(); }
void __wrap___cxa_call_terminate(void) { abort(); }
void __wrap___gxx_personality_v0(void) { abort(); }
}
/* Custom abort handler, so that std::abort will trigger these. */
void abort() {
sts::ams::AbortImpl();
}
void *__cxa_allocate_ecxeption(size_t thrown_size) {
abort();
}

View File

@@ -23,7 +23,7 @@ namespace sts::ams {
ApiInfo GetApiInfo() {
u64 exosphere_cfg;
if (spl::smc::GetConfig(&exosphere_cfg, 1, SplConfigItem_ExosphereApiVersion) != spl::smc::Result::Success) {
R_ASSERT(ResultAtmosphereExosphereNotPresent);
R_ASSERT(ResultExosphereNotPresent());
}
return ApiInfo{
@@ -61,7 +61,7 @@ namespace sts::ams {
u64 tmp;
R_TRY(spl::smc::ConvertResult(spl::smc::GetConfig(&tmp, 1, SplConfigItem_ExosphereHasRcmBugPatch)));
*out = (tmp != 0);
return ResultSuccess;
return ResultSuccess();
}
}

View File

@@ -142,17 +142,14 @@ namespace sts::boot2 {
void LaunchTitle(os::ProcessId *out_process_id, const ncm::TitleLocation &loc, u32 launch_flags) {
os::ProcessId process_id = os::InvalidProcessId;
switch (pm::shell::LaunchTitle(&process_id, loc, launch_flags)) {
case ResultKernelResourceExhausted:
case ResultKernelOutOfMemory:
case ResultKernelLimitReached:
STS_ASSERT(false);
default:
/* We don't care about other issues. */
break;
/* Launch, lightly validate result. */
{
const auto launch_result = pm::shell::LaunchTitle(&process_id, loc, launch_flags);
STS_ASSERT(!(svc::ResultOutOfResource::Includes(launch_result)));
STS_ASSERT(!(svc::ResultOutOfMemory::Includes(launch_result)));
STS_ASSERT(!(svc::ResultLimitReached::Includes(launch_result)));
}
if (out_process_id) {
*out_process_id = process_id;
}

View File

@@ -43,11 +43,11 @@ namespace sts::cfg {
bool service_present = false;
R_TRY(sm::HasService(&service_present, RequiredServicesForSdCardAccess[i]));
if (!service_present) {
return ResultFsSdCardNotPresent;
return fs::ResultSdCardNotPresent();
}
}
return ResultSuccess;
return ResultSuccess();
}
void WaitSdCardServicesReadyImpl() {
@@ -60,7 +60,7 @@ namespace sts::cfg {
R_TRY(CheckSdCardServicesReady());
R_ASSERT(fsOpenSdCardFileSystem(&g_sd_card_filesystem));
g_sd_card_initialized = true;
return ResultSuccess;
return ResultSuccess();
}
void InitializeSdCard() {

View File

@@ -24,7 +24,7 @@ namespace sts::dd {
const u64 aligned_size = size + offset;
R_TRY_CATCH(svcQueryIoMapping(&virtual_addr, aligned_addr, aligned_size)) {
/* Official software handles this by returning 0. */
R_CATCH(ResultKernelNotFound) { return 0; }
R_CATCH(svc::ResultNotFound) { return 0; }
} R_END_TRY_CATCH_WITH_ASSERT;
return static_cast<uintptr_t>(virtual_addr + offset);

View File

@@ -47,7 +47,7 @@ namespace sts::hid {
g_initialized_hid = true;
}
return ResultSuccess;
return ResultSuccess();
}
}
@@ -64,7 +64,7 @@ namespace sts::hid {
*out |= hidKeysHeld(static_cast<HidControllerID>(controller));
}
return ResultSuccess;
return ResultSuccess();
}
}

View File

@@ -33,9 +33,9 @@ namespace sts::kvdb {
Result Validate() const {
if (std::memcmp(this->magic, ArchiveHeaderMagic, sizeof(ArchiveHeaderMagic)) != 0) {
return ResultKvdbInvalidKeyValue;
return ResultInvalidKeyValue();
}
return ResultSuccess;
return ResultSuccess();
}
static ArchiveHeader Make(size_t entry_count) {
@@ -54,9 +54,9 @@ namespace sts::kvdb {
Result Validate() const {
if (std::memcmp(this->magic, ArchiveEntryMagic, sizeof(ArchiveEntryMagic)) != 0) {
return ResultKvdbInvalidKeyValue;
return ResultInvalidKeyValue();
}
return ResultSuccess;
return ResultSuccess();
}
static ArchiveEntryHeader Make(size_t ksz, size_t vsz) {
@@ -75,17 +75,17 @@ namespace sts::kvdb {
Result ArchiveReader::Peek(void *dst, size_t size) {
/* Bounds check. */
if (this->offset + size > this->buffer.GetSize() || this->offset + size <= this->offset) {
return ResultKvdbInvalidKeyValue;
return ResultInvalidKeyValue();
}
std::memcpy(dst, this->buffer.Get() + this->offset, size);
return ResultSuccess;
return ResultSuccess();
}
Result ArchiveReader::Read(void *dst, size_t size) {
R_TRY(this->Peek(dst, size));
this->offset += size;
return ResultSuccess;
return ResultSuccess();
}
Result ArchiveReader::ReadEntryCount(size_t *out) {
@@ -98,7 +98,7 @@ namespace sts::kvdb {
R_TRY(header.Validate());
*out = header.entry_count;
return ResultSuccess;
return ResultSuccess();
}
Result ArchiveReader::GetEntrySize(size_t *out_key_size, size_t *out_value_size) {
@@ -112,7 +112,7 @@ namespace sts::kvdb {
*out_key_size = header.key_size;
*out_value_size = header.value_size;
return ResultSuccess;
return ResultSuccess();
}
Result ArchiveReader::ReadEntry(void *out_key, size_t key_size, void *out_value, size_t value_size) {
@@ -130,19 +130,19 @@ namespace sts::kvdb {
R_ASSERT(this->Read(out_key, key_size));
R_ASSERT(this->Read(out_value, value_size));
return ResultSuccess;
return ResultSuccess();
}
/* Writer functionality. */
Result ArchiveWriter::Write(const void *src, size_t size) {
/* Bounds check. */
if (this->offset + size > this->buffer.GetSize() || this->offset + size <= this->offset) {
return ResultKvdbInvalidKeyValue;
return ResultInvalidKeyValue();
}
std::memcpy(this->buffer.Get() + this->offset, src, size);
this->offset += size;
return ResultSuccess;
return ResultSuccess();
}
void ArchiveWriter::WriteHeader(size_t entry_count) {

View File

@@ -41,11 +41,11 @@ namespace sts::kvdb {
if (this->backing_buffer != nullptr) {
this->entries = static_cast<decltype(this->entries)>(this->Allocate(sizeof(*this->entries) * this->capacity));
if (this->entries == nullptr) {
return ResultKvdbBufferInsufficient;
return ResultBufferInsufficient();
}
}
return ResultSuccess;
return ResultSuccess();
}
void FileKeyValueStore::Cache::Invalidate() {
@@ -159,13 +159,13 @@ namespace sts::kvdb {
const size_t file_name_len = file_name.GetLength();
const size_t key_name_len = file_name_len - FileExtensionLength;
if (file_name_len < FileExtensionLength + 2 || !file_name.EndsWith(FileExtension) || key_name_len % 2 != 0) {
return ResultKvdbInvalidKeyValue;
return ResultInvalidKeyValue();
}
/* Validate that we have space for the converted key. */
const size_t key_size = key_name_len / 2;
if (key_size > max_out_size) {
return ResultKvdbBufferInsufficient;
return ResultBufferInsufficient();
}
/* Convert the hex key back. */
@@ -177,7 +177,7 @@ namespace sts::kvdb {
}
*out_size = key_size;
return ResultSuccess;
return ResultSuccess();
}
Result FileKeyValueStore::Initialize(const char *dir) {
@@ -189,7 +189,7 @@ namespace sts::kvdb {
{
struct stat st;
if (stat(dir, &st) != 0 || !(S_ISDIR(st.st_mode))) {
return ResultFsPathNotFound;
return fs::ResultPathNotFound();
}
}
@@ -198,7 +198,7 @@ namespace sts::kvdb {
/* Initialize our cache. */
R_TRY(this->cache.Initialize(cache_buffer, cache_buffer_size, cache_capacity));
return ResultSuccess;
return ResultSuccess();
}
Result FileKeyValueStore::Get(size_t *out_size, void *out_value, size_t max_out_size, const void *key, size_t key_size) {
@@ -206,7 +206,7 @@ namespace sts::kvdb {
/* Ensure key size is small enough. */
if (key_size > MaxKeySize) {
return ResultKvdbKeyCapacityInsufficient;
return ResultKeyCapacityInsufficient();
}
/* Try to get from cache. */
@@ -214,7 +214,7 @@ namespace sts::kvdb {
auto size = this->cache.TryGet(out_value, max_out_size, key, key_size);
if (size) {
*out_size = *size;
return ResultSuccess;
return ResultSuccess();
}
}
@@ -222,9 +222,7 @@ namespace sts::kvdb {
FILE *fp = fopen(this->GetPath(key, key_size), "rb");
if (fp == nullptr) {
R_TRY_CATCH(fsdevGetLastResult()) {
R_CATCH(ResultFsPathNotFound) {
return ResultKvdbKeyNotFound;
}
R_CONVERT(fs::ResultPathNotFound, ResultKeyNotFound())
} R_END_TRY_CATCH;
}
ON_SCOPE_EXIT { fclose(fp); };
@@ -236,7 +234,7 @@ namespace sts::kvdb {
/* Ensure there's enough space for the value. */
if (max_out_size < value_size) {
return ResultKvdbBufferInsufficient;
return ResultBufferInsufficient();
}
/* Read the value. */
@@ -247,7 +245,7 @@ namespace sts::kvdb {
/* Cache the newly read value. */
this->cache.Set(key, key_size, out_value, value_size);
return ResultSuccess;
return ResultSuccess();
}
Result FileKeyValueStore::GetSize(size_t *out_size, const void *key, size_t key_size) {
@@ -255,7 +253,7 @@ namespace sts::kvdb {
/* Ensure key size is small enough. */
if (key_size > MaxKeySize) {
return ResultKvdbKeyCapacityInsufficient;
return ResultKeyCapacityInsufficient();
}
/* Try to get from cache. */
@@ -263,7 +261,7 @@ namespace sts::kvdb {
auto size = this->cache.TryGetSize(key, key_size);
if (size) {
*out_size = *size;
return ResultSuccess;
return ResultSuccess();
}
}
@@ -271,9 +269,7 @@ namespace sts::kvdb {
FILE *fp = fopen(this->GetPath(key, key_size), "rb");
if (fp == nullptr) {
R_TRY_CATCH(fsdevGetLastResult()) {
R_CATCH(ResultFsPathNotFound) {
return ResultKvdbKeyNotFound;
}
R_CONVERT(fs::ResultPathNotFound, ResultKeyNotFound())
} R_END_TRY_CATCH;
}
ON_SCOPE_EXIT { fclose(fp); };
@@ -281,7 +277,7 @@ namespace sts::kvdb {
/* Get the value size. */
fseek(fp, 0, SEEK_END);
*out_size = ftell(fp);
return ResultSuccess;
return ResultSuccess();
}
Result FileKeyValueStore::Set(const void *key, size_t key_size, const void *value, size_t value_size) {
@@ -289,7 +285,7 @@ namespace sts::kvdb {
/* Ensure key size is small enough. */
if (key_size > MaxKeySize) {
return ResultKvdbKeyCapacityInsufficient;
return ResultKeyCapacityInsufficient();
}
/* When the cache contains the key being set, Nintendo invalidates the cache. */
@@ -316,7 +312,7 @@ namespace sts::kvdb {
/* Flush the value file. */
fflush(fp);
return ResultSuccess;
return ResultSuccess();
}
Result FileKeyValueStore::Remove(const void *key, size_t key_size) {
@@ -324,7 +320,7 @@ namespace sts::kvdb {
/* Ensure key size is small enough. */
if (key_size > MaxKeySize) {
return ResultKvdbKeyCapacityInsufficient;
return ResultKeyCapacityInsufficient();
}
/* When the cache contains the key being set, Nintendo invalidates the cache. */
@@ -335,13 +331,11 @@ namespace sts::kvdb {
/* Remove the file. */
if (std::remove(this->GetPath(key, key_size)) != 0) {
R_TRY_CATCH(fsdevGetLastResult()) {
R_CATCH(ResultFsPathNotFound) {
return ResultKvdbKeyNotFound;
}
R_CONVERT(fs::ResultPathNotFound, ResultKeyNotFound())
} R_END_TRY_CATCH;
}
return ResultSuccess;
return ResultSuccess();
}
}

View File

@@ -41,12 +41,12 @@ namespace sts::map {
if (mem_info.type == MemType_Unmapped && mem_info.addr - cur_base + mem_info.size >= size) {
*out_address = cur_base;
return ResultSuccess;
return ResultSuccess();
}
const uintptr_t mem_end = mem_info.addr + mem_info.size;
if (mem_info.type == MemType_Reserved || mem_end < cur_base || (mem_end >> 31)) {
return ResultKernelOutOfMemory;
return svc::ResultOutOfMemory();
}
cur_base = mem_end;
@@ -64,39 +64,39 @@ namespace sts::map {
cur_end = cur_base + size;
if (cur_end <= cur_base) {
return ResultKernelOutOfMemory;
return svc::ResultOutOfMemory();
}
while (true) {
if (address_space.heap_size && (address_space.heap_base <= cur_end - 1 && cur_base <= address_space.heap_end - 1)) {
/* If we overlap the heap region, go to the end of the heap region. */
if (cur_base == address_space.heap_end) {
return ResultKernelOutOfMemory;
return svc::ResultOutOfMemory();
}
cur_base = address_space.heap_end;
} else if (address_space.alias_size && (address_space.alias_base <= cur_end - 1 && cur_base <= address_space.alias_end - 1)) {
/* If we overlap the alias region, go to the end of the alias region. */
if (cur_base == address_space.alias_end) {
return ResultKernelOutOfMemory;
return svc::ResultOutOfMemory();
}
cur_base = address_space.alias_end;
} else {
R_ASSERT(svcQueryMemory(&mem_info, &page_info, cur_base));
if (mem_info.type == 0 && mem_info.addr - cur_base + mem_info.size >= size) {
*out_address = cur_base;
return ResultSuccess;
return ResultSuccess();
}
if (mem_info.addr + mem_info.size <= cur_base) {
return ResultKernelOutOfMemory;
return svc::ResultOutOfMemory();
}
cur_base = mem_info.addr + mem_info.size;
if (cur_base >= address_space.aslr_end) {
return ResultKernelOutOfMemory;
return svc::ResultOutOfMemory();
}
}
cur_end = cur_base + size;
if (cur_base + size <= cur_base) {
return ResultKernelOutOfMemory;
return svc::ResultOutOfMemory();
}
}
}
@@ -106,7 +106,7 @@ namespace sts::map {
R_TRY(GetProcessAddressSpaceInfo(&address_space, process_handle));
if (size > address_space.aslr_size) {
return ResultRoInsufficientAddressSpace;
return ro::ResultInsufficientAddressSpace();
}
uintptr_t try_address;
@@ -115,7 +115,7 @@ namespace sts::map {
MappedCodeMemory tmp_mcm(process_handle, try_address, base_address, size);
R_TRY_CATCH(tmp_mcm.GetResult()) {
R_CATCH(ResultKernelInvalidMemoryState) {
R_CATCH(svc::ResultInvalidCurrentMemoryState) {
continue;
}
} R_END_TRY_CATCH;
@@ -126,10 +126,10 @@ namespace sts::map {
/* We're done searching. */
out_mcm = std::move(tmp_mcm);
return ResultSuccess;
return ResultSuccess();
}
return ResultRoInsufficientAddressSpace;
return ro::ResultInsufficientAddressSpace();;
}
Result MapCodeMemoryInProcessModern(MappedCodeMemory &out_mcm, Handle process_handle, uintptr_t base_address, size_t size) {
@@ -137,7 +137,7 @@ namespace sts::map {
R_TRY(GetProcessAddressSpaceInfo(&address_space, process_handle));
if (size > address_space.aslr_size) {
return ResultRoInsufficientAddressSpace;
return ro::ResultInsufficientAddressSpace();;
}
uintptr_t try_address;
@@ -155,7 +155,7 @@ namespace sts::map {
MappedCodeMemory tmp_mcm(process_handle, try_address, base_address, size);
R_TRY_CATCH(tmp_mcm.GetResult()) {
R_CATCH(ResultKernelInvalidMemoryState) {
R_CATCH(svc::ResultInvalidCurrentMemoryState) {
continue;
}
} R_END_TRY_CATCH;
@@ -166,10 +166,10 @@ namespace sts::map {
/* We're done searching. */
out_mcm = std::move(tmp_mcm);
return ResultSuccess;
return ResultSuccess();
}
return ResultRoInsufficientAddressSpace;
return ro::ResultInsufficientAddressSpace();;
}
}
@@ -201,7 +201,7 @@ namespace sts::map {
out->heap_end = out->heap_base + out->heap_size;
out->alias_end = out->alias_base + out->alias_size;
out->aslr_end = out->aslr_base + out->aslr_size;
return ResultSuccess;
return ResultSuccess();
}
Result LocateMappableSpace(uintptr_t *out_address, size_t size) {

View File

@@ -23,12 +23,10 @@ namespace sts::os::impl {
Result CreateEventHandles(Handle *out_readable, Handle *out_writable) {
/* Create the event handles. */
R_TRY_CATCH(svcCreateEvent(out_writable, out_readable)) {
R_CATCH(ResultKernelResourceExhausted) {
return ResultOsResourceExhausted;
}
R_CONVERT(svc::ResultOutOfResource, ResultOutOfResource());
} R_END_TRY_CATCH_WITH_ASSERT;
return ResultSuccess;
return ResultSuccess();
}
}
@@ -46,7 +44,7 @@ namespace sts::os::impl {
Handle rh, wh;
R_TRY(CreateEventHandles(&rh, &wh));
this->Initialize(rh, true, wh, true, autoclear);
return ResultSuccess;
return ResultSuccess();
}
void InterProcessEvent::Initialize(Handle read_handle, bool manage_read_handle, Handle write_handle, bool manage_write_handle, bool autoclear) {
@@ -122,14 +120,14 @@ namespace sts::os::impl {
while (true) {
/* Continuously wait, until success. */
R_TRY_CATCH(svcWaitSynchronizationSingle(handle, U64_MAX)) {
R_CATCH(ResultKernelCancelled) { continue; }
R_CATCH(svc::ResultCancelled) { continue; }
} R_END_TRY_CATCH_WITH_ASSERT;
/* Clear, if we must. */
if (this->auto_clear) {
R_TRY_CATCH(svcResetSignal(handle)) {
/* Some other thread might have caught this before we did. */
R_CATCH(ResultKernelInvalidState) { continue; }
R_CATCH(svc::ResultInvalidState) { continue; }
} R_END_TRY_CATCH_WITH_ASSERT;
}
return;
@@ -147,8 +145,8 @@ namespace sts::os::impl {
while (true) {
/* Continuously wait, until success or timeout. */
R_TRY_CATCH(svcWaitSynchronizationSingle(handle, 0)) {
R_CATCH(ResultKernelTimedOut) { return false; }
R_CATCH(ResultKernelCancelled) { continue; }
R_CATCH(svc::ResultTimedOut) { return false; }
R_CATCH(svc::ResultCancelled) { continue; }
} R_END_TRY_CATCH_WITH_ASSERT;
/* We succeeded, so we're signaled. */
@@ -164,15 +162,15 @@ namespace sts::os::impl {
while (true) {
/* Continuously wait, until success or timeout. */
R_TRY_CATCH(svcWaitSynchronizationSingle(handle, timeout_helper.NsUntilTimeout())) {
R_CATCH(ResultKernelTimedOut) { return false; }
R_CATCH(ResultKernelCancelled) { continue; }
R_CATCH(svc::ResultTimedOut) { return false; }
R_CATCH(svc::ResultCancelled) { continue; }
} R_END_TRY_CATCH_WITH_ASSERT;
/* Clear, if we must. */
if (this->auto_clear) {
R_TRY_CATCH(svcResetSignal(handle)) {
/* Some other thread might have caught this before we did. */
R_CATCH(ResultKernelInvalidState) { continue; }
R_CATCH(svc::ResultInvalidState) { continue; }
} R_END_TRY_CATCH_WITH_ASSERT;
}

View File

@@ -98,13 +98,13 @@ namespace sts::os::impl{
s32 index = WaitInvalid;
R_TRY_CATCH(svcWaitSynchronization(&index, handles, count, timeout)) {
R_CATCH(ResultKernelTimedOut) { return WaitTimedOut; }
R_CATCH(ResultKernelCancelled) { return WaitCancelled; }
R_CATCH(svc::ResultTimedOut) { return WaitTimedOut; }
R_CATCH(svc::ResultCancelled) { return WaitCancelled; }
/* All other results are critical errors. */
/* 7601: Thread termination requested. */
/* E401: Handle is dead. */
/* E601: Handle list address invalid. */
/* EE01: Too many handles. */
/* svc::ResultThreadTerminating */
/* svc::ResultInvalidHandle. */
/* svc::ResultInvalidPointer */
/* svc::ResultOutOfRange */
} R_END_TRY_CATCH_WITH_ASSERT;
return index;

View File

@@ -26,7 +26,7 @@ namespace sts::os {
R_TRY(svcCreateInterruptEvent(this->handle.GetPointer(), interrupt_id, type));
this->is_initialized = true;
return ResultSuccess;
return ResultSuccess();
}
void InterruptEvent::Finalize() {
@@ -51,14 +51,14 @@ namespace sts::os {
while (true) {
/* Continuously wait, until success. */
R_TRY_CATCH(svcWaitSynchronizationSingle(this->handle.Get(), U64_MAX)) {
R_CATCH(ResultKernelCancelled) { continue; }
R_CATCH(svc::ResultCancelled) { continue; }
} R_END_TRY_CATCH_WITH_ASSERT;
/* Clear, if we must. */
if (this->auto_clear) {
R_TRY_CATCH(svcResetSignal(this->handle.Get())) {
/* Some other thread might have caught this before we did. */
R_CATCH(ResultKernelInvalidState) { continue; }
R_CATCH(svc::ResultInvalidState) { continue; }
} R_END_TRY_CATCH_WITH_ASSERT;
}
return;
@@ -76,8 +76,8 @@ namespace sts::os {
while (true) {
/* Continuously wait, until success or timeout. */
R_TRY_CATCH(svcWaitSynchronizationSingle(this->handle.Get(), 0)) {
R_CATCH(ResultKernelTimedOut) { return false; }
R_CATCH(ResultKernelCancelled) { continue; }
R_CATCH(svc::ResultTimedOut) { return false; }
R_CATCH(svc::ResultCancelled) { continue; }
} R_END_TRY_CATCH_WITH_ASSERT;
/* We succeeded, so we're signaled. */
@@ -93,15 +93,15 @@ namespace sts::os {
while (true) {
/* Continuously wait, until success or timeout. */
R_TRY_CATCH(svcWaitSynchronizationSingle(this->handle.Get(), timeout_helper.NsUntilTimeout())) {
R_CATCH(ResultKernelTimedOut) { return false; }
R_CATCH(ResultKernelCancelled) { continue; }
R_CATCH(svc::ResultTimedOut) { return false; }
R_CATCH(svc::ResultCancelled) { continue; }
} R_END_TRY_CATCH_WITH_ASSERT;
/* Clear, if we must. */
if (this->auto_clear) {
R_TRY_CATCH(svcResetSignal(this->handle.Get())) {
/* Some other thread might have caught this before we did. */
R_CATCH(ResultKernelInvalidState) { continue; }
R_CATCH(svc::ResultInvalidState) { continue; }
} R_END_TRY_CATCH_WITH_ASSERT;
}

View File

@@ -58,17 +58,22 @@ namespace sts::os {
STS_ASSERT(this->state == SystemEventState::Uninitialized);
new (GetPointer(this->storage_for_event)) Event(autoclear);
this->state = SystemEventState::Event;
return ResultSuccess;
return ResultSuccess();
}
Result SystemEvent::InitializeAsInterProcessEvent(bool autoclear) {
STS_ASSERT(this->state == SystemEventState::Uninitialized);
new (GetPointer(this->storage_for_inter_process_event)) impl::InterProcessEvent();
this->state = SystemEventState::InterProcessEvent;
R_TRY_CLEANUP(this->GetInterProcessEvent().Initialize(autoclear), {
this->Finalize();
});
return ResultSuccess;
/* Ensure we end up in a correct state if initialization fails. */
{
auto guard = SCOPE_GUARD { this->Finalize(); };
R_TRY(this->GetInterProcessEvent().Initialize(autoclear));
guard.Cancel();
}
return ResultSuccess();
}
void SystemEvent::AttachHandles(Handle read_handle, bool manage_read_handle, Handle write_handle, bool manage_write_handle, bool autoclear) {

View File

@@ -39,7 +39,7 @@ namespace sts::pm::dmnt {
Event evt;
R_TRY(pmdmntEnableDebugForApplication(&evt));
*out_handle = evt.revent;
return ResultSuccess;
return ResultSuccess();
}
Result AtmosphereGetProcessInfo(Handle *out_handle, ncm::TitleLocation *out_loc, os::ProcessId process_id) {

View File

@@ -48,7 +48,7 @@ namespace sts::pm::info {
if (g_cached_launched_titles.find(static_cast<u64>(title_id)) != g_cached_launched_titles.end()) {
*out = true;
return ResultSuccess;
return ResultSuccess();
}
bool has_launched = false;
@@ -58,7 +58,7 @@ namespace sts::pm::info {
}
*out = has_launched;
return ResultSuccess;
return ResultSuccess();
}
bool HasLaunchedTitle(ncm::TitleId title_id) {

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2018-2019 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
namespace sts::result {
extern bool CallFatalOnResultAssertion;
}
namespace sts::result::impl {
NORETURN WEAK void OnResultAssertion(Result result) {
/* Assert that we should call fatal on result assertion. */
/* If we shouldn't fatal, this will std::abort(); */
/* If we should, we'll continue onwards. */
STS_ASSERT((sts::result::CallFatalOnResultAssertion));
/* TODO: sts::fatal:: */
fatalSimple(result.GetValue());
while (true) { /* ... */ }
}
}

View File

@@ -34,11 +34,11 @@ namespace sts::sf::cmif {
Result ServerDomainManager::Domain::ReserveIds(DomainObjectId *out_ids, size_t count) {
for (size_t i = 0; i < count; i++) {
Entry *entry = this->manager->entry_manager.AllocateEntry();
R_UNLESS(entry != nullptr, ResultServiceFrameworkOutOfDomainEntries);
R_UNLESS(entry != nullptr, sf::cmif::ResultOutOfDomainEntries());
STS_ASSERT(entry->owner == nullptr);
out_ids[i] = this->manager->entry_manager.GetId(entry);
}
return ResultSuccess;
return ResultSuccess();
}
void ServerDomainManager::Domain::ReserveSpecificIds(const DomainObjectId *ids, size_t count) {

View File

@@ -28,7 +28,7 @@ namespace sts::sf::cmif {
Result DomainServiceObjectDispatchTable::ProcessMessageImpl(ServiceDispatchContext &ctx, ServerDomainBase *domain, const cmif::PointerAndSize &in_raw_data) const {
const CmifDomainInHeader *in_header = reinterpret_cast<const CmifDomainInHeader *>(in_raw_data.GetPointer());
R_UNLESS(in_raw_data.GetSize() >= sizeof(*in_header), ResultServiceFrameworkInvalidCmifHeaderSize);
R_UNLESS(in_raw_data.GetSize() >= sizeof(*in_header), sf::cmif::ResultInvalidHeaderSize());
const cmif::PointerAndSize in_domain_raw_data = cmif::PointerAndSize(in_raw_data.GetAddress() + sizeof(*in_header), in_raw_data.GetSize() - sizeof(*in_header));
const DomainObjectId target_object_id = DomainObjectId{in_header->object_id};
@@ -36,11 +36,11 @@ namespace sts::sf::cmif {
case CmifDomainRequestType_SendMessage:
{
auto target_object = domain->GetObject(target_object_id);
R_UNLESS(static_cast<bool>(target_object), ResultServiceFrameworkTargetNotFound);
R_UNLESS(in_header->data_size + in_header->num_in_objects * sizeof(DomainObjectId) <= in_domain_raw_data.GetSize(), ResultServiceFrameworkInvalidCmifHeaderSize);
R_UNLESS(static_cast<bool>(target_object), sf::cmif::ResultTargetNotFound());
R_UNLESS(in_header->data_size + in_header->num_in_objects * sizeof(DomainObjectId) <= in_domain_raw_data.GetSize(), sf::cmif::ResultInvalidHeaderSize());
const cmif::PointerAndSize in_message_raw_data = cmif::PointerAndSize(in_domain_raw_data.GetAddress(), in_header->data_size);
DomainObjectId in_object_ids[8];
R_UNLESS(in_header->num_in_objects <= util::size(in_object_ids), ResultServiceFrameworkInvalidCmifNumInObjects);
R_UNLESS(in_header->num_in_objects <= util::size(in_object_ids), sf::cmif::ResultInvalidNumInObjects());
std::memcpy(in_object_ids, reinterpret_cast<DomainObjectId *>(in_message_raw_data.GetAddress() + in_message_raw_data.GetSize()), sizeof(DomainObjectId) * in_header->num_in_objects);
DomainServiceObjectProcessor domain_processor(domain, in_object_ids, in_header->num_in_objects);
if (ctx.processor == nullptr) {
@@ -54,15 +54,15 @@ namespace sts::sf::cmif {
case CmifDomainRequestType_Close:
/* TODO: N doesn't error check here. Should we? */
domain->UnregisterObject(target_object_id);
return ResultSuccess;
return ResultSuccess();
default:
return ResultServiceFrameworkInvalidCmifInHeader;
return sf::cmif::ResultInvalidInHeader();
}
}
Result DomainServiceObjectDispatchTable::ProcessMessageForMitmImpl(ServiceDispatchContext &ctx, ServerDomainBase *domain, const cmif::PointerAndSize &in_raw_data) const {
const CmifDomainInHeader *in_header = reinterpret_cast<const CmifDomainInHeader *>(in_raw_data.GetPointer());
R_UNLESS(in_raw_data.GetSize() >= sizeof(*in_header), ResultServiceFrameworkInvalidCmifHeaderSize);
R_UNLESS(in_raw_data.GetSize() >= sizeof(*in_header), sf::cmif::ResultInvalidHeaderSize());
const cmif::PointerAndSize in_domain_raw_data = cmif::PointerAndSize(in_raw_data.GetAddress() + sizeof(*in_header), in_raw_data.GetSize() - sizeof(*in_header));
const DomainObjectId target_object_id = DomainObjectId{in_header->object_id};
@@ -76,10 +76,10 @@ namespace sts::sf::cmif {
return ctx.session->ForwardRequest(ctx);
}
R_UNLESS(in_header->data_size + in_header->num_in_objects * sizeof(DomainObjectId) <= in_domain_raw_data.GetSize(), ResultServiceFrameworkInvalidCmifHeaderSize);
R_UNLESS(in_header->data_size + in_header->num_in_objects * sizeof(DomainObjectId) <= in_domain_raw_data.GetSize(), sf::cmif::ResultInvalidHeaderSize());
const cmif::PointerAndSize in_message_raw_data = cmif::PointerAndSize(in_domain_raw_data.GetAddress(), in_header->data_size);
DomainObjectId in_object_ids[8];
R_UNLESS(in_header->num_in_objects <= util::size(in_object_ids), ResultServiceFrameworkInvalidCmifNumInObjects);
R_UNLESS(in_header->num_in_objects <= util::size(in_object_ids), sf::cmif::ResultInvalidNumInObjects());
std::memcpy(in_object_ids, reinterpret_cast<DomainObjectId *>(in_message_raw_data.GetAddress() + in_message_raw_data.GetSize()), sizeof(DomainObjectId) * in_header->num_in_objects);
DomainServiceObjectProcessor domain_processor(domain, in_object_ids, in_header->num_in_objects);
if (ctx.processor == nullptr) {
@@ -101,16 +101,16 @@ namespace sts::sf::cmif {
/* If the object is in the domain, close our copy of it. Mitm objects are required to close their associated domain id, so this shouldn't cause desynch. */
domain->UnregisterObject(target_object_id);
return ResultSuccess;
return ResultSuccess();
}
default:
return ResultServiceFrameworkInvalidCmifInHeader;
return sf::cmif::ResultInvalidInHeader();
}
}
Result DomainServiceObjectProcessor::PrepareForProcess(const ServiceDispatchContext &ctx, const ServerMessageRuntimeMetadata runtime_metadata) const {
/* Validate in object count. */
R_UNLESS(this->impl_metadata.GetInObjectCount() == this->GetInObjectCount(), ResultServiceFrameworkInvalidCmifNumInObjects);
R_UNLESS(this->impl_metadata.GetInObjectCount() == this->GetInObjectCount(), sf::cmif::ResultInvalidNumInObjects());
/* Nintendo reserves domain object IDs here. We do this later, to support mitm semantics. */
@@ -122,7 +122,7 @@ namespace sts::sf::cmif {
for (size_t i = 0; i < this->GetInObjectCount(); i++) {
in_objects[i] = this->domain->GetObject(this->in_object_ids[i]);
}
return ResultSuccess;
return ResultSuccess();
}
HipcRequest DomainServiceObjectProcessor::PrepareForReply(const cmif::ServiceDispatchContext &ctx, PointerAndSize &out_raw_data, const ServerMessageRuntimeMetadata runtime_metadata) {

View File

@@ -24,8 +24,8 @@ namespace sts::sf::cmif {
/* Parse the CMIF in header. */
const CmifInHeader *in_header = reinterpret_cast<const CmifInHeader *>(in_raw_data.GetPointer());
R_UNLESS(in_raw_data.GetSize() >= sizeof(*in_header), ResultServiceFrameworkInvalidCmifHeaderSize);
R_UNLESS(in_header->magic == CMIF_IN_HEADER_MAGIC && in_header->version <= max_cmif_version, ResultServiceFrameworkInvalidCmifInHeader);
R_UNLESS(in_raw_data.GetSize() >= sizeof(*in_header), sf::cmif::ResultInvalidHeaderSize());
R_UNLESS(in_header->magic == CMIF_IN_HEADER_MAGIC && in_header->version <= max_cmif_version, sf::cmif::ResultInvalidInHeader());
const cmif::PointerAndSize in_message_raw_data = cmif::PointerAndSize(in_raw_data.GetAddress() + sizeof(*in_header), in_raw_data.GetSize() - sizeof(*in_header));
const u32 cmd_id = in_header->command_id;
@@ -37,7 +37,7 @@ namespace sts::sf::cmif {
break;
}
}
R_UNLESS(cmd_handler != nullptr, ResultServiceFrameworkUnknownCmifCommandId);
R_UNLESS(cmd_handler != nullptr, sf::cmif::ResultUnknownCommandId());
/* Invoke handler. */
CmifOutHeader *out_header = nullptr;
@@ -45,16 +45,16 @@ namespace sts::sf::cmif {
/* Forward forwardable results, otherwise ensure we can send result to user. */
R_TRY_CATCH(command_result) {
R_CATCH(ResultServiceFrameworkRequestDeferredByUser) { return ResultServiceFrameworkRequestDeferredByUser; }
R_CATCH(sf::impl::ResultRequestContextChanged) { return R_CURRENT_RESULT; }
R_CATCH_ALL() { STS_ASSERT(out_header != nullptr); }
} R_END_TRY_CATCH;
/* Write output header to raw data. */
if (out_header != nullptr) {
*out_header = CmifOutHeader{CMIF_OUT_HEADER_MAGIC, 0, command_result, 0};
*out_header = CmifOutHeader{CMIF_OUT_HEADER_MAGIC, 0, command_result.GetValue(), 0};
}
return ResultSuccess;
return ResultSuccess();
}
Result impl::ServiceDispatchTableBase::ProcessMessageForMitmImpl(ServiceDispatchContext &ctx, const cmif::PointerAndSize &in_raw_data, const ServiceCommandMeta *entries, const size_t entry_count) const {
@@ -64,8 +64,8 @@ namespace sts::sf::cmif {
/* Parse the CMIF in header. */
const CmifInHeader *in_header = reinterpret_cast<const CmifInHeader *>(in_raw_data.GetPointer());
R_UNLESS(in_raw_data.GetSize() >= sizeof(*in_header), ResultServiceFrameworkInvalidCmifHeaderSize);
R_UNLESS(in_header->magic == CMIF_IN_HEADER_MAGIC && in_header->version <= max_cmif_version, ResultServiceFrameworkInvalidCmifInHeader);
R_UNLESS(in_raw_data.GetSize() >= sizeof(*in_header), sf::cmif::ResultInvalidHeaderSize());
R_UNLESS(in_header->magic == CMIF_IN_HEADER_MAGIC && in_header->version <= max_cmif_version, sf::cmif::ResultInvalidInHeader());
const cmif::PointerAndSize in_message_raw_data = cmif::PointerAndSize(in_raw_data.GetAddress() + sizeof(*in_header), in_raw_data.GetSize() - sizeof(*in_header));
const u32 cmd_id = in_header->command_id;
@@ -89,19 +89,19 @@ namespace sts::sf::cmif {
/* Forward forwardable results, otherwise ensure we can send result to user. */
R_TRY_CATCH(command_result) {
R_CATCH(ResultServiceFrameworkRequestDeferredByUser) { return ResultServiceFrameworkRequestDeferredByUser; }
R_CATCH(ResultAtmosphereMitmShouldForwardToSession) {
R_CATCH(ams::mitm::ResultShouldForwardToSession) {
return ctx.session->ForwardRequest(ctx);
}
R_CATCH(sf::impl::ResultRequestContextChanged) { return R_CURRENT_RESULT; }
R_CATCH_ALL() { STS_ASSERT(out_header != nullptr); }
} R_END_TRY_CATCH;
/* Write output header to raw data. */
if (out_header != nullptr) {
*out_header = CmifOutHeader{CMIF_OUT_HEADER_MAGIC, 0, command_result, 0};
*out_header = CmifOutHeader{CMIF_OUT_HEADER_MAGIC, 0, command_result.GetValue(), 0};
}
return ResultSuccess;
return ResultSuccess();
}
}

View File

@@ -43,34 +43,34 @@ namespace sts::sf::hipc {
Result Receive(ReceiveResult *out_recv_result, Handle session_handle, const cmif::PointerAndSize &message_buffer) {
R_TRY_CATCH(ReceiveImpl(session_handle, message_buffer.GetPointer(), message_buffer.GetSize())) {
R_CATCH(ResultKernelConnectionClosed) {
R_CATCH(svc::ResultSessionClosed) {
*out_recv_result = ReceiveResult::Closed;
return ResultSuccess;
return ResultSuccess();
}
R_CATCH(ResultKernelReceiveListBroken) {
R_CATCH(svc::ResultReceiveListBroken) {
*out_recv_result = ReceiveResult::NeedsRetry;
return ResultSuccess;
return ResultSuccess();
}
} R_END_TRY_CATCH;
*out_recv_result = ReceiveResult::Success;
return ResultSuccess;
return ResultSuccess();
}
Result Receive(bool *out_closed, Handle session_handle, const cmif::PointerAndSize &message_buffer) {
R_TRY_CATCH(ReceiveImpl(session_handle, message_buffer.GetPointer(), message_buffer.GetSize())) {
R_CATCH(ResultKernelConnectionClosed) {
R_CATCH(svc::ResultSessionClosed) {
*out_closed = true;
return ResultSuccess;
return ResultSuccess();
}
} R_END_TRY_CATCH;
*out_closed = false;
return ResultSuccess;
return ResultSuccess();
}
Result Reply(Handle session_handle, const cmif::PointerAndSize &message_buffer) {
R_TRY_CATCH(ReplyImpl(session_handle, message_buffer.GetPointer(), message_buffer.GetSize())) {
R_CATCH(ResultKernelTimedOut) { return ResultSuccess; }
R_CATCH(ResultKernelConnectionClosed) { return ResultSuccess; }
R_CONVERT(svc::ResultTimedOut, ResultSuccess())
R_CONVERT(svc::ResultSessionClosed, ResultSuccess())
} R_END_TRY_CATCH;
/* ReplyImpl should *always* return an error. */
STS_ASSERT(false);
@@ -78,9 +78,9 @@ namespace sts::sf::hipc {
Result CreateSession(Handle *out_server_handle, Handle *out_client_handle) {
R_TRY_CATCH(svcCreateSession(out_server_handle, out_client_handle, 0, 0)) {
R_CATCH(ResultKernelResourceExhausted) { return ResultHipcOutOfSessions; }
R_CONVERT(svc::ResultOutOfResource, sf::hipc::ResultOutOfSessions());
} R_END_TRY_CATCH;
return ResultSuccess;
return ResultSuccess();
}
}

View File

@@ -36,7 +36,7 @@ namespace sts::sf::hipc {
Result CloneCurrentObjectImpl(Handle *out_client_handle, ServerSessionManager *tagged_manager) {
/* Clone the object. */
cmif::ServiceObjectHolder &&clone = this->session->srv_obj_holder.Clone();
R_UNLESS(clone, ResultHipcDomainObjectNotFound);
R_UNLESS(clone, sf::hipc::ResultDomainObjectNotFound());
/* Create new session handles. */
Handle server_handle;
@@ -52,7 +52,7 @@ namespace sts::sf::hipc {
R_ASSERT(tagged_manager->RegisterMitmSession(server_handle, std::move(clone), std::move(new_forward_service)));
}
return ResultSuccess;
return ResultSuccess();
}
public:
explicit HipcManager(ServerDomainSessionManager *m, ServerSession *s) : manager(m), session(s), is_mitm_session(s->forward_service != nullptr) {
@@ -62,7 +62,8 @@ namespace sts::sf::hipc {
Result ConvertCurrentObjectToDomain(sf::Out<cmif::DomainObjectId> out) {
/* Allocate a domain. */
auto domain = this->manager->AllocateDomainServiceObject();
R_UNLESS(domain, ResultHipcOutOfDomains);
R_UNLESS(domain, sf::hipc::ResultOutOfDomains());
auto domain_guard = SCOPE_GUARD { this->manager->FreeDomainServiceObject(domain); };
cmif::DomainObjectId object_id = cmif::InvalidDomainObjectId;
@@ -71,9 +72,7 @@ namespace sts::sf::hipc {
if (this->is_mitm_session) {
/* If we're a mitm session, we need to convert the remote session to domain. */
STS_ASSERT(session->forward_service->own_handle);
R_TRY_CLEANUP(serviceConvertToDomain(session->forward_service.get()), {
this->manager->FreeDomainServiceObject(domain);
});
R_TRY(serviceConvertToDomain(session->forward_service.get()));
/* The object ID reservation cannot fail here, as that would cause desynchronization from target domain. */
object_id = cmif::DomainObjectId{session->forward_service->object_id};
@@ -99,22 +98,23 @@ namespace sts::sf::hipc {
STS_ASSERT(static_cast<bool>(new_holder));
/* We succeeded! */
domain_guard.Cancel();
domain->RegisterObject(object_id, std::move(session->srv_obj_holder));
session->srv_obj_holder = std::move(new_holder);
out.SetValue(object_id);
return ResultSuccess;
return ResultSuccess();
}
Result CopyFromCurrentDomain(sf::OutMoveHandle out, cmif::DomainObjectId object_id) {
/* Get domain. */
auto domain = this->session->srv_obj_holder.GetServiceObject<cmif::DomainServiceObject>();
R_UNLESS(domain != nullptr, ResultHipcTargetNotDomain);
R_UNLESS(domain != nullptr, sf::hipc::ResultTargetNotDomain());
/* Get domain object. */
auto &&object = domain->GetObject(object_id);
if (!object) {
R_UNLESS(this->is_mitm_session, ResultHipcDomainObjectNotFound);
R_UNLESS(this->is_mitm_session, sf::hipc::ResultDomainObjectNotFound());
return cmifCopyFromCurrentDomain(this->session->forward_service->session, object_id.value, out.GetHandlePointer());
}
@@ -140,7 +140,7 @@ namespace sts::sf::hipc {
R_ASSERT(this->manager->RegisterMitmSession(server_handle, std::move(object), std::move(new_forward_service)));
}
return ResultSuccess;
return ResultSuccess();
}
Result CloneCurrentObject(sf::OutMoveHandle out) {

View File

@@ -124,7 +124,12 @@ namespace sts::sf::hipc {
std::memcpy(tls_message.GetPointer(), saved_message.GetPointer(), tls_message.GetSize());
}
return this->ProcessRequest(session, tls_message);
/* Treat a meta "Context Invalidated" message as a success. */
R_TRY_CATCH(this->ProcessRequest(session, tls_message)) {
R_CONVERT(sf::impl::ResultRequestInvalidated, ResultSuccess());
} R_END_TRY_CATCH;
return ResultSuccess();
}
void ServerManagerBase::ProcessDeferredSessions() {
@@ -135,12 +140,16 @@ namespace sts::sf::hipc {
while (it != this->deferred_session_list.end()) {
ServerSession *session = static_cast<ServerSession *>(&*it);
R_TRY_CATCH(this->ProcessForSession(session)) {
R_CATCH(ResultServiceFrameworkRequestDeferredByUser) {
R_CATCH(sf::ResultRequestDeferred) {
/* Session is still deferred, so let's continue. */
it++;
continue;
}
/* TODO: N has a result that undefers without success. */
R_CATCH(sf::impl::ResultRequestInvalidated) {
/* Session is no longer deferred! */
it = this->deferred_session_list.erase(it);
continue;
}
} R_END_TRY_CATCH_WITH_ASSERT;
/* We succeeded! Remove from deferred list. */
@@ -159,17 +168,17 @@ namespace sts::sf::hipc {
case UserDataTag::Session:
/* Try to process for session. */
R_TRY_CATCH(this->ProcessForSession(holder)) {
R_CATCH(ResultServiceFrameworkRequestDeferredByUser) {
R_CATCH(sf::ResultRequestDeferred) {
/* The session was deferred, so push it onto the deferred session list. */
std::scoped_lock lk(this->deferred_session_mutex);
this->deferred_session_list.push_back(*static_cast<ServerSession *>(holder));
return ResultSuccess;
return ResultSuccess();
}
} R_END_TRY_CATCH;
/* We successfully invoked a command...so let's see if anything can be undeferred. */
this->ProcessDeferredSessions();
return ResultSuccess;
return ResultSuccess();
break;
STS_UNREACHABLE_DEFAULT_CASE();
}

View File

@@ -65,7 +65,7 @@ namespace sts::sf::hipc {
}
}
return ResultSuccess;
return ResultSuccess();
}
void ServerSessionManager::DestroySession(ServerSession *session) {
@@ -89,7 +89,7 @@ namespace sts::sf::hipc {
session_memory->saved_message = this->GetSessionSavedMessageBuffer(session_memory);
/* Register to wait list. */
this->RegisterSessionToWaitList(session_memory);
return ResultSuccess;
return ResultSuccess();
}
Result ServerSessionManager::AcceptSessionImpl(ServerSession *session_memory, Handle port_handle, cmif::ServiceObjectHolder &&obj) {
@@ -105,7 +105,7 @@ namespace sts::sf::hipc {
/* Register session. */
R_TRY(this->RegisterSessionImpl(session_memory, session_handle, std::forward<cmif::ServiceObjectHolder>(obj)));
succeeded = true;
return ResultSuccess;
return ResultSuccess();
}
Result ServerSessionManager::RegisterMitmSessionImpl(ServerSession *session_memory, Handle mitm_session_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) {
@@ -119,7 +119,7 @@ namespace sts::sf::hipc {
session_memory->pointer_buffer = cmif::PointerAndSize(session_memory->pointer_buffer.GetAddress(), session_memory->forward_service->pointer_buffer_size);
/* Register to wait list. */
this->RegisterSessionToWaitList(session_memory);
return ResultSuccess;
return ResultSuccess();
}
Result ServerSessionManager::AcceptMitmSessionImpl(ServerSession *session_memory, Handle mitm_port_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) {
@@ -135,7 +135,7 @@ namespace sts::sf::hipc {
/* Register session. */
R_TRY(this->RegisterMitmSessionImpl(session_memory, mitm_session_handle, std::forward<cmif::ServiceObjectHolder>(obj), std::forward<std::shared_ptr<::Service>>(fsrv)));
succeeded = true;
return ResultSuccess;
return ResultSuccess();
}
Result ServerSessionManager::RegisterSession(Handle session_handle, cmif::ServiceObjectHolder &&obj) {
@@ -182,10 +182,10 @@ namespace sts::sf::hipc {
switch (recv_result) {
case hipc::ReceiveResult::Success:
session->is_closed = false;
return ResultSuccess;
return ResultSuccess();
case hipc::ReceiveResult::Closed:
session->is_closed = true;
return ResultSuccess;
return ResultSuccess();
case hipc::ReceiveResult::NeedsRetry:
continue;
STS_UNREACHABLE_DEFAULT_CASE();
@@ -206,29 +206,31 @@ namespace sts::sf::hipc {
Result ServerSessionManager::ProcessRequest(ServerSession *session, const cmif::PointerAndSize &message) {
if (session->is_closed) {
this->CloseSessionImpl(session);
return ResultSuccess;
return ResultSuccess();
}
switch (GetCmifCommandType(message)) {
case CmifCommandType_Close:
{
this->CloseSessionImpl(session);
return ResultSuccess;
return ResultSuccess();
}
default:
{
R_TRY_CATCH(this->ProcessRequestImpl(session, message, message)) {
R_CATCH(ResultServiceFrameworkRequestDeferredByUser) { /* TODO: Properly include entire range Nintendo does */
return ResultServiceFrameworkRequestDeferredByUser;
R_CATCH(sf::impl::ResultRequestContextChanged) {
/* A meta message changing the request context has been sent. */
return R_CURRENT_RESULT;
}
R_CATCH_ALL() {
/* All other results indicate something went very wrong. */
this->CloseSessionImpl(session);
return ResultSuccess;
return ResultSuccess();
}
} R_END_TRY_CATCH;
/* We succeeded, so we can process future messages on this session. */
this->RegisterSessionToWaitList(session);
return ResultSuccess;
return ResultSuccess();
}
}
}
@@ -244,13 +246,13 @@ namespace sts::sf::hipc {
case CmifCommandType_ControlWithContext:
return this->DispatchManagerRequest(session, in_message, out_message);
default:
return ResultHipcUnknownCommandType;
return sf::hipc::ResultUnknownCommandType();
}
}
Result ServerSessionManager::DispatchManagerRequest(ServerSession *session, const cmif::PointerAndSize &in_message, const cmif::PointerAndSize &out_message) {
/* This will get overridden by ... WithDomain class. */
return ResultServiceFrameworkNotSupported;
return sf::ResultNotSupported();
}
Result ServerSessionManager::DispatchRequest(cmif::ServiceObjectHolder &&obj_holder, ServerSession *session, const cmif::PointerAndSize &in_message, const cmif::PointerAndSize &out_message) {
@@ -273,10 +275,10 @@ namespace sts::sf::hipc {
const uintptr_t in_raw_addr = reinterpret_cast<uintptr_t>(dispatch_ctx.request.data.data_words);
const size_t in_raw_size = dispatch_ctx.request.meta.num_data_words * sizeof(u32);
/* Note: Nintendo does not validate this size before subtracting 0x10 from it. This is not exploitable. */
R_UNLESS(in_raw_size >= 0x10, ResultHipcInvalidRequestSize);
R_UNLESS(in_raw_addr + in_raw_size <= in_message_buffer_end, ResultHipcInvalidRequestSize);
R_UNLESS(in_raw_size >= 0x10, sf::hipc::ResultInvalidRequestSize());
R_UNLESS(in_raw_addr + in_raw_size <= in_message_buffer_end, sf::hipc::ResultInvalidRequestSize());
const uintptr_t recv_list_end = reinterpret_cast<uintptr_t>(dispatch_ctx.request.data.recv_list + dispatch_ctx.request.meta.num_recv_statics);
R_UNLESS(recv_list_end <= in_message_buffer_end, ResultHipcInvalidRequestSize);
R_UNLESS(recv_list_end <= in_message_buffer_end, sf::hipc::ResultInvalidRequestSize());
/* CMIF has 0x10 of padding in raw data, and requires 0x10 alignment. */
const cmif::PointerAndSize in_raw_data(util::AlignUp(in_raw_addr, 0x10), in_raw_size - 0x10);
@@ -294,7 +296,7 @@ namespace sts::sf::hipc {
R_TRY(hipc::Reply(session->session_handle, out_message));
}
return ResultSuccess;
return ResultSuccess();
}

View File

@@ -60,7 +60,7 @@ namespace sts::sm {
void DoWithSessionImpl(void (*Invoker)(void *), void *Function) {
impl::DoWithUserSession([&]() {
Invoker(Function);
return ResultSuccess;
return ResultSuccess();
});
}

View File

@@ -55,15 +55,15 @@ namespace sts::updater {
/* Implementations. */
Result ValidateWorkBuffer(const void *work_buffer, size_t work_buffer_size) {
if (work_buffer_size < BctSize + EksSize) {
return ResultUpdaterTooSmallWorkBuffer;
return ResultTooSmallWorkBuffer();
}
if (reinterpret_cast<uintptr_t>(work_buffer) & 0xFFF) {
return ResultUpdaterMisalignedWorkBuffer;
if (!util::IsAligned(work_buffer, 0x1000)) {
return ResultNotAlignedWorkBuffer();
}
if (reinterpret_cast<uintptr_t>(work_buffer_size) & 0x1FF) {
return ResultUpdaterMisalignedWorkBuffer;
if (util::IsAligned(work_buffer_size, 0x200)) {
return ResultNotAlignedWorkBuffer();
}
return ResultSuccess;
return ResultSuccess();
}
bool HasEks(BootImageUpdateType boot_image_update_type) {
@@ -115,7 +115,7 @@ namespace sts::updater {
/* Read data from save. */
out->needs_verify_normal = save.GetNeedsVerification(BootModeType::Normal);
out->needs_verify_safe = save.GetNeedsVerification(BootModeType::Safe);
return ResultSuccess;
return ResultSuccess();
}
Result VerifyBootImagesAndRepairIfNeeded(bool *out_repaired, BootModeType mode, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type) {
@@ -125,7 +125,7 @@ namespace sts::updater {
/* Verify the boot images in NAND. */
R_TRY_CATCH(VerifyBootImages(bip_data_id, mode, work_buffer, work_buffer_size, boot_image_update_type)) {
R_CATCH(ResultUpdaterNeedsRepairBootImages) {
R_CATCH(ResultNeedsRepairBootImages) {
/* Perform repair. */
*out_repaired = true;
R_TRY(UpdateBootImages(bip_data_id, mode, work_buffer, work_buffer_size, boot_image_update_type));
@@ -153,7 +153,7 @@ namespace sts::updater {
u32 total_entries;
R_TRY(ncmContentMetaDatabaseList(&meta_db, &total_entries, &written_entries, records, MaxContentMetas * sizeof(*records), title_type, 0, 0, UINT64_MAX, NcmContentInstallType_Full));
if (total_entries == 0) {
return ResultUpdaterBootImagePackageNotFound;
return ResultBootImagePackageNotFound();
}
STS_ASSERT(total_entries == written_entries);
@@ -166,14 +166,14 @@ namespace sts::updater {
if (attr & NcmContentMetaAttribute_IncludesExFatDriver) {
*out_data_id = records[i].title_id;
return ResultSuccess;
return ResultSuccess();
}
}
}
/* If there's only one entry or no exfat entries, return that entry. */
*out_data_id = records[0].title_id;
return ResultSuccess;
return ResultSuccess();
}
Result VerifyBootImages(u64 data_id, BootModeType mode, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type) {
@@ -191,9 +191,7 @@ namespace sts::updater {
R_TRY(ValidateWorkBuffer(work_buffer, work_buffer_size));
R_TRY_CATCH(romfsMountFromDataArchive(data_id, FsStorageId_NandSystem, GetBootImagePackageMountPath())) {
R_CATCH(ResultFsTargetNotFound) {
return ResultUpdaterBootImagePackageNotFound;
}
R_CONVERT(fs::ResultTargetNotFound, ResultBootImagePackageNotFound())
} R_END_TRY_CATCH;
ON_SCOPE_EXIT { R_ASSERT(romfsUnmount(GetBootImagePackageMountPath())); };
@@ -219,26 +217,26 @@ namespace sts::updater {
R_TRY(GetFileHash(&size, file_hash, GetPackage1Path(boot_image_update_type), work_buffer, work_buffer_size));
R_TRY(boot0_accessor.GetHash(nand_hash, size, work_buffer, work_buffer_size, Boot0Partition::Package1NormalMain));
if (std::memcmp(file_hash, nand_hash, SHA256_HASH_SIZE) != 0) {
return ResultUpdaterNeedsRepairBootImages;
return ResultNeedsRepairBootImages();
}
R_TRY(boot0_accessor.GetHash(nand_hash, size, work_buffer, work_buffer_size, Boot0Partition::Package1NormalSub));
if (std::memcmp(file_hash, nand_hash, SHA256_HASH_SIZE) != 0) {
return ResultUpdaterNeedsRepairBootImages;
return ResultNeedsRepairBootImages();
}
/* Compare Package2 Normal/Sub hashes. */
R_TRY(GetFileHash(&size, file_hash, GetPackage2Path(boot_image_update_type), work_buffer, work_buffer_size));
R_TRY(GetPackage2Hash(nand_hash, size, work_buffer, work_buffer_size, Package2Type::NormalMain));
if (std::memcmp(file_hash, nand_hash, SHA256_HASH_SIZE) != 0) {
return ResultUpdaterNeedsRepairBootImages;
return ResultNeedsRepairBootImages();
}
R_TRY(GetPackage2Hash(nand_hash, size, work_buffer, work_buffer_size, Package2Type::NormalSub));
if (std::memcmp(file_hash, nand_hash, SHA256_HASH_SIZE) != 0) {
return ResultUpdaterNeedsRepairBootImages;
return ResultNeedsRepairBootImages();
}
}
return ResultSuccess;
return ResultSuccess();
}
Result VerifyBootImagesSafe(u64 data_id, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type) {
@@ -246,9 +244,7 @@ namespace sts::updater {
R_TRY(ValidateWorkBuffer(work_buffer, work_buffer_size));
R_TRY_CATCH(romfsMountFromDataArchive(data_id, FsStorageId_NandSystem, GetBootImagePackageMountPath())) {
R_CATCH(ResultFsTargetNotFound) {
return ResultUpdaterBootImagePackageNotFound;
}
R_CONVERT(fs::ResultTargetNotFound, ResultBootImagePackageNotFound())
} R_END_TRY_CATCH;
ON_SCOPE_EXIT { R_ASSERT(romfsUnmount(GetBootImagePackageMountPath())); };
@@ -279,26 +275,26 @@ namespace sts::updater {
R_TRY(GetFileHash(&size, file_hash, GetPackage1Path(boot_image_update_type), work_buffer, work_buffer_size));
R_TRY(boot1_accessor.GetHash(nand_hash, size, work_buffer, work_buffer_size, Boot1Partition::Package1SafeMain));
if (std::memcmp(file_hash, nand_hash, SHA256_HASH_SIZE) != 0) {
return ResultUpdaterNeedsRepairBootImages;
return ResultNeedsRepairBootImages();
}
R_TRY(boot1_accessor.GetHash(nand_hash, size, work_buffer, work_buffer_size, Boot1Partition::Package1SafeSub));
if (std::memcmp(file_hash, nand_hash, SHA256_HASH_SIZE) != 0) {
return ResultUpdaterNeedsRepairBootImages;
return ResultNeedsRepairBootImages();
}
/* Compare Package2 Normal/Sub hashes. */
R_TRY(GetFileHash(&size, file_hash, GetPackage2Path(boot_image_update_type), work_buffer, work_buffer_size));
R_TRY(GetPackage2Hash(nand_hash, size, work_buffer, work_buffer_size, Package2Type::SafeMain));
if (std::memcmp(file_hash, nand_hash, SHA256_HASH_SIZE) != 0) {
return ResultUpdaterNeedsRepairBootImages;
return ResultNeedsRepairBootImages();
}
R_TRY(GetPackage2Hash(nand_hash, size, work_buffer, work_buffer_size, Package2Type::SafeSub));
if (std::memcmp(file_hash, nand_hash, SHA256_HASH_SIZE) != 0) {
return ResultUpdaterNeedsRepairBootImages;
return ResultNeedsRepairBootImages();
}
}
return ResultSuccess;
return ResultSuccess();
}
Result UpdateBootImages(u64 data_id, BootModeType mode, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type) {
@@ -316,9 +312,7 @@ namespace sts::updater {
R_TRY(ValidateWorkBuffer(work_buffer, work_buffer_size));
R_TRY_CATCH(romfsMountFromDataArchive(data_id, FsStorageId_NandSystem, GetBootImagePackageMountPath())) {
R_CATCH(ResultFsTargetNotFound) {
return ResultUpdaterBootImagePackageNotFound;
}
R_CONVERT(fs::ResultTargetNotFound, ResultBootImagePackageNotFound())
} R_END_TRY_CATCH;
ON_SCOPE_EXIT { R_ASSERT(romfsUnmount(GetBootImagePackageMountPath())); };
@@ -365,7 +359,7 @@ namespace sts::updater {
R_TRY(boot0_accessor.Write(GetPackage1Path(boot_image_update_type), work_buffer, work_buffer_size, Boot0Partition::Package1NormalMain));
}
return ResultSuccess;
return ResultSuccess();
}
Result UpdateBootImagesSafe(u64 data_id, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type) {
@@ -373,9 +367,7 @@ namespace sts::updater {
R_TRY(ValidateWorkBuffer(work_buffer, work_buffer_size));
R_TRY_CATCH(romfsMountFromDataArchive(data_id, FsStorageId_NandSystem, GetBootImagePackageMountPath())) {
R_CATCH(ResultFsTargetNotFound) {
return ResultUpdaterBootImagePackageNotFound;
}
R_CONVERT(fs::ResultTargetNotFound, ResultBootImagePackageNotFound())
} R_END_TRY_CATCH;
ON_SCOPE_EXIT { R_ASSERT(romfsUnmount(GetBootImagePackageMountPath())); };
@@ -426,7 +418,7 @@ namespace sts::updater {
R_TRY(boot1_accessor.Write(GetPackage1Path(boot_image_update_type), work_buffer, work_buffer_size, Boot1Partition::Package1SafeMain));
}
return ResultSuccess;
return ResultSuccess();
}
Result SetVerificationNeeded(BootModeType mode, bool needed, void *work_buffer, size_t work_buffer_size) {
@@ -445,7 +437,7 @@ namespace sts::updater {
save.SetNeedsVerification(mode, needed);
R_TRY(save.Save());
return ResultSuccess;
return ResultSuccess();
}
Result ValidateBctFileHash(Boot0Accessor &accessor, Boot0Partition which, const void *stored_hash, void *work_buffer, size_t work_buffer_size, BootImageUpdateType boot_image_update_type) {
@@ -468,10 +460,10 @@ namespace sts::updater {
sha256CalculateHash(file_hash, bct, BctSize);
if (std::memcmp(file_hash, stored_hash, SHA256_HASH_SIZE) != 0) {
return ResultUpdaterNeedsRepairBootImages;
return ResultNeedsRepairBootImages();
}
return ResultSuccess;
return ResultSuccess();
}
Result GetPackage2Hash(void *dst_hash, size_t package2_size, void *work_buffer, size_t work_buffer_size, Package2Type which) {
@@ -518,7 +510,7 @@ namespace sts::updater {
/* If we don't need to verify anything, we're done. */
if (!verification_state.needs_verify_normal && !verification_state.needs_verify_safe) {
return ResultSuccess;
return ResultSuccess();
}
/* Get a session to ncm. */
@@ -528,21 +520,17 @@ namespace sts::updater {
/* Verify normal, verify safe as needed. */
if (verification_state.needs_verify_normal) {
R_TRY_CATCH(VerifyBootImagesAndRepairIfNeeded(out_repaired_normal, BootModeType::Normal, work_buffer, work_buffer_size, boot_image_update_type)) {
R_CATCH(ResultUpdaterBootImagePackageNotFound) {
/* Nintendo considers failure to locate bip a success. TODO: don't do that? */
}
R_CATCH(ResultBootImagePackageNotFound) { /* Nintendo considers failure to locate bip a success. TODO: don't do that? */ }
} R_END_TRY_CATCH;
}
if (verification_state.needs_verify_safe) {
R_TRY_CATCH(VerifyBootImagesAndRepairIfNeeded(out_repaired_safe, BootModeType::Safe, work_buffer, work_buffer_size, boot_image_update_type)) {
R_CATCH(ResultUpdaterBootImagePackageNotFound) {
/* Nintendo considers failure to locate bip a success. TODO: don't do that? */
}
R_CATCH(ResultBootImagePackageNotFound) { /* Nintendo considers failure to locate bip a success. TODO: don't do that? */ }
} R_END_TRY_CATCH;
}
return ResultSuccess;
return ResultSuccess();
}
}

View File

@@ -24,7 +24,7 @@ namespace sts::updater {
Result BisAccessor::Initialize() {
R_TRY(fsOpenBisStorage(&this->storage, this->partition_id));
this->active = true;
return ResultSuccess;
return ResultSuccess();
}
void BisAccessor::Finalize() {
@@ -50,7 +50,7 @@ namespace sts::updater {
FILE *bip_fp = fopen(bip_path, "rb");
if (bip_fp == NULL) {
return ResultUpdaterInvalidBootImagePackage;
return ResultInvalidBootImagePackage();
}
ON_SCOPE_EXIT { fclose(bip_fp); };
@@ -73,7 +73,7 @@ namespace sts::updater {
break;
}
}
return ResultSuccess;
return ResultSuccess();
}
Result BisAccessor::Clear(u64 offset, u64 size, void *work_buffer, size_t work_buffer_size) {
@@ -88,7 +88,7 @@ namespace sts::updater {
R_TRY(this->Write(offset + written, work_buffer, cur_write_size));
written += cur_write_size;
}
return ResultSuccess;
return ResultSuccess();
}
Result BisAccessor::GetHash(void *dst, u64 offset, u64 size, u64 hash_size, void *work_buffer, size_t work_buffer_size) {
@@ -108,7 +108,7 @@ namespace sts::updater {
}
sha256ContextGetHash(&sha_ctx, dst);
return ResultSuccess;
return ResultSuccess();
}
size_t Boot0Accessor::GetBootloaderVersion(void *bct) {
@@ -135,7 +135,7 @@ namespace sts::updater {
Result Boot0Accessor::UpdateEksManually(void *dst_bct, const void *src_eks) {
this->CopyEks(dst_bct, src_eks, GetEksIndex(GetBootloaderVersion(dst_bct)));
return ResultSuccess;
return ResultSuccess();
}
Result Boot0Accessor::PreserveAutoRcm(void *dst_bct, void *work_buffer, Boot0Partition which) {
@@ -147,7 +147,7 @@ namespace sts::updater {
void *dst_pubk = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(dst_bct) + BctPubkOffset);
void *src_pubk = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(work_buffer) + BctPubkOffset);
std::memcpy(dst_pubk, src_pubk, BctPubkSize);
return ResultSuccess;
return ResultSuccess();
}
}

View File

@@ -149,7 +149,7 @@ namespace sts::updater {
R_TRY(BisAccessor::Read(dst, entry->size, entry->offset));
*out_size = entry->size;
return ResultSuccess;
return ResultSuccess();
}
Result Write(const void *src, size_t size, EnumType which) {

View File

@@ -39,7 +39,7 @@ namespace sts::updater {
R_TRY(this->accessor.Initialize());
this->save_buffer = work_buffer;
return ResultSuccess;
return ResultSuccess();
}
void BisSave::Finalize() {

View File

@@ -24,7 +24,7 @@ namespace sts::updater {
Result ReadFile(size_t *out_size, void *dst, size_t dst_size, const char *path) {
FILE *fp = fopen(path, "rb");
if (fp == NULL) {
return ResultUpdaterInvalidBootImagePackage;
return ResultInvalidBootImagePackage();
}
ON_SCOPE_EXIT { fclose(fp); };
@@ -34,13 +34,13 @@ namespace sts::updater {
return fsdevGetLastResult();
}
*out_size = read_size;
return ResultSuccess;
return ResultSuccess();
}
Result GetFileHash(size_t *out_size, void *dst_hash, const char *path, void *work_buffer, size_t work_buffer_size) {
FILE *fp = fopen(path, "rb");
if (fp == NULL) {
return ResultUpdaterInvalidBootImagePackage;
return ResultInvalidBootImagePackage();
}
ON_SCOPE_EXIT { fclose(fp); };
@@ -66,7 +66,7 @@ namespace sts::updater {
sha256ContextGetHash(&sha_ctx, dst_hash);
*out_size = total_size;
return ResultSuccess;
return ResultSuccess();
}
}