Advertisement
rajkosto

restoreUser.js

Mar 25th, 2018
1,257
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // restores all the files from sdcard:/user-restoreme/ to the internal USER partition, overwriting any existing
  2. // may cause your device to not be able to launch properly after a reboot, but should be recoverable by initializing data in recovery
  3. // DO NOT CHANGE THE PARTITION ID TO SYSTEM TO TRY AND ADD CUSTOM STUFF TO SYSTEM, VERY LIKELY BRICK IF YOU DO
  4. // - by rajkosto 25.03.2018.
  5.  
  6. if (IFileSystem.prototype.CreateDir === undefined || IFileSystem.prototype.DeleteDir === undefined)
  7. {
  8.     throw new Error("Missing IFileSystem functions, update your PegaSwitch from git!")
  9. }
  10.  
  11. if (IFile.prototype.SetSize === undefined)
  12. {
  13.     throw new Error("Missing IFile functions, update your PegaSwitch from git!")
  14. }
  15.  
  16. IFile.prototype.ReadPart = function (offset, size, buf) {
  17.     if(size instanceof ArrayBuffer || ArrayBuffer.isView(size)) {
  18.         buf = size;
  19.         size = buf.byteLength;
  20.     }
  21.     var ipcRes = this.sc.ipcMsg(0).datau64(0, offset, size).bDescriptor(buf, size, 1).sendTo(this.handle);
  22.     var bytes_read = [ipcRes.data[0], ipcRes.data[1]];
  23.     return ipcRes.asResult().replaceValue(bytes_read);
  24. };
  25.  
  26. sc.getFSPPR = function () {
  27.     if (sc.closed_pr !== undefined) {
  28.         return;
  29.     }
  30.     sc.enableTurbo();
  31.     var i = 0;
  32.     var srv = null;
  33.     while (true) {
  34.         sc.ipcMsg(2).setType(5).sendTo('pm:shell');
  35.         var srvResult = sc.getService("fsp-pr");
  36.         if(srvResult.isOk) {
  37.             srv = srvResult.getValue();
  38.             break;
  39.         }
  40.         i++;
  41.     }
  42.     utils.log('Got fsp-pr handle after ' + i + ' iterations: ');
  43.     utils.log('fsp-pr handle: 0x' + srv.toString(16));
  44.     sc.svcCloseHandle(srv).assertOk();
  45.     sc.closed_pr = true;
  46. };
  47.  
  48. sc.getFSPPR();
  49. sc.enableTurbo();
  50.  
  51. if(sc.pr_handle) {
  52.     sc.svcCloseHandle(sc.pr_handle);
  53.     sc.pr_handle = undefined;
  54. }
  55.  
  56. sc.getService("fsp-pr", (fsppr) => {
  57.     var pid = sc.getService('fsp-srv', (tmp_hnd) => {
  58.         utils.log("got fspsrv handle: 0x" + tmp_hnd.toString(16));
  59.         sc.ipcMsg(1).sendPid().data(0).sendTo(tmp_hnd).assertOk();
  60.         return sc.read4(sc.ipcBufAddr, 0xC >> 2);
  61.     });
  62.     utils.log('Got process PID: '+pid.toString(16));
  63.    
  64.     var buf1_sz = 0x1C;
  65.     var buf2_sz = 0x2C;
  66.     var buf = sc.malloc(buf1_sz + buf2_sz);
  67.     var buf2 = utils.add2(buf, buf1_sz);
  68.    
  69.     // buffer init
  70.     sc.write4(1, buf, 0x0>>2);
  71.     sc.write8([0xFFFFFFFF, 0xFFFFFFFF], buf, 0x4 >> 2); // This is the permissions value.
  72.     sc.write4(buf1_sz, buf, 0xC >> 2);
  73.     sc.write4(buf1_sz, buf, 0x14 >> 2);
  74.    
  75.     sc.write4(1, buf2, 0x0 >> 2);
  76.     sc.write8([0xFFFFFFFF, 0xFFFFFFFF], buf2, 0x4 >> 2); // This is the permissions value -- actual perms = buf2_val & buf1_val
  77.     sc.write4(0xFFFFFFFF, buf2, 0x14 >> 2);
  78.     sc.write4(0xFFFFFFFF, buf2, 0x18 >> 2);
  79.     sc.write4(0xFFFFFFFF, buf2, 0x24 >> 2);
  80.     sc.write4(0xFFFFFFFF, buf2, 0x28 >> 2);
  81.    
  82.     /* Change to mount a particular title's romfs */
  83.     var tid = '0000000000000000';
  84.    
  85.     sc.ipcMsg(256).data(0).sendTo(fsppr).assertOk().show();
  86.     sc.ipcMsg(1).data(pid).sendTo(fsppr).assertOk().show();
  87.     sc.ipcMsg(0).data(2, [pid,0], utils.parseAddr(tid), buf1_sz, buf2_sz, pid, pid, 0, 0, 0, 0, 0).aDescriptor(buf, buf1_sz).aDescriptor(buf2, buf2_sz).sendTo(fsppr).assertOk().show();
  88.     sc.free(buf);
  89.     sc.free(buf2);
  90. });
  91.  
  92. foreachDirEntry = function(dir_obj, callback)
  93. {
  94.     var entryCount = utils.trunc32(dir_obj.GetEntryCount().assertOk());
  95.     if (entryCount > 0 && callback !== undefined)
  96.     {
  97.         var entryBuf = new Uint32Array(0x310 * entryCount);
  98.         dir_obj.GetEntries(entryBuf, entryCount).assertOk();
  99.         for (var entryIdx = 0; entryIdx < entryCount; entryIdx++)
  100.         {
  101.             var fn = utils.u8a2str(new Uint8Array(entryBuf.buffer, 0x310 * entryIdx, 0x300));
  102.             for (var strIdx=0; strIdx<fn.length; strIdx++)
  103.             {
  104.                 if (fn.charCodeAt(strIdx) === 0)
  105.                 {
  106.                     fn = fn.substring(0, strIdx);
  107.                     break;
  108.                 }
  109.             }
  110.             var eType = entryBuf[(0x310 * entryIdx + 0x304) >> 2];         
  111.             callback(fn, eType);
  112.         }
  113.     }
  114.    
  115.     return entryCount;
  116. };
  117.  
  118. copyFiles = function(src_dir, dst_dir)
  119. {
  120.     var thefiles = [];
  121.     foreachDirEntry(src_dir, function(fn, eType)
  122.     {
  123.         if (eType === 1) { thefiles.push(fn); }
  124.     });
  125.     //dont need handle to dst_dir anymore (and it will interfere with Commit ops)
  126.     var dst_dir_fs = dst_dir.fs;
  127.     var dst_dir_path = dst_dir.path;
  128.     dst_dir.Close(); dst_dir = null;
  129.  
  130.     var CHUNK_SIZE = 1024*1024;
  131.     var buf = new ArrayBuffer(CHUNK_SIZE);
  132.     for (var fileIdx=0; fileIdx<thefiles.length; fileIdx++)
  133.     {
  134.         var fn = thefiles[fileIdx];
  135.         utils.log('[Opening existing file] ' + src_dir.path + fn);
  136.         var f_src = src_dir.fs.OpenFile(src_dir.path + fn).assertOk();
  137.         var size = f_src.GetSize().assertOk();
  138.         utils.log('[Source file size] ' + src_dir.path + fn + ' = ' + size + ' bytes');
  139.  
  140.         var f_dst = null;
  141.         try
  142.         {
  143.             //try open existing destination file
  144.             f_dst = dst_dir_fs.OpenFile(dst_dir_path + fn);
  145.             if (f_dst.isOk) //file exists, so lets just resize it to target size
  146.             {
  147.                 f_dst = f_dst.assertOk();
  148.                 var dst_size = f_dst.GetSize().assertOk();
  149.                 if (!utils.eq(dst_size, size))
  150.                 {
  151.                     utils.log('[Resizing existing file] ' + dst_dir_path + fn + ' ' + dst_size + ' -> ' + size);
  152.                     f_dst.SetSize(dst_size).assertOk();
  153.                     var new_size = f_dst.GetSize().assertOk();
  154.                     utils.log('[Resize complete] ' + dst_dir_path + fn + ' now ' + new_size);
  155.                 }                
  156.             }
  157.             else
  158.             {
  159.                 utils.log('[Creating new file] ' + dst_dir_path + fn + ' with size ' + size + ' bytes');
  160.                 dst_dir_fs.CreateFile(dst_dir_path + fn, size).assertOk();
  161.                 utils.log('[Opening new file] ' + dst_dir_path + fn);          
  162.                 f_dst = dst_dir_fs.OpenFile(dst_dir_path + fn).assertOk();
  163.             }            
  164.             utils.log('[Open dst file OK] ' + dst_dir_path + fn);
  165.             var doneBytes = [0, 0];
  166.             for (var totalSize = size; !utils.eq(doneBytes, totalSize); )
  167.             {
  168.                 var currBlockSize = totalSize;
  169.                 if (!utils.nullptr(doneBytes)) { currBlockSize = utils.sub2(totalSize, doneBytes); }
  170.                 if ((currBlockSize[1] != 0) || (currBlockSize[0] > CHUNK_SIZE)) { currBlockSize = CHUNK_SIZE; }
  171.                 else { currBlockSize = utils.trunc32(currBlockSize); }
  172.                
  173.                 var read_bytes = f_src.ReadPart(doneBytes, currBlockSize, buf).assertOk();
  174.                 utils.log('[Read bytes] ' + '@' + doneBytes + ' (' + currBlockSize + ') returned ' + read_bytes );
  175.                 /*if ((read_bytes[1] != 0) || (read_bytes[0] != currBlockSize))
  176.                 {
  177.                     throw new Error("Read mismatch, wanted " + currBlockSize + " bytes, got " + read_bytes + " bytes");
  178.                 }*/
  179.  
  180.                 var sizeAfterWrite = utils.add2(doneBytes, read_bytes);
  181.                 f_dst.Write(doneBytes, buf, read_bytes).assertOk();
  182.                 utils.log('[Wrote bytes] ' + '@' + doneBytes + ' + ' + read_bytes);
  183.                 doneBytes = sizeAfterWrite;
  184.             }
  185.             utils.log('[Write file Complete] ' + dst_dir_path + fn + ' -> ' + doneBytes + ' bytes');
  186.             f_dst.Close(); f_dst = null;
  187.             utils.log('[Close file OK] ' + dst_dir_path + fn);
  188.         }
  189.         finally
  190.         {
  191.             if (f_dst !== null && f_dst instanceof IFile) { f_dst.Close(); f_dst = null; }
  192.             if (f_src !== null) { f_src.Close(); f_src = null; }
  193.         }
  194.     }
  195.  
  196.     return dst_dir;
  197. };
  198.  
  199. evaluateDirs = function(fs_obj, root_dir)
  200. {
  201.     var folders = [];
  202.    
  203.     var dir_obj = fs_obj.OpenDir(root_dir, 1); //directories only
  204.     if (!dir_obj.isOk) { return folders; } //no dirs
  205.     else { dir_obj = dir_obj.assertOk(); }
  206.    
  207.     folders.push(dir_obj.path); //this dir
  208.     for (var evalIdx=0; evalIdx<folders.length; evalIdx++)
  209.     {
  210.         if (evalIdx !== 0)
  211.         {
  212.             dir_obj = fs_obj.OpenDir(folders[evalIdx], 1);
  213.             if (!dir_obj.isOk) { throw new Error('Unable to open dir ' + folders[evalIdx] + ' for listing'); }         
  214.             else { dir_obj = dir_obj.assertOk(); }
  215.         }
  216.  
  217.         foreachDirEntry(dir_obj, function(fn) { folders.push(dir_obj.path + fn + '/'); });
  218.         dir_obj.Close(); dir_obj = null;
  219.     }
  220.  
  221.     return folders;
  222. };
  223.  
  224. sc.getService('fsp-srv', (fsp_handle) => {
  225.     utils.log('initialized fsp-srv handle: 0x' + fsp_handle.toString(16));
  226.     sc.ipcMsg(1).sendPid().datau64(0).sendTo(fsp_handle).assertOk();
  227.  
  228.     mountSDCard = function () {
  229.         var self = this;
  230.         return sc.ipcMsg(18).sendTo(fsp_handle).asResult()
  231.             .map((r) => new self.sc.IFileSystem(self.sc, r.movedHandles[0]));
  232.     };
  233.    
  234.     mountBisFatPart = function (partId) {
  235.         var pbuf = new ArrayBuffer(1); //just a null terminator
  236.         var self = this;
  237.         return sc.ipcMsg(11).datau32(partId).xDescriptor(pbuf, pbuf.byteLength, 0).sendTo(fsp_handle).asResult()
  238.             .map((r) => new self.sc.IFileSystem(self.sc, r.movedHandles[0]));
  239.     };
  240.  
  241.     var fs_sd = null;
  242.     var fs_user = null;
  243.  
  244.     try {
  245.         utils.log("Mounting SD card");
  246.         try { fs_sd = mountSDCard().assertOk(); }
  247.         catch(e) { throw new Error("Failed to open SD card. Is it inserted?"); }
  248.         fs_sd.partition = "SDCARD";
  249.         utils.log('SDCARD handle = 0x' + fs_sd.handle.toString(16));
  250.  
  251.         var sdFolderName = "/user-restoreme/";
  252.         utils.log('[Listing folders in SDCARD] ' + sdFolderName);
  253.         var dirList = evaluateDirs(fs_sd, sdFolderName);
  254.         if (dirList.length < 1)
  255.         {
  256.             throw new Error("Unable to list SDCARD dir contents or it's empty");
  257.         }
  258.         utils.log(dirList.length + ' folders found to be restored');
  259.        
  260.         utils.log("Mounting USER partition");
  261.         try { fs_user = mountBisFatPart(30).assertOk(); }
  262.         catch(e) { throw new Error("Failed to mount USER partition"); }
  263.         fs_user.partition = "USER";
  264.         utils.log('USER handle = 0x' + fs_user.handle.toString());        
  265.  
  266.         for (var dirIndex = 0; dirIndex < dirList.length; dirIndex++)
  267.         {
  268.             var left_side = dirList[dirIndex];
  269.             var right_side = '/' + left_side.substring(sdFolderName.length);
  270.            
  271.             utils.log('[Opening folder on SD] '+ left_side);
  272.             var dir_sd = fs_sd.OpenDir(left_side, 2).assertOk();
  273.             utils.log('[Opening folder on USER] '+ right_side);
  274.             var dir_user = fs_user.OpenDir(right_side, 2);
  275.             if (!dir_user.isOk)
  276.             {
  277.                 utils.log('[Making folder on USER] '+ right_side);
  278.                 fs_user.CreateDir(right_side).assertOk();
  279.                 utils.log('[Opening newly made folder] ' + right_side);            
  280.                 dir_user = fs_user.OpenDir(right_side, 2).assertOk();
  281.                 utils.log('[New folder opened OK] '+ right_side);
  282.             }
  283.             else
  284.             {
  285.                 dir_user = dir_user.assertOk();
  286.                 utils.log('[Existing folder opened OK] '+ right_side);
  287.             }
  288.    
  289.             try
  290.             {
  291.                 dir_user = copyFiles(dir_sd, dir_user); //because we might change dst_dir inside
  292.             }
  293.             finally
  294.             {
  295.                 if (dir_sd !== null) { dir_sd.Close(); dir_sd = null; }
  296.                 if (dir_user !== null) { dir_user.Close(); dir_user = null; }
  297.             }
  298.         }
  299.        
  300.         utils.log('[Closing file systems]');
  301.     }
  302.     finally
  303.     {
  304.         if (fs_user !== null) { fs_user.Close(); fs_user = null; }
  305.         if (fs_sd !== null) { fs_sd.Close(); fs_sd = null; }
  306.     }
  307. });
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement