Ejemplo n.º 1
0
        static void ModeSpareFix()
        {
            if (string.IsNullOrEmpty(outputFile))
            {
                outputFile = filePath + "_fixed";
            }
            Console.WriteLine($"Reading spare from {filePath}...");

            using (var fixedStream = new MemoryStream())
            {
                using (var reader = new BinaryReader(File.OpenRead(filePath)))
                {
                    bool isBlockSpare = true;
                    if (reader.BaseStream.Length == 64 * 1024)
                    {
                        // must be a block-spare already, just copy it all to the fixed stream so we can fix up the ECC
                        byte[] spare = reader.ReadBytes(64 * 1024);
                        fixedStream.Write(spare, 0, 64 * 1024);
                    }
                    else
                    {
                        int numSkip = 0;
                        if (reader.BaseStream.Length == 1024 * 1024) // overdump, just skip 0xF0 after each read
                        {
                            numSkip = 0xF0;
                        }
                        else if (reader.BaseStream.Length == 1024 * 1024 * 2) // page-spare dump, we only want the spare of the last page in each block
                        {
                            numSkip = 0x1F0;
                            reader.BaseStream.Position = 0x1F0;
                        }
                        else
                        {
                            Console.WriteLine("Spare isn't overdump/page-spare/block-spare dump?");
                            return;
                        }

                        if (generateFullSpare)
                        {
                            if (numSkip != 0x1F0)
                            {
                                Console.WriteLine("Invalid spare used with -gp (-fullspare)");
                                Console.WriteLine("This switch only works with page/block-spares, not overdumps!");
                                return;
                            }

                            // user gave -gp switch, so just copy the whole page-spare instead of reducing to block-spare
                            reader.BaseStream.Position = 0;
                            byte[] spare = reader.ReadBytes(1024 * 1024 * 2);
                            fixedStream.Write(spare, 0, 1024 * 1024 * 2);

                            isBlockSpare = false;
                        }
                        else
                        {
                            while (reader.BaseStream.Position < reader.BaseStream.Length)
                            {
                                byte[] spare = reader.ReadBytes(0x10);
                                spare[6] = 0;                                              // fix page-spare dump to match format of block-spare dump
                                fixedStream.Write(spare, 0, 0x10);
                                if (reader.BaseStream.Position < reader.BaseStream.Length) // with raw page-spare dumps we're at the end here, so check for that
                                {
                                    reader.BaseStream.Position += numSkip;
                                }
                            }
                        }
                    }

                    // if nand.bin is specified, read from it and correct the spare data
                    if (!string.IsNullOrEmpty(extraPath))
                    {
                        var nand = new iQueNand(extraPath);
                        nand.Read();
                        var fixedSpare = nand.GenerateSpareData(isBlockSpare, fixedStream.ToArray()); // todo: make a stream-based GenerateSpareData method?
                        fixedStream.Position = 0;
                        fixedStream.Write(fixedSpare, 0, fixedSpare.Length);
                    }
                }
                File.WriteAllBytes(outputFile, fixedStream.ToArray());
            }
            Console.WriteLine($"Saved fixed spare to {outputFile}!");
        }
