[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 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/memory_management.cpp src/core/kernel/ports.cpp
src/core/kernel/events.cpp src/core/kernel/threads.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 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 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; Handle mainThread;
int currentThreadIndex; int currentThreadIndex;
Handle srvHandle; // Handle for the special service manager port "srv:" 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 arbiterCount;
u32 threadCount; u32 threadCount;
ServiceManager serviceManager; ServiceManager serviceManager;
@ -65,7 +67,7 @@ class Kernel {
Handle makeArbiter(); Handle makeArbiter();
Handle makeEvent(ResetType resetType); Handle makeEvent(ResetType resetType);
Handle makeProcess(); Handle makeProcess(u32 id);
Handle makePort(const char* name); Handle makePort(const char* name);
Handle makeSession(Handle port); Handle makeSession(Handle port);
Handle makeThread(u32 entrypoint, u32 initialSP, u32 priority, s32 id, u32 arg,ThreadStatus status = ThreadStatus::Dormant); 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 getMaxForResource(const KernelObject* limit, u32 resourceName);
u32 getTLSPointer(); u32 getTLSPointer();
// Functions for the err:f port
void handleErrorSyncRequest(u32 messagePointer);
void throwError(u32 messagePointer);
std::string getProcessName(u32 pid); std::string getProcessName(u32 pid);
const char* resetTypeToString(u32 type); const char* resetTypeToString(u32 type);
MAKE_LOG_FUNCTION(log, kernelLogger) MAKE_LOG_FUNCTION(log, kernelLogger)
MAKE_LOG_FUNCTION(logSVC, svcLogger) MAKE_LOG_FUNCTION(logSVC, svcLogger)
MAKE_LOG_FUNCTION(logDebugString, debugStringLogger) MAKE_LOG_FUNCTION(logDebugString, debugStringLogger)
MAKE_LOG_FUNCTION(logError, errorLogger)
// SVC implementations // SVC implementations
void arbitrateAddress(); void arbitrateAddress();
@ -98,6 +105,7 @@ class Kernel {
void duplicateHandle(); void duplicateHandle();
void mapMemoryBlock(); void mapMemoryBlock();
void queryMemory(); void queryMemory();
void getProcessID();
void getProcessInfo(); void getProcessInfo();
void getResourceLimit(); void getResourceLimit();
void getResourceLimitLimitValues(); void getResourceLimitLimitValues();

View file

@ -61,6 +61,10 @@ struct ResourceLimits {
struct Process { struct Process {
// Resource limits for this process // Resource limits for this process
ResourceLimits limits; ResourceLimits limits;
// Process ID
u32 id;
Process(u32 id) : id(id) {}
}; };
struct Event { 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 0x2B: getProcessInfo(); break;
case 0x2D: connectToPort(); break; case 0x2D: connectToPort(); break;
case 0x32: sendSyncRequest(); break; case 0x32: sendSyncRequest(); break;
case 0x35: getProcessID(); break;
case 0x37: getThreadID(); break; case 0x37: getThreadID(); break;
case 0x38: getResourceLimit(); break; case 0x38: getResourceLimit(); break;
case 0x39: getResourceLimitLimitValues(); 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 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 processHandle = makeObject(KernelObjectType::Process);
const Handle resourceLimitHandle = makeObject(KernelObjectType::ResourceLimit); const Handle resourceLimitHandle = makeObject(KernelObjectType::ResourceLimit);
// Allocate data // Allocate data
objects[processHandle].data = new Process(); objects[processHandle].data = new Process(id);
const auto processData = objects[processHandle].getData<Process>(); const auto processData = objects[processHandle].getData<Process>();
// Link resource limit object with its parent 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 // Allocate handle #0 to a dummy object and make a main process object
makeObject(KernelObjectType::Dummy); 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. // 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, // 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); mainThread = makeThread(0, VirtualAddrs::StackTop, 0x30, -2, 0, ThreadStatus::Running);
currentThreadIndex = 0; currentThreadIndex = 0;
// Create global service manager port // Create some of the OS ports
srvHandle = makePort("srv:"); srvHandle = makePort("srv:"); // Service manager port
errorPortHandle = makePort("err:f"); // Error display port
} }
// Get pointer to thread-local storage // Get pointer to thread-local storage
@ -142,6 +144,20 @@ void Kernel::outputDebugString() {
regs[0] = SVCResult::Success; 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) // Result GetProcessInfo(s64* out, Handle process, ProcessInfoType type)
void Kernel::getProcessInfo() { void Kernel::getProcessInfo() {
const auto pid = regs[1]; const auto pid = regs[1];

View file

@ -39,6 +39,7 @@ void Kernel::connectToPort() {
const u32 handlePointer = regs[0]; const u32 handlePointer = regs[0];
// Read up to max + 1 characters to see if the name is too long // Read up to max + 1 characters to see if the name is too long
std::string port = mem.readString(regs[1], Port::maxNameLen + 1); 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) { if (port.size() > Port::maxNameLen) {
Helpers::panic("ConnectToPort: Port name too long\n"); Helpers::panic("ConnectToPort: Port name too long\n");
@ -55,7 +56,6 @@ void Kernel::connectToPort() {
} }
Handle portHandle = optionalHandle.value(); Handle portHandle = optionalHandle.value();
logSVC("ConnectToPort(handle pointer = %X, port = \"%s\")\n", handlePointer, port.c_str());
const auto portData = objects[portHandle].getData<Port>(); const auto portData = objects[portHandle].getData<Port>();
if (!portData->isPublic) { if (!portData->isPublic) {
@ -96,6 +96,8 @@ void Kernel::sendSyncRequest() {
if (portHandle == srvHandle) { // Special-case SendSyncRequest targetting the "srv: port" if (portHandle == srvHandle) { // Special-case SendSyncRequest targetting the "srv: port"
serviceManager.handleSyncRequest(messagePointer); serviceManager.handleSyncRequest(messagePointer);
} else if (portHandle == errorPortHandle) { // Special-case "err:f" for juicy logs too
handleErrorSyncRequest(messagePointer);
} else { } else {
const auto portData = objects[portHandle].getData<Port>(); const auto portData = objects[portHandle].getData<Port>();
Helpers::panic("SendSyncRequest targetting port %s\n", portData->name); 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) { void FSService::initialize(u32 messagePointer) {
log("FS::Initialize (failure)\n"); log("FS::Initialize\n");
mem.write32(messagePointer + 4, Result::Failure); mem.write32(messagePointer + 4, Result::Success);
} }
void FSService::openArchive(u32 messagePointer) { void FSService::openArchive(u32 messagePointer) {
@ -40,12 +40,17 @@ void FSService::openArchive(u32 messagePointer) {
void FSService::openFileDirectly(u32 messagePointer) { void FSService::openFileDirectly(u32 messagePointer) {
const u32 archiveID = mem.read32(messagePointer + 8); const u32 archiveID = mem.read32(messagePointer + 8);
const u32 archivePathType = mem.read32(messagePointer + 12); const u32 archivePathType = mem.read32(messagePointer + 12);
const u32 archivePathSize = mem.read32(messagePointer + 16);
const u32 filePathType = mem.read32(messagePointer + 20); 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 archivePathPointer = mem.read32(messagePointer + 40);
const u32 filePathPointer = mem.read32(messagePointer + 48); const u32 filePathPointer = mem.read32(messagePointer + 48);
log("FS::OpenFileDirectly (failure)\n"); log("FS::OpenFileDirectly (failure)\n");
mem.write32(messagePointer + 4, Result::Failure); mem.write32(messagePointer + 4, Result::Success);
Helpers::panic("[FS::OpenFileDirectly] Tried to open file. Archive ID = %d\n", archiveID); mem.write32(messagePointer + 12, 69);
//Helpers::panic("[FS::OpenFileDirectly] Tried to open file. Archive ID = %d\n", archiveID);
} }