libNX FS Initalization (v0.3)

What was added:
* libNX FS initalization
What was fixed:
* Release builds
This commit is contained in:
◱ PixelyIon 2019-10-18 16:22:38 +05:30
parent e44809355c
commit 19eae34315
11 changed files with 102 additions and 17 deletions

1
app/.gitignore vendored
View File

@ -1 +1,2 @@
/build /build
/release

View File

@ -1,11 +1,10 @@
cmake_minimum_required(VERSION 3.8) cmake_minimum_required(VERSION 3.8)
project(Skyline VERSION 1 LANGUAGES CXX) project(Skyline VERSION 0.3 LANGUAGES CXX)
set(BUILD_TESTING OFF) set(BUILD_TESTING OFF)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE) set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0") set(CMAKE_CXX_FLAGS_RELEASE "-Ofast -flto=full -Wno-unused-command-line-argument")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -Ofast -flto=full")
add_subdirectory("libraries/tinyxml2") add_subdirectory("libraries/tinyxml2")
add_subdirectory("libraries/fmt") 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/am/appletOE.cpp
${source_DIR}/skyline/kernel/services/hid/hid.cpp ${source_DIR}/skyline/kernel/services/hid/hid.cpp
${source_DIR}/skyline/kernel/services/time/time.cpp ${source_DIR}/skyline/kernel/services/time/time.cpp
${source_DIR}/skyline/kernel/services/fs/fs.cpp
) )
target_link_libraries(skyline fmt tinyxml2) target_link_libraries(skyline fmt tinyxml2)
target_compile_options(skyline PRIVATE -Wno-c++17-extensions) target_compile_options(skyline PRIVATE -Wno-c++17-extensions)

View File

