forked from divinebird/pacextractor
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 0296513
Showing
3 changed files
with
167 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Extractor of SpreadTrum firmware files with extension pac | ||
|
||
Extract all data that I may recognize in package. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
|
||
#include <stdlib.h> | ||
#include <stdio.h> | ||
#include <string.h> | ||
#include <errno.h> | ||
#include <fcntl.h> | ||
#include <sys/types.h> | ||
#include <unistd.h> | ||
#include <stdint.h> | ||
|
||
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 <firmware name>.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; | ||
} |