1
0
Fork 0
mirror of https://github.com/Atmosphere-NX/Atmosphere.git synced 2024-12-19 08:52:25 +00:00

kern: Implement QueryIoMapping logic for < 8.0.0

This commit is contained in:
Michael Scire 2020-07-13 19:02:00 -07:00 committed by SciresM
parent ff022115ca
commit d9e9fbe3c2

View file

@ -32,7 +32,7 @@ namespace ams::kern::svc {
/* Check whether the address is aligned. */ /* Check whether the address is aligned. */
const bool aligned = util::IsAligned(phys_addr, PageSize); const bool aligned = util::IsAligned(phys_addr, PageSize);
if (aligned) { auto QueryIoMappingFromPageTable = [&] ALWAYS_INLINE_LAMBDA (uint64_t phys_addr, size_t size) -> Result {
/* The size must be non-zero. */ /* The size must be non-zero. */
R_UNLESS(size > 0, svc::ResultInvalidSize()); R_UNLESS(size > 0, svc::ResultInvalidSize());
@ -44,33 +44,48 @@ namespace ams::kern::svc {
/* Use the size as the found size. */ /* Use the size as the found size. */
found_size = size; found_size = size;
return ResultSuccess();
};
if (aligned) {
/* Query the input. */
R_TRY(QueryIoMappingFromPageTable(phys_addr, size));
} else { } else {
/* TODO: Older kernel ABI compatibility. */ if (kern::GetTargetFirmware() < TargetFirmware_8_0_0 && phys_addr >= PageSize) {
/* Newer kernel only allows unaligned addresses when they're special enum members. */ /* Query the aligned-down page. */
R_UNLESS(phys_addr < PageSize, svc::ResultNotFound()); const size_t offset = phys_addr & (PageSize - 1);
R_TRY(QueryIoMappingFromPageTable(phys_addr - offset, size + offset));
/* Try to find the memory region. */ /* Adjust the output address. */
const KMemoryRegion *region; found_address += offset;
switch (static_cast<ams::svc::MemoryRegionType>(phys_addr)) { } else {
case ams::svc::MemoryRegionType_KernelTraceBuffer: /* Newer kernel only allows unaligned addresses when they're special enum members. */
region = KMemoryLayout::TryGetKernelTraceBufferRegion(); R_UNLESS(phys_addr < PageSize, svc::ResultNotFound());
break;
case ams::svc::MemoryRegionType_OnMemoryBootImage: /* Try to find the memory region. */
region = KMemoryLayout::TryGetOnMemoryBootImageRegion(); const KMemoryRegion *region;
break; switch (static_cast<ams::svc::MemoryRegionType>(phys_addr)) {
case ams::svc::MemoryRegionType_DTB: case ams::svc::MemoryRegionType_KernelTraceBuffer:
region = KMemoryLayout::TryGetDTBRegion(); region = KMemoryLayout::TryGetKernelTraceBufferRegion();
break; break;
default: case ams::svc::MemoryRegionType_OnMemoryBootImage:
region = nullptr; region = KMemoryLayout::TryGetOnMemoryBootImageRegion();
break; break;
case ams::svc::MemoryRegionType_DTB:
region = KMemoryLayout::TryGetDTBRegion();
break;
default:
region = nullptr;
break;
}
/* Ensure that we found the region. */
R_UNLESS(region != nullptr, svc::ResultNotFound());
R_TRY(pt.QueryStaticMapping(std::addressof(found_address), region->GetAddress(), region->GetSize()));
found_size = region->GetSize();
} }
/* Ensure that we found the region. */
R_UNLESS(region != nullptr, svc::ResultNotFound());
R_TRY(pt.QueryStaticMapping(std::addressof(found_address), region->GetAddress(), region->GetSize()));
found_size = region->GetSize();
} }
/* We succeeded. */ /* We succeeded. */