summaryrefslogtreecommitdiffstats
path: root/libpit/source
diff options
context:
space:
mode:
authorBenjamin Dobell <benjamin.dobell+git@glassechidna.com.au>2015-02-18 17:13:56 +0100
committerBenjamin Dobell <benjamin.dobell+git@glassechidna.com.au>2015-02-18 18:13:33 +0100
commitb22ae7b89f7993f632e10e18c116f293f314575f (patch)
tree03161ccff78d3c9353e860e5cd9b74b84d07810b /libpit/source
parentUpgrade Heimdall Frontend to Qt5 and build with cmake (diff)
downloadHeimdall-b22ae7b89f7993f632e10e18c116f293f314575f.tar
Heimdall-b22ae7b89f7993f632e10e18c116f293f314575f.tar.gz
Heimdall-b22ae7b89f7993f632e10e18c116f293f314575f.tar.bz2
Heimdall-b22ae7b89f7993f632e10e18c116f293f314575f.tar.lz
Heimdall-b22ae7b89f7993f632e10e18c116f293f314575f.tar.xz
Heimdall-b22ae7b89f7993f632e10e18c116f293f314575f.tar.zst
Heimdall-b22ae7b89f7993f632e10e18c116f293f314575f.zip
Diffstat (limited to 'libpit/source')
-rw-r--r--libpit/source/libpit.cpp296
-rw-r--r--libpit/source/libpit.h417
2 files changed, 713 insertions, 0 deletions
diff --git a/libpit/source/libpit.cpp b/libpit/source/libpit.cpp
new file mode 100644
index 0000000..73bc1b8
--- /dev/null
+++ b/libpit/source/libpit.cpp
@@ -0,0 +1,296 @@
+/* Copyright (c) 2010-2014 Benjamin Dobell, Glass Echidna
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.*/
+
+// libpit
+#include "libpit.h"
+
+using namespace libpit;
+
+PitEntry::PitEntry()
+{
+ binaryType = false;
+ deviceType = 0;
+ identifier = 0;
+ attributes = 0;
+ updateAttributes = 0;
+ blockSizeOrOffset = 0;
+ blockCount = 0;
+ fileOffset = 0;
+ fileSize = 0;
+
+ memset(partitionName, 0, PitEntry::kPartitionNameMaxLength);
+ memset(flashFilename, 0, PitEntry::kFlashFilenameMaxLength);
+ memset(fotaFilename, 0, PitEntry::kFotaFilenameMaxLength);
+}
+
+PitEntry::~PitEntry()
+{
+}
+
+bool PitEntry::Matches(const PitEntry *otherPitEntry) const
+{
+ if (binaryType == otherPitEntry->binaryType && deviceType == otherPitEntry->deviceType && identifier == otherPitEntry->identifier
+ && attributes == otherPitEntry->attributes && updateAttributes == otherPitEntry->updateAttributes && blockSizeOrOffset == otherPitEntry->blockSizeOrOffset
+ && blockCount == otherPitEntry->blockCount && fileOffset == otherPitEntry->fileOffset && fileSize == otherPitEntry->fileSize
+ && strcmp(partitionName, otherPitEntry->partitionName) == 0 && strcmp(flashFilename, otherPitEntry->flashFilename) == 0
+ && strcmp(fotaFilename, otherPitEntry->fotaFilename) == 0)
+ {
+ return (true);
+ }
+ else
+ {
+ return (false);
+ }
+}
+
+
+
+PitData::PitData()
+{
+ entryCount = 0;
+
+ unknown1 = 0;
+ unknown2 = 0;
+
+ unknown3 = 0;
+ unknown4 = 0;
+
+ unknown5 = 0;
+ unknown6 = 0;
+
+ unknown7 = 0;
+ unknown8 = 0;
+}
+
+PitData::~PitData()
+{
+ for (unsigned int i = 0; i < entries.size(); i++)
+ delete entries[i];
+}
+
+bool PitData::Unpack(const unsigned char *data)
+{
+ if (PitData::UnpackInteger(data, 0) != PitData::kFileIdentifier)
+ return (false);
+
+ // Remove existing entries
+ for (unsigned int i = 0; i < entries.size(); i++)
+ delete entries[i];
+
+ entryCount = PitData::UnpackInteger(data, 4);
+
+ entries.resize(entryCount);
+
+ unknown1 = PitData::UnpackInteger(data, 8);
+ unknown2 = PitData::UnpackInteger(data, 12);
+
+ unknown3 = PitData::UnpackShort(data, 16);
+ unknown4 = PitData::UnpackShort(data, 18);
+
+ unknown5 = PitData::UnpackShort(data, 20);
+ unknown6 = PitData::UnpackShort(data, 22);
+
+ unknown7 = PitData::UnpackShort(data, 24);
+ unknown8 = PitData::UnpackShort(data, 26);
+
+ unsigned int integerValue;
+ unsigned int entryOffset;
+
+ for (unsigned int i = 0; i < entryCount; i++)
+ {
+ entryOffset = PitData::kHeaderDataSize + i * PitEntry::kDataSize;
+
+ entries[i] = new PitEntry();
+
+ integerValue = PitData::UnpackInteger(data, entryOffset);
+ entries[i]->SetBinaryType(integerValue);
+
+ integerValue = PitData::UnpackInteger(data, entryOffset + 4);
+ entries[i]->SetDeviceType(integerValue);
+
+ integerValue = PitData::UnpackInteger(data, entryOffset + 8);
+ entries[i]->SetIdentifier(integerValue);
+
+ integerValue = PitData::UnpackInteger(data, entryOffset + 12);
+ entries[i]->SetAttributes(integerValue);
+
+ integerValue = PitData::UnpackInteger(data, entryOffset + 16);
+ entries[i]->SetUpdateAttributes(integerValue);
+
+ integerValue = PitData::UnpackInteger(data, entryOffset + 20);
+ entries[i]->SetBlockSizeOrOffset(integerValue);
+
+ integerValue = PitData::UnpackInteger(data, entryOffset + 24);
+ entries[i]->SetBlockCount(integerValue);
+
+ integerValue = PitData::UnpackInteger(data, entryOffset + 28);
+ entries[i]->SetFileOffset(integerValue);
+
+ integerValue = PitData::UnpackInteger(data, entryOffset + 32);
+ entries[i]->SetFileSize(integerValue);
+
+ entries[i]->SetPartitionName((const char *)data + entryOffset + 36);
+ entries[i]->SetFlashFilename((const char *)data + entryOffset + 36 + PitEntry::kPartitionNameMaxLength);
+ entries[i]->SetFotaFilename((const char *)data + entryOffset + 36 + PitEntry::kPartitionNameMaxLength + PitEntry::kFlashFilenameMaxLength);
+ }
+
+ return (true);
+}
+
+void PitData::Pack(unsigned char *data) const
+{
+ PitData::PackInteger(data, 0, PitData::kFileIdentifier);
+
+ PitData::PackInteger(data, 4, entryCount);
+
+ PitData::PackInteger(data, 8, unknown1);
+ PitData::PackInteger(data, 12, unknown2);
+
+ PitData::PackShort(data, 16, unknown3);
+ PitData::PackShort(data, 18, unknown4);
+
+ PitData::PackShort(data, 20, unknown5);
+ PitData::PackShort(data, 22, unknown6);
+
+ PitData::PackShort(data, 24, unknown7);
+ PitData::PackShort(data, 26, unknown8);
+
+ int entryOffset;
+
+ for (unsigned int i = 0; i < entryCount; i++)
+ {
+ entryOffset = PitData::kHeaderDataSize + i * PitEntry::kDataSize;
+
+ PitData::PackInteger(data, entryOffset, entries[i]->GetBinaryType());
+
+ PitData::PackInteger(data, entryOffset + 4, entries[i]->GetDeviceType());
+ PitData::PackInteger(data, entryOffset + 8, entries[i]->GetIdentifier());
+ PitData::PackInteger(data, entryOffset + 12, entries[i]->GetAttributes());
+
+ PitData::PackInteger(data, entryOffset + 16, entries[i]->GetUpdateAttributes());
+
+ PitData::PackInteger(data, entryOffset + 20, entries[i]->GetBlockSizeOrOffset());
+ PitData::PackInteger(data, entryOffset + 24, entries[i]->GetBlockCount());
+
+ PitData::PackInteger(data, entryOffset + 28, entries[i]->GetFileOffset());
+ PitData::PackInteger(data, entryOffset + 32, entries[i]->GetFileSize());
+
+ memcpy(data + entryOffset + 36, entries[i]->GetPartitionName(), PitEntry::kPartitionNameMaxLength);
+ memcpy(data + entryOffset + 36 + PitEntry::kPartitionNameMaxLength, entries[i]->GetFlashFilename(), PitEntry::kFlashFilenameMaxLength);
+ memcpy(data + entryOffset + 36 + PitEntry::kPartitionNameMaxLength + PitEntry::kFlashFilenameMaxLength,
+ entries[i]->GetFotaFilename(), PitEntry::kFotaFilenameMaxLength);
+ }
+}
+
+bool PitData::Matches(const PitData *otherPitData) const
+{
+ if (entryCount == otherPitData->entryCount && unknown1 == otherPitData->unknown1 && unknown2 == otherPitData->unknown2
+ && unknown3 == otherPitData->unknown3 && unknown4 == otherPitData->unknown4 && unknown5 == otherPitData->unknown5
+ && unknown6 == otherPitData->unknown6 && unknown7 == otherPitData->unknown7 && unknown8 == otherPitData->unknown8)
+ {
+ for (unsigned int i = 0; i < entryCount; i++)
+ {
+ if (!entries[i]->Matches(otherPitData->entries[i]))
+ return (false);
+ }
+
+ return (true);
+ }
+ else
+ {
+ return (false);
+ }
+}
+
+void PitData::Clear(void)
+{
+ entryCount = 0;
+
+ unknown1 = 0;
+ unknown2 = 0;
+
+ unknown3 = 0;
+ unknown4 = 0;
+
+ unknown5 = 0;
+ unknown6 = 0;
+
+ unknown7 = 0;
+ unknown8 = 0;
+
+ for (unsigned int i = 0; i < entries.size(); i++)
+ delete entries[i];
+
+ entries.clear();
+}
+
+PitEntry *PitData::GetEntry(unsigned int index)
+{
+ return (entries[index]);
+}
+
+const PitEntry *PitData::GetEntry(unsigned int index) const
+{
+ return (entries[index]);
+}
+
+PitEntry *PitData::FindEntry(const char *partitionName)
+{
+ for (unsigned int i = 0; i < entries.size(); i++)
+ {
+ if (entries[i]->IsFlashable() && strcmp(entries[i]->GetPartitionName(), partitionName) == 0)
+ return (entries[i]);
+ }
+
+ return (nullptr);
+}
+
+const PitEntry *PitData::FindEntry(const char *partitionName) const
+{
+ for (unsigned int i = 0; i < entries.size(); i++)
+ {
+ if (entries[i]->IsFlashable() && strcmp(entries[i]->GetPartitionName(), partitionName) == 0)
+ return (entries[i]);
+ }
+
+ return (nullptr);
+}
+
+PitEntry *PitData::FindEntry(unsigned int partitionIdentifier)
+{
+ for (unsigned int i = 0; i < entries.size(); i++)
+ {
+ if (entries[i]->IsFlashable() && entries[i]->GetIdentifier() == partitionIdentifier)
+ return (entries[i]);
+ }
+
+ return (nullptr);
+}
+
+const PitEntry *PitData::FindEntry(unsigned int partitionIdentifier) const
+{
+ for (unsigned int i = 0; i < entries.size(); i++)
+ {
+ if (entries[i]->IsFlashable() && entries[i]->GetIdentifier() == partitionIdentifier)
+ return (entries[i]);
+ }
+
+ return (nullptr);
+}
diff --git a/libpit/source/libpit.h b/libpit/source/libpit.h
new file mode 100644
index 0000000..ccdea20
--- /dev/null
+++ b/libpit/source/libpit.h
@@ -0,0 +1,417 @@
+/* Copyright (c) 2010-2014 Benjamin Dobell, Glass Echidna
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.*/
+
+#ifndef LIBPIT_H
+#define LIBPIT_H
+
+#ifdef WIN32
+#pragma warning(disable : 4996)
+#endif
+
+#if (!(defined _MSC_VER) || (_MSC_VER < 1700))
+
+#ifndef nullptr
+#define nullptr 0
+#endif
+
+#endif
+
+// C/C++ Standard Library
+#include <cstring>
+#include <string>
+#include <vector>
+
+namespace libpit
+{
+ class PitEntry
+ {
+ public:
+
+ enum
+ {
+ kDataSize = 132,
+ kPartitionNameMaxLength = 32,
+ kFlashFilenameMaxLength = 32,
+ kFotaFilenameMaxLength = 32
+ };
+
+ enum
+ {
+ kBinaryTypeApplicationProcessor = 0,
+ kBinaryTypeCommunicationProcessor = 1
+ };
+
+ enum
+ {
+ kDeviceTypeOneNand = 0,
+ kDeviceTypeFile, // FAT
+ kDeviceTypeMMC,
+ kDeviceTypeAll // ?
+ };
+
+ enum
+ {
+ kAttributeWrite = 1,
+ kAttributeSTL = 1 << 1/*,
+ kAttributeBML = 1 << 2*/ // ???
+ };
+
+ enum
+ {
+ kUpdateAttributeFota = 1,
+ kUpdateAttributeSecure = 1 << 1
+ };
+
+ private:
+
+ unsigned int binaryType;
+ unsigned int deviceType;
+ unsigned int identifier;
+ unsigned int attributes;
+ unsigned int updateAttributes;
+
+ unsigned int blockSizeOrOffset;
+ unsigned int blockCount;
+
+ unsigned int fileOffset; // Obsolete
+ unsigned int fileSize; // Obsolete
+
+ char partitionName[kPartitionNameMaxLength];
+ char flashFilename[kFlashFilenameMaxLength]; // USB flash filename
+ char fotaFilename[kFotaFilenameMaxLength]; // Firmware over the air
+
+ public:
+
+ PitEntry();
+ ~PitEntry();
+
+ bool Matches(const PitEntry *otherPitEntry) const;
+
+ bool IsFlashable(void) const
+ {
+ return strlen(partitionName) != 0;
+ }
+
+ unsigned int GetBinaryType(void) const
+ {
+ return binaryType;
+ }
+
+ void SetBinaryType(unsigned int binaryType)
+ {
+ this->binaryType = binaryType;
+ }
+
+ unsigned int GetDeviceType(void) const
+ {
+ return deviceType;
+ }
+
+ void SetDeviceType(unsigned int deviceType)
+ {
+ this->deviceType = deviceType;
+ }
+
+ unsigned int GetIdentifier(void) const
+ {
+ return identifier;
+ }
+
+ void SetIdentifier(unsigned int identifier)
+ {
+ this->identifier = identifier;
+ }
+
+ unsigned int GetAttributes(void) const
+ {
+ return attributes;
+ }
+
+ void SetAttributes(unsigned int attributes)
+ {
+ this->attributes = attributes;
+ }
+
+ unsigned int GetUpdateAttributes(void) const
+ {
+ return updateAttributes;
+ }
+
+ void SetUpdateAttributes(unsigned int updateAttributes)
+ {
+ this->updateAttributes = updateAttributes;
+ }
+
+ // Different versions of Loke (secondary bootloaders) on different devices intepret this differently.
+ unsigned int GetBlockSizeOrOffset(void) const
+ {
+ return blockSizeOrOffset;
+ }
+
+ void SetBlockSizeOrOffset(unsigned int blockSizeOrOffset)
+ {
+ this->blockSizeOrOffset = blockSizeOrOffset;
+ }
+
+ unsigned int GetBlockCount(void) const
+ {
+ return blockCount;
+ }
+
+ void SetBlockCount(unsigned int blockCount)
+ {
+ this->blockCount = blockCount;
+ }
+
+ unsigned int GetFileOffset(void) const
+ {
+ return fileOffset;
+ }
+
+ void SetFileOffset(unsigned int fileOffset)
+ {
+ this->fileOffset = fileOffset;
+ }
+
+ unsigned int GetFileSize(void) const
+ {
+ return fileSize;
+ }
+
+ void SetFileSize(unsigned int fileSize)
+ {
+ this->fileSize = fileSize;
+ }
+
+ const char *GetPartitionName(void) const
+ {
+ return partitionName;
+ }
+
+ void SetPartitionName(const char *partitionName)
+ {
+ // This isn't strictly necessary but ensures no junk is left in our PIT file.
+ memset(this->partitionName, 0, 64);
+
+ if (strlen(partitionName) < 64)
+ strcpy(this->partitionName, partitionName);
+ else
+ memcpy(this->partitionName, partitionName, 63);
+ }
+
+ const char *GetFlashFilename(void) const
+ {
+ return flashFilename;
+ }
+
+ void SetFlashFilename(const char *flashFilename)
+ {
+ // This isn't strictly necessary but ensures no junk is left in our PIT file.
+ memset(this->flashFilename, 0, kFlashFilenameMaxLength);
+
+ if (strlen(partitionName) < 32)
+ strcpy(this->flashFilename, flashFilename);
+ else
+ memcpy(this->flashFilename, flashFilename, 31);
+ }
+
+ const char *GetFotaFilename(void) const
+ {
+ return fotaFilename;
+ }
+
+ void SetFotaFilename(const char *fotaFilename)
+ {
+ // This isn't strictly necessary but ensures no junk is left in our PIT file.
+ memset(this->fotaFilename, 0, kFotaFilenameMaxLength);
+
+ if (strlen(partitionName) < 32)
+ strcpy(this->fotaFilename, fotaFilename);
+ else
+ memcpy(this->fotaFilename, fotaFilename, 31);
+ }
+ };
+
+ class PitData
+ {
+ public:
+
+ enum
+ {
+ kFileIdentifier = 0x12349876,
+ kHeaderDataSize = 28,
+ kPaddedSizeMultiplicand = 4096
+ };
+
+ private:
+
+ unsigned int entryCount; // 0x04
+ unsigned int unknown1; // 0x08
+ unsigned int unknown2; // 0x0C
+
+ unsigned short unknown3; // 0x10
+ unsigned short unknown4; // 0x12
+
+ unsigned short unknown5; // 0x14
+ unsigned short unknown6; // 0x16
+
+ unsigned short unknown7; // 0x18
+ unsigned short unknown8; // 0x1A
+
+ // Entries start at 0x1C
+ std::vector<PitEntry *> entries;
+
+ static int UnpackInteger(const unsigned char *data, unsigned int offset)
+ {
+#ifdef WORDS_BIGENDIAN
+ int value = (data[offset] << 24) | (data[offset + 1] << 16) |
+ (data[offset + 2] << 8) | data[offset + 3];
+#else
+ // Flip endianness
+ int value = data[offset] | (data[offset + 1] << 8) |
+ (data[offset + 2] << 16) | (data[offset + 3] << 24);
+#endif
+ return (value);
+ }
+
+ static int UnpackShort(const unsigned char *data, unsigned int offset)
+ {
+#ifdef WORDS_BIGENDIAN
+ short value = (data[offset] << 8) | data[offset + 1];
+#else
+ // Flip endianness
+ short value = data[offset] | (data[offset + 1] << 8);
+#endif
+ return (value);
+ }
+
+ static void PackInteger(unsigned char *data, unsigned int offset, unsigned int value)
+ {
+#ifdef WORDS_BIGENDIAN
+ data[offset] = (value & 0xFF000000) >> 24;
+ data[offset + 1] = (value & 0x00FF0000) >> 16;
+ data[offset + 2] = (value & 0x0000FF00) >> 8;
+ data[offset + 3] = value & 0x000000FF;
+#else
+ // Flip endianness
+ data[offset] = value & 0x000000FF;
+ data[offset + 1] = (value & 0x0000FF00) >> 8;
+ data[offset + 2] = (value & 0x00FF0000) >> 16;
+ data[offset + 3] = (value & 0xFF000000) >> 24;
+#endif
+ }
+
+ static void PackShort(unsigned char *data, unsigned int offset, unsigned short value)
+ {
+#ifdef WORDS_BIGENDIAN
+ data[offset] = (value & 0xFF00) >> 8;
+ data[offset + 1] = value & 0x00FF;
+#else
+ // Flip endianness
+ data[offset] = value & 0x00FF;
+ data[offset + 1] = (value & 0xFF00) >> 8;
+#endif
+ }
+
+ public:
+
+ PitData();
+ ~PitData();
+
+ bool Unpack(const unsigned char *data);
+ void Pack(unsigned char *data) const;
+
+ bool Matches(const PitData *otherPitData) const;
+
+ void Clear(void);
+
+ PitEntry *GetEntry(unsigned int index);
+ const PitEntry *GetEntry(unsigned int index) const;
+
+ PitEntry *FindEntry(const char *partitionName);
+ const PitEntry *FindEntry(const char *partitionName) const;
+
+ PitEntry *FindEntry(unsigned int partitionIdentifier);
+ const PitEntry *FindEntry(unsigned int partitionIdentifier) const;
+
+ unsigned int GetEntryCount(void) const
+ {
+ return entryCount;
+ }
+
+ unsigned int GetDataSize(void) const
+ {
+ return PitData::kHeaderDataSize + entryCount * PitEntry::kDataSize;
+ }
+
+ unsigned int GetPaddedSize(void) const
+ {
+ unsigned int dataSize = GetDataSize();
+ unsigned int paddedSize = (dataSize / kPaddedSizeMultiplicand) * kPaddedSizeMultiplicand;
+
+ if (dataSize % kPaddedSizeMultiplicand != 0)
+ paddedSize += kPaddedSizeMultiplicand;
+
+ return paddedSize;
+ }
+
+ unsigned int GetUnknown1(void) const
+ {
+ return unknown1;
+ }
+
+ unsigned int GetUnknown2(void) const
+ {
+ return unknown2;
+ }
+
+ unsigned short GetUnknown3(void) const
+ {
+ return unknown3;
+ }
+
+ unsigned short GetUnknown4(void) const
+ {
+ return unknown4;
+ }
+
+ unsigned short GetUnknown5(void) const
+ {
+ return unknown5;
+ }
+
+ unsigned short GetUnknown6(void) const
+ {
+ return unknown6;
+ }
+
+ unsigned short GetUnknown7(void) const
+ {
+ return unknown7;
+ }
+
+ unsigned short GetUnknown8(void) const
+ {
+ return unknown8;
+ }
+ };
+}
+
+#endif