示例#1
0
        private byte[] patch_CB(byte[] CB)
        {
            if (CB == null)
            {
                return(null);
            }
            int[] patchsets = { 9188, 6752, 5772, 4577, 13121 };

            int[]      CB_patches_offsets_9188  = { 0x4f08, 0x5618, 0x5678, 0x4d10 };
            string[][] CB_patches_9188          = { new string[] { "409a0010", "60000000" }, new string[] { "480018e1", "60000000" }, new string[] { "480000b9", "60000000" }, new string[] { "7BEB0620", "48000168" } };
            int[]      CB_patches_offsets_6752  = { 0x6AA0, 0x71B0, 0x7200, 0x68A8 };
            string[][] CB_patches_6752          = { new string[] { "409a0010", "60000000" }, new string[] { "480018D9", "60000000" }, new string[] { "419A0014", "48000014" }, new string[] { "7BEB0620", "48000168" } };
            int[]      CB_patches_offsets_5772  = { 0x6A58, 0x7168, 0x71b8, 0x6860 };
            string[][] CB_patches_5772          = { new string[] { "409a0010", "60000000" }, new string[] { "480018e1", "60000000" }, new string[] { "419A0014", "48000014" }, new string[] { "7BEB0620", "48000168" } };
            int[]      CB_patches_offsets_4577  = { 0x53C0, 0x55B8, 0x5D54, 0x5DB0 };
            string[][] CB_patches_4577          = { new string[] { "7beb0620", "48000168" }, new string[] { "409a0010", "60000000" }, new string[] { "480018c5", "60000000" }, new string[] { "480000a1", "60000000" } };
            int[]      CB_patches_offsets_13121 = { 0x5240, 0x5938, 0x59B8, 0x5048, 0x58AC };
            string[][] CB_patches_13121         = { new string[] { "409A0010", "60000000" }, new string[] { "48001859", "60000000" }, new string[] { "480000b9", "60000000" }, new string[] { "7BEB0620", "48000168" }, new string[] { "48000195", "60000000" } };
            //[13121,[[0x5240,0x409A0010,0x60000000],[0x5938,0x48001859,0x60000000],[0x59B8,0x480000b9,0x60000000], [0x5048, 0x7BEB0620, 0x48000168], [0x58AC, 0x48000195, 0x60000000]]]
            int[]      CB_patches_offsets = { };
            string[][] CB_patches         = { new string[] { } };

            /*
             * int[] CB_patches_offsets = { 0x4ecc, 0x4e40, 0x4df4, 0x4f08, 0x5618, 0x5678  };
             * string[][] CB_patches_9188 = { new string[] { "409a0010", "60000000" }, new string[] { "409A0038", "48000038" },new string[] { "409a0010", "60000000" },
             *                              new string[] { "409a0010", "60000000" }, new string[] { "480018e1", "60000000" }, new string[] { "480000b9", "60000000" } };
             */
            bool found = false;

            foreach (int patchCB in patchsets)
            {
                if (Oper.ByteArrayToInt(build(CB)) == patchCB)
                {
                    if (patchCB == 9188)
                    {
                        CB_patches_offsets = CB_patches_offsets_9188;
                        CB_patches         = CB_patches_9188;
                    }
                    else if (patchCB == 6752)
                    {
                        CB_patches_offsets = CB_patches_offsets_6752;
                        CB_patches         = CB_patches_6752;
                    }
                    else if (patchCB == 5772)
                    {
                        CB_patches_offsets = CB_patches_offsets_5772;
                        CB_patches         = CB_patches_5772;
                    }
                    else if (patchCB == 4577)
                    {
                        CB_patches_offsets = CB_patches_offsets_4577;
                        CB_patches         = CB_patches_4577;
                    }
                    else if (patchCB == 13121)
                    {
                        CB_patches_offsets = CB_patches_offsets_13121;
                        CB_patches         = CB_patches_13121;
                    }
                    if (variables.debugme)
                    {
                        Console.WriteLine("{0} patches selected", patchCB);
                    }

                    Console.WriteLine("patchset for {0} found, {1} patch(es)", patchCB, CB_patches_offsets.Length);
                    found = true;
                    int keystream, patched;

                    for (int j = 0; j < CB_patches_offsets.Length; j++)
                    {
                        for (int i = 0; i < 4; i++)
                        {
                            keystream = Oper.StringToByteArray(CB_patches[j][0])[i] ^ (CB[i + CB_patches_offsets[j]]);
                            patched   = (keystream ^ (Oper.StringToByteArray(CB_patches[j][1])[i]));
                            CB[CB_patches_offsets[j] + i] = (byte)patched;
                        }
                    }
                }
            }
            if (!found)
            {
                Console.WriteLine("can't patch that CB");
                //Exit
            }
            return(CB);
        }
