1 /* Copyright (c) 2010-2017 Benjamin Dobell, Glass Echidna 2 3 Permission is hereby granted, free of charge, to any person obtaining a copy 4 of this software and associated documentation files (the "Software"), to deal 5 in the Software without restriction, including without limitation the rights 6 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 copies of the Software, and to permit persons to whom the Software is 8 furnished to do so, subject to the following conditions: 9 10 The above copyright notice and this permission notice shall be included in 11 all copies or substantial portions of the Software. 12 13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 THE SOFTWARE.*/ 20 21 #ifndef LIBPIT_H 22 #define LIBPIT_H 23 24 #ifdef WIN32 25 #pragma warning(disable : 4996) 26 #endif 27 28 // C/C++ Standard Library 29 #include <cstring> 30 #include <string> 31 #include <vector> 32 33 namespace libpit 34 { 35 class PitEntry 36 { 37 public: 38 39 enum 40 { 41 kDataSize = 132, 42 kPartitionNameMaxLength = 32, 43 kFlashFilenameMaxLength = 32, 44 kFotaFilenameMaxLength = 32 45 }; 46 47 enum 48 { 49 kBinaryTypeApplicationProcessor = 0, 50 kBinaryTypeCommunicationProcessor = 1 51 }; 52 53 enum 54 { 55 kDeviceTypeOneNand = 0, 56 kDeviceTypeFile, // FAT 57 kDeviceTypeMMC, 58 kDeviceTypeAll // ? 59 }; 60 61 enum 62 { 63 kAttributeWrite = 1, 64 kAttributeSTL = 1 << 1/*, 65 kAttributeBML = 1 << 2*/ // ??? 66 }; 67 68 enum 69 { 70 kUpdateAttributeFota = 1, 71 kUpdateAttributeSecure = 1 << 1 72 }; 73 74 private: 75 76 unsigned int binaryType; 77 unsigned int deviceType; 78 unsigned int identifier; 79 unsigned int attributes; 80 unsigned int updateAttributes; 81 82 unsigned int blockSizeOrOffset; 83 unsigned int blockCount; 84 85 unsigned int fileOffset; // Obsolete 86 unsigned int fileSize; // Obsolete 87 88 char partitionName[kPartitionNameMaxLength]; 89 char flashFilename[kFlashFilenameMaxLength]; // USB flash filename 90 char fotaFilename[kFotaFilenameMaxLength]; // Firmware over the air 91 92 public: 93 94 PitEntry(); 95 ~PitEntry(); 96 97 bool Matches(const PitEntry *otherPitEntry) const; 98 IsFlashable(void)99 bool IsFlashable(void) const 100 { 101 return strlen(partitionName) != 0; 102 } 103 GetBinaryType(void)104 unsigned int GetBinaryType(void) const 105 { 106 return binaryType; 107 } 108 SetBinaryType(unsigned int binaryType)109 void SetBinaryType(unsigned int binaryType) 110 { 111 this->binaryType = binaryType; 112 } 113 GetDeviceType(void)114 unsigned int GetDeviceType(void) const 115 { 116 return deviceType; 117 } 118 SetDeviceType(unsigned int deviceType)119 void SetDeviceType(unsigned int deviceType) 120 { 121 this->deviceType = deviceType; 122 } 123 GetIdentifier(void)124 unsigned int GetIdentifier(void) const 125 { 126 return identifier; 127 } 128 SetIdentifier(unsigned int identifier)129 void SetIdentifier(unsigned int identifier) 130 { 131 this->identifier = identifier; 132 } 133 GetAttributes(void)134 unsigned int GetAttributes(void) const 135 { 136 return attributes; 137 } 138 SetAttributes(unsigned int attributes)139 void SetAttributes(unsigned int attributes) 140 { 141 this->attributes = attributes; 142 } 143 GetUpdateAttributes(void)144 unsigned int GetUpdateAttributes(void) const 145 { 146 return updateAttributes; 147 } 148 SetUpdateAttributes(unsigned int updateAttributes)149 void SetUpdateAttributes(unsigned int updateAttributes) 150 { 151 this->updateAttributes = updateAttributes; 152 } 153 154 // Different versions of Loke (secondary bootloaders) on different devices intepret this differently. GetBlockSizeOrOffset(void)155 unsigned int GetBlockSizeOrOffset(void) const 156 { 157 return blockSizeOrOffset; 158 } 159 SetBlockSizeOrOffset(unsigned int blockSizeOrOffset)160 void SetBlockSizeOrOffset(unsigned int blockSizeOrOffset) 161 { 162 this->blockSizeOrOffset = blockSizeOrOffset; 163 } 164 GetBlockCount(void)165 unsigned int GetBlockCount(void) const 166 { 167 return blockCount; 168 } 169 SetBlockCount(unsigned int blockCount)170 void SetBlockCount(unsigned int blockCount) 171 { 172 this->blockCount = blockCount; 173 } 174 GetFileOffset(void)175 unsigned int GetFileOffset(void) const 176 { 177 return fileOffset; 178 } 179 SetFileOffset(unsigned int fileOffset)180 void SetFileOffset(unsigned int fileOffset) 181 { 182 this->fileOffset = fileOffset; 183 } 184 GetFileSize(void)185 unsigned int GetFileSize(void) const 186 { 187 return fileSize; 188 } 189 SetFileSize(unsigned int fileSize)190 void SetFileSize(unsigned int fileSize) 191 { 192 this->fileSize = fileSize; 193 } 194 GetPartitionName(void)195 const char *GetPartitionName(void) const 196 { 197 return partitionName; 198 } 199 SetPartitionName(const char * partitionName)200 void SetPartitionName(const char *partitionName) 201 { 202 // This isn't strictly necessary but ensures no junk is left in our PIT file. 203 memset(this->partitionName, 0, kPartitionNameMaxLength); 204 205 if (strlen(partitionName) < kPartitionNameMaxLength) 206 strcpy(this->partitionName, partitionName); 207 else 208 memcpy(this->partitionName, partitionName, kPartitionNameMaxLength - 1); 209 } 210 GetFlashFilename(void)211 const char *GetFlashFilename(void) const 212 { 213 return flashFilename; 214 } 215 SetFlashFilename(const char * flashFilename)216 void SetFlashFilename(const char *flashFilename) 217 { 218 // This isn't strictly necessary but ensures no junk is left in our PIT file. 219 memset(this->flashFilename, 0, kFlashFilenameMaxLength); 220 221 if (strlen(partitionName) < kFlashFilenameMaxLength) 222 strcpy(this->flashFilename, flashFilename); 223 else 224 memcpy(this->flashFilename, flashFilename, kFlashFilenameMaxLength - 1); 225 } 226 GetFotaFilename(void)227 const char *GetFotaFilename(void) const 228 { 229 return fotaFilename; 230 } 231 SetFotaFilename(const char * fotaFilename)232 void SetFotaFilename(const char *fotaFilename) 233 { 234 // This isn't strictly necessary but ensures no junk is left in our PIT file. 235 memset(this->fotaFilename, 0, kFotaFilenameMaxLength); 236 237 if (strlen(partitionName) < kFotaFilenameMaxLength) 238 strcpy(this->fotaFilename, fotaFilename); 239 else 240 memcpy(this->fotaFilename, fotaFilename, kFotaFilenameMaxLength - 1); 241 } 242 }; 243 244 class PitData 245 { 246 public: 247 248 enum 249 { 250 kFileIdentifier = 0x12349876, 251 kHeaderDataSize = 28, 252 kPaddedSizeMultiplicand = 4096 253 }; 254 255 private: 256 257 unsigned int entryCount; // 0x04 258 unsigned int unknown1; // 0x08 259 unsigned int unknown2; // 0x0C 260 261 unsigned short unknown3; // 0x10 262 unsigned short unknown4; // 0x12 263 264 unsigned short unknown5; // 0x14 265 unsigned short unknown6; // 0x16 266 267 unsigned short unknown7; // 0x18 268 unsigned short unknown8; // 0x1A 269 270 // Entries start at 0x1C 271 std::vector<PitEntry *> entries; 272 UnpackInteger(const unsigned char * data,unsigned int offset)273 static int UnpackInteger(const unsigned char *data, unsigned int offset) 274 { 275 #ifdef WORDS_BIGENDIAN 276 int value = (data[offset] << 24) | (data[offset + 1] << 16) | 277 (data[offset + 2] << 8) | data[offset + 3]; 278 #else 279 // Flip endianness 280 int value = data[offset] | (data[offset + 1] << 8) | 281 (data[offset + 2] << 16) | (data[offset + 3] << 24); 282 #endif 283 return (value); 284 } 285 UnpackShort(const unsigned char * data,unsigned int offset)286 static int UnpackShort(const unsigned char *data, unsigned int offset) 287 { 288 #ifdef WORDS_BIGENDIAN 289 short value = (data[offset] << 8) | data[offset + 1]; 290 #else 291 // Flip endianness 292 short value = data[offset] | (data[offset + 1] << 8); 293 #endif 294 return (value); 295 } 296 PackInteger(unsigned char * data,unsigned int offset,unsigned int value)297 static void PackInteger(unsigned char *data, unsigned int offset, unsigned int value) 298 { 299 #ifdef WORDS_BIGENDIAN 300 data[offset] = (value & 0xFF000000) >> 24; 301 data[offset + 1] = (value & 0x00FF0000) >> 16; 302 data[offset + 2] = (value & 0x0000FF00) >> 8; 303 data[offset + 3] = value & 0x000000FF; 304 #else 305 // Flip endianness 306 data[offset] = value & 0x000000FF; 307 data[offset + 1] = (value & 0x0000FF00) >> 8; 308 data[offset + 2] = (value & 0x00FF0000) >> 16; 309 data[offset + 3] = (value & 0xFF000000) >> 24; 310 #endif 311 } 312 PackShort(unsigned char * data,unsigned int offset,unsigned short value)313 static void PackShort(unsigned char *data, unsigned int offset, unsigned short value) 314 { 315 #ifdef WORDS_BIGENDIAN 316 data[offset] = (value & 0xFF00) >> 8; 317 data[offset + 1] = value & 0x00FF; 318 #else 319 // Flip endianness 320 data[offset] = value & 0x00FF; 321 data[offset + 1] = (value & 0xFF00) >> 8; 322 #endif 323 } 324 325 public: 326 327 PitData(); 328 ~PitData(); 329 330 bool Unpack(const unsigned char *data); 331 void Pack(unsigned char *data) const; 332 333 bool Matches(const PitData *otherPitData) const; 334 335 void Clear(void); 336 337 PitEntry *GetEntry(unsigned int index); 338 const PitEntry *GetEntry(unsigned int index) const; 339 340 PitEntry *FindEntry(const char *partitionName); 341 const PitEntry *FindEntry(const char *partitionName) const; 342 343 PitEntry *FindEntry(unsigned int partitionIdentifier); 344 const PitEntry *FindEntry(unsigned int partitionIdentifier) const; 345 GetEntryCount(void)346 unsigned int GetEntryCount(void) const 347 { 348 return entryCount; 349 } 350 GetDataSize(void)351 unsigned int GetDataSize(void) const 352 { 353 return PitData::kHeaderDataSize + entryCount * PitEntry::kDataSize; 354 } 355 GetPaddedSize(void)356 unsigned int GetPaddedSize(void) const 357 { 358 unsigned int dataSize = GetDataSize(); 359 unsigned int paddedSize = (dataSize / kPaddedSizeMultiplicand) * kPaddedSizeMultiplicand; 360 361 if (dataSize % kPaddedSizeMultiplicand != 0) 362 paddedSize += kPaddedSizeMultiplicand; 363 364 return paddedSize; 365 } 366 GetUnknown1(void)367 unsigned int GetUnknown1(void) const 368 { 369 return unknown1; 370 } 371 GetUnknown2(void)372 unsigned int GetUnknown2(void) const 373 { 374 return unknown2; 375 } 376 GetUnknown3(void)377 unsigned short GetUnknown3(void) const 378 { 379 return unknown3; 380 } 381 GetUnknown4(void)382 unsigned short GetUnknown4(void) const 383 { 384 return unknown4; 385 } 386 GetUnknown5(void)387 unsigned short GetUnknown5(void) const 388 { 389 return unknown5; 390 } 391 GetUnknown6(void)392 unsigned short GetUnknown6(void) const 393 { 394 return unknown6; 395 } 396 GetUnknown7(void)397 unsigned short GetUnknown7(void) const 398 { 399 return unknown7; 400 } 401 GetUnknown8(void)402 unsigned short GetUnknown8(void) const 403 { 404 return unknown8; 405 } 406 }; 407 } 408 409 #endif 410