mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-26 21:11:49 +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)},
|
||||
{0x3, SFUNC(INvDrvServices::Initialize)},
|
||||
{0x4, SFUNC(INvDrvServices::QueryEvent)},
|
||||
{0x8, SFUNC(INvDrvServices::SetAruidByPID)},
|
||||
{0x8, SFUNC(INvDrvServices::SetAruid)},
|
||||
{0xD, SFUNC(INvDrvServices::SetGraphicsFirmwareMemoryMarginEnabled)}
|
||||
}) {
|
||||
if (nvdrv::driver.expired())
|
||||
@ -39,26 +39,22 @@ namespace skyline::service::nvdrv {
|
||||
// Strip the permissions from the command leaving only the ID
|
||||
cmd &= 0xFFFF;
|
||||
|
||||
try {
|
||||
std::optional<kernel::ipc::IpcBuffer> buffer{std::nullopt};
|
||||
if (request.inputBuf.empty() || request.outputBuf.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) {
|
||||
std::optional<kernel::ipc::IpcBuffer> buffer{std::nullopt};
|
||||
if (request.inputBuf.empty() || request.outputBuf.empty()) {
|
||||
if (!request.inputBuf.empty())
|
||||
buffer = request.inputBuf.at(0);
|
||||
} else {
|
||||
throw exception("IOCTL Input Buffer != Output Buffer");
|
||||
}
|
||||
|
||||
response.Push(device->HandleIoctl(cmd, device::IoctlType::Ioctl, std::span<u8>(reinterpret_cast<u8 *>(buffer->address), buffer->size), {}));
|
||||
return {};
|
||||
} catch (const std::out_of_range &) {
|
||||
throw exception("IOCTL was requested on an invalid file descriptor: 0x{:X}", fd);
|
||||
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);
|
||||
} else {
|
||||
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) {
|
||||
@ -97,11 +93,47 @@ namespace skyline::service::nvdrv {
|
||||
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);
|
||||
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) {
|
||||
return {};
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ namespace skyline::service::nvdrv {
|
||||
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);
|
||||
|
||||
@ -45,9 +45,19 @@ namespace skyline::service::nvdrv {
|
||||
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)
|
||||
|
@ -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;
|
||||
try {
|
||||
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 &) {
|
||||
state.logger->Warn("Cannot find IOCTL for device '{}': 0x{:X}", GetName(), cmd);
|
||||
return NvStatus::NotImplemented;
|
||||
}
|
||||
try {
|
||||
return function.first(type, buffer, inlineBuffer);
|
||||
} catch (std::exception &e) {
|
||||
} catch (const std::exception &e) {
|
||||
throw exception("{} (Device: {})", e.what(), GetName());
|
||||
}
|
||||
exit(0);
|
||||
|
@ -17,9 +17,9 @@ namespace skyline::service::nvdrv::device {
|
||||
|
||||
NvStatus NvHostAsGpu::AllocSpace(IoctlType type, std::span<u8> buffer, std::span<u8> inlineBuffer) {
|
||||
struct Data {
|
||||
u32 pages; // In
|
||||
u32 pageSize; // In
|
||||
u32 flags; // In
|
||||
u32 pages; // In
|
||||
u32 pageSize; // In
|
||||
u32 flags; // In
|
||||
u32 _pad_;
|
||||
union {
|
||||
u64 offset; // InOut
|
||||
|
Loading…
Reference in New Issue
Block a user