diff --git a/Source/Core/Core/Boot/Boot.cpp b/Source/Core/Core/Boot/Boot.cpp index aeda7d9aef..d7f84b3ec6 100644 --- a/Source/Core/Core/Boot/Boot.cpp +++ b/Source/Core/Core/Boot/Boot.cpp @@ -60,17 +60,18 @@ void CBoot::Load_FST(bool _bIsWii) if (_bIsWii) shift = 2; - u32 fstOffset = volume.Read32(0x0424, _bIsWii) << shift; - u32 fstSize = volume.Read32(0x0428, _bIsWii) << shift; - u32 maxFstSize = volume.Read32(0x042c, _bIsWii) << shift; + u32 fst_offset, fst_size, max_fst_size; + volume.ReadSwapped(0x0424, &fst_offset, _bIsWii); + volume.ReadSwapped(0x0428, &fst_size, _bIsWii); + volume.ReadSwapped(0x042c, &max_fst_size, _bIsWii); - u32 arenaHigh = ROUND_DOWN(0x817FFFFF - maxFstSize, 0x20); - Memory::Write_U32(arenaHigh, 0x00000034); + u32 arena_high = ROUND_DOWN(0x817FFFFF - (max_fst_size << shift), 0x20); + Memory::Write_U32(arena_high, 0x00000034); // load FST - DVDRead(fstOffset, arenaHigh, fstSize, _bIsWii); - Memory::Write_U32(arenaHigh, 0x00000038); - Memory::Write_U32(maxFstSize, 0x0000003c); + DVDRead(fst_offset << shift, arena_high, fst_size << shift, _bIsWii); + Memory::Write_U32(arena_high, 0x00000038); + Memory::Write_U32(max_fst_size << shift, 0x0000003c); } void CBoot::UpdateDebugger_MapLoaded() diff --git a/Source/Core/Core/Boot/Boot_BS2Emu.cpp b/Source/Core/Core/Boot/Boot_BS2Emu.cpp index c8f6f0d270..4d81c6db32 100644 --- a/Source/Core/Core/Boot/Boot_BS2Emu.cpp +++ b/Source/Core/Core/Boot/Boot_BS2Emu.cpp @@ -90,15 +90,18 @@ bool CBoot::EmulatedBS2_GC(bool skipAppLoader) // Load Apploader to Memory - The apploader is hardcoded to begin at 0x2440 on the disc, // but the size can differ between discs. Compare with YAGCD chap 13. const DiscIO::IVolume& volume = DVDInterface::GetVolume(); - u32 iAppLoaderOffset = 0x2440; - u32 iAppLoaderEntry = volume.Read32(iAppLoaderOffset + 0x10, false); - u32 iAppLoaderSize = volume.Read32(iAppLoaderOffset + 0x14, false) + volume.Read32(iAppLoaderOffset + 0x18, false); - if ((iAppLoaderEntry == (u32)-1) || (iAppLoaderSize == (u32)-1) || skipAppLoader) + const u32 apploader_offset = 0x2440; + u32 apploader_entry, apploader_size, apploader_trailer; + if (skipAppLoader || + !volume.ReadSwapped(apploader_offset + 0x10, &apploader_entry, false) || + !volume.ReadSwapped(apploader_offset + 0x14, &apploader_size, false) || + !volume.ReadSwapped(apploader_offset + 0x18, &apploader_trailer, false) || + apploader_entry == (u32)-1 || apploader_size + apploader_trailer == (u32)-1) { INFO_LOG(BOOT, "GC BS2: Not running apploader!"); return false; } - DVDRead(iAppLoaderOffset + 0x20, 0x01200000, iAppLoaderSize, false); + DVDRead(apploader_offset + 0x20, 0x01200000, apploader_size + apploader_trailer, false); // Setup pointers like real BS2 does if (SConfig::GetInstance().bNTSC) @@ -122,7 +125,7 @@ bool CBoot::EmulatedBS2_GC(bool skipAppLoader) PowerPC::ppcState.gpr[3] = iAppLoaderFuncAddr + 0; PowerPC::ppcState.gpr[4] = iAppLoaderFuncAddr + 4; PowerPC::ppcState.gpr[5] = iAppLoaderFuncAddr + 8; - RunFunction(iAppLoaderEntry); + RunFunction(apploader_entry); u32 iAppLoaderInit = PowerPC::Read_U32(iAppLoaderFuncAddr + 0); u32 iAppLoaderMain = PowerPC::Read_U32(iAppLoaderFuncAddr + 4); u32 iAppLoaderClose = PowerPC::Read_U32(iAppLoaderFuncAddr + 8); @@ -365,18 +368,19 @@ bool CBoot::EmulatedBS2_Wii() PowerPC::ppcState.gpr[1] = 0x816ffff0; // StackPointer - u32 iAppLoaderOffset = 0x2440; // 0x1c40; + const u32 apploader_offset = 0x2440; // 0x1c40; // Load Apploader to Memory const DiscIO::IVolume& volume = DVDInterface::GetVolume(); - u32 iAppLoaderEntry = volume.Read32(iAppLoaderOffset + 0x10, true); - u32 iAppLoaderSize = volume.Read32(iAppLoaderOffset + 0x14, true); - if ((iAppLoaderEntry == (u32)-1) || (iAppLoaderSize == (u32)-1)) + u32 apploader_entry, apploader_size; + if (!volume.ReadSwapped(apploader_offset + 0x10, &apploader_entry, true) || + !volume.ReadSwapped(apploader_offset + 0x14, &apploader_size, true) || + apploader_entry == (u32)-1 || apploader_size == (u32)-1) { ERROR_LOG(BOOT, "Invalid apploader. Probably your image is corrupted."); return false; } - DVDRead(iAppLoaderOffset + 0x20, 0x01200000, iAppLoaderSize, true); + DVDRead(apploader_offset + 0x20, 0x01200000, apploader_size, true); //call iAppLoaderEntry DEBUG_LOG(BOOT, "Call iAppLoaderEntry"); @@ -385,7 +389,7 @@ bool CBoot::EmulatedBS2_Wii() PowerPC::ppcState.gpr[3] = iAppLoaderFuncAddr + 0; PowerPC::ppcState.gpr[4] = iAppLoaderFuncAddr + 4; PowerPC::ppcState.gpr[5] = iAppLoaderFuncAddr + 8; - RunFunction(iAppLoaderEntry); + RunFunction(apploader_entry); u32 iAppLoaderInit = PowerPC::Read_U32(iAppLoaderFuncAddr + 0); u32 iAppLoaderMain = PowerPC::Read_U32(iAppLoaderFuncAddr + 4); u32 iAppLoaderClose = PowerPC::Read_U32(iAppLoaderFuncAddr + 8); diff --git a/Source/Core/DiscIO/Blob.h b/Source/Core/DiscIO/Blob.h index 29a8ced696..229b2fb3bd 100644 --- a/Source/Core/DiscIO/Blob.h +++ b/Source/Core/DiscIO/Blob.h @@ -17,6 +17,7 @@ #include #include #include +#include "Common/CommonFuncs.h" #include "Common/CommonTypes.h" namespace DiscIO @@ -77,6 +78,25 @@ private: std::array m_cache_tags; }; +class CBlobBigEndianReader +{ +public: + CBlobBigEndianReader(IBlobReader& reader) : m_reader(reader) {} + + template + bool ReadSwapped(u64 offset, T* buffer) const + { + T temp; + if (!m_reader.Read(offset, sizeof(T), reinterpret_cast(&temp))) + return false; + *buffer = Common::FromBigEndian(temp); + return true; + } + +private: + IBlobReader& m_reader; +}; + // Factory function - examines the path to choose the right type of IBlobReader, and returns one. std::unique_ptr CreateBlobReader(const std::string& filename); diff --git a/Source/Core/DiscIO/DiscScrubber.cpp b/Source/Core/DiscIO/DiscScrubber.cpp index 52b18e8286..b8aac8b091 100644 --- a/Source/Core/DiscIO/DiscScrubber.cpp +++ b/Source/Core/DiscIO/DiscScrubber.cpp @@ -74,8 +74,8 @@ static SPartitionGroup PartitionGroup[4]; void MarkAsUsed(u64 _Offset, u64 _Size); void MarkAsUsedE(u64 _PartitionDataOffset, u64 _Offset, u64 _Size); -void ReadFromVolume(u64 _Offset, u32& _Buffer, bool _Decrypt); -void ReadFromVolume(u64 _Offset, u64& _Buffer, bool _Decrypt); +bool ReadFromVolume(u64 _Offset, u32& _Buffer, bool _Decrypt); +bool ReadFromVolume(u64 _Offset, u64& _Buffer, bool _Decrypt); bool ParseDisc(); bool ParsePartitionData(SPartition& _rPartition); @@ -192,16 +192,18 @@ void MarkAsUsedE(u64 _PartitionDataOffset, u64 _Offset, u64 _Size) } // Helper functions for reading the BE volume -void ReadFromVolume(u64 _Offset, u32& _Buffer, bool _Decrypt) +bool ReadFromVolume(u64 _Offset, u32& _Buffer, bool _Decrypt) { - s_disc->Read(_Offset, sizeof(u32), (u8*)&_Buffer, _Decrypt); - _Buffer = Common::swap32(_Buffer); + return s_disc->ReadSwapped(_Offset, &_Buffer, _Decrypt); } -void ReadFromVolume(u64 _Offset, u64& _Buffer, bool _Decrypt) + +bool ReadFromVolume(u64 _Offset, u64& _Buffer, bool _Decrypt) { - s_disc->Read(_Offset, sizeof(u32), (u8*)&_Buffer, _Decrypt); - _Buffer = Common::swap32((u32)_Buffer); - _Buffer <<= 2; + u32 temp_buffer; + if (!s_disc->ReadSwapped(_Offset, &temp_buffer, _Decrypt)) + return false; + _Buffer = static_cast(temp_buffer) << 2; + return true; } bool ParseDisc() @@ -211,8 +213,9 @@ bool ParseDisc() for (int x = 0; x < 4; x++) { - ReadFromVolume(0x40000 + (x * 8) + 0, PartitionGroup[x].numPartitions, false); - ReadFromVolume(0x40000 + (x * 8) + 4, PartitionGroup[x].PartitionsOffset, false); + if (!ReadFromVolume(0x40000 + (x * 8) + 0, PartitionGroup[x].numPartitions, false) || + !ReadFromVolume(0x40000 + (x * 8) + 4, PartitionGroup[x].PartitionsOffset, false)) + return false; // Read all partitions for (u32 i = 0; i < PartitionGroup[x].numPartitions; i++) @@ -222,16 +225,16 @@ bool ParseDisc() Partition.GroupNumber = x; Partition.Number = i; - ReadFromVolume(PartitionGroup[x].PartitionsOffset + (i * 8) + 0, Partition.Offset, false); - ReadFromVolume(PartitionGroup[x].PartitionsOffset + (i * 8) + 4, Partition.Type, false); - - ReadFromVolume(Partition.Offset + 0x2a4, Partition.Header.TMDSize, false); - ReadFromVolume(Partition.Offset + 0x2a8, Partition.Header.TMDOffset, false); - ReadFromVolume(Partition.Offset + 0x2ac, Partition.Header.CertChainSize, false); - ReadFromVolume(Partition.Offset + 0x2b0, Partition.Header.CertChainOffset, false); - ReadFromVolume(Partition.Offset + 0x2b4, Partition.Header.H3Offset, false); - ReadFromVolume(Partition.Offset + 0x2b8, Partition.Header.DataOffset, false); - ReadFromVolume(Partition.Offset + 0x2bc, Partition.Header.DataSize, false); + if (!ReadFromVolume(PartitionGroup[x].PartitionsOffset + (i * 8) + 0, Partition.Offset, false) || + !ReadFromVolume(PartitionGroup[x].PartitionsOffset + (i * 8) + 4, Partition.Type, false) || + !ReadFromVolume(Partition.Offset + 0x2a4, Partition.Header.TMDSize, false) || + !ReadFromVolume(Partition.Offset + 0x2a8, Partition.Header.TMDOffset, false) || + !ReadFromVolume(Partition.Offset + 0x2ac, Partition.Header.CertChainSize, false) || + !ReadFromVolume(Partition.Offset + 0x2b0, Partition.Header.CertChainOffset, false) || + !ReadFromVolume(Partition.Offset + 0x2b4, Partition.Header.H3Offset, false) || + !ReadFromVolume(Partition.Offset + 0x2b8, Partition.Header.DataOffset, false) || + !ReadFromVolume(Partition.Offset + 0x2bc, Partition.Header.DataSize, false)) + return false; PartitionGroup[x].PartitionsVec.push_back(Partition); } @@ -286,8 +289,8 @@ bool ParsePartitionData(SPartition& partition) { // Mark things as used which are not in the filesystem // Header, Header Information, Apploader - ReadFromVolume(0x2440 + 0x14, partition.Header.ApploaderSize, true); - ReadFromVolume(0x2440 + 0x18, partition.Header.ApploaderTrailerSize, true); + parsed_ok = parsed_ok && ReadFromVolume(0x2440 + 0x14, partition.Header.ApploaderSize, true); + parsed_ok = parsed_ok && ReadFromVolume(0x2440 + 0x18, partition.Header.ApploaderTrailerSize, true); MarkAsUsedE(partition.Offset + partition.Header.DataOffset , 0 @@ -296,16 +299,17 @@ bool ParsePartitionData(SPartition& partition) + partition.Header.ApploaderTrailerSize); // DOL - ReadFromVolume(0x420, partition.Header.DOLOffset, true); + partition.Header.DOLOffset = filesystem->GetBootDOLOffset(); partition.Header.DOLSize = filesystem->GetBootDOLSize(partition.Header.DOLOffset); + parsed_ok = parsed_ok && partition.Header.DOLOffset && partition.Header.DOLSize; MarkAsUsedE(partition.Offset + partition.Header.DataOffset , partition.Header.DOLOffset , partition.Header.DOLSize); // FST - ReadFromVolume(0x424, partition.Header.FSTOffset, true); - ReadFromVolume(0x428, partition.Header.FSTSize, true); + parsed_ok = parsed_ok && ReadFromVolume(0x424, partition.Header.FSTOffset, true); + parsed_ok = parsed_ok && ReadFromVolume(0x428, partition.Header.FSTSize, true); MarkAsUsedE(partition.Offset + partition.Header.DataOffset , partition.Header.FSTOffset diff --git a/Source/Core/DiscIO/FileSystemGCWii.cpp b/Source/Core/DiscIO/FileSystemGCWii.cpp index 02fb360bbe..f721173346 100644 --- a/Source/Core/DiscIO/FileSystemGCWii.cpp +++ b/Source/Core/DiscIO/FileSystemGCWii.cpp @@ -127,20 +127,24 @@ bool CFileSystemGCWii::ExportFile(const std::string& _rFullPath, const std::stri bool CFileSystemGCWii::ExportApploader(const std::string& _rExportFolder) const { - u32 AppSize = m_rVolume->Read32(0x2440 + 0x14, m_Wii); // apploader size - AppSize += m_rVolume->Read32(0x2440 + 0x18, m_Wii); // + trailer size - AppSize += 0x20; // + header size - DEBUG_LOG(DISCIO,"AppSize -> %x", AppSize); + u32 apploader_size; + u32 trailer_size; + const u32 header_size = 0x20; + if (!m_rVolume->ReadSwapped(0x2440 + 0x14, &apploader_size, m_Wii) || + !m_rVolume->ReadSwapped(0x2440 + 0x18, &trailer_size, m_Wii)) + return false; + apploader_size += trailer_size + header_size; + DEBUG_LOG(DISCIO, "Apploader size -> %x", apploader_size); - std::vector buffer(AppSize); - if (m_rVolume->Read(0x2440, AppSize, &buffer[0], m_Wii)) + std::vector buffer(apploader_size); + if (m_rVolume->Read(0x2440, apploader_size, buffer.data(), m_Wii)) { std::string exportName(_rExportFolder + "/apploader.img"); File::IOFile AppFile(exportName, "wb"); if (AppFile) { - AppFile.WriteBytes(&buffer[0], AppSize); + AppFile.WriteBytes(buffer.data(), apploader_size); return true; } } @@ -148,13 +152,20 @@ bool CFileSystemGCWii::ExportApploader(const std::string& _rExportFolder) const return false; } -u32 CFileSystemGCWii::GetBootDOLSize() const +u64 CFileSystemGCWii::GetBootDOLOffset() const { - return GetBootDOLSize((u64)m_rVolume->Read32(0x420, m_Wii) << GetOffsetShift()); + u32 offset = 0; + m_rVolume->ReadSwapped(0x420, &offset, m_Wii); + return static_cast(offset) << GetOffsetShift(); } u32 CFileSystemGCWii::GetBootDOLSize(u64 dol_offset) const { + // The dol_offset value is usually obtained by calling GetBootDOLOffset. + // If GetBootDOLOffset fails by returning 0, GetBootDOLSize should also fail. + if (dol_offset == 0) + return 0; + u32 dol_size = 0; u32 offset = 0; u32 size = 0; @@ -162,16 +173,18 @@ u32 CFileSystemGCWii::GetBootDOLSize(u64 dol_offset) const // Iterate through the 7 code segments for (u8 i = 0; i < 7; i++) { - offset = m_rVolume->Read32(dol_offset + 0x00 + i * 4, m_Wii); - size = m_rVolume->Read32(dol_offset + 0x90 + i * 4, m_Wii); + if (!m_rVolume->ReadSwapped(dol_offset + 0x00 + i * 4, &offset, m_Wii) || + !m_rVolume->ReadSwapped(dol_offset + 0x90 + i * 4, &size, m_Wii)) + return 0; dol_size = std::max(offset + size, dol_size); } // Iterate through the 11 data segments for (u8 i = 0; i < 11; i++) { - offset = m_rVolume->Read32(dol_offset + 0x1c + i * 4, m_Wii); - size = m_rVolume->Read32(dol_offset + 0xac + i * 4, m_Wii); + if (!m_rVolume->ReadSwapped(dol_offset + 0x1c + i * 4, &offset, m_Wii) || + !m_rVolume->ReadSwapped(dol_offset + 0xac + i * 4, &size, m_Wii)) + return 0; dol_size = std::max(offset + size, dol_size); } @@ -180,8 +193,11 @@ u32 CFileSystemGCWii::GetBootDOLSize(u64 dol_offset) const bool CFileSystemGCWii::ExportDOL(const std::string& _rExportFolder) const { - u32 DolOffset = m_rVolume->Read32(0x420, m_Wii) << GetOffsetShift(); - u32 DolSize = GetBootDOLSize(); + u64 DolOffset = GetBootDOLOffset(); + u32 DolSize = GetBootDOLSize(DolOffset); + + if (DolOffset == 0 || DolSize == 0) + return false; std::vector buffer(DolSize); if (m_rVolume->Read(DolOffset, DolSize, &buffer[0], m_Wii)) @@ -234,12 +250,13 @@ const SFileInfo* CFileSystemGCWii::FindFileInfo(const std::string& _rFullPath) bool CFileSystemGCWii::DetectFileSystem() { - if (m_rVolume->Read32(0x18, false) == 0x5D1C9EA3) + u32 magic_bytes; + if (m_rVolume->ReadSwapped(0x18, &magic_bytes, false) && magic_bytes == 0x5D1C9EA3) { m_Wii = true; return true; } - else if (m_rVolume->Read32(0x1c, false) == 0xC2339F3D) + else if (m_rVolume->ReadSwapped(0x1c, &magic_bytes, false) && magic_bytes == 0xC2339F3D) { m_Wii = false; return true; @@ -254,26 +271,26 @@ void CFileSystemGCWii::InitFileSystem() u32 const shift = GetOffsetShift(); // read the whole FST - u64 FSTOffset = static_cast(m_rVolume->Read32(0x424, m_Wii)) << shift; - // u32 FSTSize = Read32(0x428); - // u32 FSTMaxSize = Read32(0x42C); - + u32 fst_offset_unshifted; + if (!m_rVolume->ReadSwapped(0x424, &fst_offset_unshifted, m_Wii)) + return; + u64 FSTOffset = static_cast(fst_offset_unshifted) << shift; // read all fileinfos - SFileInfo Root - { - m_rVolume->Read32(FSTOffset + 0x0, m_Wii), - static_cast(FSTOffset + 0x4) << shift, - m_rVolume->Read32(FSTOffset + 0x8, m_Wii) - }; + u32 name_offset, offset, size; + if (!m_rVolume->ReadSwapped(FSTOffset + 0x0, &name_offset, m_Wii) || + !m_rVolume->ReadSwapped(FSTOffset + 0x4, &offset, m_Wii) || + !m_rVolume->ReadSwapped(FSTOffset + 0x8, &size, m_Wii)) + return; + SFileInfo root = { name_offset, static_cast(offset) << shift, size }; - if (!Root.IsDirectory()) + if (!root.IsDirectory()) return; // 12 bytes (the size of a file entry) times 10 * 1024 * 1024 is 120 MiB, // more than total RAM in a Wii. No file system should use anywhere near that much. static const u32 ARBITRARY_FILE_SYSTEM_SIZE_LIMIT = 10 * 1024 * 1024; - if (Root.m_FileSize > ARBITRARY_FILE_SYSTEM_SIZE_LIMIT) + if (root.m_FileSize > ARBITRARY_FILE_SYSTEM_SIZE_LIMIT) { // Without this check, Dolphin can crash by trying to allocate too much // memory when loading the file systems of certain malformed disc images. @@ -286,14 +303,17 @@ void CFileSystemGCWii::InitFileSystem() PanicAlert("Wtf?"); u64 NameTableOffset = FSTOffset; - m_FileInfoVector.reserve((size_t)Root.m_FileSize); - for (u32 i = 0; i < Root.m_FileSize; i++) + m_FileInfoVector.reserve((size_t)root.m_FileSize); + for (u32 i = 0; i < root.m_FileSize; i++) { - u64 const read_offset = FSTOffset + (i * 0xC); - u64 const name_offset = m_rVolume->Read32(read_offset + 0x0, m_Wii); - u64 const offset = static_cast(m_rVolume->Read32(read_offset + 0x4, m_Wii)) << shift; - u64 const size = m_rVolume->Read32(read_offset + 0x8, m_Wii); - m_FileInfoVector.emplace_back(name_offset, offset, size); + const u64 read_offset = FSTOffset + (i * 0xC); + name_offset = 0; + m_rVolume->ReadSwapped(read_offset + 0x0, &name_offset, m_Wii); + offset = 0; + m_rVolume->ReadSwapped(read_offset + 0x4, &offset, m_Wii); + size = 0; + m_rVolume->ReadSwapped(read_offset + 0x8, &size, m_Wii); + m_FileInfoVector.emplace_back(name_offset, static_cast(offset) << shift, size); NameTableOffset += 0xC; } diff --git a/Source/Core/DiscIO/FileSystemGCWii.h b/Source/Core/DiscIO/FileSystemGCWii.h index 3b70e63437..f9bfa5f5b1 100644 --- a/Source/Core/DiscIO/FileSystemGCWii.h +++ b/Source/Core/DiscIO/FileSystemGCWii.h @@ -30,7 +30,7 @@ public: bool ExportFile(const std::string& _rFullPath, const std::string&_rExportFilename) override; bool ExportApploader(const std::string& _rExportFolder) const override; bool ExportDOL(const std::string& _rExportFolder) const override; - u32 GetBootDOLSize() const override; + u64 GetBootDOLOffset() const override; u32 GetBootDOLSize(u64 dol_offset) const override; private: diff --git a/Source/Core/DiscIO/Filesystem.h b/Source/Core/DiscIO/Filesystem.h index 9ee60ab6d5..36fb9916a8 100644 --- a/Source/Core/DiscIO/Filesystem.h +++ b/Source/Core/DiscIO/Filesystem.h @@ -49,7 +49,7 @@ public: virtual bool ExportApploader(const std::string& _rExportFolder) const = 0; virtual bool ExportDOL(const std::string& _rExportFolder) const = 0; virtual const std::string GetFileName(u64 _Address) = 0; - virtual u32 GetBootDOLSize() const = 0; + virtual u64 GetBootDOLOffset() const = 0; virtual u32 GetBootDOLSize(u64 dol_offset) const = 0; protected: diff --git a/Source/Core/DiscIO/Volume.h b/Source/Core/DiscIO/Volume.h index a09c282748..9003770e35 100644 --- a/Source/Core/DiscIO/Volume.h +++ b/Source/Core/DiscIO/Volume.h @@ -71,11 +71,14 @@ public: // decrypt parameter must be false if not reading a Wii disc virtual bool Read(u64 _Offset, u64 _Length, u8* _pBuffer, bool decrypt) const = 0; - virtual u32 Read32(u64 _Offset, bool decrypt) const + template + bool ReadSwapped(u64 offset, T* buffer, bool decrypt) const { - u32 temp; - Read(_Offset, sizeof(u32), (u8*)&temp, decrypt); - return Common::swap32(temp); + T temp; + if (!Read(offset, sizeof(T), reinterpret_cast(&temp), decrypt)) + return false; + *buffer = Common::FromBigEndian(temp); + return true; } virtual bool GetTitleID(u64*) const { return false; } diff --git a/Source/Core/DiscIO/VolumeCreator.cpp b/Source/Core/DiscIO/VolumeCreator.cpp index a6305941ac..78d9dbfa02 100644 --- a/Source/Core/DiscIO/VolumeCreator.cpp +++ b/Source/Core/DiscIO/VolumeCreator.cpp @@ -34,33 +34,6 @@ enum EDiscType DISC_TYPE_WAD }; -class CBlobBigEndianReader -{ -public: - CBlobBigEndianReader(IBlobReader& _rReader) : m_rReader(_rReader) {} - - u32 Read32(u64 _Offset) - { - u32 Temp; - m_rReader.Read(_Offset, 4, (u8*)&Temp); - return Common::swap32(Temp); - } - u16 Read16(u64 _Offset) - { - u16 Temp; - m_rReader.Read(_Offset, 2, (u8*)&Temp); - return Common::swap16(Temp); - } - u8 Read8(u64 _Offset) - { - u8 Temp; - m_rReader.Read(_Offset, 1, &Temp); - return Temp; - } -private: - IBlobReader& m_rReader; -}; - static const unsigned char s_master_key[16] = { 0xeb,0xe4,0x2a,0x22,0x5e,0x85,0x93,0xe4, 0x48,0xd9,0xc5,0x45,0x73,0x81,0xaa,0xf7 @@ -114,8 +87,6 @@ std::unique_ptr CreateVolumeFromDirectory(const std::string& directory, void VolumeKeyForPartition(IBlobReader& _rReader, u64 offset, u8* VolumeKey) { - CBlobBigEndianReader Reader(_rReader); - u8 SubKey[16]; _rReader.Read(offset + 0x1bf, 16, SubKey); @@ -123,16 +94,17 @@ void VolumeKeyForPartition(IBlobReader& _rReader, u64 offset, u8* VolumeKey) memset(IV, 0, 16); _rReader.Read(offset + 0x44c, 8, IV); - bool usingKoreanKey = false; // Issue: 6813 // Magic value is at partition's offset + 0x1f1 (1byte) // If encrypted with the Korean key, the magic value would be 1 // Otherwise it is zero - if (Reader.Read8(0x3) == 'K' && Reader.Read8(offset + 0x1f1) == 1) - usingKoreanKey = true; + u8 using_korean_key = 0; + _rReader.Read(offset + 0x1f1, sizeof(u8), &using_korean_key); + u8 region = 0; + _rReader.Read(0x3, sizeof(u8), ®ion); mbedtls_aes_context AES_ctx; - mbedtls_aes_setkey_dec(&AES_ctx, (usingKoreanKey ? s_master_key_korean : s_master_key), 128); + mbedtls_aes_setkey_dec(&AES_ctx, (using_korean_key == 1 && region == 'K' ? s_master_key_korean : s_master_key), 128); mbedtls_aes_crypt_cbc(&AES_ctx, MBEDTLS_AES_DECRYPT, 16, IV, SubKey, VolumeKey); } @@ -141,15 +113,23 @@ static std::unique_ptr CreateVolumeFromCryptedWiiImage(std::unique_ptr< { CBlobBigEndianReader big_endian_reader(*reader); - u32 numPartitions = big_endian_reader.Read32(0x40000 + (partition_group * 8)); - u64 PartitionsOffset = (u64)big_endian_reader.Read32(0x40000 + (partition_group * 8) + 4) << 2; + u32 num_partitions; + if (!big_endian_reader.ReadSwapped(0x40000 + (partition_group * 8), &num_partitions)) + return nullptr; // Check if we're looking for a valid partition - if ((int)volume_number != -1 && volume_number > numPartitions) + if ((int)volume_number != -1 && volume_number > num_partitions) return nullptr; + u32 partitions_offset_unshifted; + if (!big_endian_reader.ReadSwapped(0x40000 + (partition_group * 8) + 4, &partitions_offset_unshifted)) + return nullptr; + u64 partitions_offset = (u64)partitions_offset_unshifted << 2; + struct SPartition { + SPartition(u64 offset, u32 type) : offset(offset), type(type) {} + u64 offset; u32 type; }; @@ -165,12 +145,14 @@ static std::unique_ptr CreateVolumeFromCryptedWiiImage(std::unique_ptr< // Read all partitions for (SPartitionGroup& group : partition_groups) { - for (u32 i = 0; i < numPartitions; i++) + for (u32 i = 0; i < num_partitions; i++) { - SPartition partition; - partition.offset = ((u64)big_endian_reader.Read32(PartitionsOffset + (i * 8) + 0)) << 2; - partition.type = big_endian_reader.Read32(PartitionsOffset + (i * 8) + 4); - group.partitions.push_back(partition); + u32 partition_offset, partition_type; + if (big_endian_reader.ReadSwapped(partitions_offset + (i * 8) + 0, &partition_offset) && + big_endian_reader.ReadSwapped(partitions_offset + (i * 8) + 4, &partition_type)) + { + group.partitions.emplace_back((u64)partition_offset << 2, partition_type); + } } } @@ -195,12 +177,12 @@ static std::unique_ptr CreateVolumeFromCryptedWiiImage(std::unique_ptr< EDiscType GetDiscType(IBlobReader& _rReader) { CBlobBigEndianReader Reader(_rReader); - u32 WiiMagic = Reader.Read32(0x18); - u32 WiiContainerMagic = Reader.Read32(0x60); - u32 WADMagic = Reader.Read32(0x02); - u32 GCMagic = Reader.Read32(0x1C); // Check for Wii + u32 WiiMagic = 0; + Reader.ReadSwapped(0x18, &WiiMagic); + u32 WiiContainerMagic = 0; + Reader.ReadSwapped(0x60, &WiiContainerMagic); if (WiiMagic == 0x5D1C9EA3 && WiiContainerMagic != 0) return DISC_TYPE_WII; if (WiiMagic == 0x5D1C9EA3 && WiiContainerMagic == 0) @@ -208,10 +190,14 @@ EDiscType GetDiscType(IBlobReader& _rReader) // Check for WAD // 0x206962 for boot2 wads + u32 WADMagic = 0; + Reader.ReadSwapped(0x02, &WADMagic); if (WADMagic == 0x00204973 || WADMagic == 0x00206962) return DISC_TYPE_WAD; // Check for GC + u32 GCMagic = 0; + Reader.ReadSwapped(0x1C, &GCMagic); if (GCMagic == 0xC2339F3D) return DISC_TYPE_GC; diff --git a/Source/Core/DiscIO/WiiWad.cpp b/Source/Core/DiscIO/WiiWad.cpp index d3d145faff..ca8a739737 100644 --- a/Source/Core/DiscIO/WiiWad.cpp +++ b/Source/Core/DiscIO/WiiWad.cpp @@ -18,22 +18,6 @@ namespace DiscIO { -class CBlobBigEndianReader -{ -public: - CBlobBigEndianReader(DiscIO::IBlobReader& _rReader) : m_rReader(_rReader) {} - - u32 Read32(u64 _Offset) - { - u32 Temp; - m_rReader.Read(_Offset, 4, (u8*)&Temp); - return(Common::swap32(Temp)); - } - -private: - DiscIO::IBlobReader& m_rReader; -}; - WiiWAD::WiiWAD(const std::string& name) { std::unique_ptr reader(DiscIO::CreateBlobReader(name)); @@ -80,27 +64,17 @@ bool WiiWAD::ParseWAD(DiscIO::IBlobReader& _rReader) { CBlobBigEndianReader ReaderBig(_rReader); - // get header size - u32 HeaderSize = ReaderBig.Read32(0); - if (HeaderSize != 0x20) - { - _dbg_assert_msg_(BOOT, (HeaderSize==0x20), "WiiWAD: Header size != 0x20"); - return false; - } - - // get header - u8 Header[0x20]; - _rReader.Read(0, HeaderSize, Header); - u32 HeaderType = ReaderBig.Read32(0x4); - if ((0x49730000 != HeaderType) && (0x69620000 != HeaderType)) + if (!IsWiiWAD(ReaderBig)) return false; - m_CertificateChainSize = ReaderBig.Read32(0x8); - u32 Reserved = ReaderBig.Read32(0xC); - m_TicketSize = ReaderBig.Read32(0x10); - m_TMDSize = ReaderBig.Read32(0x14); - m_DataAppSize = ReaderBig.Read32(0x18); - m_FooterSize = ReaderBig.Read32(0x1C); + u32 Reserved; + if (!ReaderBig.ReadSwapped(0x8, &m_CertificateChainSize) || + !ReaderBig.ReadSwapped(0xC, &Reserved) || + !ReaderBig.ReadSwapped(0x10, &m_TicketSize) || + !ReaderBig.ReadSwapped(0x14, &m_TMDSize) || + !ReaderBig.ReadSwapped(0x18, &m_DataAppSize) || + !ReaderBig.ReadSwapped(0x1C, &m_FooterSize)) + return false; if (MAX_LOGLEVEL >= LogTypes::LOG_LEVELS::LDEBUG) _dbg_assert_msg_(BOOT, Reserved==0x00, "WiiWAD: Reserved must be 0x00"); @@ -115,5 +89,13 @@ bool WiiWAD::ParseWAD(DiscIO::IBlobReader& _rReader) return true; } -} // namespace end +bool WiiWAD::IsWiiWAD(const DiscIO::CBlobBigEndianReader& reader) +{ + u32 header_size = 0; + u32 header_type = 0; + reader.ReadSwapped(0x0, &header_size); + reader.ReadSwapped(0x4, &header_type); + return header_size == 0x20 && (header_type == 0x49730000 || header_type == 0x69620000); +} +} // namespace end diff --git a/Source/Core/DiscIO/WiiWad.h b/Source/Core/DiscIO/WiiWad.h index 331cd2e3b8..935fd52cf6 100644 --- a/Source/Core/DiscIO/WiiWad.h +++ b/Source/Core/DiscIO/WiiWad.h @@ -12,6 +12,7 @@ namespace DiscIO { class IBlobReader; +class CBlobBigEndianReader; class WiiWAD { @@ -52,6 +53,7 @@ private: u8* CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset); bool ParseWAD(DiscIO::IBlobReader& _rReader); + static bool IsWiiWAD(const DiscIO::CBlobBigEndianReader& reader); }; }