示例#2
0
        public int creatergh2ecc(string filename, string outputfolder, ref ProgressBar pb, string cpukey)
        {
            eccs dt = new eccs();

            byte[] data;
            int    layout;
            bool   rgh2 = false;

            bool sts = objAlphaPattern.IsMatch(cpukey);

            if (variables.rgh2 && !String.IsNullOrEmpty(cpukey) && sts)
            {
                rgh2 = true;
            }

            long   size      = 0;
            string imagefile = filename;

            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
            if (variables.debugme)
            {
                Console.WriteLine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
            }

            string pathforit    = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            string cdrgh2file   = Path.Combine(pathforit, @"common/cdxell/CDRGH2");
            string cdfile       = Path.Combine(pathforit, @"common/cdxell/CD");
            string cdjasperfile = Path.Combine(pathforit, @"common/cdxell/CDjasper");

            /// nand image
            {
                byte[] bbimage = Nand.BadBlock.find_bad_blocks_X(imagefile, 0x50);
                data    = Oper.returnportion(ref bbimage, 0, 1 * 1024 * 1024);
                bbimage = null;

                layout = Nand.Nand.getConsole(new Nand.PrivateN(filename)).Layout;

                if (Oper.allsame(Oper.returnportion(ref data, 0x210, 0x200), 0xFF))
                {
                    Console.WriteLine("Invalid Image");
                    return(-1);
                }
                Console.WriteLine("* unpacking flash image, ....");
                unpack_base_image_ecc(ref data, ref pb, ref dt);
                dt.CB_A_crypted = dt.CB_A;
                dt.SMC          = decrypt_SMC(dt.SMC);
            }

            creatergh2eccinit(ref dt);
            ///
            ///Finished Loading images
            ///
            data = null;
            if (dt.CD_plain == null)
            {
                return(-1);
            }
            if (dt.SMC == null)
            {
                return(-1);
            }
            ///
            Console.WriteLine(" * we found the following parts: ");
            Console.WriteLine("SMC: {0}.{1}", (dt.SMC[0x101].ToString()), (dt.SMC[0x102]).ToString());
            ///
            if (dt.CB_A != null)
            {
                Console.WriteLine("CB_A: {0}", Oper.ByteArrayToInt(build(dt.CB_A)));
            }
            else
            {
                Console.WriteLine("CB_A: missing");
            }
            if (dt.CB_B != null)
            {
                Console.WriteLine("CB_B: {0}", Oper.ByteArrayToInt(build(dt.CB_B)));
            }
            else
            {
                Console.WriteLine("CB_B: missing");
            }

            ///
            ///
            int[] rghcbs  = { 6753, 6752, 5773, 4578, 4577, 5772, 9230 };
            int[] rgh1cbs = { 9188 };
            //if (rghcbs.Contains(bytearray_to_int(build(CB_A)))) rgh2 = true;
            if (dt.CB_B != null && !rgh1cbs.Contains(Oper.ByteArrayToInt(build(dt.CB_B))))
            {
                rgh2 = true;
            }
            ///
            ///
            string c;

            if (rgh2)
            {
                dt.CD_plain = Oper.openfile(cdrgh2file, ref size, 1 * 1024 * 1024);
                if (dt.CD_plain == null)
                {
                    return(-1);
                }
                if (dt.CD != null)
                {
                    Console.WriteLine("CD (image): {0}", Oper.ByteArrayToInt(build(dt.CD)));
                }
                else
                {
                    Console.WriteLine("CD (image): missing");
                }
                if (dt.CD_plain != null)
                {
                    Console.WriteLine("CD (decrypted): {0}", Oper.ByteArrayToInt(build(dt.CD_plain)));
                }
                else
                {
                    Console.WriteLine("CD (decrypted): missing");
                }
                byte[] CB_A_img_RAND = { };
                CB_A_img_RAND = Oper.returnportion(ref dt.CB_A_crypted, 0x10, 0x10);
                ///
                byte[] CB_A_img = Nand.Nand.decrypt_CB(dt.CB_A_crypted);
                Console.WriteLine(" * checking required versions...");

                int[] zephyr_builds   = { 4578, 4577, 4575, 4560, 4576 };
                int[] falcon_builds   = { 5771, 5772, 5773 };
                int[] jasper_builds   = { 6750, 6752, 6753, 6754 };
                int[] trinity_builds  = { 9188, 9230, 9231 };
                int[] corona_builds   = { 13121, 13180 };
                int[] xor_hack_builds = { 9230, 9231, 5773, 6753, 6754, 4575, 4560, 13180 };
                int[] patch_builds    = { 5772, 6752, 9188, 13121 };

                if (!zephyr_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))) &&
                    !falcon_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))) &&
                    !jasper_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))) &&
                    !corona_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))) &&
                    !trinity_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))))
                {
                    return(-3);
                }
                if (!xor_hack_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))) &&
                    !patch_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))) && String.IsNullOrEmpty(cpukey))
                {
                    return(-4);
                }

                Console.WriteLine("ok");

                Console.WriteLine(" * patching SMC...");
                dt.SMC = patch_SMC(dt.SMC);

                Console.WriteLine(" * Replacing CD...");
                dt.CD       = dt.CD_plain;
                dt.CD_plain = null;

                string cbapath = "", cbbpath = "";

                if (falcon_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))))
                {
                    cbapath = Path.Combine(pathforit, "common\\CB\\CB_A.5772.bin");
                    cbbpath = Path.Combine(pathforit, "common\\CB\\CB_B.5772.bin");
                }
                else if (jasper_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))))
                {
                    cbapath = Path.Combine(pathforit, "common\\CB\\CB_A.6752.bin");
                    cbbpath = Path.Combine(pathforit, "common\\CB\\CB_B.6752.bin");
                }
                else if (trinity_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))))
                {
                    cbapath = Path.Combine(pathforit, "common\\CB\\CB_A.9188.bin");
                    cbbpath = Path.Combine(pathforit, "common\\CB\\CB_B.9188.bin");
                }
                else if (zephyr_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))))
                {
                    cbapath = Path.Combine(pathforit, "common\\CB\\CB_A.4577.bin");
                    cbbpath = Path.Combine(pathforit, "common\\CB\\CB_B.4577.bin");
                }
                else if (corona_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))))
                {
                    cbapath = Path.Combine(pathforit, "common\\CB\\CB_A.13121.bin");
                    cbbpath = Path.Combine(pathforit, "common\\CB\\CB_B.13121.bin");
                }

                c      = "RGH2 2stage CB img";
                cpukey = "";
