public bool Read() { var numBlocks = (int)(io.Stream.Length / BLOCK_SZ); if (numBlocks != NUM_BLOCKS_IN_FAT) { return(false); // invalid image } var ret = ReadFilesystem(); if (!ret) { return(false); // failed to find valid FAT } SKSA = new iQueKernel(GetSKSAData()); SKSA.Read(); int idx = GetInodeIdx("cert.sys"); if (idx >= 0) { var data = GetInodeData(MainFsInodes[idx]); Certs = new iQueCertCollection(data); if (iQueCertCollection.MainCollection == null) { iQueCertCollection.MainCollection = new iQueCertCollection(data); // MainCollection wasn't loaded already, so lets try loading it from this nand (yolo) } } idx = GetInodeIdx("depot.sys"); HasPrivateData = idx >= 0; if (HasPrivateData) { var data = GetInodeData(MainFsInodes[idx]); PrivateData = Shared.BytesToStruct <iQuePrivateData>(data); //PrivateData.EndianSwap(); } idx = GetInodeIdx("ticket.sys"); if (idx >= 0) { var data = GetInodeData(MainFsInodes[idx]); Tickets = new iQueArrayFile <iQueTitleData>(data); for (int i = 0; i < Tickets.Count; i++) { Tickets[i] = Tickets[i].EndianSwap(); } } idx = GetInodeIdx("crl.sys"); if (idx >= 0) { var data = GetInodeData(MainFsInodes[idx]); CRL = new iQueArrayFile <iQueCertificateRevocation>(data); foreach (var crl in CRL) { crl.EndianSwap(); } } // todo: // recrypt.sys // timer.sys // sig.db return(true); }
public bool SetSKSAData(byte[] sksaData) { var sksa = new iQueKernel(sksaData); sksa.Read(); // write SK data io.Stream.Position = 0; io.Writer.Write(sksa.SKData); int lastDataBlock = -1; int curDataBlock = NUM_SK_BLOCKS; // write SA1 ticket area int sa1TicketBlock = curDataBlock; io.Stream.Position = curDataBlock * BLOCK_SZ; io.Writer.Write(new byte[BLOCK_SZ]); io.Stream.Position = curDataBlock * BLOCK_SZ; io.Writer.Write(sksa.SA1SigArea.GetBytes()); // get next good block after SA1 ticket (which will be SA1 final block) curDataBlock = GetNextGoodBlock(curDataBlock); int sa1FinalDataBlock = curDataBlock; int numDataBlocks = (int)(sksa.SA1SigArea.Ticket.ContentSize / BLOCK_SZ); for (int i = numDataBlocks - 1; i >= 0; i--) { byte[] data = new byte[BLOCK_SZ]; Array.Copy(sksa.SA1Data, i * BLOCK_SZ, data, 0, BLOCK_SZ); io.Stream.Position = curDataBlock * BLOCK_SZ; io.Writer.Write(data); lastDataBlock = curDataBlock; curDataBlock = GetNextGoodBlock(curDataBlock); } if (sksa.SA2IsValid) { // write SA2 ticket area int sa2TicketBlock = curDataBlock; io.Stream.Position = curDataBlock * BLOCK_SZ; io.Writer.Write(new byte[BLOCK_SZ]); io.Stream.Position = curDataBlock * BLOCK_SZ; io.Writer.Write(sksa.SA2SigArea.GetBytes()); // get next good block after SA2 ticket (which will be SA2 final block) curDataBlock = GetNextGoodBlock(curDataBlock); int sa2FinalDataBlock = curDataBlock; numDataBlocks = (int)(sksa.SA2SigArea.Ticket.ContentSize / BLOCK_SZ); for (int i = numDataBlocks - 1; i >= 0; i--) { byte[] data = new byte[BLOCK_SZ]; Array.Copy(sksa.SA2Data, i * BLOCK_SZ, data, 0, BLOCK_SZ); io.Stream.Position = curDataBlock * BLOCK_SZ; io.Writer.Write(data); lastDataBlock = curDataBlock; curDataBlock = GetNextGoodBlock(curDataBlock); } } io.Stream.Flush(); Console.WriteLine("Updated SKSA!"); Console.WriteLine("Wrote updated nand to " + FilePath); // reload this.SKSA SKSA = new iQueKernel(GetSKSAData()); SKSA.Read(); return(true); }