LibHac/LibHac/Xci.cs
Alex Barney 3d50085e22
Use Storage throughout the library instead of Stream (#18)
*Create an IStorage interface and Storage abstract class to use instead of Stream

* Improve AES-XTS performance by ~16x

* Double AES-CTR performance: 800 MB/s -> 1600 MB/s on a 6700K

* Add AES-XTS tests

* Add AES benchmark and AES-CTR writing

* Add support for a hashed FAT in save files

* Add option to export decrypted NCA

* Allow opening decrypted package1 and package2

* Make sure romfs disposal can cascade all the way down

* Validate NCA, NPDM and package2 signatures
2018-11-18 23:20:34 -05:00

69 lines
2.4 KiB
C#

using System.Collections.Generic;
using System.Linq;
using LibHac.IO;
namespace LibHac
{
public class Xci
{
private const string RootPartitionName = "rootpt";
private const string UpdatePartitionName = "update";
private const string NormalPartitionName = "normal";
private const string SecurePartitionName = "secure";
private const string LogoPartitionName = "logo";
public XciHeader Header { get; }
public XciPartition RootPartition { get; }
public XciPartition UpdatePartition { get; }
public XciPartition NormalPartition { get; }
public XciPartition SecurePartition { get; }
public XciPartition LogoPartition { get; }
public List<XciPartition> Partitions { get; } = new List<XciPartition>();
public Xci(Keyset keyset, IStorage storage)
{
Header = new XciHeader(keyset, storage.AsStream());
IStorage hfs0Stream = storage.Slice(Header.PartitionFsHeaderAddress);
RootPartition = new XciPartition(hfs0Stream)
{
Name = RootPartitionName,
Offset = Header.PartitionFsHeaderAddress,
HashValidity = Header.PartitionFsHeaderValidity
};
Partitions.Add(RootPartition);
foreach (PfsFileEntry file in RootPartition.Files)
{
IStorage partitionStorage = RootPartition.OpenFile(file);
var partition = new XciPartition(partitionStorage)
{
Name = file.Name,
Offset = Header.PartitionFsHeaderAddress + RootPartition.HeaderSize + file.Offset,
HashValidity = file.HashValidity
};
Partitions.Add(partition);
}
UpdatePartition = Partitions.FirstOrDefault(x => x.Name == UpdatePartitionName);
NormalPartition = Partitions.FirstOrDefault(x => x.Name == NormalPartitionName);
SecurePartition = Partitions.FirstOrDefault(x => x.Name == SecurePartitionName);
LogoPartition = Partitions.FirstOrDefault(x => x.Name == LogoPartitionName);
}
}
public class XciPartition : Pfs
{
public string Name { get; internal set; }
public long Offset { get; internal set; }
public Validity HashValidity { get; set; } = Validity.Unchecked;
public XciPartition(IStorage storage) : base(storage) { }
}
}