mirror of
https://github.com/reswitched/Mephisto.git
synced 2024-06-22 22:31:41 -04:00
updates and such from private
This commit is contained in:
parent
6081adccfa
commit
3b2063f6c7
13
.dir-locals.el
Normal file
13
.dir-locals.el
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
(
|
||||||
|
(nil . (
|
||||||
|
(tab-width . 4)
|
||||||
|
(c-basic-offset . 4)
|
||||||
|
(indent-tabs-mode . t)
|
||||||
|
(c-auto-align-backslashes . nil)
|
||||||
|
(c-file-offsets . (
|
||||||
|
(cpp-define-intro . 0)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
77
Cpu.cpp
77
Cpu.cpp
|
@ -4,27 +4,41 @@ void intrHook(uc_engine *uc, uint32_t intNo, void *user_data) {
|
||||||
((Cpu *) user_data)->interruptHook(intNo);
|
((Cpu *) user_data)->interruptHook(intNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool unmpdHook(uc_engine *uc, uc_mem_type type, gptr addr, int size, guint value, void *user_data) {
|
bool unmpdHook(uc_engine *uc, uc_mem_type type, gptr addr, uint32_t size, guint value, void *user_data) {
|
||||||
return ((Cpu *) user_data)->unmappedHook(type, addr, size, value);
|
return ((Cpu *) user_data)->unmappedHook(type, addr, size, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mmioHook(uc_engine *uc, uc_mem_type type, gptr address, int size, gptr value, void *user_data) {
|
void mmioHook(uc_engine *uc, uc_mem_type type, gptr address, uint32_t size, gptr value, void *user_data) {
|
||||||
gptr physicalAddress = ((Cpu *) user_data)->mmioHandler->getPhysicalAddressFromVirtual(address);
|
auto cpu = (Cpu *) user_data;
|
||||||
MmioBase *mmio = ((Cpu *) user_data)->mmioHandler->getMMIOFromPhysicalAddress(address);
|
auto physicalAddress = cpu->mmioHandler->getPhysicalAddressFromVirtual(address);
|
||||||
|
auto mmio = cpu->mmioHandler->getMMIOFromPhysicalAddress(address);
|
||||||
assert(mmio != nullptr);
|
assert(mmio != nullptr);
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case UC_MEM_READ:
|
case UC_MEM_READ:
|
||||||
LOG_DEBUG(Cpu, "MMIO Read at " ADDRFMT " size %x", physicalAddress, size);
|
LOG_DEBUG(Cpu, "MMIO Read at " ADDRFMT " size %x", physicalAddress, size);
|
||||||
((Cpu *) user_data)->readmem(address, &value, size);
|
|
||||||
LOG_DEBUG(Cpu, "Stored value %x", (int) ((Cpu *) user_data)->read8(address));
|
uint64_t ovalue;
|
||||||
|
if(mmio->read(physicalAddress, size, ovalue)) {
|
||||||
|
switch(size) {
|
||||||
|
case 1:
|
||||||
|
cpu->guestptr<uint8_t>(address) = (uint8_t) ovalue;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
cpu->guestptr<uint16_t>(address) = (uint16_t) ovalue;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
cpu->guestptr<uint32_t>(address) = (uint32_t) ovalue;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
cpu->guestptr<uint64_t>(address) = ovalue;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case UC_MEM_WRITE:
|
case UC_MEM_WRITE:
|
||||||
LOG_DEBUG(Cpu, "MMIO Write at " ADDRFMT " size %x data %lx", physicalAddress, size, value);
|
LOG_DEBUG(Cpu, "MMIO Write at " ADDRFMT " size %x data %lx", physicalAddress, size, value);
|
||||||
/*if() {
|
mmio->write(physicalAddress, size, value);
|
||||||
((Cpu *) user_data)->writemem(address, &value, size);
|
|
||||||
}*/
|
|
||||||
//mmio->swrite(physicalAddress, size, &value);
|
|
||||||
((Cpu *) user_data)->writemem(address, &value, size);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,6 +54,21 @@ void codeBpHook(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
|
||||||
ctu->gdbStub._break();
|
ctu->gdbStub._break();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void memBpHook(uc_engine *uc, uc_mem_type type, uint64_t address, uint32_t size, uint64_t value, void *user_data) {
|
||||||
|
auto ctu = (Ctu *) user_data;
|
||||||
|
if(ctu->cpu.hitMemBreakpoint) {
|
||||||
|
ctu->cpu.hitMemBreakpoint = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cout << "Hit memory breakpoint accessing ... " << hex << address << endl;
|
||||||
|
auto thread = ctu->tm.current();
|
||||||
|
assert(thread != nullptr);
|
||||||
|
ctu->tm.requeue();
|
||||||
|
ctu->cpu.stop();
|
||||||
|
ctu->gdbStub._break(true);
|
||||||
|
ctu->cpu.hitMemBreakpoint = true;
|
||||||
|
}
|
||||||
|
|
||||||
Cpu::Cpu(Ctu *_ctu) : ctu(_ctu) {
|
Cpu::Cpu(Ctu *_ctu) : ctu(_ctu) {
|
||||||
CHECKED(uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc));
|
CHECKED(uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc));
|
||||||
|
|
||||||
|
@ -55,6 +84,8 @@ Cpu::Cpu(Ctu *_ctu) : ctu(_ctu) {
|
||||||
|
|
||||||
for(auto i = 0; i < 0x80; ++i)
|
for(auto i = 0; i < 0x80; ++i)
|
||||||
svcHandlers[i] = nullptr;
|
svcHandlers[i] = nullptr;
|
||||||
|
|
||||||
|
hitMemBreakpoint = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cpu::~Cpu() {
|
Cpu::~Cpu() {
|
||||||
|
@ -306,9 +337,21 @@ bool Cpu::unmappedHook(uc_mem_type type, gptr addr, int size, guint value) {
|
||||||
break;
|
break;
|
||||||
case UC_MEM_WRITE_UNMAPPED:
|
case UC_MEM_WRITE_UNMAPPED:
|
||||||
case UC_MEM_WRITE_PROT:
|
case UC_MEM_WRITE_PROT:
|
||||||
LOG_INFO(Cpu, "Attempted to write to %s memory at " ADDRFMT " from " ADDRFMT, (type == UC_MEM_READ_UNMAPPED ? "unmapped" : "protected"), addr, pc());
|
LOG_INFO(Cpu, "Attempted to write " LONGFMT " to %s memory at " ADDRFMT " from " ADDRFMT, value, (type == UC_MEM_READ_UNMAPPED ? "unmapped" : "protected"), addr, pc());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if(ctu->gdbStub.enabled) {
|
||||||
|
auto thread = ctu->tm.current();
|
||||||
|
if(thread == nullptr)
|
||||||
|
return false;
|
||||||
|
ctu->tm.requeue();
|
||||||
|
ctu->gdbStub._break(false);
|
||||||
|
if(type == UC_MEM_FETCH_PROT || type == UC_MEM_FETCH_UNMAPPED)
|
||||||
|
pc(TERMADDR);
|
||||||
|
else
|
||||||
|
stop();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -328,6 +371,14 @@ hook_t Cpu::addCodeBreakpoint(gptr addr) {
|
||||||
return hookHandle;
|
return hookHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cpu::removeCodeBreakpoint(hook_t hook) {
|
hook_t Cpu::addMemoryBreakpoint(gptr addr, guint len, BreakpointType type) {
|
||||||
|
assert(ctu->gdbStub.enabled);
|
||||||
|
|
||||||
|
hook_t hookHandle;
|
||||||
|
CHECKED(uc_hook_add(uc, &hookHandle, ((type == BreakpointType::Read || type == BreakpointType::Access) ? UC_HOOK_MEM_READ : 0) | ((type == BreakpointType::Write || type == BreakpointType::Access) ? UC_HOOK_MEM_WRITE : 0), (void *)memBpHook, ctu, addr, addr + len));
|
||||||
|
return hookHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cpu::removeBreakpoint(hook_t hook) {
|
||||||
CHECKED(uc_hook_del(uc, hook));
|
CHECKED(uc_hook_del(uc, hook));
|
||||||
}
|
}
|
||||||
|
|
9
Cpu.h
9
Cpu.h
|
@ -46,7 +46,8 @@ public:
|
||||||
void registerSvcHandler(int num, std::function<void(Cpu *)> handler);
|
void registerSvcHandler(int num, std::function<void(Cpu *)> handler);
|
||||||
|
|
||||||
hook_t addCodeBreakpoint(gptr addr);
|
hook_t addCodeBreakpoint(gptr addr);
|
||||||
void removeCodeBreakpoint(hook_t hook);
|
hook_t addMemoryBreakpoint(gptr addr, guint len, BreakpointType type);
|
||||||
|
void removeBreakpoint(hook_t hook);
|
||||||
|
|
||||||
void interruptHook(uint32_t intNo);
|
void interruptHook(uint32_t intNo);
|
||||||
bool unmappedHook(uc_mem_type type, gptr addr, int size, guint value);
|
bool unmappedHook(uc_mem_type type, gptr addr, int size, guint value);
|
||||||
|
@ -54,6 +55,8 @@ public:
|
||||||
void setMmio(Mmio *_mmioHandler);// { mmioHandler = _mmioHandler; }
|
void setMmio(Mmio *_mmioHandler);// { mmioHandler = _mmioHandler; }
|
||||||
Mmio *mmioHandler;
|
Mmio *mmioHandler;
|
||||||
|
|
||||||
|
bool hitMemBreakpoint;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ctu *ctu;
|
Ctu *ctu;
|
||||||
uc_engine *uc;
|
uc_engine *uc;
|
||||||
|
@ -85,6 +88,10 @@ public:
|
||||||
return *Guest<T>(cpu, addr + i * sizeof(T));
|
return *Guest<T>(cpu, addr + i * sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const T &operator[](unsigned int i) {
|
||||||
|
return *Guest<T>(cpu, addr + i * sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
Guest<T> operator+(const int &i) {
|
Guest<T> operator+(const int &i) {
|
||||||
return Guest<T>(cpu, addr + i * sizeof(T));
|
return Guest<T>(cpu, addr + i * sizeof(T));
|
||||||
}
|
}
|
||||||
|
|
2
Ctu.cpp
2
Ctu.cpp
|
@ -11,8 +11,8 @@ void Ctu::execProgram(gptr ep) {
|
||||||
auto ss = 8 * 1024 * 1024;
|
auto ss = 8 * 1024 * 1024;
|
||||||
|
|
||||||
cpu.map(sp - ss, ss);
|
cpu.map(sp - ss, ss);
|
||||||
cpu.setMmio(&mmiohandler);
|
|
||||||
mmiohandler.MMIOInitialize();
|
mmiohandler.MMIOInitialize();
|
||||||
|
cpu.setMmio(&mmiohandler);
|
||||||
|
|
||||||
auto mainThread = tm.create(ep, sp);
|
auto mainThread = tm.create(ep, sp);
|
||||||
mainThread->regs.X1 = mainThread->handle;
|
mainThread->regs.X1 = mainThread->handle;
|
||||||
|
|
50
Ctu.h
50
Ctu.h
|
@ -81,14 +81,56 @@ extern LogLevel g_LogLevel;
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
class Ctu;
|
class Ctu;
|
||||||
|
class LogMessage;
|
||||||
|
|
||||||
|
enum class BreakpointType {
|
||||||
|
None,
|
||||||
|
Execute,
|
||||||
|
Read,
|
||||||
|
Write,
|
||||||
|
Access
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float64_t low;
|
||||||
|
float64_t high;
|
||||||
|
} float128;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
guint SP, PC, NZCV;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
guint gprs[31];
|
||||||
|
float128 fprs[32];
|
||||||
|
};
|
||||||
|
struct {
|
||||||
|
guint X0, X1, X2, X3,
|
||||||
|
X4, X5, X6, X7,
|
||||||
|
X8, X9, X10, X11,
|
||||||
|
X12, X13, X14, X15,
|
||||||
|
X16, X17, X18, X19,
|
||||||
|
X20, X21, X22, X23,
|
||||||
|
X24, X25, X26, X27,
|
||||||
|
X28, X29, X30;
|
||||||
|
float128 Q0, Q1, Q2, Q3,
|
||||||
|
Q4, Q5, Q6, Q7,
|
||||||
|
Q8, Q9, Q10, Q11,
|
||||||
|
Q12, Q13, Q14, Q15,
|
||||||
|
Q16, Q17, Q18, Q19,
|
||||||
|
Q20, Q21, Q22, Q23,
|
||||||
|
Q24, Q25, Q26, Q27,
|
||||||
|
Q28, Q29, Q30, Q31;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
} ThreadRegisters;
|
||||||
|
|
||||||
#include "optionparser.h"
|
#include "optionparser.h"
|
||||||
#include "Lisparser.h"
|
#include "Lisparser.h"
|
||||||
#include "KObject.h"
|
#include "KObject.h"
|
||||||
#include "ThreadManager.h"
|
|
||||||
#include "Mmio.h"
|
#include "Mmio.h"
|
||||||
#include "Cpu.h"
|
#include "Cpu.h"
|
||||||
#include "Sync.h"
|
#include "Sync.h"
|
||||||
|
#include "ThreadManager.h"
|
||||||
#include "Svc.h"
|
#include "Svc.h"
|
||||||
#include "Ipc.h"
|
#include "Ipc.h"
|
||||||
#include "Nxo.h"
|
#include "Nxo.h"
|
||||||
|
@ -131,6 +173,7 @@ public:
|
||||||
ghandle newHandle(shared_ptr<T> obj) {
|
ghandle newHandle(shared_ptr<T> obj) {
|
||||||
static_assert(std::is_base_of<KObject, T>::value, "T must derive from KObject");
|
static_assert(std::is_base_of<KObject, T>::value, "T must derive from KObject");
|
||||||
auto hnd = handleId++;
|
auto hnd = handleId++;
|
||||||
|
LOG_DEBUG(Ctu, "Creating handle %x", hnd);
|
||||||
handles[hnd] = dynamic_pointer_cast<KObject>(obj);
|
handles[hnd] = dynamic_pointer_cast<KObject>(obj);
|
||||||
return hnd;
|
return hnd;
|
||||||
}
|
}
|
||||||
|
@ -148,11 +191,14 @@ public:
|
||||||
LOG_ERROR(Ctu, "Got null pointer after cast. Before: 0x%p", (void *) obj.get());
|
LOG_ERROR(Ctu, "Got null pointer after cast. Before: 0x%p", (void *) obj.get());
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
bool hasHandle(ghandle handle) {
|
||||||
|
return handles.find(handle) != handles.end();
|
||||||
|
}
|
||||||
ghandle duplicateHandle(KObject *ptr);
|
ghandle duplicateHandle(KObject *ptr);
|
||||||
void deleteHandle(ghandle handle);
|
void deleteHandle(ghandle handle);
|
||||||
|
|
||||||
Mmio mmiohandler;
|
|
||||||
Cpu cpu;
|
Cpu cpu;
|
||||||
|
Mmio mmiohandler;
|
||||||
Svc svc;
|
Svc svc;
|
||||||
Ipc ipc;
|
Ipc ipc;
|
||||||
ThreadManager tm;
|
ThreadManager tm;
|
||||||
|
|
2
DEPS.txt
Normal file
2
DEPS.txt
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
https://github.com/lz4/lz4.git
|
||||||
|
https://pypi.python.org/pypi/tatsu/4.0.0
|
|
@ -177,6 +177,7 @@ void GdbStub::enable(uint16_t port) {
|
||||||
|
|
||||||
enabled = true;
|
enabled = true;
|
||||||
haltLoop = true;
|
haltLoop = true;
|
||||||
|
remoteBreak = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t GdbStub::readByte() {
|
uint8_t GdbStub::readByte() {
|
||||||
|
@ -244,7 +245,7 @@ void GdbStub::removeBreakpoint(BreakpointType type, gptr addr) {
|
||||||
if(bp != p.end()) {
|
if(bp != p.end()) {
|
||||||
LOG_DEBUG(GdbStub, "gdb: removed a breakpoint: %016lx bytes at %016lx of type %d",
|
LOG_DEBUG(GdbStub, "gdb: removed a breakpoint: %016lx bytes at %016lx of type %d",
|
||||||
bp->second.len, bp->second.addr, type);
|
bp->second.len, bp->second.addr, type);
|
||||||
ctu->cpu.removeCodeBreakpoint(bp->second.hook);
|
ctu->cpu.removeBreakpoint(bp->second.hook);
|
||||||
p.erase(addr);
|
p.erase(addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -379,7 +380,7 @@ void GdbStub::readCommand() {
|
||||||
} else if(c == 0x03) {
|
} else if(c == 0x03) {
|
||||||
LOG_INFO(GdbStub, "gdb: found break command");
|
LOG_INFO(GdbStub, "gdb: found break command");
|
||||||
haltLoop = true;
|
haltLoop = true;
|
||||||
sendSignal(SIGTRAP);
|
remoteBreak = true;
|
||||||
return;
|
return;
|
||||||
} else if(c != GDB_STUB_START) {
|
} else if(c != GDB_STUB_START) {
|
||||||
LOG_DEBUG(GdbStub, "gdb: read invalid byte %02x", c);
|
LOG_DEBUG(GdbStub, "gdb: read invalid byte %02x", c);
|
||||||
|
@ -574,6 +575,8 @@ bool GdbStub::commitBreakpoint(BreakpointType type, gptr addr, uint32_t len) {
|
||||||
|
|
||||||
if(type == BreakpointType::Execute)
|
if(type == BreakpointType::Execute)
|
||||||
breakpoint.hook = ctu->cpu.addCodeBreakpoint(addr);
|
breakpoint.hook = ctu->cpu.addCodeBreakpoint(addr);
|
||||||
|
else
|
||||||
|
breakpoint.hook = ctu->cpu.addMemoryBreakpoint(addr, len, type);
|
||||||
|
|
||||||
p.insert({addr, breakpoint});
|
p.insert({addr, breakpoint});
|
||||||
|
|
||||||
|
|
13
GdbStub.h
13
GdbStub.h
|
@ -11,15 +11,6 @@
|
||||||
|
|
||||||
#define GDB_BUFFER_SIZE 10000
|
#define GDB_BUFFER_SIZE 10000
|
||||||
|
|
||||||
/// Breakpoint Method
|
|
||||||
enum class BreakpointType {
|
|
||||||
None,
|
|
||||||
Execute,
|
|
||||||
Read,
|
|
||||||
Write,
|
|
||||||
Access
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BreakpointAddress {
|
struct BreakpointAddress {
|
||||||
gptr address;
|
gptr address;
|
||||||
BreakpointType type;
|
BreakpointType type;
|
||||||
|
@ -41,8 +32,9 @@ public:
|
||||||
void handlePacket();
|
void handlePacket();
|
||||||
auto getNextBreakpointFromAddress(gptr addr, BreakpointType type);
|
auto getNextBreakpointFromAddress(gptr addr, BreakpointType type);
|
||||||
bool checkBreakpoint(gptr addr, BreakpointType type);
|
bool checkBreakpoint(gptr addr, BreakpointType type);
|
||||||
|
void sendSignal(uint32_t signal);
|
||||||
|
|
||||||
bool memoryBreak, haltLoop, stepLoop, enabled;
|
bool memoryBreak, haltLoop, stepLoop, remoteBreak, enabled;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
auto& getBreakpointList(BreakpointType type);
|
auto& getBreakpointList(BreakpointType type);
|
||||||
|
@ -52,7 +44,6 @@ private:
|
||||||
void sendReply(const char* reply);
|
void sendReply(const char* reply);
|
||||||
void handleQuery();
|
void handleQuery();
|
||||||
void handleSetThread();
|
void handleSetThread();
|
||||||
void sendSignal(uint32_t signal);
|
|
||||||
void readCommand();
|
void readCommand();
|
||||||
bool isDataAvailable();
|
bool isDataAvailable();
|
||||||
void readRegister();
|
void readRegister();
|
||||||
|
|
12
Ipc.cpp
12
Ipc.cpp
|
@ -137,7 +137,7 @@ void OutgoingIpcMessage::initialize(uint _moveCount, uint _copyCount, uint dataB
|
||||||
auto dataWords = (realDataOffset >> 2) + (dataBytes & 3) ? (dataBytes >> 2) + 1 : (dataBytes >> 2);
|
auto dataWords = (realDataOffset >> 2) + (dataBytes & 3) ? (dataBytes >> 2) + 1 : (dataBytes >> 2);
|
||||||
|
|
||||||
buf[1] |= 4 + (isDomainObject ? 4 : 0) + 4 + dataWords;
|
buf[1] |= 4 + (isDomainObject ? 4 : 0) + 4 + dataWords;
|
||||||
|
|
||||||
sfcoOffset = pos * 4;
|
sfcoOffset = pos * 4;
|
||||||
buf[pos] = FOURCC('S', 'F', 'C', 'O');
|
buf[pos] = FOURCC('S', 'F', 'C', 'O');
|
||||||
}
|
}
|
||||||
|
@ -167,7 +167,7 @@ uint32_t IpcService::messageSync(shared_ptr<array<uint8_t, 0x100>> buf, bool& cl
|
||||||
closeHandle = true;
|
closeHandle = true;
|
||||||
resp.initialize(0, 0, 0);
|
resp.initialize(0, 0, 0);
|
||||||
resp.errCode = 0;
|
resp.errCode = 0;
|
||||||
ret = 0;
|
ret = 0x25a0b;
|
||||||
break;
|
break;
|
||||||
case 4: // Normal
|
case 4: // Normal
|
||||||
ret = target->dispatch(msg, resp);
|
ret = target->dispatch(msg, resp);
|
||||||
|
@ -197,6 +197,14 @@ uint32_t IpcService::messageSync(shared_ptr<array<uint8_t, 0x100>> buf, bool& cl
|
||||||
resp.errCode = 0;
|
resp.errCode = 0;
|
||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
|
case 4: // DuplicateSession
|
||||||
|
LOG_DEBUG(Ipc, "DuplicateSessionEx");
|
||||||
|
resp.isDomainObject = false;
|
||||||
|
resp.initialize(1, 0, 0);
|
||||||
|
resp.move(0, ctu->duplicateHandle(dynamic_cast<KObject *>(this)));
|
||||||
|
resp.errCode = 0;
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_ERROR(Ipc, "Unknown cmdId to control %u", msg.cmdId);
|
LOG_ERROR(Ipc, "Unknown cmdId to control %u", msg.cmdId);
|
||||||
}
|
}
|
||||||
|
|
7
Ipc.h
7
Ipc.h
|
@ -109,6 +109,13 @@ public:
|
||||||
return (T) (ptr + sfciOffset + 8 + offset);
|
return (T) (ptr + sfciOffset + 8 + offset);
|
||||||
}
|
}
|
||||||
gptr getBuffer(int btype, int num, guint& size) {
|
gptr getBuffer(int btype, int num, guint& size) {
|
||||||
|
if(btype & 0x20) {
|
||||||
|
auto buf = getBuffer((btype & ~0x20) | 4, num, size);
|
||||||
|
if(size != 0)
|
||||||
|
return buf;
|
||||||
|
return getBuffer((btype & ~0x20) | 8, num, size);
|
||||||
|
}
|
||||||
|
|
||||||
size = 0;
|
size = 0;
|
||||||
auto ax = (btype & 3) == 1;
|
auto ax = (btype & 3) == 1;
|
||||||
auto flags_ = btype & 0xC0;
|
auto flags_ = btype & 0xC0;
|
||||||
|
|
65
Mmio.cpp
65
Mmio.cpp
|
@ -1,25 +1,74 @@
|
||||||
#include "Ctu.h"
|
#include "Ctu.h"
|
||||||
|
|
||||||
Mmio::Mmio(Ctu *_ctu) {
|
class ApbMmio : public MmioBase {
|
||||||
MMIORegister(0x70000000, 0x1000, new ApbMmio());
|
public:
|
||||||
|
bool read(gptr addr, guint size, uint64_t &value) {
|
||||||
|
switch(addr) {
|
||||||
|
case 0x70000804: // TEGRA_APB_MISC_BASE | APB_MISC_GP_HIDREV
|
||||||
|
value = 0x2100;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool write(gptr addr, guint size, uint64_t value) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class FuseMmio : public MmioBase {
|
||||||
|
public:
|
||||||
|
bool read(gptr addr, guint size, uint64_t &value) {
|
||||||
|
switch(addr) {
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool write(gptr addr, guint size, uint64_t value) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class GpuMmio : public MmioBase {
|
||||||
|
public:
|
||||||
|
bool read(gptr addr, guint size, uint64_t &value) {
|
||||||
|
switch(addr) {
|
||||||
|
case 0x57000000:
|
||||||
|
// boot 0: NVGPU_GPU_ARCH_GM200 | NVGPU_GPU_IMPL_GM20B | revision A1
|
||||||
|
value = ((0x120 | 0xB) << 20) | 0xA1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool write(gptr addr, guint size, uint64_t value) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Mmio::Mmio(Ctu *_ctu) {
|
||||||
|
MMIORegister(0x50000000, 0x24000, new MmioBase());
|
||||||
|
MMIORegister(0x54200000, 0x400000, new MmioBase());
|
||||||
|
MMIORegister(0x57000000, 0x1000000, new GpuMmio());
|
||||||
|
MMIORegister(0x58000000, 0x1000000, new GpuMmio());
|
||||||
|
MMIORegister(0x70000000, 0x1000, new ApbMmio());
|
||||||
|
MMIORegister(0x7000f800, 0x400, new FuseMmio());
|
||||||
MMIORegister(0x702ec000, 0x2000, new ApbMmio());
|
MMIORegister(0x702ec000, 0x2000, new ApbMmio());
|
||||||
MMIORegister(0x70030000, 0x8000, new ApbMmio());
|
MMIORegister(0x70030000, 0x8000, new ApbMmio());
|
||||||
|
MMIORegister(0x700e3000, 0x100, new ApbMmio());
|
||||||
MMIORegister(0x702ef700, 0x40, new ApbMmio());
|
MMIORegister(0x702ef700, 0x40, new ApbMmio());
|
||||||
MMIORegister(0x702f9000, 0x1000, new ApbMmio());
|
MMIORegister(0x702f9000, 0x1000, new ApbMmio());
|
||||||
|
|
||||||
//MMIORegister(0x70030000, 0x8000, new ApbMmio());
|
//MMIORegister(0x70030000, 0x8000, new ApbMmio());
|
||||||
ctu = _ctu;
|
ctu = _ctu;
|
||||||
//MMIOInitialize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mmio::MMIORegister(gptr base, guint size, MmioBase *mmioBase) {
|
void Mmio::MMIORegister(gptr base, guint size, MmioBase *mmioBase) {
|
||||||
LOG_DEBUG(Mmio, "Registered MMIO " ADDRFMT, base);
|
LOG_DEBUG(Mmio, "Registered MMIO " ADDRFMT, base);
|
||||||
mmioBase->setSize(size);
|
mmioBase->setSize(size);
|
||||||
|
|
||||||
mmioBases[base] = mmioBase;
|
mmioBases[base] = mmioBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mmio::MMIOInitialize() {
|
void Mmio::MMIOInitialize() {
|
||||||
|
mmioBaseSize = 0;
|
||||||
for(auto item : mmioBases) {
|
for(auto item : mmioBases) {
|
||||||
item.second->setOffset(mmioBaseSize);
|
item.second->setOffset(mmioBaseSize);
|
||||||
mmioBaseSize += item.second->mmioSize;
|
mmioBaseSize += item.second->mmioSize;
|
||||||
|
@ -33,8 +82,8 @@ void Mmio::MMIOInitialize() {
|
||||||
|
|
||||||
gptr Mmio::getVirtualAddressFromAddr(gptr addr) {
|
gptr Mmio::getVirtualAddressFromAddr(gptr addr) {
|
||||||
for(auto item : mmioBases) {
|
for(auto item : mmioBases) {
|
||||||
if(addr >= item.first && addr <= (item.first+item.second->mmioSize)) {
|
if(addr >= item.first && addr < item.first + item.second->mmioSize) {
|
||||||
return mmioBaseAddr+item.second->offsetFromMMIO;
|
return mmioBaseAddr + item.second->offsetFromMMIO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0x0;
|
return 0x0;
|
||||||
|
@ -44,8 +93,8 @@ gptr Mmio::getPhysicalAddressFromVirtual(gptr addr) {
|
||||||
if(addr < mmioBaseAddr) return 0x0;
|
if(addr < mmioBaseAddr) return 0x0;
|
||||||
gptr offset = addr - mmioBaseAddr;
|
gptr offset = addr - mmioBaseAddr;
|
||||||
for(auto item : mmioBases) {
|
for(auto item : mmioBases) {
|
||||||
if(item.second->offsetFromMMIO >= offset && offset <= item.second->offsetFromMMIO+item.second->mmioSize) {
|
if(item.second->offsetFromMMIO <= offset && offset < item.second->offsetFromMMIO + item.second->mmioSize) {
|
||||||
return item.first+offset;
|
return item.first + offset - item.second->offsetFromMMIO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0x0;
|
return 0x0;
|
||||||
|
@ -56,7 +105,7 @@ MmioBase *Mmio::getMMIOFromPhysicalAddress(gptr addr) {
|
||||||
if(addr < mmioBaseAddr) return nullptr;
|
if(addr < mmioBaseAddr) return nullptr;
|
||||||
gptr offset = addr - mmioBaseAddr;
|
gptr offset = addr - mmioBaseAddr;
|
||||||
for(auto item : mmioBases) {
|
for(auto item : mmioBases) {
|
||||||
if(item.second->offsetFromMMIO >= offset && offset <= item.second->offsetFromMMIO+item.second->mmioSize) {
|
if(item.second->offsetFromMMIO <= offset && offset < item.second->offsetFromMMIO + item.second->mmioSize) {
|
||||||
return item.second;
|
return item.second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
16
Mmio.h
16
Mmio.h
|
@ -12,11 +12,10 @@ public:
|
||||||
}
|
}
|
||||||
void Setup();
|
void Setup();
|
||||||
|
|
||||||
virtual bool sread(gptr addr, guint size, void *out) {
|
virtual bool read(gptr addr, guint size, uint64_t &value) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
virtual bool swrite(gptr addr, guint size, void *value) {
|
virtual bool write(gptr addr, guint size, uint64_t value) {
|
||||||
cout << "no" << endl;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,14 +57,3 @@ private:
|
||||||
guint mmioBaseSize = 0;
|
guint mmioBaseSize = 0;
|
||||||
unordered_map<gptr, MmioBase *> mmioBases;
|
unordered_map<gptr, MmioBase *> mmioBases;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ApbMmio : public MmioBase {
|
|
||||||
public:
|
|
||||||
bool sread(gptr addr, guint size, void *out) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool swrite(gptr addr, guint size, void *value) {
|
|
||||||
//*value = 0xdeadbeef;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
67
Svc.cpp
67
Svc.cpp
|
@ -64,6 +64,8 @@
|
||||||
}); \
|
}); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
#define UNIMPLEMENTED(svc) do { LOG_ERROR(Svc[svc], "!Unimplemented!"); } while(0)
|
||||||
|
|
||||||
Svc::Svc(Ctu *_ctu) : ctu(_ctu) {
|
Svc::Svc(Ctu *_ctu) : ctu(_ctu) {
|
||||||
registerSvc_ret_X0_X1( 0x01, SetHeapSize, IX1);
|
registerSvc_ret_X0_X1( 0x01, SetHeapSize, IX1);
|
||||||
registerSvc_ret_X0( 0x03, SetMemoryAttribute, IX0, IX1, IX2, IX3);
|
registerSvc_ret_X0( 0x03, SetMemoryAttribute, IX0, IX1, IX2, IX3);
|
||||||
|
@ -111,9 +113,9 @@ Svc::Svc(Ctu *_ctu) : ctu(_ctu) {
|
||||||
registerSvc_ret_X0_X1( 0x53, CreateInterruptEvent, IX1);
|
registerSvc_ret_X0_X1( 0x53, CreateInterruptEvent, IX1);
|
||||||
registerSvc_ret_X0_X1( 0x55, QueryIoMapping, IX1, IX2);
|
registerSvc_ret_X0_X1( 0x55, QueryIoMapping, IX1, IX2);
|
||||||
registerSvc_ret_X0_X1( 0x56, CreateDeviceAddressSpace, IX1, IX2);
|
registerSvc_ret_X0_X1( 0x56, CreateDeviceAddressSpace, IX1, IX2);
|
||||||
registerSvc_ret_X0_X1( 0x57, AttachDeviceAddressSpace, (ghandle) IX0, IX1, IX2);
|
registerSvc_ret_X0( 0x57, AttachDeviceAddressSpace, IX0, (ghandle) IX1);
|
||||||
registerSvc_ret_X0_X1( 0x59, MapDeviceAddressSpaceByForce, (ghandle) IX0, (ghandle) IX1, IX2, IX3, IX4, IX5);
|
registerSvc_ret_X0( 0x59, MapDeviceAddressSpaceByForce, (ghandle) IX0, (ghandle) IX1, IX2, IX3, IX4, IX5);
|
||||||
registerSvc_ret_X0( 0x5c, UnmapDeviceAddressSpace, IX0, (ghandle) IX1, IX2, IX3);
|
registerSvc_ret_X0( 0x5c, UnmapDeviceAddressSpace, IX0, (ghandle) IX1, IX2, IX3, IX4);
|
||||||
registerSvc_ret_X0( 0x74, MapProcessMemory, IX0, (ghandle) IX1, IX2, IX3);
|
registerSvc_ret_X0( 0x74, MapProcessMemory, IX0, (ghandle) IX1, IX2, IX3);
|
||||||
registerSvc_ret_X0( 0x75, UnmapProcessMemory, IX0, (ghandle) IX1, IX2, IX3);
|
registerSvc_ret_X0( 0x75, UnmapProcessMemory, IX0, (ghandle) IX1, IX2, IX3);
|
||||||
registerSvc_ret_X0( 0x77, MapProcessCodeMemory, (ghandle) IX0, IX1, IX2, IX3);
|
registerSvc_ret_X0( 0x77, MapProcessCodeMemory, (ghandle) IX0, IX1, IX2, IX3);
|
||||||
|
@ -144,6 +146,7 @@ guint Svc::MirrorStack(gptr dest, gptr src, guint size) {
|
||||||
|
|
||||||
guint Svc::UnmapMemory(gptr dest, gptr src, guint size) {
|
guint Svc::UnmapMemory(gptr dest, gptr src, guint size) {
|
||||||
LOG_DEBUG(Svc[0x05], "UnmapMemory 0x" ADDRFMT " 0x" ADDRFMT " - 0x" LONGFMT, dest, src, size);
|
LOG_DEBUG(Svc[0x05], "UnmapMemory 0x" ADDRFMT " 0x" ADDRFMT " - 0x" LONGFMT, dest, src, size);
|
||||||
|
ctu->cpu.unmap(dest, size);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,6 +241,7 @@ guint Svc::GetCurrentProcessorNumber(guint tmp) {
|
||||||
|
|
||||||
guint Svc::SignalEvent(ghandle handle) {
|
guint Svc::SignalEvent(ghandle handle) {
|
||||||
LOG_DEBUG(Svc[0x11], "SignalEvent 0x%x", handle);
|
LOG_DEBUG(Svc[0x11], "SignalEvent 0x%x", handle);
|
||||||
|
UNIMPLEMENTED(0x11);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,10 +261,10 @@ guint Svc::MapMemoryBlock(ghandle handle, gptr addr, guint size, guint perm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
tuple<guint, guint> Svc::CreateTransferMemory(gptr addr, guint size, guint perm) {
|
tuple<guint, guint> Svc::CreateTransferMemory(gptr addr, guint size, guint perm) {
|
||||||
LOG_DEBUG(Svc[0x15], "CreateTransferMemory 0x" LONGFMT " 0x" LONGFMT " 0x" LONGFMT, addr, size, perm);
|
LOG_DEBUG(Svc[0x15], "CreateTransferMemory 0x" LONGFMT " 0x" LONGFMT " 0x" LONGFMT, addr, size, perm);
|
||||||
auto tm = make_shared<MemoryBlock>(size, perm);
|
auto tm = make_shared<MemoryBlock>(size, perm);
|
||||||
tm->addr = addr;
|
tm->addr = addr;
|
||||||
return make_tuple(0, ctu->newHandle(tm));
|
return make_tuple(0, ctu->newHandle(tm));
|
||||||
}
|
}
|
||||||
|
|
||||||
guint Svc::CloseHandle(ghandle handle) {
|
guint Svc::CloseHandle(ghandle handle) {
|
||||||
|
@ -271,6 +275,7 @@ guint Svc::CloseHandle(ghandle handle) {
|
||||||
|
|
||||||
guint Svc::ResetSignal(ghandle handle) {
|
guint Svc::ResetSignal(ghandle handle) {
|
||||||
LOG_DEBUG(Svc[0x17], "ResetSignal 0x%x", handle);
|
LOG_DEBUG(Svc[0x17], "ResetSignal 0x%x", handle);
|
||||||
|
UNIMPLEMENTED(0x17);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,6 +315,7 @@ tuple<guint, guint> Svc::WaitSynchronization(gptr handles, guint numHandles, gui
|
||||||
|
|
||||||
guint Svc::CancelSynchronization(ghandle handle) {
|
guint Svc::CancelSynchronization(ghandle handle) {
|
||||||
LOG_DEBUG(Svc[0x19], "CancelSynchronization 0x%x", handle);
|
LOG_DEBUG(Svc[0x19], "CancelSynchronization 0x%x", handle);
|
||||||
|
UNIMPLEMENTED(0x19);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -445,6 +451,7 @@ guint Svc::SendSyncRequest(ghandle handle) {
|
||||||
|
|
||||||
guint Svc::SendSyncRequestEx(gptr buf, guint size, ghandle handle) {
|
guint Svc::SendSyncRequestEx(gptr buf, guint size, ghandle handle) {
|
||||||
LOG_ERROR(Svc[0x22], "SendSyncRequestEx not implemented");
|
LOG_ERROR(Svc[0x22], "SendSyncRequestEx not implemented");
|
||||||
|
UNIMPLEMENTED(0x22);
|
||||||
return 0xf601;
|
return 0xf601;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -490,7 +497,7 @@ tuple<guint, guint> Svc::GetInfo(guint id1, ghandle handle, guint id2) {
|
||||||
matchpair(3, 0, 0x1000000000);
|
matchpair(3, 0, 0x1000000000);
|
||||||
matchpair(4, 0, 0xaa0000000);
|
matchpair(4, 0, 0xaa0000000);
|
||||||
matchpair(5, 0, ctu->heapsize); // Heap region size
|
matchpair(5, 0, ctu->heapsize); // Heap region size
|
||||||
matchpair(6, 0, 0x100000);
|
matchpair(6, 0, 0x400000);
|
||||||
matchpair(7, 0, 0x10000);
|
matchpair(7, 0, 0x10000);
|
||||||
matchpair(12, 0, 0x8000000);
|
matchpair(12, 0, 0x8000000);
|
||||||
matchpair(13, 0, 0x7ff8000000);
|
matchpair(13, 0, 0x7ff8000000);
|
||||||
|
@ -548,11 +555,11 @@ tuple<guint, guint> Svc::ReplyAndReceive(gptr handles, guint numHandles, ghandle
|
||||||
|
|
||||||
tuple<guint, guint, guint> Svc::CreateEvent(ghandle clientOut, ghandle serverOut, guint unk) {
|
tuple<guint, guint, guint> Svc::CreateEvent(ghandle clientOut, ghandle serverOut, guint unk) {
|
||||||
LOG_DEBUG(Svc[0x45], "CreateEvent");
|
LOG_DEBUG(Svc[0x45], "CreateEvent");
|
||||||
return make_tuple(0, 0, 0);
|
return make_tuple(0, ctu->newHandle(make_shared<Waitable>()), ctu->newHandle(make_shared<Waitable>()));
|
||||||
}
|
}
|
||||||
|
|
||||||
tuple<guint, guint> Svc::ReadWriteRegister(guint reg, guint rwm, guint val) {
|
tuple<guint, guint> Svc::ReadWriteRegister(guint reg, guint rwm, guint val) {
|
||||||
LOG_DEBUG(Svc[0x4E], "ReadWriteRegister");
|
LOG_DEBUG(Svc[0x4E], "ReadWriteRegister reg=" ADDRFMT " rwm=" LONGFMT " val=" LONGFMT, reg, rwm, val);
|
||||||
return make_tuple(0, 0);
|
return make_tuple(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -574,13 +581,14 @@ guint Svc::UnmapTransferMemory(ghandle handle, gptr addr, guint size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
tuple<guint, guint> Svc::CreateInterruptEvent(guint irq) {
|
tuple<guint, guint> Svc::CreateInterruptEvent(guint irq) {
|
||||||
LOG_DEBUG(Svc[0x53], "CreateInterruptEvent");
|
LOG_DEBUG(Svc[0x53], "CreateInterruptEvent irq=" LONGFMT, irq);
|
||||||
return make_tuple(0, 0);
|
return make_tuple(0, ctu->newHandle(make_shared<InstantWaitable>()));
|
||||||
}
|
}
|
||||||
|
|
||||||
tuple<guint, guint> Svc::QueryIoMapping(gptr physaddr, guint size) {
|
tuple<guint, guint> Svc::QueryIoMapping(gptr physaddr, guint size) {
|
||||||
LOG_DEBUG(Svc[0x55], "QueryIoMapping");
|
LOG_DEBUG(Svc[0x55], "QueryIoMapping " ADDRFMT " size " LONGFMT, physaddr, size);
|
||||||
gptr addr = ctu->mmiohandler.getVirtualAddressFromAddr(physaddr);
|
gptr addr = ctu->mmiohandler.getVirtualAddressFromAddr(physaddr);
|
||||||
|
LOG_DEBUG(Svc[0x55], ADDRFMT, addr);
|
||||||
if(addr == 0x0) { // force exit for now
|
if(addr == 0x0) { // force exit for now
|
||||||
cout << "!Unknown physical address!" << endl;
|
cout << "!Unknown physical address!" << endl;
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -588,23 +596,36 @@ tuple<guint, guint> Svc::QueryIoMapping(gptr physaddr, guint size) {
|
||||||
return make_tuple(0x0, addr);
|
return make_tuple(0x0, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
tuple<guint, guint> Svc::CreateDeviceAddressSpace(guint base, guint size) {
|
class DeviceMemory : public KObject {
|
||||||
LOG_DEBUG(Svc[0x56], "CreateDeviceAddressSpace");
|
public:
|
||||||
return make_tuple(0, 0);
|
DeviceMemory(gptr _start, gptr _end) : start(_start), end(_end) {
|
||||||
|
}
|
||||||
|
|
||||||
|
gptr start, end;
|
||||||
|
list<guint> devices;
|
||||||
|
};
|
||||||
|
|
||||||
|
tuple<guint, guint> Svc::CreateDeviceAddressSpace(gptr start, gptr end) {
|
||||||
|
LOG_DEBUG(Svc[0x56], "CreateDeviceAddressSpace start=" ADDRFMT " end=" ADDRFMT, start, end);
|
||||||
|
auto obj = make_shared<DeviceMemory>(start, end);
|
||||||
|
return make_tuple(0, ctu->newHandle(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
tuple<guint, guint> Svc::AttachDeviceAddressSpace(ghandle handle, guint dev, gptr addr) {
|
guint Svc::AttachDeviceAddressSpace(guint dev, ghandle handle) {
|
||||||
LOG_DEBUG(Svc[0x57], "AttachDeviceAddressSpace");
|
LOG_DEBUG(Svc[0x57], "AttachDeviceAddressSpace dev=" LONGFMT " handle=%x", dev, handle);
|
||||||
return make_tuple(0, 0);
|
auto obj = ctu->getHandle<DeviceMemory>(handle);
|
||||||
|
obj->devices.push_back(dev);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
tuple<guint, guint> Svc::MapDeviceAddressSpaceByForce(ghandle handle, ghandle phandle, gptr paddr, guint size, gptr maddr, guint perm) {
|
guint Svc::MapDeviceAddressSpaceByForce(ghandle handle, ghandle phandle, gptr vaddr, guint size, gptr saddr, guint perm) {
|
||||||
LOG_DEBUG(Svc[0x59], "MapDeviceAddressSpaceByForce");
|
LOG_DEBUG(Svc[0x59], "MapDeviceAddressSpaceByForce handle=%x phandle=%x vaddr=" ADDRFMT " size=" LONGFMT " saddr=" ADDRFMT " perm=" LONGFMT, handle, phandle, vaddr, size, saddr, perm);
|
||||||
return make_tuple(0, 0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
guint Svc::UnmapDeviceAddressSpace(guint unk0, ghandle phandle, gptr maddr, guint size) {
|
guint Svc::UnmapDeviceAddressSpace(guint unk0, ghandle phandle, gptr maddr, guint size, gptr paddr) {
|
||||||
LOG_DEBUG(Svc[0x5c], "UnmapDeviceAddressSpace");
|
LOG_DEBUG(Svc[0x5c], "UnmapDeviceAddressSpace");
|
||||||
|
UNIMPLEMENTED(0x5c);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
8
Svc.h
8
Svc.h
|
@ -67,10 +67,10 @@ private:
|
||||||
guint UnmapTransferMemory(ghandle handle, gptr addr, guint size); // 0x52
|
guint UnmapTransferMemory(ghandle handle, gptr addr, guint size); // 0x52
|
||||||
tuple<guint, guint> CreateInterruptEvent(guint irq); // 0x53
|
tuple<guint, guint> CreateInterruptEvent(guint irq); // 0x53
|
||||||
tuple<guint, guint> QueryIoMapping(gptr physaddr, guint size); // 0x55
|
tuple<guint, guint> QueryIoMapping(gptr physaddr, guint size); // 0x55
|
||||||
tuple<guint, guint> CreateDeviceAddressSpace(guint base, guint size); // 0x56
|
tuple<guint, guint> CreateDeviceAddressSpace(gptr start, gptr end); // 0x56
|
||||||
tuple<guint, guint> AttachDeviceAddressSpace(ghandle handle, guint dev, gptr addr); // 0x57
|
guint AttachDeviceAddressSpace(guint dev, ghandle handle); // 0x57
|
||||||
tuple<guint, guint> MapDeviceAddressSpaceByForce(ghandle handle, ghandle phandle, gptr paddr, guint size, gptr maddr, guint perm); // 0x59
|
guint MapDeviceAddressSpaceByForce(ghandle handle, ghandle phandle, gptr vaddr, guint size, gptr saddr, guint perm); // 0x59
|
||||||
guint UnmapDeviceAddressSpace(guint unk0, ghandle phandle, gptr maddr, guint size); // 0x5c
|
guint UnmapDeviceAddressSpace(guint unk0, ghandle phandle, gptr maddr, guint size, gptr paddr); // 0x5c
|
||||||
guint MapProcessMemory(gptr dstaddr, ghandle handle, gptr srcaddr, guint size); // 0x74
|
guint MapProcessMemory(gptr dstaddr, ghandle handle, gptr srcaddr, guint size); // 0x74
|
||||||
guint UnmapProcessMemory(gptr dstaddr, ghandle handle, gptr srcaddr, guint size); // 0x75
|
guint UnmapProcessMemory(gptr dstaddr, ghandle handle, gptr srcaddr, guint size); // 0x75
|
||||||
guint MapProcessCodeMemory(ghandle handle, gptr dstaddr, gptr srcaddr, guint size); // 0x77
|
guint MapProcessCodeMemory(ghandle handle, gptr dstaddr, gptr srcaddr, guint size); // 0x77
|
||||||
|
|
10
Sync.h
10
Sync.h
|
@ -10,7 +10,7 @@ public:
|
||||||
void release();
|
void release();
|
||||||
|
|
||||||
void wait(function<int()> cb);
|
void wait(function<int()> cb);
|
||||||
void wait(function<int(bool)> cb);
|
virtual void wait(function<int(bool)> cb);
|
||||||
|
|
||||||
void signal(bool one=false);
|
void signal(bool one=false);
|
||||||
void cancel();
|
void cancel();
|
||||||
|
@ -26,6 +26,14 @@ private:
|
||||||
bool presignaled, canceled;
|
bool presignaled, canceled;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class InstantWaitable : public Waitable {
|
||||||
|
public:
|
||||||
|
virtual void wait(function<int(bool)> cb) {
|
||||||
|
Waitable::wait(cb);
|
||||||
|
signal(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class Semaphore : public Waitable {
|
class Semaphore : public Waitable {
|
||||||
public:
|
public:
|
||||||
Semaphore(Guest<uint32_t> _vptr);
|
Semaphore(Guest<uint32_t> _vptr);
|
||||||
|
|
|
@ -18,6 +18,7 @@ void Thread::assignHandle(uint32_t _handle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Thread::terminate() {
|
void Thread::terminate() {
|
||||||
|
signal();
|
||||||
ctu->tm.terminate(id);
|
ctu->tm.terminate(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,6 +103,12 @@ void ThreadManager::start() {
|
||||||
while(true) {
|
while(true) {
|
||||||
if(ctu->gdbStub.enabled) {
|
if(ctu->gdbStub.enabled) {
|
||||||
ctu->gdbStub.handlePacket();
|
ctu->gdbStub.handlePacket();
|
||||||
|
if(ctu->gdbStub.remoteBreak) {
|
||||||
|
ctu->gdbStub.remoteBreak = false;
|
||||||
|
if(_current != nullptr)
|
||||||
|
_current->freeze();
|
||||||
|
ctu->gdbStub.sendSignal(SIGTRAP);
|
||||||
|
}
|
||||||
if(ctu->gdbStub.haltLoop && !ctu->gdbStub.stepLoop)
|
if(ctu->gdbStub.haltLoop && !ctu->gdbStub.stepLoop)
|
||||||
continue;
|
continue;
|
||||||
auto wasStep = ctu->gdbStub.stepLoop;
|
auto wasStep = ctu->gdbStub.stepLoop;
|
||||||
|
|
|
@ -1,40 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Ctu.h"
|
#include "Ctu.h"
|
||||||
|
|
||||||
typedef struct {
|
class Thread : public Waitable {
|
||||||
float64_t low;
|
|
||||||
float64_t high;
|
|
||||||
} float128;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
guint SP, PC, NZCV;
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
guint gprs[31];
|
|
||||||
float128 fprs[32];
|
|
||||||
};
|
|
||||||
struct {
|
|
||||||
guint X0, X1, X2, X3,
|
|
||||||
X4, X5, X6, X7,
|
|
||||||
X8, X9, X10, X11,
|
|
||||||
X12, X13, X14, X15,
|
|
||||||
X16, X17, X18, X19,
|
|
||||||
X20, X21, X22, X23,
|
|
||||||
X24, X25, X26, X27,
|
|
||||||
X28, X29, X30;
|
|
||||||
float128 Q0, Q1, Q2, Q3,
|
|
||||||
Q4, Q5, Q6, Q7,
|
|
||||||
Q8, Q9, Q10, Q11,
|
|
||||||
Q12, Q13, Q14, Q15,
|
|
||||||
Q16, Q17, Q18, Q19,
|
|
||||||
Q20, Q21, Q22, Q23,
|
|
||||||
Q24, Q25, Q26, Q27,
|
|
||||||
Q28, Q29, Q30, Q31;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
} ThreadRegisters;
|
|
||||||
|
|
||||||
class Thread : public KObject {
|
|
||||||
public:
|
public:
|
||||||
Thread(Ctu *_ctu, int _id);
|
Thread(Ctu *_ctu, int _id);
|
||||||
void assignHandle(ghandle handle);
|
void assignHandle(ghandle handle);
|
||||||
|
|
3914
genallipc.py
3914
genallipc.py
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,7 @@
|
||||||
import glob, hashlib, json, os, os.path, re, sys
|
import glob, hashlib, json, os, os.path, re, sys
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
import idparser, partialparser
|
import idparser, partialparser
|
||||||
|
from cStringIO import StringIO
|
||||||
|
|
||||||
def emitInt(x):
|
def emitInt(x):
|
||||||
return '0x%x' % x if x > 9 else str(x)
|
return '0x%x' % x if x > 9 else str(x)
|
||||||
|
@ -115,6 +116,7 @@ def isPointerType(type):
|
||||||
return isPointerType(allTypes[type[0]])
|
return isPointerType(allTypes[type[0]])
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
INIT = 'INIT'
|
||||||
AFTER = 'AFTER'
|
AFTER = 'AFTER'
|
||||||
|
|
||||||
def generateCaller(qname, fname, func):
|
def generateCaller(qname, fname, func):
|
||||||
|
@ -155,7 +157,7 @@ def generateCaller(qname, fname, func):
|
||||||
elif type == 'KObject':
|
elif type == 'KObject':
|
||||||
params.append('ctu->getHandle<KObject>(req.getCopied(%i))' % hndOff)
|
params.append('ctu->getHandle<KObject>(req.getCopied(%i))' % hndOff)
|
||||||
logFmt.append('KObject %s= 0x%%x' % ('%s ' % name if name else ''))
|
logFmt.append('KObject %s= 0x%%x' % ('%s ' % name if name else ''))
|
||||||
logElems.append('req.getCopied(%i)' % objOff)
|
logElems.append('req.getCopied(%i)' % hndOff)
|
||||||
hndOff += 1
|
hndOff += 1
|
||||||
elif type == 'pid':
|
elif type == 'pid':
|
||||||
params.append('req.pid')
|
params.append('req.pid')
|
||||||
|
@ -242,7 +244,7 @@ def generateCaller(qname, fname, func):
|
||||||
yield 'return 0xf601;'
|
yield 'return 0xf601;'
|
||||||
return
|
return
|
||||||
|
|
||||||
yield 'resp.initialize(%i, %i, %i);' % (objOff, hndOff, outOffset - 8)
|
yield INIT, 'resp.initialize(%i, %i, %i);' % (objOff, hndOff, outOffset - 8)
|
||||||
if len(logFmt):
|
if len(logFmt):
|
||||||
yield 'LOG_DEBUG(IpcStubs, "IPC message to %s: %s"%s);' % (qname + '::' + fname, ', '.join(logFmt), (', ' + ', '.join(logElems)) if logElems else '')
|
yield 'LOG_DEBUG(IpcStubs, "IPC message to %s: %s"%s);' % (qname + '::' + fname, ', '.join(logFmt), (', ' + ', '.join(logElems)) if logElems else '')
|
||||||
else:
|
else:
|
||||||
|
@ -253,12 +255,20 @@ def generateCaller(qname, fname, func):
|
||||||
|
|
||||||
def reorder(gen):
|
def reorder(gen):
|
||||||
after = []
|
after = []
|
||||||
|
before = []
|
||||||
for x in gen:
|
for x in gen:
|
||||||
if x == AFTER:
|
if x == AFTER:
|
||||||
for elem in after:
|
for elem in after:
|
||||||
yield elem
|
yield elem
|
||||||
|
elif isinstance(x, tuple) and x[0] == INIT:
|
||||||
|
yield x[1]
|
||||||
|
for elem in before:
|
||||||
|
yield elem
|
||||||
|
before = None
|
||||||
elif isinstance(x, tuple) and x[0] == AFTER:
|
elif isinstance(x, tuple) and x[0] == AFTER:
|
||||||
after.append(x[1])
|
after.append(x[1])
|
||||||
|
elif before is not None:
|
||||||
|
before.append(x)
|
||||||
else:
|
else:
|
||||||
yield x
|
yield x
|
||||||
|
|
||||||
|
@ -305,90 +315,100 @@ def main():
|
||||||
for name in sorted(ifaces.keys()):
|
for name in sorted(ifaces.keys()):
|
||||||
namespaces[ns].append('class %s;' % name)
|
namespaces[ns].append('class %s;' % name)
|
||||||
|
|
||||||
with file('IpcStubs.h', 'w') as fp:
|
fp = StringIO()
|
||||||
print >>fp, '#pragma once'
|
print >>fp, '#pragma once'
|
||||||
print >>fp, '#include "Ctu.h"'
|
print >>fp, '#include "Ctu.h"'
|
||||||
print >>fp
|
print >>fp
|
||||||
|
|
||||||
print >>fp, '#define SERVICE_MAPPING() do { \\'
|
print >>fp, '#define SERVICE_MAPPING() do { \\'
|
||||||
for iname, snames in sorted(services.items(), key=lambda x: x[0]):
|
for iname, snames in sorted(services.items(), key=lambda x: x[0]):
|
||||||
for sname in snames:
|
for sname in snames:
|
||||||
print >>fp, '\tSERVICE("%s", %s); \\' % (sname, iname)
|
print >>fp, '\tSERVICE("%s", %s); \\' % (sname, iname)
|
||||||
print >>fp, '} while(0)'
|
print >>fp, '} while(0)'
|
||||||
print >>fp
|
print >>fp
|
||||||
|
|
||||||
for ns, elems in sorted(namespaces.items(), key=lambda x: x[0]):
|
for ns, elems in sorted(namespaces.items(), key=lambda x: x[0]):
|
||||||
if ns is not None:
|
if ns is not None:
|
||||||
print >>fp, 'namespace %s {' % ns
|
print >>fp, 'namespace %s {' % ns
|
||||||
hasUsing = False
|
hasUsing = False
|
||||||
for elem in elems:
|
for elem in elems:
|
||||||
if not hasUsing and elem.startswith('using'):
|
if not hasUsing and elem.startswith('using'):
|
||||||
hasUsing = True
|
hasUsing = True
|
||||||
elif hasUsing and elem.startswith('class'):
|
elif hasUsing and elem.startswith('class'):
|
||||||
print >>fp
|
print >>fp
|
||||||
hasUsing = False
|
hasUsing = False
|
||||||
print >>fp, ('\t' if ns is not None else '') + elem
|
print >>fp, ('\t' if ns is not None else '') + elem
|
||||||
if ns is not None:
|
if ns is not None:
|
||||||
print >>fp, '}'
|
print >>fp, '}'
|
||||||
|
|
||||||
print >>fp
|
print >>fp
|
||||||
|
|
||||||
allcode = '\n'.join(file(fn, 'r').read() for fn in glob.glob('ipcimpl/*.cpp'))
|
allcode = '\n'.join(file(fn, 'r').read() for fn in glob.glob('ipcimpl/*.cpp'))
|
||||||
|
|
||||||
partials = parsePartials(allcode)
|
partials = parsePartials(allcode)
|
||||||
|
|
||||||
for ns, ifaces in sorted(ifacesByNs.items(), key=lambda x: x[0]):
|
for ns, ifaces in sorted(ifacesByNs.items(), key=lambda x: x[0]):
|
||||||
print >>fp, '%snamespace %s {' % ('//// ' if ns is None else '', ns)
|
print >>fp, '%snamespace %s {' % ('//// ' if ns is None else '', ns)
|
||||||
for name, funcs in sorted(ifaces.items(), key=lambda x: x[0]):
|
for name, funcs in sorted(ifaces.items(), key=lambda x: x[0]):
|
||||||
qname = '%s::%s' % (ns, name) if ns else name
|
qname = '%s::%s' % (ns, name) if ns else name
|
||||||
partial = partials[qname] if qname in partials else None
|
partial = partials[qname] if qname in partials else None
|
||||||
print >>fp, '\tclass %s : public IpcService {' % name
|
print >>fp, '\tclass %s : public IpcService {' % name
|
||||||
print >>fp, '\tpublic:'
|
print >>fp, '\tpublic:'
|
||||||
if re.search('(^|[^a-zA-Z0-9:])%s::%s[^a-zA-Z0-9:]' % (qname, name), allcode):
|
if re.search('(^|[^a-zA-Z0-9:])%s::%s[^a-zA-Z0-9:]' % (qname, name), allcode):
|
||||||
print >>fp, '\t\t%s(Ctu *_ctu%s);' % (name, ', ' + ', '.join('%s _%s' % (k, v) for k, v in partial[1]) if partial and partial[1] else '')
|
print >>fp, '\t\t%s(Ctu *_ctu%s);' % (name, ', ' + ', '.join('%s _%s' % (k, v) for k, v in partial[1]) if partial and partial[1] else '')
|
||||||
else:
|
else:
|
||||||
print >>fp, '\t\t%s(Ctu *_ctu%s) : IpcService(_ctu)%s {}' % (name, ', ' + ', '.join('%s _%s' % (k, v) for k, v in partial[1]) if partial and partial[1] else '', ', ' + ', '.join('%s(_%s)' % (v, v) for k, v in partial[1]) if partial and partial[1] else '')
|
print >>fp, '\t\t%s(Ctu *_ctu%s) : IpcService(_ctu)%s {}' % (name, ', ' + ', '.join('%s _%s' % (k, v) for k, v in partial[1]) if partial and partial[1] else '', ', ' + ', '.join('%s(_%s)' % (v, v) for k, v in partial[1]) if partial and partial[1] else '')
|
||||||
print >>fp, '\t\tuint32_t dispatch(IncomingIpcMessage &req, OutgoingIpcMessage &resp) {'
|
print >>fp, '\t\tuint32_t dispatch(IncomingIpcMessage &req, OutgoingIpcMessage &resp) {'
|
||||||
print >>fp, '\t\t\tswitch(req.cmdId) {'
|
print >>fp, '\t\t\tswitch(req.cmdId) {'
|
||||||
for fname, func in sorted(funcs.items(), key=lambda x: x[1]['cmdId']):
|
for fname, func in sorted(funcs.items(), key=lambda x: x[1]['cmdId']):
|
||||||
print >>fp, '\t\t\tcase %i: {' % func['cmdId'];
|
print >>fp, '\t\t\tcase %i: {' % func['cmdId'];
|
||||||
print >>fp, '\n'.join('\t\t\t\t' + x for x in reorder(generateCaller(qname, fname, func)))
|
print >>fp, '\n'.join('\t\t\t\t' + x for x in reorder(generateCaller(qname, fname, func)))
|
||||||
print >>fp, '\t\t\t}'
|
|
||||||
print >>fp, '\t\t\tdefault:'
|
|
||||||
print >>fp, '\t\t\t\tLOG_ERROR(IpcStubs, "Unknown message cmdId %%u to interface %s", req.cmdId);' % ('%s::%s' % (ns, name) if ns else name)
|
|
||||||
print >>fp, '\t\t\t}'
|
print >>fp, '\t\t\t}'
|
||||||
print >>fp, '\t\t}'
|
print >>fp, '\t\t\tdefault:'
|
||||||
for fname, func in sorted(funcs.items(), key=lambda x: x[0]):
|
print >>fp, '\t\t\t\tLOG_ERROR(IpcStubs, "Unknown message cmdId %%u to interface %s", req.cmdId);' % ('%s::%s' % (ns, name) if ns else name)
|
||||||
implemented = re.search('[^a-zA-Z0-9:]%s::%s[^a-zA-Z0-9:]' % (qname, fname), allcode)
|
print >>fp, '\t\t\t}'
|
||||||
print >>fp, '\t\tuint32_t %s(%s);' % (fname, generatePrototype(func))
|
print >>fp, '\t\t}'
|
||||||
if partial:
|
for fname, func in sorted(funcs.items(), key=lambda x: x[0]):
|
||||||
for x in partial[0]:
|
implemented = re.search('[^a-zA-Z0-9:]%s::%s[^a-zA-Z0-9:]' % (qname, fname), allcode)
|
||||||
print >>fp, '\t\t%s' % x
|
print >>fp, '\t\tuint32_t %s(%s);' % (fname, generatePrototype(func))
|
||||||
print >>fp, '\t};'
|
if partial:
|
||||||
print >>fp, '%s}' % ('//// ' if ns is None else '')
|
for x in partial[0]:
|
||||||
|
print >>fp, '\t\t%s' % x
|
||||||
|
print >>fp, '\t};'
|
||||||
|
print >>fp, '%s}' % ('//// ' if ns is None else '')
|
||||||
|
|
||||||
print >>fp, '#ifdef DEFINE_STUBS'
|
print >>fp, '#ifdef DEFINE_STUBS'
|
||||||
for name, funcs in sorted(ifaces.items(), key=lambda x: x[0]):
|
for name, funcs in sorted(ifaces.items(), key=lambda x: x[0]):
|
||||||
qname = '%s::%s' % (ns, name) if ns else name
|
qname = '%s::%s' % (ns, name) if ns else name
|
||||||
partial = partials[qname] if qname in partials else None
|
partial = partials[qname] if qname in partials else None
|
||||||
for fname, func in sorted(funcs.items(), key=lambda x: x[0]):
|
for fname, func in sorted(funcs.items(), key=lambda x: x[0]):
|
||||||
implemented = re.search('[^a-zA-Z0-9:]%s::%s[^a-zA-Z0-9:]' % (qname, fname), allcode)
|
implemented = re.search('[^a-zA-Z0-9:]%s::%s[^a-zA-Z0-9:]' % (qname, fname), allcode)
|
||||||
if not implemented:
|
if not implemented:
|
||||||
print >>fp, 'uint32_t %s::%s(%s) {' % (qname, fname, generatePrototype(func))
|
print >>fp, 'uint32_t %s::%s(%s) {' % (qname, fname, generatePrototype(func))
|
||||||
print >>fp, '\tLOG_DEBUG(IpcStubs, "Stub implementation for %s::%s");' % (qname, fname)
|
print >>fp, '\tLOG_DEBUG(IpcStubs, "Stub implementation for %s::%s");' % (qname, fname)
|
||||||
for i, (name, elem) in enumerate(func['outputs']):
|
for i, (name, elem) in enumerate(func['outputs']):
|
||||||
if elem[0] == 'object' and elem[1][0] != 'IUnknown':
|
if elem[0] == 'object' and elem[1][0] != 'IUnknown':
|
||||||
name = name if name else '_%i' % (len(func['inputs']) + i)
|
name = name if name else '_%i' % (len(func['inputs']) + i)
|
||||||
print >>fp, '\t%s = buildInterface(%s);' % (name, elem[1][0])
|
print >>fp, '\t%s = buildInterface(%s);' % (name, elem[1][0])
|
||||||
if elem[1][0] in partials and partials[elem[1][0]][1]:
|
if elem[1][0] in partials and partials[elem[1][0]][1]:
|
||||||
print 'Bare construction of interface %s requiring parameters. Created in %s::%s for parameter %s' % (elem[1][0], qname, fname, name)
|
print 'Bare construction of interface %s requiring parameters. Created in %s::%s for parameter %s' % (elem[1][0], qname, fname, name)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
elif elem[0] == 'KObject':
|
elif elem[0] == 'KObject':
|
||||||
name = name if name else '_%i' % (len(func['inputs']) + i)
|
name = name if name else '_%i' % (len(func['inputs']) + i)
|
||||||
print >>fp, '\t%s = make_shared<FauxHandle>(0x%x);' % (name, uniqInt(qname, fname, name))
|
print >>fp, '\t%s = make_shared<FauxHandle>(0x%x);' % (name, uniqInt(qname, fname, name))
|
||||||
print >>fp, '\treturn 0;'
|
print >>fp, '\treturn 0;'
|
||||||
print >>fp, '}'
|
print >>fp, '}'
|
||||||
print >>fp, '#endif // DEFINE_STUBS'
|
print >>fp, '#endif // DEFINE_STUBS'
|
||||||
|
|
||||||
|
code = fp.getvalue()
|
||||||
|
if os.path.exists('IpcStubs.h'):
|
||||||
|
with file('IpcStubs.h', 'r') as fp:
|
||||||
|
match = fp.read() == code
|
||||||
|
else:
|
||||||
|
match = False
|
||||||
|
if not match:
|
||||||
|
with file('IpcStubs.h', 'w') as fp:
|
||||||
|
fp.write(code)
|
||||||
|
|
||||||
if __name__=='__main__':
|
if __name__=='__main__':
|
||||||
main(*sys.argv[1:])
|
main(*sys.argv[1:])
|
||||||
|
|
209
ipcclient.py
Normal file
209
ipcclient.py
Normal file
|
@ -0,0 +1,209 @@
|
||||||
|
from socket import *
|
||||||
|
from struct import pack, unpack
|
||||||
|
import math, sys
|
||||||
|
|
||||||
|
def dump(data):
|
||||||
|
data = map(ord, data)
|
||||||
|
fmt = '%%0%ix |' % (int(math.log(len(data), 16)) + 1)
|
||||||
|
for i in xrange(0, len(data), 16):
|
||||||
|
print fmt % i,
|
||||||
|
ascii = ''
|
||||||
|
for j in xrange(16):
|
||||||
|
if i + j < len(data):
|
||||||
|
print '%02x' % data[i + j],
|
||||||
|
if 0x20 <= data[i+j] <= 0x7E:
|
||||||
|
ascii += chr(data[i+j])
|
||||||
|
else:
|
||||||
|
ascii += '.'
|
||||||
|
else:
|
||||||
|
print ' ',
|
||||||
|
ascii += ' '
|
||||||
|
if j == 7:
|
||||||
|
print '',
|
||||||
|
ascii += ' '
|
||||||
|
print '|', ascii
|
||||||
|
|
||||||
|
def hexify(obj, name, pname=None):
|
||||||
|
def sub(v):
|
||||||
|
if isinstance(v, list) or isinstance(v, tuple):
|
||||||
|
return '[%s]' % ', '.join(map(sub, v))
|
||||||
|
elif isinstance(v, str):
|
||||||
|
return 'buf<0x%x>' % len(v)
|
||||||
|
else:
|
||||||
|
return '0x%x' % v
|
||||||
|
|
||||||
|
pname = name if pname is None else pname
|
||||||
|
value = getattr(obj, pname)
|
||||||
|
if len(value) == 0:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
return ', %s=%s' % (name, sub(value))
|
||||||
|
|
||||||
|
class IPCMessage(object):
|
||||||
|
def __init__(self, cmdId=0, client=None):
|
||||||
|
self.client = client
|
||||||
|
|
||||||
|
self.type = -1
|
||||||
|
self.cmdId = cmdId
|
||||||
|
self.request = False
|
||||||
|
|
||||||
|
self.pid = -1
|
||||||
|
self.dataBuffer = []
|
||||||
|
|
||||||
|
self.aDescriptors = []
|
||||||
|
self.bDescriptors = []
|
||||||
|
self.cDescriptors = []
|
||||||
|
self.xDescriptors = []
|
||||||
|
|
||||||
|
self.copiedHandles = []
|
||||||
|
self.movedHandles = []
|
||||||
|
|
||||||
|
def setType(self, type):
|
||||||
|
self.type = type
|
||||||
|
return self
|
||||||
|
def hasPID(self, pid=0xDEAD):
|
||||||
|
self.pid = pid
|
||||||
|
return self
|
||||||
|
def data(self, *args):
|
||||||
|
self.dataBuffer += list(args)
|
||||||
|
return self
|
||||||
|
def aDescriptor(self, data, perms):
|
||||||
|
self.aDescriptors.append((data, perms))
|
||||||
|
return self
|
||||||
|
def bDescriptor(self, data, perms):
|
||||||
|
self.bDescriptors.append((data, perms))
|
||||||
|
return self
|
||||||
|
def cDescriptor(self, data):
|
||||||
|
self.cDescriptors.append(data)
|
||||||
|
return self
|
||||||
|
def xDescriptor(self, data, counter):
|
||||||
|
self.xDescriptors.append((data, counter))
|
||||||
|
return self
|
||||||
|
def copyHandle(self, handle):
|
||||||
|
self.copiedHandles.append(handle)
|
||||||
|
return self
|
||||||
|
def moveHandle(self, handle):
|
||||||
|
self.movedHandles.append(handle)
|
||||||
|
return self
|
||||||
|
|
||||||
|
def sendTo(self, handle):
|
||||||
|
return self.client.sendMsg(handle, self)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '%s(%s%s%s%s%s%s%s%s%s)' % (
|
||||||
|
self.__class__.__name__,
|
||||||
|
'cmdId=%i' % self.cmdId,
|
||||||
|
', type=%i' % self.type if self.type != 0 else '',
|
||||||
|
hexify(self, 'data', 'dataBuffer'),
|
||||||
|
hexify(self, 'aDescriptors'),
|
||||||
|
hexify(self, 'bDescriptors'),
|
||||||
|
hexify(self, 'cDescriptors'),
|
||||||
|
hexify(self, 'xDescriptors'),
|
||||||
|
hexify(self, 'copiedHandles'),
|
||||||
|
hexify(self, 'movedHandles'),
|
||||||
|
)
|
||||||
|
|
||||||
|
class Client(object):
|
||||||
|
def __init__(self, host='127.0.0.1'):
|
||||||
|
self.sock = socket(AF_INET, SOCK_STREAM)
|
||||||
|
self.sock.connect((host, 31337))
|
||||||
|
|
||||||
|
self.autoHandles = {}
|
||||||
|
|
||||||
|
def getService(self, name):
|
||||||
|
if name not in self.autoHandles:
|
||||||
|
print 'Getting service', name
|
||||||
|
self.writeint(0)
|
||||||
|
self.writedata(name)
|
||||||
|
self.autoHandles[name] = self.readint()
|
||||||
|
return self.autoHandles[name]
|
||||||
|
|
||||||
|
def closeHandle(self, handle):
|
||||||
|
print 'Closing handle %x' % handle
|
||||||
|
self.writeint(1)
|
||||||
|
self.writeint(handle)
|
||||||
|
|
||||||
|
def ipcMsg(self, cmdId):
|
||||||
|
return IPCMessage(cmdId, client=self)
|
||||||
|
|
||||||
|
def sendMsg(self, nameOrHandle, msg):
|
||||||
|
if isinstance(nameOrHandle, str) or isinstance(nameOrHandle, unicode):
|
||||||
|
handle = self.getService(nameOrHandle)
|
||||||
|
name = nameOrHandle
|
||||||
|
else:
|
||||||
|
handle = nameOrHandle
|
||||||
|
name = None
|
||||||
|
|
||||||
|
self.writeint(2)
|
||||||
|
self.writeint(4 if msg.type == -1 else msg.type)
|
||||||
|
self.writeint(len(msg.dataBuffer) + 1)
|
||||||
|
map(self.writeint, [msg.cmdId] + list(msg.dataBuffer))
|
||||||
|
self.writeint(msg.pid)
|
||||||
|
self.writeint(len(msg.copiedHandles))
|
||||||
|
map(self.writeint, msg.copiedHandles)
|
||||||
|
self.writeint(len(msg.movedHandles))
|
||||||
|
map(self.writeint, msg.movedHandles)
|
||||||
|
self.writeint(len(msg.aDescriptors))
|
||||||
|
[(self.writedata(y), self.writeint(z)) for y, z in msg.aDescriptors]
|
||||||
|
self.writeint(len(msg.bDescriptors))
|
||||||
|
[(self.writedata(y), self.writeint(z)) for y, z in msg.bDescriptors]
|
||||||
|
self.writeint(len(msg.cDescriptors))
|
||||||
|
[self.writedata(y) for y in msg.cDescriptors]
|
||||||
|
self.writeint(len(msg.xDescriptors))
|
||||||
|
[(self.writedata(y), self.writeint(z)) for y, z in msg.xDescriptors]
|
||||||
|
self.writeint(handle)
|
||||||
|
|
||||||
|
error_code = self.readint()
|
||||||
|
if error_code != 0:
|
||||||
|
if error_code == 0xf601 and name is not None:
|
||||||
|
del self.autoHandles[name]
|
||||||
|
return error_code, None
|
||||||
|
|
||||||
|
data = [self.readint() for i in xrange(self.readint(0))]
|
||||||
|
copy = [self.readint() for i in xrange(self.readint(0))]
|
||||||
|
move = [self.readint() for i in xrange(self.readint(0))]
|
||||||
|
a = [(self.readdata(), self.readint()) for i in xrange(self.readint(0))]
|
||||||
|
b = [(self.readdata(), self.readint()) for i in xrange(self.readint(0))]
|
||||||
|
c = [self.readdata() for i in xrange(self.readint(0))]
|
||||||
|
x = [(self.readdata(), self.readint()) for i in xrange(self.readint(0))]
|
||||||
|
request_type = self.readint()
|
||||||
|
|
||||||
|
if request_type is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
msg = IPCMessage(data[0])
|
||||||
|
msg.setType(request_type)
|
||||||
|
msg.data(*data[1:])
|
||||||
|
map(msg.copyHandle, copy)
|
||||||
|
map(msg.moveHandle, move)
|
||||||
|
map(lambda v: msg.aDescriptor(*v), a)
|
||||||
|
map(lambda v: msg.bDescriptor(*v), b)
|
||||||
|
map(lambda v: msg.cDescriptor(v), c)
|
||||||
|
map(lambda v: msg.xDescriptor(*v), x)
|
||||||
|
msg.data = msg.dataBuffer
|
||||||
|
return 0, msg
|
||||||
|
|
||||||
|
def readint(self, default=None):
|
||||||
|
data = self.sock.recv(8)
|
||||||
|
if len(data) != 8:
|
||||||
|
return default
|
||||||
|
return unpack('<Q', data)[0]
|
||||||
|
def readdata(self, default=None):
|
||||||
|
size = self.readint()
|
||||||
|
if size is None:
|
||||||
|
return default
|
||||||
|
odata = ''
|
||||||
|
while len(odata) != size:
|
||||||
|
data = self.sock.recv(size - len(odata))
|
||||||
|
if len(data) == 0:
|
||||||
|
return None
|
||||||
|
odata += data
|
||||||
|
return odata
|
||||||
|
def writeint(self, v):
|
||||||
|
self.sock.send(pack('<Q', v & 0xFFFFFFFFFFFFFFFF))
|
||||||
|
def writedata(self, v):
|
||||||
|
self.writeint(len(v))
|
||||||
|
if isinstance(v, str) or isinstance(v, unicode):
|
||||||
|
self.sock.send(v)
|
||||||
|
else:
|
||||||
|
self.sock.send(''.join(map(chr, v)))
|
|
@ -3,6 +3,6 @@ interface nn::lm::ILogService is lm {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface nn::lm::ILogger {
|
interface nn::lm::ILogger {
|
||||||
[0] Unknown0(buffer<unknown, 0x21, 0>);
|
[0] Log(buffer<u8, 0x21, 0> message);
|
||||||
[1] Unknown1(u32);
|
[1] Unknown1(u32);
|
||||||
}
|
}
|
23
ipcdefs/nfc.id
Normal file
23
ipcdefs/nfc.id
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
interface nn::nfc::detail::ISystemManager is nfc:sys {
|
||||||
|
[0] GetISystem() -> object<nn::nfc::detail::ISystem>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface nn::nfc::detail::IUserManager is nfc:user {
|
||||||
|
[0] GetIUser() -> object<nn::nfc::detail::IUser>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface nn::nfc::mifare::detail::IUserManager is nfc:mf:u {
|
||||||
|
[0] GetIUserMifare() -> object<nn::nfc::mifare::detail::IUser>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface nn::nfp::detail::IDebugManager is nfp:dbg {
|
||||||
|
[0] GetIDebug() -> object<nn::nfp::detail::IDebug>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface nn::nfp::detail::ISystemManager is nfp:sys {
|
||||||
|
[0] GetISystem() -> object<nn::nfp::detail::ISystem>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface nn::nfp::detail::IUserManager is nfp:user {
|
||||||
|
[0] GetIUser() -> object<nn::nfp::detail::IUser>;
|
||||||
|
}
|
10
ipcdefs/nv.id
Normal file
10
ipcdefs/nv.id
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
interface NvidiaService is nvdrv, nvdrv:a, nvdrv:s, nvdrv:t {
|
||||||
|
[0] Open(buffer<i8, 5, 0> path) -> u32 fd;
|
||||||
|
[1] Ioctl(u32 fd, u32 request, buffer<unknown, 0x21, 0> inbuf) -> buffer<unknown, 0x22, 0> outbuf;
|
||||||
|
[2] Close(u32 fd);
|
||||||
|
[3] Initialize(u32 tmemSize, KObject process, KObject transferMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface NvidiaDebugger is nvdrvdbg {
|
||||||
|
}
|
||||||
|
|
21
ipcdefs/pdm.id
Normal file
21
ipcdefs/pdm.id
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
interface nn::pdm::detail::IQueryService is pdm:qry {
|
||||||
|
[0] Unknown0(u32) -> (u32, buffer<unknown, 6, 0>);
|
||||||
|
[1] Unknown1() -> (u32, buffer<unknown, 6, 0>);
|
||||||
|
[2] Unknown2(u64, u64) -> (u32, buffer<unknown, 6, 0>);
|
||||||
|
[3] Unknown3(u64) -> (u32, buffer<unknown, 6, 0>);
|
||||||
|
[4] Unknown4(u64) -> (u64, u64, u64, u64, u64);
|
||||||
|
[5] Unknown5(u64, u64, u64) -> (u64, u64, u64, u64, u64);
|
||||||
|
[6] Unknown6(u64, u64) -> (u64, u64, u64, u64, u64);
|
||||||
|
[7] Unknown7(buffer<unknown, 5, 0>) -> (u32, buffer<unknown, 6, 0>);
|
||||||
|
[8] Unknown8(u32) -> (u32, buffer<unknown, 6, 0>);
|
||||||
|
[9] Unknown9() -> (u32, u32, u32);
|
||||||
|
[10] Unknown10(u32) -> (u32, buffer<unknown, 6, 0>);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface nn::pdm::detail::INotifyService is pdm:ntfy {
|
||||||
|
[0] Unknown0(u64, u64);
|
||||||
|
[2] Unknown2(u8);
|
||||||
|
[3] Unknown3(u8);
|
||||||
|
[4] Unknown4();
|
||||||
|
[5] Unknown5(buffer<unknown, 5, 0>);
|
||||||
|
}
|
46
ipcdefs/ptm.id
Normal file
46
ipcdefs/ptm.id
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
interface TcService is tc {
|
||||||
|
[0] Unknown0();
|
||||||
|
[1] Unknown1();
|
||||||
|
[2] Unknown2();
|
||||||
|
[3] Unknown3();
|
||||||
|
[4] Unknown4();
|
||||||
|
[5] Unknown5();
|
||||||
|
[6] Unknown6();
|
||||||
|
[7] Unknown7();
|
||||||
|
[8] Unknown8();
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FanService is fan {
|
||||||
|
[0] Unknown0();
|
||||||
|
[1] Unknown1();
|
||||||
|
[2] Unknown2();
|
||||||
|
[3] Unknown3();
|
||||||
|
[4] Unknown4();
|
||||||
|
[5] Unknown5();
|
||||||
|
[6] Unknown6();
|
||||||
|
[7] Unknown7();
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PsmService is psm {
|
||||||
|
[0] Unknown0();
|
||||||
|
[1] Unknown1();
|
||||||
|
[2] Unknown2();
|
||||||
|
[3] Unknown3();
|
||||||
|
[4] Unknown4();
|
||||||
|
[5] Unknown5();
|
||||||
|
[6] Unknown6();
|
||||||
|
[7] Unknown7() -> object<IPsmSession>;
|
||||||
|
[8] Unknown8();
|
||||||
|
[9] Unknown9();
|
||||||
|
[10] Unknown10();
|
||||||
|
[11] Unknown11();
|
||||||
|
[12] Unknown12();
|
||||||
|
[13] Unknown13();
|
||||||
|
[14] Unknown14();
|
||||||
|
[15] Unknown15();
|
||||||
|
[16] Unknown16();
|
||||||
|
[17] Unknown17();
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IPsmSession {
|
||||||
|
}
|
143
ipcimpl/lm.cpp
Normal file
143
ipcimpl/lm.cpp
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
#include "Ctu.h"
|
||||||
|
#include <byteswap.h>
|
||||||
|
|
||||||
|
/*$IPC$
|
||||||
|
partial nn::lm::ILogger {
|
||||||
|
LogMessage *current;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
class LogMessage {
|
||||||
|
public:
|
||||||
|
LogMessage(int _severity, int _verbosity) : severity(_severity), verbosity(_verbosity) {
|
||||||
|
message = "";
|
||||||
|
filename = function = module = thread = "unknown";
|
||||||
|
line = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addMessage(char *data) {
|
||||||
|
message += data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print() {
|
||||||
|
while(message.back() == '\n')
|
||||||
|
message = message.substr(0, message.size() - 1);
|
||||||
|
|
||||||
|
if(message.size() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
LOG_DEBUG(Lm, "Thread %s, module %s, file %s, function %s, line %i:", thread.c_str(), module.c_str(), filename.c_str(), function.c_str(), line);
|
||||||
|
LOG_DEBUG(Lm, "%s", message.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
int severity, verbosity, line;
|
||||||
|
string message, filename, function, module, thread;
|
||||||
|
};
|
||||||
|
|
||||||
|
nn::lm::ILogger::ILogger(Ctu *_ctu) : IpcService(_ctu), current(nullptr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct InLogPacket {
|
||||||
|
uint64_t pid;
|
||||||
|
gptr threadContext;
|
||||||
|
uint16_t flags;
|
||||||
|
uint8_t severity, verbosity;
|
||||||
|
uint32_t payloadSize;
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
void dumpstring(uint8_t *data, guint size) {
|
||||||
|
gptr addr = 0x0;
|
||||||
|
|
||||||
|
auto hfmt = "%08lx | ";
|
||||||
|
if((addr + size) & 0xFFFF000000000000)
|
||||||
|
hfmt = "%016lx | ";
|
||||||
|
else if((addr + size) & 0xFFFFFFFF00000000)
|
||||||
|
hfmt = "%012lx | ";
|
||||||
|
|
||||||
|
for(uint32_t i = 0; i < size; i += 16) {
|
||||||
|
printf(hfmt, addr+i);
|
||||||
|
string ascii = "";
|
||||||
|
for(uint8_t j = 0; j < 16; j++) {
|
||||||
|
if((i+j) < size) {
|
||||||
|
printf("%02x ", (uint8_t)data[i+j]);
|
||||||
|
if(isprint(data[i+j]))
|
||||||
|
ascii += data[i+j];
|
||||||
|
else
|
||||||
|
ascii += ".";
|
||||||
|
} else {
|
||||||
|
printf(" ");
|
||||||
|
ascii += " ";
|
||||||
|
}
|
||||||
|
if(j==7) {
|
||||||
|
printf(" ");
|
||||||
|
ascii += " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("| %s\n", ascii.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nn::lm::ILogger::Log(IN uint8_t *message, guint messageSize) {
|
||||||
|
auto packet = (InLogPacket *) message;
|
||||||
|
dumpstring(message, messageSize);
|
||||||
|
|
||||||
|
bool isHead = packet->flags & 1;
|
||||||
|
bool isTail = packet->flags & 2;
|
||||||
|
|
||||||
|
if(isHead || current == nullptr) {
|
||||||
|
if(current != nullptr)
|
||||||
|
delete current;
|
||||||
|
current = new LogMessage(packet->severity, packet->verbosity);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto offset = 24;
|
||||||
|
while(offset < messageSize) {
|
||||||
|
uint8_t id = *(uint8_t *)(&message[offset++]);
|
||||||
|
uint8_t len = *(uint8_t *)(&message[offset++]);
|
||||||
|
|
||||||
|
auto buf = new char[len + 1];
|
||||||
|
memset(buf, 0, len + 1);
|
||||||
|
memcpy(buf, &message[offset], len);
|
||||||
|
if(len == 0) {
|
||||||
|
delete[] buf;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(id) {
|
||||||
|
case 2:
|
||||||
|
current->addMessage(buf);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
current->line = *(uint32_t *)(message + offset);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
current->filename = buf;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
current->function = buf;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
current->module = buf;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
current->thread = buf;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
LOG_DEBUG(Lm, "Invalid ID: %d!!!", id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
offset += len;
|
||||||
|
delete[] buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isTail) {
|
||||||
|
current->print();
|
||||||
|
delete current;
|
||||||
|
current = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -13,3 +13,10 @@ uint32_t nn::settings::ISystemSettingsServer::GetMiiAuthorId(OUT nn::util::Uuid&
|
||||||
buf[1] = 0x000000d00db3c001;
|
buf[1] = 0x000000d00db3c001;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t nn::settings::IFactorySettingsServer::GetConfigurationId1(OUT nn::settings::factory::ConfigurationId1& _0) {
|
||||||
|
LOG_DEBUG(IpcStubs, "Stub implementation for nn::settings::IFactorySettingsServer::GetConfigurationId1");
|
||||||
|
memset(_0, 0, 0x1e);
|
||||||
|
strcpy((char *) _0, "MP_00_01_00_00");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
10
main.cpp
10
main.cpp
|
@ -60,19 +60,25 @@ bool exists(string fn) {
|
||||||
void loadNso(Ctu &ctu, const string &lfn, gptr raddr) {
|
void loadNso(Ctu &ctu, const string &lfn, gptr raddr) {
|
||||||
assert(exists(lfn));
|
assert(exists(lfn));
|
||||||
Nso file(lfn);
|
Nso file(lfn);
|
||||||
file.load(ctu, raddr, false);
|
if(file.load(ctu, raddr, false) == 0) {
|
||||||
|
LOG_ERROR(NsoLoader, "Failed to load %s", lfn.c_str());
|
||||||
|
}
|
||||||
ctu.loadbase = min(raddr, ctu.loadbase);
|
ctu.loadbase = min(raddr, ctu.loadbase);
|
||||||
auto top = raddr + 0x100000000;
|
auto top = raddr + 0x100000000;
|
||||||
ctu.loadsize = max(top - ctu.loadbase, ctu.loadsize);
|
ctu.loadsize = max(top - ctu.loadbase, ctu.loadsize);
|
||||||
|
LOG_INFO(NsoLoader, "Loaded %s at " ADDRFMT, lfn.c_str(), ctu.loadbase);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loadNro(Ctu &ctu, const string &lfn, gptr raddr) {
|
void loadNro(Ctu &ctu, const string &lfn, gptr raddr) {
|
||||||
assert(exists(lfn));
|
assert(exists(lfn));
|
||||||
Nro file(lfn);
|
Nro file(lfn);
|
||||||
file.load(ctu, raddr, true);
|
if(file.load(ctu, raddr, true) == 0) {
|
||||||
|
LOG_ERROR(NroLoader, "Failed to load %s", lfn.c_str());
|
||||||
|
}
|
||||||
ctu.loadbase = min(raddr, ctu.loadbase);
|
ctu.loadbase = min(raddr, ctu.loadbase);
|
||||||
auto top = raddr + 0x100000000;
|
auto top = raddr + 0x100000000;
|
||||||
ctu.loadsize = max(top - ctu.loadbase, ctu.loadsize);
|
ctu.loadsize = max(top - ctu.loadbase, ctu.loadsize);
|
||||||
|
LOG_INFO(NroLoader, "Loaded %s at " ADDRFMT, lfn.c_str(), ctu.loadbase);
|
||||||
}
|
}
|
||||||
|
|
||||||
void runLisp(Ctu &ctu, const string &dir, shared_ptr<Atom> code) {
|
void runLisp(Ctu &ctu, const string &dir, shared_ptr<Atom> code) {
|
||||||
|
|
63
wireprotocol.txt
Normal file
63
wireprotocol.txt
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
Open session
|
||||||
|
- cmd: 0
|
||||||
|
- name: data
|
||||||
|
Response:
|
||||||
|
- handle: int
|
||||||
|
|
||||||
|
Close handle
|
||||||
|
- cmd: 1
|
||||||
|
- handle: int
|
||||||
|
Response:
|
||||||
|
none
|
||||||
|
|
||||||
|
IPC message
|
||||||
|
- cmd: 2
|
||||||
|
- request_type: int
|
||||||
|
- data_count: int
|
||||||
|
- data: int[data_count]
|
||||||
|
- copy_count: int
|
||||||
|
- copied_handles: int[copy_count]
|
||||||
|
- move_count: int
|
||||||
|
- moved_handles: int[move_count]
|
||||||
|
- a_count: int
|
||||||
|
- a_buffers:
|
||||||
|
- blob: data
|
||||||
|
- perms: int
|
||||||
|
- b_count: int
|
||||||
|
- b_buffers:
|
||||||
|
- blob: data
|
||||||
|
- perms: int
|
||||||
|
- c_count: int
|
||||||
|
- c_buffers:
|
||||||
|
- blob: data
|
||||||
|
- x_count: int
|
||||||
|
- x_buffers:
|
||||||
|
- blob: data
|
||||||
|
- counter: int
|
||||||
|
- handle: int
|
||||||
|
Response:
|
||||||
|
- error_code: int
|
||||||
|
- data_count: int
|
||||||
|
- data: int[data_count]
|
||||||
|
- copy_count: int
|
||||||
|
- copied_handles: int[copy_count]
|
||||||
|
- move_count: int
|
||||||
|
- moved_handles: int[move_count]
|
||||||
|
- a_count: int
|
||||||
|
- a_buffers:
|
||||||
|
- blob: data
|
||||||
|
- perms: int
|
||||||
|
- b_count: int
|
||||||
|
- b_buffers:
|
||||||
|
- blob: data
|
||||||
|
- perms: int
|
||||||
|
- c_count: int
|
||||||
|
- c_buffers:
|
||||||
|
- blob: data
|
||||||
|
- x_count: int
|
||||||
|
- x_buffers:
|
||||||
|
- blob: data
|
||||||
|
- counter: int
|
||||||
|
- response_type: int
|
||||||
|
|
||||||
|
NOTE: If error_code is nonzero, no fields will follow!
|
Loading…
Reference in a new issue