mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-06 22:25:41 +12:00
[Kernel] Implement err:f
This commit is contained in:
parent
88c93645e3
commit
5992a58351
7 changed files with 92 additions and 12 deletions
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
45
src/core/kernel/error.cpp
Normal 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");
|
||||
}
|
|
@ -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];
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
Loading…
Add table
Reference in a new issue