diff --git a/libraries/libstratosphere/include/stratosphere/fssrv.hpp b/libraries/libstratosphere/include/stratosphere/fssrv.hpp index c668a2b81..7fcc318ed 100644 --- a/libraries/libstratosphere/include/stratosphere/fssrv.hpp +++ b/libraries/libstratosphere/include/stratosphere/fssrv.hpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include diff --git a/libraries/libstratosphere/include/stratosphere/fssrv/fssrv_access_control.hpp b/libraries/libstratosphere/include/stratosphere/fssrv/fssrv_access_control.hpp new file mode 100644 index 000000000..526233625 --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/fssrv/fssrv_access_control.hpp @@ -0,0 +1,23 @@ +/* + * 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 . + */ +#pragma once +#include + +namespace ams::fssrv { + + void SetDebugFlagEnabled(bool en); + +} diff --git a/libraries/libstratosphere/include/stratosphere/fssystem.hpp b/libraries/libstratosphere/include/stratosphere/fssystem.hpp index b86c94700..cb98f8217 100644 --- a/libraries/libstratosphere/include/stratosphere/fssystem.hpp +++ b/libraries/libstratosphere/include/stratosphere/fssystem.hpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include diff --git a/libraries/libstratosphere/include/stratosphere/fssystem/fssystem_service_context.hpp b/libraries/libstratosphere/include/stratosphere/fssystem/fssystem_service_context.hpp new file mode 100644 index 000000000..bc17f4e05 --- /dev/null +++ b/libraries/libstratosphere/include/stratosphere/fssystem/fssystem_service_context.hpp @@ -0,0 +1,53 @@ +/* + * 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 . + */ +#pragma once +#include +#include + +namespace ams::fssystem { + + class ServiceContext { + private: + struct DeferredProcessContextForDeviceError { + u64 process_id; + bool is_process_deferred; + bool is_invoke_deferral_requested; + }; + + struct DeferredProcessContextForPriority { + int session_type; + bool is_process_deferred; + bool is_acquired; + }; + private: + fs::PriorityRaw m_priority; + DeferredProcessContextForDeviceError m_deferred_process_context_for_device_error; + DeferredProcessContextForPriority m_deferred_process_context_for_priority; + int m_storage_flag; + void *m_request_hook_context; + bool m_enable_count_failed_ideal_pooled_buffer_allocations; + public: + ServiceContext() : m_priority(fs::PriorityRaw_Normal), m_storage_flag(0), m_request_hook_context(nullptr), m_enable_count_failed_ideal_pooled_buffer_allocations(false) { + /* ... */ + } + }; + + void RegisterServiceContext(ServiceContext *context); + void UnregisterServiceContext(); + + ServiceContext *GetServiceContext(); + +} diff --git a/libraries/libstratosphere/source/fssrv/fssrv_access_control.cpp b/libraries/libstratosphere/source/fssrv/fssrv_access_control.cpp new file mode 100644 index 000000000..fbb64a6ed --- /dev/null +++ b/libraries/libstratosphere/source/fssrv/fssrv_access_control.cpp @@ -0,0 +1,31 @@ +/* + * 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 . + */ +#include + +namespace ams::fssrv { + + namespace { + + constinit bool g_is_debug_flag_enabled = false; + + } + + void SetDebugFlagEnabled(bool en) { + /* Set global debug flag. */ + g_is_debug_flag_enabled = en; + } + +} diff --git a/libraries/libstratosphere/source/fssystem/fssystem_file_system_proxy_api.cpp b/libraries/libstratosphere/source/fssystem/fssystem_file_system_proxy_api.cpp index 6a9af0269..ebee5e05b 100644 --- a/libraries/libstratosphere/source/fssystem/fssystem_file_system_proxy_api.cpp +++ b/libraries/libstratosphere/source/fssystem/fssystem_file_system_proxy_api.cpp @@ -22,6 +22,8 @@ namespace ams::fssystem { namespace { + /* TODO: Heap sizes need to match FS, when this is FS in master rather than ams.mitm. */ + /* Official FS has a 4.5 MB exp heap, a 6 MB buffer pool, an 8 MB device buffer manager heap, and a 14 MB buffer manager heap. */ /* We don't need so much memory for ams.mitm (as we're servicing a much more limited context). */ /* We'll give ourselves a 1.5 MB exp heap, a 1 MB buffer pool, a 1 MB device buffer manager heap, and a 1 MB buffer manager heap. */ @@ -68,6 +70,7 @@ namespace ams::fssystem { alignas(os::MemoryPageSize) u8 g_device_buffer[DeviceBufferSize]; alignas(os::MemoryPageSize) u8 g_buffer_pool[BufferPoolSize]; + util::TypedStorage g_buffer_allocator; util::TypedStorage g_allocator; @@ -87,14 +90,23 @@ namespace ams::fssystem { } void InitializeForFileSystemProxy() { - /* TODO FS-REIMPL: fssystem::RegisterServiceContext */ + /* TODO FS-REIMPL: Setup MainThreadStackUsageReporter. */ - /* TODO FS-REIMPL: spl::InitializeForFs(); */ + /* Register service context for main thread. */ + fssystem::ServiceContext context; + fssystem::RegisterServiceContext(std::addressof(context)); + + /* Initialize spl library. */ + spl::InitializeForFs(); + /* TODO FS-REIMPL: spl::SetIsAvailableAccessKeyHandler(fssrv::IsAvailableAccessKey) */ /* Determine whether we're prod or dev. */ bool is_prod = !spl::IsDevelopment(); bool is_development_function_enabled = spl::IsDevelopmentFunctionEnabled(); + /* Set debug flags. */ + fssrv::SetDebugFlagEnabled(is_development_function_enabled); + /* Setup our crypto configuration. */ SetUpKekAccessKeys(is_prod); @@ -106,6 +118,7 @@ namespace ams::fssystem { util::ConstructAt(g_allocator, GetPointer(g_buffer_allocator)); /* Set allocators. */ + /* TODO FS-REIMPL: sf::SetGlobalDefaultMemoryResource() */ fs::SetAllocator(AllocateForFileSystemProxy, DeallocateForFileSystemProxy); fssystem::InitializeAllocator(AllocateForFileSystemProxy, DeallocateForFileSystemProxy); @@ -114,11 +127,16 @@ namespace ams::fssystem { util::ConstructAt(g_buffer_manager); GetReference(g_buffer_manager).Initialize(MaxCacheCount, reinterpret_cast(g_buffer_manager_heap), BufferManagerHeapSize, BlockSize); - /* TODO FS-REIMPL: Memory Report Creators, fssrv::SetMemoryReportCreator */ + /* TODO FS-REIMPL: os::AllocateMemoryBlock(...); */ + /* TODO FS-REIMPL: fssrv::storage::CreateDeviceAddressSpace(...); */ + fssystem::InitializeBufferPool(reinterpret_cast(g_device_buffer), DeviceBufferSize); - /* TODO FS-REIMPL: Create Pooled Threads, fssystem::RegisterThreadPool. */ + /* TODO FS-REIMPL: Create Pooled Threads/Stack Usage Reporter, fssystem::RegisterThreadPool. */ + + /* TODO FS-REIMPL: fssrv::GetFileSystemProxyServices(), some service creation. */ /* Initialize fs creators. */ + /* TODO FS-REIMPL: Revise for accuracy. */ util::ConstructAt(g_rom_fs_creator, GetPointer(g_allocator)); util::ConstructAt(g_partition_fs_creator); util::ConstructAt(g_storage_on_nca_creator, GetPointer(g_allocator), *GetNcaCryptoConfiguration(is_prod), is_prod, GetPointer(g_buffer_manager)); @@ -131,18 +149,33 @@ namespace ams::fssystem { .storage_on_nca_creator = GetPointer(g_storage_on_nca_creator), }; + /* TODO FS-REIMPL: Revise above for latest firmware, all the new Services creation. */ + + /* TODO FS-REIMPL: Memory Report Creators, fssrv::SetMemoryReportCreator */ + /* TODO FS-REIMPL: Sd Card detection, speed emulation. */ /* Initialize fssrv. TODO FS-REIMPL: More arguments, more actions taken. */ fssrv::InitializeForFileSystemProxy(std::addressof(g_fs_creator_interfaces), GetPointer(g_buffer_manager), is_development_function_enabled); + /* TODO FS-REIMPL: GetFileSystemProxyServiceObject(), set current process, initialize global service object. */ + /* Disable auto-abort in fs library code. */ /* TODO: fs::SetEnabledAutoAbort(false); */ /* TODO FS-REIMPL: Initialize fsp server. */ - /* NOTE: This is done in fsp server init, normally. */ - fssystem::InitializeBufferPool(reinterpret_cast(g_device_buffer), DeviceBufferSize); + /* TODO FS-REIMPL: Cleanup calls. */ + + /* TODO FS-REIMPL: Spawn worker threads. */ + + /* TODO FS-REIMPL: Set mmc devices ready. */ + + /* TODO FS-REIMPL: fssrv::LoopPmEventServer(...); */ + + /* TODO FS-REIMPL: Wait/destroy threads. */ + + /* TODO FS-REIMPL: spl::Finalize(); */ } const ::ams::fssrv::fscreator::FileSystemCreatorInterfaces *GetFileSystemCreatorInterfaces() { diff --git a/libraries/libstratosphere/source/fssystem/fssystem_service_context.cpp b/libraries/libstratosphere/source/fssystem/fssystem_service_context.cpp new file mode 100644 index 000000000..9255ee355 --- /dev/null +++ b/libraries/libstratosphere/source/fssystem/fssystem_service_context.cpp @@ -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 . + */ +#include + +namespace ams::fssystem { + + namespace { + + os::SdkThreadLocalStorage g_tls_service_context; + + } + + void RegisterServiceContext(ServiceContext *context) { + /* Check pre-conditions. */ + AMS_ASSERT(context != nullptr); + AMS_ASSERT(g_tls_service_context.GetValue() == 0); + + /* Register context. */ + g_tls_service_context.SetValue(reinterpret_cast(context)); + } + + void UnregisterServiceContext() { + /* Unregister context. */ + g_tls_service_context.SetValue(0); + } + + ServiceContext *GetServiceContext() { + /* Get context. */ + auto * const context = reinterpret_cast(g_tls_service_context.GetValue()); + AMS_ASSERT(context != nullptr); + + return context; + } + +} diff --git a/stratosphere/fs/Makefile b/stratosphere/fs/Makefile new file mode 100644 index 000000000..1957b6cdb --- /dev/null +++ b/stratosphere/fs/Makefile @@ -0,0 +1,107 @@ +#--------------------------------------------------------------------------------- +# 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 := $(call FIND_SOURCE_FILES,$(SOURCES),c) +CPPFILES := $(call FIND_SOURCE_FILES,$(SOURCES),cpp) +SFILES := $(call FIND_SOURCE_FILES,$(SOURCES),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).kip $(TARGET).elf + + +#--------------------------------------------------------------------------------- +else +.PHONY: all + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +all : $(OUTPUT).kip + +$(OUTPUT).kip : $(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 +#--------------------------------------------------------------------------------------- diff --git a/stratosphere/fs/fs.json b/stratosphere/fs/fs.json new file mode 100644 index 000000000..0cc6f0ddc --- /dev/null +++ b/stratosphere/fs/fs.json @@ -0,0 +1,103 @@ +{ + "name": "FS", + "title_id": "0x0100000000000000", + "main_thread_stack_size": "0xC000", + "main_thread_priority": 45, + "default_cpu_id": 3, + "process_category": 1, + "use_secure_memory": true, + "immortal": true, + "kernel_capabilities": [{ + "type": "map_page", + "value": "0x60006000" + }, { + "type": "map", + "value": { + "address": "0x700b0000", + "is_ro": false, + "size": "0x00005000", + "is_io": true + } + }, { + "type": "map", + "value": { + "address": "0x70000000", + "is_ro": false, + "size": "0x00004000", + "is_io": true + } + }, { + "type": "handle_table_size", + "value": 256 + }, { + "type": "irq_pair", + "value": [46, 47] + }, { + "type": "irq_pair", + "value": [51, 63] + }, { + "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", + "svcMapTransferMemory": "0x51", + "svcUnmapTransferMemory": "0x52", + "svcCreateInterruptEvent": "0x53", + "svcQueryIoMapping": "0x55", + "svcCreateDeviceAddressSpace": "0x56", + "svcAttachDeviceAddressSpace": "0x57", + "svcDetachDeviceAddressSpace": "0x58", + "svcMapDeviceAddressSpaceAligned": "0x5a", + "svcUnmapDeviceAddressSpace": "0x5c", + "svcGetSystemInfo": "0x6f", + "svcCallSecureMonitor": "0x7F" + } + }] +} \ No newline at end of file diff --git a/stratosphere/fs/source/fs_main.cpp b/stratosphere/fs/source/fs_main.cpp new file mode 100644 index 000000000..4456c1f9e --- /dev/null +++ b/stratosphere/fs/source/fs_main.cpp @@ -0,0 +1,50 @@ +/* + * 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 . + */ +#include + +namespace ams { + + namespace init { + + void InitializeSystemModule() { + /* TODO? */ + + /* Initialize services we need. */ + R_ABORT_UNLESS(sm::Initialize()); + + /* TODO? */ + + /* 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() { + /* Initialize fssystem library for FS. */ + fssystem::InitializeForFileSystemProxy(); + } + +}