mirror of
https://github.com/RPCSX/rpcsx.git
synced 2025-12-06 07:12:14 +01:00
838 lines
23 KiB
C++
838 lines
23 KiB
C++
#include "KernelContext.hpp"
|
|
#include "sys/sysproto.hpp"
|
|
#include "thread/Process.hpp"
|
|
#include "thread/Thread.hpp"
|
|
#include "time.hpp"
|
|
#include "utils/Logs.hpp"
|
|
|
|
namespace orbis {
|
|
SysResult kern_sysctl(Thread *thread, ptr<sint> name, uint namelen,
|
|
ptr<void> old, ptr<size_t> oldlenp, ptr<void> new_,
|
|
size_t newlen) {
|
|
enum sysctl_ctl { unspec, kern, vm, vfs, net, debug, hw, machdep, user };
|
|
|
|
enum sysctl_kern {
|
|
proc = 14,
|
|
boottime = 21,
|
|
os_rel_date = 24,
|
|
usrstack = 33,
|
|
arnd = 37,
|
|
|
|
// FIXME
|
|
smp_cpus = 1000,
|
|
sdk_version,
|
|
sched_cpusetsize,
|
|
proc_ptc,
|
|
cpu_mode,
|
|
rng_pseudo,
|
|
backup_restore_mode,
|
|
console,
|
|
init_safe_mode,
|
|
geom,
|
|
};
|
|
|
|
enum sysctl_hw {
|
|
ncpu = 3,
|
|
pagesize = 7,
|
|
|
|
// FIXME
|
|
config = 1000,
|
|
};
|
|
|
|
enum sysctl_vm {
|
|
// FIXME
|
|
swap_avail = 1000,
|
|
swap_total,
|
|
kern_heap_size,
|
|
budgets,
|
|
};
|
|
|
|
enum sysctl_hw_config {
|
|
chassis_info,
|
|
optical_out = 1000,
|
|
};
|
|
|
|
enum sysctl_machdep {
|
|
// FIXME
|
|
tsc_freq = 1000,
|
|
liverpool,
|
|
bootparams,
|
|
idps,
|
|
openpsid_for_sys,
|
|
sceKernelIsCavern,
|
|
};
|
|
|
|
enum sysctl_machdep_liverpool {
|
|
telemetry = 1000,
|
|
icc_max,
|
|
};
|
|
enum sysctl_machdep_bootparams {
|
|
is_main_on_standby = 1000,
|
|
};
|
|
|
|
enum sysctl_kern_geom {
|
|
updtfmt = 1000,
|
|
};
|
|
|
|
enum sysctl_vm_budgets_ {
|
|
mlock_total = 1000,
|
|
};
|
|
|
|
struct ProcInfo {
|
|
char data[0x448];
|
|
};
|
|
|
|
// for (unsigned int i = 0; i < namelen; ++i) {
|
|
// std::fprintf(stderr, " name[%u] = %u\n", i, name[i]);
|
|
// }
|
|
|
|
if (namelen == 6) {
|
|
// 4.17.0.0.3.0
|
|
if (name[0] == net && name[1] == 17 && name[2] == 0 && name[3] == 0 &&
|
|
name[4] == 3 && name[5] == 0) {
|
|
return ErrorCode::OPNOTSUPP;
|
|
}
|
|
}
|
|
|
|
if (namelen == 3) {
|
|
// 1 - 14 - 41 - debug flags?
|
|
|
|
if (name[0] == machdep && name[1] == bootparams &&
|
|
name[2] == is_main_on_standby) {
|
|
if (*oldlenp != 4 || new_ != nullptr || newlen != 0) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
*(uint32_t *)old = 0;
|
|
return {};
|
|
}
|
|
|
|
if (name[0] == kern && name[1] == os_rel_date) {
|
|
if (*oldlenp != 4 || new_ != nullptr || newlen != 0) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
*(uint32_t *)old = 0xaae93; // FIXME
|
|
return {};
|
|
}
|
|
|
|
if (name[0] == kern && name[1] == proc && name[2] == 41) {
|
|
// std::printf(" kern.14.41\n");
|
|
|
|
if (*oldlenp != 4 || new_ != nullptr || newlen != 0) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
*(uint32_t *)old = 0;
|
|
return {};
|
|
}
|
|
|
|
if (name[0] == kern && name[1] == proc && name[2] == 42) {
|
|
// std::printf(" kern.14.42\n");
|
|
|
|
if ((oldlenp != nullptr && *oldlenp != 0) || new_ == nullptr ||
|
|
newlen != 4) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
// set record
|
|
auto record = *(uint32_t *)new_;
|
|
// ORBIS_LOG_WARNING("sys___sysctl: set record", record);
|
|
return {};
|
|
}
|
|
|
|
if (name[0] == kern && name[1] == proc && name[2] == 8) {
|
|
// KERN_PROC_PROC
|
|
ORBIS_LOG_ERROR("KERN_PROC_PROC");
|
|
thread->where();
|
|
std::memset(old, 0, sizeof(ProcInfo));
|
|
*oldlenp = sizeof(ProcInfo);
|
|
return {};
|
|
}
|
|
|
|
if (name[0] == machdep && name[1] == liverpool && name[2] == telemetry) {
|
|
if (*oldlenp != 8 || new_ != nullptr || newlen != 0) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
*(uint64_t *)old = 0;
|
|
return {};
|
|
}
|
|
if (name[0] == machdep && name[1] == liverpool && name[2] == icc_max) {
|
|
if (*oldlenp != 4 || new_ != nullptr || newlen != 0) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
*(uint32_t *)old = 0;
|
|
return {};
|
|
}
|
|
|
|
if (name[0] == hw && name[1] == config && name[2] == chassis_info) {
|
|
if (*oldlenp != 8 || new_ != nullptr || newlen != 0) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
*(uint64_t *)old = 0;
|
|
return {};
|
|
}
|
|
|
|
if (name[0] == kern && name[1] == geom && name[2] == updtfmt) {
|
|
if (*oldlenp != 4 || new_ != nullptr || newlen != 0) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
*(uint32_t *)old = 0;
|
|
return {};
|
|
}
|
|
|
|
if (name[0] == vm && name[1] == budgets && name[2] == mlock_total) {
|
|
if (*oldlenp != 8 || new_ != nullptr || newlen != 0) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
*(uint64_t *)old = 5056ull * 1024 * 1024;
|
|
return {};
|
|
}
|
|
}
|
|
|
|
if (namelen >= 3) {
|
|
if (name[0] == kern && name[1] == proc && name[2] == 1) {
|
|
ORBIS_LOG_ERROR("KERN_PROC_PROC 2");
|
|
|
|
if (namelen >= 4) {
|
|
auto process = g_context.findProcessById(name[3]);
|
|
if (process == nullptr || process->exitStatus.has_value()) {
|
|
return ErrorCode::SRCH;
|
|
}
|
|
}
|
|
|
|
std::memset(old, 0, sizeof(ProcInfo));
|
|
*oldlenp = sizeof(ProcInfo);
|
|
return {};
|
|
}
|
|
}
|
|
|
|
if (namelen == 4) {
|
|
if (name[0] == kern && name[1] == proc && name[2] == 37) {
|
|
if (oldlenp && old && *oldlenp == 4) {
|
|
return uwrite(ptr<uint32_t>(old), ~0u);
|
|
}
|
|
}
|
|
|
|
if (name[0] == kern && name[1] == proc && name[2] == 55) {
|
|
if (g_context.fwType != FwType::Ps5) {
|
|
return orbis::ErrorCode::INVAL;
|
|
}
|
|
|
|
if (oldlenp && old && *oldlenp == 4) {
|
|
return uwrite<uint32_t>(ptr<uint32_t>(old),
|
|
thread->tproc->type == ProcessType::Ps5 ? 1
|
|
: 0);
|
|
}
|
|
}
|
|
|
|
if (name[0] == kern && name[1] == proc && name[2] == 36) {
|
|
Process *process = thread->tproc;
|
|
if (process->pid != name[3]) {
|
|
process = g_context.findProcessById(name[3]);
|
|
if (process == nullptr) {
|
|
ORBIS_LOG_ERROR("get sdk version by pid: process not found", name[3],
|
|
thread->tproc->pid);
|
|
return ErrorCode::SRCH;
|
|
}
|
|
}
|
|
|
|
size_t oldlen;
|
|
ORBIS_RET_ON_ERROR(uread(oldlen, oldlenp));
|
|
|
|
if (oldlen < sizeof(uint32_t)) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
auto sdkVersion = process->sdkVersion;
|
|
if (sdkVersion == 0) {
|
|
sdkVersion = g_context.fwSdkVersion;
|
|
}
|
|
|
|
ORBIS_RET_ON_ERROR(uwrite(ptr<uint32_t>(old), sdkVersion));
|
|
ORBIS_LOG_ERROR("get sdk version by pid", name[3], sdkVersion);
|
|
return uwrite(oldlenp, sizeof(uint32_t));
|
|
}
|
|
|
|
if (name[0] == 1 && name[1] == proc && name[2] == 35) {
|
|
// AppInfo get/set
|
|
|
|
// 1 - 14 - 35 - pid
|
|
|
|
Process *process = thread->tproc;
|
|
if (process->pid != name[3] && name[3] != -1) {
|
|
process = g_context.findProcessById(name[3]);
|
|
if (process == nullptr) {
|
|
ORBIS_LOG_ERROR("appinfo process not found", name[3],
|
|
thread->tproc->pid);
|
|
return ErrorCode::SRCH;
|
|
}
|
|
}
|
|
|
|
if (old) {
|
|
size_t oldlen;
|
|
if (auto errc = uread(oldlen, oldlenp); errc != ErrorCode{}) {
|
|
return errc;
|
|
}
|
|
|
|
if (oldlen < sizeof(AppInfo)) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
if (auto errc = uwrite((ptr<AppInfo>)old, process->appInfo);
|
|
errc != ErrorCode{}) {
|
|
return errc;
|
|
}
|
|
|
|
if (auto errc = uwrite(oldlenp, sizeof(AppInfo)); errc != ErrorCode{}) {
|
|
return errc;
|
|
}
|
|
}
|
|
|
|
if (new_) {
|
|
if (newlen != sizeof(AppInfo)) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
auto result = uread(process->appInfo, (ptr<AppInfo>)new_);
|
|
if (result == ErrorCode{}) {
|
|
auto &appInfo = process->appInfo;
|
|
ORBIS_LOG_ERROR("set AppInfo", appInfo.appId, appInfo.unk0,
|
|
appInfo.unk1, appInfo.appType, appInfo.titleId,
|
|
appInfo.unk2, appInfo.unk3, appInfo.unk5,
|
|
appInfo.unk6, appInfo.unk7, appInfo.unk8);
|
|
|
|
// HACK
|
|
if (appInfo.appId == 0 && appInfo.unk4 == 0) {
|
|
appInfo.unk4 = orbis::slong(0x80000000'00000000);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
if (name[0] == 1 && name[1] == 14 && name[2] == 44) {
|
|
// GetLibkernelTextLocation
|
|
if (*oldlenp != 16) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
auto *dest = (uint64_t *)old;
|
|
|
|
for (auto [id, mod] : thread->tproc->modulesMap) {
|
|
if (std::string_view("libkernel") == mod->moduleName) {
|
|
dest[0] = (uint64_t)mod->segments[0].addr;
|
|
dest[1] = mod->segments[0].size;
|
|
return {};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (namelen == 2) {
|
|
switch (name[0]) {
|
|
case sysctl_ctl::unspec: {
|
|
switch (name[1]) {
|
|
case 3: {
|
|
// std::fprintf(stderr, " unspec - get name of '%s'\n",
|
|
// std::string((char *)new_, newlen).c_str());
|
|
auto searchName = std::string_view((char *)new_, newlen);
|
|
auto *dest = (std::uint32_t *)old;
|
|
std::uint32_t count = 0;
|
|
|
|
if (searchName == "kern.smp.cpus") {
|
|
if (*oldlenp < 2 * sizeof(uint32_t)) {
|
|
std::fprintf(stderr, " %s error\n", searchName.data());
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
dest[count++] = kern;
|
|
dest[count++] = smp_cpus;
|
|
} else if (searchName == "machdep.tsc_freq") {
|
|
if (*oldlenp < 2 * sizeof(uint32_t)) {
|
|
std::fprintf(stderr, " %s error\n", searchName.data());
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
dest[count++] = machdep;
|
|
dest[count++] = tsc_freq;
|
|
} else if (searchName == "kern.sdk_version") {
|
|
if (*oldlenp < 2 * sizeof(uint32_t)) {
|
|
std::fprintf(stderr, " %s error\n", searchName.data());
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
dest[count++] = kern;
|
|
dest[count++] = sdk_version;
|
|
} else if (searchName == "kern.rng_pseudo") {
|
|
if (*oldlenp < 2 * sizeof(uint32_t)) {
|
|
std::fprintf(stderr, " %s error\n", searchName.data());
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
dest[count++] = kern;
|
|
dest[count++] = rng_pseudo;
|
|
} else if (searchName == "kern.sched.cpusetsize") {
|
|
if (*oldlenp < 2 * sizeof(uint32_t)) {
|
|
std::fprintf(stderr, " %s error\n", searchName.data());
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
dest[count++] = kern;
|
|
dest[count++] = sched_cpusetsize;
|
|
} else if (searchName == "kern.proc.ptc") {
|
|
if (*oldlenp < 2 * sizeof(uint32_t)) {
|
|
std::fprintf(stderr, " %s error\n", searchName.data());
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
dest[count++] = kern;
|
|
dest[count++] = proc_ptc;
|
|
} else if (searchName == "kern.cpumode") {
|
|
if (*oldlenp < 2 * sizeof(uint32_t)) {
|
|
std::fprintf(stderr, " %s error\n", searchName.data());
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
dest[count++] = kern;
|
|
dest[count++] = cpu_mode;
|
|
} else if (searchName == "kern.backup_restore_mode") {
|
|
if (*oldlenp < 2 * sizeof(uint32_t)) {
|
|
std::fprintf(stderr, " %s error\n", searchName.data());
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
dest[count++] = kern;
|
|
dest[count++] = backup_restore_mode;
|
|
} else if (searchName == "kern.console") {
|
|
if (*oldlenp < 2 * sizeof(uint32_t)) {
|
|
std::fprintf(stderr, " %s error\n", searchName.data());
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
dest[count++] = kern;
|
|
dest[count++] = console;
|
|
} else if (searchName == "kern.init_safe_mode") {
|
|
if (*oldlenp < 2 * sizeof(uint32_t)) {
|
|
std::fprintf(stderr, " %s error\n", searchName.data());
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
dest[count++] = kern;
|
|
dest[count++] = init_safe_mode;
|
|
} else if (searchName == "hw.config.chassis_info") {
|
|
if (*oldlenp < 3 * sizeof(uint32_t)) {
|
|
std::fprintf(stderr, " %s error\n", searchName.data());
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
dest[count++] = hw;
|
|
dest[count++] = config;
|
|
dest[count++] = chassis_info;
|
|
} else if (searchName == "machdep.liverpool.telemetry") {
|
|
if (*oldlenp < 3 * sizeof(uint32_t)) {
|
|
std::fprintf(stderr, " %s error\n", searchName.data());
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
dest[count++] = machdep;
|
|
dest[count++] = liverpool;
|
|
dest[count++] = telemetry;
|
|
} else if (searchName == "machdep.liverpool.icc_max") {
|
|
if (*oldlenp < 3 * sizeof(uint32_t)) {
|
|
std::fprintf(stderr, " %s error\n", searchName.data());
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
dest[count++] = machdep;
|
|
dest[count++] = liverpool;
|
|
dest[count++] = icc_max;
|
|
} else if (searchName == "vm.swap_avail") {
|
|
if (*oldlenp < 2 * sizeof(uint32_t)) {
|
|
std::fprintf(stderr, " %s error\n", searchName.data());
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
dest[count++] = vm;
|
|
dest[count++] = swap_avail;
|
|
} else if (searchName == "vm.kern_heap_size") {
|
|
if (*oldlenp < 2 * sizeof(uint32_t)) {
|
|
std::fprintf(stderr, " %s error\n", searchName.data());
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
dest[count++] = vm;
|
|
dest[count++] = kern_heap_size;
|
|
} else if (searchName == "vm.swap_total") {
|
|
if (*oldlenp < 2 * sizeof(uint32_t)) {
|
|
std::fprintf(stderr, " %s error\n", searchName.data());
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
dest[count++] = vm;
|
|
dest[count++] = swap_total;
|
|
} else if (searchName == "machdep.bootparams.is_main_on_standby") {
|
|
if (*oldlenp < 3 * sizeof(uint32_t)) {
|
|
std::fprintf(stderr, " %s error\n", searchName.data());
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
dest[count++] = machdep;
|
|
dest[count++] = bootparams;
|
|
dest[count++] = is_main_on_standby;
|
|
} else if (searchName == "hw.config.optical_out") {
|
|
if (*oldlenp < 3 * sizeof(uint32_t)) {
|
|
std::fprintf(stderr, " %s error\n", searchName.data());
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
dest[count++] = hw;
|
|
dest[count++] = config;
|
|
dest[count++] = optical_out;
|
|
} else if (searchName == "machdep.idps") {
|
|
if (*oldlenp < 2 * sizeof(uint32_t)) {
|
|
std::fprintf(stderr, " %s error\n", searchName.data());
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
dest[count++] = machdep;
|
|
dest[count++] = idps;
|
|
} else if (searchName == "kern.geom.updtfmt") {
|
|
if (*oldlenp < 3 * sizeof(uint32_t)) {
|
|
std::fprintf(stderr, " %s error\n", searchName.data());
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
dest[count++] = kern;
|
|
dest[count++] = geom;
|
|
dest[count++] = updtfmt;
|
|
} else if (searchName == "machdep.openpsid_for_sys") {
|
|
if (*oldlenp < 2 * sizeof(uint32_t)) {
|
|
std::fprintf(stderr, " %s error\n", searchName.data());
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
dest[count++] = machdep;
|
|
dest[count++] = openpsid_for_sys;
|
|
} else if (searchName == "machdep.sceKernelIsCavern") {
|
|
if (*oldlenp < 2 * sizeof(uint32_t)) {
|
|
std::fprintf(stderr, " %s error\n", searchName.data());
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
dest[count++] = machdep;
|
|
dest[count++] = sceKernelIsCavern;
|
|
} else if (searchName == "vm.budgets.mlock_total") {
|
|
if (*oldlenp < 3 * sizeof(uint32_t)) {
|
|
std::fprintf(stderr, " %s error\n", searchName.data());
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
dest[count++] = vm;
|
|
dest[count++] = budgets;
|
|
dest[count++] = mlock_total;
|
|
}
|
|
|
|
if (count == 0) {
|
|
std::fprintf(stderr, "sys___sysctl: %s is unknown\n",
|
|
searchName.data());
|
|
return ErrorCode::SRCH;
|
|
}
|
|
|
|
*oldlenp = count * sizeof(uint32_t);
|
|
return {};
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
std::printf(" unspec_%u\n", name[1]);
|
|
return {};
|
|
}
|
|
|
|
case sysctl_ctl::kern:
|
|
switch (name[1]) {
|
|
case sysctl_kern::boottime: {
|
|
// FIXME: implement boottime support
|
|
if (*oldlenp < sizeof(timeval) || new_ != nullptr || newlen != 0) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
*oldlenp = sizeof(timeval);
|
|
*ptr<timeval>(old) = {
|
|
.tv_sec = 60,
|
|
.tv_usec = 0,
|
|
};
|
|
return {};
|
|
}
|
|
case sysctl_kern::usrstack: {
|
|
if (*oldlenp != 8 || new_ != nullptr || newlen != 0) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
std::printf("Reporting stack at %p\n", thread->stackEnd);
|
|
*(ptr<void> *)old = thread->stackEnd;
|
|
return {};
|
|
}
|
|
|
|
case sysctl_kern::smp_cpus:
|
|
if (*oldlenp != 4 || new_ != nullptr || newlen != 0) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
*(uint32_t *)old = 6;
|
|
return {};
|
|
|
|
case sysctl_kern::sdk_version: {
|
|
if (*oldlenp != 4 || new_ != nullptr || newlen != 0) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
std::printf("Reporting SDK version %x\n", thread->tproc->sdkVersion);
|
|
*(uint32_t *)old = thread->tproc->sdkVersion;
|
|
return {};
|
|
}
|
|
|
|
case sysctl_kern::sched_cpusetsize:
|
|
if (*oldlenp != 4 || new_ != nullptr || newlen != 0) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
*(std::uint32_t *)old = 4;
|
|
return {};
|
|
|
|
case sysctl_kern::rng_pseudo:
|
|
if (*oldlenp != 0x40 || new_ != nullptr || newlen != 0) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
std::memset(old, 0, 0x40);
|
|
return {};
|
|
|
|
case sysctl_kern::arnd: {
|
|
struct kern37_value {
|
|
std::uint64_t size;
|
|
std::uint64_t unk[7];
|
|
};
|
|
|
|
if (*oldlenp != sizeof(kern37_value) || new_ != nullptr ||
|
|
newlen != 0) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
auto value = (kern37_value *)old;
|
|
value->size = sizeof(kern37_value);
|
|
return {};
|
|
}
|
|
|
|
case sysctl_kern::proc_ptc: {
|
|
if (*oldlenp != 8 || new_ != nullptr || newlen != 0) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
*(std::uint64_t *)old = 1357;
|
|
return {};
|
|
}
|
|
|
|
case sysctl_kern::cpu_mode: {
|
|
if (*oldlenp != 4 || new_ != nullptr || newlen != 0) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
// 0 - 6 cpu
|
|
// 1 - 7 cpu, low power
|
|
// 5 - 7 cpu, normal
|
|
*(std::uint32_t *)old = 5;
|
|
return {};
|
|
}
|
|
|
|
case sysctl_kern::backup_restore_mode:
|
|
if (*oldlenp != 4 || new_ != nullptr || newlen != 0) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
// 0 - normal
|
|
// 1 - backup
|
|
// 2 - restore
|
|
*(std::uint32_t *)old = 0;
|
|
return {};
|
|
|
|
case sysctl_kern::init_safe_mode:
|
|
if (old && oldlenp) {
|
|
ORBIS_LOG_ERROR("sysctl: get kern.init_safe_mode", oldlenp, new_,
|
|
newlen);
|
|
if (*oldlenp != 4) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
*(std::uint32_t *)old = g_context.safeMode;
|
|
}
|
|
if (new_ != nullptr && newlen == 4) {
|
|
ORBIS_LOG_ERROR("sysctl: set kern.init_safe_mode",
|
|
*(std::uint32_t *)new_, newlen);
|
|
}
|
|
return {};
|
|
|
|
default:
|
|
return ErrorCode::INVAL;
|
|
}
|
|
break;
|
|
|
|
case sysctl_ctl::vm:
|
|
switch (name[1]) {
|
|
case sysctl_vm::kern_heap_size:
|
|
if (*oldlenp != 4 || new_ != nullptr || newlen != 0) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
*(std::uint32_t *)old = (1 << 14) >> 14;
|
|
return {};
|
|
|
|
case sysctl_vm::swap_total:
|
|
if (*oldlenp != 8 || new_ != nullptr || newlen != 0) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
*(std::uint64_t *)old = 0;
|
|
return {};
|
|
|
|
case sysctl_vm::swap_avail:
|
|
if (*oldlenp != 4 || new_ != nullptr || newlen != 0) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
*(std::uint32_t *)old = (1 << 14) >> 14;
|
|
return {};
|
|
|
|
default:
|
|
break;
|
|
}
|
|
case sysctl_ctl::vfs:
|
|
case sysctl_ctl::net:
|
|
case sysctl_ctl::debug:
|
|
return ErrorCode::INVAL;
|
|
|
|
case sysctl_ctl::hw:
|
|
switch (name[1]) {
|
|
case sysctl_hw::pagesize:
|
|
if (*oldlenp != 4 || new_ != nullptr || newlen != 0) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
*(uint32_t *)old = 0x4000;
|
|
return {};
|
|
|
|
case sysctl_hw::ncpu:
|
|
if (*oldlenp != 4 || new_ != nullptr || newlen != 0) {
|
|
|
|
} else {
|
|
|
|
*(uint32_t *)old = 7;
|
|
return {};
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case sysctl_ctl::machdep:
|
|
switch (name[1]) {
|
|
case sysctl_machdep::tsc_freq: {
|
|
if (*oldlenp != 8 || new_ != nullptr || newlen != 0) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
if (std::string_view((char *)thread->tproc->appInfo.titleId) ==
|
|
"NPXS20973") {
|
|
ORBIS_LOG_ERROR("get tsc freq: returning patched value");
|
|
*(uint64_t *)old = 1000000;
|
|
} else {
|
|
*(uint64_t *)old = g_context.getTscFreq();
|
|
}
|
|
return {};
|
|
}
|
|
|
|
case sysctl_machdep::idps: {
|
|
if (*oldlenp != 16 || new_ != nullptr || newlen != 0) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
std::memset(old, 0, 16);
|
|
return uwrite<short>((short *)((char *)old + 4), 0x8401);
|
|
}
|
|
|
|
case sysctl_machdep::openpsid_for_sys: {
|
|
if (*oldlenp != 16 || new_ != nullptr || newlen != 0) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
std::memset(old, 0, 16);
|
|
return {};
|
|
}
|
|
|
|
case sysctl_machdep::sceKernelIsCavern: {
|
|
if (*oldlenp != 4 || new_ != nullptr || newlen != 0) {
|
|
return ErrorCode::INVAL;
|
|
}
|
|
|
|
*(uint32_t *)old = 1;
|
|
return {};
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
case sysctl_ctl::user:
|
|
break;
|
|
}
|
|
}
|
|
|
|
std::string concatName;
|
|
for (unsigned int i = 0; i < namelen; ++i) {
|
|
if (i != 0) {
|
|
concatName += '.';
|
|
}
|
|
|
|
concatName += std::to_string(name[i]);
|
|
}
|
|
|
|
std::size_t oldLen = oldlenp ? *oldlenp : 0;
|
|
ORBIS_LOG_TODO(__FUNCTION__, concatName, oldLen, new_, newlen);
|
|
thread->where();
|
|
return {};
|
|
}
|
|
} // namespace orbis
|
|
|
|
orbis::SysResult orbis::sys___sysctl(Thread *thread, ptr<sint> name,
|
|
uint namelen, ptr<void> old,
|
|
ptr<size_t> oldlenp, ptr<void> new_,
|
|
size_t newlen) {
|
|
|
|
auto result = kern_sysctl(thread, name, namelen, old, oldlenp, new_, newlen);
|
|
|
|
if (result.isError()) {
|
|
std::string concatName;
|
|
for (unsigned int i = 0; i < namelen; ++i) {
|
|
if (i != 0) {
|
|
concatName += '.';
|
|
}
|
|
|
|
concatName += std::to_string(name[i]);
|
|
}
|
|
|
|
std::size_t oldLen = oldlenp ? *oldlenp : 0;
|
|
ORBIS_LOG_TODO(__FUNCTION__, concatName, oldLen, new_, newlen);
|
|
thread->where();
|
|
}
|
|
|
|
return result;
|
|
} |