wtf:
                if (String.IsNullOrEmpty(cpukey))
                {
                    if (patch_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_B))))
                    {
                        Console.WriteLine(" * patching CB_B...");
                        dt.CB_B = patch_CB(dt.CB_B);
                        dt.CB_A = dt.CB_A_crypted;
                    }
                    else if (xor_hack_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_B))))
                    {
                        Console.WriteLine();
                        Console.WriteLine("* XOR HACK NEEDED FOR CB {0}", Oper.ByteArrayToInt(build(dt.CB_B)));

                        byte[] CB_B_plain = Oper.openfile(Path.Combine(variables.pathforit, @"common\CB\CB_B." + Oper.ByteArrayToInt(build(dt.CB_B)) + ".bin"), ref size, 0);
                        if (CB_B_plain == null)
                        {
                            Console.WriteLine("Failed to open CB_B.{0}.bin", Oper.ByteArrayToInt(build(dt.CB_B))); return(5);
                        }

                        byte[] CB_B_patched = Oper.openfile(cbbpath, ref size, 0);
                        if (CB_B_patched == null)
                        {
                            Console.WriteLine("Failed to open {0}", cbbpath); return(5);
                        }
                        Console.WriteLine(" * patching CB_B...");

                        CB_B_patched = patch_CB(CB_B_patched);
                        if (CB_B_patched == null)
                        {
                            Console.WriteLine("Failed to patch the CB_B"); return(5);
                        }
                        Console.WriteLine(" * Applying XOR Hack to CB_B {0}", Oper.ByteArrayToInt(build(dt.CB_B)));

                        dt.CB_B = xor_hack(dt.CB_B, CB_B_plain, CB_B_patched);
                        Console.WriteLine(" * Replacing CB_A {0} with {1}", Oper.ByteArrayToInt(build(dt.CB_A)), Oper.ByteArrayToInt(build(CB_B_patched)));

                        dt.CB_A = Oper.openfile(cbapath, ref size, 0);
                        if (dt.CB_A == null)
                        {
                            Console.WriteLine("Failed to open {0}", cbapath); return(5);
                        }
                        byte[] CB_A_key = { };
                        dt.CB_A = Nand.Nand.encrypt_CB(dt.CB_A, CB_A_img_RAND, ref CB_A_key);
                    }
                }
                else
                {
                    if (MessageBox.Show("Are you sure you want to build a new bootloader chain?", "Bootloader Chain", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.No)
                    {
                        cpukey = "";
                        goto wtf;
                    }
                    Console.WriteLine("\n * Building new bootloader chain using cpu_key: {0}", cpukey);

                    dt.CB_A = Oper.openfile(cbapath, ref size, 0);
                    dt.CB_B = Oper.openfile(cbbpath, ref size, 0);

                    dt.CB_B = patch_CB(dt.CB_B);

                    byte[] CB_A_key = { };
                    dt.CB_A = Nand.Nand.encrypt_CB(dt.CB_A, CB_A_img_RAND, ref CB_A_key);
                    dt.CB_B = Nand.Nand.encrypt_CB_cpukey(dt.CB_B, CB_A_key, Oper.StringToByteArray(cpukey));
                }
                ///
                ///
                ///
                Console.WriteLine(" * constructing new image...");

                c = c + ", CB=" + Oper.ByteArrayToInt(build(dt.CB_A));
            }
            else
            {
                if (dt.CD != null)
                {
                    Console.WriteLine("CD (image): {0}", Oper.ByteArrayToInt(build(dt.CD)));
                }
                else
                {
                    Console.WriteLine("CD (image): missing");
                }
                if (dt.CD_plain != null)
                {
                    Console.WriteLine("CD (decrypted): {0}", Oper.ByteArrayToInt(build(dt.CD_plain)));
                }
                else
                {
                    Console.WriteLine("CD (decrypted): missing");
                }
                int[] jasper_builds = { 6750, 6752, 6753 };
                if (jasper_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))))
                {
                    dt.CD_plain = Oper.openfile(cdjasperfile, ref size, 1 * 1024 * 1024);
                }
                if (dt.CD_plain == null)
                {
                    return(-1);
                }
                byte[] CB_A_img_RAND = { };
                if (!donor)
                {
                    CB_A_img_RAND = Oper.returnportion(ref dt.CB_A_crypted, 0x10, 0x10);
                }
                ///
                if (Oper.ByteArrayToInt(build(dt.CB_A)) >= 1888 && Oper.ByteArrayToInt(build(dt.CB_A)) <= 1940 || Oper.ByteArrayToInt(build(dt.CB_A)) == 7373 || Oper.ByteArrayToInt(build(dt.CB_A)) == 8192)
                {
                    Console.WriteLine(" * using donor CB");
                    dt.CB_A_crypted = null;
                    if (MessageBox.Show("There have been various reports that using a different bootloader improves the glitch speeds on xenon. Click Yes to use the 7375 Bootloader or Click No to use the 1940 one.", "Choose CB", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.Yes)
                    {
                        dt.CB_A = Oper.openfile(Path.Combine(variables.pathforit, @"common\CB\CB_A.7375.bin"), ref size, 0);
                    }
                    else
                    {
                        dt.CB_A = Oper.openfile(Path.Combine(variables.pathforit, @"common\CB\CB_A.1940.bin"), ref size, 0);
                    }
                    if (dt.CB_A == null)
                    {
                        Console.WriteLine("Failed to open CB"); return(5);
                    }
                    dt.CB_B     = null;
                    dt.CD_plain = Oper.openfile(cdfile, ref size, 1 * 1024 * 1024);
                    if (dt.CD_plain == null)
                    {
                        return(-1);
                    }
                }
                ///
                ///
                ///
                int[] xenon_builds  = { 1923, 7375 };
                int[] zephyr_builds = { 4578, 4579, 4575 };
                int[] falcon_builds = { 5771, 5772, 5773 };
                //int[] jasper_builds = { 6750, 6752, 6753 };
                int[] trinity_builds  = { 9188, 9230 };
                int[] corona_builds   = { 13121, 13180 };
                int[] slim_builds     = { 9188, 9230, 13121 };
                int[] xor_hack_builds = { 9230, 5773, 6753, 4575 };

                if (!donor)
                {
                    if ((dt.CB_A_crypted != null) && (Oper.ByteArrayToInt(build(dt.CB_A)) != 9230))
                    {
                        dt.CB_A = Nand.Nand.decrypt_CB(dt.CB_A_crypted);
                        if (dt.CB_A == null)
                        {
                            Console.WriteLine("Error");
                        }
                    }
                }
                if (dt.CB_B != null && !slim_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))))
                {
                    Console.WriteLine("Not supported yet");
                    return(5);
                }


                if (trinity_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))))
                {
                    Console.WriteLine(" * this image will be valid *only* for: trinity (slim)");
                }
                else if (corona_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))))
                {
                    Console.WriteLine(" * this image will be valid *only* for: corona");
                }
                else if (zephyr_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))))
                {
                    Console.WriteLine(" * this image will be valid *only* for: zephyr");
                }
                else if (falcon_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))))
                {
                    Console.WriteLine(" * this image will be valid *only* for: falcon");
                }
                else if (jasper_builds.Contains(Oper.ByteArrayToInt(build(dt.CB_A))))
                {
                    if (donor)
                    {
                        Console.WriteLine(" * this image will be valid *only* for: jasper (CB_6751)");
                    }
                    else
                    {
                        Console.WriteLine(" * this image will be valid *only* for: jasper (CB_6750)");
                    }
                }
                else
                {
                    Console.WriteLine(" * this image will be valid *only* for: xenon");
                }

                Console.WriteLine(" * patching SMC...");
                dt.SMC = patch_SMC(dt.SMC);

                dt.CD       = dt.CD_plain;
                dt.CD_plain = null;

                if (dt.CB_B != null)
                {
                    Console.WriteLine(" * patching CB_B...");
                    dt.CB_B = patch_CB(dt.CB_B);
                    c       = "patched CB img";
                }
                else
                {
                    //Nand.savefile(CB_A, "CB_f.bin");
                    Console.WriteLine(" * zero-pairing...");
                    for (int bytes = 0x20; bytes < 0x40; bytes++)
                    {
                        dt.CB_A[bytes] = 0x00;
                    }
                    c = "zeropair image";
                }
                if (!Directory.Exists(Path.Combine(Directory.GetCurrentDirectory(), "output")))
                {
                    Directory.CreateDirectory(Path.Combine(Directory.GetCurrentDirectory(), "output"));
                }
                ///
                ///
                ///
                Console.WriteLine(" * constructing new image...");
                byte[] random = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

                c = c + ", version=01, CB=" + Oper.ByteArrayToInt(build(dt.CB_A));

                if (dt.CB_B == null)
                {
                    byte[] CB_A_key = { };
                    //Nand.savefile(CB_A, "CB_d.bin");
                    dt.CB_A = Nand.Nand.encrypt_CB(dt.CB_A, random, ref CB_A_key);
                    //Nand.savefile(CB_A, "CB_e.bin");
                    //Console.WriteLine(ByteArrayToString(CB_A_key));
                    dt.CD = Nand.Nand.encrypt_CD(dt.CD, random, CB_A_key);
                }
            }

            createrghheader(ref dt, c);
            ///
            dt.SMC = encrypt_SMC(dt.SMC);
            ///
            ///
            byte[] newXell = dt.Xell;
            if (dt.Xell.Length <= 256 * 1024)
            {
                Console.WriteLine(" * No separate recovery Xell available!");
                newXell = Oper.concatByteArrays(dt.Xell, dt.Xell, dt.Xell.Length, dt.Xell.Length);
            }
            dt.Xell = null;
            ///
            /// Start of image creation
            ///
            byte[] Final = { };
            Console.WriteLine(" * Flash Layout:");
            Final = addtoflash(Oper.returnportion(ref dt.Header, 0x00, 0x200), Final, "Header", 0x00, 0x200);
            Final = padto_v2(Final, 0x4000 - dt.SMC.Length);
            ///
            Final       = addtoflash(dt.SMC, Final, "SMC", Final.Length, dt.SMC.Length);
            dt.SMC      = null;
            Final       = addtoflash(dt.Keyvault, Final, "Keyvault", Final.Length, dt.Keyvault.Length);
            dt.Keyvault = null;
            ///
            if (dt.CB_B != null)
            {
                if (!rgh2)
                {
                    Final = addtoflash(dt.CB_A_crypted, Final, "CB_A " + Oper.ByteArrayToInt(build(dt.CB_A)), Final.Length, dt.CB_A_crypted.Length);
                }
                else
                {
                    Final = addtoflash(dt.CB_A, Final, "CB_A " + Oper.ByteArrayToInt(build(dt.CB_A)), Final.Length, dt.CB_A.Length);
                }
                Final = addtoflash(dt.CB_B, Final, "CB_B " + Oper.ByteArrayToInt(build(dt.CB_B)), Final.Length, dt.CB_B.Length);
            }
            else
            {
                Final = addtoflash(dt.CB_A, Final, "CB_A " + Oper.ByteArrayToInt(build(dt.CB_A)), Final.Length, dt.CB_A.Length);
            }
            dt.CB_A = null; dt.CB_B = null; dt.CB_A_crypted = null;
            ///
            Final = addtoflash(dt.CD, Final, "CD " + Oper.ByteArrayToInt(build(dt.CD)), Final.Length, dt.CD.Length);
            dt.CD = null;
            Final = padto_v2(Final, XELL_BASE_FLASH);
            ///
            Final   = addtoflash(Oper.returnportion(ref newXell, 0, 256 * 1024), Final, "Xell (backup)", Final.Length, 256 * 1024);
            Final   = addtoflash(Oper.returnportion(ref newXell, 256 * 1024, newXell.Length - (256 * 1024)), Final, "Xell (main)", Final.Length, newXell.Length - (256 * 1024));
            newXell = null;
            ///
            if (variables.extractfiles || variables.debugme)
            {
                Oper.savefile(Final, Path.Combine(outputfolder, "image_no.ecc"));
            }

            if (hasecc)
            {
                Console.Write(" * Encoding ECC...");
                Final = Nand.Nand.addecc_v2(Final, true, 0, layout);
            }
            else
            {
                Console.WriteLine("NOT adding Spare Data");
            }

            Console.WriteLine("Done!");
            ///
            Oper.savefile(Final, Path.Combine(outputfolder, "image_00000000.ecc"));
            DirectoryInfo dinfo = new DirectoryInfo(outputfolder);

            Console.WriteLine("------------- Written into {0}\n", Path.Combine(dinfo.Name, "image_00000000.ecc"));
            pb.Value = pb.Maximum;
            return(1);
        }