Ejemplo n.º 2
0
        static void ModeNAND()
        {
            Console.WriteLine($"Opening NAND image from {filePath}...");
            Console.WriteLine();

            if (!string.IsNullOrEmpty(outputFile) && !string.IsNullOrEmpty(updateKernelPath))
            {
                // we're updating kernel with output file specified, so copy the input file to specified output file and work with that instead
                if (File.Exists(outputFile))
                {
                    File.Delete(outputFile);
                }

                File.Copy(filePath, outputFile);
                filePath = outputFile;
            }

            var nandFile = new iQueNand(filePath)
            {
                SkipVerifyFsChecksums = skipVerifyChecksums,
                InodesOffset          = isBadDump ? 0x10 : 0
            };

            if (!nandFile.Read())
            {
                Console.WriteLine($"[!] Failed to read NAND image!");
                return;
            }

            if (printInfo)
            {
                Console.WriteLine(nandFile.ToString(true, true, showAllFsInfo));
            }

            if (writeInfo)
            {
                File.WriteAllText(filePath + ".txt", nandFile.ToString(true, false, showAllFsInfo));
                Console.WriteLine($"Wrote detailed NAND info to {filePath}.txt");
            }

            if (!string.IsNullOrEmpty(updateKernelPath))
            {
                Console.WriteLine($"Updating NAND SKSA to {updateKernelPath}");
                nandFile.SetSKSAData(updateKernelPath);
            }
            else
            {
                // extract / extractkernel can only be used if we aren't updating kernel in the same session
                if (extractAll)
                {
                    if (string.IsNullOrEmpty(outputFile))
                    {
                        outputFile = filePath + "_ext";
                        Console.WriteLine("[!] No output path (-o) given, set path to:");
                        Console.WriteLine($"- {outputFile}");
                        Console.WriteLine();
                    }

                    if (!Directory.Exists(outputFile))
                    {
                        Directory.CreateDirectory(outputFile);
                    }

                    int count = 0;
                    foreach (var file in nandFile.MainFsInodes)
                    {
                        if (!file.IsValid)
                        {
                            continue;
                        }

                        var extPath = Path.Combine(outputFile, file.NameString);
                        Console.WriteLine($"Writing file to {extPath}");
                        File.WriteAllBytes(extPath, nandFile.GetInodeData(file));
                        count++;
                    }

                    Console.WriteLine($"Extracted {count} files to {outputFile}");
                }

                if (extractKernel)
                {
                    if (string.IsNullOrEmpty(outputFile))
                    {
                        outputFile = filePath + ".sksa.bin";
                        Console.WriteLine("[!] No output path (-o) given, set path to:");
                        Console.WriteLine($"- {outputFile}");
                        Console.WriteLine();
                    }
                    if (extractAll) // if we just extracted the fs files we'll extract SKSA into the same folder
                    {
                        outputFile = Path.Combine(outputFile, "sksa.bin");
                    }

                    File.WriteAllBytes(outputFile, nandFile.GetSKSAData());

                    Console.WriteLine($"Extracted SKSA to {outputFile}");
                }
            }

            if (!string.IsNullOrEmpty(generateSparePath))
            {
                File.WriteAllBytes(generateSparePath, nandFile.GenerateSpareData(!generateFullSpare));
                Console.WriteLine($"Wrote generated {(generateFullSpare ? "page" : "block")}-spare data to {generateSparePath}");
            }
        }
