mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-24 19:37:39 +00:00
Add basic cpio features
This commit is contained in:
parent
a4ce9f6f05
commit
1e3bcfc8cd
@ -9,7 +9,7 @@ LOCAL_C_INCLUDES := \
|
|||||||
jni/ndk-compression/lz4/lib/ \
|
jni/ndk-compression/lz4/lib/ \
|
||||||
jni/ndk-compression/bzip2/
|
jni/ndk-compression/bzip2/
|
||||||
|
|
||||||
LOCAL_SRC_FILES := main.c unpack.c repack.c hexpatch.c parseimg.c compress.c utils.c
|
LOCAL_SRC_FILES := main.c unpack.c repack.c hexpatch.c parseimg.c compress.c utils.c cpio.c
|
||||||
LOCAL_CFLAGS += -DZLIB_CONST
|
LOCAL_CFLAGS += -DZLIB_CONST
|
||||||
include $(BUILD_EXECUTABLE)
|
include $(BUILD_EXECUTABLE)
|
||||||
|
|
||||||
|
158
jni/magiskboot/cpio.c
Normal file
158
jni/magiskboot/cpio.c
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
#include "magiskboot.h"
|
||||||
|
#include "cpio.h"
|
||||||
|
|
||||||
|
static uint32_t x8u(char *hex) {
|
||||||
|
uint32_t val, inpos = 8, outpos;
|
||||||
|
char pattern[6];
|
||||||
|
|
||||||
|
while (*hex == '0') {
|
||||||
|
hex++;
|
||||||
|
if (!--inpos) return 0;
|
||||||
|
}
|
||||||
|
// Because scanf gratuitously treats %*X differently than printf does.
|
||||||
|
sprintf(pattern, "%%%dx%%n", inpos);
|
||||||
|
sscanf(hex, pattern, &val, &outpos);
|
||||||
|
if (inpos != outpos) error(1, "bad cpio header");
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cpio_vec_insert(vector *v, cpio_file *n) {
|
||||||
|
cpio_file *f, *t;
|
||||||
|
int shift = 0;
|
||||||
|
// Insert in alphabet order
|
||||||
|
vec_for_each(v, f) {
|
||||||
|
if (shift) {
|
||||||
|
vec_entry(v)[_i] = t;
|
||||||
|
t = f;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
t = f;
|
||||||
|
if (strcmp(f->filename, n->filename) == 0) {
|
||||||
|
// Replace, then all is done
|
||||||
|
vec_entry(v)[_i] = n;
|
||||||
|
return;
|
||||||
|
} else if (strcmp(f->filename, n->filename) > 0) {
|
||||||
|
// Insert, then start shifting
|
||||||
|
vec_entry(v)[_i] = n;
|
||||||
|
t = f;
|
||||||
|
shift = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vec_push_back(v, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse cpio file to a vector of cpio_file
|
||||||
|
void parse_cpio(const char *filename, vector *v) {
|
||||||
|
printf("\nLoading cpio: [%s]\n\n", filename);
|
||||||
|
int fd = open(filename, O_RDONLY);
|
||||||
|
if (fd < 0)
|
||||||
|
error(1, "Cannot open %s", filename);
|
||||||
|
cpio_newc_header header;
|
||||||
|
cpio_file *f;
|
||||||
|
while(read(fd, &header, 110) == 110) {
|
||||||
|
f = calloc(sizeof(*f), 1);
|
||||||
|
// f->ino = x8u(header.ino);
|
||||||
|
f->mode = x8u(header.mode);
|
||||||
|
f->uid = x8u(header.uid);
|
||||||
|
f->gid = x8u(header.gid);
|
||||||
|
// f->nlink = x8u(header.nlink);
|
||||||
|
// f->mtime = x8u(header.mtime);
|
||||||
|
f->filesize = x8u(header.filesize);
|
||||||
|
// f->devmajor = x8u(header.devmajor);
|
||||||
|
// f->devminor = x8u(header.devminor);
|
||||||
|
// f->rdevmajor = x8u(header.rdevmajor);
|
||||||
|
// f->rdevminor = x8u(header.rdevminor);
|
||||||
|
f->namesize = x8u(header.namesize);
|
||||||
|
// f->check = x8u(header.check);
|
||||||
|
f->filename = malloc(f->namesize);
|
||||||
|
read(fd, f->filename, f->namesize);
|
||||||
|
file_align(fd, 4, 0);
|
||||||
|
if (f->filesize) {
|
||||||
|
f->data = malloc(f->filesize);
|
||||||
|
read(fd, f->data, f->filesize);
|
||||||
|
file_align(fd, 4, 0);
|
||||||
|
}
|
||||||
|
vec_push_back(v, f);
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_cpio(const char *filename, vector *v) {
|
||||||
|
printf("\nDump cpio: [%s]\n\n", filename);
|
||||||
|
int fd = open_new(filename);
|
||||||
|
unsigned inode = 300000;
|
||||||
|
char header[111];
|
||||||
|
cpio_file *f;
|
||||||
|
vec_for_each(v, f) {
|
||||||
|
if (f->remove) continue;
|
||||||
|
sprintf(header, "070701%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x",
|
||||||
|
inode++, // f->ino
|
||||||
|
f->mode,
|
||||||
|
f->uid,
|
||||||
|
f->gid,
|
||||||
|
1, // f->nlink
|
||||||
|
0, // f->mtime
|
||||||
|
f->filesize,
|
||||||
|
0, // f->devmajor
|
||||||
|
0, // f->devminor
|
||||||
|
0, // f->rdevmajor
|
||||||
|
0, // f->rdevminor
|
||||||
|
f->namesize,
|
||||||
|
0 // f->check
|
||||||
|
);
|
||||||
|
write(fd, header, 110);
|
||||||
|
write(fd, f->filename, f->namesize);
|
||||||
|
file_align(fd, 4, 1);
|
||||||
|
if (f->filesize) {
|
||||||
|
write(fd, f->data, f->filesize);
|
||||||
|
file_align(fd, 4, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cpio_vec_destroy(vector *v) {
|
||||||
|
// Free each cpio_file
|
||||||
|
cpio_file *f;
|
||||||
|
vec_for_each(v, f) {
|
||||||
|
free(f->filename);
|
||||||
|
free(f->data);
|
||||||
|
free(f);
|
||||||
|
}
|
||||||
|
vec_destroy(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cpio_rm(int recursive, const char *entry, vector *v) {
|
||||||
|
cpio_file *f;
|
||||||
|
vec_for_each(v, f) {
|
||||||
|
if ((recursive && strncmp(f->filename, entry, strlen(entry)) == 0)
|
||||||
|
|| (strcmp(f->filename, entry) == 0) ) {
|
||||||
|
f->remove = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void cpio_mkdir(mode_t mode, const char *entry, vector *v) {
|
||||||
|
cpio_file *f = calloc(sizeof(*f), 1);
|
||||||
|
f->mode = S_IFDIR | mode;
|
||||||
|
f->namesize = strlen(entry) + 1;
|
||||||
|
f->filename = malloc(f->namesize);
|
||||||
|
memcpy(f->filename, entry, f->namesize);
|
||||||
|
cpio_vec_insert(v, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cpio_add(mode_t mode, const char *entry, const char *filename, vector *v) {
|
||||||
|
int fd = open(filename, O_RDONLY);
|
||||||
|
if (fd < 0)
|
||||||
|
error(1, "Cannot open %s", filename);
|
||||||
|
cpio_file *f = calloc(sizeof(*f), 1);
|
||||||
|
f->mode = S_IFREG | mode;
|
||||||
|
f->namesize = strlen(entry) + 1;
|
||||||
|
f->filename = malloc(f->namesize);
|
||||||
|
memcpy(f->filename, entry, f->namesize);
|
||||||
|
f->filesize = lseek(fd, 0, SEEK_END);
|
||||||
|
lseek(fd, 0, SEEK_SET);
|
||||||
|
f->data = malloc(f->filesize);
|
||||||
|
read(fd, f->data, f->filesize);
|
||||||
|
cpio_vec_insert(v, f);
|
||||||
|
}
|
42
jni/magiskboot/cpio.h
Normal file
42
jni/magiskboot/cpio.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#ifndef _CPIO_H_
|
||||||
|
#define _CPIO_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef struct cpio_file {
|
||||||
|
// uint32_t ino;
|
||||||
|
uint32_t mode;
|
||||||
|
uint32_t uid;
|
||||||
|
uint32_t gid;
|
||||||
|
// uint32_t nlink;
|
||||||
|
// uint32_t mtime;
|
||||||
|
uint32_t filesize;
|
||||||
|
// uint32_t devmajor;
|
||||||
|
// uint32_t devminor;
|
||||||
|
// uint32_t rdevmajor;
|
||||||
|
// uint32_t rdevminor;
|
||||||
|
uint32_t namesize;
|
||||||
|
// uint32_t check;
|
||||||
|
char *filename;
|
||||||
|
void *data;
|
||||||
|
int remove;
|
||||||
|
} cpio_file;
|
||||||
|
|
||||||
|
typedef struct cpio_newc_header {
|
||||||
|
char magic[6];
|
||||||
|
char ino[8];
|
||||||
|
char mode[8];
|
||||||
|
char uid[8];
|
||||||
|
char gid[8];
|
||||||
|
char nlink[8];
|
||||||
|
char mtime[8];
|
||||||
|
char filesize[8];
|
||||||
|
char devmajor[8];
|
||||||
|
char devminor[8];
|
||||||
|
char rdevmajor[8];
|
||||||
|
char rdevminor[8];
|
||||||
|
char namesize[8];
|
||||||
|
char check[8];
|
||||||
|
} cpio_newc_header;
|
||||||
|
|
||||||
|
#endif
|
@ -1,27 +1,11 @@
|
|||||||
#include "magiskboot.h"
|
#include "magiskboot.h"
|
||||||
|
|
||||||
static int hex2int(char c) {
|
static void hex2byte(const char *hex, unsigned char *str) {
|
||||||
int first = c / 16 - 3;
|
char high, low;
|
||||||
int second = c % 16;
|
for (int i = 0, length = strlen(hex); i < length; i += 2) {
|
||||||
int result = first * 10 + second;
|
high = toupper(hex[i]) - '0';
|
||||||
if(result > 9) result--;
|
low = toupper(hex[i + 1]) - '0';
|
||||||
return result;
|
str[i / 2] = ((high > 9 ? high - 7 : high) << 4) + (low > 9 ? low - 7 : low);
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned hex2ascii(char c, char d) {
|
|
||||||
int high = hex2int(c) * 16;
|
|
||||||
int low = hex2int(d);
|
|
||||||
return high + low;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void hexstr2str(const char *hex, unsigned char *str) {
|
|
||||||
char buf = 0;
|
|
||||||
for(int i = 0, length = strlen(hex); i < length; ++i){
|
|
||||||
if(i % 2){
|
|
||||||
str[i / 2] = hex2ascii(buf, hex[i]);
|
|
||||||
} else{
|
|
||||||
buf = hex[i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,8 +16,8 @@ void hexpatch(const char *image, const char *from, const char *to) {
|
|||||||
mmap_rw(image, &file, &filesize);
|
mmap_rw(image, &file, &filesize);
|
||||||
pattern = malloc(patternsize);
|
pattern = malloc(patternsize);
|
||||||
patch = malloc(patchsize);
|
patch = malloc(patchsize);
|
||||||
hexstr2str(from, pattern);
|
hex2byte(from, pattern);
|
||||||
hexstr2str(to, patch);
|
hex2byte(to, patch);
|
||||||
for (size_t i = 0; i < filesize - patternsize; ++i) {
|
for (size_t i = 0; i < filesize - patternsize; ++i) {
|
||||||
if (memcmp(file + i, pattern, patternsize) == 0) {
|
if (memcmp(file + i, pattern, patternsize) == 0) {
|
||||||
printf("Pattern %s found!\nPatching to %s\n", from, to);
|
printf("Pattern %s found!\nPatching to %s\n", from, to);
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/sendfile.h>
|
#include <sys/sendfile.h>
|
||||||
@ -48,12 +50,37 @@ typedef enum {
|
|||||||
QCDT,
|
QCDT,
|
||||||
} file_t;
|
} file_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NONE,
|
||||||
|
RM,
|
||||||
|
MKDIR,
|
||||||
|
ADD
|
||||||
|
} command_t;
|
||||||
|
|
||||||
extern char *SUP_EXT_LIST[SUP_NUM];
|
extern char *SUP_EXT_LIST[SUP_NUM];
|
||||||
extern file_t SUP_TYPE_LIST[SUP_NUM];
|
extern file_t SUP_TYPE_LIST[SUP_NUM];
|
||||||
// Cannot declare in header, but place a copy here for convenience
|
// Cannot declare in header, but place a copy here for convenience
|
||||||
// char *SUP_EXT_LIST[SUP_NUM] = { "gz", "xz", "lzma", "bz2", "lz4" };
|
// char *SUP_EXT_LIST[SUP_NUM] = { "gz", "xz", "lzma", "bz2", "lz4" };
|
||||||
// file_t SUP_TYPE_LIST[SUP_NUM] = { GZIP, XZ, LZMA, BZIP2, LZ4 };
|
// file_t SUP_TYPE_LIST[SUP_NUM] = { GZIP, XZ, LZMA, BZIP2, LZ4 };
|
||||||
|
|
||||||
|
// Vector
|
||||||
|
typedef struct vector {
|
||||||
|
size_t size;
|
||||||
|
size_t cap;
|
||||||
|
void **data;
|
||||||
|
} vector;
|
||||||
|
void vec_init(vector *v);
|
||||||
|
void vec_push_back(vector *v, void *p);
|
||||||
|
void vec_destroy(vector *v);
|
||||||
|
|
||||||
|
#define vec_size(v) (v)->size
|
||||||
|
#define vec_cap(v) (v)->cap
|
||||||
|
#define vec_entry(v) (v)->data
|
||||||
|
// vec_for_each(vector *v, void *e)
|
||||||
|
#define vec_for_each(v, e) \
|
||||||
|
e = (v)->data[0]; \
|
||||||
|
for (size_t _i = 0; _i < (v)->size; ++_i, e = (v)->data[_i])
|
||||||
|
|
||||||
// Global variables
|
// Global variables
|
||||||
extern unsigned char *kernel, *ramdisk, *second, *dtb;
|
extern unsigned char *kernel, *ramdisk, *second, *dtb;
|
||||||
extern boot_img_hdr hdr;
|
extern boot_img_hdr hdr;
|
||||||
@ -62,9 +89,8 @@ extern int mtk_kernel, mtk_ramdisk;
|
|||||||
|
|
||||||
// Main entries
|
// Main entries
|
||||||
void unpack(const char *image);
|
void unpack(const char *image);
|
||||||
void repack(const char *image);
|
void repack(const char* orig_image, const char* out_image);
|
||||||
void hexpatch(const char *image, const char *from, const char *to);
|
void hexpatch(const char *image, const char *from, const char *to);
|
||||||
void cpio(const char *filename);
|
|
||||||
void error(int rc, const char *msg, ...);
|
void error(int rc, const char *msg, ...);
|
||||||
void parse_img(unsigned char *orig, size_t size);
|
void parse_img(unsigned char *orig, size_t size);
|
||||||
void cleanup();
|
void cleanup();
|
||||||
@ -79,12 +105,20 @@ void comp_file(const char *method, const char *from);
|
|||||||
int decomp(file_t type, const char *to, const unsigned char *from, size_t size);
|
int decomp(file_t type, const char *to, const unsigned char *from, size_t size);
|
||||||
void decomp_file(char *from);
|
void decomp_file(char *from);
|
||||||
|
|
||||||
|
// CPIO
|
||||||
|
void parse_cpio(const char *filename, vector *v);
|
||||||
|
void dump_cpio(const char *filename, vector *v);
|
||||||
|
void cpio_vec_destroy(vector *v);
|
||||||
|
void cpio_rm(int recursive, const char *entry, vector *v);
|
||||||
|
void cpio_mkdir(mode_t mode, const char *entry, vector *v);
|
||||||
|
void cpio_add(mode_t mode, const char *entry, const char *filename, vector *v);
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
void mmap_ro(const char *filename, unsigned char **buf, size_t *size);
|
void mmap_ro(const char *filename, unsigned char **buf, size_t *size);
|
||||||
void mmap_rw(const char *filename, unsigned char **buf, size_t *size);
|
void mmap_rw(const char *filename, unsigned char **buf, size_t *size);
|
||||||
file_t check_type(const unsigned char *buf);
|
file_t check_type(const unsigned char *buf);
|
||||||
void mem_align(size_t *pos, size_t align);
|
void mem_align(size_t *pos, size_t align);
|
||||||
void file_align(int fd, size_t align);
|
void file_align(int fd, size_t align, int out);
|
||||||
int open_new(const char *filename);
|
int open_new(const char *filename);
|
||||||
void print_info();
|
void print_info();
|
||||||
|
|
||||||
|
@ -6,22 +6,36 @@
|
|||||||
|
|
||||||
static void usage(char *arg0) {
|
static void usage(char *arg0) {
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
fprintf(stderr, "%s --unpack <bootimage>\n", arg0);
|
fprintf(stderr, "%s --unpack <bootimg>\n", arg0);
|
||||||
fprintf(stderr, " Unpack <bootimage> to kernel, ramdisk.cpio, (second), (dtb) into the\n current directory\n\n");
|
fprintf(stderr, " Unpack <bootimg> to kernel, ramdisk.cpio, (second), (dtb) into the\n current directory\n\n");
|
||||||
fprintf(stderr, "%s --repack <bootimage>\n", arg0);
|
|
||||||
|
fprintf(stderr, "%s --repack <origbootimg> [outbootimg]\n", arg0);
|
||||||
fprintf(stderr, " Repack kernel, ramdisk.cpio[.ext], second, dtb... from current directory\n");
|
fprintf(stderr, " Repack kernel, ramdisk.cpio[.ext], second, dtb... from current directory\n");
|
||||||
fprintf(stderr, " to new-image.img. <bootimage> is the original boot image you've just unpacked.\n");
|
fprintf(stderr, " to [outbootimg], or new-boot.img if not specified.\n");
|
||||||
fprintf(stderr, " If file ramdisk.cpio exists, it will auto re-compress with the same method\n");
|
fprintf(stderr, " It will compress ramdisk.cpio with the same method used in <origbootimg>\n");
|
||||||
fprintf(stderr, " used in <bootimage>, or it will attempt to find ramdisk.cpio.[ext], and repack\n");
|
fprintf(stderr, " if exists, or attempt to find ramdisk.cpio.[ext], and repack\n");
|
||||||
fprintf(stderr, " directly with the compressed file\n\n");
|
fprintf(stderr, " directly with the compressed ramdisk file\n\n");
|
||||||
|
|
||||||
fprintf(stderr, "%s --hexpatch <file> <hexpattern1> <hexpattern2>\n", arg0);
|
fprintf(stderr, "%s --hexpatch <file> <hexpattern1> <hexpattern2>\n", arg0);
|
||||||
fprintf(stderr, " Search <hexpattern1> in <file>, and replace with <hexpattern2>\n\n");
|
fprintf(stderr, " Search <hexpattern1> in <file>, and replace with <hexpattern2>\n\n");
|
||||||
|
|
||||||
|
fprintf(stderr, "%s --cpio-<cmd> <incpio> <outcpio> [flags...] [params...]\n", arg0);
|
||||||
|
fprintf(stderr, " Do cpio related cmds to <incpio> and output to <outcpio>\n Supported commands:\n");
|
||||||
|
fprintf(stderr, " --cpio-rm [-r] <entry>\n Remove entry from cpio, flag -r to remove recursively\n");
|
||||||
|
fprintf(stderr, " --cpio-mkdir <mode> <entry>\n Create directory as an <entry>\n");
|
||||||
|
fprintf(stderr, " --cpio-add <mode> <entry> <infile>\n Add <infile> as an <entry>; will replace <entry> if already exists\n");
|
||||||
|
fprintf(stderr, " e.g: the command to add /tmp/tmpfile as entry init.magisk.rc:\n");
|
||||||
|
fprintf(stderr, " %s --cpio-add <incpio> <outcpio> 0750 init.magisk.rc /tmp/tmpfile\n\n", arg0);
|
||||||
|
|
||||||
fprintf(stderr, "%s --compress[=method] <file>\n", arg0);
|
fprintf(stderr, "%s --compress[=method] <file>\n", arg0);
|
||||||
fprintf(stderr, " Compress <file> with [method], or gzip if not specified.\n Supported methods: " SUP_LIST "\n\n");
|
fprintf(stderr, " Compress <file> with [method], or gzip if not specified.\n Supported methods: " SUP_LIST "\n\n");
|
||||||
|
|
||||||
fprintf(stderr, "%s --decompress <file>\n", arg0);
|
fprintf(stderr, "%s --decompress <file>\n", arg0);
|
||||||
fprintf(stderr, " Auto check file type, and decompress <file> accordingly\n Supported methods: " SUP_LIST "\n\n");
|
fprintf(stderr, " Auto check file type, and decompress <file> accordingly\n Supported methods: " SUP_LIST "\n\n");
|
||||||
|
|
||||||
fprintf(stderr, "%s --cleanup\n", arg0);
|
fprintf(stderr, "%s --cleanup\n", arg0);
|
||||||
fprintf(stderr, " Cleanup the current working directory\n\n");
|
fprintf(stderr, " Cleanup the current working directory\n\n");
|
||||||
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,33 +50,67 @@ void error(int rc, const char *msg, ...) {
|
|||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
printf("MagiskBoot (by topjohnwu) - Boot Image Modification Tool\n");
|
printf("MagiskBoot (by topjohnwu) - Boot Image Modification Tool\n");
|
||||||
if (argc < 3) {
|
|
||||||
if (strcmp(argv[1], "--cleanup") == 0) {
|
|
||||||
cleanup();
|
|
||||||
} else {
|
|
||||||
usage(argv[0]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (strcmp(argv[1], "--unpack") == 0) {
|
|
||||||
unpack(argv[2]);
|
|
||||||
} else if (strcmp(argv[1], "--repack") == 0) {
|
|
||||||
repack(argv[2]);
|
|
||||||
} else if (strcmp(argv[1], "--hexpatch") == 0) {
|
|
||||||
if (argc < 5)
|
|
||||||
usage(argv[0]);
|
|
||||||
hexpatch(argv[2], argv[3], argv[4]);
|
|
||||||
} else if (strcmp(argv[1], "--decompress") == 0) {
|
|
||||||
decomp_file(argv[2]);
|
|
||||||
} else if (strstr(argv[1], "--compress") != NULL) {
|
|
||||||
char *method;
|
|
||||||
method = strchr(argv[1], '=');
|
|
||||||
if (method == NULL) method = "gzip";
|
|
||||||
else method++;
|
|
||||||
comp_file(method, argv[2]);
|
|
||||||
} else {
|
|
||||||
usage(argv[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
|
if (argc > 1 && strcmp(argv[1], "--cleanup") == 0) {
|
||||||
|
cleanup();
|
||||||
|
} else if (argc > 2 && strcmp(argv[1], "--unpack") == 0) {
|
||||||
|
unpack(argv[2]);
|
||||||
|
} else if (argc > 2 && strcmp(argv[1], "--repack") == 0) {
|
||||||
|
repack(argv[2], argc > 3 ? argv[3] : NEW_BOOT);
|
||||||
|
} else if (argc > 2 && strcmp(argv[1], "--decompress") == 0) {
|
||||||
|
decomp_file(argv[2]);
|
||||||
|
} else if (argc > 2 && strncmp(argv[1], "--compress", 10) == 0) {
|
||||||
|
char *method;
|
||||||
|
method = strchr(argv[1], '=');
|
||||||
|
if (method == NULL) method = "gzip";
|
||||||
|
else method++;
|
||||||
|
comp_file(method, argv[2]);
|
||||||
|
} else if (argc > 4 && strcmp(argv[1], "--hexpatch") == 0) {
|
||||||
|
hexpatch(argv[2], argv[3], argv[4]);
|
||||||
|
} else if (argc > 4 && strncmp(argv[1], "--cpio", 6) == 0) {
|
||||||
|
int recursive = 0;
|
||||||
|
char *command;
|
||||||
|
command_t cmd;
|
||||||
|
command = strchr(argv[1] + 2, '-');
|
||||||
|
if (command == NULL) usage(argv[0]);
|
||||||
|
else command++;
|
||||||
|
if (strcmp(command, "rm") == 0) {
|
||||||
|
cmd = RM;
|
||||||
|
if (argc > 5 && strcmp(argv[4], "-r") == 0) {
|
||||||
|
recursive = 1;
|
||||||
|
argv[4] = argv[5];
|
||||||
|
argc--;
|
||||||
|
}
|
||||||
|
} else if (argc > 5 && strcmp(command, "mkdir") == 0) {
|
||||||
|
cmd = MKDIR;
|
||||||
|
} else if (argc > 6 && strcmp(command, "add") == 0) {
|
||||||
|
cmd = ADD;
|
||||||
|
} else {
|
||||||
|
cmd = NONE;
|
||||||
|
usage(argv[0]);
|
||||||
|
}
|
||||||
|
vector v;
|
||||||
|
vec_init(&v);
|
||||||
|
parse_cpio(argv[2], &v);
|
||||||
|
switch(cmd) {
|
||||||
|
case RM:
|
||||||
|
cpio_rm(recursive, argv[4], &v);
|
||||||
|
break;
|
||||||
|
case MKDIR:
|
||||||
|
cpio_mkdir(strtoul(argv[4], NULL, 8), argv[5], &v);
|
||||||
|
break;
|
||||||
|
case ADD:
|
||||||
|
cpio_add(strtoul(argv[4], NULL, 8), argv[5], argv[6], &v);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Never happen
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dump_cpio(argv[3], &v);
|
||||||
|
cpio_vec_destroy(&v);
|
||||||
|
} else {
|
||||||
|
usage(argv[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -20,20 +20,20 @@ static void restore_buf(const void *buf, size_t size, int fd) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void repack(const char* image) {
|
void repack(const char* orig_image, const char* out_image) {
|
||||||
size_t size;
|
size_t size;
|
||||||
unsigned char *orig;
|
unsigned char *orig;
|
||||||
char name[PATH_MAX];
|
char name[PATH_MAX];
|
||||||
|
|
||||||
// Load original image
|
// Load original image
|
||||||
mmap_ro(image, &orig, &size);
|
mmap_ro(orig_image, &orig, &size);
|
||||||
|
|
||||||
// Parse original image
|
// Parse original image
|
||||||
printf("\nParsing boot image: [%s]\n\n", image);
|
printf("\nParsing boot image: [%s]\n\n", orig_image);
|
||||||
parse_img(orig, size);
|
parse_img(orig, size);
|
||||||
|
|
||||||
// Create new image
|
// Create new image
|
||||||
int fd = open_new(NEW_BOOT);
|
int fd = open_new(out_image);
|
||||||
|
|
||||||
// Set all sizes to 0
|
// Set all sizes to 0
|
||||||
hdr.kernel_size = 0;
|
hdr.kernel_size = 0;
|
||||||
@ -51,7 +51,7 @@ void repack(const char* image) {
|
|||||||
hdr.kernel_size += 512;
|
hdr.kernel_size += 512;
|
||||||
}
|
}
|
||||||
hdr.kernel_size += restore(KERNEL_FILE, fd);
|
hdr.kernel_size += restore(KERNEL_FILE, fd);
|
||||||
file_align(fd, hdr.page_size);
|
file_align(fd, hdr.page_size, 1);
|
||||||
|
|
||||||
// Restore ramdisk
|
// Restore ramdisk
|
||||||
if (mtk_ramdisk) {
|
if (mtk_ramdisk) {
|
||||||
@ -90,22 +90,22 @@ void repack(const char* image) {
|
|||||||
if (!found)
|
if (!found)
|
||||||
error(1, "No ramdisk exists!");
|
error(1, "No ramdisk exists!");
|
||||||
hdr.ramdisk_size += restore(name, fd);
|
hdr.ramdisk_size += restore(name, fd);
|
||||||
file_align(fd, hdr.page_size);
|
file_align(fd, hdr.page_size, 1);
|
||||||
|
|
||||||
// Restore second
|
// Restore second
|
||||||
if (access(SECOND_FILE, R_OK) == 0) {
|
if (access(SECOND_FILE, R_OK) == 0) {
|
||||||
hdr.second_size += restore(SECOND_FILE, fd);
|
hdr.second_size += restore(SECOND_FILE, fd);
|
||||||
file_align(fd, hdr.page_size);
|
file_align(fd, hdr.page_size, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore dtb
|
// Restore dtb
|
||||||
if (access(DTB_FILE, R_OK) == 0) {
|
if (access(DTB_FILE, R_OK) == 0) {
|
||||||
hdr.dt_size += restore(DTB_FILE, fd);
|
hdr.dt_size += restore(DTB_FILE, fd);
|
||||||
file_align(fd, hdr.page_size);
|
file_align(fd, hdr.page_size, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write header back
|
// Write header back
|
||||||
printf("\nRepack to boot image: [%s]\n\n", NEW_BOOT);
|
printf("\nRepack to boot image: [%s]\n\n", out_image);
|
||||||
print_info();
|
print_info();
|
||||||
lseek(fd, 0, SEEK_SET);
|
lseek(fd, 0, SEEK_SET);
|
||||||
write(fd, &hdr, sizeof(hdr));
|
write(fd, &hdr, sizeof(hdr));
|
||||||
|
@ -62,13 +62,15 @@ void mem_align(size_t *pos, size_t align) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void file_align(int fd, size_t align) {
|
void file_align(int fd, size_t align, int out) {
|
||||||
size_t pos = lseek(fd, 0, SEEK_CUR);
|
size_t pos = lseek(fd, 0, SEEK_CUR);
|
||||||
size_t mask = align - 1;
|
size_t mask = align - 1;
|
||||||
if (pos & mask) {
|
if (pos & mask) {
|
||||||
pos += align - (pos & mask);
|
pos += align - (pos & mask);
|
||||||
ftruncate(fd, pos);
|
if (out) {
|
||||||
lseek(fd, 0, SEEK_END);
|
ftruncate(fd, pos);
|
||||||
|
}
|
||||||
|
lseek(fd, pos, SEEK_SET);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,3 +140,27 @@ void cleanup() {
|
|||||||
unlink(name);
|
unlink(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void vec_init(vector *v) {
|
||||||
|
vec_size(v) = 0;
|
||||||
|
vec_cap(v) = 1;
|
||||||
|
vec_entry(v) = malloc(sizeof(void*));
|
||||||
|
}
|
||||||
|
|
||||||
|
void vec_push_back(vector *v, void *p) {
|
||||||
|
if (v == NULL) return;
|
||||||
|
if (vec_size(v) == vec_cap(v)) {
|
||||||
|
vec_cap(v) *= 2;
|
||||||
|
vec_entry(v) = realloc(vec_entry(v), sizeof(void*) * vec_cap(v));
|
||||||
|
}
|
||||||
|
vec_entry(v)[vec_size(v)] = p;
|
||||||
|
++vec_size(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vec_destroy(vector *v) {
|
||||||
|
// Will not free each entry!
|
||||||
|
// Manually free each entry, then call this function
|
||||||
|
vec_size(v) = 0;
|
||||||
|
vec_cap(v) = 0;
|
||||||
|
free(v->data);
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user