mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-29 23:34:16 +01:00
Implement IOCTL2 & IOCTL3
This commit is contained in:
parent
a5fece8020
commit
bb2c31264d
@ -13,7 +13,7 @@ namespace skyline::service::nvdrv {
|
|||||||
{0x2, SFUNC(INvDrvServices::Close)},
|
{0x2, SFUNC(INvDrvServices::Close)},
|
||||||
{0x3, SFUNC(INvDrvServices::Initialize)},
|
{0x3, SFUNC(INvDrvServices::Initialize)},
|
||||||
{0x4, SFUNC(INvDrvServices::QueryEvent)},
|
{0x4, SFUNC(INvDrvServices::QueryEvent)},
|
||||||
{0x8, SFUNC(INvDrvServices::SetAruidByPID)},
|
{0x8, SFUNC(INvDrvServices::SetAruid)},
|
||||||
{0xD, SFUNC(INvDrvServices::SetGraphicsFirmwareMemoryMarginEnabled)}
|
{0xD, SFUNC(INvDrvServices::SetGraphicsFirmwareMemoryMarginEnabled)}
|
||||||
}) {
|
}) {
|
||||||
if (nvdrv::driver.expired())
|
if (nvdrv::driver.expired())
|
||||||
@ -39,26 +39,22 @@ namespace skyline::service::nvdrv {
|
|||||||
// Strip the permissions from the command leaving only the ID
|
// Strip the permissions from the command leaving only the ID
|
||||||
cmd &= 0xFFFF;
|
cmd &= 0xFFFF;
|
||||||
|
|
||||||
try {
|
std::optional<kernel::ipc::IpcBuffer> buffer{std::nullopt};
|
||||||
std::optional<kernel::ipc::IpcBuffer> buffer{std::nullopt};
|
if (request.inputBuf.empty() || request.outputBuf.empty()) {
|
||||||
if (request.inputBuf.empty() || request.outputBuf.empty()) {
|
if (!request.inputBuf.empty())
|
||||||
if (!request.inputBuf.empty())
|
|
||||||
buffer = request.inputBuf.at(0);
|
|
||||||
else if (!request.outputBuf.empty())
|
|
||||||
buffer = request.outputBuf.at(0);
|
|
||||||
else
|
|
||||||
throw exception("No IOCTL Buffers");
|
|
||||||
} else if (request.inputBuf.at(0).address == request.outputBuf.at(0).address) {
|
|
||||||
buffer = request.inputBuf.at(0);
|
buffer = request.inputBuf.at(0);
|
||||||
} else {
|
else if (!request.outputBuf.empty())
|
||||||
throw exception("IOCTL Input Buffer != Output Buffer");
|
buffer = request.outputBuf.at(0);
|
||||||
}
|
else
|
||||||
|
throw exception("No IOCTL Buffers");
|
||||||
response.Push(device->HandleIoctl(cmd, device::IoctlType::Ioctl, std::span<u8>(reinterpret_cast<u8 *>(buffer->address), buffer->size), {}));
|
} else if (request.inputBuf.at(0).address == request.outputBuf.at(0).address) {
|
||||||
return {};
|
buffer = request.inputBuf.at(0);
|
||||||
} catch (const std::out_of_range &) {
|
} else {
|
||||||
throw exception("IOCTL was requested on an invalid file descriptor: 0x{:X}", fd);
|
throw exception("IOCTL Input Buffer (0x{:X}) != Output Buffer (0x{:X})", request.inputBuf[0].address, request.outputBuf[0].address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
response.Push(device->HandleIoctl(cmd, device::IoctlType::Ioctl, std::span<u8>(reinterpret_cast<u8 *>(buffer->address), buffer->size), {}));
|
||||||
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Result INvDrvServices::Close(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result INvDrvServices::Close(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
@ -97,11 +93,47 @@ namespace skyline::service::nvdrv {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Result INvDrvServices::SetAruidByPID(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result INvDrvServices::SetAruid(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
response.Push(device::NvStatus::Success);
|
response.Push(device::NvStatus::Success);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result INvDrvServices::Ioctl2(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
auto fd = request.Pop<u32>();
|
||||||
|
auto cmd = request.Pop<u32>();
|
||||||
|
|
||||||
|
auto device = driver->GetDevice(fd);
|
||||||
|
|
||||||
|
// Strip the permissions from the command leaving only the ID
|
||||||
|
cmd &= 0xFFFF;
|
||||||
|
|
||||||
|
if (request.inputBuf.size() < 2 || request.outputBuf.empty())
|
||||||
|
throw exception("Inadequate amount of buffers for IOCTL2: I - {}, O - {}", request.inputBuf.size(), request.outputBuf.size());
|
||||||
|
else if (request.inputBuf[0].address != request.outputBuf[0].address)
|
||||||
|
throw exception("IOCTL2 Input Buffer (0x{:X}) != Output Buffer (0x{:X}) [Input Buffer #2: 0x{:X}]", request.inputBuf[0].address, request.outputBuf[0].address, request.inputBuf[1].address);
|
||||||
|
|
||||||
|
response.Push(device->HandleIoctl(cmd, device::IoctlType::Ioctl2, std::span<u8>(reinterpret_cast<u8 *>(request.inputBuf[0].address), request.inputBuf[0].size), std::span<u8>(reinterpret_cast<u8 *>(request.inputBuf[1].address), request.inputBuf[1].size)));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Result INvDrvServices::Ioctl3(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
|
auto fd = request.Pop<u32>();
|
||||||
|
auto cmd = request.Pop<u32>();
|
||||||
|
|
||||||
|
auto device = driver->GetDevice(fd);
|
||||||
|
|
||||||
|
// Strip the permissions from the command leaving only the ID
|
||||||
|
cmd &= 0xFFFF;
|
||||||
|
|
||||||
|
if (request.inputBuf.empty() || request.outputBuf.size() < 2)
|
||||||
|
throw exception("Inadequate amount of buffers for IOCTL3: I - {}, O - {}", request.inputBuf.size(), request.outputBuf.size());
|
||||||
|
else if (request.inputBuf[0].address != request.outputBuf[0].address)
|
||||||
|
throw exception("IOCTL3 Input Buffer (0x{:X}) != Output Buffer (0x{:X}) [Output Buffer #2: 0x{:X}]", request.inputBuf[0].address, request.outputBuf[0].address, request.outputBuf[1].address);
|
||||||
|
|
||||||
|
response.Push(device->HandleIoctl(cmd, device::IoctlType::Ioctl3, std::span<u8>(reinterpret_cast<u8 *>(request.inputBuf[0].address), request.inputBuf[0].size), std::span<u8>(reinterpret_cast<u8 *>(request.outputBuf[1].address), request.outputBuf[1].size)));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
Result INvDrvServices::SetGraphicsFirmwareMemoryMarginEnabled(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
Result INvDrvServices::SetGraphicsFirmwareMemoryMarginEnabled(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ namespace skyline::service::nvdrv {
|
|||||||
Result Open(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result Open(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Close the specified FD (https://switchbrew.org/wiki/NV_services#Close)
|
* @brief Perform an IOCTL on the specified FD (https://switchbrew.org/wiki/NV_services#Ioctl)
|
||||||
*/
|
*/
|
||||||
Result Ioctl(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result Ioctl(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
@ -45,9 +45,19 @@ namespace skyline::service::nvdrv {
|
|||||||
Result QueryEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result QueryEvent(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This sets the AppletResourceUserId which matches the PID (https://switchbrew.org/wiki/NV_services#SetAruidByPID)
|
* @brief This sets the AppletResourceUserId which matches the PID (https://switchbrew.org/wiki/NV_services#SetAruid)
|
||||||
*/
|
*/
|
||||||
Result SetAruidByPID(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
Result SetAruid(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Perform an IOCTL on the specified FD with an extra input buffer (https://switchbrew.org/wiki/NV_services#Ioctl2)
|
||||||
|
*/
|
||||||
|
Result Ioctl2(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Perform an IOCTL on the specified FD with an extra output buffer (https://switchbrew.org/wiki/NV_services#Ioctl3)
|
||||||
|
*/
|
||||||
|
Result Ioctl3(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This enables the graphics firmware memory margin (https://switchbrew.org/wiki/NV_services#SetGraphicsFirmwareMemoryMarginEnabled)
|
* @brief This enables the graphics firmware memory margin (https://switchbrew.org/wiki/NV_services#SetGraphicsFirmwareMemoryMarginEnabled)
|
||||||
|
@ -21,14 +21,24 @@ namespace skyline::service::nvdrv::device {
|
|||||||
std::pair<std::function<NvStatus(IoctlType, std::span<u8>, std::span<u8>)>, std::string_view> function;
|
std::pair<std::function<NvStatus(IoctlType, std::span<u8>, std::span<u8>)>, std::string_view> function;
|
||||||
try {
|
try {
|
||||||
function = GetIoctlFunction(cmd);
|
function = GetIoctlFunction(cmd);
|
||||||
state.logger->Debug("IOCTL @ {}: {}", GetName(), function.second);
|
std::string_view typeString{[type] {
|
||||||
|
switch (type) {
|
||||||
|
case IoctlType::Ioctl:
|
||||||
|
return "IOCTL";
|
||||||
|
case IoctlType::Ioctl2:
|
||||||
|
return "IOCTL2";
|
||||||
|
case IoctlType::Ioctl3:
|
||||||
|
return "IOCTL3";
|
||||||
|
}
|
||||||
|
}()};
|
||||||
|
state.logger->Debug("{} @ {}: {}", typeString, GetName(), function.second);
|
||||||
} catch (std::out_of_range &) {
|
} catch (std::out_of_range &) {
|
||||||
state.logger->Warn("Cannot find IOCTL for device '{}': 0x{:X}", GetName(), cmd);
|
state.logger->Warn("Cannot find IOCTL for device '{}': 0x{:X}", GetName(), cmd);
|
||||||
return NvStatus::NotImplemented;
|
return NvStatus::NotImplemented;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return function.first(type, buffer, inlineBuffer);
|
return function.first(type, buffer, inlineBuffer);
|
||||||
} catch (std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
throw exception("{} (Device: {})", e.what(), GetName());
|
throw exception("{} (Device: {})", e.what(), GetName());
|
||||||
}
|
}
|
||||||
exit(0);
|
exit(0);
|
||||||
|
@ -17,9 +17,9 @@ namespace skyline::service::nvdrv::device {
|
|||||||
|
|
||||||
NvStatus NvHostAsGpu::AllocSpace(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
NvStatus NvHostAsGpu::AllocSpace(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||||
struct Data {
|
struct Data {
|
||||||
u32 pages; // In
|
u32 pages; // In
|
||||||
u32 pageSize; // In
|
u32 pageSize; // In
|
||||||
u32 flags; // In
|
u32 flags; // In
|
||||||
u32 _pad_;
|
u32 _pad_;
|
||||||
union {
|
union {
|
||||||
u64 offset; // InOut
|
u64 offset; // InOut
|
||||||
|
Loading…
Reference in New Issue
Block a user