mirror of
https://github.com/reswitched/Mephisto.git
synced 2024-05-11 09:14:54 -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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void mmioHook(uc_engine *uc, uc_mem_type type, gptr address, int size, gptr value, void *user_data) {
|
||||
gptr physicalAddress = ((Cpu *) user_data)->mmioHandler->getPhysicalAddressFromVirtual(address);
|
||||
MmioBase *mmio = ((Cpu *) user_data)->mmioHandler->getMMIOFromPhysicalAddress(address);
|
||||
void mmioHook(uc_engine *uc, uc_mem_type type, gptr address, uint32_t size, gptr value, void *user_data) {
|
||||
auto cpu = (Cpu *) user_data;
|
||||
auto physicalAddress = cpu->mmioHandler->getPhysicalAddressFromVirtual(address);
|
||||
auto mmio = cpu->mmioHandler->getMMIOFromPhysicalAddress(address);
|
||||
assert(mmio != nullptr);
|
||||
switch(type) {
|
||||
case UC_MEM_READ:
|
||||
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;
|
||||
case UC_MEM_WRITE:
|
||||
LOG_DEBUG(Cpu, "MMIO Write at " ADDRFMT " size %x data %lx", physicalAddress, size, value);
|
||||
/*if() {
|
||||
((Cpu *) user_data)->writemem(address, &value, size);
|
||||
}*/
|
||||
//mmio->swrite(physicalAddress, size, &value);
|
||||
((Cpu *) user_data)->writemem(address, &value, size);
|
||||
mmio->write(physicalAddress, size, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +54,21 @@ void codeBpHook(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
|
|||
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) {
|
||||
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)
|
||||
svcHandlers[i] = nullptr;
|
||||
|
||||
hitMemBreakpoint = false;
|
||||
}
|
||||
|
||||
Cpu::~Cpu() {
|
||||
|
@ -306,9 +337,21 @@ bool Cpu::unmappedHook(uc_mem_type type, gptr addr, int size, guint value) {
|
|||
break;
|
||||
case UC_MEM_WRITE_UNMAPPED:
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -328,6 +371,14 @@ hook_t Cpu::addCodeBreakpoint(gptr addr) {
|
|||
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));
|
||||
}
|
||||
|
|
9
Cpu.h
9
Cpu.h
|
@ -46,7 +46,8 @@ public:
|
|||
void registerSvcHandler(int num, std::function<void(Cpu *)> handler);
|
||||
|
||||
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);
|
||||
bool unmappedHook(uc_mem_type type, gptr addr, int size, guint value);
|
||||
|
@ -54,6 +55,8 @@ public:
|
|||
void setMmio(Mmio *_mmioHandler);// { mmioHandler = _mmioHandler; }
|
||||
Mmio *mmioHandler;
|
||||
|
||||
bool hitMemBreakpoint;
|
||||
|
||||
private:
|
||||
Ctu *ctu;
|
||||
uc_engine *uc;
|
||||
|
@ -85,6 +88,10 @@ public:
|
|||
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) {
|
||||
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;
|
||||
|
||||
cpu.map(sp - ss, ss);
|
||||
cpu.setMmio(&mmiohandler);
|
||||
mmiohandler.MMIOInitialize();
|
||||
cpu.setMmio(&mmiohandler);
|
||||
|
||||
auto mainThread = tm.create(ep, sp);
|
||||
mainThread->regs.X1 = mainThread->handle;
|
||||
|
|
50
Ctu.h
50
Ctu.h
|
@ -81,14 +81,56 @@ extern LogLevel g_LogLevel;
|
|||
} while(0)
|
||||
|
||||
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 "Lisparser.h"
|
||||
#include "KObject.h"
|
||||
#include "ThreadManager.h"
|
||||
#include "Mmio.h"
|
||||
#include "Cpu.h"
|
||||
#include "Sync.h"
|
||||
#include "ThreadManager.h"
|
||||
#include "Svc.h"
|
||||
#include "Ipc.h"
|
||||
#include "Nxo.h"
|
||||
|
@ -131,6 +173,7 @@ public:
|
|||
ghandle newHandle(shared_ptr<T> obj) {
|
||||
static_assert(std::is_base_of<KObject, T>::value, "T must derive from KObject");
|
||||
auto hnd = handleId++;
|
||||
LOG_DEBUG(Ctu, "Creating handle %x", hnd);
|
||||
handles[hnd] = dynamic_pointer_cast<KObject>(obj);
|
||||
return hnd;
|
||||
}
|
||||
|
@ -148,11 +191,14 @@ public:
|
|||
LOG_ERROR(Ctu, "Got null pointer after cast. Before: 0x%p", (void *) obj.get());
|
||||
return temp;
|
||||
}
|
||||
bool hasHandle(ghandle handle) {
|
||||
return handles.find(handle) != handles.end();
|
||||
}
|
||||
ghandle duplicateHandle(KObject *ptr);
|
||||
void deleteHandle(ghandle handle);
|
||||
|
||||
Mmio mmiohandler;
|
||||
Cpu cpu;
|
||||
Mmio mmiohandler;
|
||||
Svc svc;
|
||||
Ipc ipc;
|
||||
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;
|
||||
haltLoop = true;
|
||||
remoteBreak = false;
|
||||
}
|
||||
|
||||
uint8_t GdbStub::readByte() {
|
||||
|
@ -244,7 +245,7 @@ void GdbStub::removeBreakpoint(BreakpointType type, gptr addr) {
|
|||
if(bp != p.end()) {
|
||||
LOG_DEBUG(GdbStub, "gdb: removed a breakpoint: %016lx bytes at %016lx of type %d",
|
||||
bp->second.len, bp->second.addr, type);
|
||||
ctu->cpu.removeCodeBreakpoint(bp->second.hook);
|
||||
ctu->cpu.removeBreakpoint(bp->second.hook);
|
||||
p.erase(addr);
|
||||
}
|
||||
}
|
||||
|
@ -379,7 +380,7 @@ void GdbStub::readCommand() {
|
|||
} else if(c == 0x03) {
|
||||
LOG_INFO(GdbStub, "gdb: found break command");
|
||||
haltLoop = true;
|
||||
sendSignal(SIGTRAP);
|
||||
remoteBreak = true;
|
||||
return;
|
||||
} else if(c != GDB_STUB_START) {
|
||||
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)
|
||||
breakpoint.hook = ctu->cpu.addCodeBreakpoint(addr);
|
||||
else
|
||||
breakpoint.hook = ctu->cpu.addMemoryBreakpoint(addr, len, type);
|
||||
|
||||
p.insert({addr, breakpoint});
|
||||
|
||||
|
|
13
GdbStub.h
13
GdbStub.h
|
@ -11,15 +11,6 @@
|
|||
|
||||
#define GDB_BUFFER_SIZE 10000
|
||||
|
||||
/// Breakpoint Method
|
||||
enum class BreakpointType {
|
||||
None,
|
||||
Execute,
|
||||
Read,
|
||||
Write,
|
||||
Access
|
||||
};
|
||||
|
||||
struct BreakpointAddress {
|
||||
gptr address;
|
||||
BreakpointType type;
|
||||
|
@ -41,8 +32,9 @@ public:
|
|||
void handlePacket();
|
||||
auto getNextBreakpointFromAddress(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:
|
||||
auto& getBreakpointList(BreakpointType type);
|
||||
|
@ -52,7 +44,6 @@ private:
|
|||
void sendReply(const char* reply);
|
||||
void handleQuery();
|
||||
void handleSetThread();
|
||||
void sendSignal(uint32_t signal);
|
||||
void readCommand();
|
||||
bool isDataAvailable();
|
||||
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);
|
||||
|
||||
buf[1] |= 4 + (isDomainObject ? 4 : 0) + 4 + dataWords;
|
||||
|
||||
|
||||
sfcoOffset = pos * 4;
|
||||
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;
|
||||
resp.initialize(0, 0, 0);
|
||||
resp.errCode = 0;
|
||||
ret = 0;
|
||||
ret = 0x25a0b;
|
||||
break;
|
||||
case 4: // Normal
|
||||
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;
|
||||
ret = 0;
|
||||
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:
|
||||
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);
|
||||
}
|
||||
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;
|
||||
auto ax = (btype & 3) == 1;
|
||||
auto flags_ = btype & 0xC0;
|
||||
|
|
65
Mmio.cpp
65
Mmio.cpp
|
@ -1,25 +1,74 @@
|
|||
#include "Ctu.h"
|
||||
|
||||
Mmio::Mmio(Ctu *_ctu) {
|
||||
MMIORegister(0x70000000, 0x1000, new ApbMmio());
|
||||
class ApbMmio : public MmioBase {
|
||||
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(0x70030000, 0x8000, new ApbMmio());
|
||||
MMIORegister(0x700e3000, 0x100, new ApbMmio());
|
||||
MMIORegister(0x702ef700, 0x40, new ApbMmio());
|
||||
MMIORegister(0x702f9000, 0x1000, new ApbMmio());
|
||||
|
||||
//MMIORegister(0x70030000, 0x8000, new ApbMmio());
|
||||
ctu = _ctu;
|
||||
//MMIOInitialize();
|
||||
}
|
||||
|
||||
void Mmio::MMIORegister(gptr base, guint size, MmioBase *mmioBase) {
|
||||
LOG_DEBUG(Mmio, "Registered MMIO " ADDRFMT, base);
|
||||
mmioBase->setSize(size);
|
||||
|
||||
mmioBases[base] = mmioBase;
|
||||
}
|
||||
|
||||
void Mmio::MMIOInitialize() {
|
||||
mmioBaseSize = 0;
|
||||
for(auto item : mmioBases) {
|
||||
item.second->setOffset(mmioBaseSize);
|
||||
mmioBaseSize += item.second->mmioSize;
|
||||
|
@ -33,8 +82,8 @@ void Mmio::MMIOInitialize() {
|
|||
|
||||
gptr Mmio::getVirtualAddressFromAddr(gptr addr) {
|
||||
for(auto item : mmioBases) {
|
||||
if(addr >= item.first && addr <= (item.first+item.second->mmioSize)) {
|
||||
return mmioBaseAddr+item.second->offsetFromMMIO;
|
||||
if(addr >= item.first && addr < item.first + item.second->mmioSize) {
|
||||
return mmioBaseAddr + item.second->offsetFromMMIO;
|
||||
}
|
||||
}
|
||||
return 0x0;
|
||||
|
@ -44,8 +93,8 @@ gptr Mmio::getPhysicalAddressFromVirtual(gptr addr) {
|
|||
if(addr < mmioBaseAddr) return 0x0;
|
||||
gptr offset = addr - mmioBaseAddr;
|
||||
for(auto item : mmioBases) {
|
||||
if(item.second->offsetFromMMIO >= offset && offset <= item.second->offsetFromMMIO+item.second->mmioSize) {
|
||||
return item.first+offset;
|
||||
if(item.second->offsetFromMMIO <= offset && offset < item.second->offsetFromMMIO + item.second->mmioSize) {
|
||||
return item.first + offset - item.second->offsetFromMMIO;
|
||||
}
|
||||
}
|
||||
return 0x0;
|
||||
|
@ -56,7 +105,7 @@ MmioBase *Mmio::getMMIOFromPhysicalAddress(gptr addr) {
|
|||
if(addr < mmioBaseAddr) return nullptr;
|
||||
gptr offset = addr - mmioBaseAddr;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
16
Mmio.h
16
Mmio.h
|
@ -12,11 +12,10 @@ public:
|
|||
}
|
||||
void Setup();
|
||||
|
||||
virtual bool sread(gptr addr, guint size, void *out) {
|
||||
virtual bool read(gptr addr, guint size, uint64_t &value) {
|
||||
return false;
|
||||
}
|
||||
virtual bool swrite(gptr addr, guint size, void *value) {
|
||||
cout << "no" << endl;
|
||||
virtual bool write(gptr addr, guint size, uint64_t value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -58,14 +57,3 @@ private:
|
|||
guint mmioBaseSize = 0;
|
||||
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)
|
||||
|
||||
#define UNIMPLEMENTED(svc) do { LOG_ERROR(Svc[svc], "!Unimplemented!"); } while(0)
|
||||
|
||||
Svc::Svc(Ctu *_ctu) : ctu(_ctu) {
|
||||
registerSvc_ret_X0_X1( 0x01, SetHeapSize, IX1);
|
||||
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( 0x55, QueryIoMapping, IX1, IX2);
|
||||
registerSvc_ret_X0_X1( 0x56, CreateDeviceAddressSpace, IX1, IX2);
|
||||
registerSvc_ret_X0_X1( 0x57, AttachDeviceAddressSpace, (ghandle) IX0, IX1, IX2);
|
||||
registerSvc_ret_X0_X1( 0x59, MapDeviceAddressSpaceByForce, (ghandle) IX0, (ghandle) IX1, IX2, IX3, IX4, IX5);
|
||||
registerSvc_ret_X0( 0x5c, UnmapDeviceAddressSpace, IX0, (ghandle) IX1, IX2, IX3);
|
||||
registerSvc_ret_X0( 0x57, AttachDeviceAddressSpace, IX0, (ghandle) IX1);
|
||||
registerSvc_ret_X0( 0x59, MapDeviceAddressSpaceByForce, (ghandle) IX0, (ghandle) IX1, IX2, IX3, IX4, IX5);
|
||||
registerSvc_ret_X0( 0x5c, UnmapDeviceAddressSpace, IX0, (ghandle) IX1, IX2, IX3, IX4);
|
||||
registerSvc_ret_X0( 0x74, MapProcessMemory, 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);
|
||||
|
@ -144,6 +146,7 @@ guint Svc::MirrorStack(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);
|
||||
ctu->cpu.unmap(dest, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -238,6 +241,7 @@ guint Svc::GetCurrentProcessorNumber(guint tmp) {
|
|||
|
||||
guint Svc::SignalEvent(ghandle handle) {
|
||||
LOG_DEBUG(Svc[0x11], "SignalEvent 0x%x", handle);
|
||||
UNIMPLEMENTED(0x11);
|
||||
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) {
|
||||
LOG_DEBUG(Svc[0x15], "CreateTransferMemory 0x" LONGFMT " 0x" LONGFMT " 0x" LONGFMT, addr, size, perm);
|
||||
auto tm = make_shared<MemoryBlock>(size, perm);
|
||||
tm->addr = addr;
|
||||
return make_tuple(0, ctu->newHandle(tm));
|
||||
LOG_DEBUG(Svc[0x15], "CreateTransferMemory 0x" LONGFMT " 0x" LONGFMT " 0x" LONGFMT, addr, size, perm);
|
||||
auto tm = make_shared<MemoryBlock>(size, perm);
|
||||
tm->addr = addr;
|
||||
return make_tuple(0, ctu->newHandle(tm));
|
||||
}
|
||||
|
||||
guint Svc::CloseHandle(ghandle handle) {
|
||||
|
@ -271,6 +275,7 @@ guint Svc::CloseHandle(ghandle handle) {
|
|||
|
||||
guint Svc::ResetSignal(ghandle handle) {
|
||||
LOG_DEBUG(Svc[0x17], "ResetSignal 0x%x", handle);
|
||||
UNIMPLEMENTED(0x17);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -310,6 +315,7 @@ tuple<guint, guint> Svc::WaitSynchronization(gptr handles, guint numHandles, gui
|
|||
|
||||
guint Svc::CancelSynchronization(ghandle handle) {
|
||||
LOG_DEBUG(Svc[0x19], "CancelSynchronization 0x%x", handle);
|
||||
UNIMPLEMENTED(0x19);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -445,6 +451,7 @@ guint Svc::SendSyncRequest(ghandle handle) {
|
|||
|
||||
guint Svc::SendSyncRequestEx(gptr buf, guint size, ghandle handle) {
|
||||
LOG_ERROR(Svc[0x22], "SendSyncRequestEx not implemented");
|
||||
UNIMPLEMENTED(0x22);
|
||||
return 0xf601;
|
||||
}
|
||||
|
||||
|
@ -490,7 +497,7 @@ tuple<guint, guint> Svc::GetInfo(guint id1, ghandle handle, guint id2) {
|
|||
matchpair(3, 0, 0x1000000000);
|
||||
matchpair(4, 0, 0xaa0000000);
|
||||
matchpair(5, 0, ctu->heapsize); // Heap region size
|
||||
matchpair(6, 0, 0x100000);
|
||||
matchpair(6, 0, 0x400000);
|
||||
matchpair(7, 0, 0x10000);
|
||||
matchpair(12, 0, 0x8000000);
|
||||
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) {
|
||||
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) {
|
||||
LOG_DEBUG(Svc[0x4E], "ReadWriteRegister");
|
||||
LOG_DEBUG(Svc[0x4E], "ReadWriteRegister reg=" ADDRFMT " rwm=" LONGFMT " val=" LONGFMT, reg, rwm, val);
|
||||
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) {
|
||||
LOG_DEBUG(Svc[0x53], "CreateInterruptEvent");
|
||||
return make_tuple(0, 0);
|
||||
LOG_DEBUG(Svc[0x53], "CreateInterruptEvent irq=" LONGFMT, irq);
|
||||
return make_tuple(0, ctu->newHandle(make_shared<InstantWaitable>()));
|
||||
}
|
||||
|
||||
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);
|
||||
LOG_DEBUG(Svc[0x55], ADDRFMT, addr);
|
||||
if(addr == 0x0) { // force exit for now
|
||||
cout << "!Unknown physical address!" << endl;
|
||||
exit(1);
|
||||
|
@ -588,23 +596,36 @@ tuple<guint, guint> Svc::QueryIoMapping(gptr physaddr, guint size) {
|
|||
return make_tuple(0x0, addr);
|
||||
}
|
||||
|
||||
tuple<guint, guint> Svc::CreateDeviceAddressSpace(guint base, guint size) {
|
||||
LOG_DEBUG(Svc[0x56], "CreateDeviceAddressSpace");
|
||||
return make_tuple(0, 0);
|
||||
class DeviceMemory : public KObject {
|
||||
public:
|
||||
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) {
|
||||
LOG_DEBUG(Svc[0x57], "AttachDeviceAddressSpace");
|
||||
return make_tuple(0, 0);
|
||||
guint Svc::AttachDeviceAddressSpace(guint dev, ghandle handle) {
|
||||
LOG_DEBUG(Svc[0x57], "AttachDeviceAddressSpace dev=" LONGFMT " handle=%x", dev, handle);
|
||||
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) {
|
||||
LOG_DEBUG(Svc[0x59], "MapDeviceAddressSpaceByForce");
|
||||
return make_tuple(0, 0);
|
||||
guint Svc::MapDeviceAddressSpaceByForce(ghandle handle, ghandle phandle, gptr vaddr, guint size, gptr saddr, guint perm) {
|
||||
LOG_DEBUG(Svc[0x59], "MapDeviceAddressSpaceByForce handle=%x phandle=%x vaddr=" ADDRFMT " size=" LONGFMT " saddr=" ADDRFMT " perm=" LONGFMT, handle, phandle, vaddr, size, saddr, perm);
|
||||
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");
|
||||
UNIMPLEMENTED(0x5c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
8
Svc.h
8
Svc.h
|
@ -67,10 +67,10 @@ private:
|
|||
guint UnmapTransferMemory(ghandle handle, gptr addr, guint size); // 0x52
|
||||
tuple<guint, guint> CreateInterruptEvent(guint irq); // 0x53
|
||||
tuple<guint, guint> QueryIoMapping(gptr physaddr, guint size); // 0x55
|
||||
tuple<guint, guint> CreateDeviceAddressSpace(guint base, guint size); // 0x56
|
||||
tuple<guint, guint> AttachDeviceAddressSpace(ghandle handle, guint dev, gptr addr); // 0x57
|
||||
tuple<guint, guint> MapDeviceAddressSpaceByForce(ghandle handle, ghandle phandle, gptr paddr, guint size, gptr maddr, guint perm); // 0x59
|
||||
guint UnmapDeviceAddressSpace(guint unk0, ghandle phandle, gptr maddr, guint size); // 0x5c
|
||||
tuple<guint, guint> CreateDeviceAddressSpace(gptr start, gptr end); // 0x56
|
||||
guint AttachDeviceAddressSpace(guint dev, ghandle handle); // 0x57
|
||||
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, gptr paddr); // 0x5c
|
||||
guint MapProcessMemory(gptr dstaddr, ghandle handle, gptr srcaddr, guint size); // 0x74
|
||||
guint UnmapProcessMemory(gptr dstaddr, ghandle handle, gptr srcaddr, guint size); // 0x75
|
||||
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 wait(function<int()> cb);
|
||||
void wait(function<int(bool)> cb);
|
||||
virtual void wait(function<int(bool)> cb);
|
||||
|
||||
void signal(bool one=false);
|
||||
void cancel();
|
||||
|
@ -26,6 +26,14 @@ private:
|
|||
bool presignaled, canceled;
|
||||
};
|
||||
|
||||
class InstantWaitable : public Waitable {
|
||||
public:
|
||||
virtual void wait(function<int(bool)> cb) {
|
||||
Waitable::wait(cb);
|
||||
signal(true);
|
||||
}
|
||||
};
|
||||
|
||||
class Semaphore : public Waitable {
|
||||
public:
|
||||
Semaphore(Guest<uint32_t> _vptr);
|
||||
|
|
|
@ -18,6 +18,7 @@ void Thread::assignHandle(uint32_t _handle) {
|
|||
}
|
||||
|
||||
void Thread::terminate() {
|
||||
signal();
|
||||
ctu->tm.terminate(id);
|
||||
}
|
||||
|
||||
|
@ -102,6 +103,12 @@ void ThreadManager::start() {
|
|||
while(true) {
|
||||
if(ctu->gdbStub.enabled) {
|
||||
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)
|
||||
continue;
|
||||
auto wasStep = ctu->gdbStub.stepLoop;
|
||||
|
|
|
@ -1,40 +1,7 @@
|
|||
#pragma once
|
||||
#include "Ctu.h"
|
||||
|
||||
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;
|
||||
|
||||
class Thread : public KObject {
|
||||
class Thread : public Waitable {
|
||||
public:
|
||||
Thread(Ctu *_ctu, int _id);
|
||||
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
|
||||
from pprint import pprint
|
||||
import idparser, partialparser
|
||||
from cStringIO import StringIO
|
||||
|
||||
def emitInt(x):
|
||||
return '0x%x' % x if x > 9 else str(x)
|
||||
|
@ -115,6 +116,7 @@ def isPointerType(type):
|
|||
return isPointerType(allTypes[type[0]])
|
||||
return True
|
||||
|
||||
INIT = 'INIT'
|
||||
AFTER = 'AFTER'
|
||||
|
||||
def generateCaller(qname, fname, func):
|
||||
|
@ -155,7 +157,7 @@ def generateCaller(qname, fname, func):
|
|||
elif type == 'KObject':
|
||||
params.append('ctu->getHandle<KObject>(req.getCopied(%i))' % hndOff)
|
||||
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
|
||||
elif type == 'pid':
|
||||
params.append('req.pid')
|
||||
|
@ -242,7 +244,7 @@ def generateCaller(qname, fname, func):
|
|||
yield 'return 0xf601;'
|
||||
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):
|
||||
yield 'LOG_DEBUG(IpcStubs, "IPC message to %s: %s"%s);' % (qname + '::' + fname, ', '.join(logFmt), (', ' + ', '.join(logElems)) if logElems else '')
|
||||
else:
|
||||
|
@ -253,12 +255,20 @@ def generateCaller(qname, fname, func):
|
|||
|
||||
def reorder(gen):
|
||||
after = []
|
||||
before = []
|
||||
for x in gen:
|
||||
if x == AFTER:
|
||||
for elem in after:
|
||||
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:
|
||||
after.append(x[1])
|
||||
elif before is not None:
|
||||
before.append(x)
|
||||
else:
|
||||
yield x
|
||||
|
||||
|
@ -305,90 +315,100 @@ def main():
|
|||
for name in sorted(ifaces.keys()):
|
||||
namespaces[ns].append('class %s;' % name)
|
||||
|
||||
with file('IpcStubs.h', 'w') as fp:
|
||||
print >>fp, '#pragma once'
|
||||
print >>fp, '#include "Ctu.h"'
|
||||
print >>fp
|
||||
fp = StringIO()
|
||||
print >>fp, '#pragma once'
|
||||
print >>fp, '#include "Ctu.h"'
|
||||
print >>fp
|
||||
|
||||
print >>fp, '#define SERVICE_MAPPING() do { \\'
|
||||
for iname, snames in sorted(services.items(), key=lambda x: x[0]):
|
||||
for sname in snames:
|
||||
print >>fp, '\tSERVICE("%s", %s); \\' % (sname, iname)
|
||||
print >>fp, '} while(0)'
|
||||
print >>fp
|
||||
print >>fp, '#define SERVICE_MAPPING() do { \\'
|
||||
for iname, snames in sorted(services.items(), key=lambda x: x[0]):
|
||||
for sname in snames:
|
||||
print >>fp, '\tSERVICE("%s", %s); \\' % (sname, iname)
|
||||
print >>fp, '} while(0)'
|
||||
print >>fp
|
||||
|
||||
for ns, elems in sorted(namespaces.items(), key=lambda x: x[0]):
|
||||
if ns is not None:
|
||||
print >>fp, 'namespace %s {' % ns
|
||||
hasUsing = False
|
||||
for elem in elems:
|
||||
if not hasUsing and elem.startswith('using'):
|
||||
hasUsing = True
|
||||
elif hasUsing and elem.startswith('class'):
|
||||
print >>fp
|
||||
hasUsing = False
|
||||
print >>fp, ('\t' if ns is not None else '') + elem
|
||||
if ns is not None:
|
||||
print >>fp, '}'
|
||||
for ns, elems in sorted(namespaces.items(), key=lambda x: x[0]):
|
||||
if ns is not None:
|
||||
print >>fp, 'namespace %s {' % ns
|
||||
hasUsing = False
|
||||
for elem in elems:
|
||||
if not hasUsing and elem.startswith('using'):
|
||||
hasUsing = True
|
||||
elif hasUsing and elem.startswith('class'):
|
||||
print >>fp
|
||||
hasUsing = False
|
||||
print >>fp, ('\t' if ns is not None else '') + elem
|
||||
if ns is not None:
|
||||
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]):
|
||||
print >>fp, '%snamespace %s {' % ('//// ' if ns is None else '', ns)
|
||||
for name, funcs in sorted(ifaces.items(), key=lambda x: x[0]):
|
||||
qname = '%s::%s' % (ns, name) if ns else name
|
||||
partial = partials[qname] if qname in partials else None
|
||||
print >>fp, '\tclass %s : public IpcService {' % name
|
||||
print >>fp, '\tpublic:'
|
||||
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 '')
|
||||
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\t\tswitch(req.cmdId) {'
|
||||
for fname, func in sorted(funcs.items(), key=lambda x: x[1]['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, '\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)
|
||||
for ns, ifaces in sorted(ifacesByNs.items(), key=lambda x: x[0]):
|
||||
print >>fp, '%snamespace %s {' % ('//// ' if ns is None else '', ns)
|
||||
for name, funcs in sorted(ifaces.items(), key=lambda x: x[0]):
|
||||
qname = '%s::%s' % (ns, name) if ns else name
|
||||
partial = partials[qname] if qname in partials else None
|
||||
print >>fp, '\tclass %s : public IpcService {' % name
|
||||
print >>fp, '\tpublic:'
|
||||
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 '')
|
||||
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\t\tswitch(req.cmdId) {'
|
||||
for fname, func in sorted(funcs.items(), key=lambda x: x[1]['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, '\t\t\t}'
|
||||
print >>fp, '\t\t}'
|
||||
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)
|
||||
print >>fp, '\t\tuint32_t %s(%s);' % (fname, generatePrototype(func))
|
||||
if partial:
|
||||
for x in partial[0]:
|
||||
print >>fp, '\t\t%s' % x
|
||||
print >>fp, '\t};'
|
||||
print >>fp, '%s}' % ('//// ' if ns is None else '')
|
||||
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}'
|
||||
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)
|
||||
print >>fp, '\t\tuint32_t %s(%s);' % (fname, generatePrototype(func))
|
||||
if partial:
|
||||
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'
|
||||
for name, funcs in sorted(ifaces.items(), key=lambda x: x[0]):
|
||||
qname = '%s::%s' % (ns, name) if ns else name
|
||||
partial = partials[qname] if qname in partials else None
|
||||
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)
|
||||
if not implemented:
|
||||
print >>fp, 'uint32_t %s::%s(%s) {' % (qname, fname, generatePrototype(func))
|
||||
print >>fp, '\tLOG_DEBUG(IpcStubs, "Stub implementation for %s::%s");' % (qname, fname)
|
||||
for i, (name, elem) in enumerate(func['outputs']):
|
||||
if elem[0] == 'object' and elem[1][0] != 'IUnknown':
|
||||
name = name if name else '_%i' % (len(func['inputs']) + i)
|
||||
print >>fp, '\t%s = buildInterface(%s);' % (name, elem[1][0])
|
||||
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)
|
||||
sys.exit(1)
|
||||
elif elem[0] == 'KObject':
|
||||
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, '\treturn 0;'
|
||||
print >>fp, '}'
|
||||
print >>fp, '#endif // DEFINE_STUBS'
|
||||
print >>fp, '#ifdef DEFINE_STUBS'
|
||||
for name, funcs in sorted(ifaces.items(), key=lambda x: x[0]):
|
||||
qname = '%s::%s' % (ns, name) if ns else name
|
||||
partial = partials[qname] if qname in partials else None
|
||||
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)
|
||||
if not implemented:
|
||||
print >>fp, 'uint32_t %s::%s(%s) {' % (qname, fname, generatePrototype(func))
|
||||
print >>fp, '\tLOG_DEBUG(IpcStubs, "Stub implementation for %s::%s");' % (qname, fname)
|
||||
for i, (name, elem) in enumerate(func['outputs']):
|
||||
if elem[0] == 'object' and elem[1][0] != 'IUnknown':
|
||||
name = name if name else '_%i' % (len(func['inputs']) + i)
|
||||
print >>fp, '\t%s = buildInterface(%s);' % (name, elem[1][0])
|
||||
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)
|
||||
sys.exit(1)
|
||||
elif elem[0] == 'KObject':
|
||||
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, '\treturn 0;'
|
||||
print >>fp, '}'
|
||||
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__':
|
||||
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 {
|
||||
[0] Unknown0(buffer<unknown, 0x21, 0>);
|
||||
[0] Log(buffer<u8, 0x21, 0> message);
|
||||
[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;
|
||||
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) {
|
||||
assert(exists(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);
|
||||
auto top = raddr + 0x100000000;
|
||||
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) {
|
||||
assert(exists(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);
|
||||
auto top = raddr + 0x100000000;
|
||||
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) {
|
||||
|
|
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