Init
This commit is contained in:
commit
02965135bd
3 changed files with 167 additions and 0 deletions
21
Makefile
Normal file
21
Makefile
Normal file
|
@ -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
|
3
README.md
Normal file
3
README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Extractor of SpreadTrum firmware files with extension pac
|
||||
|
||||
Extract all data that I may recognize in package.
|
143
pacextractor.c
Normal file
143
pacextractor.c
Normal file
|
@ -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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue