[Kernel] Implement err:f

This commit is contained in:
wheremyfoodat 2022-10-05 00:29:29 +03:00
parent 88c93645e3
commit 5992a58351
7 changed files with 92 additions and 12 deletions

View file

@ -50,7 +50,7 @@ set(SOURCE_FILES src/main.cpp src/emulator.cpp src/core/CPU/cpu_dynarmic.cpp src
set(KERNEL_SOURCE_FILES src/core/kernel/kernel.cpp src/core/kernel/resource_limits.cpp
src/core/kernel/memory_management.cpp src/core/kernel/ports.cpp
src/core/kernel/events.cpp src/core/kernel/threads.cpp
src/core/kernel/address_arbiter.cpp
src/core/kernel/address_arbiter.cpp src/core/kernel/error.cpp
)
set(SERVICE_SOURCE_FILES src/core/services/service_manager.cpp src/core/services/apt.cpp src/core/services/hid.cpp
src/core/services/fs.cpp src/core/services/gsp_gpu.cpp src/core/services/gsp_lcd.cpp

View file

@ -27,6 +27,8 @@ class Kernel {
Handle mainThread;
int currentThreadIndex;
Handle srvHandle; // Handle for the special service manager port "srv:"
Handle errorPortHandle; // Handle for the err:f port used for displaying errors
u32 arbiterCount;
u32 threadCount;
ServiceManager serviceManager;
@ -65,7 +67,7 @@ class Kernel {
Handle makeArbiter();
Handle makeEvent(ResetType resetType);
Handle makeProcess();
Handle makeProcess(u32 id);
Handle makePort(const char* name);
Handle makeSession(Handle port);
Handle makeThread(u32 entrypoint, u32 initialSP, u32 priority, s32 id, u32 arg,ThreadStatus status = ThreadStatus::Dormant);
@ -81,12 +83,17 @@ class Kernel {
u32 getMaxForResource(const KernelObject* limit, u32 resourceName);
u32 getTLSPointer();
// Functions for the err:f port
void handleErrorSyncRequest(u32 messagePointer);
void throwError(u32 messagePointer);
std::string getProcessName(u32 pid);
const char* resetTypeToString(u32 type);
MAKE_LOG_FUNCTION(log, kernelLogger)
MAKE_LOG_FUNCTION(logSVC, svcLogger)
MAKE_LOG_FUNCTION(logDebugString, debugStringLogger)
MAKE_LOG_FUNCTION(logError, errorLogger)
// SVC implementations
void arbitrateAddress();
@ -98,6 +105,7 @@ class Kernel {
void duplicateHandle();
void mapMemoryBlock();
void queryMemory();
void getProcessID();
void getProcessInfo();
void getResourceLimit();
void getResourceLimitLimitValues();

View file

@ -61,6 +61,10 @@ struct ResourceLimits {
struct Process {
// Resource limits for this process
ResourceLimits limits;
// Process ID
u32 id;
Process(u32 id) : id(id) {}
};
struct Event {

45
src/core/kernel/error.cpp Normal file
View file

@ -0,0 +1,45 @@
#include "kernel.hpp"
namespace Commands {
enum : u32 {
Throw = 0x00010800
};
}
namespace FatalErrorType {
enum : u32 {
Generic = 0,
Corrupted = 1,
CardRemoved = 2,
Exception = 3,
ResultFailure = 4,
Logged = 5
};
}
// Handle SendSyncRequest targetting the err:f port
void Kernel::handleErrorSyncRequest(u32 messagePointer) {
u32 cmd = mem.read32(messagePointer);
switch (cmd) {
case Commands::Throw: throwError(messagePointer); break;
default:
Helpers::panic("Unimplemented err:f command %08X\n", cmd);
break;
}
}
void Kernel::throwError(u32 messagePointer) {
const auto type = mem.read8(messagePointer + 4); // Fatal error type
const u32 pc = mem.read32(messagePointer + 12);
const u32 pid = mem.read32(messagePointer + 16);
logError("Thrown fatal error @ %08X (pid = %X, type = %d)\n", pc, pid, type);
// Read the error message if type == 4
if (type == FatalErrorType::ResultFailure) {
const auto error = mem.readString(messagePointer + 0x24, 0x60);
logError("ERROR: %s\n", error.c_str());
}
Helpers::panic("Thrown fatal error");
}

View file

@ -34,6 +34,7 @@ void Kernel::serviceSVC(u32 svc) {
case 0x2B: getProcessInfo(); break;
case 0x2D: connectToPort(); break;
case 0x32: sendSyncRequest(); break;
case 0x35: getProcessID(); break;
case 0x37: getThreadID(); break;
case 0x38: getResourceLimit(); break;
case 0x39: getResourceLimitLimitValues(); break;
@ -50,12 +51,12 @@ void Kernel::setVersion(u8 major, u8 minor) {
mem.kernelVersion = descriptor; // The memory objects needs a copy because you can read the kernel ver from config mem
}
Handle Kernel::makeProcess() {
Handle Kernel::makeProcess(u32 id) {
const Handle processHandle = makeObject(KernelObjectType::Process);
const Handle resourceLimitHandle = makeObject(KernelObjectType::ResourceLimit);
// Allocate data
objects[processHandle].data = new Process();
objects[processHandle].data = new Process(id);
const auto processData = objects[processHandle].getData<Process>();
// Link resource limit object with its parent process
@ -99,7 +100,7 @@ void Kernel::reset() {
// Allocate handle #0 to a dummy object and make a main process object
makeObject(KernelObjectType::Dummy);
currentProcess = makeProcess();
currentProcess = makeProcess(1); // Use ID = 1 for main process
// Make main thread object. We do not have to set the entrypoint and SP for it as the ROM loader does.
// Main thread seems to have a priority of 0x30. TODO: This creates a dummy context for thread 0,
@ -107,8 +108,9 @@ void Kernel::reset() {
mainThread = makeThread(0, VirtualAddrs::StackTop, 0x30, -2, 0, ThreadStatus::Running);
currentThreadIndex = 0;
// Create global service manager port
srvHandle = makePort("srv:");
// Create some of the OS ports
srvHandle = makePort("srv:"); // Service manager port
errorPortHandle = makePort("err:f"); // Error display port
}
// Get pointer to thread-local storage
@ -142,6 +144,20 @@ void Kernel::outputDebugString() {
regs[0] = SVCResult::Success;
}
void Kernel::getProcessID() {
const auto pid = regs[1];
const auto process = getProcessFromPID(pid);
logSVC("GetProcessID(process: %s)\n", getProcessName(pid).c_str());
if (process == nullptr) [[unlikely]] {
regs[0] = SVCResult::BadHandle;
return;
}
regs[0] = SVCResult::Success;
regs[1] = process->getData<Process>()->id;
}
// Result GetProcessInfo(s64* out, Handle process, ProcessInfoType type)
void Kernel::getProcessInfo() {
const auto pid = regs[1];

View file

@ -39,6 +39,7 @@ void Kernel::connectToPort() {
const u32 handlePointer = regs[0];
// Read up to max + 1 characters to see if the name is too long
std::string port = mem.readString(regs[1], Port::maxNameLen + 1);
logSVC("ConnectToPort(handle pointer = %X, port = \"%s\")\n", handlePointer, port.c_str());
if (port.size() > Port::maxNameLen) {
Helpers::panic("ConnectToPort: Port name too long\n");
@ -55,7 +56,6 @@ void Kernel::connectToPort() {
}
Handle portHandle = optionalHandle.value();
logSVC("ConnectToPort(handle pointer = %X, port = \"%s\")\n", handlePointer, port.c_str());
const auto portData = objects[portHandle].getData<Port>();
if (!portData->isPublic) {
@ -96,6 +96,8 @@ void Kernel::sendSyncRequest() {
if (portHandle == srvHandle) { // Special-case SendSyncRequest targetting the "srv: port"
serviceManager.handleSyncRequest(messagePointer);
} else if (portHandle == errorPortHandle) { // Special-case "err:f" for juicy logs too
handleErrorSyncRequest(messagePointer);
} else {
const auto portData = objects[portHandle].getData<Port>();
Helpers::panic("SendSyncRequest targetting port %s\n", portData->name);

View file

@ -28,8 +28,8 @@ void FSService::handleSyncRequest(u32 messagePointer) {
}
void FSService::initialize(u32 messagePointer) {
log("FS::Initialize (failure)\n");
mem.write32(messagePointer + 4, Result::Failure);
log("FS::Initialize\n");
mem.write32(messagePointer + 4, Result::Success);
}
void FSService::openArchive(u32 messagePointer) {
@ -40,12 +40,17 @@ void FSService::openArchive(u32 messagePointer) {
void FSService::openFileDirectly(u32 messagePointer) {
const u32 archiveID = mem.read32(messagePointer + 8);
const u32 archivePathType = mem.read32(messagePointer + 12);
const u32 archivePathSize = mem.read32(messagePointer + 16);
const u32 filePathType = mem.read32(messagePointer + 20);
const u32 filePathSize = mem.read32(messagePointer + 24);
const u32 openFlags = mem.read32(messagePointer + 28);
const u32 attributes = mem.read32(messagePointer + 32);
const u32 archivePathPointer = mem.read32(messagePointer + 40);
const u32 filePathPointer = mem.read32(messagePointer + 48);
log("FS::OpenFileDirectly (failure)\n");
mem.write32(messagePointer + 4, Result::Failure);
Helpers::panic("[FS::OpenFileDirectly] Tried to open file. Archive ID = %d\n", archiveID);
mem.write32(messagePointer + 4, Result::Success);
mem.write32(messagePointer + 12, 69);
//Helpers::panic("[FS::OpenFileDirectly] Tried to open file. Archive ID = %d\n", archiveID);
}