mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-28 20:40:24 +00:00
dd: implement DeviceAddressSpaceType api
This commit is contained in:
parent
708f5bf1fb
commit
4d1c4f1677
15 changed files with 626 additions and 52 deletions
|
@ -16,5 +16,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "dd/dd_io_mappings.hpp"
|
||||
#include "dd/dd_process_handle.hpp"
|
||||
#include <stratosphere/dd/dd_types.hpp>
|
||||
#include <stratosphere/dd/dd_device_address_space.hpp>
|
||||
#include <stratosphere/dd/dd_io_mappings.hpp>
|
||||
#include <stratosphere/dd/dd_process_handle.hpp>
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
|
||||
#include <stratosphere/dd/dd_device_address_space_common.hpp>
|
||||
#include <stratosphere/dd/dd_device_address_space_types.hpp>
|
||||
#include <stratosphere/dd/dd_device_address_space_api.hpp>
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <stratosphere/dd/dd_types.hpp>
|
||||
#include <stratosphere/dd/dd_device_address_space_common.hpp>
|
||||
#include <stratosphere/dd/dd_device_address_space_types.hpp>
|
||||
|
||||
namespace ams::dd {
|
||||
|
||||
Result CreateDeviceAddressSpace(DeviceAddressSpaceType *das, u64 address, u64 size);
|
||||
Result CreateDeviceAddressSpace(DeviceAddressSpaceType *das, u64 size);
|
||||
void DestroyDeviceAddressSpace(DeviceAddressSpaceType *das);
|
||||
|
||||
void AttachDeviceAddressSpaceHandle(DeviceAddressSpaceType *das, Handle handle, bool managed);
|
||||
|
||||
Handle GetDeviceAddressSpaceHandle(DeviceAddressSpaceType *das);
|
||||
|
||||
Result MapDeviceAddressSpaceAligned(DeviceAddressSpaceType *das, ProcessHandle process_handle, u64 process_address, size_t size, DeviceVirtualAddress device_address, MemoryPermission device_perm);
|
||||
Result MapDeviceAddressSpaceNotAligned(DeviceAddressSpaceType *das, ProcessHandle process_handle, u64 process_address, size_t size, DeviceVirtualAddress device_address, MemoryPermission device_perm);
|
||||
void UnmapDeviceAddressSpace(DeviceAddressSpaceType *das, ProcessHandle process_handle, u64 process_address, size_t size, DeviceVirtualAddress device_address);
|
||||
|
||||
void InitializeDeviceAddressSpaceMapInfo(DeviceAddressSpaceMapInfo *info, DeviceAddressSpaceType *das, ProcessHandle process_handle, u64 process_address, size_t size, DeviceVirtualAddress device_address, MemoryPermission device_perm);
|
||||
|
||||
Result MapNextDeviceAddressSpaceRegion(size_t *out_mapped_size, DeviceAddressSpaceMapInfo *info);
|
||||
void UnmapDeviceAddressSpaceRegion(DeviceAddressSpaceMapInfo *info);
|
||||
|
||||
u64 GetMappedProcessAddress(DeviceAddressSpaceMapInfo *info);
|
||||
DeviceVirtualAddress GetMappedDeviceVirtualAddress(DeviceAddressSpaceMapInfo *info);
|
||||
size_t GetMappedSize(DeviceAddressSpaceMapInfo *info);
|
||||
|
||||
Result AttachDeviceAddressSpace(DeviceAddressSpaceType *das, DeviceName device_name);
|
||||
void DetachDeviceAddressSpace(DeviceAddressSpaceType *das, DeviceName device_name);
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <stratosphere/dd/dd_types.hpp>
|
||||
|
||||
namespace ams::dd {
|
||||
|
||||
using DeviceName = ::ams::svc::DeviceName;
|
||||
|
||||
constexpr inline u64 DeviceAddressSpaceMemoryRegionAlignment = 4_KB;
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <stratosphere/dd/dd_types.hpp>
|
||||
|
||||
namespace ams::dd {
|
||||
|
||||
using DeviceVirtualAddress = u64;
|
||||
|
||||
using DeviceAddressSpaceHandle = ::Handle;
|
||||
|
||||
struct DeviceAddressSpaceType {
|
||||
enum State {
|
||||
State_NotInitialized = 0,
|
||||
State_Initialized = 1,
|
||||
};
|
||||
DeviceAddressSpaceHandle device_handle;
|
||||
u8 state;
|
||||
bool is_handle_managed;
|
||||
};
|
||||
static_assert(std::is_trivial<DeviceAddressSpaceType>::value);
|
||||
|
||||
struct DeviceAddressSpaceMapInfo {
|
||||
size_t last_mapped_size;
|
||||
size_t size;
|
||||
u64 process_address;
|
||||
DeviceVirtualAddress device_start_address;
|
||||
DeviceVirtualAddress device_end_address;
|
||||
ProcessHandle process_handle;
|
||||
MemoryPermission device_permission;
|
||||
DeviceAddressSpaceType *device_address_space;
|
||||
};
|
||||
static_assert(std::is_trivial<DeviceAddressSpaceMapInfo>::value);
|
||||
|
||||
}
|
|
@ -19,10 +19,6 @@
|
|||
|
||||
namespace ams::dd {
|
||||
|
||||
u32 ReadRegister(dd::PhysicalAddress phys_addr);
|
||||
void WriteRegister(dd::PhysicalAddress phys_addr, u32 value);
|
||||
u32 ReadWriteRegister(dd::PhysicalAddress phys_addr, u32 value, u32 mask);
|
||||
|
||||
/* Convenience Helper. */
|
||||
inline uintptr_t GetIoMapping(dd::PhysicalAddress phys_addr, size_t size) {
|
||||
const uintptr_t io_mapping = dd::QueryIoMapping(phys_addr, size);
|
||||
|
|
|
@ -13,12 +13,12 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <stratosphere/dd/dd_types.hpp>
|
||||
|
||||
namespace ams::dd {
|
||||
|
||||
::Handle GetCurrentProcessHandle();
|
||||
ProcessHandle GetCurrentProcessHandle();
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
#include <stratosphere/dd/dd_types.hpp>
|
||||
|
||||
namespace ams::dd {
|
||||
|
||||
using ProcessHandle = ::Handle;
|
||||
|
||||
enum MemoryPermission {
|
||||
MemoryPermission_None = 0,
|
||||
MemoryPermission_ReadOnly = (1u << 0),
|
||||
MemoryPermission_WriteOnly = (1u << 1),
|
||||
|
||||
MemoryPermission_ReadWrite = MemoryPermission_ReadOnly | MemoryPermission_WriteOnly,
|
||||
};
|
||||
|
||||
}
|
190
libraries/libstratosphere/source/dd/dd_device_address_space.cpp
Normal file
190
libraries/libstratosphere/source/dd/dd_device_address_space.cpp
Normal file
|
@ -0,0 +1,190 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "impl/dd_device_address_space_impl.hpp"
|
||||
|
||||
namespace ams::dd {
|
||||
|
||||
Result CreateDeviceAddressSpace(DeviceAddressSpaceType *das, u64 address, u64 size) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(util::IsAligned(address, os::MemoryPageSize));
|
||||
AMS_ASSERT(util::IsAligned(size, os::MemoryPageSize));
|
||||
AMS_ASSERT(size > 0);
|
||||
|
||||
/* Ensure we leave in a consistent state. */
|
||||
auto state_guard = SCOPE_GUARD { das->state = DeviceAddressSpaceType::State_NotInitialized; };
|
||||
|
||||
/* Create the address space. */
|
||||
DeviceAddressSpaceHandle handle;
|
||||
R_TRY(impl::DeviceAddressSpaceImpl::Create(std::addressof(handle), address, size));
|
||||
|
||||
/* Set the values in the das. */
|
||||
das->device_handle = handle;
|
||||
das->is_handle_managed = true;
|
||||
das->state = DeviceAddressSpaceType::State_Initialized;
|
||||
|
||||
/* We succeeded. */
|
||||
state_guard.Cancel();
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result CreateDeviceAddressSpace(DeviceAddressSpaceType *das, u64 size) {
|
||||
return CreateDeviceAddressSpace(das, 0, size);
|
||||
}
|
||||
|
||||
void DestroyDeviceAddressSpace(DeviceAddressSpaceType *das) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(das->state == DeviceAddressSpaceType::State_Initialized);
|
||||
|
||||
/* Destroy the handle. */
|
||||
if (das->is_handle_managed) {
|
||||
impl::DeviceAddressSpaceImpl::Close(das->device_handle);
|
||||
}
|
||||
|
||||
das->device_handle = 0;
|
||||
das->is_handle_managed = false;
|
||||
das->state = DeviceAddressSpaceType::State_NotInitialized;
|
||||
}
|
||||
|
||||
void AttachDeviceAddressSpaceHandle(DeviceAddressSpaceType *das, Handle handle, bool managed) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(handle != svc::InvalidHandle);
|
||||
|
||||
das->device_handle = handle;
|
||||
das->is_handle_managed = managed;
|
||||
das->state = DeviceAddressSpaceType::State_Initialized;
|
||||
}
|
||||
|
||||
Handle GetDeviceAddressSpaceHandle(DeviceAddressSpaceType *das) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(das->state == DeviceAddressSpaceType::State_Initialized);
|
||||
|
||||
return das->device_handle;
|
||||
}
|
||||
|
||||
Result MapDeviceAddressSpaceAligned(DeviceAddressSpaceType *das, ProcessHandle process_handle, u64 process_address, size_t size, DeviceVirtualAddress device_address, MemoryPermission device_perm) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(das->state == DeviceAddressSpaceType::State_Initialized);
|
||||
AMS_ASSERT(util::IsAligned(process_address, os::MemoryPageSize));
|
||||
AMS_ASSERT(util::IsAligned(device_address, os::MemoryPageSize));
|
||||
AMS_ASSERT(util::IsAligned(size, os::MemoryPageSize));
|
||||
AMS_ASSERT(process_address + size > process_address);
|
||||
AMS_ASSERT(device_address + size > device_address);
|
||||
AMS_ASSERT(size > 0);
|
||||
AMS_ASSERT((process_address & (4_MB - 1)) == (device_address & (4_MB - 1)));
|
||||
|
||||
return impl::DeviceAddressSpaceImpl::MapAligned(das->device_handle, process_handle, process_address, size, device_address, device_perm);
|
||||
}
|
||||
|
||||
Result MapDeviceAddressSpaceNotAligned(DeviceAddressSpaceType *das, ProcessHandle process_handle, u64 process_address, size_t size, DeviceVirtualAddress device_address, MemoryPermission device_perm) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(das->state == DeviceAddressSpaceType::State_Initialized);
|
||||
AMS_ASSERT(util::IsAligned(process_address, os::MemoryPageSize));
|
||||
AMS_ASSERT(util::IsAligned(device_address, os::MemoryPageSize));
|
||||
AMS_ASSERT(util::IsAligned(size, os::MemoryPageSize));
|
||||
AMS_ASSERT(process_address + size > process_address);
|
||||
AMS_ASSERT(device_address + size > device_address);
|
||||
AMS_ASSERT(size > 0);
|
||||
|
||||
return impl::DeviceAddressSpaceImpl::MapNotAligned(das->device_handle, process_handle, process_address, size, device_address, device_perm);
|
||||
}
|
||||
|
||||
void UnmapDeviceAddressSpace(DeviceAddressSpaceType *das, ProcessHandle process_handle, u64 process_address, size_t size, DeviceVirtualAddress device_address) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(das->state == DeviceAddressSpaceType::State_Initialized);
|
||||
AMS_ASSERT(util::IsAligned(process_address, os::MemoryPageSize));
|
||||
AMS_ASSERT(util::IsAligned(device_address, os::MemoryPageSize));
|
||||
AMS_ASSERT(util::IsAligned(size, os::MemoryPageSize));
|
||||
AMS_ASSERT(process_address + size > process_address);
|
||||
AMS_ASSERT(device_address + size > device_address);
|
||||
AMS_ASSERT(size > 0);
|
||||
|
||||
return impl::DeviceAddressSpaceImpl::Unmap(das->device_handle, process_handle, process_address, size, device_address);
|
||||
}
|
||||
|
||||
void InitializeDeviceAddressSpaceMapInfo(DeviceAddressSpaceMapInfo *info, DeviceAddressSpaceType *das, ProcessHandle process_handle, u64 process_address, size_t size, DeviceVirtualAddress device_address, MemoryPermission device_perm) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(das->state == DeviceAddressSpaceType::State_Initialized);
|
||||
AMS_ASSERT(util::IsAligned(process_address, os::MemoryPageSize));
|
||||
AMS_ASSERT(util::IsAligned(device_address, os::MemoryPageSize));
|
||||
AMS_ASSERT(util::IsAligned(size, os::MemoryPageSize));
|
||||
AMS_ASSERT(process_address + size > process_address);
|
||||
AMS_ASSERT(device_address + size > device_address);
|
||||
AMS_ASSERT(size > 0);
|
||||
|
||||
info->last_mapped_size = 0;
|
||||
info->process_address = process_address;
|
||||
info->size = size;
|
||||
info->device_start_address = device_address;
|
||||
info->device_end_address = device_address + size;
|
||||
info->process_handle = process_handle;
|
||||
info->device_permission = device_perm;
|
||||
info->device_address_space = das;
|
||||
}
|
||||
|
||||
Result MapNextDeviceAddressSpaceRegion(size_t *out_mapped_size, DeviceAddressSpaceMapInfo *info) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(info->last_mapped_size == 0);
|
||||
|
||||
size_t mapped_size = 0;
|
||||
if (info->device_start_address < info->device_end_address) {
|
||||
R_TRY(impl::DeviceAddressSpaceImpl::MapPartially(std::addressof(mapped_size), info->device_address_space->device_handle, info->process_handle, info->process_address, info->size, info->device_start_address, info->device_permission));
|
||||
}
|
||||
|
||||
info->last_mapped_size = mapped_size;
|
||||
*out_mapped_size = mapped_size;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
void UnmapDeviceAddressSpaceRegion(DeviceAddressSpaceMapInfo *info) {
|
||||
/* Check pre-conditions. */
|
||||
const size_t last_mapped_size = info->last_mapped_size;
|
||||
AMS_ASSERT(last_mapped_size > 0);
|
||||
|
||||
impl::DeviceAddressSpaceImpl::Unmap(info->device_address_space->device_handle, info->process_handle, info->process_address, last_mapped_size, info->device_start_address);
|
||||
|
||||
info->last_mapped_size = 0;
|
||||
info->process_address += last_mapped_size;
|
||||
info->device_start_address += last_mapped_size;
|
||||
}
|
||||
|
||||
u64 GetMappedProcessAddress(DeviceAddressSpaceMapInfo *info) {
|
||||
return info->process_address;
|
||||
}
|
||||
|
||||
DeviceVirtualAddress GetMappedDeviceVirtualAddress(DeviceAddressSpaceMapInfo *info) {
|
||||
return info->device_start_address;
|
||||
}
|
||||
|
||||
size_t GetMappedSize(DeviceAddressSpaceMapInfo *info) {
|
||||
return info->last_mapped_size;
|
||||
}
|
||||
|
||||
Result AttachDeviceAddressSpace(DeviceAddressSpaceType *das, DeviceName device_name) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(das->state == DeviceAddressSpaceType::State_Initialized);
|
||||
|
||||
return impl::DeviceAddressSpaceImpl::Attach(das, device_name);
|
||||
}
|
||||
|
||||
void DetachDeviceAddressSpace(DeviceAddressSpaceType *das, DeviceName device_name) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(das->state == DeviceAddressSpaceType::State_Initialized);
|
||||
|
||||
return impl::DeviceAddressSpaceImpl::Detach(das, device_name);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
#if defined(ATMOSPHERE_OS_HORIZON)
|
||||
#include "dd_device_address_space_impl.os.horizon.hpp"
|
||||
#else
|
||||
#error "Unknown os for dd::DeviceAddressSpaceImpl"
|
||||
#endif
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "dd_device_address_space_impl.os.horizon.hpp"
|
||||
|
||||
namespace ams::dd::impl {
|
||||
|
||||
static_assert(static_cast<int>(dd::MemoryPermission_None) == static_cast<int>(svc::MemoryPermission_None));
|
||||
static_assert(static_cast<int>(dd::MemoryPermission_ReadOnly) == static_cast<int>(svc::MemoryPermission_Read));
|
||||
static_assert(static_cast<int>(dd::MemoryPermission_WriteOnly) == static_cast<int>(svc::MemoryPermission_Write));
|
||||
static_assert(static_cast<int>(dd::MemoryPermission_ReadWrite) == static_cast<int>(svc::MemoryPermission_ReadWrite));
|
||||
|
||||
Result DeviceAddressSpaceImplByHorizon::Create(DeviceAddressSpaceHandle *out, u64 address, u64 size) {
|
||||
/* Create the space. */
|
||||
svc::Handle handle;
|
||||
R_TRY_CATCH(svc::CreateDeviceAddressSpace(std::addressof(handle), address, size)) {
|
||||
R_CONVERT(svc::ResultOutOfMemory, dd::ResultOutOfMemory())
|
||||
R_CONVERT(svc::ResultOutOfResource, dd::ResultOutOfResource())
|
||||
} R_END_TRY_CATCH_WITH_ABORT_UNLESS;
|
||||
|
||||
*out = static_cast<DeviceAddressSpaceHandle>(handle);
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
void DeviceAddressSpaceImplByHorizon::Close(DeviceAddressSpaceHandle handle) {
|
||||
const auto svc_handle = svc::Handle(handle);
|
||||
if (svc_handle == svc::PseudoHandle::CurrentThread || svc_handle == svc::PseudoHandle::CurrentProcess) {
|
||||
return;
|
||||
}
|
||||
|
||||
R_ABORT_UNLESS(svc::CloseHandle(svc_handle));
|
||||
}
|
||||
|
||||
Result DeviceAddressSpaceImplByHorizon::MapAligned(DeviceAddressSpaceHandle handle, ProcessHandle process_handle, u64 process_address, size_t process_size, DeviceVirtualAddress device_address, dd::MemoryPermission device_perm) {
|
||||
/* Check alignment. */
|
||||
AMS_ABORT_UNLESS((process_address & (4_MB - 1)) == (device_address & (4_MB - 1)));
|
||||
|
||||
R_TRY_CATCH(svc::MapDeviceAddressSpaceAligned(svc::Handle(handle), svc::Handle(process_handle), process_address, process_size, device_address, static_cast<svc::MemoryPermission>(device_perm))) {
|
||||
R_CONVERT(svc::ResultInvalidHandle, dd::ResultInvalidHandle())
|
||||
R_CONVERT(svc::ResultOutOfMemory, dd::ResultOutOfMemory())
|
||||
R_CONVERT(svc::ResultOutOfResource, dd::ResultOutOfResource())
|
||||
R_CONVERT(svc::ResultInvalidCurrentMemory, dd::ResultInvalidMemoryState())
|
||||
} R_END_TRY_CATCH_WITH_ABORT_UNLESS;
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result DeviceAddressSpaceImplByHorizon::MapNotAligned(DeviceAddressSpaceHandle handle, ProcessHandle process_handle, u64 process_address, size_t process_size, DeviceVirtualAddress device_address, dd::MemoryPermission device_perm) {
|
||||
R_TRY_CATCH(svc::MapDeviceAddressSpaceByForce(svc::Handle(handle), svc::Handle(process_handle), process_address, process_size, device_address, static_cast<svc::MemoryPermission>(device_perm))) {
|
||||
R_CONVERT(svc::ResultInvalidHandle, dd::ResultInvalidHandle())
|
||||
R_CONVERT(svc::ResultOutOfMemory, dd::ResultOutOfMemory())
|
||||
R_CONVERT(svc::ResultOutOfResource, dd::ResultOutOfResource())
|
||||
R_CONVERT(svc::ResultInvalidCurrentMemory, dd::ResultInvalidMemoryState())
|
||||
} R_END_TRY_CATCH_WITH_ABORT_UNLESS;
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result DeviceAddressSpaceImplByHorizon::MapPartially(size_t *out_mapped_size, DeviceAddressSpaceHandle handle, ProcessHandle process_handle, u64 process_address, size_t process_size, DeviceVirtualAddress device_address, dd::MemoryPermission device_perm) {
|
||||
ams::svc::Size mapped_size = 0;
|
||||
R_TRY_CATCH(svc::MapDeviceAddressSpace(std::addressof(mapped_size), svc::Handle(handle), svc::Handle(process_handle), process_address, process_size, device_address, static_cast<svc::MemoryPermission>(device_perm))) {
|
||||
R_CONVERT(svc::ResultInvalidHandle, dd::ResultInvalidHandle())
|
||||
R_CONVERT(svc::ResultOutOfMemory, dd::ResultOutOfMemory())
|
||||
R_CONVERT(svc::ResultOutOfResource, dd::ResultOutOfResource())
|
||||
R_CONVERT(svc::ResultInvalidCurrentMemory, dd::ResultInvalidMemoryState())
|
||||
} R_END_TRY_CATCH_WITH_ABORT_UNLESS;
|
||||
|
||||
*out_mapped_size = mapped_size;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
void DeviceAddressSpaceImplByHorizon::Unmap(DeviceAddressSpaceHandle handle, ProcessHandle process_handle, u64 process_address, size_t process_size, DeviceVirtualAddress device_address) {
|
||||
R_ABORT_UNLESS(svc::UnmapDeviceAddressSpace(svc::Handle(handle), svc::Handle(process_handle), process_address, process_size, device_address));
|
||||
}
|
||||
|
||||
Result DeviceAddressSpaceImplByHorizon::Attach(DeviceAddressSpaceType *das, DeviceName device_name) {
|
||||
R_TRY_CATCH(svc::AttachDeviceAddressSpace(static_cast<svc::DeviceName>(device_name), svc::Handle(das->device_handle))) {
|
||||
R_CONVERT(svc::ResultOutOfMemory, dd::ResultOutOfMemory())
|
||||
} R_END_TRY_CATCH_WITH_ABORT_UNLESS;
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
void DeviceAddressSpaceImplByHorizon::Detach(DeviceAddressSpaceType *das, DeviceName device_name) {
|
||||
R_ABORT_UNLESS(svc::DetachDeviceAddressSpace(static_cast<svc::DeviceName>(device_name), svc::Handle(das->device_handle)));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
namespace ams::dd::impl {
|
||||
|
||||
class DeviceAddressSpaceImplByHorizon {
|
||||
public:
|
||||
static Result Create(DeviceAddressSpaceHandle *out, u64 address, u64 size);
|
||||
static void Close(DeviceAddressSpaceHandle handle);
|
||||
|
||||
static Result MapAligned(DeviceAddressSpaceHandle handle, ProcessHandle process_handle, u64 process_address, size_t process_size, DeviceVirtualAddress device_address, dd::MemoryPermission device_perm);
|
||||
static Result MapNotAligned(DeviceAddressSpaceHandle handle, ProcessHandle process_handle, u64 process_address, size_t process_size, DeviceVirtualAddress device_address, dd::MemoryPermission device_perm);
|
||||
static Result MapPartially(size_t *out_mapped_size, DeviceAddressSpaceHandle handle, ProcessHandle process_handle, u64 process_address, size_t process_size, DeviceVirtualAddress device_address, dd::MemoryPermission device_perm);
|
||||
static void Unmap(DeviceAddressSpaceHandle handle, ProcessHandle process_handle, u64 process_address, size_t process_size, DeviceVirtualAddress device_address);
|
||||
|
||||
static Result Attach(DeviceAddressSpaceType *das, DeviceName device_name);
|
||||
static void Detach(DeviceAddressSpaceType *das, DeviceName device_name);
|
||||
};
|
||||
|
||||
using DeviceAddressSpaceImpl = DeviceAddressSpaceImplByHorizon;
|
||||
|
||||
}
|
|
@ -26,6 +26,7 @@
|
|||
#include <vapours/results/cal_results.hpp>
|
||||
#include <vapours/results/capsrv_results.hpp>
|
||||
#include <vapours/results/creport_results.hpp>
|
||||
#include <vapours/results/dd_results.hpp>
|
||||
#include <vapours/results/ddsf_results.hpp>
|
||||
#include <vapours/results/debug_results.hpp>
|
||||
#include <vapours/results/dmnt_results.hpp>
|
||||
|
|
35
libraries/libvapours/include/vapours/results/dd_results.hpp
Normal file
35
libraries/libvapours/include/vapours/results/dd_results.hpp
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/results/results_common.hpp>
|
||||
|
||||
namespace ams::dd {
|
||||
|
||||
R_DEFINE_NAMESPACE_RESULT_MODULE(6);
|
||||
|
||||
R_DEFINE_ERROR_RESULT(EndOfQuery, 1);
|
||||
R_DEFINE_ERROR_RESULT(InvalidCurrentMemory, 2);
|
||||
R_DEFINE_ERROR_RESULT(NotSingleRegion, 3);
|
||||
R_DEFINE_ERROR_RESULT(InvalidMemoryState, 4);
|
||||
R_DEFINE_ERROR_RESULT(OutOfMemory, 5);
|
||||
R_DEFINE_ERROR_RESULT(OutOfResource, 6);
|
||||
R_DEFINE_ERROR_RESULT(NotSupported, 7);
|
||||
R_DEFINE_ERROR_RESULT(InvalidHandle, 8);
|
||||
|
||||
R_DEFINE_ERROR_RESULT(InternalError, 1023);
|
||||
|
||||
}
|
|
@ -31,21 +31,21 @@ namespace ams::boot {
|
|||
namespace {
|
||||
|
||||
/* Helpful defines. */
|
||||
constexpr size_t DeviceAddressSpaceAlignSize = 0x400000;
|
||||
constexpr size_t DeviceAddressSpaceAlignMask = DeviceAddressSpaceAlignSize - 1;
|
||||
constexpr uintptr_t FrameBufferPaddr = DisplayConfigFrameBufferAddress;
|
||||
constexpr size_t FrameBufferWidth = 768;
|
||||
constexpr size_t DeviceAddressSpaceAlignSize = 4_MB;
|
||||
|
||||
constexpr dd::DeviceVirtualAddress FrameBufferDeviceAddress = DisplayConfigFrameBufferAddress;
|
||||
|
||||
constexpr size_t FrameBufferWidth = 768;
|
||||
constexpr size_t FrameBufferHeight = 1280;
|
||||
constexpr size_t FrameBufferSize = FrameBufferHeight * FrameBufferWidth * sizeof(u32);
|
||||
constexpr size_t FrameBufferSize = FrameBufferHeight * FrameBufferWidth * sizeof(u32);
|
||||
|
||||
constexpr inline dd::PhysicalAddress PmcBase = 0x7000E400;
|
||||
|
||||
constexpr uintptr_t Disp1Base = 0x54200000ul;
|
||||
constexpr uintptr_t DsiBase = 0x54300000ul;
|
||||
constexpr uintptr_t ClkRstBase = 0x60006000ul;
|
||||
constexpr uintptr_t GpioBase = 0x6000D000ul;
|
||||
constexpr uintptr_t ApbMiscBase = 0x70000000ul;
|
||||
constexpr uintptr_t MipiCalBase = 0x700E3000ul;
|
||||
constexpr dd::PhysicalAddress PmcBase = 0x7000E400ul;
|
||||
constexpr dd::PhysicalAddress Disp1Base = 0x54200000ul;
|
||||
constexpr dd::PhysicalAddress DsiBase = 0x54300000ul;
|
||||
constexpr dd::PhysicalAddress ClkRstBase = 0x60006000ul;
|
||||
constexpr dd::PhysicalAddress GpioBase = 0x6000D000ul;
|
||||
constexpr dd::PhysicalAddress ApbMiscBase = 0x70000000ul;
|
||||
constexpr dd::PhysicalAddress MipiCalBase = 0x700E3000ul;
|
||||
|
||||
constexpr size_t Disp1Size = 3 * os::MemoryPageSize;
|
||||
constexpr size_t DsiSize = os::MemoryPageSize;
|
||||
|
@ -54,9 +54,9 @@ namespace ams::boot {
|
|||
constexpr size_t ApbMiscSize = os::MemoryPageSize;
|
||||
constexpr size_t MipiCalSize = os::MemoryPageSize;
|
||||
|
||||
constexpr s32 DsiWaitForCommandMilliSecondsMax = 250;
|
||||
constexpr s32 DsiWaitForCommandCompletionMilliSeconds = 5;
|
||||
constexpr s32 DsiWaitForHostControlMilliSecondsMax = 150;
|
||||
constexpr int DsiWaitForCommandMilliSecondsMax = 250;
|
||||
constexpr int DsiWaitForCommandCompletionMilliSeconds = 5;
|
||||
constexpr int DsiWaitForHostControlMilliSecondsMax = 150;
|
||||
|
||||
constexpr size_t GPIO_PORT3_CNF_0 = 0x200;
|
||||
constexpr size_t GPIO_PORT3_OE_0 = 0x210;
|
||||
|
@ -66,32 +66,40 @@ namespace ams::boot {
|
|||
constexpr size_t GPIO_PORT6_OE_1 = 0x514;
|
||||
constexpr size_t GPIO_PORT6_OUT_1 = 0x524;
|
||||
|
||||
/* Types. */
|
||||
|
||||
/* Globals. */
|
||||
constinit bool g_is_display_intialized = false;
|
||||
constinit u32 *g_frame_buffer = nullptr;
|
||||
constinit spl::SocType g_soc_type = spl::SocType_Erista;
|
||||
|
||||
constinit u32 g_lcd_vendor = 0;
|
||||
constinit Handle g_dc_das_hnd = INVALID_HANDLE;
|
||||
constinit int g_display_brightness = 100;
|
||||
|
||||
constinit dd::DeviceAddressSpaceType g_device_address_space;
|
||||
|
||||
constinit u32 *g_frame_buffer = nullptr;
|
||||
constinit u8 g_frame_buffer_storage[DeviceAddressSpaceAlignSize + FrameBufferSize];
|
||||
|
||||
constinit uintptr_t g_disp1_regs = 0;
|
||||
constinit uintptr_t g_dsi_regs = 0;
|
||||
constinit uintptr_t g_clk_rst_regs = 0;
|
||||
constinit uintptr_t g_gpio_regs = 0;
|
||||
constinit uintptr_t g_disp1_regs = 0;
|
||||
constinit uintptr_t g_dsi_regs = 0;
|
||||
constinit uintptr_t g_clk_rst_regs = 0;
|
||||
constinit uintptr_t g_gpio_regs = 0;
|
||||
constinit uintptr_t g_apb_misc_regs = 0;
|
||||
constinit uintptr_t g_mipi_cal_regs = 0;
|
||||
|
||||
/* Helper functions. */
|
||||
void InitializeRegisterBaseAddresses() {
|
||||
g_disp1_regs = dd::GetIoMapping(Disp1Base, Disp1Size);
|
||||
g_dsi_regs = dd::GetIoMapping(DsiBase, DsiSize);
|
||||
g_clk_rst_regs = dd::GetIoMapping(ClkRstBase, ClkRstSize);
|
||||
g_gpio_regs = dd::GetIoMapping(GpioBase, GpioSize);
|
||||
g_apb_misc_regs = dd::GetIoMapping(ApbMiscBase, ApbMiscSize);
|
||||
g_mipi_cal_regs = dd::GetIoMapping(MipiCalBase, MipiCalSize);
|
||||
void InitializeRegisterVirtualAddresses() {
|
||||
g_disp1_regs = dd::QueryIoMapping(Disp1Base, Disp1Size);
|
||||
g_dsi_regs = dd::QueryIoMapping(DsiBase, DsiSize);
|
||||
g_clk_rst_regs = dd::QueryIoMapping(ClkRstBase, ClkRstSize);
|
||||
g_gpio_regs = dd::QueryIoMapping(GpioBase, GpioSize);
|
||||
g_apb_misc_regs = dd::QueryIoMapping(ApbMiscBase, ApbMiscSize);
|
||||
g_mipi_cal_regs = dd::QueryIoMapping(MipiCalBase, MipiCalSize);
|
||||
|
||||
AMS_ABORT_UNLESS(g_disp1_regs != 0);
|
||||
AMS_ABORT_UNLESS(g_dsi_regs != 0);
|
||||
AMS_ABORT_UNLESS(g_clk_rst_regs != 0);
|
||||
AMS_ABORT_UNLESS(g_gpio_regs != 0);
|
||||
AMS_ABORT_UNLESS(g_apb_misc_regs != 0);
|
||||
AMS_ABORT_UNLESS(g_mipi_cal_regs != 0);
|
||||
}
|
||||
|
||||
inline void DoRegisterWrites(uintptr_t base_address, const RegisterWrite *reg_writes, size_t num_writes) {
|
||||
|
@ -128,34 +136,38 @@ namespace ams::boot {
|
|||
void InitializeFrameBuffer() {
|
||||
if (g_frame_buffer != nullptr) {
|
||||
std::memset(g_frame_buffer, 0x00, FrameBufferSize);
|
||||
armDCacheFlush(g_frame_buffer, FrameBufferSize);
|
||||
dd::FlushDataCache(g_frame_buffer, FrameBufferSize);
|
||||
} else {
|
||||
const uintptr_t frame_buffer_aligned = ((reinterpret_cast<uintptr_t>(g_frame_buffer_storage) + DeviceAddressSpaceAlignMask) & ~uintptr_t(DeviceAddressSpaceAlignMask));
|
||||
const uintptr_t frame_buffer_aligned = util::AlignUp(reinterpret_cast<uintptr_t>(g_frame_buffer_storage), DeviceAddressSpaceAlignSize);
|
||||
g_frame_buffer = reinterpret_cast<u32 *>(frame_buffer_aligned);
|
||||
|
||||
std::memset(g_frame_buffer, 0x00, FrameBufferSize);
|
||||
armDCacheFlush(g_frame_buffer, FrameBufferSize);
|
||||
dd::FlushDataCache(g_frame_buffer, FrameBufferSize);
|
||||
|
||||
/* Create Address Space. */
|
||||
R_ABORT_UNLESS(svcCreateDeviceAddressSpace(&g_dc_das_hnd, 0, (1ul << 32)));
|
||||
R_ABORT_UNLESS(dd::CreateDeviceAddressSpace(std::addressof(g_device_address_space), 0, (UINT64_C(1) << 32)));
|
||||
|
||||
/* Attach it to the DC. */
|
||||
R_ABORT_UNLESS(svcAttachDeviceAddressSpace(svc::DeviceName_Dc, g_dc_das_hnd));
|
||||
R_ABORT_UNLESS(dd::AttachDeviceAddressSpace(std::addressof(g_device_address_space), svc::DeviceName_Dc));
|
||||
|
||||
/* Map the framebuffer for the DC as read-only. */
|
||||
R_ABORT_UNLESS(svcMapDeviceAddressSpaceAligned(g_dc_das_hnd, dd::GetCurrentProcessHandle(), frame_buffer_aligned, FrameBufferSize, FrameBufferPaddr, 1));
|
||||
R_ABORT_UNLESS(dd::MapDeviceAddressSpaceAligned(std::addressof(g_device_address_space), dd::GetCurrentProcessHandle(), frame_buffer_aligned, FrameBufferSize, FrameBufferDeviceAddress, dd::MemoryPermission_ReadOnly));
|
||||
}
|
||||
}
|
||||
|
||||
void FinalizeFrameBuffer() {
|
||||
if (g_frame_buffer != nullptr) {
|
||||
const uintptr_t frame_buffer_aligned = reinterpret_cast<uintptr_t>(g_frame_buffer);
|
||||
const uintptr_t frame_buffer_aligned = util::AlignUp(reinterpret_cast<uintptr_t>(g_frame_buffer), DeviceAddressSpaceAlignSize);
|
||||
|
||||
/* Unmap the framebuffer from the DC. */
|
||||
R_ABORT_UNLESS(svcUnmapDeviceAddressSpace(g_dc_das_hnd, dd::GetCurrentProcessHandle(), frame_buffer_aligned, FrameBufferSize, FrameBufferPaddr));
|
||||
dd::UnmapDeviceAddressSpace(std::addressof(g_device_address_space), dd::GetCurrentProcessHandle(), frame_buffer_aligned, FrameBufferSize, FrameBufferDeviceAddress);
|
||||
|
||||
/* Detach address space from the DC. */
|
||||
R_ABORT_UNLESS(svcDetachDeviceAddressSpace(svc::DeviceName_Dc, g_dc_das_hnd));
|
||||
/* Close the address space. */
|
||||
R_ABORT_UNLESS(svcCloseHandle(g_dc_das_hnd));
|
||||
g_dc_das_hnd = INVALID_HANDLE;
|
||||
dd::DetachDeviceAddressSpace(std::addressof(g_device_address_space), svc::DeviceName_Dc);
|
||||
|
||||
/* Destroy the address space. */
|
||||
dd::DestroyDeviceAddressSpace(std::addressof(g_device_address_space));
|
||||
|
||||
g_frame_buffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -192,7 +204,7 @@ namespace ams::boot {
|
|||
|
||||
void InitializeDisplay() {
|
||||
/* Setup globals. */
|
||||
InitializeRegisterBaseAddresses();
|
||||
InitializeRegisterVirtualAddresses();
|
||||
g_soc_type = spl::GetSocType();
|
||||
InitializeFrameBuffer();
|
||||
|
||||
|
|
Loading…
Reference in a new issue