mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-24 07:40:26 +01:00
strat: use ams::Main() instead of main(argc, argv)
This commit is contained in:
parent
6a53726833
commit
ffc143860b
@ -26,7 +26,7 @@ CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
|
||||
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS)
|
||||
endif
|
||||
|
||||
export LDFLAGS = -specs=$(TOPDIR)/$(notdir $(TOPDIR)).specs -fno-asynchronous-unwind-tables -fno-unwind-tables -fno-exceptions -fno-rtti -fno-use-cxa-atexit -nostdlib -nostartfiles -g -gdwarf-4 $(SETTINGS) -Wl,-Map,$(notdir $*.map) -Wl,-z,relro,-z,now
|
||||
export LDFLAGS = -specs=$(TOPDIR)/$(notdir $(TOPDIR)).specs -fno-asynchronous-unwind-tables -fno-unwind-tables -fno-exceptions -fno-rtti -fno-use-cxa-atexit -nostdlib -nostartfiles -g -gdwarf-4 $(CXXFLAGS) -Wl,-Map,$(notdir $*.map) -Wl,-z,relro,-z,now
|
||||
|
||||
export CXXWRAPS := -Wl,--wrap,__cxa_pure_virtual \
|
||||
-Wl,--wrap,__cxa_throw \
|
||||
|
@ -12,7 +12,7 @@ export CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||
export CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS) -fno-use-cxa-atexit
|
||||
export ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||
|
||||
export LDFLAGS = -specs=$(TOPDIR)/$(notdir $(TOPDIR)).specs -fno-asynchronous-unwind-tables -fno-unwind-tables -nostdlib -nostartfiles -g -gdwarf-4 $(SETTINGS) -Wl,-Map,$(notdir $*.map) -Wl,-z,relro,-z,now
|
||||
export LDFLAGS = -specs=$(TOPDIR)/$(notdir $(TOPDIR)).specs -fno-asynchronous-unwind-tables -fno-unwind-tables -nostdlib -nostartfiles -g -gdwarf-4 $(CXXFLAGS) -Wl,-Map,$(notdir $*.map) -Wl,-z,relro,-z,now
|
||||
|
||||
export CXXWRAPS := -Wl,--wrap,__cxa_pure_virtual \
|
||||
-Wl,--wrap,__cxa_throw \
|
||||
|
@ -21,6 +21,15 @@ export CFLAGS = $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
|
||||
export CXXFLAGS = $(CFLAGS) $(ATMOSPHERE_CXXFLAGS)
|
||||
export ASFLAGS = $(ATMOSPHERE_ASFLAGS) $(SETTINGS) $(DEFINES)
|
||||
|
||||
export CXXREQUIRED := -Wl,--require-defined,__libnx_initheap \
|
||||
-Wl,--require-defined,__libnx_exception_handler \
|
||||
-Wl,--require-defined,__libnx_alloc \
|
||||
-Wl,--require-defined,__libnx_aligned_alloc \
|
||||
-Wl,--require-defined,__libnx_free \
|
||||
-Wl,--require-defined,__appInit \
|
||||
-Wl,--require-defined,__appExit \
|
||||
-Wl,--require-defined,argvSetup
|
||||
|
||||
export CXXWRAPS := -Wl,--wrap,__cxa_pure_virtual \
|
||||
-Wl,--wrap,__cxa_throw \
|
||||
-Wl,--wrap,__cxa_rethrow \
|
||||
@ -37,7 +46,7 @@ export CXXWRAPS := -Wl,--wrap,__cxa_pure_virtual \
|
||||
-Wl,--wrap,_ZNSt11logic_errorC2EPKc \
|
||||
-Wl,--wrap,exit
|
||||
|
||||
export LDFLAGS = -specs=$(ATMOSPHERE_LIBRARIES_DIR)/libstratosphere/stratosphere.specs -specs=$(DEVKITPRO)/libnx/switch.specs $(SETTINGS) $(CXXWRAPS) -Wl,-Map,$(notdir $*.map)
|
||||
export LDFLAGS = -specs=$(ATMOSPHERE_LIBRARIES_DIR)/libstratosphere/stratosphere.specs -specs=$(DEVKITPRO)/libnx/switch.specs $(CXXFLAGS) $(CXXWRAPS) $(CXXREQUIRED) -Wl,-Map,$(notdir $*.map)
|
||||
|
||||
export LIBS = -lstratosphere -lnx
|
||||
|
||||
|
@ -126,6 +126,9 @@ ams_environment_weak.o: CXXFLAGS += -fno-lto
|
||||
pm_info_api_weak.o: CXXFLAGS += -fno-lto
|
||||
hos_stratosphere_api.o: CXXFLAGS += -fno-lto
|
||||
|
||||
init_operator_new.o: CXXFLAGS += -fno-lto
|
||||
init_libnx_shim.os.horizon.o: CXXFLAGS += -fno-lto
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
%_bin.h %.bin.o : %.bin
|
||||
#---------------------------------------------------------------------------------
|
||||
|
@ -62,6 +62,7 @@
|
||||
#include <stratosphere/htclow.hpp>
|
||||
#include <stratosphere/htcs.hpp>
|
||||
#include <stratosphere/i2c.hpp>
|
||||
#include <stratosphere/init.hpp>
|
||||
#include <stratosphere/kvdb.hpp>
|
||||
#include <stratosphere/ldr.hpp>
|
||||
#include <stratosphere/lr.hpp>
|
||||
|
@ -62,3 +62,4 @@
|
||||
#include <stratosphere/fs/fs_system_data.hpp>
|
||||
#include <stratosphere/fs/fs_program_index_map_info.hpp>
|
||||
#include <stratosphere/fs/impl/fs_access_log_impl.hpp>
|
||||
#include <stratosphere/fs/fs_api.hpp>
|
||||
|
24
libraries/libstratosphere/include/stratosphere/fs/fs_api.hpp
Normal file
24
libraries/libstratosphere/include/stratosphere/fs/fs_api.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 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/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
|
||||
namespace ams::fs {
|
||||
|
||||
void InitializeForSystem();
|
||||
void InitializeWithMultiSessionForSystem();
|
||||
|
||||
}
|
18
libraries/libstratosphere/include/stratosphere/init.hpp
Normal file
18
libraries/libstratosphere/include/stratosphere/init.hpp
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <stratosphere/init/init_malloc.hpp>
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 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/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
|
||||
namespace ams::mem {
|
||||
|
||||
class StandardAllocator;
|
||||
|
||||
}
|
||||
|
||||
namespace ams::init {
|
||||
|
||||
void InitializeAllocator(void *address, size_t size, bool cache_enabled);
|
||||
void InitializeAllocator(void *address, size_t size);
|
||||
|
||||
mem::StandardAllocator *GetAllocator();
|
||||
|
||||
}
|
@ -52,3 +52,4 @@
|
||||
#include <stratosphere/os/os_barrier.hpp>
|
||||
#include <stratosphere/os/os_io_region.hpp>
|
||||
#include <stratosphere/os/os_multiple_wait.hpp>
|
||||
#include <stratosphere/os/os_argument.hpp>
|
||||
|
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
|
||||
namespace ams::os {
|
||||
|
||||
int GetHostArgc();
|
||||
char **GetHostArgv();
|
||||
|
||||
}
|
@ -75,7 +75,9 @@ namespace ams::erpt::srv {
|
||||
g_heap_handle = lmem::CreateExpHeap(mem, mem_size, lmem::CreateOption_ThreadSafe);
|
||||
AMS_ABORT_UNLESS(g_heap_handle != nullptr);
|
||||
|
||||
fs::InitializeForSystem();
|
||||
fs::SetAllocator(Allocate, DeallocateWithSize);
|
||||
fs::SetEnabledAutoAbort(false);
|
||||
|
||||
R_ABORT_UNLESS(fs::MountSdCardErrorReportDirectoryForAtmosphere(ReportOnSdStoragePath));
|
||||
|
||||
|
38
libraries/libstratosphere/source/fs/fs_api.cpp
Normal file
38
libraries/libstratosphere/source/fs/fs_api.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 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>
|
||||
|
||||
extern "C" {
|
||||
|
||||
extern u32 __nx_fs_num_sessions;
|
||||
|
||||
}
|
||||
|
||||
namespace ams::fs {
|
||||
|
||||
/* TODO: FileSystemProxySessionSetting */
|
||||
|
||||
void InitializeForSystem() {
|
||||
__nx_fs_num_sessions = 1;
|
||||
R_ABORT_UNLESS(::fsInitialize());
|
||||
}
|
||||
|
||||
void InitializeWithMultiSessionForSystem() {
|
||||
__nx_fs_num_sessions = 2;
|
||||
R_ABORT_UNLESS(::fsInitialize());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 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>
|
||||
|
||||
extern "C" {
|
||||
|
||||
constinit u32 __nx_fs_num_sessions = 1;
|
||||
constinit u32 __nx_applet_type = AppletType_None;
|
||||
|
||||
extern int __system_argc;
|
||||
extern char** __system_argv;
|
||||
|
||||
alignas(16) constinit u8 __nx_exception_stack[::ams::os::MemoryPageSize];
|
||||
constinit u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
|
||||
|
||||
}
|
||||
|
||||
namespace ams {
|
||||
|
||||
namespace hos {
|
||||
|
||||
void InitializeForStratosphere();
|
||||
|
||||
}
|
||||
|
||||
namespace init {
|
||||
|
||||
void InitializeSystemModule();
|
||||
void FinalizeSystemModule();
|
||||
|
||||
void Startup();
|
||||
|
||||
}
|
||||
|
||||
void Main();
|
||||
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
constinit char *g_empty_argv = nullptr;
|
||||
|
||||
}
|
||||
|
||||
extern "C" void __libnx_exception_handler(ThreadExceptionDump *ctx) {
|
||||
::ams::CrashHandler(ctx);
|
||||
}
|
||||
|
||||
extern "C" void __libnx_initheap(void) {
|
||||
/* Stratosphere system modules do not support newlib heap. */
|
||||
}
|
||||
|
||||
extern "C" void __appInit(void) {
|
||||
/* The very first thing all stratosphere code must do is initialize the os library. */
|
||||
::ams::hos::InitializeForStratosphere();
|
||||
}
|
||||
|
||||
extern "C" void __appExit(void) {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
extern "C" void argvSetup(void) {
|
||||
/* We don't use newlib argc/argv, so we can clear these. */
|
||||
__system_argc = 0;
|
||||
__system_argv = std::addressof(g_empty_argv);
|
||||
}
|
||||
|
||||
extern "C" int main(int argc, char **argv) {
|
||||
/* We don't use newlib argc/argv. */
|
||||
AMS_UNUSED(argc, argv);
|
||||
|
||||
/* Perform remainder of logic with system module initialized. */
|
||||
{
|
||||
::ams::init::InitializeSystemModule();
|
||||
ON_SCOPE_EXIT { ::ams::init::FinalizeSystemModule(); };
|
||||
|
||||
/* Perform miscellaneous startup. */
|
||||
::ams::init::Startup();
|
||||
|
||||
/* Invoke ams main. */
|
||||
::ams::Main();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" WEAK_SYMBOL void *__libnx_alloc(size_t) {
|
||||
AMS_ABORT("__libnx_alloc was called");
|
||||
}
|
||||
|
||||
extern "C" WEAK_SYMBOL void *__libnx_aligned_alloc(size_t, size_t) {
|
||||
AMS_ABORT("__libnx_aligned_alloc was called");
|
||||
}
|
||||
|
||||
extern "C" WEAK_SYMBOL void __libnx_free(void *) {
|
||||
AMS_ABORT("__libnx_free was called");
|
||||
}
|
147
libraries/libstratosphere/source/init/init_malloc.cpp
Normal file
147
libraries/libstratosphere/source/init/init_malloc.cpp
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (c) 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 ams::init {
|
||||
|
||||
namespace {
|
||||
|
||||
constinit void *g_malloc_region_address = nullptr;
|
||||
constinit size_t g_malloc_region_size = 0;
|
||||
|
||||
constinit util::TypedStorage<mem::StandardAllocator> g_malloc_allocator;
|
||||
|
||||
}
|
||||
|
||||
void InitializeAllocator(void *address, size_t size, bool cache_enabled) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ABORT_UNLESS(g_malloc_region_size == 0);
|
||||
AMS_ABORT_UNLESS(size > 0);
|
||||
|
||||
/* Construct malloc allocator. */
|
||||
util::ConstructAt(g_malloc_allocator);
|
||||
|
||||
/* Initialize allocator. */
|
||||
util::GetReference(g_malloc_allocator).Initialize(address, size, cache_enabled);
|
||||
|
||||
/* Set malloc globals. */
|
||||
g_malloc_region_address = address;
|
||||
g_malloc_region_size = size;
|
||||
}
|
||||
|
||||
void InitializeAllocator(void *address, size_t size) {
|
||||
return InitializeAllocator(address, size, false);
|
||||
}
|
||||
|
||||
mem::StandardAllocator *GetAllocator() {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(g_malloc_region_size > 0);
|
||||
|
||||
return util::GetPointer(g_malloc_allocator);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern "C" void *malloc(size_t size) {
|
||||
/* We require that an allocator region exists. */
|
||||
if (::ams::init::g_malloc_region_size == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Try to allocate. */
|
||||
void *ptr = ::ams::util::GetReference(::ams::init::g_malloc_allocator).Allocate(size);
|
||||
if (ptr == nullptr) {
|
||||
errno = ENOMEM;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
extern "C" void free(void *ptr) {
|
||||
/* We require that an allocator region exists. */
|
||||
if (::ams::init::g_malloc_region_size == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ptr != nullptr) {
|
||||
::ams::util::GetReference(::ams::init::g_malloc_allocator).Free(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void *calloc(size_t num, size_t size) {
|
||||
/* We require that an allocator region exists. */
|
||||
if (::ams::init::g_malloc_region_size == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Allocate the total needed space. */
|
||||
const size_t total = num * size;
|
||||
void *ptr = std::malloc(total);
|
||||
|
||||
/* Zero the memory if needed. */
|
||||
if (ptr != nullptr) {
|
||||
std::memset(ptr, 0, total);
|
||||
} else {
|
||||
errno = ENOMEM;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
extern "C" void *realloc(void *ptr, size_t new_size) {
|
||||
/* We require that an allocator region exists. */
|
||||
if (::ams::init::g_malloc_region_size == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Try to reallocate. */
|
||||
void *r = ::ams::util::GetReference(::ams::init::g_malloc_allocator).Reallocate(ptr, new_size);
|
||||
if (r == nullptr) {
|
||||
errno = ENOMEM;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
extern "C" void *aligned_alloc(size_t align, size_t size) {
|
||||
/* We require that an allocator region exists. */
|
||||
if (::ams::init::g_malloc_region_size == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Try to allocate. */
|
||||
void *ptr = ::ams::util::GetReference(::ams::init::g_malloc_allocator).Allocate(size, align);
|
||||
if (ptr == nullptr) {
|
||||
errno = ENOMEM;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
extern "C" size_t malloc_usable_size(void *ptr) {
|
||||
/* We require that an allocator region exists. */
|
||||
if (::ams::init::g_malloc_region_size == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Try to get the usable size. */
|
||||
if (ptr == nullptr) {
|
||||
errno = ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ::ams::util::GetReference(::ams::init::g_malloc_allocator).GetSizeOf(ptr);
|
||||
}
|
48
libraries/libstratosphere/source/init/init_operator_new.cpp
Normal file
48
libraries/libstratosphere/source/init/init_operator_new.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 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>
|
||||
|
||||
WEAK_SYMBOL void *operator new(size_t size) {
|
||||
return std::malloc(size);
|
||||
}
|
||||
|
||||
WEAK_SYMBOL void *operator new(size_t size, const std::nothrow_t &) {
|
||||
return std::malloc(size);
|
||||
}
|
||||
|
||||
WEAK_SYMBOL void operator delete(void *p) {
|
||||
return std::free(p);
|
||||
}
|
||||
|
||||
WEAK_SYMBOL void operator delete(void *p, size_t) {
|
||||
return std::free(p);
|
||||
}
|
||||
|
||||
WEAK_SYMBOL void *operator new[](size_t size) {
|
||||
return std::malloc(size);
|
||||
}
|
||||
|
||||
WEAK_SYMBOL void *operator new[](size_t size, const std::nothrow_t &) {
|
||||
return std::malloc(size);
|
||||
}
|
||||
|
||||
WEAK_SYMBOL void operator delete[](void *p) {
|
||||
return std::free(p);
|
||||
}
|
||||
|
||||
WEAK_SYMBOL void operator delete[](void *p, size_t) {
|
||||
return std::free(p);
|
||||
}
|
34
libraries/libstratosphere/source/init/init_system_module.cpp
Normal file
34
libraries/libstratosphere/source/init/init_system_module.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 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 ams::init {
|
||||
|
||||
WEAK_SYMBOL void InitializeSystemModule() {
|
||||
/* TODO: What should we do here, if anything? */
|
||||
/* Nintendo does nndiagStartup(); nn::diag::InitializeSystemProcessAbortObserver(); */
|
||||
}
|
||||
|
||||
WEAK_SYMBOL void FinalizeSystemModule() {
|
||||
/* Do nothing by default. */
|
||||
}
|
||||
|
||||
WEAK_SYMBOL void Startup() {
|
||||
/* TODO: What should we do here, if anything? */
|
||||
/* Nintendo determines heap size and does init::InitializeAllocator, as relevant. */
|
||||
}
|
||||
|
||||
}
|
@ -103,14 +103,15 @@ namespace ams::lm::srv {
|
||||
}
|
||||
|
||||
void FlushThreadFunction(void *) {
|
||||
/* Disable abort. */
|
||||
/* Initialize fs. */
|
||||
fs::InitializeWithMultiSessionForSystem();
|
||||
fs::SetEnabledAutoAbort(false);
|
||||
|
||||
/* Create fs heap. */
|
||||
g_fs_heap_handle = lmem::CreateExpHeap(g_fs_heap, sizeof(g_fs_heap), lmem::CreateOption_None);
|
||||
AMS_ABORT_UNLESS(g_fs_heap_handle != nullptr);
|
||||
|
||||
/* Set fs allocation functions. */
|
||||
/* Set fs allocator functions. */
|
||||
fs::SetAllocator(AllocateForFs, DeallocateForFs);
|
||||
|
||||
/* Create SD card detection event notifier. */
|
||||
|
@ -353,7 +353,7 @@ namespace ams::mem::impl::heap {
|
||||
|
||||
std::scoped_lock lk(this->lock);
|
||||
if (Span *span = GetSpanFromPointer(std::addressof(this->span_table), ptr); span != nullptr && !span->page_class) {
|
||||
*out = (span->aux.large.color[0] << 0) | (span->aux.large.color[1] << 0) | (span->aux.large.color[2] << 16);
|
||||
*out = (span->aux.large.color[0] << 0) | (span->aux.large.color[1] << 8) | (span->aux.large.color[2] << 16);
|
||||
return 0;
|
||||
} else {
|
||||
return EINVAL;
|
||||
@ -387,7 +387,7 @@ namespace ams::mem::impl::heap {
|
||||
errno_t GetName(const void *ptr, char *dst, size_t dst_size) {
|
||||
std::scoped_lock lk(this->lock);
|
||||
if (Span *span = GetSpanFromPointer(std::addressof(this->span_table), ptr); span != nullptr && !span->page_class) {
|
||||
strlcpy(dst, span->aux.large.name, dst_size);
|
||||
util::Strlcpy(dst, span->aux.large.name, dst_size);
|
||||
return 0;
|
||||
} else {
|
||||
return EINVAL;
|
||||
@ -397,7 +397,7 @@ namespace ams::mem::impl::heap {
|
||||
errno_t SetName(const void *ptr, const char *name) {
|
||||
std::scoped_lock lk(this->lock);
|
||||
if (Span *span = GetSpanFromPointer(std::addressof(this->span_table), ptr); span != nullptr && !span->page_class) {
|
||||
strlcpy(span->aux.large.name, name, sizeof(span->aux.large.name));
|
||||
util::Strlcpy(span->aux.large.name, name, sizeof(span->aux.large.name));
|
||||
return 0;
|
||||
} else {
|
||||
return EINVAL;
|
||||
|
51
libraries/libstratosphere/source/os/os_argument.cpp
Normal file
51
libraries/libstratosphere/source/os/os_argument.cpp
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 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 ams::os {
|
||||
|
||||
namespace {
|
||||
|
||||
struct CommandLineParameter {
|
||||
int argc;
|
||||
char **argv;
|
||||
};
|
||||
|
||||
constinit const char *g_command_line_parameter_argv[2] = { "", nullptr };
|
||||
constinit CommandLineParameter g_command_line_parameter = {
|
||||
1,
|
||||
const_cast<char **>(g_command_line_parameter_argv),
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void SetHostArgc(int argc) {
|
||||
g_command_line_parameter.argc = argc;
|
||||
}
|
||||
|
||||
void SetHostArgv(char **argv) {
|
||||
g_command_line_parameter.argv = argv;
|
||||
}
|
||||
|
||||
int GetHostArgc() {
|
||||
return g_command_line_parameter.argc;
|
||||
}
|
||||
|
||||
char **GetHostArgv() {
|
||||
return g_command_line_parameter.argv;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright (c) 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>
|
||||
#include "impl/os_resource_manager.hpp"
|
||||
|
||||
extern "C" { extern u8 __argdata__[]; }
|
||||
|
||||
namespace ams::os {
|
||||
|
||||
namespace {
|
||||
|
||||
class MemoryArranger {
|
||||
private:
|
||||
uintptr_t m_address;
|
||||
public:
|
||||
constexpr MemoryArranger(uintptr_t address) : m_address(address) { /* ... */ }
|
||||
|
||||
template<typename T>
|
||||
T *Arrange() {
|
||||
this->Align(alignof(T));
|
||||
return static_cast<T *>(this->Arrange(sizeof(T)));
|
||||
}
|
||||
|
||||
void *Arrange(size_t size) {
|
||||
const auto address = m_address;
|
||||
m_address += size;
|
||||
return reinterpret_cast<void *>(address);
|
||||
}
|
||||
|
||||
void Align(size_t align) {
|
||||
m_address = util::AlignUp(m_address, align);
|
||||
}
|
||||
|
||||
char *ArrangeCharArray(size_t size) {
|
||||
return reinterpret_cast<char *>(Arrange(size));
|
||||
}
|
||||
};
|
||||
|
||||
bool HasArguments(uintptr_t args_region) {
|
||||
/* Check that the arguments region is read-write. */
|
||||
svc::MemoryInfo mi;
|
||||
svc::PageInfo pi;
|
||||
|
||||
if (R_FAILED(svc::QueryMemory(std::addressof(mi), std::addressof(pi), args_region))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return mi.permission == svc::MemoryPermission_ReadWrite;
|
||||
}
|
||||
|
||||
const char *SkipSpace(const char *p, const char *end) {
|
||||
while (p < end && std::isspace(*p)) { ++p; }
|
||||
return p;
|
||||
}
|
||||
|
||||
const char *GetTokenEnd(const char *p, const char *end) {
|
||||
while (p < end && !std::isspace(*p)) { ++p; }
|
||||
return p;
|
||||
}
|
||||
|
||||
const char *GetQuotedTokenEnd(const char *p, const char *end) {
|
||||
while (p < end && *p != '"') { ++p; }
|
||||
return p;
|
||||
}
|
||||
|
||||
int MakeArgv(char **out_argv_buf, char *arg_buf, const char *cmd_line, size_t cmd_line_size, int arg_max) {
|
||||
/* Prepare to parse arguments. */
|
||||
auto idx = 0;
|
||||
auto src = cmd_line;
|
||||
auto dst = arg_buf;
|
||||
const auto end = src + cmd_line_size;
|
||||
|
||||
/* Parse all tokens. */
|
||||
while (true) {
|
||||
/* Advance past any spaces. */
|
||||
src = SkipSpace(src, end);
|
||||
if (src >= end) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check that we don't have too many arguments. */
|
||||
if (idx >= arg_max) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Find the start/end of the current argument token. */
|
||||
const char *arg_end;
|
||||
const char *src_next;
|
||||
if (*src == '"') {
|
||||
++src;
|
||||
arg_end = GetQuotedTokenEnd(src, end);
|
||||
src_next = arg_end + 1;
|
||||
} else {
|
||||
arg_end = GetTokenEnd(src, end);
|
||||
src_next = arg_end;
|
||||
}
|
||||
|
||||
/* Determine token size. */
|
||||
const auto arg_size = arg_end - src;
|
||||
|
||||
/* Set the argv pointer. */
|
||||
out_argv_buf[idx++] = dst;
|
||||
|
||||
/* Copy the argument. */
|
||||
std::memcpy(dst, src, arg_size);
|
||||
dst += arg_size;
|
||||
|
||||
/* Null-terminate the argument token. */
|
||||
*(dst++) = '\x00';
|
||||
|
||||
/* Advance to next token. */
|
||||
src = src_next;
|
||||
}
|
||||
|
||||
/* Null terminate the final token. */
|
||||
*(dst++) = '\x00';
|
||||
|
||||
/* Null terminate argv. */
|
||||
out_argv_buf[idx] = nullptr;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void SetHostArgc(int argc);
|
||||
void SetHostArgv(char **argv);
|
||||
|
||||
void InitializeForStratosphereInternal() {
|
||||
/* Initialize the global os resource manager. */
|
||||
os::impl::ResourceManagerHolder::InitializeResourceManagerInstance();
|
||||
|
||||
/* Setup host argc/argv as needed. */
|
||||
const uintptr_t args_region = reinterpret_cast<uintptr_t>(__argdata__);
|
||||
if (HasArguments(args_region)) {
|
||||
/* Create arguments memory arranger. */
|
||||
MemoryArranger arranger(args_region);
|
||||
|
||||
/* Arrange. */
|
||||
const auto &header = *arranger.Arrange<ldr::ProgramArguments>();
|
||||
const char *cmd_line = arranger.ArrangeCharArray(header.arguments_size);
|
||||
char *arg_buf = arranger.ArrangeCharArray(header.arguments_size + 2);
|
||||
char **argv_buf = arranger.Arrange<char *>();
|
||||
|
||||
/* Determine extents. */
|
||||
const auto arg_buf_size = reinterpret_cast<uintptr_t>(argv_buf) - args_region;
|
||||
const auto arg_max = (header.allocated_size - arg_buf_size) / sizeof(char *);
|
||||
|
||||
/* Make argv. */
|
||||
const auto arg_count = MakeArgv(argv_buf, arg_buf, cmd_line, header.arguments_size, arg_max);
|
||||
|
||||
/* Set host argc/argv. */
|
||||
os::SetHostArgc(arg_count);
|
||||
os::SetHostArgv(argv_buf);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -15,151 +15,66 @@
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
extern "C" {
|
||||
extern u32 __start__;
|
||||
|
||||
u32 __nx_applet_type = AppletType_None;
|
||||
u32 __nx_fs_num_sessions = 2;
|
||||
|
||||
#define INNER_HEAP_SIZE 0x0
|
||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||
|
||||
void __libnx_initheap(void);
|
||||
void __appInit(void);
|
||||
void __appExit(void);
|
||||
|
||||
void *__libnx_alloc(size_t size);
|
||||
void *__libnx_aligned_alloc(size_t alignment, size_t size);
|
||||
void __libnx_free(void *mem);
|
||||
}
|
||||
|
||||
using namespace ams;
|
||||
|
||||
#define AMS_LM_USE_FATAL_ERROR 1
|
||||
|
||||
#if AMS_LM_USE_FATAL_ERROR
|
||||
|
||||
extern "C" {
|
||||
|
||||
/* Exception handling. */
|
||||
alignas(16) u8 __nx_exception_stack[ams::os::MemoryPageSize];
|
||||
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx);
|
||||
|
||||
}
|
||||
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
|
||||
ams::CrashHandler(ctx);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void __libnx_initheap(void) {
|
||||
void* addr = nx_inner_heap;
|
||||
size_t size = nx_inner_heap_size;
|
||||
|
||||
/* Newlib */
|
||||
extern char* fake_heap_start;
|
||||
extern char* fake_heap_end;
|
||||
|
||||
fake_heap_start = (char*)addr;
|
||||
fake_heap_end = (char*)addr + size;
|
||||
}
|
||||
|
||||
void __appInit(void) {
|
||||
hos::InitializeForStratosphere();
|
||||
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
R_ABORT_UNLESS(::fsInitialize());
|
||||
R_ABORT_UNLESS(::setsysInitialize());
|
||||
R_ABORT_UNLESS(::pscmInitialize());
|
||||
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void __appExit(void) {
|
||||
fsExit();
|
||||
}
|
||||
|
||||
namespace ams {
|
||||
|
||||
void *Malloc(size_t) {
|
||||
AMS_ABORT("ams::Malloc was called");
|
||||
namespace lm::srv {
|
||||
|
||||
void StartLogServerProxy();
|
||||
void StopLogServerProxy();
|
||||
|
||||
void InitializeFlushThread();
|
||||
void FinalizeFlushThread();
|
||||
|
||||
void InitializeIpcServer();
|
||||
void LoopIpcServer();
|
||||
void FinalizeIpcServer();
|
||||
|
||||
}
|
||||
|
||||
void Free(void *) {
|
||||
AMS_ABORT("ams::Free was called");
|
||||
namespace init {
|
||||
|
||||
void InitializeSystemModule() {
|
||||
/* Initialize our connection to sm. */
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
/* Initialize services we need. */
|
||||
R_ABORT_UNLESS(::setsysInitialize());
|
||||
R_ABORT_UNLESS(::pscmInitialize());
|
||||
|
||||
/* Verify that we can sanely execute. */
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void FinalizeSystemModule() { /* ... */ }
|
||||
|
||||
void Startup() { /* ... */ }
|
||||
|
||||
}
|
||||
|
||||
void Main() {
|
||||
/* Check thread priority. */
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(LogManager, MainThread));
|
||||
|
||||
/* Set thread name. */
|
||||
os::ChangeThreadPriority(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_PRIORITY(lm, IpcServer));
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(lm, IpcServer));
|
||||
|
||||
/* Start log server proxy. */
|
||||
lm::srv::StartLogServerProxy();
|
||||
|
||||
/* Initialize flush thread. */
|
||||
lm::srv::InitializeFlushThread();
|
||||
|
||||
/* Process IPC server. */
|
||||
lm::srv::InitializeIpcServer();
|
||||
lm::srv::LoopIpcServer();
|
||||
lm::srv::FinalizeIpcServer();
|
||||
|
||||
/* Finalize flush thread. */
|
||||
lm::srv::FinalizeFlushThread();
|
||||
|
||||
/* Stop log server proxy. */
|
||||
lm::srv::StopLogServerProxy();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void *operator new(size_t) {
|
||||
AMS_ABORT("operator new(size_t) was called");
|
||||
}
|
||||
|
||||
void operator delete(void *) {
|
||||
AMS_ABORT("operator delete(void *) was called");
|
||||
}
|
||||
|
||||
void operator delete(void *, size_t) {
|
||||
AMS_ABORT("operator delete(void *, size_t) was called");
|
||||
}
|
||||
|
||||
void *__libnx_alloc(size_t) {
|
||||
AMS_ABORT("__libnx_alloc was called");
|
||||
}
|
||||
|
||||
void *__libnx_aligned_alloc(size_t, size_t) {
|
||||
AMS_ABORT("__libnx_aligned_alloc was called");
|
||||
}
|
||||
|
||||
void __libnx_free(void *) {
|
||||
AMS_ABORT("__libnx_free was called");
|
||||
}
|
||||
|
||||
namespace ams::lm::srv {
|
||||
|
||||
void StartLogServerProxy();
|
||||
void StopLogServerProxy();
|
||||
|
||||
void InitializeFlushThread();
|
||||
void FinalizeFlushThread();
|
||||
|
||||
void InitializeIpcServer();
|
||||
void LoopIpcServer();
|
||||
void FinalizeIpcServer();
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
AMS_UNUSED(argc, argv);
|
||||
|
||||
/* Check thread priority. */
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(LogManager, MainThread));
|
||||
|
||||
/* Set thread name. */
|
||||
os::ChangeThreadPriority(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_PRIORITY(lm, IpcServer));
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(lm, IpcServer));
|
||||
|
||||
/* Start log server proxy. */
|
||||
lm::srv::StartLogServerProxy();
|
||||
|
||||
/* Initialize flush thread. */
|
||||
lm::srv::InitializeFlushThread();
|
||||
|
||||
/* Process IPC server. */
|
||||
lm::srv::InitializeIpcServer();
|
||||
lm::srv::LoopIpcServer();
|
||||
lm::srv::FinalizeIpcServer();
|
||||
|
||||
/* Finalize flush thread. */
|
||||
lm::srv::FinalizeFlushThread();
|
||||
|
||||
/* Stop log server proxy. */
|
||||
lm::srv::StopLogServerProxy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -16,165 +16,78 @@
|
||||
#include <stratosphere.hpp>
|
||||
#include "tio_file_server.hpp"
|
||||
|
||||
extern "C" {
|
||||
extern u32 __start__;
|
||||
|
||||
u32 __nx_applet_type = AppletType_None;
|
||||
u32 __nx_fs_num_sessions = 1;
|
||||
|
||||
#define INNER_HEAP_SIZE 0x0
|
||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||
|
||||
void __libnx_initheap(void);
|
||||
void __appInit(void);
|
||||
void __appExit(void);
|
||||
|
||||
void *__libnx_alloc(size_t size);
|
||||
void *__libnx_aligned_alloc(size_t alignment, size_t size);
|
||||
void __libnx_free(void *mem);
|
||||
}
|
||||
|
||||
using namespace ams;
|
||||
|
||||
#define AMS_TIO_SERVER_USE_FATAL_ERROR 1
|
||||
|
||||
#if AMS_TIO_SERVER_USE_FATAL_ERROR
|
||||
|
||||
extern "C" {
|
||||
|
||||
/* Exception handling. */
|
||||
alignas(16) u8 __nx_exception_stack[ams::os::MemoryPageSize];
|
||||
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx);
|
||||
|
||||
}
|
||||
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
|
||||
ams::CrashHandler(ctx);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace ams::tio {
|
||||
|
||||
namespace {
|
||||
|
||||
alignas(0x40) constinit u8 g_fs_heap_buffer[64_KB];
|
||||
alignas(0x40) constinit u8 g_htcs_buffer[1_KB];
|
||||
lmem::HeapHandle g_fs_heap_handle;
|
||||
|
||||
void *AllocateForFs(size_t size) {
|
||||
return lmem::AllocateFromExpHeap(g_fs_heap_handle, size);
|
||||
}
|
||||
|
||||
void DeallocateForFs(void *p, size_t size) {
|
||||
AMS_UNUSED(size);
|
||||
|
||||
return lmem::FreeToExpHeap(g_fs_heap_handle, p);
|
||||
}
|
||||
|
||||
void InitializeFsHeap() {
|
||||
/* Setup fs allocator. */
|
||||
g_fs_heap_handle = lmem::CreateExpHeap(g_fs_heap_buffer, sizeof(g_fs_heap_buffer), lmem::CreateOption_ThreadSafe);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void __libnx_initheap(void) {
|
||||
void* addr = nx_inner_heap;
|
||||
size_t size = nx_inner_heap_size;
|
||||
|
||||
/* Newlib */
|
||||
extern char* fake_heap_start;
|
||||
extern char* fake_heap_end;
|
||||
|
||||
fake_heap_start = (char*)addr;
|
||||
fake_heap_end = (char*)addr + size;
|
||||
|
||||
ams::tio::InitializeFsHeap();
|
||||
}
|
||||
|
||||
void __appInit(void) {
|
||||
hos::InitializeForStratosphere();
|
||||
|
||||
/* Initialize FS heap. */
|
||||
fs::SetAllocator(tio::AllocateForFs, tio::DeallocateForFs);
|
||||
|
||||
/* Disable FS auto-abort. */
|
||||
fs::SetEnabledAutoAbort(false);
|
||||
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
R_ABORT_UNLESS(fsInitialize());
|
||||
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void __appExit(void) {
|
||||
fsExit();
|
||||
}
|
||||
|
||||
namespace ams {
|
||||
|
||||
void *Malloc(size_t) {
|
||||
AMS_ABORT("ams::Malloc was called");
|
||||
namespace tio {
|
||||
|
||||
namespace {
|
||||
|
||||
alignas(0x40) constinit u8 g_fs_heap_buffer[64_KB];
|
||||
alignas(0x40) constinit u8 g_htcs_buffer[1_KB];
|
||||
lmem::HeapHandle g_fs_heap_handle;
|
||||
|
||||
void *AllocateForFs(size_t size) {
|
||||
return lmem::AllocateFromExpHeap(g_fs_heap_handle, size);
|
||||
}
|
||||
|
||||
void DeallocateForFs(void *p, size_t size) {
|
||||
AMS_UNUSED(size);
|
||||
|
||||
return lmem::FreeToExpHeap(g_fs_heap_handle, p);
|
||||
}
|
||||
|
||||
void InitializeFsHeap() {
|
||||
/* Setup fs allocator. */
|
||||
g_fs_heap_handle = lmem::CreateExpHeap(g_fs_heap_buffer, sizeof(g_fs_heap_buffer), lmem::CreateOption_ThreadSafe);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Free(void *) {
|
||||
AMS_ABORT("ams::Free was called");
|
||||
namespace init {
|
||||
|
||||
void InitializeSystemModule() {
|
||||
/* Initialize heap. */
|
||||
tio::InitializeFsHeap();
|
||||
|
||||
/* Initialize our connection to sm. */
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
/* Initialize fs. */
|
||||
fs::InitializeForSystem();
|
||||
fs::SetAllocator(tio::AllocateForFs, tio::DeallocateForFs);
|
||||
fs::SetEnabledAutoAbort(false);
|
||||
|
||||
/* Verify that we can sanely execute. */
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void FinalizeSystemModule() { /* ... */ }
|
||||
|
||||
void Startup() { /* ... */ }
|
||||
|
||||
}
|
||||
|
||||
void Main() {
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(TioServer, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(TioServer, Main));
|
||||
|
||||
/* Initialize htcs. */
|
||||
constexpr auto HtcsSocketCountMax = 2;
|
||||
const size_t buffer_size = htcs::GetWorkingMemorySize(HtcsSocketCountMax);
|
||||
AMS_ABORT_UNLESS(sizeof(tio::g_htcs_buffer) >= buffer_size);
|
||||
htcs::InitializeForSystem(tio::g_htcs_buffer, buffer_size, HtcsSocketCountMax);
|
||||
|
||||
/* Initialize the file server. */
|
||||
tio::InitializeFileServer();
|
||||
|
||||
/* Start the file server. */
|
||||
tio::StartFileServer();
|
||||
|
||||
/* Wait for the file server to finish. */
|
||||
tio::WaitFileServer();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void *operator new(size_t) {
|
||||
AMS_ABORT("operator new(size_t) was called");
|
||||
}
|
||||
|
||||
void operator delete(void *) {
|
||||
AMS_ABORT("operator delete(void *) was called");
|
||||
}
|
||||
|
||||
void operator delete(void *, size_t) {
|
||||
AMS_ABORT("operator delete(void *, size_t) was called");
|
||||
}
|
||||
|
||||
void *__libnx_alloc(size_t) {
|
||||
AMS_ABORT("__libnx_alloc was called");
|
||||
}
|
||||
|
||||
void *__libnx_aligned_alloc(size_t, size_t) {
|
||||
AMS_ABORT("__libnx_aligned_alloc was called");
|
||||
}
|
||||
|
||||
void __libnx_free(void *) {
|
||||
AMS_ABORT("__libnx_free was called");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
AMS_UNUSED(argc, argv);
|
||||
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(TioServer, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(TioServer, Main));
|
||||
|
||||
/* Initialize htcs. */
|
||||
constexpr auto HtcsSocketCountMax = 2;
|
||||
const size_t buffer_size = htcs::GetWorkingMemorySize(HtcsSocketCountMax);
|
||||
AMS_ABORT_UNLESS(sizeof(tio::g_htcs_buffer) >= buffer_size);
|
||||
htcs::InitializeForSystem(tio::g_htcs_buffer, buffer_size, HtcsSocketCountMax);
|
||||
|
||||
/* Initialize the file server. */
|
||||
tio::InitializeFileServer();
|
||||
|
||||
/* Start the file server. */
|
||||
tio::StartFileServer();
|
||||
|
||||
/* Wait for the file server to finish. */
|
||||
tio::WaitFileServer();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -19,123 +19,76 @@
|
||||
#include "bpc_mitm/bpc_ams_power_utils.hpp"
|
||||
#include "sysupdater/sysupdater_fs_utils.hpp"
|
||||
|
||||
extern "C" {
|
||||
extern u32 __start__;
|
||||
|
||||
u32 __nx_applet_type = AppletType_None;
|
||||
u32 __nx_fs_num_sessions = 1;
|
||||
|
||||
#define INNER_HEAP_SIZE 0x1000000
|
||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||
|
||||
void __libnx_initheap(void);
|
||||
void __appInit(void);
|
||||
void __appExit(void);
|
||||
|
||||
/* Exception handling. */
|
||||
alignas(16) u8 __nx_exception_stack[ams::os::MemoryPageSize];
|
||||
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx);
|
||||
|
||||
void *__libnx_alloc(size_t size);
|
||||
void *__libnx_aligned_alloc(size_t alignment, size_t size);
|
||||
void __libnx_free(void *mem);
|
||||
}
|
||||
|
||||
namespace ams {
|
||||
|
||||
/* Override. */
|
||||
namespace {
|
||||
|
||||
/* TODO: we really shouldn't be using malloc just to avoid dealing with real allocator separation. */
|
||||
constexpr size_t MallocBufferSize = 16_MB;
|
||||
alignas(os::MemoryPageSize) constinit u8 g_malloc_buffer[MallocBufferSize];
|
||||
|
||||
}
|
||||
|
||||
namespace init {
|
||||
|
||||
void InitializeSystemModule() {
|
||||
/* Initialize our connection to sm. */
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
/* Initialize fs. */
|
||||
fs::InitializeForSystem();
|
||||
fs::SetEnabledAutoAbort(false);
|
||||
|
||||
/* Initialize other services. */
|
||||
R_ABORT_UNLESS(pmdmntInitialize());
|
||||
R_ABORT_UNLESS(pminfoInitialize());
|
||||
ncm::Initialize();
|
||||
spl::InitializeForFs();
|
||||
|
||||
/* Verify that we can sanely execute. */
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void FinalizeSystemModule() { /* ... */ }
|
||||
|
||||
void Startup() {
|
||||
/* Initialize the global malloc allocator. */
|
||||
init::InitializeAllocator(g_malloc_buffer, sizeof(g_malloc_buffer));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ExceptionHandler(FatalErrorContext *ctx) {
|
||||
/* We're bpc-mitm (or ams_mitm, anyway), so manually reboot to fatal error. */
|
||||
mitm::bpc::RebootForFatalError(ctx);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
using namespace ams;
|
||||
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
|
||||
ams::CrashHandler(ctx);
|
||||
}
|
||||
|
||||
void __libnx_initheap(void) {
|
||||
void* addr = nx_inner_heap;
|
||||
size_t size = nx_inner_heap_size;
|
||||
|
||||
/* Newlib */
|
||||
extern char* fake_heap_start;
|
||||
extern char* fake_heap_end;
|
||||
|
||||
fake_heap_start = (char*)addr;
|
||||
fake_heap_end = (char*)addr + size;
|
||||
}
|
||||
|
||||
void __appInit(void) {
|
||||
hos::InitializeForStratosphere();
|
||||
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
R_ABORT_UNLESS(fsInitialize());
|
||||
R_ABORT_UNLESS(pmdmntInitialize());
|
||||
R_ABORT_UNLESS(pminfoInitialize());
|
||||
ncm::Initialize();
|
||||
spl::InitializeForFs();
|
||||
|
||||
/* Disable auto-abort in fs operations. */
|
||||
fs::SetEnabledAutoAbort(false);
|
||||
|
||||
/* Initialize fssystem library. */
|
||||
fssystem::InitializeForFileSystemProxy();
|
||||
|
||||
/* Configure ncm to use fssystem library to mount content from the sd card. */
|
||||
ncm::SetMountContentMetaFunction(mitm::sysupdater::MountSdCardContentMeta);
|
||||
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void __appExit(void) {
|
||||
/* Cleanup services. */
|
||||
spl::Finalize();
|
||||
ncm::Finalize();
|
||||
pminfoExit();
|
||||
pmdmntExit();
|
||||
fsExit();
|
||||
}
|
||||
|
||||
void *__libnx_alloc(size_t size) {
|
||||
AMS_UNUSED(size);
|
||||
AMS_ABORT("__libnx_alloc was called");
|
||||
}
|
||||
|
||||
void *__libnx_aligned_alloc(size_t alignment, size_t size) {
|
||||
AMS_UNUSED(alignment, size);
|
||||
AMS_ABORT("__libnx_aligned_alloc was called");
|
||||
}
|
||||
|
||||
void __libnx_free(void *mem) {
|
||||
AMS_UNUSED(mem);
|
||||
AMS_ABORT("__libnx_free was called");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
AMS_UNUSED(argc, argv);
|
||||
|
||||
/* Register "ams" port, use up its session. */
|
||||
{
|
||||
svc::Handle ams_port;
|
||||
R_ABORT_UNLESS(svc::ManageNamedPort(std::addressof(ams_port), "ams", 1));
|
||||
|
||||
svc::Handle ams_session;
|
||||
R_ABORT_UNLESS(svc::ConnectToNamedPort(std::addressof(ams_session), "ams"));
|
||||
void NORETURN Exit(int rc) {
|
||||
AMS_UNUSED(rc);
|
||||
AMS_ABORT("Exit called by immortal process");
|
||||
}
|
||||
|
||||
/* Launch all mitm modules in sequence. */
|
||||
mitm::LaunchAllModules();
|
||||
void Main() {
|
||||
/* Register "ams" port, use up its session. */
|
||||
{
|
||||
svc::Handle ams_port;
|
||||
R_ABORT_UNLESS(svc::ManageNamedPort(std::addressof(ams_port), "ams", 1));
|
||||
|
||||
/* Wait for all mitm modules to end. */
|
||||
mitm::WaitAllModules();
|
||||
svc::Handle ams_session;
|
||||
R_ABORT_UNLESS(svc::ConnectToNamedPort(std::addressof(ams_session), "ams"));
|
||||
}
|
||||
|
||||
/* Initialize fssystem library. */
|
||||
fssystem::InitializeForFileSystemProxy();
|
||||
|
||||
/* Configure ncm to use fssystem library to mount content from the sd card. */
|
||||
ncm::SetMountContentMetaFunction(mitm::sysupdater::MountSdCardContentMeta);
|
||||
|
||||
/* Launch all mitm modules in sequence. */
|
||||
mitm::LaunchAllModules();
|
||||
|
||||
/* Wait for all mitm modules to end. */
|
||||
mitm::WaitAllModules();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -324,11 +324,11 @@ namespace ams::mitm::fs {
|
||||
AMS_ABORT_UNLESS(num_child_dirs >= 0);
|
||||
|
||||
{
|
||||
BuildDirectoryContext **child_dirs = reinterpret_cast<BuildDirectoryContext **>(std::malloc(sizeof(BuildDirectoryContext *) * num_child_dirs));
|
||||
BuildDirectoryContext **child_dirs = num_child_dirs != 0 ? reinterpret_cast<BuildDirectoryContext **>(std::malloc(sizeof(BuildDirectoryContext *) * num_child_dirs)) : nullptr;
|
||||
AMS_ABORT_UNLESS(num_child_dirs == 0 || child_dirs != nullptr);
|
||||
ON_SCOPE_EXIT { std::free(child_dirs); };
|
||||
AMS_ABORT_UNLESS(child_dirs != nullptr);
|
||||
s64 cur_child_dir_ind = 0;
|
||||
|
||||
s64 cur_child_dir_ind = 0;
|
||||
{
|
||||
OpenFileSystemRomfsDirectory(&dir, this->program_id, parent, OpenDirectoryMode_All, fs);
|
||||
ON_SCOPE_EXIT { fsDirClose(&dir); };
|
||||
@ -342,6 +342,8 @@ namespace ams::mitm::fs {
|
||||
|
||||
AMS_ABORT_UNLESS(this->dir_entry.type == FsDirEntryType_Dir || this->dir_entry.type == FsDirEntryType_File);
|
||||
if (this->dir_entry.type == FsDirEntryType_Dir) {
|
||||
AMS_ABORT_UNLESS(child_dirs != nullptr);
|
||||
|
||||
BuildDirectoryContext *real_child = nullptr;
|
||||
this->AddDirectory(&real_child, parent, std::make_unique<BuildDirectoryContext>(this->dir_entry.name, strlen(this->dir_entry.name)));
|
||||
AMS_ABORT_UNLESS(real_child != nullptr);
|
||||
|
@ -24,258 +24,190 @@
|
||||
#include "boot_pinmux_initial_configuration.hpp"
|
||||
#include "boot_repair_boot_images.hpp"
|
||||
#include "boot_splash_screen.hpp"
|
||||
|
||||
#include "boot_power_utils.hpp"
|
||||
|
||||
using namespace ams;
|
||||
|
||||
extern "C" {
|
||||
extern u32 __start__;
|
||||
|
||||
u32 __nx_applet_type = AppletType_None;
|
||||
u32 __nx_fs_num_sessions = 1;
|
||||
|
||||
/* TODO: Evaluate to what extent this can be reduced further. */
|
||||
#define INNER_HEAP_SIZE 0x0
|
||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||
|
||||
void __libnx_initheap(void);
|
||||
void __appInit(void);
|
||||
void __appExit(void);
|
||||
|
||||
/* Exception handling. */
|
||||
alignas(16) u8 __nx_exception_stack[ams::os::MemoryPageSize];
|
||||
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx);
|
||||
|
||||
void *__libnx_alloc(size_t size);
|
||||
void *__libnx_aligned_alloc(size_t alignment, size_t size);
|
||||
void __libnx_free(void *mem);
|
||||
}
|
||||
|
||||
namespace ams {
|
||||
|
||||
namespace boot {
|
||||
|
||||
namespace {
|
||||
|
||||
constinit u8 g_exp_heap_memory[20_KB];
|
||||
constinit u8 g_unit_heap_memory[5_KB];
|
||||
constinit lmem::HeapHandle g_exp_heap_handle;
|
||||
constinit lmem::HeapHandle g_unit_heap_handle;
|
||||
|
||||
constinit sf::ExpHeapMemoryResource g_exp_heap_memory_resource;
|
||||
constinit sf::UnitHeapMemoryResource g_unit_heap_memory_resource;
|
||||
|
||||
void *Allocate(size_t size) {
|
||||
void *mem = lmem::AllocateFromExpHeap(g_exp_heap_handle, size);
|
||||
return mem;
|
||||
}
|
||||
|
||||
void Deallocate(void *p, size_t size) {
|
||||
AMS_UNUSED(size);
|
||||
lmem::FreeToExpHeap(g_exp_heap_handle, p);
|
||||
}
|
||||
|
||||
void InitializeHeaps() {
|
||||
/* Create the heaps. */
|
||||
g_exp_heap_handle = lmem::CreateExpHeap(g_exp_heap_memory, sizeof(g_exp_heap_memory), lmem::CreateOption_ThreadSafe);
|
||||
g_unit_heap_handle = lmem::CreateUnitHeap(g_unit_heap_memory, sizeof(g_unit_heap_memory), sizeof(ddsf::DeviceCodeEntryHolder), lmem::CreateOption_ThreadSafe);
|
||||
|
||||
/* Attach the memory resources. */
|
||||
g_exp_heap_memory_resource.Attach(g_exp_heap_handle);
|
||||
g_unit_heap_memory_resource.Attach(g_unit_heap_handle);
|
||||
|
||||
/* Register with ddsf. */
|
||||
ddsf::SetMemoryResource(std::addressof(g_exp_heap_memory_resource));
|
||||
ddsf::SetDeviceCodeEntryHolderMemoryResource(std::addressof(g_unit_heap_memory_resource));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace init {
|
||||
|
||||
void InitializeSystemModule() {
|
||||
/* Initialize heaps. */
|
||||
boot::InitializeHeaps();
|
||||
|
||||
/* Set fs allocator. */
|
||||
fs::SetAllocator(boot::Allocate, boot::Deallocate);
|
||||
|
||||
/* Initialize services we need. */
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
fs::InitializeForSystem();
|
||||
spl::Initialize();
|
||||
R_ABORT_UNLESS(pmshellInitialize());
|
||||
|
||||
/* Verify that we can sanely execute. */
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void FinalizeSystemModule() { /* ... */ }
|
||||
|
||||
void Startup() { /* ... */ }
|
||||
|
||||
}
|
||||
|
||||
void ExceptionHandler(FatalErrorContext *ctx) {
|
||||
/* We're boot sysmodule, so manually reboot to fatal error. */
|
||||
boot::RebootForFatalError(ctx);
|
||||
}
|
||||
|
||||
}
|
||||
void Main() {
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(boot, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(boot, Main));
|
||||
|
||||
using namespace ams;
|
||||
/* Perform atmosphere-specific init. */
|
||||
ams::InitializeForBoot();
|
||||
|
||||
namespace {
|
||||
/* Set the reboot payload with ams.mitm. */
|
||||
boot::SetInitialRebootPayload();
|
||||
|
||||
constinit u8 g_exp_heap_memory[20_KB];
|
||||
constinit u8 g_unit_heap_memory[5_KB];
|
||||
constinit lmem::HeapHandle g_exp_heap_handle;
|
||||
constinit lmem::HeapHandle g_unit_heap_handle;
|
||||
/* Change voltage from 3.3v to 1.8v for select devices. */
|
||||
boot::ChangeGpioVoltageTo1_8v();
|
||||
|
||||
constinit sf::ExpHeapMemoryResource g_exp_heap_memory_resource;
|
||||
constinit sf::UnitHeapMemoryResource g_unit_heap_memory_resource;
|
||||
/* Setup gpio. */
|
||||
gpio::driver::SetInitialGpioConfig();
|
||||
|
||||
void *Allocate(size_t size) {
|
||||
void *mem = lmem::AllocateFromExpHeap(g_exp_heap_handle, size);
|
||||
return mem;
|
||||
}
|
||||
/* Initialize the gpio server library. */
|
||||
boot::InitializeGpioDriverLibrary();
|
||||
|
||||
void Deallocate(void *p, size_t size) {
|
||||
AMS_UNUSED(size);
|
||||
lmem::FreeToExpHeap(g_exp_heap_handle, p);
|
||||
}
|
||||
/* Initialize the i2c server library. */
|
||||
boot::InitializeI2cDriverLibrary();
|
||||
|
||||
void InitializeHeaps() {
|
||||
/* Create the heaps. */
|
||||
g_exp_heap_handle = lmem::CreateExpHeap(g_exp_heap_memory, sizeof(g_exp_heap_memory), lmem::CreateOption_ThreadSafe);
|
||||
g_unit_heap_handle = lmem::CreateUnitHeap(g_unit_heap_memory, sizeof(g_unit_heap_memory), sizeof(ddsf::DeviceCodeEntryHolder), lmem::CreateOption_ThreadSafe);
|
||||
/* Get the hardware type. */
|
||||
const auto hw_type = spl::GetHardwareType();
|
||||
|
||||
/* Attach the memory resources. */
|
||||
g_exp_heap_memory_resource.Attach(g_exp_heap_handle);
|
||||
g_unit_heap_memory_resource.Attach(g_unit_heap_handle);
|
||||
/* Initialize the power control library without interrupt event handling. */
|
||||
if (hw_type != spl::HardwareType::Calcio) {
|
||||
powctl::Initialize(false);
|
||||
}
|
||||
|
||||
/* Register with ddsf. */
|
||||
ddsf::SetMemoryResource(std::addressof(g_exp_heap_memory_resource));
|
||||
ddsf::SetDeviceCodeEntryHolderMemoryResource(std::addressof(g_unit_heap_memory_resource));
|
||||
/* Check USB PLL/UTMIP clock. */
|
||||
boot::CheckClock();
|
||||
|
||||
/* Talk to PMIC/RTC, set boot reason with SPL. */
|
||||
boot::DetectBootReason();
|
||||
|
||||
/* Display the splash screen and check the battery charge. */
|
||||
if (hw_type != spl::HardwareType::Calcio) {
|
||||
/* Display splash screen for two seconds. */
|
||||
boot::ShowSplashScreen();
|
||||
|
||||
/* Check that the battery has enough to boot. */
|
||||
boot::CheckBatteryCharge();
|
||||
}
|
||||
|
||||
/* Configure pinmux + drive pads. */
|
||||
boot::SetInitialPinmuxConfiguration();
|
||||
|
||||
/* Configure the PMC wake pin settings. */
|
||||
gpio::driver::SetInitialWakePinConfig();
|
||||
|
||||
/* Configure output clock. */
|
||||
if (hw_type != spl::HardwareType::Calcio) {
|
||||
boot::SetInitialClockConfiguration();
|
||||
}
|
||||
|
||||
/* Set Fan enable config (Copper only). */
|
||||
boot::SetFanPowerEnabled();
|
||||
|
||||
/* Repair boot partitions in NAND if needed. */
|
||||
boot::CheckAndRepairBootImages();
|
||||
|
||||
/* Finalize the power control library. */
|
||||
if (hw_type != spl::HardwareType::Calcio) {
|
||||
powctl::Finalize();
|
||||
}
|
||||
|
||||
/* Finalize the i2c server library. */
|
||||
boot::FinalizeI2cDriverLibrary();
|
||||
|
||||
/* Finalize the gpio server library. */
|
||||
boot::FinalizeGpioDriverLibrary();
|
||||
|
||||
/* Tell PM to start boot2. */
|
||||
R_ABORT_UNLESS(pmshellNotifyBootFinished());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
|
||||
ams::CrashHandler(ctx);
|
||||
}
|
||||
|
||||
void __libnx_initheap(void) {
|
||||
void* addr = nx_inner_heap;
|
||||
size_t size = nx_inner_heap_size;
|
||||
|
||||
/* Newlib */
|
||||
extern char* fake_heap_start;
|
||||
extern char* fake_heap_end;
|
||||
|
||||
fake_heap_start = (char*)addr;
|
||||
fake_heap_end = (char*)addr + size;
|
||||
|
||||
InitializeHeaps();
|
||||
}
|
||||
|
||||
void __appInit(void) {
|
||||
hos::InitializeForStratosphere();
|
||||
|
||||
fs::SetAllocator(Allocate, Deallocate);
|
||||
|
||||
/* Initialize services we need. */
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
R_ABORT_UNLESS(fsInitialize());
|
||||
spl::Initialize();
|
||||
R_ABORT_UNLESS(pmshellInitialize());
|
||||
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void __appExit(void) {
|
||||
/* Cleanup services. */
|
||||
pmshellExit();
|
||||
spl::Finalize();
|
||||
fsExit();
|
||||
}
|
||||
|
||||
namespace ams {
|
||||
|
||||
void *Malloc(size_t) {
|
||||
AMS_ABORT("ams::Malloc was called");
|
||||
}
|
||||
|
||||
void Free(void *) {
|
||||
AMS_ABORT("ams::Free was called");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void *__libnx_alloc(size_t) {
|
||||
AMS_ABORT("__libnx_alloc was called");
|
||||
}
|
||||
|
||||
void *__libnx_aligned_alloc(size_t, size_t) {
|
||||
AMS_ABORT("__libnx_aligned_alloc was called");
|
||||
}
|
||||
|
||||
void __libnx_free(void *) {
|
||||
AMS_ABORT("__libnx_free was called");
|
||||
}
|
||||
|
||||
/* Override operator new. */
|
||||
void *operator new(size_t size) {
|
||||
return Allocate(size);
|
||||
return ams::boot::Allocate(size);
|
||||
}
|
||||
|
||||
void *operator new(size_t size, const std::nothrow_t &) {
|
||||
return Allocate(size);
|
||||
return ams::boot::Allocate(size);
|
||||
}
|
||||
|
||||
void operator delete(void *p) {
|
||||
return Deallocate(p, 0);
|
||||
return ams::boot::Deallocate(p, 0);
|
||||
}
|
||||
|
||||
void operator delete(void *p, size_t size) {
|
||||
return Deallocate(p, size);
|
||||
return ams::boot::Deallocate(p, size);
|
||||
}
|
||||
|
||||
void *operator new[](size_t size) {
|
||||
return Allocate(size);
|
||||
return ams::boot::Allocate(size);
|
||||
}
|
||||
|
||||
void *operator new[](size_t size, const std::nothrow_t &) {
|
||||
return Allocate(size);
|
||||
return ams::boot::Allocate(size);
|
||||
}
|
||||
|
||||
void operator delete[](void *p) {
|
||||
return Deallocate(p, 0);
|
||||
return ams::boot::Deallocate(p, 0);
|
||||
}
|
||||
|
||||
void operator delete[](void *p, size_t size) {
|
||||
return Deallocate(p, size);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
AMS_UNUSED(argc, argv);
|
||||
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(boot, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(boot, Main));
|
||||
|
||||
/* Perform atmosphere-specific init. */
|
||||
ams::InitializeForBoot();
|
||||
|
||||
/* Set the reboot payload with ams.mitm. */
|
||||
boot::SetInitialRebootPayload();
|
||||
|
||||
/* Change voltage from 3.3v to 1.8v for select devices. */
|
||||
boot::ChangeGpioVoltageTo1_8v();
|
||||
|
||||
/* Setup gpio. */
|
||||
gpio::driver::SetInitialGpioConfig();
|
||||
|
||||
/* Initialize the gpio server library. */
|
||||
boot::InitializeGpioDriverLibrary();
|
||||
|
||||
/* Initialize the i2c server library. */
|
||||
boot::InitializeI2cDriverLibrary();
|
||||
|
||||
/* Get the hardware type. */
|
||||
const auto hw_type = spl::GetHardwareType();
|
||||
|
||||
/* Initialize the power control library without interrupt event handling. */
|
||||
if (hw_type != spl::HardwareType::Calcio) {
|
||||
powctl::Initialize(false);
|
||||
}
|
||||
|
||||
/* Check USB PLL/UTMIP clock. */
|
||||
boot::CheckClock();
|
||||
|
||||
/* Talk to PMIC/RTC, set boot reason with SPL. */
|
||||
boot::DetectBootReason();
|
||||
|
||||
/* Display the splash screen and check the battery charge. */
|
||||
if (hw_type != spl::HardwareType::Calcio) {
|
||||
/* Display splash screen for two seconds. */
|
||||
boot::ShowSplashScreen();
|
||||
|
||||
/* Check that the battery has enough to boot. */
|
||||
boot::CheckBatteryCharge();
|
||||
}
|
||||
|
||||
/* Configure pinmux + drive pads. */
|
||||
boot::SetInitialPinmuxConfiguration();
|
||||
|
||||
/* Configure the PMC wake pin settings. */
|
||||
gpio::driver::SetInitialWakePinConfig();
|
||||
|
||||
/* Configure output clock. */
|
||||
if (hw_type != spl::HardwareType::Calcio) {
|
||||
boot::SetInitialClockConfiguration();
|
||||
}
|
||||
|
||||
/* Set Fan enable config (Copper only). */
|
||||
boot::SetFanPowerEnabled();
|
||||
|
||||
/* Repair boot partitions in NAND if needed. */
|
||||
boot::CheckAndRepairBootImages();
|
||||
|
||||
/* Finalize the power control library. */
|
||||
if (hw_type != spl::HardwareType::Calcio) {
|
||||
powctl::Finalize();
|
||||
}
|
||||
|
||||
/* Finalize the i2c server library. */
|
||||
boot::FinalizeI2cDriverLibrary();
|
||||
|
||||
/* Finalize the gpio server library. */
|
||||
boot::FinalizeGpioDriverLibrary();
|
||||
|
||||
/* Tell PM to start boot2. */
|
||||
R_ABORT_UNLESS(pmshellNotifyBootFinished());
|
||||
|
||||
return 0;
|
||||
return ams::boot::Deallocate(p, size);
|
||||
}
|
||||
|
@ -15,148 +15,73 @@
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
extern "C" {
|
||||
extern u32 __start__;
|
||||
|
||||
u32 __nx_applet_type = AppletType_None;
|
||||
u32 __nx_fs_num_sessions = 1;
|
||||
|
||||
#define INNER_HEAP_SIZE 0x0
|
||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||
|
||||
void __libnx_initheap(void);
|
||||
void __appInit(void);
|
||||
void __appExit(void);
|
||||
|
||||
/* Exception handling. */
|
||||
alignas(16) u8 __nx_exception_stack[ams::os::MemoryPageSize];
|
||||
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx);
|
||||
|
||||
void *__libnx_alloc(size_t size);
|
||||
void *__libnx_aligned_alloc(size_t alignment, size_t size);
|
||||
void __libnx_free(void *mem);
|
||||
}
|
||||
|
||||
using namespace ams;
|
||||
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
|
||||
ams::CrashHandler(ctx);
|
||||
}
|
||||
|
||||
void __libnx_initheap(void) {
|
||||
void* addr = nx_inner_heap;
|
||||
size_t size = nx_inner_heap_size;
|
||||
|
||||
/* Newlib */
|
||||
extern char* fake_heap_start;
|
||||
extern char* fake_heap_end;
|
||||
|
||||
fake_heap_start = (char*)addr;
|
||||
fake_heap_end = (char*)addr + size;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
constinit u8 g_fs_heap_memory[2_KB];
|
||||
lmem::HeapHandle g_fs_heap_handle;
|
||||
|
||||
void *AllocateForFs(size_t size) {
|
||||
return lmem::AllocateFromExpHeap(g_fs_heap_handle, size);
|
||||
}
|
||||
|
||||
void DeallocateForFs(void *p, size_t size) {
|
||||
AMS_UNUSED(size);
|
||||
return lmem::FreeToExpHeap(g_fs_heap_handle, p);
|
||||
}
|
||||
|
||||
void InitializeFsHeap() {
|
||||
g_fs_heap_handle = lmem::CreateExpHeap(g_fs_heap_memory, sizeof(g_fs_heap_memory), lmem::CreateOption_None);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void __appInit(void) {
|
||||
hos::InitializeForStratosphere();
|
||||
|
||||
InitializeFsHeap();
|
||||
fs::SetAllocator(AllocateForFs, DeallocateForFs);
|
||||
|
||||
/* Initialize services we need. */
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
R_ABORT_UNLESS(fsInitialize());
|
||||
R_ABORT_UNLESS(pmbmInitialize());
|
||||
R_ABORT_UNLESS(pminfoInitialize());
|
||||
R_ABORT_UNLESS(pmshellInitialize());
|
||||
R_ABORT_UNLESS(setsysInitialize());
|
||||
gpio::Initialize();
|
||||
|
||||
/* Mount the SD card. */
|
||||
R_ABORT_UNLESS(fs::MountSdCard("sdmc"));
|
||||
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void __appExit(void) {
|
||||
fs::Unmount("sdmc");
|
||||
gpio::Finalize();
|
||||
setsysExit();
|
||||
pmshellExit();
|
||||
pminfoExit();
|
||||
pmbmExit();
|
||||
fsExit();
|
||||
}
|
||||
|
||||
namespace ams {
|
||||
|
||||
void *Malloc(size_t) {
|
||||
AMS_ABORT("ams::Malloc was called");
|
||||
namespace boot2 {
|
||||
|
||||
namespace {
|
||||
|
||||
constinit u8 g_fs_heap_memory[2_KB];
|
||||
constinit lmem::HeapHandle g_fs_heap_handle;
|
||||
|
||||
void *AllocateForFs(size_t size) {
|
||||
return lmem::AllocateFromExpHeap(g_fs_heap_handle, size);
|
||||
}
|
||||
|
||||
void DeallocateForFs(void *p, size_t size) {
|
||||
AMS_UNUSED(size);
|
||||
return lmem::FreeToExpHeap(g_fs_heap_handle, p);
|
||||
}
|
||||
|
||||
void InitializeFsHeap() {
|
||||
g_fs_heap_handle = lmem::CreateExpHeap(g_fs_heap_memory, sizeof(g_fs_heap_memory), lmem::CreateOption_None);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Free(void *) {
|
||||
AMS_ABORT("ams::Free was called");
|
||||
namespace init {
|
||||
|
||||
void InitializeSystemModule() {
|
||||
/* Initialize heap. */
|
||||
boot2::InitializeFsHeap();
|
||||
|
||||
/* Initialize our connection to sm. */
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
/* Initialize fs. */
|
||||
fs::InitializeForSystem();
|
||||
fs::SetAllocator(boot2::AllocateForFs, boot2::DeallocateForFs);
|
||||
fs::SetEnabledAutoAbort(false);
|
||||
|
||||
/* Initialize other services we need. */
|
||||
R_ABORT_UNLESS(pmbmInitialize());
|
||||
R_ABORT_UNLESS(pminfoInitialize());
|
||||
R_ABORT_UNLESS(pmshellInitialize());
|
||||
R_ABORT_UNLESS(setsysInitialize());
|
||||
gpio::Initialize();
|
||||
|
||||
/* Mount the SD card. */
|
||||
R_ABORT_UNLESS(fs::MountSdCard("sdmc"));
|
||||
|
||||
/* Verify that we can sanely execute. */
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void FinalizeSystemModule() { /* ... */ }
|
||||
|
||||
void Startup() { /* ... */ }
|
||||
|
||||
}
|
||||
|
||||
void Main() {
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(boot2, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(boot2, Main));
|
||||
|
||||
/* Launch all programs off of SYSTEM/the SD. */
|
||||
boot2::LaunchPostSdCardBootPrograms();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void *operator new(size_t) {
|
||||
AMS_ABORT("operator new(size_t) was called");
|
||||
}
|
||||
|
||||
void operator delete(void *) {
|
||||
AMS_ABORT("operator delete(void *) was called");
|
||||
}
|
||||
|
||||
void operator delete(void *, size_t) {
|
||||
AMS_ABORT("operator delete(void *, size_t) was called");
|
||||
}
|
||||
|
||||
void *__libnx_alloc(size_t) {
|
||||
AMS_ABORT("__libnx_alloc was called");
|
||||
}
|
||||
|
||||
void *__libnx_aligned_alloc(size_t, size_t) {
|
||||
AMS_ABORT("__libnx_aligned_alloc was called");
|
||||
}
|
||||
|
||||
void __libnx_free(void *) {
|
||||
AMS_ABORT("__libnx_free was called");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
AMS_UNUSED(argc, argv);
|
||||
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(boot2, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(boot2, Main));
|
||||
|
||||
/* Launch all programs off of SYSTEM/the SD. */
|
||||
boot2::LaunchPostSdCardBootPrograms();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -17,198 +17,140 @@
|
||||
#include "creport_crash_report.hpp"
|
||||
#include "creport_utils.hpp"
|
||||
|
||||
|
||||
extern "C" {
|
||||
extern u32 __start__;
|
||||
|
||||
u32 __nx_applet_type = AppletType_None;
|
||||
u32 __nx_fs_num_sessions = 1;
|
||||
|
||||
#define INNER_HEAP_SIZE 0x0
|
||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||
|
||||
void __libnx_initheap(void);
|
||||
void __appInit(void);
|
||||
void __appExit(void);
|
||||
|
||||
/* Exception handling. */
|
||||
alignas(16) u8 __nx_exception_stack[ams::os::MemoryPageSize];
|
||||
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx);
|
||||
|
||||
void *__libnx_alloc(size_t size);
|
||||
void *__libnx_aligned_alloc(size_t alignment, size_t size);
|
||||
void __libnx_free(void *mem);
|
||||
}
|
||||
|
||||
using namespace ams;
|
||||
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
|
||||
ams::CrashHandler(ctx);
|
||||
}
|
||||
|
||||
void __libnx_initheap(void) {
|
||||
void* addr = nx_inner_heap;
|
||||
size_t size = nx_inner_heap_size;
|
||||
|
||||
/* Newlib */
|
||||
extern char* fake_heap_start;
|
||||
extern char* fake_heap_end;
|
||||
|
||||
fake_heap_start = (char*)addr;
|
||||
fake_heap_end = (char*)addr + size;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
constinit u8 g_fs_heap_memory[4_KB];
|
||||
lmem::HeapHandle g_fs_heap_handle;
|
||||
|
||||
void *AllocateForFs(size_t size) {
|
||||
return lmem::AllocateFromExpHeap(g_fs_heap_handle, size);
|
||||
}
|
||||
|
||||
void DeallocateForFs(void *p, size_t size) {
|
||||
AMS_UNUSED(size);
|
||||
return lmem::FreeToExpHeap(g_fs_heap_handle, p);
|
||||
}
|
||||
|
||||
void InitializeFsHeap() {
|
||||
g_fs_heap_handle = lmem::CreateExpHeap(g_fs_heap_memory, sizeof(g_fs_heap_memory), lmem::CreateOption_None);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void __appInit(void) {
|
||||
hos::InitializeForStratosphere();
|
||||
|
||||
InitializeFsHeap();
|
||||
fs::SetAllocator(AllocateForFs, DeallocateForFs);
|
||||
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
R_ABORT_UNLESS(fsInitialize());
|
||||
|
||||
R_ABORT_UNLESS(fs::MountSdCard("sdmc"));
|
||||
}
|
||||
|
||||
void __appExit(void) {
|
||||
/* Cleanup services. */
|
||||
fsExit();
|
||||
}
|
||||
|
||||
namespace ams {
|
||||
|
||||
void *Malloc(size_t) {
|
||||
AMS_ABORT("ams::Malloc was called");
|
||||
}
|
||||
namespace creport {
|
||||
|
||||
void Free(void *) {
|
||||
AMS_ABORT("ams::Free was called");
|
||||
}
|
||||
namespace {
|
||||
|
||||
}
|
||||
constinit u8 g_fs_heap_memory[4_KB];
|
||||
lmem::HeapHandle g_fs_heap_handle;
|
||||
|
||||
void *operator new(size_t) {
|
||||
AMS_ABORT("operator new(size_t) was called");
|
||||
}
|
||||
|
||||
void operator delete(void *) {
|
||||
AMS_ABORT("operator delete(void *) was called");
|
||||
}
|
||||
|
||||
void operator delete(void *, size_t) {
|
||||
AMS_ABORT("operator delete(void *, size_t) was called");
|
||||
}
|
||||
|
||||
void *__libnx_alloc(size_t) {
|
||||
AMS_ABORT("__libnx_alloc was called");
|
||||
}
|
||||
|
||||
void *__libnx_aligned_alloc(size_t, size_t) {
|
||||
AMS_ABORT("__libnx_aligned_alloc was called");
|
||||
}
|
||||
|
||||
void __libnx_free(void *) {
|
||||
AMS_ABORT("__libnx_free was called");
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
constinit creport::CrashReport g_crash_report;
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(creport, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(creport, Main));
|
||||
|
||||
/* Validate arguments. */
|
||||
if (argc < 2) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
for (int i = 0; i < argc; i++) {
|
||||
if (argv[i] == NULL) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse arguments. */
|
||||
const os::ProcessId crashed_pid = creport::ParseProcessIdArgument(argv[0]);
|
||||
const bool has_extra_info = argv[1][0] == '1';
|
||||
const bool enable_screenshot = argc >= 3 && argv[2][0] == '1';
|
||||
const bool enable_jit_debug = argc >= 4 && argv[3][0] == '1';
|
||||
|
||||
/* Initialize the crash report. */
|
||||
g_crash_report.Initialize();
|
||||
|
||||
/* Try to debug the crashed process. */
|
||||
g_crash_report.BuildReport(crashed_pid, has_extra_info);
|
||||
if (!g_crash_report.IsComplete()) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
/* Save report to file. */
|
||||
g_crash_report.SaveReport(enable_screenshot);
|
||||
|
||||
/* If we should, try to terminate the process. */
|
||||
if (hos::GetVersion() < hos::Version_11_0_0 || !enable_jit_debug) {
|
||||
if (hos::GetVersion() >= hos::Version_10_0_0) {
|
||||
/* On 10.0.0+, use pgl to terminate. */
|
||||
if (R_SUCCEEDED(pgl::Initialize())) {
|
||||
ON_SCOPE_EXIT { pgl::Finalize(); };
|
||||
|
||||
pgl::TerminateProcess(crashed_pid);
|
||||
void *AllocateForFs(size_t size) {
|
||||
return lmem::AllocateFromExpHeap(g_fs_heap_handle, size);
|
||||
}
|
||||
} else {
|
||||
/* On < 10.0.0, use ns:dev to terminate. */
|
||||
if (R_SUCCEEDED(::nsdevInitialize())) {
|
||||
ON_SCOPE_EXIT { ::nsdevExit(); };
|
||||
|
||||
nsdevTerminateProcess(static_cast<u64>(crashed_pid));
|
||||
void DeallocateForFs(void *p, size_t size) {
|
||||
AMS_UNUSED(size);
|
||||
return lmem::FreeToExpHeap(g_fs_heap_handle, p);
|
||||
}
|
||||
|
||||
void InitializeFsHeap() {
|
||||
g_fs_heap_handle = lmem::CreateExpHeap(g_fs_heap_memory, sizeof(g_fs_heap_memory), lmem::CreateOption_None);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace init {
|
||||
|
||||
void InitializeSystemModule() {
|
||||
/* Initialize heap. */
|
||||
creport::InitializeFsHeap();
|
||||
|
||||
/* Initialize our connection to sm. */
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
/* Initialize fs. */
|
||||
fs::InitializeForSystem();
|
||||
fs::SetAllocator(creport::AllocateForFs, creport::DeallocateForFs);
|
||||
fs::SetEnabledAutoAbort(false);
|
||||
|
||||
/* Mount the SD card. */
|
||||
R_ABORT_UNLESS(fs::MountSdCard("sdmc"));
|
||||
}
|
||||
|
||||
void FinalizeSystemModule() { /* ... */ }
|
||||
|
||||
void Startup() { /* ... */ }
|
||||
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
constinit creport::CrashReport g_crash_report;
|
||||
|
||||
}
|
||||
|
||||
void Main() {
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(creport, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(creport, Main));
|
||||
|
||||
/* Get arguments. */
|
||||
const int num_args = os::GetHostArgc();
|
||||
char ** const args = os::GetHostArgv();
|
||||
|
||||
/* Validate arguments. */
|
||||
if (num_args < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto i = 0; i < num_args; ++i) {
|
||||
if (args[i] == nullptr) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Don't fatal if we have extra info, or if we're 5.0.0+ and an application crashed. */
|
||||
if (hos::GetVersion() >= hos::Version_5_0_0) {
|
||||
if (g_crash_report.IsApplication()) {
|
||||
return EXIT_SUCCESS;
|
||||
/* Parse arguments. */
|
||||
const os::ProcessId crashed_pid = creport::ParseProcessIdArgument(args[0]);
|
||||
const bool has_extra_info = args[1][0] == '1';
|
||||
const bool enable_screenshot = num_args >= 3 && args[2][0] == '1';
|
||||
const bool enable_jit_debug = num_args >= 4 && args[3][0] == '1';
|
||||
|
||||
/* Initialize the crash report. */
|
||||
g_crash_report.Initialize();
|
||||
|
||||
/* Try to debug the crashed process. */
|
||||
g_crash_report.BuildReport(crashed_pid, has_extra_info);
|
||||
if (!g_crash_report.IsComplete()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Save report to file. */
|
||||
g_crash_report.SaveReport(enable_screenshot);
|
||||
|
||||
/* Try to terminate the process, if we should. */
|
||||
const auto fw_ver = hos::GetVersion();
|
||||
if (fw_ver < hos::Version_11_0_0 || !enable_jit_debug) {
|
||||
if (fw_ver >= hos::Version_10_0_0) {
|
||||
/* Use pgl to terminate. */
|
||||
if (R_SUCCEEDED(pgl::Initialize())) {
|
||||
ON_SCOPE_EXIT { pgl::Finalize(); };
|
||||
|
||||
pgl::TerminateProcess(crashed_pid);
|
||||
}
|
||||
} else {
|
||||
/* Use ns to terminate. */
|
||||
if (R_SUCCEEDED(::nsdevInitialize())) {
|
||||
ON_SCOPE_EXIT { ::nsdevExit(); };
|
||||
|
||||
nsdevTerminateProcess(crashed_pid.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If we're on 5.0.0+ and an application crashed, or if we have extra info, we don't need to fatal. */
|
||||
if (fw_ver >= hos::Version_5_0_0) {
|
||||
if (g_crash_report.IsApplication()) {
|
||||
return;
|
||||
}
|
||||
} else if (has_extra_info) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* We also don't need to fatal on user break. */
|
||||
if (g_crash_report.IsUserBreak()) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Throw fatal error. */
|
||||
{
|
||||
::FatalCpuContext ctx;
|
||||
g_crash_report.GetFatalContext(std::addressof(ctx));
|
||||
fatalThrowWithContext(g_crash_report.GetResult().GetValue(), FatalPolicy_ErrorScreen, std::addressof(ctx));
|
||||
}
|
||||
} else if (has_extra_info) {
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* Also don't fatal if we're a user break. */
|
||||
if (g_crash_report.IsUserBreak()) {
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/* Throw fatal error. */
|
||||
::FatalCpuContext ctx;
|
||||
g_crash_report.GetFatalContext(&ctx);
|
||||
fatalThrowWithContext(g_crash_report.GetResult().GetValue(), FatalPolicy_ErrorScreen, &ctx);
|
||||
}
|
||||
|
@ -15,222 +15,137 @@
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
extern "C" {
|
||||
extern u32 __start__;
|
||||
|
||||
u32 __nx_applet_type = AppletType_None;
|
||||
u32 __nx_fs_num_sessions = 1;
|
||||
|
||||
#define INNER_HEAP_SIZE 0x0
|
||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||
|
||||
void __libnx_initheap(void);
|
||||
void __appInit(void);
|
||||
void __appExit(void);
|
||||
|
||||
void *__libnx_alloc(size_t size);
|
||||
void *__libnx_aligned_alloc(size_t alignment, size_t size);
|
||||
void __libnx_free(void *mem);
|
||||
}
|
||||
|
||||
using namespace ams;
|
||||
|
||||
#define AMS_CS_SERVER_USE_FATAL_ERROR 1
|
||||
|
||||
#if AMS_CS_SERVER_USE_FATAL_ERROR
|
||||
|
||||
extern "C" {
|
||||
|
||||
/* Exception handling. */
|
||||
alignas(16) u8 __nx_exception_stack[ams::os::MemoryPageSize];
|
||||
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx);
|
||||
|
||||
}
|
||||
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
|
||||
ams::CrashHandler(ctx);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace ams::cs {
|
||||
|
||||
namespace {
|
||||
|
||||
alignas(os::ThreadStackAlignment) constinit u8 g_shell_stack[4_KB];
|
||||
alignas(os::ThreadStackAlignment) constinit u8 g_runner_stack[4_KB];
|
||||
|
||||
alignas(os::MemoryPageSize) constinit u8 g_heap_memory[32_KB];
|
||||
|
||||
alignas(0x40) constinit u8 g_htcs_buffer[2_KB];
|
||||
|
||||
constinit os::SdkMutex g_heap_mutex;
|
||||
constinit lmem::HeapHandle g_heap_handle;
|
||||
|
||||
void *Allocate(size_t size) {
|
||||
std::scoped_lock lk(g_heap_mutex);
|
||||
void *mem = lmem::AllocateFromExpHeap(g_heap_handle, size);
|
||||
return mem;
|
||||
}
|
||||
|
||||
void Deallocate(void *p, size_t size) {
|
||||
AMS_UNUSED(size);
|
||||
|
||||
std::scoped_lock lk(g_heap_mutex);
|
||||
lmem::FreeToExpHeap(g_heap_handle, p);
|
||||
}
|
||||
|
||||
void InitializeHeap() {
|
||||
std::scoped_lock lk(g_heap_mutex);
|
||||
g_heap_handle = lmem::CreateExpHeap(g_heap_memory, sizeof(g_heap_memory), lmem::CreateOption_None);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void __libnx_initheap(void) {
|
||||
void* addr = nx_inner_heap;
|
||||
size_t size = nx_inner_heap_size;
|
||||
|
||||
/* Newlib */
|
||||
extern char* fake_heap_start;
|
||||
extern char* fake_heap_end;
|
||||
|
||||
fake_heap_start = (char*)addr;
|
||||
fake_heap_end = (char*)addr + size;
|
||||
|
||||
cs::InitializeHeap();
|
||||
}
|
||||
|
||||
void __appInit(void) {
|
||||
hos::InitializeForStratosphere();
|
||||
|
||||
fs::SetAllocator(cs::Allocate, cs::Deallocate);
|
||||
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
R_ABORT_UNLESS(fsInitialize());
|
||||
lr::Initialize();
|
||||
R_ABORT_UNLESS(ldr::InitializeForShell());
|
||||
R_ABORT_UNLESS(pgl::Initialize());
|
||||
R_ABORT_UNLESS(setsysInitialize());
|
||||
/* TODO: Other services? */
|
||||
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void __appExit(void) {
|
||||
/* TODO: Other services? */
|
||||
setsysExit();
|
||||
pgl::Finalize();
|
||||
ldr::FinalizeForShell();
|
||||
lr::Finalize();
|
||||
fsExit();
|
||||
}
|
||||
|
||||
namespace ams {
|
||||
|
||||
void *Malloc(size_t) {
|
||||
AMS_ABORT("ams::Malloc was called");
|
||||
}
|
||||
namespace cs {
|
||||
|
||||
void Free(void *) {
|
||||
AMS_ABORT("ams::Free was called");
|
||||
}
|
||||
namespace {
|
||||
|
||||
}
|
||||
alignas(os::ThreadStackAlignment) constinit u8 g_shell_stack[4_KB];
|
||||
alignas(os::ThreadStackAlignment) constinit u8 g_runner_stack[4_KB];
|
||||
|
||||
void *operator new(size_t) {
|
||||
AMS_ABORT("operator new(size_t) was called");
|
||||
}
|
||||
alignas(os::MemoryPageSize) constinit u8 g_heap_memory[32_KB];
|
||||
|
||||
void operator delete(void *) {
|
||||
AMS_ABORT("operator delete(void *) was called");
|
||||
}
|
||||
alignas(0x40) constinit u8 g_htcs_buffer[2_KB];
|
||||
|
||||
void operator delete(void *, size_t) {
|
||||
AMS_ABORT("operator delete(void *, size_t) was called");
|
||||
}
|
||||
constinit os::SdkMutex g_heap_mutex;
|
||||
constinit lmem::HeapHandle g_heap_handle;
|
||||
|
||||
void *__libnx_alloc(size_t) {
|
||||
AMS_ABORT("__libnx_alloc was called");
|
||||
}
|
||||
void *Allocate(size_t size) {
|
||||
std::scoped_lock lk(g_heap_mutex);
|
||||
void *mem = lmem::AllocateFromExpHeap(g_heap_handle, size);
|
||||
return mem;
|
||||
}
|
||||
|
||||
void *__libnx_aligned_alloc(size_t, size_t) {
|
||||
AMS_ABORT("__libnx_aligned_alloc was called");
|
||||
}
|
||||
void Deallocate(void *p, size_t size) {
|
||||
AMS_UNUSED(size);
|
||||
|
||||
void __libnx_free(void *) {
|
||||
AMS_ABORT("__libnx_free was called");
|
||||
}
|
||||
std::scoped_lock lk(g_heap_mutex);
|
||||
lmem::FreeToExpHeap(g_heap_handle, p);
|
||||
}
|
||||
|
||||
namespace ams::cs {
|
||||
void InitializeHeap() {
|
||||
std::scoped_lock lk(g_heap_mutex);
|
||||
g_heap_handle = lmem::CreateExpHeap(g_heap_memory, sizeof(g_heap_memory), lmem::CreateOption_None);
|
||||
}
|
||||
|
||||
namespace {
|
||||
}
|
||||
|
||||
constinit ::ams::cs::CommandProcessor g_command_processor;
|
||||
namespace {
|
||||
|
||||
constinit ::ams::scs::ShellServer g_shell_server;
|
||||
constinit ::ams::scs::ShellServer g_runner_server;
|
||||
constinit ::ams::cs::CommandProcessor g_command_processor;
|
||||
|
||||
constinit sf::UnmanagedServiceObject<htc::tenv::IServiceManager, htc::tenv::ServiceManager> g_tenv_service_manager;
|
||||
constinit ::ams::scs::ShellServer g_shell_server;
|
||||
constinit ::ams::scs::ShellServer g_runner_server;
|
||||
|
||||
constinit sf::UnmanagedServiceObject<htc::tenv::IServiceManager, htc::tenv::ServiceManager> g_tenv_service_manager;
|
||||
|
||||
void InitializeCommandProcessor() {
|
||||
g_command_processor.Initialize();
|
||||
}
|
||||
|
||||
void InitializeShellServers() {
|
||||
g_shell_server.Initialize("iywys@$cs", g_shell_stack, sizeof(g_shell_stack), std::addressof(g_command_processor));
|
||||
g_shell_server.Start();
|
||||
|
||||
g_runner_server.Initialize("iywys@$csForRunnerTools", g_runner_stack, sizeof(g_runner_stack), std::addressof(g_command_processor));
|
||||
g_runner_server.Start();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
AMS_UNUSED(argc, argv);
|
||||
|
||||
using namespace ams::cs;
|
||||
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(cs, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(cs, Main));
|
||||
|
||||
/* Initialize htcs. */
|
||||
constexpr auto HtcsSocketCountMax = 6;
|
||||
const size_t buffer_size = htcs::GetWorkingMemorySize(2 * HtcsSocketCountMax);
|
||||
AMS_ABORT_UNLESS(sizeof(g_htcs_buffer) >= buffer_size);
|
||||
htcs::InitializeForSystem(g_htcs_buffer, buffer_size, HtcsSocketCountMax);
|
||||
|
||||
/* Initialize audio server. */
|
||||
cs::InitializeAudioServer();
|
||||
|
||||
/* Initialize remote video server. */
|
||||
cs::InitializeRemoteVideoServer();
|
||||
|
||||
/* Initialize hid server. */
|
||||
cs::InitializeHidServer();
|
||||
|
||||
/* Initialize target io server. */
|
||||
cs::InitializeTargetIoServer();
|
||||
|
||||
/* Initialize command processor. */
|
||||
g_command_processor.Initialize();
|
||||
|
||||
/* Setup scs. */
|
||||
scs::InitializeShell();
|
||||
|
||||
/* Setup target environment service. */
|
||||
scs::InitializeTenvServiceManager();
|
||||
|
||||
/* Initialize the shell servers. */
|
||||
g_shell_server.Initialize("iywys@$cs", g_shell_stack, sizeof(g_shell_stack), std::addressof(g_command_processor));
|
||||
g_shell_server.Start();
|
||||
|
||||
g_runner_server.Initialize("iywys@$csForRunnerTools", g_runner_stack, sizeof(g_runner_stack), std::addressof(g_command_processor));
|
||||
g_runner_server.Start();
|
||||
|
||||
/* Register htc:tenv. */
|
||||
R_ABORT_UNLESS(scs::GetServerManager()->RegisterObjectForServer(g_tenv_service_manager.GetShared(), htc::tenv::ServiceName, scs::SessionCount[scs::Port_HtcTenv]));
|
||||
|
||||
/* Start the scs ipc server. */
|
||||
scs::StartServer();
|
||||
|
||||
return 0;
|
||||
namespace init {
|
||||
|
||||
void InitializeSystemModule() {
|
||||
/* Initialize heap. */
|
||||
cs::InitializeHeap();
|
||||
|
||||
/* Initialize our connection to sm. */
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
/* Initialize fs. */
|
||||
fs::InitializeForSystem();
|
||||
fs::SetAllocator(cs::Allocate, cs::Deallocate);
|
||||
fs::SetEnabledAutoAbort(false);
|
||||
|
||||
/* Initialize other services we need. */
|
||||
lr::Initialize();
|
||||
R_ABORT_UNLESS(ldr::InitializeForShell());
|
||||
R_ABORT_UNLESS(pgl::Initialize());
|
||||
R_ABORT_UNLESS(setsysInitialize());
|
||||
|
||||
/* Verify that we can sanely execute. */
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void FinalizeSystemModule() { /* ... */ }
|
||||
|
||||
void Startup() { /* ... */ }
|
||||
|
||||
}
|
||||
|
||||
void Main() {
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(cs, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(cs, Main));
|
||||
|
||||
/* Initialize htcs. */
|
||||
constexpr auto HtcsSocketCountMax = 6;
|
||||
const size_t buffer_size = htcs::GetWorkingMemorySize(2 * HtcsSocketCountMax);
|
||||
AMS_ABORT_UNLESS(sizeof(cs::g_htcs_buffer) >= buffer_size);
|
||||
htcs::InitializeForSystem(cs::g_htcs_buffer, buffer_size, HtcsSocketCountMax);
|
||||
|
||||
/* Initialize audio server. */
|
||||
cs::InitializeAudioServer();
|
||||
|
||||
/* Initialize remote video server. */
|
||||
cs::InitializeRemoteVideoServer();
|
||||
|
||||
/* Initialize hid server. */
|
||||
cs::InitializeHidServer();
|
||||
|
||||
/* Initialize target io server. */
|
||||
cs::InitializeTargetIoServer();
|
||||
|
||||
/* Initialize command processor. */
|
||||
cs::InitializeCommandProcessor();
|
||||
|
||||
/* Setup scs. */
|
||||
scs::InitializeShell();
|
||||
|
||||
/* Setup target environment service. */
|
||||
scs::InitializeTenvServiceManager();
|
||||
|
||||
/* Initialize the shell servers. */
|
||||
cs::InitializeShellServers();
|
||||
|
||||
/* Register htc:tenv. */
|
||||
R_ABORT_UNLESS(scs::GetServerManager()->RegisterObjectForServer(cs::g_tenv_service_manager.GetShared(), htc::tenv::ServiceName, scs::SessionCount[scs::Port_HtcTenv]));
|
||||
|
||||
/* Start the scs ipc server. */
|
||||
scs::StartServer();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,140 +17,55 @@
|
||||
#include "dmnt2_debug_log.hpp"
|
||||
#include "dmnt2_gdb_server.hpp"
|
||||
|
||||
extern "C" {
|
||||
extern u32 __start__;
|
||||
|
||||
u32 __nx_applet_type = AppletType_None;
|
||||
u32 __nx_fs_num_sessions = 1;
|
||||
|
||||
#define INNER_HEAP_SIZE 0x0
|
||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||
|
||||
void __libnx_initheap(void);
|
||||
void __appInit(void);
|
||||
void __appExit(void);
|
||||
|
||||
void *__libnx_alloc(size_t size);
|
||||
void *__libnx_aligned_alloc(size_t alignment, size_t size);
|
||||
void __libnx_free(void *mem);
|
||||
}
|
||||
|
||||
using namespace ams;
|
||||
|
||||
#define AMS_DMNT2_SERVER_USE_FATAL_ERROR 1
|
||||
|
||||
#if AMS_DMNT2_SERVER_USE_FATAL_ERROR
|
||||
|
||||
extern "C" {
|
||||
|
||||
/* Exception handling. */
|
||||
alignas(16) u8 __nx_exception_stack[ams::os::MemoryPageSize];
|
||||
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx);
|
||||
|
||||
}
|
||||
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
|
||||
ams::CrashHandler(ctx);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace ams::dmnt {
|
||||
|
||||
namespace {
|
||||
|
||||
alignas(0x40) constinit u8 g_htcs_buffer[4_KB];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void __libnx_initheap(void) {
|
||||
void* addr = nx_inner_heap;
|
||||
size_t size = nx_inner_heap_size;
|
||||
|
||||
/* Newlib */
|
||||
extern char* fake_heap_start;
|
||||
extern char* fake_heap_end;
|
||||
|
||||
fake_heap_start = (char*)addr;
|
||||
fake_heap_end = (char*)addr + size;
|
||||
}
|
||||
|
||||
void __appInit(void) {
|
||||
hos::InitializeForStratosphere();
|
||||
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
/* TODO */
|
||||
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void __appExit(void) {
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
namespace ams {
|
||||
|
||||
void *Malloc(size_t) {
|
||||
AMS_ABORT("ams::Malloc was called");
|
||||
namespace dmnt {
|
||||
|
||||
namespace {
|
||||
|
||||
alignas(0x40) constinit u8 g_htcs_buffer[4_KB];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Free(void *) {
|
||||
AMS_ABORT("ams::Free was called");
|
||||
namespace init {
|
||||
|
||||
void InitializeSystemModule() {
|
||||
/* Initialize our connection to sm. */
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
/* Verify that we can sanely execute. */
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void FinalizeSystemModule() { /* ... */ }
|
||||
|
||||
void Startup() { /* ... */ }
|
||||
|
||||
}
|
||||
|
||||
void Main() {
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(dmnt, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(dmnt, Main));
|
||||
|
||||
/* Initialize htcs. */
|
||||
constexpr auto HtcsSocketCountMax = 8;
|
||||
const size_t buffer_size = htcs::GetWorkingMemorySize(HtcsSocketCountMax);
|
||||
AMS_ABORT_UNLESS(sizeof(dmnt::g_htcs_buffer) >= buffer_size);
|
||||
htcs::InitializeForSystem(dmnt::g_htcs_buffer, buffer_size, HtcsSocketCountMax);
|
||||
|
||||
/* Initialize debug log thread. */
|
||||
dmnt::InitializeDebugLog();
|
||||
|
||||
/* Start GdbServer. */
|
||||
dmnt::InitializeGdbServer();
|
||||
|
||||
/* TODO */
|
||||
while (true) {
|
||||
os::SleepThread(TimeSpan::FromDays(1));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void *operator new(size_t) {
|
||||
AMS_ABORT("operator new(size_t) was called");
|
||||
}
|
||||
|
||||
void operator delete(void *) {
|
||||
AMS_ABORT("operator delete(void *) was called");
|
||||
}
|
||||
|
||||
void operator delete(void *, size_t) {
|
||||
AMS_ABORT("operator delete(void *, size_t) was called");
|
||||
}
|
||||
|
||||
void *__libnx_alloc(size_t) {
|
||||
AMS_ABORT("__libnx_alloc was called");
|
||||
}
|
||||
|
||||
void *__libnx_aligned_alloc(size_t, size_t) {
|
||||
AMS_ABORT("__libnx_aligned_alloc was called");
|
||||
}
|
||||
|
||||
void __libnx_free(void *) {
|
||||
AMS_ABORT("__libnx_free was called");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
AMS_UNUSED(argc, argv);
|
||||
|
||||
/* TODO ThreadName */
|
||||
|
||||
/* Initialize htcs. */
|
||||
constexpr auto HtcsSocketCountMax = 8;
|
||||
const size_t buffer_size = htcs::GetWorkingMemorySize(HtcsSocketCountMax);
|
||||
AMS_ABORT_UNLESS(sizeof(dmnt::g_htcs_buffer) >= buffer_size);
|
||||
htcs::InitializeForSystem(dmnt::g_htcs_buffer, buffer_size, HtcsSocketCountMax);
|
||||
|
||||
/* Initialize debug log thread. */
|
||||
dmnt::InitializeDebugLog();
|
||||
|
||||
/* Start GdbServer. */
|
||||
dmnt::InitializeGdbServer();
|
||||
|
||||
/* TODO */
|
||||
while (true) {
|
||||
os::SleepThread(TimeSpan::FromDays(1));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -17,213 +17,149 @@
|
||||
#include "cheat/dmnt_cheat_service.hpp"
|
||||
#include "cheat/impl/dmnt_cheat_api.hpp"
|
||||
|
||||
extern "C" {
|
||||
extern u32 __start__;
|
||||
|
||||
u32 __nx_applet_type = AppletType_None;
|
||||
u32 __nx_fs_num_sessions = 1;
|
||||
|
||||
#define INNER_HEAP_SIZE 0x0
|
||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||
|
||||
void __libnx_initheap(void);
|
||||
void __appInit(void);
|
||||
void __appExit(void);
|
||||
|
||||
void *__libnx_alloc(size_t size);
|
||||
void *__libnx_aligned_alloc(size_t alignment, size_t size);
|
||||
void __libnx_free(void *mem);
|
||||
}
|
||||
|
||||
using namespace ams;
|
||||
|
||||
void __libnx_initheap(void) {
|
||||
void* addr = nx_inner_heap;
|
||||
size_t size = nx_inner_heap_size;
|
||||
|
||||
/* Newlib */
|
||||
extern char* fake_heap_start;
|
||||
extern char* fake_heap_end;
|
||||
|
||||
fake_heap_start = (char*)addr;
|
||||
fake_heap_end = (char*)addr + size;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
|
||||
constinit u8 g_fs_heap_memory[4_KB];
|
||||
lmem::HeapHandle g_fs_heap_handle;
|
||||
|
||||
void *AllocateForFs(size_t size) {
|
||||
return lmem::AllocateFromExpHeap(g_fs_heap_handle, size);
|
||||
}
|
||||
|
||||
void DeallocateForFs(void *p, size_t size) {
|
||||
AMS_UNUSED(size);
|
||||
return lmem::FreeToExpHeap(g_fs_heap_handle, p);
|
||||
}
|
||||
|
||||
void InitializeFsHeap() {
|
||||
g_fs_heap_handle = lmem::CreateExpHeap(g_fs_heap_memory, sizeof(g_fs_heap_memory), lmem::CreateOption_None);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void __appInit(void) {
|
||||
hos::InitializeForStratosphere();
|
||||
|
||||
InitializeFsHeap();
|
||||
fs::SetAllocator(AllocateForFs, DeallocateForFs);
|
||||
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
R_ABORT_UNLESS(pmdmntInitialize());
|
||||
R_ABORT_UNLESS(pminfoInitialize());
|
||||
R_ABORT_UNLESS(ldrDmntInitialize());
|
||||
R_ABORT_UNLESS(roDmntInitialize());
|
||||
R_ABORT_UNLESS(nsdevInitialize());
|
||||
lr::Initialize();
|
||||
R_ABORT_UNLESS(setInitialize());
|
||||
R_ABORT_UNLESS(setsysInitialize());
|
||||
R_ABORT_UNLESS(hidInitialize());
|
||||
R_ABORT_UNLESS(fsInitialize());
|
||||
|
||||
R_ABORT_UNLESS(fs::MountSdCard("sdmc"));
|
||||
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void __appExit(void) {
|
||||
/* Cleanup services. */
|
||||
fsExit();
|
||||
hidExit();
|
||||
setsysExit();
|
||||
setExit();
|
||||
lr::Finalize();
|
||||
nsdevExit();
|
||||
roDmntExit();
|
||||
ldrDmntExit();
|
||||
pminfoExit();
|
||||
pmdmntExit();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
using ServerOptions = sf::hipc::DefaultServerManagerOptions;
|
||||
|
||||
constexpr sm::ServiceName DebugMonitorServiceName = sm::ServiceName::Encode("dmnt:-");
|
||||
constexpr size_t DebugMonitorMaxSessions = 4;
|
||||
|
||||
constexpr sm::ServiceName CheatServiceName = sm::ServiceName::Encode("dmnt:cht");
|
||||
constexpr size_t CheatMaxSessions = 2;
|
||||
|
||||
/* dmnt:-, dmnt:cht. */
|
||||
constexpr size_t NumServers = 2;
|
||||
constexpr size_t NumSessions = DebugMonitorMaxSessions + CheatMaxSessions;
|
||||
|
||||
sf::hipc::ServerManager<NumServers, ServerOptions, NumSessions> g_server_manager;
|
||||
|
||||
constinit sf::UnmanagedServiceObject<dmnt::cheat::impl::ICheatInterface, dmnt::cheat::CheatService> g_cheat_service;
|
||||
|
||||
void LoopServerThread(void *) {
|
||||
g_server_manager.LoopProcess();
|
||||
}
|
||||
|
||||
constexpr size_t TotalThreads = DebugMonitorMaxSessions + 1;
|
||||
static_assert(TotalThreads >= 1, "TotalThreads");
|
||||
constexpr size_t NumExtraThreads = TotalThreads - 1;
|
||||
constexpr size_t ThreadStackSize = 0x4000;
|
||||
alignas(os::MemoryPageSize) u8 g_extra_thread_stacks[NumExtraThreads][ThreadStackSize];
|
||||
|
||||
os::ThreadType g_extra_threads[NumExtraThreads];
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace ams {
|
||||
|
||||
void *Malloc(size_t) {
|
||||
AMS_ABORT("ams::Malloc was called");
|
||||
namespace dmnt {
|
||||
|
||||
namespace {
|
||||
|
||||
constinit u8 g_fs_heap_memory[4_KB];
|
||||
lmem::HeapHandle g_fs_heap_handle;
|
||||
|
||||
void *AllocateForFs(size_t size) {
|
||||
return lmem::AllocateFromExpHeap(g_fs_heap_handle, size);
|
||||
}
|
||||
|
||||
void DeallocateForFs(void *p, size_t size) {
|
||||
AMS_UNUSED(size);
|
||||
return lmem::FreeToExpHeap(g_fs_heap_handle, p);
|
||||
}
|
||||
|
||||
void InitializeFsHeap() {
|
||||
g_fs_heap_handle = lmem::CreateExpHeap(g_fs_heap_memory, sizeof(g_fs_heap_memory), lmem::CreateOption_None);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
using ServerOptions = sf::hipc::DefaultServerManagerOptions;
|
||||
|
||||
constexpr sm::ServiceName DebugMonitorServiceName = sm::ServiceName::Encode("dmnt:-");
|
||||
constexpr size_t DebugMonitorMaxSessions = 4;
|
||||
|
||||
constexpr sm::ServiceName CheatServiceName = sm::ServiceName::Encode("dmnt:cht");
|
||||
constexpr size_t CheatMaxSessions = 2;
|
||||
|
||||
/* dmnt:-, dmnt:cht. */
|
||||
constexpr size_t NumServers = 2;
|
||||
constexpr size_t NumSessions = DebugMonitorMaxSessions + CheatMaxSessions;
|
||||
|
||||
sf::hipc::ServerManager<NumServers, ServerOptions, NumSessions> g_server_manager;
|
||||
|
||||
constinit sf::UnmanagedServiceObject<dmnt::cheat::impl::ICheatInterface, dmnt::cheat::CheatService> g_cheat_service;
|
||||
|
||||
void LoopServerThread(void *) {
|
||||
g_server_manager.LoopProcess();
|
||||
}
|
||||
|
||||
/* NOTE: Nintendo loops four threads processing on the manager -- we'll loop an extra fifth for our cheat service. */
|
||||
constexpr size_t TotalThreads = DebugMonitorMaxSessions + 1;
|
||||
static_assert(TotalThreads >= 1, "TotalThreads");
|
||||
constexpr size_t NumExtraThreads = TotalThreads - 1;
|
||||
constexpr size_t ThreadStackSize = 0x4000;
|
||||
alignas(os::MemoryPageSize) u8 g_extra_thread_stacks[NumExtraThreads][ThreadStackSize];
|
||||
|
||||
os::ThreadType g_extra_threads[NumExtraThreads];
|
||||
|
||||
void InitializeIpcServer() {
|
||||
/* Create services. */
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterObjectForServer(g_cheat_service.GetShared(), CheatServiceName, CheatMaxSessions));
|
||||
}
|
||||
|
||||
void LoopProcessIpcServer() {
|
||||
/* Initialize threads. */
|
||||
if constexpr (NumExtraThreads > 0) {
|
||||
static_assert(AMS_GET_SYSTEM_THREAD_PRIORITY(dmnt, Main) == AMS_GET_SYSTEM_THREAD_PRIORITY(dmnt, Ipc));
|
||||
for (size_t i = 0; i < NumExtraThreads; i++) {
|
||||
R_ABORT_UNLESS(os::CreateThread(std::addressof(g_extra_threads[i]), LoopServerThread, nullptr, g_extra_thread_stacks[i], ThreadStackSize, AMS_GET_SYSTEM_THREAD_PRIORITY(dmnt, Ipc)));
|
||||
os::SetThreadNamePointer(std::addressof(g_extra_threads[i]), AMS_GET_SYSTEM_THREAD_NAME(dmnt, Ipc));
|
||||
}
|
||||
}
|
||||
|
||||
/* Start extra threads. */
|
||||
if constexpr (NumExtraThreads > 0) {
|
||||
for (size_t i = 0; i < NumExtraThreads; i++) {
|
||||
os::StartThread(std::addressof(g_extra_threads[i]));
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop this thread. */
|
||||
LoopServerThread(nullptr);
|
||||
|
||||
/* Wait for extra threads to finish. */
|
||||
if constexpr (NumExtraThreads > 0) {
|
||||
for (size_t i = 0; i < NumExtraThreads; i++) {
|
||||
os::WaitThread(std::addressof(g_extra_threads[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Free(void *) {
|
||||
AMS_ABORT("ams::Free was called");
|
||||
namespace init {
|
||||
|
||||
void InitializeSystemModule() {
|
||||
/* Initialize heap. */
|
||||
dmnt::InitializeFsHeap();
|
||||
|
||||
/* Initialize our connection to sm. */
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
/* Initialize fs. */
|
||||
fs::InitializeForSystem();
|
||||
fs::SetAllocator(dmnt::AllocateForFs, dmnt::DeallocateForFs);
|
||||
fs::SetEnabledAutoAbort(false);
|
||||
|
||||
/* Initialize other services we need. */
|
||||
R_ABORT_UNLESS(pmdmntInitialize());
|
||||
R_ABORT_UNLESS(pminfoInitialize());
|
||||
R_ABORT_UNLESS(ldrDmntInitialize());
|
||||
R_ABORT_UNLESS(roDmntInitialize());
|
||||
R_ABORT_UNLESS(nsdevInitialize());
|
||||
lr::Initialize();
|
||||
R_ABORT_UNLESS(setInitialize());
|
||||
R_ABORT_UNLESS(setsysInitialize());
|
||||
R_ABORT_UNLESS(hidInitialize());
|
||||
|
||||
/* Mount the SD card. */
|
||||
R_ABORT_UNLESS(fs::MountSdCard("sdmc"));
|
||||
|
||||
/* Verify that we can sanely execute. */
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void FinalizeSystemModule() { /* ... */ }
|
||||
|
||||
void Startup() { /* ... */ }
|
||||
|
||||
}
|
||||
|
||||
void Main() {
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(dmnt, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(dmnt, Main));
|
||||
|
||||
/* Initialize the cheat manager. */
|
||||
dmnt::cheat::impl::InitializeCheatManager();
|
||||
|
||||
/* Initialize ipc server. */
|
||||
dmnt::InitializeIpcServer();
|
||||
|
||||
/* Loop processing ipc server. */
|
||||
dmnt::LoopProcessIpcServer();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void *operator new(size_t) {
|
||||
AMS_ABORT("operator new(size_t) was called");
|
||||
}
|
||||
|
||||
void operator delete(void *) {
|
||||
AMS_ABORT("operator delete(void *) was called");
|
||||
}
|
||||
|
||||
void operator delete(void *, size_t) {
|
||||
AMS_ABORT("operator delete(void *, size_t) was called");
|
||||
}
|
||||
|
||||
void *__libnx_alloc(size_t) {
|
||||
AMS_ABORT("__libnx_alloc was called");
|
||||
}
|
||||
|
||||
void *__libnx_aligned_alloc(size_t, size_t) {
|
||||
AMS_ABORT("__libnx_aligned_alloc was called");
|
||||
}
|
||||
|
||||
void __libnx_free(void *) {
|
||||
AMS_ABORT("__libnx_free was called");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
AMS_UNUSED(argc, argv);
|
||||
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(dmnt, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(dmnt, Main));
|
||||
|
||||
/* Initialize the cheat manager. */
|
||||
ams::dmnt::cheat::impl::InitializeCheatManager();
|
||||
|
||||
/* Create services. */
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterObjectForServer(g_cheat_service.GetShared(), CheatServiceName, CheatMaxSessions));
|
||||
|
||||
/* Loop forever, servicing our services. */
|
||||
/* Nintendo loops four threads processing on the manager -- we'll loop an extra fifth for our cheat service. */
|
||||
{
|
||||
|
||||
/* Initialize threads. */
|
||||
if constexpr (NumExtraThreads > 0) {
|
||||
static_assert(AMS_GET_SYSTEM_THREAD_PRIORITY(dmnt, Main) == AMS_GET_SYSTEM_THREAD_PRIORITY(dmnt, Ipc));
|
||||
for (size_t i = 0; i < NumExtraThreads; i++) {
|
||||
R_ABORT_UNLESS(os::CreateThread(std::addressof(g_extra_threads[i]), LoopServerThread, nullptr, g_extra_thread_stacks[i], ThreadStackSize, AMS_GET_SYSTEM_THREAD_PRIORITY(dmnt, Ipc)));
|
||||
os::SetThreadNamePointer(std::addressof(g_extra_threads[i]), AMS_GET_SYSTEM_THREAD_NAME(dmnt, Ipc));
|
||||
}
|
||||
}
|
||||
|
||||
/* Start extra threads. */
|
||||
if constexpr (NumExtraThreads > 0) {
|
||||
for (size_t i = 0; i < NumExtraThreads; i++) {
|
||||
os::StartThread(std::addressof(g_extra_threads[i]));
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop this thread. */
|
||||
LoopServerThread(nullptr);
|
||||
|
||||
/* Wait for extra threads to finish. */
|
||||
if constexpr (NumExtraThreads > 0) {
|
||||
for (size_t i = 0; i < NumExtraThreads; i++) {
|
||||
os::WaitThread(std::addressof(g_extra_threads[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -15,54 +15,21 @@
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
extern "C" {
|
||||
extern u32 __start__;
|
||||
namespace ams {
|
||||
|
||||
u32 __nx_applet_type = AppletType_None;
|
||||
namespace init {
|
||||
|
||||
#define INNER_HEAP_SIZE 0x2000
|
||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||
void InitializeSystemModule() { /* ... */ }
|
||||
|
||||
void __libnx_initheap(void);
|
||||
void __appInit(void);
|
||||
void __appExit(void);
|
||||
void FinalizeSystemModule() { /* ... */ }
|
||||
|
||||
void Startup() { /* ... */ }
|
||||
|
||||
}
|
||||
|
||||
void Main() {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* Exception handling. */
|
||||
alignas(16) u8 __nx_exception_stack[ams::os::MemoryPageSize];
|
||||
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx);
|
||||
}
|
||||
|
||||
using namespace ams;
|
||||
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
|
||||
ams::CrashHandler(ctx);
|
||||
}
|
||||
|
||||
void __libnx_initheap(void) {
|
||||
void* addr = nx_inner_heap;
|
||||
size_t size = nx_inner_heap_size;
|
||||
|
||||
/* Newlib */
|
||||
extern char* fake_heap_start;
|
||||
extern char* fake_heap_end;
|
||||
|
||||
fake_heap_start = (char*)addr;
|
||||
fake_heap_end = (char*)addr + size;
|
||||
}
|
||||
|
||||
void __appInit(void) {
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
void __appExit(void) {
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
AMS_UNUSED(argc, argv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -15,208 +15,127 @@
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
extern "C" {
|
||||
extern u32 __start__;
|
||||
|
||||
u32 __nx_applet_type = AppletType_None;
|
||||
u32 __nx_fs_num_sessions = 1;
|
||||
|
||||
#define INNER_HEAP_SIZE 0x0
|
||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||
|
||||
void __libnx_initheap(void);
|
||||
void __appInit(void);
|
||||
void __appExit(void);
|
||||
|
||||
/* Exception handling. */
|
||||
alignas(16) u8 __nx_exception_stack[ams::os::MemoryPageSize];
|
||||
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx);
|
||||
|
||||
void *__libnx_alloc(size_t size);
|
||||
void *__libnx_aligned_alloc(size_t alignment, size_t size);
|
||||
void __libnx_free(void *mem);
|
||||
}
|
||||
|
||||
using namespace ams;
|
||||
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
|
||||
ams::CrashHandler(ctx);
|
||||
}
|
||||
|
||||
void __libnx_initheap(void) {
|
||||
void* addr = nx_inner_heap;
|
||||
size_t size = nx_inner_heap_size;
|
||||
|
||||
/* Newlib */
|
||||
extern char* fake_heap_start;
|
||||
extern char* fake_heap_end;
|
||||
|
||||
fake_heap_start = (char*)addr;
|
||||
fake_heap_end = (char*)addr + size;
|
||||
}
|
||||
|
||||
void __appInit(void) {
|
||||
hos::InitializeForStratosphere();
|
||||
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
R_ABORT_UNLESS(setInitialize());
|
||||
R_ABORT_UNLESS(setsysInitialize());
|
||||
R_ABORT_UNLESS(pscmInitialize());
|
||||
R_ABORT_UNLESS(time::Initialize());
|
||||
if (hos::GetVersion() >= hos::Version_11_0_0) {
|
||||
R_ABORT_UNLESS(ectxrInitialize());
|
||||
}
|
||||
R_ABORT_UNLESS(fsInitialize());
|
||||
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void __appExit(void) {
|
||||
fsExit();
|
||||
time::Finalize();
|
||||
pscmExit();
|
||||
setsysExit();
|
||||
setExit();
|
||||
}
|
||||
|
||||
namespace ams::erpt {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr size_t MemoryHeapSize = 196_KB;
|
||||
alignas(os::MemoryPageSize) u8 g_memory_heap[MemoryHeapSize];
|
||||
|
||||
}
|
||||
|
||||
int MakeProductModelString(char *dst, size_t dst_size, settings::system::ProductModel model) {
|
||||
switch (model) {
|
||||
case settings::system::ProductModel_Invalid: return util::Strlcpy(dst, "Invalid", static_cast<int>(dst_size));
|
||||
case settings::system::ProductModel_Nx: return util::Strlcpy(dst, "NX", static_cast<int>(dst_size));
|
||||
default: return util::SNPrintf(dst, dst_size, "%d", static_cast<int>(model));
|
||||
}
|
||||
}
|
||||
|
||||
const char *GetRegionString(settings::system::RegionCode code) {
|
||||
switch (code) {
|
||||
case settings::system::RegionCode_Japan: return "Japan";
|
||||
case settings::system::RegionCode_Usa: return "Usa";
|
||||
case settings::system::RegionCode_Europe: return "Europe";
|
||||
case settings::system::RegionCode_Australia: return "Australia";
|
||||
case settings::system::RegionCode_HongKongTaiwanKorea: return "HongKongTaiwanKorea";
|
||||
case settings::system::RegionCode_China: return "China";
|
||||
default: return "RegionUnknown";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace ams {
|
||||
|
||||
void *Malloc(size_t) {
|
||||
AMS_ABORT("ams::Malloc was called");
|
||||
namespace erpt {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr size_t MemoryHeapSize = 196_KB;
|
||||
alignas(os::MemoryPageSize) u8 g_memory_heap[MemoryHeapSize];
|
||||
|
||||
}
|
||||
|
||||
int MakeProductModelString(char *dst, size_t dst_size, settings::system::ProductModel model) {
|
||||
switch (model) {
|
||||
case settings::system::ProductModel_Invalid: return util::Strlcpy(dst, "Invalid", static_cast<int>(dst_size));
|
||||
case settings::system::ProductModel_Nx: return util::Strlcpy(dst, "NX", static_cast<int>(dst_size));
|
||||
default: return util::SNPrintf(dst, dst_size, "%d", static_cast<int>(model));
|
||||
}
|
||||
}
|
||||
|
||||
const char *GetRegionString(settings::system::RegionCode code) {
|
||||
switch (code) {
|
||||
case settings::system::RegionCode_Japan: return "Japan";
|
||||
case settings::system::RegionCode_Usa: return "Usa";
|
||||
case settings::system::RegionCode_Europe: return "Europe";
|
||||
case settings::system::RegionCode_Australia: return "Australia";
|
||||
case settings::system::RegionCode_HongKongTaiwanKorea: return "HongKongTaiwanKorea";
|
||||
case settings::system::RegionCode_China: return "China";
|
||||
default: return "RegionUnknown";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Free(void *) {
|
||||
AMS_ABORT("ams::Free was called");
|
||||
namespace init {
|
||||
|
||||
void InitializeSystemModule() {
|
||||
/* Initialize our connection to sm. */
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
/* Initialize services we need (which won't be initialized later). */
|
||||
R_ABORT_UNLESS(setInitialize());
|
||||
R_ABORT_UNLESS(setsysInitialize());
|
||||
R_ABORT_UNLESS(pscmInitialize());
|
||||
R_ABORT_UNLESS(time::Initialize());
|
||||
if (hos::GetVersion() >= hos::Version_11_0_0) {
|
||||
R_ABORT_UNLESS(ectxrInitialize());
|
||||
}
|
||||
|
||||
/* Verify that we can sanely execute. */
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void FinalizeSystemModule() { /* ... */ }
|
||||
|
||||
void Startup() { /* ... */ }
|
||||
|
||||
}
|
||||
|
||||
void Main() {
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(erpt, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(erpt, Main));
|
||||
|
||||
/* Set the memory heap for erpt::srv namespace. */
|
||||
R_ABORT_UNLESS(erpt::srv::Initialize(erpt::g_memory_heap, erpt::MemoryHeapSize));
|
||||
|
||||
/* Atmosphere always wants to redirect new reports to the SD card, to prevent them from being logged. */
|
||||
erpt::srv::SetRedirectNewReportsToSdCard(true);
|
||||
|
||||
/* Configure the OS version. */
|
||||
{
|
||||
settings::system::FirmwareVersion firmware_version = {};
|
||||
settings::system::SerialNumber serial_number = {};
|
||||
settings::system::GetFirmwareVersion(std::addressof(firmware_version));
|
||||
settings::system::GetSerialNumber(std::addressof(serial_number));
|
||||
|
||||
char os_private[0x60];
|
||||
const auto os_priv_len = util::SNPrintf(os_private, sizeof(os_private), "%s (%.8s)", firmware_version.display_name, firmware_version.revision);
|
||||
AMS_ASSERT(static_cast<size_t>(os_priv_len) < sizeof(os_private));
|
||||
AMS_UNUSED(os_priv_len);
|
||||
|
||||
R_ABORT_UNLESS(erpt::srv::SetSerialNumberAndOsVersion(serial_number.str,
|
||||
strnlen(serial_number.str, sizeof(serial_number.str) - 1) + 1,
|
||||
firmware_version.display_version,
|
||||
strnlen(firmware_version.display_version, sizeof(firmware_version.display_version) - 1) + 1,
|
||||
os_private,
|
||||
strnlen(os_private, sizeof(os_private) - 1) + 1));
|
||||
}
|
||||
|
||||
/* Configure the product model. */
|
||||
{
|
||||
char product_model[0x10];
|
||||
const auto pm_len = erpt::MakeProductModelString(product_model, sizeof(product_model), settings::system::GetProductModel());
|
||||
AMS_ASSERT(static_cast<size_t>(pm_len) < sizeof(product_model));
|
||||
AMS_UNUSED(pm_len);
|
||||
|
||||
R_ABORT_UNLESS(erpt::srv::SetProductModel(product_model, static_cast<u32>(std::strlen(product_model))));
|
||||
}
|
||||
|
||||
/* Configure the region. */
|
||||
{
|
||||
settings::system::RegionCode code;
|
||||
settings::system::GetRegionCode(std::addressof(code));
|
||||
const char *region_str = erpt::GetRegionString(code);
|
||||
R_ABORT_UNLESS(erpt::srv::SetRegionSetting(region_str, static_cast<u32>(std::strlen(region_str))));
|
||||
}
|
||||
|
||||
/* Start the erpt server. */
|
||||
R_ABORT_UNLESS(erpt::srv::InitializeAndStartService());
|
||||
|
||||
/* Launch sprofile on 13.0.0+ */
|
||||
if (hos::GetVersion() >= hos::Version_13_0_0) {
|
||||
/* Initialize the sprofile server. */
|
||||
sprofile::srv::Initialize();
|
||||
|
||||
/* Start the sprofile ipc server. */
|
||||
sprofile::srv::StartIpcServer();
|
||||
}
|
||||
|
||||
/* Wait forever. */
|
||||
erpt::srv::Wait();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void *operator new(size_t) {
|
||||
AMS_ABORT("operator new(size_t) was called");
|
||||
}
|
||||
|
||||
void operator delete(void *) {
|
||||
AMS_ABORT("operator delete(void *) was called");
|
||||
}
|
||||
|
||||
void operator delete(void *, size_t) {
|
||||
AMS_ABORT("operator delete(void *, size_t) was called");
|
||||
}
|
||||
|
||||
void *__libnx_alloc(size_t) {
|
||||
AMS_ABORT("__libnx_alloc was called");
|
||||
}
|
||||
|
||||
void *__libnx_aligned_alloc(size_t, size_t) {
|
||||
AMS_ABORT("__libnx_aligned_alloc was called");
|
||||
}
|
||||
|
||||
void __libnx_free(void *) {
|
||||
AMS_ABORT("__libnx_free was called");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
AMS_UNUSED(argc, argv);
|
||||
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(erpt, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(erpt, Main));
|
||||
|
||||
/* Set the memory heap for erpt::srv namespace. */
|
||||
R_ABORT_UNLESS(erpt::srv::Initialize(erpt::g_memory_heap, erpt::MemoryHeapSize));
|
||||
|
||||
/* Atmosphere always wants to redirect new reports to the SD card, to prevent them from being logged. */
|
||||
erpt::srv::SetRedirectNewReportsToSdCard(true);
|
||||
|
||||
/* Configure the OS version. */
|
||||
{
|
||||
settings::system::FirmwareVersion firmware_version = {};
|
||||
settings::system::SerialNumber serial_number = {};
|
||||
settings::system::GetFirmwareVersion(std::addressof(firmware_version));
|
||||
settings::system::GetSerialNumber(std::addressof(serial_number));
|
||||
|
||||
char os_private[0x60];
|
||||
const auto os_priv_len = util::SNPrintf(os_private, sizeof(os_private), "%s (%.8s)", firmware_version.display_name, firmware_version.revision);
|
||||
AMS_ASSERT(static_cast<size_t>(os_priv_len) < sizeof(os_private));
|
||||
AMS_UNUSED(os_priv_len);
|
||||
|
||||
R_ABORT_UNLESS(erpt::srv::SetSerialNumberAndOsVersion(serial_number.str,
|
||||
strnlen(serial_number.str, sizeof(serial_number.str) - 1) + 1,
|
||||
firmware_version.display_version,
|
||||
strnlen(firmware_version.display_version, sizeof(firmware_version.display_version) - 1) + 1,
|
||||
os_private,
|
||||
strnlen(os_private, sizeof(os_private) - 1) + 1));
|
||||
}
|
||||
|
||||
/* Configure the product model. */
|
||||
{
|
||||
char product_model[0x10];
|
||||
const auto pm_len = erpt::MakeProductModelString(product_model, sizeof(product_model), settings::system::GetProductModel());
|
||||
AMS_ASSERT(static_cast<size_t>(pm_len) < sizeof(product_model));
|
||||
AMS_UNUSED(pm_len);
|
||||
|
||||
R_ABORT_UNLESS(erpt::srv::SetProductModel(product_model, static_cast<u32>(std::strlen(product_model))));
|
||||
}
|
||||
|
||||
/* Configure the region. */
|
||||
{
|
||||
settings::system::RegionCode code;
|
||||
settings::system::GetRegionCode(std::addressof(code));
|
||||
const char *region_str = erpt::GetRegionString(code);
|
||||
R_ABORT_UNLESS(erpt::srv::SetRegionSetting(region_str, static_cast<u32>(std::strlen(region_str))));
|
||||
}
|
||||
|
||||
/* Start the erpt server. */
|
||||
R_ABORT_UNLESS(erpt::srv::InitializeAndStartService());
|
||||
|
||||
/* Launch sprofile on 13.0.0+ */
|
||||
if (hos::GetVersion() >= hos::Version_13_0_0) {
|
||||
/* Initialize the sprofile server. */
|
||||
sprofile::srv::Initialize();
|
||||
|
||||
/* Start the sprofile ipc server. */
|
||||
sprofile::srv::StartIpcServer();
|
||||
}
|
||||
|
||||
/* Wait forever. */
|
||||
erpt::srv::Wait();
|
||||
|
||||
/* Cleanup */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,24 @@ namespace ams::fatal::srv {
|
||||
namespace {
|
||||
|
||||
/* Global config. */
|
||||
FatalConfig g_config;
|
||||
constinit os::SdkMutex g_config_mutex;
|
||||
constinit bool g_initialized_config;
|
||||
constinit util::TypedStorage<FatalConfig> g_config;
|
||||
|
||||
FatalConfig &GetFatalConfigImpl() {
|
||||
if (AMS_UNLIKELY(!g_initialized_config)) {
|
||||
std::scoped_lock lk(g_config_mutex);
|
||||
|
||||
if (AMS_LIKELY(!g_initialized_config)) {
|
||||
util::ConstructAt(g_config);
|
||||
|
||||
g_initialized_config = true;
|
||||
}
|
||||
}
|
||||
|
||||
return util::GetReference(g_config);
|
||||
}
|
||||
|
||||
|
||||
/* Event creator. */
|
||||
os::NativeHandle GetFatalDirtyEventReadableHandle() {
|
||||
@ -31,18 +48,18 @@ namespace ams::fatal::srv {
|
||||
}
|
||||
|
||||
/* Global event. */
|
||||
os::SystemEventType g_fatal_dirty_event;
|
||||
os::MultiWaitHolderType g_fatal_dirty_multi_wait_holder;
|
||||
bool g_initialized;
|
||||
constinit os::SystemEventType g_fatal_dirty_event;
|
||||
constinit os::MultiWaitHolderType g_fatal_dirty_multi_wait_holder;
|
||||
constinit bool g_initialized_fatal_dirty_event;
|
||||
|
||||
}
|
||||
|
||||
os::MultiWaitHolderType *GetFatalDirtyMultiWaitHolder() {
|
||||
if (AMS_UNLIKELY(!g_initialized)) {
|
||||
if (AMS_UNLIKELY(!g_initialized_fatal_dirty_event)) {
|
||||
os::AttachReadableHandleToSystemEvent(std::addressof(g_fatal_dirty_event), GetFatalDirtyEventReadableHandle(), true, os::EventClearMode_ManualClear);
|
||||
os::InitializeMultiWaitHolder(std::addressof(g_fatal_dirty_multi_wait_holder), std::addressof(g_fatal_dirty_event));
|
||||
os::SetMultiWaitHolderUserData(std::addressof(g_fatal_dirty_multi_wait_holder), reinterpret_cast<uintptr_t>(std::addressof(g_fatal_dirty_multi_wait_holder)));
|
||||
g_initialized = true;
|
||||
g_initialized_fatal_dirty_event = true;
|
||||
}
|
||||
return std::addressof(g_fatal_dirty_multi_wait_holder);
|
||||
}
|
||||
@ -52,7 +69,7 @@ namespace ams::fatal::srv {
|
||||
|
||||
u64 flags_0, flags_1;
|
||||
if (R_SUCCEEDED(setsysGetFatalDirtyFlags(&flags_0, &flags_1)) && (flags_0 & 1)) {
|
||||
g_config.UpdateLanguageCode();
|
||||
GetFatalConfigImpl().UpdateLanguageCode();
|
||||
}
|
||||
}
|
||||
|
||||
@ -103,7 +120,7 @@ namespace ams::fatal::srv {
|
||||
}
|
||||
|
||||
const FatalConfig &GetFatalConfig() {
|
||||
return g_config;
|
||||
return GetFatalConfigImpl();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,222 +19,140 @@
|
||||
#include "fatal_repair.hpp"
|
||||
#include "fatal_font.hpp"
|
||||
|
||||
/* Set libnx graphics globals. */
|
||||
extern "C" {
|
||||
extern u32 __start__;
|
||||
|
||||
u32 __nx_applet_type = AppletType_None;
|
||||
u32 __nx_fs_num_sessions = 1;
|
||||
|
||||
#define INNER_HEAP_SIZE 0x0
|
||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||
|
||||
u32 __nx_nv_transfermem_size = 0x40000;
|
||||
ViLayerFlags __nx_vi_stray_layer_flags = (ViLayerFlags)0;
|
||||
|
||||
void __libnx_initheap(void);
|
||||
void __appInit(void);
|
||||
void __appExit(void);
|
||||
|
||||
/* Exception handling. */
|
||||
alignas(16) u8 __nx_exception_stack[ams::os::MemoryPageSize];
|
||||
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx);
|
||||
|
||||
void *__libnx_alloc(size_t size);
|
||||
void *__libnx_aligned_alloc(size_t alignment, size_t size);
|
||||
void __libnx_free(void *mem);
|
||||
}
|
||||
|
||||
using namespace ams;
|
||||
|
||||
namespace ams::fatal {
|
||||
|
||||
namespace {
|
||||
|
||||
constinit u8 g_fs_heap_memory[2_KB];
|
||||
lmem::HeapHandle g_fs_heap_handle;
|
||||
|
||||
void *AllocateForFs(size_t size) {
|
||||
return lmem::AllocateFromExpHeap(g_fs_heap_handle, size);
|
||||
}
|
||||
|
||||
void DeallocateForFs(void *p, size_t size) {
|
||||
AMS_UNUSED(size);
|
||||
return lmem::FreeToExpHeap(g_fs_heap_handle, p);
|
||||
}
|
||||
|
||||
void InitializeFsHeap() {
|
||||
g_fs_heap_handle = lmem::CreateExpHeap(g_fs_heap_memory, sizeof(g_fs_heap_memory), lmem::CreateOption_ThreadSafe);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
|
||||
ams::CrashHandler(ctx);
|
||||
}
|
||||
|
||||
void __libnx_initheap(void) {
|
||||
void* addr = nx_inner_heap;
|
||||
size_t size = nx_inner_heap_size;
|
||||
|
||||
/* Newlib */
|
||||
extern char* fake_heap_start;
|
||||
extern char* fake_heap_end;
|
||||
|
||||
fake_heap_start = (char*)addr;
|
||||
fake_heap_end = (char*)addr + size;
|
||||
}
|
||||
|
||||
void __appInit(void) {
|
||||
hos::InitializeForStratosphere();
|
||||
|
||||
fatal::InitializeFsHeap();
|
||||
fs::SetAllocator(fatal::AllocateForFs, fatal::DeallocateForFs);
|
||||
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
R_ABORT_UNLESS(setInitialize());
|
||||
R_ABORT_UNLESS(setsysInitialize());
|
||||
R_ABORT_UNLESS(pminfoInitialize());
|
||||
R_ABORT_UNLESS(i2cInitialize());
|
||||
R_ABORT_UNLESS(bpcInitialize());
|
||||
|
||||
if (hos::GetVersion() >= hos::Version_8_0_0) {
|
||||
R_ABORT_UNLESS(clkrstInitialize());
|
||||
} else {
|
||||
R_ABORT_UNLESS(pcvInitialize());
|
||||
}
|
||||
|
||||
R_ABORT_UNLESS(lblInitialize());
|
||||
R_ABORT_UNLESS(psmInitialize());
|
||||
R_ABORT_UNLESS(spsmInitialize());
|
||||
R_ABORT_UNLESS(plInitialize(::PlServiceType_User));
|
||||
gpio::Initialize();
|
||||
R_ABORT_UNLESS(fsInitialize());
|
||||
|
||||
R_ABORT_UNLESS(fs::MountSdCard("sdmc"));
|
||||
|
||||
/* fatal cannot throw fatal, so don't do: ams::CheckApiVersion(); */
|
||||
}
|
||||
|
||||
void __appExit(void) {
|
||||
/* Cleanup services. */
|
||||
fsExit();
|
||||
plExit();
|
||||
gpio::Finalize();
|
||||
spsmExit();
|
||||
psmExit();
|
||||
lblExit();
|
||||
if (hos::GetVersion() >= hos::Version_8_0_0) {
|
||||
clkrstExit();
|
||||
} else {
|
||||
pcvExit();
|
||||
}
|
||||
bpcExit();
|
||||
i2cExit();
|
||||
pminfoExit();
|
||||
setsysExit();
|
||||
setExit();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
using ServerOptions = sf::hipc::DefaultServerManagerOptions;
|
||||
|
||||
constexpr sm::ServiceName UserServiceName = sm::ServiceName::Encode("fatal:u");
|
||||
constexpr size_t UserMaxSessions = 4;
|
||||
|
||||
constexpr sm::ServiceName PrivateServiceName = sm::ServiceName::Encode("fatal:p");
|
||||
constexpr size_t PrivateMaxSessions = 4;
|
||||
|
||||
/* fatal:u, fatal:p. */
|
||||
constexpr size_t NumServers = 2;
|
||||
constexpr size_t NumSessions = UserMaxSessions + PrivateMaxSessions;
|
||||
|
||||
sf::hipc::ServerManager<NumServers, ServerOptions, NumSessions> g_server_manager;
|
||||
|
||||
constinit sf::UnmanagedServiceObject<fatal::impl::IService, fatal::srv::Service> g_user_service_object;
|
||||
constinit sf::UnmanagedServiceObject<fatal::impl::IPrivateService, fatal::srv::Service> g_private_service_object;
|
||||
|
||||
}
|
||||
|
||||
namespace ams {
|
||||
|
||||
void *Malloc(size_t) {
|
||||
AMS_ABORT("ams::Malloc was called");
|
||||
}
|
||||
namespace fatal::srv {
|
||||
|
||||
void Free(void *) {
|
||||
AMS_ABORT("ams::Free was called");
|
||||
}
|
||||
namespace {
|
||||
|
||||
}
|
||||
constinit u8 g_fs_heap_memory[2_KB];
|
||||
lmem::HeapHandle g_fs_heap_handle;
|
||||
|
||||
void *operator new(size_t) {
|
||||
AMS_ABORT("operator new(size_t) was called");
|
||||
}
|
||||
void *AllocateForFs(size_t size) {
|
||||
return lmem::AllocateFromExpHeap(g_fs_heap_handle, size);
|
||||
}
|
||||
|
||||
void operator delete(void *) {
|
||||
AMS_ABORT("operator delete(void *) was called");
|
||||
}
|
||||
void DeallocateForFs(void *p, size_t size) {
|
||||
AMS_UNUSED(size);
|
||||
return lmem::FreeToExpHeap(g_fs_heap_handle, p);
|
||||
}
|
||||
|
||||
void operator delete(void *, size_t) {
|
||||
AMS_ABORT("operator delete(void *, size_t) was called");
|
||||
}
|
||||
void InitializeFsHeap() {
|
||||
g_fs_heap_handle = lmem::CreateExpHeap(g_fs_heap_memory, sizeof(g_fs_heap_memory), lmem::CreateOption_ThreadSafe);
|
||||
}
|
||||
|
||||
void *__libnx_alloc(size_t) {
|
||||
AMS_ABORT("__libnx_alloc was called");
|
||||
}
|
||||
|
||||
void *__libnx_aligned_alloc(size_t, size_t) {
|
||||
AMS_ABORT("__libnx_aligned_alloc was called");
|
||||
}
|
||||
|
||||
void __libnx_free(void *) {
|
||||
AMS_ABORT("__libnx_free was called");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
AMS_UNUSED(argc, argv);
|
||||
|
||||
/* Disable auto-abort in fs operations. */
|
||||
fs::SetEnabledAutoAbort(false);
|
||||
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(fatal, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(fatal, Main));
|
||||
|
||||
/* Load shared font. */
|
||||
R_ABORT_UNLESS(fatal::srv::font::InitializeSharedFont());
|
||||
|
||||
/* Check whether we should throw fatal due to repair process. */
|
||||
fatal::srv::CheckRepairStatus();
|
||||
|
||||
/* Create services. */
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterObjectForServer(g_user_service_object.GetShared(), UserServiceName, UserMaxSessions));
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterObjectForServer(g_private_service_object.GetShared(), PrivateServiceName, PrivateMaxSessions));
|
||||
|
||||
/* Add dirty event holder. */
|
||||
auto *dirty_event_holder = ams::fatal::srv::GetFatalDirtyMultiWaitHolder();
|
||||
g_server_manager.AddUserMultiWaitHolder(dirty_event_holder);
|
||||
|
||||
/* Loop forever, servicing our services. */
|
||||
/* Because fatal has a user wait holder, we need to specify how to process manually. */
|
||||
while (auto *signaled_holder = g_server_manager.WaitSignaled()) {
|
||||
if (signaled_holder == dirty_event_holder) {
|
||||
/* Dirty event holder was signaled. */
|
||||
fatal::srv::OnFatalDirtyEvent();
|
||||
g_server_manager.AddUserMultiWaitHolder(signaled_holder);
|
||||
} else {
|
||||
/* A server/session was signaled. Have the manager handle it. */
|
||||
R_ABORT_UNLESS(g_server_manager.Process(signaled_holder));
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
using ServerOptions = sf::hipc::DefaultServerManagerOptions;
|
||||
|
||||
constexpr sm::ServiceName UserServiceName = sm::ServiceName::Encode("fatal:u");
|
||||
constexpr size_t UserMaxSessions = 4;
|
||||
|
||||
constexpr sm::ServiceName PrivateServiceName = sm::ServiceName::Encode("fatal:p");
|
||||
constexpr size_t PrivateMaxSessions = 4;
|
||||
|
||||
/* fatal:u, fatal:p. */
|
||||
constexpr size_t NumServers = 2;
|
||||
constexpr size_t NumSessions = UserMaxSessions + PrivateMaxSessions;
|
||||
|
||||
sf::hipc::ServerManager<NumServers, ServerOptions, NumSessions> g_server_manager;
|
||||
|
||||
constinit sf::UnmanagedServiceObject<fatal::impl::IService, fatal::srv::Service> g_user_service_object;
|
||||
constinit sf::UnmanagedServiceObject<fatal::impl::IPrivateService, fatal::srv::Service> g_private_service_object;
|
||||
|
||||
void InitializeAndLoopIpcServer() {
|
||||
/* Create services. */
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterObjectForServer(g_user_service_object.GetShared(), UserServiceName, UserMaxSessions));
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterObjectForServer(g_private_service_object.GetShared(), PrivateServiceName, PrivateMaxSessions));
|
||||
|
||||
/* Add dirty event holder. */
|
||||
auto *dirty_event_holder = fatal::srv::GetFatalDirtyMultiWaitHolder();
|
||||
g_server_manager.AddUserMultiWaitHolder(dirty_event_holder);
|
||||
|
||||
/* Loop forever, servicing our services. */
|
||||
/* Because fatal has a user wait holder, we need to specify how to process manually. */
|
||||
while (auto *signaled_holder = g_server_manager.WaitSignaled()) {
|
||||
if (signaled_holder == dirty_event_holder) {
|
||||
/* Dirty event holder was signaled. */
|
||||
fatal::srv::OnFatalDirtyEvent();
|
||||
g_server_manager.AddUserMultiWaitHolder(signaled_holder);
|
||||
} else {
|
||||
/* A server/session was signaled. Have the manager handle it. */
|
||||
R_ABORT_UNLESS(g_server_manager.Process(signaled_holder));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
namespace init {
|
||||
|
||||
void InitializeSystemModule() {
|
||||
/* Initialize heap. */
|
||||
fatal::srv::InitializeFsHeap();
|
||||
|
||||
/* Initialize our connection to sm. */
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
/* Initialize fs. */
|
||||
fs::InitializeForSystem();
|
||||
fs::SetAllocator(fatal::srv::AllocateForFs, fatal::srv::DeallocateForFs);
|
||||
fs::SetEnabledAutoAbort(false);
|
||||
|
||||
/* Initialize other services we need. */
|
||||
R_ABORT_UNLESS(setInitialize());
|
||||
R_ABORT_UNLESS(setsysInitialize());
|
||||
R_ABORT_UNLESS(pminfoInitialize());
|
||||
R_ABORT_UNLESS(i2cInitialize());
|
||||
R_ABORT_UNLESS(bpcInitialize());
|
||||
|
||||
if (hos::GetVersion() >= hos::Version_8_0_0) {
|
||||
R_ABORT_UNLESS(clkrstInitialize());
|
||||
} else {
|
||||
R_ABORT_UNLESS(pcvInitialize());
|
||||
}
|
||||
|
||||
R_ABORT_UNLESS(lblInitialize());
|
||||
R_ABORT_UNLESS(psmInitialize());
|
||||
R_ABORT_UNLESS(spsmInitialize());
|
||||
R_ABORT_UNLESS(plInitialize(::PlServiceType_User));
|
||||
gpio::Initialize();
|
||||
|
||||
/* Mount the SD card. */
|
||||
R_ABORT_UNLESS(fs::MountSdCard("sdmc"));
|
||||
}
|
||||
|
||||
void FinalizeSystemModule() { /* ... */ }
|
||||
|
||||
void Startup() { /* ... */ }
|
||||
|
||||
}
|
||||
|
||||
void Main() {
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(fatal, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(fatal, Main));
|
||||
|
||||
/* Load shared font. */
|
||||
R_ABORT_UNLESS(fatal::srv::font::InitializeSharedFont());
|
||||
|
||||
/* Check whether we should throw fatal due to repair process. */
|
||||
fatal::srv::CheckRepairStatus();
|
||||
|
||||
/* Loop processing the IPC server. */
|
||||
fatal::srv::InitializeAndLoopIpcServer();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -15,315 +15,217 @@
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
extern "C" {
|
||||
extern u32 __start__;
|
||||
|
||||
u32 __nx_applet_type = AppletType_None;
|
||||
u32 __nx_fs_num_sessions = 1;
|
||||
|
||||
#define INNER_HEAP_SIZE 0x0
|
||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||
|
||||
void __libnx_initheap(void);
|
||||
void __appInit(void);
|
||||
void __appExit(void);
|
||||
|
||||
void *__libnx_alloc(size_t size);
|
||||
void *__libnx_aligned_alloc(size_t alignment, size_t size);
|
||||
void __libnx_free(void *mem);
|
||||
}
|
||||
|
||||
using namespace ams;
|
||||
|
||||
#define AMS_HTC_USE_FATAL_ERROR 1
|
||||
|
||||
#if AMS_HTC_USE_FATAL_ERROR
|
||||
|
||||
extern "C" {
|
||||
|
||||
/* Exception handling. */
|
||||
alignas(16) u8 __nx_exception_stack[ams::os::MemoryPageSize];
|
||||
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx);
|
||||
|
||||
}
|
||||
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
|
||||
ams::CrashHandler(ctx);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace ams::htc {
|
||||
|
||||
namespace {
|
||||
|
||||
alignas(0x40) constinit u8 g_heap_buffer[4_KB];
|
||||
lmem::HeapHandle g_heap_handle;
|
||||
|
||||
void *Allocate(size_t size) {
|
||||
return lmem::AllocateFromExpHeap(g_heap_handle, size);
|
||||
}
|
||||
|
||||
void Deallocate(void *p, size_t size) {
|
||||
AMS_UNUSED(size);
|
||||
|
||||
return lmem::FreeToExpHeap(g_heap_handle, p);
|
||||
}
|
||||
|
||||
void InitializeHeap() {
|
||||
/* Setup server allocator. */
|
||||
g_heap_handle = lmem::CreateExpHeap(g_heap_buffer, sizeof(g_heap_buffer), lmem::CreateOption_ThreadSafe);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void __libnx_initheap(void) {
|
||||
void* addr = nx_inner_heap;
|
||||
size_t size = nx_inner_heap_size;
|
||||
|
||||
/* Newlib */
|
||||
extern char* fake_heap_start;
|
||||
extern char* fake_heap_end;
|
||||
|
||||
fake_heap_start = (char*)addr;
|
||||
fake_heap_end = (char*)addr + size;
|
||||
|
||||
ams::htc::InitializeHeap();
|
||||
}
|
||||
|
||||
void __appInit(void) {
|
||||
hos::InitializeForStratosphere();
|
||||
|
||||
fs::SetAllocator(htc::Allocate, htc::Deallocate);
|
||||
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
R_ABORT_UNLESS(setsysInitialize());
|
||||
R_ABORT_UNLESS(setcalInitialize());
|
||||
R_ABORT_UNLESS(pscmInitialize());
|
||||
R_ABORT_UNLESS(fsInitialize());
|
||||
|
||||
R_ABORT_UNLESS(fs::MountSdCard("sdmc"));
|
||||
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void __appExit(void) {
|
||||
fsExit();
|
||||
setsysExit();
|
||||
}
|
||||
|
||||
namespace ams {
|
||||
|
||||
void *Malloc(size_t) {
|
||||
AMS_ABORT("ams::Malloc was called");
|
||||
}
|
||||
namespace htc {
|
||||
|
||||
void Free(void *) {
|
||||
AMS_ABORT("ams::Free was called");
|
||||
}
|
||||
namespace {
|
||||
|
||||
void *MallocForRapidJson(size_t) {
|
||||
AMS_ABORT("ams::MallocForRapidJson was called");
|
||||
}
|
||||
alignas(0x40) constinit u8 g_heap_buffer[4_KB];
|
||||
lmem::HeapHandle g_heap_handle;
|
||||
|
||||
void *ReallocForRapidJson(void *, size_t) {
|
||||
AMS_ABORT("ams::ReallocForRapidJson was called");
|
||||
}
|
||||
|
||||
void FreeForRapidJson(void *ptr) {
|
||||
if (ptr != nullptr) {
|
||||
AMS_ABORT("ams::FreeForRapidJson was called");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void *operator new(size_t) {
|
||||
AMS_ABORT("operator new(size_t) was called");
|
||||
}
|
||||
|
||||
void operator delete(void *) {
|
||||
AMS_ABORT("operator delete(void *) was called");
|
||||
}
|
||||
|
||||
void operator delete(void *, size_t) {
|
||||
AMS_ABORT("operator delete(void *, size_t) was called");
|
||||
}
|
||||
|
||||
void *__libnx_alloc(size_t) {
|
||||
AMS_ABORT("__libnx_alloc was called");
|
||||
}
|
||||
|
||||
void *__libnx_aligned_alloc(size_t, size_t) {
|
||||
AMS_ABORT("__libnx_aligned_alloc was called");
|
||||
}
|
||||
|
||||
void __libnx_free(void *) {
|
||||
AMS_ABORT("__libnx_free was called");
|
||||
}
|
||||
|
||||
namespace ams::htc {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr htclow::impl::DriverType DefaultHtclowDriverType = htclow::impl::DriverType::Usb;
|
||||
|
||||
constexpr inline size_t NumHtcsIpcThreads = 8;
|
||||
|
||||
alignas(os::ThreadStackAlignment) u8 g_htc_ipc_thread_stack[4_KB];
|
||||
alignas(os::ThreadStackAlignment) u8 g_htcfs_ipc_thread_stack[4_KB];
|
||||
alignas(os::ThreadStackAlignment) u8 g_htcs_ipc_thread_stack[NumHtcsIpcThreads][4_KB];
|
||||
|
||||
htclow::impl::DriverType GetHtclowDriverType() {
|
||||
/* Get the transport type. */
|
||||
char transport[0x10];
|
||||
if (settings::fwdbg::GetSettingsItemValue(transport, sizeof(transport), "bsp0", "tm_transport") == 0) {
|
||||
return DefaultHtclowDriverType;
|
||||
void *Allocate(size_t size) {
|
||||
return lmem::AllocateFromExpHeap(g_heap_handle, size);
|
||||
}
|
||||
|
||||
/* Make the transport type case insensitive. */
|
||||
transport[util::size(transport) - 1] = '\x00';
|
||||
for (size_t i = 0; i < util::size(transport); ++i) {
|
||||
transport[i] = std::tolower(static_cast<unsigned char>(transport[i]));
|
||||
void Deallocate(void *p, size_t size) {
|
||||
AMS_UNUSED(size);
|
||||
|
||||
return lmem::FreeToExpHeap(g_heap_handle, p);
|
||||
}
|
||||
|
||||
/* Select the transport. */
|
||||
if (std::strstr(transport, "usb")) {
|
||||
return htclow::impl::DriverType::Usb;
|
||||
} else if (std::strstr(transport, "hb")) {
|
||||
return htclow::impl::DriverType::HostBridge;
|
||||
} else if (std::strstr(transport, "plainchannel")) {
|
||||
return htclow::impl::DriverType::PlainChannel;
|
||||
} else if (std::strstr(transport, "socket")) {
|
||||
/* NOTE: Nintendo does not actually allow socket driver to be selected. */
|
||||
/* Should we disallow this? Undesirable, because people will want to use docked tma. */
|
||||
|
||||
/* TODO: Right now, SocketDriver causes a hang on init. This is because */
|
||||
/* the socket driver requires wi-fi, but wi-fi can't happen until the system is fully up. */
|
||||
/* The system can't initialize fully until we acknowledge power state events. */
|
||||
/* We can't acknowledge power state events until our driver is online. */
|
||||
/* Resolving this chicken-and-egg problem without compromising design will require thought. */
|
||||
|
||||
//return htclow::impl::DriverType::Socket;
|
||||
return DefaultHtclowDriverType;
|
||||
} else {
|
||||
return DefaultHtclowDriverType;
|
||||
void InitializeHeap() {
|
||||
/* Setup server allocator. */
|
||||
g_heap_handle = lmem::CreateExpHeap(g_heap_buffer, sizeof(g_heap_buffer), lmem::CreateOption_ThreadSafe);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void HtcIpcThreadFunction(void *) {
|
||||
htc::server::LoopHtcmiscServer();
|
||||
namespace {
|
||||
|
||||
constexpr htclow::impl::DriverType DefaultHtclowDriverType = htclow::impl::DriverType::Usb;
|
||||
|
||||
constexpr inline size_t NumHtcsIpcThreads = 8;
|
||||
|
||||
alignas(os::ThreadStackAlignment) u8 g_htc_ipc_thread_stack[4_KB];
|
||||
alignas(os::ThreadStackAlignment) u8 g_htcfs_ipc_thread_stack[4_KB];
|
||||
alignas(os::ThreadStackAlignment) u8 g_htcs_ipc_thread_stack[NumHtcsIpcThreads][4_KB];
|
||||
|
||||
htclow::impl::DriverType GetHtclowDriverType() {
|
||||
/* Get the transport type. */
|
||||
char transport[0x10];
|
||||
if (settings::fwdbg::GetSettingsItemValue(transport, sizeof(transport), "bsp0", "tm_transport") == 0) {
|
||||
return DefaultHtclowDriverType;
|
||||
}
|
||||
|
||||
/* Make the transport type case insensitive. */
|
||||
transport[util::size(transport) - 1] = '\x00';
|
||||
for (size_t i = 0; i < util::size(transport); ++i) {
|
||||
transport[i] = std::tolower(static_cast<unsigned char>(transport[i]));
|
||||
}
|
||||
|
||||
/* Select the transport. */
|
||||
if (std::strstr(transport, "usb")) {
|
||||
return htclow::impl::DriverType::Usb;
|
||||
} else if (std::strstr(transport, "hb")) {
|
||||
return htclow::impl::DriverType::HostBridge;
|
||||
} else if (std::strstr(transport, "plainchannel")) {
|
||||
return htclow::impl::DriverType::PlainChannel;
|
||||
} else if (std::strstr(transport, "socket")) {
|
||||
/* NOTE: Nintendo does not actually allow socket driver to be selected. */
|
||||
/* Should we disallow this? Undesirable, because people will want to use docked tma. */
|
||||
|
||||
/* TODO: Right now, SocketDriver causes a hang on init. This is because */
|
||||
/* the socket driver requires wi-fi, but wi-fi can't happen until the system is fully up. */
|
||||
/* The system can't initialize fully until we acknowledge power state events. */
|
||||
/* We can't acknowledge power state events until our driver is online. */
|
||||
/* Resolving this chicken-and-egg problem without compromising design will require thought. */
|
||||
|
||||
//return htclow::impl::DriverType::Socket;
|
||||
return DefaultHtclowDriverType;
|
||||
} else {
|
||||
return DefaultHtclowDriverType;
|
||||
}
|
||||
}
|
||||
|
||||
void HtcIpcThreadFunction(void *) {
|
||||
htc::server::LoopHtcmiscServer();
|
||||
}
|
||||
|
||||
void HtcfsIpcThreadFunction(void *) {
|
||||
htcfs::LoopHipcServer();
|
||||
}
|
||||
|
||||
void HtcsIpcThreadFunction(void *) {
|
||||
htcs::server::LoopHipcServer();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void HtcfsIpcThreadFunction(void *) {
|
||||
htcfs::LoopHipcServer();
|
||||
}
|
||||
namespace server {
|
||||
|
||||
void InitializePowerStateMonitor(htclow::impl::DriverType driver_type, htclow::HtclowManager *htclow_manager);
|
||||
void FinalizePowerStateMonitor();
|
||||
|
||||
void LoopMonitorPowerState();
|
||||
|
||||
void HtcsIpcThreadFunction(void *) {
|
||||
htcs::server::LoopHipcServer();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace server {
|
||||
namespace htclow::driver {
|
||||
|
||||
void InitializePowerStateMonitor(htclow::impl::DriverType driver_type, htclow::HtclowManager *htclow_manager);
|
||||
void FinalizePowerStateMonitor();
|
||||
void InitializeSocketApiForSocketDriver();
|
||||
|
||||
void LoopMonitorPowerState();
|
||||
}
|
||||
|
||||
namespace init {
|
||||
|
||||
void InitializeSystemModule() {
|
||||
/* Initialize heap. */
|
||||
htc::InitializeHeap();
|
||||
|
||||
/* Initialize our connection to sm. */
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
/* Initialize fs. */
|
||||
fs::InitializeForSystem();
|
||||
fs::SetAllocator(htc::Allocate, htc::Deallocate);
|
||||
fs::SetEnabledAutoAbort(false);
|
||||
|
||||
/* Initialize other services we need. */
|
||||
R_ABORT_UNLESS(setsysInitialize());
|
||||
R_ABORT_UNLESS(setcalInitialize());
|
||||
R_ABORT_UNLESS(pscmInitialize());
|
||||
|
||||
/* Mount the SD card. */
|
||||
R_ABORT_UNLESS(fs::MountSdCard("sdmc"));
|
||||
|
||||
/* Verify that we can sanely execute. */
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void FinalizeSystemModule() { /* ... */ }
|
||||
|
||||
void Startup() { /* ... */ }
|
||||
|
||||
}
|
||||
|
||||
void Main() {
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(htc, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(htc, Main));
|
||||
|
||||
/* Get and set the default driver type. */
|
||||
const auto driver_type = htc::GetHtclowDriverType();
|
||||
htclow::HtclowManagerHolder::SetDefaultDriver(driver_type);
|
||||
|
||||
/* If necessary, initialize the socket driver. */
|
||||
if (driver_type == htclow::impl::DriverType::Socket) {
|
||||
htclow::driver::InitializeSocketApiForSocketDriver();
|
||||
}
|
||||
|
||||
/* Initialize the htclow manager. */
|
||||
htclow::HtclowManagerHolder::AddReference();
|
||||
ON_SCOPE_EXIT { htclow::HtclowManagerHolder::Release(); };
|
||||
|
||||
/* Get the htclow manager. */
|
||||
auto *htclow_manager = htclow::HtclowManagerHolder::GetHtclowManager();
|
||||
|
||||
/* Initialize the htc misc server. */
|
||||
htc::server::InitializeHtcmiscServer(htclow_manager);
|
||||
|
||||
/* Create the htc misc ipc thread. */
|
||||
os::ThreadType htc_ipc_thread;
|
||||
os::CreateThread(std::addressof(htc_ipc_thread), htc::HtcIpcThreadFunction, nullptr, htc::g_htc_ipc_thread_stack, sizeof(htc::g_htc_ipc_thread_stack), AMS_GET_SYSTEM_THREAD_PRIORITY(htc, HtcIpc));
|
||||
os::SetThreadNamePointer(std::addressof(htc_ipc_thread), AMS_GET_SYSTEM_THREAD_NAME(htc, HtcIpc));
|
||||
|
||||
/* Initialize the htcfs server. */
|
||||
htcfs::Initialize(htclow_manager);
|
||||
htcfs::RegisterHipcServer();
|
||||
|
||||
/* Create the htcfs ipc thread. */
|
||||
os::ThreadType htcfs_ipc_thread;
|
||||
os::CreateThread(std::addressof(htcfs_ipc_thread), htc::HtcfsIpcThreadFunction, nullptr, htc::g_htcfs_ipc_thread_stack, sizeof(htc::g_htcfs_ipc_thread_stack), AMS_GET_SYSTEM_THREAD_PRIORITY(htc, HtcfsIpc));
|
||||
os::SetThreadNamePointer(std::addressof(htcfs_ipc_thread), AMS_GET_SYSTEM_THREAD_NAME(htc, HtcfsIpc));
|
||||
|
||||
/* Initialize the htcs server. */
|
||||
htcs::server::Initialize();
|
||||
htcs::server::RegisterHipcServer();
|
||||
|
||||
/* Create the htcs ipc threads. */
|
||||
os::ThreadType htcs_ipc_threads[htc::NumHtcsIpcThreads];
|
||||
for (size_t i = 0; i < htc::NumHtcsIpcThreads; ++i) {
|
||||
os::CreateThread(std::addressof(htcs_ipc_threads[i]), htc::HtcsIpcThreadFunction, nullptr, htc::g_htcs_ipc_thread_stack[i], sizeof(htc::g_htcs_ipc_thread_stack[i]), AMS_GET_SYSTEM_THREAD_PRIORITY(htc, HtcsIpc));
|
||||
os::SetThreadNamePointer(std::addressof(htcs_ipc_threads[i]), AMS_GET_SYSTEM_THREAD_NAME(htc, HtcsIpc));
|
||||
}
|
||||
|
||||
/* Initialize psc. */
|
||||
htc::server::InitializePowerStateMonitor(driver_type, htclow_manager);
|
||||
|
||||
/* Start all threads. */
|
||||
os::StartThread(std::addressof(htc_ipc_thread));
|
||||
os::StartThread(std::addressof(htcfs_ipc_thread));
|
||||
for (size_t i = 0; i < htc::NumHtcsIpcThreads; ++i) {
|
||||
os::StartThread(std::addressof(htcs_ipc_threads[i]));
|
||||
}
|
||||
|
||||
/* Loop psc monitor. */
|
||||
htc::server::LoopMonitorPowerState();
|
||||
|
||||
/* Destroy all threads. */
|
||||
for (size_t i = 0; i < htc::NumHtcsIpcThreads; ++i) {
|
||||
os::WaitThread(std::addressof(htcs_ipc_threads[i]));
|
||||
os::DestroyThread(std::addressof(htcs_ipc_threads[i]));
|
||||
}
|
||||
|
||||
os::WaitThread(std::addressof(htcfs_ipc_thread));
|
||||
os::DestroyThread(std::addressof(htcfs_ipc_thread));
|
||||
os::WaitThread(std::addressof(htc_ipc_thread));
|
||||
os::DestroyThread(std::addressof(htc_ipc_thread));
|
||||
|
||||
/* Finalize psc monitor. */
|
||||
htc::server::FinalizePowerStateMonitor();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace ams::htclow::driver {
|
||||
|
||||
void InitializeSocketApiForSocketDriver();
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
AMS_UNUSED(argc, argv);
|
||||
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(htc, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(htc, Main));
|
||||
|
||||
/* Get and set the default driver type. */
|
||||
const auto driver_type = htc::GetHtclowDriverType();
|
||||
htclow::HtclowManagerHolder::SetDefaultDriver(driver_type);
|
||||
|
||||
/* If necessary, initialize the socket driver. */
|
||||
if (driver_type == htclow::impl::DriverType::Socket) {
|
||||
htclow::driver::InitializeSocketApiForSocketDriver();
|
||||
}
|
||||
|
||||
/* Initialize the htclow manager. */
|
||||
htclow::HtclowManagerHolder::AddReference();
|
||||
ON_SCOPE_EXIT { htclow::HtclowManagerHolder::Release(); };
|
||||
|
||||
/* Get the htclow manager. */
|
||||
auto *htclow_manager = htclow::HtclowManagerHolder::GetHtclowManager();
|
||||
|
||||
/* Initialize the htc misc server. */
|
||||
htc::server::InitializeHtcmiscServer(htclow_manager);
|
||||
|
||||
/* Create the htc misc ipc thread. */
|
||||
os::ThreadType htc_ipc_thread;
|
||||
os::CreateThread(std::addressof(htc_ipc_thread), htc::HtcIpcThreadFunction, nullptr, htc::g_htc_ipc_thread_stack, sizeof(htc::g_htc_ipc_thread_stack), AMS_GET_SYSTEM_THREAD_PRIORITY(htc, HtcIpc));
|
||||
os::SetThreadNamePointer(std::addressof(htc_ipc_thread), AMS_GET_SYSTEM_THREAD_NAME(htc, HtcIpc));
|
||||
|
||||
/* Initialize the htcfs server. */
|
||||
htcfs::Initialize(htclow_manager);
|
||||
htcfs::RegisterHipcServer();
|
||||
|
||||
/* Create the htcfs ipc thread. */
|
||||
os::ThreadType htcfs_ipc_thread;
|
||||
os::CreateThread(std::addressof(htcfs_ipc_thread), htc::HtcfsIpcThreadFunction, nullptr, htc::g_htcfs_ipc_thread_stack, sizeof(htc::g_htcfs_ipc_thread_stack), AMS_GET_SYSTEM_THREAD_PRIORITY(htc, HtcfsIpc));
|
||||
os::SetThreadNamePointer(std::addressof(htcfs_ipc_thread), AMS_GET_SYSTEM_THREAD_NAME(htc, HtcfsIpc));
|
||||
|
||||
/* Initialize the htcs server. */
|
||||
htcs::server::Initialize();
|
||||
htcs::server::RegisterHipcServer();
|
||||
|
||||
/* Create the htcs ipc threads. */
|
||||
os::ThreadType htcs_ipc_threads[htc::NumHtcsIpcThreads];
|
||||
for (size_t i = 0; i < htc::NumHtcsIpcThreads; ++i) {
|
||||
os::CreateThread(std::addressof(htcs_ipc_threads[i]), htc::HtcsIpcThreadFunction, nullptr, htc::g_htcs_ipc_thread_stack[i], sizeof(htc::g_htcs_ipc_thread_stack[i]), AMS_GET_SYSTEM_THREAD_PRIORITY(htc, HtcsIpc));
|
||||
os::SetThreadNamePointer(std::addressof(htcs_ipc_threads[i]), AMS_GET_SYSTEM_THREAD_NAME(htc, HtcsIpc));
|
||||
}
|
||||
|
||||
/* Initialize psc. */
|
||||
htc::server::InitializePowerStateMonitor(driver_type, htclow_manager);
|
||||
|
||||
/* Start all threads. */
|
||||
os::StartThread(std::addressof(htc_ipc_thread));
|
||||
os::StartThread(std::addressof(htcfs_ipc_thread));
|
||||
for (size_t i = 0; i < htc::NumHtcsIpcThreads; ++i) {
|
||||
os::StartThread(std::addressof(htcs_ipc_threads[i]));
|
||||
}
|
||||
|
||||
/* Loop psc monitor. */
|
||||
htc::server::LoopMonitorPowerState();
|
||||
|
||||
/* Destroy all threads. */
|
||||
for (size_t i = 0; i < htc::NumHtcsIpcThreads; ++i) {
|
||||
os::WaitThread(std::addressof(htcs_ipc_threads[i]));
|
||||
os::DestroyThread(std::addressof(htcs_ipc_threads[i]));
|
||||
}
|
||||
os::WaitThread(std::addressof(htcfs_ipc_thread));
|
||||
os::DestroyThread(std::addressof(htcfs_ipc_thread));
|
||||
os::WaitThread(std::addressof(htc_ipc_thread));
|
||||
os::DestroyThread(std::addressof(htc_ipc_thread));
|
||||
|
||||
/* Finalize psc monitor. */
|
||||
htc::server::FinalizePowerStateMonitor();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -4,10 +4,18 @@
|
||||
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../../libraries/config/templates/stratosphere.mk
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# jpegdec uses libjpeg.
|
||||
# jpegdec uses libjpeg-turbo.
|
||||
#---------------------------------------------------------------------------------
|
||||
LIBS += -ljpeg
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# jpegdec overrides libjpeg-turbo's memory allocation routines.
|
||||
#---------------------------------------------------------------------------------
|
||||
CXXWRAPS += -Wl,--wrap,jpeg_get_small
|
||||
CXXWRAPS += -Wl,--wrap,jpeg_get_large
|
||||
CXXWRAPS += -Wl,--wrap,jpeg_free_small
|
||||
CXXWRAPS += -Wl,--wrap,jpeg_free_large
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# no real need to edit anything past this point unless you need to add additional
|
||||
# rules for different file extensions
|
||||
|
@ -14,78 +14,46 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "jpegdec_memory_management.hpp"
|
||||
|
||||
/* TODO: Update libjpeg-turbo to include Nintendo's changes (support for work buffer, rather than malloc) */
|
||||
namespace ams {
|
||||
|
||||
extern "C" {
|
||||
extern u32 __start__;
|
||||
namespace init {
|
||||
|
||||
u32 __nx_applet_type = AppletType_None;
|
||||
void InitializeSystemModule() {
|
||||
/* Initialize heap. */
|
||||
jpegdec::InitializeJpegHeap();
|
||||
|
||||
#define INNER_HEAP_SIZE 0x18000
|
||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||
/* Initialize our connection to sm. */
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
void __libnx_initheap(void);
|
||||
void __appInit(void);
|
||||
void __appExit(void);
|
||||
/* Verify that we can sanely execute. */
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void FinalizeSystemModule() { /* ... */ }
|
||||
|
||||
void Startup() { /* ... */ }
|
||||
|
||||
}
|
||||
|
||||
void Main() {
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(jpegdec, Main));
|
||||
|
||||
/* Official jpegdec changes its thread priority to 21 in main. */
|
||||
/* This is because older versions of the sysmodule had priority 20 in npdm. */
|
||||
os::ChangeThreadPriority(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_PRIORITY(jpegdec, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(jpegdec, Main));
|
||||
|
||||
/* Initialize the capsrv library. */
|
||||
R_ABORT_UNLESS(capsrv::server::InitializeForDecoderServer());
|
||||
|
||||
/* Service the decoder server. */
|
||||
capsrv::server::DecoderControlServerThreadFunction(nullptr);
|
||||
|
||||
/* Finalize the capsrv library. */
|
||||
capsrv::server::FinalizeForDecoderServer();
|
||||
}
|
||||
|
||||
/* Exception handling. */
|
||||
alignas(16) u8 __nx_exception_stack[ams::os::MemoryPageSize];
|
||||
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx);
|
||||
}
|
||||
|
||||
using namespace ams;
|
||||
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
|
||||
ams::CrashHandler(ctx);
|
||||
}
|
||||
|
||||
void __libnx_initheap(void) {
|
||||
void* addr = nx_inner_heap;
|
||||
size_t size = nx_inner_heap_size;
|
||||
|
||||
/* Newlib */
|
||||
extern char* fake_heap_start;
|
||||
extern char* fake_heap_end;
|
||||
|
||||
fake_heap_start = (char*)addr;
|
||||
fake_heap_end = (char*)addr + size;
|
||||
}
|
||||
|
||||
void __appInit(void) {
|
||||
hos::InitializeForStratosphere();
|
||||
ams::CheckApiVersion();
|
||||
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
}
|
||||
|
||||
void __appExit(void) {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
AMS_UNUSED(argc, argv);
|
||||
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(jpegdec, Main));
|
||||
|
||||
/* Official jpegdec changes its thread priority to 21 in main. */
|
||||
/* This is because older versions of the sysmodule had priority 20 in npdm. */
|
||||
os::ChangeThreadPriority(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_PRIORITY(jpegdec, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(jpegdec, Main));
|
||||
|
||||
/* Initialize the capsrv library. */
|
||||
R_ABORT_UNLESS(capsrv::server::InitializeForDecoderServer());
|
||||
|
||||
/* Service the decoder server. */
|
||||
capsrv::server::DecoderControlServerThreadFunction(nullptr);
|
||||
|
||||
/* Finalize the capsrv library. */
|
||||
capsrv::server::FinalizeForDecoderServer();
|
||||
|
||||
/* Cleanup */
|
||||
return 0;
|
||||
}
|
||||
|
55
stratosphere/jpegdec/source/jpegdec_memory_management.cpp
Normal file
55
stratosphere/jpegdec/source/jpegdec_memory_management.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 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>
|
||||
#include "jpegdec_memory_management.hpp"
|
||||
|
||||
namespace ams::jpegdec {
|
||||
|
||||
namespace {
|
||||
|
||||
/* TODO: Update libjpeg-turbo to include Nintendo's changes (support for work buffer, rather than malloc) */
|
||||
constexpr size_t JpegHeapSize = 96_KB;
|
||||
alignas(0x10) constinit u8 g_jpeg_heap_memory[JpegHeapSize];
|
||||
|
||||
constinit lmem::HeapHandle g_jpeg_heap_handle;
|
||||
|
||||
}
|
||||
|
||||
void InitializeJpegHeap() {
|
||||
g_jpeg_heap_handle = lmem::CreateExpHeap(g_jpeg_heap_memory, sizeof(g_jpeg_heap_memory), lmem::CreateOption_None);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern "C" void *__wrap_jpeg_get_small(void *cinfo, size_t size) {
|
||||
AMS_UNUSED(cinfo);
|
||||
return ::ams::lmem::AllocateFromExpHeap(::ams::jpegdec::g_jpeg_heap_handle, size);
|
||||
}
|
||||
|
||||
extern "C" void __wrap_jpeg_free_small(void *cinfo, void *ptr, size_t size) {
|
||||
AMS_UNUSED(cinfo, size);
|
||||
return ::ams::lmem::FreeToExpHeap(::ams::jpegdec::g_jpeg_heap_handle, ptr);
|
||||
}
|
||||
|
||||
extern "C" void *__wrap_jpeg_get_large(void *cinfo, size_t size) {
|
||||
AMS_UNUSED(cinfo);
|
||||
return ::ams::lmem::AllocateFromExpHeap(::ams::jpegdec::g_jpeg_heap_handle, size);
|
||||
}
|
||||
|
||||
extern "C" void __wrap_jpeg_free_large(void *cinfo, void *ptr, size_t size) {
|
||||
AMS_UNUSED(cinfo, size);
|
||||
return ::ams::lmem::FreeToExpHeap(::ams::jpegdec::g_jpeg_heap_handle, ptr);
|
||||
}
|
@ -14,13 +14,9 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "impl/os_resource_manager.hpp"
|
||||
|
||||
namespace ams::os {
|
||||
namespace ams::jpegdec {
|
||||
|
||||
void InitializeForStratosphereInternal() {
|
||||
/* Initialize the global os resource manager. */
|
||||
os::impl::ResourceManagerHolder::InitializeResourceManagerInstance();
|
||||
}
|
||||
void InitializeJpegHeap();
|
||||
|
||||
}
|
@ -17,206 +17,152 @@
|
||||
#include "ldr_development_manager.hpp"
|
||||
#include "ldr_loader_service.hpp"
|
||||
|
||||
extern "C" {
|
||||
extern u32 __start__;
|
||||
|
||||
u32 __nx_applet_type = AppletType_None;
|
||||
u32 __nx_fs_num_sessions = 1;
|
||||
|
||||
#define INNER_HEAP_SIZE 0x0
|
||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||
|
||||
void __libnx_initheap(void);
|
||||
void __appInit(void);
|
||||
void __appExit(void);
|
||||
|
||||
/* Exception handling. */
|
||||
alignas(16) u8 __nx_exception_stack[ams::os::MemoryPageSize];
|
||||
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx);
|
||||
|
||||
void *__libnx_alloc(size_t size);
|
||||
void *__libnx_aligned_alloc(size_t alignment, size_t size);
|
||||
void __libnx_free(void *mem);
|
||||
}
|
||||
|
||||
using namespace ams;
|
||||
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
|
||||
ams::CrashHandler(ctx);
|
||||
}
|
||||
|
||||
namespace ams::ldr {
|
||||
|
||||
namespace {
|
||||
|
||||
constinit u8 g_heap_memory[16_KB];
|
||||
lmem::HeapHandle g_server_heap_handle;
|
||||
constinit ams::sf::ExpHeapAllocator g_server_allocator;
|
||||
|
||||
void *Allocate(size_t size) {
|
||||
return lmem::AllocateFromExpHeap(g_server_heap_handle, size);
|
||||
}
|
||||
|
||||
void Deallocate(void *p, size_t size) {
|
||||
AMS_UNUSED(size);
|
||||
return lmem::FreeToExpHeap(g_server_heap_handle, p);
|
||||
}
|
||||
|
||||
void InitializeHeap() {
|
||||
g_server_heap_handle = lmem::CreateExpHeap(g_heap_memory, sizeof(g_heap_memory), lmem::CreateOption_None);
|
||||
g_server_allocator.Attach(g_server_heap_handle);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct ServerOptions {
|
||||
static constexpr size_t PointerBufferSize = 0x400;
|
||||
static constexpr size_t MaxDomains = 0;
|
||||
static constexpr size_t MaxDomainObjects = 0;
|
||||
};
|
||||
|
||||
/* ldr:pm, ldr:shel, ldr:dmnt. */
|
||||
enum PortIndex {
|
||||
PortIndex_ProcessManager,
|
||||
PortIndex_Shell,
|
||||
PortIndex_DebugMonitor,
|
||||
PortIndex_Count,
|
||||
};
|
||||
|
||||
constexpr sm::ServiceName ProcessManagerServiceName = sm::ServiceName::Encode("ldr:pm");
|
||||
constexpr size_t ProcessManagerMaxSessions = 1;
|
||||
|
||||
constexpr sm::ServiceName ShellServiceName = sm::ServiceName::Encode("ldr:shel");
|
||||
constexpr size_t ShellMaxSessions = 3;
|
||||
|
||||
constexpr sm::ServiceName DebugMonitorServiceName = sm::ServiceName::Encode("ldr:dmnt");
|
||||
constexpr size_t DebugMonitorMaxSessions = 3;
|
||||
|
||||
constinit sf::UnmanagedServiceObject<impl::IProcessManagerInterface, LoaderService> g_pm_service;
|
||||
constinit sf::UnmanagedServiceObject<impl::IShellInterface, LoaderService> g_shell_service;
|
||||
constinit sf::UnmanagedServiceObject<impl::IDebugMonitorInterface, LoaderService> g_dmnt_service;
|
||||
|
||||
constexpr size_t MaxSessions = ProcessManagerMaxSessions + ShellMaxSessions + DebugMonitorMaxSessions + 1;
|
||||
|
||||
using ServerManager = ams::sf::hipc::ServerManager<PortIndex_Count, ServerOptions, MaxSessions>;
|
||||
|
||||
ServerManager g_server_manager;
|
||||
|
||||
void RegisterServiceSessions() {
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterObjectForServer(g_pm_service.GetShared(), ProcessManagerServiceName, ProcessManagerMaxSessions));
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterObjectForServer(g_shell_service.GetShared(), ShellServiceName, ShellMaxSessions));
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterObjectForServer(g_dmnt_service.GetShared(), DebugMonitorServiceName, DebugMonitorMaxSessions));
|
||||
}
|
||||
|
||||
void LoopProcess() {
|
||||
g_server_manager.LoopProcess();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void __libnx_initheap(void) {
|
||||
void* addr = nx_inner_heap;
|
||||
size_t size = nx_inner_heap_size;
|
||||
|
||||
/* Newlib */
|
||||
extern char* fake_heap_start;
|
||||
extern char* fake_heap_end;
|
||||
|
||||
fake_heap_start = (char*)addr;
|
||||
fake_heap_end = (char*)addr + size;
|
||||
|
||||
ams::ldr::InitializeHeap();
|
||||
}
|
||||
|
||||
void __appInit(void) {
|
||||
hos::InitializeForStratosphere();
|
||||
|
||||
fs::SetAllocator(ldr::Allocate, ldr::Deallocate);
|
||||
|
||||
/* Initialize services we need. */
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
R_ABORT_UNLESS(fsInitialize());
|
||||
lr::Initialize();
|
||||
R_ABORT_UNLESS(fsldrInitialize());
|
||||
spl::Initialize();
|
||||
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void __appExit(void) {
|
||||
/* Cleanup services. */
|
||||
spl::Finalize();
|
||||
fsldrExit();
|
||||
lr::Finalize();
|
||||
fsExit();
|
||||
}
|
||||
|
||||
namespace ams {
|
||||
|
||||
void *Malloc(size_t) {
|
||||
AMS_ABORT("ams::Malloc was called");
|
||||
namespace ldr {
|
||||
|
||||
namespace {
|
||||
|
||||
constinit u8 g_heap_memory[16_KB];
|
||||
lmem::HeapHandle g_server_heap_handle;
|
||||
constinit ams::sf::ExpHeapAllocator g_server_allocator;
|
||||
|
||||
void *Allocate(size_t size) {
|
||||
return lmem::AllocateFromExpHeap(g_server_heap_handle, size);
|
||||
}
|
||||
|
||||
void Deallocate(void *p, size_t size) {
|
||||
AMS_UNUSED(size);
|
||||
return lmem::FreeToExpHeap(g_server_heap_handle, p);
|
||||
}
|
||||
|
||||
void InitializeHeap() {
|
||||
g_server_heap_handle = lmem::CreateExpHeap(g_heap_memory, sizeof(g_heap_memory), lmem::CreateOption_None);
|
||||
g_server_allocator.Attach(g_server_heap_handle);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct ServerOptions {
|
||||
static constexpr size_t PointerBufferSize = 0x400;
|
||||
static constexpr size_t MaxDomains = 0;
|
||||
static constexpr size_t MaxDomainObjects = 0;
|
||||
};
|
||||
|
||||
/* ldr:pm, ldr:shel, ldr:dmnt. */
|
||||
enum PortIndex {
|
||||
PortIndex_ProcessManager,
|
||||
PortIndex_Shell,
|
||||
PortIndex_DebugMonitor,
|
||||
PortIndex_Count,
|
||||
};
|
||||
|
||||
constexpr sm::ServiceName ProcessManagerServiceName = sm::ServiceName::Encode("ldr:pm");
|
||||
constexpr size_t ProcessManagerMaxSessions = 1;
|
||||
|
||||
constexpr sm::ServiceName ShellServiceName = sm::ServiceName::Encode("ldr:shel");
|
||||
constexpr size_t ShellMaxSessions = 3;
|
||||
|
||||
constexpr sm::ServiceName DebugMonitorServiceName = sm::ServiceName::Encode("ldr:dmnt");
|
||||
constexpr size_t DebugMonitorMaxSessions = 3;
|
||||
|
||||
constinit sf::UnmanagedServiceObject<impl::IProcessManagerInterface, LoaderService> g_pm_service;
|
||||
constinit sf::UnmanagedServiceObject<impl::IShellInterface, LoaderService> g_shell_service;
|
||||
constinit sf::UnmanagedServiceObject<impl::IDebugMonitorInterface, LoaderService> g_dmnt_service;
|
||||
|
||||
constexpr size_t MaxSessions = ProcessManagerMaxSessions + ShellMaxSessions + DebugMonitorMaxSessions + 1;
|
||||
|
||||
using ServerManager = ams::sf::hipc::ServerManager<PortIndex_Count, ServerOptions, MaxSessions>;
|
||||
|
||||
ServerManager g_server_manager;
|
||||
|
||||
void RegisterServiceSessions() {
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterObjectForServer(g_pm_service.GetShared(), ProcessManagerServiceName, ProcessManagerMaxSessions));
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterObjectForServer(g_shell_service.GetShared(), ShellServiceName, ShellMaxSessions));
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterObjectForServer(g_dmnt_service.GetShared(), DebugMonitorServiceName, DebugMonitorMaxSessions));
|
||||
}
|
||||
|
||||
void LoopProcess() {
|
||||
g_server_manager.LoopProcess();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Free(void *) {
|
||||
AMS_ABORT("ams::Free was called");
|
||||
namespace init {
|
||||
|
||||
void InitializeSystemModule() {
|
||||
/* Initialize heap. */
|
||||
ldr::InitializeHeap();
|
||||
|
||||
/* Set fs allocator. */
|
||||
fs::SetAllocator(ldr::Allocate, ldr::Deallocate);
|
||||
|
||||
/* Initialize services we need. */
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
fs::InitializeForSystem();
|
||||
lr::Initialize();
|
||||
R_ABORT_UNLESS(fsldrInitialize());
|
||||
spl::Initialize();
|
||||
|
||||
/* Verify that we can sanely execute. */
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void FinalizeSystemModule() { /* ... */ }
|
||||
|
||||
void Startup() { /* ... */ }
|
||||
|
||||
}
|
||||
|
||||
void NORETURN Exit(int rc) {
|
||||
AMS_UNUSED(rc);
|
||||
AMS_ABORT("Exit called by immortal process");
|
||||
}
|
||||
|
||||
void Main() {
|
||||
/* Disable auto-abort in fs operations. */
|
||||
fs::SetEnabledAutoAbort(false);
|
||||
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(ldr, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(ldr, Main));
|
||||
|
||||
/* Configure development. */
|
||||
/* NOTE: Nintendo really does call the getter function three times instead of caching the value. */
|
||||
ldr::SetDevelopmentForAcidProductionCheck(spl::IsDevelopment());
|
||||
ldr::SetDevelopmentForAntiDowngradeCheck(spl::IsDevelopment());
|
||||
ldr::SetDevelopmentForAcidSignatureCheck(spl::IsDevelopment());
|
||||
|
||||
/* Register the loader services. */
|
||||
ldr::RegisterServiceSessions();
|
||||
|
||||
/* Loop forever, servicing our services. */
|
||||
ldr::LoopProcess();
|
||||
|
||||
/* This can never be reached. */
|
||||
AMS_ASSUME(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Override operator new. */
|
||||
void *operator new(size_t size) {
|
||||
return ldr::Allocate(size);
|
||||
return ams::ldr::Allocate(size);
|
||||
}
|
||||
|
||||
void *operator new(size_t size, const std::nothrow_t &) {
|
||||
return ams::ldr::Allocate(size);
|
||||
}
|
||||
|
||||
void operator delete(void *p) {
|
||||
return ldr::Deallocate(p, 0);
|
||||
return ams::ldr::Deallocate(p, 0);
|
||||
}
|
||||
|
||||
void operator delete(void *p, size_t size) {
|
||||
return ldr::Deallocate(p, size);
|
||||
return ams::ldr::Deallocate(p, size);
|
||||
}
|
||||
|
||||
void *__libnx_alloc(size_t) {
|
||||
AMS_ABORT("__libnx_alloc was called");
|
||||
}
|
||||
|
||||
void *__libnx_aligned_alloc(size_t, size_t) {
|
||||
AMS_ABORT("__libnx_aligned_alloc was called");
|
||||
}
|
||||
|
||||
void __libnx_free(void *) {
|
||||
AMS_ABORT("__libnx_free was called");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
AMS_UNUSED(argc, argv);
|
||||
|
||||
/* Disable auto-abort in fs operations. */
|
||||
fs::SetEnabledAutoAbort(false);
|
||||
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(ldr, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(ldr, Main));
|
||||
|
||||
/* Configure development. */
|
||||
/* NOTE: Nintendo really does call the getter function three times instead of caching the value. */
|
||||
ldr::SetDevelopmentForAcidProductionCheck(spl::IsDevelopment());
|
||||
ldr::SetDevelopmentForAntiDowngradeCheck(spl::IsDevelopment());
|
||||
ldr::SetDevelopmentForAcidSignatureCheck(spl::IsDevelopment());
|
||||
|
||||
/* Register the loader services. */
|
||||
ldr::RegisterServiceSessions();
|
||||
|
||||
/* Loop forever, servicing our services. */
|
||||
ldr::LoopProcess();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -15,291 +15,245 @@
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
extern "C" {
|
||||
extern u32 __start__;
|
||||
|
||||
u32 __nx_applet_type = AppletType_None;
|
||||
u32 __nx_fs_num_sessions = 2;
|
||||
|
||||
#define INNER_HEAP_SIZE 0x0
|
||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||
|
||||
void __libnx_initheap(void);
|
||||
void __appInit(void);
|
||||
void __appExit(void);
|
||||
|
||||
/* Exception handling. */
|
||||
alignas(16) u8 __nx_exception_stack[ams::os::MemoryPageSize];
|
||||
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx);
|
||||
|
||||
void *__libnx_alloc(size_t size);
|
||||
void *__libnx_aligned_alloc(size_t alignment, size_t size);
|
||||
void __libnx_free(void *mem);
|
||||
}
|
||||
|
||||
using namespace ams;
|
||||
|
||||
namespace {
|
||||
|
||||
u8 g_heap_memory[1_MB];
|
||||
lmem::HeapHandle g_heap_handle;
|
||||
|
||||
void *Allocate(size_t size) {
|
||||
void *mem = lmem::AllocateFromExpHeap(g_heap_handle, size);
|
||||
ncm::GetHeapState().Allocate(size);
|
||||
return mem;
|
||||
}
|
||||
|
||||
void Deallocate(void *p, size_t size) {
|
||||
ncm::GetHeapState().Free(size != 0 ? size : lmem::GetExpHeapMemoryBlockSize(p));
|
||||
lmem::FreeToExpHeap(g_heap_handle, p);
|
||||
}
|
||||
|
||||
void InitializeHeap() {
|
||||
g_heap_handle = lmem::CreateExpHeap(g_heap_memory, sizeof(g_heap_memory), lmem::CreateOption_ThreadSafe);
|
||||
ncm::GetHeapState().Initialize(g_heap_handle);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
|
||||
ams::CrashHandler(ctx);
|
||||
}
|
||||
|
||||
void __libnx_initheap(void) {
|
||||
void * addr = nx_inner_heap;
|
||||
size_t size = nx_inner_heap_size;
|
||||
|
||||
/* Newlib */
|
||||
extern char *fake_heap_start;
|
||||
extern char *fake_heap_end;
|
||||
|
||||
fake_heap_start = (char*)addr;
|
||||
fake_heap_end = (char*)addr + size;
|
||||
|
||||
InitializeHeap();
|
||||
}
|
||||
|
||||
void __appInit(void) {
|
||||
hos::InitializeForStratosphere();
|
||||
|
||||
fs::SetAllocator(Allocate, Deallocate);
|
||||
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
R_ABORT_UNLESS(fsInitialize());
|
||||
spl::Initialize();
|
||||
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void __appExit(void) {
|
||||
/* Cleanup services. */
|
||||
spl::Finalize();
|
||||
fsExit();
|
||||
}
|
||||
|
||||
namespace ams {
|
||||
|
||||
void *Malloc(size_t) {
|
||||
AMS_ABORT("ams::Malloc was called");
|
||||
namespace ncm {
|
||||
|
||||
namespace {
|
||||
|
||||
u8 g_heap_memory[1_MB];
|
||||
lmem::HeapHandle g_heap_handle;
|
||||
|
||||
void *Allocate(size_t size) {
|
||||
void *mem = lmem::AllocateFromExpHeap(g_heap_handle, size);
|
||||
ncm::GetHeapState().Allocate(size);
|
||||
return mem;
|
||||
}
|
||||
|
||||
void Deallocate(void *p, size_t size) {
|
||||
ncm::GetHeapState().Free(size != 0 ? size : lmem::GetExpHeapMemoryBlockSize(p));
|
||||
lmem::FreeToExpHeap(g_heap_handle, p);
|
||||
}
|
||||
|
||||
void InitializeHeap() {
|
||||
g_heap_handle = lmem::CreateExpHeap(g_heap_memory, sizeof(g_heap_memory), lmem::CreateOption_ThreadSafe);
|
||||
ncm::GetHeapState().Initialize(g_heap_handle);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct ContentManagerServerOptions {
|
||||
static constexpr size_t PointerBufferSize = 0x400;
|
||||
static constexpr size_t MaxDomains = 0;
|
||||
static constexpr size_t MaxDomainObjects = 0;
|
||||
};
|
||||
|
||||
constexpr inline size_t ContentManagerNumServers = 1;
|
||||
constexpr inline size_t ContentManagerManagerSessions = 16;
|
||||
constexpr inline size_t ContentManagerExtraSessions = 16;
|
||||
constexpr inline size_t ContentManagerMaxSessions = ContentManagerManagerSessions + ContentManagerExtraSessions;
|
||||
|
||||
constexpr inline sm::ServiceName ContentManagerServiceName = sm::ServiceName::Encode("ncm");
|
||||
|
||||
alignas(os::ThreadStackAlignment) u8 g_content_manager_thread_stack[16_KB];
|
||||
alignas(os::ThreadStackAlignment) u8 g_location_resolver_thread_stack[16_KB];
|
||||
|
||||
class ContentManagerServerManager : public sf::hipc::ServerManager<ContentManagerNumServers, ContentManagerServerOptions, ContentManagerMaxSessions> {
|
||||
private:
|
||||
using ServiceImpl = ncm::ContentManagerImpl;
|
||||
private:
|
||||
os::ThreadType m_thread;
|
||||
sf::SharedPointer<ncm::IContentManager> m_manager;
|
||||
private:
|
||||
static void ThreadFunction(void *_this) {
|
||||
reinterpret_cast<ContentManagerServerManager *>(_this)->LoopProcess();
|
||||
}
|
||||
public:
|
||||
explicit ContentManagerServerManager(sf::SharedPointer<ncm::IContentManager> manager) : m_manager(manager) { /* ... */ }
|
||||
|
||||
ams::Result Initialize() {
|
||||
return this->RegisterObjectForServer(m_manager, ContentManagerServiceName, ContentManagerManagerSessions);
|
||||
}
|
||||
|
||||
ams::Result StartThreads() {
|
||||
R_TRY(os::CreateThread(std::addressof(m_thread), ThreadFunction, this, g_content_manager_thread_stack, sizeof(g_content_manager_thread_stack), AMS_GET_SYSTEM_THREAD_PRIORITY(ncm, ContentManagerServerIpcSession)));
|
||||
os::SetThreadNamePointer(std::addressof(m_thread), AMS_GET_SYSTEM_THREAD_NAME(ncm, ContentManagerServerIpcSession));
|
||||
os::StartThread(std::addressof(m_thread));
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
void Wait() {
|
||||
os::WaitThread(std::addressof(m_thread));
|
||||
}
|
||||
};
|
||||
|
||||
struct LocationResolverServerOptions {
|
||||
static constexpr size_t PointerBufferSize = 0x400;
|
||||
static constexpr size_t MaxDomains = 0;
|
||||
static constexpr size_t MaxDomainObjects = 0;
|
||||
};
|
||||
|
||||
constexpr inline size_t LocationResolverNumServers = 1;
|
||||
constexpr inline size_t LocationResolverManagerSessions = 16;
|
||||
constexpr inline size_t LocationResolverExtraSessions = 16;
|
||||
constexpr inline size_t LocationResolverMaxSessions = LocationResolverManagerSessions + LocationResolverExtraSessions;
|
||||
|
||||
constexpr inline sm::ServiceName LocationResolverServiceName = sm::ServiceName::Encode("lr");
|
||||
|
||||
class LocationResolverServerManager : public sf::hipc::ServerManager<LocationResolverNumServers, LocationResolverServerOptions, LocationResolverMaxSessions> {
|
||||
private:
|
||||
using ServiceImpl = lr::LocationResolverManagerImpl;
|
||||
private:
|
||||
os::ThreadType m_thread;
|
||||
sf::SharedPointer<lr::ILocationResolverManager> m_manager;
|
||||
private:
|
||||
static void ThreadFunction(void *_this) {
|
||||
reinterpret_cast<LocationResolverServerManager *>(_this)->LoopProcess();
|
||||
}
|
||||
public:
|
||||
LocationResolverServerManager(sf::SharedPointer<lr::ILocationResolverManager> manager) : m_manager(manager) { /* ... */ }
|
||||
|
||||
ams::Result Initialize() {
|
||||
return this->RegisterObjectForServer(m_manager, LocationResolverServiceName, LocationResolverManagerSessions);
|
||||
}
|
||||
|
||||
ams::Result StartThreads() {
|
||||
R_TRY(os::CreateThread(std::addressof(m_thread), ThreadFunction, this, g_location_resolver_thread_stack, sizeof(g_location_resolver_thread_stack), AMS_GET_SYSTEM_THREAD_PRIORITY(ncm, LocationResolverServerIpcSession)));
|
||||
os::SetThreadNamePointer(std::addressof(m_thread), AMS_GET_SYSTEM_THREAD_NAME(ncm, LocationResolverServerIpcSession));
|
||||
os::StartThread(std::addressof(m_thread));
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
void Wait() {
|
||||
os::WaitThread(std::addressof(m_thread));
|
||||
}
|
||||
};
|
||||
|
||||
sf::UnmanagedServiceObject<ncm::IContentManager, ncm::ContentManagerImpl> g_ncm_manager_service_object;
|
||||
ContentManagerServerManager g_ncm_server_manager(g_ncm_manager_service_object.GetShared());
|
||||
|
||||
sf::UnmanagedServiceObject<lr::ILocationResolverManager, lr::LocationResolverManagerImpl> g_lr_manager_service_object;
|
||||
LocationResolverServerManager g_lr_server_manager(g_lr_manager_service_object.GetShared());
|
||||
|
||||
/* Compile-time configuration. */
|
||||
#ifdef NCM_BUILD_FOR_INTITIALIZE
|
||||
constexpr inline bool BuildSystemDatabase = true;
|
||||
#else
|
||||
constexpr inline bool BuildSystemDatabase = false;
|
||||
#endif
|
||||
|
||||
#ifdef NCM_BUILD_FOR_SAFEMODE
|
||||
constexpr inline bool ImportSystemDatabaseFromSignedSystemPartitionOnSdCard = true;
|
||||
#else
|
||||
constexpr inline bool ImportSystemDatabaseFromSignedSystemPartitionOnSdCard = false;
|
||||
#endif
|
||||
|
||||
static_assert(!(BuildSystemDatabase && ImportSystemDatabaseFromSignedSystemPartitionOnSdCard), "Invalid NCM build configuration!");
|
||||
|
||||
constexpr inline ncm::ContentManagerConfig ManagerConfig = { BuildSystemDatabase, ImportSystemDatabaseFromSignedSystemPartitionOnSdCard };
|
||||
|
||||
}
|
||||
|
||||
void NcmMain() {
|
||||
/* Initialize spl. */
|
||||
spl::Initialize();
|
||||
ON_SCOPE_EXIT { spl::Finalize(); };
|
||||
|
||||
/* Initialize fs. */
|
||||
fs::InitializeWithMultiSessionForSystem();
|
||||
fs::SetAllocator(Allocate, Deallocate);
|
||||
fs::SetEnabledAutoAbort(false);
|
||||
|
||||
/* Create and initialize the content manager. */
|
||||
R_ABORT_UNLESS(g_ncm_manager_service_object.GetImpl().Initialize(ManagerConfig));
|
||||
|
||||
/* Initialize ncm's server and start threads. */
|
||||
R_ABORT_UNLESS(g_ncm_server_manager.Initialize());
|
||||
R_ABORT_UNLESS(g_ncm_server_manager.StartThreads());
|
||||
|
||||
/* Initialize ncm api. */
|
||||
ncm::InitializeWithObject(g_ncm_manager_service_object.GetShared());
|
||||
|
||||
/* Initialize lr's server and start threads. */
|
||||
R_ABORT_UNLESS(g_lr_server_manager.Initialize());
|
||||
R_ABORT_UNLESS(g_lr_server_manager.StartThreads());
|
||||
|
||||
/* Wait indefinitely. */
|
||||
g_ncm_server_manager.Wait();
|
||||
g_lr_server_manager.Wait();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Free(void *) {
|
||||
AMS_ABORT("ams::Free was called");
|
||||
namespace init {
|
||||
|
||||
void InitializeSystemModule() {
|
||||
/* Initialize heap. */
|
||||
ncm::InitializeHeap();
|
||||
|
||||
/* Initialize our connection to sm. */
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
/* Verify that we can sanely execute. */
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void FinalizeSystemModule() { /* ... */ }
|
||||
|
||||
void Startup() { /* ... */ }
|
||||
|
||||
}
|
||||
|
||||
void NORETURN Exit(int rc) {
|
||||
AMS_UNUSED(rc);
|
||||
AMS_ABORT("Exit called by immortal process");
|
||||
}
|
||||
|
||||
void Main() {
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(ncm, MainWaitThreads));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(ncm, MainWaitThreads));
|
||||
|
||||
/* Invoke NCM main. */
|
||||
ncm::NcmMain();
|
||||
|
||||
/* This can never be reached. */
|
||||
AMS_ASSUME(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void *__libnx_alloc(size_t) {
|
||||
AMS_ABORT("__libnx_alloc was called");
|
||||
}
|
||||
|
||||
void *__libnx_aligned_alloc(size_t, size_t) {
|
||||
AMS_ABORT("__libnx_aligned_alloc was called");
|
||||
}
|
||||
|
||||
void __libnx_free(void *) {
|
||||
AMS_ABORT("__libnx_free was called");
|
||||
}
|
||||
|
||||
/* Override operator new. */
|
||||
void *operator new(size_t size) {
|
||||
return Allocate(size);
|
||||
return ams::ncm::Allocate(size);
|
||||
}
|
||||
|
||||
void *operator new(size_t size, const std::nothrow_t &) {
|
||||
return Allocate(size);
|
||||
return ams::ncm::Allocate(size);
|
||||
}
|
||||
|
||||
void operator delete(void *p) {
|
||||
return Deallocate(p, 0);
|
||||
return ams::ncm::Deallocate(p, 0);
|
||||
}
|
||||
|
||||
void operator delete(void *p, size_t size) {
|
||||
return Deallocate(p, size);
|
||||
return ams::ncm::Deallocate(p, size);
|
||||
}
|
||||
|
||||
void *operator new[](size_t size) {
|
||||
return Allocate(size);
|
||||
return ams::ncm::Allocate(size);
|
||||
}
|
||||
|
||||
void *operator new[](size_t size, const std::nothrow_t &) {
|
||||
return Allocate(size);
|
||||
return ams::ncm::Allocate(size);
|
||||
}
|
||||
|
||||
void operator delete[](void *p) {
|
||||
return Deallocate(p, 0);
|
||||
return ams::ncm::Deallocate(p, 0);
|
||||
}
|
||||
|
||||
void operator delete[](void *p, size_t size) {
|
||||
return Deallocate(p, size);
|
||||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
struct ContentManagerServerOptions {
|
||||
static constexpr size_t PointerBufferSize = 0x400;
|
||||
static constexpr size_t MaxDomains = 0;
|
||||
static constexpr size_t MaxDomainObjects = 0;
|
||||
};
|
||||
|
||||
constexpr inline size_t ContentManagerNumServers = 1;
|
||||
constexpr inline size_t ContentManagerManagerSessions = 16;
|
||||
constexpr inline size_t ContentManagerExtraSessions = 16;
|
||||
constexpr inline size_t ContentManagerMaxSessions = ContentManagerManagerSessions + ContentManagerExtraSessions;
|
||||
|
||||
constexpr inline sm::ServiceName ContentManagerServiceName = sm::ServiceName::Encode("ncm");
|
||||
|
||||
alignas(os::ThreadStackAlignment) u8 g_content_manager_thread_stack[16_KB];
|
||||
alignas(os::ThreadStackAlignment) u8 g_location_resolver_thread_stack[16_KB];
|
||||
|
||||
class ContentManagerServerManager : public sf::hipc::ServerManager<ContentManagerNumServers, ContentManagerServerOptions, ContentManagerMaxSessions> {
|
||||
private:
|
||||
using ServiceImpl = ncm::ContentManagerImpl;
|
||||
private:
|
||||
os::ThreadType m_thread;
|
||||
sf::SharedPointer<ncm::IContentManager> m_manager;
|
||||
private:
|
||||
static void ThreadFunction(void *_this) {
|
||||
reinterpret_cast<ContentManagerServerManager *>(_this)->LoopProcess();
|
||||
}
|
||||
public:
|
||||
explicit ContentManagerServerManager(sf::SharedPointer<ncm::IContentManager> manager) : m_manager(manager) { /* ... */ }
|
||||
|
||||
ams::Result Initialize() {
|
||||
return this->RegisterObjectForServer(m_manager, ContentManagerServiceName, ContentManagerManagerSessions);
|
||||
}
|
||||
|
||||
ams::Result StartThreads() {
|
||||
R_TRY(os::CreateThread(std::addressof(m_thread), ThreadFunction, this, g_content_manager_thread_stack, sizeof(g_content_manager_thread_stack), AMS_GET_SYSTEM_THREAD_PRIORITY(ncm, ContentManagerServerIpcSession)));
|
||||
os::SetThreadNamePointer(std::addressof(m_thread), AMS_GET_SYSTEM_THREAD_NAME(ncm, ContentManagerServerIpcSession));
|
||||
os::StartThread(std::addressof(m_thread));
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
void Wait() {
|
||||
os::WaitThread(std::addressof(m_thread));
|
||||
}
|
||||
};
|
||||
|
||||
struct LocationResolverServerOptions {
|
||||
static constexpr size_t PointerBufferSize = 0x400;
|
||||
static constexpr size_t MaxDomains = 0;
|
||||
static constexpr size_t MaxDomainObjects = 0;
|
||||
};
|
||||
|
||||
constexpr inline size_t LocationResolverNumServers = 1;
|
||||
constexpr inline size_t LocationResolverManagerSessions = 16;
|
||||
constexpr inline size_t LocationResolverExtraSessions = 16;
|
||||
constexpr inline size_t LocationResolverMaxSessions = LocationResolverManagerSessions + LocationResolverExtraSessions;
|
||||
|
||||
constexpr inline sm::ServiceName LocationResolverServiceName = sm::ServiceName::Encode("lr");
|
||||
|
||||
class LocationResolverServerManager : public sf::hipc::ServerManager<LocationResolverNumServers, LocationResolverServerOptions, LocationResolverMaxSessions> {
|
||||
private:
|
||||
using ServiceImpl = lr::LocationResolverManagerImpl;
|
||||
private:
|
||||
os::ThreadType m_thread;
|
||||
sf::SharedPointer<lr::ILocationResolverManager> m_manager;
|
||||
private:
|
||||
static void ThreadFunction(void *_this) {
|
||||
reinterpret_cast<LocationResolverServerManager *>(_this)->LoopProcess();
|
||||
}
|
||||
public:
|
||||
LocationResolverServerManager(sf::SharedPointer<lr::ILocationResolverManager> manager) : m_manager(manager) { /* ... */ }
|
||||
|
||||
ams::Result Initialize() {
|
||||
return this->RegisterObjectForServer(m_manager, LocationResolverServiceName, LocationResolverManagerSessions);
|
||||
}
|
||||
|
||||
ams::Result StartThreads() {
|
||||
R_TRY(os::CreateThread(std::addressof(m_thread), ThreadFunction, this, g_location_resolver_thread_stack, sizeof(g_location_resolver_thread_stack), AMS_GET_SYSTEM_THREAD_PRIORITY(ncm, LocationResolverServerIpcSession)));
|
||||
os::SetThreadNamePointer(std::addressof(m_thread), AMS_GET_SYSTEM_THREAD_NAME(ncm, LocationResolverServerIpcSession));
|
||||
os::StartThread(std::addressof(m_thread));
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
void Wait() {
|
||||
os::WaitThread(std::addressof(m_thread));
|
||||
}
|
||||
};
|
||||
|
||||
sf::UnmanagedServiceObject<ncm::IContentManager, ncm::ContentManagerImpl> g_ncm_manager_service_object;
|
||||
ContentManagerServerManager g_ncm_server_manager(g_ncm_manager_service_object.GetShared());
|
||||
|
||||
sf::UnmanagedServiceObject<lr::ILocationResolverManager, lr::LocationResolverManagerImpl> g_lr_manager_service_object;
|
||||
LocationResolverServerManager g_lr_server_manager(g_lr_manager_service_object.GetShared());
|
||||
|
||||
/* Compile-time configuration. */
|
||||
#ifdef NCM_BUILD_FOR_INTITIALIZE
|
||||
constexpr inline bool BuildSystemDatabase = true;
|
||||
#else
|
||||
constexpr inline bool BuildSystemDatabase = false;
|
||||
#endif
|
||||
|
||||
#ifdef NCM_BUILD_FOR_SAFEMODE
|
||||
constexpr inline bool ImportSystemDatabaseFromSignedSystemPartitionOnSdCard = true;
|
||||
#else
|
||||
constexpr inline bool ImportSystemDatabaseFromSignedSystemPartitionOnSdCard = false;
|
||||
#endif
|
||||
|
||||
static_assert(!(BuildSystemDatabase && ImportSystemDatabaseFromSignedSystemPartitionOnSdCard), "Invalid NCM build configuration!");
|
||||
|
||||
constexpr inline ncm::ContentManagerConfig ManagerConfig = { BuildSystemDatabase, ImportSystemDatabaseFromSignedSystemPartitionOnSdCard };
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
AMS_UNUSED(argc, argv);
|
||||
|
||||
/* Disable auto-abort in fs operations. */
|
||||
fs::SetEnabledAutoAbort(false);
|
||||
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(ncm, MainWaitThreads));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(ncm, MainWaitThreads));
|
||||
|
||||
/* Create and initialize the content manager. */
|
||||
R_ABORT_UNLESS(g_ncm_manager_service_object.GetImpl().Initialize(ManagerConfig));
|
||||
|
||||
/* Initialize ncm's server and start threads. */
|
||||
R_ABORT_UNLESS(g_ncm_server_manager.Initialize());
|
||||
R_ABORT_UNLESS(g_ncm_server_manager.StartThreads());
|
||||
|
||||
/* Initialize ncm api. */
|
||||
ncm::InitializeWithObject(g_ncm_manager_service_object.GetShared());
|
||||
|
||||
/* Initialize lr's server and start threads. */
|
||||
R_ABORT_UNLESS(g_lr_server_manager.Initialize());
|
||||
R_ABORT_UNLESS(g_lr_server_manager.StartThreads());
|
||||
|
||||
/* Wait indefinitely. */
|
||||
g_ncm_server_manager.Wait();
|
||||
g_lr_server_manager.Wait();
|
||||
|
||||
return 0;
|
||||
return ams::ncm::Deallocate(p, size);
|
||||
}
|
||||
|
@ -15,127 +15,46 @@
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
extern "C" {
|
||||
extern u32 __start__;
|
||||
|
||||
u32 __nx_applet_type = AppletType_None;
|
||||
u32 __nx_fs_num_sessions = 1;
|
||||
|
||||
#define INNER_HEAP_SIZE 0x0
|
||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||
|
||||
void __libnx_initheap(void);
|
||||
void __appInit(void);
|
||||
void __appExit(void);
|
||||
|
||||
/* Exception handling. */
|
||||
alignas(16) u8 __nx_exception_stack[ams::os::MemoryPageSize];
|
||||
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx);
|
||||
|
||||
void *__libnx_alloc(size_t size);
|
||||
void *__libnx_aligned_alloc(size_t alignment, size_t size);
|
||||
void __libnx_free(void *mem);
|
||||
}
|
||||
|
||||
using namespace ams;
|
||||
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
|
||||
ams::CrashHandler(ctx);
|
||||
}
|
||||
|
||||
void __libnx_initheap(void) {
|
||||
void* addr = nx_inner_heap;
|
||||
size_t size = nx_inner_heap_size;
|
||||
|
||||
/* Newlib */
|
||||
extern char* fake_heap_start;
|
||||
extern char* fake_heap_end;
|
||||
|
||||
fake_heap_start = (char*)addr;
|
||||
fake_heap_end = (char*)addr + size;
|
||||
}
|
||||
|
||||
void __appInit(void) {
|
||||
hos::InitializeForStratosphere();
|
||||
|
||||
ams::pgl::srv::InitializeHeap();
|
||||
|
||||
fs::SetAllocator(pgl::srv::Allocate, pgl::srv::Deallocate);
|
||||
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
R_ABORT_UNLESS(setInitialize());
|
||||
R_ABORT_UNLESS(setsysInitialize());
|
||||
R_ABORT_UNLESS(pmshellInitialize());
|
||||
R_ABORT_UNLESS(ldrShellInitialize());
|
||||
R_ABORT_UNLESS(lrInitialize());
|
||||
R_ABORT_UNLESS(fsInitialize());
|
||||
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void __appExit(void) {
|
||||
fsExit();
|
||||
lrExit();
|
||||
ldrShellExit();
|
||||
pmshellExit();
|
||||
setsysExit();
|
||||
setExit();
|
||||
}
|
||||
|
||||
namespace ams {
|
||||
|
||||
void *Malloc(size_t) {
|
||||
AMS_ABORT("ams::Malloc was called");
|
||||
namespace init {
|
||||
|
||||
void InitializeSystemModule() {
|
||||
/* Initialize heap. */
|
||||
pgl::srv::InitializeHeap();
|
||||
|
||||
/* Initialize our connection to sm. */
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
/* Initialize fs. */
|
||||
fs::InitializeForSystem();
|
||||
fs::SetAllocator(pgl::srv::Allocate, pgl::srv::Deallocate);
|
||||
fs::SetEnabledAutoAbort(false);
|
||||
|
||||
/* Initialize other services we need. */
|
||||
R_ABORT_UNLESS(setInitialize());
|
||||
R_ABORT_UNLESS(setsysInitialize());
|
||||
R_ABORT_UNLESS(pmshellInitialize());
|
||||
R_ABORT_UNLESS(ldrShellInitialize());
|
||||
R_ABORT_UNLESS(lrInitialize());
|
||||
|
||||
/* Verify that we can sanely execute. */
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void FinalizeSystemModule() { /* ... */ }
|
||||
|
||||
void Startup() { /* ... */ }
|
||||
|
||||
}
|
||||
|
||||
void Free(void *) {
|
||||
AMS_ABORT("ams::Free was called");
|
||||
void Main() {
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(pgl, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(pgl, Main));
|
||||
|
||||
/* Initialize and start the server. */
|
||||
pgl::srv::StartServer();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void *operator new(size_t size) {
|
||||
return pgl::srv::Allocate(size);
|
||||
}
|
||||
|
||||
void operator delete(void *p) {
|
||||
return pgl::srv::Deallocate(p, 0);
|
||||
}
|
||||
|
||||
void operator delete(void *p, size_t size) {
|
||||
return pgl::srv::Deallocate(p, size);
|
||||
}
|
||||
|
||||
void *__libnx_alloc(size_t) {
|
||||
AMS_ABORT("__libnx_alloc was called");
|
||||
}
|
||||
|
||||
void *__libnx_aligned_alloc(size_t, size_t) {
|
||||
AMS_ABORT("__libnx_aligned_alloc was called");
|
||||
}
|
||||
|
||||
void __libnx_free(void *) {
|
||||
AMS_ABORT("__libnx_free was called");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
AMS_UNUSED(argc, argv);
|
||||
|
||||
/* Disable auto-abort in fs operations. */
|
||||
fs::SetEnabledAutoAbort(false);
|
||||
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(pgl, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(pgl, Main));
|
||||
|
||||
/* Initialize and start the server. */
|
||||
pgl::srv::StartServer();
|
||||
|
||||
/* Cleanup */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -18,263 +18,205 @@
|
||||
#include "pm_debug_monitor_service.hpp"
|
||||
#include "pm_info_service.hpp"
|
||||
#include "pm_shell_service.hpp"
|
||||
|
||||
#include "impl/pm_process_manager.hpp"
|
||||
|
||||
extern "C" {
|
||||
extern u32 __start__;
|
||||
|
||||
u32 __nx_applet_type = AppletType_None;
|
||||
|
||||
#define INNER_HEAP_SIZE 0x0
|
||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||
|
||||
void __libnx_initheap(void);
|
||||
void __appInit(void);
|
||||
void __appExit(void);
|
||||
|
||||
/* Exception handling. */
|
||||
alignas(16) u8 __nx_exception_stack[ams::os::MemoryPageSize];
|
||||
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx);
|
||||
|
||||
void *__libnx_alloc(size_t size);
|
||||
void *__libnx_aligned_alloc(size_t alignment, size_t size);
|
||||
void __libnx_free(void *mem);
|
||||
}
|
||||
|
||||
using namespace ams;
|
||||
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
|
||||
ams::CrashHandler(ctx);
|
||||
}
|
||||
|
||||
void __libnx_initheap(void) {
|
||||
void* addr = nx_inner_heap;
|
||||
size_t size = nx_inner_heap_size;
|
||||
|
||||
/* Newlib */
|
||||
extern char* fake_heap_start;
|
||||
extern char* fake_heap_end;
|
||||
|
||||
fake_heap_start = (char*)addr;
|
||||
fake_heap_end = (char*)addr + size;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr u32 PrivilegedFileAccessHeader[0x1C / sizeof(u32)] = {0x00000001, 0x00000000, 0x80000000, 0x0000001C, 0x00000000, 0x0000001C, 0x00000000};
|
||||
constexpr u32 PrivilegedFileAccessControl[0x2C / sizeof(u32)] = {0x00000001, 0x00000000, 0x80000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF};
|
||||
constexpr u8 PrivilegedServiceAccessControl[] = {0x80, '*', 0x00, '*'};
|
||||
constexpr size_t ProcessCountMax = 0x40;
|
||||
|
||||
/* This uses debugging SVCs to retrieve a process's program id. */
|
||||
ncm::ProgramId GetProcessProgramId(os::ProcessId process_id) {
|
||||
/* Get a debug handle. */
|
||||
svc::Handle debug_handle;
|
||||
R_ABORT_UNLESS(svc::DebugActiveProcess(std::addressof(debug_handle), process_id.value));
|
||||
ON_SCOPE_EXIT { R_ABORT_UNLESS(svc::CloseHandle(debug_handle)); };
|
||||
|
||||
/* Loop until we get the event that tells us about the process. */
|
||||
svc::DebugEventInfo d;
|
||||
while (true) {
|
||||
R_ABORT_UNLESS(svc::GetDebugEvent(std::addressof(d), debug_handle));
|
||||
if (d.type == svc::DebugEvent_CreateProcess) {
|
||||
return ncm::ProgramId{d.info.create_process.program_id};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This works around a bug fixed by FS in 4.0.0. */
|
||||
/* Not doing so will cause KIPs with higher process IDs than 7 to be unable to use filesystem services. */
|
||||
/* It also registers privileged processes with SM, so that their program ids can be known. */
|
||||
void RegisterPrivilegedProcess(os::ProcessId process_id, ncm::ProgramId program_id) {
|
||||
fsprUnregisterProgram(process_id.value);
|
||||
fsprRegisterProgram(process_id.value, process_id.value, NcmStorageId_BuiltInSystem, PrivilegedFileAccessHeader, sizeof(PrivilegedFileAccessHeader), PrivilegedFileAccessControl, sizeof(PrivilegedFileAccessControl));
|
||||
sm::manager::UnregisterProcess(process_id);
|
||||
sm::manager::RegisterProcess(process_id, program_id, cfg::OverrideStatus{}, PrivilegedServiceAccessControl, sizeof(PrivilegedServiceAccessControl), PrivilegedServiceAccessControl, sizeof(PrivilegedServiceAccessControl));
|
||||
}
|
||||
|
||||
void RegisterPrivilegedProcesses() {
|
||||
/* Get privileged process range. */
|
||||
os::ProcessId min_priv_process_id = os::InvalidProcessId, max_priv_process_id = os::InvalidProcessId;
|
||||
cfg::GetInitialProcessRange(&min_priv_process_id, &max_priv_process_id);
|
||||
|
||||
/* Get current process id/program id. */
|
||||
const auto cur_process_id = os::GetCurrentProcessId();
|
||||
const auto cur_program_id = os::GetCurrentProgramId();
|
||||
|
||||
/* Get list of processes, register all privileged ones. */
|
||||
s32 num_pids;
|
||||
os::ProcessId pids[ProcessCountMax];
|
||||
R_ABORT_UNLESS(svc::GetProcessList(&num_pids, reinterpret_cast<u64 *>(pids), ProcessCountMax));
|
||||
for (s32 i = 0; i < num_pids; i++) {
|
||||
if (min_priv_process_id <= pids[i] && pids[i] <= max_priv_process_id) {
|
||||
RegisterPrivilegedProcess(pids[i], pids[i] == cur_process_id ? cur_program_id : GetProcessProgramId(pids[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void __appInit(void) {
|
||||
hos::InitializeForStratosphere();
|
||||
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
R_ABORT_UNLESS(fsprInitialize());
|
||||
R_ABORT_UNLESS(smManagerInitialize());
|
||||
|
||||
/* This works around a bug with process permissions on < 4.0.0. */
|
||||
/* It also informs SM of privileged process information. */
|
||||
RegisterPrivilegedProcesses();
|
||||
|
||||
/* Use AMS manager extension to tell SM that FS has been worked around. */
|
||||
R_ABORT_UNLESS(sm::manager::EndInitialDefers());
|
||||
|
||||
R_ABORT_UNLESS(ldrPmInitialize());
|
||||
spl::Initialize();
|
||||
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void __appExit(void) {
|
||||
/* Cleanup services. */
|
||||
spl::Finalize();
|
||||
ldrPmExit();
|
||||
smManagerExit();
|
||||
fsprExit();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/* pm:shell, pm:dmnt, pm:bm, pm:info. */
|
||||
enum PortIndex {
|
||||
PortIndex_Shell,
|
||||
PortIndex_DebugMonitor,
|
||||
PortIndex_BootMode,
|
||||
PortIndex_Information,
|
||||
PortIndex_Count,
|
||||
};
|
||||
|
||||
using ServerOptions = sf::hipc::DefaultServerManagerOptions;
|
||||
|
||||
constexpr sm::ServiceName ShellServiceName = sm::ServiceName::Encode("pm:shell");
|
||||
constexpr size_t ShellMaxSessions = 8; /* Official maximum is 3. */
|
||||
|
||||
constexpr sm::ServiceName DebugMonitorServiceName = sm::ServiceName::Encode("pm:dmnt");
|
||||
constexpr size_t DebugMonitorMaxSessions = 16;
|
||||
|
||||
constexpr sm::ServiceName BootModeServiceName = sm::ServiceName::Encode("pm:bm");
|
||||
constexpr size_t BootModeMaxSessions = 8; /* Official maximum is 4. */
|
||||
|
||||
constexpr sm::ServiceName InformationServiceName = sm::ServiceName::Encode("pm:info");
|
||||
constexpr size_t InformationMaxSessions = 48 - (ShellMaxSessions + DebugMonitorMaxSessions + BootModeMaxSessions);
|
||||
|
||||
static_assert(InformationMaxSessions >= 16, "InformationMaxSessions");
|
||||
|
||||
constexpr size_t MaxSessions = ShellMaxSessions + DebugMonitorMaxSessions + BootModeMaxSessions + InformationMaxSessions;
|
||||
static_assert(MaxSessions == 48, "MaxSessions");
|
||||
|
||||
class ServerManager final : public sf::hipc::ServerManager<PortIndex_Count, ServerOptions, MaxSessions> {
|
||||
private:
|
||||
virtual ams::Result OnNeedsToAccept(int port_index, Server *server) override;
|
||||
};
|
||||
|
||||
ServerManager g_server_manager;
|
||||
|
||||
/* NOTE: Nintendo only uses an unmanaged object for boot mode service, but no pm service has any class members/state, so we'll do it for all. */
|
||||
sf::UnmanagedServiceObject<pm::impl::IShellInterface, pm::ShellService> g_shell_service;
|
||||
sf::UnmanagedServiceObject<pm::impl::IDeprecatedShellInterface, pm::ShellService> g_deprecated_shell_service;
|
||||
|
||||
sf::UnmanagedServiceObject<pm::impl::IDebugMonitorInterface, pm::DebugMonitorService> g_dmnt_service;
|
||||
sf::UnmanagedServiceObject<pm::impl::IDeprecatedDebugMonitorInterface, pm::DebugMonitorService> g_deprecated_dmnt_service;
|
||||
|
||||
sf::UnmanagedServiceObject<pm::impl::IBootModeInterface, pm::BootModeService> g_boot_mode_service;
|
||||
sf::UnmanagedServiceObject<pm::impl::IInformationInterface, pm::InformationService> g_information_service;
|
||||
|
||||
ams::Result ServerManager::OnNeedsToAccept(int port_index, Server *server) {
|
||||
switch (port_index) {
|
||||
case PortIndex_Shell:
|
||||
if (hos::GetVersion() >= hos::Version_5_0_0) {
|
||||
return this->AcceptImpl(server, g_shell_service.GetShared());
|
||||
} else {
|
||||
return this->AcceptImpl(server, g_deprecated_shell_service.GetShared());
|
||||
}
|
||||
case PortIndex_DebugMonitor:
|
||||
if (hos::GetVersion() >= hos::Version_5_0_0) {
|
||||
return this->AcceptImpl(server, g_dmnt_service.GetShared());
|
||||
} else {
|
||||
return this->AcceptImpl(server, g_deprecated_dmnt_service.GetShared());
|
||||
}
|
||||
case PortIndex_BootMode:
|
||||
return this->AcceptImpl(server, g_boot_mode_service.GetShared());
|
||||
case PortIndex_Information:
|
||||
return this->AcceptImpl(server, g_information_service.GetShared());
|
||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace ams {
|
||||
|
||||
void *Malloc(size_t) {
|
||||
AMS_ABORT("ams::Malloc was called");
|
||||
namespace pm {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr u32 PrivilegedFileAccessHeader[0x1C / sizeof(u32)] = {0x00000001, 0x00000000, 0x80000000, 0x0000001C, 0x00000000, 0x0000001C, 0x00000000};
|
||||
constexpr u32 PrivilegedFileAccessControl[0x2C / sizeof(u32)] = {0x00000001, 0x00000000, 0x80000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF};
|
||||
constexpr u8 PrivilegedServiceAccessControl[] = {0x80, '*', 0x00, '*'};
|
||||
constexpr size_t ProcessCountMax = 0x40;
|
||||
|
||||
/* This uses debugging SVCs to retrieve a process's program id. */
|
||||
ncm::ProgramId GetProcessProgramId(os::ProcessId process_id) {
|
||||
/* Get a debug handle. */
|
||||
svc::Handle debug_handle;
|
||||
R_ABORT_UNLESS(svc::DebugActiveProcess(std::addressof(debug_handle), process_id.value));
|
||||
ON_SCOPE_EXIT { R_ABORT_UNLESS(svc::CloseHandle(debug_handle)); };
|
||||
|
||||
/* Loop until we get the event that tells us about the process. */
|
||||
svc::DebugEventInfo d;
|
||||
while (true) {
|
||||
R_ABORT_UNLESS(svc::GetDebugEvent(std::addressof(d), debug_handle));
|
||||
if (d.type == svc::DebugEvent_CreateProcess) {
|
||||
return ncm::ProgramId{d.info.create_process.program_id};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This works around a bug fixed by FS in 4.0.0. */
|
||||
/* Not doing so will cause KIPs with higher process IDs than 7 to be unable to use filesystem services. */
|
||||
/* It also registers privileged processes with SM, so that their program ids can be known. */
|
||||
void RegisterPrivilegedProcess(os::ProcessId process_id, ncm::ProgramId program_id) {
|
||||
fsprUnregisterProgram(process_id.value);
|
||||
fsprRegisterProgram(process_id.value, process_id.value, NcmStorageId_BuiltInSystem, PrivilegedFileAccessHeader, sizeof(PrivilegedFileAccessHeader), PrivilegedFileAccessControl, sizeof(PrivilegedFileAccessControl));
|
||||
sm::manager::UnregisterProcess(process_id);
|
||||
sm::manager::RegisterProcess(process_id, program_id, cfg::OverrideStatus{}, PrivilegedServiceAccessControl, sizeof(PrivilegedServiceAccessControl), PrivilegedServiceAccessControl, sizeof(PrivilegedServiceAccessControl));
|
||||
}
|
||||
|
||||
void RegisterPrivilegedProcesses() {
|
||||
/* Get privileged process range. */
|
||||
os::ProcessId min_priv_process_id = os::InvalidProcessId, max_priv_process_id = os::InvalidProcessId;
|
||||
cfg::GetInitialProcessRange(&min_priv_process_id, &max_priv_process_id);
|
||||
|
||||
/* Get current process id/program id. */
|
||||
const auto cur_process_id = os::GetCurrentProcessId();
|
||||
const auto cur_program_id = os::GetCurrentProgramId();
|
||||
|
||||
/* Get list of processes, register all privileged ones. */
|
||||
s32 num_pids;
|
||||
os::ProcessId pids[ProcessCountMax];
|
||||
R_ABORT_UNLESS(svc::GetProcessList(&num_pids, reinterpret_cast<u64 *>(pids), ProcessCountMax));
|
||||
for (s32 i = 0; i < num_pids; i++) {
|
||||
if (min_priv_process_id <= pids[i] && pids[i] <= max_priv_process_id) {
|
||||
RegisterPrivilegedProcess(pids[i], pids[i] == cur_process_id ? cur_program_id : GetProcessProgramId(pids[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/* pm:shell, pm:dmnt, pm:bm, pm:info. */
|
||||
enum PortIndex {
|
||||
PortIndex_Shell,
|
||||
PortIndex_DebugMonitor,
|
||||
PortIndex_BootMode,
|
||||
PortIndex_Information,
|
||||
PortIndex_Count,
|
||||
};
|
||||
|
||||
using ServerOptions = sf::hipc::DefaultServerManagerOptions;
|
||||
|
||||
constexpr sm::ServiceName ShellServiceName = sm::ServiceName::Encode("pm:shell");
|
||||
constexpr size_t ShellMaxSessions = 8; /* Official maximum is 3. */
|
||||
|
||||
constexpr sm::ServiceName DebugMonitorServiceName = sm::ServiceName::Encode("pm:dmnt");
|
||||
constexpr size_t DebugMonitorMaxSessions = 16;
|
||||
|
||||
constexpr sm::ServiceName BootModeServiceName = sm::ServiceName::Encode("pm:bm");
|
||||
constexpr size_t BootModeMaxSessions = 8; /* Official maximum is 4. */
|
||||
|
||||
constexpr sm::ServiceName InformationServiceName = sm::ServiceName::Encode("pm:info");
|
||||
constexpr size_t InformationMaxSessions = 48 - (ShellMaxSessions + DebugMonitorMaxSessions + BootModeMaxSessions);
|
||||
|
||||
static_assert(InformationMaxSessions >= 16, "InformationMaxSessions");
|
||||
|
||||
constexpr size_t MaxSessions = ShellMaxSessions + DebugMonitorMaxSessions + BootModeMaxSessions + InformationMaxSessions;
|
||||
static_assert(MaxSessions == 48, "MaxSessions");
|
||||
|
||||
class ServerManager final : public sf::hipc::ServerManager<PortIndex_Count, ServerOptions, MaxSessions> {
|
||||
private:
|
||||
virtual ams::Result OnNeedsToAccept(int port_index, Server *server) override;
|
||||
};
|
||||
|
||||
ServerManager g_server_manager;
|
||||
|
||||
/* NOTE: Nintendo only uses an unmanaged object for boot mode service, but no pm service has any class members/state, so we'll do it for all. */
|
||||
sf::UnmanagedServiceObject<pm::impl::IShellInterface, pm::ShellService> g_shell_service;
|
||||
sf::UnmanagedServiceObject<pm::impl::IDeprecatedShellInterface, pm::ShellService> g_deprecated_shell_service;
|
||||
|
||||
sf::UnmanagedServiceObject<pm::impl::IDebugMonitorInterface, pm::DebugMonitorService> g_dmnt_service;
|
||||
sf::UnmanagedServiceObject<pm::impl::IDeprecatedDebugMonitorInterface, pm::DebugMonitorService> g_deprecated_dmnt_service;
|
||||
|
||||
sf::UnmanagedServiceObject<pm::impl::IBootModeInterface, pm::BootModeService> g_boot_mode_service;
|
||||
sf::UnmanagedServiceObject<pm::impl::IInformationInterface, pm::InformationService> g_information_service;
|
||||
|
||||
ams::Result ServerManager::OnNeedsToAccept(int port_index, Server *server) {
|
||||
switch (port_index) {
|
||||
case PortIndex_Shell:
|
||||
if (hos::GetVersion() >= hos::Version_5_0_0) {
|
||||
return this->AcceptImpl(server, g_shell_service.GetShared());
|
||||
} else {
|
||||
return this->AcceptImpl(server, g_deprecated_shell_service.GetShared());
|
||||
}
|
||||
case PortIndex_DebugMonitor:
|
||||
if (hos::GetVersion() >= hos::Version_5_0_0) {
|
||||
return this->AcceptImpl(server, g_dmnt_service.GetShared());
|
||||
} else {
|
||||
return this->AcceptImpl(server, g_deprecated_dmnt_service.GetShared());
|
||||
}
|
||||
case PortIndex_BootMode:
|
||||
return this->AcceptImpl(server, g_boot_mode_service.GetShared());
|
||||
case PortIndex_Information:
|
||||
return this->AcceptImpl(server, g_information_service.GetShared());
|
||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterServices() {
|
||||
/* NOTE: Extra sessions have been added to pm:bm and pm:info to facilitate access by the rest of stratosphere. */
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterServer(PortIndex_Shell, ShellServiceName, ShellMaxSessions));
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterServer(PortIndex_DebugMonitor, DebugMonitorServiceName, DebugMonitorMaxSessions));
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterServer(PortIndex_BootMode, BootModeServiceName, BootModeMaxSessions));
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterServer(PortIndex_Information, InformationServiceName, InformationMaxSessions));
|
||||
}
|
||||
|
||||
void LoopProcess() {
|
||||
g_server_manager.LoopProcess();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Free(void *) {
|
||||
AMS_ABORT("ams::Free was called");
|
||||
namespace init {
|
||||
|
||||
void InitializeSystemModule() {
|
||||
/* Initialize our connection to sm. */
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
/* Initialize manager interfaces for fs and sm. */
|
||||
R_ABORT_UNLESS(fsprInitialize());
|
||||
R_ABORT_UNLESS(smManagerInitialize());
|
||||
|
||||
/* Work around a bug with process permissions on < 4.0.0. */
|
||||
/* This registers all initial processes explicitly with both fs and sm. */
|
||||
pm::RegisterPrivilegedProcesses();
|
||||
|
||||
/* Use our manager extension to tell SM that the FS bug has been worked around. */
|
||||
R_ABORT_UNLESS(sm::manager::EndInitialDefers());
|
||||
|
||||
/* Initialize remaining services we need. */
|
||||
R_ABORT_UNLESS(ldrPmInitialize());
|
||||
spl::Initialize();
|
||||
|
||||
/* Verify that we can sanely execute. */
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void FinalizeSystemModule() { /* ... */ }
|
||||
|
||||
void Startup() { /* ... */ }
|
||||
|
||||
}
|
||||
|
||||
void NORETURN Exit(int rc) {
|
||||
AMS_UNUSED(rc);
|
||||
AMS_ABORT("Exit called by immortal process");
|
||||
}
|
||||
|
||||
void Main() {
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(pm, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(pm, Main));
|
||||
|
||||
/* Initialize process manager implementation. */
|
||||
R_ABORT_UNLESS(pm::impl::InitializeProcessManager());
|
||||
|
||||
/* Create Services. */
|
||||
pm::RegisterServices();
|
||||
|
||||
/* Loop forever, servicing our services. */
|
||||
pm::LoopProcess();
|
||||
|
||||
/* This can never be reached. */
|
||||
AMS_ASSUME(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void *operator new(size_t) {
|
||||
AMS_ABORT("operator new(size_t) was called");
|
||||
}
|
||||
|
||||
void operator delete(void *) {
|
||||
AMS_ABORT("operator delete(void *) was called");
|
||||
}
|
||||
|
||||
void operator delete(void *, size_t) {
|
||||
AMS_ABORT("operator delete(void *, size_t) was called");
|
||||
}
|
||||
|
||||
void *__libnx_alloc(size_t) {
|
||||
AMS_ABORT("__libnx_alloc was called");
|
||||
}
|
||||
|
||||
void *__libnx_aligned_alloc(size_t, size_t) {
|
||||
AMS_ABORT("__libnx_aligned_alloc was called");
|
||||
}
|
||||
|
||||
void __libnx_free(void *) {
|
||||
AMS_ABORT("__libnx_free was called");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
AMS_UNUSED(argc, argv);
|
||||
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(pm, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(pm, Main));
|
||||
|
||||
/* Initialize process manager implementation. */
|
||||
R_ABORT_UNLESS(pm::impl::InitializeProcessManager());
|
||||
|
||||
/* Create Services. */
|
||||
/* NOTE: Extra sessions have been added to pm:bm and pm:info to facilitate access by the rest of stratosphere. */
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterServer(PortIndex_Shell, ShellServiceName, ShellMaxSessions));
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterServer(PortIndex_DebugMonitor, DebugMonitorServiceName, DebugMonitorMaxSessions));
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterServer(PortIndex_BootMode, BootModeServiceName, BootModeMaxSessions));
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterServer(PortIndex_Information, InformationServiceName, InformationMaxSessions));
|
||||
|
||||
/* Loop forever, servicing our services. */
|
||||
g_server_manager.LoopProcess();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -17,209 +17,141 @@
|
||||
#include "ro_debug_monitor_service.hpp"
|
||||
#include "ro_ro_service.hpp"
|
||||
|
||||
extern "C" {
|
||||
extern u32 __start__;
|
||||
|
||||
u32 __nx_applet_type = AppletType_None;
|
||||
u32 __nx_fs_num_sessions = 1;
|
||||
|
||||
#define INNER_HEAP_SIZE 0x0
|
||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||
|
||||
void __libnx_initheap(void);
|
||||
void __appInit(void);
|
||||
void __appExit(void);
|
||||
|
||||
void *__libnx_alloc(size_t size);
|
||||
void *__libnx_aligned_alloc(size_t alignment, size_t size);
|
||||
void __libnx_free(void *mem);
|
||||
}
|
||||
|
||||
using namespace ams;
|
||||
|
||||
namespace ams::ro {
|
||||
|
||||
namespace {
|
||||
|
||||
/* ldr:ro, ro:dmnt, ro:1. */
|
||||
enum PortIndex {
|
||||
PortIndex_DebugMonitor,
|
||||
PortIndex_User,
|
||||
PortIndex_JitPlugin,
|
||||
PortIndex_Count,
|
||||
};
|
||||
|
||||
constexpr sm::ServiceName DebugMonitorServiceName = sm::ServiceName::Encode("ro:dmnt");
|
||||
constexpr size_t DebugMonitorMaxSessions = 2;
|
||||
|
||||
/* NOTE: Official code passes 32 for ldr:ro max sessions. We will pass 2, because that's the actual limit. */
|
||||
constexpr sm::ServiceName UserServiceName = sm::ServiceName::Encode("ldr:ro");
|
||||
constexpr size_t UserMaxSessions = 2;
|
||||
|
||||
constexpr sm::ServiceName JitPluginServiceName = sm::ServiceName::Encode("ro:1");
|
||||
constexpr size_t JitPluginMaxSessions = 2;
|
||||
|
||||
static constexpr size_t MaxSessions = DebugMonitorMaxSessions + UserMaxSessions + JitPluginMaxSessions;
|
||||
|
||||
using ServerOptions = sf::hipc::DefaultServerManagerOptions;
|
||||
|
||||
class ServerManager final : public sf::hipc::ServerManager<PortIndex_Count, ServerOptions, MaxSessions> {
|
||||
private:
|
||||
virtual ams::Result OnNeedsToAccept(int port_index, Server *server) override;
|
||||
};
|
||||
|
||||
using Allocator = sf::ExpHeapAllocator;
|
||||
using ObjectFactory = sf::ObjectFactory<sf::ExpHeapAllocator::Policy>;
|
||||
|
||||
alignas(0x40) constinit u8 g_server_allocator_buffer[4_KB];
|
||||
lmem::HeapHandle g_server_heap_handle;
|
||||
Allocator g_server_allocator;
|
||||
|
||||
ServerManager g_server_manager;
|
||||
|
||||
ams::Result ServerManager::OnNeedsToAccept(int port_index, Server *server) {
|
||||
switch (port_index) {
|
||||
case PortIndex_DebugMonitor:
|
||||
return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced<ro::impl::IDebugMonitorInterface, ro::DebugMonitorService>(std::addressof(g_server_allocator)));
|
||||
case PortIndex_User:
|
||||
return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced<ro::impl::IRoInterface, ro::RoService>(std::addressof(g_server_allocator), ro::NrrKind_User));
|
||||
case PortIndex_JitPlugin:
|
||||
return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced<ro::impl::IRoInterface, ro::RoService>(std::addressof(g_server_allocator), ro::NrrKind_JitPlugin));
|
||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
}
|
||||
|
||||
void *Allocate(size_t size) {
|
||||
return lmem::AllocateFromExpHeap(g_server_heap_handle, size);
|
||||
}
|
||||
|
||||
void Deallocate(void *p, size_t size) {
|
||||
AMS_UNUSED(size);
|
||||
|
||||
return lmem::FreeToExpHeap(g_server_heap_handle, p);
|
||||
}
|
||||
|
||||
void InitializeHeap() {
|
||||
/* Setup server allocator. */
|
||||
g_server_heap_handle = lmem::CreateExpHeap(g_server_allocator_buffer, sizeof(g_server_allocator_buffer), lmem::CreateOption_None);
|
||||
}
|
||||
|
||||
void LoopServer() {
|
||||
/* Create services. */
|
||||
R_ABORT_UNLESS(ro::g_server_manager.RegisterServer(PortIndex_DebugMonitor, DebugMonitorServiceName, DebugMonitorMaxSessions));
|
||||
|
||||
R_ABORT_UNLESS(ro::g_server_manager.RegisterServer(PortIndex_User, UserServiceName, UserMaxSessions));
|
||||
if (hos::GetVersion() >= hos::Version_7_0_0) {
|
||||
R_ABORT_UNLESS(ro::g_server_manager.RegisterServer(PortIndex_JitPlugin, JitPluginServiceName, JitPluginMaxSessions));
|
||||
}
|
||||
|
||||
/* Loop forever, servicing our services. */
|
||||
ro::g_server_manager.LoopProcess();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void __libnx_initheap(void) {
|
||||
void* addr = nx_inner_heap;
|
||||
size_t size = nx_inner_heap_size;
|
||||
|
||||
/* Newlib */
|
||||
extern char* fake_heap_start;
|
||||
extern char* fake_heap_end;
|
||||
|
||||
fake_heap_start = (char*)addr;
|
||||
fake_heap_end = (char*)addr + size;
|
||||
|
||||
ams::ro::InitializeHeap();
|
||||
}
|
||||
|
||||
void __appInit(void) {
|
||||
hos::InitializeForStratosphere();
|
||||
|
||||
fs::SetAllocator(ro::Allocate, ro::Deallocate);
|
||||
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
R_ABORT_UNLESS(setsysInitialize());
|
||||
R_ABORT_UNLESS(fsInitialize());
|
||||
spl::Initialize();
|
||||
|
||||
R_ABORT_UNLESS(fs::MountSdCard("sdmc"));
|
||||
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void __appExit(void) {
|
||||
fsExit();
|
||||
|
||||
setsysExit();
|
||||
}
|
||||
|
||||
namespace ams {
|
||||
|
||||
void *Malloc(size_t) {
|
||||
AMS_ABORT("ams::Malloc was called");
|
||||
namespace ro {
|
||||
|
||||
namespace {
|
||||
|
||||
/* ldr:ro, ro:dmnt, ro:1. */
|
||||
enum PortIndex {
|
||||
PortIndex_DebugMonitor,
|
||||
PortIndex_User,
|
||||
PortIndex_JitPlugin,
|
||||
PortIndex_Count,
|
||||
};
|
||||
|
||||
constexpr sm::ServiceName DebugMonitorServiceName = sm::ServiceName::Encode("ro:dmnt");
|
||||
constexpr size_t DebugMonitorMaxSessions = 2;
|
||||
|
||||
/* NOTE: Official code passes 32 for ldr:ro max sessions. We will pass 2, because that's the actual limit. */
|
||||
constexpr sm::ServiceName UserServiceName = sm::ServiceName::Encode("ldr:ro");
|
||||
constexpr size_t UserMaxSessions = 2;
|
||||
|
||||
constexpr sm::ServiceName JitPluginServiceName = sm::ServiceName::Encode("ro:1");
|
||||
constexpr size_t JitPluginMaxSessions = 2;
|
||||
|
||||
static constexpr size_t MaxSessions = DebugMonitorMaxSessions + UserMaxSessions + JitPluginMaxSessions;
|
||||
|
||||
using ServerOptions = sf::hipc::DefaultServerManagerOptions;
|
||||
|
||||
class ServerManager final : public sf::hipc::ServerManager<PortIndex_Count, ServerOptions, MaxSessions> {
|
||||
private:
|
||||
virtual ams::Result OnNeedsToAccept(int port_index, Server *server) override;
|
||||
};
|
||||
|
||||
using Allocator = sf::ExpHeapAllocator;
|
||||
using ObjectFactory = sf::ObjectFactory<sf::ExpHeapAllocator::Policy>;
|
||||
|
||||
alignas(0x40) constinit u8 g_server_allocator_buffer[4_KB];
|
||||
lmem::HeapHandle g_server_heap_handle;
|
||||
Allocator g_server_allocator;
|
||||
|
||||
ServerManager g_server_manager;
|
||||
|
||||
ams::Result ServerManager::OnNeedsToAccept(int port_index, Server *server) {
|
||||
switch (port_index) {
|
||||
case PortIndex_DebugMonitor:
|
||||
return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced<ro::impl::IDebugMonitorInterface, ro::DebugMonitorService>(std::addressof(g_server_allocator)));
|
||||
case PortIndex_User:
|
||||
return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced<ro::impl::IRoInterface, ro::RoService>(std::addressof(g_server_allocator), ro::NrrKind_User));
|
||||
case PortIndex_JitPlugin:
|
||||
return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced<ro::impl::IRoInterface, ro::RoService>(std::addressof(g_server_allocator), ro::NrrKind_JitPlugin));
|
||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
}
|
||||
|
||||
void *Allocate(size_t size) {
|
||||
return lmem::AllocateFromExpHeap(g_server_heap_handle, size);
|
||||
}
|
||||
|
||||
void Deallocate(void *p, size_t size) {
|
||||
AMS_UNUSED(size);
|
||||
|
||||
return lmem::FreeToExpHeap(g_server_heap_handle, p);
|
||||
}
|
||||
|
||||
void InitializeHeap() {
|
||||
/* Setup server allocator. */
|
||||
g_server_heap_handle = lmem::CreateExpHeap(g_server_allocator_buffer, sizeof(g_server_allocator_buffer), lmem::CreateOption_None);
|
||||
}
|
||||
|
||||
void LoopServer() {
|
||||
/* Create services. */
|
||||
R_ABORT_UNLESS(ro::g_server_manager.RegisterServer(PortIndex_DebugMonitor, DebugMonitorServiceName, DebugMonitorMaxSessions));
|
||||
|
||||
R_ABORT_UNLESS(ro::g_server_manager.RegisterServer(PortIndex_User, UserServiceName, UserMaxSessions));
|
||||
if (hos::GetVersion() >= hos::Version_7_0_0) {
|
||||
R_ABORT_UNLESS(ro::g_server_manager.RegisterServer(PortIndex_JitPlugin, JitPluginServiceName, JitPluginMaxSessions));
|
||||
}
|
||||
|
||||
/* Loop forever, servicing our services. */
|
||||
ro::g_server_manager.LoopProcess();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Free(void *) {
|
||||
AMS_ABORT("ams::Free was called");
|
||||
namespace init {
|
||||
|
||||
void InitializeSystemModule() {
|
||||
/* Initialize heap. */
|
||||
ro::InitializeHeap();
|
||||
|
||||
/* Initialize our connection to sm. */
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
/* Initialize fs. */
|
||||
fs::InitializeForSystem();
|
||||
fs::SetAllocator(ro::Allocate, ro::Deallocate);
|
||||
fs::SetEnabledAutoAbort(false);
|
||||
|
||||
/* Initialize other services we need. */
|
||||
R_ABORT_UNLESS(setsysInitialize());
|
||||
|
||||
/* Mount the SD card. */
|
||||
R_ABORT_UNLESS(fs::MountSdCard("sdmc"));
|
||||
|
||||
/* Verify that we can sanely execute. */
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void FinalizeSystemModule() { /* ... */ }
|
||||
|
||||
void Startup() { /* ... */ }
|
||||
|
||||
}
|
||||
|
||||
void Main() {
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(ro, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(ro, Main));
|
||||
|
||||
/* Attach the server allocator. */
|
||||
ro::g_server_allocator.Attach(ro::g_server_heap_handle);
|
||||
|
||||
/* Initialize Debug config. */
|
||||
{
|
||||
spl::Initialize();
|
||||
ON_SCOPE_EXIT { spl::Finalize(); };
|
||||
|
||||
ro::SetDevelopmentHardware(spl::IsDevelopment());
|
||||
ro::SetDevelopmentFunctionEnabled(spl::IsDevelopmentFunctionEnabled());
|
||||
}
|
||||
|
||||
/* Run the ro server. */
|
||||
ro::LoopServer();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void *operator new(size_t) {
|
||||
AMS_ABORT("operator new(size_t) was called");
|
||||
}
|
||||
|
||||
void operator delete(void *) {
|
||||
AMS_ABORT("operator delete(void *) was called");
|
||||
}
|
||||
|
||||
void operator delete(void *, size_t) {
|
||||
AMS_ABORT("operator delete(void *, size_t) was called");
|
||||
}
|
||||
|
||||
void *__libnx_alloc(size_t) {
|
||||
AMS_ABORT("__libnx_alloc was called");
|
||||
}
|
||||
|
||||
void *__libnx_aligned_alloc(size_t, size_t) {
|
||||
AMS_ABORT("__libnx_aligned_alloc was called");
|
||||
}
|
||||
|
||||
void __libnx_free(void *) {
|
||||
AMS_ABORT("__libnx_free was called");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
AMS_UNUSED(argc, argv);
|
||||
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(ro, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(ro, Main));
|
||||
|
||||
/* Attach the server allocator. */
|
||||
ro::g_server_allocator.Attach(ro::g_server_heap_handle);
|
||||
|
||||
/* Disable auto-abort in fs operations. */
|
||||
fs::SetEnabledAutoAbort(false);
|
||||
|
||||
/* Initialize Debug config. */
|
||||
{
|
||||
ON_SCOPE_EXIT { spl::Finalize(); };
|
||||
|
||||
ro::SetDevelopmentHardware(spl::IsDevelopment());
|
||||
ro::SetDevelopmentFunctionEnabled(spl::IsDevelopmentFunctionEnabled());
|
||||
}
|
||||
|
||||
/* Run the ro server. */
|
||||
ro::LoopServer();
|
||||
|
||||
/* Cleanup */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -16,121 +16,36 @@
|
||||
#include <stratosphere.hpp>
|
||||
#include "sm_tipc_server.hpp"
|
||||
|
||||
extern "C" {
|
||||
extern u32 __start__;
|
||||
|
||||
extern int __system_argc;
|
||||
extern char** __system_argv;
|
||||
|
||||
u32 __nx_applet_type = AppletType_None;
|
||||
|
||||
#define INNER_HEAP_SIZE 0x0
|
||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||
|
||||
void __libnx_initheap(void);
|
||||
void argvSetup(void);
|
||||
void __appInit(void);
|
||||
void __appExit(void);
|
||||
|
||||
/* Exception handling. */
|
||||
alignas(16) u8 __nx_exception_stack[ams::os::MemoryPageSize];
|
||||
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx);
|
||||
|
||||
void *__libnx_alloc(size_t size);
|
||||
void *__libnx_aligned_alloc(size_t alignment, size_t size);
|
||||
void __libnx_free(void *mem);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
constinit char *g_empty_argv = nullptr;
|
||||
|
||||
}
|
||||
|
||||
namespace ams {
|
||||
|
||||
namespace init {
|
||||
|
||||
void InitializeSystemModule() { /* ... */ }
|
||||
|
||||
void FinalizeSystemModule() { /* ... */ }
|
||||
|
||||
void Startup() { /* ... */ }
|
||||
|
||||
}
|
||||
|
||||
void NORETURN Exit(int rc) {
|
||||
AMS_UNUSED(rc);
|
||||
AMS_ABORT("Exit called by immortal process");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
using namespace ams;
|
||||
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
|
||||
ams::CrashHandler(ctx);
|
||||
}
|
||||
|
||||
|
||||
void __libnx_initheap(void) {
|
||||
void* addr = nx_inner_heap;
|
||||
size_t size = nx_inner_heap_size;
|
||||
|
||||
/* Newlib */
|
||||
extern char* fake_heap_start;
|
||||
extern char* fake_heap_end;
|
||||
|
||||
fake_heap_start = (char*)addr;
|
||||
fake_heap_end = (char*)addr + size;
|
||||
}
|
||||
|
||||
void argvSetup(void) {
|
||||
/* We don't need argc/argv, so set them to empty defaults. */
|
||||
__system_argc = 0;
|
||||
__system_argv = std::addressof(g_empty_argv);
|
||||
}
|
||||
|
||||
void __appInit(void) {
|
||||
hos::InitializeForStratosphere();
|
||||
|
||||
/* We must do no service setup here, because we are sm. */
|
||||
}
|
||||
|
||||
void __appExit(void) {
|
||||
/* Nothing to clean up, because we're sm. */
|
||||
}
|
||||
|
||||
void *operator new(size_t) {
|
||||
AMS_ABORT("operator new(size_t) was called");
|
||||
}
|
||||
|
||||
void operator delete(void *) {
|
||||
AMS_ABORT("operator delete(void *) was called");
|
||||
}
|
||||
|
||||
void operator delete(void *, size_t) {
|
||||
AMS_ABORT("operator delete(void *, size_t) was called");
|
||||
}
|
||||
|
||||
void *__libnx_alloc(size_t) {
|
||||
AMS_ABORT("__libnx_alloc was called");
|
||||
}
|
||||
|
||||
void *__libnx_aligned_alloc(size_t, size_t) {
|
||||
AMS_ABORT("__libnx_aligned_alloc was called");
|
||||
}
|
||||
|
||||
void __libnx_free(void *) {
|
||||
AMS_ABORT("__libnx_free was called");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
AMS_UNUSED(argc, argv);
|
||||
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(sm, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(sm, Main));
|
||||
|
||||
/* Initialize the server. */
|
||||
sm::InitializeTipcServer();
|
||||
|
||||
/* Loop forever, processing our services. */
|
||||
sm::LoopProcessTipcServer();
|
||||
|
||||
/* This can never be reached. */
|
||||
AMS_ASSUME(false);
|
||||
void Main() {
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(sm, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(sm, Main));
|
||||
|
||||
/* Initialize the server. */
|
||||
sm::InitializeTipcServer();
|
||||
|
||||
/* Loop forever, processing our services. */
|
||||
sm::LoopProcessTipcServer();
|
||||
|
||||
/* This can never be reached. */
|
||||
AMS_ASSUME(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -26,221 +26,163 @@
|
||||
|
||||
#include "spl_deprecated_service.hpp"
|
||||
|
||||
extern "C" {
|
||||
extern u32 __start__;
|
||||
|
||||
u32 __nx_applet_type = AppletType_None;
|
||||
|
||||
#define INNER_HEAP_SIZE 0x0
|
||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||
|
||||
void __libnx_initheap(void);
|
||||
void __appInit(void);
|
||||
void __appExit(void);
|
||||
|
||||
/* Exception handling. */
|
||||
alignas(16) u8 __nx_exception_stack[ams::os::MemoryPageSize];
|
||||
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx);
|
||||
|
||||
void *__libnx_alloc(size_t size);
|
||||
void *__libnx_aligned_alloc(size_t alignment, size_t size);
|
||||
void __libnx_free(void *mem);
|
||||
}
|
||||
|
||||
using namespace ams;
|
||||
|
||||
void __libnx_exception_handler(ThreadExceptionDump *ctx) {
|
||||
ams::CrashHandler(ctx);
|
||||
}
|
||||
|
||||
void __libnx_initheap(void) {
|
||||
void* addr = nx_inner_heap;
|
||||
size_t size = nx_inner_heap_size;
|
||||
|
||||
/* Newlib */
|
||||
extern char* fake_heap_start;
|
||||
extern char* fake_heap_end;
|
||||
|
||||
fake_heap_start = (char*)addr;
|
||||
fake_heap_end = (char*)addr + size;
|
||||
}
|
||||
|
||||
void __appInit(void) {
|
||||
hos::InitializeForStratosphere();
|
||||
|
||||
/* SPL doesn't really access any services... */
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void __appExit(void) {
|
||||
/* SPL doesn't really access any services... */
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
struct SplServerOptions {
|
||||
static constexpr size_t PointerBufferSize = 0x800;
|
||||
static constexpr size_t MaxDomains = 0;
|
||||
static constexpr size_t MaxDomainObjects = 0;
|
||||
};
|
||||
|
||||
enum PortIndex {
|
||||
PortIndex_General,
|
||||
PortIndex_Random,
|
||||
PortIndex_Crypto,
|
||||
PortIndex_Fs,
|
||||
PortIndex_Ssl,
|
||||
PortIndex_Es,
|
||||
PortIndex_Manu,
|
||||
PortIndex_Count,
|
||||
};
|
||||
|
||||
constexpr sm::ServiceName RandomServiceName = sm::ServiceName::Encode("csrng");
|
||||
constexpr size_t RandomMaxSessions = 3;
|
||||
|
||||
constexpr sm::ServiceName GeneralServiceName = sm::ServiceName::Encode("spl:");
|
||||
constexpr size_t DeprecatedMaxSessions = 13;
|
||||
constexpr size_t GeneralMaxSessions = 7;
|
||||
|
||||
constexpr sm::ServiceName CryptoServiceName = sm::ServiceName::Encode("spl:mig");
|
||||
constexpr size_t CryptoMaxSessions = 7;
|
||||
|
||||
constexpr sm::ServiceName SslServiceName = sm::ServiceName::Encode("spl:ssl");
|
||||
constexpr size_t SslMaxSessions = 2;
|
||||
|
||||
constexpr sm::ServiceName EsServiceName = sm::ServiceName::Encode("spl:es");
|
||||
constexpr size_t EsMaxSessions = 2;
|
||||
|
||||
constexpr sm::ServiceName FsServiceName = sm::ServiceName::Encode("spl:fs");
|
||||
constexpr size_t FsMaxSessions = 3;
|
||||
|
||||
constexpr sm::ServiceName ManuServiceName = sm::ServiceName::Encode("spl:manu");
|
||||
constexpr size_t ManuMaxSessions = 1;
|
||||
|
||||
/* csrng, spl:, spl:mig, spl:ssl, spl:es, spl:fs, spl:manu. */
|
||||
/* TODO: Consider max sessions enforcement? */
|
||||
constexpr size_t ModernMaxSessions = GeneralMaxSessions + CryptoMaxSessions + SslMaxSessions + EsMaxSessions + FsMaxSessions + ManuMaxSessions;
|
||||
constexpr size_t NumSessions = RandomMaxSessions + std::max(DeprecatedMaxSessions, ModernMaxSessions) + 1;
|
||||
|
||||
class ServerManager final : public sf::hipc::ServerManager<PortIndex_Count, SplServerOptions, NumSessions> {
|
||||
private:
|
||||
sf::ExpHeapAllocator *m_allocator;
|
||||
spl::GeneralService m_general_service;
|
||||
sf::UnmanagedServiceObjectByPointer<spl::impl::IGeneralInterface, spl::GeneralService> m_general_service_object;
|
||||
spl::RandomService m_random_service;
|
||||
sf::UnmanagedServiceObjectByPointer<spl::impl::IRandomInterface, spl::RandomService> m_random_service_object;
|
||||
public:
|
||||
ServerManager(sf::ExpHeapAllocator *allocator) : m_allocator(allocator), m_general_service(), m_general_service_object(std::addressof(m_general_service)), m_random_service(), m_random_service_object(std::addressof(m_random_service)) {
|
||||
/* ... */
|
||||
}
|
||||
private:
|
||||
virtual ams::Result OnNeedsToAccept(int port_index, Server *server) override;
|
||||
};
|
||||
|
||||
using Allocator = sf::ExpHeapAllocator;
|
||||
using ObjectFactory = sf::ObjectFactory<sf::ExpHeapAllocator::Policy>;
|
||||
|
||||
alignas(0x40) constinit u8 g_server_allocator_buffer[8_KB];
|
||||
Allocator g_server_allocator;
|
||||
|
||||
ServerManager g_server_manager(std::addressof(g_server_allocator));
|
||||
|
||||
ams::Result ServerManager::OnNeedsToAccept(int port_index, Server *server) {
|
||||
switch (port_index) {
|
||||
case PortIndex_General:
|
||||
if (hos::GetVersion() >= hos::Version_4_0_0) {
|
||||
return this->AcceptImpl(server, m_general_service_object.GetShared());
|
||||
} else {
|
||||
return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced<spl::impl::IDeprecatedGeneralInterface, spl::DeprecatedService>(m_allocator));
|
||||
}
|
||||
case PortIndex_Random:
|
||||
return this->AcceptImpl(server, m_random_service_object.GetShared());
|
||||
case PortIndex_Crypto:
|
||||
return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced<spl::impl::ICryptoInterface, spl::CryptoService>(m_allocator));
|
||||
case PortIndex_Fs:
|
||||
return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced<spl::impl::IFsInterface, spl::FsService>(m_allocator));
|
||||
case PortIndex_Ssl:
|
||||
return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced<spl::impl::ISslInterface, spl::SslService>(m_allocator));
|
||||
case PortIndex_Es:
|
||||
return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced<spl::impl::IEsInterface, spl::EsService>(m_allocator));
|
||||
case PortIndex_Manu:
|
||||
return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced<spl::impl::IManuInterface, spl::ManuService>(m_allocator));
|
||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace ams {
|
||||
|
||||
void *Malloc(size_t) {
|
||||
AMS_ABORT("ams::Malloc was called");
|
||||
}
|
||||
namespace spl {
|
||||
|
||||
void Free(void *) {
|
||||
AMS_ABORT("ams::Free was called");
|
||||
}
|
||||
namespace {
|
||||
|
||||
}
|
||||
struct SplServerOptions {
|
||||
static constexpr size_t PointerBufferSize = 0x800;
|
||||
static constexpr size_t MaxDomains = 0;
|
||||
static constexpr size_t MaxDomainObjects = 0;
|
||||
};
|
||||
|
||||
void *operator new(size_t) {
|
||||
AMS_ABORT("operator new(size_t) was called");
|
||||
}
|
||||
enum PortIndex {
|
||||
PortIndex_General,
|
||||
PortIndex_Random,
|
||||
PortIndex_Crypto,
|
||||
PortIndex_Fs,
|
||||
PortIndex_Ssl,
|
||||
PortIndex_Es,
|
||||
PortIndex_Manu,
|
||||
PortIndex_Count,
|
||||
};
|
||||
|
||||
void operator delete(void *) {
|
||||
AMS_ABORT("operator delete(void *) was called");
|
||||
}
|
||||
constexpr sm::ServiceName RandomServiceName = sm::ServiceName::Encode("csrng");
|
||||
constexpr size_t RandomMaxSessions = 3;
|
||||
|
||||
void operator delete(void *, size_t) {
|
||||
AMS_ABORT("operator delete(void *, size_t) was called");
|
||||
}
|
||||
constexpr sm::ServiceName GeneralServiceName = sm::ServiceName::Encode("spl:");
|
||||
constexpr size_t DeprecatedMaxSessions = 13;
|
||||
constexpr size_t GeneralMaxSessions = 7;
|
||||
|
||||
void *__libnx_alloc(size_t) {
|
||||
AMS_ABORT("__libnx_alloc was called");
|
||||
}
|
||||
constexpr sm::ServiceName CryptoServiceName = sm::ServiceName::Encode("spl:mig");
|
||||
constexpr size_t CryptoMaxSessions = 7;
|
||||
|
||||
void *__libnx_aligned_alloc(size_t, size_t) {
|
||||
AMS_ABORT("__libnx_aligned_alloc was called");
|
||||
}
|
||||
constexpr sm::ServiceName SslServiceName = sm::ServiceName::Encode("spl:ssl");
|
||||
constexpr size_t SslMaxSessions = 2;
|
||||
|
||||
void __libnx_free(void *) {
|
||||
AMS_ABORT("__libnx_free was called");
|
||||
}
|
||||
constexpr sm::ServiceName EsServiceName = sm::ServiceName::Encode("spl:es");
|
||||
constexpr size_t EsMaxSessions = 2;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
AMS_UNUSED(argc, argv);
|
||||
constexpr sm::ServiceName FsServiceName = sm::ServiceName::Encode("spl:fs");
|
||||
constexpr size_t FsMaxSessions = 3;
|
||||
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(spl, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(spl, Main));
|
||||
constexpr sm::ServiceName ManuServiceName = sm::ServiceName::Encode("spl:manu");
|
||||
constexpr size_t ManuMaxSessions = 1;
|
||||
|
||||
/* Setup server allocator. */
|
||||
g_server_allocator.Attach(lmem::CreateExpHeap(g_server_allocator_buffer, sizeof(g_server_allocator_buffer), lmem::CreateOption_None));
|
||||
/* csrng, spl:, spl:mig, spl:ssl, spl:es, spl:fs, spl:manu. */
|
||||
/* TODO: Consider max sessions enforcement? */
|
||||
constexpr size_t ModernMaxSessions = GeneralMaxSessions + CryptoMaxSessions + SslMaxSessions + EsMaxSessions + FsMaxSessions + ManuMaxSessions;
|
||||
constexpr size_t NumSessions = RandomMaxSessions + std::max(DeprecatedMaxSessions, ModernMaxSessions) + 1;
|
||||
|
||||
/* Initialize global context. */
|
||||
spl::impl::Initialize();
|
||||
class ServerManager final : public sf::hipc::ServerManager<PortIndex_Count, SplServerOptions, NumSessions> {
|
||||
private:
|
||||
sf::ExpHeapAllocator *m_allocator;
|
||||
spl::GeneralService m_general_service;
|
||||
sf::UnmanagedServiceObjectByPointer<spl::impl::IGeneralInterface, spl::GeneralService> m_general_service_object;
|
||||
spl::RandomService m_random_service;
|
||||
sf::UnmanagedServiceObjectByPointer<spl::impl::IRandomInterface, spl::RandomService> m_random_service_object;
|
||||
public:
|
||||
ServerManager(sf::ExpHeapAllocator *allocator) : m_allocator(allocator), m_general_service(), m_general_service_object(std::addressof(m_general_service)), m_random_service(), m_random_service_object(std::addressof(m_random_service)) {
|
||||
/* ... */
|
||||
}
|
||||
private:
|
||||
virtual ams::Result OnNeedsToAccept(int port_index, Server *server) override;
|
||||
};
|
||||
|
||||
using Allocator = sf::ExpHeapAllocator;
|
||||
using ObjectFactory = sf::ObjectFactory<sf::ExpHeapAllocator::Policy>;
|
||||
|
||||
alignas(0x40) constinit u8 g_server_allocator_buffer[8_KB];
|
||||
Allocator g_server_allocator;
|
||||
|
||||
ServerManager g_server_manager(std::addressof(g_server_allocator));
|
||||
|
||||
ams::Result ServerManager::OnNeedsToAccept(int port_index, Server *server) {
|
||||
switch (port_index) {
|
||||
case PortIndex_General:
|
||||
if (hos::GetVersion() >= hos::Version_4_0_0) {
|
||||
return this->AcceptImpl(server, m_general_service_object.GetShared());
|
||||
} else {
|
||||
return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced<spl::impl::IDeprecatedGeneralInterface, spl::DeprecatedService>(m_allocator));
|
||||
}
|
||||
case PortIndex_Random:
|
||||
return this->AcceptImpl(server, m_random_service_object.GetShared());
|
||||
case PortIndex_Crypto:
|
||||
return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced<spl::impl::ICryptoInterface, spl::CryptoService>(m_allocator));
|
||||
case PortIndex_Fs:
|
||||
return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced<spl::impl::IFsInterface, spl::FsService>(m_allocator));
|
||||
case PortIndex_Ssl:
|
||||
return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced<spl::impl::ISslInterface, spl::SslService>(m_allocator));
|
||||
case PortIndex_Es:
|
||||
return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced<spl::impl::IEsInterface, spl::EsService>(m_allocator));
|
||||
case PortIndex_Manu:
|
||||
return this->AcceptImpl(server, ObjectFactory::CreateSharedEmplaced<spl::impl::IManuInterface, spl::ManuService>(m_allocator));
|
||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
}
|
||||
|
||||
void SplMain() {
|
||||
/* Setup server allocator. */
|
||||
g_server_allocator.Attach(lmem::CreateExpHeap(g_server_allocator_buffer, sizeof(g_server_allocator_buffer), lmem::CreateOption_None));
|
||||
|
||||
/* Initialize global context. */
|
||||
spl::impl::Initialize();
|
||||
|
||||
/* Create services. */
|
||||
const auto fw_ver = hos::GetVersion();
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterServer(PortIndex_General, GeneralServiceName, fw_ver >= hos::Version_4_0_0 ? GeneralMaxSessions : DeprecatedMaxSessions));
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterServer(PortIndex_Random, RandomServiceName, RandomMaxSessions));
|
||||
if (fw_ver >= hos::Version_4_0_0) {
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterServer(PortIndex_Crypto, CryptoServiceName, CryptoMaxSessions));
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterServer(PortIndex_Fs, FsServiceName, FsMaxSessions));
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterServer(PortIndex_Ssl, SslServiceName, SslMaxSessions));
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterServer(PortIndex_Es, EsServiceName, EsMaxSessions));
|
||||
if (fw_ver >= hos::Version_5_0_0) {
|
||||
g_server_manager.RegisterServer(PortIndex_Manu, ManuServiceName, ManuMaxSessions);
|
||||
}
|
||||
}
|
||||
|
||||
/* Loop forever, servicing our services. */
|
||||
g_server_manager.LoopProcess();
|
||||
}
|
||||
|
||||
/* Create services. */
|
||||
const auto fw_ver = hos::GetVersion();
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterServer(PortIndex_General, GeneralServiceName, fw_ver >= hos::Version_4_0_0 ? GeneralMaxSessions : DeprecatedMaxSessions));
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterServer(PortIndex_Random, RandomServiceName, RandomMaxSessions));
|
||||
if (fw_ver >= hos::Version_4_0_0) {
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterServer(PortIndex_Crypto, CryptoServiceName, CryptoMaxSessions));
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterServer(PortIndex_Fs, FsServiceName, FsMaxSessions));
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterServer(PortIndex_Ssl, SslServiceName, SslMaxSessions));
|
||||
R_ABORT_UNLESS(g_server_manager.RegisterServer(PortIndex_Es, EsServiceName, EsMaxSessions));
|
||||
if (fw_ver >= hos::Version_5_0_0) {
|
||||
g_server_manager.RegisterServer(PortIndex_Manu, ManuServiceName, ManuMaxSessions);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Loop forever, servicing our services. */
|
||||
g_server_manager.LoopProcess();
|
||||
namespace init {
|
||||
|
||||
void InitializeSystemModule() {
|
||||
/* Initialize our connection to sm. */
|
||||
R_ABORT_UNLESS(sm::Initialize());
|
||||
|
||||
/* Verify that we can sanely execute. */
|
||||
ams::CheckApiVersion();
|
||||
}
|
||||
|
||||
void FinalizeSystemModule() { /* ... */ }
|
||||
|
||||
void Startup() { /* ... */ }
|
||||
|
||||
}
|
||||
|
||||
void NORETURN Exit(int rc) {
|
||||
AMS_UNUSED(rc);
|
||||
AMS_ABORT("Exit called by immortal process");
|
||||
}
|
||||
|
||||
void Main() {
|
||||
/* Set thread name. */
|
||||
os::SetThreadNamePointer(os::GetCurrentThread(), AMS_GET_SYSTEM_THREAD_NAME(spl, Main));
|
||||
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(spl, Main));
|
||||
|
||||
/* Invoke SPL main. */
|
||||
spl::SplMain();
|
||||
|
||||
/* This can never be reached. */
|
||||
AMS_ASSUME(false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user