From 19eae343155f5c2dcaacb129e06eaa5e1a18697d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=97=B1=20PixelyIon?= Date: Fri, 18 Oct 2019 16:22:38 +0530 Subject: [PATCH] libNX FS Initalization (v0.3) What was added: * libNX FS initalization What was fixed: * Release builds --- app/.gitignore | 1 + app/CMakeLists.txt | 6 +-- app/build.gradle | 11 +++-- .../skyline/kernel/services/base_service.h | 4 ++ .../cpp/skyline/kernel/services/fs/fs.cpp | 18 ++++++++ .../main/cpp/skyline/kernel/services/fs/fs.h | 45 +++++++++++++++++++ .../cpp/skyline/kernel/services/hid/hid.cpp | 2 +- .../skyline/kernel/services/serviceman.cpp | 26 ++++++++--- app/src/main/cpp/skyline/kernel/svc.cpp | 2 +- .../cpp/skyline/kernel/types/KProcess.cpp | 2 +- app/src/main/cpp/skyline/nce.cpp | 2 +- 11 files changed, 102 insertions(+), 17 deletions(-) create mode 100644 app/src/main/cpp/skyline/kernel/services/fs/fs.cpp create mode 100644 app/src/main/cpp/skyline/kernel/services/fs/fs.h diff --git a/app/.gitignore b/app/.gitignore index 796b96d1..67e07b8f 100644 --- a/app/.gitignore +++ b/app/.gitignore @@ -1 +1,2 @@ /build +/release diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 82e4e43f..1b22c1bb 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -1,11 +1,10 @@ cmake_minimum_required(VERSION 3.8) -project(Skyline VERSION 1 LANGUAGES CXX) +project(Skyline VERSION 0.3 LANGUAGES CXX) set(BUILD_TESTING OFF) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED TRUE) -set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0") -set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -flto=full") +set(CMAKE_CXX_FLAGS_RELEASE "-Ofast -flto=full -Wno-unused-command-line-argument") add_subdirectory("libraries/tinyxml2") add_subdirectory("libraries/fmt") @@ -35,6 +34,7 @@ add_library(skyline SHARED ${source_DIR}/skyline/kernel/services/am/appletOE.cpp ${source_DIR}/skyline/kernel/services/hid/hid.cpp ${source_DIR}/skyline/kernel/services/time/time.cpp + ${source_DIR}/skyline/kernel/services/fs/fs.cpp ) target_link_libraries(skyline fmt tinyxml2) target_compile_options(skyline PRIVATE -Wno-c++17-extensions) diff --git a/app/build.gradle b/app/build.gradle index 82bc1295..1c2bc437 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -7,19 +7,24 @@ android { applicationId "skyline.emu" minSdkVersion 26 targetSdkVersion 29 - versionCode 1 - versionName "1.0" + versionCode 3 + versionName "0.3" ndk { abiFilters "arm64-v8a" } - signingConfig signingConfigs.debug } buildTypes { release { + debuggable true minifyEnabled true + shrinkResources true + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + signingConfig signingConfigs.debug } debug { + debuggable true minifyEnabled false + shrinkResources false } } externalNativeBuild { diff --git a/app/src/main/cpp/skyline/kernel/services/base_service.h b/app/src/main/cpp/skyline/kernel/services/base_service.h index f3b7b007..688d07da 100644 --- a/app/src/main/cpp/skyline/kernel/services/base_service.h +++ b/app/src/main/cpp/skyline/kernel/services/base_service.h @@ -34,6 +34,8 @@ namespace skyline::kernel::service { time, time_ISystemClock, time_ITimeZoneService, + fs_fsp, + fs_IFileSystem, }; /** @@ -61,6 +63,8 @@ namespace skyline::kernel::service { {"time:a", Service::time}, {"time:ISystemClock", Service::time_ISystemClock}, {"time:ITimeZoneService", Service::time_ITimeZoneService}, + {"fsp-srv", Service::fs_fsp}, + {"fs:IFileSystem", Service::fs_IFileSystem}, }; class ServiceManager; diff --git a/app/src/main/cpp/skyline/kernel/services/fs/fs.cpp b/app/src/main/cpp/skyline/kernel/services/fs/fs.cpp new file mode 100644 index 00000000..894e82fe --- /dev/null +++ b/app/src/main/cpp/skyline/kernel/services/fs/fs.cpp @@ -0,0 +1,18 @@ +#include "fs.h" + +namespace skyline::kernel::service::fs { + fsp::fsp(const DeviceState &state, ServiceManager& manager) : BaseService(state, manager, false, Service::fs_fsp, { + {0x1, SFunc(fsp::SetCurrentProcess)}, + {0x12, SFunc(fsp::OpenSdCardFileSystem)} + }) {} + + void fsp::SetCurrentProcess(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { + process = *reinterpret_cast(request.cmdArg); + } + + void fsp::OpenSdCardFileSystem(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { + manager.RegisterService(std::make_shared(FsType::SdCard, state, manager), session, response); + } + + IFileSystem::IFileSystem(FsType type, const DeviceState &state, ServiceManager &manager) : type(type), BaseService(state, manager, false, Service::fs_IFileSystem, {}) {} +} diff --git a/app/src/main/cpp/skyline/kernel/services/fs/fs.h b/app/src/main/cpp/skyline/kernel/services/fs/fs.h new file mode 100644 index 00000000..ac7f74b5 --- /dev/null +++ b/app/src/main/cpp/skyline/kernel/services/fs/fs.h @@ -0,0 +1,45 @@ +#pragma once + +#include +#include + +namespace skyline::kernel::service::fs { + /** + * @brief These are the possible types of the filesystem + */ + enum FsType { + Nand, + SdCard, + GameCard + }; + + /** + * @brief fsp-srv or IFileSystemProxy is responsible for providing handles to file systems (https://switchbrew.org/wiki/Filesystem_services#fsp-srv) + */ + class fsp : public BaseService { + public: + pid_t process{}; //!< This holds the PID set by SetCurrentProcess + + fsp(const DeviceState &state, ServiceManager& manager); + + /** + * @brief This sets the PID of the process using FS currently (https://switchbrew.org/wiki/Filesystem_services#SetCurrentProcess) + */ + void SetCurrentProcess(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); + + /** + * @brief This returns a handle to an instance of #IFileSystem (https://switchbrew.org/wiki/Filesystem_services#IFileSystem) with type SDCard + */ + void OpenSdCardFileSystem(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response); + }; + + /** + * @brief IFileSystem is used to interact with a filesystem (https://switchbrew.org/wiki/Filesystem_services#IFileSystem) + */ + class IFileSystem : public BaseService { + public: + FsType type; + + IFileSystem(FsType type, const DeviceState &state, ServiceManager& manager); + }; +} diff --git a/app/src/main/cpp/skyline/kernel/services/hid/hid.cpp b/app/src/main/cpp/skyline/kernel/services/hid/hid.cpp index c975af24..78953c72 100644 --- a/app/src/main/cpp/skyline/kernel/services/hid/hid.cpp +++ b/app/src/main/cpp/skyline/kernel/services/hid/hid.cpp @@ -33,7 +33,7 @@ namespace skyline::kernel::service::hid { u64 appletUserId; } *input = reinterpret_cast(request.cmdArg); styleSet = *reinterpret_cast(&input->styleSet); - state.logger->Write(Logger::Info, "Controller Support: Pro-Controller: {} Joy-Con: Handheld: {}, Dual: {}, L: {}, R: {} GameCube: {} PokeBall: {} NES: {} NES Handheld: {} SNES: {}", static_cast(styleSet->pro_controller), static_cast(styleSet->joycon_handheld), static_cast(styleSet->joycon_dual), static_cast(styleSet->joycon_left), static_cast + state.logger->Write(Logger::Debug, "Controller Support: Pro-Controller: {} Joy-Con: Handheld: {}, Dual: {}, L: {}, R: {} GameCube: {} PokeBall: {} NES: {} NES Handheld: {} SNES: {}", static_cast(styleSet->pro_controller), static_cast(styleSet->joycon_handheld), static_cast(styleSet->joycon_dual), static_cast(styleSet->joycon_left), static_cast (styleSet->joycon_right), static_cast(styleSet->gamecube), static_cast(styleSet->pokeball), static_cast(styleSet->nes), static_cast(styleSet->nes_handheld), static_cast(styleSet->snes)); } diff --git a/app/src/main/cpp/skyline/kernel/services/serviceman.cpp b/app/src/main/cpp/skyline/kernel/services/serviceman.cpp index e31f5835..2bb82f77 100644 --- a/app/src/main/cpp/skyline/kernel/services/serviceman.cpp +++ b/app/src/main/cpp/skyline/kernel/services/serviceman.cpp @@ -7,6 +7,7 @@ #include "fatal/fatal.h" #include "hid/hid.h" #include "time/timesrv.h" +#include "fs/fs.h" namespace skyline::kernel::service { ServiceManager::ServiceManager(const DeviceState &state) : state(state) {} @@ -68,6 +69,9 @@ namespace skyline::kernel::service { case Service::time: serviceObj = std::make_shared(state, *this); break; + case Service::fs_fsp: + serviceObj = std::make_shared(state, *this); + break; default: throw exception("GetService called on missing object"); } @@ -81,23 +85,31 @@ namespace skyline::kernel::service { std::shared_ptr ServiceManager::NewService(const Service serviceType, type::KSession &session, ipc::IpcResponse &response) { auto serviceObject = GetService(serviceType); + handle_t handle{}; if (response.isDomain) { session.domainTable[++session.handleIndex] = serviceObject; response.domainObjects.push_back(session.handleIndex); - } else - response.moveHandles.push_back(state.thisProcess->NewHandle(serviceObject).handle); - state.logger->Write(Logger::Debug, "Service has been created: \"{}\"", serviceObject->getName()); + handle = session.handleIndex; + } else { + handle = state.thisProcess->NewHandle(serviceObject).handle; + response.moveHandles.push_back(handle); + } + state.logger->Write(Logger::Debug, "Service has been created: \"{}\" (0x{:X})", serviceObject->getName(), handle); return serviceObject; } - void ServiceManager::RegisterService(std::shared_ptr serviceObject, type::KSession &session, ipc::IpcResponse &response) { + void ServiceManager::RegisterService(std::shared_ptr serviceObject, type::KSession &session, ipc::IpcResponse &response) { // NOLINT(performance-unnecessary-value-param) serviceVec.push_back(serviceObject); + handle_t handle{}; if (response.isDomain) { session.domainTable[++session.handleIndex] = serviceObject; response.domainObjects.push_back(session.handleIndex); - } else - response.moveHandles.push_back(state.thisProcess->NewHandle(serviceObject).handle); - state.logger->Write(Logger::Debug, "Service has been registered: \"{}\"", serviceObject->getName()); + handle = session.handleIndex; + } else { + handle = state.thisProcess->NewHandle(serviceObject).handle; + response.moveHandles.push_back(handle); + } + state.logger->Write(Logger::Debug, "Service has been registered: \"{}\" (0x{:X})", serviceObject->getName(), handle); } void ServiceManager::CloseSession(const handle_t handle) { diff --git a/app/src/main/cpp/skyline/kernel/svc.cpp b/app/src/main/cpp/skyline/kernel/svc.cpp index 80e2d831..b09fd70f 100644 --- a/app/src/main/cpp/skyline/kernel/svc.cpp +++ b/app/src/main/cpp/skyline/kernel/svc.cpp @@ -98,7 +98,6 @@ namespace skyline::kernel::svc { } void WaitSynchronization(DeviceState &state) { - state.thisThread->timeout = GetCurrTimeNs() + state.nce->GetRegister(Xreg::X3); auto numHandles = state.nce->GetRegister(Wreg::W2); if (numHandles > constant::MaxSyncHandles) { state.nce->SetRegister(Wreg::W0, constant::status::MaxHandles); @@ -126,6 +125,7 @@ namespace skyline::kernel::svc { state.thisThread->waitObjects.push_back(syncObject); syncObject->waitThreads.push_back(state.thisThread->pid); } + state.thisThread->timeout = GetCurrTimeNs() + state.nce->GetRegister(Xreg::X3); state.thisThread->status = type::KThread::ThreadStatus::WaitSync; } diff --git a/app/src/main/cpp/skyline/kernel/types/KProcess.cpp b/app/src/main/cpp/skyline/kernel/types/KProcess.cpp index 2d28b975..8b85e8b3 100644 --- a/app/src/main/cpp/skyline/kernel/types/KProcess.cpp +++ b/app/src/main/cpp/skyline/kernel/types/KProcess.cpp @@ -43,7 +43,7 @@ namespace skyline::kernel::type { MapPrivateRegion(0, constant::DefHeapSize, {true, true, true}, memory::Type::Heap, memory::Region::Heap); memFd = open(fmt::format("/proc/{}/mem", pid).c_str(), O_RDWR | O_CLOEXEC); // NOLINT(hicpp-signed-bitwise) if (memFd == -1) - throw exception(fmt::format("Cannot open file descriptor to /proc/{}/mem", pid)); + throw exception(fmt::format("Cannot open file descriptor to /proc/{}/mem, \"{}\"", pid, strerror(errno))); } KProcess::~KProcess() { diff --git a/app/src/main/cpp/skyline/nce.cpp b/app/src/main/cpp/skyline/nce.cpp index e6aac67f..ad6fd1a4 100644 --- a/app/src/main/cpp/skyline/nce.cpp +++ b/app/src/main/cpp/skyline/nce.cpp @@ -73,7 +73,7 @@ namespace skyline { } } } else if (state->thisThread->status == kernel::type::KThread::ThreadStatus::WaitSync || state->thisThread->status == kernel::type::KThread::ThreadStatus::Sleeping || state->thisThread->status == kernel::type::KThread::ThreadStatus::WaitCondVar) { - if (state->thisThread->timeout >= GetCurrTimeNs()) { + if (state->thisThread->timeout <= GetCurrTimeNs()) { if (state->thisThread->status == kernel::type::KThread::ThreadStatus::WaitSync || state->thisThread->status == kernel::type::KThread::ThreadStatus::WaitCondVar) SetRegister(Wreg::W0, constant::status::Timeout); state->thisThread->status = kernel::type::KThread::ThreadStatus::Runnable;