This commit is contained in:
Alex Barney 2020-03-18 00:07:33 -07:00
parent d3df3e86fb
commit 7b24f7c79f
3 changed files with 77 additions and 38 deletions

View file

@ -43,27 +43,27 @@ namespace LibHac.Es
public enum SignatureType public enum SignatureType
{ {
Rsa4096Sha1 = 0x10000, Rsa4096Sha1 = 0x10000,
Rsa2048Sha1, Rsa2048Sha1 = 0x10001,
EcdsaSha1, EcdsaSha1 = 0x10002,
Rsa4096Sha256, Rsa4096Sha256 = 0x10003,
Rsa2048Sha256, Rsa2048Sha256 = 0x10004,
EcdsaSha256 EcdsaSha256 = 0x10005
} }
public enum TitleKeyType : byte public enum TitleKeyType : byte
{ {
Common, Common = 0,
Personalized Personalized = 1
} }
public enum LicenseType : byte public enum LicenseType : byte
{ {
Permanent, Permanent = 0,
Demo, Demo = 1,
Trial, Trial = 2,
Rental, Rental = 3,
Subscription, Subscription = 4,
Service Service = 5
} }
[Flags] [Flags]

View file

@ -1,6 +1,7 @@
using LibHac.Common; using LibHac.Common;
using LibHac.Fs; using LibHac.Fs;
using LibHac.FsSystem; using LibHac.FsSystem;
using LibHac.FsSystem.Detail;
namespace LibHac namespace LibHac
{ {
@ -11,6 +12,7 @@ namespace LibHac
private IStorage BaseStorage { get; } private IStorage BaseStorage { get; }
private object InitLocker { get; } = new object(); private object InitLocker { get; } = new object();
private XciPartition RootPartition { get; set; } private XciPartition RootPartition { get; set; }
private IFileSystem RootPartition2 { get; set; }
public Xci(Keyset keyset, IStorage storage) public Xci(Keyset keyset, IStorage storage)
{ {
@ -25,7 +27,7 @@ namespace LibHac
return GetRootPartition().FileExists(type.GetFileName()); return GetRootPartition().FileExists(type.GetFileName());
} }
public XciPartition OpenPartition(XciPartitionType type) public XciPartition OpenPartitionO(XciPartitionType type)
{ {
XciPartition root = GetRootPartition(); XciPartition root = GetRootPartition();
if (type == XciPartitionType.Root) return root; if (type == XciPartitionType.Root) return root;
@ -34,6 +36,19 @@ namespace LibHac
return new XciPartition(partitionFile.AsStorage()); return new XciPartition(partitionFile.AsStorage());
} }
public IFileSystem OpenPartition(XciPartitionType type)
{
IFileSystem root = GetRootPartition2();
if (type == XciPartitionType.Root) return root;
root.OpenFile(out IFile partitionFile, type.GetFileName().ToU8Span(), OpenMode.Read).ThrowIfFailure();
var partitionFs = new PartitionFileSystemCore<HashedEntry>();
partitionFs.Initialize(partitionFile.AsStorage()).ThrowIfFailure();
return partitionFs;
}
private XciPartition GetRootPartition() private XciPartition GetRootPartition()
{ {
if (RootPartition != null) return RootPartition; if (RootPartition != null) return RootPartition;
@ -43,6 +58,15 @@ namespace LibHac
return RootPartition; return RootPartition;
} }
private IFileSystem GetRootPartition2()
{
if (RootPartition2 != null) return RootPartition2;
InitializeRootPartition2();
return RootPartition2;
}
private void InitializeRootPartition() private void InitializeRootPartition()
{ {
lock (InitLocker) lock (InitLocker)
@ -58,6 +82,21 @@ namespace LibHac
}; };
} }
} }
private void InitializeRootPartition2()
{
lock (InitLocker)
{
if (RootPartition2 != null) return;
IStorage rootStorage = BaseStorage.Slice(Header.RootPartitionOffset);
var partitionFs = new PartitionFileSystemCore<HashedEntry>();
partitionFs.Initialize(rootStorage).ThrowIfFailure();
RootPartition2 = partitionFs;
}
}
} }
public class XciPartition : PartitionFileSystem public class XciPartition : PartitionFileSystem

