erpt: reimplement the sysmodule (#875)

* erpt: reimplement the sysmodule

* fatal: update for latest bindings

* erpt: amend logic for culling orphan attachments
This commit is contained in:
SciresM
2020-04-13 17:07:37 -07:00
committed by GitHub
parent eca5ac01b8
commit 79b9e07ee9
117 changed files with 6716 additions and 59 deletions

128
stratosphere/erpt/Makefile Normal file
View File

@@ -0,0 +1,128 @@
#---------------------------------------------------------------------------------
# pull in common stratosphere sysmodule configuration
#---------------------------------------------------------------------------------
include $(dir $(abspath $(lastword $(MAKEFILE_LIST))))/../../libraries/config/templates/stratosphere.mk
#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
# rules for different file extensions
#---------------------------------------------------------------------------------
ifneq ($(BUILD),$(notdir $(CURDIR)))
#---------------------------------------------------------------------------------
export OUTPUT := $(CURDIR)/$(TARGET)
export TOPDIR := $(CURDIR)
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
export DEPSDIR := $(CURDIR)/$(BUILD)
CFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.c)) $(notdir $(wildcard $(dir)/*.board.*.c)) $(notdir $(wildcard $(dir)/*.os.*.c)), \
$(notdir $(wildcard $(dir)/*.c))))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).c)))
CFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).c)))
CPPFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.cpp)) $(notdir $(wildcard $(dir)/*.board.*.cpp)) $(notdir $(wildcard $(dir)/*.os.*.cpp)), \
$(notdir $(wildcard $(dir)/*.cpp))))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).cpp)))
CPPFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).cpp)))
SFILES := $(foreach dir,$(SOURCES),$(filter-out $(notdir $(wildcard $(dir)/*.arch.*.s)) $(notdir $(wildcard $(dir)/*.board.*.s)) $(notdir $(wildcard $(dir)/*.os.*.s)), \
$(notdir $(wildcard $(dir)/*.s))))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.arch.$(ATMOSPHERE_ARCH_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.board.$(ATMOSPHERE_BOARD_NAME).s)))
SFILES += $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.os.$(ATMOSPHERE_OS_NAME).s)))
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
#---------------------------------------------------------------------------------
# use CXX for linking C++ projects, CC for standard C
#---------------------------------------------------------------------------------
ifeq ($(strip $(CPPFILES)),)
#---------------------------------------------------------------------------------
export LD := $(CC)
#---------------------------------------------------------------------------------
else
#---------------------------------------------------------------------------------
export LD := $(CXX)
#---------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------
export OFILES := $(addsuffix .o,$(BINFILES)) \
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
export BUILD_EXEFS_SRC := $(TOPDIR)/$(EXEFS_SRC)
ifeq ($(strip $(CONFIG_JSON)),)
jsons := $(wildcard *.json)
ifneq (,$(findstring $(TARGET).json,$(jsons)))
export APP_JSON := $(TOPDIR)/$(TARGET).json
else
ifneq (,$(findstring config.json,$(jsons)))
export APP_JSON := $(TOPDIR)/config.json
endif
endif
else
export APP_JSON := $(TOPDIR)/$(CONFIG_JSON)
endif
.PHONY: $(BUILD) clean all
#---------------------------------------------------------------------------------
all: $(BUILD)
$(BUILD):
@[ -d $@ ] || mkdir -p $@
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
#---------------------------------------------------------------------------------
clean:
@echo clean ...
@rm -fr $(BUILD) $(TARGET).nsp $(TARGET).npdm $(TARGET).nso $(TARGET).elf
#---------------------------------------------------------------------------------
else
.PHONY: all
DEPENDS := $(OFILES:.o=.d)
#---------------------------------------------------------------------------------
# main targets
#---------------------------------------------------------------------------------
all : $(OUTPUT).nsp
ifeq ($(strip $(APP_JSON)),)
$(OUTPUT).nsp : $(OUTPUT).nso
else
$(OUTPUT).nsp : $(OUTPUT).nso $(OUTPUT).npdm
endif
$(OUTPUT).nso : $(OUTPUT).elf
$(OUTPUT).elf : $(OFILES)
#---------------------------------------------------------------------------------
# you need a rule like this for each extension you use as binary data
#---------------------------------------------------------------------------------
%.bin.o : %.bin
#---------------------------------------------------------------------------------
@echo $(notdir $<)
@$(bin2o)
-include $(DEPENDS)
#---------------------------------------------------------------------------------------
endif
#---------------------------------------------------------------------------------------

View File

@@ -0,0 +1,88 @@
{
"name": "erpt",
"title_id": "0x010000000000002b",
"title_id_range_min": "0x010000000000002b",
"title_id_range_max": "0x010000000000002b",
"main_thread_stack_size": "0x00001000",
"main_thread_priority": 49,
"default_cpu_id": 3,
"process_category": 0,
"is_retail": true,
"pool_partition": 2,
"is_64_bit": true,
"address_space_type": 1,
"filesystem_access": {
"permissions": "0xFFFFFFFFFFFFFFFF"
},
"service_access": ["lm", "fsp-srv", "time:u", "set", "set:sys", "srepo:u", "psc:m", "csrng"],
"service_host": ["erpt:r", "erpt:c"],
"kernel_capabilities": [{
"type": "kernel_flags",
"value": {
"highest_thread_priority": 63,
"lowest_thread_priority": 24,
"lowest_cpu_id": 3,
"highest_cpu_id": 3
}
}, {
"type": "syscalls",
"value": {
"svcSetHeapSize": "0x01",
"svcSetMemoryPermission": "0x02",
"svcSetMemoryAttribute": "0x03",
"svcMapMemory": "0x04",
"svcUnmapMemory": "0x05",
"svcQueryMemory": "0x06",
"svcExitProcess": "0x07",
"svcCreateThread": "0x08",
"svcStartThread": "0x09",
"svcExitThread": "0x0a",
"svcSleepThread": "0x0b",
"svcGetThreadPriority": "0x0c",
"svcSetThreadPriority": "0x0d",
"svcGetThreadCoreMask": "0x0e",
"svcSetThreadCoreMask": "0x0f",
"svcGetCurrentProcessorNumber": "0x10",
"svcSignalEvent": "0x11",
"svcClearEvent": "0x12",
"svcMapSharedMemory": "0x13",
"svcUnmapSharedMemory": "0x14",
"svcCreateTransferMemory": "0x15",
"svcCloseHandle": "0x16",
"svcResetSignal": "0x17",
"svcWaitSynchronization": "0x18",
"svcCancelSynchronization": "0x19",
"svcArbitrateLock": "0x1a",
"svcArbitrateUnlock": "0x1b",
"svcWaitProcessWideKeyAtomic": "0x1c",
"svcSignalProcessWideKey": "0x1d",
"svcGetSystemTick": "0x1e",
"svcConnectToNamedPort": "0x1f",
"svcSendSyncRequestLight": "0x20",
"svcSendSyncRequest": "0x21",
"svcSendSyncRequestWithUserBuffer": "0x22",
"svcSendAsyncRequestWithUserBuffer": "0x23",
"svcGetProcessId": "0x24",
"svcGetThreadId": "0x25",
"svcBreak": "0x26",
"svcOutputDebugString": "0x27",
"svcReturnFromException": "0x28",
"svcGetInfo": "0x29",
"svcWaitForAddress": "0x34",
"svcSignalToAddress": "0x35",
"svcCreateSession": "0x40",
"svcAcceptSession": "0x41",
"svcReplyAndReceiveLight": "0x42",
"svcReplyAndReceive": "0x43",
"svcReplyAndReceiveWithUserBuffer": "0x44",
"svcCreateEvent": "0x45",
"svcCallSecureMonitor": "0x7f"
}
}, {
"type": "min_kernel_version",
"value": "0x0030"
}, {
"type": "handle_table_size",
"value": 256
}]
}

View File

@@ -0,0 +1,176 @@
/*
* Copyright (c) 2018-2020 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 __start__;
u32 __nx_applet_type = AppletType_None;
u32 __nx_fs_num_sessions = 1;
#define INNER_HEAP_SIZE 0x4000
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);
}
namespace ams {
ncm::ProgramId CurrentProgramId = ncm::SystemProgramId::Erpt;
namespace result {
bool CallFatalOnResultAssertion = false;
}
}
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::SetVersionForLibnx();
sm::DoWithSession([&]() {
R_ABORT_UNLESS(setInitialize());
R_ABORT_UNLESS(setsysInitialize());
R_ABORT_UNLESS(pscmInitialize());
R_ABORT_UNLESS(time::Initialize());
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 std::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";
}
}
}
int main(int argc, char **argv)
{
/* 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];
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-truncation"
const auto os_priv_len = std::snprintf(os_private, sizeof(os_private), "%s (%.8s)", firmware_version.display_name, firmware_version.revision);
#pragma GCC diagnostic pop
AMS_ASSERT(static_cast<size_t>(os_priv_len) < sizeof(os_private));
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));
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());
/* Wait forever. */
erpt::srv::Wait();
/* Cleanup */
return 0;
}

View File

@@ -60,8 +60,8 @@ namespace ams::fatal::srv {
std::memset(this, 0, sizeof(*this));
/* Get information from set. */
setsysGetSerialNumber(this->serial_number);
setsysGetFirmwareVersion(&this->firmware_version);
settings::system::GetSerialNumber(std::addressof(this->serial_number));
settings::system::GetFirmwareVersion(std::addressof(this->firmware_version));
setsysGetQuestFlag(&this->quest_flag);
this->UpdateLanguageCode();

View File

@@ -20,8 +20,8 @@ namespace ams::fatal::srv {
class FatalConfig {
private:
char serial_number[0x18];
SetSysFirmwareVersion firmware_version;
settings::system::SerialNumber serial_number;
settings::system::FirmwareVersion firmware_version;
u64 language_code;
u64 quest_reboot_interval_second;
bool transition_to_fatal;
@@ -35,11 +35,11 @@ namespace ams::fatal::srv {
public:
FatalConfig();
const char *GetSerialNumber() const {
const settings::system::SerialNumber &GetSerialNumber() const {
return this->serial_number;
}
const SetSysFirmwareVersion &GetFirmwareVersion() const {
const settings::system::FirmwareVersion &GetFirmwareVersion() const {
return this->firmware_version;
}