commit 02965135bdb5ddba39bec22c35f7f41e2b0d7a2f Author: Vasily A. Avilov Date: Tue Jan 26 18:44:44 2016 +1000 Init diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b1b2175 --- /dev/null +++ b/Makefile @@ -0,0 +1,21 @@ +#CFLAGS=-O3 -Wall +CFLAGS=-g -ggdb -Wall +#LDLIBS=-l + +all: pacextractor + +version.h: + if [ ! -f version.h ]; then \ + if [ -d .git ]; then \ + echo '#define VERSION_STR "$(shell git describe --tags --abbrev=0)"' > version.h; \ + else \ + echo '#define VERSION_STR ""' > version.h; \ + fi \ + fi + +pacextractor.o: version.h + +clean: + rm -f pacextractor *.o version.h + +.PHONY: clean all \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..8519b60 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Extractor of SpreadTrum firmware files with extension pac + +Extract all data that I may recognize in package. \ No newline at end of file diff --git a/pacextractor.c b/pacextractor.c new file mode 100644 index 0000000..287b4cc --- /dev/null +++ b/pacextractor.c @@ -0,0 +1,143 @@ + +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + int16_t someField[24]; + int32_t someInt; + int16_t productName[256]; + int16_t firmwareName[256]; + int32_t partitionCount; + int32_t partitionsListStart; + int32_t someIntFields1[5]; + int16_t productName2[50]; + int16_t someIntFields2[6]; + int16_t someIntFields3[2]; +} PacHeader; + +typedef struct { + uint32_t length; + int16_t partitionName[256]; + int16_t fileName[512]; + uint32_t partitionSize; + int32_t someFileds1[2]; + uint32_t partitionAddrInPac; + int32_t someFileds2[3]; + int32_t dataArray[]; +} PartitionHeader; + +void getString(int16_t* baseString, char* resString) { + if(*baseString == 0) { + *resString = 0; + return; + } + int length = 0; + do { + *resString = 0xFF & *baseString; + resString++; + baseString++; + if(++length > 256) + break; + } while(baseString > 0); + *resString = 0; +} + +int main(int argc, char** argv) { + if(argc < 2) { + printf("command format:\n capextractor .pac"); + exit(EXIT_FAILURE); + } + + int fd = open(argv[1], O_RDONLY); + if (fd == -1) { + printf("file %s is not find", argv[1]); + exit(EXIT_FAILURE); + } + +// fseek(fd, 0, SEEK_END); +// int firmwareSize = (fd); +// fseek(fd, 0, SEEK_SET); + struct stat st; + stat(argv[1], &st); + int firmwareSize = st.st_size; + if(firmwareSize < sizeof(PacHeader)) { + printf("file %s is not firmware", argv[1]); + exit(EXIT_FAILURE); + } + + PacHeader pacHeader; + size_t rb =read(fd, &pacHeader, sizeof(PacHeader)); + if(rb <= 0) { + printf("Error while parsing PAC header"); + exit(EXIT_FAILURE); + } + + char buffer[256]; + char buffer1[256]; + getString(pacHeader.firmwareName, buffer); + printf("Firmware name: %s\n", buffer); + uint32_t curPos = pacHeader.partitionsListStart; + PartitionHeader** partHeaders = malloc(sizeof(PartitionHeader**)*pacHeader.partitionCount); + int i; + for(i = 0; i < pacHeader.partitionCount; i++) { + lseek(fd, curPos, SEEK_SET); + uint32_t length; + rb =read(fd, &length, sizeof(uint32_t)); + if(rb <= 0) { + printf("Partition header error"); + exit(EXIT_FAILURE); + } + partHeaders[i] = malloc(length); + lseek(fd, curPos, SEEK_SET); + curPos += length; + rb =read(fd, partHeaders[i], length); + if(rb <= 0) { + printf("Partition header error"); + exit(EXIT_FAILURE); + } + getString(partHeaders[i]->partitionName, buffer); + getString(partHeaders[i]->fileName, buffer1); + printf("Partition name: %s\n\twith file name: %s\n\twith size %u\n", buffer, buffer1, partHeaders[i]->partitionSize); + } + + for(i = 0; i < pacHeader.partitionCount; i++) { + if(partHeaders[i]->partitionSize == 0) { + free(partHeaders[i]); + continue; + } + lseek(fd, partHeaders[i]->partitionAddrInPac, SEEK_SET); + getString(partHeaders[i]->fileName, buffer); + remove(buffer); + int fd_new = open(buffer, O_WRONLY | O_CREAT, 0666); + printf("Extract %s\n", buffer); + uint32_t dataSizeLeft = partHeaders[i]->partitionSize; + while(dataSizeLeft > 0) { + uint32_t copyLength = (dataSizeLeft > 256) ? 256 : dataSizeLeft; + dataSizeLeft -= copyLength; + rb =read(fd, buffer, copyLength); + if(rb != copyLength) { + printf("Partition image extraction error"); + exit(EXIT_FAILURE); + } + rb = write(fd_new, buffer, copyLength); + if(rb != copyLength) { + printf("Partition image extraction error"); + exit(EXIT_FAILURE); + } + printf("\r\t%02d%%", (uint64_t)100 - (uint64_t)100*dataSizeLeft/partHeaders[i]->partitionSize); + } + printf("\n"); + close(fd_new); + free(partHeaders[i]); + } + free(partHeaders); + close(fd); + + return EXIT_SUCCESS; +} \ No newline at end of file