From a75145a2c66808f1c4c905da415f0c9c22172dfd Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Sat, 20 May 2017 20:40:13 -0700 Subject: [PATCH 1/7] Make BitField and ResultCode constexpr-initializable --- src/common/bit_field.h | 93 +++++++++++++++++++++++++----------------- src/core/hle/result.h | 33 +++++++-------- 2 files changed, 71 insertions(+), 55 deletions(-) diff --git a/src/common/bit_field.h b/src/common/bit_field.h index 030f7caeb..72a01c7a8 100644 --- a/src/common/bit_field.h +++ b/src/common/bit_field.h @@ -108,7 +108,7 @@ * symptoms. */ #pragma pack(1) -template +template struct BitField { private: // We hide the copy assigment operator here, because the default copy @@ -117,40 +117,6 @@ private: // We don't delete it because we want BitField to be trivially copyable. BitField& operator=(const BitField&) = default; -public: - // This constructor and assignment operator might be considered ambiguous: - // Would they initialize the storage or just the bitfield? - // Hence, delete them. Use the Assign method to set bitfield values! - BitField(T val) = delete; - BitField& operator=(T val) = delete; - - // Force default constructor to be created - // so that we can use this within unions - BitField() = default; - - FORCE_INLINE operator T() const { - return Value(); - } - - FORCE_INLINE void Assign(const T& value) { - storage = (storage & ~GetMask()) | (((StorageType)value << position) & GetMask()); - } - - FORCE_INLINE T Value() const { - if (std::numeric_limits::is_signed) { - std::size_t shift = 8 * sizeof(T) - bits; - return (T)((storage << (shift - position)) >> shift); - } else { - return (T)((storage & GetMask()) >> position); - } - } - - // TODO: we may want to change this to explicit operator bool() if it's bug-free in VS2015 - FORCE_INLINE bool ToBool() const { - return Value() != 0; - } - -private: // StorageType is T for non-enum types and the underlying type of T if // T is an enumeration. Note that T is wrapped within an enable_if in the // former case to workaround compile errors which arise when using @@ -161,10 +127,63 @@ private: // Unsigned version of StorageType typedef typename std::make_unsigned::type StorageTypeU; - FORCE_INLINE StorageType GetMask() const { - return (((StorageTypeU)~0) >> (8 * sizeof(T) - bits)) << position; +public: + /// Constants to allow limited introspection of fields if needed + static constexpr size_t position = Position; + static constexpr size_t bits = Bits; + static constexpr StorageType mask = (((StorageTypeU)~0) >> (8 * sizeof(T) - bits)) << position; + + /** + * Formats a value by masking and shifting it according to the field parameters. A value + * containing several bitfields can be assembled by formatting each of their values and ORing + * the results together. + */ + static constexpr FORCE_INLINE StorageType FormatValue(const T& value) { + return ((StorageType)value << position) & mask; } + /** + * Extracts a value from the passed storage. In most situations prefer use the member functions + * (such as Value() or operator T), but this can be used to extract a value from a bitfield + * union in a constexpr context. + */ + static constexpr FORCE_INLINE T ExtractValue(const StorageType& storage) { + if (std::numeric_limits::is_signed) { + std::size_t shift = 8 * sizeof(T) - bits; + return (T)((storage << (shift - position)) >> shift); + } else { + return (T)((storage & mask) >> position); + } + } + + // This constructor and assignment operator might be considered ambiguous: + // Would they initialize the storage or just the bitfield? + // Hence, delete them. Use the Assign method to set bitfield values! + BitField(T val) = delete; + BitField& operator=(T val) = delete; + + // Force default constructor to be created + // so that we can use this within unions + constexpr BitField() = default; + + FORCE_INLINE operator T() const { + return Value(); + } + + FORCE_INLINE void Assign(const T& value) { + storage = (storage & ~mask) | FormatValue(value); + } + + FORCE_INLINE T Value() const { + return ExtractValue(storage); + } + + // TODO: we may want to change this to explicit operator bool() if it's bug-free in VS2015 + FORCE_INLINE bool ToBool() const { + return Value() != 0; + } + +private: StorageType storage; static_assert(bits + position <= 8 * sizeof(T), "Bitfield out of range"); diff --git a/src/core/hle/result.h b/src/core/hle/result.h index 13b948871..db548bd76 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h @@ -228,45 +228,42 @@ union ResultCode { // error BitField<31, 1, u32> is_error; - explicit ResultCode(u32 raw) : raw(raw) {} - ResultCode(ErrorDescription description_, ErrorModule module_, ErrorSummary summary_, - ErrorLevel level_) - : raw(0) { - description.Assign(description_); - module.Assign(module_); - summary.Assign(summary_); - level.Assign(level_); - } + constexpr explicit ResultCode(u32 raw) : raw(raw) {} - ResultCode& operator=(const ResultCode& o) { + constexpr ResultCode(ErrorDescription description_, ErrorModule module_, ErrorSummary summary_, + ErrorLevel level_) + : raw(description.FormatValue(description_) | module.FormatValue(module_) | + summary.FormatValue(summary_) | level.FormatValue(level_)) {} + + constexpr ResultCode& operator=(const ResultCode& o) { raw = o.raw; return *this; } - bool IsSuccess() const { - return is_error == 0; + constexpr bool IsSuccess() const { + return is_error.ExtractValue(raw) == 0; } - bool IsError() const { - return is_error == 1; + constexpr bool IsError() const { + return is_error.ExtractValue(raw) == 1; } }; -inline bool operator==(const ResultCode& a, const ResultCode& b) { +constexpr bool operator==(const ResultCode& a, const ResultCode& b) { return a.raw == b.raw; } -inline bool operator!=(const ResultCode& a, const ResultCode& b) { +constexpr bool operator!=(const ResultCode& a, const ResultCode& b) { return a.raw != b.raw; } // Convenience functions for creating some common kinds of errors: /// The default success `ResultCode`. -const ResultCode RESULT_SUCCESS(0); +constexpr ResultCode RESULT_SUCCESS(0); /// Might be returned instead of a dummy success for unimplemented APIs. -inline ResultCode UnimplementedFunction(ErrorModule module) { +constexpr ResultCode UnimplementedFunction(ErrorModule module) { return ResultCode(ErrorDescription::NotImplemented, module, ErrorSummary::NotSupported, ErrorLevel::Permanent); } From 3b1f0fea31d3c56d94f580c1ea3978a5590b5f8a Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Sat, 20 May 2017 21:00:18 -0700 Subject: [PATCH 2/7] result: Make error description a generic integer It is now known that result code description vary depending on the module, and so they're best defined on a per-module basis. To support this, allow passing in an arbitrary integer instead of limiting to the ones in the ErrorDescription enum. These will be gradually migrated to their individual users, but a few will be kept as "common" codes shared by all modules. --- src/core/hle/result.h | 17 ++++++++++++++--- src/core/hle/service/cfg/cfg.cpp | 5 +++-- src/core/hle/service/ptm/ptm.cpp | 2 +- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/core/hle/result.h b/src/core/hle/result.h index db548bd76..c44668732 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h @@ -13,9 +13,14 @@ // All the constants in this file come from http://3dbrew.org/wiki/Error_codes -/// Detailed description of the error. This listing is likely incomplete. +/** + * Detailed description of the error. Code 0 always means success. Codes 1000 and above are + * considered "well-known" and have common values between all modules. The meaning of other codes + * vary by module. + */ enum class ErrorDescription : u32 { Success = 0, + SessionClosedByRemote = 26, WrongPermission = 46, OS_InvalidBufferDescriptor = 48, @@ -45,6 +50,8 @@ enum class ErrorDescription : u32 { FS_UnsupportedOpenFlags = 760, FS_IncorrectExeFSReadSize = 761, FS_UnexpectedFileOrDirectory = 770, + + // Codes 1000 and above are considered "well-known" and have common values between all modules. InvalidSection = 1000, TooLarge = 1001, NotAuthorized = 1002, @@ -218,7 +225,7 @@ enum class ErrorLevel : u32 { union ResultCode { u32 raw; - BitField<0, 10, ErrorDescription> description; + BitField<0, 10, u32> description; BitField<10, 8, ErrorModule> module; BitField<21, 6, ErrorSummary> summary; @@ -230,7 +237,11 @@ union ResultCode { constexpr explicit ResultCode(u32 raw) : raw(raw) {} - constexpr ResultCode(ErrorDescription description_, ErrorModule module_, ErrorSummary summary_, + constexpr ResultCode(ErrorDescription description, ErrorModule module, ErrorSummary summary, + ErrorLevel level) + : ResultCode(static_cast(description), module, summary, level) {} + + constexpr ResultCode(u32 description_, ErrorModule module_, ErrorSummary summary_, ErrorLevel level_) : raw(description.FormatValue(description_) | module.FormatValue(module_) | summary.FormatValue(summary_) | level.FormatValue(level_)) {} diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp index 8c8c1ec77..14185ae20 100644 --- a/src/core/hle/service/cfg/cfg.cpp +++ b/src/core/hle/service/cfg/cfg.cpp @@ -411,7 +411,8 @@ ResultCode UpdateConfigNANDSavegame() { ResultCode FormatConfig() { ResultCode res = DeleteConfigNANDSaveFile(); // The delete command fails if the file doesn't exist, so we have to check that too - if (!res.IsSuccess() && res.description != ErrorDescription::FS_FileNotFound) { + if (!res.IsSuccess() && + res.description != static_cast(ErrorDescription::FS_FileNotFound)) { return res; } // Delete the old data @@ -534,7 +535,7 @@ ResultCode LoadConfigNANDSaveFile() { Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path); // If the archive didn't exist, create the files inside - if (archive_result.Code().description == ErrorDescription::FS_NotFormatted) { + if (archive_result.Code().description == static_cast(ErrorDescription::FS_NotFormatted)) { // Format the archive to create the directories Service::FS::FormatArchive(Service::FS::ArchiveIdCode::SystemSaveData, FileSys::ArchiveFormatInfo(), archive_path); diff --git a/src/core/hle/service/ptm/ptm.cpp b/src/core/hle/service/ptm/ptm.cpp index 319e8c946..b6d6d105a 100644 --- a/src/core/hle/service/ptm/ptm.cpp +++ b/src/core/hle/service/ptm/ptm.cpp @@ -134,7 +134,7 @@ void Init() { auto archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path); // If the archive didn't exist, create the files inside - if (archive_result.Code().description == ErrorDescription::FS_NotFormatted) { + if (archive_result.Code().description == static_cast(ErrorDescription::FS_NotFormatted)) { // Format the archive to create the directories Service::FS::FormatArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, FileSys::ArchiveFormatInfo(), archive_path); From 92be29adba56408685e594e5e659f1dc83686cde Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Sat, 20 May 2017 21:41:11 -0700 Subject: [PATCH 3/7] FileSys: Move all result description to errors.h --- src/core/file_sys/archive_extsavedata.cpp | 12 +- .../file_sys/archive_source_sd_savedata.cpp | 7 +- src/core/file_sys/archive_systemsavedata.cpp | 4 +- src/core/file_sys/disk_archive.cpp | 7 +- src/core/file_sys/errors.h | 127 ++++++++++++------ src/core/hle/result.h | 21 --- src/core/hle/service/cfg/cfg.cpp | 6 +- src/core/hle/service/fs/archive.cpp | 28 ++-- src/core/hle/service/fs/fs_user.cpp | 5 +- src/core/hle/service/ptm/ptm.cpp | 3 +- 10 files changed, 115 insertions(+), 105 deletions(-) diff --git a/src/core/file_sys/archive_extsavedata.cpp b/src/core/file_sys/archive_extsavedata.cpp index f454e7840..4867c9d17 100644 --- a/src/core/file_sys/archive_extsavedata.cpp +++ b/src/core/file_sys/archive_extsavedata.cpp @@ -38,8 +38,7 @@ public: ResultVal Write(u64 offset, size_t length, bool flush, const u8* buffer) const override { if (offset > size) { - return ResultCode(ErrorDescription::FS_WriteBeyondEnd, ErrorModule::FS, - ErrorSummary::InvalidArgument, ErrorLevel::Usage); + return ERR_WRITE_BEYOND_END; } else if (offset == size) { return MakeResult(0); } @@ -191,11 +190,9 @@ ResultVal> ArchiveFactory_ExtSaveData::Open(cons // TODO(Subv): Verify the archive behavior of SharedExtSaveData compared to ExtSaveData. // ExtSaveData seems to return FS_NotFound (120) when the archive doesn't exist. if (!shared) { - return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, - ErrorSummary::InvalidState, ErrorLevel::Status); + return ERR_NOT_FOUND_INVALID_STATE; } else { - return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, - ErrorSummary::InvalidState, ErrorLevel::Status); + return ERR_NOT_FORMATTED; } } auto archive = std::make_unique(fullpath); @@ -230,8 +227,7 @@ ResultVal ArchiveFactory_ExtSaveData::GetFormatInfo(const Pat if (!file.IsOpen()) { LOG_ERROR(Service_FS, "Could not open metadata information for archive"); // TODO(Subv): Verify error code - return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, - ErrorSummary::InvalidState, ErrorLevel::Status); + return ERR_NOT_FORMATTED; } ArchiveFormatInfo info = {}; diff --git a/src/core/file_sys/archive_source_sd_savedata.cpp b/src/core/file_sys/archive_source_sd_savedata.cpp index f31a68038..a7e331724 100644 --- a/src/core/file_sys/archive_source_sd_savedata.cpp +++ b/src/core/file_sys/archive_source_sd_savedata.cpp @@ -6,6 +6,7 @@ #include "common/logging/log.h" #include "common/string_util.h" #include "core/file_sys/archive_source_sd_savedata.h" +#include "core/file_sys/errors.h" #include "core/file_sys/savedata_archive.h" #include "core/hle/service/fs/archive.h" @@ -49,8 +50,7 @@ ResultVal> ArchiveSource_SDSaveData::Open(u64 pr // save file/directory structure expected by the game has not yet been initialized. // Returning the NotFormatted error code will signal the game to provision the SaveData // archive with the files and folders that it expects. - return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, - ErrorSummary::InvalidState, ErrorLevel::Status); + return ERR_NOT_FORMATTED; } auto archive = std::make_unique(std::move(concrete_mount_point)); @@ -81,8 +81,7 @@ ResultVal ArchiveSource_SDSaveData::GetFormatInfo(u64 program if (!file.IsOpen()) { LOG_ERROR(Service_FS, "Could not open metadata information for archive"); // TODO(Subv): Verify error code - return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, - ErrorSummary::InvalidState, ErrorLevel::Status); + return ERR_NOT_FORMATTED; } ArchiveFormatInfo info = {}; diff --git a/src/core/file_sys/archive_systemsavedata.cpp b/src/core/file_sys/archive_systemsavedata.cpp index 8986b5c0e..81423bffd 100644 --- a/src/core/file_sys/archive_systemsavedata.cpp +++ b/src/core/file_sys/archive_systemsavedata.cpp @@ -9,6 +9,7 @@ #include "common/file_util.h" #include "common/string_util.h" #include "core/file_sys/archive_systemsavedata.h" +#include "core/file_sys/errors.h" #include "core/file_sys/savedata_archive.h" #include "core/hle/service/fs/archive.h" @@ -53,8 +54,7 @@ ResultVal> ArchiveFactory_SystemSaveData::Open(c std::string fullpath = GetSystemSaveDataPath(base_path, path); if (!FileUtil::Exists(fullpath)) { // TODO(Subv): Check error code, this one is probably wrong - return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS, - ErrorSummary::InvalidState, ErrorLevel::Status); + return ERR_NOT_FORMATTED; } auto archive = std::make_unique(fullpath); return MakeResult>(std::move(archive)); diff --git a/src/core/file_sys/disk_archive.cpp b/src/core/file_sys/disk_archive.cpp index a243d9a13..98d80aabc 100644 --- a/src/core/file_sys/disk_archive.cpp +++ b/src/core/file_sys/disk_archive.cpp @@ -9,6 +9,7 @@ #include "common/file_util.h" #include "common/logging/log.h" #include "core/file_sys/disk_archive.h" +#include "core/file_sys/errors.h" //////////////////////////////////////////////////////////////////////////////////////////////////// // FileSys namespace @@ -17,8 +18,7 @@ namespace FileSys { ResultVal DiskFile::Read(const u64 offset, const size_t length, u8* buffer) const { if (!mode.read_flag) - return ResultCode(ErrorDescription::FS_InvalidOpenFlags, ErrorModule::FS, - ErrorSummary::Canceled, ErrorLevel::Status); + return ERROR_INVALID_OPEN_FLAGS; file->Seek(offset, SEEK_SET); return MakeResult(file->ReadBytes(buffer, length)); @@ -27,8 +27,7 @@ ResultVal DiskFile::Read(const u64 offset, const size_t length, u8* buff ResultVal DiskFile::Write(const u64 offset, const size_t length, const bool flush, const u8* buffer) const { if (!mode.write_flag) - return ResultCode(ErrorDescription::FS_InvalidOpenFlags, ErrorModule::FS, - ErrorSummary::Canceled, ErrorLevel::Status); + return ERROR_INVALID_OPEN_FLAGS; file->Seek(offset, SEEK_SET); size_t written = file->WriteBytes(buffer, length); diff --git a/src/core/file_sys/errors.h b/src/core/file_sys/errors.h index 9fc8d753b..a974bc775 100644 --- a/src/core/file_sys/errors.h +++ b/src/core/file_sys/errors.h @@ -2,52 +2,93 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#pragma once + #include "core/hle/result.h" namespace FileSys { -const ResultCode ERROR_INVALID_PATH(ErrorDescription::FS_InvalidPath, ErrorModule::FS, - ErrorSummary::InvalidArgument, ErrorLevel::Usage); -const ResultCode ERROR_UNSUPPORTED_OPEN_FLAGS(ErrorDescription::FS_UnsupportedOpenFlags, - ErrorModule::FS, ErrorSummary::NotSupported, - ErrorLevel::Usage); -const ResultCode ERROR_INVALID_OPEN_FLAGS(ErrorDescription::FS_InvalidOpenFlags, ErrorModule::FS, - ErrorSummary::Canceled, ErrorLevel::Status); -const ResultCode ERROR_INVALID_READ_FLAG(ErrorDescription::FS_InvalidReadFlag, ErrorModule::FS, - ErrorSummary::InvalidArgument, ErrorLevel::Usage); -const ResultCode ERROR_FILE_NOT_FOUND(ErrorDescription::FS_FileNotFound, ErrorModule::FS, - ErrorSummary::NotFound, ErrorLevel::Status); -const ResultCode ERROR_PATH_NOT_FOUND(ErrorDescription::FS_PathNotFound, ErrorModule::FS, - ErrorSummary::NotFound, ErrorLevel::Status); -const ResultCode ERROR_NOT_FOUND(ErrorDescription::FS_NotFound, ErrorModule::FS, - ErrorSummary::NotFound, ErrorLevel::Status); -const ResultCode ERROR_UNEXPECTED_FILE_OR_DIRECTORY(ErrorDescription::FS_UnexpectedFileOrDirectory, - ErrorModule::FS, ErrorSummary::NotSupported, - ErrorLevel::Usage); -const ResultCode ERROR_UNEXPECTED_FILE_OR_DIRECTORY_SDMC(ErrorDescription::FS_NotAFile, - ErrorModule::FS, ErrorSummary::Canceled, - ErrorLevel::Status); -const ResultCode ERROR_DIRECTORY_ALREADY_EXISTS(ErrorDescription::FS_DirectoryAlreadyExists, - ErrorModule::FS, ErrorSummary::NothingHappened, - ErrorLevel::Status); -const ResultCode ERROR_FILE_ALREADY_EXISTS(ErrorDescription::FS_FileAlreadyExists, ErrorModule::FS, - ErrorSummary::NothingHappened, ErrorLevel::Status); -const ResultCode ERROR_ALREADY_EXISTS(ErrorDescription::FS_AlreadyExists, ErrorModule::FS, - ErrorSummary::NothingHappened, ErrorLevel::Status); -const ResultCode ERROR_DIRECTORY_NOT_EMPTY(ErrorDescription::FS_DirectoryNotEmpty, ErrorModule::FS, - ErrorSummary::Canceled, ErrorLevel::Status); -const ResultCode ERROR_GAMECARD_NOT_INSERTED(ErrorDescription::FS_GameCardNotInserted, - ErrorModule::FS, ErrorSummary::NotFound, - ErrorLevel::Status); -const ResultCode ERROR_INCORRECT_EXEFS_READ_SIZE(ErrorDescription::FS_IncorrectExeFSReadSize, - ErrorModule::FS, ErrorSummary::NotSupported, - ErrorLevel::Usage); -const ResultCode ERROR_ROMFS_NOT_FOUND(ErrorDescription::FS_RomFSNotFound, ErrorModule::FS, - ErrorSummary::NotFound, ErrorLevel::Status); -const ResultCode ERROR_COMMAND_NOT_ALLOWED(ErrorDescription::FS_CommandNotAllowed, ErrorModule::FS, - ErrorSummary::WrongArgument, ErrorLevel::Permanent); -const ResultCode ERROR_EXEFS_SECTION_NOT_FOUND(ErrorDescription::FS_ExeFSSectionNotFound, - ErrorModule::FS, ErrorSummary::NotFound, - ErrorLevel::Status); +namespace ErrCodes { +enum { + RomFSNotFound = 100, + ArchiveNotMounted = 101, + FileNotFound = 112, + PathNotFound = 113, + GameCardNotInserted = 141, + NotFound = 120, + FileAlreadyExists = 180, + DirectoryAlreadyExists = 185, + AlreadyExists = 190, + InvalidOpenFlags = 230, + DirectoryNotEmpty = 240, + NotAFile = 250, + NotFormatted = 340, ///< This is used by the FS service when creating a SaveData archive + ExeFSSectionNotFound = 567, + CommandNotAllowed = 630, + InvalidReadFlag = 700, + InvalidPath = 702, + WriteBeyondEnd = 705, + UnsupportedOpenFlags = 760, + IncorrectExeFSReadSize = 761, + UnexpectedFileOrDirectory = 770, +}; +} + +constexpr ResultCode ERROR_INVALID_PATH(ErrCodes::InvalidPath, ErrorModule::FS, + ErrorSummary::InvalidArgument, ErrorLevel::Usage); +constexpr ResultCode ERROR_UNSUPPORTED_OPEN_FLAGS(ErrCodes::UnsupportedOpenFlags, ErrorModule::FS, + ErrorSummary::NotSupported, ErrorLevel::Usage); +constexpr ResultCode ERROR_INVALID_OPEN_FLAGS(ErrCodes::InvalidOpenFlags, ErrorModule::FS, + ErrorSummary::Canceled, ErrorLevel::Status); +constexpr ResultCode ERROR_INVALID_READ_FLAG(ErrCodes::InvalidReadFlag, ErrorModule::FS, + ErrorSummary::InvalidArgument, ErrorLevel::Usage); +constexpr ResultCode ERROR_FILE_NOT_FOUND(ErrCodes::FileNotFound, ErrorModule::FS, + ErrorSummary::NotFound, ErrorLevel::Status); +constexpr ResultCode ERROR_PATH_NOT_FOUND(ErrCodes::PathNotFound, ErrorModule::FS, + ErrorSummary::NotFound, ErrorLevel::Status); +constexpr ResultCode ERROR_NOT_FOUND(ErrCodes::NotFound, ErrorModule::FS, ErrorSummary::NotFound, + ErrorLevel::Status); +constexpr ResultCode ERROR_UNEXPECTED_FILE_OR_DIRECTORY(ErrCodes::UnexpectedFileOrDirectory, + ErrorModule::FS, ErrorSummary::NotSupported, + ErrorLevel::Usage); +constexpr ResultCode ERROR_UNEXPECTED_FILE_OR_DIRECTORY_SDMC(ErrCodes::NotAFile, ErrorModule::FS, + ErrorSummary::Canceled, + ErrorLevel::Status); +constexpr ResultCode ERROR_DIRECTORY_ALREADY_EXISTS(ErrCodes::DirectoryAlreadyExists, + ErrorModule::FS, ErrorSummary::NothingHappened, + ErrorLevel::Status); +constexpr ResultCode ERROR_FILE_ALREADY_EXISTS(ErrCodes::FileAlreadyExists, ErrorModule::FS, + ErrorSummary::NothingHappened, ErrorLevel::Status); +constexpr ResultCode ERROR_ALREADY_EXISTS(ErrCodes::AlreadyExists, ErrorModule::FS, + ErrorSummary::NothingHappened, ErrorLevel::Status); +constexpr ResultCode ERROR_DIRECTORY_NOT_EMPTY(ErrCodes::DirectoryNotEmpty, ErrorModule::FS, + ErrorSummary::Canceled, ErrorLevel::Status); +constexpr ResultCode ERROR_GAMECARD_NOT_INSERTED(ErrCodes::GameCardNotInserted, ErrorModule::FS, + ErrorSummary::NotFound, ErrorLevel::Status); +constexpr ResultCode ERROR_INCORRECT_EXEFS_READ_SIZE(ErrCodes::IncorrectExeFSReadSize, + ErrorModule::FS, ErrorSummary::NotSupported, + ErrorLevel::Usage); +constexpr ResultCode ERROR_ROMFS_NOT_FOUND(ErrCodes::RomFSNotFound, ErrorModule::FS, + ErrorSummary::NotFound, ErrorLevel::Status); +constexpr ResultCode ERROR_COMMAND_NOT_ALLOWED(ErrCodes::CommandNotAllowed, ErrorModule::FS, + ErrorSummary::WrongArgument, ErrorLevel::Permanent); +constexpr ResultCode ERROR_EXEFS_SECTION_NOT_FOUND(ErrCodes::ExeFSSectionNotFound, ErrorModule::FS, + ErrorSummary::NotFound, ErrorLevel::Status); + +/// Returned when a function is passed an invalid archive handle. +constexpr ResultCode ERR_INVALID_ARCHIVE_HANDLE(ErrCodes::ArchiveNotMounted, ErrorModule::FS, + ErrorSummary::NotFound, + ErrorLevel::Status); // 0xC8804465 +constexpr ResultCode ERR_WRITE_BEYOND_END(ErrCodes::WriteBeyondEnd, ErrorModule::FS, + ErrorSummary::InvalidArgument, ErrorLevel::Usage); + +/** + * Variant of ERROR_NOT_FOUND returned in some places in the code. Unknown if these usages are + * correct or a bug. + */ +constexpr ResultCode ERR_NOT_FOUND_INVALID_STATE(ErrCodes::NotFound, ErrorModule::FS, + ErrorSummary::InvalidState, ErrorLevel::Status); +constexpr ResultCode ERR_NOT_FORMATTED(ErrCodes::NotFormatted, ErrorModule::FS, + ErrorSummary::InvalidState, ErrorLevel::Status); } // namespace FileSys diff --git a/src/core/hle/result.h b/src/core/hle/result.h index c44668732..b066b7d4e 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h @@ -26,30 +26,9 @@ enum class ErrorDescription : u32 { OS_InvalidBufferDescriptor = 48, MaxConnectionsReached = 52, WrongAddress = 53, - FS_RomFSNotFound = 100, - FS_ArchiveNotMounted = 101, - FS_FileNotFound = 112, - FS_PathNotFound = 113, - FS_GameCardNotInserted = 141, - FS_NotFound = 120, - FS_FileAlreadyExists = 180, - FS_DirectoryAlreadyExists = 185, - FS_AlreadyExists = 190, - FS_InvalidOpenFlags = 230, - FS_DirectoryNotEmpty = 240, - FS_NotAFile = 250, - FS_NotFormatted = 340, ///< This is used by the FS service when creating a SaveData archive OutofRangeOrMisalignedAddress = 513, // TODO(purpasmart): Check if this name fits its actual usage GPU_FirstInitialization = 519, - FS_ExeFSSectionNotFound = 567, - FS_CommandNotAllowed = 630, - FS_InvalidReadFlag = 700, - FS_InvalidPath = 702, - FS_WriteBeyondEnd = 705, - FS_UnsupportedOpenFlags = 760, - FS_IncorrectExeFSReadSize = 761, - FS_UnexpectedFileOrDirectory = 770, // Codes 1000 and above are considered "well-known" and have common values between all modules. InvalidSection = 1000, diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp index 14185ae20..caa41ded7 100644 --- a/src/core/hle/service/cfg/cfg.cpp +++ b/src/core/hle/service/cfg/cfg.cpp @@ -11,6 +11,7 @@ #include "common/string_util.h" #include "common/swap.h" #include "core/file_sys/archive_systemsavedata.h" +#include "core/file_sys/errors.h" #include "core/file_sys/file_backend.h" #include "core/hle/result.h" #include "core/hle/service/cfg/cfg.h" @@ -411,8 +412,7 @@ ResultCode UpdateConfigNANDSavegame() { ResultCode FormatConfig() { ResultCode res = DeleteConfigNANDSaveFile(); // The delete command fails if the file doesn't exist, so we have to check that too - if (!res.IsSuccess() && - res.description != static_cast(ErrorDescription::FS_FileNotFound)) { + if (!res.IsSuccess() && res != FileSys::ERROR_FILE_NOT_FOUND) { return res; } // Delete the old data @@ -535,7 +535,7 @@ ResultCode LoadConfigNANDSaveFile() { Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SystemSaveData, archive_path); // If the archive didn't exist, create the files inside - if (archive_result.Code().description == static_cast(ErrorDescription::FS_NotFormatted)) { + if (archive_result.Code() == FileSys::ERR_NOT_FORMATTED) { // Format the archive to create the directories Service::FS::FormatArchive(Service::FS::ArchiveIdCode::SystemSaveData, FileSys::ArchiveFormatInfo(), archive_path); diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index 6cddc1fdb..5c1235f8b 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp @@ -22,6 +22,7 @@ #include "core/file_sys/archive_sdmcwriteonly.h" #include "core/file_sys/archive_systemsavedata.h" #include "core/file_sys/directory_backend.h" +#include "core/file_sys/errors.h" #include "core/file_sys/file_backend.h" #include "core/hle/kernel/client_session.h" #include "core/hle/result.h" @@ -55,11 +56,6 @@ namespace FS { const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::FS, ErrorSummary::InvalidArgument, ErrorLevel::Permanent); -/// Returned when a function is passed an invalid archive handle. -const ResultCode ERR_INVALID_ARCHIVE_HANDLE(ErrorDescription::FS_ArchiveNotMounted, ErrorModule::FS, - ErrorSummary::NotFound, - ErrorLevel::Status); // 0xC8804465 - // Command to access archive file enum class FileCommand : u32 { Dummy1 = 0x000100C6, @@ -284,7 +280,7 @@ ResultVal OpenArchive(ArchiveIdCode id_code, FileSys::Path& archi ResultCode CloseArchive(ArchiveHandle handle) { if (handle_map.erase(handle) == 0) - return ERR_INVALID_ARCHIVE_HANDLE; + return FileSys::ERR_INVALID_ARCHIVE_HANDLE; else return RESULT_SUCCESS; } @@ -309,7 +305,7 @@ ResultVal> OpenFileFromArchive(ArchiveHandle archive_handl const FileSys::Mode mode) { ArchiveBackend* archive = GetArchive(archive_handle); if (archive == nullptr) - return ERR_INVALID_ARCHIVE_HANDLE; + return FileSys::ERR_INVALID_ARCHIVE_HANDLE; auto backend = archive->OpenFile(path, mode); if (backend.Failed()) @@ -322,7 +318,7 @@ ResultVal> OpenFileFromArchive(ArchiveHandle archive_handl ResultCode DeleteFileFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { ArchiveBackend* archive = GetArchive(archive_handle); if (archive == nullptr) - return ERR_INVALID_ARCHIVE_HANDLE; + return FileSys::ERR_INVALID_ARCHIVE_HANDLE; return archive->DeleteFile(path); } @@ -334,7 +330,7 @@ ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, ArchiveBackend* src_archive = GetArchive(src_archive_handle); ArchiveBackend* dest_archive = GetArchive(dest_archive_handle); if (src_archive == nullptr || dest_archive == nullptr) - return ERR_INVALID_ARCHIVE_HANDLE; + return FileSys::ERR_INVALID_ARCHIVE_HANDLE; if (src_archive == dest_archive) { return src_archive->RenameFile(src_path, dest_path); @@ -347,7 +343,7 @@ ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle, ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { ArchiveBackend* archive = GetArchive(archive_handle); if (archive == nullptr) - return ERR_INVALID_ARCHIVE_HANDLE; + return FileSys::ERR_INVALID_ARCHIVE_HANDLE; return archive->DeleteDirectory(path); } @@ -356,7 +352,7 @@ ResultCode DeleteDirectoryRecursivelyFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { ArchiveBackend* archive = GetArchive(archive_handle); if (archive == nullptr) - return ERR_INVALID_ARCHIVE_HANDLE; + return FileSys::ERR_INVALID_ARCHIVE_HANDLE; return archive->DeleteDirectoryRecursively(path); } @@ -365,7 +361,7 @@ ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path u64 file_size) { ArchiveBackend* archive = GetArchive(archive_handle); if (archive == nullptr) - return ERR_INVALID_ARCHIVE_HANDLE; + return FileSys::ERR_INVALID_ARCHIVE_HANDLE; return archive->CreateFile(path, file_size); } @@ -373,7 +369,7 @@ ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) { ArchiveBackend* archive = GetArchive(archive_handle); if (archive == nullptr) - return ERR_INVALID_ARCHIVE_HANDLE; + return FileSys::ERR_INVALID_ARCHIVE_HANDLE; return archive->CreateDirectory(path); } @@ -385,7 +381,7 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle, ArchiveBackend* src_archive = GetArchive(src_archive_handle); ArchiveBackend* dest_archive = GetArchive(dest_archive_handle); if (src_archive == nullptr || dest_archive == nullptr) - return ERR_INVALID_ARCHIVE_HANDLE; + return FileSys::ERR_INVALID_ARCHIVE_HANDLE; if (src_archive == dest_archive) { return src_archive->RenameDirectory(src_path, dest_path); @@ -399,7 +395,7 @@ ResultVal> OpenDirectoryFromArchive(ArchiveHandle arc const FileSys::Path& path) { ArchiveBackend* archive = GetArchive(archive_handle); if (archive == nullptr) - return ERR_INVALID_ARCHIVE_HANDLE; + return FileSys::ERR_INVALID_ARCHIVE_HANDLE; auto backend = archive->OpenDirectory(path); if (backend.Failed()) @@ -412,7 +408,7 @@ ResultVal> OpenDirectoryFromArchive(ArchiveHandle arc ResultVal GetFreeBytesInArchive(ArchiveHandle archive_handle) { ArchiveBackend* archive = GetArchive(archive_handle); if (archive == nullptr) - return ERR_INVALID_ARCHIVE_HANDLE; + return FileSys::ERR_INVALID_ARCHIVE_HANDLE; return MakeResult(archive->GetFreeBytes()); } diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp index 33b290699..ad1aadab5 100644 --- a/src/core/hle/service/fs/fs_user.cpp +++ b/src/core/hle/service/fs/fs_user.cpp @@ -8,6 +8,7 @@ #include "common/logging/log.h" #include "common/scope_exit.h" #include "common/string_util.h" +#include "core/file_sys/errors.h" #include "core/hle/kernel/client_session.h" #include "core/hle/result.h" #include "core/hle/service/fs/archive.h" @@ -539,9 +540,7 @@ static void FormatSaveData(Service::Interface* self) { if (archive_id != FS::ArchiveIdCode::SaveData) { LOG_ERROR(Service_FS, "tried to format an archive different than SaveData, %u", static_cast(archive_id)); - cmd_buff[1] = ResultCode(ErrorDescription::FS_InvalidPath, ErrorModule::FS, - ErrorSummary::InvalidArgument, ErrorLevel::Usage) - .raw; + cmd_buff[1] = FileSys::ERROR_INVALID_PATH.raw; return; } diff --git a/src/core/hle/service/ptm/ptm.cpp b/src/core/hle/service/ptm/ptm.cpp index b6d6d105a..39382ef09 100644 --- a/src/core/hle/service/ptm/ptm.cpp +++ b/src/core/hle/service/ptm/ptm.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include "common/logging/log.h" +#include "core/file_sys/errors.h" #include "core/file_sys/file_backend.h" #include "core/hle/service/fs/archive.h" #include "core/hle/service/ptm/ptm.h" @@ -134,7 +135,7 @@ void Init() { auto archive_result = Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path); // If the archive didn't exist, create the files inside - if (archive_result.Code().description == static_cast(ErrorDescription::FS_NotFormatted)) { + if (archive_result.Code() == FileSys::ERR_NOT_FORMATTED) { // Format the archive to create the directories Service::FS::FormatArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, FileSys::ArchiveFormatInfo(), archive_path); From 743d18f0e463aa25af53ceaa25231800453810ea Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Sat, 20 May 2017 21:54:27 -0700 Subject: [PATCH 4/7] GSP_GPU: Move error codes from result.h to local file --- src/core/hle/result.h | 3 --- src/core/hle/service/gsp_gpu.cpp | 37 ++++++++++++++++++++------------ 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/core/hle/result.h b/src/core/hle/result.h index b066b7d4e..e76be606e 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h @@ -26,9 +26,6 @@ enum class ErrorDescription : u32 { OS_InvalidBufferDescriptor = 48, MaxConnectionsReached = 52, WrongAddress = 53, - OutofRangeOrMisalignedAddress = - 513, // TODO(purpasmart): Check if this name fits its actual usage - GPU_FirstInitialization = 519, // Codes 1000 and above are considered "well-known" and have common values between all modules. InvalidSection = 1000, diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp index a960778a7..46c4ed01a 100644 --- a/src/core/hle/service/gsp_gpu.cpp +++ b/src/core/hle/service/gsp_gpu.cpp @@ -25,13 +25,24 @@ namespace GSP { // Beginning address of HW regs const u32 REGS_BEGIN = 0x1EB00000; -const ResultCode ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED( - ErrorDescription::OutofRangeOrMisalignedAddress, ErrorModule::GX, ErrorSummary::InvalidArgument, - ErrorLevel::Usage); // 0xE0E02A01 -const ResultCode ERR_GSP_REGS_MISALIGNED(ErrorDescription::MisalignedSize, ErrorModule::GX, +namespace ErrCodes { +enum { + // TODO(purpasmart): Check if this name fits its actual usage + OutofRangeOrMisalignedAddress = 513, + FirstInitialization = 519, +}; +} + +constexpr ResultCode RESULT_FIRST_INITIALIZATION(ErrCodes::FirstInitialization, ErrorModule::GX, + ErrorSummary::Success, ErrorLevel::Success); +constexpr ResultCode ERR_REGS_OUTOFRANGE_OR_MISALIGNED(ErrCodes::OutofRangeOrMisalignedAddress, + ErrorModule::GX, + ErrorSummary::InvalidArgument, + ErrorLevel::Usage); // 0xE0E02A01 +constexpr ResultCode ERR_REGS_MISALIGNED(ErrorDescription::MisalignedSize, ErrorModule::GX, ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E02BF2 -const ResultCode ERR_GSP_REGS_INVALID_SIZE(ErrorDescription::InvalidSize, ErrorModule::GX, +constexpr ResultCode ERR_REGS_INVALID_SIZE(ErrorDescription::InvalidSize, ErrorModule::GX, ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E02BEC @@ -93,11 +104,11 @@ static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, VAddr data_va LOG_ERROR(Service_GSP, "Write address was out of range or misaligned! (address=0x%08x, size=0x%08x)", base_address, size_in_bytes); - return ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED; + return ERR_REGS_OUTOFRANGE_OR_MISALIGNED; } else if (size_in_bytes <= max_size_in_bytes) { if (size_in_bytes & 3) { LOG_ERROR(Service_GSP, "Misaligned size 0x%08x", size_in_bytes); - return ERR_GSP_REGS_MISALIGNED; + return ERR_REGS_MISALIGNED; } else { while (size_in_bytes > 0) { WriteSingleHWReg(base_address, Memory::Read32(data_vaddr)); @@ -111,7 +122,7 @@ static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, VAddr data_va } else { LOG_ERROR(Service_GSP, "Out of range size 0x%08x", size_in_bytes); - return ERR_GSP_REGS_INVALID_SIZE; + return ERR_REGS_INVALID_SIZE; } } @@ -134,11 +145,11 @@ static ResultCode WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, VAddr LOG_ERROR(Service_GSP, "Write address was out of range or misaligned! (address=0x%08x, size=0x%08x)", base_address, size_in_bytes); - return ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED; + return ERR_REGS_OUTOFRANGE_OR_MISALIGNED; } else if (size_in_bytes <= max_size_in_bytes) { if (size_in_bytes & 3) { LOG_ERROR(Service_GSP, "Misaligned size 0x%08x", size_in_bytes); - return ERR_GSP_REGS_MISALIGNED; + return ERR_REGS_MISALIGNED; } else { while (size_in_bytes > 0) { const u32 reg_address = base_address + REGS_BEGIN; @@ -164,7 +175,7 @@ static ResultCode WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, VAddr } else { LOG_ERROR(Service_GSP, "Out of range size 0x%08x", size_in_bytes); - return ERR_GSP_REGS_INVALID_SIZE; + return ERR_REGS_INVALID_SIZE; } } @@ -372,9 +383,7 @@ static void RegisterInterruptRelayQueue(Interface* self) { if (first_initialization) { // This specific code is required for a successful initialization, rather than 0 first_initialization = false; - cmd_buff[1] = ResultCode(ErrorDescription::GPU_FirstInitialization, ErrorModule::GX, - ErrorSummary::Success, ErrorLevel::Success) - .raw; + cmd_buff[1] = RESULT_FIRST_INITIALIZATION.raw; } else { cmd_buff[1] = RESULT_SUCCESS.raw; } From 2cdb40d709f2a5d4f7f3159d4c6d80fe7905b4f3 Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Sun, 21 May 2017 00:11:36 -0700 Subject: [PATCH 5/7] Kernel: Centralize error definitions in errors.h --- src/core/CMakeLists.txt | 1 + src/core/hle/function_wrappers.h | 2 +- src/core/hle/ipc.h | 7 ++ src/core/hle/kernel/address_arbiter.cpp | 7 +- src/core/hle/kernel/client_port.cpp | 4 +- src/core/hle/kernel/client_session.cpp | 3 +- src/core/hle/kernel/errors.h | 98 +++++++++++++++++++++++++ src/core/hle/kernel/kernel.cpp | 1 + src/core/hle/kernel/kernel.h | 7 -- src/core/hle/kernel/process.cpp | 1 + src/core/hle/kernel/semaphore.cpp | 7 +- src/core/hle/kernel/shared_memory.cpp | 16 ++-- src/core/hle/kernel/thread.cpp | 24 ++++-- src/core/hle/kernel/thread.h | 2 +- src/core/hle/kernel/vm_manager.cpp | 1 + src/core/hle/kernel/vm_manager.h | 8 -- src/core/hle/result.h | 6 -- src/core/hle/service/boss/boss.cpp | 4 +- src/core/hle/service/dsp_dsp.cpp | 4 +- src/core/hle/service/fs/fs_user.cpp | 4 +- src/core/hle/service/ir/ir_user.cpp | 3 +- src/core/hle/service/srv.cpp | 4 +- src/core/hle/svc.cpp | 96 ++++++++---------------- 23 files changed, 178 insertions(+), 132 deletions(-) create mode 100644 src/core/hle/kernel/errors.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index c733e5d21..e0b9b98e8 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -230,6 +230,7 @@ set(HEADERS hle/kernel/address_arbiter.h hle/kernel/client_port.h hle/kernel/client_session.h + hle/kernel/errors.h hle/kernel/event.h hle/kernel/kernel.h hle/kernel/memory.h diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index f6eb900f0..18b6e7017 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h @@ -53,7 +53,7 @@ void Wrap() { FuncReturn(retval); } -template +template void Wrap() { u32 param_1 = 0; u32 retval = func(¶m_1, PARAM(0), PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw; diff --git a/src/core/hle/ipc.h b/src/core/hle/ipc.h index 3a5d481a5..303ca090d 100644 --- a/src/core/hle/ipc.h +++ b/src/core/hle/ipc.h @@ -5,6 +5,7 @@ #pragma once #include "common/common_types.h" +#include "core/hle/kernel/errors.h" #include "core/hle/kernel/thread.h" #include "core/memory.h" @@ -43,6 +44,12 @@ inline u32* GetStaticBuffers(const int offset = 0) { namespace IPC { +// These errors are commonly returned by invalid IPC translations, so alias them here for +// convenience. +// TODO(yuriks): These will probably go away once translation is implemented inside the kernel. +using Kernel::ERR_INVALID_BUFFER_DESCRIPTOR; +constexpr auto ERR_INVALID_HANDLE = Kernel::ERR_INVALID_HANDLE_OS; + enum DescriptorType : u32 { // Buffer related desciptors types (mask : 0x0F) StaticBuffer = 0x02, diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index 01fab123e..776d342f0 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp @@ -5,6 +5,7 @@ #include "common/common_types.h" #include "common/logging/log.h" #include "core/hle/kernel/address_arbiter.h" +#include "core/hle/kernel/errors.h" #include "core/hle/kernel/thread.h" #include "core/memory.h" @@ -74,8 +75,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, default: LOG_ERROR(Kernel, "unknown type=%d", type); - return ResultCode(ErrorDescription::InvalidEnumValue, ErrorModule::Kernel, - ErrorSummary::WrongArgument, ErrorLevel::Usage); + return ERR_INVALID_ENUM_VALUE_FND; } // The calls that use a timeout seem to always return a Timeout error even if they did not put @@ -83,8 +83,7 @@ ResultCode AddressArbiter::ArbitrateAddress(ArbitrationType type, VAddr address, if (type == ArbitrationType::WaitIfLessThanWithTimeout || type == ArbitrationType::DecrementAndWaitIfLessThanWithTimeout) { - return ResultCode(ErrorDescription::Timeout, ErrorModule::OS, ErrorSummary::StatusChanged, - ErrorLevel::Info); + return RESULT_TIMEOUT; } return RESULT_SUCCESS; } diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp index ddcf4c916..03ffdece1 100644 --- a/src/core/hle/kernel/client_port.cpp +++ b/src/core/hle/kernel/client_port.cpp @@ -5,6 +5,7 @@ #include "common/assert.h" #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/client_session.h" +#include "core/hle/kernel/errors.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/server_port.h" #include "core/hle/kernel/server_session.h" @@ -19,8 +20,7 @@ ResultVal> ClientPort::Connect() { // AcceptSession before returning from this call. if (active_sessions >= max_sessions) { - return ResultCode(ErrorDescription::MaxConnectionsReached, ErrorModule::OS, - ErrorSummary::WouldBlock, ErrorLevel::Temporary); + return ERR_MAX_CONNECTIONS_REACHED; } active_sessions++; diff --git a/src/core/hle/kernel/client_session.cpp b/src/core/hle/kernel/client_session.cpp index e297b7464..783b1c061 100644 --- a/src/core/hle/kernel/client_session.cpp +++ b/src/core/hle/kernel/client_session.cpp @@ -30,8 +30,7 @@ ResultCode ClientSession::SendSyncRequest() { if (parent->server) return parent->server->HandleSyncRequest(); - return ResultCode(ErrorDescription::SessionClosedByRemote, ErrorModule::OS, - ErrorSummary::Canceled, ErrorLevel::Status); + return ERR_SESSION_CLOSED_BY_REMOTE; } } // namespace diff --git a/src/core/hle/kernel/errors.h b/src/core/hle/kernel/errors.h new file mode 100644 index 000000000..b3b60e7df --- /dev/null +++ b/src/core/hle/kernel/errors.h @@ -0,0 +1,98 @@ +// Copyright 2017 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/result.h" + +namespace Kernel { + +namespace ErrCodes { +enum { + OutOfHandles = 19, + SessionClosedByRemote = 26, + PortNameTooLong = 30, + WrongPermission = 46, + InvalidBufferDescriptor = 48, + MaxConnectionsReached = 52, +}; +} + +// WARNING: The kernel is quite inconsistent in it's usage of errors code. Make sure to always +// double check that the code matches before re-using the constant. + +constexpr ResultCode ERR_OUT_OF_HANDLES(ErrCodes::OutOfHandles, ErrorModule::Kernel, + ErrorSummary::OutOfResource, + ErrorLevel::Permanent); // 0xD8600413 +constexpr ResultCode ERR_SESSION_CLOSED_BY_REMOTE(ErrCodes::SessionClosedByRemote, ErrorModule::OS, + ErrorSummary::Canceled, + ErrorLevel::Status); // 0xC920181A +constexpr ResultCode ERR_PORT_NAME_TOO_LONG(ErrCodes::PortNameTooLong, ErrorModule::OS, + ErrorSummary::InvalidArgument, + ErrorLevel::Usage); // 0xE0E0181E +constexpr ResultCode ERR_WRONG_PERMISSION(ErrCodes::WrongPermission, ErrorModule::OS, + ErrorSummary::WrongArgument, ErrorLevel::Permanent); +constexpr ResultCode ERR_INVALID_BUFFER_DESCRIPTOR(ErrCodes::InvalidBufferDescriptor, + ErrorModule::OS, ErrorSummary::WrongArgument, + ErrorLevel::Permanent); +constexpr ResultCode ERR_MAX_CONNECTIONS_REACHED(ErrCodes::MaxConnectionsReached, ErrorModule::OS, + ErrorSummary::WouldBlock, + ErrorLevel::Temporary); // 0xD0401834 + +constexpr ResultCode ERR_NOT_AUTHORIZED(ErrorDescription::NotAuthorized, ErrorModule::OS, + ErrorSummary::WrongArgument, + ErrorLevel::Permanent); // 0xD9001BEA +constexpr ResultCode ERR_INVALID_ENUM_VALUE(ErrorDescription::InvalidEnumValue, ErrorModule::Kernel, + ErrorSummary::InvalidArgument, + ErrorLevel::Permanent); // 0xD8E007ED +constexpr ResultCode ERR_INVALID_ENUM_VALUE_FND(ErrorDescription::InvalidEnumValue, + ErrorModule::FND, ErrorSummary::InvalidArgument, + ErrorLevel::Permanent); // 0xD8E093ED +constexpr ResultCode ERR_INVALID_COMBINATION(ErrorDescription::InvalidCombination, ErrorModule::OS, + ErrorSummary::InvalidArgument, + ErrorLevel::Usage); // 0xE0E01BEE +constexpr ResultCode ERR_INVALID_COMBINATION_KERNEL(ErrorDescription::InvalidCombination, + ErrorModule::Kernel, + ErrorSummary::WrongArgument, + ErrorLevel::Permanent); // 0xD90007EE +constexpr ResultCode ERR_MISALIGNED_ADDRESS(ErrorDescription::MisalignedAddress, ErrorModule::OS, + ErrorSummary::InvalidArgument, + ErrorLevel::Usage); // 0xE0E01BF1 +constexpr ResultCode ERR_MISALIGNED_SIZE(ErrorDescription::MisalignedSize, ErrorModule::OS, + ErrorSummary::InvalidArgument, + ErrorLevel::Usage); // 0xE0E01BF2 +constexpr ResultCode ERR_OUT_OF_MEMORY(ErrorDescription::OutOfMemory, ErrorModule::Kernel, + ErrorSummary::OutOfResource, + ErrorLevel::Permanent); // 0xD86007F3 +constexpr ResultCode ERR_NOT_IMPLEMENTED(ErrorDescription::NotImplemented, ErrorModule::OS, + ErrorSummary::InvalidArgument, + ErrorLevel::Usage); // 0xE0E01BF4 +constexpr ResultCode ERR_INVALID_ADDRESS(ErrorDescription::InvalidAddress, ErrorModule::OS, + ErrorSummary::InvalidArgument, + ErrorLevel::Usage); // 0xE0E01BF5 +constexpr ResultCode ERR_INVALID_ADDRESS_STATE(ErrorDescription::InvalidAddress, ErrorModule::OS, + ErrorSummary::InvalidState, + ErrorLevel::Usage); // 0xE0A01BF5 +constexpr ResultCode ERR_INVALID_POINTER(ErrorDescription::InvalidPointer, ErrorModule::Kernel, + ErrorSummary::InvalidArgument, + ErrorLevel::Permanent); // 0xD8E007F6 +constexpr ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::Kernel, + ErrorSummary::InvalidArgument, + ErrorLevel::Permanent); // 0xD8E007F7 +/// Alternate code returned instead of ERR_INVALID_HANDLE in some code paths. +constexpr ResultCode ERR_INVALID_HANDLE_OS(ErrorDescription::InvalidHandle, ErrorModule::OS, + ErrorSummary::WrongArgument, + ErrorLevel::Permanent); // 0xD9001BF7 +constexpr ResultCode ERR_NOT_FOUND(ErrorDescription::NotFound, ErrorModule::Kernel, + ErrorSummary::NotFound, ErrorLevel::Permanent); // 0xD88007FA +constexpr ResultCode ERR_OUT_OF_RANGE(ErrorDescription::OutOfRange, ErrorModule::OS, + ErrorSummary::InvalidArgument, + ErrorLevel::Usage); // 0xE0E01BFD +constexpr ResultCode ERR_OUT_OF_RANGE_KERNEL(ErrorDescription::OutOfRange, ErrorModule::Kernel, + ErrorSummary::InvalidArgument, + ErrorLevel::Permanent); // 0xD8E007FD +constexpr ResultCode RESULT_TIMEOUT(ErrorDescription::Timeout, ErrorModule::OS, + ErrorSummary::StatusChanged, ErrorLevel::Info); + +} // namespace Kernel diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index f599916f0..7f84e01aa 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -6,6 +6,7 @@ #include "common/assert.h" #include "common/logging/log.h" #include "core/hle/config_mem.h" +#include "core/hle/kernel/errors.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/memory.h" #include "core/hle/kernel/process.h" diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index bb8b99bb5..94f2025a0 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -19,13 +19,6 @@ using Handle = u32; class Thread; -// TODO: Verify code -const ResultCode ERR_OUT_OF_HANDLES(ErrorDescription::OutOfMemory, ErrorModule::Kernel, - ErrorSummary::OutOfResource, ErrorLevel::Temporary); -// TOOD: Verify code -const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::Kernel, - ErrorSummary::InvalidArgument, ErrorLevel::Permanent); - enum KernelHandle : Handle { CurrentThread = 0xFFFF8000, CurrentProcess = 0xFFFF8001, diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 32cb25fb7..1c31ec950 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -6,6 +6,7 @@ #include "common/assert.h" #include "common/common_funcs.h" #include "common/logging/log.h" +#include "core/hle/kernel/errors.h" #include "core/hle/kernel/memory.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/resource_limit.h" diff --git a/src/core/hle/kernel/semaphore.cpp b/src/core/hle/kernel/semaphore.cpp index 8bda2f75d..fcf586728 100644 --- a/src/core/hle/kernel/semaphore.cpp +++ b/src/core/hle/kernel/semaphore.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include "common/assert.h" +#include "core/hle/kernel/errors.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/semaphore.h" #include "core/hle/kernel/thread.h" @@ -16,8 +17,7 @@ ResultVal> Semaphore::Create(s32 initial_count, s32 max_cou std::string name) { if (initial_count > max_count) - return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::Kernel, - ErrorSummary::WrongArgument, ErrorLevel::Permanent); + return ERR_INVALID_COMBINATION_KERNEL; SharedPtr semaphore(new Semaphore); @@ -42,8 +42,7 @@ void Semaphore::Acquire(Thread* thread) { ResultVal Semaphore::Release(s32 release_count) { if (max_count - available_count < release_count) - return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel, - ErrorSummary::InvalidArgument, ErrorLevel::Permanent); + return ERR_OUT_OF_RANGE_KERNEL; s32 previous_count = available_count; available_count += release_count; diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp index bc1560d12..922e5ab58 100644 --- a/src/core/hle/kernel/shared_memory.cpp +++ b/src/core/hle/kernel/shared_memory.cpp @@ -4,6 +4,7 @@ #include #include "common/logging/log.h" +#include "core/hle/kernel/errors.h" #include "core/hle/kernel/memory.h" #include "core/hle/kernel/shared_memory.h" #include "core/memory.h" @@ -102,24 +103,21 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi // Automatically allocated memory blocks can only be mapped with other_permissions = DontCare if (base_address == 0 && other_permissions != MemoryPermission::DontCare) { - return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, - ErrorSummary::InvalidArgument, ErrorLevel::Usage); + return ERR_INVALID_COMBINATION; } // Error out if the requested permissions don't match what the creator process allows. if (static_cast(permissions) & ~static_cast(own_other_permissions)) { LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match", GetObjectId(), address, name.c_str()); - return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, - ErrorSummary::InvalidArgument, ErrorLevel::Usage); + return ERR_INVALID_COMBINATION; } // Heap-backed memory blocks can not be mapped with other_permissions = DontCare if (base_address != 0 && other_permissions == MemoryPermission::DontCare) { LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match", GetObjectId(), address, name.c_str()); - return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, - ErrorSummary::InvalidArgument, ErrorLevel::Usage); + return ERR_INVALID_COMBINATION; } // Error out if the provided permissions are not compatible with what the creator process needs. @@ -127,8 +125,7 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi static_cast(this->permissions) & ~static_cast(other_permissions)) { LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match", GetObjectId(), address, name.c_str()); - return ResultCode(ErrorDescription::WrongPermission, ErrorModule::OS, - ErrorSummary::WrongArgument, ErrorLevel::Permanent); + return ERR_WRONG_PERMISSION; } // TODO(Subv): Check for the Shared Device Mem flag in the creator process. @@ -144,8 +141,7 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi if (address < Memory::HEAP_VADDR || address + size >= Memory::SHARED_MEMORY_VADDR_END) { LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, invalid address", GetObjectId(), address, name.c_str()); - return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS, - ErrorSummary::InvalidArgument, ErrorLevel::Usage); + return ERR_INVALID_ADDRESS; } } diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 3b7555d87..519ff51a8 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -14,6 +14,7 @@ #include "core/arm/skyeye_common/armstate.h" #include "core/core.h" #include "core/core_timing.h" +#include "core/hle/kernel/errors.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/memory.h" #include "core/hle/kernel/mutex.h" @@ -241,9 +242,7 @@ static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) { for (auto& object : thread->wait_objects) object->RemoveWaitingThread(thread.get()); thread->wait_objects.clear(); - thread->SetWaitSynchronizationResult(ResultCode(ErrorDescription::Timeout, ErrorModule::OS, - ErrorSummary::StatusChanged, - ErrorLevel::Info)); + thread->SetWaitSynchronizationResult(RESULT_TIMEOUT); } thread->ResumeFromWait(); @@ -351,10 +350,20 @@ static void ResetThreadContext(ARM_Interface::ThreadContext& context, u32 stack_ context.cpsr = USER32MODE | ((entry_point & 1) << 5); // Usermode and THUMB mode } -ResultVal> Thread::Create(std::string name, VAddr entry_point, s32 priority, +ResultVal> Thread::Create(std::string name, VAddr entry_point, u32 priority, u32 arg, s32 processor_id, VAddr stack_top) { - ASSERT_MSG(priority >= THREADPRIO_HIGHEST && priority <= THREADPRIO_LOWEST, - "Invalid thread priority"); + // Check if priority is in ranged. Lowest priority -> highest priority id. + if (priority > THREADPRIO_LOWEST) { + LOG_ERROR(Kernel_SVC, "Invalid thread priority: %d", priority); + return ERR_OUT_OF_RANGE; + } + + if (processor_id > THREADPROCESSORID_MAX) { + LOG_ERROR(Kernel_SVC, "Invalid processor id: %d", processor_id); + return ERR_OUT_OF_RANGE_KERNEL; + } + + // TODO(yuriks): Other checks, returning 0xD9001BEA if (!Memory::IsValidVirtualAddress(entry_point)) { LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name.c_str(), entry_point); @@ -399,8 +408,7 @@ ResultVal> Thread::Create(std::string name, VAddr entry_point, if (linheap_memory->size() + Memory::PAGE_SIZE > memory_region->size) { LOG_ERROR(Kernel_SVC, "Not enough space in region to allocate a new TLS page for thread"); - return ResultCode(ErrorDescription::OutOfMemory, ErrorModule::Kernel, - ErrorSummary::OutOfResource, ErrorLevel::Permanent); + return ERR_OUT_OF_MEMORY; } u32 offset = linheap_memory->size(); diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 6ab31c70b..7b5169cfc 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -57,7 +57,7 @@ public: * @param stack_top The address of the thread's stack top * @return A shared pointer to the newly created thread */ - static ResultVal> Create(std::string name, VAddr entry_point, s32 priority, + static ResultVal> Create(std::string name, VAddr entry_point, u32 priority, u32 arg, s32 processor_id, VAddr stack_top); std::string GetName() const override { diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index 6dd24f846..cef1f7fa8 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp @@ -4,6 +4,7 @@ #include #include "common/assert.h" +#include "core/hle/kernel/errors.h" #include "core/hle/kernel/vm_manager.h" #include "core/memory.h" #include "core/memory_setup.h" diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h index 9055664b2..38e0d74d0 100644 --- a/src/core/hle/kernel/vm_manager.h +++ b/src/core/hle/kernel/vm_manager.h @@ -13,14 +13,6 @@ namespace Kernel { -const ResultCode ERR_INVALID_ADDRESS{// 0xE0E01BF5 - ErrorDescription::InvalidAddress, ErrorModule::OS, - ErrorSummary::InvalidArgument, ErrorLevel::Usage}; - -const ResultCode ERR_INVALID_ADDRESS_STATE{// 0xE0A01BF5 - ErrorDescription::InvalidAddress, ErrorModule::OS, - ErrorSummary::InvalidState, ErrorLevel::Usage}; - enum class VMAType : u8 { /// VMA represents an unmapped region of the address space. Free, diff --git a/src/core/hle/result.h b/src/core/hle/result.h index e76be606e..c49650f7d 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h @@ -21,12 +21,6 @@ enum class ErrorDescription : u32 { Success = 0, - SessionClosedByRemote = 26, - WrongPermission = 46, - OS_InvalidBufferDescriptor = 48, - MaxConnectionsReached = 52, - WrongAddress = 53, - // Codes 1000 and above are considered "well-known" and have common values between all modules. InvalidSection = 1000, TooLarge = 1001, diff --git a/src/core/hle/service/boss/boss.cpp b/src/core/hle/service/boss/boss.cpp index e0de037f8..91056189a 100644 --- a/src/core/hle/service/boss/boss.cpp +++ b/src/core/hle/service/boss/boss.cpp @@ -24,9 +24,7 @@ void InitializeSession(Service::Interface* self) { if (translation != IPC::CallingPidDesc()) { cmd_buff[0] = IPC::MakeHeader(0, 0x1, 0); // 0x40 - cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, - ErrorSummary::WrongArgument, ErrorLevel::Permanent) - .raw; + cmd_buff[1] = IPC::ERR_INVALID_BUFFER_DESCRIPTOR.raw; LOG_ERROR(Service_BOSS, "The translation was invalid, translation=0x%08X", translation); return; } diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp index 39711ea97..79171a0bc 100644 --- a/src/core/hle/service/dsp_dsp.cpp +++ b/src/core/hle/service/dsp_dsp.cpp @@ -289,9 +289,7 @@ static void WriteProcessPipe(Service::Interface* self) { "size=0x%X, buffer=0x%08X", cmd_buff[3], pipe_index, size, buffer); cmd_buff[0] = IPC::MakeHeader(0, 1, 0); - cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, - ErrorSummary::WrongArgument, ErrorLevel::Permanent) - .raw; + cmd_buff[1] = IPC::ERR_INVALID_BUFFER_DESCRIPTOR.raw; return; } diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp index ad1aadab5..e53a970d3 100644 --- a/src/core/hle/service/fs/fs_user.cpp +++ b/src/core/hle/service/fs/fs_user.cpp @@ -801,9 +801,7 @@ static void InitializeWithSdkVersion(Service::Interface* self) { cmd_buff[1] = RESULT_SUCCESS.raw; } else { LOG_ERROR(Service_FS, "ProcessId Header must be 0x20"); - cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, - ErrorSummary::WrongArgument, ErrorLevel::Permanent) - .raw; + cmd_buff[1] = IPC::ERR_INVALID_BUFFER_DESCRIPTOR.raw; } } diff --git a/src/core/hle/service/ir/ir_user.cpp b/src/core/hle/service/ir/ir_user.cpp index 226af0083..369115f09 100644 --- a/src/core/hle/service/ir/ir_user.cpp +++ b/src/core/hle/service/ir/ir_user.cpp @@ -267,8 +267,7 @@ static void InitializeIrNopShared(Interface* self) { shared_memory = Kernel::g_handle_table.Get(handle); if (!shared_memory) { LOG_CRITICAL(Service_IR, "invalid shared memory handle 0x%08X", handle); - rb.Push(ResultCode(ErrorDescription::InvalidHandle, ErrorModule::OS, - ErrorSummary::WrongArgument, ErrorLevel::Permanent)); + rb.Push(IPC::ERR_INVALID_HANDLE); return; } shared_memory->name = "IR_USER: shared memory"; diff --git a/src/core/hle/service/srv.cpp b/src/core/hle/service/srv.cpp index 3bd787147..130c9d25e 100644 --- a/src/core/hle/service/srv.cpp +++ b/src/core/hle/service/srv.cpp @@ -30,9 +30,7 @@ static void RegisterClient(Interface* self) { if (cmd_buff[1] != IPC::CallingPidDesc()) { cmd_buff[0] = IPC::MakeHeader(0x0, 0x1, 0); // 0x40 - cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, - ErrorSummary::WrongArgument, ErrorLevel::Permanent) - .raw; + cmd_buff[1] = IPC::ERR_INVALID_BUFFER_DESCRIPTOR.raw; return; } cmd_buff[0] = IPC::MakeHeader(0x1, 0x1, 0); // 0x10040 diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 8538cfc9d..30230d65a 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -14,6 +14,7 @@ #include "core/hle/kernel/address_arbiter.h" #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/client_session.h" +#include "core/hle/kernel/errors.h" #include "core/hle/kernel/event.h" #include "core/hle/kernel/memory.h" #include "core/hle/kernel/mutex.h" @@ -37,25 +38,6 @@ using Kernel::ERR_INVALID_HANDLE; namespace SVC { -const ResultCode ERR_NOT_FOUND(ErrorDescription::NotFound, ErrorModule::Kernel, - ErrorSummary::NotFound, ErrorLevel::Permanent); // 0xD88007FA -const ResultCode ERR_PORT_NAME_TOO_LONG(ErrorDescription(30), ErrorModule::OS, - ErrorSummary::InvalidArgument, - ErrorLevel::Usage); // 0xE0E0181E - -const ResultCode ERR_SYNC_TIMEOUT(ErrorDescription::Timeout, ErrorModule::OS, - ErrorSummary::StatusChanged, ErrorLevel::Info); - -const ResultCode ERR_MISALIGNED_ADDRESS{// 0xE0E01BF1 - ErrorDescription::MisalignedAddress, ErrorModule::OS, - ErrorSummary::InvalidArgument, ErrorLevel::Usage}; -const ResultCode ERR_MISALIGNED_SIZE{// 0xE0E01BF2 - ErrorDescription::MisalignedSize, ErrorModule::OS, - ErrorSummary::InvalidArgument, ErrorLevel::Usage}; -const ResultCode ERR_INVALID_COMBINATION{// 0xE0E01BEE - ErrorDescription::InvalidCombination, ErrorModule::OS, - ErrorSummary::InvalidArgument, ErrorLevel::Usage}; - enum ControlMemoryOperation { MEMOP_FREE = 1, MEMOP_RESERVE = 2, // This operation seems to be unsupported in the kernel @@ -195,8 +177,7 @@ static ResultCode MapMemoryBlock(Kernel::Handle handle, u32 addr, u32 permission LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions); } - return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, - ErrorSummary::InvalidArgument, ErrorLevel::Usage); + return Kernel::ERR_INVALID_COMBINATION; } static ResultCode UnmapMemoryBlock(Kernel::Handle handle, u32 addr) { @@ -216,16 +197,16 @@ static ResultCode UnmapMemoryBlock(Kernel::Handle handle, u32 addr) { /// Connect to an OS service given the port name, returns the handle to the port to out static ResultCode ConnectToPort(Kernel::Handle* out_handle, const char* port_name) { if (port_name == nullptr) - return ERR_NOT_FOUND; + return Kernel::ERR_NOT_FOUND; if (std::strlen(port_name) > 11) - return ERR_PORT_NAME_TOO_LONG; + return Kernel::ERR_PORT_NAME_TOO_LONG; LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name); auto it = Service::g_kernel_named_ports.find(port_name); if (it == Service::g_kernel_named_ports.end()) { LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: %s", port_name); - return ERR_NOT_FOUND; + return Kernel::ERR_NOT_FOUND; } auto client_port = it->second; @@ -275,7 +256,7 @@ static ResultCode WaitSynchronization1(Kernel::Handle handle, s64 nano_seconds) if (object->ShouldWait(thread)) { if (nano_seconds == 0) - return ERR_SYNC_TIMEOUT; + return Kernel::RESULT_TIMEOUT; thread->wait_objects = {object}; object->AddWaitingThread(thread); @@ -289,7 +270,7 @@ static ResultCode WaitSynchronization1(Kernel::Handle handle, s64 nano_seconds) // Note: The output of this SVC will be set to RESULT_SUCCESS if the thread // resumes due to a signal in its wait objects. // Otherwise we retain the default value of timeout. - return ERR_SYNC_TIMEOUT; + return Kernel::RESULT_TIMEOUT; } object->Acquire(thread); @@ -304,8 +285,7 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha // Check if 'handles' is invalid if (handles == nullptr) - return ResultCode(ErrorDescription::InvalidPointer, ErrorModule::Kernel, - ErrorSummary::InvalidArgument, ErrorLevel::Permanent); + return Kernel::ERR_INVALID_POINTER; // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If // this happens, the running application will crash. @@ -313,8 +293,7 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha // Check if 'handle_count' is invalid if (handle_count < 0) - return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS, - ErrorSummary::InvalidArgument, ErrorLevel::Usage); + return Kernel::ERR_OUT_OF_RANGE; using ObjectPtr = Kernel::SharedPtr; std::vector objects(handle_count); @@ -344,7 +323,7 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha // If a timeout value of 0 was provided, just return the Timeout error code instead of // suspending the thread. if (nano_seconds == 0) - return ERR_SYNC_TIMEOUT; + return Kernel::RESULT_TIMEOUT; // Put the thread to sleep thread->status = THREADSTATUS_WAIT_SYNCH_ALL; @@ -365,7 +344,7 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha *out = -1; // Note: The output of this SVC will be set to RESULT_SUCCESS if the thread resumes due to // a signal in one of its wait objects. - return ERR_SYNC_TIMEOUT; + return Kernel::RESULT_TIMEOUT; } else { // Find the first object that is acquirable in the provided list of objects auto itr = std::find_if(objects.begin(), objects.end(), [thread](const ObjectPtr& object) { @@ -385,7 +364,7 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha // If a timeout value of 0 was provided, just return the Timeout error code instead of // suspending the thread. if (nano_seconds == 0) - return ERR_SYNC_TIMEOUT; + return Kernel::RESULT_TIMEOUT; // Put the thread to sleep thread->status = THREADSTATUS_WAIT_SYNCH_ANY; @@ -411,7 +390,7 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha // Otherwise we retain the default value of timeout, and -1 in the out parameter thread->wait_set_output = true; *out = -1; - return ERR_SYNC_TIMEOUT; + return Kernel::RESULT_TIMEOUT; } } @@ -520,22 +499,20 @@ static ResultCode GetResourceLimitLimitValues(s64* values, Kernel::Handle resour } /// Creates a new thread -static ResultCode CreateThread(Kernel::Handle* out_handle, s32 priority, u32 entry_point, u32 arg, +static ResultCode CreateThread(Kernel::Handle* out_handle, u32 priority, u32 entry_point, u32 arg, u32 stack_top, s32 processor_id) { using Kernel::Thread; std::string name = Common::StringFromFormat("unknown-%08" PRIX32, entry_point); if (priority > THREADPRIO_LOWEST) { - return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS, - ErrorSummary::InvalidArgument, ErrorLevel::Usage); + return Kernel::ERR_OUT_OF_RANGE; } using Kernel::ResourceLimit; Kernel::SharedPtr& resource_limit = Kernel::g_current_process->resource_limit; if (resource_limit->GetMaxResourceValue(Kernel::ResourceTypes::PRIORITY) > priority) { - return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::OS, - ErrorSummary::WrongArgument, ErrorLevel::Permanent); + return Kernel::ERR_NOT_AUTHORIZED; } switch (processor_id) { @@ -605,8 +582,7 @@ static ResultCode GetThreadPriority(s32* priority, Kernel::Handle handle) { /// Sets the priority for the specified thread static ResultCode SetThreadPriority(Kernel::Handle handle, s32 priority) { if (priority > THREADPRIO_LOWEST) { - return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS, - ErrorSummary::InvalidArgument, ErrorLevel::Usage); + return Kernel::ERR_OUT_OF_RANGE; } SharedPtr thread = Kernel::g_handle_table.Get(handle); @@ -618,8 +594,7 @@ static ResultCode SetThreadPriority(Kernel::Handle handle, s32 priority) { // the one from the thread owner's resource limit. Kernel::SharedPtr& resource_limit = Kernel::g_current_process->resource_limit; if (resource_limit->GetMaxResourceValue(Kernel::ResourceTypes::PRIORITY) > priority) { - return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::OS, - ErrorSummary::WrongArgument, ErrorLevel::Permanent); + return Kernel::ERR_NOT_AUTHORIZED; } thread->SetPriority(priority); @@ -743,8 +718,7 @@ static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_inf auto vma = process->vm_manager.FindVMA(addr); if (vma == Kernel::g_current_process->vm_manager.vma_map.end()) - return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS, - ErrorSummary::InvalidArgument, ErrorLevel::Usage); + return Kernel::ERR_INVALID_ADDRESS; memory_info->base_address = vma->second.base; memory_info->permission = static_cast(vma->second.permissions); @@ -842,8 +816,7 @@ static ResultCode SetTimer(Kernel::Handle handle, s64 initial, s64 interval) { LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle); if (initial < 0 || interval < 0) { - return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel, - ErrorSummary::InvalidArgument, ErrorLevel::Permanent); + return Kernel::ERR_OUT_OF_RANGE_KERNEL; } SharedPtr timer = Kernel::g_handle_table.Get(handle); @@ -902,8 +875,7 @@ static ResultCode CreateMemoryBlock(Kernel::Handle* out_handle, u32 addr, u32 si using Kernel::SharedMemory; if (size % Memory::PAGE_SIZE != 0) - return ResultCode(ErrorDescription::MisalignedSize, ErrorModule::OS, - ErrorSummary::InvalidArgument, ErrorLevel::Usage); + return Kernel::ERR_MISALIGNED_SIZE; SharedPtr shared_memory = nullptr; @@ -924,16 +896,14 @@ static ResultCode CreateMemoryBlock(Kernel::Handle* out_handle, u32 addr, u32 si if (!VerifyPermissions(static_cast(my_permission)) || !VerifyPermissions(static_cast(other_permission))) - return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, - ErrorSummary::InvalidArgument, ErrorLevel::Usage); + return Kernel::ERR_INVALID_COMBINATION; // TODO(Subv): Processes with memory type APPLICATION are not allowed // to create memory blocks with addr = 0, any attempts to do so // should return error 0xD92007EA. if ((addr < Memory::PROCESS_IMAGE_VADDR || addr + size > Memory::SHARED_MEMORY_VADDR_END) && addr != 0) { - return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS, - ErrorSummary::InvalidArgument, ErrorLevel::Usage); + return Kernel::ERR_INVALID_ADDRESS; } // When trying to create a memory block with address = 0, @@ -1035,7 +1005,7 @@ static ResultCode GetProcessInfo(s64* out, Kernel::Handle process_handle, u32 ty *out = process->heap_used + process->linear_heap_used + process->misc_memory_used; if (*out % Memory::PAGE_SIZE != 0) { LOG_ERROR(Kernel_SVC, "called, memory size not page-aligned"); - return ERR_MISALIGNED_SIZE; + return Kernel::ERR_MISALIGNED_SIZE; } break; case 1: @@ -1051,19 +1021,15 @@ static ResultCode GetProcessInfo(s64* out, Kernel::Handle process_handle, u32 ty case 20: *out = Memory::FCRAM_PADDR - process->GetLinearHeapBase(); break; + case 21: + case 22: + case 23: + // These return a different error value than higher invalid values + LOG_ERROR(Kernel_SVC, "unknown GetProcessInfo type=%u", type); + return Kernel::ERR_NOT_IMPLEMENTED; default: LOG_ERROR(Kernel_SVC, "unknown GetProcessInfo type=%u", type); - - if (type >= 21 && type <= 23) { - return ResultCode( // 0xE0E01BF4 - ErrorDescription::NotImplemented, ErrorModule::OS, ErrorSummary::InvalidArgument, - ErrorLevel::Usage); - } else { - return ResultCode( // 0xD8E007ED - ErrorDescription::InvalidEnumValue, ErrorModule::Kernel, - ErrorSummary::InvalidArgument, ErrorLevel::Permanent); - } - break; + return Kernel::ERR_INVALID_ENUM_VALUE; } return RESULT_SUCCESS; From c1a9e940680874a7571f18d8767fe953996907b8 Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Sun, 21 May 2017 15:49:55 -0700 Subject: [PATCH 6/7] Common: Clean up meta-template logic in BitField --- src/common/bit_field.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/common/bit_field.h b/src/common/bit_field.h index 72a01c7a8..0cc0a1be0 100644 --- a/src/common/bit_field.h +++ b/src/common/bit_field.h @@ -121,11 +121,11 @@ private: // T is an enumeration. Note that T is wrapped within an enable_if in the // former case to workaround compile errors which arise when using // std::underlying_type::type directly. - typedef typename std::conditional::value, std::underlying_type, - std::enable_if>::type::type StorageType; + using StorageType = typename std::conditional_t::value, std::underlying_type, + std::enable_if>::type; // Unsigned version of StorageType - typedef typename std::make_unsigned::type StorageTypeU; + using StorageTypeU = std::make_unsigned_t; public: /// Constants to allow limited introspection of fields if needed From a5810d61dab191b5a8e3cbb9de9fc9a8bad88826 Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Wed, 24 May 2017 21:04:55 -0700 Subject: [PATCH 7/7] FS: Remove unused result definition --- src/core/hle/service/fs/archive.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index 5c1235f8b..632712f2c 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp @@ -51,11 +51,6 @@ static constexpr Kernel::Handle INVALID_HANDLE{}; namespace Service { namespace FS { -// TODO: Verify code -/// Returned when a function is passed an invalid handle. -const ResultCode ERR_INVALID_HANDLE(ErrorDescription::InvalidHandle, ErrorModule::FS, - ErrorSummary::InvalidArgument, ErrorLevel::Permanent); - // Command to access archive file enum class FileCommand : u32 { Dummy1 = 0x000100C6,