View file

@ -47,20 +47,20 @@ namespace hactoolnet
if (ctx.Options.OutDir != null) if (ctx.Options.OutDir != null)
{ {
XciPartition root = xci.OpenPartition(XciPartitionType.Root); IFileSystem root = xci.OpenPartition(XciPartitionType.Root);
if (root == null) if (root == null)
{ {
ctx.Logger.LogMessage("Could not find root partition"); ctx.Logger.LogMessage("Could not find root partition");
return; return;
} }
foreach (PartitionFileEntry sub in root.Files) //foreach (PartitionFileEntry sub in root.Files)
{ //{
var subPfs = new PartitionFileSystem(root.OpenFile(sub, OpenMode.Read).AsStorage()); // var subPfs = new PartitionFileSystem(root.OpenFile(sub, OpenMode.Read).AsStorage());
string subDir = Path.Combine(ctx.Options.OutDir, sub.Name); // string subDir = Path.Combine(ctx.Options.OutDir, sub.Name);
subPfs.Extract(subDir, ctx.Logger); // subPfs.Extract(subDir, ctx.Logger);
} //}
} }
if (ctx.Options.ExefsOutDir != null || ctx.Options.ExefsOut != null) if (ctx.Options.ExefsOutDir != null || ctx.Options.ExefsOut != null)
@ -113,7 +113,7 @@ namespace hactoolnet
private static Nca GetXciMainNca(Xci xci, Context ctx) private static Nca GetXciMainNca(Xci xci, Context ctx)
{ {
XciPartition partition = xci.OpenPartition(XciPartitionType.Secure); IFileSystem partition = xci.OpenPartition(XciPartitionType.Secure);
if (partition == null) if (partition == null)
{ {
@ -123,16 +123,16 @@ namespace hactoolnet
Nca mainNca = null; Nca mainNca = null;
foreach (PartitionFileEntry fileEntry in partition.Files.Where(x => x.Name.EndsWith(".nca"))) //foreach (PartitionFileEntry fileEntry in partition.Files.Where(x => x.Name.EndsWith(".nca")))
{ //{
IStorage ncaStorage = partition.OpenFile(fileEntry, OpenMode.Read).AsStorage(); // IStorage ncaStorage = partition.OpenFile(fileEntry, OpenMode.Read).AsStorage();
var nca = new Nca(ctx.Keyset, ncaStorage); // var nca = new Nca(ctx.Keyset, ncaStorage);
if (nca.Header.ContentType == NcaContentType.Program) // if (nca.Header.ContentType == NcaContentType.Program)
{ // {
mainNca = nca; // mainNca = nca;
} // }
} //}
return mainNca; return mainNca;
} }
@ -153,15 +153,15 @@ namespace hactoolnet
PrintItem(sb, colLen, "Cartridge Size:", $"0x{Util.MediaToReal(xci.Header.ValidDataEndPage + 1):x12}"); PrintItem(sb, colLen, "Cartridge Size:", $"0x{Util.MediaToReal(xci.Header.ValidDataEndPage + 1):x12}");
PrintItem(sb, colLen, "Header IV:", xci.Header.AesCbcIv); PrintItem(sb, colLen, "Header IV:", xci.Header.AesCbcIv);
PrintPartition(sb, colLen, xci.OpenPartition(XciPartitionType.Root), XciPartitionType.Root); //PrintPartition(sb, colLen, xci.OpenPartition(XciPartitionType.Root), XciPartitionType.Root);
foreach (XciPartitionType type in Enum.GetValues(typeof(XciPartitionType))) //foreach (XciPartitionType type in Enum.GetValues(typeof(XciPartitionType)))
{ //{
if (type == XciPartitionType.Root || !xci.HasPartition(type)) continue; // if (type == XciPartitionType.Root || !xci.HasPartition(type)) continue;
XciPartition partition = xci.OpenPartition(type); // IFileSystem partition = xci.OpenPartition(type);
PrintPartition(sb, colLen, partition, type); // PrintPartition(sb, colLen, partition, type);
} //}
return sb.ToString(); return sb.ToString();
} }