updates and such from private

This commit is contained in:
misson20000 2017-11-05 11:14:19 -08:00
parent 6081adccfa
commit 3b2063f6c7
29 changed files with 2870 additions and 2154 deletions

13
.dir-locals.el Normal file
View 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
View file

@ -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
View file

@ -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));
}

View file

@ -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
View file

@ -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
View file

@ -0,0 +1,2 @@
https://github.com/lz4/lz4.git
https://pypi.python.org/pypi/tatsu/4.0.0

View file

@ -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});

View file

@ -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
View file

@ -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
View file

@ -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;

View file

@ -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
View file

@ -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
View file

@ -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
View file

@ -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
View file

@ -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);

View file

@ -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;

View file

@ -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);

File diff suppressed because it is too large Load diff

View file

@ -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
View 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)))

View file

@ -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
View 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
View 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
View 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
View 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
View 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;
}

View file

@ -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;
}

View file

@ -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
View 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!