public static void Process(Context ctx) { using (var file = new LocalStorage(ctx.Options.InFile, FileAccess.Read)) { var xci = new Xci(ctx.Keyset, file); ctx.Logger.LogMessage(xci.Print()); if (ctx.Options.RootDir != null) { xci.OpenPartition(XciPartitionType.Root).Extract(ctx.Options.RootDir, ctx.Logger); } if (ctx.Options.UpdateDir != null && xci.HasPartition(XciPartitionType.Update)) { xci.OpenPartition(XciPartitionType.Update).Extract(ctx.Options.UpdateDir, ctx.Logger); } if (ctx.Options.NormalDir != null && xci.HasPartition(XciPartitionType.Normal)) { xci.OpenPartition(XciPartitionType.Normal).Extract(ctx.Options.NormalDir, ctx.Logger); } if (ctx.Options.SecureDir != null && xci.HasPartition(XciPartitionType.Secure)) { xci.OpenPartition(XciPartitionType.Secure).Extract(ctx.Options.SecureDir, ctx.Logger); } if (ctx.Options.LogoDir != null && xci.HasPartition(XciPartitionType.Logo)) { xci.OpenPartition(XciPartitionType.Logo).Extract(ctx.Options.LogoDir, ctx.Logger); } if (ctx.Options.OutDir != null) { XciPartition root = xci.OpenPartition(XciPartitionType.Root); if (root == null) { ctx.Logger.LogMessage("Could not find root partition"); return; } foreach (PartitionFileEntry sub in root.Files) { var subPfs = new PartitionFileSystem(root.OpenFile(sub, OpenMode.Read).AsStorage()); string subDir = Path.Combine(ctx.Options.OutDir, sub.Name); subPfs.Extract(subDir, ctx.Logger); } } if (ctx.Options.ExefsOutDir != null || ctx.Options.ExefsOut != null) { Nca mainNca = GetXciMainNca(xci, ctx); if (mainNca == null) { ctx.Logger.LogMessage("Could not find Program NCA"); return; } if (!mainNca.SectionExists(NcaSectionType.Code)) { ctx.Logger.LogMessage("NCA has no ExeFS section"); return; } if (ctx.Options.ExefsOutDir != null) { mainNca.ExtractSection(NcaSectionType.Code, ctx.Options.ExefsOutDir, ctx.Options.IntegrityLevel, ctx.Logger); } if (ctx.Options.ExefsOut != null) { mainNca.ExportSection(NcaSectionType.Code, ctx.Options.ExefsOut, ctx.Options.Raw, ctx.Options.IntegrityLevel, ctx.Logger); } } if (ctx.Options.RomfsOutDir != null || ctx.Options.RomfsOut != null) { Nca mainNca = GetXciMainNca(xci, ctx); if (mainNca == null) { ctx.Logger.LogMessage("Could not find Program NCA"); return; } if (!mainNca.SectionExists(NcaSectionType.Data)) { ctx.Logger.LogMessage("NCA has no RomFS section"); return; } ProcessRomfs.Process(ctx, mainNca.OpenStorage(NcaSectionType.Data, ctx.Options.IntegrityLevel, false)); } } }
private static bool Run(string[] args) { Console.OutputEncoding = Encoding.UTF8; var ctx = new Context(); ctx.Options = CliParser.Parse(args); if (ctx.Options == null) { return(false); } StreamWriter logWriter = null; ResultLogger resultLogger = null; try { using (var logger = new ProgressBar()) { ctx.Logger = logger; ctx.FsClient = new FileSystemClient(new StopWatchTimeSpanGenerator()); if (ctx.Options.AccessLog != null) { logWriter = new StreamWriter(ctx.Options.AccessLog); var accessLog = new TextWriterAccessLog(logWriter); ctx.FsClient.SetAccessLogTarget(AccessLogTarget.All); ctx.FsClient.SetGlobalAccessLogMode(GlobalAccessLogMode.Log); ctx.FsClient.SetAccessLogObject(accessLog); } if (ctx.Options.ResultLog != null) { resultLogger = new ResultLogger(new StreamWriter(ctx.Options.ResultLog), printStackTrace: true, printSourceInfo: true, combineRepeats: true); Result.SetLogger(resultLogger); } OpenKeySet(ctx); if (ctx.Options.RunCustom) { CustomTask(ctx); return(true); } RunTask(ctx); } } finally { logWriter?.Dispose(); if (resultLogger != null) { Result.SetLogger(null); resultLogger.Dispose(); } } return(true); }
private static void OpenKeySet(Context ctx) { #if CORERT_NO_REFLECTION string home = HomeFolder.GetFolderPath(Environment.SpecialFolder.UserProfile); #else string home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); #endif string homeTitleKeyFile = Path.Combine(home, ".switch", "title.keys"); string homeConsoleKeyFile = Path.Combine(home, ".switch", "console.keys"); string prodKeyFile = Path.Combine(home, ".switch", "prod.keys"); string devKeyFile = Path.Combine(home, ".switch", "dev.keys"); string titleKeyFile = ctx.Options.TitleKeyFile; string consoleKeyFile = ctx.Options.ConsoleKeyFile; // Check if the files from the command line exist if (titleKeyFile != null && !File.Exists(titleKeyFile)) { titleKeyFile = null; } if (consoleKeyFile != null && !File.Exists(consoleKeyFile)) { consoleKeyFile = null; } if (!File.Exists(prodKeyFile)) { prodKeyFile = null; } if (!File.Exists(devKeyFile)) { devKeyFile = null; } // Check the home directory if no existing key files were specified if (consoleKeyFile == null && File.Exists(homeConsoleKeyFile)) { consoleKeyFile = homeConsoleKeyFile; } if (titleKeyFile == null && File.Exists(homeTitleKeyFile)) { titleKeyFile = homeTitleKeyFile; } var keySet = KeySet.CreateDefaultKeySet(); // If the user specifies a key file then only load that file into the mode they specified, // otherwise load both prod.keys and dev.keys. // Todo: Should we add a way that both dev-only key files and mixed prod/dev key files // can both be loaded when specifying a key file in dev mode? if (ctx.Options.Keyfile != null && File.Exists(ctx.Options.Keyfile)) { keySet.SetMode(ctx.Options.KeyMode); ExternalKeyReader.ReadKeyFile(keySet, ctx.Options.Keyfile, titleKeyFile, consoleKeyFile, ctx.Logger); } else { ExternalKeyReader.ReadKeyFile(keySet, prodKeyFile, devKeyFile, titleKeyFile, consoleKeyFile, ctx.Logger); } keySet.SetMode(ctx.Options.KeyMode); if (ctx.Options.SdSeed != null) { keySet.SetSdSeed(ctx.Options.SdSeed.ToBytes()); } ctx.KeySet = keySet; }
// For running random stuff // ReSharper disable once UnusedParameter.Local private static void CustomTask(Context ctx) { }
private static void RunTask(Context ctx) { switch (ctx.Options.InFileType) { case FileType.Nca: ProcessNca.Process(ctx); break; case FileType.Pfs0: case FileType.Nsp: ProcessPfs.Process(ctx); break; case FileType.PfsBuild: ProcessFsBuild.ProcessPartitionFs(ctx); break; case FileType.Romfs: ProcessRomfs.Process(ctx); break; case FileType.RomfsBuild: ProcessFsBuild.ProcessRomFs(ctx); break; case FileType.Nax0: ProcessNax0.Process(ctx); break; case FileType.SwitchFs: ProcessSwitchFs.Process(ctx); break; case FileType.Save: ProcessSave.Process(ctx); break; case FileType.Xci: ProcessXci.Process(ctx); break; case FileType.Keygen: ProcessKeygen(ctx); break; case FileType.Pk11: ProcessPackage.ProcessPk11(ctx); break; case FileType.Pk21: ProcessPackage.ProcessPk21(ctx); break; case FileType.Kip1: ProcessKip.ProcessKip1(ctx); break; case FileType.Ini1: ProcessKip.ProcessIni1(ctx); break; case FileType.Ndv0: ProcessDelta.Process(ctx); break; case FileType.Bench: ProcessBench.Process(ctx); break; default: throw new ArgumentOutOfRangeException(); } }