Add Mutexes to Logger, Introduce util::MakeMagic and Refactor IPC

This commit adds mutexes to the logger so they produce a valid log file rather than breaking due to a race condition. It also introduced `util::MakeMagic` so the magic functions are far more clear. A small refactor of IPC was also done which cleared up some of the for loops.
This commit is contained in:
◱ PixelyIon 2020-04-18 02:49:19 +05:30 committed by ◱ PixelyIon
parent 91644255da
commit af98455ede
14 changed files with 383 additions and 366 deletions

View File

@ -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<u8>(level)] << "|" << str << "\n";
logFile.flush();
}
DeviceState::DeviceState(kernel::OS *os, std::shared_ptr<kernel::type::KProcess> &process, std::shared_ptr<JvmManager> jvmManager, std::shared_ptr<Settings> settings, std::shared_ptr<Logger> 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<NCE>(*this));
gpu = std::move(std::make_shared<gpu::GPU>(*this));

View File

@ -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<typename TypeVal, typename TypeMul>
inline TypeVal AlignUp(TypeVal value, TypeMul multiple) {
constexpr inline TypeVal AlignUp(TypeVal value, TypeMul multiple) {
static_assert(std::is_integral<TypeVal>() && std::is_integral<TypeMul>());
multiple--;
return (value + multiple) & ~(multiple);
@ -108,7 +108,7 @@ namespace skyline {
* @return The aligned value
*/
template<typename TypeVal, typename TypeMul>
inline TypeVal AlignDown(TypeVal value, TypeMul multiple) {
constexpr inline TypeVal AlignDown(TypeVal value, TypeMul multiple) {
static_assert(std::is_integral<TypeVal>() && std::is_integral<TypeMul>());
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<typename Type>
constexpr Type MakeMagic(std::string_view string) {
Type object{};
auto offset = 0;
for(auto& character : string) {
object |= static_cast<Type>(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> nce; //!< This holds a reference to the NCE class
std::shared_ptr<gpu::GPU> gpu; //!< This holds a reference to the GPU class
std::shared_ptr<audio::Audio> audio; //!< This holds a reference to the Audio class
std::shared_ptr<JvmManager> jvmManager; //!< This holds a reference to the JvmManager class
std::shared_ptr<JvmManager> jvm; //!< This holds a reference to the JvmManager class
std::shared_ptr<Settings> settings; //!< This holds a reference to the Settings class
std::shared_ptr<Logger> logger; //!< This holds a reference to the Logger class
};

View File

@ -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<kernel::type::KEvent>(state)), bufferEvent(std::make_shared<kernel::type::KEvent>(state)) {
GPU::GPU(const DeviceState &state) : state(state), window(ANativeWindow_fromSurface(state.jvm->GetEnv(), Surface)), vsyncEvent(std::make_shared<kernel::type::KEvent>(state)), bufferEvent(std::make_shared<kernel::type::KEvent>(state)) {
ANativeWindow_acquire(window);
resolution.width = static_cast<u32>(ANativeWindow_getWidth(window));
resolution.height = static_cast<u32>(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<u32>(ANativeWindow_getWidth(window));
resolution.height = static_cast<u32>(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();

View File

@ -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

View File

@ -25,17 +25,17 @@ namespace skyline::kernel::ipc {
if (header->handleDesc) {
handleDesc = reinterpret_cast<HandleDescriptor *>(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<KHandle *>(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<KHandle *>(pointer));
pointer += sizeof(KHandle);
}
}
for (uint index = 0; header->xNo > index; index++) {
for (u8 index = 0; header->xNo > index; index++) {
auto bufX = reinterpret_cast<BufferDescriptorX *>(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<BufferDescriptorABW *>(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<BufferDescriptorABW *>(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<BufferDescriptorABW *>(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<u64>(pointer) - reinterpret_cast<u64>(tls)) - 1U) & ~(ipcPaddingSum - 1U)) + ipcPaddingSum + (reinterpret_cast<u64>(tls) - reinterpret_cast<u64>(pointer))); // Calculate the amount of padding at the front
auto offset = reinterpret_cast<u64>(pointer) - reinterpret_cast<u64>(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<KHandle *>(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<u32>("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<BufferDescriptorC *>(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<u8>(header->cFlag) - 2) > index; index++) { // (cFlag - 2) C descriptors are present
for (u8 index = 0; (static_cast<u8>(header->cFlag) - 2) > index; index++) { // (cFlag - 2) C descriptors are present
auto bufC = reinterpret_cast<BufferDescriptorC *>(pointer);
if (bufC->address) {
outputBuf.emplace_back(bufC);
@ -143,13 +140,10 @@ namespace skyline::kernel::ipc {
auto tls = state.process->GetPointer<u8>(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<CommandHeader *>(pointer);
header->rawSize = static_cast<u32>((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<u32>((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<u8>(moveHandles.size());
pointer += sizeof(HandleDescriptor);
for (unsigned int copyHandle : copyHandles) {
for (auto copyHandle : copyHandles) {
*reinterpret_cast<KHandle *>(pointer) = copyHandle;
pointer += sizeof(KHandle);
}
for (unsigned int moveHandle : moveHandles) {
for (auto moveHandle : moveHandles) {
*reinterpret_cast<KHandle *>(pointer) = moveHandle;
pointer += sizeof(KHandle);
}
}
u64 padding = ((((reinterpret_cast<u64>(pointer) - reinterpret_cast<u64>(tls)) - 1U) & ~(ipcPaddingSum - 1U)) + ipcPaddingSum + (reinterpret_cast<u64>(tls) - reinterpret_cast<u64>(pointer))); // Calculate the amount of padding at the front
auto offset = reinterpret_cast<u64>(pointer) - reinterpret_cast<u64>(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<PayloadHeader *>(pointer);
payload->magic = sfcoMagic;
payload->magic = util::MakeMagic<u32>("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) {

View File

@ -6,325 +6,332 @@
#include <array>
#include <common.h>
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<u32>(address & 0x7FFFFFFF80000000);
address32_35 = static_cast<u16>(address & 0x78000000);
address36_38 = static_cast<u16>(address & 0x7000000);
counter0_5 = static_cast<u16>(address & 0x7E00);
counter9_11 = static_cast<u16>(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<u64>(address0_31) | static_cast<u64>(address32_35) << 32 | static_cast<u64>(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<u16>(counter0_5) | static_cast<u16>(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<u32>(address & 0x7FFFFFFF80000000);
address32_35 = static_cast<u8>(address & 0x78000000);
address36_38 = static_cast<u8>(address & 0x7000000);
size0_31 = static_cast<u32>(size & 0x7FFFFFFF80000000);
size32_35 = static_cast<u8>(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<u64>(address0_31) | static_cast<u64>(address32_35) << 32 | static_cast<u64>(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<u64>(size0_31) | static_cast<u64>(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<KHandle> 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<KHandle> moveHandles; //!< A vector of handles that should be moved from the server to the client process rather than copied
std::vector<KHandle> domainObjects; //!< A vector of all input domain objects
std::vector<InputBuffer> inputBuf; //!< This is a vector of input buffers
std::vector<OutputBuffer> 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<typename ValueType>
inline ValueType &Pop() {
ValueType &value = *reinterpret_cast<ValueType *>(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<typename ValueType>
inline void Skip() {
payloadOffset += sizeof(ValueType);
}
};
/**
* @brief This class encapsulates an IPC Response (https://switchbrew.org/wiki/IPC_Marshalling)
*/
class IpcResponse {
private:
std::vector<u8> 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<KHandle> copyHandles; //!< A vector of handles to copy
std::vector<KHandle> moveHandles; //!< A vector of handles to move
std::vector<KHandle> 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<typename ValueType>
inline void Push(const ValueType &value) {
argVec.reserve(argVec.size() + sizeof(ValueType));
auto item = reinterpret_cast<const u8 *>(&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<u32>(address & 0x7FFFFFFF80000000);
address32_35 = static_cast<u16>(address & 0x78000000);
address36_38 = static_cast<u16>(address & 0x7000000);
counter0_5 = static_cast<u16>(address & 0x7E00);
counter9_11 = static_cast<u16>(address & 0x38);
}
}
/**
* @return The address of the buffer
*/
inline u64 Address() const {
return static_cast<u64>(address0_31) | static_cast<u64>(address32_35) << 32 | static_cast<u64>(address36_38) << 36;
}
/**
* @return The buffer counter
*/
inline u16 Counter() const {
return static_cast<u16>(counter0_5) | static_cast<u16>(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<u32>(address & 0x7FFFFFFF80000000);
address32_35 = static_cast<u8>(address & 0x78000000);
address36_38 = static_cast<u8>(address & 0x7000000);
size0_31 = static_cast<u32>(size & 0x7FFFFFFF80000000);
size32_35 = static_cast<u8>(size & 0x78000000);
}
/**
* @return The address of the buffer
*/
inline u64 Address() const {
return static_cast<u64>(address0_31) | static_cast<u64>(address32_35) << 32 | static_cast<u64>(address36_38) << 36;
}
/**
* @return The size of the buffer
*/
inline u64 Size() const {
return static_cast<u64>(size0_31) | static_cast<u64>(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<KHandle> 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<KHandle> moveHandles; //!< A vector of handles that should be moved from the server to the client process rather than copied
std::vector<KHandle> domainObjects; //!< A vector of all input domain objects
std::vector<InputBuffer> inputBuf; //!< This is a vector of input buffers
std::vector<OutputBuffer> 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<typename ValueType>
inline ValueType &Pop() {
ValueType &value = *reinterpret_cast<ValueType *>(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<typename ValueType>
inline void Skip() {
payloadOffset += sizeof(ValueType);
}
};
/**
* @brief This class encapsulates an IPC Response (https://switchbrew.org/wiki/IPC_Marshalling)
*/
class IpcResponse {
private:
std::vector<u8> 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<KHandle> copyHandles; //!< A vector of handles to copy
std::vector<KHandle> moveHandles; //!< A vector of handles to move
std::vector<KHandle> 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<typename ValueType>
inline void Push(const ValueType &value) {
argVec.reserve(argVec.size() + sizeof(ValueType));
auto item = reinterpret_cast<const u8 *>(&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();
};
}
}

View File

@ -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;

View File

@ -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<type::KSharedMemory>(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;

View File

@ -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);

View File

@ -112,7 +112,7 @@ namespace skyline::kernel::type {
auto source = GetHostAddress(offset);
if (source) {
memcpy(destination, reinterpret_cast<void *>(source), size);
std::memcpy(destination, reinterpret_cast<void *>(source), size);
return;
}
}
@ -136,7 +136,7 @@ namespace skyline::kernel::type {
auto destination = GetHostAddress(offset);
if (destination) {
memcpy(reinterpret_cast<void *>(destination), source, size);
std::memcpy(reinterpret_cast<void *>(destination), source, size);
return;
}
}
@ -160,7 +160,7 @@ namespace skyline::kernel::type {
auto destinationHost = GetHostAddress(destination);
if (sourceHost && destinationHost) {
memcpy(reinterpret_cast<void *>(destinationHost), reinterpret_cast<const void *>(sourceHost), size);
std::memcpy(reinterpret_cast<void *>(destinationHost), reinterpret_cast<const void *>(sourceHost), size);
} else {
if (size <= PAGE_SIZE) {
std::vector<u8> 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();

View File

@ -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<u8> data(std::min(size, kernel.size));
memcpy(data.data(), reinterpret_cast<const void *>(kernel.address), std::min(size, kernel.size));
std::memcpy(data.data(), reinterpret_cast<const void *>(kernel.address), std::min(size, kernel.size));
munmap(reinterpret_cast<void *>(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<u64>(address);
kernel.size = size;

View File

@ -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<void *>(nAddress), reinterpret_cast<void *>(address), block.size);
std::memcpy(reinterpret_cast<void *>(nAddress), reinterpret_cast<void *>(address), block.size);
}
if (!block.permission.w) {
if (mHost) {

View File

@ -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<u32>("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<kernel::type::KPrivateMemory>(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);

View File

@ -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<u32>("REV0"); //!< The HOS 1.0 revision magic
constexpr u32 RevMagic = Rev0Magic + (SupportedRevision << 24); //!< The revision magic for our supported revision
namespace supportTags {