private static HierarchicalDuplexStorage InitDuplexStorage(IStorage baseStorage, Header header) { FsLayout layout = header.Layout; var duplexLayers = new DuplexFsLayerInfo[3]; duplexLayers[0] = new DuplexFsLayerInfo { DataA = header.DuplexMasterBitmapA, DataB = header.DuplexMasterBitmapB, Info = header.Duplex.Layers[0] }; duplexLayers[1] = new DuplexFsLayerInfo { DataA = baseStorage.Slice(layout.DuplexL1OffsetA, layout.DuplexL1Size), DataB = baseStorage.Slice(layout.DuplexL1OffsetB, layout.DuplexL1Size), Info = header.Duplex.Layers[1] }; duplexLayers[2] = new DuplexFsLayerInfo { DataA = baseStorage.Slice(layout.DuplexDataOffsetA, layout.DuplexDataSize), DataB = baseStorage.Slice(layout.DuplexDataOffsetB, layout.DuplexDataSize), Info = header.Duplex.Layers[2] }; return(new HierarchicalDuplexStorage(duplexLayers, layout.DuplexIndex == 1)); }
public Header(IStorage storage, KeySet keySet) { MainStorage = storage; MainHeader = MainStorage.Slice(0x100, 0x200); DuplexHeader = MainStorage.Slice(0x300, 0x44); DataIvfcHeader = MainStorage.Slice(0x344, 0xC0); JournalHeader = MainStorage.Slice(0x408, 0x200); SaveHeader = MainStorage.Slice(0x608, 0x48); MainRemapHeader = MainStorage.Slice(0x650, 0x40); MetaDataRemapHeader = MainStorage.Slice(0x690, 0x40); ExtraDataStorage = MainStorage.Slice(0x6D8, 0x400); FatIvfcHeader = MainStorage.Slice(0xAD8, 0xC0); Layout = new FsLayout(MainHeader); DuplexMasterBitmapA = MainStorage.Slice(Layout.DuplexMasterOffsetA, Layout.DuplexMasterSize); DuplexMasterBitmapB = MainStorage.Slice(Layout.DuplexMasterOffsetB, Layout.DuplexMasterSize); DataIvfcMaster = MainStorage.Slice(Layout.IvfcMasterHashOffsetA, Layout.IvfcMasterHashSize); FatIvfcMaster = MainStorage.Slice(Layout.FatIvfcMasterHashA, Layout.IvfcMasterHashSize); var reader = new BinaryReader(storage.AsStream()); reader.BaseStream.Position = 0; Data = reader.ReadBytes(0x4000); reader.BaseStream.Position = 0; Cmac = reader.ReadBytes(0x10); reader.BaseStream.Position = 0x100; reader.BaseStream.Position = 0x300; Duplex = new DuplexHeader(reader); reader.BaseStream.Position = 0x6D8; ExtraData = new ExtraData(reader); Ivfc = new IvfcHeader(DataIvfcHeader) { NumLevels = 5 }; if (Layout.Version >= 0x50000) { FatIvfc = new IvfcHeader(FatIvfcHeader) { NumLevels = 4 }; } MasterHash = storage.Slice(Layout.IvfcMasterHashOffsetA, Layout.IvfcMasterHashSize); Span <byte> actualHeaderHash = stackalloc byte[Sha256.DigestSize]; Sha256.GenerateSha256Hash(Data.AsSpan(0x300, 0x3d00), actualHeaderHash); HeaderHashValidity = Utilities.SpansEqual(Layout.Hash, actualHeaderHash) ? Validity.Valid : Validity.Invalid; SignatureValidity = ValidateSignature(keySet); }
public Header(IStorage storage, Keyset keyset) { MainStorage = storage; MainHeader = MainStorage.Slice(0x100, 0x200); DuplexHeader = MainStorage.Slice(0x300, 0x44); DataIvfcHeader = MainStorage.Slice(0x344, 0xC0); JournalHeader = MainStorage.Slice(0x408, 0x200); SaveHeader = MainStorage.Slice(0x608, 0x48); MainRemapHeader = MainStorage.Slice(0x650, 0x40); MetaDataRemapHeader = MainStorage.Slice(0x690, 0x40); ExtraDataStorage = MainStorage.Slice(0x6D8, 0x400); FatIvfcHeader = MainStorage.Slice(0xAD8, 0xC0); Layout = new FsLayout(MainHeader); DuplexMasterBitmapA = MainStorage.Slice(Layout.DuplexMasterOffsetA, Layout.DuplexMasterSize); DuplexMasterBitmapB = MainStorage.Slice(Layout.DuplexMasterOffsetB, Layout.DuplexMasterSize); DataIvfcMaster = MainStorage.Slice(Layout.IvfcMasterHashOffsetA, Layout.IvfcMasterHashSize); FatIvfcMaster = MainStorage.Slice(Layout.FatIvfcMasterHashA, Layout.IvfcMasterHashSize); var reader = new BinaryReader(storage.AsStream()); reader.BaseStream.Position = 0; Data = reader.ReadBytes(0x4000); reader.BaseStream.Position = 0; Cmac = reader.ReadBytes(0x10); reader.BaseStream.Position = 0x100; reader.BaseStream.Position = 0x300; Duplex = new DuplexHeader(reader); reader.BaseStream.Position = 0x6D8; ExtraData = new ExtraData(reader); Ivfc = new IvfcHeader(DataIvfcHeader) { NumLevels = 5 }; if (Layout.Version >= 0x50000) { FatIvfc = new IvfcHeader(FatIvfcHeader) { NumLevels = 4 }; } MasterHash = storage.Slice(Layout.IvfcMasterHashOffsetA, Layout.IvfcMasterHashSize); HeaderHashValidity = Crypto.CheckMemoryHashTable(Data, Layout.Hash, 0x300, 0x3d00); SignatureValidity = ValidateSignature(keyset); }
public SaveDataFileSystem(Keyset keyset, IStorage storage, IntegrityCheckLevel integrityCheckLevel, bool leaveOpen) { BaseStorage = storage; LeaveOpen = leaveOpen; Keyset = keyset; var headerA = new Header(BaseStorage, keyset); var headerB = new Header(BaseStorage.Slice(0x4000), keyset); if (headerA.HeaderHashValidity == Validity.Valid) { IsFirstHeaderInUse = true; } else if (headerB.HeaderHashValidity == Validity.Valid) { IsFirstHeaderInUse = false; } else { ThrowHelper.ThrowResult(ResultFs.InvalidSaveDataHeader, "Savedata header is not valid."); } Header = IsFirstHeaderInUse ? headerA : headerB; FsLayout layout = Header.Layout; IStorage dataRemapBase = BaseStorage.Slice(layout.FileMapDataOffset, layout.FileMapDataSize); IStorage dataRemapEntries = BaseStorage.Slice(layout.FileMapEntryOffset, layout.FileMapEntrySize); IStorage metadataRemapEntries = BaseStorage.Slice(layout.MetaMapEntryOffset, layout.MetaMapEntrySize); DataRemapStorage = new RemapStorage(dataRemapBase, Header.MainRemapHeader, dataRemapEntries, leaveOpen); DuplexStorage = InitDuplexStorage(DataRemapStorage, Header); MetaRemapStorage = new RemapStorage(DuplexStorage, Header.MetaDataRemapHeader, metadataRemapEntries, leaveOpen); var journalMapInfo = new JournalMapParams { MapStorage = MetaRemapStorage.Slice(layout.JournalMapTableOffset, layout.JournalMapTableSize), PhysicalBlockBitmap = MetaRemapStorage.Slice(layout.JournalPhysicalBitmapOffset, layout.JournalPhysicalBitmapSize), VirtualBlockBitmap = MetaRemapStorage.Slice(layout.JournalVirtualBitmapOffset, layout.JournalVirtualBitmapSize), FreeBlockBitmap = MetaRemapStorage.Slice(layout.JournalFreeBitmapOffset, layout.JournalFreeBitmapSize), }; IStorage journalData = DataRemapStorage.Slice(layout.JournalDataOffset, layout.JournalDataSizeB + layout.JournalSize); JournalStorage = new JournalStorage(journalData, Header.JournalHeader, journalMapInfo, leaveOpen); CoreDataIvfcStorage = InitJournalIvfcStorage(integrityCheckLevel); IStorage fatStorage = MetaRemapStorage.Slice(layout.FatOffset, layout.FatSize); if (Header.Layout.Version >= 0x50000) { FatIvfcStorage = InitFatIvfcStorage(integrityCheckLevel); fatStorage = FatIvfcStorage; } SaveDataFileSystemCore = new SaveDataFileSystemCore(CoreDataIvfcStorage, fatStorage, Header.SaveHeader); }