diff --git a/app/src/main/cpp/skyline/common.cpp b/app/src/main/cpp/skyline/common.cpp index 6100d595..20207ac7 100644 --- a/app/src/main/cpp/skyline/common.cpp +++ b/app/src/main/cpp/skyline/common.cpp @@ -24,7 +24,7 @@ namespace skyline { void GroupMutex::lock(Group group) { auto none = Group::None; constexpr u64 timeout = 100; // The timeout in ns - auto end = utils::GetTimeNs() + timeout; + auto end = util::GetTimeNs() + timeout; while (true) { if (next == group) { @@ -41,7 +41,7 @@ namespace skyline { } else { flag.compare_exchange_weak(none, group); } - } else if (flag == group && (next == Group::None || utils::GetTimeNs() >= end)) { + } else if (flag == group && (next == Group::None || util::GetTimeNs() >= end)) { std::lock_guard lock(mtx); if (flag == group) { @@ -127,13 +127,14 @@ namespace skyline { Logger::~Logger() { WriteHeader("Logging ended"); + logFile.flush(); } void Logger::WriteHeader(const std::string &str) { syslog(LOG_ALERT, "%s", str.c_str()); + std::lock_guard guard(mtx); logFile << "0|" << str << "\n"; - logFile.flush(); } void Logger::Write(const LogLevel level, std::string str) { @@ -143,12 +144,12 @@ namespace skyline { if (character == '\n') character = '\\'; + std::lock_guard guard(mtx); logFile << "1|" << levelStr[static_cast(level)] << "|" << str << "\n"; - logFile.flush(); } DeviceState::DeviceState(kernel::OS *os, std::shared_ptr &process, std::shared_ptr jvmManager, std::shared_ptr settings, std::shared_ptr logger) - : os(os), jvmManager(std::move(jvmManager)), settings(std::move(settings)), logger(std::move(logger)), process(process) { + : os(os), jvm(std::move(jvmManager)), settings(std::move(settings)), logger(std::move(logger)), process(process) { // We assign these later as they use the state in their constructor and we don't want null pointers nce = std::move(std::make_shared(*this)); gpu = std::move(std::make_shared(*this)); diff --git a/app/src/main/cpp/skyline/common.h b/app/src/main/cpp/skyline/common.h index bb16e1e0..59e9da66 100644 --- a/app/src/main/cpp/skyline/common.h +++ b/app/src/main/cpp/skyline/common.h @@ -68,7 +68,7 @@ namespace skyline { NSP, //!< The NSP format from "nspwn" exploit: https://switchbrew.org/wiki/Switch_System_Flaws }; - namespace utils { + namespace util { /** * @brief Returns the current time in nanoseconds * @return The current time in nanoseconds @@ -93,7 +93,7 @@ namespace skyline { * @return The aligned value */ template - inline TypeVal AlignUp(TypeVal value, TypeMul multiple) { + constexpr inline TypeVal AlignUp(TypeVal value, TypeMul multiple) { static_assert(std::is_integral() && std::is_integral()); multiple--; return (value + multiple) & ~(multiple); @@ -108,7 +108,7 @@ namespace skyline { * @return The aligned value */ template - inline TypeVal AlignDown(TypeVal value, TypeMul multiple) { + constexpr inline TypeVal AlignDown(TypeVal value, TypeMul multiple) { static_assert(std::is_integral() && std::is_integral()); return value & ~(multiple - 1); } @@ -117,7 +117,7 @@ namespace skyline { * @param address The address to check for alignment * @return If the address is page aligned */ - inline bool PageAligned(u64 address) { + constexpr inline bool PageAligned(u64 address) { return !(address & (PAGE_SIZE - 1U)); } @@ -125,9 +125,26 @@ namespace skyline { * @param address The address to check for alignment * @return If the address is word aligned */ - inline bool WordAligned(u64 address) { + constexpr inline bool WordAligned(u64 address) { return !(address & 3U); } + + /** + * @param string The string to create a magic from + * @return The magic of the supplied string + */ + template + constexpr Type MakeMagic(std::string_view string) { + Type object{}; + auto offset = 0; + + for(auto& character : string) { + object |= static_cast(character) << offset; + offset += sizeof(character) * 8; + } + + return object; + } } /** @@ -198,6 +215,7 @@ namespace skyline { std::ofstream logFile; //!< An output stream to the log file const char *levelStr[4] = {"0", "1", "2", "3"}; //!< This is used to denote the LogLevel when written out to a file static constexpr int levelSyslog[4] = {LOG_ERR, LOG_WARNING, LOG_INFO, LOG_DEBUG}; //!< This corresponds to LogLevel and provides it's equivalent for syslog + Mutex mtx; //!< A mutex to lock before logging anything public: enum class LogLevel { Error, Warn, Info, Debug }; //!< The level of a particular log @@ -360,7 +378,7 @@ namespace skyline { std::shared_ptr nce; //!< This holds a reference to the NCE class std::shared_ptr gpu; //!< This holds a reference to the GPU class std::shared_ptr audio; //!< This holds a reference to the Audio class - std::shared_ptr jvmManager; //!< This holds a reference to the JvmManager class + std::shared_ptr jvm; //!< This holds a reference to the JvmManager class std::shared_ptr settings; //!< This holds a reference to the Settings class std::shared_ptr logger; //!< This holds a reference to the Logger class }; diff --git a/app/src/main/cpp/skyline/gpu.cpp b/app/src/main/cpp/skyline/gpu.cpp index a22521fe..dcc9f529 100644 --- a/app/src/main/cpp/skyline/gpu.cpp +++ b/app/src/main/cpp/skyline/gpu.cpp @@ -10,7 +10,7 @@ extern bool Halt; extern jobject Surface; namespace skyline::gpu { - GPU::GPU(const DeviceState &state) : state(state), window(ANativeWindow_fromSurface(state.jvmManager->GetEnv(), Surface)), vsyncEvent(std::make_shared(state)), bufferEvent(std::make_shared(state)) { + GPU::GPU(const DeviceState &state) : state(state), window(ANativeWindow_fromSurface(state.jvm->GetEnv(), Surface)), vsyncEvent(std::make_shared(state)), bufferEvent(std::make_shared(state)) { ANativeWindow_acquire(window); resolution.width = static_cast(ANativeWindow_getWidth(window)); resolution.height = static_cast(ANativeWindow_getHeight(window)); @@ -25,7 +25,7 @@ namespace skyline::gpu { if (surfaceUpdate) { if (Surface == nullptr) return; - window = ANativeWindow_fromSurface(state.jvmManager->GetEnv(), Surface); + window = ANativeWindow_fromSurface(state.jvm->GetEnv(), Surface); ANativeWindow_acquire(window); resolution.width = static_cast(ANativeWindow_getWidth(window)); resolution.height = static_cast(ANativeWindow_getHeight(window)); @@ -51,7 +51,7 @@ namespace skyline::gpu { ARect rect; ANativeWindow_lock(window, &windowBuffer, &rect); - memcpy(windowBuffer.bits, texture->backing.data(), texture->backing.size()); + std::memcpy(windowBuffer.bits, texture->backing.data(), texture->backing.size()); ANativeWindow_unlockAndPost(window); vsyncEvent->Signal(); diff --git a/app/src/main/cpp/skyline/gpu/texture.cpp b/app/src/main/cpp/skyline/gpu/texture.cpp index abcbad2d..7858f75e 100644 --- a/app/src/main/cpp/skyline/gpu/texture.cpp +++ b/app/src/main/cpp/skyline/gpu/texture.cpp @@ -26,8 +26,8 @@ namespace skyline::gpu { constexpr auto gobHeight = 8; // The height of a GOB in lines auto robHeight = gobHeight * guest->tileConfig.blockHeight; // The height of a single ROB (Row of Blocks) in lines - auto surfaceHeightRobs = utils::AlignUp(dimensions.height / format.blockHeight, robHeight) / robHeight; // The height of the surface in ROBs (Row Of Blocks) - auto robWidthBytes = utils::AlignUp((guest->tileConfig.surfaceWidth / format.blockWidth) * format.bpb, gobWidth); // The width of a ROB in bytes + auto surfaceHeightRobs = util::AlignUp(dimensions.height / format.blockHeight, robHeight) / robHeight; // The height of the surface in ROBs (Row Of Blocks) + auto robWidthBytes = util::AlignUp((guest->tileConfig.surfaceWidth / format.blockWidth) * format.bpb, gobWidth); // The width of a ROB in bytes auto robWidthBlocks = robWidthBytes / gobWidth; // The width of a ROB in blocks (and GOBs because block width == 1 on the Tegra X1) auto robBytes = robWidthBytes * robHeight; // The size of a ROB in bytes auto gobYOffset = robWidthBytes * gobHeight; // The offset of the next Y-axis GOB from the current one in linear space diff --git a/app/src/main/cpp/skyline/kernel/ipc.cpp b/app/src/main/cpp/skyline/kernel/ipc.cpp index 85d88f11..e4d0c471 100644 --- a/app/src/main/cpp/skyline/kernel/ipc.cpp +++ b/app/src/main/cpp/skyline/kernel/ipc.cpp @@ -25,17 +25,17 @@ namespace skyline::kernel::ipc { if (header->handleDesc) { handleDesc = reinterpret_cast(pointer); pointer += sizeof(HandleDescriptor) + (handleDesc->sendPid ? sizeof(u64) : 0); - for (uint index = 0; handleDesc->copyCount > index; index++) { + for (u32 index = 0; handleDesc->copyCount > index; index++) { copyHandles.push_back(*reinterpret_cast(pointer)); pointer += sizeof(KHandle); } - for (uint index = 0; handleDesc->moveCount > index; index++) { + for (u32 index = 0; handleDesc->moveCount > index; index++) { moveHandles.push_back(*reinterpret_cast(pointer)); pointer += sizeof(KHandle); } } - for (uint index = 0; header->xNo > index; index++) { + for (u8 index = 0; header->xNo > index; index++) { auto bufX = reinterpret_cast(pointer); if (bufX->Address()) { inputBuf.emplace_back(bufX); @@ -44,7 +44,7 @@ namespace skyline::kernel::ipc { pointer += sizeof(BufferDescriptorX); } - for (uint index = 0; header->aNo > index; index++) { + for (u8 index = 0; header->aNo > index; index++) { auto bufA = reinterpret_cast(pointer); if (bufA->Address()) { inputBuf.emplace_back(bufA); @@ -53,7 +53,7 @@ namespace skyline::kernel::ipc { pointer += sizeof(BufferDescriptorABW); } - for (uint index = 0; header->bNo > index; index++) { + for (u8 index = 0; header->bNo > index; index++) { auto bufB = reinterpret_cast(pointer); if (bufB->Address()) { outputBuf.emplace_back(bufB); @@ -62,7 +62,7 @@ namespace skyline::kernel::ipc { pointer += sizeof(BufferDescriptorABW); } - for (uint index = 0; header->wNo > index; index++) { + for (u8 index = 0; header->wNo > index; index++) { auto bufW = reinterpret_cast(pointer); if (bufW->Address()) { inputBuf.emplace_back(bufW, IpcBufferType::W); @@ -72,9 +72,8 @@ namespace skyline::kernel::ipc { pointer += sizeof(BufferDescriptorABW); } - constexpr auto ipcPaddingSum = 0x10; // The sum of the padding surrounding the data payload - - u64 padding = ((((reinterpret_cast(pointer) - reinterpret_cast(tls)) - 1U) & ~(ipcPaddingSum - 1U)) + ipcPaddingSum + (reinterpret_cast(tls) - reinterpret_cast(pointer))); // Calculate the amount of padding at the front + auto offset = reinterpret_cast(pointer) - reinterpret_cast(tls); // We calculate the relative offset as the absolute one might differ + auto padding = util::AlignUp(offset, constant::IpcPaddingSum) - offset; // Calculate the amount of padding at the front pointer += padding; if (isDomain && (header->type == CommandType::Request)) { @@ -88,7 +87,7 @@ namespace skyline::kernel::ipc { cmdArgSz = domain->payloadSz - sizeof(PayloadHeader); pointer += domain->payloadSz; - for (uint index = 0; domain->inputCount > index; index++) { + for (u8 index = 0; domain->inputCount > index; index++) { domainObjects.push_back(*reinterpret_cast(pointer)); pointer += sizeof(KHandle); } @@ -97,18 +96,16 @@ namespace skyline::kernel::ipc { pointer += sizeof(PayloadHeader); cmdArg = pointer; - cmdArgSz = (header->rawSize * sizeof(u32)) - (ipcPaddingSum + sizeof(PayloadHeader)); + cmdArgSz = (header->rawSize * sizeof(u32)) - (constant::IpcPaddingSum + sizeof(PayloadHeader)); pointer += cmdArgSz; } payloadOffset = cmdArg; - constexpr auto sfciMagic = 0x49434653; //!< SFCI in reverse, present in received IPC messages - - if (payload->magic != sfciMagic && header->type != CommandType::Control) + if (payload->magic != util::MakeMagic("SFCI") && header->type != CommandType::Control) // SFCI is the magic in received IPC messages state.logger->Debug("Unexpected Magic in PayloadHeader: 0x{:X}", u32(payload->magic)); - pointer += ipcPaddingSum - padding; + pointer += constant::IpcPaddingSum - padding; if (header->cFlag == BufferCFlag::SingleDescriptor) { auto bufC = reinterpret_cast(pointer); @@ -117,7 +114,7 @@ namespace skyline::kernel::ipc { state.logger->Debug("Buf C: AD: 0x{:X} SZ: 0x{:X}", u64(bufC->address), u16(bufC->size)); } } else if (header->cFlag > BufferCFlag::SingleDescriptor) { - for (uint index = 0; (static_cast(header->cFlag) - 2) > index; index++) { // (cFlag - 2) C descriptors are present + for (u8 index = 0; (static_cast(header->cFlag) - 2) > index; index++) { // (cFlag - 2) C descriptors are present auto bufC = reinterpret_cast(pointer); if (bufC->address) { outputBuf.emplace_back(bufC); @@ -143,13 +140,10 @@ namespace skyline::kernel::ipc { auto tls = state.process->GetPointer(state.thread->tls); u8 *pointer = tls; - constexpr auto tlsIpcSize = 0x100; // The size of the IPC command buffer in a TLS slot - memset(tls, 0, tlsIpcSize); - - constexpr auto ipcPaddingSum = 0x10; // The sum of the padding surrounding the data payload + memset(tls, 0, constant::TlsIpcSize); auto header = reinterpret_cast(pointer); - header->rawSize = static_cast((sizeof(PayloadHeader) + argVec.size() + (domainObjects.size() * sizeof(KHandle)) + ipcPaddingSum + (isDomain ? sizeof(DomainHeaderRequest) : 0)) / sizeof(u32)); // Size is in 32-bit units because Nintendo + header->rawSize = static_cast((sizeof(PayloadHeader) + argVec.size() + (domainObjects.size() * sizeof(KHandle)) + constant::IpcPaddingSum + (isDomain ? sizeof(DomainHeaderRequest) : 0)) / sizeof(u32)); // Size is in 32-bit units because Nintendo header->handleDesc = (!copyHandles.empty() || !moveHandles.empty()); pointer += sizeof(CommandHeader); @@ -159,18 +153,19 @@ namespace skyline::kernel::ipc { handleDesc->moveCount = static_cast(moveHandles.size()); pointer += sizeof(HandleDescriptor); - for (unsigned int copyHandle : copyHandles) { + for (auto copyHandle : copyHandles) { *reinterpret_cast(pointer) = copyHandle; pointer += sizeof(KHandle); } - for (unsigned int moveHandle : moveHandles) { + for (auto moveHandle : moveHandles) { *reinterpret_cast(pointer) = moveHandle; pointer += sizeof(KHandle); } } - u64 padding = ((((reinterpret_cast(pointer) - reinterpret_cast(tls)) - 1U) & ~(ipcPaddingSum - 1U)) + ipcPaddingSum + (reinterpret_cast(tls) - reinterpret_cast(pointer))); // Calculate the amount of padding at the front + auto offset = reinterpret_cast(pointer) - reinterpret_cast(tls); // We calculate the relative offset as the absolute one might differ + auto padding = util::AlignUp(offset, constant::IpcPaddingSum) - offset; // Calculate the amount of padding at the front pointer += padding; if (isDomain) { @@ -179,16 +174,14 @@ namespace skyline::kernel::ipc { pointer += sizeof(DomainHeaderResponse); } - constexpr auto sfcoMagic = 0x4F434653; // SFCO in reverse, IPC Response Magic - auto payload = reinterpret_cast(pointer); - payload->magic = sfcoMagic; + payload->magic = util::MakeMagic("SFCO"); // SFCO is the magic in IPC responses payload->version = 1; payload->value = errorCode; pointer += sizeof(PayloadHeader); if (!argVec.empty()) - memcpy(pointer, argVec.data(), argVec.size()); + std::memcpy(pointer, argVec.data(), argVec.size()); pointer += argVec.size(); if (isDomain) { diff --git a/app/src/main/cpp/skyline/kernel/ipc.h b/app/src/main/cpp/skyline/kernel/ipc.h index ebdcee7c..561178ce 100644 --- a/app/src/main/cpp/skyline/kernel/ipc.h +++ b/app/src/main/cpp/skyline/kernel/ipc.h @@ -6,325 +6,332 @@ #include #include -namespace skyline::kernel::ipc { - /** - * @brief This reflects the value in CommandStruct::type - */ - enum class CommandType : u16 { - Invalid = 0, LegacyRequest = 1, Close = 2, LegacyControl = 3, Request = 4, Control = 5, RequestWithContext = 6, ControlWithContext = 7 - }; +namespace skyline { + namespace constant { + constexpr auto IpcPaddingSum = 0x10; // The sum of the padding surrounding the data payload + constexpr auto TlsIpcSize = 0x100; // The size of the IPC command buffer in a TLS slot + } - /** - * @brief This reflects the value in CommandStruct::c_flags - */ - enum class BufferCFlag : u8 { - None = 0, InlineDescriptor = 1, SingleDescriptor = 2 - }; - - /** - * @brief This bit-field structure holds the header of an IPC command. (https://switchbrew.org/wiki/IPC_Marshalling#IPC_Command_Structure) - */ - struct CommandHeader { - CommandType type : 16; - u8 xNo : 4; - u8 aNo : 4; - u8 bNo : 4; - u8 wNo : 4; - u32 rawSize : 10; - BufferCFlag cFlag : 4; - u32 : 17; - bool handleDesc : 1; - }; - static_assert(sizeof(CommandHeader) == 8); - - /** - * @brief This bit-field structure holds the handle descriptor of a received IPC command. (https://switchbrew.org/wiki/IPC_Marshalling#Handle_descriptor) - */ - struct HandleDescriptor { - bool sendPid : 1; - u32 copyCount : 4; - u32 moveCount : 4; - u32 : 23; - }; - static_assert(sizeof(HandleDescriptor) == 4); - - /** - * @brief This bit-field structure holds the domain's header of an IPC request command. (https://switchbrew.org/wiki/IPC_Marshalling#Domains) - */ - struct DomainHeaderRequest { - u8 command; - u8 inputCount; - u16 payloadSz; - u32 objectId; - u32 : 32; - u32 token; - }; - static_assert(sizeof(DomainHeaderRequest) == 16); - - /** - * @brief This reflects the value of DomainHeaderRequest::command - */ - enum class DomainCommand : u8 { - SendMessage = 1, CloseVHandle = 2 - }; - - /** - * @brief This bit-field structure holds the domain's header of an IPC response command. (https://switchbrew.org/wiki/IPC_Marshalling#Domains) - */ - struct DomainHeaderResponse { - u32 outputCount; - u32 : 32; - u64 : 64; - }; - static_assert(sizeof(DomainHeaderResponse) == 16); - - /** - * @brief This bit-field structure holds the data payload of an IPC command. (https://switchbrew.org/wiki/IPC_Marshalling#Data_payload) - */ - struct PayloadHeader { - u32 magic; - u32 version; - u32 value; - u32 token; - }; - static_assert(sizeof(PayloadHeader) == 16); - - - /** - * @brief This reflects which function PayloadHeader::value refers to when a control request is sent (https://switchbrew.org/wiki/IPC_Marshalling#Control) - */ - enum class ControlCommand : u32 { - ConvertCurrentObjectToDomain = 0, CopyFromCurrentDomain = 1, CloneCurrentObject = 2, QueryPointerBufferSize = 3, CloneCurrentObjectEx = 4 - }; - - /** - * @brief This is a buffer descriptor for X buffers: https://switchbrew.org/wiki/IPC_Marshalling#Buffer_descriptor_X_.22Pointer.22 - */ - struct BufferDescriptorX { - u16 counter0_5 : 6; //!< The first 5 bits of the counter - u16 address36_38 : 3; //!< Bit 36-38 of the address - u16 counter9_11 : 3; //!< Bit 9-11 of the counter - u16 address32_35 : 4; //!< Bit 32-35 of the address - u16 size : 16; //!< The 16 bit size of the buffer - u32 address0_31 : 32; //!< The first 32-bits of the address - - BufferDescriptorX(u64 address, u16 counter, u16 size) : size(size) { - address0_31 = static_cast(address & 0x7FFFFFFF80000000); - address32_35 = static_cast(address & 0x78000000); - address36_38 = static_cast(address & 0x7000000); - counter0_5 = static_cast(address & 0x7E00); - counter9_11 = static_cast(address & 0x38); - } + namespace kernel::ipc { + /** + * @brief This reflects the value in CommandStruct::type + */ + enum class CommandType : u16 { + Invalid = 0, LegacyRequest = 1, Close = 2, LegacyControl = 3, Request = 4, Control = 5, RequestWithContext = 6, ControlWithContext = 7 + }; /** - * @return The address of the buffer + * @brief This reflects the value in CommandStruct::c_flags */ - inline u64 Address() const { - return static_cast(address0_31) | static_cast(address32_35) << 32 | static_cast(address36_38) << 36; - } + enum class BufferCFlag : u8 { + None = 0, InlineDescriptor = 1, SingleDescriptor = 2 + }; /** - * @return The buffer counter + * @brief This bit-field structure holds the header of an IPC command. (https://switchbrew.org/wiki/IPC_Marshalling#IPC_Command_Structure) */ - inline u16 Counter() const { - return static_cast(counter0_5) | static_cast(counter9_11) << 9; - } - }; - static_assert(sizeof(BufferDescriptorX) == 8); - - /** - * @brief This is a buffer descriptor for A/B/W buffers: https://switchbrew.org/wiki/IPC_Marshalling#Buffer_descriptor_A.2FB.2FW_.22Send.22.2F.22Receive.22.2F.22Exchange.22 - */ - struct BufferDescriptorABW { - u32 size0_31 : 32; //!< The first 32 bits of the size - u32 address0_31 : 32; //!< The first 32 bits of the address - u8 flags : 2; //!< The buffer flags - u8 address36_38 : 3; //!< Bit 36-38 of the address - u32 : 19; - u8 size32_35 : 4; //!< Bit 32-35 of the size - u8 address32_35 : 4; //!< Bit 32-35 of the address - - BufferDescriptorABW(u64 address, u64 size) { - address0_31 = static_cast(address & 0x7FFFFFFF80000000); - address32_35 = static_cast(address & 0x78000000); - address36_38 = static_cast(address & 0x7000000); - size0_31 = static_cast(size & 0x7FFFFFFF80000000); - size32_35 = static_cast(size & 0x78000000); - } + struct CommandHeader { + CommandType type : 16; + u8 xNo : 4; + u8 aNo : 4; + u8 bNo : 4; + u8 wNo : 4; + u32 rawSize : 10; + BufferCFlag cFlag : 4; + u32 : 17; + bool handleDesc : 1; + }; + static_assert(sizeof(CommandHeader) == 8); /** - * @return The address of the buffer + * @brief This bit-field structure holds the handle descriptor of a received IPC command. (https://switchbrew.org/wiki/IPC_Marshalling#Handle_descriptor) */ - inline u64 Address() const { - return static_cast(address0_31) | static_cast(address32_35) << 32 | static_cast(address36_38) << 36; - } + struct HandleDescriptor { + bool sendPid : 1; + u32 copyCount : 4; + u32 moveCount : 4; + u32 : 23; + }; + static_assert(sizeof(HandleDescriptor) == 4); /** - * @return The size of the buffer + * @brief This bit-field structure holds the domain's header of an IPC request command. (https://switchbrew.org/wiki/IPC_Marshalling#Domains) */ - inline u64 Size() const { - return static_cast(size0_31) | static_cast(size32_35) << 32; - } - }; - static_assert(sizeof(BufferDescriptorABW) == 12); - - /** - * @brief This is a buffer descriptor for C buffers: https://switchbrew.org/wiki/IPC_Marshalling#Buffer_descriptor_C_.22ReceiveList.22 - */ - struct BufferDescriptorC { - u64 address : 48; //!< The 48-bit address of the buffer - u32 size : 16; //!< The 16-bit size of the buffer - - BufferDescriptorC(u64 address, u16 size) : address(address), size(size) {} - }; - static_assert(sizeof(BufferDescriptorC) == 8); - - /** - * @brief This enumerates the types of IPC buffers - */ - enum class IpcBufferType { - X, //!< This is a type-X buffer - A, //!< This is a type-A buffer - B, //!< This is a type-B buffer - W, //!< This is a type-W buffer - C //!< This is a type-C buffer - }; - - /** - * @brief Describes a buffer by holding the address and size - */ - struct IpcBuffer { - u64 address; //!< The address of the buffer - size_t size; //!< The size of the buffer - IpcBufferType type; //!< The type of the buffer + struct DomainHeaderRequest { + u8 command; + u8 inputCount; + u16 payloadSz; + u32 objectId; + u32 : 32; + u32 token; + }; + static_assert(sizeof(DomainHeaderRequest) == 16); /** - * @param address The address of the buffer - * @param size The size of the buffer - * @param type The type of the buffer + * @brief This reflects the value of DomainHeaderRequest::command */ - IpcBuffer(u64 address, size_t size, IpcBufferType type); - }; - - /** - * @brief This holds an input IPC buffer - */ - struct InputBuffer : public IpcBuffer { - /** - * @param aBuf The X Buffer Descriptor that has contains the input data - */ - InputBuffer(kernel::ipc::BufferDescriptorX *xBuf); + enum class DomainCommand : u8 { + SendMessage = 1, CloseVHandle = 2 + }; /** - * @param aBuf The A or W Buffer Descriptor that has contains the input data + * @brief This bit-field structure holds the domain's header of an IPC response command. (https://switchbrew.org/wiki/IPC_Marshalling#Domains) */ - InputBuffer(kernel::ipc::BufferDescriptorABW *aBuf, IpcBufferType type = IpcBufferType::A); - }; - - /** - * @brief This holds an output IPC buffer - */ - struct OutputBuffer : public IpcBuffer { - /** - * @param bBuf The B or W Buffer Descriptor that has to be outputted to - */ - OutputBuffer(kernel::ipc::BufferDescriptorABW *bBuf, IpcBufferType type = IpcBufferType::B); + struct DomainHeaderResponse { + u32 outputCount; + u32 : 32; + u64 : 64; + }; + static_assert(sizeof(DomainHeaderResponse) == 16); /** - * @param cBuf The C Buffer Descriptor that has to be outputted to + * @brief This bit-field structure holds the data payload of an IPC command. (https://switchbrew.org/wiki/IPC_Marshalling#Data_payload) */ - OutputBuffer(kernel::ipc::BufferDescriptorC *cBuf); - }; + struct PayloadHeader { + u32 magic; + u32 version; + u32 value; + u32 token; + }; + static_assert(sizeof(PayloadHeader) == 16); - /** - * @brief This class encapsulates an IPC Request (https://switchbrew.org/wiki/IPC_Marshalling) - */ - class IpcRequest { - private: - const DeviceState &state; //!< The state of the device - u8 *payloadOffset; //!< This is the offset of the data read from the payload - - public: - CommandHeader *header{}; //!< The header of the request - HandleDescriptor *handleDesc{}; //!< The handle descriptor in case CommandHeader::handle_desc is true in the header - bool isDomain{}; //!< If this is a domain request - DomainHeaderRequest *domain{}; //!< In case this is a domain request, this holds data regarding it - PayloadHeader *payload{}; //!< This is the header of the payload - u8 *cmdArg{}; //!< This is a pointer to the data payload (End of PayloadHeader) - u64 cmdArgSz{}; //!< This is the size of the data payload - std::vector copyHandles; //!< A vector of handles that should be copied from the server to the client process (The difference is just to match application expectations, there is no real difference b/w copying and moving handles) - std::vector moveHandles; //!< A vector of handles that should be moved from the server to the client process rather than copied - std::vector domainObjects; //!< A vector of all input domain objects - std::vector inputBuf; //!< This is a vector of input buffers - std::vector outputBuf; //!< This is a vector of output buffers /** - * @param isDomain If the following request is a domain request - * @param state The state of the device + * @brief This reflects which function PayloadHeader::value refers to when a control request is sent (https://switchbrew.org/wiki/IPC_Marshalling#Control) */ - IpcRequest(bool isDomain, const DeviceState &state); + enum class ControlCommand : u32 { + ConvertCurrentObjectToDomain = 0, CopyFromCurrentDomain = 1, CloneCurrentObject = 2, QueryPointerBufferSize = 3, CloneCurrentObjectEx = 4 + }; /** - * @brief This returns a reference to an item from the top of the payload - * @tparam ValueType The type of the object to read + * @brief This is a buffer descriptor for X buffers: https://switchbrew.org/wiki/IPC_Marshalling#Buffer_descriptor_X_.22Pointer.22 */ - template - inline ValueType &Pop() { - ValueType &value = *reinterpret_cast(payloadOffset); - payloadOffset += sizeof(ValueType); - return value; - } + struct BufferDescriptorX { + u16 counter0_5 : 6; //!< The first 5 bits of the counter + u16 address36_38 : 3; //!< Bit 36-38 of the address + u16 counter9_11 : 3; //!< Bit 9-11 of the counter + u16 address32_35 : 4; //!< Bit 32-35 of the address + u16 size : 16; //!< The 16 bit size of the buffer + u32 address0_31 : 32; //!< The first 32-bits of the address - /** - * @brief This skips an object to pop off the top - * @tparam ValueType The type of the object to skip - */ - template - inline void Skip() { - payloadOffset += sizeof(ValueType); - } - }; - - /** - * @brief This class encapsulates an IPC Response (https://switchbrew.org/wiki/IPC_Marshalling) - */ - class IpcResponse { - private: - std::vector argVec; //!< This holds all of the contents to be pushed to the payload - const DeviceState &state; //!< The state of the device - - public: - bool nWrite{}; //!< This is to signal the IPC handler to not write this, as it will be manually written - bool isDomain{}; //!< If this is a domain request - u32 errorCode{}; //!< The error code to respond with, it is 0 (Success) by default - std::vector copyHandles; //!< A vector of handles to copy - std::vector moveHandles; //!< A vector of handles to move - std::vector domainObjects; //!< A vector of domain objects to write - - /** - * @param isDomain If the following request is a domain request - * @param state The state of the device - */ - IpcResponse(bool isDomain, const DeviceState &state); - - /** - * @brief Writes an object to the payload - * @tparam ValueType The type of the object to write - * @param value A reference to the object to be written - */ - template - inline void Push(const ValueType &value) { - argVec.reserve(argVec.size() + sizeof(ValueType)); - auto item = reinterpret_cast(&value); - for (uint index = 0; sizeof(ValueType) > index; index++) { - argVec.push_back(*item); - item++; + BufferDescriptorX(u64 address, u16 counter, u16 size) : size(size) { + address0_31 = static_cast(address & 0x7FFFFFFF80000000); + address32_35 = static_cast(address & 0x78000000); + address36_38 = static_cast(address & 0x7000000); + counter0_5 = static_cast(address & 0x7E00); + counter9_11 = static_cast(address & 0x38); } - } + + /** + * @return The address of the buffer + */ + inline u64 Address() const { + return static_cast(address0_31) | static_cast(address32_35) << 32 | static_cast(address36_38) << 36; + } + + /** + * @return The buffer counter + */ + inline u16 Counter() const { + return static_cast(counter0_5) | static_cast(counter9_11) << 9; + } + }; + static_assert(sizeof(BufferDescriptorX) == 8); /** - * @brief Writes this IpcResponse object's contents into TLS + * @brief This is a buffer descriptor for A/B/W buffers: https://switchbrew.org/wiki/IPC_Marshalling#Buffer_descriptor_A.2FB.2FW_.22Send.22.2F.22Receive.22.2F.22Exchange.22 */ - void WriteResponse(); - }; + struct BufferDescriptorABW { + u32 size0_31 : 32; //!< The first 32 bits of the size + u32 address0_31 : 32; //!< The first 32 bits of the address + u8 flags : 2; //!< The buffer flags + u8 address36_38 : 3; //!< Bit 36-38 of the address + u32 : 19; + u8 size32_35 : 4; //!< Bit 32-35 of the size + u8 address32_35 : 4; //!< Bit 32-35 of the address + + BufferDescriptorABW(u64 address, u64 size) { + address0_31 = static_cast(address & 0x7FFFFFFF80000000); + address32_35 = static_cast(address & 0x78000000); + address36_38 = static_cast(address & 0x7000000); + size0_31 = static_cast(size & 0x7FFFFFFF80000000); + size32_35 = static_cast(size & 0x78000000); + } + + /** + * @return The address of the buffer + */ + inline u64 Address() const { + return static_cast(address0_31) | static_cast(address32_35) << 32 | static_cast(address36_38) << 36; + } + + /** + * @return The size of the buffer + */ + inline u64 Size() const { + return static_cast(size0_31) | static_cast(size32_35) << 32; + } + }; + static_assert(sizeof(BufferDescriptorABW) == 12); + + /** + * @brief This is a buffer descriptor for C buffers: https://switchbrew.org/wiki/IPC_Marshalling#Buffer_descriptor_C_.22ReceiveList.22 + */ + struct BufferDescriptorC { + u64 address : 48; //!< The 48-bit address of the buffer + u32 size : 16; //!< The 16-bit size of the buffer + + BufferDescriptorC(u64 address, u16 size) : address(address), size(size) {} + }; + static_assert(sizeof(BufferDescriptorC) == 8); + + /** + * @brief This enumerates the types of IPC buffers + */ + enum class IpcBufferType { + X, //!< This is a type-X buffer + A, //!< This is a type-A buffer + B, //!< This is a type-B buffer + W, //!< This is a type-W buffer + C //!< This is a type-C buffer + }; + + /** + * @brief Describes a buffer by holding the address and size + */ + struct IpcBuffer { + u64 address; //!< The address of the buffer + size_t size; //!< The size of the buffer + IpcBufferType type; //!< The type of the buffer + + /** + * @param address The address of the buffer + * @param size The size of the buffer + * @param type The type of the buffer + */ + IpcBuffer(u64 address, size_t size, IpcBufferType type); + }; + + /** + * @brief This holds an input IPC buffer + */ + struct InputBuffer : public IpcBuffer { + /** + * @param aBuf The X Buffer Descriptor that has contains the input data + */ + InputBuffer(kernel::ipc::BufferDescriptorX *xBuf); + + /** + * @param aBuf The A or W Buffer Descriptor that has contains the input data + */ + InputBuffer(kernel::ipc::BufferDescriptorABW *aBuf, IpcBufferType type = IpcBufferType::A); + }; + + /** + * @brief This holds an output IPC buffer + */ + struct OutputBuffer : public IpcBuffer { + /** + * @param bBuf The B or W Buffer Descriptor that has to be outputted to + */ + OutputBuffer(kernel::ipc::BufferDescriptorABW *bBuf, IpcBufferType type = IpcBufferType::B); + + /** + * @param cBuf The C Buffer Descriptor that has to be outputted to + */ + OutputBuffer(kernel::ipc::BufferDescriptorC *cBuf); + }; + + /** + * @brief This class encapsulates an IPC Request (https://switchbrew.org/wiki/IPC_Marshalling) + */ + class IpcRequest { + private: + const DeviceState &state; //!< The state of the device + u8 *payloadOffset; //!< This is the offset of the data read from the payload + + public: + CommandHeader *header{}; //!< The header of the request + HandleDescriptor *handleDesc{}; //!< The handle descriptor in case CommandHeader::handle_desc is true in the header + bool isDomain{}; //!< If this is a domain request + DomainHeaderRequest *domain{}; //!< In case this is a domain request, this holds data regarding it + PayloadHeader *payload{}; //!< This is the header of the payload + u8 *cmdArg{}; //!< This is a pointer to the data payload (End of PayloadHeader) + u64 cmdArgSz{}; //!< This is the size of the data payload + std::vector copyHandles; //!< A vector of handles that should be copied from the server to the client process (The difference is just to match application expectations, there is no real difference b/w copying and moving handles) + std::vector moveHandles; //!< A vector of handles that should be moved from the server to the client process rather than copied + std::vector domainObjects; //!< A vector of all input domain objects + std::vector inputBuf; //!< This is a vector of input buffers + std::vector outputBuf; //!< This is a vector of output buffers + + /** + * @param isDomain If the following request is a domain request + * @param state The state of the device + */ + IpcRequest(bool isDomain, const DeviceState &state); + + /** + * @brief This returns a reference to an item from the top of the payload + * @tparam ValueType The type of the object to read + */ + template + inline ValueType &Pop() { + ValueType &value = *reinterpret_cast(payloadOffset); + payloadOffset += sizeof(ValueType); + return value; + } + + /** + * @brief This skips an object to pop off the top + * @tparam ValueType The type of the object to skip + */ + template + inline void Skip() { + payloadOffset += sizeof(ValueType); + } + }; + + /** + * @brief This class encapsulates an IPC Response (https://switchbrew.org/wiki/IPC_Marshalling) + */ + class IpcResponse { + private: + std::vector argVec; //!< This holds all of the contents to be pushed to the payload + const DeviceState &state; //!< The state of the device + + public: + bool nWrite{}; //!< This is to signal the IPC handler to not write this, as it will be manually written + bool isDomain{}; //!< If this is a domain request + u32 errorCode{}; //!< The error code to respond with, it is 0 (Success) by default + std::vector copyHandles; //!< A vector of handles to copy + std::vector moveHandles; //!< A vector of handles to move + std::vector domainObjects; //!< A vector of domain objects to write + + /** + * @param isDomain If the following request is a domain request + * @param state The state of the device + */ + IpcResponse(bool isDomain, const DeviceState &state); + + /** + * @brief Writes an object to the payload + * @tparam ValueType The type of the object to write + * @param value A reference to the object to be written + */ + template + inline void Push(const ValueType &value) { + argVec.reserve(argVec.size() + sizeof(ValueType)); + auto item = reinterpret_cast(&value); + for (uint index = 0; sizeof(ValueType) > index; index++) { + argVec.push_back(*item); + item++; + } + } + + /** + * @brief Writes this IpcResponse object's contents into TLS + */ + void WriteResponse(); + }; + } } diff --git a/app/src/main/cpp/skyline/kernel/memory.cpp b/app/src/main/cpp/skyline/kernel/memory.cpp index cedc2c53..c4031d61 100644 --- a/app/src/main/cpp/skyline/kernel/memory.cpp +++ b/app/src/main/cpp/skyline/kernel/memory.cpp @@ -144,8 +144,8 @@ namespace skyline::kernel { case memory::AddressSpaceType::AddressSpace39Bit: { base.address = constant::BaseAddress; base.size = 0x7FF8000000; - code.address = utils::AlignDown(address, 0x200000); - code.size = utils::AlignUp(address + size, 0x200000) - code.address; + code.address = util::AlignDown(address, 0x200000); + code.size = util::AlignUp(address + size, 0x200000) - code.address; alias.address = code.address + code.size; alias.size = 0x1000000000; heap.address = alias.address + alias.size; diff --git a/app/src/main/cpp/skyline/kernel/svc.cpp b/app/src/main/cpp/skyline/kernel/svc.cpp index 70a90132..ca626210 100644 --- a/app/src/main/cpp/skyline/kernel/svc.cpp +++ b/app/src/main/cpp/skyline/kernel/svc.cpp @@ -28,14 +28,14 @@ namespace skyline::kernel::svc { void SetMemoryAttribute(DeviceState &state) { auto address = state.ctx->registers.x0; - if (!utils::PageAligned(address)) { + if (!util::PageAligned(address)) { state.ctx->registers.w0 = constant::status::InvAddress; state.logger->Warn("svcSetMemoryAttribute: 'address' not page aligned: 0x{:X}", address); return; } auto size = state.ctx->registers.x1; - if (!utils::PageAligned(size)) { + if (!util::PageAligned(size)) { state.ctx->registers.w0 = constant::status::InvSize; state.logger->Warn("svcSetMemoryAttribute: 'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size); return; @@ -77,13 +77,13 @@ namespace skyline::kernel::svc { auto source = state.ctx->registers.x1; auto size = state.ctx->registers.x2; - if (!utils::PageAligned(destination) || !utils::PageAligned(source)) { + if (!util::PageAligned(destination) || !util::PageAligned(source)) { state.ctx->registers.w0 = constant::status::InvAddress; state.logger->Warn("svcMapMemory: Addresses not page aligned: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes)", source, destination, size); return; } - if (!utils::PageAligned(size)) { + if (!util::PageAligned(size)) { state.ctx->registers.w0 = constant::status::InvSize; state.logger->Warn("svcMapMemory: 'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size); return; @@ -126,13 +126,13 @@ namespace skyline::kernel::svc { auto destination = state.ctx->registers.x1; auto size = state.ctx->registers.x2; - if (!utils::PageAligned(destination) || !utils::PageAligned(source)) { + if (!util::PageAligned(destination) || !util::PageAligned(source)) { state.ctx->registers.w0 = constant::status::InvAddress; state.logger->Warn("svcUnmapMemory: Addresses not page aligned: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes)", source, destination, size); return; } - if (!utils::PageAligned(size)) { + if (!util::PageAligned(size)) { state.ctx->registers.w0 = constant::status::InvSize; state.logger->Warn("svcUnmapMemory: 'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size); return; @@ -307,14 +307,14 @@ namespace skyline::kernel::svc { auto object = state.process->GetHandle(state.ctx->registers.w0); u64 address = state.ctx->registers.x1; - if (!utils::PageAligned(address)) { + if (!util::PageAligned(address)) { state.ctx->registers.w0 = constant::status::InvAddress; state.logger->Warn("svcMapSharedMemory: 'address' not page aligned: 0x{:X}", address); return; } auto size = state.ctx->registers.x2; - if (!utils::PageAligned(size)) { + if (!util::PageAligned(size)) { state.ctx->registers.w0 = constant::status::InvSize; state.logger->Warn("svcMapSharedMemory: 'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size); return; @@ -341,14 +341,14 @@ namespace skyline::kernel::svc { void CreateTransferMemory(DeviceState &state) { u64 address = state.ctx->registers.x1; - if (!utils::PageAligned(address)) { + if (!util::PageAligned(address)) { state.ctx->registers.w0 = constant::status::InvAddress; state.logger->Warn("svcCreateTransferMemory: 'address' not page aligned: 0x{:X}", address); return; } u64 size = state.ctx->registers.x2; - if (!utils::PageAligned(size)) { + if (!util::PageAligned(size)) { state.ctx->registers.w0 = constant::status::InvSize; state.logger->Warn("svcCreateTransferMemory: 'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size); return; @@ -449,7 +449,7 @@ namespace skyline::kernel::svc { auto timeout = state.ctx->registers.x3; state.logger->Debug("svcWaitSynchronization: Waiting on handles:\n{}Timeout: 0x{:X} ns", handleStr, timeout); - auto start = utils::GetTimeNs(); + auto start = util::GetTimeNs(); while (true) { if (state.thread->cancelSync) { state.thread->cancelSync = false; @@ -468,7 +468,7 @@ namespace skyline::kernel::svc { index++; } - if ((utils::GetTimeNs() - start) >= timeout) { + if ((util::GetTimeNs() - start) >= timeout) { state.logger->Debug("svcWaitSynchronization: Wait has timed out"); state.ctx->registers.w0 = constant::status::Timeout; return; @@ -487,7 +487,7 @@ namespace skyline::kernel::svc { void ArbitrateLock(DeviceState &state) { auto address = state.ctx->registers.x1; - if (!utils::WordAligned(address)) { + if (!util::WordAligned(address)) { state.logger->Warn("svcArbitrateLock: 'address' not word aligned: 0x{:X}", address); state.ctx->registers.w0 = constant::status::InvAddress; return; @@ -510,7 +510,7 @@ namespace skyline::kernel::svc { void ArbitrateUnlock(DeviceState &state) { auto address = state.ctx->registers.x0; - if (!utils::WordAligned(address)) { + if (!util::WordAligned(address)) { state.logger->Warn("svcArbitrateUnlock: 'address' not word aligned: 0x{:X}", address); state.ctx->registers.w0 = constant::status::InvAddress; return; @@ -529,7 +529,7 @@ namespace skyline::kernel::svc { void WaitProcessWideKeyAtomic(DeviceState &state) { auto mtxAddress = state.ctx->registers.x0; - if (!utils::WordAligned(mtxAddress)) { + if (!util::WordAligned(mtxAddress)) { state.logger->Warn("svcWaitProcessWideKeyAtomic: mutex address not word aligned: 0x{:X}", mtxAddress); state.ctx->registers.w0 = constant::status::InvAddress; return; diff --git a/app/src/main/cpp/skyline/kernel/types/KPrivateMemory.cpp b/app/src/main/cpp/skyline/kernel/types/KPrivateMemory.cpp index 7ea4a127..81d3b6fb 100644 --- a/app/src/main/cpp/skyline/kernel/types/KPrivateMemory.cpp +++ b/app/src/main/cpp/skyline/kernel/types/KPrivateMemory.cpp @@ -10,7 +10,7 @@ namespace skyline::kernel::type { KPrivateMemory::KPrivateMemory(const DeviceState &state, u64 address, size_t size, memory::Permission permission, const memory::MemoryState memState) : size(size), KMemory(state, KType::KPrivateMemory) { - if (address && !utils::PageAligned(address)) + if (address && !util::PageAligned(address)) throw exception("KPrivateMemory was created with non-page-aligned address: 0x{:X}", address); fd = ASharedMemory_create("KPrivateMemory", size); diff --git a/app/src/main/cpp/skyline/kernel/types/KProcess.cpp b/app/src/main/cpp/skyline/kernel/types/KProcess.cpp index 6db5d7d1..21bc56ac 100644 --- a/app/src/main/cpp/skyline/kernel/types/KProcess.cpp +++ b/app/src/main/cpp/skyline/kernel/types/KProcess.cpp @@ -112,7 +112,7 @@ namespace skyline::kernel::type { auto source = GetHostAddress(offset); if (source) { - memcpy(destination, reinterpret_cast(source), size); + std::memcpy(destination, reinterpret_cast(source), size); return; } } @@ -136,7 +136,7 @@ namespace skyline::kernel::type { auto destination = GetHostAddress(offset); if (destination) { - memcpy(reinterpret_cast(destination), source, size); + std::memcpy(reinterpret_cast(destination), source, size); return; } } @@ -160,7 +160,7 @@ namespace skyline::kernel::type { auto destinationHost = GetHostAddress(destination); if (sourceHost && destinationHost) { - memcpy(reinterpret_cast(destinationHost), reinterpret_cast(sourceHost), size); + std::memcpy(reinterpret_cast(destinationHost), reinterpret_cast(sourceHost), size); } else { if (size <= PAGE_SIZE) { std::vector buffer(size); @@ -282,9 +282,9 @@ namespace skyline::kernel::type { lock.unlock(); bool timedOut{}; - auto start = utils::GetTimeNs(); + auto start = util::GetTimeNs(); while (!status->flag) - if ((utils::GetTimeNs() - start) >= timeout) + if ((util::GetTimeNs() - start) >= timeout) timedOut = true; lock.lock(); diff --git a/app/src/main/cpp/skyline/kernel/types/KSharedMemory.cpp b/app/src/main/cpp/skyline/kernel/types/KSharedMemory.cpp index a9764fee..e70abed3 100644 --- a/app/src/main/cpp/skyline/kernel/types/KSharedMemory.cpp +++ b/app/src/main/cpp/skyline/kernel/types/KSharedMemory.cpp @@ -10,7 +10,7 @@ namespace skyline::kernel::type { KSharedMemory::KSharedMemory(const DeviceState &state, u64 address, size_t size, const memory::Permission permission, memory::MemoryState memState, int mmapFlags) : initialState(memState), KMemory(state, KType::KSharedMemory) { - if (address && !utils::PageAligned(address)) + if (address && !util::PageAligned(address)) throw exception("KSharedMemory was created with non-page-aligned address: 0x{:X}", address); fd = ASharedMemory_create("KSharedMemory", size); @@ -25,7 +25,7 @@ namespace skyline::kernel::type { } u64 KSharedMemory::Map(const u64 address, const u64 size, memory::Permission permission) { - if (address && !utils::PageAligned(address)) + if (address && !util::PageAligned(address)) throw exception("KSharedMemory was mapped to a non-page-aligned address: 0x{:X}", address); Registers fregs{ @@ -129,7 +129,7 @@ namespace skyline::kernel::type { throw exception("An error occurred while creating shared memory: {}", fd); std::vector data(std::min(size, kernel.size)); - memcpy(data.data(), reinterpret_cast(kernel.address), std::min(size, kernel.size)); + std::memcpy(data.data(), reinterpret_cast(kernel.address), std::min(size, kernel.size)); munmap(reinterpret_cast(kernel.address), kernel.size); @@ -137,7 +137,7 @@ namespace skyline::kernel::type { if (address == MAP_FAILED) throw exception("An occurred while mapping shared memory: {}", strerror(errno)); - memcpy(address, data.data(), std::min(size, kernel.size)); + std::memcpy(address, data.data(), std::min(size, kernel.size)); kernel.address = reinterpret_cast(address); kernel.size = size; diff --git a/app/src/main/cpp/skyline/kernel/types/KTransferMemory.cpp b/app/src/main/cpp/skyline/kernel/types/KTransferMemory.cpp index b0a58fa5..66d078d1 100644 --- a/app/src/main/cpp/skyline/kernel/types/KTransferMemory.cpp +++ b/app/src/main/cpp/skyline/kernel/types/KTransferMemory.cpp @@ -8,7 +8,7 @@ namespace skyline::kernel::type { KTransferMemory::KTransferMemory(const DeviceState &state, bool host, u64 address, size_t size, const memory::Permission permission, memory::MemoryState memState) : host(host), size(size), KMemory(state, KType::KTransferMemory) { - if (address && !utils::PageAligned(address)) + if (address && !util::PageAligned(address)) throw exception("KTransferMemory was created with non-page-aligned address: 0x{:X}", address); BlockDescriptor block{ @@ -53,7 +53,7 @@ namespace skyline::kernel::type { } u64 KTransferMemory::Transfer(bool mHost, u64 nAddress, u64 nSize) { - if (nAddress && !utils::PageAligned(nAddress)) + if (nAddress && !util::PageAligned(nAddress)) throw exception("KTransferMemory was transferred to a non-page-aligned address: 0x{:X}", nAddress); nSize = nSize ? nSize : size; @@ -95,7 +95,7 @@ namespace skyline::kernel::type { else if (!mHost && !host) state.process->CopyMemory(address, nAddress, block.size); else if (mHost && host) - memcpy(reinterpret_cast(nAddress), reinterpret_cast(address), block.size); + std::memcpy(reinterpret_cast(nAddress), reinterpret_cast(address), block.size); } if (!block.permission.w) { if (mHost) { diff --git a/app/src/main/cpp/skyline/loader/nro.cpp b/app/src/main/cpp/skyline/loader/nro.cpp index 21c77dcf..b672c5d8 100644 --- a/app/src/main/cpp/skyline/loader/nro.cpp +++ b/app/src/main/cpp/skyline/loader/nro.cpp @@ -9,9 +9,7 @@ namespace skyline::loader { NroLoader::NroLoader(const int romFd) : Loader(romFd) { ReadOffset((u32 *) &header, 0x0, sizeof(NroHeader)); - constexpr auto nroMagic = 0x304F524E; // "NRO0" in reverse, this is written at the start of every NRO file - - if (header.magic != nroMagic) + if (header.magic != util::MakeMagic("NRO0")) throw exception("Invalid NRO magic! 0x{0:X}", header.magic); } @@ -30,7 +28,7 @@ namespace skyline::loader { u64 rodataSize = rodata.size(); u64 dataSize = data.size(); u64 patchSize = patch.size() * sizeof(u32); - u64 padding = utils::AlignUp(textSize + rodataSize + dataSize + header.bssSize + patchSize, PAGE_SIZE) - (textSize + rodataSize + dataSize + header.bssSize + patchSize); + u64 padding = util::AlignUp(textSize + rodataSize + dataSize + header.bssSize + patchSize, PAGE_SIZE) - (textSize + rodataSize + dataSize + header.bssSize + patchSize); process->NewHandle(constant::BaseAddress, textSize, memory::Permission{true, true, true}, memory::states::CodeStatic); // R-X state.logger->Debug("Successfully mapped section .text @ 0x{0:X}, Size = 0x{1:X}", constant::BaseAddress, textSize); diff --git a/app/src/main/cpp/skyline/services/audio/IAudioRenderer/revision_info.h b/app/src/main/cpp/skyline/services/audio/IAudioRenderer/revision_info.h index a30944a3..bce5e57c 100644 --- a/app/src/main/cpp/skyline/services/audio/IAudioRenderer/revision_info.h +++ b/app/src/main/cpp/skyline/services/audio/IAudioRenderer/revision_info.h @@ -8,7 +8,7 @@ namespace skyline { namespace constant { constexpr u32 SupportedRevision = 7; //!< The audren revision our implementation supports - constexpr u32 Rev0Magic = ('R' << 0) | ('E' << 8) | ('V' << 16) | ('0' << 24); //!< The HOS 1.0 revision magic + constexpr u32 Rev0Magic = util::MakeMagic("REV0"); //!< The HOS 1.0 revision magic constexpr u32 RevMagic = Rev0Magic + (SupportedRevision << 24); //!< The revision magic for our supported revision namespace supportTags {