Compare commits

..

1 Commits

Author SHA1 Message Date
08999cef10 Android #31 2023-08-06 00:57:55 +00:00
44 changed files with 622 additions and 905 deletions

View File

@ -35,7 +35,7 @@ void RomFSFactory::SetPackedUpdate(VirtualFile update_raw_file) {
update_raw = std::move(update_raw_file); update_raw = std::move(update_raw_file);
} }
VirtualFile RomFSFactory::OpenCurrentProcess(u64 current_process_title_id) const { ResultVal<VirtualFile> RomFSFactory::OpenCurrentProcess(u64 current_process_title_id) const {
if (!updatable) { if (!updatable) {
return file; return file;
} }
@ -45,11 +45,12 @@ VirtualFile RomFSFactory::OpenCurrentProcess(u64 current_process_title_id) const
return patch_manager.PatchRomFS(file, ivfc_offset, ContentRecordType::Program, update_raw); return patch_manager.PatchRomFS(file, ivfc_offset, ContentRecordType::Program, update_raw);
} }
VirtualFile RomFSFactory::OpenPatchedRomFS(u64 title_id, ContentRecordType type) const { ResultVal<VirtualFile> RomFSFactory::OpenPatchedRomFS(u64 title_id, ContentRecordType type) const {
auto nca = content_provider.GetEntry(title_id, type); auto nca = content_provider.GetEntry(title_id, type);
if (nca == nullptr) { if (nca == nullptr) {
return nullptr; // TODO: Find the right error code to use here
return ResultUnknown;
} }
const PatchManager patch_manager{title_id, filesystem_controller, content_provider}; const PatchManager patch_manager{title_id, filesystem_controller, content_provider};
@ -57,20 +58,28 @@ VirtualFile RomFSFactory::OpenPatchedRomFS(u64 title_id, ContentRecordType type)
return patch_manager.PatchRomFS(nca->GetRomFS(), nca->GetBaseIVFCOffset(), type); return patch_manager.PatchRomFS(nca->GetRomFS(), nca->GetBaseIVFCOffset(), type);
} }
VirtualFile RomFSFactory::OpenPatchedRomFSWithProgramIndex(u64 title_id, u8 program_index, ResultVal<VirtualFile> RomFSFactory::OpenPatchedRomFSWithProgramIndex(
ContentRecordType type) const { u64 title_id, u8 program_index, ContentRecordType type) const {
const auto res_title_id = GetBaseTitleIDWithProgramIndex(title_id, program_index); const auto res_title_id = GetBaseTitleIDWithProgramIndex(title_id, program_index);
return OpenPatchedRomFS(res_title_id, type); return OpenPatchedRomFS(res_title_id, type);
} }
VirtualFile RomFSFactory::Open(u64 title_id, StorageId storage, ContentRecordType type) const { ResultVal<VirtualFile> RomFSFactory::Open(u64 title_id, StorageId storage,
ContentRecordType type) const {
const std::shared_ptr<NCA> res = GetEntry(title_id, storage, type); const std::shared_ptr<NCA> res = GetEntry(title_id, storage, type);
if (res == nullptr) { if (res == nullptr) {
return nullptr; // TODO(DarkLordZach): Find the right error code to use here
return ResultUnknown;
} }
return res->GetRomFS(); const auto romfs = res->GetRomFS();
if (romfs == nullptr) {
// TODO(DarkLordZach): Find the right error code to use here
return ResultUnknown;
}
return romfs;
} }
std::shared_ptr<NCA> RomFSFactory::GetEntry(u64 title_id, StorageId storage, std::shared_ptr<NCA> RomFSFactory::GetEntry(u64 title_id, StorageId storage,

View File

@ -41,11 +41,13 @@ public:
~RomFSFactory(); ~RomFSFactory();
void SetPackedUpdate(VirtualFile update_raw_file); void SetPackedUpdate(VirtualFile update_raw_file);
[[nodiscard]] VirtualFile OpenCurrentProcess(u64 current_process_title_id) const; [[nodiscard]] ResultVal<VirtualFile> OpenCurrentProcess(u64 current_process_title_id) const;
[[nodiscard]] VirtualFile OpenPatchedRomFS(u64 title_id, ContentRecordType type) const; [[nodiscard]] ResultVal<VirtualFile> OpenPatchedRomFS(u64 title_id,
[[nodiscard]] VirtualFile OpenPatchedRomFSWithProgramIndex(u64 title_id, u8 program_index, ContentRecordType type) const;
ContentRecordType type) const; [[nodiscard]] ResultVal<VirtualFile> OpenPatchedRomFSWithProgramIndex(
[[nodiscard]] VirtualFile Open(u64 title_id, StorageId storage, ContentRecordType type) const; u64 title_id, u8 program_index, ContentRecordType type) const;
[[nodiscard]] ResultVal<VirtualFile> Open(u64 title_id, StorageId storage,
ContentRecordType type) const;
private: private:
[[nodiscard]] std::shared_ptr<NCA> GetEntry(u64 title_id, StorageId storage, [[nodiscard]] std::shared_ptr<NCA> GetEntry(u64 title_id, StorageId storage,

View File

@ -108,16 +108,26 @@ SaveDataFactory::SaveDataFactory(Core::System& system_, VirtualDir save_director
SaveDataFactory::~SaveDataFactory() = default; SaveDataFactory::~SaveDataFactory() = default;
VirtualDir SaveDataFactory::Create(SaveDataSpaceId space, const SaveDataAttribute& meta) const { ResultVal<VirtualDir> SaveDataFactory::Create(SaveDataSpaceId space,
const SaveDataAttribute& meta) const {
PrintSaveDataAttributeWarnings(meta); PrintSaveDataAttributeWarnings(meta);
const auto save_directory = const auto save_directory =
GetFullPath(system, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id); GetFullPath(system, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id);
return dir->CreateDirectoryRelative(save_directory); auto out = dir->CreateDirectoryRelative(save_directory);
// Return an error if the save data doesn't actually exist.
if (out == nullptr) {
// TODO(DarkLordZach): Find out correct error code.
return ResultUnknown;
}
return out;
} }
VirtualDir SaveDataFactory::Open(SaveDataSpaceId space, const SaveDataAttribute& meta) const { ResultVal<VirtualDir> SaveDataFactory::Open(SaveDataSpaceId space,
const SaveDataAttribute& meta) const {
const auto save_directory = const auto save_directory =
GetFullPath(system, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id); GetFullPath(system, dir, space, meta.type, meta.title_id, meta.user_id, meta.save_id);
@ -128,6 +138,12 @@ VirtualDir SaveDataFactory::Open(SaveDataSpaceId space, const SaveDataAttribute&
return Create(space, meta); return Create(space, meta);
} }
// Return an error if the save data doesn't actually exist.
if (out == nullptr) {
// TODO(Subv): Find out correct error code.
return ResultUnknown;
}
return out; return out;
} }

View File

@ -89,8 +89,8 @@ public:
explicit SaveDataFactory(Core::System& system_, VirtualDir save_directory_); explicit SaveDataFactory(Core::System& system_, VirtualDir save_directory_);
~SaveDataFactory(); ~SaveDataFactory();
VirtualDir Create(SaveDataSpaceId space, const SaveDataAttribute& meta) const; ResultVal<VirtualDir> Create(SaveDataSpaceId space, const SaveDataAttribute& meta) const;
VirtualDir Open(SaveDataSpaceId space, const SaveDataAttribute& meta) const; ResultVal<VirtualDir> Open(SaveDataSpaceId space, const SaveDataAttribute& meta) const;
VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space) const; VirtualDir GetSaveDataSpaceDirectory(SaveDataSpaceId space) const;

View File

@ -23,7 +23,7 @@ SDMCFactory::SDMCFactory(VirtualDir sd_dir_, VirtualDir sd_mod_dir_)
SDMCFactory::~SDMCFactory() = default; SDMCFactory::~SDMCFactory() = default;
VirtualDir SDMCFactory::Open() const { ResultVal<VirtualDir> SDMCFactory::Open() const {
return sd_dir; return sd_dir;
} }

View File

@ -18,7 +18,7 @@ public:
explicit SDMCFactory(VirtualDir sd_dir_, VirtualDir sd_mod_dir_); explicit SDMCFactory(VirtualDir sd_dir_, VirtualDir sd_mod_dir_);
~SDMCFactory(); ~SDMCFactory();
VirtualDir Open() const; ResultVal<VirtualDir> Open() const;
VirtualDir GetSDMCModificationLoadRoot(u64 title_id) const; VirtualDir GetSDMCModificationLoadRoot(u64 title_id) const;
VirtualDir GetSDMCContentDirectory() const; VirtualDir GetSDMCContentDirectory() const;

View File

@ -768,7 +768,7 @@ Result KPageTable::UnmapProcessMemory(KProcessAddress dst_addr, size_t size,
m_memory_block_slab_manager, num_allocator_blocks); m_memory_block_slab_manager, num_allocator_blocks);
R_TRY(allocator_result); R_TRY(allocator_result);
R_TRY(Operate(dst_addr, num_pages, KMemoryPermission::None, OperationType::Unmap)); CASCADE_CODE(Operate(dst_addr, num_pages, KMemoryPermission::None, OperationType::Unmap));
// Apply the memory block update. // Apply the memory block update.
m_memory_block_manager.Update(std::addressof(allocator), dst_addr, num_pages, m_memory_block_manager.Update(std::addressof(allocator), dst_addr, num_pages,

View File

@ -283,6 +283,159 @@ private:
u32 description_end; u32 description_end;
}; };
/**
* This is an optional value type. It holds a `Result` and, if that code is ResultSuccess, it
* also holds a result of type `T`. If the code is an error code (not ResultSuccess), then trying
* to access the inner value with operator* is undefined behavior and will assert with Unwrap().
* Users of this class must be cognizant to check the status of the ResultVal with operator bool(),
* Code(), Succeeded() or Failed() prior to accessing the inner value.
*
* An example of how it could be used:
* \code
* ResultVal<int> Frobnicate(float strength) {
* if (strength < 0.f || strength > 1.0f) {
* // Can't frobnicate too weakly or too strongly
* return Result{ErrorModule::Common, 1};
* } else {
* // Frobnicated! Give caller a cookie
* return 42;
* }
* }
* \endcode
*
* \code
* auto frob_result = Frobnicate(0.75f);
* if (frob_result) {
* // Frobbed ok
* printf("My cookie is %d\n", *frob_result);
* } else {
* printf("Guess I overdid it. :( Error code: %ux\n", frob_result.Code().raw);
* }
* \endcode
*/
template <typename T>
class ResultVal {
public:
constexpr ResultVal() : expected{} {}
constexpr ResultVal(Result code) : expected{Common::Unexpected(code)} {}
constexpr ResultVal(ResultRange range) : expected{Common::Unexpected(range)} {}
template <typename U>
constexpr ResultVal(U&& val) : expected{std::forward<U>(val)} {}
template <typename... Args>
constexpr ResultVal(Args&&... args) : expected{std::in_place, std::forward<Args>(args)...} {}
~ResultVal() = default;
constexpr ResultVal(const ResultVal&) = default;
constexpr ResultVal(ResultVal&&) = default;
ResultVal& operator=(const ResultVal&) = default;
ResultVal& operator=(ResultVal&&) = default;
[[nodiscard]] constexpr explicit operator bool() const noexcept {
return expected.has_value();
}
[[nodiscard]] constexpr Result Code() const {
return expected.has_value() ? ResultSuccess : expected.error();
}
[[nodiscard]] constexpr bool Succeeded() const {
return expected.has_value();
}
[[nodiscard]] constexpr bool Failed() const {
return !expected.has_value();
}
[[nodiscard]] constexpr T* operator->() {
return std::addressof(expected.value());
}
[[nodiscard]] constexpr const T* operator->() const {
return std::addressof(expected.value());
}
[[nodiscard]] constexpr T& operator*() & {
return *expected;
}
[[nodiscard]] constexpr const T& operator*() const& {
return *expected;
}
[[nodiscard]] constexpr T&& operator*() && {
return *expected;
}
[[nodiscard]] constexpr const T&& operator*() const&& {
return *expected;
}
[[nodiscard]] constexpr T& Unwrap() & {
ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal");
return expected.value();
}
[[nodiscard]] constexpr const T& Unwrap() const& {
ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal");
return expected.value();
}
[[nodiscard]] constexpr T&& Unwrap() && {
ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal");
return std::move(expected.value());
}
[[nodiscard]] constexpr const T&& Unwrap() const&& {
ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal");
return std::move(expected.value());
}
template <typename U>
[[nodiscard]] constexpr T ValueOr(U&& v) const& {
return expected.value_or(v);
}
template <typename U>
[[nodiscard]] constexpr T ValueOr(U&& v) && {
return expected.value_or(v);
}
private:
// TODO (Morph): Replace this with C++23 std::expected.
Common::Expected<T, Result> expected;
};
/**
* Check for the success of `source` (which must evaluate to a ResultVal). If it succeeds, unwraps
* the contained value and assigns it to `target`, which can be either an l-value expression or a
* variable declaration. If it fails the return code is returned from the current function. Thus it
* can be used to cascade errors out, achieving something akin to exception handling.
*/
#define CASCADE_RESULT(target, source) \
auto CONCAT2(check_result_L, __LINE__) = source; \
if (CONCAT2(check_result_L, __LINE__).Failed()) { \
return CONCAT2(check_result_L, __LINE__).Code(); \
} \
target = std::move(*CONCAT2(check_result_L, __LINE__))
/**
* Analogous to CASCADE_RESULT, but for a bare Result. The code will be propagated if
* non-success, or discarded otherwise.
*/
#define CASCADE_CODE(source) \
do { \
auto CONCAT2(check_result_L, __LINE__) = source; \
if (CONCAT2(check_result_L, __LINE__).IsError()) { \
return CONCAT2(check_result_L, __LINE__); \
} \
} while (false)
#define R_SUCCEEDED(res) (static_cast<Result>(res).IsSuccess()) #define R_SUCCEEDED(res) (static_cast<Result>(res).IsSuccess())
#define R_FAILED(res) (static_cast<Result>(res).IsFailure()) #define R_FAILED(res) (static_cast<Result>(res).IsFailure())

View File

@ -765,16 +765,15 @@ Result Module::Interface::InitializeApplicationInfoBase() {
// TODO(ogniK): This should be changed to reflect the target process for when we have multiple // TODO(ogniK): This should be changed to reflect the target process for when we have multiple
// processes emulated. As we don't actually have pid support we should assume we're just using // processes emulated. As we don't actually have pid support we should assume we're just using
// our own process // our own process
Glue::ApplicationLaunchProperty launch_property{}; const auto launch_property =
const auto result = system.GetARPManager().GetLaunchProperty( system.GetARPManager().GetLaunchProperty(system.GetApplicationProcessProgramID());
&launch_property, system.GetApplicationProcessProgramID());
if (result != ResultSuccess) { if (launch_property.Failed()) {
LOG_ERROR(Service_ACC, "Failed to get launch property"); LOG_ERROR(Service_ACC, "Failed to get launch property");
return Account::ResultInvalidApplication; return Account::ResultInvalidApplication;
} }
switch (launch_property.base_game_storage_id) { switch (launch_property->base_game_storage_id) {
case FileSys::StorageId::GameCard: case FileSys::StorageId::GameCard:
application_info.application_type = ApplicationType::GameCard; application_info.application_type = ApplicationType::GameCard;
break; break;
@ -786,7 +785,7 @@ Result Module::Interface::InitializeApplicationInfoBase() {
break; break;
default: default:
LOG_ERROR(Service_ACC, "Invalid game storage ID! storage_id={}", LOG_ERROR(Service_ACC, "Invalid game storage ID! storage_id={}",
launch_property.base_game_storage_id); launch_property->base_game_storage_id);
return Account::ResultInvalidApplication; return Account::ResultInvalidApplication;
} }

View File

@ -1578,13 +1578,11 @@ void IApplicationFunctions::EnsureSaveData(HLERequestContext& ctx) {
attribute.title_id = system.GetApplicationProcessProgramID(); attribute.title_id = system.GetApplicationProcessProgramID();
attribute.user_id = user_id; attribute.user_id = user_id;
attribute.type = FileSys::SaveDataType::SaveData; attribute.type = FileSys::SaveDataType::SaveData;
FileSys::VirtualDir save_data{};
const auto res = system.GetFileSystemController().CreateSaveData( const auto res = system.GetFileSystemController().CreateSaveData(
&save_data, FileSys::SaveDataSpaceId::NandUser, attribute); FileSys::SaveDataSpaceId::NandUser, attribute);
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(res); rb.Push(res.Code());
rb.Push<u64>(0); rb.Push<u64>(0);
} }
@ -1669,30 +1667,26 @@ void IApplicationFunctions::GetDesiredLanguage(HLERequestContext& ctx) {
auto app_man = ns_am2->GetApplicationManagerInterface(); auto app_man = ns_am2->GetApplicationManagerInterface();
// Get desired application language // Get desired application language
u8 desired_language{}; const auto res_lang = app_man->GetApplicationDesiredLanguage(supported_languages);
const auto res_lang = if (res_lang.Failed()) {
app_man->GetApplicationDesiredLanguage(&desired_language, supported_languages);
if (res_lang != ResultSuccess) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res_lang); rb.Push(res_lang.Code());
return; return;
} }
// Convert to settings language code. // Convert to settings language code.
u64 language_code{}; const auto res_code = app_man->ConvertApplicationLanguageToLanguageCode(*res_lang);
const auto res_code = if (res_code.Failed()) {
app_man->ConvertApplicationLanguageToLanguageCode(&language_code, desired_language);
if (res_code != ResultSuccess) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res_code); rb.Push(res_code.Code());
return; return;
} }
LOG_DEBUG(Service_AM, "got desired_language={:016X}", language_code); LOG_DEBUG(Service_AM, "got desired_language={:016X}", *res_code);
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.Push(language_code); rb.Push(*res_code);
} }
void IApplicationFunctions::IsGamePlayRecordingSupported(HLERequestContext& ctx) { void IApplicationFunctions::IsGamePlayRecordingSupported(HLERequestContext& ctx) {

View File

@ -22,13 +22,13 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
{9, nullptr, "GetAudioOutputMode"}, {9, nullptr, "GetAudioOutputMode"},
{10, nullptr, "SetAudioOutputMode"}, {10, nullptr, "SetAudioOutputMode"},
{11, nullptr, "SetForceMutePolicy"}, {11, nullptr, "SetForceMutePolicy"},
{12, &AudCtl::GetForceMutePolicy, "GetForceMutePolicy"}, {12, nullptr, "GetForceMutePolicy"},
{13, &AudCtl::GetOutputModeSetting, "GetOutputModeSetting"}, {13, nullptr, "GetOutputModeSetting"},
{14, nullptr, "SetOutputModeSetting"}, {14, nullptr, "SetOutputModeSetting"},
{15, nullptr, "SetOutputTarget"}, {15, nullptr, "SetOutputTarget"},
{16, nullptr, "SetInputTargetForceEnabled"}, {16, nullptr, "SetInputTargetForceEnabled"},
{17, nullptr, "SetHeadphoneOutputLevelMode"}, {17, nullptr, "SetHeadphoneOutputLevelMode"},
{18, &AudCtl::GetHeadphoneOutputLevelMode, "GetHeadphoneOutputLevelMode"}, {18, nullptr, "GetHeadphoneOutputLevelMode"},
{19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"}, {19, nullptr, "AcquireAudioVolumeUpdateEventForPlayReport"},
{20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"}, {20, nullptr, "AcquireAudioOutputDeviceUpdateEventForPlayReport"},
{21, nullptr, "GetAudioOutputTargetForPlayReport"}, {21, nullptr, "GetAudioOutputTargetForPlayReport"},
@ -41,7 +41,7 @@ AudCtl::AudCtl(Core::System& system_) : ServiceFramework{system_, "audctl"} {
{28, nullptr, "GetAudioOutputChannelCountForPlayReport"}, {28, nullptr, "GetAudioOutputChannelCountForPlayReport"},
{29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"}, {29, nullptr, "BindAudioOutputChannelCountUpdateEventForPlayReport"},
{30, nullptr, "SetSpeakerAutoMuteEnabled"}, {30, nullptr, "SetSpeakerAutoMuteEnabled"},
{31, &AudCtl::IsSpeakerAutoMuteEnabled, "IsSpeakerAutoMuteEnabled"}, {31, nullptr, "IsSpeakerAutoMuteEnabled"},
{32, nullptr, "GetActiveOutputTarget"}, {32, nullptr, "GetActiveOutputTarget"},
{33, nullptr, "GetTargetDeviceInfo"}, {33, nullptr, "GetTargetDeviceInfo"},
{34, nullptr, "AcquireTargetNotification"}, {34, nullptr, "AcquireTargetNotification"},
@ -96,42 +96,4 @@ void AudCtl::GetTargetVolumeMax(HLERequestContext& ctx) {
rb.Push(target_max_volume); rb.Push(target_max_volume);
} }
void AudCtl::GetForceMutePolicy(HLERequestContext& ctx) {
LOG_WARNING(Audio, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.PushEnum(ForceMutePolicy::Disable);
}
void AudCtl::GetOutputModeSetting(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto value = rp.Pop<u32>();
LOG_WARNING(Audio, "(STUBBED) called, value={}", value);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.PushEnum(AudioOutputMode::PcmAuto);
}
void AudCtl::GetHeadphoneOutputLevelMode(HLERequestContext& ctx) {
LOG_WARNING(Audio, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.PushEnum(HeadphoneOutputLevelMode::Normal);
}
void AudCtl::IsSpeakerAutoMuteEnabled(HLERequestContext& ctx) {
const bool is_speaker_auto_mute_enabled = false;
LOG_WARNING(Audio, "(STUBBED) called, is_speaker_auto_mute_enabled={}",
is_speaker_auto_mute_enabled);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push<u8>(is_speaker_auto_mute_enabled);
}
} // namespace Service::Audio } // namespace Service::Audio

View File

@ -17,30 +17,8 @@ public:
~AudCtl() override; ~AudCtl() override;
private: private:
enum class AudioOutputMode {
Invalid,
Pcm1ch,
Pcm2ch,
Pcm6ch,
PcmAuto,
};
enum class ForceMutePolicy {
Disable,
SpeakerMuteOnHeadphoneUnplugged,
};
enum class HeadphoneOutputLevelMode {
Normal,
HighPower,
};
void GetTargetVolumeMin(HLERequestContext& ctx); void GetTargetVolumeMin(HLERequestContext& ctx);
void GetTargetVolumeMax(HLERequestContext& ctx); void GetTargetVolumeMax(HLERequestContext& ctx);
void GetForceMutePolicy(HLERequestContext& ctx);
void GetOutputModeSetting(HLERequestContext& ctx);
void GetHeadphoneOutputLevelMode(HLERequestContext& ctx);
void IsSpeakerAutoMuteEnabled(HLERequestContext& ctx);
}; };
} // namespace Service::Audio } // namespace Service::Audio

View File

@ -57,8 +57,8 @@ Result VfsDirectoryServiceWrapper::CreateFile(const std::string& path_, u64 size
return FileSys::ERROR_PATH_NOT_FOUND; return FileSys::ERROR_PATH_NOT_FOUND;
} }
FileSys::EntryType entry_type{}; const auto entry_type = GetEntryType(path);
if (GetEntryType(&entry_type, path) == ResultSuccess) { if (entry_type.Code() == ResultSuccess) {
return FileSys::ERROR_PATH_ALREADY_EXISTS; return FileSys::ERROR_PATH_ALREADY_EXISTS;
} }
@ -210,8 +210,8 @@ Result VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_path_,
return ResultUnknown; return ResultUnknown;
} }
Result VfsDirectoryServiceWrapper::OpenFile(FileSys::VirtualFile* out_file, ResultVal<FileSys::VirtualFile> VfsDirectoryServiceWrapper::OpenFile(const std::string& path_,
const std::string& path_, FileSys::Mode mode) const { FileSys::Mode mode) const {
const std::string path(Common::FS::SanitizePath(path_)); const std::string path(Common::FS::SanitizePath(path_));
std::string_view npath = path; std::string_view npath = path;
while (!npath.empty() && (npath[0] == '/' || npath[0] == '\\')) { while (!npath.empty() && (npath[0] == '/' || npath[0] == '\\')) {
@ -224,68 +224,50 @@ Result VfsDirectoryServiceWrapper::OpenFile(FileSys::VirtualFile* out_file,
} }
if (mode == FileSys::Mode::Append) { if (mode == FileSys::Mode::Append) {
*out_file = std::make_shared<FileSys::OffsetVfsFile>(file, 0, file->GetSize()); return std::make_shared<FileSys::OffsetVfsFile>(file, 0, file->GetSize());
} else {
*out_file = file;
} }
return ResultSuccess; return file;
} }
Result VfsDirectoryServiceWrapper::OpenDirectory(FileSys::VirtualDir* out_directory, ResultVal<FileSys::VirtualDir> VfsDirectoryServiceWrapper::OpenDirectory(const std::string& path_) {
const std::string& path_) {
std::string path(Common::FS::SanitizePath(path_)); std::string path(Common::FS::SanitizePath(path_));
auto dir = GetDirectoryRelativeWrapped(backing, path); auto dir = GetDirectoryRelativeWrapped(backing, path);
if (dir == nullptr) { if (dir == nullptr) {
// TODO(DarkLordZach): Find a better error code for this // TODO(DarkLordZach): Find a better error code for this
return FileSys::ERROR_PATH_NOT_FOUND; return FileSys::ERROR_PATH_NOT_FOUND;
} }
*out_directory = dir; return dir;
return ResultSuccess;
} }
Result VfsDirectoryServiceWrapper::GetEntryType(FileSys::EntryType* out_entry_type, ResultVal<FileSys::EntryType> VfsDirectoryServiceWrapper::GetEntryType(
const std::string& path_) const { const std::string& path_) const {
std::string path(Common::FS::SanitizePath(path_)); std::string path(Common::FS::SanitizePath(path_));
auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path));
if (dir == nullptr) { if (dir == nullptr)
return FileSys::ERROR_PATH_NOT_FOUND; return FileSys::ERROR_PATH_NOT_FOUND;
}
auto filename = Common::FS::GetFilename(path); auto filename = Common::FS::GetFilename(path);
// TODO(Subv): Some games use the '/' path, find out what this means. // TODO(Subv): Some games use the '/' path, find out what this means.
if (filename.empty()) { if (filename.empty())
*out_entry_type = FileSys::EntryType::Directory; return FileSys::EntryType::Directory;
return ResultSuccess;
}
if (dir->GetFile(filename) != nullptr) {
*out_entry_type = FileSys::EntryType::File;
return ResultSuccess;
}
if (dir->GetSubdirectory(filename) != nullptr) {
*out_entry_type = FileSys::EntryType::Directory;
return ResultSuccess;
}
if (dir->GetFile(filename) != nullptr)
return FileSys::EntryType::File;
if (dir->GetSubdirectory(filename) != nullptr)
return FileSys::EntryType::Directory;
return FileSys::ERROR_PATH_NOT_FOUND; return FileSys::ERROR_PATH_NOT_FOUND;
} }
Result VfsDirectoryServiceWrapper::GetFileTimeStampRaw( ResultVal<FileSys::FileTimeStampRaw> VfsDirectoryServiceWrapper::GetFileTimeStampRaw(
FileSys::FileTimeStampRaw* out_file_time_stamp_raw, const std::string& path) const { const std::string& path) const {
auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path));
if (dir == nullptr) { if (dir == nullptr) {
return FileSys::ERROR_PATH_NOT_FOUND; return FileSys::ERROR_PATH_NOT_FOUND;
} }
if (GetEntryType(path).Failed()) {
FileSys::EntryType entry_type;
if (GetEntryType(&entry_type, path) != ResultSuccess) {
return FileSys::ERROR_PATH_NOT_FOUND; return FileSys::ERROR_PATH_NOT_FOUND;
} }
return dir->GetFileTimeStamp(Common::FS::GetFilename(path));
*out_file_time_stamp_raw = dir->GetFileTimeStamp(Common::FS::GetFilename(path));
return ResultSuccess;
} }
FileSystemController::FileSystemController(Core::System& system_) : system{system_} {} FileSystemController::FileSystemController(Core::System& system_) : system{system_} {}
@ -328,54 +310,57 @@ void FileSystemController::SetPackedUpdate(FileSys::VirtualFile update_raw) {
romfs_factory->SetPackedUpdate(std::move(update_raw)); romfs_factory->SetPackedUpdate(std::move(update_raw));
} }
FileSys::VirtualFile FileSystemController::OpenRomFSCurrentProcess() const { ResultVal<FileSys::VirtualFile> FileSystemController::OpenRomFSCurrentProcess() const {
LOG_TRACE(Service_FS, "Opening RomFS for current process"); LOG_TRACE(Service_FS, "Opening RomFS for current process");
if (romfs_factory == nullptr) { if (romfs_factory == nullptr) {
return nullptr; // TODO(bunnei): Find a better error code for this
return ResultUnknown;
} }
return romfs_factory->OpenCurrentProcess(system.GetApplicationProcessProgramID()); return romfs_factory->OpenCurrentProcess(system.GetApplicationProcessProgramID());
} }
FileSys::VirtualFile FileSystemController::OpenPatchedRomFS(u64 title_id, ResultVal<FileSys::VirtualFile> FileSystemController::OpenPatchedRomFS(
FileSys::ContentRecordType type) const { u64 title_id, FileSys::ContentRecordType type) const {
LOG_TRACE(Service_FS, "Opening patched RomFS for title_id={:016X}", title_id); LOG_TRACE(Service_FS, "Opening patched RomFS for title_id={:016X}", title_id);
if (romfs_factory == nullptr) { if (romfs_factory == nullptr) {
return nullptr; // TODO: Find a better error code for this
return ResultUnknown;
} }
return romfs_factory->OpenPatchedRomFS(title_id, type); return romfs_factory->OpenPatchedRomFS(title_id, type);
} }
FileSys::VirtualFile FileSystemController::OpenPatchedRomFSWithProgramIndex( ResultVal<FileSys::VirtualFile> FileSystemController::OpenPatchedRomFSWithProgramIndex(
u64 title_id, u8 program_index, FileSys::ContentRecordType type) const { u64 title_id, u8 program_index, FileSys::ContentRecordType type) const {
LOG_TRACE(Service_FS, "Opening patched RomFS for title_id={:016X}, program_index={}", title_id, LOG_TRACE(Service_FS, "Opening patched RomFS for title_id={:016X}, program_index={}", title_id,
program_index); program_index);
if (romfs_factory == nullptr) { if (romfs_factory == nullptr) {
return nullptr; // TODO: Find a better error code for this
return ResultUnknown;
} }
return romfs_factory->OpenPatchedRomFSWithProgramIndex(title_id, program_index, type); return romfs_factory->OpenPatchedRomFSWithProgramIndex(title_id, program_index, type);
} }
FileSys::VirtualFile FileSystemController::OpenRomFS(u64 title_id, FileSys::StorageId storage_id, ResultVal<FileSys::VirtualFile> FileSystemController::OpenRomFS(
FileSys::ContentRecordType type) const { u64 title_id, FileSys::StorageId storage_id, FileSys::ContentRecordType type) const {
LOG_TRACE(Service_FS, "Opening RomFS for title_id={:016X}, storage_id={:02X}, type={:02X}", LOG_TRACE(Service_FS, "Opening RomFS for title_id={:016X}, storage_id={:02X}, type={:02X}",
title_id, storage_id, type); title_id, storage_id, type);
if (romfs_factory == nullptr) { if (romfs_factory == nullptr) {
return nullptr; // TODO(bunnei): Find a better error code for this
return ResultUnknown;
} }
return romfs_factory->Open(title_id, storage_id, type); return romfs_factory->Open(title_id, storage_id, type);
} }
Result FileSystemController::CreateSaveData(FileSys::VirtualDir* out_save_data, ResultVal<FileSys::VirtualDir> FileSystemController::CreateSaveData(
FileSys::SaveDataSpaceId space, FileSys::SaveDataSpaceId space, const FileSys::SaveDataAttribute& save_struct) const {
const FileSys::SaveDataAttribute& save_struct) const {
LOG_TRACE(Service_FS, "Creating Save Data for space_id={:01X}, save_struct={}", space, LOG_TRACE(Service_FS, "Creating Save Data for space_id={:01X}, save_struct={}", space,
save_struct.DebugInfo()); save_struct.DebugInfo());
@ -383,18 +368,11 @@ Result FileSystemController::CreateSaveData(FileSys::VirtualDir* out_save_data,
return FileSys::ERROR_ENTITY_NOT_FOUND; return FileSys::ERROR_ENTITY_NOT_FOUND;
} }
auto save_data = save_data_factory->Create(space, save_struct); return save_data_factory->Create(space, save_struct);
if (save_data == nullptr) {
return FileSys::ERROR_ENTITY_NOT_FOUND;
}
*out_save_data = save_data;
return ResultSuccess;
} }
Result FileSystemController::OpenSaveData(FileSys::VirtualDir* out_save_data, ResultVal<FileSys::VirtualDir> FileSystemController::OpenSaveData(
FileSys::SaveDataSpaceId space, FileSys::SaveDataSpaceId space, const FileSys::SaveDataAttribute& attribute) const {
const FileSys::SaveDataAttribute& attribute) const {
LOG_TRACE(Service_FS, "Opening Save Data for space_id={:01X}, save_struct={}", space, LOG_TRACE(Service_FS, "Opening Save Data for space_id={:01X}, save_struct={}", space,
attribute.DebugInfo()); attribute.DebugInfo());
@ -402,50 +380,32 @@ Result FileSystemController::OpenSaveData(FileSys::VirtualDir* out_save_data,
return FileSys::ERROR_ENTITY_NOT_FOUND; return FileSys::ERROR_ENTITY_NOT_FOUND;
} }
auto save_data = save_data_factory->Open(space, attribute); return save_data_factory->Open(space, attribute);
if (save_data == nullptr) {
return FileSys::ERROR_ENTITY_NOT_FOUND;
}
*out_save_data = save_data;
return ResultSuccess;
} }
Result FileSystemController::OpenSaveDataSpace(FileSys::VirtualDir* out_save_data_space, ResultVal<FileSys::VirtualDir> FileSystemController::OpenSaveDataSpace(
FileSys::SaveDataSpaceId space) const { FileSys::SaveDataSpaceId space) const {
LOG_TRACE(Service_FS, "Opening Save Data Space for space_id={:01X}", space); LOG_TRACE(Service_FS, "Opening Save Data Space for space_id={:01X}", space);
if (save_data_factory == nullptr) { if (save_data_factory == nullptr) {
return FileSys::ERROR_ENTITY_NOT_FOUND; return FileSys::ERROR_ENTITY_NOT_FOUND;
} }
auto save_data_space = save_data_factory->GetSaveDataSpaceDirectory(space); return save_data_factory->GetSaveDataSpaceDirectory(space);
if (save_data_space == nullptr) {
return FileSys::ERROR_ENTITY_NOT_FOUND;
}
*out_save_data_space = save_data_space;
return ResultSuccess;
} }
Result FileSystemController::OpenSDMC(FileSys::VirtualDir* out_sdmc) const { ResultVal<FileSys::VirtualDir> FileSystemController::OpenSDMC() const {
LOG_TRACE(Service_FS, "Opening SDMC"); LOG_TRACE(Service_FS, "Opening SDMC");
if (sdmc_factory == nullptr) { if (sdmc_factory == nullptr) {
return FileSys::ERROR_SD_CARD_NOT_FOUND; return FileSys::ERROR_SD_CARD_NOT_FOUND;
} }
auto sdmc = sdmc_factory->Open(); return sdmc_factory->Open();
if (sdmc == nullptr) {
return FileSys::ERROR_SD_CARD_NOT_FOUND;
}
*out_sdmc = sdmc;
return ResultSuccess;
} }
Result FileSystemController::OpenBISPartition(FileSys::VirtualDir* out_bis_partition, ResultVal<FileSys::VirtualDir> FileSystemController::OpenBISPartition(
FileSys::BisPartitionId id) const { FileSys::BisPartitionId id) const {
LOG_TRACE(Service_FS, "Opening BIS Partition with id={:08X}", id); LOG_TRACE(Service_FS, "Opening BIS Partition with id={:08X}", id);
if (bis_factory == nullptr) { if (bis_factory == nullptr) {
@ -457,12 +417,11 @@ Result FileSystemController::OpenBISPartition(FileSys::VirtualDir* out_bis_parti
return FileSys::ERROR_INVALID_ARGUMENT; return FileSys::ERROR_INVALID_ARGUMENT;
} }
*out_bis_partition = part; return part;
return ResultSuccess;
} }
Result FileSystemController::OpenBISPartitionStorage( ResultVal<FileSys::VirtualFile> FileSystemController::OpenBISPartitionStorage(
FileSys::VirtualFile* out_bis_partition_storage, FileSys::BisPartitionId id) const { FileSys::BisPartitionId id) const {
LOG_TRACE(Service_FS, "Opening BIS Partition Storage with id={:08X}", id); LOG_TRACE(Service_FS, "Opening BIS Partition Storage with id={:08X}", id);
if (bis_factory == nullptr) { if (bis_factory == nullptr) {
@ -474,8 +433,7 @@ Result FileSystemController::OpenBISPartitionStorage(
return FileSys::ERROR_INVALID_ARGUMENT; return FileSys::ERROR_INVALID_ARGUMENT;
} }
*out_bis_partition_storage = part; return part;
return ResultSuccess;
} }
u64 FileSystemController::GetFreeSpaceSize(FileSys::StorageId id) const { u64 FileSystemController::GetFreeSpaceSize(FileSys::StorageId id) const {

View File

@ -64,24 +64,21 @@ public:
Result RegisterBIS(std::unique_ptr<FileSys::BISFactory>&& factory); Result RegisterBIS(std::unique_ptr<FileSys::BISFactory>&& factory);
void SetPackedUpdate(FileSys::VirtualFile update_raw); void SetPackedUpdate(FileSys::VirtualFile update_raw);
FileSys::VirtualFile OpenRomFSCurrentProcess() const; ResultVal<FileSys::VirtualFile> OpenRomFSCurrentProcess() const;
FileSys::VirtualFile OpenPatchedRomFS(u64 title_id, FileSys::ContentRecordType type) const; ResultVal<FileSys::VirtualFile> OpenPatchedRomFS(u64 title_id,
FileSys::VirtualFile OpenPatchedRomFSWithProgramIndex(u64 title_id, u8 program_index, FileSys::ContentRecordType type) const;
FileSys::ContentRecordType type) const; ResultVal<FileSys::VirtualFile> OpenPatchedRomFSWithProgramIndex(
FileSys::VirtualFile OpenRomFS(u64 title_id, FileSys::StorageId storage_id, u64 title_id, u8 program_index, FileSys::ContentRecordType type) const;
FileSys::ContentRecordType type) const; ResultVal<FileSys::VirtualFile> OpenRomFS(u64 title_id, FileSys::StorageId storage_id,
FileSys::ContentRecordType type) const;
Result CreateSaveData(FileSys::VirtualDir* out_save_data, FileSys::SaveDataSpaceId space, ResultVal<FileSys::VirtualDir> CreateSaveData(
const FileSys::SaveDataAttribute& save_struct) const; FileSys::SaveDataSpaceId space, const FileSys::SaveDataAttribute& save_struct) const;
Result OpenSaveData(FileSys::VirtualDir* out_save_data, FileSys::SaveDataSpaceId space, ResultVal<FileSys::VirtualDir> OpenSaveData(
const FileSys::SaveDataAttribute& save_struct) const; FileSys::SaveDataSpaceId space, const FileSys::SaveDataAttribute& save_struct) const;
Result OpenSaveDataSpace(FileSys::VirtualDir* out_save_data_space, ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space) const;
FileSys::SaveDataSpaceId space) const; ResultVal<FileSys::VirtualDir> OpenSDMC() const;
Result OpenSDMC(FileSys::VirtualDir* out_sdmc) const; ResultVal<FileSys::VirtualDir> OpenBISPartition(FileSys::BisPartitionId id) const;
Result OpenBISPartition(FileSys::VirtualDir* out_bis_partition, ResultVal<FileSys::VirtualFile> OpenBISPartitionStorage(FileSys::BisPartitionId id) const;
FileSys::BisPartitionId id) const;
Result OpenBISPartitionStorage(FileSys::VirtualFile* out_bis_partition_storage,
FileSys::BisPartitionId id) const;
u64 GetFreeSpaceSize(FileSys::StorageId id) const; u64 GetFreeSpaceSize(FileSys::StorageId id) const;
u64 GetTotalSpaceSize(FileSys::StorageId id) const; u64 GetTotalSpaceSize(FileSys::StorageId id) const;
@ -227,28 +224,26 @@ public:
* @param mode Mode to open the file with * @param mode Mode to open the file with
* @return Opened file, or error code * @return Opened file, or error code
*/ */
Result OpenFile(FileSys::VirtualFile* out_file, const std::string& path, ResultVal<FileSys::VirtualFile> OpenFile(const std::string& path, FileSys::Mode mode) const;
FileSys::Mode mode) const;
/** /**
* Open a directory specified by its path * Open a directory specified by its path
* @param path Path relative to the archive * @param path Path relative to the archive
* @return Opened directory, or error code * @return Opened directory, or error code
*/ */
Result OpenDirectory(FileSys::VirtualDir* out_directory, const std::string& path); ResultVal<FileSys::VirtualDir> OpenDirectory(const std::string& path);
/** /**
* Get the type of the specified path * Get the type of the specified path
* @return The type of the specified path or error code * @return The type of the specified path or error code
*/ */
Result GetEntryType(FileSys::EntryType* out_entry_type, const std::string& path) const; ResultVal<FileSys::EntryType> GetEntryType(const std::string& path) const;
/** /**
* Get the timestamp of the specified path * Get the timestamp of the specified path
* @return The timestamp of the specified path or error code * @return The timestamp of the specified path or error code
*/ */
Result GetFileTimeStampRaw(FileSys::FileTimeStampRaw* out_time_stamp_raw, ResultVal<FileSys::FileTimeStampRaw> GetFileTimeStampRaw(const std::string& path) const;
const std::string& path) const;
private: private:
FileSys::VirtualDir backing; FileSys::VirtualDir backing;

View File

@ -419,15 +419,14 @@ public:
LOG_DEBUG(Service_FS, "called. file={}, mode={}", name, mode); LOG_DEBUG(Service_FS, "called. file={}, mode={}", name, mode);
FileSys::VirtualFile vfs_file{}; auto result = backend.OpenFile(name, mode);
auto result = backend.OpenFile(&vfs_file, name, mode); if (result.Failed()) {
if (result != ResultSuccess) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result); rb.Push(result.Code());
return; return;
} }
auto file = std::make_shared<IFile>(system, vfs_file); auto file = std::make_shared<IFile>(system, result.Unwrap());
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
@ -445,15 +444,14 @@ public:
LOG_DEBUG(Service_FS, "called. directory={}, filter={}", name, filter_flags); LOG_DEBUG(Service_FS, "called. directory={}, filter={}", name, filter_flags);
FileSys::VirtualDir vfs_dir{}; auto result = backend.OpenDirectory(name);
auto result = backend.OpenDirectory(&vfs_dir, name); if (result.Failed()) {
if (result != ResultSuccess) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result); rb.Push(result.Code());
return; return;
} }
auto directory = std::make_shared<IDirectory>(system, vfs_dir); auto directory = std::make_shared<IDirectory>(system, result.Unwrap());
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
@ -466,17 +464,16 @@ public:
LOG_DEBUG(Service_FS, "called. file={}", name); LOG_DEBUG(Service_FS, "called. file={}", name);
FileSys::EntryType vfs_entry_type{}; auto result = backend.GetEntryType(name);
auto result = backend.GetEntryType(&vfs_entry_type, name); if (result.Failed()) {
if (result != ResultSuccess) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result); rb.Push(result.Code());
return; return;
} }
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.Push<u32>(static_cast<u32>(vfs_entry_type)); rb.Push<u32>(static_cast<u32>(*result));
} }
void Commit(HLERequestContext& ctx) { void Commit(HLERequestContext& ctx) {
@ -508,17 +505,16 @@ public:
LOG_WARNING(Service_FS, "(Partial Implementation) called. file={}", name); LOG_WARNING(Service_FS, "(Partial Implementation) called. file={}", name);
FileSys::FileTimeStampRaw vfs_timestamp{}; auto result = backend.GetFileTimeStampRaw(name);
auto result = backend.GetFileTimeStampRaw(&vfs_timestamp, name); if (result.Failed()) {
if (result != ResultSuccess) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result); rb.Push(result.Code());
return; return;
} }
IPC::ResponseBuilder rb{ctx, 10}; IPC::ResponseBuilder rb{ctx, 10};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.PushRaw(vfs_timestamp); rb.PushRaw(*result);
} }
private: private:
@ -576,15 +572,14 @@ private:
} }
void FindAllSaves(FileSys::SaveDataSpaceId space) { void FindAllSaves(FileSys::SaveDataSpaceId space) {
FileSys::VirtualDir save_root{}; const auto save_root = fsc.OpenSaveDataSpace(space);
const auto result = fsc.OpenSaveDataSpace(&save_root, space);
if (result != ResultSuccess || save_root == nullptr) { if (save_root.Failed() || *save_root == nullptr) {
LOG_ERROR(Service_FS, "The save root for the space_id={:02X} was invalid!", space); LOG_ERROR(Service_FS, "The save root for the space_id={:02X} was invalid!", space);
return; return;
} }
for (const auto& type : save_root->GetSubdirectories()) { for (const auto& type : (*save_root)->GetSubdirectories()) {
if (type->GetName() == "save") { if (type->GetName() == "save") {
for (const auto& save_id : type->GetSubdirectories()) { for (const auto& save_id : type->GetSubdirectories()) {
for (const auto& user_id : save_id->GetSubdirectories()) { for (const auto& user_id : save_id->GetSubdirectories()) {
@ -842,11 +837,9 @@ void FSP_SRV::OpenFileSystemWithPatch(HLERequestContext& ctx) {
void FSP_SRV::OpenSdCardFileSystem(HLERequestContext& ctx) { void FSP_SRV::OpenSdCardFileSystem(HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called"); LOG_DEBUG(Service_FS, "called");
FileSys::VirtualDir sdmc_dir{}; auto filesystem =
fsc.OpenSDMC(&sdmc_dir); std::make_shared<IFileSystem>(system, fsc.OpenSDMC().Unwrap(),
SizeGetter::FromStorageId(fsc, FileSys::StorageId::SdCard));
auto filesystem = std::make_shared<IFileSystem>(
system, sdmc_dir, SizeGetter::FromStorageId(fsc, FileSys::StorageId::SdCard));
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
@ -863,8 +856,7 @@ void FSP_SRV::CreateSaveDataFileSystem(HLERequestContext& ctx) {
LOG_DEBUG(Service_FS, "called save_struct = {}, uid = {:016X}{:016X}", save_struct.DebugInfo(), LOG_DEBUG(Service_FS, "called save_struct = {}, uid = {:016X}{:016X}", save_struct.DebugInfo(),
uid[1], uid[0]); uid[1], uid[0]);
FileSys::VirtualDir save_data_dir{}; fsc.CreateSaveData(FileSys::SaveDataSpaceId::NandUser, save_struct);
fsc.CreateSaveData(&save_data_dir, FileSys::SaveDataSpaceId::NandUser, save_struct);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
@ -882,9 +874,8 @@ void FSP_SRV::OpenSaveDataFileSystem(HLERequestContext& ctx) {
LOG_INFO(Service_FS, "called."); LOG_INFO(Service_FS, "called.");
FileSys::VirtualDir dir{}; auto dir = fsc.OpenSaveData(parameters.space_id, parameters.attribute);
auto result = fsc.OpenSaveData(&dir, parameters.space_id, parameters.attribute); if (dir.Failed()) {
if (result != ResultSuccess) {
IPC::ResponseBuilder rb{ctx, 2, 0, 0}; IPC::ResponseBuilder rb{ctx, 2, 0, 0};
rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND); rb.Push(FileSys::ERROR_ENTITY_NOT_FOUND);
return; return;
@ -908,8 +899,8 @@ void FSP_SRV::OpenSaveDataFileSystem(HLERequestContext& ctx) {
ASSERT(false); ASSERT(false);
} }
auto filesystem = auto filesystem = std::make_shared<IFileSystem>(system, std::move(dir.Unwrap()),
std::make_shared<IFileSystem>(system, std::move(dir), SizeGetter::FromStorageId(fsc, id)); SizeGetter::FromStorageId(fsc, id));
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
@ -979,7 +970,7 @@ void FSP_SRV::OpenDataStorageByCurrentProcess(HLERequestContext& ctx) {
if (!romfs) { if (!romfs) {
auto current_romfs = fsc.OpenRomFSCurrentProcess(); auto current_romfs = fsc.OpenRomFSCurrentProcess();
if (!current_romfs) { if (current_romfs.Failed()) {
// TODO (bunnei): Find the right error code to use here // TODO (bunnei): Find the right error code to use here
LOG_CRITICAL(Service_FS, "no file system interface available!"); LOG_CRITICAL(Service_FS, "no file system interface available!");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
@ -987,7 +978,7 @@ void FSP_SRV::OpenDataStorageByCurrentProcess(HLERequestContext& ctx) {
return; return;
} }
romfs = current_romfs; romfs = current_romfs.Unwrap();
} }
auto storage = std::make_shared<IStorage>(system, romfs); auto storage = std::make_shared<IStorage>(system, romfs);
@ -1008,7 +999,7 @@ void FSP_SRV::OpenDataStorageByDataId(HLERequestContext& ctx) {
auto data = fsc.OpenRomFS(title_id, storage_id, FileSys::ContentRecordType::Data); auto data = fsc.OpenRomFS(title_id, storage_id, FileSys::ContentRecordType::Data);
if (!data) { if (data.Failed()) {
const auto archive = FileSys::SystemArchive::SynthesizeSystemArchive(title_id); const auto archive = FileSys::SystemArchive::SynthesizeSystemArchive(title_id);
if (archive != nullptr) { if (archive != nullptr) {
@ -1030,7 +1021,7 @@ void FSP_SRV::OpenDataStorageByDataId(HLERequestContext& ctx) {
const FileSys::PatchManager pm{title_id, fsc, content_provider}; const FileSys::PatchManager pm{title_id, fsc, content_provider};
auto storage = std::make_shared<IStorage>( auto storage = std::make_shared<IStorage>(
system, pm.PatchRomFS(std::move(data), 0, FileSys::ContentRecordType::Data)); system, pm.PatchRomFS(std::move(data.Unwrap()), 0, FileSys::ContentRecordType::Data));
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
@ -1060,7 +1051,7 @@ void FSP_SRV::OpenDataStorageWithProgramIndex(HLERequestContext& ctx) {
fsc.OpenPatchedRomFSWithProgramIndex(system.GetApplicationProcessProgramID(), program_index, fsc.OpenPatchedRomFSWithProgramIndex(system.GetApplicationProcessProgramID(), program_index,
FileSys::ContentRecordType::Program); FileSys::ContentRecordType::Program);
if (!patched_romfs) { if (patched_romfs.Failed()) {
// TODO: Find the right error code to use here // TODO: Find the right error code to use here
LOG_ERROR(Service_FS, "could not open storage with program_index={}", program_index); LOG_ERROR(Service_FS, "could not open storage with program_index={}", program_index);
@ -1069,7 +1060,7 @@ void FSP_SRV::OpenDataStorageWithProgramIndex(HLERequestContext& ctx) {
return; return;
} }
auto storage = std::make_shared<IStorage>(system, std::move(patched_romfs)); auto storage = std::make_shared<IStorage>(system, std::move(patched_romfs.Unwrap()));
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);

View File

@ -65,19 +65,18 @@ void ARP_R::GetApplicationLaunchProperty(HLERequestContext& ctx) {
return; return;
} }
ApplicationLaunchProperty launch_property{}; const auto res = manager.GetLaunchProperty(*title_id);
const auto res = manager.GetLaunchProperty(&launch_property, *title_id);
if (res != ResultSuccess) { if (res.Failed()) {
LOG_ERROR(Service_ARP, "Failed to get launch property!"); LOG_ERROR(Service_ARP, "Failed to get launch property!");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res); rb.Push(res.Code());
return; return;
} }
IPC::ResponseBuilder rb{ctx, 6}; IPC::ResponseBuilder rb{ctx, 6};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.PushRaw(launch_property); rb.PushRaw(*res);
} }
void ARP_R::GetApplicationLaunchPropertyWithApplicationId(HLERequestContext& ctx) { void ARP_R::GetApplicationLaunchPropertyWithApplicationId(HLERequestContext& ctx) {
@ -86,19 +85,18 @@ void ARP_R::GetApplicationLaunchPropertyWithApplicationId(HLERequestContext& ctx
LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id); LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id);
ApplicationLaunchProperty launch_property{}; const auto res = manager.GetLaunchProperty(title_id);
const auto res = manager.GetLaunchProperty(&launch_property, title_id);
if (res != ResultSuccess) { if (res.Failed()) {
LOG_ERROR(Service_ARP, "Failed to get launch property!"); LOG_ERROR(Service_ARP, "Failed to get launch property!");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res); rb.Push(res.Code());
return; return;
} }
IPC::ResponseBuilder rb{ctx, 6}; IPC::ResponseBuilder rb{ctx, 6};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.PushRaw(launch_property); rb.PushRaw(*res);
} }
void ARP_R::GetApplicationControlProperty(HLERequestContext& ctx) { void ARP_R::GetApplicationControlProperty(HLERequestContext& ctx) {
@ -115,17 +113,16 @@ void ARP_R::GetApplicationControlProperty(HLERequestContext& ctx) {
return; return;
} }
std::vector<u8> nacp_data; const auto res = manager.GetControlProperty(*title_id);
const auto res = manager.GetControlProperty(&nacp_data, *title_id);
if (res != ResultSuccess) { if (res.Failed()) {
LOG_ERROR(Service_ARP, "Failed to get control property!"); LOG_ERROR(Service_ARP, "Failed to get control property!");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res); rb.Push(res.Code());
return; return;
} }
ctx.WriteBuffer(nacp_data); ctx.WriteBuffer(*res);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
@ -137,17 +134,16 @@ void ARP_R::GetApplicationControlPropertyWithApplicationId(HLERequestContext& ct
LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id); LOG_DEBUG(Service_ARP, "called, title_id={:016X}", title_id);
std::vector<u8> nacp_data; const auto res = manager.GetControlProperty(title_id);
const auto res = manager.GetControlProperty(&nacp_data, title_id);
if (res != ResultSuccess) { if (res.Failed()) {
LOG_ERROR(Service_ARP, "Failed to get control property!"); LOG_ERROR(Service_ARP, "Failed to get control property!");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res); rb.Push(res.Code());
return; return;
} }
ctx.WriteBuffer(nacp_data); ctx.WriteBuffer(*res);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);

View File

@ -15,8 +15,7 @@ ARPManager::ARPManager() = default;
ARPManager::~ARPManager() = default; ARPManager::~ARPManager() = default;
Result ARPManager::GetLaunchProperty(ApplicationLaunchProperty* out_launch_property, ResultVal<ApplicationLaunchProperty> ARPManager::GetLaunchProperty(u64 title_id) const {
u64 title_id) const {
if (title_id == 0) { if (title_id == 0) {
return Glue::ResultInvalidProcessId; return Glue::ResultInvalidProcessId;
} }
@ -26,11 +25,10 @@ Result ARPManager::GetLaunchProperty(ApplicationLaunchProperty* out_launch_prope
return Glue::ResultProcessIdNotRegistered; return Glue::ResultProcessIdNotRegistered;
} }
*out_launch_property = iter->second.launch; return iter->second.launch;
return ResultSuccess;
} }
Result ARPManager::GetControlProperty(std::vector<u8>* out_control_property, u64 title_id) const { ResultVal<std::vector<u8>> ARPManager::GetControlProperty(u64 title_id) const {
if (title_id == 0) { if (title_id == 0) {
return Glue::ResultInvalidProcessId; return Glue::ResultInvalidProcessId;
} }
@ -40,8 +38,7 @@ Result ARPManager::GetControlProperty(std::vector<u8>* out_control_property, u64
return Glue::ResultProcessIdNotRegistered; return Glue::ResultProcessIdNotRegistered;
} }
*out_control_property = iter->second.control; return iter->second.control;
return ResultSuccess;
} }
Result ARPManager::Register(u64 title_id, ApplicationLaunchProperty launch, Result ARPManager::Register(u64 title_id, ApplicationLaunchProperty launch,

View File

@ -32,12 +32,12 @@ public:
// Returns the ApplicationLaunchProperty corresponding to the provided title ID if it was // Returns the ApplicationLaunchProperty corresponding to the provided title ID if it was
// previously registered, otherwise ResultProcessIdNotRegistered if it was never registered or // previously registered, otherwise ResultProcessIdNotRegistered if it was never registered or
// ResultInvalidProcessId if the title ID is 0. // ResultInvalidProcessId if the title ID is 0.
Result GetLaunchProperty(ApplicationLaunchProperty* out_launch_property, u64 title_id) const; ResultVal<ApplicationLaunchProperty> GetLaunchProperty(u64 title_id) const;
// Returns a vector of the raw bytes of NACP data (necessarily 0x4000 in size) corresponding to // Returns a vector of the raw bytes of NACP data (necessarily 0x4000 in size) corresponding to
// the provided title ID if it was previously registered, otherwise ResultProcessIdNotRegistered // the provided title ID if it was previously registered, otherwise ResultProcessIdNotRegistered
// if it was never registered or ResultInvalidProcessId if the title ID is 0. // if it was never registered or ResultInvalidProcessId if the title ID is 0.
Result GetControlProperty(std::vector<u8>* out_control_property, u64 title_id) const; ResultVal<std::vector<u8>> GetControlProperty(u64 title_id) const;
// Adds a new entry to the internal database with the provided parameters, returning // Adds a new entry to the internal database with the provided parameters, returning
// ResultProcessIdNotRegistered if attempting to re-register a title ID without an intermediate // ResultProcessIdNotRegistered if attempting to re-register a title ID without an intermediate

View File

@ -357,8 +357,7 @@ public:
return ResultSuccess; return ResultSuccess;
} }
Result MapProcessCodeMemory(VAddr* out_map_location, Kernel::KProcess* process, VAddr base_addr, ResultVal<VAddr> MapProcessCodeMemory(Kernel::KProcess* process, VAddr base_addr, u64 size) {
u64 size) {
auto& page_table{process->GetPageTable()}; auto& page_table{process->GetPageTable()};
VAddr addr{}; VAddr addr{};
@ -373,21 +372,20 @@ public:
R_TRY(result); R_TRY(result);
if (ValidateRegionForMap(page_table, addr, size)) { if (ValidateRegionForMap(page_table, addr, size)) {
*out_map_location = addr; return addr;
return ResultSuccess;
} }
} }
return ERROR_INSUFFICIENT_ADDRESS_SPACE; return ERROR_INSUFFICIENT_ADDRESS_SPACE;
} }
Result MapNro(VAddr* out_map_location, Kernel::KProcess* process, VAddr nro_addr, ResultVal<VAddr> MapNro(Kernel::KProcess* process, VAddr nro_addr, std::size_t nro_size,
std::size_t nro_size, VAddr bss_addr, std::size_t bss_size, std::size_t size) { VAddr bss_addr, std::size_t bss_size, std::size_t size) {
for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) { for (std::size_t retry = 0; retry < MAXIMUM_MAP_RETRIES; retry++) {
auto& page_table{process->GetPageTable()}; auto& page_table{process->GetPageTable()};
VAddr addr{}; VAddr addr{};
R_TRY(MapProcessCodeMemory(&addr, process, nro_addr, nro_size)); CASCADE_RESULT(addr, MapProcessCodeMemory(process, nro_addr, nro_size));
if (bss_size) { if (bss_size) {
auto block_guard = detail::ScopeExit([&] { auto block_guard = detail::ScopeExit([&] {
@ -413,8 +411,7 @@ public:
} }
if (ValidateRegionForMap(page_table, addr, size)) { if (ValidateRegionForMap(page_table, addr, size)) {
*out_map_location = addr; return addr;
return ResultSuccess;
} }
} }
@ -440,9 +437,9 @@ public:
CopyCode(nro_addr + nro_header.segment_headers[DATA_INDEX].memory_offset, data_start, CopyCode(nro_addr + nro_header.segment_headers[DATA_INDEX].memory_offset, data_start,
nro_header.segment_headers[DATA_INDEX].memory_size); nro_header.segment_headers[DATA_INDEX].memory_size);
R_TRY(process->GetPageTable().SetProcessMemoryPermission( CASCADE_CODE(process->GetPageTable().SetProcessMemoryPermission(
text_start, ro_start - text_start, Kernel::Svc::MemoryPermission::ReadExecute)); text_start, ro_start - text_start, Kernel::Svc::MemoryPermission::ReadExecute));
R_TRY(process->GetPageTable().SetProcessMemoryPermission( CASCADE_CODE(process->GetPageTable().SetProcessMemoryPermission(
ro_start, data_start - ro_start, Kernel::Svc::MemoryPermission::Read)); ro_start, data_start - ro_start, Kernel::Svc::MemoryPermission::Read));
return process->GetPageTable().SetProcessMemoryPermission( return process->GetPageTable().SetProcessMemoryPermission(
@ -545,32 +542,31 @@ public:
} }
// Map memory for the NRO // Map memory for the NRO
VAddr map_location{}; const auto map_result{MapNro(system.ApplicationProcess(), nro_address, nro_size,
const auto map_result{MapNro(&map_location, system.ApplicationProcess(), nro_address, bss_address, bss_size, nro_size + bss_size)};
nro_size, bss_address, bss_size, nro_size + bss_size)}; if (map_result.Failed()) {
if (map_result != ResultSuccess) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(map_result); rb.Push(map_result.Code());
} }
// Load the NRO into the mapped memory // Load the NRO into the mapped memory
if (const auto result{ if (const auto result{
LoadNro(system.ApplicationProcess(), header, nro_address, map_location)}; LoadNro(system.ApplicationProcess(), header, nro_address, *map_result)};
result.IsError()) { result.IsError()) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result); rb.Push(map_result.Code());
} }
// Track the loaded NRO // Track the loaded NRO
nro.insert_or_assign(map_location, nro.insert_or_assign(*map_result,
NROInfo{hash, map_location, nro_size, bss_address, bss_size, NROInfo{hash, *map_result, nro_size, bss_address, bss_size,
header.segment_headers[TEXT_INDEX].memory_size, header.segment_headers[TEXT_INDEX].memory_size,
header.segment_headers[RO_INDEX].memory_size, header.segment_headers[RO_INDEX].memory_size,
header.segment_headers[DATA_INDEX].memory_size, nro_address}); header.segment_headers[DATA_INDEX].memory_size, nro_address});
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.Push(map_location); rb.Push(*map_result);
} }
Result UnmapNro(const NROInfo& info) { Result UnmapNro(const NROInfo& info) {
@ -578,19 +574,19 @@ public:
auto& page_table{system.ApplicationProcess()->GetPageTable()}; auto& page_table{system.ApplicationProcess()->GetPageTable()};
if (info.bss_size != 0) { if (info.bss_size != 0) {
R_TRY(page_table.UnmapCodeMemory( CASCADE_CODE(page_table.UnmapCodeMemory(
info.nro_address + info.text_size + info.ro_size + info.data_size, info.bss_address, info.nro_address + info.text_size + info.ro_size + info.data_size, info.bss_address,
info.bss_size, Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange)); info.bss_size, Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange));
} }
R_TRY(page_table.UnmapCodeMemory( CASCADE_CODE(page_table.UnmapCodeMemory(
info.nro_address + info.text_size + info.ro_size, info.nro_address + info.text_size + info.ro_size,
info.src_addr + info.text_size + info.ro_size, info.data_size, info.src_addr + info.text_size + info.ro_size, info.data_size,
Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange)); Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange));
R_TRY(page_table.UnmapCodeMemory( CASCADE_CODE(page_table.UnmapCodeMemory(
info.nro_address + info.text_size, info.src_addr + info.text_size, info.ro_size, info.nro_address + info.text_size, info.src_addr + info.text_size, info.ro_size,
Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange)); Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange));
R_TRY(page_table.UnmapCodeMemory( CASCADE_CODE(page_table.UnmapCodeMemory(
info.nro_address, info.src_addr, info.text_size, info.nro_address, info.src_addr, info.text_size,
Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange)); Kernel::KPageTable::ICacheInvalidationStrategy::InvalidateRange));
return ResultSuccess; return ResultSuccess;

View File

@ -101,14 +101,20 @@ private:
LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag); LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
const auto default_miis{manager.GetDefault(source_flag)}; const auto result{manager.GetDefault(source_flag)};
if (default_miis.size() > 0) { if (result.Failed()) {
ctx.WriteBuffer(SerializeArray(default_miis)); IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result.Code());
return;
}
if (result->size() > 0) {
ctx.WriteBuffer(SerializeArray(*result));
} }
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.Push<u32>(static_cast<u32>(default_miis.size())); rb.Push<u32>(static_cast<u32>(result->size()));
} }
void Get1(HLERequestContext& ctx) { void Get1(HLERequestContext& ctx) {
@ -117,10 +123,15 @@ private:
LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag); LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
const auto default_miis{manager.GetDefault(source_flag)}; const auto result{manager.GetDefault(source_flag)};
if (result.Failed()) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result.Code());
return;
}
std::vector<CharInfo> values; std::vector<CharInfo> values;
for (const auto& element : default_miis) { for (const auto& element : *result) {
values.emplace_back(element.info); values.emplace_back(element.info);
} }
@ -128,7 +139,7 @@ private:
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.Push<u32>(static_cast<u32>(default_miis.size())); rb.Push<u32>(static_cast<u32>(result->size()));
} }
void UpdateLatest(HLERequestContext& ctx) { void UpdateLatest(HLERequestContext& ctx) {
@ -138,17 +149,16 @@ private:
LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag); LOG_DEBUG(Service_Mii, "called with source_flag={}", source_flag);
CharInfo new_char_info{}; const auto result{manager.UpdateLatest(info, source_flag)};
const auto result{manager.UpdateLatest(&new_char_info, info, source_flag)}; if (result.Failed()) {
if (result != ResultSuccess) {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result); rb.Push(result.Code());
return; return;
} }
IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)}; IPC::ResponseBuilder rb{ctx, 2 + sizeof(CharInfo) / sizeof(u32)};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.PushRaw<CharInfo>(new_char_info); rb.PushRaw<CharInfo>(*result);
} }
void BuildRandom(HLERequestContext& ctx) { void BuildRandom(HLERequestContext& ctx) {

View File

@ -409,7 +409,8 @@ u32 MiiManager::GetCount(SourceFlag source_flag) const {
return static_cast<u32>(count); return static_cast<u32>(count);
} }
Result MiiManager::UpdateLatest(CharInfo* out_info, const CharInfo& info, SourceFlag source_flag) { ResultVal<CharInfo> MiiManager::UpdateLatest([[maybe_unused]] const CharInfo& info,
SourceFlag source_flag) {
if ((source_flag & SourceFlag::Database) == SourceFlag::None) { if ((source_flag & SourceFlag::Database) == SourceFlag::None) {
return ERROR_CANNOT_FIND_ENTRY; return ERROR_CANNOT_FIND_ENTRY;
} }
@ -671,7 +672,7 @@ bool MiiManager::ValidateV3Info(const Ver3StoreData& mii_v3) const {
return is_valid; return is_valid;
} }
std::vector<MiiInfoElement> MiiManager::GetDefault(SourceFlag source_flag) { ResultVal<std::vector<MiiInfoElement>> MiiManager::GetDefault(SourceFlag source_flag) {
std::vector<MiiInfoElement> result; std::vector<MiiInfoElement> result;
if ((source_flag & SourceFlag::Default) == SourceFlag::None) { if ((source_flag & SourceFlag::Default) == SourceFlag::None) {

View File

@ -19,12 +19,12 @@ public:
bool CheckAndResetUpdateCounter(SourceFlag source_flag, u64& current_update_counter); bool CheckAndResetUpdateCounter(SourceFlag source_flag, u64& current_update_counter);
bool IsFullDatabase() const; bool IsFullDatabase() const;
u32 GetCount(SourceFlag source_flag) const; u32 GetCount(SourceFlag source_flag) const;
Result UpdateLatest(CharInfo* out_info, const CharInfo& info, SourceFlag source_flag); ResultVal<CharInfo> UpdateLatest(const CharInfo& info, SourceFlag source_flag);
CharInfo BuildRandom(Age age, Gender gender, Race race); CharInfo BuildRandom(Age age, Gender gender, Race race);
CharInfo BuildDefault(std::size_t index); CharInfo BuildDefault(std::size_t index);
CharInfo ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const; CharInfo ConvertV3ToCharInfo(const Ver3StoreData& mii_v3) const;
bool ValidateV3Info(const Ver3StoreData& mii_v3) const; bool ValidateV3Info(const Ver3StoreData& mii_v3) const;
std::vector<MiiInfoElement> GetDefault(SourceFlag source_flag); ResultVal<std::vector<MiiInfoElement>> GetDefault(SourceFlag source_flag);
Result GetIndex(const CharInfo& info, u32& index); Result GetIndex(const CharInfo& info, u32& index);
// This is nn::mii::detail::Ver::StoreDataRaw::BuildFromStoreData // This is nn::mii::detail::Ver::StoreDataRaw::BuildFromStoreData

View File

@ -392,20 +392,19 @@ void IApplicationManagerInterface::GetApplicationDesiredLanguage(HLERequestConte
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const auto supported_languages = rp.Pop<u32>(); const auto supported_languages = rp.Pop<u32>();
u8 desired_language{}; const auto res = GetApplicationDesiredLanguage(supported_languages);
const auto res = GetApplicationDesiredLanguage(&desired_language, supported_languages); if (res.Succeeded()) {
if (res == ResultSuccess) {
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.Push<u32>(desired_language); rb.Push<u32>(*res);
} else { } else {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res); rb.Push(res.Code());
} }
} }
Result IApplicationManagerInterface::GetApplicationDesiredLanguage(u8* out_desired_language, ResultVal<u8> IApplicationManagerInterface::GetApplicationDesiredLanguage(
const u32 supported_languages) { const u32 supported_languages) {
LOG_DEBUG(Service_NS, "called with supported_languages={:08X}", supported_languages); LOG_DEBUG(Service_NS, "called with supported_languages={:08X}", supported_languages);
// Get language code from settings // Get language code from settings
@ -431,8 +430,7 @@ Result IApplicationManagerInterface::GetApplicationDesiredLanguage(u8* out_desir
for (const auto lang : *priority_list) { for (const auto lang : *priority_list) {
const auto supported_flag = GetSupportedLanguageFlag(lang); const auto supported_flag = GetSupportedLanguageFlag(lang);
if (supported_languages == 0 || (supported_languages & supported_flag) == supported_flag) { if (supported_languages == 0 || (supported_languages & supported_flag) == supported_flag) {
*out_desired_language = static_cast<u8>(lang); return static_cast<u8>(lang);
return ResultSuccess;
} }
} }
@ -446,20 +444,19 @@ void IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode(
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const auto application_language = rp.Pop<u8>(); const auto application_language = rp.Pop<u8>();
u64 language_code{}; const auto res = ConvertApplicationLanguageToLanguageCode(application_language);
const auto res = ConvertApplicationLanguageToLanguageCode(&language_code, application_language); if (res.Succeeded()) {
if (res == ResultSuccess) {
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.Push(language_code); rb.Push(*res);
} else { } else {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res); rb.Push(res.Code());
} }
} }
Result IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode( ResultVal<u64> IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode(
u64* out_language_code, u8 application_language) { u8 application_language) {
const auto language_code = const auto language_code =
ConvertToLanguageCode(static_cast<ApplicationLanguage>(application_language)); ConvertToLanguageCode(static_cast<ApplicationLanguage>(application_language));
if (language_code == std::nullopt) { if (language_code == std::nullopt) {
@ -467,8 +464,7 @@ Result IApplicationManagerInterface::ConvertApplicationLanguageToLanguageCode(
return Service::NS::ResultApplicationLanguageNotFound; return Service::NS::ResultApplicationLanguageNotFound;
} }
*out_language_code = static_cast<u64>(*language_code); return static_cast<u64>(*language_code);
return ResultSuccess;
} }
IApplicationVersionInterface::IApplicationVersionInterface(Core::System& system_) IApplicationVersionInterface::IApplicationVersionInterface(Core::System& system_)
@ -622,13 +618,12 @@ void IReadOnlyApplicationControlDataInterface::GetApplicationControlData(HLERequ
static_assert(sizeof(RequestParameters) == 0x10, "RequestParameters has incorrect size."); static_assert(sizeof(RequestParameters) == 0x10, "RequestParameters has incorrect size.");
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
std::vector<u8> nacp_data{};
const auto parameters{rp.PopRaw<RequestParameters>()}; const auto parameters{rp.PopRaw<RequestParameters>()};
const auto result = const auto nacp_data{system.GetARPManager().GetControlProperty(parameters.application_id)};
system.GetARPManager().GetControlProperty(&nacp_data, parameters.application_id); const auto result = nacp_data ? ResultSuccess : ResultUnknown;
if (result == ResultSuccess) { if (nacp_data) {
ctx.WriteBuffer(nacp_data.data(), nacp_data.size()); ctx.WriteBuffer(nacp_data->data(), nacp_data->size());
} }
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};

View File

@ -28,9 +28,8 @@ public:
explicit IApplicationManagerInterface(Core::System& system_); explicit IApplicationManagerInterface(Core::System& system_);
~IApplicationManagerInterface() override; ~IApplicationManagerInterface() override;
Result GetApplicationDesiredLanguage(u8* out_desired_language, u32 supported_languages); ResultVal<u8> GetApplicationDesiredLanguage(u32 supported_languages);
Result ConvertApplicationLanguageToLanguageCode(u64* out_language_code, ResultVal<u64> ConvertApplicationLanguageToLanguageCode(u8 application_language);
u8 application_language);
private: private:
void GetApplicationControlData(HLERequestContext& ctx); void GetApplicationControlData(HLERequestContext& ctx);

View File

@ -183,7 +183,7 @@ std::optional<u32> Nvnflinger::FindBufferQueueId(u64 display_id, u64 layer_id) {
return layer->GetBinderId(); return layer->GetBinderId();
} }
Result Nvnflinger::FindVsyncEvent(Kernel::KReadableEvent** out_vsync_event, u64 display_id) { ResultVal<Kernel::KReadableEvent*> Nvnflinger::FindVsyncEvent(u64 display_id) {
const auto lock_guard = Lock(); const auto lock_guard = Lock();
auto* const display = FindDisplay(display_id); auto* const display = FindDisplay(display_id);
@ -191,7 +191,7 @@ Result Nvnflinger::FindVsyncEvent(Kernel::KReadableEvent** out_vsync_event, u64
return VI::ResultNotFound; return VI::ResultNotFound;
} }
return display->GetVSyncEvent(out_vsync_event); return display->GetVSyncEvent();
} }
VI::Display* Nvnflinger::FindDisplay(u64 display_id) { VI::Display* Nvnflinger::FindDisplay(u64 display_id) {

View File

@ -82,7 +82,7 @@ public:
/// ///
/// If an invalid display ID is provided, then VI::ResultNotFound is returned. /// If an invalid display ID is provided, then VI::ResultNotFound is returned.
/// If the vsync event has already been retrieved, then VI::ResultPermissionDenied is returned. /// If the vsync event has already been retrieved, then VI::ResultPermissionDenied is returned.
[[nodiscard]] Result FindVsyncEvent(Kernel::KReadableEvent** out_vsync_event, u64 display_id); [[nodiscard]] ResultVal<Kernel::KReadableEvent*> FindVsyncEvent(u64 display_id);
/// Performs a composition request to the emulated nvidia GPU and triggers the vsync events when /// Performs a composition request to the emulated nvidia GPU and triggers the vsync events when
/// finished. /// finished.

View File

@ -8,16 +8,15 @@
namespace Service::OLSC { namespace Service::OLSC {
class IOlscServiceForApplication final : public ServiceFramework<IOlscServiceForApplication> { class OLSC final : public ServiceFramework<OLSC> {
public: public:
explicit IOlscServiceForApplication(Core::System& system_) explicit OLSC(Core::System& system_) : ServiceFramework{system_, "olsc:u"} {
: ServiceFramework{system_, "olsc:u"} {
// clang-format off // clang-format off
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, &IOlscServiceForApplication::Initialize, "Initialize"}, {0, &OLSC::Initialize, "Initialize"},
{10, nullptr, "VerifySaveDataBackupLicenseAsync"}, {10, nullptr, "VerifySaveDataBackupLicenseAsync"},
{13, &IOlscServiceForApplication::GetSaveDataBackupSetting, "GetSaveDataBackupSetting"}, {13, &OLSC::GetSaveDataBackupSetting, "GetSaveDataBackupSetting"},
{14, &IOlscServiceForApplication::SetSaveDataBackupSettingEnabled, "SetSaveDataBackupSettingEnabled"}, {14, &OLSC::SetSaveDataBackupSettingEnabled, "SetSaveDataBackupSettingEnabled"},
{15, nullptr, "SetCustomData"}, {15, nullptr, "SetCustomData"},
{16, nullptr, "DeleteSaveDataBackupSetting"}, {16, nullptr, "DeleteSaveDataBackupSetting"},
{18, nullptr, "GetSaveDataBackupInfoCache"}, {18, nullptr, "GetSaveDataBackupInfoCache"},
@ -73,155 +72,10 @@ private:
bool initialized{}; bool initialized{};
}; };
class INativeHandleHolder final : public ServiceFramework<INativeHandleHolder> {
public:
explicit INativeHandleHolder(Core::System& system_)
: ServiceFramework{system_, "INativeHandleHolder"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "GetNativeHandle"},
};
// clang-format on
RegisterHandlers(functions);
}
};
class ITransferTaskListController final : public ServiceFramework<ITransferTaskListController> {
public:
explicit ITransferTaskListController(Core::System& system_)
: ServiceFramework{system_, "ITransferTaskListController"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, nullptr, "Unknown0"},
{1, nullptr, "Unknown1"},
{2, nullptr, "Unknown2"},
{3, nullptr, "Unknown3"},
{4, nullptr, "Unknown4"},
{5, &ITransferTaskListController::GetNativeHandleHolder , "GetNativeHandleHolder"},
{6, nullptr, "Unknown6"},
{7, nullptr, "Unknown7"},
{8, nullptr, "GetRemoteStorageController"},
{9, &ITransferTaskListController::GetNativeHandleHolder, "GetNativeHandleHolder2"},
{10, nullptr, "Unknown10"},
{11, nullptr, "Unknown11"},
{12, nullptr, "Unknown12"},
{13, nullptr, "Unknown13"},
{14, nullptr, "Unknown14"},
{15, nullptr, "Unknown15"},
{16, nullptr, "Unknown16"},
{17, nullptr, "Unknown17"},
{18, nullptr, "Unknown18"},
{19, nullptr, "Unknown19"},
{20, nullptr, "Unknown20"},
{21, nullptr, "Unknown21"},
{22, nullptr, "Unknown22"},
{23, nullptr, "Unknown23"},
{24, nullptr, "Unknown24"},
{25, nullptr, "Unknown25"},
};
// clang-format on
RegisterHandlers(functions);
}
private:
void GetNativeHandleHolder(HLERequestContext& ctx) {
LOG_INFO(Service_OLSC, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<INativeHandleHolder>(system);
}
};
class IOlscServiceForSystemService final : public ServiceFramework<IOlscServiceForSystemService> {
public:
explicit IOlscServiceForSystemService(Core::System& system_)
: ServiceFramework{system_, "olsc:s"} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &IOlscServiceForSystemService::OpenTransferTaskListController, "OpenTransferTaskListController"},
{1, nullptr, "OpenRemoteStorageController"},
{2, nullptr, "OpenDaemonController"},
{10, nullptr, "Unknown10"},
{11, nullptr, "Unknown11"},
{12, nullptr, "Unknown12"},
{13, nullptr, "Unknown13"},
{100, nullptr, "ListLastTransferTaskErrorInfo"},
{101, nullptr, "GetLastErrorInfoCount"},
{102, nullptr, "RemoveLastErrorInfoOld"},
{103, nullptr, "GetLastErrorInfo"},
{104, nullptr, "GetLastErrorEventHolder"},
{105, nullptr, "GetLastTransferTaskErrorInfo"},
{200, nullptr, "GetDataTransferPolicyInfo"},
{201, nullptr, "RemoveDataTransferPolicyInfo"},
{202, nullptr, "UpdateDataTransferPolicyOld"},
{203, nullptr, "UpdateDataTransferPolicy"},
{204, nullptr, "CleanupDataTransferPolicyInfo"},
{205, nullptr, "RequestDataTransferPolicy"},
{300, nullptr, "GetAutoTransferSeriesInfo"},
{301, nullptr, "UpdateAutoTransferSeriesInfo"},
{400, nullptr, "CleanupSaveDataArchiveInfoType1"},
{900, nullptr, "CleanupTransferTask"},
{902, nullptr, "CleanupSeriesInfoType0"},
{903, nullptr, "CleanupSaveDataArchiveInfoType0"},
{904, nullptr, "CleanupApplicationAutoTransferSetting"},
{905, nullptr, "CleanupErrorHistory"},
{906, nullptr, "SetLastError"},
{907, nullptr, "AddSaveDataArchiveInfoType0"},
{908, nullptr, "RemoveSeriesInfoType0"},
{909, nullptr, "GetSeriesInfoType0"},
{910, nullptr, "RemoveLastErrorInfo"},
{911, nullptr, "CleanupSeriesInfoType1"},
{912, nullptr, "RemoveSeriesInfoType1"},
{913, nullptr, "GetSeriesInfoType1"},
{1000, nullptr, "UpdateIssueOld"},
{1010, nullptr, "Unknown1010"},
{1011, nullptr, "ListIssueInfoOld"},
{1012, nullptr, "GetIssueOld"},
{1013, nullptr, "GetIssue2Old"},
{1014, nullptr, "GetIssue3Old"},
{1020, nullptr, "RepairIssueOld"},
{1021, nullptr, "RepairIssueWithUserIdOld"},
{1022, nullptr, "RepairIssue2Old"},
{1023, nullptr, "RepairIssue3Old"},
{1024, nullptr, "Unknown1024"},
{1100, nullptr, "UpdateIssue"},
{1110, nullptr, "Unknown1110"},
{1111, nullptr, "ListIssueInfo"},
{1112, nullptr, "GetIssue"},
{1113, nullptr, "GetIssue2"},
{1114, nullptr, "GetIssue3"},
{1120, nullptr, "RepairIssue"},
{1121, nullptr, "RepairIssueWithUserId"},
{1122, nullptr, "RepairIssue2"},
{1123, nullptr, "RepairIssue3"},
{1124, nullptr, "Unknown1124"},
};
// clang-format on
RegisterHandlers(functions);
}
private:
void OpenTransferTaskListController(HLERequestContext& ctx) {
LOG_INFO(Service_OLSC, "called");
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
rb.PushIpcInterface<ITransferTaskListController>(system);
}
};
void LoopProcess(Core::System& system) { void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system); auto server_manager = std::make_unique<ServerManager>(system);
server_manager->RegisterNamedService("olsc:u", server_manager->RegisterNamedService("olsc:u", std::make_shared<OLSC>(system));
std::make_shared<IOlscServiceForApplication>(system));
server_manager->RegisterNamedService("olsc:s",
std::make_shared<IOlscServiceForSystemService>(system));
ServerManager::RunServer(std::move(server_manager)); ServerManager::RunServer(std::move(server_manager));
} }

View File

@ -6,7 +6,6 @@
#include "core/file_sys/control_metadata.h" #include "core/file_sys/control_metadata.h"
#include "core/file_sys/patch_manager.h" #include "core/file_sys/patch_manager.h"
#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/pctl/pctl.h" #include "core/hle/service/pctl/pctl.h"
#include "core/hle/service/pctl/pctl_module.h" #include "core/hle/service/pctl/pctl_module.h"
#include "core/hle/service/server_manager.h" #include "core/hle/service/server_manager.h"
@ -25,8 +24,7 @@ constexpr Result ResultNoRestrictionEnabled{ErrorModule::PCTL, 181};
class IParentalControlService final : public ServiceFramework<IParentalControlService> { class IParentalControlService final : public ServiceFramework<IParentalControlService> {
public: public:
explicit IParentalControlService(Core::System& system_, Capability capability_) explicit IParentalControlService(Core::System& system_, Capability capability_)
: ServiceFramework{system_, "IParentalControlService"}, capability{capability_}, : ServiceFramework{system_, "IParentalControlService"}, capability{capability_} {
service_context{system_, "IParentalControlService"} {
// clang-format off // clang-format off
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{1, &IParentalControlService::Initialize, "Initialize"}, {1, &IParentalControlService::Initialize, "Initialize"},
@ -35,7 +33,7 @@ public:
{1003, nullptr, "ConfirmResumeApplicationPermission"}, {1003, nullptr, "ConfirmResumeApplicationPermission"},
{1004, nullptr, "ConfirmSnsPostPermission"}, {1004, nullptr, "ConfirmSnsPostPermission"},
{1005, nullptr, "ConfirmSystemSettingsPermission"}, {1005, nullptr, "ConfirmSystemSettingsPermission"},
{1006, &IParentalControlService::IsRestrictionTemporaryUnlocked, "IsRestrictionTemporaryUnlocked"}, {1006, nullptr, "IsRestrictionTemporaryUnlocked"},
{1007, nullptr, "RevertRestrictionTemporaryUnlocked"}, {1007, nullptr, "RevertRestrictionTemporaryUnlocked"},
{1008, nullptr, "EnterRestrictedSystemSettings"}, {1008, nullptr, "EnterRestrictedSystemSettings"},
{1009, nullptr, "LeaveRestrictedSystemSettings"}, {1009, nullptr, "LeaveRestrictedSystemSettings"},
@ -49,14 +47,14 @@ public:
{1017, &IParentalControlService::EndFreeCommunication, "EndFreeCommunication"}, {1017, &IParentalControlService::EndFreeCommunication, "EndFreeCommunication"},
{1018, &IParentalControlService::IsFreeCommunicationAvailable, "IsFreeCommunicationAvailable"}, {1018, &IParentalControlService::IsFreeCommunicationAvailable, "IsFreeCommunicationAvailable"},
{1031, &IParentalControlService::IsRestrictionEnabled, "IsRestrictionEnabled"}, {1031, &IParentalControlService::IsRestrictionEnabled, "IsRestrictionEnabled"},
{1032, &IParentalControlService::GetSafetyLevel, "GetSafetyLevel"}, {1032, nullptr, "GetSafetyLevel"},
{1033, nullptr, "SetSafetyLevel"}, {1033, nullptr, "SetSafetyLevel"},
{1034, nullptr, "GetSafetyLevelSettings"}, {1034, nullptr, "GetSafetyLevelSettings"},
{1035, &IParentalControlService::GetCurrentSettings, "GetCurrentSettings"}, {1035, nullptr, "GetCurrentSettings"},
{1036, nullptr, "SetCustomSafetyLevelSettings"}, {1036, nullptr, "SetCustomSafetyLevelSettings"},
{1037, nullptr, "GetDefaultRatingOrganization"}, {1037, nullptr, "GetDefaultRatingOrganization"},
{1038, nullptr, "SetDefaultRatingOrganization"}, {1038, nullptr, "SetDefaultRatingOrganization"},
{1039, &IParentalControlService::GetFreeCommunicationApplicationListCount, "GetFreeCommunicationApplicationListCount"}, {1039, nullptr, "GetFreeCommunicationApplicationListCount"},
{1042, nullptr, "AddToFreeCommunicationApplicationList"}, {1042, nullptr, "AddToFreeCommunicationApplicationList"},
{1043, nullptr, "DeleteSettings"}, {1043, nullptr, "DeleteSettings"},
{1044, nullptr, "GetFreeCommunicationApplicationList"}, {1044, nullptr, "GetFreeCommunicationApplicationList"},
@ -78,7 +76,7 @@ public:
{1206, nullptr, "GetPinCodeLength"}, {1206, nullptr, "GetPinCodeLength"},
{1207, nullptr, "GetPinCodeChangedEvent"}, {1207, nullptr, "GetPinCodeChangedEvent"},
{1208, nullptr, "GetPinCode"}, {1208, nullptr, "GetPinCode"},
{1403, &IParentalControlService::IsPairingActive, "IsPairingActive"}, {1403, nullptr, "IsPairingActive"},
{1406, nullptr, "GetSettingsLastUpdated"}, {1406, nullptr, "GetSettingsLastUpdated"},
{1411, nullptr, "GetPairingAccountInfo"}, {1411, nullptr, "GetPairingAccountInfo"},
{1421, nullptr, "GetAccountNickname"}, {1421, nullptr, "GetAccountNickname"},
@ -86,18 +84,18 @@ public:
{1425, nullptr, "RequestPostEvents"}, {1425, nullptr, "RequestPostEvents"},
{1426, nullptr, "GetPostEventInterval"}, {1426, nullptr, "GetPostEventInterval"},
{1427, nullptr, "SetPostEventInterval"}, {1427, nullptr, "SetPostEventInterval"},
{1432, &IParentalControlService::GetSynchronizationEvent, "GetSynchronizationEvent"}, {1432, nullptr, "GetSynchronizationEvent"},
{1451, nullptr, "StartPlayTimer"}, {1451, nullptr, "StartPlayTimer"},
{1452, nullptr, "StopPlayTimer"}, {1452, nullptr, "StopPlayTimer"},
{1453, nullptr, "IsPlayTimerEnabled"}, {1453, nullptr, "IsPlayTimerEnabled"},
{1454, nullptr, "GetPlayTimerRemainingTime"}, {1454, nullptr, "GetPlayTimerRemainingTime"},
{1455, nullptr, "IsRestrictedByPlayTimer"}, {1455, nullptr, "IsRestrictedByPlayTimer"},
{1456, &IParentalControlService::GetPlayTimerSettings, "GetPlayTimerSettings"}, {1456, nullptr, "GetPlayTimerSettings"},
{1457, &IParentalControlService::GetPlayTimerEventToRequestSuspension, "GetPlayTimerEventToRequestSuspension"}, {1457, nullptr, "GetPlayTimerEventToRequestSuspension"},
{1458, &IParentalControlService::IsPlayTimerAlarmDisabled, "IsPlayTimerAlarmDisabled"}, {1458, nullptr, "IsPlayTimerAlarmDisabled"},
{1471, nullptr, "NotifyWrongPinCodeInputManyTimes"}, {1471, nullptr, "NotifyWrongPinCodeInputManyTimes"},
{1472, nullptr, "CancelNetworkRequest"}, {1472, nullptr, "CancelNetworkRequest"},
{1473, &IParentalControlService::GetUnlinkedEvent, "GetUnlinkedEvent"}, {1473, nullptr, "GetUnlinkedEvent"},
{1474, nullptr, "ClearUnlinkedEvent"}, {1474, nullptr, "ClearUnlinkedEvent"},
{1601, nullptr, "DisableAllFeatures"}, {1601, nullptr, "DisableAllFeatures"},
{1602, nullptr, "PostEnableAllFeatures"}, {1602, nullptr, "PostEnableAllFeatures"},
@ -133,12 +131,6 @@ public:
}; };
// clang-format on // clang-format on
RegisterHandlers(functions); RegisterHandlers(functions);
synchronization_event =
service_context.CreateEvent("IParentalControlService::SynchronizationEvent");
unlinked_event = service_context.CreateEvent("IParentalControlService::UnlinkedEvent");
request_suspension_event =
service_context.CreateEvent("IParentalControlService::RequestSuspensionEvent");
} }
private: private:
@ -236,17 +228,6 @@ private:
states.free_communication = true; states.free_communication = true;
} }
void IsRestrictionTemporaryUnlocked(HLERequestContext& ctx) {
const bool is_temporary_unlocked = false;
LOG_WARNING(Service_PCTL, "(STUBBED) called, is_temporary_unlocked={}",
is_temporary_unlocked);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push<u8>(is_temporary_unlocked);
}
void ConfirmStereoVisionPermission(HLERequestContext& ctx) { void ConfirmStereoVisionPermission(HLERequestContext& ctx) {
LOG_DEBUG(Service_PCTL, "called"); LOG_DEBUG(Service_PCTL, "called");
states.stereo_vision = true; states.stereo_vision = true;
@ -287,34 +268,6 @@ private:
rb.Push(pin_code[0] != '\0'); rb.Push(pin_code[0] != '\0');
} }
void GetSafetyLevel(HLERequestContext& ctx) {
const u32 safety_level = 0;
LOG_WARNING(Service_PCTL, "(STUBBED) called, safety_level={}", safety_level);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(safety_level);
}
void GetCurrentSettings(HLERequestContext& ctx) {
LOG_INFO(Service_PCTL, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.PushRaw(restriction_settings);
}
void GetFreeCommunicationApplicationListCount(HLERequestContext& ctx) {
const u32 count = 4;
LOG_WARNING(Service_PCTL, "(STUBBED) called, count={}", count);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push(count);
}
void ConfirmStereoVisionRestrictionConfigurable(HLERequestContext& ctx) { void ConfirmStereoVisionRestrictionConfigurable(HLERequestContext& ctx) {
LOG_DEBUG(Service_PCTL, "called"); LOG_DEBUG(Service_PCTL, "called");
@ -347,61 +300,6 @@ private:
} }
} }
void IsPairingActive(HLERequestContext& ctx) {
const bool is_pairing_active = false;
LOG_WARNING(Service_PCTL, "(STUBBED) called, is_pairing_active={}", is_pairing_active);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push<u8>(is_pairing_active);
}
void GetSynchronizationEvent(HLERequestContext& ctx) {
LOG_INFO(Service_PCTL, "called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(synchronization_event->GetReadableEvent());
}
void GetPlayTimerSettings(HLERequestContext& ctx) {
LOG_WARNING(Service_PCTL, "(STUBBED) called");
const PlayTimerSettings timer_settings{};
IPC::ResponseBuilder rb{ctx, 15};
rb.Push(ResultSuccess);
rb.PushRaw(timer_settings);
}
void GetPlayTimerEventToRequestSuspension(HLERequestContext& ctx) {
LOG_INFO(Service_PCTL, "called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(request_suspension_event->GetReadableEvent());
}
void IsPlayTimerAlarmDisabled(HLERequestContext& ctx) {
const bool is_play_timer_alarm_disabled = false;
LOG_INFO(Service_PCTL, "called, is_play_timer_alarm_disabled={}",
is_play_timer_alarm_disabled);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push<u8>(is_play_timer_alarm_disabled);
}
void GetUnlinkedEvent(HLERequestContext& ctx) {
LOG_INFO(Service_PCTL, "called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess);
rb.PushCopyObjects(unlinked_event->GetReadableEvent());
}
void SetStereoVisionRestriction(HLERequestContext& ctx) { void SetStereoVisionRestriction(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const auto can_use = rp.Pop<bool>(); const auto can_use = rp.Pop<bool>();
@ -466,30 +364,10 @@ private:
bool disabled{}; bool disabled{};
}; };
// This is nn::pctl::RestrictionSettings
struct RestrictionSettings {
u8 rating_age;
bool sns_post_restriction;
bool free_communication_restriction;
};
static_assert(sizeof(RestrictionSettings) == 0x3, "RestrictionSettings has incorrect size.");
// This is nn::pctl::PlayTimerSettings
struct PlayTimerSettings {
std::array<u32, 13> settings;
};
static_assert(sizeof(PlayTimerSettings) == 0x34, "PlayTimerSettings has incorrect size.");
States states{}; States states{};
ParentalControlSettings settings{}; ParentalControlSettings settings{};
RestrictionSettings restriction_settings{};
std::array<char, 8> pin_code{}; std::array<char, 8> pin_code{};
Capability capability{}; Capability capability{};
Kernel::KEvent* synchronization_event;
Kernel::KEvent* unlinked_event;
Kernel::KEvent* request_suspension_event;
KernelHelpers::ServiceContext service_context;
}; };
void Module::Interface::CreateService(HLERequestContext& ctx) { void Module::Interface::CreateService(HLERequestContext& ctx) {

View File

@ -102,17 +102,16 @@ Result ServerManager::RegisterNamedService(const std::string& service_name,
m_system.ServiceManager().RegisterService(service_name, max_sessions, handler))); m_system.ServiceManager().RegisterService(service_name, max_sessions, handler)));
// Get the registered port. // Get the registered port.
Kernel::KPort* port{}; auto port = m_system.ServiceManager().GetServicePort(service_name);
ASSERT( ASSERT(port.Succeeded());
R_SUCCEEDED(m_system.ServiceManager().GetServicePort(std::addressof(port), service_name)));
// Open a new reference to the server port. // Open a new reference to the server port.
port->GetServerPort().Open(); (*port)->GetServerPort().Open();
// Begin tracking the server port. // Begin tracking the server port.
{ {
std::scoped_lock ll{m_list_mutex}; std::scoped_lock ll{m_list_mutex};
m_ports.emplace(std::addressof(port->GetServerPort()), std::move(handler)); m_ports.emplace(std::addressof((*port)->GetServerPort()), std::move(handler));
} }
// Signal the wakeup event. // Signal the wakeup event.

View File

@ -52,7 +52,8 @@ static Result ValidateServiceName(const std::string& name) {
Result ServiceManager::RegisterService(std::string name, u32 max_sessions, Result ServiceManager::RegisterService(std::string name, u32 max_sessions,
SessionRequestHandlerPtr handler) { SessionRequestHandlerPtr handler) {
R_TRY(ValidateServiceName(name));
CASCADE_CODE(ValidateServiceName(name));
std::scoped_lock lk{lock}; std::scoped_lock lk{lock};
if (registered_services.find(name) != registered_services.end()) { if (registered_services.find(name) != registered_services.end()) {
@ -76,7 +77,7 @@ Result ServiceManager::RegisterService(std::string name, u32 max_sessions,
} }
Result ServiceManager::UnregisterService(const std::string& name) { Result ServiceManager::UnregisterService(const std::string& name) {
R_TRY(ValidateServiceName(name)); CASCADE_CODE(ValidateServiceName(name));
std::scoped_lock lk{lock}; std::scoped_lock lk{lock};
const auto iter = registered_services.find(name); const auto iter = registered_services.find(name);
@ -91,8 +92,8 @@ Result ServiceManager::UnregisterService(const std::string& name) {
return ResultSuccess; return ResultSuccess;
} }
Result ServiceManager::GetServicePort(Kernel::KPort** out_port, const std::string& name) { ResultVal<Kernel::KPort*> ServiceManager::GetServicePort(const std::string& name) {
R_TRY(ValidateServiceName(name)); CASCADE_CODE(ValidateServiceName(name));
std::scoped_lock lk{lock}; std::scoped_lock lk{lock};
auto it = service_ports.find(name); auto it = service_ports.find(name);
@ -101,8 +102,7 @@ Result ServiceManager::GetServicePort(Kernel::KPort** out_port, const std::strin
return Service::SM::ResultNotRegistered; return Service::SM::ResultNotRegistered;
} }
*out_port = it->second; return it->second;
return ResultSuccess;
} }
/** /**
@ -122,34 +122,32 @@ void SM::Initialize(HLERequestContext& ctx) {
} }
void SM::GetService(HLERequestContext& ctx) { void SM::GetService(HLERequestContext& ctx) {
Kernel::KClientSession* client_session{}; auto result = GetServiceImpl(ctx);
auto result = GetServiceImpl(&client_session, ctx);
if (ctx.GetIsDeferred()) { if (ctx.GetIsDeferred()) {
// Don't overwrite the command buffer. // Don't overwrite the command buffer.
return; return;
} }
if (result == ResultSuccess) { if (result.Succeeded()) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
rb.Push(result); rb.Push(result.Code());
rb.PushMoveObjects(client_session); rb.PushMoveObjects(result.Unwrap());
} else { } else {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result); rb.Push(result.Code());
} }
} }
void SM::GetServiceTipc(HLERequestContext& ctx) { void SM::GetServiceTipc(HLERequestContext& ctx) {
Kernel::KClientSession* client_session{}; auto result = GetServiceImpl(ctx);
auto result = GetServiceImpl(&client_session, ctx);
if (ctx.GetIsDeferred()) { if (ctx.GetIsDeferred()) {
// Don't overwrite the command buffer. // Don't overwrite the command buffer.
return; return;
} }
IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
rb.Push(result); rb.Push(result.Code());
rb.PushMoveObjects(result == ResultSuccess ? client_session : nullptr); rb.PushMoveObjects(result.Succeeded() ? result.Unwrap() : nullptr);
} }
static std::string PopServiceName(IPC::RequestParser& rp) { static std::string PopServiceName(IPC::RequestParser& rp) {
@ -163,7 +161,7 @@ static std::string PopServiceName(IPC::RequestParser& rp) {
return result; return result;
} }
Result SM::GetServiceImpl(Kernel::KClientSession** out_client_session, HLERequestContext& ctx) { ResultVal<Kernel::KClientSession*> SM::GetServiceImpl(HLERequestContext& ctx) {
if (!ctx.GetManager()->GetIsInitializedForSm()) { if (!ctx.GetManager()->GetIsInitializedForSm()) {
return Service::SM::ResultInvalidClient; return Service::SM::ResultInvalidClient;
} }
@ -172,18 +170,18 @@ Result SM::GetServiceImpl(Kernel::KClientSession** out_client_session, HLEReques
std::string name(PopServiceName(rp)); std::string name(PopServiceName(rp));
// Find the named port. // Find the named port.
Kernel::KPort* port{}; auto port_result = service_manager.GetServicePort(name);
auto port_result = service_manager.GetServicePort(&port, name); if (port_result.Code() == Service::SM::ResultInvalidServiceName) {
if (port_result == Service::SM::ResultInvalidServiceName) {
LOG_ERROR(Service_SM, "Invalid service name '{}'", name); LOG_ERROR(Service_SM, "Invalid service name '{}'", name);
return Service::SM::ResultInvalidServiceName; return Service::SM::ResultInvalidServiceName;
} }
if (port_result != ResultSuccess) { if (port_result.Failed()) {
LOG_INFO(Service_SM, "Waiting for service {} to become available", name); LOG_INFO(Service_SM, "Waiting for service {} to become available", name);
ctx.SetIsDeferred(); ctx.SetIsDeferred();
return Service::SM::ResultNotRegistered; return Service::SM::ResultNotRegistered;
} }
auto& port = port_result.Unwrap();
// Create a new session. // Create a new session.
Kernel::KClientSession* session{}; Kernel::KClientSession* session{};
@ -194,8 +192,7 @@ Result SM::GetServiceImpl(Kernel::KClientSession** out_client_session, HLEReques
LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetId()); LOG_DEBUG(Service_SM, "called service={} -> session={}", name, session->GetId());
*out_client_session = session; return session;
return ResultSuccess;
} }
void SM::RegisterService(HLERequestContext& ctx) { void SM::RegisterService(HLERequestContext& ctx) {

View File

@ -42,7 +42,7 @@ private:
void RegisterService(HLERequestContext& ctx); void RegisterService(HLERequestContext& ctx);
void UnregisterService(HLERequestContext& ctx); void UnregisterService(HLERequestContext& ctx);
Result GetServiceImpl(Kernel::KClientSession** out_client_session, HLERequestContext& ctx); ResultVal<Kernel::KClientSession*> GetServiceImpl(HLERequestContext& ctx);
ServiceManager& service_manager; ServiceManager& service_manager;
Kernel::KernelCore& kernel; Kernel::KernelCore& kernel;
@ -55,7 +55,7 @@ public:
Result RegisterService(std::string name, u32 max_sessions, SessionRequestHandlerPtr handler); Result RegisterService(std::string name, u32 max_sessions, SessionRequestHandlerPtr handler);
Result UnregisterService(const std::string& name); Result UnregisterService(const std::string& name);
Result GetServicePort(Kernel::KPort** out_port, const std::string& name); ResultVal<Kernel::KPort*> GetServicePort(const std::string& name);
template <Common::DerivedFrom<SessionRequestHandler> T> template <Common::DerivedFrom<SessionRequestHandler> T>
std::shared_ptr<T> GetService(const std::string& service_name) const { std::shared_ptr<T> GetService(const std::string& service_name) const {

View File

@ -54,7 +54,7 @@ NSD::NSD(Core::System& system_, const char* name) : ServiceFramework{system_, na
RegisterHandlers(functions); RegisterHandlers(functions);
} }
static std::string ResolveImpl(const std::string& fqdn_in) { static ResultVal<std::string> ResolveImpl(const std::string& fqdn_in) {
// The real implementation makes various substitutions. // The real implementation makes various substitutions.
// For now we just return the string as-is, which is good enough when not // For now we just return the string as-is, which is good enough when not
// connecting to real Nintendo servers. // connecting to real Nintendo servers.
@ -64,10 +64,13 @@ static std::string ResolveImpl(const std::string& fqdn_in) {
static Result ResolveCommon(const std::string& fqdn_in, std::array<char, 0x100>& fqdn_out) { static Result ResolveCommon(const std::string& fqdn_in, std::array<char, 0x100>& fqdn_out) {
const auto res = ResolveImpl(fqdn_in); const auto res = ResolveImpl(fqdn_in);
if (res.size() >= fqdn_out.size()) { if (res.Failed()) {
return res.Code();
}
if (res->size() >= fqdn_out.size()) {
return ResultOverflow; return ResultOverflow;
} }
std::memcpy(fqdn_out.data(), res.c_str(), res.size() + 1); std::memcpy(fqdn_out.data(), res->c_str(), res->size() + 1);
return ResultSuccess; return ResultSuccess;
} }

View File

@ -30,10 +30,10 @@ void Module::Interface::GetConfig(HLERequestContext& ctx) {
// This should call svcCallSecureMonitor with the appropriate args. // This should call svcCallSecureMonitor with the appropriate args.
// Since we do not have it implemented yet, we will use this for now. // Since we do not have it implemented yet, we will use this for now.
u64 smc_result{}; const auto smc_result = GetConfigImpl(config_item);
const auto result_code = GetConfigImpl(&smc_result, config_item); const auto result_code = smc_result.Code();
if (result_code != ResultSuccess) { if (smc_result.Failed()) {
LOG_ERROR(Service_SPL, "called, config_item={}, result_code={}", config_item, LOG_ERROR(Service_SPL, "called, config_item={}, result_code={}", config_item,
result_code.raw); result_code.raw);
@ -42,11 +42,11 @@ void Module::Interface::GetConfig(HLERequestContext& ctx) {
} }
LOG_DEBUG(Service_SPL, "called, config_item={}, result_code={}, smc_result={}", config_item, LOG_DEBUG(Service_SPL, "called, config_item={}, result_code={}, smc_result={}", config_item,
result_code.raw, smc_result); result_code.raw, *smc_result);
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(result_code); rb.Push(result_code);
rb.Push(smc_result); rb.Push(*smc_result);
} }
void Module::Interface::ModularExponentiate(HLERequestContext& ctx) { void Module::Interface::ModularExponentiate(HLERequestContext& ctx) {
@ -99,7 +99,7 @@ void Module::Interface::GetBootReason(HLERequestContext& ctx) {
rb.Push(ResultSecureMonitorNotImplemented); rb.Push(ResultSecureMonitorNotImplemented);
} }
Result Module::Interface::GetConfigImpl(u64* out_config, ConfigItem config_item) const { ResultVal<u64> Module::Interface::GetConfigImpl(ConfigItem config_item) const {
switch (config_item) { switch (config_item) {
case ConfigItem::DisableProgramVerification: case ConfigItem::DisableProgramVerification:
case ConfigItem::DramId: case ConfigItem::DramId:
@ -121,50 +121,40 @@ Result Module::Interface::GetConfigImpl(u64* out_config, ConfigItem config_item)
return ResultSecureMonitorNotImplemented; return ResultSecureMonitorNotImplemented;
case ConfigItem::ExosphereApiVersion: case ConfigItem::ExosphereApiVersion:
// Get information about the current exosphere version. // Get information about the current exosphere version.
*out_config = (u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MAJOR} << 56) | return (u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MAJOR} << 56) |
(u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MINOR} << 48) | (u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MINOR} << 48) |
(u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MICRO} << 40) | (u64{HLE::ApiVersion::ATMOSPHERE_RELEASE_VERSION_MICRO} << 40) |
(static_cast<u64>(HLE::ApiVersion::GetTargetFirmware())); (static_cast<u64>(HLE::ApiVersion::GetTargetFirmware()));
return ResultSuccess;
case ConfigItem::ExosphereNeedsReboot: case ConfigItem::ExosphereNeedsReboot:
// We are executing, so we aren't in the process of rebooting. // We are executing, so we aren't in the process of rebooting.
*out_config = u64{0}; return u64{0};
return ResultSuccess;
case ConfigItem::ExosphereNeedsShutdown: case ConfigItem::ExosphereNeedsShutdown:
// We are executing, so we aren't in the process of shutting down. // We are executing, so we aren't in the process of shutting down.
*out_config = u64{0}; return u64{0};
return ResultSuccess;
case ConfigItem::ExosphereGitCommitHash: case ConfigItem::ExosphereGitCommitHash:
// Get information about the current exosphere git commit hash. // Get information about the current exosphere git commit hash.
*out_config = u64{0}; return u64{0};
return ResultSuccess;
case ConfigItem::ExosphereHasRcmBugPatch: case ConfigItem::ExosphereHasRcmBugPatch:
// Get information about whether this unit has the RCM bug patched. // Get information about whether this unit has the RCM bug patched.
*out_config = u64{0}; return u64{0};
return ResultSuccess;
case ConfigItem::ExosphereBlankProdInfo: case ConfigItem::ExosphereBlankProdInfo:
// Get whether this unit should simulate a "blanked" PRODINFO. // Get whether this unit should simulate a "blanked" PRODINFO.
*out_config = u64{0}; return u64{0};
return ResultSuccess;
case ConfigItem::ExosphereAllowCalWrites: case ConfigItem::ExosphereAllowCalWrites:
// Get whether this unit should allow writing to the calibration partition. // Get whether this unit should allow writing to the calibration partition.
*out_config = u64{0}; return u64{0};
return ResultSuccess;
case ConfigItem::ExosphereEmummcType: case ConfigItem::ExosphereEmummcType:
// Get what kind of emummc this unit has active. // Get what kind of emummc this unit has active.
*out_config = u64{0}; return u64{0};
return ResultSuccess;
case ConfigItem::ExospherePayloadAddress: case ConfigItem::ExospherePayloadAddress:
// Gets the physical address of the reboot payload buffer, if one exists. // Gets the physical address of the reboot payload buffer, if one exists.
return ResultSecureMonitorNotInitialized; return ResultSecureMonitorNotInitialized;
case ConfigItem::ExosphereLogConfiguration: case ConfigItem::ExosphereLogConfiguration:
// Get the log configuration. // Get the log configuration.
*out_config = u64{0}; return u64{0};
return ResultSuccess;
case ConfigItem::ExosphereForceEnableUsb30: case ConfigItem::ExosphereForceEnableUsb30:
// Get whether usb 3.0 should be force-enabled. // Get whether usb 3.0 should be force-enabled.
*out_config = u64{0}; return u64{0};
return ResultSuccess;
default: default:
return ResultSecureMonitorInvalidArgument; return ResultSecureMonitorInvalidArgument;
} }

View File

@ -35,7 +35,7 @@ public:
std::shared_ptr<Module> module; std::shared_ptr<Module> module;
private: private:
Result GetConfigImpl(u64* out_config, ConfigItem config_item) const; ResultVal<u64> GetConfigImpl(ConfigItem config_item) const;
std::mt19937 rng; std::mt19937 rng;
}; };

View File

@ -4,7 +4,6 @@
#include "common/string_util.h" #include "common/string_util.h"
#include "core/core.h" #include "core/core.h"
#include "core/hle/result.h"
#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/server_manager.h" #include "core/hle/service/server_manager.h"
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
@ -142,12 +141,12 @@ private:
bool did_set_host_name = false; bool did_set_host_name = false;
bool did_handshake = false; bool did_handshake = false;
Result SetSocketDescriptorImpl(s32* out_fd, s32 fd) { ResultVal<s32> SetSocketDescriptorImpl(s32 fd) {
LOG_DEBUG(Service_SSL, "called, fd={}", fd); LOG_DEBUG(Service_SSL, "called, fd={}", fd);
ASSERT(!did_handshake); ASSERT(!did_handshake);
auto bsd = system.ServiceManager().GetService<Service::Sockets::BSD>("bsd:u"); auto bsd = system.ServiceManager().GetService<Service::Sockets::BSD>("bsd:u");
ASSERT_OR_EXECUTE(bsd, { return ResultInternalError; }); ASSERT_OR_EXECUTE(bsd, { return ResultInternalError; });
s32 ret_fd;
// Based on https://switchbrew.org/wiki/SSL_services#SetSocketDescriptor // Based on https://switchbrew.org/wiki/SSL_services#SetSocketDescriptor
if (do_not_close_socket) { if (do_not_close_socket) {
auto res = bsd->DuplicateSocketImpl(fd); auto res = bsd->DuplicateSocketImpl(fd);
@ -157,9 +156,9 @@ private:
} }
fd = *res; fd = *res;
fd_to_close = fd; fd_to_close = fd;
*out_fd = fd; ret_fd = fd;
} else { } else {
*out_fd = -1; ret_fd = -1;
} }
std::optional<std::shared_ptr<Network::SocketBase>> sock = bsd->GetSocket(fd); std::optional<std::shared_ptr<Network::SocketBase>> sock = bsd->GetSocket(fd);
if (!sock.has_value()) { if (!sock.has_value()) {
@ -168,7 +167,7 @@ private:
} }
socket = std::move(*sock); socket = std::move(*sock);
backend->SetSocket(socket); backend->SetSocket(socket);
return ResultSuccess; return ret_fd;
} }
Result SetHostNameImpl(const std::string& hostname) { Result SetHostNameImpl(const std::string& hostname) {
@ -248,36 +247,34 @@ private:
return ret; return ret;
} }
Result ReadImpl(std::vector<u8>* out_data, size_t size) { ResultVal<std::vector<u8>> ReadImpl(size_t size) {
ASSERT_OR_EXECUTE(did_handshake, { return ResultInternalError; }); ASSERT_OR_EXECUTE(did_handshake, { return ResultInternalError; });
size_t actual_size{}; std::vector<u8> res(size);
Result res = backend->Read(&actual_size, *out_data); ResultVal<size_t> actual = backend->Read(res);
if (res != ResultSuccess) { if (actual.Failed()) {
return res; return actual.Code();
} }
out_data->resize(actual_size); res.resize(*actual);
return res; return res;
} }
Result WriteImpl(size_t* out_size, std::span<const u8> data) { ResultVal<size_t> WriteImpl(std::span<const u8> data) {
ASSERT_OR_EXECUTE(did_handshake, { return ResultInternalError; }); ASSERT_OR_EXECUTE(did_handshake, { return ResultInternalError; });
return backend->Write(out_size, data); return backend->Write(data);
} }
Result PendingImpl(s32* out_pending) { ResultVal<s32> PendingImpl() {
LOG_WARNING(Service_SSL, "(STUBBED) called."); LOG_WARNING(Service_SSL, "(STUBBED) called.");
*out_pending = 0; return 0;
return ResultSuccess;
} }
void SetSocketDescriptor(HLERequestContext& ctx) { void SetSocketDescriptor(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const s32 in_fd = rp.Pop<s32>(); const s32 fd = rp.Pop<s32>();
s32 out_fd{-1}; const ResultVal<s32> res = SetSocketDescriptorImpl(fd);
const Result res = SetSocketDescriptorImpl(&out_fd, in_fd);
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(res); rb.Push(res.Code());
rb.Push<s32>(out_fd); rb.Push<s32>(res.ValueOr(-1));
} }
void SetHostName(HLERequestContext& ctx) { void SetHostName(HLERequestContext& ctx) {
@ -316,15 +313,14 @@ private:
}; };
static_assert(sizeof(OutputParameters) == 0x8); static_assert(sizeof(OutputParameters) == 0x8);
Result res = DoHandshakeImpl(); const Result res = DoHandshakeImpl();
OutputParameters out{}; OutputParameters out{};
if (res == ResultSuccess) { if (res == ResultSuccess) {
std::vector<std::vector<u8>> certs; auto certs = backend->GetServerCerts();
res = backend->GetServerCerts(&certs); if (certs.Succeeded()) {
if (res == ResultSuccess) { const std::vector<u8> certs_buf = SerializeServerCerts(*certs);
const std::vector<u8> certs_buf = SerializeServerCerts(certs);
ctx.WriteBuffer(certs_buf); ctx.WriteBuffer(certs_buf);
out.certs_count = static_cast<u32>(certs.size()); out.certs_count = static_cast<u32>(certs->size());
out.certs_size = static_cast<u32>(certs_buf.size()); out.certs_size = static_cast<u32>(certs_buf.size());
} }
} }
@ -334,32 +330,29 @@ private:
} }
void Read(HLERequestContext& ctx) { void Read(HLERequestContext& ctx) {
std::vector<u8> output_bytes; const ResultVal<std::vector<u8>> res = ReadImpl(ctx.GetWriteBufferSize());
const Result res = ReadImpl(&output_bytes, ctx.GetWriteBufferSize());
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(res); rb.Push(res.Code());
if (res == ResultSuccess) { if (res.Succeeded()) {
rb.Push(static_cast<u32>(output_bytes.size())); rb.Push(static_cast<u32>(res->size()));
ctx.WriteBuffer(output_bytes); ctx.WriteBuffer(*res);
} else { } else {
rb.Push(static_cast<u32>(0)); rb.Push(static_cast<u32>(0));
} }
} }
void Write(HLERequestContext& ctx) { void Write(HLERequestContext& ctx) {
size_t write_size{0}; const ResultVal<size_t> res = WriteImpl(ctx.ReadBuffer());
const Result res = WriteImpl(&write_size, ctx.ReadBuffer());
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(res); rb.Push(res.Code());
rb.Push(static_cast<u32>(write_size)); rb.Push(static_cast<u32>(res.ValueOr(0)));
} }
void Pending(HLERequestContext& ctx) { void Pending(HLERequestContext& ctx) {
s32 pending_size{0}; const ResultVal<s32> res = PendingImpl();
const Result res = PendingImpl(&pending_size);
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(res); rb.Push(res.Code());
rb.Push<s32>(pending_size); rb.Push<s32>(res.ValueOr(0));
} }
void SetSessionCacheMode(HLERequestContext& ctx) { void SetSessionCacheMode(HLERequestContext& ctx) {
@ -445,14 +438,13 @@ private:
void CreateConnection(HLERequestContext& ctx) { void CreateConnection(HLERequestContext& ctx) {
LOG_WARNING(Service_SSL, "called"); LOG_WARNING(Service_SSL, "called");
std::unique_ptr<SSLConnectionBackend> backend; auto backend_res = CreateSSLConnectionBackend();
const Result res = CreateSSLConnectionBackend(&backend);
IPC::ResponseBuilder rb{ctx, 2, 0, 1}; IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(res); rb.Push(backend_res.Code());
if (res == ResultSuccess) { if (backend_res.Succeeded()) {
rb.PushIpcInterface<ISslConnection>(system, ssl_version, shared_data, rb.PushIpcInterface<ISslConnection>(system, ssl_version, shared_data,
std::move(backend)); std::move(*backend_res));
} }
} }

View File

@ -35,11 +35,11 @@ public:
virtual void SetSocket(std::shared_ptr<Network::SocketBase> socket) = 0; virtual void SetSocket(std::shared_ptr<Network::SocketBase> socket) = 0;
virtual Result SetHostName(const std::string& hostname) = 0; virtual Result SetHostName(const std::string& hostname) = 0;
virtual Result DoHandshake() = 0; virtual Result DoHandshake() = 0;
virtual Result Read(size_t* out_size, std::span<u8> data) = 0; virtual ResultVal<size_t> Read(std::span<u8> data) = 0;
virtual Result Write(size_t* out_size, std::span<const u8> data) = 0; virtual ResultVal<size_t> Write(std::span<const u8> data) = 0;
virtual Result GetServerCerts(std::vector<std::vector<u8>>* out_certs) = 0; virtual ResultVal<std::vector<std::vector<u8>>> GetServerCerts() = 0;
}; };
Result CreateSSLConnectionBackend(std::unique_ptr<SSLConnectionBackend>* out_backend); ResultVal<std::unique_ptr<SSLConnectionBackend>> CreateSSLConnectionBackend();
} // namespace Service::SSL } // namespace Service::SSL

View File

@ -7,7 +7,7 @@
namespace Service::SSL { namespace Service::SSL {
Result CreateSSLConnectionBackend(std::unique_ptr<SSLConnectionBackend>* out_backend) { ResultVal<std::unique_ptr<SSLConnectionBackend>> CreateSSLConnectionBackend() {
LOG_ERROR(Service_SSL, LOG_ERROR(Service_SSL,
"Can't create SSL connection because no SSL backend is available on this platform"); "Can't create SSL connection because no SSL backend is available on this platform");
return ResultInternalError; return ResultInternalError;

View File

@ -105,30 +105,31 @@ public:
return ResultInternalError; return ResultInternalError;
} }
} }
return HandleReturn("SSL_do_handshake", 0, ret); return HandleReturn("SSL_do_handshake", 0, ret).Code();
} }
Result Read(size_t* out_size, std::span<u8> data) override { ResultVal<size_t> Read(std::span<u8> data) override {
const int ret = SSL_read_ex(ssl, data.data(), data.size(), out_size); size_t actual;
return HandleReturn("SSL_read_ex", out_size, ret); const int ret = SSL_read_ex(ssl, data.data(), data.size(), &actual);
return HandleReturn("SSL_read_ex", actual, ret);
} }
Result Write(size_t* out_size, std::span<const u8> data) override { ResultVal<size_t> Write(std::span<const u8> data) override {
const int ret = SSL_write_ex(ssl, data.data(), data.size(), out_size); size_t actual;
return HandleReturn("SSL_write_ex", out_size, ret); const int ret = SSL_write_ex(ssl, data.data(), data.size(), &actual);
return HandleReturn("SSL_write_ex", actual, ret);
} }
Result HandleReturn(const char* what, size_t* actual, int ret) { ResultVal<size_t> HandleReturn(const char* what, size_t actual, int ret) {
const int ssl_err = SSL_get_error(ssl, ret); const int ssl_err = SSL_get_error(ssl, ret);
CheckOpenSSLErrors(); CheckOpenSSLErrors();
switch (ssl_err) { switch (ssl_err) {
case SSL_ERROR_NONE: case SSL_ERROR_NONE:
return ResultSuccess; return actual;
case SSL_ERROR_ZERO_RETURN: case SSL_ERROR_ZERO_RETURN:
LOG_DEBUG(Service_SSL, "{} => SSL_ERROR_ZERO_RETURN", what); LOG_DEBUG(Service_SSL, "{} => SSL_ERROR_ZERO_RETURN", what);
// DoHandshake special-cases this, but for Read and Write: // DoHandshake special-cases this, but for Read and Write:
*actual = 0; return size_t(0);
return ResultSuccess;
case SSL_ERROR_WANT_READ: case SSL_ERROR_WANT_READ:
LOG_DEBUG(Service_SSL, "{} => SSL_ERROR_WANT_READ", what); LOG_DEBUG(Service_SSL, "{} => SSL_ERROR_WANT_READ", what);
return ResultWouldBlock; return ResultWouldBlock;
@ -138,20 +139,20 @@ public:
default: default:
if (ssl_err == SSL_ERROR_SYSCALL && got_read_eof) { if (ssl_err == SSL_ERROR_SYSCALL && got_read_eof) {
LOG_DEBUG(Service_SSL, "{} => SSL_ERROR_SYSCALL because server hung up", what); LOG_DEBUG(Service_SSL, "{} => SSL_ERROR_SYSCALL because server hung up", what);
*actual = 0; return size_t(0);
return ResultSuccess;
} }
LOG_ERROR(Service_SSL, "{} => other SSL_get_error return value {}", what, ssl_err); LOG_ERROR(Service_SSL, "{} => other SSL_get_error return value {}", what, ssl_err);
return ResultInternalError; return ResultInternalError;
} }
} }
Result GetServerCerts(std::vector<std::vector<u8>>* out_certs) override { ResultVal<std::vector<std::vector<u8>>> GetServerCerts() override {
STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl); STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl);
if (!chain) { if (!chain) {
LOG_ERROR(Service_SSL, "SSL_get_peer_cert_chain returned nullptr"); LOG_ERROR(Service_SSL, "SSL_get_peer_cert_chain returned nullptr");
return ResultInternalError; return ResultInternalError;
} }
std::vector<std::vector<u8>> ret;
int count = sk_X509_num(chain); int count = sk_X509_num(chain);
ASSERT(count >= 0); ASSERT(count >= 0);
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
@ -160,10 +161,10 @@ public:
unsigned char* buf = nullptr; unsigned char* buf = nullptr;
int len = i2d_X509(x509, &buf); int len = i2d_X509(x509, &buf);
ASSERT_OR_EXECUTE(len >= 0 && buf, { continue; }); ASSERT_OR_EXECUTE(len >= 0 && buf, { continue; });
out_certs->emplace_back(buf, buf + len); ret.emplace_back(buf, buf + len);
OPENSSL_free(buf); OPENSSL_free(buf);
} }
return ResultSuccess; return ret;
} }
~SSLConnectionBackendOpenSSL() { ~SSLConnectionBackendOpenSSL() {
@ -252,13 +253,13 @@ public:
std::shared_ptr<Network::SocketBase> socket; std::shared_ptr<Network::SocketBase> socket;
}; };
Result CreateSSLConnectionBackend(std::unique_ptr<SSLConnectionBackend>* out_backend) { ResultVal<std::unique_ptr<SSLConnectionBackend>> CreateSSLConnectionBackend() {
auto conn = std::make_unique<SSLConnectionBackendOpenSSL>(); auto conn = std::make_unique<SSLConnectionBackendOpenSSL>();
const Result res = conn->Init();
R_TRY(conn->Init()); if (res.IsFailure()) {
return res;
*out_backend = std::move(conn); }
return ResultSuccess; return conn;
} }
namespace { namespace {

View File

@ -299,22 +299,21 @@ public:
return ResultSuccess; return ResultSuccess;
} }
Result Read(size_t* out_size, std::span<u8> data) override { ResultVal<size_t> Read(std::span<u8> data) override {
*out_size = 0;
if (handshake_state != HandshakeState::Connected) { if (handshake_state != HandshakeState::Connected) {
LOG_ERROR(Service_SSL, "Called Read but we did not successfully handshake"); LOG_ERROR(Service_SSL, "Called Read but we did not successfully handshake");
return ResultInternalError; return ResultInternalError;
} }
if (data.size() == 0 || got_read_eof) { if (data.size() == 0 || got_read_eof) {
return ResultSuccess; return size_t(0);
} }
while (1) { while (1) {
if (!cleartext_read_buf.empty()) { if (!cleartext_read_buf.empty()) {
*out_size = std::min(cleartext_read_buf.size(), data.size()); const size_t read_size = std::min(cleartext_read_buf.size(), data.size());
std::memcpy(data.data(), cleartext_read_buf.data(), *out_size); std::memcpy(data.data(), cleartext_read_buf.data(), read_size);
cleartext_read_buf.erase(cleartext_read_buf.begin(), cleartext_read_buf.erase(cleartext_read_buf.begin(),
cleartext_read_buf.begin() + *out_size); cleartext_read_buf.begin() + read_size);
return ResultSuccess; return read_size;
} }
if (!ciphertext_read_buf.empty()) { if (!ciphertext_read_buf.empty()) {
SecBuffer empty{ SecBuffer empty{
@ -367,8 +366,7 @@ public:
case SEC_I_CONTEXT_EXPIRED: case SEC_I_CONTEXT_EXPIRED:
// Server hung up by sending close_notify. // Server hung up by sending close_notify.
got_read_eof = true; got_read_eof = true;
*out_size = 0; return size_t(0);
return ResultSuccess;
default: default:
LOG_ERROR(Service_SSL, "DecryptMessage failed: {}", LOG_ERROR(Service_SSL, "DecryptMessage failed: {}",
Common::NativeErrorToString(ret)); Common::NativeErrorToString(ret));
@ -381,21 +379,18 @@ public:
} }
if (ciphertext_read_buf.empty()) { if (ciphertext_read_buf.empty()) {
got_read_eof = true; got_read_eof = true;
*out_size = 0; return size_t(0);
return ResultSuccess;
} }
} }
} }
Result Write(size_t* out_size, std::span<const u8> data) override { ResultVal<size_t> Write(std::span<const u8> data) override {
*out_size = 0;
if (handshake_state != HandshakeState::Connected) { if (handshake_state != HandshakeState::Connected) {
LOG_ERROR(Service_SSL, "Called Write but we did not successfully handshake"); LOG_ERROR(Service_SSL, "Called Write but we did not successfully handshake");
return ResultInternalError; return ResultInternalError;
} }
if (data.size() == 0) { if (data.size() == 0) {
return ResultSuccess; return size_t(0);
} }
data = data.subspan(0, std::min<size_t>(data.size(), stream_sizes.cbMaximumMessage)); data = data.subspan(0, std::min<size_t>(data.size(), stream_sizes.cbMaximumMessage));
if (!cleartext_write_buf.empty()) { if (!cleartext_write_buf.empty()) {
@ -407,7 +402,7 @@ public:
LOG_ERROR(Service_SSL, "Called Write but buffer does not match previous buffer"); LOG_ERROR(Service_SSL, "Called Write but buffer does not match previous buffer");
return ResultInternalError; return ResultInternalError;
} }
return WriteAlreadyEncryptedData(out_size); return WriteAlreadyEncryptedData();
} else { } else {
cleartext_write_buf.assign(data.begin(), data.end()); cleartext_write_buf.assign(data.begin(), data.end());
} }
@ -453,21 +448,21 @@ public:
tmp_data_buf.end()); tmp_data_buf.end());
ciphertext_write_buf.insert(ciphertext_write_buf.end(), trailer_buf.begin(), ciphertext_write_buf.insert(ciphertext_write_buf.end(), trailer_buf.begin(),
trailer_buf.end()); trailer_buf.end());
return WriteAlreadyEncryptedData(out_size); return WriteAlreadyEncryptedData();
} }
Result WriteAlreadyEncryptedData(size_t* out_size) { ResultVal<size_t> WriteAlreadyEncryptedData() {
const Result r = FlushCiphertextWriteBuf(); const Result r = FlushCiphertextWriteBuf();
if (r != ResultSuccess) { if (r != ResultSuccess) {
return r; return r;
} }
// write buf is empty // write buf is empty
*out_size = cleartext_write_buf.size(); const size_t cleartext_bytes_written = cleartext_write_buf.size();
cleartext_write_buf.clear(); cleartext_write_buf.clear();
return ResultSuccess; return cleartext_bytes_written;
} }
Result GetServerCerts(std::vector<std::vector<u8>>* out_certs) override { ResultVal<std::vector<std::vector<u8>>> GetServerCerts() override {
PCCERT_CONTEXT returned_cert = nullptr; PCCERT_CONTEXT returned_cert = nullptr;
const SECURITY_STATUS ret = const SECURITY_STATUS ret =
QueryContextAttributes(&ctxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &returned_cert); QueryContextAttributes(&ctxt, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &returned_cert);
@ -478,15 +473,16 @@ public:
return ResultInternalError; return ResultInternalError;
} }
PCCERT_CONTEXT some_cert = nullptr; PCCERT_CONTEXT some_cert = nullptr;
std::vector<std::vector<u8>> certs;
while ((some_cert = CertEnumCertificatesInStore(returned_cert->hCertStore, some_cert))) { while ((some_cert = CertEnumCertificatesInStore(returned_cert->hCertStore, some_cert))) {
out_certs->emplace_back(static_cast<u8*>(some_cert->pbCertEncoded), certs.emplace_back(static_cast<u8*>(some_cert->pbCertEncoded),
static_cast<u8*>(some_cert->pbCertEncoded) + static_cast<u8*>(some_cert->pbCertEncoded) +
some_cert->cbCertEncoded); some_cert->cbCertEncoded);
} }
std::reverse(out_certs->begin(), std::reverse(certs.begin(),
out_certs->end()); // Windows returns certs in reverse order from what we want certs.end()); // Windows returns certs in reverse order from what we want
CertFreeCertificateContext(returned_cert); CertFreeCertificateContext(returned_cert);
return ResultSuccess; return certs;
} }
~SSLConnectionBackendSchannel() { ~SSLConnectionBackendSchannel() {
@ -536,13 +532,13 @@ public:
size_t read_buf_fill_size = 0; size_t read_buf_fill_size = 0;
}; };
Result CreateSSLConnectionBackend(std::unique_ptr<SSLConnectionBackend>* out_backend) { ResultVal<std::unique_ptr<SSLConnectionBackend>> CreateSSLConnectionBackend() {
auto conn = std::make_unique<SSLConnectionBackendSchannel>(); auto conn = std::make_unique<SSLConnectionBackendSchannel>();
const Result res = conn->Init();
R_TRY(conn->Init()); if (res.IsFailure()) {
return res;
*out_backend = std::move(conn); }
return ResultSuccess; return conn;
} }
} // namespace Service::SSL } // namespace Service::SSL

View File

@ -103,20 +103,24 @@ public:
return HandleReturn("SSLHandshake", 0, status).Code(); return HandleReturn("SSLHandshake", 0, status).Code();
} }
Result Read(size_t* out_size, std::span<u8> data) override { ResultVal<size_t> Read(std::span<u8> data) override {
OSStatus status = SSLRead(context, data.data(), data.size(), out_size); size_t actual;
return HandleReturn("SSLRead", out_size, status); OSStatus status = SSLRead(context, data.data(), data.size(), &actual);
;
return HandleReturn("SSLRead", actual, status);
} }
Result Write(size_t* out_size, std::span<const u8> data) override { ResultVal<size_t> Write(std::span<const u8> data) override {
OSStatus status = SSLWrite(context, data.data(), data.size(), out_size); size_t actual;
return HandleReturn("SSLWrite", out_size, status); OSStatus status = SSLWrite(context, data.data(), data.size(), &actual);
;
return HandleReturn("SSLWrite", actual, status);
} }
Result HandleReturn(const char* what, size_t* actual, OSStatus status) { ResultVal<size_t> HandleReturn(const char* what, size_t actual, OSStatus status) {
switch (status) { switch (status) {
case 0: case 0:
return ResultSuccess; return actual;
case errSSLWouldBlock: case errSSLWouldBlock:
return ResultWouldBlock; return ResultWouldBlock;
default: { default: {
@ -132,21 +136,22 @@ public:
} }
} }
Result GetServerCerts(std::vector<std::vector<u8>>* out_certs) override { ResultVal<std::vector<std::vector<u8>>> GetServerCerts() override {
CFReleaser<SecTrustRef> trust; CFReleaser<SecTrustRef> trust;
OSStatus status = SSLCopyPeerTrust(context, &trust.ptr); OSStatus status = SSLCopyPeerTrust(context, &trust.ptr);
if (status) { if (status) {
LOG_ERROR(Service_SSL, "SSLCopyPeerTrust failed: {}", OSStatusToString(status)); LOG_ERROR(Service_SSL, "SSLCopyPeerTrust failed: {}", OSStatusToString(status));
return ResultInternalError; return ResultInternalError;
} }
std::vector<std::vector<u8>> ret;
for (CFIndex i = 0, count = SecTrustGetCertificateCount(trust); i < count; i++) { for (CFIndex i = 0, count = SecTrustGetCertificateCount(trust); i < count; i++) {
SecCertificateRef cert = SecTrustGetCertificateAtIndex(trust, i); SecCertificateRef cert = SecTrustGetCertificateAtIndex(trust, i);
CFReleaser<CFDataRef> data(SecCertificateCopyData(cert)); CFReleaser<CFDataRef> data(SecCertificateCopyData(cert));
ASSERT_OR_EXECUTE(data, { return ResultInternalError; }); ASSERT_OR_EXECUTE(data, { return ResultInternalError; });
const u8* ptr = CFDataGetBytePtr(data); const u8* ptr = CFDataGetBytePtr(data);
out_certs->emplace_back(ptr, ptr + CFDataGetLength(data)); ret.emplace_back(ptr, ptr + CFDataGetLength(data));
} }
return ResultSuccess; return ret;
} }
static OSStatus ReadCallback(SSLConnectionRef connection, void* data, size_t* dataLength) { static OSStatus ReadCallback(SSLConnectionRef connection, void* data, size_t* dataLength) {
@ -205,13 +210,13 @@ private:
std::shared_ptr<Network::SocketBase> socket; std::shared_ptr<Network::SocketBase> socket;
}; };
Result CreateSSLConnectionBackend(std::unique_ptr<SSLConnectionBackend>* out_backend) { ResultVal<std::unique_ptr<SSLConnectionBackend>> CreateSSLConnectionBackend() {
auto conn = std::make_unique<SSLConnectionBackendSecureTransport>(); auto conn = std::make_unique<SSLConnectionBackendSecureTransport>();
const Result res = conn->Init();
R_TRY(conn->Init()); if (res.IsFailure()) {
return res;
*out_backend = std::move(conn); }
return ResultSuccess; return conn;
} }
} // namespace Service::SSL } // namespace Service::SSL

View File

@ -58,15 +58,14 @@ const Layer& Display::GetLayer(std::size_t index) const {
return *layers.at(index); return *layers.at(index);
} }
Result Display::GetVSyncEvent(Kernel::KReadableEvent** out_vsync_event) { ResultVal<Kernel::KReadableEvent*> Display::GetVSyncEvent() {
if (got_vsync_event) { if (got_vsync_event) {
return ResultPermissionDenied; return ResultPermissionDenied;
} }
got_vsync_event = true; got_vsync_event = true;
*out_vsync_event = GetVSyncEventUnchecked(); return GetVSyncEventUnchecked();
return ResultSuccess;
} }
Kernel::KReadableEvent* Display::GetVSyncEventUnchecked() { Kernel::KReadableEvent* Display::GetVSyncEventUnchecked() {

View File

@ -85,7 +85,7 @@ public:
* @returns The internal Vsync event if it has not yet been retrieved, * @returns The internal Vsync event if it has not yet been retrieved,
* VI::ResultPermissionDenied otherwise. * VI::ResultPermissionDenied otherwise.
*/ */
[[nodiscard]] Result GetVSyncEvent(Kernel::KReadableEvent** out_vsync_event); [[nodiscard]] ResultVal<Kernel::KReadableEvent*> GetVSyncEvent();
/// Gets the internal vsync event. /// Gets the internal vsync event.
Kernel::KReadableEvent* GetVSyncEventUnchecked(); Kernel::KReadableEvent* GetVSyncEventUnchecked();

View File

@ -683,9 +683,9 @@ private:
LOG_DEBUG(Service_VI, "called. display_id={}", display_id); LOG_DEBUG(Service_VI, "called. display_id={}", display_id);
Kernel::KReadableEvent* vsync_event{}; const auto vsync_event = nv_flinger.FindVsyncEvent(display_id);
const auto result = nv_flinger.FindVsyncEvent(&vsync_event, display_id); if (vsync_event.Failed()) {
if (result != ResultSuccess) { const auto result = vsync_event.Code();
if (result == ResultNotFound) { if (result == ResultNotFound) {
LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id);
} }
@ -697,7 +697,7 @@ private:
IPC::ResponseBuilder rb{ctx, 2, 1}; IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.PushCopyObjects(vsync_event); rb.PushCopyObjects(*vsync_event);
} }
void ConvertScalingMode(HLERequestContext& ctx) { void ConvertScalingMode(HLERequestContext& ctx) {
@ -705,16 +705,15 @@ private:
const auto mode = rp.PopEnum<NintendoScaleMode>(); const auto mode = rp.PopEnum<NintendoScaleMode>();
LOG_DEBUG(Service_VI, "called mode={}", mode); LOG_DEBUG(Service_VI, "called mode={}", mode);
ConvertedScaleMode converted_mode{}; const auto converted_mode = ConvertScalingModeImpl(mode);
const auto result = ConvertScalingModeImpl(&converted_mode, mode);
if (result == ResultSuccess) { if (converted_mode.Succeeded()) {
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.PushEnum(converted_mode); rb.PushEnum(*converted_mode);
} else { } else {
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(result); rb.Push(converted_mode.Code());
} }
} }
@ -761,24 +760,18 @@ private:
rb.Push(alignment); rb.Push(alignment);
} }
static Result ConvertScalingModeImpl(ConvertedScaleMode* out_scaling_mode, static ResultVal<ConvertedScaleMode> ConvertScalingModeImpl(NintendoScaleMode mode) {
NintendoScaleMode mode) {
switch (mode) { switch (mode) {
case NintendoScaleMode::None: case NintendoScaleMode::None:
*out_scaling_mode = ConvertedScaleMode::None; return ConvertedScaleMode::None;
return ResultSuccess;
case NintendoScaleMode::Freeze: case NintendoScaleMode::Freeze:
*out_scaling_mode = ConvertedScaleMode::Freeze; return ConvertedScaleMode::Freeze;
return ResultSuccess;
case NintendoScaleMode::ScaleToWindow: case NintendoScaleMode::ScaleToWindow:
*out_scaling_mode = ConvertedScaleMode::ScaleToWindow; return ConvertedScaleMode::ScaleToWindow;
return ResultSuccess;
case NintendoScaleMode::ScaleAndCrop: case NintendoScaleMode::ScaleAndCrop:
*out_scaling_mode = ConvertedScaleMode::ScaleAndCrop; return ConvertedScaleMode::ScaleAndCrop;
return ResultSuccess;
case NintendoScaleMode::PreserveAspectRatio: case NintendoScaleMode::PreserveAspectRatio:
*out_scaling_mode = ConvertedScaleMode::PreserveAspectRatio; return ConvertedScaleMode::PreserveAspectRatio;
return ResultSuccess;
default: default:
LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode); LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode);
return ResultOperationFailed; return ResultOperationFailed;

View File

@ -106,43 +106,6 @@ bool IsASTCSupported() {
return true; return true;
} }
static bool HasSlowSoftwareAstc(std::string_view vendor_name, std::string_view renderer) {
// ifdef for Unix reduces string comparisons for non-Windows drivers, and Intel
#ifdef YUZU_UNIX
// Sorted vaguely by how likely a vendor is to appear
if (vendor_name == "AMD") {
// RadeonSI
return true;
}
if (vendor_name == "Intel") {
// Must be inside YUZU_UNIX ifdef as the Windows driver uses the same vendor string
// iris, crocus
const bool is_intel_dg = (renderer.find("DG") != std::string_view::npos);
return is_intel_dg;
}
if (vendor_name == "nouveau") {
return true;
}
if (vendor_name == "X.Org") {
// R600
return true;
}
#endif
if (vendor_name == "Collabora Ltd") {
// Zink
return true;
}
if (vendor_name == "Microsoft Corporation") {
// d3d12
return true;
}
if (vendor_name == "Mesa/X.org") {
// llvmpipe, softpipe, virgl
return true;
}
return false;
}
[[nodiscard]] bool IsDebugToolAttached(std::span<const std::string_view> extensions) { [[nodiscard]] bool IsDebugToolAttached(std::span<const std::string_view> extensions) {
const bool nsight = std::getenv("NVTX_INJECTION64_PATH") || std::getenv("NSIGHT_LAUNCHED"); const bool nsight = std::getenv("NVTX_INJECTION64_PATH") || std::getenv("NSIGHT_LAUNCHED");
return nsight || HasExtension(extensions, "GL_EXT_debug_tool") || return nsight || HasExtension(extensions, "GL_EXT_debug_tool") ||
@ -157,16 +120,12 @@ Device::Device(Core::Frontend::EmuWindow& emu_window) {
} }
vendor_name = reinterpret_cast<const char*>(glGetString(GL_VENDOR)); vendor_name = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
const std::string_view version = reinterpret_cast<const char*>(glGetString(GL_VERSION)); const std::string_view version = reinterpret_cast<const char*>(glGetString(GL_VERSION));
const std::string_view renderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
const std::vector extensions = GetExtensions(); const std::vector extensions = GetExtensions();
const bool is_nvidia = vendor_name == "NVIDIA Corporation"; const bool is_nvidia = vendor_name == "NVIDIA Corporation";
const bool is_amd = vendor_name == "ATI Technologies Inc."; const bool is_amd = vendor_name == "ATI Technologies Inc.";
const bool is_intel = vendor_name == "Intel"; const bool is_intel = vendor_name == "Intel";
const bool has_slow_software_astc =
!is_nvidia && !is_amd && HasSlowSoftwareAstc(vendor_name, renderer);
#ifdef __unix__ #ifdef __unix__
constexpr bool is_linux = true; constexpr bool is_linux = true;
#else #else
@ -193,7 +152,7 @@ Device::Device(Core::Frontend::EmuWindow& emu_window) {
has_vertex_viewport_layer = GLAD_GL_ARB_shader_viewport_layer_array; has_vertex_viewport_layer = GLAD_GL_ARB_shader_viewport_layer_array;
has_image_load_formatted = HasExtension(extensions, "GL_EXT_shader_image_load_formatted"); has_image_load_formatted = HasExtension(extensions, "GL_EXT_shader_image_load_formatted");
has_texture_shadow_lod = HasExtension(extensions, "GL_EXT_texture_shadow_lod"); has_texture_shadow_lod = HasExtension(extensions, "GL_EXT_texture_shadow_lod");
has_astc = !has_slow_software_astc && IsASTCSupported(); has_astc = IsASTCSupported();
has_variable_aoffi = TestVariableAoffi(); has_variable_aoffi = TestVariableAoffi();
has_component_indexing_bug = is_amd; has_component_indexing_bug = is_amd;
has_precise_bug = TestPreciseBug(); has_precise_bug = TestPreciseBug();