@ -7,19 +7,24 @@ android {
applicationId "skyline.emu" applicationId "skyline.emu"
minSdkVersion 26 minSdkVersion 26
targetSdkVersion 29 targetSdkVersion 29
versionCode 1 versionCode 3
versionName "1.0" versionName "0.3"
ndk { ndk {
abiFilters "arm64-v8a" abiFilters "arm64-v8a"
} }
signingConfig signingConfigs.debug
} }
buildTypes { buildTypes {
release { release {
debuggable true
minifyEnabled true minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.debug
} }
debug { debug {
debuggable true
minifyEnabled false minifyEnabled false
shrinkResources false
} }
} }
externalNativeBuild { externalNativeBuild {

View File

@ -34,6 +34,8 @@ namespace skyline::kernel::service {
time, time,
time_ISystemClock, time_ISystemClock,
time_ITimeZoneService, time_ITimeZoneService,
fs_fsp,
fs_IFileSystem,
}; };
/** /**
@ -61,6 +63,8 @@ namespace skyline::kernel::service {
{"time:a", Service::time}, {"time:a", Service::time},
{"time:ISystemClock", Service::time_ISystemClock}, {"time:ISystemClock", Service::time_ISystemClock},
{"time:ITimeZoneService", Service::time_ITimeZoneService}, {"time:ITimeZoneService", Service::time_ITimeZoneService},
{"fsp-srv", Service::fs_fsp},
{"fs:IFileSystem", Service::fs_IFileSystem},
}; };
class ServiceManager; class ServiceManager;

View File

@ -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<pid_t*>(request.cmdArg);
}
void fsp::OpenSdCardFileSystem(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
manager.RegisterService(std::make_shared<IFileSystem>(FsType::SdCard, state, manager), session, response);
}
IFileSystem::IFileSystem(FsType type, const DeviceState &state, ServiceManager &manager) : type(type), BaseService(state, manager, false, Service::fs_IFileSystem, {}) {}
}

View File

@ -0,0 +1,45 @@
#pragma once
#include <kernel/services/base_service.h>
#include <kernel/services/serviceman.h>
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);
};
}

View File

@ -33,7 +33,7 @@ namespace skyline::kernel::service::hid {
u64 appletUserId; u64 appletUserId;
} *input = reinterpret_cast<InputStruct *>(request.cmdArg); } *input = reinterpret_cast<InputStruct *>(request.cmdArg);
styleSet = *reinterpret_cast<StyleSet *>(&input->styleSet); styleSet = *reinterpret_cast<StyleSet *>(&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<bool>(styleSet->pro_controller), static_cast<bool>(styleSet->joycon_handheld), static_cast<bool>(styleSet->joycon_dual), static_cast<bool>(styleSet->joycon_left), static_cast<bool> state.logger->Write(Logger::Debug, "Controller Support: Pro-Controller: {} Joy-Con: Handheld: {}, Dual: {}, L: {}, R: {} GameCube: {} PokeBall: {} NES: {} NES Handheld: {} SNES: {}", static_cast<bool>(styleSet->pro_controller), static_cast<bool>(styleSet->joycon_handheld), static_cast<bool>(styleSet->joycon_dual), static_cast<bool>(styleSet->joycon_left), static_cast<bool>
(styleSet->joycon_right), static_cast<bool>(styleSet->gamecube), static_cast<bool>(styleSet->pokeball), static_cast<bool>(styleSet->nes), static_cast<bool>(styleSet->nes_handheld), static_cast<bool>(styleSet->snes)); (styleSet->joycon_right), static_cast<bool>(styleSet->gamecube), static_cast<bool>(styleSet->pokeball), static_cast<bool>(styleSet->nes), static_cast<bool>(styleSet->nes_handheld), static_cast<bool>(styleSet->snes));
} }

View File

@ -7,6 +7,7 @@
#include "fatal/fatal.h" #include "fatal/fatal.h"
#include "hid/hid.h" #include "hid/hid.h"
#include "time/timesrv.h" #include "time/timesrv.h"
#include "fs/fs.h"
namespace skyline::kernel::service { namespace skyline::kernel::service {
ServiceManager::ServiceManager(const DeviceState &state) : state(state) {} ServiceManager::ServiceManager(const DeviceState &state) : state(state) {}
@ -68,6 +69,9 @@ namespace skyline::kernel::service {
case Service::time: case Service::time:
serviceObj = std::make_shared<time::time>(state, *this); serviceObj = std::make_shared<time::time>(state, *this);
break; break;
case Service::fs_fsp:
serviceObj = std::make_shared<fs::fsp>(state, *this);
break;
default: default:
throw exception("GetService called on missing object"); throw exception("GetService called on missing object");
} }
@ -81,23 +85,31 @@ namespace skyline::kernel::service {
std::shared_ptr<BaseService> ServiceManager::NewService(const Service serviceType, type::KSession &session, ipc::IpcResponse &response) { std::shared_ptr<BaseService> ServiceManager::NewService(const Service serviceType, type::KSession &session, ipc::IpcResponse &response) {
auto serviceObject = GetService(serviceType); auto serviceObject = GetService(serviceType);
handle_t handle{};
if (response.isDomain) { if (response.isDomain) {
session.domainTable[++session.handleIndex] = serviceObject; session.domainTable[++session.handleIndex] = serviceObject;
response.domainObjects.push_back(session.handleIndex); response.domainObjects.push_back(session.handleIndex);
} else handle = session.handleIndex;
response.moveHandles.push_back(state.thisProcess->NewHandle<type::KSession>(serviceObject).handle); } else {
state.logger->Write(Logger::Debug, "Service has been created: \"{}\"", serviceObject->getName()); handle = state.thisProcess->NewHandle<type::KSession>(serviceObject).handle;
response.moveHandles.push_back(handle);
}
state.logger->Write(Logger::Debug, "Service has been created: \"{}\" (0x{:X})", serviceObject->getName(), handle);
return serviceObject; return serviceObject;
} }
void ServiceManager::RegisterService(std::shared_ptr<BaseService> serviceObject, type::KSession &session, ipc::IpcResponse &response) { void ServiceManager::RegisterService(std::shared_ptr<BaseService> serviceObject, type::KSession &session, ipc::IpcResponse &response) { // NOLINT(performance-unnecessary-value-param)
serviceVec.push_back(serviceObject); serviceVec.push_back(serviceObject);
handle_t handle{};
if (response.isDomain) { if (response.isDomain) {
session.domainTable[++session.handleIndex] = serviceObject; session.domainTable[++session.handleIndex] = serviceObject;
response.domainObjects.push_back(session.handleIndex); response.domainObjects.push_back(session.handleIndex);
} else handle = session.handleIndex;
response.moveHandles.push_back(state.thisProcess->NewHandle<type::KSession>(serviceObject).handle); } else {
state.logger->Write(Logger::Debug, "Service has been registered: \"{}\"", serviceObject->getName()); handle = state.thisProcess->NewHandle<type::KSession>(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) { void ServiceManager::CloseSession(const handle_t handle) {

View File

@ -98,7 +98,6 @@ namespace skyline::kernel::svc {
} }
void WaitSynchronization(DeviceState &state) { void WaitSynchronization(DeviceState &state) {
state.thisThread->timeout = GetCurrTimeNs() + state.nce->GetRegister(Xreg::X3);
auto numHandles = state.nce->GetRegister(Wreg::W2); auto numHandles = state.nce->GetRegister(Wreg::W2);
if (numHandles > constant::MaxSyncHandles) { if (numHandles > constant::MaxSyncHandles) {
state.nce->SetRegister(Wreg::W0, constant::status::MaxHandles); state.nce->SetRegister(Wreg::W0, constant::status::MaxHandles);
@ -126,6 +125,7 @@ namespace skyline::kernel::svc {
state.thisThread->waitObjects.push_back(syncObject); state.thisThread->waitObjects.push_back(syncObject);
syncObject->waitThreads.push_back(state.thisThread->pid); syncObject->waitThreads.push_back(state.thisThread->pid);
} }
state.thisThread->timeout = GetCurrTimeNs() + state.nce->GetRegister(Xreg::X3);
state.thisThread->status = type::KThread::ThreadStatus::WaitSync; state.thisThread->status = type::KThread::ThreadStatus::WaitSync;
} }

View File

@ -43,7 +43,7 @@ namespace skyline::kernel::type {
MapPrivateRegion(0, constant::DefHeapSize, {true, true, true}, memory::Type::Heap, memory::Region::Heap); 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) memFd = open(fmt::format("/proc/{}/mem", pid).c_str(), O_RDWR | O_CLOEXEC); // NOLINT(hicpp-signed-bitwise)
if (memFd == -1) 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() { KProcess::~KProcess() {

View File

@ -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) { } 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) if (state->thisThread->status == kernel::type::KThread::ThreadStatus::WaitSync || state->thisThread->status == kernel::type::KThread::ThreadStatus::WaitCondVar)
SetRegister(Wreg::W0, constant::status::Timeout); SetRegister(Wreg::W0, constant::status::Timeout);
state->thisThread->status = kernel::type::KThread::ThreadStatus::Runnable; state->thisThread->status = kernel::type::KThread::ThreadStatus::Runnable;