mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-29 14:55:28 +03:00
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:
parent
91644255da
commit
af98455ede
@ -24,7 +24,7 @@ namespace skyline {
|
|||||||
void GroupMutex::lock(Group group) {
|
void GroupMutex::lock(Group group) {
|
||||||
auto none = Group::None;
|
auto none = Group::None;
|
||||||
constexpr u64 timeout = 100; // The timeout in ns
|
constexpr u64 timeout = 100; // The timeout in ns
|
||||||
auto end = utils::GetTimeNs() + timeout;
|
auto end = util::GetTimeNs() + timeout;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (next == group) {
|
if (next == group) {
|
||||||
@ -41,7 +41,7 @@ namespace skyline {
|
|||||||
} else {
|
} else {
|
||||||
flag.compare_exchange_weak(none, group);
|
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);
|
std::lock_guard lock(mtx);
|
||||||
|
|
||||||
if (flag == group) {
|
if (flag == group) {
|
||||||
@ -127,13 +127,14 @@ namespace skyline {
|
|||||||
|
|
||||||
Logger::~Logger() {
|
Logger::~Logger() {
|
||||||
WriteHeader("Logging ended");
|
WriteHeader("Logging ended");
|
||||||
|
logFile.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logger::WriteHeader(const std::string &str) {
|
void Logger::WriteHeader(const std::string &str) {
|
||||||
syslog(LOG_ALERT, "%s", str.c_str());
|
syslog(LOG_ALERT, "%s", str.c_str());
|
||||||
|
|
||||||
|
std::lock_guard guard(mtx);
|
||||||
logFile << "0|" << str << "\n";
|
logFile << "0|" << str << "\n";
|
||||||
logFile.flush();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logger::Write(const LogLevel level, std::string str) {
|
void Logger::Write(const LogLevel level, std::string str) {
|
||||||
@ -143,12 +144,12 @@ namespace skyline {
|
|||||||
if (character == '\n')
|
if (character == '\n')
|
||||||
character = '\\';
|
character = '\\';
|
||||||
|
|
||||||
|
std::lock_guard guard(mtx);
|
||||||
logFile << "1|" << levelStr[static_cast<u8>(level)] << "|" << str << "\n";
|
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)
|
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
|
// 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));
|
nce = std::move(std::make_shared<NCE>(*this));
|
||||||
gpu = std::move(std::make_shared<gpu::GPU>(*this));
|
gpu = std::move(std::make_shared<gpu::GPU>(*this));
|
||||||
|
@ -68,7 +68,7 @@ namespace skyline {
|
|||||||
NSP, //!< The NSP format from "nspwn" exploit: https://switchbrew.org/wiki/Switch_System_Flaws
|
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
|
* @brief Returns the current time in nanoseconds
|
||||||
* @return The current time in nanoseconds
|
* @return The current time in nanoseconds
|
||||||
@ -93,7 +93,7 @@ namespace skyline {
|
|||||||
* @return The aligned value
|
* @return The aligned value
|
||||||
*/
|
*/
|
||||||
template<typename TypeVal, typename TypeMul>
|
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>());
|
static_assert(std::is_integral<TypeVal>() && std::is_integral<TypeMul>());
|
||||||
multiple--;
|
multiple--;
|
||||||
return (value + multiple) & ~(multiple);
|
return (value + multiple) & ~(multiple);
|
||||||
@ -108,7 +108,7 @@ namespace skyline {
|
|||||||
* @return The aligned value
|
* @return The aligned value
|
||||||
*/
|
*/
|
||||||
template<typename TypeVal, typename TypeMul>
|
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>());
|
static_assert(std::is_integral<TypeVal>() && std::is_integral<TypeMul>());
|
||||||
return value & ~(multiple - 1);
|
return value & ~(multiple - 1);
|
||||||
}
|
}
|
||||||
@ -117,7 +117,7 @@ namespace skyline {
|
|||||||
* @param address The address to check for alignment
|
* @param address The address to check for alignment
|
||||||
* @return If the address is page aligned
|
* @return If the address is page aligned
|
||||||
*/
|
*/
|
||||||
inline bool PageAligned(u64 address) {
|
constexpr inline bool PageAligned(u64 address) {
|
||||||
return !(address & (PAGE_SIZE - 1U));
|
return !(address & (PAGE_SIZE - 1U));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,9 +125,26 @@ namespace skyline {
|
|||||||
* @param address The address to check for alignment
|
* @param address The address to check for alignment
|
||||||
* @return If the address is word aligned
|
* @return If the address is word aligned
|
||||||
*/
|
*/
|
||||||
inline bool WordAligned(u64 address) {
|
constexpr inline bool WordAligned(u64 address) {
|
||||||
return !(address & 3U);
|
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
|
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
|
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
|
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:
|
public:
|
||||||
enum class LogLevel { Error, Warn, Info, Debug }; //!< The level of a particular log
|
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<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<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<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<Settings> settings; //!< This holds a reference to the Settings class
|
||||||
std::shared_ptr<Logger> logger; //!< This holds a reference to the Logger class
|
std::shared_ptr<Logger> logger; //!< This holds a reference to the Logger class
|
||||||
};
|
};
|
||||||
|
@ -10,7 +10,7 @@ extern bool Halt;
|
|||||||
extern jobject Surface;
|
extern jobject Surface;
|
||||||
|
|
||||||
namespace skyline::gpu {
|
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);
|
ANativeWindow_acquire(window);
|
||||||
resolution.width = static_cast<u32>(ANativeWindow_getWidth(window));
|
resolution.width = static_cast<u32>(ANativeWindow_getWidth(window));
|
||||||
resolution.height = static_cast<u32>(ANativeWindow_getHeight(window));
|
resolution.height = static_cast<u32>(ANativeWindow_getHeight(window));
|
||||||
@ -25,7 +25,7 @@ namespace skyline::gpu {
|
|||||||
if (surfaceUpdate) {
|
if (surfaceUpdate) {
|
||||||
if (Surface == nullptr)
|
if (Surface == nullptr)
|
||||||
return;
|
return;
|
||||||
window = ANativeWindow_fromSurface(state.jvmManager->GetEnv(), Surface);
|
window = ANativeWindow_fromSurface(state.jvm->GetEnv(), Surface);
|
||||||
ANativeWindow_acquire(window);
|
ANativeWindow_acquire(window);
|
||||||
resolution.width = static_cast<u32>(ANativeWindow_getWidth(window));
|
resolution.width = static_cast<u32>(ANativeWindow_getWidth(window));
|
||||||
resolution.height = static_cast<u32>(ANativeWindow_getHeight(window));
|
resolution.height = static_cast<u32>(ANativeWindow_getHeight(window));
|
||||||
@ -51,7 +51,7 @@ namespace skyline::gpu {
|
|||||||
ARect rect;
|
ARect rect;
|
||||||
|
|
||||||
ANativeWindow_lock(window, &windowBuffer, &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);
|
ANativeWindow_unlockAndPost(window);
|
||||||
|
|
||||||
vsyncEvent->Signal();
|
vsyncEvent->Signal();
|
||||||
|
@ -26,8 +26,8 @@ namespace skyline::gpu {
|
|||||||
constexpr auto gobHeight = 8; // The height of a GOB in lines
|
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 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 surfaceHeightRobs = util::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 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 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 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
|
auto gobYOffset = robWidthBytes * gobHeight; // The offset of the next Y-axis GOB from the current one in linear space
|
||||||
|
@ -25,17 +25,17 @@ namespace skyline::kernel::ipc {
|
|||||||
if (header->handleDesc) {
|
if (header->handleDesc) {
|
||||||
handleDesc = reinterpret_cast<HandleDescriptor *>(pointer);
|
handleDesc = reinterpret_cast<HandleDescriptor *>(pointer);
|
||||||
pointer += sizeof(HandleDescriptor) + (handleDesc->sendPid ? sizeof(u64) : 0);
|
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));
|
copyHandles.push_back(*reinterpret_cast<KHandle *>(pointer));
|
||||||
pointer += sizeof(KHandle);
|
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));
|
moveHandles.push_back(*reinterpret_cast<KHandle *>(pointer));
|
||||||
pointer += sizeof(KHandle);
|
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);
|
auto bufX = reinterpret_cast<BufferDescriptorX *>(pointer);
|
||||||
if (bufX->Address()) {
|
if (bufX->Address()) {
|
||||||
inputBuf.emplace_back(bufX);
|
inputBuf.emplace_back(bufX);
|
||||||
@ -44,7 +44,7 @@ namespace skyline::kernel::ipc {
|
|||||||
pointer += sizeof(BufferDescriptorX);
|
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);
|
auto bufA = reinterpret_cast<BufferDescriptorABW *>(pointer);
|
||||||
if (bufA->Address()) {
|
if (bufA->Address()) {
|
||||||
inputBuf.emplace_back(bufA);
|
inputBuf.emplace_back(bufA);
|
||||||
@ -53,7 +53,7 @@ namespace skyline::kernel::ipc {
|
|||||||
pointer += sizeof(BufferDescriptorABW);
|
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);
|
auto bufB = reinterpret_cast<BufferDescriptorABW *>(pointer);
|
||||||
if (bufB->Address()) {
|
if (bufB->Address()) {
|
||||||
outputBuf.emplace_back(bufB);
|
outputBuf.emplace_back(bufB);
|
||||||
@ -62,7 +62,7 @@ namespace skyline::kernel::ipc {
|
|||||||
pointer += sizeof(BufferDescriptorABW);
|
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);
|
auto bufW = reinterpret_cast<BufferDescriptorABW *>(pointer);
|
||||||
if (bufW->Address()) {
|
if (bufW->Address()) {
|
||||||
inputBuf.emplace_back(bufW, IpcBufferType::W);
|
inputBuf.emplace_back(bufW, IpcBufferType::W);
|
||||||
@ -72,9 +72,8 @@ namespace skyline::kernel::ipc {
|
|||||||
pointer += sizeof(BufferDescriptorABW);
|
pointer += sizeof(BufferDescriptorABW);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr auto ipcPaddingSum = 0x10; // The sum of the padding surrounding the data payload
|
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
|
||||||
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
|
|
||||||
pointer += padding;
|
pointer += padding;
|
||||||
|
|
||||||
if (isDomain && (header->type == CommandType::Request)) {
|
if (isDomain && (header->type == CommandType::Request)) {
|
||||||
@ -88,7 +87,7 @@ namespace skyline::kernel::ipc {
|
|||||||
cmdArgSz = domain->payloadSz - sizeof(PayloadHeader);
|
cmdArgSz = domain->payloadSz - sizeof(PayloadHeader);
|
||||||
pointer += domain->payloadSz;
|
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));
|
domainObjects.push_back(*reinterpret_cast<KHandle *>(pointer));
|
||||||
pointer += sizeof(KHandle);
|
pointer += sizeof(KHandle);
|
||||||
}
|
}
|
||||||
@ -97,18 +96,16 @@ namespace skyline::kernel::ipc {
|
|||||||
pointer += sizeof(PayloadHeader);
|
pointer += sizeof(PayloadHeader);
|
||||||
|
|
||||||
cmdArg = pointer;
|
cmdArg = pointer;
|
||||||
cmdArgSz = (header->rawSize * sizeof(u32)) - (ipcPaddingSum + sizeof(PayloadHeader));
|
cmdArgSz = (header->rawSize * sizeof(u32)) - (constant::IpcPaddingSum + sizeof(PayloadHeader));
|
||||||
pointer += cmdArgSz;
|
pointer += cmdArgSz;
|
||||||
}
|
}
|
||||||
|
|
||||||
payloadOffset = cmdArg;
|
payloadOffset = cmdArg;
|
||||||
|
|
||||||
constexpr auto sfciMagic = 0x49434653; //!< SFCI in reverse, present in received IPC messages
|
if (payload->magic != util::MakeMagic<u32>("SFCI") && header->type != CommandType::Control) // SFCI is the magic in received IPC messages
|
||||||
|
|
||||||
if (payload->magic != sfciMagic && header->type != CommandType::Control)
|
|
||||||
state.logger->Debug("Unexpected Magic in PayloadHeader: 0x{:X}", u32(payload->magic));
|
state.logger->Debug("Unexpected Magic in PayloadHeader: 0x{:X}", u32(payload->magic));
|
||||||
|
|
||||||
pointer += ipcPaddingSum - padding;
|
pointer += constant::IpcPaddingSum - padding;
|
||||||
|
|
||||||
if (header->cFlag == BufferCFlag::SingleDescriptor) {
|
if (header->cFlag == BufferCFlag::SingleDescriptor) {
|
||||||
auto bufC = reinterpret_cast<BufferDescriptorC *>(pointer);
|
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));
|
state.logger->Debug("Buf C: AD: 0x{:X} SZ: 0x{:X}", u64(bufC->address), u16(bufC->size));
|
||||||
}
|
}
|
||||||
} else if (header->cFlag > BufferCFlag::SingleDescriptor) {
|
} 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);
|
auto bufC = reinterpret_cast<BufferDescriptorC *>(pointer);
|
||||||
if (bufC->address) {
|
if (bufC->address) {
|
||||||
outputBuf.emplace_back(bufC);
|
outputBuf.emplace_back(bufC);
|
||||||
@ -143,13 +140,10 @@ namespace skyline::kernel::ipc {
|
|||||||
auto tls = state.process->GetPointer<u8>(state.thread->tls);
|
auto tls = state.process->GetPointer<u8>(state.thread->tls);
|
||||||
u8 *pointer = tls;
|
u8 *pointer = tls;
|
||||||
|
|
||||||
constexpr auto tlsIpcSize = 0x100; // The size of the IPC command buffer in a TLS slot
|
memset(tls, 0, constant::TlsIpcSize);
|
||||||
memset(tls, 0, tlsIpcSize);
|
|
||||||
|
|
||||||
constexpr auto ipcPaddingSum = 0x10; // The sum of the padding surrounding the data payload
|
|
||||||
|
|
||||||
auto header = reinterpret_cast<CommandHeader *>(pointer);
|
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());
|
header->handleDesc = (!copyHandles.empty() || !moveHandles.empty());
|
||||||
pointer += sizeof(CommandHeader);
|
pointer += sizeof(CommandHeader);
|
||||||
|
|
||||||
@ -159,18 +153,19 @@ namespace skyline::kernel::ipc {
|
|||||||
handleDesc->moveCount = static_cast<u8>(moveHandles.size());
|
handleDesc->moveCount = static_cast<u8>(moveHandles.size());
|
||||||
pointer += sizeof(HandleDescriptor);
|
pointer += sizeof(HandleDescriptor);
|
||||||
|
|
||||||
for (unsigned int copyHandle : copyHandles) {
|
for (auto copyHandle : copyHandles) {
|
||||||
*reinterpret_cast<KHandle *>(pointer) = copyHandle;
|
*reinterpret_cast<KHandle *>(pointer) = copyHandle;
|
||||||
pointer += sizeof(KHandle);
|
pointer += sizeof(KHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (unsigned int moveHandle : moveHandles) {
|
for (auto moveHandle : moveHandles) {
|
||||||
*reinterpret_cast<KHandle *>(pointer) = moveHandle;
|
*reinterpret_cast<KHandle *>(pointer) = moveHandle;
|
||||||
pointer += sizeof(KHandle);
|
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;
|
pointer += padding;
|
||||||
|
|
||||||
if (isDomain) {
|
if (isDomain) {
|
||||||
@ -179,16 +174,14 @@ namespace skyline::kernel::ipc {
|
|||||||
pointer += sizeof(DomainHeaderResponse);
|
pointer += sizeof(DomainHeaderResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr auto sfcoMagic = 0x4F434653; // SFCO in reverse, IPC Response Magic
|
|
||||||
|
|
||||||
auto payload = reinterpret_cast<PayloadHeader *>(pointer);
|
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->version = 1;
|
||||||
payload->value = errorCode;
|
payload->value = errorCode;
|
||||||
pointer += sizeof(PayloadHeader);
|
pointer += sizeof(PayloadHeader);
|
||||||
|
|
||||||
if (!argVec.empty())
|
if (!argVec.empty())
|
||||||
memcpy(pointer, argVec.data(), argVec.size());
|
std::memcpy(pointer, argVec.data(), argVec.size());
|
||||||
pointer += argVec.size();
|
pointer += argVec.size();
|
||||||
|
|
||||||
if (isDomain) {
|
if (isDomain) {
|
||||||
|
@ -6,7 +6,13 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
|
|
||||||
namespace skyline::kernel::ipc {
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace kernel::ipc {
|
||||||
/**
|
/**
|
||||||
* @brief This reflects the value in CommandStruct::type
|
* @brief This reflects the value in CommandStruct::type
|
||||||
*/
|
*/
|
||||||
@ -327,4 +333,5 @@ namespace skyline::kernel::ipc {
|
|||||||
*/
|
*/
|
||||||
void WriteResponse();
|
void WriteResponse();
|
||||||
};
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,8 +144,8 @@ namespace skyline::kernel {
|
|||||||
case memory::AddressSpaceType::AddressSpace39Bit: {
|
case memory::AddressSpaceType::AddressSpace39Bit: {
|
||||||
base.address = constant::BaseAddress;
|
base.address = constant::BaseAddress;
|
||||||
base.size = 0x7FF8000000;
|
base.size = 0x7FF8000000;
|
||||||
code.address = utils::AlignDown(address, 0x200000);
|
code.address = util::AlignDown(address, 0x200000);
|
||||||
code.size = utils::AlignUp(address + size, 0x200000) - code.address;
|
code.size = util::AlignUp(address + size, 0x200000) - code.address;
|
||||||
alias.address = code.address + code.size;
|
alias.address = code.address + code.size;
|
||||||
alias.size = 0x1000000000;
|
alias.size = 0x1000000000;
|
||||||
heap.address = alias.address + alias.size;
|
heap.address = alias.address + alias.size;
|
||||||
|
@ -28,14 +28,14 @@ namespace skyline::kernel::svc {
|
|||||||
|
|
||||||
void SetMemoryAttribute(DeviceState &state) {
|
void SetMemoryAttribute(DeviceState &state) {
|
||||||
auto address = state.ctx->registers.x0;
|
auto address = state.ctx->registers.x0;
|
||||||
if (!utils::PageAligned(address)) {
|
if (!util::PageAligned(address)) {
|
||||||
state.ctx->registers.w0 = constant::status::InvAddress;
|
state.ctx->registers.w0 = constant::status::InvAddress;
|
||||||
state.logger->Warn("svcSetMemoryAttribute: 'address' not page aligned: 0x{:X}", address);
|
state.logger->Warn("svcSetMemoryAttribute: 'address' not page aligned: 0x{:X}", address);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto size = state.ctx->registers.x1;
|
auto size = state.ctx->registers.x1;
|
||||||
if (!utils::PageAligned(size)) {
|
if (!util::PageAligned(size)) {
|
||||||
state.ctx->registers.w0 = constant::status::InvSize;
|
state.ctx->registers.w0 = constant::status::InvSize;
|
||||||
state.logger->Warn("svcSetMemoryAttribute: 'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
state.logger->Warn("svcSetMemoryAttribute: 'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
||||||
return;
|
return;
|
||||||
@ -77,13 +77,13 @@ namespace skyline::kernel::svc {
|
|||||||
auto source = state.ctx->registers.x1;
|
auto source = state.ctx->registers.x1;
|
||||||
auto size = state.ctx->registers.x2;
|
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.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);
|
state.logger->Warn("svcMapMemory: Addresses not page aligned: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes)", source, destination, size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!utils::PageAligned(size)) {
|
if (!util::PageAligned(size)) {
|
||||||
state.ctx->registers.w0 = constant::status::InvSize;
|
state.ctx->registers.w0 = constant::status::InvSize;
|
||||||
state.logger->Warn("svcMapMemory: 'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
state.logger->Warn("svcMapMemory: 'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
||||||
return;
|
return;
|
||||||
@ -126,13 +126,13 @@ namespace skyline::kernel::svc {
|
|||||||
auto destination = state.ctx->registers.x1;
|
auto destination = state.ctx->registers.x1;
|
||||||
auto size = state.ctx->registers.x2;
|
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.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);
|
state.logger->Warn("svcUnmapMemory: Addresses not page aligned: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes)", source, destination, size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!utils::PageAligned(size)) {
|
if (!util::PageAligned(size)) {
|
||||||
state.ctx->registers.w0 = constant::status::InvSize;
|
state.ctx->registers.w0 = constant::status::InvSize;
|
||||||
state.logger->Warn("svcUnmapMemory: 'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
state.logger->Warn("svcUnmapMemory: 'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
||||||
return;
|
return;
|
||||||
@ -307,14 +307,14 @@ namespace skyline::kernel::svc {
|
|||||||
auto object = state.process->GetHandle<type::KSharedMemory>(state.ctx->registers.w0);
|
auto object = state.process->GetHandle<type::KSharedMemory>(state.ctx->registers.w0);
|
||||||
u64 address = state.ctx->registers.x1;
|
u64 address = state.ctx->registers.x1;
|
||||||
|
|
||||||
if (!utils::PageAligned(address)) {
|
if (!util::PageAligned(address)) {
|
||||||
state.ctx->registers.w0 = constant::status::InvAddress;
|
state.ctx->registers.w0 = constant::status::InvAddress;
|
||||||
state.logger->Warn("svcMapSharedMemory: 'address' not page aligned: 0x{:X}", address);
|
state.logger->Warn("svcMapSharedMemory: 'address' not page aligned: 0x{:X}", address);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto size = state.ctx->registers.x2;
|
auto size = state.ctx->registers.x2;
|
||||||
if (!utils::PageAligned(size)) {
|
if (!util::PageAligned(size)) {
|
||||||
state.ctx->registers.w0 = constant::status::InvSize;
|
state.ctx->registers.w0 = constant::status::InvSize;
|
||||||
state.logger->Warn("svcMapSharedMemory: 'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
state.logger->Warn("svcMapSharedMemory: 'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
||||||
return;
|
return;
|
||||||
@ -341,14 +341,14 @@ namespace skyline::kernel::svc {
|
|||||||
|
|
||||||
void CreateTransferMemory(DeviceState &state) {
|
void CreateTransferMemory(DeviceState &state) {
|
||||||
u64 address = state.ctx->registers.x1;
|
u64 address = state.ctx->registers.x1;
|
||||||
if (!utils::PageAligned(address)) {
|
if (!util::PageAligned(address)) {
|
||||||
state.ctx->registers.w0 = constant::status::InvAddress;
|
state.ctx->registers.w0 = constant::status::InvAddress;
|
||||||
state.logger->Warn("svcCreateTransferMemory: 'address' not page aligned: 0x{:X}", address);
|
state.logger->Warn("svcCreateTransferMemory: 'address' not page aligned: 0x{:X}", address);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 size = state.ctx->registers.x2;
|
u64 size = state.ctx->registers.x2;
|
||||||
if (!utils::PageAligned(size)) {
|
if (!util::PageAligned(size)) {
|
||||||
state.ctx->registers.w0 = constant::status::InvSize;
|
state.ctx->registers.w0 = constant::status::InvSize;
|
||||||
state.logger->Warn("svcCreateTransferMemory: 'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
state.logger->Warn("svcCreateTransferMemory: 'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
||||||
return;
|
return;
|
||||||
@ -449,7 +449,7 @@ namespace skyline::kernel::svc {
|
|||||||
auto timeout = state.ctx->registers.x3;
|
auto timeout = state.ctx->registers.x3;
|
||||||
state.logger->Debug("svcWaitSynchronization: Waiting on handles:\n{}Timeout: 0x{:X} ns", handleStr, timeout);
|
state.logger->Debug("svcWaitSynchronization: Waiting on handles:\n{}Timeout: 0x{:X} ns", handleStr, timeout);
|
||||||
|
|
||||||
auto start = utils::GetTimeNs();
|
auto start = util::GetTimeNs();
|
||||||
while (true) {
|
while (true) {
|
||||||
if (state.thread->cancelSync) {
|
if (state.thread->cancelSync) {
|
||||||
state.thread->cancelSync = false;
|
state.thread->cancelSync = false;
|
||||||
@ -468,7 +468,7 @@ namespace skyline::kernel::svc {
|
|||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((utils::GetTimeNs() - start) >= timeout) {
|
if ((util::GetTimeNs() - start) >= timeout) {
|
||||||
state.logger->Debug("svcWaitSynchronization: Wait has timed out");
|
state.logger->Debug("svcWaitSynchronization: Wait has timed out");
|
||||||
state.ctx->registers.w0 = constant::status::Timeout;
|
state.ctx->registers.w0 = constant::status::Timeout;
|
||||||
return;
|
return;
|
||||||
@ -487,7 +487,7 @@ namespace skyline::kernel::svc {
|
|||||||
|
|
||||||
void ArbitrateLock(DeviceState &state) {
|
void ArbitrateLock(DeviceState &state) {
|
||||||
auto address = state.ctx->registers.x1;
|
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.logger->Warn("svcArbitrateLock: 'address' not word aligned: 0x{:X}", address);
|
||||||
state.ctx->registers.w0 = constant::status::InvAddress;
|
state.ctx->registers.w0 = constant::status::InvAddress;
|
||||||
return;
|
return;
|
||||||
@ -510,7 +510,7 @@ namespace skyline::kernel::svc {
|
|||||||
|
|
||||||
void ArbitrateUnlock(DeviceState &state) {
|
void ArbitrateUnlock(DeviceState &state) {
|
||||||
auto address = state.ctx->registers.x0;
|
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.logger->Warn("svcArbitrateUnlock: 'address' not word aligned: 0x{:X}", address);
|
||||||
state.ctx->registers.w0 = constant::status::InvAddress;
|
state.ctx->registers.w0 = constant::status::InvAddress;
|
||||||
return;
|
return;
|
||||||
@ -529,7 +529,7 @@ namespace skyline::kernel::svc {
|
|||||||
|
|
||||||
void WaitProcessWideKeyAtomic(DeviceState &state) {
|
void WaitProcessWideKeyAtomic(DeviceState &state) {
|
||||||
auto mtxAddress = state.ctx->registers.x0;
|
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.logger->Warn("svcWaitProcessWideKeyAtomic: mutex address not word aligned: 0x{:X}", mtxAddress);
|
||||||
state.ctx->registers.w0 = constant::status::InvAddress;
|
state.ctx->registers.w0 = constant::status::InvAddress;
|
||||||
return;
|
return;
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
namespace skyline::kernel::type {
|
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) {
|
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);
|
throw exception("KPrivateMemory was created with non-page-aligned address: 0x{:X}", address);
|
||||||
|
|
||||||
fd = ASharedMemory_create("KPrivateMemory", size);
|
fd = ASharedMemory_create("KPrivateMemory", size);
|
||||||
|
@ -112,7 +112,7 @@ namespace skyline::kernel::type {
|
|||||||
auto source = GetHostAddress(offset);
|
auto source = GetHostAddress(offset);
|
||||||
|
|
||||||
if (source) {
|
if (source) {
|
||||||
memcpy(destination, reinterpret_cast<void *>(source), size);
|
std::memcpy(destination, reinterpret_cast<void *>(source), size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -136,7 +136,7 @@ namespace skyline::kernel::type {
|
|||||||
auto destination = GetHostAddress(offset);
|
auto destination = GetHostAddress(offset);
|
||||||
|
|
||||||
if (destination) {
|
if (destination) {
|
||||||
memcpy(reinterpret_cast<void *>(destination), source, size);
|
std::memcpy(reinterpret_cast<void *>(destination), source, size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -160,7 +160,7 @@ namespace skyline::kernel::type {
|
|||||||
auto destinationHost = GetHostAddress(destination);
|
auto destinationHost = GetHostAddress(destination);
|
||||||
|
|
||||||
if (sourceHost && destinationHost) {
|
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 {
|
} else {
|
||||||
if (size <= PAGE_SIZE) {
|
if (size <= PAGE_SIZE) {
|
||||||
std::vector<u8> buffer(size);
|
std::vector<u8> buffer(size);
|
||||||
@ -282,9 +282,9 @@ namespace skyline::kernel::type {
|
|||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
|
||||||
bool timedOut{};
|
bool timedOut{};
|
||||||
auto start = utils::GetTimeNs();
|
auto start = util::GetTimeNs();
|
||||||
while (!status->flag)
|
while (!status->flag)
|
||||||
if ((utils::GetTimeNs() - start) >= timeout)
|
if ((util::GetTimeNs() - start) >= timeout)
|
||||||
timedOut = true;
|
timedOut = true;
|
||||||
|
|
||||||
lock.lock();
|
lock.lock();
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
namespace skyline::kernel::type {
|
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) {
|
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);
|
throw exception("KSharedMemory was created with non-page-aligned address: 0x{:X}", address);
|
||||||
|
|
||||||
fd = ASharedMemory_create("KSharedMemory", size);
|
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) {
|
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);
|
throw exception("KSharedMemory was mapped to a non-page-aligned address: 0x{:X}", address);
|
||||||
|
|
||||||
Registers fregs{
|
Registers fregs{
|
||||||
@ -129,7 +129,7 @@ namespace skyline::kernel::type {
|
|||||||
throw exception("An error occurred while creating shared memory: {}", fd);
|
throw exception("An error occurred while creating shared memory: {}", fd);
|
||||||
|
|
||||||
std::vector<u8> data(std::min(size, kernel.size));
|
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);
|
munmap(reinterpret_cast<void *>(kernel.address), kernel.size);
|
||||||
|
|
||||||
@ -137,7 +137,7 @@ namespace skyline::kernel::type {
|
|||||||
if (address == MAP_FAILED)
|
if (address == MAP_FAILED)
|
||||||
throw exception("An occurred while mapping shared memory: {}", strerror(errno));
|
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.address = reinterpret_cast<u64>(address);
|
||||||
kernel.size = size;
|
kernel.size = size;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
namespace skyline::kernel::type {
|
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) {
|
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);
|
throw exception("KTransferMemory was created with non-page-aligned address: 0x{:X}", address);
|
||||||
|
|
||||||
BlockDescriptor block{
|
BlockDescriptor block{
|
||||||
@ -53,7 +53,7 @@ namespace skyline::kernel::type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
u64 KTransferMemory::Transfer(bool mHost, u64 nAddress, u64 nSize) {
|
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);
|
throw exception("KTransferMemory was transferred to a non-page-aligned address: 0x{:X}", nAddress);
|
||||||
|
|
||||||
nSize = nSize ? nSize : size;
|
nSize = nSize ? nSize : size;
|
||||||
@ -95,7 +95,7 @@ namespace skyline::kernel::type {
|
|||||||
else if (!mHost && !host)
|
else if (!mHost && !host)
|
||||||
state.process->CopyMemory(address, nAddress, block.size);
|
state.process->CopyMemory(address, nAddress, block.size);
|
||||||
else if (mHost && host)
|
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 (!block.permission.w) {
|
||||||
if (mHost) {
|
if (mHost) {
|
||||||
|
@ -9,9 +9,7 @@ namespace skyline::loader {
|
|||||||
NroLoader::NroLoader(const int romFd) : Loader(romFd) {
|
NroLoader::NroLoader(const int romFd) : Loader(romFd) {
|
||||||
ReadOffset((u32 *) &header, 0x0, sizeof(NroHeader));
|
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 != util::MakeMagic<u32>("NRO0"))
|
||||||
|
|
||||||
if (header.magic != nroMagic)
|
|
||||||
throw exception("Invalid NRO magic! 0x{0:X}", header.magic);
|
throw exception("Invalid NRO magic! 0x{0:X}", header.magic);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,7 +28,7 @@ namespace skyline::loader {
|
|||||||
u64 rodataSize = rodata.size();
|
u64 rodataSize = rodata.size();
|
||||||
u64 dataSize = data.size();
|
u64 dataSize = data.size();
|
||||||
u64 patchSize = patch.size() * sizeof(u32);
|
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
|
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);
|
state.logger->Debug("Successfully mapped section .text @ 0x{0:X}, Size = 0x{1:X}", constant::BaseAddress, textSize);
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
namespace skyline {
|
namespace skyline {
|
||||||
namespace constant {
|
namespace constant {
|
||||||
constexpr u32 SupportedRevision = 7; //!< The audren revision our implementation supports
|
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
|
constexpr u32 RevMagic = Rev0Magic + (SupportedRevision << 24); //!< The revision magic for our supported revision
|
||||||
|
|
||||||
namespace supportTags {
|
namespace supportTags {
|
||||||
|
Loading…
Reference in New Issue
Block a user