mirror of
https://github.com/wiiu-env/MochaLite.git
synced 2024-11-01 02:25:10 +01:00
43f1af08a3
NOTE: This is a work in progress commit. It includes debug and test functions and some features that existed before might not even work. It is not finished and not very well tested. So it's warning to NOT use this for everyday playing! This is target for developers to look some stuff up that I was working on. See also my post on gbatemp for more information.
757 lines
25 KiB
Python
757 lines
25 KiB
Python
# may or may not be inspired by plutoo's ctrrpc
|
|
import errno
|
|
import socket
|
|
import os
|
|
import sys
|
|
import struct
|
|
from time import sleep
|
|
|
|
def buffer(size):
|
|
return bytearray([0x00] * size)
|
|
|
|
def copy_string(buffer, s, offset):
|
|
s += "\0"
|
|
buffer[offset : (offset + len(s))] = bytearray(s, "ascii")
|
|
|
|
def copy_word(buffer, w, offset):
|
|
buffer[offset : (offset + 4)] = struct.pack(">I", w)
|
|
|
|
def get_string(buffer, offset):
|
|
s = buffer[offset:]
|
|
if b'\x00' in s:
|
|
return s[:s.index(b'\x00')].decode("utf-8")
|
|
else:
|
|
return s.decode("utf-8")
|
|
|
|
class wupclient:
|
|
s=None
|
|
|
|
def __init__(self, ip='192.168.178.23', port=1337):
|
|
self.s=socket.socket()
|
|
self.s.connect((ip, port))
|
|
self.fsa_handle = None
|
|
self.cwd = "/vol/storage_mlc01"
|
|
|
|
def __del__(self):
|
|
if self.fsa_handle != None:
|
|
self.close(self.fsa_handle)
|
|
self.fsa_handle = None
|
|
|
|
# fundamental comms
|
|
def send(self, command, data):
|
|
request = struct.pack('>I', command) + data
|
|
|
|
self.s.send(request)
|
|
response = self.s.recv(0x600)
|
|
|
|
ret = struct.unpack(">I", response[:4])[0]
|
|
return (ret, response[4:])
|
|
|
|
# core commands
|
|
def read(self, addr, len):
|
|
data = struct.pack(">II", addr, len)
|
|
ret, data = self.send(1, data)
|
|
if ret == 0:
|
|
return data
|
|
else:
|
|
print("read error : %08X" % ret)
|
|
return None
|
|
|
|
def write(self, addr, data):
|
|
data = struct.pack(">I", addr) + data
|
|
ret, data = self.send(0, data)
|
|
if ret == 0:
|
|
return ret
|
|
else:
|
|
print("write error : %08X" % ret)
|
|
return None
|
|
|
|
def svc(self, svc_id, arguments):
|
|
data = struct.pack(">I", svc_id)
|
|
for a in arguments:
|
|
data += struct.pack(">I", a)
|
|
ret, data = self.send(2, data)
|
|
if ret == 0:
|
|
return struct.unpack(">I", data)[0]
|
|
else:
|
|
print("svc error : %08X" % ret)
|
|
return None
|
|
|
|
def kill(self):
|
|
ret, _ = self.send(3, bytearray())
|
|
return ret
|
|
|
|
def memcpy(self, dst, src, len):
|
|
data = struct.pack(">III", dst, src, len)
|
|
ret, data = self.send(4, data)
|
|
if ret == 0:
|
|
return ret
|
|
else:
|
|
print("memcpy error : %08X" % ret)
|
|
return None
|
|
|
|
def repeatwrite(self, dst, val, n):
|
|
data = struct.pack(">III", dst, val, n)
|
|
ret, data = self.send(5, data)
|
|
if ret == 0:
|
|
return ret
|
|
else:
|
|
print("repeatwrite error : %08X" % ret)
|
|
return None
|
|
|
|
# derivatives
|
|
def alloc(self, size, align = None):
|
|
if size == 0:
|
|
return 0
|
|
if align == None:
|
|
return self.svc(0x27, [0xCAFF, size])
|
|
else:
|
|
return self.svc(0x28, [0xCAFF, size, align])
|
|
|
|
def free(self, address):
|
|
if address == 0:
|
|
return 0
|
|
return self.svc(0x29, [0xCAFF, address])
|
|
|
|
def load_buffer(self, b, align = None):
|
|
if len(b) == 0:
|
|
return 0
|
|
address = self.alloc(len(b), align)
|
|
self.write(address, b)
|
|
return address
|
|
|
|
def load_string(self, s, align = None):
|
|
return self.load_buffer(bytearray(s + "\0", "ascii"), align)
|
|
|
|
def open(self, device, mode):
|
|
address = self.load_string(device)
|
|
handle = self.svc(0x33, [address, mode])
|
|
self.free(address)
|
|
return handle
|
|
|
|
def close(self, handle):
|
|
return self.svc(0x34, [handle])
|
|
|
|
def ioctl(self, handle, cmd, inbuf, outbuf_size):
|
|
in_address = self.load_buffer(inbuf)
|
|
out_data = None
|
|
if outbuf_size > 0:
|
|
out_address = self.alloc(outbuf_size)
|
|
ret = self.svc(0x38, [handle, cmd, in_address, len(inbuf), out_address, outbuf_size])
|
|
out_data = self.read(out_address, outbuf_size)
|
|
self.free(out_address)
|
|
else:
|
|
ret = self.svc(0x38, [handle, cmd, in_address, len(inbuf), 0, 0])
|
|
self.free(in_address)
|
|
return (ret, out_data)
|
|
|
|
def iovec(self, vecs):
|
|
data = bytearray()
|
|
for (a, s) in vecs:
|
|
data += struct.pack(">III", a, s, 0)
|
|
return self.load_buffer(data)
|
|
|
|
def ioctlv(self, handle, cmd, inbufs, outbuf_sizes, inbufs_ptr = [], outbufs_ptr = []):
|
|
inbufs = [(self.load_buffer(b, 0x40), len(b)) for b in inbufs]
|
|
outbufs = [(self.alloc(s, 0x40), s) for s in outbuf_sizes]
|
|
iovecs = self.iovec(inbufs + inbufs_ptr + outbufs_ptr + outbufs)
|
|
out_data = []
|
|
ret = self.svc(0x39, [handle, cmd, len(inbufs + inbufs_ptr), len(outbufs + outbufs_ptr), iovecs])
|
|
for (a, s) in outbufs:
|
|
out_data += [self.read(a, s)]
|
|
for (a, _) in (inbufs + outbufs):
|
|
self.free(a)
|
|
self.free(iovecs)
|
|
return (ret, out_data)
|
|
|
|
# fsa
|
|
def FSA_Mount(self, handle, device_path, volume_path, flags):
|
|
inbuffer = buffer(0x520)
|
|
copy_string(inbuffer, device_path, 0x0004)
|
|
copy_string(inbuffer, volume_path, 0x0284)
|
|
copy_word(inbuffer, flags, 0x0504)
|
|
(ret, _) = self.ioctlv(handle, 0x01, [inbuffer, bytearray()], [0x293])
|
|
return ret
|
|
|
|
def FSA_Unmount(self, handle, path, flags):
|
|
inbuffer = buffer(0x520)
|
|
copy_string(inbuffer, path, 0x4)
|
|
copy_word(inbuffer, flags, 0x284)
|
|
(ret, _) = self.ioctl(handle, 0x02, inbuffer, 0x293)
|
|
return ret
|
|
|
|
def FSA_RawOpen(self, handle, device):
|
|
inbuffer = buffer(0x520)
|
|
copy_string(inbuffer, device, 0x4)
|
|
(ret, data) = self.ioctl(handle, 0x6A, inbuffer, 0x293)
|
|
return (ret, struct.unpack(">I", data[4:8])[0])
|
|
|
|
def FSA_OpenDir(self, handle, path):
|
|
inbuffer = buffer(0x520)
|
|
copy_string(inbuffer, path, 0x4)
|
|
(ret, data) = self.ioctl(handle, 0x0A, inbuffer, 0x293)
|
|
return (ret, struct.unpack(">I", data[4:8])[0])
|
|
|
|
def FSA_ReadDir(self, handle, dir_handle):
|
|
inbuffer = buffer(0x520)
|
|
copy_word(inbuffer, dir_handle, 0x4)
|
|
(ret, data) = self.ioctl(handle, 0x0B, inbuffer, 0x293)
|
|
data = bytearray(data[4:])
|
|
unk = data[:0x64]
|
|
if ret == 0:
|
|
return (ret, {"name" : get_string(data, 0x64), "is_file" : (unk[0] & 128) != 128, "unk" : unk})
|
|
else:
|
|
return (ret, None)
|
|
|
|
def FSA_CloseDir(self, handle, dir_handle):
|
|
inbuffer = buffer(0x520)
|
|
copy_word(inbuffer, dir_handle, 0x4)
|
|
(ret, data) = self.ioctl(handle, 0x0D, inbuffer, 0x293)
|
|
return ret
|
|
|
|
def FSA_OpenFile(self, handle, path, mode):
|
|
inbuffer = buffer(0x520)
|
|
copy_string(inbuffer, path, 0x4)
|
|
copy_string(inbuffer, mode, 0x284)
|
|
(ret, data) = self.ioctl(handle, 0x0E, inbuffer, 0x293)
|
|
return (ret, struct.unpack(">I", data[4:8])[0])
|
|
|
|
def FSA_MakeDir(self, handle, path, flags):
|
|
inbuffer = buffer(0x520)
|
|
copy_string(inbuffer, path, 0x4)
|
|
copy_word(inbuffer, flags, 0x284)
|
|
(ret, _) = self.ioctl(handle, 0x07, inbuffer, 0x293)
|
|
return ret
|
|
|
|
def FSA_ReadFile(self, handle, file_handle, size, cnt):
|
|
inbuffer = buffer(0x520)
|
|
copy_word(inbuffer, size, 0x08)
|
|
copy_word(inbuffer, cnt, 0x0C)
|
|
copy_word(inbuffer, file_handle, 0x14)
|
|
(ret, data) = self.ioctlv(handle, 0x0F, [inbuffer], [size * cnt, 0x293])
|
|
return (ret, data[0])
|
|
|
|
def FSA_WriteFile(self, handle, file_handle, data):
|
|
inbuffer = buffer(0x520)
|
|
copy_word(inbuffer, 1, 0x08) # size
|
|
copy_word(inbuffer, len(data), 0x0C) # cnt
|
|
copy_word(inbuffer, file_handle, 0x14)
|
|
(ret, data) = self.ioctlv(handle, 0x10, [inbuffer, data], [0x293])
|
|
return (ret)
|
|
|
|
def FSA_ReadFilePtr(self, handle, file_handle, size, cnt, ptr):
|
|
inbuffer = buffer(0x520)
|
|
copy_word(inbuffer, size, 0x08)
|
|
copy_word(inbuffer, cnt, 0x0C)
|
|
copy_word(inbuffer, file_handle, 0x14)
|
|
(ret, data) = self.ioctlv(handle, 0x0F, [inbuffer], [0x293], [], [(ptr, size*cnt)])
|
|
return (ret, data[0])
|
|
|
|
def FSA_WriteFilePtr(self, handle, file_handle, size, cnt, ptr):
|
|
inbuffer = buffer(0x520)
|
|
copy_word(inbuffer, size, 0x08)
|
|
copy_word(inbuffer, cnt, 0x0C)
|
|
copy_word(inbuffer, file_handle, 0x14)
|
|
(ret, data) = self.ioctlv(handle, 0x10, [inbuffer], [0x293], [(ptr, size*cnt)], [])
|
|
return (ret)
|
|
|
|
def FSA_GetStatFile(self, handle, file_handle):
|
|
inbuffer = buffer(0x520)
|
|
copy_word(inbuffer, file_handle, 0x4)
|
|
(ret, data) = self.ioctl(handle, 0x14, inbuffer, 0x64)
|
|
return (ret, struct.unpack(">IIIIIIIIIIIIIIIIIIIIIIIII", data))
|
|
|
|
def FSA_CloseFile(self, handle, file_handle):
|
|
inbuffer = buffer(0x520)
|
|
copy_word(inbuffer, file_handle, 0x4)
|
|
(ret, data) = self.ioctl(handle, 0x15, inbuffer, 0x293)
|
|
return ret
|
|
|
|
def FSA_ChangeMode(self, handle, path, mode):
|
|
mask = 0x777
|
|
inbuffer = buffer(0x520)
|
|
copy_string(inbuffer, path, 0x0004)
|
|
copy_word(inbuffer, mode, 0x0284)
|
|
copy_word(inbuffer, mask, 0x0288)
|
|
(ret, _) = self.ioctl(handle, 0x20, inbuffer, 0x293)
|
|
return ret
|
|
|
|
# mcp
|
|
def MCP_InstallGetInfo(self, handle, path):
|
|
inbuffer = buffer(0x27F)
|
|
copy_string(inbuffer, path, 0x0)
|
|
(ret, data) = self.ioctlv(handle, 0x80, [inbuffer], [0x16])
|
|
return (ret, struct.unpack(">IIIIIH", data[0]))
|
|
|
|
def MCP_Install(self, handle, path):
|
|
inbuffer = buffer(0x27F)
|
|
copy_string(inbuffer, path, 0x0)
|
|
(ret, _) = self.ioctlv(handle, 0x81, [inbuffer], [])
|
|
return ret
|
|
|
|
def MCP_InstallGetProgress(self, handle):
|
|
(ret, data) = self.ioctl(handle, 0x82, [], 0x24)
|
|
return (ret, struct.unpack(">IIIIIIIII", data))
|
|
|
|
def MCP_CopyTitle(self, handle, path, dst_device_id, flush):
|
|
inbuffer = buffer(0x27F)
|
|
copy_string(inbuffer, path, 0x0)
|
|
inbuffer2 = buffer(0x4)
|
|
copy_word(inbuffer2, dst_device_id, 0x0)
|
|
inbuffer3 = buffer(0x4)
|
|
copy_word(inbuffer3, flush, 0x0)
|
|
(ret, _) = self.ioctlv(handle, 0x85, [inbuffer, inbuffer2, inbuffer3], [])
|
|
return ret
|
|
|
|
def MCP_InstallSetTargetDevice(self, handle, device):
|
|
inbuffer = buffer(0x4)
|
|
copy_word(inbuffer, device, 0x0)
|
|
(ret, _) = self.ioctl(handle, 0x8D, inbuffer, 0)
|
|
return ret
|
|
|
|
def MCP_InstallSetTargetUsb(self, handle, device):
|
|
inbuffer = buffer(0x4)
|
|
copy_word(inbuffer, device, 0x0)
|
|
(ret, _) = self.ioctl(handle, 0xF1, inbuffer, 0)
|
|
return ret
|
|
|
|
# syslog (tmp)
|
|
def dump_syslog(self):
|
|
syslog_address = struct.unpack(">I", self.read(0x05095ECC, 4))[0] + 0x10
|
|
block_size = 0x400
|
|
for i in range(0, 0x40000, block_size):
|
|
data = self.read(syslog_address + i, 0x400)
|
|
# if 0 in data:
|
|
# print(data[:data.index(0)].decode("ascii"))
|
|
# break
|
|
# else:
|
|
print(data)
|
|
|
|
# file management
|
|
def get_fsa_handle(self):
|
|
if self.fsa_handle == None:
|
|
self.fsa_handle = self.open("/dev/fsa", 0)
|
|
return self.fsa_handle
|
|
|
|
def mkdir(self, path, flags):
|
|
fsa_handle = self.get_fsa_handle()
|
|
if path[0] != "/":
|
|
path = self.cwd + "/" + path
|
|
ret = w.FSA_MakeDir(fsa_handle, path, flags)
|
|
if ret == 0:
|
|
return 0
|
|
else:
|
|
print("mkdir error (%s, %08X)" % (path, ret))
|
|
return ret
|
|
|
|
def chmod(self, filename, flags):
|
|
fsa_handle = self.get_fsa_handle()
|
|
if filename[0] != "/":
|
|
filename = self.cwd + "/" + filename
|
|
ret = w.FSA_ChangeMode(fsa_handle, filename, flags)
|
|
print("chmod returned : " + hex(ret))
|
|
|
|
def cd(self, path):
|
|
if path[0] != "/" and self.cwd[0] == "/":
|
|
return self.cd(self.cwd + "/" + path)
|
|
fsa_handle = self.get_fsa_handle()
|
|
ret, dir_handle = self.FSA_OpenDir(fsa_handle, path if path != None else self.cwd)
|
|
if ret == 0:
|
|
self.cwd = path
|
|
self.FSA_CloseDir(fsa_handle, dir_handle)
|
|
return 0
|
|
else:
|
|
print("cd error : path does not exist (%s)" % (path))
|
|
return -1
|
|
|
|
def ls(self, path = None, return_data = False):
|
|
fsa_handle = self.get_fsa_handle()
|
|
if path != None and path[0] != "/":
|
|
path = self.cwd + "/" + path
|
|
ret, dir_handle = self.FSA_OpenDir(fsa_handle, path if path != None else self.cwd)
|
|
if ret != 0x0:
|
|
print("opendir error : " + hex(ret))
|
|
return [] if return_data else None
|
|
entries = []
|
|
while True:
|
|
ret, data = self.FSA_ReadDir(fsa_handle, dir_handle)
|
|
if ret != 0:
|
|
break
|
|
if not(return_data):
|
|
if data["is_file"]:
|
|
print(" %s" % data["name"])
|
|
else:
|
|
print(" %s/" % data["name"])
|
|
else:
|
|
entries += [data]
|
|
ret = self.FSA_CloseDir(fsa_handle, dir_handle)
|
|
return entries if return_data else None
|
|
|
|
def dldir(self, path):
|
|
if path[0] != "/":
|
|
path = self.cwd + "/" + path
|
|
entries = self.ls(path, True)
|
|
for e in entries:
|
|
if e["is_file"]:
|
|
print(e["name"])
|
|
self.dl(path + "/" + e["name"],path[1:])
|
|
else:
|
|
print(e["name"] + "/")
|
|
self.dldir(path + "/" + e["name"])
|
|
|
|
def cpdir(self, srcpath, dstpath):
|
|
entries = self.ls(srcpath, True)
|
|
q = [(srcpath, dstpath, e) for e in entries]
|
|
while len(q) > 0:
|
|
_srcpath, _dstpath, e = q.pop()
|
|
_srcpath += "/" + e["name"]
|
|
_dstpath += "/" + e["name"]
|
|
if e["is_file"]:
|
|
print(e["name"])
|
|
self.cp(_srcpath, _dstpath)
|
|
else:
|
|
self.mkdir(_dstpath, 0x600)
|
|
entries = self.ls(_srcpath, True)
|
|
q += [(_srcpath, _dstpath, e) for e in entries]
|
|
|
|
def pwd(self):
|
|
return self.cwd
|
|
|
|
def cp(self, filename_in, filename_out):
|
|
fsa_handle = self.get_fsa_handle()
|
|
ret, in_file_handle = self.FSA_OpenFile(fsa_handle, filename_in, "r")
|
|
if ret != 0x0:
|
|
print("cp error : could not open " + filename_in)
|
|
return
|
|
ret, out_file_handle = self.FSA_OpenFile(fsa_handle, filename_out, "w")
|
|
if ret != 0x0:
|
|
print("cp error : could not open " + filename_out)
|
|
return
|
|
block_size = 0x10000
|
|
buffer = self.alloc(block_size, 0x40)
|
|
k = 0
|
|
while True:
|
|
ret, _ = self.FSA_ReadFilePtr(fsa_handle, in_file_handle, 0x1, block_size, buffer)
|
|
k += ret
|
|
ret = self.FSA_WriteFilePtr(fsa_handle, out_file_handle, 0x1, ret, buffer)
|
|
sys.stdout.write(hex(k) + "\r"); sys.stdout.flush();
|
|
if ret < block_size:
|
|
break
|
|
self.free(buffer)
|
|
ret = self.FSA_CloseFile(fsa_handle, out_file_handle)
|
|
ret = self.FSA_CloseFile(fsa_handle, in_file_handle)
|
|
|
|
def df(self, filename_out, src, size):
|
|
fsa_handle = self.get_fsa_handle()
|
|
ret, out_file_handle = self.FSA_OpenFile(fsa_handle, filename_out, "w")
|
|
if ret != 0x0:
|
|
print("df error : could not open " + filename_out)
|
|
return
|
|
block_size = 0x10000
|
|
buffer = self.alloc(block_size, 0x40)
|
|
k = 0
|
|
while k < size:
|
|
cur_size = min(size - k, block_size)
|
|
self.memcpy(buffer, src + k, cur_size)
|
|
k += cur_size
|
|
ret = self.FSA_WriteFilePtr(fsa_handle, out_file_handle, 0x1, cur_size, buffer)
|
|
sys.stdout.write(hex(k) + " (%f) " % (float(k * 100) / size) + "\r"); sys.stdout.flush();
|
|
self.free(buffer)
|
|
ret = self.FSA_CloseFile(fsa_handle, out_file_handle)
|
|
|
|
def dl(self, filename, directorypath = None, local_filename = None):
|
|
fsa_handle = self.get_fsa_handle()
|
|
if filename[0] != "/":
|
|
filename = self.cwd + "/" + filename
|
|
if local_filename == None:
|
|
if "/" in filename:
|
|
local_filename = filename[[i for i, x in enumerate(filename) if x == "/"][-1]+1:]
|
|
else:
|
|
local_filename = filename
|
|
ret, file_handle = self.FSA_OpenFile(fsa_handle, filename, "r")
|
|
if ret != 0x0:
|
|
print("dl error : could not open " + filename)
|
|
return
|
|
buffer = bytearray()
|
|
block_size = 0x400
|
|
while True:
|
|
ret, data = self.FSA_ReadFile(fsa_handle, file_handle, 0x1, block_size)
|
|
# print(hex(ret), data)
|
|
buffer += data[:ret]
|
|
sys.stdout.write(hex(len(buffer)) + "\r"); sys.stdout.flush();
|
|
if ret < block_size:
|
|
break
|
|
ret = self.FSA_CloseFile(fsa_handle, file_handle)
|
|
if directorypath == None:
|
|
open(local_filename, "wb").write(buffer)
|
|
else:
|
|
dir_path = os.path.dirname(os.path.abspath(sys.argv[0])).replace('\\','/')
|
|
fullpath = dir_path + "/" + directorypath + "/"
|
|
fullpath = fullpath.replace("//","/")
|
|
mkdir_p(fullpath)
|
|
open(fullpath + local_filename, "wb").write(buffer)
|
|
|
|
def mkdir_p(path):
|
|
try:
|
|
os.makedirs(path)
|
|
except OSError as exc: # Python >2.5
|
|
if exc.errno == errno.EEXIST and os.path.isdir(path):
|
|
pass
|
|
else:
|
|
raise
|
|
|
|
def fr(self, filename, offset, size):
|
|
fsa_handle = self.get_fsa_handle()
|
|
if filename[0] != "/":
|
|
filename = self.cwd + "/" + filename
|
|
ret, file_handle = self.FSA_OpenFile(fsa_handle, filename, "r")
|
|
if ret != 0x0:
|
|
print("fr error : could not open " + filename)
|
|
return
|
|
buffer = bytearray()
|
|
block_size = 0x400
|
|
while True:
|
|
ret, data = self.FSA_ReadFile(fsa_handle, file_handle, 0x1, block_size if (block_size < size) else size)
|
|
buffer += data[:ret]
|
|
sys.stdout.write(hex(len(buffer)) + "\r"); sys.stdout.flush();
|
|
if len(buffer) >= size:
|
|
break
|
|
ret = self.FSA_CloseFile(fsa_handle, file_handle)
|
|
return buffer
|
|
|
|
def fw(self, filename, offset, buffer):
|
|
fsa_handle = self.get_fsa_handle()
|
|
if filename[0] != "/":
|
|
filename = self.cwd + "/" + filename
|
|
ret, file_handle = self.FSA_OpenFile(fsa_handle, filename, "r+")
|
|
if ret != 0x0:
|
|
print("fw error : could not open " + filename)
|
|
return
|
|
block_size = 0x400
|
|
k = 0
|
|
while True:
|
|
cur_size = min(len(buffer) - k, block_size)
|
|
if cur_size <= 0:
|
|
break
|
|
sys.stdout.write(hex(k) + "\r"); sys.stdout.flush();
|
|
ret = self.FSA_WriteFile(fsa_handle, file_handle, buffer[k:(k+cur_size)])
|
|
k += cur_size
|
|
ret = self.FSA_CloseFile(fsa_handle, file_handle)
|
|
|
|
def stat(self, filename):
|
|
fsa_handle = self.get_fsa_handle()
|
|
if filename[0] != "/":
|
|
filename = self.cwd + "/" + filename
|
|
ret, file_handle = self.FSA_OpenFile(fsa_handle, filename, "r")
|
|
if ret != 0x0:
|
|
print("stat error : could not open " + filename)
|
|
return
|
|
(ret, stats) = self.FSA_GetStatFile(fsa_handle, file_handle)
|
|
if ret != 0x0:
|
|
print("stat error : " + hex(ret))
|
|
else:
|
|
print("flags: " + hex(stats[1]))
|
|
print("mode: " + hex(stats[2]))
|
|
print("owner: " + hex(stats[3]))
|
|
print("group: " + hex(stats[4]))
|
|
print("size: " + hex(stats[5]))
|
|
ret = self.FSA_CloseFile(fsa_handle, file_handle)
|
|
|
|
def up(self, local_filename, filename = None):
|
|
fsa_handle = self.get_fsa_handle()
|
|
if filename == None:
|
|
if "/" in local_filename:
|
|
filename = local_filename[[i for i, x in enumerate(local_filename) if x == "/"][-1]+1:]
|
|
else:
|
|
filename = local_filename
|
|
if filename[0] != "/":
|
|
filename = self.cwd + "/" + filename
|
|
f = open(local_filename, "rb")
|
|
ret, file_handle = self.FSA_OpenFile(fsa_handle, filename, "w")
|
|
if ret != 0x0:
|
|
print("up error : could not open " + filename)
|
|
return
|
|
progress = 0
|
|
block_size = 0x400
|
|
while True:
|
|
data = f.read(block_size)
|
|
ret = self.FSA_WriteFile(fsa_handle, file_handle, data)
|
|
progress += len(data)
|
|
sys.stdout.write(hex(progress) + "\r"); sys.stdout.flush();
|
|
if len(data) < block_size:
|
|
break
|
|
ret = self.FSA_CloseFile(fsa_handle, file_handle)
|
|
|
|
def mkdir_p(path):
|
|
try:
|
|
os.makedirs(path)
|
|
except OSError as exc:
|
|
if exc.errno == errno.EEXIST and os.path.isdir(path):
|
|
pass
|
|
else:
|
|
raise
|
|
|
|
def mount_sd():
|
|
handle = w.open("/dev/fsa", 0)
|
|
print(hex(handle))
|
|
|
|
ret = w.FSA_Mount(handle, "/dev/sdcard01", "/vol/storage_sdcard", 2)
|
|
print(hex(ret))
|
|
|
|
ret = w.close(handle)
|
|
print(hex(ret))
|
|
|
|
def unmount_sd():
|
|
handle = w.open("/dev/fsa", 0)
|
|
print(hex(handle))
|
|
|
|
ret = w.FSA_Unmount(handle, "/vol/storage_sdcard", 2)
|
|
print(hex(ret))
|
|
|
|
ret = w.close(handle)
|
|
print(hex(ret))
|
|
|
|
def mount_slccmpt01():
|
|
handle = w.open("/dev/fsa", 0)
|
|
print(hex(handle))
|
|
|
|
ret = w.FSA_Mount(handle, "/dev/slccmpt01", "/vol/storage_slccmpt01", 2)
|
|
print(hex(ret))
|
|
|
|
ret = w.close(handle)
|
|
print(hex(ret))
|
|
|
|
def unmount_slccmpt01():
|
|
handle = w.open("/dev/fsa", 0)
|
|
print(hex(handle))
|
|
|
|
ret = w.FSA_Unmount(handle, "/vol/storage_slccmpt01", 2)
|
|
print(hex(ret))
|
|
|
|
ret = w.close(handle)
|
|
print(hex(ret))
|
|
|
|
def mount_odd_content():
|
|
handle = w.open("/dev/fsa", 0)
|
|
print(hex(handle))
|
|
|
|
ret = w.FSA_Mount(handle, "/dev/odd03", "/vol/storage_odd_content", 2)
|
|
print(hex(ret))
|
|
|
|
ret = w.close(handle)
|
|
print(hex(ret))
|
|
|
|
def unmount_odd_content():
|
|
handle = w.open("/dev/fsa", 0)
|
|
print(hex(handle))
|
|
|
|
ret = w.FSA_Unmount(handle, "/vol/storage_odd_content", 2)
|
|
print(hex(ret))
|
|
|
|
ret = w.close(handle)
|
|
print(hex(ret))
|
|
|
|
def mount_odd_update():
|
|
handle = w.open("/dev/fsa", 0)
|
|
print(hex(handle))
|
|
|
|
ret = w.FSA_Mount(handle, "/dev/odd02", "/vol/storage_odd_update", 2)
|
|
print(hex(ret))
|
|
|
|
ret = w.close(handle)
|
|
print(hex(ret))
|
|
|
|
def unmount_odd_update():
|
|
handle = w.open("/dev/fsa", 0)
|
|
print(hex(handle))
|
|
|
|
ret = w.FSA_Unmount(handle, "/vol/storage_odd_update", 2)
|
|
print(hex(ret))
|
|
|
|
ret = w.close(handle)
|
|
print(hex(ret))
|
|
|
|
def mount_odd_tickets():
|
|
handle = w.open("/dev/fsa", 0)
|
|
print(hex(handle))
|
|
|
|
ret = w.FSA_Mount(handle, "/dev/odd01", "/vol/storage_odd_tickets", 2)
|
|
print(hex(ret))
|
|
|
|
ret = w.close(handle)
|
|
print(hex(ret))
|
|
|
|
def unmount_odd_tickets():
|
|
handle = w.open("/dev/fsa", 0)
|
|
print(hex(handle))
|
|
|
|
ret = w.FSA_Unmount(handle, "/vol/storage_odd_tickets", 2)
|
|
print(hex(ret))
|
|
|
|
ret = w.close(handle)
|
|
print(hex(ret))
|
|
|
|
def install_title(path, installToUsb = 0):
|
|
mcp_handle = w.open("/dev/mcp", 0)
|
|
print(hex(mcp_handle))
|
|
|
|
ret, data = w.MCP_InstallGetInfo(mcp_handle, "/vol/storage_sdcard/"+path)
|
|
print("install info : " + hex(ret), [hex(v) for v in data])
|
|
if ret != 0:
|
|
ret = w.close(mcp_handle)
|
|
print(hex(ret))
|
|
return
|
|
|
|
ret = w.MCP_InstallSetTargetDevice(mcp_handle, installToUsb)
|
|
print("install set target device : " + hex(ret))
|
|
if ret != 0:
|
|
ret = w.close(mcp_handle)
|
|
print(hex(ret))
|
|
return
|
|
|
|
ret = w.MCP_InstallSetTargetUsb(mcp_handle, installToUsb)
|
|
print("install set target usb : " + hex(ret))
|
|
if ret != 0:
|
|
ret = w.close(mcp_handle)
|
|
print(hex(ret))
|
|
return
|
|
|
|
ret = w.MCP_Install(mcp_handle, "/vol/storage_sdcard/"+path)
|
|
print("install : " + hex(ret))
|
|
|
|
ret = w.close(mcp_handle)
|
|
print(hex(ret))
|
|
|
|
def get_nim_status():
|
|
nim_handle = w.open("/dev/nim", 0)
|
|
print(hex(nim_handle))
|
|
|
|
inbuffer = buffer(0x80)
|
|
(ret, data) = w.ioctlv(nim_handle, 0x00, [inbuffer], [0x80])
|
|
|
|
print(hex(ret), "".join("%02X" % v for v in data[0]))
|
|
|
|
ret = w.close(nim_handle)
|
|
print(hex(ret))
|
|
|
|
def read_and_print(adr, size):
|
|
data = w.read(adr, size)
|
|
data = struct.unpack(">%dI" % (len(data) // 4), data)
|
|
for i in range(0, len(data), 4):
|
|
print(" ".join("%08X"%v for v in data[i:i+4]))
|
|
|
|
if __name__ == '__main__':
|
|
w = wupclient()
|
|
# mount_sd()
|
|
# mount_odd_content()
|
|
|
|
# w.up("/media/harddisk1/loadiine_code/homebrew_launcher_rpx/homebrew_launcher.rpx", "homebrew_launcher_rpx.rpx")
|
|
# w.up("/media/harddisk1/gx2sploit/gx2sploit.rpx", "homebrew_launcher_rpx.rpx")
|
|
# print(w.pwd())
|
|
# w.ls()
|
|
w.dump_syslog()
|
|
# w.mkdir("/vol/storage_sdcard/usr", 0x600)
|
|
# install_title("install", 1)
|
|
# get_nim_status()
|
|
# w.kill()
|