skyline/app/src/main/cpp/skyline/kernel/types/KTransferMemory.cpp
TheASVigilante 1513e5f6df Implement svcSetMemoryPermission
Used by Minecraft legends, this should allow it to proceed further.
2023-05-05 18:16:17 +02:00

65 lines
2.6 KiB
C++

// SPDX-License-Identifier: MPL-2.0
// Copyright © 2023 Skyline Team and Contributors (https://github.com/skyline-emu/)
#include "KTransferMemory.h"
#include "KProcess.h"
namespace skyline::kernel::type {
KTransferMemory::KTransferMemory(const DeviceState &state, size_t size)
: KMemory(state, KType::KTransferMemory, size) {}
u8 *KTransferMemory::Map(span<u8> map, memory::Permission permission) {
std::memcpy(host.data(), map.data(), map.size());
u8 *result{KMemory::Map(map, permission)};
auto oldChunk{state.process->memory.GetChunk(map.data()).value()};
originalMapping = oldChunk.second;
if (!originalMapping.state.transferMemoryAllowed) [[unlikely]] {
Logger::Warn("Tried to map transfer memory with incompatible state at: 0x{:X} (0x{:X} bytes)", map.data(), map.size());
return nullptr;
} else {
state.process->memory.MapTransferMemory(guest, permission);
state.process->memory.SetLockOnChunks(guest, true);
return result;
}
}
void KTransferMemory::Unmap(span<u8> map) {
KMemory::Unmap(map);
guest = span<u8>{};
switch (originalMapping.state.type) {
case memory::MemoryType::CodeMutable:
state.process->memory.MapMutableCodeMemory(map);
break;
case memory::MemoryType::Heap:
state.process->memory.MapHeapMemory(map);
break;
default:
Logger::Warn("Unmapping KTransferMemory with incompatible state: (0x{:X})", originalMapping.state.value);
}
std::memcpy(map.data(), host.data(), map.size());
}
KTransferMemory::~KTransferMemory() {
if (state.process && guest.valid()) {
if (mmap(guest.data(), guest.size(), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED | MAP_ANONYMOUS | MAP_POPULATE, -1, 0) == MAP_FAILED) [[unlikely]]
Logger::Warn("An error occurred while unmapping transfer memory in guest: {}", strerror(errno));
switch (originalMapping.state.type) {
case memory::MemoryType::CodeMutable:
state.process->memory.MapMutableCodeMemory(guest);
break;
case memory::MemoryType::Heap:
state.process->memory.MapHeapMemory(guest);
break;
default:
Logger::Warn("Unmapping KTransferMemory with incompatible state: (0x{:X})", originalMapping.state.value);
}
std::memcpy(guest.data(), host.data(), guest.size());
}
}
}