mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Support hashed partition FS building
This commit is contained in:
parent
468c78aadd
commit
caccc5a677
4 changed files with 64 additions and 7 deletions
src
|
@ -2,6 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace LibHac.IO
|
||||
|
@ -38,7 +39,9 @@ namespace LibHac.IO
|
|||
File = file,
|
||||
Length = file.GetSize(),
|
||||
Offset = CurrentOffset,
|
||||
NameLength = Encoding.UTF8.GetByteCount(filename)
|
||||
NameLength = Encoding.UTF8.GetByteCount(filename),
|
||||
HashOffset = 0,
|
||||
HashLength = 0x200
|
||||
};
|
||||
|
||||
CurrentOffset += entry.Length;
|
||||
|
@ -60,8 +63,10 @@ namespace LibHac.IO
|
|||
|
||||
private byte[] BuildMetaData(PartitionFileSystemType type)
|
||||
{
|
||||
if (type == PartitionFileSystemType.Hashed) CalculateHashes();
|
||||
|
||||
int entryTableSize = Entries.Count * PartitionFileEntry.GetEntrySize(type);
|
||||
int stringTableSize = CalcStringTableSize(HeaderSize + entryTableSize);
|
||||
int stringTableSize = CalcStringTableSize(HeaderSize + entryTableSize, type);
|
||||
int metaDataSize = HeaderSize + entryTableSize + stringTableSize;
|
||||
|
||||
var metaData = new byte[metaDataSize];
|
||||
|
@ -79,7 +84,17 @@ namespace LibHac.IO
|
|||
writer.Write(entry.Offset);
|
||||
writer.Write(entry.Length);
|
||||
writer.Write(stringOffset);
|
||||
writer.Write(0);
|
||||
|
||||
if (type == PartitionFileSystemType.Standard)
|
||||
{
|
||||
writer.Write(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Write(entry.HashLength);
|
||||
writer.Write(entry.HashOffset);
|
||||
writer.Write(entry.Hash);
|
||||
}
|
||||
|
||||
stringOffset += entry.NameLength + 1;
|
||||
}
|
||||
|
@ -92,7 +107,7 @@ namespace LibHac.IO
|
|||
return metaData;
|
||||
}
|
||||
|
||||
private int CalcStringTableSize(int startOffset)
|
||||
private int CalcStringTableSize(int startOffset, PartitionFileSystemType type)
|
||||
{
|
||||
int size = 0;
|
||||
|
||||
|
@ -101,7 +116,7 @@ namespace LibHac.IO
|
|||
size += entry.NameLength + 1;
|
||||
}
|
||||
|
||||
int endOffset = Util.AlignUp(startOffset + size, MetaDataAlignment);
|
||||
int endOffset = Util.AlignUp(startOffset + size, GetMetaDataAlignment(type));
|
||||
return endOffset - startOffset;
|
||||
}
|
||||
|
||||
|
@ -115,6 +130,32 @@ namespace LibHac.IO
|
|||
}
|
||||
}
|
||||
|
||||
private int GetMetaDataAlignment(PartitionFileSystemType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case PartitionFileSystemType.Standard: return 0x20;
|
||||
case PartitionFileSystemType.Hashed: return 0x200;
|
||||
default: throw new ArgumentOutOfRangeException(nameof(type), type, null);
|
||||
}
|
||||
}
|
||||
|
||||
private void CalculateHashes()
|
||||
{
|
||||
using (SHA256 sha = SHA256.Create())
|
||||
{
|
||||
foreach (Entry entry in Entries)
|
||||
{
|
||||
if (entry.HashLength == 0) entry.HashLength = 0x200;
|
||||
|
||||
var data = new byte[entry.HashLength];
|
||||
entry.File.Read(data, entry.HashOffset);
|
||||
|
||||
entry.Hash = sha.ComputeHash(data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class Entry
|
||||
{
|
||||
public string Name;
|
||||
|
@ -122,6 +163,10 @@ namespace LibHac.IO
|
|||
public long Length;
|
||||
public long Offset;
|
||||
public int NameLength;
|
||||
|
||||
public int HashLength;
|
||||
public long HashOffset;
|
||||
public byte[] Hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ namespace hactoolnet
|
|||
new CliOption("listfiles", 0, (o, a) => o.ListFiles = true),
|
||||
new CliOption("sign", 0, (o, a) => o.SignSave = true),
|
||||
new CliOption("readbench", 0, (o, a) => o.ReadBench = true),
|
||||
new CliOption("hashedfs", 0, (o, a) => o.BuildHfs = true),
|
||||
new CliOption("title", 1, (o, a) => o.TitleId = ParseTitleId(a[0])),
|
||||
new CliOption("bench", 1, (o, a) => o.BenchType = a[0]),
|
||||
|
||||
|
@ -162,7 +163,7 @@ namespace hactoolnet
|
|||
sb.AppendLine(" -y, --verify Verify all hashes in the input file.");
|
||||
sb.AppendLine(" -h, --enablehash Enable hash checks when reading the input file.");
|
||||
sb.AppendLine(" -k, --keyset Load keys from an external file.");
|
||||
sb.AppendLine(" -t, --intype=type Specify input file type [nca, xci, romfs, pk11, pk21, ini1, kip1, switchfs, save, ndv0, keygen, romfsbuild]");
|
||||
sb.AppendLine(" -t, --intype=type Specify input file type [nca, xci, romfs, pfs0, pk11, pk21, ini1, kip1, switchfs, save, ndv0, keygen, romfsbuild, pfsbuild]");
|
||||
sb.AppendLine(" --titlekeys <file> Load title keys from an external file.");
|
||||
sb.AppendLine("NCA options:");
|
||||
sb.AppendLine(" --plaintext <file> Specify file path for saving a decrypted copy of the NCA.");
|
||||
|
@ -186,6 +187,12 @@ namespace hactoolnet
|
|||
sb.AppendLine("RomFS creation options:");
|
||||
sb.AppendLine(" Input path must be a directory");
|
||||
sb.AppendLine(" --outfile <file> Specify created RomFS file path.");
|
||||
sb.AppendLine("Partition FS options:");
|
||||
sb.AppendLine(" --outdir <dir> Specify extracted FS directory path.");
|
||||
sb.AppendLine("Partition FS creation options:");
|
||||
sb.AppendLine(" Input path must be a directory");
|
||||
sb.AppendLine(" --outfile <file> Specify created Partition FS file path.");
|
||||
sb.AppendLine(" --hashedfs Create a hashed Partition FS (HFS0).");
|
||||
sb.AppendLine("XCI options:");
|
||||
sb.AppendLine(" --rootdir <dir> Specify root XCI directory path.");
|
||||
sb.AppendLine(" --updatedir <dir> Specify update XCI directory path.");
|
||||
|
|
|
@ -44,6 +44,7 @@ namespace hactoolnet
|
|||
public bool ListFiles;
|
||||
public bool SignSave;
|
||||
public bool ReadBench;
|
||||
public bool BuildHfs;
|
||||
public ulong TitleId;
|
||||
public string BenchType;
|
||||
|
||||
|
|
|
@ -37,10 +37,14 @@ namespace hactoolnet
|
|||
return;
|
||||
}
|
||||
|
||||
PartitionFileSystemType type = ctx.Options.BuildHfs
|
||||
? PartitionFileSystemType.Hashed
|
||||
: PartitionFileSystemType.Standard;
|
||||
|
||||
var localFs = new LocalFileSystem(ctx.Options.InFile);
|
||||
|
||||
var builder = new PartitionFileSystemBuilder(localFs);
|
||||
IStorage partitionFs = builder.Build(PartitionFileSystemType.Standard);
|
||||
IStorage partitionFs = builder.Build(type);
|
||||
|
||||
ctx.Logger.LogMessage($"Building Partition FS as {ctx.Options.OutFile}");
|
||||
|
||||
|
|
Loading…
Reference in a new issue