Ejemplo n.º 3
0
        static void ModeNAND()
        {
            Console.WriteLine($"Opening NAND image from {filePath}...");
            Console.WriteLine();

            if (!string.IsNullOrEmpty(outputFile) && !string.IsNullOrEmpty(updateKernelPath))
            {
                // we're updating kernel with output file specified, so copy the input file to specified output file and work with that instead
                if (File.Exists(outputFile))
                {
                    File.Delete(outputFile);
                }

                File.Copy(filePath, outputFile);
                filePath = outputFile;
            }

            var nandFile = new iQueNand(filePath)
            {
                SkipVerifyFsChecksums = skipVerifyChecksums || fixFsChecksums,
                InodesOffset          = isBadDump ? 0x10 : 0
            };

            if (!nandFile.Read())
            {
                Console.WriteLine($"[!] Failed to read NAND image!");
                return;
            }

            if (!string.IsNullOrEmpty(addFiles) || !string.IsNullOrEmpty(addFilesList))
            {
                var filesToAdd = new List <string>();
                if (!string.IsNullOrEmpty(addFiles))
                {
                    var files = addFiles.Split(',');
                    filesToAdd.AddRange(files);
                }

                if (!string.IsNullOrEmpty(addFilesList))
                {
                    if (File.Exists(addFilesList))
                    {
                        var files = File.ReadAllLines(addFilesList);
                        filesToAdd.AddRange(files);
                    }
                    else
                    {
                        Console.WriteLine($"[!] -al (addlist) failed, list {addFilesList} doesn't exist!");
                    }
                }

                if (filesToAdd.Count > 0)
                {
                    int successful = 0;
                    foreach (var file in filesToAdd)
                    {
                        if (File.Exists(file))
                        {
                            Console.WriteLine($"Adding file to NAND: {file}");
                            BbInode node = new BbInode();
                            if (nandFile.FileWrite(Path.GetFileName(file), File.ReadAllBytes(file), ref node))
                            {
                                Console.WriteLine($"File added successfully! name: {node.NameString}, block: {node.BlockIdx}");
                                successful++;
                            }
                            else
                            {
                                Console.WriteLine($"[!] Failed to add file, likely not enough free space in nand!");
                            }
                        }
                        else
                        {
                            Console.WriteLine($"[!] Failed to add non-existing file:{Environment.NewLine}\t{file}");
                        }
                    }
                    if (successful > 0)
                    {
                        Console.WriteLine("Writing updated FS to NAND...");
                        if (nandFile.WriteFilesystem())
                        {
                            Console.WriteLine($"Added {successful} files successfully!");
                        }
                        else
                        {
                            Console.WriteLine("[!] Failed to write updated FS, couldn't find FS block to write?");
                        }
                    }
                }
                else
                {
                    Console.WriteLine("[!] -al (addlist) failed, no files to add!");
                }
            }

            if (!string.IsNullOrEmpty(deleteFiles))
            {
                var filesToDelete = deleteFiles.Split(',');
                int successful    = 0;
                foreach (var file in filesToDelete)
                {
                    // lazy way to get proper 8.3 name for this file..
                    BbInode inode = new BbInode();
                    inode.NameString = Path.GetFileName(file);

                    if (nandFile.FileDelete(inode.NameString))
                    {
                        Console.WriteLine($"File {inode.NameString} removed from NAND!");
                        successful++;
                    }
                    else
                    {
                        Console.WriteLine($"Failed to remove file {inode.NameString} from NAND...");
                    }
                }

                if (successful > 0)
                {
                    Console.WriteLine("Writing updated FS to NAND...");
                    if (nandFile.WriteFilesystem())
                    {
                        Console.WriteLine($"Removed {successful} files successfully!");
                    }
                    else
                    {
                        Console.WriteLine("[!] Failed to write updated FS, couldn't find FS block to write?");
                    }
                }
            }

            if (fixFsChecksums)
            {
                nandFile.RepairFsChecksums();
            }

            if (printInfo)
            {
                Console.WriteLine(nandFile.ToString(true, true, showAllFsInfo));
            }

            if (writeInfo)
            {
                File.WriteAllText(filePath + ".txt", nandFile.ToString(true, false, showAllFsInfo));
                Console.WriteLine($"Wrote detailed NAND info to {filePath}.txt");
            }

            if (!string.IsNullOrEmpty(updateKernelPath))
            {
                Console.WriteLine($"Updating NAND SKSA to {updateKernelPath}");
                nandFile.SetSKSAData(updateKernelPath);
            }
            else
            {
                // extract / extractkernel can only be used if we aren't updating kernel in the same session
                if (extractAll)
                {
                    if (string.IsNullOrEmpty(outputFile))
                    {
                        outputFile = filePath + "_ext";
                        Console.WriteLine("[!] No output path (-o) given, set path to:");
                        Console.WriteLine($"- {outputFile}");
                        Console.WriteLine();
                    }

                    if (!Directory.Exists(outputFile))
                    {
                        Directory.CreateDirectory(outputFile);
                    }

                    int count = 0;
                    foreach (var file in nandFile.MainFsInodes)
                    {
                        if (!file.IsValid)
                        {
                            continue;
                        }

                        var extPath = Path.Combine(outputFile, file.NameString);
                        Console.WriteLine($"Writing file to {extPath}");
                        File.WriteAllBytes(extPath, nandFile.FileRead(file));
                        count++;
                    }

                    Console.WriteLine($"Extracted {count} files to {outputFile}");
                }

                if (extractKernel)
                {
                    if (string.IsNullOrEmpty(outputFile))
                    {
                        outputFile = filePath + ".sksa.bin";
                        Console.WriteLine("[!] No output path (-o) given, set path to:");
                        Console.WriteLine($"- {outputFile}");
                        Console.WriteLine();
                    }
                    if (extractAll) // if we just extracted the fs files we'll extract SKSA into the same folder
                    {
                        outputFile = Path.Combine(outputFile, "sksa.bin");
                    }

                    File.WriteAllBytes(outputFile, nandFile.GetSKSAData());

                    Console.WriteLine($"Extracted SKSA to {outputFile}");
                }
            }

            if (!string.IsNullOrEmpty(generateSparePath))
            {
                File.WriteAllBytes(generateSparePath, nandFile.GenerateSpareData(!generateFullSpare));
                Console.WriteLine($"Wrote generated {(generateFullSpare ? "page" : "block")}-spare data to {generateSparePath}");
            }
        }