|
#include <unistd.h> |
|
#include <stdlib.h> |
|
#include <stdio.h> |
|
#include <string.h> |
|
#include <stdint.h> |
|
#include <stdarg.h> |
|
#include <sys/types.h> |
|
#include <strings.h> |
|
#include <endian.h> |
|
#include "zlib.h" |
|
|
|
#define DZ_FILE_MAGIC 0x74189632 |
|
#define DZ_PART_MAGIC 0x78951230 |
|
|
|
#define TOT_FILE_MAGIC_1 0xAA55DD44 |
|
#define TOT_FILE_MAGIC_2 0x8FF7C88F |
|
#define TOT_FLASHMAP_MAGIC 0xAA55EC33 |
|
#define TOT_INFO_MAGIC 0x56781234 |
|
|
|
#define TOTLOC_FLASHMAP_MAGIC 0x2000 |
|
#define TOTLOC_FLASHMAP 0x2010 |
|
#define TOTLOC_INFO 0x6010 |
|
#define TOTLOC_PARTLABELS 0x6230 |
|
|
|
#define BLOCK_SIZE 512 |
|
|
|
typedef struct __attribute__((packed)) { |
|
uint32_t magic; |
|
uint32_t unk1; |
|
uint32_t unk2; |
|
uint32_t unk3; |
|
char model[0x20]; |
|
char image[0x90]; |
|
uint32_t partsCount; |
|
char chksum [0x10]; |
|
uint8_t unknown[0x0A]; |
|
char chksum2 [0x10]; |
|
char serial[50]; |
|
char user[15]; |
|
} main_header; |
|
|
|
typedef struct __attribute__((packed)) { |
|
uint32_t magic; |
|
char name[0x20]; |
|
char filename[0x40]; |
|
uint32_t unpackedSize; |
|
uint32_t packedSize; |
|
uint8_t checksum[0x10]; |
|
uint32_t flashAtBlock; |
|
uint32_t lengthInBlocks; |
|
uint8_t trash[0x17C]; |
|
} part_header; |
|
|
|
|
|
typedef struct __attribute__((packed)) { |
|
uint32_t flashAtBlock; |
|
uint32_t readFromFileAtBlock; |
|
uint32_t lengthInBlocks; |
|
uint32_t unknownAlwaysZero; |
|
|
|
} tot_flashmap_record; |
|
|
|
|
|
typedef struct __attribute__((packed)) { |
|
uint32_t magic; |
|
char model[0x10]; |
|
char image[0x90]; |
|
char serial[50]; |
|
char user[15]; |
|
} tot_info_record; |
|
|
|
typedef struct __attribute__((packed)) { |
|
char partName[0x20]; |
|
} tot_partname_record; |
|
|
|
|
|
void initTot(uint8_t* totHeader, int numberOfParts, main_header* mainHeader) { |
|
|
|
memset(totHeader,0xff,0x100000); |
|
|
|
*(uint32_t*)(totHeader) = TOT_FILE_MAGIC_1; |
|
*(uint32_t*)(totHeader+8) = TOT_FILE_MAGIC_2; |
|
|
|
*(uint32_t*)(totHeader+TOTLOC_FLASHMAP_MAGIC) = TOT_FLASHMAP_MAGIC; |
|
|
|
memset(totHeader+TOTLOC_INFO,0x00,0xE4); |
|
memset(totHeader+TOTLOC_PARTLABELS,0x00,sizeof(tot_partname_record)*numberOfParts); |
|
|
|
*(uint32_t*)(totHeader+TOTLOC_INFO) = TOT_INFO_MAGIC; |
|
|
|
strcpy(((tot_info_record*)(totHeader+TOTLOC_INFO))->model,mainHeader->model); |
|
strcpy(((tot_info_record*)(totHeader+TOTLOC_INFO))->image,mainHeader->image); |
|
strcpy(((tot_info_record*)(totHeader+TOTLOC_INFO))->serial,mainHeader->serial); |
|
strcpy(((tot_info_record*)(totHeader+TOTLOC_INFO))->user,mainHeader->user); |
|
|
|
} |
|
|
|
|
|
int main(int argc, char **argv) { |
|
|
|
if (argc<2) { |
|
printf("usage: dz2tot <dz filename>\n"); |
|
exit(-1); |
|
} |
|
|
|
FILE* dzFile; |
|
FILE* outFile; |
|
|
|
uint32_t partsCount; |
|
uint64_t mergeSizeInBlocks = 0; |
|
|
|
uint8_t* totHeader; |
|
tot_flashmap_record* totFlashMapRecord; |
|
tot_partname_record* totPartNameRecord; |
|
|
|
|
|
uint8_t* buff; |
|
|
|
uint8_t* compBuff; |
|
uint8_t* decompBuff; |
|
|
|
|
|
totHeader = malloc(0x100000); |
|
|
|
dzFile = fopen(argv[1],"rb"); |
|
if (dzFile==NULL) { |
|
printf("Error opening file :(\n"); |
|
exit(-1); |
|
} |
|
|
|
buff = malloc(sizeof(main_header)); |
|
|
|
fread(buff,sizeof(main_header),1,dzFile); |
|
|
|
if (((main_header*)buff)->magic != DZ_FILE_MAGIC) { |
|
printf("Unsupported file type :(\n"); |
|
exit(-1); |
|
} |
|
|
|
printf("DZ file format identifier detected\n"); |
|
|
|
printf("Model: %s\n",((main_header*)buff)->model); |
|
printf("Image: %s\n",((main_header*)buff)->image); |
|
printf("Serial: %s\n",((main_header*)buff)->serial); |
|
printf("User: %s\n",((main_header*)buff)->user); |
|
|
|
partsCount = ((main_header*)buff)->partsCount; |
|
|
|
printf("File contains %d (parts of) flash partitions.\n",partsCount); |
|
|
|
initTot(totHeader,partsCount, ((main_header*)buff)); |
|
|
|
totFlashMapRecord = (tot_flashmap_record*)(totHeader+TOTLOC_FLASHMAP); |
|
totPartNameRecord = (tot_partname_record*)(totHeader+TOTLOC_PARTLABELS); |
|
|
|
free(buff); |
|
|
|
fseek(dzFile,0x200,SEEK_SET); |
|
|
|
outFile = fopen("NewFile.tot","wb"); |
|
|
|
fseek(outFile,0x100000,SEEK_SET); |
|
|
|
for (int part=0;part<partsCount;part++){ |
|
|
|
buff=malloc(sizeof(part_header)); |
|
fread(buff,sizeof(part_header),1,dzFile); |
|
|
|
if (((part_header*)buff)->magic != DZ_PART_MAGIC) { |
|
printf("Unsupported file type, can't find parts :(\n"); |
|
exit(-1); |
|
} |
|
printf("--------------------------------------\n"); |
|
printf("Partition name: %s \n",((part_header*)buff)->name); |
|
printf("File name: %s \n",((part_header*)buff)->filename); |
|
printf("\n"); |
|
printf("Unpacked data size: 0x%04x \n",((part_header*)buff)->unpackedSize); |
|
printf("Compressed data size: 0x%04x \n",((part_header*)buff)->packedSize); |
|
|
|
printf("Checksum: "); |
|
for(int x=0;x<16;x++){ printf("%02X",((part_header*)buff)->checksum[x]); } |
|
printf("\n"); |
|
|
|
printf("Part start: block 0x%04x (byte offset 0x%04X) \n",((part_header*)buff)->flashAtBlock,((part_header*)buff)->flashAtBlock * BLOCK_SIZE); |
|
printf("Part length: 0x%04x blocks (0x%04X bytes) \n",((part_header*)buff)->lengthInBlocks,((part_header*)buff)->lengthInBlocks * BLOCK_SIZE); |
|
|
|
compBuff = malloc(((part_header*)buff)->packedSize); |
|
decompBuff = malloc(((part_header*)buff)->unpackedSize); |
|
fread(compBuff,1,((part_header*)buff)->packedSize,dzFile); |
|
uint64_t bufsz = (((part_header*)buff)->unpackedSize); |
|
|
|
if (uncompress(decompBuff,&bufsz,compBuff,((part_header*)buff)->packedSize) == 0) { |
|
fwrite(decompBuff,bufsz,1,outFile); |
|
} else { |
|
printf("Decompression error on %s :(\n",((part_header*)buff)->filename); |
|
exit(-1); |
|
} |
|
|
|
free(compBuff); |
|
free(decompBuff); |
|
|
|
totFlashMapRecord->flashAtBlock=((part_header*)buff)->flashAtBlock; |
|
totFlashMapRecord->readFromFileAtBlock=mergeSizeInBlocks; |
|
totFlashMapRecord->lengthInBlocks=((part_header*)buff)->unpackedSize / BLOCK_SIZE; |
|
totFlashMapRecord->unknownAlwaysZero=0; |
|
|
|
strcpy(totPartNameRecord->partName,((part_header*)buff)->name); |
|
|
|
mergeSizeInBlocks += ((part_header*)buff)->unpackedSize / BLOCK_SIZE; |
|
totFlashMapRecord++; |
|
totPartNameRecord++; |
|
|
|
free(buff); |
|
|
|
} |
|
|
|
fseek(outFile,0,SEEK_SET); |
|
fwrite(totHeader,0x100000,1,outFile); |
|
|
|
free(totHeader); |
|
|
|
fclose(dzFile); |
|
fclose(outFile); |
|
|
|
} |