Compare commits

...

16 commits

Author SHA1 Message Date
misson20000
a3cedc251c
Merge pull request #31 from Thog/feature/swipc
Use SwIPC as a submodule
2018-08-16 01:59:28 -07:00
misson20000
29d5a00ebe
Merge pull request #30 from Thog/feature/ipc-5.x
ipc: Add 5.0+ message types
2018-08-16 01:59:16 -07:00
misson20000
63ddfccaa3
Merge pull request #29 from Thog/feature/decompressed-nso
Support uncompressed segments in NSO
2018-08-16 01:59:08 -07:00
Thog
f3afe2dcc9
nso: Do not try to decompress if segment isn't compressed 2018-08-16 10:02:16 +02:00
Thog
ed9905785f
Update SwIPC submodule
This also add enum and versioning support.
Please note that actual SwIPC master doesn't have parameters for
LaunchProcess (in pm:shel)
2018-08-16 09:47:24 +02:00
Thog
2ae322bd9d
Fix structure with sized members 2018-08-16 09:47:14 +02:00
Thog
c2ee5f8a05
Make Mephisto uses SwIPC directly
This permite to provide more up to date data.

Please note that this cannot work with actual SwiPC master because it's
missing a __init__.py file.
2018-08-16 09:47:03 +02:00
Thog
4e658cab57
ipc: Add 5.0+ message types (ignore the context for now) 2018-08-16 09:44:46 +02:00
misson20000
7c46b8e68a return correct error code on svcGetInfo instead of crashing 2018-07-17 23:25:52 -07:00
misson20000
355af21785 ~IFile: only close files if we actually opened them (fixes heisensegfault) 2018-05-16 12:25:22 -07:00
misson20000
b2b6a831f2 add svcMap/UnmapPhysicalMemory 2018-05-16 12:23:58 -07:00
misson20000
175186ddbe ldr:ro implementation 2018-04-26 20:29:24 -07:00
misson20000
7e05066e43 fix svcQueryMemory for heap region 2018-03-28 20:42:24 -07:00
misson20000
86e61651db add --initialize-memory option to help catch uninitialized memory errors 2018-03-28 14:24:58 -07:00
misson20000
5632e77ed4 add --relocate option, for running relocations on NRO files (useful for debugging libtransistor's relocator) 2018-03-28 14:24:35 -07:00
misson20000
fb375ce291 move map region to within 38-bit address space 2018-03-05 14:36:16 -08:00
44 changed files with 368 additions and 7481 deletions

2
.gitignore vendored
View file

@ -3,8 +3,6 @@
*.pch
ctu
membundle.bin
ipcdefs/auto.id
ipcdefs/cache
IpcStubs.h
SwitchFS/syssave*
SwitchFS/sdcard

3
.gitmodules vendored
View file

@ -1,3 +1,6 @@
[submodule "unicorn"]
path = unicorn
url = https://github.com/reswitched/unicorn.git
[submodule "SwIPC"]
path = SwIPC
url = https://github.com/reswitched/SwIPC.git

View file

@ -120,7 +120,14 @@ void Cpu::stop() {
bool Cpu::map(gptr addr, guint size) {
CHECKED(uc_mem_map(uc, addr, size, UC_PROT_ALL));
auto temp = new uint8_t[size];
memset(temp, 0, size);
if(ctu->initializeMemory) {
uint8_t val[] = "badmem!!";
for(size_t sz = 0; sz < size; sz++) {
temp[sz] = val[sz % sizeof(val)];
}
} else {
memset(temp, 0, size);
}
writemem(addr, temp, size);
delete[] temp;
return true;

22
Ctu.h
View file

@ -214,10 +214,30 @@ public:
gptr loadbase, loadsize;
bool socketsEnabled;
bool initializeMemory = false;
private:
ghandle handleId;
unordered_map<ghandle, shared_ptr<KObject>> handles;
};
// TODO: move this/autogenerate this
#define VERSION_1_0_0 0
#define VERSION_2_0_0 1
#define VERSION_2_1_0 2
#define VERSION_2_2_0 3
#define VERSION_2_3_0 4
#define VERSION_3_0_0 5
#define VERSION_3_0_1 6
#define VERSION_3_0_2 7
#define VERSION_4_0_0 8
#define VERSION_4_0_1 9
#define VERSION_4_1_0 10
#define VERSION_5_0_0 11
#define VERSION_5_0_1 12
#define VERSION_5_0_2 13
#define VERSION_5_1_0 14
#define TARGET_VERSION VERSION_5_1_0
#include "IpcStubs.h"

View file

@ -174,9 +174,11 @@ uint32_t IpcService::messageSync(shared_ptr<array<uint8_t, 0x100>> buf, bool& cl
ret = 0x25a0b;
break;
case 4: // Normal
case 6: // Normal with Context
ret = target->dispatch(msg, resp);
break;
case 5: // Control
case 7: // Control with Context
switch(msg.cmdId) {
case 0: // ConvertSessionToDomain
LOG_DEBUG(Ipc, "ConvertSessionToDomain");
@ -239,7 +241,7 @@ ghandle IpcService::fauxNewHandle(shared_ptr<KObject> obj) {
}
Ipc::Ipc(Ctu *_ctu) : ctu(_ctu) {
sm = make_shared<SmService>(ctu);
sm = make_shared<nn::sm::detail::IUserInterface>(ctu);
}
ghandle Ipc::ConnectToPort(string name) {

6
Ipc.h
View file

@ -244,13 +244,15 @@ protected:
class IUnknown : public IpcService {
};
class SmService;
namespace nn::sm::detail {
class IUserInterface;
}
class Ipc {
public:
Ipc(Ctu *_ctu);
ghandle ConnectToPort(string name);
shared_ptr<SmService> sm;
shared_ptr<nn::sm::detail::IUserInterface> sm;
private:
Ctu *ctu;
};

View file

@ -11,10 +11,10 @@ OBJ_FILES := $(CPP_FILES:.cpp=.o) $(IPCIMPL_FILES:.cpp=.o)
all: ctu
ipcdefs/auto.id: genallipc.py
$(PYTHON2) genallipc.py
SwIPC/ipcdefs/auto.id: SwIPC/scripts/genallipc.py
cd SwIPC && $(PYTHON2) scripts/genallipc.py
IpcStubs.h: $(ID_FILES) $(IPCIMPL_FILES) ipcdefs/auto.id generateIpcStubs.py idparser.py partialparser.py
IpcStubs.h: $(ID_FILES) $(IPCIMPL_FILES) SwIPC/ipcdefs/auto.id generateIpcStubs.py SwIPC/idparser.py partialparser.py
$(PYTHON2) generateIpcStubs.py
%.pch: % IpcStubs.h $(H_FILES)

17
Nxo.cpp
View file

@ -141,18 +141,20 @@ guint Kip::load(Ctu &ctu, gptr base, bool relocate) {
}
typedef struct {
uint32_t magic, pad0, pad1, pad2;
uint32_t magic, pad0, pad1, flags;
uint32_t textOff, textLoc, textSize, pad3;
uint32_t rdataOff, rdataLoc, rdataSize, pad4;
uint32_t dataOff, dataLoc, dataSize;
uint32_t bssSize;
} NsoHeader;
char *decompress(ifstream &fp, uint32_t offset, uint32_t csize, uint32_t usize) {
char *nso_read_and_decompress(ifstream &fp, uint32_t offset, uint32_t csize, uint32_t usize, bool need_decompression) {
fp.seekg(offset);
char *buf = new char[csize];
char *obuf = new char[usize];
fp.read(buf, csize);
if (!need_decompression)
return buf;
char *obuf = new char[usize];
assert(LZ4_decompress_safe(buf, obuf, csize, usize) == usize);
delete[] buf;
return obuf;
@ -170,15 +172,18 @@ guint Nso::load(Ctu &ctu, gptr base, bool relocate) {
ctu.cpu.map(base, tsize);
char *text = decompress(fp, hdr.textOff, hdr.rdataOff - hdr.textOff, hdr.textSize);
bool is_text_compressed = ((hdr.flags >> 0) & 1) != 0;
char *text = nso_read_and_decompress(fp, hdr.textOff, hdr.rdataOff - hdr.textOff, hdr.textSize, is_text_compressed);
ctu.cpu.writemem(base + hdr.textLoc, text, hdr.textSize);
delete[] text;
char *rdata = decompress(fp, hdr.rdataOff, hdr.dataOff - hdr.rdataOff, hdr.rdataSize);
bool is_rdata_compressed = ((hdr.flags >> 1) & 1) != 0;
char *rdata = nso_read_and_decompress(fp, hdr.rdataOff, hdr.dataOff - hdr.rdataOff, hdr.rdataSize, is_rdata_compressed);
ctu.cpu.writemem(base + hdr.rdataLoc, rdata, hdr.rdataSize);
delete[] rdata;
char *data = decompress(fp, hdr.dataOff, length - hdr.dataOff, hdr.dataSize);
bool is_data_compressed = ((hdr.flags >> 2) & 1) != 0;
char *data = nso_read_and_decompress(fp, hdr.dataOff, length - hdr.dataOff, hdr.dataSize, is_data_compressed);
ctu.cpu.writemem(base + hdr.dataLoc, data, hdr.dataSize);
delete[] data;

21
Svc.cpp
View file

@ -105,6 +105,8 @@ Svc::Svc(Ctu *_ctu) : ctu(_ctu) {
registerSvc_ret_X0( 0x26, Break, IX0, IX1, IX2);
registerSvc_ret_X0( 0x27, OutputDebugString, IX0, IX1);
registerSvc_ret_X0_X1( 0x29, GetInfo, IX1, (ghandle) IX2, IX3);
registerSvc_ret_X0( 0x2C, MapPhysicalMemory, IX0, IX1);
registerSvc_ret_X0( 0x2D, UnmapPhysicalMemory, IX0, IX1);
registerSvc_ret_X0_X1_X2( 0x40, CreateSession, (ghandle) IX0, (ghandle) IX1, IX2);
registerSvc_ret_X0_X1( 0x41, AcceptSession, (ghandle) IX1);
registerSvc_ret_X0_X1( 0x43, ReplyAndReceive, IX1, IX2, (ghandle) IX3, IX4);
@ -178,7 +180,7 @@ tuple<guint, guint> Svc::QueryMemory(gptr meminfo, gptr pageinfo, gptr addr) {
minfo.size = end - begin + 1;
minfo.memory_type = perm == -1 ? 0 : 3; // FREE or CODE
minfo.memory_attribute = 0;
if(addr >= 0xaa0000000 && addr <= 0xaa0000000 + ctu->heapsize) {
if(addr >= 0xaa0000000 && addr < 0xaa0000000 + ctu->heapsize) {
minfo.memory_type = 5; // HEAP
}
minfo.permission = 0;
@ -523,7 +525,7 @@ tuple<guint, guint> Svc::GetInfo(guint id1, ghandle handle, guint id2) {
LOG_DEBUG(Svc[0x29], "GetInfo handle=0x%x id1=0x" LONGFMT " id2=" LONGFMT, handle, id1, id2);
matchpair(0, 0, 0xF);
matchpair(1, 0, 0xFFFFFFFF00000000);
matchpair(2, 0, 0xbb00000000); // map region
matchpair(2, 0, 0xbb0000000); // map region
matchpair(3, 0, 0x1000000000); // size
matchpair(4, 0, 0xaa0000000); // heap region
matchpair(5, 0, ctu->heapsize); // size
@ -531,12 +533,23 @@ tuple<guint, guint> Svc::GetInfo(guint id1, ghandle handle, guint id2) {
matchpair(7, 0, 0x10000);
matchpair(12, 0, 0x8000000);
matchpair(13, 0, 0x7ff8000000);
matchpair(14, 0, 0xbb00000000); // new map region
matchpair(14, 0, 0xbb0000000); // new map region
matchpair(15, 0, 0x1000000000); // size
matchpair(18, 0, 0x0100000000000036); // Title ID
matchone(11, 0);
LOG_ERROR(Svc[0x29], "Unknown getinfo");
return make_tuple(0xf001, 0);
}
guint Svc::MapPhysicalMemory(gptr addr, guint size) {
LOG_DEBUG(Svc[0x2C], "MapPhysicalMemory(0x" LONGFMT ", 0x" LONGFMT ")", addr, size);
ctu->cpu.map(addr, size);
return 0;
}
guint Svc::UnmapPhysicalMemory(gptr addr, guint size) {
ctu->cpu.unmap(addr, size);
return 0;
}
tuple<guint, guint, guint> Svc::CreateSession(ghandle clientOut, ghandle serverOut, guint unk) {

2
Svc.h
View file

@ -58,6 +58,8 @@ private:
guint Break(guint X0, guint X1, guint info); // 0x26
guint OutputDebugString(guint ptr, guint size); // 0x27
tuple<guint, guint> GetInfo(guint id1, ghandle handle, guint id2); // 0x29
guint MapPhysicalMemory(gptr addr, guint size); // 0x2C
guint UnmapPhysicalMemory(gptr addr, guint size); // 0x2D
tuple<guint, guint, guint> CreateSession(ghandle clientOut, ghandle serverOut, guint unk); // 0x40
tuple<guint, guint> AcceptSession(ghandle port); // 0x41
tuple<guint, guint> ReplyAndReceive(gptr handles, guint numHandles, ghandle replySession, guint timeout); // 0x43

1
SwIPC Submodule

@ -0,0 +1 @@
Subproject commit 9bb842022806979ce6f6c97dce686c378c386c86

File diff suppressed because it is too large Load diff

View file

@ -1,11 +1,17 @@
import glob, hashlib, json, os, os.path, re, sys
from pprint import pprint
import idparser, partialparser
from SwIPC import idparser
import partialparser
from cStringIO import StringIO
def emitInt(x):
return '0x%x' % x if x > 9 else str(x)
handlemap = dict(
session='IPipe',
port='NPort',
)
typemap = dict(
i8='int8_t',
i16='int16_t',
@ -61,10 +67,12 @@ def splitByNs(obj):
ons[ns][name] = x
return ons
def retype(spec, noIndex=False):
def retype(spec, noIndex=False, noArray=False):
if spec[0] == 'unknown':
return 'uint8_t'
elif spec[0] == 'bytes':
if noArray:
return 'uint8_t'
return 'uint8_t%s' % ('[%s]' % emitInt(spec[1]) if not noIndex else ' *')
else:
return typemap[spec[0]] if spec[0] in typemap else spec[0];
@ -84,7 +92,7 @@ def formatParam(param, input, i):
elif spec[0] == 'unknown':
assert False
elif spec[0] == 'buffer':
type = '%s *' % retype(spec[1])
type = '%s *' % retype(spec[1], noArray=True)
hasSize = True
elif spec[0] == 'array':
type = retype(spec[1]) + ' *'
@ -92,7 +100,10 @@ def formatParam(param, input, i):
elif spec[0] == 'object':
type = 'shared_ptr<%s>' % spec[1][0]
elif spec[0] == 'KObject':
type = 'shared_ptr<KObject>'
if len(spec) >= 2 and spec[2][0] in handlemap:
type = 'shared_ptr<%s>' % handlemap[spec[2][0]]
else:
type = 'shared_ptr<KObject>'
else:
type = typemap[spec[0]] if spec[0] in typemap else spec[0]
@ -101,7 +112,6 @@ def formatParam(param, input, i):
type = type[:-len(arrspec)]
else:
arrspec = ''
return '%s %s%s %s%s%s' % ('IN' if input else 'OUT', type, '&' if not input and (not type.endswith('*') and not arrspec) else '', name, arrspec, ', guint %s_size' % name if hasSize else '')
def generatePrototype(func):
@ -114,6 +124,8 @@ def isPointerType(type):
return True
elif type[0] in allTypes:
return isPointerType(allTypes[type[0]])
elif type[0] == 'struct' or type[0] == 'enum':
return False
return True
INIT = 'INIT'
@ -143,9 +155,9 @@ def generateCaller(qname, fname, func):
yield 'auto %s = req.getBuffer(%s, %i, %s);' % (an, emitInt(rest[1]), cbo, sn)
yield 'auto %s = new uint8_t[%s];' % (bn, sn)
yield 'ctu->cpu.readmem(%s, %s, %s);' % (an, bn, sn)
params.append('(%s *) %s' % (retype(rest[0]), bn))
params.append('(%s *) %s' % (retype(rest[0], noArray=True), bn))
params.append(sn)
logFmt.append('%s *%s= buffer<0x" ADDRFMT ">' % (retype(rest[0]), '%s ' % name if name else ''))
logFmt.append('%s *%s= buffer<0x" ADDRFMT ">' % (retype(rest[0], noArray=True), '%s ' % name if name else ''))
logElems.append(sn)
bufSizes += 1
yield AFTER, 'delete[] %s;' % bn
@ -155,9 +167,11 @@ def generateCaller(qname, fname, func):
logElems.append('req.getMoved(%i)' % objOff)
objOff += 1
elif type == 'KObject':
params.append('ctu->getHandle<KObject>(req.getCopied(%i))' % hndOff)
handle_operation = rest[0][0] if len(rest) > 0 else 'copy'
req_function = 'getMoved' if handle_operation == 'move' else 'getCopied'
params.append('ctu->getHandle<KObject>(req.%s(%i))' % (req_function, hndOff))
logFmt.append('KObject %s= 0x%%x' % ('%s ' % name if name else ''))
logElems.append('req.getCopied(%i)' % hndOff)
logElems.append('req.%s(%i)' % (req_function, hndOff))
hndOff += 1
elif type == 'pid':
params.append('req.pid')
@ -175,7 +189,7 @@ def generateCaller(qname, fname, func):
logElems.append('bufferToString(req.getDataPointer<uint8_t *>(%s), %s).c_str()' % (emitInt(inpOffset), emitInt(typeSize(elem))))
else:
params.append('req.getData<%s>(%s)' % (retype(elem), emitInt(inpOffset)))
if typeSize(elem) == 16:
if typeSize(elem) == 16 or elem[0] not in typesizes:
logFmt.append('%s %s= %%s' % (retype(elem), '%s ' % name if name else ''))
logElems.append('bufferToString(req.getDataPointer<uint8_t *>(%s), %s).c_str()' % (emitInt(inpOffset), emitInt(typeSize(elem))))
else:
@ -216,12 +230,22 @@ def generateCaller(qname, fname, func):
yield AFTER, '\tresp.move(%i, createHandle(%s));' % (objOff, tn)
objOff += 1
elif type == 'KObject':
handle_operation = rest[0][0] if len(rest) > 0 else 'copy'
resp_function = 'move' if handle_operation == 'move' else 'copy'
handle_creation_fnction = 'createHandle' if handle_operation == 'move' else 'ctu->newHandle'
tn = tempname()
yield 'shared_ptr<KObject> %s;' % tn
if len(rest) > 1 and rest[1][0] in handlemap:
definition = 'shared_ptr<%s>' % handlemap[rest[1][0]]
else:
definition = 'shared_ptr<KObject>'
yield '%s %s;' % (definition, tn)
params.append(tn)
yield AFTER, 'if(%s != nullptr)' % tn
yield AFTER, '\tresp.copy(%i, ctu->newHandle(%s));' % (hndOff, tn)
hndOff += 1
yield AFTER, '\tresp.%s(%i, %s(%s));' % (resp_function, hndOff, handle_creation_fnction, tn)
if resp_function == 'move':
objOff += 1
else:
hndOff += 1
elif type == 'pid':
assert False
else:
@ -276,6 +300,29 @@ def parsePartials(code):
code = '\n'.join(re.findall(r'/\*\$IPC\$(.*?)\*/', code, re.M|re.S))
return partialparser.parse(code)
def getVersionName(version):
if version == None:
return None
return "VERSION_%s" % version.replace(".", "_")
def getVersionId(target_version):
for id, version in enumerate(idparser.versionInfo):
if (version == target_version):
return id
return -1
def generateVersionChecks(first_version, last_version):
first_version_id = getVersionId(first_version)
last_version_id = getVersionId(last_version)
if first_version_id > 0 and last_version_id != -1:
return '#if TARGET_VERSION >= %s && TARGET_VERSION <= %s' % (getVersionName(first_version), getVersionName(last_version))
if first_version_id > 0:
return '#if TARGET_VERSION >= %s' % getVersionName(first_version)
elif last_version_id != -1:
return '#if TARGET_VERSION <= %s' % getVersionName(last_version)
return None
usedInts = []
def uniqInt(*args):
args = ''.join(map(str, args))
@ -289,15 +336,7 @@ def uniqInt(*args):
def main():
global allTypes
fns = ['ipcdefs/auto.id'] + [x for x in glob.glob('ipcdefs/*.id') if x != 'ipcdefs/auto.id']
if os.path.exists('ipcdefs/cache') and all(os.path.getmtime('ipcdefs/cache') > os.path.getmtime(x) for x in fns):
res = json.load(file('ipcdefs/cache'))
else:
res = idparser.parse('\n'.join(file(fn).read() for fn in fns))
with file('ipcdefs/cache', 'w') as fp:
json.dump(res, fp)
types, ifaces, services = res
types, ifaces, services = idparser.getAll()
allTypes = types
@ -308,8 +347,22 @@ def main():
for ns, types in typesByNs.items():
for name, spec in sorted(types.items(), key=lambda x: x[0]):
retyped, plain = retype(spec, noIndex=True), retype(spec)
namespaces[ns].append('using %s = %s;%s' % (name, retyped, ' // ' + plain if retyped != plain else ''))
if spec[0] == 'struct':
namespaces[ns].append('using %s = struct {' % (name))
for sub_spec in spec[1:][0]:
extra_data = ''
if sub_spec[1][0] == 'bytes':
extra_data = '[%s]' % emitInt(sub_spec[1][1])
namespaces[ns].append('\t%s %s%s;' % (retype(sub_spec[1], noArray=True), sub_spec[0], extra_data))
namespaces[ns].append('};')
elif spec[0] == 'enum':
namespaces[ns].append('using %s = enum {' % (name))
for sub_spec in spec[1:][0]:
namespaces[ns].append('\t%s = %d,' % (sub_spec[0], sub_spec[1]))
namespaces[ns].append('};')
else:
retyped, plain = retype(spec, noIndex=True), retype(spec)
namespaces[ns].append('using %s = %s;%s' % (name, retyped, ' // ' + plain if retyped != plain else ''))
for ns, ifaces in ifacesByNs.items():
for name in sorted(ifaces.keys()):
@ -320,6 +373,12 @@ def main():
print >>fp, '#include "Ctu.h"'
print >>fp
for id, version in enumerate(idparser.versionInfo):
version = getVersionName(version)
print >>fp,"#ifndef %s" % (version)
print >>fp, "#define %s %d" % (version, id)
print >>fp, "#endif\n"
print >>fp, '#define SERVICE_MAPPING() do { \\'
for iname, snames in sorted(services.items(), key=lambda x: x[0]):
for sname in snames:
@ -362,17 +421,28 @@ def main():
print >>fp, '\t\t~%s();' % name
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)))
for func in sorted(funcs['cmds'], key=lambda x: x['cmdId']):
conditional_case = generateVersionChecks(func['versionAdded'], func['lastVersion'])
if conditional_case != None:
print >>fp, '\t\t\t%s' % conditional_case
print >>fp, '\t\t\tcase %i: {' % func['cmdId']
print >>fp, '\n'.join('\t\t\t\t' + x for x in reorder(generateCaller(qname, func['name'], func)))
print >>fp, '\t\t\t}'
if conditional_case != None:
print >>fp, '\t\t\t#endif'
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]):
for func in sorted(funcs['cmds'], key=lambda x: x['name']):
fname = func['name']
implemented = re.search('[^a-zA-Z0-9:]%s::%s[^a-zA-Z0-9:]' % (qname, fname), allcode)
conditional_case = generateVersionChecks(func['versionAdded'], func['lastVersion'])
if conditional_case != None:
print >>fp, '\t\t%s' % conditional_case
print >>fp, '\t\tuint32_t %s(%s);' % (fname, generatePrototype(func))
if conditional_case != None:
print >>fp, '\t\t#endif'
if partial:
for x in partial[0]:
print >>fp, '\t\t%s' % x
@ -383,9 +453,13 @@ def main():
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]):
for func in sorted(funcs['cmds'], key=lambda x: x['name']):
fname = func['name']
implemented = re.search('[^a-zA-Z0-9:]%s::%s[^a-zA-Z0-9:]' % (qname, fname), allcode)
if not implemented:
conditional_case = generateVersionChecks(func['versionAdded'], func['lastVersion'])
if conditional_case != None:
print >>fp, '%s' % conditional_case
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']):
@ -400,6 +474,8 @@ def main():
print >>fp, '\t%s = make_shared<FauxHandle>(0x%x);' % (name, uniqInt(qname, fname, name))
print >>fp, '\treturn 0;'
print >>fp, '}'
if conditional_case != None:
print >>fp, '#endif'
print >>fp, '#endif // DEFINE_STUBS'
code = fp.getvalue()

View file

@ -1,95 +0,0 @@
import sys, tatsu
grammar = '''
start = { def }+ $ ;
number
=
| /0x[0-9a-fA-F]+/
| /[0-9]+/
;
def
=
| typeDef
| interface
;
expression
=
| type
| number
;
name = /[a-zA-Z_][a-zA-Z0-9_:]*/ ;
sname = /[a-zA-Z_][a-zA-Z0-9_:\-]*/ ;
serviceNameList = @:','.{ sname } ;
template = '<' @:','.{ expression } '>' ;
type = name:name template:[ template ] ;
typeDef = 'type' name:name '=' type:type ';' ;
interface = 'interface' name:name [ 'is' serviceNames:serviceNameList ] '{' functions:{ funcDef }* '}' ;
namedTuple = '(' @:','.{ type [ name ] } ')' ;
namedType = type [ name ] ;
funcDef = '[' cmdId:number ']' name:name inputs:namedTuple [ '->' outputs:( namedType | namedTuple ) ] ';' ;
'''
class Semantics(object):
def number(self, ast):
if ast.startswith('0x'):
return int(ast[2:], 16)
return int(ast)
def namedTuple(self, ast):
return [elem if isinstance(elem, list) else [elem, None] for elem in ast]
def namedType(self, ast):
return [ast if isinstance(ast, list) else [ast, None]]
def parseType(type):
if not isinstance(type, tatsu.ast.AST) or 'template' not in type:
return type
name, template = type['name'], type['template']
if template is None:
return [name]
else:
return [name] + map(parseType, template)
def parse(data):
ast = tatsu.parse(grammar, data, semantics=Semantics(), eol_comments_re=r'\/\/.*?$')
types = {}
for elem in ast:
if 'type' not in elem:
continue
#assert elem['name'] not in types
types[elem['name']] = parseType(elem['type'])
ifaces = {}
services = {}
for elem in ast:
if 'functions' not in elem:
continue
#assert elem['name'] not in ifaces
ifaces[elem['name']] = iface = {}
if elem['serviceNames']:
services[elem['name']] = list(elem['serviceNames'])
for func in elem['functions']:
if func['name'] in iface:
print >>sys.stderr, 'Duplicate function %s in %s' % (func['name'], elem['name'])
sys.exit(1)
assert func['name'] not in iface
iface[func['name']] = fdef = {}
fdef['cmdId'] = func['cmdId']
fdef['inputs'] = [(name, parseType(type)) for type, name in func['inputs']]
if func['outputs'] is None:
fdef['outputs'] = []
elif isinstance(func['outputs'], tatsu.ast.AST):
fdef['outputs'] = [(None, parseType(func['outputs']))]
else:
fdef['outputs'] = [(name, parseType(type)) for type, name in func['outputs']]
return types, ifaces, services

File diff suppressed because it is too large Load diff

View file

@ -1,8 +0,0 @@
interface nn::bgtc::IStateControlService is bgtc:sc {
}
interface nn::bgtc::ITaskService is bgtc:t {
[3] Unknown3() -> KObject;
[5] Unknown5(buffer<unknown, 9, 0>);
[14] Unknown14() -> KObject;
}

View file

@ -1,48 +0,0 @@
interface nn::socket::sf::IClient is bsd:u, bsd:s {
[0] RegisterClient(u64, u64, u64, u64, u64 pid, u64 transferMemorySize, pid, KObject) -> u32 bsd_errno; // tested
[1] StartMonitoring(u64, pid);
[2] Socket(u32 domain, u32 type, u32 protocol) -> (i32 ret, u32 bsd_errno); // tested
[3] SocketExempt(u32, u32, u32) -> (i32 ret, u32 bsd_errno);
[4] Open(u32, buffer<unknown, 0x21, 0>) -> (i32 ret, u32 bsd_errno);
[5] Select(u32 nfds, bytes<0x18> timeout, buffer<fd_set, 0x21, 0> readfds_in, buffer<fd_set, 0x21, 0> writefds_in, buffer<fd_set, 0x21, 0> errorfds_in) -> (i32 ret, u32 bsd_errno, buffer<fd_set, 0x22, 0> readfds_out, buffer<fd_set, 0x22, 0> writefds_out, buffer<fd_set, 0x22, 0> errorfds_out);
[6] Poll(u32, u32, buffer<unknown, 0x21, 0>) -> (i32 ret, u32 bsd_errno, buffer<unknown, 0x22, 0>);
[7] Sysctl(buffer<unknown, 0x21, 0>, buffer<unknown, 0x21, 0>) -> (i32 ret, u32 bsd_errno, u32, buffer<unknown, 0x22, 0>);
[8] Recv(u32 socket, u32 flags) -> (i32 ret, u32 bsd_errno, buffer<i8, 0x22, 0> message); // tested
[9] RecvFrom(u32 sock, u32 flags) -> (i32 ret, u32 bsd_errno, u32 addrlen, buffer<i8, 0x22, 0> message, buffer<sockaddr, 0x22, 0>);
[10] Send(u32 socket, u32 flags, buffer<i8, 0x21, 0>) -> (i32 ret, u32 bsd_errno); // tested
[11] SendTo(u32 socket, u32 flags, buffer<i8, 0x21, 0>, buffer<sockaddr, 0x21, 0>) -> (i32 ret, u32 bsd_errno); // tested
[12] Accept(u32 socket) -> (i32 ret, u32 bsd_errno, u32 addrlen, buffer<sockaddr, 0x22, 0> addr); // tested
[13] Bind(u32 socket, buffer<sockaddr, 0x21, 0>) -> (i32 ret, u32 bsd_errno); // tested
[14] Connect(u32 socket, buffer<sockaddr, 0x21, 0>) -> (i32 ret, u32 bsd_errno); // tested
[15] GetPeerName(u32 socket) -> (i32 ret, u32 bsd_errno, u32 addrlen, buffer<sockaddr, 0x22, 0> addr);
[16] GetSockName(u32 socket) -> (i32 ret, u32 bsd_errno, u32 addrlen, buffer<sockaddr, 0x22, 0> addr);
[17] GetSockOpt(u32, u32, u32) -> (i32 ret, u32 bsd_errno, u32, buffer<unknown, 0x22, 0>);
[18] Listen(u32 socket, u32 backlog) -> (i32 ret, u32 bsd_errno); // tested
[19] Ioctl(u32, u32, u32, buffer<unknown, 0x21, 0>, buffer<unknown, 0x21, 0>, buffer<unknown, 0x21, 0>, buffer<unknown, 0x21, 0>) -> (i32 ret, u32 bsd_errno, buffer<unknown, 0x22, 0>, buffer<unknown, 0x22, 0>, buffer<unknown, 0x22, 0>, buffer<unknown, 0x22, 0>);
[20] Fcntl(u32, u32, u32) -> (i32 ret, u32 bsd_errno);
[21] SetSockOpt(u32 socket, u32 level, u32 option_name, buffer<unknown, 0x21, 0>) -> (i32 ret, u32 bsd_errno);
[22] Shutdown(u32 socket, u32 how) -> (i32 ret, u32 bsd_errno);
[23] ShutdownAllSockets(u32 how) -> (i32 ret, u32 bsd_errno);
[24] Write(u32 socket, buffer<i8, 0x21, 0> message) -> (i32 ret, u32 bsd_errno);
[25] Read(u32 socket) -> (i32 ret, u32 bsd_errno, buffer<i8, 0x22, 0> message);
[26] Close(u32 socket) -> (i32 ret, u32 bsd_errno); // tested
[27] DuplicateSocket(u32, u64) -> (i32 ret, u32 bsd_errno);
[28] GetResourceStatistics(u64, pid) -> (i32 ret, u32 bsd_errno, buffer<unknown, 0x22, 0>);
[29] RecvMMsg(u32, u32, u32, u128) -> (i32 ret, u32 bsd_errno, buffer<unknown, 0x22, 0>); // [3.0.0+]
[30] SendMMsg(u32, u32, u32, buffer<unknown, 0x21, 0>, buffer<unknown, 0x21, 0>) -> (i32 ret, u32 bsd_errno); // [3.0.0+]
}
type packed_addrinfo = unknown;
interface nn::socket::resolver::IResolver is sfdnsres {
[0] SetDnsAddressesPrivate(u32, buffer<unknown, 5, 0>);
[1] GetDnsAddressPrivate(u32) -> buffer<unknown, 6, 0>;
[2] GetHostByName(u8, u32, u64, pid, buffer<unknown, 5, 0>) -> (u32, u32, u32, buffer<unknown, 6, 0>);
[3] GetHostByAddr(u32, u32, u32, u64, pid, buffer<unknown, 5, 0>) -> (u32, u32, u32, buffer<unknown, 6, 0>);
[4] GetHostStringError(u32) -> buffer<unknown, 6, 0>;
[5] GetGaiStringError(u32) -> buffer<unknown, 6, 0>;
[6] GetAddrInfo(bool enable_nsd_resolve, u32, u64 pid_placeholder, pid, buffer<i8, 5, 0> host, buffer<i8, 5, 0> service, buffer<packed_addrinfo, 5, 0> hints) -> (i32 ret, u32 bsd_errno, u32 packed_addrinfo_size, buffer<packed_addrinfo, 6, 0> response);
[7] GetNameInfo(u32, u32, u64, pid, buffer<unknown, 5, 0>) -> (u32, u32, buffer<unknown, 6, 0>, buffer<unknown, 6, 0>);
[8] RequestCancelHandle(u64, pid) -> u32;
[9] CancelSocketCall(u32, u64, pid);
}

View file

@ -1,7 +0,0 @@
interface nn::capsrv::sf::IAlbumControlService is caps:c {
}
interface nn::capsrv::sf::IAlbumAccessorService is caps:a {
}

View file

@ -1,2 +0,0 @@
interface nn::es::IETicketService is es {
}

View file

@ -1,5 +0,0 @@
interface nn::fatalsrv::IService is fatal:u {
[0] Unknown0(u64, u64, pid);
[1] Unknown1(u64, u64, pid);
[2] TransitionToFatalError(u64 errorCode, u64, buffer<unknown, 0x15, 0x110> errorBuf, pid);
}

View file

@ -1,156 +0,0 @@
type nn::fssrv::sf::SaveStruct = bytes<0x40>;
type nn::fssrv::sf::SaveCreateStruct = bytes<0x40>;
type nn::fssrv::sf::Partition = u32;
// --------------------------------------------- FSP-SRV ---------------------------------------------
interface nn::fssrv::sf::IFileSystemProxy is fsp-srv {
[1] Initialize(u64, pid);
[2] OpenDataFileSystemByCurrentProcess() -> object<nn::fssrv::sf::IFileSystem>;
[7] MountContent7(nn::ApplicationId tid, u32 ncaType) -> object<nn::fssrv::sf::IFileSystem>;
[8] MountContent(nn::ApplicationId tid, u32 flag, buffer<i8, 0x19, 0x301> path) -> object<nn::fssrv::sf::IFileSystem> contentFs;
[9] OpenDataFileSystemByApplicationId(nn::ApplicationId tid) -> object<nn::fssrv::sf::IFileSystem> dataFiles;
[11] MountBis(nn::fssrv::sf::Partition partitionID, buffer<i8, 0x19, 0x301> path) -> object<nn::fssrv::sf::IFileSystem> Bis;
[12] OpenBisPartition(nn::fssrv::sf::Partition partitionID) -> object<nn::fssrv::sf::IStorage> BisPartition;
[13] InvalidateBisCache();
[17] OpenHostFileSystemImpl(buffer<i8, 0x19, 0x301> path) -> object<nn::fssrv::sf::IFileSystem>;
[18] MountSdCard() -> object<nn::fssrv::sf::IFileSystem> sdCard;
[19] FormatSdCard();
[21] DeleteSaveData(nn::ApplicationId tid);
[22] CreateSaveData(nn::fssrv::sf::SaveStruct saveStruct, nn::fssrv::sf::SaveCreateStruct saveCreate, u128 input);
[23] CreateSystemSaveData(nn::fssrv::sf::SaveStruct saveStruct, nn::fssrv::sf::SaveCreateStruct saveCreate);
[24] RegisterSaveDataAtomicDeletion(buffer<void, 5, 0>);
[25] DeleteSaveDataWithSpaceId(u8, u64);
[26] FormatSdCardDryRun();
[27] IsExFatSupported() -> u8 isSupported;
[30] OpenGameCardPartition(nn::fssrv::sf::Partition partitionID, u32) -> object<nn::fssrv::sf::IStorage> gameCardFs;
[31] MountGameCardPartition(u32, u32) -> object<nn::fssrv::sf::IFileSystem> gameCardPartitionFs;
[32] ExtendSaveData(u8, u64, u64, u64);
[51] MountSaveData(u8 input, nn::fssrv::sf::SaveStruct saveStruct) -> object<nn::fssrv::sf::IFileSystem> saveDataFs;
[52] MountSystemSaveData(u8 input, nn::fssrv::sf::SaveStruct saveStruct) -> object<nn::fssrv::sf::IFileSystem> systemSaveDataFs;
[53] MountSaveDataReadOnly(u8 input, nn::fssrv::sf::SaveStruct saveStruct) -> object<nn::fssrv::sf::IFileSystem> saveDataFs;
[57] ReadSaveDataFileSystemExtraDataWithSpaceId (u8, u64) -> buffer<void, 6, 0>;
[58] ReadSaveDataFileSystemExtraData(u64) -> buffer<void, 6, 0>;
[59] WriteSaveDataFileSystemExtraData(u64, u8, buffer<void, 5, 0>);
[60] OpenSaveDataInfoReader() -> object<nn::fssrv::sf::ISaveDataInfoReader>;
[61] OpenSaveDataIterator(u8) -> object<IUnknown>;
[80] OpenSaveDataThumbnailFile(u8, bytes<0x40>, u32) -> object<nn::fssrv::sf::IFile> thumbnail;
[100] MountImageDirectory(u32) -> object<nn::fssrv::sf::IFileSystem> imageFs;
[110] MountContentStorage(u32 contentStorageID) -> object<nn::fssrv::sf::IFileSystem> contentFs;
[200] OpenDataStorageByCurrentProcess() -> object<nn::fssrv::sf::IStorage> dataStorage;
[201] OpenDataStorageByApplicationId(nn::ApplicationId tid) -> object<nn::fssrv::sf::IStorage> dataStorage;
[202] OpenDataStorageByDataId(nn::ApplicationId tid, u8 storageId) -> object<nn::fssrv::sf::IStorage> dataStorage;
[203] OpenRomStorage() -> object<nn::fssrv::sf::IStorage>;
[400] OpenDeviceOperator() -> object<nn::fssrv::sf::IDeviceOperator>;
[500] OpenSdCardDetectionEventNotifier() -> object<nn::fssrv::sf::IEventNotifier> SdEventNotify;
[501] OpenGameCardDetectionEventNotifier() -> object<nn::fssrv::sf::IEventNotifier> GameCardEventNotify;
[600] SetCurrentPosixTime(u64 time);
[601] QuerySaveDataTotalSize(u64, u64) -> u64 saveDataSize;
[602] VerifySaveData(nn::ApplicationId tid) -> buffer<void, 6, 0>;
[603] CorruptSaveDataForDebug(nn::ApplicationId tid);
[604] CreatePaddingFile(u64 size);
[605] DeleteAllPaddingFiles();
[606] GetRightsId(u64, u8) -> u128 rights;
[607] RegisterExternalKey(u128, u128);
[608] UnregisterExternalKey();
[609] GetRightsIdByPath(buffer<i8, 0x19, 0x301> path) -> u128 rights;
[610] GetRightsIdByPath2(buffer<i8, 0x19, 0x301> path) -> (u128 rights, u8);
[620] SetSdCardEncryptionSeed(u128 seedmaybe);
[800] GetAndClearFileSystemProxyErrorInfo() -> bytes<0x80> errorInfo;
[1000] SetBisRootForHost(u32, buffer<i8, 0x19, 0x301> path);
[1001] SetSaveDataSize(u64, u64);
[1002] SetSaveDataRootPath(buffer<i8, 0x19, 0x301> path);
[1003] DisableAutoSaveDataCreation();
[1004] SetGlobalAccessLogMode(u32 mode);
[1005] GetGlobalAccessLogMode() -> u32 logMode;
[1006] OutputAccessLogToSdCard(buffer<void, 5, 0> logText);
}
interface nn::fssrv::sf::IStorage {
[0] Read(u64 offset, u64 length) -> buffer<i8, 0x46, 0> buffer;
[1] Write(u64 offset, u64 length, buffer<i8, 0x45, 0> data);
[2] Flush();
[3] SetSize(u64 size);
[4] GetSize() -> u64 size;
}
interface nn::fssrv::sf::IFileSystem {
[0] CreateFile(u64 mode, u32 size, buffer<i8, 0x19, 0x301> path);
[1] DeleteFile(buffer<i8, 0x19, 0x301> path);
[2] CreateDirectory(buffer<i8, 0x19, 0x301> path);
[3] DeleteDirectory(buffer<i8, 0x19, 0x301> path);
[4] DeleteDirectoryRecursively(buffer<i8, 0x19, 0x301> path);
[5] RenameFile(buffer<i8, 0x19, 0x301> oldPath, buffer<i8, 0x19, 0x301> newPath);
[6] RenameDirectory(buffer<i8, 0x19, 0x301> oldPath, buffer<i8, 0x19, 0x301> newPath);
[7] GetEntryType(buffer<i8, 0x19, 0x301> path) -> u32;
[8] OpenFile(u32 mode, buffer<i8, 0x19, 0x301> path) -> object<nn::fssrv::sf::IFile> file;
[9] OpenDirectory(u32, buffer<i8, 0x19, 0x301> path) -> object<nn::fssrv::sf::IDirectory> directory;
[10] Commit();
[11] GetFreeSpaceSize(buffer<i8, 0x19, 0x301> path) -> u64 totalFreeSpace;
[12] GetTotalSpaceSize(buffer<i8, 0x19, 0x301> path) -> u64 totalSize;
[13] CleanDirectoryRecursively(buffer<i8, 0x19, 0x301> path);
[14] GetFileTimeStampRaw(buffer<i8, 0x19, 0x301> path) -> bytes<0x20> timestamp;
}
interface nn::fssrv::sf::IDeviceOperator {
[0] IsSdCardInserted() -> u8 isSdInserted;
[1] GetSdCardSpeedMode() -> u64 sdSpeed;
[2] GetSdCardCid(u64) -> buffer<unknown, 6, 0> cid;
[3] GetSdCardUserAreaSize() -> u64 size;
[4] GetSdCardProtectedAreaSize() -> u64 protectedSize;
[5] GetAndClearSdCardErrorInfo(u64) -> (u128, u64, buffer<unknown, 6, 0>);
[100] GetMmcCid(u64) -> buffer<unknown, 6, 0> cid;
[101] GetMmcSpeedMode() -> u64 speedMode;
[110] EraseMmc(u32);
[111] GetMmcPartitionSize(u32) -> u64 paritionSize;
[112] GetMmcPatrolCount() -> u32 patrolCount;
[113] GetAndClearMmcErrorInfo(u64) -> (u128, u64, buffer<unknown, 6, 0>);
[114] GetMmcExtendedCsd(u64) -> buffer<unknown, 6, 0>;
[200] IsGameCardInserted() -> u8 isGameInserted;
[201] EraseGameCard(u32, u64);
[202] GetGameCardHandle() -> u32 gamecardHandle;
[203] GetGameCardUpdatePartitionInfo(u32) -> (u32 version, nn::ApplicationId TID);
[204] FinalizeGameCardDriver();
[205] GetGameCardAttribute(u32) -> u8 attribute;
[206] GetGameCardDeviceCertificate(u64, u32) -> buffer<unknown, 6, 0> certificate;
[207] GetGameCardAsicInfo(u64, u64, buffer<unknown, 5, 0>) -> buffer<unknown, 6, 0>;
[208] GetGameCardIdSet(u64) -> buffer<unknown, 6, 0>;
[209] WriteToGameCard(u64, u64) -> buffer<unknown, 6, 0>;
[210] SetVerifyWriteEnalbleFlag(u8 flag);
[211] GetGameCardImageHash(u64, u32) -> buffer<unknown, 6, 0> imageHash;
[212] GetGameCardDeviceIdForProdCard(u64, u64, buffer<unknown, 5, 0>) -> buffer<unknown, 6, 0> errorInfo;
[213] EraseAndWriteParamDirectly(u64, buffer<unknown, 5, 0>);
[214] GetGameCardCid(u64) -> buffer<unknown, 6, 0> cid;
[215] ForceEraseGameCard();
[216] GetGameCardErrorInfo() -> u128 errorInfo;
[217] GetGameCardErrorReportInfo() -> bytes<0x40> errorReportInfo;
[218] GetGameCardDeviceId(u64) -> buffer<unknown, 6, 0> deviceID;
[300] SetSpeedEmulationMode(u32 mode);
[301] GetSpeedEmulationMode() -> u32 emuMode;
}
interface nn::fssrv::sf::IDirectory {
[0] Read() -> (u64, buffer<unknown, 6, 0>);
[1] GetEntryCount() -> u64;
}
interface nn::fssrv::sf::IFile {
[0] Read(u64, u64 offset, u32 size) -> (u64 out_size, buffer<i8, 0x46, 0> out_buf);
[1] Write(u64, u64 offset, u32 size, buffer<i8, 0x45, 0> buf);
[2] Flush();
[3] SetSize(u64 size);
[4] GetSize() -> u64 fileSize;
}
// --------------------------------------------- FSP-PR ---------------------------------------------
interface nn::fssrv::sf::IProgramRegistry {
[0] SetFsPermissions(u64, u64, u8, u64, u64, buffer<unknown, 5, 0>, buffer<unknown, 5, 0>);
[1] ClearFsPermissions(u64 pid);
[256] SetEnabledProgramVerification(u8 enabled);
}
// --------------------------------------------- FSP-LDR ---------------------------------------------
interface nn::fssrv::sf::IFileSystemProxyForLoader {
[0] MountCode(nn::ApplicationId TID, buffer<i8, 0x19, 0x301> contentPath) -> object<nn::fssrv::sf::IFileSystem> contentFs;
[1] IsCodeMounted(nn::ApplicationId TID) -> u8 isMounted;
}

View file

View file

@ -1,28 +0,0 @@
interface nn::gpio::IManager is gpio {
[0] Unknown0(u32) -> object<IUnknown>;
[1] GetPadSession(u32) -> object<nn::gpio::IPadSession>;
[2] Unknown2(u32) -> object<IUnknown>;
[3] Unknown3(u32) -> u8;
[4] Unknown4() -> u128;
[5] Unknown5(u32, u8);
[6] Unknown6(u8);
}
interface nn::gpio::IPadSession {
[0] Unknown0(u32);
[1] Unknown1() -> u32;
[2] Unknown2(u32);
[3] Unknown3() -> u32;
[4] Unknown4(u8);
[5] Unknown5() -> u8;
[6] Unknown6() -> u32;
[7] Unknown7();
[8] Unknown8(u32);
[9] Unknown9() -> u32;
[10] Unknown10() -> KObject;
[11] Unknown11();
[12] Unknown12(u8);
[13] Unknown13() -> u8;
[14] Unknown14(u32);
[15] Unknown15() -> u32;
}

View file

@ -1,4 +0,0 @@
interface nn::ro::detail::ILdrShellInterface is ldr:shel {
[0] AddProcessToLaunchQueue(buffer<unknown, 0x19, 0x200>, u32 size, nn::ncm::ApplicationId appID);
[1] ClearLaunchQueue();
}

View file

@ -1,8 +0,0 @@
interface nn::lm::ILogService is lm {
[0] Initialize(u64, pid) -> object<nn::lm::ILogger> Log;
}
interface nn::lm::ILogger {
[0] Log(buffer<u8, 0x21, 0> message);
[1] Unknown1(u32);
}

View file

@ -1,24 +0,0 @@
interface nn::ncm::detail::INcmInterface4Unknown {
[10] Unknown10();
[13] Unknown13() -> u64;
}
interface nn::ncm::detail::INcmInterface5Unknown {
[5] Unknown5() -> u64;
[7] Unknown7() -> u64;
[8] Unknown8();
[15] Unknown15();
}
interface nn::ncm::detail::INcmInterface is ncm {
[2] Unknown2() -> u64;
[3] Unknown3() -> u64;
[4] Unknown4() -> object<nn::ncm::detail::INcmInterface4Unknown>;
[5] Unknown5() -> object<nn::ncm::detail::INcmInterface5Unknown>;
[9] Unknown9() -> u64;
[11] Unknown11() -> u64;
}
interface nn::ncm::detail::LocationResolverInterface is lr {
}

View file

@ -1,23 +0,0 @@
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>;
}

View file

@ -1,9 +0,0 @@
interface nn::nim::detail::INetworkInstallManager is nim {
[2] Unknown2(buffer<unknown, 6, 0x200>) -> (u64, u64);
[8] Unknown8() -> (u64, u64);
[40] Unknown40(buffer<unknown, 6, 0x200>) -> (u64, u64);
}
interface nn::nim::detail::IShopServiceManager is nim:shp {
}

View file

@ -1,8 +0,0 @@
interface nn::npns::Weird {
}
interface nn::npns::INpnsSystem is npns:s {
[5] SetInterfaceVersion() -> KObject;
[7] Unknown7() -> KObject;
[103] Unknown103() -> KObject;
}

View file

@ -1,10 +0,0 @@
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 {
}

View file

@ -1,3 +0,0 @@
interface nn::ovln::ISender is ovln:snd {
[0] Unknown0(u64 unk1, u64 unk2, u64 unk3, u64 unk4, u64 unk5, u64 unk6, u64 unk7, u64 unk8, u64 unk9, u64 unk10, u64 unk11, u64 unk12, u64 unk13, u64 unk14, u64 unk15, u64 unk16, u64 unk17);
}

View file

@ -1,21 +0,0 @@
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>);
}

View file

@ -1,9 +0,0 @@
interface Pm::Shell is pm:shell {
[0] LaunchTitle(u64, nn::ApplicationId tid);
[3] GetProcessEventWaiter() -> KObject;
}
interface Pm::Bm is pm:bm {
[0] Init() -> (u64);
[1] EnableMaintenanceMode();
}

View file

@ -1,10 +0,0 @@
interface nn::psc::sf::IPmControl is psc:c {
}
interface nn::psc::sf::IPmModule {
[0] Unknown0(u32, buffer<unknown, 5, 0>) -> KObject;
}
interface nn::psc::sf::IPmService is psc:m {
[0] GetIPmModule() -> object<nn::psc::sf::IPmModule>;
}

View file

@ -1,46 +0,0 @@
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 {
}

View file

@ -1,8 +0,0 @@
type ServiceName = bytes<8>;
interface SmService {
[0] Initialize();
[1] GetService(ServiceName name) -> object<IPipe>;
[2] RegisterService(ServiceName name) -> object<NPort>;
[3] UnregisterService(ServiceName name);
}

View file

@ -27,7 +27,7 @@ nn::socket::sf::IClient::IClient(Ctu *_ctu) : IpcService(_ctu) {
passthrough = _ctu->socketsEnabled;
}
uint32_t nn::socket::sf::IClient::Accept(IN uint32_t socket, OUT int32_t& ret, OUT uint32_t& bsd_errno, OUT uint32_t& sockaddr_len, OUT sockaddr * _4, guint _4_size) {
uint32_t nn::socket::sf::IClient::Accept(IN uint32_t socket, OUT int32_t& ret, OUT uint32_t& bsd_errno, OUT uint32_t& sockaddr_len, OUT nn::socket::sockaddr_in * _4, guint _4_size) {
LOG_DEBUG(IpcStubs, "Stub implementation for nn::socket::sf::IClient::accept");
if(passthrough) {
struct sockaddr *addr = (struct sockaddr *) _4;
@ -42,7 +42,8 @@ uint32_t nn::socket::sf::IClient::Accept(IN uint32_t socket, OUT int32_t& ret, O
}
return 0;
}
uint32_t nn::socket::sf::IClient::Bind(IN uint32_t socket, IN sockaddr * _1, guint _1_size, OUT int32_t& ret, OUT uint32_t& bsd_errno) {
uint32_t nn::socket::sf::IClient::Bind(IN uint32_t socket, IN nn::socket::sockaddr_in * _1, guint _1_size, OUT int32_t& ret, OUT uint32_t& bsd_errno) {
LOG_DEBUG(IpcStubs, "Stub implementation for nn::socket::sf::IClient::bind");
if(passthrough) {
struct sockaddr *addr = (struct sockaddr *) _1;
@ -66,7 +67,7 @@ uint32_t nn::socket::sf::IClient::Close(IN uint32_t socket, OUT int32_t& ret, OU
}
return 0;
}
uint32_t nn::socket::sf::IClient::Connect(IN uint32_t socket, IN sockaddr * _1, guint _1_size, OUT int32_t& ret, OUT uint32_t& bsd_errno) {
uint32_t nn::socket::sf::IClient::Connect(IN uint32_t socket, IN nn::socket::sockaddr_in * _1, guint _1_size, OUT int32_t& ret, OUT uint32_t& bsd_errno) {
LOG_DEBUG(IpcStubs, "Stub implementation for nn::socket::sf::IClient::connect");
if(passthrough) {
struct sockaddr *addr = (struct sockaddr *) _1;
@ -79,7 +80,7 @@ uint32_t nn::socket::sf::IClient::Connect(IN uint32_t socket, IN sockaddr * _1,
}
return 0;
}
uint32_t nn::socket::sf::IClient::GetSockName(IN uint32_t socket, OUT int32_t& ret, OUT uint32_t& bsd_errno, OUT uint32_t& sockaddr_len, OUT sockaddr * _4, guint _4_size) {
uint32_t nn::socket::sf::IClient::GetSockName(IN uint32_t socket, OUT int32_t& ret, OUT uint32_t& bsd_errno, OUT uint32_t& sockaddr_len, OUT nn::socket::sockaddr_in * _4, guint _4_size) {
LOG_DEBUG(IpcStubs, "Stub implementation for nn::socket::sf::IClient::getsockname");
if(passthrough) {
struct sockaddr *addr = (struct sockaddr *) _4;
@ -128,7 +129,7 @@ uint32_t nn::socket::sf::IClient::Send(IN uint32_t socket, IN uint32_t flags, IN
}
return 0;
}
uint32_t nn::socket::sf::IClient::SendTo(IN uint32_t socket, IN uint32_t flags, IN int8_t * _2, guint _2_size, IN sockaddr * _3, guint _3_size, OUT int32_t& ret, OUT uint32_t& bsd_errno) {
uint32_t nn::socket::sf::IClient::SendTo(IN uint32_t socket, IN uint32_t flags, IN int8_t * _2, guint _2_size, IN nn::socket::sockaddr_in * _3, guint _3_size, OUT int32_t& ret, OUT uint32_t& bsd_errno) {
LOG_DEBUG(IpcStubs, "Stub implementation for nn::socket::sf::IClient::sendto");
if(passthrough) {
struct sockaddr *addr = (struct sockaddr *) _3;

View file

@ -60,7 +60,7 @@ uint32_t nn::fssrv::sf::IStorage::GetSize(OUT uint64_t& size) {
LOG_DEBUG(Fsp, "Failed to get file size!");
return 0;
}
uint32_t nn::fssrv::sf::IStorage::Read(IN uint64_t offset, IN uint64_t length, OUT int8_t * buffer, guint buffer_size) {
uint32_t nn::fssrv::sf::IStorage::Read(IN uint64_t offset, IN uint64_t length, OUT uint8_t * buffer, guint buffer_size) {
if(isOpen && fp != nullptr) {
uint32_t s = ((uint32_t)buffer_size < (uint32_t)length ? (uint32_t)buffer_size : (uint32_t)length);
bufferOffset = offset;
@ -87,7 +87,7 @@ uint32_t nn::fssrv::sf::IStorage::SetSize(IN uint64_t size) {
}
return 0;
}
uint32_t nn::fssrv::sf::IStorage::Write(IN uint64_t offset, IN uint64_t length, IN int8_t * data, guint data_size) {
uint32_t nn::fssrv::sf::IStorage::Write(IN uint64_t offset, IN uint64_t length, IN uint8_t * data, guint data_size) {
if(isOpen && fp != nullptr) {
bufferOffset = offset;
uint32_t s = ((uint32_t)data_size < (uint32_t)length ? (uint32_t)data_size : (uint32_t)length);
@ -106,19 +106,21 @@ uint32_t nn::fssrv::sf::IStorage::Write(IN uint64_t offset, IN uint64_t length,
}
// Funcs
uint32_t nn::fssrv::sf::IFileSystemProxy::OpenBisPartition(IN nn::fssrv::sf::Partition partitionID, OUT shared_ptr<nn::fssrv::sf::IStorage>& BisPartition) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::OpenBisPartition");
uint32_t nn::fssrv::sf::IFileSystemProxy::OpenBisStorage(IN nn::fssrv::sf::Partition partitionID, OUT shared_ptr<nn::fssrv::sf::IStorage>& BisPartition) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::OpenBisStorage");
BisPartition = buildInterface(nn::fssrv::sf::IStorage, "bis.istorage");
return 0x0;
}
uint32_t nn::fssrv::sf::IFileSystemProxy::OpenDataStorageByApplicationId(IN nn::ApplicationId tid, OUT shared_ptr<nn::fssrv::sf::IStorage>& dataStorage) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::OpenDataStorageByApplicationId 0x" ADDRFMT, tid);
#if TARGET_VERSION >= VERSION_3_0_0
uint32_t nn::fssrv::sf::IFileSystemProxy::OpenDataStorageByProgramId(IN nn::ApplicationId tid, OUT shared_ptr<nn::fssrv::sf::IStorage>& dataStorage) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::OpenDataStorageByProgramId 0x" ADDRFMT, tid);
std::stringstream ss;
ss << "tid_archives_" << hex << tid << ".istorage";
dataStorage = buildInterface(nn::fssrv::sf::IStorage, ss.str());
return 0;
}
#endif
uint32_t nn::fssrv::sf::IFileSystemProxy::OpenDataStorageByCurrentProcess(OUT shared_ptr<nn::fssrv::sf::IStorage>& dataStorage) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::OpenDataStorageByCurrentProcess");
@ -127,22 +129,23 @@ uint32_t nn::fssrv::sf::IFileSystemProxy::OpenDataStorageByCurrentProcess(OUT sh
return 0;
}
uint32_t nn::fssrv::sf::IFileSystemProxy::OpenDataStorageByDataId(IN nn::ApplicationId tid, IN uint8_t storageId, OUT shared_ptr<nn::fssrv::sf::IStorage>& dataStorage) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::OpenDataStorageByDataId 0x" ADDRFMT, 0x0100000000000800+(uint64_t)storageId);
uint32_t nn::fssrv::sf::IFileSystemProxy::OpenDataStorageByDataId(IN uint8_t storageId, IN nn::ApplicationId tid, OUT shared_ptr<nn::fssrv::sf::IStorage>& dataStorage) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::OpenDataStorageByDataId 0x" ADDRFMT, tid);
std::stringstream ss;
ss << "archives/" << hex << setw(16) << setfill('0') << 0x0100000000000800+(uint64_t)storageId << ".istorage";
ss << "archives/" << hex << setw(16) << setfill('0') << tid << ".istorage";
dataStorage = buildInterface(nn::fssrv::sf::IStorage, ss.str());
return 0;
}
uint32_t nn::fssrv::sf::IFileSystemProxy::OpenGameCardPartition(IN nn::fssrv::sf::Partition partitionID, IN uint32_t _1, OUT shared_ptr<nn::fssrv::sf::IStorage>& gameCardFs) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::OpenGameCardPartition");
uint32_t nn::fssrv::sf::IFileSystemProxy::OpenGameCardStorage(IN nn::fssrv::sf::Partition partitionID, IN uint32_t _1, OUT shared_ptr<nn::fssrv::sf::IStorage>& gameCardFs) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::OpenGameCardStorage");
gameCardFs = buildInterface(nn::fssrv::sf::IStorage, "GamePartition.istorage");
return 0;
}
uint32_t nn::fssrv::sf::IFileSystemProxy::OpenRomStorage(OUT shared_ptr<nn::fssrv::sf::IStorage>& _0) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::OpenRomStorage");
uint32_t nn::fssrv::sf::IFileSystemProxy::OpenPatchDataStorageByCurrentProcess(OUT shared_ptr<nn::fssrv::sf::IStorage>& _0) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::OpenPatchDataStorageByCurrentProcess");
_0 = buildInterface(nn::fssrv::sf::IStorage, "RomStorage.istorage");
return 0;
}
@ -156,13 +159,13 @@ nn::fssrv::sf::IFileSystem::IFileSystem(Ctu *_ctu, string _fnPath) : IpcService
LOG_DEBUG(Fsp, "Open path %s", fnPath.c_str());
}
uint32_t nn::fssrv::sf::IFileSystem::DeleteFile(IN int8_t * path, guint path_size) {
uint32_t nn::fssrv::sf::IFileSystem::DeleteFile(IN uint8_t * path, guint path_size) {
LOG_DEBUG(Fsp, "Delete file %s", (fnPath+string((char*)path)).c_str());
remove((fnPath+string((char*)path)).c_str());
return 0;
}
uint32_t nn::fssrv::sf::IFileSystem::CreateFile(IN uint64_t mode, IN uint32_t size, IN int8_t * path, guint path_size) {
uint32_t nn::fssrv::sf::IFileSystem::CreateFile(IN uint32_t mode, IN uint64_t size, IN uint8_t * path, guint path_size) {
LOG_DEBUG(Fsp, "Create file %s", (fnPath+string((char*)path)).c_str());
FILE *fp = fopen((fnPath+string((char*)path)).c_str(), "wb");
if(!fp)
@ -171,22 +174,22 @@ uint32_t nn::fssrv::sf::IFileSystem::CreateFile(IN uint64_t mode, IN uint32_t si
return 0;
}
uint32_t nn::fssrv::sf::IFileSystem::CreateDirectory(IN int8_t * path, guint path_size) {
uint32_t nn::fssrv::sf::IFileSystem::CreateDirectory(IN uint8_t * path, guint path_size) {
LOG_DEBUG(Fsp, "Create directory %s", (fnPath+string((char*)path)).c_str());
if (mkdir((fnPath+string((char*)path)).c_str(), 0755) == -1)
return 0x7d402;
return 0;
}
uint32_t nn::fssrv::sf::IFileSystem::GetEntryType(IN int8_t * path, guint path_size, OUT uint32_t& _1) {
uint32_t nn::fssrv::sf::IFileSystem::GetEntryType(IN uint8_t * path, guint path_size, OUT nn::fssrv::sf::DirectoryEntryType& _1) {
LOG_DEBUG(IpcStubs, "GetEntryType for file %s", (fnPath + string((char*)path)).c_str());
struct stat path_stat;
stat((fnPath+string((char*)path)).c_str(), &path_stat);
if (S_ISREG(path_stat.st_mode))
_1 = 1;
_1 = File;
else if (S_ISDIR(path_stat.st_mode))
_1 = 0;
_1 = Directory;
else
return 0x271002;
return 0;
@ -194,95 +197,111 @@ uint32_t nn::fssrv::sf::IFileSystem::GetEntryType(IN int8_t * path, guint path_s
// Funcs
#if TARGET_VERSION == VERSION_1_0_0
uint32_t nn::fssrv::sf::IFileSystemProxy::OpenFileSystem(IN nn::fssrv::sf::FileSystemType filesystem_type, IN nn::ApplicationId tid, IN uint8_t * path, guint path_size, OUT shared_ptr<nn::fssrv::sf::IFileSystem>& contentFs) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::OpenFileSystem");
contentFs = buildInterface(nn::fssrv::sf::IFileSystem, "");
return 0;
}
#endif
uint32_t nn::fssrv::sf::IFileSystemProxy::OpenDataFileSystemByCurrentProcess(OUT shared_ptr<nn::fssrv::sf::IFileSystem>& _0) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::OpenDataFileSystemByCurrentProcess");
_0 = buildInterface(nn::fssrv::sf::IFileSystem, "");
return 0;
}
uint32_t nn::fssrv::sf::IFileSystemProxy::MountContent7(IN nn::ApplicationId tid, IN uint32_t ncaType, OUT shared_ptr<nn::fssrv::sf::IFileSystem>& _2) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::MountContent7");
#if TARGET_VERSION >= VERSION_2_0_0
uint32_t nn::fssrv::sf::IFileSystemProxy::OpenFileSystemWithPatch(IN nn::fssrv::sf::FileSystemType filesystem_type, IN nn::ApplicationId tid, OUT shared_ptr<nn::fssrv::sf::IFileSystem>& _2) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::OpenFileSystemWithPatch");
_2 = buildInterface(nn::fssrv::sf::IFileSystem, "");
return 0;
}
#endif
uint32_t nn::fssrv::sf::IFileSystemProxy::MountContent(IN nn::ApplicationId tid, IN uint32_t flag, IN int8_t * path, guint path_size, OUT shared_ptr<nn::fssrv::sf::IFileSystem>& contentFs) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::MountContent");
#if TARGET_VERSION >= VERSION_2_0_0
uint32_t nn::fssrv::sf::IFileSystemProxy::OpenFileSystemWithId(IN nn::fssrv::sf::FileSystemType filesystem_type, IN nn::ApplicationId tid, IN uint8_t * path, guint path_size, OUT shared_ptr<nn::fssrv::sf::IFileSystem>& contentFs) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::OpenFileSystemWithId");
contentFs = buildInterface(nn::fssrv::sf::IFileSystem, "");
return 0;
}
#endif
#if TARGET_VERSION >= VERSION_3_0_0
uint32_t nn::fssrv::sf::IFileSystemProxy::OpenDataFileSystemByApplicationId(IN nn::ApplicationId tid, OUT shared_ptr<nn::fssrv::sf::IFileSystem>& dataFiles) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::OpenDataFileSystemByApplicationId");
dataFiles = buildInterface(nn::fssrv::sf::IFileSystem, "");
return 0;
}
#endif
uint32_t nn::fssrv::sf::IFileSystemProxy::MountBis(IN nn::fssrv::sf::Partition partitionID, IN int8_t * path, guint path_size, OUT shared_ptr<nn::fssrv::sf::IFileSystem>& Bis) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::MountBis");
uint32_t nn::fssrv::sf::IFileSystemProxy::OpenBisFileSystem(IN nn::fssrv::sf::Partition partitionID, IN uint8_t * path, guint path_size, OUT shared_ptr<nn::fssrv::sf::IFileSystem>& Bis) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::OpenBisFileSystem");
Bis = buildInterface(nn::fssrv::sf::IFileSystem, string("BIS/") + to_string(partitionID));
return 0;
}
uint32_t nn::fssrv::sf::IFileSystemProxy::OpenHostFileSystemImpl(IN int8_t * path, guint path_size, OUT shared_ptr<nn::fssrv::sf::IFileSystem>& _1) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::OpenHostFileSystemImpl");
uint32_t nn::fssrv::sf::IFileSystemProxy::OpenHostFileSystem(IN uint8_t * path, guint path_size, OUT shared_ptr<nn::fssrv::sf::IFileSystem>& _1) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::OpenHostFileSystem");
_1 = buildInterface(nn::fssrv::sf::IFileSystem, "");
return 0;
}
uint32_t nn::fssrv::sf::IFileSystemProxy::MountSdCard(OUT shared_ptr<nn::fssrv::sf::IFileSystem>& sdCard) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::MountSdCard");
uint32_t nn::fssrv::sf::IFileSystemProxy::OpenSdCardFileSystem(OUT shared_ptr<nn::fssrv::sf::IFileSystem>& sdCard) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::OpenSdCardFileSystem");
sdCard = buildInterface(nn::fssrv::sf::IFileSystem, "SDCard");
return 0;
}
uint32_t nn::fssrv::sf::IFileSystemProxy::MountGameCardPartition(IN uint32_t _0, IN uint32_t _1, OUT shared_ptr<nn::fssrv::sf::IFileSystem>& gameCardPartitionFs) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::MountGameCardPartition");
uint32_t nn::fssrv::sf::IFileSystemProxy::OpenGameCardFileSystem(IN uint32_t _0, IN uint32_t _1, OUT shared_ptr<nn::fssrv::sf::IFileSystem>& gameCardPartitionFs) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::OpenGameCardFileSystem");
gameCardPartitionFs = buildInterface(nn::fssrv::sf::IFileSystem, "GameCard");
return 0;
}
uint32_t nn::fssrv::sf::IFileSystemProxy::MountSaveData(IN uint8_t input, IN nn::fssrv::sf::SaveStruct saveStruct, OUT shared_ptr<nn::fssrv::sf::IFileSystem>& saveDataFs) {
uint32_t nn::fssrv::sf::IFileSystemProxy::OpenSaveDataFileSystem(IN uint8_t input, IN nn::fssrv::sf::SaveStruct saveStruct, OUT shared_ptr<nn::fssrv::sf::IFileSystem>& saveDataFs) {
uint64_t tid = *(uint64_t *)(&saveStruct[0x18]);
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::MountSaveData 0x" ADDRFMT, tid);
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::OpenSaveDataFileSystem 0x" ADDRFMT, tid);
std::stringstream ss;
ss << "save_" << hex << tid;
saveDataFs = buildInterface(nn::fssrv::sf::IFileSystem, ss.str());
return 0;
}
uint32_t nn::fssrv::sf::IFileSystemProxy::MountSystemSaveData(IN uint8_t input, IN nn::fssrv::sf::SaveStruct saveStruct, OUT shared_ptr<nn::fssrv::sf::IFileSystem>& systemSaveDataFs) {
uint32_t nn::fssrv::sf::IFileSystemProxy::OpenSaveDataFileSystemBySystemSaveDataId(IN uint8_t input, IN nn::fssrv::sf::SaveStruct saveStruct, OUT shared_ptr<nn::fssrv::sf::IFileSystem>& systemSaveDataFs) {
uint64_t tid = *(uint64_t *)(&saveStruct[0x18]);
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::MountSystemSaveData 0x" ADDRFMT, tid);
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::OpenSaveDataFileSystemBySystemSaveDataId 0x" ADDRFMT, tid);
std::stringstream ss;
ss << "syssave_" << hex << tid;
systemSaveDataFs = buildInterface(nn::fssrv::sf::IFileSystem, ss.str());
return 0;
}
uint32_t nn::fssrv::sf::IFileSystemProxy::MountSaveDataReadOnly(IN uint8_t input, IN nn::fssrv::sf::SaveStruct saveStruct, OUT shared_ptr<nn::fssrv::sf::IFileSystem>& saveDataFs) {
#if TARGET_VERSION >= VERSION_2_0_0
uint32_t nn::fssrv::sf::IFileSystemProxy::OpenReadOnlySaveDataFileSystem(IN uint8_t input, IN nn::fssrv::sf::SaveStruct saveStruct, OUT shared_ptr<nn::fssrv::sf::IFileSystem>& saveDataFs) {
uint64_t tid = *(uint64_t *)(&saveStruct[0x18]);
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::MountSaveDataReadOnly 0x" ADDRFMT, tid);
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::OpenReadOnlySaveDataFileSystem 0x" ADDRFMT, tid);
std::stringstream ss;
ss << "save_" << hex << tid;
saveDataFs = buildInterface(nn::fssrv::sf::IFileSystem, ss.str());
return 0;
}
#endif
uint32_t nn::fssrv::sf::IFileSystemProxy::MountImageDirectory(IN uint32_t _0, OUT shared_ptr<nn::fssrv::sf::IFileSystem>& imageFs) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::MountImageDirectory");
uint32_t nn::fssrv::sf::IFileSystemProxy::OpenImageDirectoryFileSystem(IN uint32_t _0, OUT shared_ptr<nn::fssrv::sf::IFileSystem>& imageFs) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::OpenImageDirectoryFileSystem");
imageFs = buildInterface(nn::fssrv::sf::IFileSystem, string("Image_") + to_string(_0));
return 0;
}
uint32_t nn::fssrv::sf::IFileSystemProxy::MountContentStorage(IN uint32_t contentStorageID, OUT shared_ptr<nn::fssrv::sf::IFileSystem>& contentFs) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::MountContentStorage");
uint32_t nn::fssrv::sf::IFileSystemProxy::OpenContentStorageFileSystem(IN uint32_t contentStorageID, OUT shared_ptr<nn::fssrv::sf::IFileSystem>& contentFs) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::OpenContentStorageFileSystem");
contentFs = buildInterface(nn::fssrv::sf::IFileSystem, string("CS_") + to_string(contentStorageID));
return 0;
}
uint32_t nn::fssrv::sf::IFileSystemProxyForLoader::MountCode(IN nn::ApplicationId TID, IN int8_t * contentPath, guint contentPath_size, OUT shared_ptr<nn::fssrv::sf::IFileSystem>& contentFs) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxyForLoader::MountCode");
uint32_t nn::fssrv::sf::IFileSystemProxyForLoader::OpenCodeFileSystem(IN nn::ApplicationId TID, IN uint8_t * contentPath, guint contentPath_size, OUT shared_ptr<nn::fssrv::sf::IFileSystem>& contentFs) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxyForLoader::OpenCodeFileSystem");
contentFs = buildInterface(nn::fssrv::sf::IFileSystem, "");
return 0;
}
@ -302,20 +321,10 @@ nn::fssrv::sf::IDirectory::IDirectory(Ctu *_ctu, string _fn, uint32_t _filter)
}
}
struct DirectoryEntry {
char path[0x300];
uint32_t unk1;
uint8_t entry_type;
uint8_t pad[3];
uint64_t filesize;
};
static_assert(sizeof(DirectoryEntry) == 0x310);
uint32_t nn::fssrv::sf::IDirectory::Read(OUT uint64_t& entries_read, OUT uint8_t * entries_buf, guint entries_buf_len) {
uint64_t entries_count = entries_buf_len / sizeof(DirectoryEntry);
uint32_t nn::fssrv::sf::IDirectory::Read(OUT uint64_t& entries_read, OUT nn::fssrv::sf::IDirectoryEntry * entries, guint entries_buf_len) {
uint64_t entries_count = entries_buf_len / sizeof(nn::fssrv::sf::IDirectoryEntry);
LOG_DEBUG(Fsp, "IDirectory::Read: Attempting to read " LONGFMT " entries (from " LONGFMT ")", entries_count, entries_buf_len);
struct DirectoryEntry *entries = (struct DirectoryEntry*)entries_buf;
struct dirent *curdir;
struct stat curdir_stat;
uint64_t i;
@ -324,9 +333,9 @@ uint32_t nn::fssrv::sf::IDirectory::Read(OUT uint64_t& entries_read, OUT uint8_t
curdir = readdir((DIR*)fp);
if (curdir == nullptr)
break;
strcpy(entries[i].path, curdir->d_name);
strcpy((char*)entries[i].path, (char*)curdir->d_name);
entries[i].unk1 = 0;
entries[i].entry_type = curdir->d_type == DT_DIR ? 0 : 1;
entries[i].directory_entry_type = curdir->d_type == DT_DIR ? Directory : File;
if (stat((fn + std::string("/") + std::string(curdir->d_name)).c_str(), &curdir_stat) == -1) {
LOG_DEBUG(Fsp, "We got an error getting size of %s", curdir->d_name);
perror("stat");
@ -356,7 +365,9 @@ nn::fssrv::sf::IFile::IFile(Ctu *_ctu, string _fn, uint32_t _mode) : IpcServic
}
nn::fssrv::sf::IFile::~IFile() {
fclose((FILE*)fp);
if(isOpen) {
fclose((FILE*)fp);
}
}
uint32_t nn::fssrv::sf::IFile::GetSize(OUT uint64_t& fileSize) {
@ -372,26 +383,26 @@ uint32_t nn::fssrv::sf::IFile::GetSize(OUT uint64_t& fileSize) {
return 0;
}
uint32_t nn::fssrv::sf::IFile::Read(IN uint64_t _0, IN uint64_t offset, IN uint32_t size, OUT uint64_t& out_size, OUT int8_t * out_buf, guint out_buf_size) {
uint32_t nn::fssrv::sf::IFile::Read(IN uint32_t _0, IN uint64_t offset, IN uint64_t size, OUT uint64_t& out_size, OUT uint8_t * out_buf, guint out_buf_size) {
LOG_DEBUG(Fsp, "IFile::Read from %s from " LONGFMT, fn.c_str(), offset);
if(isOpen && fp != nullptr) {
uint32_t s = ((uint32_t)out_buf_size < size ? (uint32_t)out_buf_size : size);
uint64_t s = ((uint64_t)out_buf_size < size ? (uint64_t)out_buf_size : size);
bufferOffset = offset;
fseek((FILE *)fp, offset, SEEK_SET);
size_t s_read = fread(out_buf, 1, s, (FILE *)fp);
bufferOffset = ftell((FILE *)fp);
out_size = (uint32_t)s_read;
out_size = (uint64_t)s_read;
} else {
LOG_DEBUG(Fsp, "File is closed !");
}
return 0x0;
}
uint32_t nn::fssrv::sf::IFile::Write(IN uint64_t _0, IN uint64_t offset, IN uint32_t size, IN int8_t * buf, guint buf_size) {
uint32_t nn::fssrv::sf::IFile::Write(IN uint32_t _0, IN uint64_t offset, IN uint64_t size, IN uint8_t * buf, guint buf_size) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFile::Write");
if(isOpen && fp != nullptr) {
bufferOffset = offset;
uint32_t s = ((uint32_t)buf_size < size ? (uint32_t)buf_size : size);
uint64_t s = ((uint64_t)buf_size < size ? (uint64_t)buf_size : size);
fseek((FILE *)fp, offset, SEEK_SET);
fwrite(buf, 1, s, (FILE *)fp);
if(size-s > 0) {
@ -431,7 +442,7 @@ uint32_t nn::fssrv::sf::IFile::SetSize(IN uint64_t size) {
}
// Funcs
uint32_t nn::fssrv::sf::IFileSystem::OpenFile(IN uint32_t mode, IN int8_t * path, guint path_size, OUT shared_ptr<nn::fssrv::sf::IFile>& file) {
uint32_t nn::fssrv::sf::IFileSystem::OpenFile(IN uint32_t mode, IN uint8_t * path, guint path_size, OUT shared_ptr<nn::fssrv::sf::IFile>& file) {
LOG_DEBUG(Fsp, "OpenFile %s", path);
auto tempi = buildInterface(nn::fssrv::sf::IFile, fnPath + "/" + string((char*)path), mode);
if(tempi->isOpen) {
@ -441,7 +452,7 @@ uint32_t nn::fssrv::sf::IFileSystem::OpenFile(IN uint32_t mode, IN int8_t * path
return 0x7d402;
}
uint32_t nn::fssrv::sf::IFileSystem::OpenDirectory(IN uint32_t filter, IN int8_t * path, guint path_size, OUT shared_ptr<nn::fssrv::sf::IDirectory>& dir) {
uint32_t nn::fssrv::sf::IFileSystem::OpenDirectory(IN uint32_t filter, IN uint8_t * path, guint path_size, OUT shared_ptr<nn::fssrv::sf::IDirectory>& dir) {
LOG_DEBUG(Fsp, "OpenDirectory %s", path);
auto tempi = buildInterface(nn::fssrv::sf::IDirectory, fnPath + "/" + string((char*)path), filter);
if(tempi->isOpen) {
@ -451,9 +462,9 @@ uint32_t nn::fssrv::sf::IFileSystem::OpenDirectory(IN uint32_t filter, IN int8_t
return 0x7d402;
}
uint32_t nn::fssrv::sf::IFileSystemProxy::OpenSaveDataThumbnailFile(IN uint8_t _0, IN uint8_t * _1, IN uint32_t _2, OUT shared_ptr<nn::fssrv::sf::IFile>& thumbnail) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::OpenSaveDataThumbnailFile");
thumbnail = buildInterface(nn::fssrv::sf::IFile, string((char*)_1), _0);
uint32_t nn::fssrv::sf::IFileSystemProxy::OpenSaveDataMetaFile(IN uint8_t _0, IN uint32_t _1, IN uint8_t * _2, OUT shared_ptr<nn::fssrv::sf::IFileSystem>& imageFs) {
LOG_DEBUG(Fsp, "Stub implementation for nn::fssrv::sf::IFileSystemProxy::OpenSaveDataMetaFile");
imageFs = buildInterface(nn::fssrv::sf::IFileSystem, string((char*)_2));
return 0;
}
@ -461,8 +472,8 @@ uint32_t nn::fssrv::sf::IFileSystemProxy::OpenSaveDataThumbnailFile(IN uint8_t _
/* ---------------------------------------- End of IFile ---------------------------------------- */
uint32_t nn::fssrv::sf::IEventNotifier::Unknown0(OUT shared_ptr<KObject>& _0) {
LOG_DEBUG(IpcStubs, "Stub implementation for nn::fssrv::sf::IEventNotifier::Unknown0");
uint32_t nn::fssrv::sf::IEventNotifier::GetEventHandle(OUT shared_ptr<KObject>& _0) {
LOG_DEBUG(IpcStubs, "Stub implementation for nn::fssrv::sf::IEventNotifier::GetEventHandle");
_0 = make_shared<Waitable>();
return 0;
}

View file

@ -78,7 +78,7 @@ void dumpstring(uint8_t *data, guint size) {
}
}
uint32_t nn::lm::ILogger::Log(IN uint8_t *message, guint messageSize) {
uint32_t nn::lm::ILogger::Initialize(IN uint8_t *message, guint messageSize) {
auto packet = (InLogPacket *) message;
dumpstring(message, messageSize);

View file

@ -1,9 +1,10 @@
#include "Ctu.h"
uint32_t nn::nim::detail::INetworkInstallManager::Unknown40(IN uint8_t * _0, guint _0_size, OUT uint64_t& _1, OUT uint64_t& _2) {
#if TARGET_VERSION >= VERSION_2_0_0
uint32_t nn::nim::detail::INetworkInstallManager::ListApplyDeltaTask2(OUT uint32_t& _0, OUT uint8_t * _1, guint _1_size) {
LOG_DEBUG(IpcStubs, "Stub implementation for nn::nim::detail::INetworkInstallManager::Unknown40");
memset(_0, 0xDE, _0_size);
_1 = 0;
_2 = 0;
memset(_1, 0xDE, _1_size);
_0 = 0;
return 0;
}
#endif

View file

@ -1,11 +1,11 @@
#include "Ctu.h"
uint32_t Pm::Shell::LaunchTitle(IN uint64_t _0, IN nn::ApplicationId tid) {
LOG_DEBUG(Pm::Shell, "Attempted to launch title " ADDRFMT, tid);
uint32_t nn::pm::detail::IShellInterface::LaunchProcess(/*IN uint64_t _0, IN nn::ApplicationId tid*/) {
//LOG_DEBUG(Pm::Shell, "Attempted to launch title " ADDRFMT, tid);
return 0;
}
uint32_t Pm::Shell::GetProcessEventWaiter(OUT shared_ptr<KObject>& _0) {
uint32_t nn::pm::detail::IShellInterface::GetProcessEventWaiter(OUT shared_ptr<KObject>& _0) {
LOG_DEBUG(IpcStubs, "Stub implementation for Pm::Shell::GetProcessEventWaiter");
_0 = make_shared<Waitable>();
return 0;

76
ipcimpl/ro.cpp Normal file
View file

@ -0,0 +1,76 @@
#include "Ctu.h"
/*$IPC$
partial nn::ro::detail::IRoInterface {
class GuestNro;
std::map<gptr, GuestNro*> nroMap;
}
*/
uint32_t nn::ro::detail::IRoInterface::Unknown4(IN uint64_t pid_placeholder, IN gpid _1, IN shared_ptr<KObject> process) {
LOG_DEBUG(IpcStubs, "Stub implementation for nn::ro::detail::IRoInterface::Initialize");
return 0;
}
class nn::ro::detail::IRoInterface::GuestNro {
public:
GuestNro(Ctu *ctu, gptr src_image_addr, gptr src_bss_addr, uint64_t nro_size, uint64_t bss_size) :
ctu(ctu),
src_image_addr(src_image_addr),
src_bss_addr(src_bss_addr),
nro_size(nro_size),
bss_size(bss_size) {
dst_addr = target_address;
target_address+= nro_size + bss_size;
char *image = new char[nro_size];
ctu->cpu.map(dst_addr, nro_size);
ctu->cpu.readmem(src_image_addr, image, nro_size);
ctu->cpu.writemem(dst_addr, image, nro_size);
ctu->cpu.map(dst_addr + nro_size, bss_size);
ctu->cpu.unmap(src_image_addr, nro_size);
ctu->cpu.unmap(src_bss_addr, bss_size);
}
~GuestNro() {
ctu->cpu.map(src_image_addr, nro_size);
ctu->cpu.map(src_bss_addr, bss_size);
ctu->cpu.unmap(dst_addr, nro_size);
ctu->cpu.unmap(dst_addr + nro_size, bss_size);
}
static gptr target_address;
gptr dst_addr;
Ctu *ctu;
const gptr src_image_addr;
const gptr src_bss_addr;
const uint64_t nro_size;
const uint64_t bss_size;
};
gptr nn::ro::detail::IRoInterface::GuestNro::target_address = 0x7800000000;
uint32_t nn::ro::detail::IRoInterface::Unknown0(IN uint64_t pid_placeholder, IN uint64_t nro_image_addr, IN uint64_t nro_size, IN uint64_t bss_addr, IN uint64_t bss_size, IN gpid _5, OUT uint64_t& nro_load_addr) {
LOG_DEBUG(IpcStubs, "Stub implementation for nn::ro::detail::IRoInterface::LoadNro");
GuestNro *nro = new GuestNro(ctu, nro_image_addr, bss_addr, nro_size, bss_size);
nro_load_addr = nro->dst_addr;
nroMap[nro->dst_addr] = nro;
return 0;
}
uint32_t nn::ro::detail::IRoInterface::Unknown2(IN uint64_t pid_placeholder, IN uint64_t nrr_addr, IN uint64_t nrr_size, IN gpid _3) {
LOG_DEBUG(IpcStubs, "Stub implementation for nn::ro::detail::IRoInterface::LoadNrr");
return 0;
}
uint32_t nn::ro::detail::IRoInterface::Unknown1(IN uint64_t pid_placeholder, IN uint64_t nro_load_addr, IN gpid _2) {
LOG_DEBUG(IpcStubs, "Stub implementation for nn::ro::detail::IRoInterface::UnloadNro");
delete nroMap[nro_load_addr];
return 0;
}
uint32_t nn::ro::detail::IRoInterface::Unknown3(IN uint64_t pid_placeholder, IN uint64_t nrr_addr, IN gpid _2) {
LOG_DEBUG(IpcStubs, "Stub implementation for nn::ro::detail::IRoInterface::UnloadNrr");
return 0;
}

View file

@ -1,21 +1,21 @@
#include "Ctu.h"
/*$IPC$
partial SmService {
partial nn::sm::detail::IUserInterface {
unordered_map<string, shared_ptr<NPort>> ports;
}
*/
static bool smInitialized = false;
uint32_t SmService::Initialize() {
uint32_t nn::sm::detail::IUserInterface::Initialize(IN gpid _0, IN uint64_t reserved) {
smInitialized = true;
return 0;
}
#define SERVICE(str, iface) do { if(name == (str)) { svc = buildInterface(iface); return 0; } } while(0)
uint32_t SmService::GetService(IN ServiceName _name, OUT shared_ptr<IPipe>& svc) {
uint32_t nn::sm::detail::IUserInterface::GetService(IN ServiceName _name, OUT shared_ptr<IPipe>& svc) {
if(!smInitialized) {
// FIXME: libtransistor need to impl ::Initialize
// return 0x415;
@ -34,7 +34,7 @@ uint32_t SmService::GetService(IN ServiceName _name, OUT shared_ptr<IPipe>& svc)
return 0xC15;
}
uint32_t SmService::RegisterService(IN ServiceName _name, OUT shared_ptr<NPort>& port) {
uint32_t nn::sm::detail::IUserInterface::RegisterService(IN ServiceName _name, IN uint8_t _1, IN uint32_t maxHandles, OUT shared_ptr<NPort>& port) {
string name((char *) _name, strnlen((char *) _name, 8));
LOG_DEBUG(Sm, "Registering service %s", name.c_str());
port = buildInterface(NPort, name);

View file

@ -38,7 +38,7 @@ struct Arg: public option::Arg
}
};
enum optionIndex { UNKNOWN, HELP, ENABLE_GDB, PORT, NSO, NRO, KIP, ENABLE_SOCKETS };
enum optionIndex { UNKNOWN, HELP, ENABLE_GDB, PORT, NSO, NRO, KIP, ENABLE_SOCKETS, RELOCATE, INITIALIZE_MEMORY };
const option::Descriptor usage[] =
{
{UNKNOWN, 0, "", "",Arg::None, "USAGE: ctu [options] <load-directory>\n\n"
@ -49,7 +49,9 @@ const option::Descriptor usage[] =
{NSO, 0,"","load-nso",Arg::NonEmpty, " --load-nso \tLoad an NSO without load directory"},
{NRO, 0,"","load-nro",Arg::NonEmpty, " --load-nro \tLoad an NRO without load directory (entry point .text+0x80)"},
{KIP, 0,"","load-kip",Arg::NonEmpty, " --load-kip \tLoad a KIP without load directory"},
{ENABLE_SOCKETS, 0, "b","enable-sockets",Arg::None, " -- enable-sockets, -b \tEnable BSD socket passthrough." },
{ENABLE_SOCKETS, 0, "b","enable-sockets",Arg::None, " --enable-sockets, -b \tEnable BSD socket passthrough." },
{RELOCATE, 0, "r","relocate",Arg::None, " --relocate, -r \tRelocate loaded NRO files" },
{INITIALIZE_MEMORY, 0, "m", "initialize-memory", Arg::None, " --initialize-memory, -m \tInitialize memory to help catch uninitialized memory bugs" },
{0,0,nullptr,nullptr,nullptr,nullptr}
};
@ -82,10 +84,10 @@ void loadNso(Ctu &ctu, const string &lfn, gptr raddr) {
LOG_INFO(NsoLoader, "Loaded %s at " ADDRFMT, lfn.c_str(), ctu.loadbase);
}
void loadNro(Ctu &ctu, const string &lfn, gptr raddr) {
void loadNro(Ctu &ctu, const string &lfn, gptr raddr, bool relocate) {
assert(exists(lfn));
Nro file(lfn);
if(file.load(ctu, raddr, true) == 0) {
if(file.load(ctu, raddr, relocate) == 0) {
LOG_ERROR(NroLoader, "Failed to load %s", lfn.c_str());
}
ctu.loadbase = min(raddr, ctu.loadbase);
@ -170,12 +172,19 @@ int main(int argc, char **argv) {
} else {
ctu.socketsEnabled = false;
}
ctu.initializeMemory = options[INITIALIZE_MEMORY].count() > 0;
bool relocate = false;
if(options[RELOCATE].count()) {
relocate = true;
}
if(options[NSO].count()) {
loadNso(ctu, options[NSO][0].arg, 0x7100000000);
ctu.execProgram(0x7100000000);
} else if(options[NRO].count()) {
loadNro(ctu, options[NRO][0].arg, 0x7100000000);
loadNro(ctu, options[NRO][0].arg, 0x7100000000, relocate);
ctu.execProgram(0x7100000000);
} else if(options[KIP].count()) {
loadKip(ctu, options[KIP][0].arg, 0x7100000000);