Skip to content

Instantly share code, notes, and snippets.

@kgsws
Created November 6, 2017 22:05
Show Gist options
  • Save kgsws/1806750e2b7dc5eb9b8170ef52d7189b to your computer and use it in GitHub Desktop.
Save kgsws/1806750e2b7dc5eb9b8170ef52d7189b to your computer and use it in GitHub Desktop.
sc.killAutoHandle();
function c32to8(data)
{
var len = data.length;
var ret = new Uint8Array(len * 4);
var offs = 0;
for(i = 0; i < len; i++)
{
ret[offs++] = data[i] & 0xFF;
ret[offs++] = (data[i] >> 8) & 0xFF;
ret[offs++] = (data[i] >> 16) & 0xFF;
ret[offs++] = data[i] >> 24;
}
return ret;
}
function c64to8(data)
{
var len = data.length;
var ret = new Uint8Array(len * 8);
var offs = 0;
for(i = 0; i < len; i++)
{
ret[offs++] = data[i][0] & 0xFF;
ret[offs++] = (data[i][0] >> 8) & 0xFF;
ret[offs++] = (data[i][0] >> 16) & 0xFF;
ret[offs++] = (data[i][0] >> 24) & 0xFF;
ret[offs++] = data[i][1] & 0xFF;
ret[offs++] = (data[i][1] >> 8) & 0xFF;
ret[offs++] = (data[i][1] >> 16) & 0xFF;
ret[offs++] = (data[i][1] >> 24) & 0xFF;
}
return ret;
}
function c8to32(data)
{
var len = data.length / 4;
var ret = new Uint32Array(len);
var offs = 0;
for(i = 0; i < len; i++)
{
ret[i] = data[offs++];
ret[i] |= data[offs++] << 8;
ret[i] |= data[offs++] << 16;
ret[i] |= data[offs++] << 24;
}
return ret;
}
function _crc(data, len)
{
var crc = 0;
for(j = 0; j < len; j++)
{
var v = 0x80;
for(i = 0; i < 8; i++)
{
var xorf = crc & 0x8000;
crc = (crc << 1) & 0xFFFF
if(data[j] & v)
crc = (crc + 1) & 0xFFFF;
if(xorf)
crc ^= 0x1021;
v >>= 1;
}
}
return crc;
}
function writePdm(payload)
{
// var data = payload.buffer;
// utils.hexdump("dat", data);
sc.ipcMsg(4).sendTo('pdm:ntfy').assertOk();
// sc.ipcMsg(5).aDescriptor(data, data.byteLength, 0).sendTo('pdm:ntfy').assertOk();
sc.ipcMsg(5).aDescriptor(payload, payload.length, 0).sendTo('pdm:ntfy').assertOk();
}
function getMiiAuthorId()
{
return c32to8(sc.ipcMsg(90).sendTo('set:sys').assertOk().data);
}
function crcMiiBuf(b, authorid)
{
var ret = new Uint8Array(b.length + 4);
ret.set(b);
var crc1 = _crc(ret, b.length + 2);
ret[b.length] = crc1 >> 8;
ret[b.length+1] = crc1 & 0xFF;
var temp = new Uint8Array(authorid.length + ret.length);
temp.set(authorid);
temp.set(ret, authorid.length);
var crc2 = _crc(temp, temp.length);
ret[b.length+2] = crc2 >> 8;
ret[b.length+3] = crc2 & 0xFF;
return ret;
}
function AddOrReplace(hnd, key, unm, authorid)
{
var crcbuf = new Uint8Array(unm.length + key.length);
crcbuf.set(unm);
crcbuf.set(key, unm.length);
crcbuf = crcMiiBuf(crcbuf, authorid);
var new_mii = new Uint8Array(crcbuf.length + 4);
new_mii.set(crcbuf);
var new_mii_as_words = c8to32(new_mii);
var ipc = sc.ipcMsg(13);
ipc.datau32.apply(ipc, new_mii_as_words);
ipc.sendTo(hnd).assertOk();
}
function Move(hnd, key, pos)
{
var data = new Uint32Array(key.length / 4 + 1);
data.set(c8to32(key));
data[data.length - 1] = pos;
var ipc = sc.ipcMsg(12);
ipc.datau32.apply(ipc, data);
ipc.sendTo(hnd).assertOk();
}
function Delete(hnd, key)
{
var data = c8to32(key);
var ipc = sc.ipcMsg(14);
ipc.datau32.apply(ipc, data);
ipc.sendTo(hnd).assertOk();
}
function GetCount(hnd)
{
ret = sc.ipcMsg(2).datau32(1).sendTo(hnd).assertOk().data[0];
// utils.log("mii count is " + ret.toString());
return ret;
}
function GetDefault(hnd, offset)
{
ret = sc.ipcMsg(7).datau32(offset).sendTo(hnd).assertOk();
return ret.data;
}
function GetLoadBase(hnd, authorid)
{
var unm = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x97, 0x02, 0x00, 0x00, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x41, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
var key = c64to8([[0xcafe, 0], [0xcafe0080, 0]]);
AddOrReplace(hnd, key, unm, authorid);
var data = GetDefault(hnd, (0x010b4b20 + 0xC + 0x44 * (GetCount(hnd) - 1) - 0x01079438) / 4);
Delete(hnd, key);
return utils.add2([data[5], data[6]], -0x9c540);
}
function Wipe(hnd)
{
var buf = new Uint8Array(100*0x44);
var count = sc.ipcMsg(9).data(1).bDescriptor(buf, buf.length, 0).sendTo(hnd).assertOk().data[0];
if(!count)
return;
utils.log("mii count to delete " + count.toString());
var key = new Uint8Array(16);
for(mii = 0; mii < count; mii++)
{
for(j = 0; j < 16; j++)
key[j] = buf[j + 48 + mii * 0x44];
Delete(hnd, key);
}
}
function getServicePid(service)
{
var res = this.ipcMsg(2).setType(3).datau64(0).sendTo(service).assertOk();
this.svcCloseHandle(res.movedHandles[0]);
return res.pid[0];
};
function checkMiiCode(code)
{
var checker = [0,1,2,3,4,5,6,7,8,16,17,18,19,20,21,22,23,24,32,33,34,35,36,37,38,39,40,48,49,50,51,52,53,54,55,56,64,65,66,67,68,69,70,71,72,80,81,82,83,84,85,86,87,88,96,97,98,99,100,101,102,103,104,112,113,114,115,116,117,118,119,120,128,129,130,131,132,133,134,135,136];
return checker.indexOf(code) >= 0;
}
authorid = getMiiAuthorId();
utils.log("Author ID: " + Array.apply([], authorid).join(","));
// wipe all miis
handle = sc.ipcMsg(0).data(0xA523B78F).sendTo('mii:e').assertOk().movedHandles[0];
utils.log("mii handle is 0x" + handle.toString(16));
utils.log("wipe miis ...");
Wipe(handle);
resetcount = 0;
sdbPid = getServicePid(handle);
tid = utils.parseAddr('0100000000000039');
utils.log("reloading, this might take a while ...");
while(1)
{
sdbBase = GetLoadBase(handle, authorid);
// utils.log("sdbBase at " + utils.paddr(sdbBase));
if(checkMiiCode(sdbBase[0] >>> 24) && checkMiiCode((sdbBase[0] >>> 16) & 0xFF) && sdbBase[1] > 0)
{
sc.svcCloseHandle(handle);
utils.log("sdb pid is 0x" + sdbPid.toString(16) + " sdbBase at " + utils.paddr(sdbBase));
utils.log("** good base ***");
break;
} else
{
// utils.log("this is a bad base 0x" + sdbBase[0].toString(16));
sc.svcCloseHandle(handle);
// restart sdb
sc.ipcMsg(1).data(sdbPid).sendTo('pm:shell').assertOk();
sdbPid = this.sc.ipcMsg(0).datau64(0, tid, 3).sendTo('pm:shell').data[0];
if(!(resetcount & 15))
utils.log("new sdb pid: 0x" + sdbPid.toString(16));
sc.killAutoHandle();
handle = sc.ipcMsg(0).data(0xA523B78F).sendTo('mii:e').assertOk().movedHandles[0];
// utils.log("mii handle is 0x" + handle.toString(16));
}
resetcount++;
}
utils.log("done");
@kgsws
Copy link
Author

kgsws commented Nov 6, 2017

This script resets sdb module until it's load address is usable.
Note: it also wipes all your Miis.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment